@consenti/api 0.5.0 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (63) hide show
  1. package/README.md +143 -11
  2. package/dist/chunk-7NKW7UTJ.js +2 -0
  3. package/dist/chunk-7NKW7UTJ.js.map +1 -0
  4. package/dist/dashboard/assets/{ApiConfig-dmDLJNfI.js → ApiConfig-DLPkgWsM.js} +1 -1
  5. package/dist/dashboard/assets/{ArchivedProfileList-ChWp1RHE.js → ArchivedProfileList-fRvXAaWy.js} +1 -1
  6. package/dist/dashboard/assets/{AuditLog-3lekUOk8.js → AuditLog-9flkPiEQ.js} +1 -1
  7. package/dist/dashboard/assets/{ChangePassword-BYlF08cE.js → ChangePassword-D--mNLLR.js} +1 -1
  8. package/dist/dashboard/assets/{ConfirmDialog-sMBVcbiI.js → ConfirmDialog-CJAqYRfE.js} +1 -1
  9. package/dist/dashboard/assets/{ConsentList-DLDBSjxO.js → ConsentList-CyddMOrW.js} +1 -1
  10. package/dist/dashboard/assets/{ConsentTemplateEditor-0iB6G95-.js → ConsentTemplateEditor-DZGFzkTA.js} +1 -1
  11. package/dist/dashboard/assets/{ConsentTemplateList-BnU_nL8h.js → ConsentTemplateList-CwNVxHyZ.js} +1 -1
  12. package/dist/dashboard/assets/{HeadingTagInput-7owwn9Vj.js → HeadingTagInput-DGKZYLTR.js} +1 -1
  13. package/dist/dashboard/assets/{HowItWorks-B05y-6xX.js → HowItWorks-10CyO4Kp.js} +1 -1
  14. package/dist/dashboard/assets/{PermissionGate-D45f3WrO.js → PermissionGate-CkaZ9DKx.js} +1 -1
  15. package/dist/dashboard/assets/PreviewPane-ArCfR0c9.js +38 -0
  16. package/dist/dashboard/assets/{ProfileEditor-CuMRNzdM.js → ProfileEditor-BNUxXKMk.js} +1 -1
  17. package/dist/dashboard/assets/{ProfileList-CFZ_i1zk.js → ProfileList-Ti5ZML_L.js} +1 -1
  18. package/dist/dashboard/assets/{ProfileVersionHistory-40HtQSrd.js → ProfileVersionHistory-D2KtUROF.js} +1 -1
  19. package/dist/dashboard/assets/{RecordDetailModal-hpJgK02E.js → RecordDetailModal-4OyHjtux.js} +1 -1
  20. package/dist/dashboard/assets/{Reports-BlvcycZ8.js → Reports-CHpF_j2k.js} +1 -1
  21. package/dist/dashboard/assets/{RoleList-CTeQdx6f.js → RoleList-BICQW5gU.js} +1 -1
  22. package/dist/dashboard/assets/{Select-CeC6GRyb.js → Select-C7q2vevu.js} +1 -1
  23. package/dist/dashboard/assets/{Settings-DLsvGtMh.js → Settings-BlOcU0wL.js} +1 -1
  24. package/dist/dashboard/assets/{SetupWizard-BVzGrBm2.js → SetupWizard-DReZ5DWr.js} +1 -1
  25. package/dist/dashboard/assets/{Table-CcBP7eXS.js → Table-C59yMXY2.js} +1 -1
  26. package/dist/dashboard/assets/{TenantList-DLgPnlVv.js → TenantList-Bbwcxyo8.js} +1 -1
  27. package/dist/dashboard/assets/{UITemplateEditor-B9EBcvOB.js → UITemplateEditor-CR7TnHBH.js} +1 -1
  28. package/dist/dashboard/assets/{UITemplateList-CGYRRlCh.js → UITemplateList-NKwDQJAw.js} +1 -1
  29. package/dist/dashboard/assets/{UserList-BbpiUrVr.js → UserList-DMk0_UF0.js} +1 -1
  30. package/dist/dashboard/assets/{VendorList-mlOlW7ht.js → VendorList-BawJ8Kyc.js} +1 -1
  31. package/dist/dashboard/assets/{VisitorList-Dne7xkNx.js → VisitorList-BVSFRtul.js} +1 -1
  32. package/dist/dashboard/assets/check-BAoHs1bd.js +1 -0
  33. package/dist/dashboard/assets/{copy-FTaGH7-z.js → copy-DjZpSOQM.js} +1 -1
  34. package/dist/dashboard/assets/{external-link-5y29qnhn.js → external-link-CFayXpKz.js} +1 -1
  35. package/dist/dashboard/assets/{index-BaYVhd1M.js → index-D7qdwIxs.js} +2 -2
  36. package/dist/dashboard/assets/{profiles-D-hvl_fK.js → profiles-Jb6uV-0U.js} +1 -1
  37. package/dist/dashboard/assets/{roles-DZyZwZDr.js → roles-ChXEt79v.js} +1 -1
  38. package/dist/dashboard/assets/{rotate-ccw-clock-C5cVu2_f.js → rotate-ccw-clock-503u3yEE.js} +1 -1
  39. package/dist/dashboard/assets/{search-mdMD-WTj.js → search-B05qPv24.js} +1 -1
  40. package/dist/dashboard/assets/{square-pen-BoEcHaSW.js → square-pen-BX2H18m3.js} +1 -1
  41. package/dist/dashboard/assets/{templates-DLMsZs7d.js → templates-DalUjETH.js} +1 -1
  42. package/dist/dashboard/assets/{trash-BVDX09Xe.js → trash-Bfqti-Og.js} +1 -1
  43. package/dist/dashboard/assets/{useHashQuery-wXzkY-tk.js → useHashQuery-DzYBqPIg.js} +1 -1
  44. package/dist/dashboard/assets/{users-BLTbK4tk.js → users-CDdO4hYQ.js} +1 -1
  45. package/dist/dashboard/assets/x-Clw5rGTJ.js +1 -0
  46. package/dist/dashboard/index.html +1 -1
  47. package/dist/dist-MNR4WETI.js +2 -0
  48. package/dist/index.cjs +77 -75
  49. package/dist/index.cjs.map +1 -1
  50. package/dist/index.d.cts +45 -9
  51. package/dist/index.d.ts +45 -9
  52. package/dist/index.js +76 -74
  53. package/dist/index.js.map +1 -1
  54. package/dist/widget/widget.js +1 -1
  55. package/package.json +3 -2
  56. package/scripts/migrate-to-consenti-prefix.mjs +196 -0
  57. package/dist/chunk-COR72NFQ.js +0 -2
  58. package/dist/chunk-COR72NFQ.js.map +0 -1
  59. package/dist/dashboard/assets/PreviewPane-Czax39la.js +0 -38
  60. package/dist/dashboard/assets/check-IM5PInrX.js +0 -1
  61. package/dist/dashboard/assets/x-CtCy0YcJ.js +0 -1
  62. package/dist/dist-QJYW5KUK.js +0 -2
  63. /package/dist/{dist-QJYW5KUK.js.map → dist-MNR4WETI.js.map} +0 -0
package/dist/index.cjs CHANGED
@@ -1,48 +1,45 @@
1
- "use strict";var ic=Object.create;var wt=Object.defineProperty;var oc=Object.getOwnPropertyDescriptor;var sc=Object.getOwnPropertyNames;var rc=Object.getPrototypeOf,ac=Object.prototype.hasOwnProperty;var I=(i,e)=>()=>(i&&(e=i(i=0)),e);var Pn=(i,e)=>{for(var t in e)wt(i,t,{get:e[t],enumerable:!0})},Ui=(i,e,t,n)=>{if(e&&typeof e=="object"||typeof e=="function")for(let o of sc(e))!ac.call(i,o)&&o!==t&&wt(i,o,{get:()=>e[o],enumerable:!(n=oc(e,o))||n.enumerable});return i};var ee=(i,e,t)=>(t=i!=null?ic(rc(i)):{},Ui(e||!i||!i.__esModule?wt(t,"default",{value:i,enumerable:!0}):t,i)),cc=i=>Ui(wt({},"__esModule",{value:!0}),i);var lc,f,p=I(()=>{"use strict";lc=()=>typeof document>"u"?new URL(`file:${__filename}`).href:document.currentScript&&document.currentScript.tagName.toUpperCase()==="SCRIPT"?document.currentScript.src:new URL("main.js",document.baseURI).href,f=lc()});var qt,qn=I(()=>{"use strict";p();qt={complianceGroup:"opt-in",gpcMode:"ignore",defaultLocale:"en",expiryDays:365,cookies:{security_storage:{purpose:"necessary",listenGpc:!1},functionality_storage:{purpose:"functional",listenGpc:!1},personalization_storage:{purpose:"preferences",listenGpc:!1},analytics_storage:{purpose:"analytics",listenGpc:!0},ad_storage:{purpose:"marketing",listenGpc:!0,cpraCategory:"sharing"}},translations:{en:{mainBanner:{position:"bottom",heading:"We value your privacy",htmlText:"We use cookies and similar technologies to enhance your browsing experience, analyse site traffic, and show you personalised content. Non-essential cookies require your consent under the GDPR and ePrivacy Directive.",buttons:{"accept-all":{text:"Accept All",style:"primary",action:"custom",cookies:"*"},"reject-optional":{text:"Reject Optional",style:"primary",action:"custom",cookies:"!"},"manage-preferences":{text:"Manage Preferences",style:"text",action:"manage"}}},gpcBanner:{position:"bottom",heading:"Global Privacy Control detected",htmlText:"Your browser is sending a Global Privacy Control signal. We have applied your preference and will not set non-essential cookies unless you change your settings below.",buttons:{"accept-all":{text:"Accept All",style:"primary",action:"custom",cookies:"*"},"confirm-settings":{text:"Confirm Settings",style:"primary",action:"custom",cookies:"!"},"manage-preferences":{text:"Manage Preferences",style:"text",action:"manage"}}},preferenceModal:{position:"right",heading:"Privacy Preferences",subheading:"Manage your consent settings for each category below.",htmlText:"You can choose which cookie categories you allow. Your choices apply to this site only. Essential cookies cannot be disabled as they are required for the site to function correctly.",buttons:{"accept-all":{text:"Accept All",style:"primary",action:"custom",cookies:"*"},"reject-optional":{text:"Reject Optional",style:"primary",action:"custom",cookies:"!"},"save-preferences":{text:"Save My Preferences",style:"primary",action:"submit"}},categories:{necessary:{heading:"Strictly Necessary",htmlText:"These cookies are required for the website to function and cannot be disabled. They are usually set in response to actions you take, such as setting your privacy preferences, logging in, or filling in forms.",legalBasis:"mandatory",cookies:["security_storage"]},functional:{heading:"Functional",htmlText:"These cookies enable enhanced functionality and personalisation. They may be set by us or by third-party providers whose services we have added to our pages. If you do not allow these cookies, some or all of these features may not function properly.",legalBasis:"consent",cookies:["functionality_storage","personalization_storage"]},analytics:{heading:"Analytics",htmlText:"These cookies allow us to count visits and traffic sources so we can measure and improve site performance. They help us understand which pages are most and least popular. All information collected is aggregated and therefore anonymous.",legalBasis:"consent",cookies:["analytics_storage"]},marketing:{heading:"Marketing",htmlText:"These cookies may be set through our site by advertising partners to build a profile of your interests and show you relevant adverts on other sites. They do not store personal information directly but identify your browser and device uniquely.",legalBasis:"consent",cookies:["ad_storage"]}}}}}}});var Jt,Jn=I(()=>{"use strict";p();Jt={complianceGroup:"opt-out",gpcMode:"honor",defaultLocale:"en",expiryDays:365,cookies:{security_storage:{purpose:"necessary",listenGpc:!1},functionality_storage:{purpose:"functional",listenGpc:!0},personalization_storage:{purpose:"preferences",listenGpc:!0},analytics_storage:{purpose:"analytics",listenGpc:!0},ad_storage:{purpose:"marketing",listenGpc:!0,cpraCategory:"sharing"}},translations:{en:{mainBanner:{position:"bottom",heading:"We use cookies",htmlText:"We and our partners use cookies and similar tracking technologies to improve your experience, analyse site usage, and show relevant advertising. You may opt out of the sale or sharing of your personal data at any time.",buttons:{"accept-all":{text:"Accept All",style:"primary",action:"custom",cookies:"*"},"do-not-sell-share":{text:"Do Not Sell or Share My Personal Information",style:"secondary",action:"custom",cookies:"!"},"manage-preferences":{text:"Manage Preferences",style:"text",action:"manage"}}},gpcBanner:{position:"bottom",heading:"Your opt-out has been applied",htmlText:"Your browser sent a Global Privacy Control signal. We have automatically opted you out of the sale and sharing of your personal data as required by applicable US state privacy laws.",buttons:{"accept-all":{text:"Accept All",style:"primary",action:"custom",cookies:"*"},"confirm-opt-out":{text:"Confirm Opt-Out",style:"secondary",action:"custom",cookies:"!"},"manage-preferences":{text:"Manage Preferences",style:"text",action:"manage"}}},preferenceModal:{position:"right",heading:"Cookie Preferences",subheading:"Manage your data preferences. You may opt out of non-essential uses at any time.",htmlText:"Under applicable US state privacy laws, you have the right to opt out of the sale and sharing of your personal data. Toggle the categories below to exercise your rights.",buttons:{"accept-all":{text:"Accept All",style:"primary",action:"custom",cookies:"*"},"opt-out-all":{text:"Opt Out of All",style:"secondary",action:"custom",cookies:"!"},"save-choices":{text:"Save My Choices",style:"primary",action:"submit"}},categories:{necessary:{heading:"Strictly Necessary",htmlText:"These cookies are required for the website to operate and cannot be disabled. They do not involve the sale or sharing of personal data.",legalBasis:"mandatory",cookies:["security_storage"]},functional:{heading:"Functional",htmlText:"These cookies improve the functionality of the site. Disabling them may affect how the site operates. You may opt out at any time.",legalBasis:"consent",cookies:["functionality_storage","personalization_storage"]},analytics:{heading:"Analytics",htmlText:"Analytics cookies help us understand how visitors interact with the site. Opting out prevents your data from being included in usage statistics.",legalBasis:"consent",cookies:["analytics_storage"]},marketing:{heading:"Sale / Sharing of Personal Data",htmlText:"These cookies involve the sale or sharing of your personal data with advertising partners for targeted advertising. You have the right to opt out of this under applicable US state privacy laws.",legalBasis:"consent",cookies:["ad_storage"]}}}}}}});var zt,zn=I(()=>{"use strict";p();zt={complianceGroup:"opt-out-strict",gpcMode:"honor",defaultLocale:"en",expiryDays:365,cookies:{security_storage:{purpose:"necessary",listenGpc:!1},functionality_storage:{purpose:"functional",listenGpc:!0,cpraCategory:"sharing"},personalization_storage:{purpose:"preferences",listenGpc:!0,cpraCategory:"sharing"},analytics_storage:{purpose:"analytics",listenGpc:!0,cpraCategory:"sharing"},ad_storage:{purpose:"marketing",listenGpc:!0,cpraCategory:"sharing"},sensitive_info_storage:{purpose:"marketing",listenGpc:!0,cpraCategory:"sensitive"}},translations:{en:{mainBanner:{position:"bottom",heading:"Your California Privacy Rights",htmlText:"Under the California Privacy Rights Act (CPRA), you have the right to opt out of the sale, sharing, and use of sensitive personal information. We use cookies and tracking technologies that may involve the sale or sharing of your data with third parties.",buttons:{"accept-all":{text:"Accept All",style:"primary",action:"custom",cookies:"*"},"opt-out-sale-sharing-sensitive":{text:"Opt Out of Sale, Sharing & Sensitive Use",style:"secondary",action:"custom",cookies:"!"},manage:{text:"Manage",style:"text",action:"manage"}}},gpcBanner:{position:"bottom",heading:"GPC opt-out applied automatically",htmlText:"Your browser sent a Global Privacy Control signal. Under the CPRA, we are required to honor this as a Do Not Sell or Share My Personal Information request. Your opt-out has been applied automatically.",buttons:{"accept-all":{text:"Accept All",style:"primary",action:"custom",cookies:"*"},"confirm-opt-out":{text:"Confirm Opt-Out",style:"secondary",action:"custom",cookies:"!"},"review-choices":{text:"Review Choices",style:"text",action:"manage"}}},preferenceModal:{position:"right",heading:"Privacy Rights Center",subheading:"Manage your CPRA rights: opt out of sale, sharing, and limit the use of sensitive personal information.",htmlText:"As a California resident, you have the right under CPRA to opt out of the sale and sharing of your personal information, including for cross-context behavioral advertising, and to limit the use of your sensitive personal information. Toggle each category below to exercise your rights.",buttons:{"accept-all":{text:"Accept All",style:"primary",action:"custom",cookies:"*"},"opt-out-sale-sharing-sensitive":{text:"Opt Out of Sale, Sharing & Sensitive Use",style:"secondary",action:"custom",cookies:"!"},"save-choices":{text:"Save My Choices",style:"primary",action:"submit"}},categories:{necessary:{heading:"Strictly Necessary",htmlText:"Essential to deliver the service. These cookies are not sold or shared and cannot be disabled.",legalBasis:"mandatory",cookies:["security_storage"]},functional:{heading:"Functional & Personalisation",htmlText:"Improve site functionality and remember your preferences. May involve sharing of browsing data.",legalBasis:"consent",cookies:["functionality_storage","personalization_storage"]},analytics:{heading:"Analytics (Sharing)",htmlText:'Measure site performance. Analytics data may be shared with third-party providers, which constitutes "sharing" under CPRA.',legalBasis:"consent",cookies:["analytics_storage"]},marketing:{heading:"Sale & Sharing of Personal Data",htmlText:"Advertising and retargeting cookies that involve the sale or sharing of your personal data with third-party advertisers for cross-context behavioural advertising.",legalBasis:"consent",cookies:["ad_storage"]},sensitive:{heading:"Sensitive Personal Information",htmlText:"Some technologies may use sensitive personal information as defined by CPRA (e.g. precise geolocation, health data). You have the right to limit such use.",legalBasis:"consent",cookies:["sensitive_info_storage"]}}}}}}});var Kt,Kn=I(()=>{"use strict";p();Kt={complianceGroup:"opt-in-dpdpa",gpcMode:"ignore",defaultLocale:"en",expiryDays:365,cookies:{security_storage:{purpose:"necessary",listenGpc:!1},functionality_storage:{purpose:"functional",listenGpc:!1},personalization_storage:{purpose:"preferences",listenGpc:!1},analytics_storage:{purpose:"analytics",listenGpc:!1},ad_storage:{purpose:"marketing",listenGpc:!1}},translations:{en:{mainBanner:{position:"bottom",heading:"Data Protection Notice",htmlText:"We are the Data Fiduciary under India's Digital Personal Data Protection Act (DPDPA). Your explicit consent is required before we process your personal data using non-essential cookies. You may withdraw consent at any time without affecting prior processing.",buttons:{"consent-all":{text:"I Consent",style:"primary",action:"custom",cookies:"*"},"deny-all":{text:"I Do Not Consent",style:"secondary",action:"custom",cookies:"!"},"review-choices":{text:"Review Choices",style:"text",action:"manage"}}},preferenceModal:{position:"right",heading:"Consent Preferences",subheading:"Review the purposes for which we process your personal data and provide or withdraw consent for each.",htmlText:"Under the Digital Personal Data Protection Act (DPDPA) 2023, you have the right to give, manage, and withdraw consent for personal data processing. Legitimate interest is not a valid legal basis under the DPDPA \u2014 all data processing requires your explicit consent.",buttons:{"consent-all":{text:"Give Consent to All",style:"primary",action:"custom",cookies:"*"},"withdraw-all":{text:"Withdraw All Consent",style:"secondary",action:"custom",cookies:"!"},"save-choices":{text:"Save Choices",style:"secondary",action:"submit"}},categories:{necessary:{heading:"Strictly Necessary",htmlText:"Required to deliver the core service. No personal data is shared and consent is not required for these.",legalBasis:"mandatory",cookies:["security_storage"]},functional:{heading:"Functional",htmlText:"Enable enhanced features and personalisation. Your explicit consent is required under the DPDPA before we process data for these purposes.",legalBasis:"consent",cookies:["functionality_storage","personalization_storage"]},analytics:{heading:"Analytics",htmlText:"Help us understand how you interact with the site. Your consent is required before any analytics data is collected.",legalBasis:"consent",cookies:["analytics_storage"]},marketing:{heading:"Marketing & Advertising",htmlText:"Allow personalised advertising based on your browsing activity. Requires your explicit consent under the DPDPA.",legalBasis:"consent",cookies:["ad_storage"]}}}}}}});var Yt,Yn=I(()=>{"use strict";p();Yt={complianceGroup:"opt-in-china",gpcMode:"ignore",defaultLocale:"en",expiryDays:365,cookies:{security_storage:{purpose:"necessary",listenGpc:!1},functionality_storage:{purpose:"functional",listenGpc:!1},personalization_storage:{purpose:"preferences",listenGpc:!1},analytics_storage:{purpose:"analytics",listenGpc:!1},ad_storage:{purpose:"marketing",listenGpc:!1}},translations:{en:{mainBanner:{position:"bottom",heading:"Personal Information Processing Notice",htmlText:"In accordance with China's Personal Information Protection Law (PIPL), Data Security Law (DSL), and Cybersecurity Law (CSL), we process personal information only for specified, explicit, and legitimate purposes with minimum data collection. Your consent is required for non-essential cookies.",buttons:{"agree-all":{text:"Agree to All",style:"primary",action:"custom",cookies:"*"},"reject-non-necessary":{text:"Reject Non-Necessary",style:"secondary",action:"custom",cookies:"!"},"manage-preferences":{text:"Manage Preferences",style:"text",action:"manage"}}},preferenceModal:{position:"right",heading:"Personal Information Processing Settings",subheading:"Review the purpose and scope of each category of personal information processing.",htmlText:"Under the PIPL, you have the right to know, decide, and restrict the processing of your personal information. Processing is limited to the stated purposes. Cross-border transfers of your data, if any, are handled in accordance with Chapter III of the PIPL, including security assessments or standard contracts where applicable.",buttons:{"agree-all":{text:"Agree to All",style:"primary",action:"custom",cookies:"*"},"disagree-all":{text:"Disagree to All",style:"secondary",action:"custom",cookies:"!"},"confirm-settings":{text:"Confirm Settings",style:"primary",action:"submit"}},categories:{necessary:{heading:"Necessary for Service",htmlText:"Required to deliver the core service and ensure network security under the CSL. Cannot be disabled.",legalBasis:"mandatory",cookies:["security_storage"]},functional:{heading:"Functionality & Personalisation",htmlText:"Enable enhanced features. Personal information is processed only for the stated purposes and retained for no longer than necessary.",legalBasis:"consent",cookies:["functionality_storage","personalization_storage"]},analytics:{heading:"Statistical Analysis",htmlText:"Collect and analyse usage data to improve the service. Data is processed within China unless cross-border transfer requirements are satisfied.",legalBasis:"consent",cookies:["analytics_storage"]},marketing:{heading:"Targeted Advertising",htmlText:"Personalise advertisements based on your interactions. Requires explicit consent under PIPL. You may withdraw consent and object to personalised advertising at any time.",legalBasis:"consent",cookies:["ad_storage"]}}}}}}});var Qt,Qn=I(()=>{"use strict";p();Qt={complianceGroup:"opt-in-brazil",gpcMode:"ignore",defaultLocale:"en",expiryDays:365,cookies:{security_storage:{purpose:"necessary",listenGpc:!1},functionality_storage:{purpose:"functional",listenGpc:!1},personalization_storage:{purpose:"preferences",listenGpc:!1},analytics_storage:{purpose:"analytics",listenGpc:!1},ad_storage:{purpose:"marketing",listenGpc:!1}},translations:{en:{mainBanner:{position:"bottom",heading:"We value your privacy",htmlText:"In accordance with Brazil's Lei Geral de Prote\xE7\xE3o de Dados (LGPD), we process personal data only with a valid legal basis. Non-essential cookies require your prior consent. You may withdraw consent at any time. Legitimate interest applies where noted.",buttons:{"accept-all":{text:"Accept All",style:"primary",action:"custom",cookies:"*"},"reject-optional":{text:"Reject Optional",style:"secondary",action:"custom",cookies:"!"},manage:{text:"Manage",style:"text",action:"manage"}}},preferenceModal:{position:"right",heading:"Privacy Preferences",subheading:"Review and manage your data processing preferences under the LGPD.",htmlText:"You have rights under the LGPD including: access, correction, deletion, portability, and withdrawal of consent. Categories based on legitimate interest are indicated below \u2014 you may object to these at any time.",buttons:{"accept-all":{text:"Accept All",style:"primary",action:"custom",cookies:"*"},"reject-optional":{text:"Reject Optional",style:"secondary",action:"custom",cookies:"!"},"save-preferences":{text:"Save My Preferences",style:"primary",action:"submit"}},categories:{necessary:{heading:"Strictly Necessary",htmlText:"Essential for the service to function. Legal basis: fulfillment of a contract or legal obligation. Cannot be disabled.",legalBasis:"mandatory",cookies:["security_storage"]},functional:{heading:"Functional",htmlText:"Enhance site functionality and remember your settings. Legal basis: legitimate interest (LGPD Art. 7, X). You may object to this processing at any time.",legalBasis:"legitimate_interest",legitimateInterestDescription:"Remembering a visitor's in-session preferences (e.g. layout, saved settings) is necessary to deliver the functionality they engaged with, has minimal privacy impact since no data is shared with third parties, and is limited to what a visitor would reasonably expect from using the site, per the balancing test required by LGPD Art. 10.",cookies:["functionality_storage","personalization_storage"]},analytics:{heading:"Analytics",htmlText:"Help us understand how visitors use the site so we can improve it. Legal basis: your consent.",legalBasis:"consent",cookies:["analytics_storage"]},marketing:{heading:"Marketing & Advertising",htmlText:"Personalise ads and measure campaign effectiveness. Legal basis: your consent. You may withdraw consent at any time without affecting the lawfulness of prior processing.",legalBasis:"consent",cookies:["ad_storage"]}}}}}}});var Zt,Zn=I(()=>{"use strict";p();Zt={complianceGroup:"general-privacy-consent",gpcMode:"ignore",defaultLocale:"en",expiryDays:365,cookies:{security_storage:{purpose:"necessary",listenGpc:!1},functionality_storage:{purpose:"functional",listenGpc:!1},personalization_storage:{purpose:"preferences",listenGpc:!1},analytics_storage:{purpose:"analytics",listenGpc:!1},ad_storage:{purpose:"marketing",listenGpc:!1}},translations:{en:{mainBanner:{position:"bottom",heading:"We use cookies",htmlText:"We use cookies to improve your browsing experience, analyse site traffic, and show you relevant content. By continuing to use this site, you accept our use of cookies. You can manage your preferences at any time.",buttons:{"accept-all":{text:"Accept All",style:"primary",action:"custom",cookies:"*"},"reject-marketing":{text:"Reject Marketing",style:"secondary",action:"custom",cookies:["security_storage","functionality_storage","personalization_storage","analytics_storage"]},"manage-preferences":{text:"Manage Preferences",style:"text",action:"manage"}}},preferenceModal:{position:"right",heading:"Cookie Settings",subheading:"We document the legal basis for each category of cookie we use.",htmlText:"A privacy notice or consent framework applies in your jurisdiction. While a strict cookie consent banner may not be legally required, we document our legal basis for processing to follow privacy best practices.",buttons:{"accept-all":{text:"Accept All",style:"primary",action:"custom",cookies:"*"},"necessary-only":{text:"Necessary Only",style:"secondary",action:"custom",cookies:"!"},"save-preferences":{text:"Save My Settings",style:"primary",action:"submit"}},categories:{necessary:{heading:"Strictly Necessary",htmlText:"Required to deliver the service. No optional data processing takes place. Cannot be disabled.",legalBasis:"mandatory",cookies:["security_storage"]},functional:{heading:"Functional",htmlText:"Improve how the site works and remember your preferences. Legal basis: legitimate interest.",legalBasis:"legitimate_interest",legitimateInterestDescription:"Remembering a visitor's in-session preferences (e.g. layout, saved settings) is a low-privacy-impact processing activity that a visitor would reasonably expect from using the site, and is necessary to deliver the functionality they engaged with \u2014 our interest in providing it is not overridden by the visitor's privacy interest, since no data leaves the site and nothing is used for profiling or advertising.",cookies:["functionality_storage","personalization_storage"]},analytics:{heading:"Analytics",htmlText:"Help us understand usage patterns to improve the site. Legal basis: legitimate interest. Data is aggregated and anonymised where possible.",legalBasis:"legitimate_interest",legitimateInterestDescription:"Measuring aggregate, anonymised site usage to improve performance and content is a reasonable, low-risk business interest that does not identify individual visitors or feed advertising/profiling, and is proportionate to the minimal impact on visitor privacy.",cookies:["analytics_storage"]},marketing:{heading:"Marketing",htmlText:"Personalise advertising and measure campaign reach. Legal basis: your consent. You may withdraw consent at any time.",legalBasis:"consent",cookies:["ad_storage"]}}}}}}});var Xt,Xn=I(()=>{"use strict";p();Xt={complianceGroup:"notice-only",gpcMode:"ignore",defaultLocale:"en",expiryDays:365,cookies:{security_storage:{purpose:"necessary",listenGpc:!1}},translations:{en:{mainBanner:{position:"bottom",heading:"This site uses essential cookies only",htmlText:"We use strictly necessary cookies to ensure this website functions correctly. No tracking, advertising, or analytics cookies are used. No specific cookie consent law applies in your jurisdiction.",buttons:{ok:{text:"OK",style:"primary",action:"close"}}},preferenceModal:{position:"right",heading:"Cookie Information",subheading:"We only use cookies that are strictly necessary for this site to work.",htmlText:"This site does not use optional cookies. The only cookie set is required to maintain basic security and session integrity. You cannot disable it without affecting site functionality.",buttons:{close:{text:"Close",style:"primary",action:"close"}},categories:{necessary:{heading:"Strictly Necessary",htmlText:"Required for the site to function. These cookies do not track you and cannot be disabled.",legalBasis:"mandatory",cookies:["security_storage"]}}}}}}});var Mo,Go=I(()=>{"use strict";p();Mo={mainBanner:{heading:"Wir sch\xE4tzen Ihre Privatsph\xE4re",htmlText:"Wir verwenden Cookies, um Ihre Browser-Erfahrung zu verbessern, personalisierte Inhalte oder Anzeigen bereitzustellen und unseren Datenverkehr zu analysieren. Mit dem Klicken auf <strong>Alle akzeptieren</strong> stimmen Sie der Verwendung von Cookies zu. Sie k\xF6nnen Ihre Einstellungen jederzeit \xE4ndern.",buttons:{"accept-all":"Alle akzeptieren","reject-optional":"Alle ablehnen","manage-preferences":"Einstellungen verwalten"}},gpcBanner:{heading:"Datenschutzpr\xE4ferenz erkannt",htmlText:"Ihr Browser hat ein Global Privacy Control (GPC) Signal gesendet. Wir haben Ihre Datenschutzpr\xE4ferenz ber\xFCcksichtigt.",buttons:{"accept-all":"Einstellungen \xFCberpr\xFCfen","confirm-settings":"Weiter"}},preferenceModal:{heading:"Datenschutzeinstellungen",subheading:"W\xE4hlen Sie aus, welche Cookies Sie erlauben.",htmlText:"Wir verwenden verschiedene Cookie-Typen. Sie k\xF6nnen die einzelnen Kategorien aktivieren oder deaktivieren. Notwendige Cookies k\xF6nnen nicht deaktiviert werden.",buttons:{"accept-all":"Alle akzeptieren","reject-optional":"Alle ablehnen","save-preferences":"Auswahl speichern"},categories:{"cat-necessary":{heading:"Unbedingt erforderlich",htmlText:"Diese Cookies sind f\xFCr das Funktionieren der Website unbedingt erforderlich und k\xF6nnen nicht deaktiviert werden."},"cat-functional":{heading:"Funktional",htmlText:"Erm\xF6glichen erweiterte Funktionen wie gespeicherte Pr\xE4ferenzen und Personalisierung."},"cat-preferences":{heading:"Pr\xE4ferenzen",htmlText:"Speichern Ihre pers\xF6nlichen Einstellungen und Pr\xE4ferenzen f\xFCr zuk\xFCnftige Besuche."},"cat-analytics":{heading:"Analyse",htmlText:"Helfen uns zu verstehen, wie Besucher mit unserer Website interagieren."},"cat-marketing":{heading:"Marketing",htmlText:"Werden verwendet, um Ihnen relevante Werbung anzuzeigen."}}}}});var jo,Bo=I(()=>{"use strict";p();jo={mainBanner:{heading:"Valoramos su privacidad",htmlText:"Utilizamos cookies para mejorar su experiencia de navegaci\xF3n, mostrar anuncios o contenido personalizados y analizar nuestro tr\xE1fico. Al hacer clic en <strong>Aceptar todo</strong>, consiente el uso de cookies. Puede cambiar sus preferencias en cualquier momento.",buttons:{"accept-all":"Aceptar todo","reject-optional":"Rechazar todo","manage-preferences":"Gestionar preferencias"}},gpcBanner:{heading:"Preferencia de privacidad reconocida",htmlText:"Su navegador ha enviado una se\xF1al Global Privacy Control (GPC). Hemos aplicado su preferencia de privacidad.",buttons:{"accept-all":"Revisar preferencias","confirm-settings":"Continuar"}},preferenceModal:{heading:"Preferencias de privacidad",subheading:"Elija qu\xE9 cookies desea permitir.",htmlText:"Utilizamos distintos tipos de cookies. Puede activar o desactivar cada categor\xEDa. Las cookies necesarias no pueden desactivarse.",buttons:{"accept-all":"Aceptar todo","reject-optional":"Rechazar todo","save-preferences":"Guardar selecci\xF3n"},categories:{"cat-necessary":{heading:"Estrictamente necesarias",htmlText:"Estas cookies son imprescindibles para el funcionamiento del sitio web y no pueden desactivarse."},"cat-functional":{heading:"Funcionales",htmlText:"Permiten funciones avanzadas como preferencias guardadas y personalizaci\xF3n."},"cat-preferences":{heading:"Preferencias",htmlText:"Guardan su configuraci\xF3n personal y preferencias para visitas futuras."},"cat-analytics":{heading:"Anal\xEDticas",htmlText:"Nos ayudan a entender c\xF3mo los visitantes interact\xFAan con nuestro sitio web."},"cat-marketing":{heading:"Marketing",htmlText:"Se utilizan para mostrarle publicidad relevante."}}}}});var Fo,$o=I(()=>{"use strict";p();Fo={mainBanner:{heading:"Nous respectons votre vie priv\xE9e",htmlText:"Nous utilisons des cookies pour am\xE9liorer votre exp\xE9rience de navigation, afficher des publicit\xE9s ou du contenu personnalis\xE9s et analyser notre trafic. En cliquant sur <strong>Tout accepter</strong>, vous consentez \xE0 l'utilisation des cookies. Vous pouvez modifier vos pr\xE9f\xE9rences \xE0 tout moment.",buttons:{"accept-all":"Tout accepter","reject-optional":"Tout refuser","manage-preferences":"G\xE9rer les pr\xE9f\xE9rences"}},gpcBanner:{heading:"Pr\xE9f\xE9rence de confidentialit\xE9 reconnue",htmlText:"Votre navigateur a envoy\xE9 un signal Global Privacy Control (GPC). Nous avons appliqu\xE9 votre pr\xE9f\xE9rence de confidentialit\xE9.",buttons:{"accept-all":"V\xE9rifier les pr\xE9f\xE9rences","confirm-settings":"Continuer"}},preferenceModal:{heading:"Param\xE8tres de confidentialit\xE9",subheading:"Choisissez les cookies que vous souhaitez autoriser.",htmlText:"Nous utilisons diff\xE9rents types de cookies. Vous pouvez activer ou d\xE9sactiver chaque cat\xE9gorie. Les cookies n\xE9cessaires ne peuvent pas \xEAtre d\xE9sactiv\xE9s.",buttons:{"accept-all":"Tout accepter","reject-optional":"Tout refuser","save-preferences":"Enregistrer la s\xE9lection"},categories:{"cat-necessary":{heading:"Strictement n\xE9cessaires",htmlText:"Ces cookies sont indispensables au fonctionnement du site web et ne peuvent pas \xEAtre d\xE9sactiv\xE9s."},"cat-functional":{heading:"Fonctionnels",htmlText:"Permettent des fonctionnalit\xE9s avanc\xE9es comme les pr\xE9f\xE9rences enregistr\xE9es et la personnalisation."},"cat-preferences":{heading:"Pr\xE9f\xE9rences",htmlText:"Sauvegardent vos param\xE8tres personnels et pr\xE9f\xE9rences pour les visites futures."},"cat-analytics":{heading:"Analytiques",htmlText:"Nous aident \xE0 comprendre comment les visiteurs interagissent avec notre site web."},"cat-marketing":{heading:"Marketing",htmlText:"Sont utilis\xE9s pour vous afficher des publicit\xE9s pertinentes."}}}}});var Ho,Vo=I(()=>{"use strict";p();Ho={mainBanner:{heading:"\u30D7\u30E9\u30A4\u30D0\u30B7\u30FC\u3092\u5927\u5207\u306B\u3057\u3066\u3044\u307E\u3059",htmlText:"\u30D6\u30E9\u30A6\u30B8\u30F3\u30B0\u4F53\u9A13\u306E\u5411\u4E0A\u3001\u30D1\u30FC\u30BD\u30CA\u30E9\u30A4\u30BA\u3055\u308C\u305F\u5E83\u544A\u30FB\u30B3\u30F3\u30C6\u30F3\u30C4\u306E\u8868\u793A\u3001\u30C8\u30E9\u30D5\u30A3\u30C3\u30AF\u5206\u6790\u306E\u305F\u3081\u306BCookie\u3092\u4F7F\u7528\u3057\u3066\u3044\u307E\u3059\u3002<strong>\u3059\u3079\u3066\u540C\u610F</strong>\u3092\u30AF\u30EA\u30C3\u30AF\u3059\u308B\u3053\u3068\u3067\u3001Cookie\u306E\u4F7F\u7528\u306B\u540C\u610F\u3057\u305F\u3053\u3068\u306B\u306A\u308A\u307E\u3059\u3002\u8A2D\u5B9A\u306F\u3044\u3064\u3067\u3082\u5909\u66F4\u3067\u304D\u307E\u3059\u3002",buttons:{"accept-all":"\u3059\u3079\u3066\u540C\u610F","reject-optional":"\u3059\u3079\u3066\u62D2\u5426","manage-preferences":"\u8A2D\u5B9A\u3092\u7BA1\u7406"}},gpcBanner:{heading:"\u30D7\u30E9\u30A4\u30D0\u30B7\u30FC\u8A2D\u5B9A\u304C\u691C\u51FA\u3055\u308C\u307E\u3057\u305F",htmlText:"\u30D6\u30E9\u30A6\u30B6\u304B\u3089Global Privacy Control\uFF08GPC\uFF09\u30B7\u30B0\u30CA\u30EB\u304C\u9001\u4FE1\u3055\u308C\u307E\u3057\u305F\u3002\u304A\u5BA2\u69D8\u306E\u30D7\u30E9\u30A4\u30D0\u30B7\u30FC\u8A2D\u5B9A\u3092\u9069\u7528\u3057\u307E\u3057\u305F\u3002",buttons:{"accept-all":"\u8A2D\u5B9A\u3092\u78BA\u8A8D","confirm-settings":"\u7D9A\u884C"}},preferenceModal:{heading:"\u30D7\u30E9\u30A4\u30D0\u30B7\u30FC\u8A2D\u5B9A",subheading:"\u8A31\u53EF\u3059\u308BCookie\u3092\u9078\u629E\u3057\u3066\u304F\u3060\u3055\u3044\u3002",htmlText:"\u3055\u307E\u3056\u307E\u306A\u7A2E\u985E\u306ECookie\u3092\u4F7F\u7528\u3057\u3066\u3044\u307E\u3059\u3002\u5404\u30AB\u30C6\u30B4\u30EA\u3092\u6709\u52B9\u307E\u305F\u306F\u7121\u52B9\u306B\u3059\u308B\u3053\u3068\u304C\u3067\u304D\u307E\u3059\u3002\u5FC5\u9808Cookie\u306F\u7121\u52B9\u306B\u3067\u304D\u307E\u305B\u3093\u3002",buttons:{"accept-all":"\u3059\u3079\u3066\u540C\u610F","reject-optional":"\u3059\u3079\u3066\u62D2\u5426","save-preferences":"\u9078\u629E\u3092\u4FDD\u5B58"},categories:{"cat-necessary":{heading:"\u5FC5\u9808",htmlText:"\u3053\u308C\u3089\u306ECookie\u306F\u30A6\u30A7\u30D6\u30B5\u30A4\u30C8\u306E\u6A5F\u80FD\u306B\u4E0D\u53EF\u6B20\u3067\u3042\u308A\u3001\u7121\u52B9\u306B\u3059\u308B\u3053\u3068\u306F\u3067\u304D\u307E\u305B\u3093\u3002"},"cat-functional":{heading:"\u6A5F\u80FD",htmlText:"\u4FDD\u5B58\u3055\u308C\u305F\u8A2D\u5B9A\u3084\u30D1\u30FC\u30BD\u30CA\u30E9\u30A4\u30BC\u30FC\u30B7\u30E7\u30F3\u306A\u3069\u306E\u9AD8\u5EA6\u306A\u6A5F\u80FD\u3092\u6709\u52B9\u306B\u3057\u307E\u3059\u3002"},"cat-preferences":{heading:"\u8A2D\u5B9A",htmlText:"\u5C06\u6765\u306E\u8A2A\u554F\u306E\u305F\u3081\u306B\u500B\u4EBA\u8A2D\u5B9A\u3084\u597D\u307F\u3092\u4FDD\u5B58\u3057\u307E\u3059\u3002"},"cat-analytics":{heading:"\u5206\u6790",htmlText:"\u8A2A\u554F\u8005\u304C\u3069\u306E\u3088\u3046\u306B\u30A6\u30A7\u30D6\u30B5\u30A4\u30C8\u3092\u5229\u7528\u3057\u3066\u3044\u308B\u304B\u3092\u7406\u89E3\u3059\u308B\u306E\u306B\u5F79\u7ACB\u3061\u307E\u3059\u3002"},"cat-marketing":{heading:"\u30DE\u30FC\u30B1\u30C6\u30A3\u30F3\u30B0",htmlText:"\u95A2\u9023\u3059\u308B\u5E83\u544A\u3092\u8868\u793A\u3059\u308B\u305F\u3081\u306B\u4F7F\u7528\u3055\u308C\u307E\u3059\u3002"}}}}});var Wo,qo=I(()=>{"use strict";p();Wo={mainBanner:{heading:"Wir verwenden Cookies",htmlText:"Wir verwenden Cookies, um unsere Dienste zu verbessern. Sie k\xF6nnen dem Verkauf oder der Weitergabe Ihrer pers\xF6nlichen Daten jederzeit widersprechen.",buttons:{"accept-all":"Alle akzeptieren","do-not-sell-share":"Nicht verkaufen oder weitergeben","manage-preferences":"Einstellungen verwalten"}},gpcBanner:{heading:"GPC erkannt \u2013 Opt-out angewendet",htmlText:"Ihr Browser hat ein Global Privacy Control Signal gesendet. Wir haben Sie vom Verkauf und der Weitergabe Ihrer Daten abgemeldet.",buttons:{"accept-all":"Einstellungen \xFCberpr\xFCfen","confirm-opt-out":"Weiter"}},preferenceModal:{heading:"Datenschutzeinstellungen",subheading:"W\xE4hlen Sie Ihre Datenschutzoptionen.",buttons:{"accept-all":"Alle akzeptieren","opt-out-all":"Nicht verkaufen oder weitergeben","save-choices":"Auswahl speichern"},categories:{"cat-necessary":{heading:"Unbedingt erforderlich",htmlText:"Diese Cookies sind f\xFCr das Funktionieren der Website unbedingt erforderlich."},"cat-functional":{heading:"Funktional",htmlText:"Erm\xF6glichen erweiterte Funktionen und Personalisierung."},"cat-preferences":{heading:"Pr\xE4ferenzen",htmlText:"Speichern Ihre Einstellungen f\xFCr zuk\xFCnftige Besuche."},"cat-analytics":{heading:"Analyse",htmlText:"Helfen uns zu verstehen, wie Besucher unsere Website nutzen."},"cat-marketing":{heading:"Werbung / Verkauf",htmlText:"Erm\xF6glichen gezielte Werbung. Sie k\xF6nnen dem Verkauf Ihrer Daten widersprechen."}}}}});var Jo,zo=I(()=>{"use strict";p();Jo={mainBanner:{heading:"Utilizamos cookies",htmlText:"Utilizamos cookies para mejorar nuestros servicios. Puede oponerse a la venta o al intercambio de sus datos personales en cualquier momento.",buttons:{"accept-all":"Aceptar todo","do-not-sell-share":"No vender ni compartir","manage-preferences":"Gestionar preferencias"}},gpcBanner:{heading:"GPC detectado \u2013 exclusi\xF3n aplicada",htmlText:"Su navegador ha enviado una se\xF1al Global Privacy Control. Le hemos excluido de la venta y el intercambio de sus datos.",buttons:{"accept-all":"Revisar preferencias","confirm-opt-out":"Continuar"}},preferenceModal:{heading:"Preferencias de privacidad",subheading:"Elija sus opciones de privacidad.",buttons:{"accept-all":"Aceptar todo","opt-out-all":"No vender ni compartir","save-choices":"Guardar selecci\xF3n"},categories:{"cat-necessary":{heading:"Estrictamente necesarias",htmlText:"Imprescindibles para el funcionamiento del sitio web."},"cat-functional":{heading:"Funcionales",htmlText:"Permiten funciones avanzadas y personalizaci\xF3n."},"cat-preferences":{heading:"Preferencias",htmlText:"Guardan su configuraci\xF3n para visitas futuras."},"cat-analytics":{heading:"Anal\xEDticas",htmlText:"Nos ayudan a entender c\xF3mo los visitantes utilizan nuestro sitio."},"cat-marketing":{heading:"Publicidad / Venta",htmlText:"Permiten publicidad dirigida. Puede oponerse a la venta de sus datos."}}}}});var Ko,Yo=I(()=>{"use strict";p();Ko={mainBanner:{heading:"Nous utilisons des cookies",htmlText:"Nous utilisons des cookies pour am\xE9liorer nos services. Vous pouvez vous opposer \xE0 la vente ou au partage de vos donn\xE9es personnelles \xE0 tout moment.",buttons:{"accept-all":"Tout accepter","do-not-sell-share":"Ne pas vendre ni partager","manage-preferences":"G\xE9rer les pr\xE9f\xE9rences"}},gpcBanner:{heading:"GPC d\xE9tect\xE9 \u2013 exclusion appliqu\xE9e",htmlText:"Votre navigateur a envoy\xE9 un signal Global Privacy Control. Nous avons appliqu\xE9 votre demande de ne pas vendre ni partager vos donn\xE9es.",buttons:{"accept-all":"V\xE9rifier les pr\xE9f\xE9rences","confirm-opt-out":"Continuer"}},preferenceModal:{heading:"Param\xE8tres de confidentialit\xE9",subheading:"Choisissez vos options de confidentialit\xE9.",buttons:{"accept-all":"Tout accepter","opt-out-all":"Ne pas vendre ni partager","save-choices":"Enregistrer la s\xE9lection"},categories:{"cat-necessary":{heading:"Strictement n\xE9cessaires",htmlText:"Indispensables au fonctionnement du site web."},"cat-functional":{heading:"Fonctionnels",htmlText:"Permettent des fonctionnalit\xE9s avanc\xE9es et la personnalisation."},"cat-preferences":{heading:"Pr\xE9f\xE9rences",htmlText:"Sauvegardent vos param\xE8tres pour les visites futures."},"cat-analytics":{heading:"Analytiques",htmlText:"Nous aident \xE0 comprendre comment les visiteurs utilisent notre site."},"cat-marketing":{heading:"Publicit\xE9 / Vente",htmlText:"Permettent la publicit\xE9 cibl\xE9e. Vous pouvez vous opposer \xE0 la vente de vos donn\xE9es."}}}}});var Qo,Zo=I(()=>{"use strict";p();Qo={mainBanner:{heading:"Cookie\u3092\u4F7F\u7528\u3057\u3066\u3044\u307E\u3059",htmlText:"\u30B5\u30FC\u30D3\u30B9\u5411\u4E0A\u306E\u305F\u3081\u306BCookie\u3092\u4F7F\u7528\u3057\u3066\u3044\u307E\u3059\u3002\u500B\u4EBA\u30C7\u30FC\u30BF\u306E\u8CA9\u58F2\u3084\u5171\u6709\u306B\u306F\u3044\u3064\u3067\u3082\u7570\u8B70\u3092\u7533\u3057\u7ACB\u3066\u308B\u3053\u3068\u304C\u3067\u304D\u307E\u3059\u3002",buttons:{"accept-all":"\u3059\u3079\u3066\u540C\u610F","do-not-sell-share":"\u8CA9\u58F2\u30FB\u5171\u6709\u3057\u306A\u3044","manage-preferences":"\u8A2D\u5B9A\u3092\u7BA1\u7406"}},gpcBanner:{heading:"GPC\u691C\u51FA \u2013 \u30AA\u30D7\u30C8\u30A2\u30A6\u30C8\u9069\u7528\u6E08\u307F",htmlText:"\u30D6\u30E9\u30A6\u30B6\u304B\u3089Global Privacy Control\u30B7\u30B0\u30CA\u30EB\u304C\u9001\u4FE1\u3055\u308C\u307E\u3057\u305F\u3002\u30C7\u30FC\u30BF\u306E\u8CA9\u58F2\u304A\u3088\u3073\u5171\u6709\u304B\u3089\u30AA\u30D7\u30C8\u30A2\u30A6\u30C8\u3057\u307E\u3057\u305F\u3002",buttons:{"accept-all":"\u8A2D\u5B9A\u3092\u78BA\u8A8D","confirm-opt-out":"\u7D9A\u884C"}},preferenceModal:{heading:"\u30D7\u30E9\u30A4\u30D0\u30B7\u30FC\u8A2D\u5B9A",subheading:"\u30D7\u30E9\u30A4\u30D0\u30B7\u30FC\u30AA\u30D7\u30B7\u30E7\u30F3\u3092\u9078\u629E\u3057\u3066\u304F\u3060\u3055\u3044\u3002",buttons:{"accept-all":"\u3059\u3079\u3066\u540C\u610F","opt-out-all":"\u8CA9\u58F2\u30FB\u5171\u6709\u3057\u306A\u3044","save-choices":"\u9078\u629E\u3092\u4FDD\u5B58"},categories:{"cat-necessary":{heading:"\u5FC5\u9808",htmlText:"\u30A6\u30A7\u30D6\u30B5\u30A4\u30C8\u306E\u6A5F\u80FD\u306B\u4E0D\u53EF\u6B20\u3067\u3059\u3002"},"cat-functional":{heading:"\u6A5F\u80FD",htmlText:"\u9AD8\u5EA6\u306A\u6A5F\u80FD\u3068\u30D1\u30FC\u30BD\u30CA\u30E9\u30A4\u30BC\u30FC\u30B7\u30E7\u30F3\u3092\u6709\u52B9\u306B\u3057\u307E\u3059\u3002"},"cat-preferences":{heading:"\u8A2D\u5B9A",htmlText:"\u5C06\u6765\u306E\u8A2A\u554F\u306E\u305F\u3081\u306B\u8A2D\u5B9A\u3092\u4FDD\u5B58\u3057\u307E\u3059\u3002"},"cat-analytics":{heading:"\u5206\u6790",htmlText:"\u8A2A\u554F\u8005\u306E\u30B5\u30A4\u30C8\u5229\u7528\u72B6\u6CC1\u3092\u628A\u63E1\u3059\u308B\u306E\u306B\u5F79\u7ACB\u3061\u307E\u3059\u3002"},"cat-marketing":{heading:"\u5E83\u544A\u30FB\u8CA9\u58F2",htmlText:"\u30BF\u30FC\u30B2\u30C3\u30C8\u5E83\u544A\u3092\u53EF\u80FD\u306B\u3057\u307E\u3059\u3002\u30C7\u30FC\u30BF\u306E\u8CA9\u58F2\u306B\u7570\u8B70\u3092\u7533\u3057\u7ACB\u3066\u308B\u3053\u3068\u304C\u3067\u304D\u307E\u3059\u3002"}}}}});var Xo,es=I(()=>{"use strict";p();Xo={mainBanner:{heading:"Datenschutzrechte in Kalifornien",htmlText:"Gem\xE4\xDF dem California Privacy Rights Act (CPRA) haben Sie das Recht, dem Verkauf, der Weitergabe und der Verwendung Ihrer pers\xF6nlichen Daten zu widersprechen.",buttons:{"accept-all":"Alle akzeptieren","opt-out-sale-sharing-sensitive":"Meine Daten nicht verkaufen oder teilen",manage:"Einstellungen verwalten"}},gpcBanner:{heading:"GPC erkannt \u2013 CPRA-Opt-out angewendet",htmlText:"Ihr Global Privacy Control Signal wurde erkannt. Ihr Recht auf Opt-out gem\xE4\xDF CPRA wurde automatisch angewendet.",buttons:{"accept-all":"Einstellungen \xFCberpr\xFCfen","confirm-opt-out":"Weiter"}},preferenceModal:{heading:"Datenschutzeinstellungen (CPRA)",subheading:"Verwalten Sie Ihre Datenschutzrechte.",buttons:{"accept-all":"Alle akzeptieren","opt-out-sale-sharing-sensitive":"Meine Daten nicht verkaufen oder teilen","save-choices":"Auswahl speichern"},categories:{"cat-necessary":{heading:"Unbedingt erforderlich",htmlText:"F\xFCr den Betrieb der Website unbedingt erforderlich."},"cat-functional":{heading:"Funktional",htmlText:"Erm\xF6glichen erweiterte Funktionen."},"cat-preferences":{heading:"Pr\xE4ferenzen",htmlText:"Speichern Ihre pers\xF6nlichen Einstellungen."},"cat-analytics":{heading:"Analyse",htmlText:"Helfen uns, die Website-Nutzung zu verstehen."},"cat-marketing":{heading:"Verkauf / Weitergabe (CPRA)",htmlText:"Verkauf und Weitergabe pers\xF6nlicher Daten gem\xE4\xDF CPRA. Sie k\xF6nnen widersprechen."}}}}});var ts,ns=I(()=>{"use strict";p();ts={mainBanner:{heading:"Derechos de privacidad en California",htmlText:"De acuerdo con la Ley de Derechos de Privacidad de California (CPRA), tiene derecho a oponerse a la venta, el intercambio y el uso de sus datos personales.",buttons:{"accept-all":"Aceptar todo","opt-out-sale-sharing-sensitive":"No vender ni compartir mis datos",manage:"Gestionar preferencias"}},gpcBanner:{heading:"GPC detectado \u2013 exclusi\xF3n CPRA aplicada",htmlText:"Se ha detectado su se\xF1al Global Privacy Control. Su derecho de exclusi\xF3n seg\xFAn la CPRA se ha aplicado autom\xE1ticamente.",buttons:{"accept-all":"Revisar preferencias","confirm-opt-out":"Continuar"}},preferenceModal:{heading:"Configuraci\xF3n de privacidad (CPRA)",subheading:"Administre sus derechos de privacidad.",buttons:{"accept-all":"Aceptar todo","opt-out-sale-sharing-sensitive":"No vender ni compartir mis datos","save-choices":"Guardar selecci\xF3n"},categories:{"cat-necessary":{heading:"Estrictamente necesarias",htmlText:"Imprescindibles para el funcionamiento del sitio."},"cat-functional":{heading:"Funcionales",htmlText:"Permiten funciones avanzadas."},"cat-preferences":{heading:"Preferencias",htmlText:"Guardan su configuraci\xF3n personal."},"cat-analytics":{heading:"Anal\xEDticas",htmlText:"Nos ayudan a entender el uso del sitio."},"cat-marketing":{heading:"Venta / Intercambio (CPRA)",htmlText:"Venta e intercambio de datos personales seg\xFAn la CPRA. Puede oponerse."}}}}});var is,os=I(()=>{"use strict";p();is={mainBanner:{heading:"Droits \xE0 la vie priv\xE9e en Californie",htmlText:"Conform\xE9ment au California Privacy Rights Act (CPRA), vous avez le droit de vous opposer \xE0 la vente, au partage et \xE0 l'utilisation de vos donn\xE9es personnelles.",buttons:{"accept-all":"Tout accepter","opt-out-sale-sharing-sensitive":"Ne pas vendre ni partager mes donn\xE9es",manage:"G\xE9rer les pr\xE9f\xE9rences"}},gpcBanner:{heading:"GPC d\xE9tect\xE9 \u2013 exclusion CPRA appliqu\xE9e",htmlText:"Votre signal Global Privacy Control a \xE9t\xE9 d\xE9tect\xE9. Votre droit d'exclusion selon la CPRA a \xE9t\xE9 appliqu\xE9 automatiquement.",buttons:{"accept-all":"V\xE9rifier les pr\xE9f\xE9rences","confirm-opt-out":"Continuer"}},preferenceModal:{heading:"Param\xE8tres de confidentialit\xE9 (CPRA)",subheading:"G\xE9rez vos droits \xE0 la vie priv\xE9e.",buttons:{"accept-all":"Tout accepter","opt-out-sale-sharing-sensitive":"Ne pas vendre ni partager mes donn\xE9es","save-choices":"Enregistrer la s\xE9lection"},categories:{"cat-necessary":{heading:"Strictement n\xE9cessaires",htmlText:"Indispensables au fonctionnement du site."},"cat-functional":{heading:"Fonctionnels",htmlText:"Permettent des fonctionnalit\xE9s avanc\xE9es."},"cat-preferences":{heading:"Pr\xE9f\xE9rences",htmlText:"Sauvegardent vos param\xE8tres personnels."},"cat-analytics":{heading:"Analytiques",htmlText:"Nous aident \xE0 comprendre l'utilisation du site."},"cat-marketing":{heading:"Vente / Partage (CPRA)",htmlText:"Vente et partage de donn\xE9es personnelles selon la CPRA. Vous pouvez vous y opposer."}}}}});var ss,rs=I(()=>{"use strict";p();ss={mainBanner:{heading:"\u30AB\u30EA\u30D5\u30A9\u30EB\u30CB\u30A2\u5DDE\u306E\u30D7\u30E9\u30A4\u30D0\u30B7\u30FC\u6A29",htmlText:"\u30AB\u30EA\u30D5\u30A9\u30EB\u30CB\u30A2\u30FB\u30D7\u30E9\u30A4\u30D0\u30B7\u30FC\u6A29\u6CD5\uFF08CPRA\uFF09\u306B\u57FA\u3065\u304D\u3001\u304A\u5BA2\u69D8\u306B\u306F\u500B\u4EBA\u30C7\u30FC\u30BF\u306E\u8CA9\u58F2\u30FB\u5171\u6709\u30FB\u5229\u7528\u306B\u7570\u8B70\u3092\u7533\u3057\u7ACB\u3066\u308B\u6A29\u5229\u304C\u3042\u308A\u307E\u3059\u3002",buttons:{"accept-all":"\u3059\u3079\u3066\u540C\u610F","opt-out-sale-sharing-sensitive":"\u8CA9\u58F2\u30FB\u5171\u6709\u3057\u306A\u3044",manage:"\u8A2D\u5B9A\u3092\u7BA1\u7406"}},gpcBanner:{heading:"GPC\u691C\u51FA \u2013 CPRA\u30AA\u30D7\u30C8\u30A2\u30A6\u30C8\u9069\u7528\u6E08\u307F",htmlText:"\u30D6\u30E9\u30A6\u30B6\u304B\u3089Global Privacy Control\u30B7\u30B0\u30CA\u30EB\u304C\u691C\u51FA\u3055\u308C\u307E\u3057\u305F\u3002CPRA\u306B\u57FA\u3065\u304F\u30AA\u30D7\u30C8\u30A2\u30A6\u30C8\u6A29\u304C\u81EA\u52D5\u7684\u306B\u9069\u7528\u3055\u308C\u307E\u3057\u305F\u3002",buttons:{"accept-all":"\u8A2D\u5B9A\u3092\u78BA\u8A8D","confirm-opt-out":"\u7D9A\u884C"}},preferenceModal:{heading:"\u30D7\u30E9\u30A4\u30D0\u30B7\u30FC\u8A2D\u5B9A\uFF08CPRA\uFF09",subheading:"\u30D7\u30E9\u30A4\u30D0\u30B7\u30FC\u6A29\u3092\u7BA1\u7406\u3057\u3066\u304F\u3060\u3055\u3044\u3002",buttons:{"accept-all":"\u3059\u3079\u3066\u540C\u610F","opt-out-sale-sharing-sensitive":"\u8CA9\u58F2\u30FB\u5171\u6709\u3057\u306A\u3044","save-choices":"\u9078\u629E\u3092\u4FDD\u5B58"},categories:{"cat-necessary":{heading:"\u5FC5\u9808",htmlText:"\u30A6\u30A7\u30D6\u30B5\u30A4\u30C8\u306E\u52D5\u4F5C\u306B\u4E0D\u53EF\u6B20\u3067\u3059\u3002"},"cat-functional":{heading:"\u6A5F\u80FD",htmlText:"\u9AD8\u5EA6\u306A\u6A5F\u80FD\u3092\u6709\u52B9\u306B\u3057\u307E\u3059\u3002"},"cat-preferences":{heading:"\u8A2D\u5B9A",htmlText:"\u500B\u4EBA\u8A2D\u5B9A\u3092\u4FDD\u5B58\u3057\u307E\u3059\u3002"},"cat-analytics":{heading:"\u5206\u6790",htmlText:"\u30B5\u30A4\u30C8\u5229\u7528\u72B6\u6CC1\u306E\u628A\u63E1\u306B\u5F79\u7ACB\u3066\u307E\u3059\u3002"},"cat-marketing":{heading:"\u8CA9\u58F2\u30FB\u5171\u6709\uFF08CPRA\uFF09",htmlText:"CPRA\u306B\u57FA\u3065\u304F\u500B\u4EBA\u30C7\u30FC\u30BF\u306E\u8CA9\u58F2\u304A\u3088\u3073\u5171\u6709\u3002\u7570\u8B70\u3092\u7533\u3057\u7ACB\u3066\u308B\u3053\u3068\u304C\u3067\u304D\u307E\u3059\u3002"}}}}});var as,cs=I(()=>{"use strict";p();as={mainBanner:{heading:"Datenschutzhinweis",htmlText:"Wir sind der f\xFCr die Datenverarbeitung Verantwortliche gem\xE4\xDF dem Digitalen Personaldatenschutzgesetz (DPDPA) Indiens. Ihre Einwilligung ist erforderlich, bevor wir Ihre personenbezogenen Daten verarbeiten.",buttons:{"consent-all":"Ich stimme zu","deny-all":"Ich stimme nicht zu","review-choices":"Auswahl \xFCberpr\xFCfen"}},preferenceModal:{heading:"Datenschutzeinstellungen (DPDPA)",subheading:"Bitte w\xE4hlen Sie aus, in welche Verarbeitungen Sie einwilligen.",buttons:{"consent-all":"Ich stimme zu","withdraw-all":"Ich stimme nicht zu","save-choices":"Auswahl speichern"},categories:{"cat-necessary":{heading:"Unbedingt erforderlich",htmlText:"F\xFCr den Betrieb der Website unbedingt erforderlich. Keine Einwilligung erforderlich."},"cat-functional":{heading:"Funktional",htmlText:"Erm\xF6glichen erweiterte Funktionen. Ihre Einwilligung ist gem\xE4\xDF DPDPA erforderlich."},"cat-preferences":{heading:"Pr\xE4ferenzen",htmlText:"Speichern Ihre pers\xF6nlichen Einstellungen. Einwilligung gem\xE4\xDF DPDPA erforderlich."},"cat-analytics":{heading:"Analyse",htmlText:"Helfen uns, die Website-Nutzung zu verstehen. Einwilligung gem\xE4\xDF DPDPA erforderlich."},"cat-marketing":{heading:"Marketing",htmlText:"Erm\xF6glichen personalisierte Werbung. Einwilligung gem\xE4\xDF DPDPA erforderlich."}}}}});var ls,ds=I(()=>{"use strict";p();ls={mainBanner:{heading:"Aviso de protecci\xF3n de datos",htmlText:"Somos el Fiduciario de Datos seg\xFAn la Ley de Protecci\xF3n de Datos Digitales Personales (DPDPA) de India. Su consentimiento es necesario antes de que procesemos sus datos personales.",buttons:{"consent-all":"Doy mi consentimiento","deny-all":"No doy mi consentimiento","review-choices":"Revisar opciones"}},preferenceModal:{heading:"Configuraci\xF3n de privacidad (DPDPA)",subheading:"Elija en qu\xE9 procesamientos desea dar su consentimiento.",buttons:{"consent-all":"Doy mi consentimiento","withdraw-all":"No doy mi consentimiento","save-choices":"Guardar selecci\xF3n"},categories:{"cat-necessary":{heading:"Estrictamente necesarias",htmlText:"Imprescindibles para el funcionamiento del sitio. No requieren consentimiento."},"cat-functional":{heading:"Funcionales",htmlText:"Permiten funciones avanzadas. Su consentimiento es requerido seg\xFAn la DPDPA."},"cat-preferences":{heading:"Preferencias",htmlText:"Guardan su configuraci\xF3n personal. Se requiere consentimiento seg\xFAn la DPDPA."},"cat-analytics":{heading:"Anal\xEDticas",htmlText:"Nos ayudan a entender el uso del sitio. Se requiere consentimiento seg\xFAn la DPDPA."},"cat-marketing":{heading:"Marketing",htmlText:"Permiten publicidad personalizada. Se requiere consentimiento seg\xFAn la DPDPA."}}}}});var us,ps=I(()=>{"use strict";p();us={mainBanner:{heading:"Avis de protection des donn\xE9es",htmlText:"Nous sommes le Fiduciaire de donn\xE9es au sens de la loi indienne sur la protection des donn\xE9es personnelles num\xE9riques (DPDPA). Votre consentement est requis avant que nous traitions vos donn\xE9es personnelles.",buttons:{"consent-all":"Je consens","deny-all":"Je ne consens pas","review-choices":"Examiner les choix"}},preferenceModal:{heading:"Param\xE8tres de confidentialit\xE9 (DPDPA)",subheading:"Choisissez les traitements auxquels vous consentez.",buttons:{"consent-all":"Je consens","withdraw-all":"Je ne consens pas","save-choices":"Enregistrer la s\xE9lection"},categories:{"cat-necessary":{heading:"Strictement n\xE9cessaires",htmlText:"Indispensables au fonctionnement du site. Aucun consentement requis."},"cat-functional":{heading:"Fonctionnels",htmlText:"Permettent des fonctionnalit\xE9s avanc\xE9es. Votre consentement est requis selon la DPDPA."},"cat-preferences":{heading:"Pr\xE9f\xE9rences",htmlText:"Sauvegardent vos param\xE8tres personnels. Consentement requis selon la DPDPA."},"cat-analytics":{heading:"Analytiques",htmlText:"Nous aident \xE0 comprendre l'utilisation du site. Consentement requis selon la DPDPA."},"cat-marketing":{heading:"Marketing",htmlText:"Permettent la publicit\xE9 personnalis\xE9e. Consentement requis selon la DPDPA."}}}}});var ms,gs=I(()=>{"use strict";p();ms={mainBanner:{heading:"\u30C7\u30FC\u30BF\u4FDD\u8B77\u306B\u95A2\u3059\u308B\u304A\u77E5\u3089\u305B",htmlText:"\u5F53\u793E\u306F\u30A4\u30F3\u30C9\u306E\u30C7\u30B8\u30BF\u30EB\u500B\u4EBA\u30C7\u30FC\u30BF\u4FDD\u8B77\u6CD5\uFF08DPDPA\uFF09\u306B\u57FA\u3065\u304F\u30C7\u30FC\u30BF\u53D7\u8A17\u8005\u3067\u3059\u3002\u304A\u5BA2\u69D8\u306E\u500B\u4EBA\u30C7\u30FC\u30BF\u3092\u51E6\u7406\u3059\u308B\u524D\u306B\u540C\u610F\u304C\u5FC5\u8981\u3067\u3059\u3002",buttons:{"consent-all":"\u540C\u610F\u3059\u308B","deny-all":"\u540C\u610F\u3057\u306A\u3044","review-choices":"\u9078\u629E\u3092\u78BA\u8A8D"}},preferenceModal:{heading:"\u30D7\u30E9\u30A4\u30D0\u30B7\u30FC\u8A2D\u5B9A\uFF08DPDPA\uFF09",subheading:"\u540C\u610F\u3059\u308B\u51E6\u7406\u3092\u9078\u629E\u3057\u3066\u304F\u3060\u3055\u3044\u3002",buttons:{"consent-all":"\u540C\u610F\u3059\u308B","withdraw-all":"\u540C\u610F\u3057\u306A\u3044","save-choices":"\u9078\u629E\u3092\u4FDD\u5B58"},categories:{"cat-necessary":{heading:"\u5FC5\u9808",htmlText:"\u30A6\u30A7\u30D6\u30B5\u30A4\u30C8\u306E\u52D5\u4F5C\u306B\u4E0D\u53EF\u6B20\u3067\u3059\u3002\u540C\u610F\u306F\u4E0D\u8981\u3067\u3059\u3002"},"cat-functional":{heading:"\u6A5F\u80FD",htmlText:"\u9AD8\u5EA6\u306A\u6A5F\u80FD\u3092\u6709\u52B9\u306B\u3057\u307E\u3059\u3002DPDPA\u306B\u57FA\u3065\u304D\u540C\u610F\u304C\u5FC5\u8981\u3067\u3059\u3002"},"cat-preferences":{heading:"\u8A2D\u5B9A",htmlText:"\u500B\u4EBA\u8A2D\u5B9A\u3092\u4FDD\u5B58\u3057\u307E\u3059\u3002DPDPA\u306B\u57FA\u3065\u304D\u540C\u610F\u304C\u5FC5\u8981\u3067\u3059\u3002"},"cat-analytics":{heading:"\u5206\u6790",htmlText:"\u30B5\u30A4\u30C8\u5229\u7528\u72B6\u6CC1\u306E\u628A\u63E1\u306B\u4F7F\u7528\u3057\u307E\u3059\u3002DPDPA\u306B\u57FA\u3065\u304D\u540C\u610F\u304C\u5FC5\u8981\u3067\u3059\u3002"},"cat-marketing":{heading:"\u30DE\u30FC\u30B1\u30C6\u30A3\u30F3\u30B0",htmlText:"\u30D1\u30FC\u30BD\u30CA\u30E9\u30A4\u30BA\u3055\u308C\u305F\u5E83\u544A\u3092\u53EF\u80FD\u306B\u3057\u307E\u3059\u3002DPDPA\u306B\u57FA\u3065\u304D\u540C\u610F\u304C\u5FC5\u8981\u3067\u3059\u3002"}}}}});var fs,hs=I(()=>{"use strict";p();fs={mainBanner:{heading:"Hinweis zur Verarbeitung personenbezogener Daten",htmlText:"Gem\xE4\xDF dem Gesetz zum Schutz personenbezogener Daten (PIPL) m\xFCssen wir Sie vor der Verarbeitung Ihrer Daten informieren. Wir verarbeiten Daten nur zu den angegebenen Zwecken auf Grundlage Ihrer Einwilligung.",buttons:{"agree-all":"Zustimmen","reject-non-necessary":"Ablehnen","manage-preferences":"Einstellungen"}},preferenceModal:{heading:"Datenschutzeinstellungen (PIPL)",subheading:"Bitte w\xE4hlen Sie, welcher Datenverarbeitung Sie zustimmen.",buttons:{"agree-all":"Zustimmen","disagree-all":"Ablehnen","confirm-settings":"Auswahl speichern"},categories:{"cat-necessary":{heading:"Unbedingt erforderlich",htmlText:"F\xFCr den Betrieb der Website unbedingt erforderlich. Zweck: Sicherheit und grundlegende Funktionalit\xE4t."},"cat-functional":{heading:"Funktional",htmlText:"Zweck: Verbesserung der Benutzererfahrung. Einwilligung gem\xE4\xDF PIPL erforderlich."},"cat-preferences":{heading:"Pr\xE4ferenzen",htmlText:"Zweck: Speicherung personalisierter Einstellungen. Einwilligung gem\xE4\xDF PIPL erforderlich."},"cat-analytics":{heading:"Analyse",htmlText:"Zweck: Statistiken zur Website-Nutzung. Einwilligung gem\xE4\xDF PIPL erforderlich."},"cat-marketing":{heading:"Marketing",htmlText:"Zweck: Personalisierte Werbung. Einwilligung gem\xE4\xDF PIPL erforderlich."}}}}});var ys,_s=I(()=>{"use strict";p();ys={mainBanner:{heading:"Aviso de tratamiento de informaci\xF3n personal",htmlText:"De conformidad con la Ley de Protecci\xF3n de Informaci\xF3n Personal (PIPL), debemos informarle antes de tratar sus datos. Solo procesamos datos con fines espec\xEDficos y con su consentimiento.",buttons:{"agree-all":"Aceptar","reject-non-necessary":"Rechazar","manage-preferences":"Configuraci\xF3n"}},preferenceModal:{heading:"Configuraci\xF3n de privacidad (PIPL)",subheading:"Elija qu\xE9 tratamientos de datos acepta.",buttons:{"agree-all":"Aceptar","disagree-all":"Rechazar","confirm-settings":"Guardar selecci\xF3n"},categories:{"cat-necessary":{heading:"Estrictamente necesarias",htmlText:"Imprescindibles para el sitio. Finalidad: seguridad y funcionalidad b\xE1sica."},"cat-functional":{heading:"Funcionales",htmlText:"Finalidad: mejorar la experiencia del usuario. Se requiere consentimiento seg\xFAn la PIPL."},"cat-preferences":{heading:"Preferencias",htmlText:"Finalidad: guardar configuraci\xF3n personalizada. Se requiere consentimiento seg\xFAn la PIPL."},"cat-analytics":{heading:"Anal\xEDticas",htmlText:"Finalidad: estad\xEDsticas de uso del sitio. Se requiere consentimiento seg\xFAn la PIPL."},"cat-marketing":{heading:"Marketing",htmlText:"Finalidad: publicidad personalizada. Se requiere consentimiento seg\xFAn la PIPL."}}}}});var ws,Es=I(()=>{"use strict";p();ws={mainBanner:{heading:"Avis de traitement des informations personnelles",htmlText:"Conform\xE9ment \xE0 la loi sur la protection des informations personnelles (PIPL), nous devons vous informer avant tout traitement. Nous traitons les donn\xE9es \xE0 des fins sp\xE9cifiques uniquement, avec votre consentement.",buttons:{"agree-all":"Accepter","reject-non-necessary":"Refuser","manage-preferences":"Param\xE8tres"}},preferenceModal:{heading:"Param\xE8tres de confidentialit\xE9 (PIPL)",subheading:"Choisissez les traitements de donn\xE9es que vous acceptez.",buttons:{"agree-all":"Accepter","disagree-all":"Refuser","confirm-settings":"Enregistrer la s\xE9lection"},categories:{"cat-necessary":{heading:"Strictement n\xE9cessaires",htmlText:"Indispensables au site. Finalit\xE9 : s\xE9curit\xE9 et fonctionnalit\xE9 de base."},"cat-functional":{heading:"Fonctionnels",htmlText:"Finalit\xE9 : am\xE9liorer l'exp\xE9rience utilisateur. Consentement requis selon la PIPL."},"cat-preferences":{heading:"Pr\xE9f\xE9rences",htmlText:"Finalit\xE9 : sauvegarder les param\xE8tres personnalis\xE9s. Consentement requis selon la PIPL."},"cat-analytics":{heading:"Analytiques",htmlText:"Finalit\xE9 : statistiques d'utilisation du site. Consentement requis selon la PIPL."},"cat-marketing":{heading:"Marketing",htmlText:"Finalit\xE9 : publicit\xE9 personnalis\xE9e. Consentement requis selon la PIPL."}}}}});var Rs,Ss=I(()=>{"use strict";p();Rs={mainBanner:{heading:"\u500B\u4EBA\u60C5\u5831\u51E6\u7406\u306B\u95A2\u3059\u308B\u304A\u77E5\u3089\u305B",htmlText:"\u500B\u4EBA\u60C5\u5831\u4FDD\u8B77\u6CD5\uFF08PIPL\uFF09\u306B\u57FA\u3065\u304D\u3001\u30C7\u30FC\u30BF\u51E6\u7406\u306E\u524D\u306B\u304A\u77E5\u3089\u305B\u3059\u308B\u7FA9\u52D9\u304C\u3042\u308A\u307E\u3059\u3002\u304A\u5BA2\u69D8\u306E\u540C\u610F\u3092\u5F97\u305F\u7279\u5B9A\u306E\u76EE\u7684\u306B\u306E\u307F\u30C7\u30FC\u30BF\u3092\u4F7F\u7528\u3057\u307E\u3059\u3002",buttons:{"agree-all":"\u540C\u610F\u3059\u308B","reject-non-necessary":"\u62D2\u5426\u3059\u308B","manage-preferences":"\u8A2D\u5B9A"}},preferenceModal:{heading:"\u30D7\u30E9\u30A4\u30D0\u30B7\u30FC\u8A2D\u5B9A\uFF08PIPL\uFF09",subheading:"\u540C\u610F\u3059\u308B\u30C7\u30FC\u30BF\u51E6\u7406\u3092\u9078\u629E\u3057\u3066\u304F\u3060\u3055\u3044\u3002",buttons:{"agree-all":"\u540C\u610F\u3059\u308B","disagree-all":"\u62D2\u5426\u3059\u308B","confirm-settings":"\u9078\u629E\u3092\u4FDD\u5B58"},categories:{"cat-necessary":{heading:"\u5FC5\u9808",htmlText:"\u30A6\u30A7\u30D6\u30B5\u30A4\u30C8\u306B\u4E0D\u53EF\u6B20\u3067\u3059\u3002\u76EE\u7684\uFF1A\u30BB\u30AD\u30E5\u30EA\u30C6\u30A3\u3068\u57FA\u672C\u6A5F\u80FD\u3002"},"cat-functional":{heading:"\u6A5F\u80FD",htmlText:"\u76EE\u7684\uFF1A\u30E6\u30FC\u30B6\u30FC\u4F53\u9A13\u306E\u5411\u4E0A\u3002PIPL\u306B\u57FA\u3065\u304D\u540C\u610F\u304C\u5FC5\u8981\u3067\u3059\u3002"},"cat-preferences":{heading:"\u8A2D\u5B9A",htmlText:"\u76EE\u7684\uFF1A\u500B\u4EBA\u8A2D\u5B9A\u306E\u4FDD\u5B58\u3002PIPL\u306B\u57FA\u3065\u304D\u540C\u610F\u304C\u5FC5\u8981\u3067\u3059\u3002"},"cat-analytics":{heading:"\u5206\u6790",htmlText:"\u76EE\u7684\uFF1A\u30B5\u30A4\u30C8\u5229\u7528\u7D71\u8A08\u3002PIPL\u306B\u57FA\u3065\u304D\u540C\u610F\u304C\u5FC5\u8981\u3067\u3059\u3002"},"cat-marketing":{heading:"\u30DE\u30FC\u30B1\u30C6\u30A3\u30F3\u30B0",htmlText:"\u76EE\u7684\uFF1A\u30D1\u30FC\u30BD\u30CA\u30E9\u30A4\u30BA\u3055\u308C\u305F\u5E83\u544A\u3002PIPL\u306B\u57FA\u3065\u304D\u540C\u610F\u304C\u5FC5\u8981\u3067\u3059\u3002"}}}}});var Cs,vs=I(()=>{"use strict";p();Cs={mainBanner:{heading:"Wir sch\xE4tzen Ihre Privatsph\xE4re",htmlText:"Gem\xE4\xDF dem brasilianischen Datenschutzgesetz (LGPD) verarbeiten wir Ihre personenbezogenen Daten auf Grundlage Ihrer Einwilligung oder unseres berechtigten Interesses, sofern anwendbar. Sie k\xF6nnen Ihre Wahl jederzeit \xE4ndern.",buttons:{"accept-all":"Alle akzeptieren","reject-optional":"Alle ablehnen",manage:"Verwalten"}},preferenceModal:{heading:"Datenschutzeinstellungen (LGPD)",subheading:"W\xE4hlen Sie Ihre Datenschutzoptionen.",buttons:{"accept-all":"Alle akzeptieren","reject-optional":"Alle ablehnen","save-preferences":"Auswahl speichern"},categories:{"cat-necessary":{heading:"Unbedingt erforderlich",htmlText:"F\xFCr den Betrieb der Website unbedingt erforderlich."},"cat-functional":{heading:"Funktional",htmlText:"Erm\xF6glichen erweiterte Funktionen. Rechtsgrundlage: berechtigtes Interesse (LGPD Art. 10)."},"cat-preferences":{heading:"Pr\xE4ferenzen",htmlText:"Speichern Ihre Einstellungen. Rechtsgrundlage: berechtigtes Interesse (LGPD Art. 10)."},"cat-analytics":{heading:"Analyse",htmlText:"Helfen uns, die Website-Nutzung zu verstehen. Einwilligung gem\xE4\xDF LGPD erforderlich."},"cat-marketing":{heading:"Marketing",htmlText:"Erm\xF6glichen personalisierte Werbung. Einwilligung gem\xE4\xDF LGPD erforderlich."}}}}});var As,Ts=I(()=>{"use strict";p();As={mainBanner:{heading:"Valoramos su privacidad",htmlText:"De acuerdo con la Ley General de Protecci\xF3n de Datos (LGPD) de Brasil, tratamos sus datos personales con su consentimiento o con base en inter\xE9s leg\xEDtimo cuando corresponda. Puede cambiar sus preferencias en cualquier momento.",buttons:{"accept-all":"Aceptar todo","reject-optional":"Rechazar todo",manage:"Gestionar"}},preferenceModal:{heading:"Configuraci\xF3n de privacidad (LGPD)",subheading:"Elija sus opciones de privacidad.",buttons:{"accept-all":"Aceptar todo","reject-optional":"Rechazar todo","save-preferences":"Guardar selecci\xF3n"},categories:{"cat-necessary":{heading:"Estrictamente necesarias",htmlText:"Imprescindibles para el funcionamiento del sitio."},"cat-functional":{heading:"Funcionales",htmlText:"Permiten funciones avanzadas. Base legal: inter\xE9s leg\xEDtimo (LGPD Art. 10)."},"cat-preferences":{heading:"Preferencias",htmlText:"Guardan su configuraci\xF3n. Base legal: inter\xE9s leg\xEDtimo (LGPD Art. 10)."},"cat-analytics":{heading:"Anal\xEDticas",htmlText:"Nos ayudan a comprender el uso del sitio. Se requiere consentimiento seg\xFAn la LGPD."},"cat-marketing":{heading:"Marketing",htmlText:"Permiten publicidad personalizada. Se requiere consentimiento seg\xFAn la LGPD."}}}}});var Is,Ps=I(()=>{"use strict";p();Is={mainBanner:{heading:"Nous respectons votre vie priv\xE9e",htmlText:"Conform\xE9ment \xE0 la loi br\xE9silienne sur la protection des donn\xE9es (LGPD), nous traitons vos donn\xE9es personnelles sur la base de votre consentement ou d'un int\xE9r\xEAt l\xE9gitime, selon le cas. Vous pouvez modifier vos pr\xE9f\xE9rences \xE0 tout moment.",buttons:{"accept-all":"Tout accepter","reject-optional":"Tout refuser",manage:"G\xE9rer"}},preferenceModal:{heading:"Param\xE8tres de confidentialit\xE9 (LGPD)",subheading:"Choisissez vos options de confidentialit\xE9.",buttons:{"accept-all":"Tout accepter","reject-optional":"Tout refuser","save-preferences":"Enregistrer la s\xE9lection"},categories:{"cat-necessary":{heading:"Strictement n\xE9cessaires",htmlText:"Indispensables au fonctionnement du site."},"cat-functional":{heading:"Fonctionnels",htmlText:"Permettent des fonctionnalit\xE9s avanc\xE9es. Base l\xE9gale : int\xE9r\xEAt l\xE9gitime (LGPD Art. 10)."},"cat-preferences":{heading:"Pr\xE9f\xE9rences",htmlText:"Sauvegardent vos param\xE8tres. Base l\xE9gale : int\xE9r\xEAt l\xE9gitime (LGPD Art. 10)."},"cat-analytics":{heading:"Analytiques",htmlText:"Nous aident \xE0 comprendre l'utilisation du site. Consentement requis selon la LGPD."},"cat-marketing":{heading:"Marketing",htmlText:"Permettent la publicit\xE9 personnalis\xE9e. Consentement requis selon la LGPD."}}}}});var bs,Os=I(()=>{"use strict";p();bs={mainBanner:{heading:"\u30D7\u30E9\u30A4\u30D0\u30B7\u30FC\u3092\u5927\u5207\u306B\u3057\u3066\u3044\u307E\u3059",htmlText:"\u30D6\u30E9\u30B8\u30EB\u306E\u4E00\u822C\u30C7\u30FC\u30BF\u4FDD\u8B77\u6CD5\uFF08LGPD\uFF09\u306B\u57FA\u3065\u304D\u3001\u304A\u5BA2\u69D8\u306E\u540C\u610F\u307E\u305F\u306F\u6B63\u5F53\u306A\u5229\u76CA\u3092\u6839\u62E0\u3068\u3057\u3066\u500B\u4EBA\u30C7\u30FC\u30BF\u3092\u51E6\u7406\u3057\u307E\u3059\u3002\u8A2D\u5B9A\u306F\u3044\u3064\u3067\u3082\u5909\u66F4\u3067\u304D\u307E\u3059\u3002",buttons:{"accept-all":"\u3059\u3079\u3066\u540C\u610F","reject-optional":"\u3059\u3079\u3066\u62D2\u5426",manage:"\u7BA1\u7406\u3059\u308B"}},preferenceModal:{heading:"\u30D7\u30E9\u30A4\u30D0\u30B7\u30FC\u8A2D\u5B9A\uFF08LGPD\uFF09",subheading:"\u30D7\u30E9\u30A4\u30D0\u30B7\u30FC\u30AA\u30D7\u30B7\u30E7\u30F3\u3092\u9078\u629E\u3057\u3066\u304F\u3060\u3055\u3044\u3002",buttons:{"accept-all":"\u3059\u3079\u3066\u540C\u610F","reject-optional":"\u3059\u3079\u3066\u62D2\u5426","save-preferences":"\u9078\u629E\u3092\u4FDD\u5B58"},categories:{"cat-necessary":{heading:"\u5FC5\u9808",htmlText:"\u30A6\u30A7\u30D6\u30B5\u30A4\u30C8\u306E\u52D5\u4F5C\u306B\u4E0D\u53EF\u6B20\u3067\u3059\u3002"},"cat-functional":{heading:"\u6A5F\u80FD",htmlText:"\u9AD8\u5EA6\u306A\u6A5F\u80FD\u3092\u6709\u52B9\u306B\u3057\u307E\u3059\u3002\u6CD5\u7684\u6839\u62E0\uFF1A\u6B63\u5F53\u306A\u5229\u76CA\uFF08LGPD\u7B2C10\u6761\uFF09\u3002"},"cat-preferences":{heading:"\u8A2D\u5B9A",htmlText:"\u8A2D\u5B9A\u3092\u4FDD\u5B58\u3057\u307E\u3059\u3002\u6CD5\u7684\u6839\u62E0\uFF1A\u6B63\u5F53\u306A\u5229\u76CA\uFF08LGPD\u7B2C10\u6761\uFF09\u3002"},"cat-analytics":{heading:"\u5206\u6790",htmlText:"\u30B5\u30A4\u30C8\u5229\u7528\u72B6\u6CC1\u306E\u628A\u63E1\u306B\u5F79\u7ACB\u3066\u307E\u3059\u3002LGPD\u306B\u57FA\u3065\u304D\u540C\u610F\u304C\u5FC5\u8981\u3067\u3059\u3002"},"cat-marketing":{heading:"\u30DE\u30FC\u30B1\u30C6\u30A3\u30F3\u30B0",htmlText:"\u30D1\u30FC\u30BD\u30CA\u30E9\u30A4\u30BA\u3055\u308C\u305F\u5E83\u544A\u3092\u53EF\u80FD\u306B\u3057\u307E\u3059\u3002LGPD\u306B\u57FA\u3065\u304D\u540C\u610F\u304C\u5FC5\u8981\u3067\u3059\u3002"}}}}});var Ds,ks=I(()=>{"use strict";p();Ds={mainBanner:{heading:"Wir verwenden Cookies",htmlText:"Wir verwenden Cookies und \xE4hnliche Technologien, um unsere Dienste bereitzustellen und zu verbessern. F\xFCr Marketing-Cookies ist Ihre Einwilligung erforderlich. Andere Cookies basieren auf unserem berechtigten Interesse.",buttons:{"accept-all":"Alle akzeptieren","reject-marketing":"Marketing ablehnen","manage-preferences":"Einstellungen verwalten"}},preferenceModal:{heading:"Datenschutzeinstellungen",subheading:"W\xE4hlen Sie Ihre Cookie-Pr\xE4ferenzen.",buttons:{"accept-all":"Alle akzeptieren","necessary-only":"Marketing ablehnen","save-preferences":"Auswahl speichern"},categories:{"cat-necessary":{heading:"Unbedingt erforderlich",htmlText:"F\xFCr den Betrieb der Website unbedingt erforderlich."},"cat-functional":{heading:"Funktional",htmlText:"Erm\xF6glichen erweiterte Funktionen. Rechtsgrundlage: berechtigtes Interesse."},"cat-preferences":{heading:"Pr\xE4ferenzen",htmlText:"Speichern Ihre pers\xF6nlichen Einstellungen. Rechtsgrundlage: berechtigtes Interesse."},"cat-analytics":{heading:"Analyse",htmlText:"Helfen uns, die Website-Nutzung zu verstehen. Rechtsgrundlage: berechtigtes Interesse."},"cat-marketing":{heading:"Marketing",htmlText:"Erm\xF6glichen personalisierte Werbung. Ihre Einwilligung ist erforderlich."}}}}});var Ls,Ns=I(()=>{"use strict";p();Ls={mainBanner:{heading:"Usamos cookies",htmlText:"Utilizamos cookies y tecnolog\xEDas similares para ofrecer y mejorar nuestros servicios. Las cookies de marketing requieren su consentimiento. Las dem\xE1s se basan en inter\xE9s leg\xEDtimo.",buttons:{"accept-all":"Aceptar todo","reject-marketing":"Rechazar marketing","manage-preferences":"Gestionar preferencias"}},preferenceModal:{heading:"Configuraci\xF3n de privacidad",subheading:"Elija sus preferencias de cookies.",buttons:{"accept-all":"Aceptar todo","necessary-only":"Rechazar marketing","save-preferences":"Guardar selecci\xF3n"},categories:{"cat-necessary":{heading:"Estrictamente necesarias",htmlText:"Imprescindibles para el funcionamiento del sitio."},"cat-functional":{heading:"Funcionales",htmlText:"Permiten funciones avanzadas. Base legal: inter\xE9s leg\xEDtimo."},"cat-preferences":{heading:"Preferencias",htmlText:"Guardan su configuraci\xF3n personal. Base legal: inter\xE9s leg\xEDtimo."},"cat-analytics":{heading:"Anal\xEDticas",htmlText:"Nos ayudan a entender el uso del sitio. Base legal: inter\xE9s leg\xEDtimo."},"cat-marketing":{heading:"Marketing",htmlText:"Permiten publicidad personalizada. Se requiere su consentimiento."}}}}});var Us,xs=I(()=>{"use strict";p();Us={mainBanner:{heading:"Nous utilisons des cookies",htmlText:"Nous utilisons des cookies et des technologies similaires pour fournir et am\xE9liorer nos services. Les cookies marketing n\xE9cessitent votre consentement. Les autres reposent sur notre int\xE9r\xEAt l\xE9gitime.",buttons:{"accept-all":"Tout accepter","reject-marketing":"Refuser le marketing","manage-preferences":"G\xE9rer les pr\xE9f\xE9rences"}},preferenceModal:{heading:"Param\xE8tres de confidentialit\xE9",subheading:"Choisissez vos pr\xE9f\xE9rences en mati\xE8re de cookies.",buttons:{"accept-all":"Tout accepter","necessary-only":"Refuser le marketing","save-preferences":"Enregistrer la s\xE9lection"},categories:{"cat-necessary":{heading:"Strictement n\xE9cessaires",htmlText:"Indispensables au fonctionnement du site."},"cat-functional":{heading:"Fonctionnels",htmlText:"Permettent des fonctionnalit\xE9s avanc\xE9es. Base l\xE9gale : int\xE9r\xEAt l\xE9gitime."},"cat-preferences":{heading:"Pr\xE9f\xE9rences",htmlText:"Sauvegardent vos param\xE8tres personnels. Base l\xE9gale : int\xE9r\xEAt l\xE9gitime."},"cat-analytics":{heading:"Analytiques",htmlText:"Nous aident \xE0 comprendre l'utilisation du site. Base l\xE9gale : int\xE9r\xEAt l\xE9gitime."},"cat-marketing":{heading:"Marketing",htmlText:"Permettent la publicit\xE9 personnalis\xE9e. Votre consentement est requis."}}}}});var Ms,Gs=I(()=>{"use strict";p();Ms={mainBanner:{heading:"Cookie\u3092\u4F7F\u7528\u3057\u3066\u3044\u307E\u3059",htmlText:"\u30B5\u30FC\u30D3\u30B9\u306E\u63D0\u4F9B\u30FB\u6539\u5584\u306E\u305F\u3081\u306BCookie\u304A\u3088\u3073\u985E\u4F3C\u6280\u8853\u3092\u4F7F\u7528\u3057\u3066\u3044\u307E\u3059\u3002\u30DE\u30FC\u30B1\u30C6\u30A3\u30F3\u30B0Cookie\u306B\u306F\u304A\u5BA2\u69D8\u306E\u540C\u610F\u304C\u5FC5\u8981\u3067\u3059\u3002\u305D\u306E\u4ED6\u306F\u6B63\u5F53\u306A\u5229\u76CA\u3092\u6839\u62E0\u3068\u3057\u3066\u3044\u307E\u3059\u3002",buttons:{"accept-all":"\u3059\u3079\u3066\u540C\u610F","reject-marketing":"\u30DE\u30FC\u30B1\u30C6\u30A3\u30F3\u30B0\u3092\u62D2\u5426","manage-preferences":"\u8A2D\u5B9A\u3092\u7BA1\u7406"}},preferenceModal:{heading:"\u30D7\u30E9\u30A4\u30D0\u30B7\u30FC\u8A2D\u5B9A",subheading:"Cookie\u306E\u8A2D\u5B9A\u3092\u9078\u629E\u3057\u3066\u304F\u3060\u3055\u3044\u3002",buttons:{"accept-all":"\u3059\u3079\u3066\u540C\u610F","necessary-only":"\u30DE\u30FC\u30B1\u30C6\u30A3\u30F3\u30B0\u3092\u62D2\u5426","save-preferences":"\u9078\u629E\u3092\u4FDD\u5B58"},categories:{"cat-necessary":{heading:"\u5FC5\u9808",htmlText:"\u30A6\u30A7\u30D6\u30B5\u30A4\u30C8\u306E\u52D5\u4F5C\u306B\u4E0D\u53EF\u6B20\u3067\u3059\u3002"},"cat-functional":{heading:"\u6A5F\u80FD",htmlText:"\u9AD8\u5EA6\u306A\u6A5F\u80FD\u3092\u6709\u52B9\u306B\u3057\u307E\u3059\u3002\u6CD5\u7684\u6839\u62E0\uFF1A\u6B63\u5F53\u306A\u5229\u76CA\u3002"},"cat-preferences":{heading:"\u8A2D\u5B9A",htmlText:"\u500B\u4EBA\u8A2D\u5B9A\u3092\u4FDD\u5B58\u3057\u307E\u3059\u3002\u6CD5\u7684\u6839\u62E0\uFF1A\u6B63\u5F53\u306A\u5229\u76CA\u3002"},"cat-analytics":{heading:"\u5206\u6790",htmlText:"\u30B5\u30A4\u30C8\u5229\u7528\u72B6\u6CC1\u306E\u628A\u63E1\u306B\u5F79\u7ACB\u3066\u307E\u3059\u3002\u6CD5\u7684\u6839\u62E0\uFF1A\u6B63\u5F53\u306A\u5229\u76CA\u3002"},"cat-marketing":{heading:"\u30DE\u30FC\u30B1\u30C6\u30A3\u30F3\u30B0",htmlText:"\u30D1\u30FC\u30BD\u30CA\u30E9\u30A4\u30BA\u3055\u308C\u305F\u5E83\u544A\u3092\u53EF\u80FD\u306B\u3057\u307E\u3059\u3002\u304A\u5BA2\u69D8\u306E\u540C\u610F\u304C\u5FC5\u8981\u3067\u3059\u3002"}}}}});var js,Bs=I(()=>{"use strict";p();js={mainBanner:{heading:"Diese Website verwendet nur notwendige Cookies",htmlText:"Wir verwenden ausschlie\xDFlich technisch notwendige Cookies, die f\xFCr den Betrieb der Website erforderlich sind. Es werden keine Marketing- oder Analyse-Cookies eingesetzt.",buttons:{ok:"OK"}},preferenceModal:{heading:"Cookie-Informationen",buttons:{close:"Schlie\xDFen"},categories:{"cat-necessary":{heading:"Notwendige Cookies",htmlText:"Technisch notwendige Cookies, die f\xFCr den ordnungsgem\xE4\xDFen Betrieb der Website erforderlich sind. Sie k\xF6nnen nicht deaktiviert werden."}}}}});var Fs,$s=I(()=>{"use strict";p();Fs={mainBanner:{heading:"Este sitio solo usa cookies esenciales",htmlText:"\xDAnicamente utilizamos cookies t\xE9cnicamente necesarias para el funcionamiento del sitio. No utilizamos cookies de marketing ni anal\xEDticas.",buttons:{ok:"Aceptar"}},preferenceModal:{heading:"Informaci\xF3n sobre cookies",buttons:{close:"Cerrar"},categories:{"cat-necessary":{heading:"Cookies necesarias",htmlText:"Cookies t\xE9cnicamente necesarias para el correcto funcionamiento del sitio. No pueden desactivarse."}}}}});var Hs,Vs=I(()=>{"use strict";p();Hs={mainBanner:{heading:"Ce site utilise uniquement des cookies essentiels",htmlText:"Nous n'utilisons que des cookies techniquement n\xE9cessaires au bon fonctionnement du site. Aucun cookie de marketing ou d'analyse n'est utilis\xE9.",buttons:{ok:"OK"}},preferenceModal:{heading:"Informations sur les cookies",buttons:{close:"Fermer"},categories:{"cat-necessary":{heading:"Cookies n\xE9cessaires",htmlText:"Cookies techniquement n\xE9cessaires au bon fonctionnement du site. Ils ne peuvent pas \xEAtre d\xE9sactiv\xE9s."}}}}});var Ws,qs=I(()=>{"use strict";p();Ws={mainBanner:{heading:"\u5F53\u30B5\u30A4\u30C8\u306F\u5FC5\u9808Cookie\u306E\u307F\u3092\u4F7F\u7528\u3057\u3066\u3044\u307E\u3059",htmlText:"\u30B5\u30A4\u30C8\u306E\u6B63\u5E38\u306A\u52D5\u4F5C\u306B\u5FC5\u8981\u306A\u6280\u8853\u7684Cookie\u306E\u307F\u3092\u4F7F\u7528\u3057\u3066\u3044\u307E\u3059\u3002\u30DE\u30FC\u30B1\u30C6\u30A3\u30F3\u30B0\u3084\u5206\u6790\u306ECookie\u306F\u4F7F\u7528\u3057\u3066\u3044\u307E\u305B\u3093\u3002",buttons:{ok:"OK"}},preferenceModal:{heading:"Cookie\u306B\u95A2\u3059\u308B\u60C5\u5831",buttons:{close:"\u9589\u3058\u308B"},categories:{"cat-necessary":{heading:"\u5FC5\u9808Cookie",htmlText:"\u30B5\u30A4\u30C8\u306E\u6B63\u5E38\u306A\u52D5\u4F5C\u306B\u5FC5\u8981\u306A\u6280\u8853\u7684Cookie\u3067\u3059\u3002\u7121\u52B9\u306B\u3059\u308B\u3053\u3068\u306F\u3067\u304D\u307E\u305B\u3093\u3002"}}}}});var Js={};Pn(Js,{DEFAULT_PROFILES:()=>en,GENERAL_PRIVACY_CONSENT_EN_PROFILE:()=>Zt,GENERIC_AGE_GATE_TEXT:()=>hl,GENERIC_GPC_BANNER_TEXT:()=>fl,NOTICE_ONLY_EN_PROFILE:()=>Xt,OPT_IN_BRAZIL_EN_PROFILE:()=>Qt,OPT_IN_CHINA_EN_PROFILE:()=>Yt,OPT_IN_DPDPA_EN_PROFILE:()=>Kt,OPT_IN_EN_PROFILE:()=>qt,OPT_OUT_EN_PROFILE:()=>Jt,OPT_OUT_STRICT_EN_PROFILE:()=>zt,resolveLocaleTranslation:()=>yl});function ei(i,e){let t={};for(let[n,o]of Object.entries(i))t[n]=e[n]!==void 0?{...o,text:e[n]}:o;return t}function yl(i,e){let n=en[i]?.translations.en;if(!n)return;if(e==="en")return n;let o=gl[i]?.[e];if(!o)return;let s={};for(let[r,a]of Object.entries(n.preferenceModal.categories)){let c=o.preferenceModal.categories[`cat-${r}`];s[r]=c?{...a,heading:c.heading,htmlText:c.htmlText}:a}return{mainBanner:{...n.mainBanner,heading:o.mainBanner.heading,htmlText:o.mainBanner.htmlText,buttons:ei(n.mainBanner.buttons,o.mainBanner.buttons)},...n.gpcBanner?{gpcBanner:o.gpcBanner?{...n.gpcBanner,heading:o.gpcBanner.heading,htmlText:o.gpcBanner.htmlText,buttons:ei(n.gpcBanner.buttons,o.gpcBanner.buttons)}:n.gpcBanner}:{},preferenceModal:{...n.preferenceModal,heading:o.preferenceModal.heading,...o.preferenceModal.subheading?{subheading:o.preferenceModal.subheading}:{},...o.preferenceModal.htmlText?{htmlText:o.preferenceModal.htmlText}:{},buttons:ei(n.preferenceModal.buttons,o.preferenceModal.buttons),categories:s}}}var en,gl,fl,hl,ti=I(()=>{"use strict";p();qn();Jn();zn();Kn();Yn();Qn();Zn();Xn();Go();Bo();$o();Vo();qo();zo();Yo();Zo();es();ns();os();rs();cs();ds();ps();gs();hs();_s();Es();Ss();vs();Ts();Ps();Os();ks();Ns();xs();Gs();Bs();$s();Vs();qs();qn();Jn();zn();Kn();Yn();Qn();Zn();Xn();en={"opt-in":qt,"opt-out":Jt,"opt-out-strict":zt,"opt-in-dpdpa":Kt,"opt-in-china":Yt,"opt-in-brazil":Qt,"general-privacy-consent":Zt,"notice-only":Xt},gl={"opt-in":{de:Mo,es:jo,fr:Fo,ja:Ho},"opt-out":{de:Wo,es:Jo,fr:Ko,ja:Qo},"opt-out-strict":{de:Xo,es:ts,fr:is,ja:ss},"opt-in-dpdpa":{de:as,es:ls,fr:us,ja:ms},"opt-in-china":{de:fs,es:ys,fr:ws,ja:Rs},"opt-in-brazil":{de:Cs,es:As,fr:Is,ja:bs},"general-privacy-consent":{de:Ds,es:Ls,fr:Us,ja:Ms},"notice-only":{de:js,es:Fs,fr:Hs,ja:Ws}},fl={en:{heading:"Global Privacy Control detected",htmlText:"Your browser sent a Global Privacy Control signal. We have applied your privacy preference accordingly \u2014 you can review or change your choices below."},de:{heading:"Global Privacy Control erkannt",htmlText:"Ihr Browser hat ein Global-Privacy-Control-Signal gesendet. Wir haben Ihre Datenschutzeinstellung entsprechend angewendet \u2014 Sie k\xF6nnen Ihre Auswahl unten \xFCberpr\xFCfen oder \xE4ndern."},es:{heading:"Control de privacidad global detectado",htmlText:"Su navegador envi\xF3 una se\xF1al de Global Privacy Control. Hemos aplicado su preferencia de privacidad en consecuencia; puede revisar o cambiar sus opciones a continuaci\xF3n."},fr:{heading:"Contr\xF4le de confidentialit\xE9 global d\xE9tect\xE9",htmlText:"Votre navigateur a envoy\xE9 un signal Global Privacy Control. Nous avons appliqu\xE9 votre pr\xE9f\xE9rence de confidentialit\xE9 en cons\xE9quence \u2014 vous pouvez v\xE9rifier ou modifier vos choix ci-dessous."},ja:{heading:"\u30B0\u30ED\u30FC\u30D0\u30EB\u30FB\u30D7\u30E9\u30A4\u30D0\u30B7\u30FC\u30FB\u30B3\u30F3\u30C8\u30ED\u30FC\u30EB\u3092\u691C\u51FA\u3057\u307E\u3057\u305F",htmlText:"\u304A\u4F7F\u3044\u306E\u30D6\u30E9\u30A6\u30B6\u304B\u3089Global Privacy Control\u4FE1\u53F7\u304C\u9001\u4FE1\u3055\u308C\u307E\u3057\u305F\u3002\u3053\u308C\u306B\u5FDC\u3058\u3066\u304A\u5BA2\u69D8\u306E\u30D7\u30E9\u30A4\u30D0\u30B7\u30FC\u8A2D\u5B9A\u3092\u9069\u7528\u3057\u307E\u3057\u305F\u3002\u4EE5\u4E0B\u3067\u9078\u629E\u5185\u5BB9\u3092\u78BA\u8A8D\u30FB\u5909\u66F4\u3044\u305F\u3060\u3051\u307E\u3059\u3002"}},hl={en:{heading:"Are you 16 or older?",htmlText:"Please confirm your age before we show you cookie preferences.",confirmButtonLabel:"Yes",denyButtonLabel:"No",parentalConsent:{heading:"Parental consent required",htmlText:"Only strictly necessary cookies will be used until a parent or guardian verifies consent on your behalf.",confirmButtonLabel:"OK"}},de:{heading:"Bist du 16 Jahre oder \xE4lter?",htmlText:"Bitte best\xE4tige dein Alter, bevor wir dir die Cookie-Einstellungen anzeigen.",confirmButtonLabel:"Ja",denyButtonLabel:"Nein",parentalConsent:{heading:"Elterliche Zustimmung erforderlich",htmlText:"Bis ein Elternteil oder Erziehungsberechtigter die Zustimmung in deinem Namen best\xE4tigt, werden nur unbedingt erforderliche Cookies verwendet.",confirmButtonLabel:"OK"}},es:{heading:"\xBFTienes 16 a\xF1os o m\xE1s?",htmlText:"Confirma tu edad antes de mostrarte las preferencias de cookies.",confirmButtonLabel:"S\xED",denyButtonLabel:"No",parentalConsent:{heading:"Se requiere consentimiento parental",htmlText:"Solo se utilizar\xE1n las cookies estrictamente necesarias hasta que un padre, madre o tutor confirme el consentimiento en tu nombre.",confirmButtonLabel:"Aceptar"}},fr:{heading:"Avez-vous 16 ans ou plus\xA0?",htmlText:"Merci de confirmer votre \xE2ge avant que nous vous montrions les pr\xE9f\xE9rences de cookies.",confirmButtonLabel:"Oui",denyButtonLabel:"Non",parentalConsent:{heading:"Consentement parental requis",htmlText:"Seuls les cookies strictement n\xE9cessaires seront utilis\xE9s jusqu\u2019\xE0 ce qu\u2019un parent ou tuteur confirme son consentement en votre nom.",confirmButtonLabel:"OK"}},ja:{heading:"16\u6B73\u4EE5\u4E0A\u3067\u3059\u304B?",htmlText:"Cookie\u306E\u8A2D\u5B9A\u3092\u8868\u793A\u3059\u308B\u524D\u306B\u3001\u5E74\u9F62\u3092\u3054\u78BA\u8A8D\u304F\u3060\u3055\u3044\u3002",confirmButtonLabel:"\u306F\u3044",denyButtonLabel:"\u3044\u3044\u3048",parentalConsent:{heading:"\u4FDD\u8B77\u8005\u306E\u540C\u610F\u304C\u5FC5\u8981\u3067\u3059",htmlText:"\u4FDD\u8B77\u8005\u304C\u540C\u610F\u3092\u78BA\u8A8D\u3059\u308B\u307E\u3067\u3001\u5FC5\u8981\u6700\u5C0F\u9650\u306ECookie\u306E\u307F\u304C\u4F7F\u7528\u3055\u308C\u307E\u3059\u3002",confirmButtonLabel:"OK"}}}});function _l(i,e){let t;return function(...n){t!==void 0&&clearTimeout(t),t=setTimeout(()=>{i.apply(this,n)},e)}}var zs=I(()=>{"use strict";p()});function wl(i,e){let t=0;return function(...n){let o=Date.now();o-t>=e&&(t=o,i.apply(this,n))}}var Ks=I(()=>{"use strict";p()});function El(){return typeof process>"u"||process.env.NO_COLOR?!1:process.env.FORCE_COLOR?!0:!!process.stdout?.isTTY}function ye(i,e){return t=>El()?`\x1B[${i}m${t}\x1B[${e}m`:t}function Sl(i,e=10){let t=i.toUpperCase().padEnd(e);return Rl[i](t)}function vl(i,e){let{symbol:t,paint:n}=Cl[i];return`${n(t)} ${e}`}var Z,Rl,Cl,Ys=I(()=>{"use strict";p();Z={bold:ye(1,22),dim:ye(2,22),red:ye(31,39),green:ye(32,39),yellow:ye(33,39),blue:ye(34,39),magenta:ye(35,39),cyan:ye(36,39),gray:ye(90,39)},Rl={pass:i=>Z.bold(Z.green(i)),fail:i=>Z.bold(Z.red(i)),error:i=>Z.bold(Z.red(i)),"not-applicable":i=>Z.gray(i),"new-baseline":i=>Z.bold(Z.blue(i))};Cl={info:{symbol:"\u2139",paint:Z.cyan},success:{symbol:"\u2713",paint:Z.green},warn:{symbol:"\u26A0",paint:Z.yellow},error:{symbol:"\u2717",paint:Z.red}}});function Ol(i){return Qs[i.id]??"functional"}function Ll(i,e){for(let t of Object.values(e))if(t.cookies.includes(i))return t}function Be(i){let e=new Map;for(let t of Object.values(i))for(let n of t.cookies)e.set(n,t);return e}function Fe(i,e){return e.get(i)?.legalBasis??"consent"}function ni(i,e){return Fe(i,e)==="mandatory"}function Ml(i){if(!i||typeof i!="object")return!1;let e=i;if(typeof e.version!="string")return!1;let t=e.countries;return!t||typeof t!="object"?!1:Object.values(t).every(n=>!!n&&typeof n=="object"&&typeof n.complianceGroup=="string")}async function oi(i,e){let t={map:De};if(i===void 0||i==="default")return t;let n,o;if(typeof i=="string")try{if(o=await fetch(i),!o.ok)return e(`compliance.complianceMap fetch from "${i}" failed (HTTP ${o.status}) \u2014 falling back to the embedded map.`),t;n=await o.json()}catch(r){return e(`compliance.complianceMap fetch from "${i}" failed (${r instanceof Error?r.message:String(r)}) \u2014 falling back to the embedded map.`),t}else n=i;if(!Ml(n))return e(`compliance.complianceMap ${typeof i=="string"?`at "${i}"`:"object"} failed validation \u2014 falling back to the embedded map.`),t;for(let[r,a]of Object.entries(n.countries))a.overriddenRegions&&a.default===void 0&&e(`compliance.complianceMap country "${r}" has overriddenRegions but no explicit default \u2014 falling back to complianceGroup ("${a.complianceGroup}"), which may under-comply for regions not listed.`);let s={map:n};return o&&(s.response=o),s}var tn,ot,Al,Tl,Il,nn,Pl,bl,Qs,Dl,kl,ii,De,Nl,Ul,xl,Zs=I(()=>{"use strict";p();tn=["opt-in","opt-out","opt-out-strict","opt-in-dpdpa","opt-in-china","opt-in-brazil","general-privacy-consent","notice-only"],ot={"opt-out-strict":{label:"Opt-out Strict (CPRA / California)",description:"California CPRA: opt-out with sale/sharing/sensitive categories required. GPC must be honored. Stricter than general US state laws.",compliances:["cpra"],defaultGpc:"honor",gpcAutoHonor:!0,allowsLegitimateInterest:!1,allowsTcf:!1,requiresCpraCategory:!0,requiresDpdpaDisclosure:!1},"opt-out":{label:"Opt-out (US State Laws)",description:"US state privacy laws. Collect first, allow opt-out of sale/share. Covers CCPA and all state-level equivalents.",compliances:["ccpa","vcdpa","cpa-co","ctdpa","ucpa","icdpa-ia","icdpa-in","tipa","mcdpa-mt","mcdpa-mn","ocpa","tdpsa","dpdpa-de","njdpa","nhpa","ndpa-ne","modpa","kcdpa","ridtpa"],defaultGpc:"honor",gpcAutoHonor:!0,allowsLegitimateInterest:!1,allowsTcf:!1,requiresCpraCategory:!1,requiresDpdpaDisclosure:!1},"notice-only":{label:"Notice Only",description:"A privacy notice is generally sufficient. No dedicated cookie banner law is encoded for this jurisdiction.",compliances:["privacy-fj","privacy-pg"],defaultGpc:"ignore",gpcAutoHonor:!1,allowsLegitimateInterest:!0,allowsTcf:!1,requiresCpraCategory:!1,requiresDpdpaDisclosure:!1},"opt-in":{label:"Standard Opt-in (GDPR)",description:"GDPR / ePrivacy style: prior consent required before non-essential cookies. Granular consent, easy reject, easy withdrawal.",compliances:["gdpr","eprivacy","uk-gdpr","pecr","revfadp","kvkk","pdpa-th","pdpl-sa","uae-pdpl","difc-dpl","adgm-dpr","qpdl-qa","pdpl-bh","pdpl-om","law25"],defaultGpc:"ignore",gpcAutoHonor:!1,allowsLegitimateInterest:!0,allowsTcf:!0,requiresCpraCategory:!1,requiresDpdpaDisclosure:!1},"opt-in-dpdpa":{label:"Opt-in (India DPDPA)",description:"India's Digital Personal Data Protection Act. Opt-in consent with data fiduciary disclosure. No legitimate interest basis.",compliances:["dpdpa"],defaultGpc:"ignore",gpcAutoHonor:!1,allowsLegitimateInterest:!1,allowsTcf:!1,requiresCpraCategory:!1,requiresDpdpaDisclosure:!0},"opt-in-china":{label:"Opt-in (China PIPL / DSL)",description:"China PIPL + DSL + CSL: strict opt-in with purpose specification, data minimisation, and cross-border transfer controls.",compliances:["pipl","dsl-cn","csl-cn"],defaultGpc:"ignore",gpcAutoHonor:!1,allowsLegitimateInterest:!1,allowsTcf:!1,requiresCpraCategory:!1,requiresDpdpaDisclosure:!1},"opt-in-brazil":{label:"Opt-in (Brazil LGPD)",description:"Brazil LGPD: opt-in consent required. Legitimate interest is a valid basis. Analytics and advertising may differ in treatment.",compliances:["lgpd"],defaultGpc:"ignore",gpcAutoHonor:!1,allowsLegitimateInterest:!0,allowsTcf:!1,requiresCpraCategory:!1,requiresDpdpaDisclosure:!1},"general-privacy-consent":{label:"General Privacy Consent",description:"Privacy notice or consent rules exist but the jurisdiction does not have a GDPR/PECR-style strict cookie banner law. Documenting legal basis is best practice.",compliances:["pipeda","popia","appi","pipa-kr","pdpa-sg","pdpa-my","dpa-ph","pdp-id","pdpd-vn","privacy-au","privacy-nz","pdpl-hk","pdpa-mo","pdpl-tw","privacy-bn","privacy-lk","privacy-np","privacy-kw","privacy-il","ndpa-ng","dpa-ke","dpa-gh","dpa-ug","dpa-rw","dpa-mu","dpa-bw","dpa-zm","dpa-zw","dpa-eg","dpa-ma","dpa-tn","dpa-dz","lfpdppp","lpdp-ar","lpdp-pe","law1581-co","law18331-uy","law19628-cl","lopdp-ec","lpdp-cr","data-protection-pa","data-protection-do"],defaultGpc:"ignore",gpcAutoHonor:!1,allowsLegitimateInterest:!0,allowsTcf:!1,requiresCpraCategory:!1,requiresDpdpaDisclosure:!1}},Al=[{value:"ignore",label:"Ignore",description:"Do not check or respond to the GPC browser signal."},{value:"honor",label:"Honor",description:"Respect GPC as a valid opt-out signal. Show GPC variant banner once."},{value:"strict",label:"Strict",description:"Silently deny all non-mandatory cookies when GPC is detected. No banner shown."}],Tl=[{value:"mandatory",label:"Strictly Necessary",description:"Required for the service to function. No consent needed."},{value:"consent",label:"Consent",description:"Requires explicit user agreement. User can withdraw at any time."},{value:"legitimate_interest",label:"Legitimate Interest",description:"Based on legitimate business interest. User has the right to object."}],Il=[{value:"sale",label:"Sale",description:"Sale of personal data to third parties for their own use."},{value:"sharing",label:"Sharing",description:"Sharing for cross-context behavioral advertising (even without payment)."},{value:"sensitive",label:"Sensitive",description:"Sensitive personal information (geolocation, health, race, biometrics, etc.). Requires opt-in even in California."}],nn=["necessary","functional","preferences","analytics","marketing"],Pl=[{value:"necessary",label:"Necessary",description:"Strictly required to deliver the service or ensure security/compliance. Always granted."},{value:"functional",label:"Functional",description:"Optional features that enhance functionality but are not essential."},{value:"preferences",label:"Preferences",description:'Remember user choices and personalize the experience ("Remember me").'},{value:"analytics",label:"Analytics",description:"Measure usage and performance to improve the product."},{value:"marketing",label:"Marketing",description:"Advertising, profiling, cross-site tracking, retargeting, ad personalization."}],bl={necessary:{legalBasis:"mandatory",listenGpc:!1},functional:{legalBasis:"legitimate_interest",listenGpc:!1},preferences:{legalBasis:"legitimate_interest",listenGpc:!1},analytics:{legalBasis:"consent",listenGpc:!0},marketing:{legalBasis:"consent",listenGpc:!0,cpraCategory:"sharing"}},Qs={security_storage:"necessary",functionality_storage:"functional",personalization_storage:"preferences",analytics_storage:"analytics",ad_storage:"marketing",ad_user_data:"marketing",ad_personalization:"marketing"};Dl=[{id:1,name:"Store and/or access information on a device",description:"Cookies, device identifiers, or other information can be stored or accessed on your device."},{id:2,name:"Select basic ads",description:"Ads can be shown based on the content you're viewing, the app you're using, or your approximate location."},{id:3,name:"Create a personalised ads profile",description:"A profile can be built about you and your interests to show you personalised ads."},{id:4,name:"Select personalised ads",description:"Personalised ads can be shown to you based on a profile about you."},{id:5,name:"Create a personalised content profile",description:"A profile can be built about you and your interests to show you personalised content."},{id:6,name:"Select personalised content",description:"Personalised content can be shown to you based on a profile about you."},{id:7,name:"Measure ad performance",description:"The performance and effectiveness of ads that you see or interact with can be measured."},{id:8,name:"Measure content performance",description:"The performance and effectiveness of content that you see or interact with can be measured."},{id:9,name:"Apply market research to generate audience insights",description:"Market research can be used to learn more about the audiences who visit sites or use apps."},{id:10,name:"Develop and improve products",description:"Your data can be used to improve existing systems and software, and to develop new products."},{id:11,name:"Use limited data to select content",description:"Content can be selected based on limited data such as the website you are visiting."}],kl=[{id:1,name:"Use precise geolocation data",description:"Your precise location (within a radius of less than 500 metres) can be used."},{id:2,name:"Actively scan device characteristics for identification",description:"Your device can be identified based on a scan of your device's unique combination of characteristics."}];ii={"opt-in":{categoryErrors:[{rule:"legal-basis-required",field:"legalBasis",check:i=>!i.legalBasis,message:i=>`Category "${i}" must have a legal basis set (Consent, Legitimate Interest, or Strictly Necessary) for GDPR compliance.`}],categoryWarnings:[{rule:"legitimate-interest-balancing-test-recommended",field:"legitimateInterestDescription",check:i=>i.legalBasis==="legitimate_interest"&&!String(i.legitimateInterestDescription??"").trim(),message:i=>`Category "${i}" relies on Legitimate Interest but has no balancing-test description. GDPR Art. 6(1)(f) requires you to conduct and be able to demonstrate a Legitimate Interests Assessment \u2014 note that Art. 5(3) ePrivacy still requires consent (LI cannot substitute) for the cookie storage/access itself, so this basis should only cover the downstream processing purpose, not the placement of a non-essential cookie.`,suggestion:`Document your Legitimate Interests Assessment in the category's "Legitimate Interest Description" field.`}],cookieErrors:[],cookieWarnings:[{rule:"pre-grant-opt-in-risk",field:"preGrant",check:(i,e)=>e==="consent"&&i.preGrant===!0,message:i=>`Parameter "${i}" is pre-granted, which may violate GDPR's opt-in requirement. Only use "Pre Grant" on custom profiles targeting jurisdictions where pre-granted consent is valid.`,suggestion:'Disable "Pre Grant" unless this profile specifically targets a jurisdiction that permits pre-granted consent.'}]},"opt-out":{categoryErrors:[],categoryWarnings:[],cookieErrors:[],cookieWarnings:[{rule:"gpc-recommended",field:"listenGpc",check:(i,e)=>e!=="mandatory"&&!i.listenGpc,message:i=>`Parameter "${i}" does not listen for the GPC signal. US state privacy laws require honoring GPC for opt-out of sale/sharing.`,suggestion:'Enable "Listen for GPC signal" on this parameter.'}]},"opt-out-strict":{categoryErrors:[],categoryWarnings:[],cookieErrors:[{rule:"cpra-category-required",field:"cpraCategory",check:(i,e)=>e!=="mandatory"&&!i.cpraCategory,message:i=>`Parameter "${i}" must have a CPRA category (Sale, Sharing, or Sensitive) assigned. Required under CPRA for all non-necessary parameters.`},{rule:"gpc-strict-required",field:"listenGpc",check:i=>(i.cpraCategory==="sale"||i.cpraCategory==="sharing")&&!i.listenGpc,message:i=>`Parameter "${i}" is tagged Sale/Sharing but does not listen for the GPC signal. 11 CCR \xA77025 requires honoring GPC as a Do Not Sell/Share My Personal Information request for these parameters \u2014 this is mandatory, not optional.`}],cookieWarnings:[]},"opt-in-dpdpa":{categoryErrors:[{rule:"no-li-allowed",field:"legalBasis",check:i=>i.legalBasis==="legitimate_interest",message:i=>`Category "${i}" uses Legitimate Interest, which is not a valid legal basis under India's DPDPA. Use Consent or Strictly Necessary.`},{rule:"legal-basis-required",field:"legalBasis",check:i=>!i.legalBasis,message:i=>`Category "${i}" must have a legal basis set (Consent or Strictly Necessary) for DPDPA compliance.`}],categoryWarnings:[],cookieErrors:[],cookieWarnings:[{rule:"pre-grant-opt-in-risk",field:"preGrant",check:(i,e)=>e==="consent"&&i.preGrant===!0,message:i=>`Parameter "${i}" is pre-granted, which may violate DPDPA's opt-in requirement. Only use "Pre Grant" on custom profiles targeting jurisdictions where pre-granted consent is valid.`,suggestion:'Disable "Pre Grant" unless this profile specifically targets a jurisdiction that permits pre-granted consent.'}]},"opt-in-china":{categoryErrors:[{rule:"no-li-allowed",field:"legalBasis",check:i=>i.legalBasis==="legitimate_interest",message:i=>`Category "${i}" uses Legitimate Interest, which is not one of PIPL Article 13's enumerated legal bases. Use Consent or Strictly Necessary.`},{rule:"legal-basis-required",field:"legalBasis",check:i=>!i.legalBasis,message:i=>`Category "${i}" must have a legal basis set for China PIPL compliance. Consent is the primary valid basis.`}],categoryWarnings:[],cookieErrors:[],cookieWarnings:[{rule:"pre-grant-opt-in-risk",field:"preGrant",check:(i,e)=>e==="consent"&&i.preGrant===!0,message:i=>`Parameter "${i}" is pre-granted, which may violate PIPL's opt-in requirement. Only use "Pre Grant" on custom profiles targeting jurisdictions where pre-granted consent is valid.`,suggestion:'Disable "Pre Grant" unless this profile specifically targets a jurisdiction that permits pre-granted consent.'}]},"opt-in-brazil":{categoryErrors:[{rule:"legal-basis-required",field:"legalBasis",check:i=>!i.legalBasis,message:i=>`Category "${i}" must have a legal basis set. Brazil's LGPD requires one of ten legal bases; Consent or Legitimate Interest are most common for parameters.`}],categoryWarnings:[{rule:"legitimate-interest-balancing-test-recommended",field:"legitimateInterestDescription",check:i=>i.legalBasis==="legitimate_interest"&&!String(i.legitimateInterestDescription??"").trim(),message:i=>`Category "${i}" relies on Legitimate Interest but has no balancing-test description. LGPD Art. 10 requires the legitimate interest basis to be documented and, on request, made available to the ANPD as a Data Protection Impact Report (relat\xF3rio de impacto).`,suggestion:`Document your legitimate interest assessment in the category's "Legitimate Interest Description" field.`}],cookieErrors:[],cookieWarnings:[{rule:"pre-grant-opt-in-risk",field:"preGrant",check:(i,e)=>e==="consent"&&i.preGrant===!0,message:i=>`Parameter "${i}" is pre-granted, which may violate LGPD's opt-in requirement. Only use "Pre Grant" on custom profiles targeting jurisdictions where pre-granted consent is valid.`,suggestion:'Disable "Pre Grant" unless this profile specifically targets a jurisdiction that permits pre-granted consent.'}]},"general-privacy-consent":{categoryErrors:[],categoryWarnings:[{rule:"legal-basis-recommended",field:"legalBasis",check:i=>!i.legalBasis,message:i=>`Category "${i}" has no legal basis documented. While a strict cookie banner may not be legally required in this jurisdiction, documenting legal basis is a privacy best practice.`,suggestion:"Set a legal basis to improve compliance documentation and future-proof against stricter enforcement."},{rule:"legitimate-interest-balancing-test-recommended",field:"legitimateInterestDescription",check:i=>i.legalBasis==="legitimate_interest"&&!String(i.legitimateInterestDescription??"").trim(),message:i=>`Category "${i}" relies on Legitimate Interest but has no balancing-test description documented. Most legitimate-interest-style bases in this jurisdiction group expect a documented justification, and it future-proofs the profile against stricter enforcement.`,suggestion:`Document your legitimate interest justification in the category's "Legitimate Interest Description" field.`}],cookieErrors:[],cookieWarnings:[]},"notice-only":{categoryErrors:[],categoryWarnings:[],cookieErrors:[],cookieWarnings:[]}},De={version:"2026-07",countries:{AT:{name:"Austria",type:"country",complianceGroup:"opt-in",default:"opt-in",description:"Austria (GDPR)",locales:["de-AT"],compliance:["gdpr","eprivacy"],timezones:["Europe/Vienna"]},BE:{name:"Belgium",type:"country",complianceGroup:"opt-in",default:"opt-in",description:"Belgium (GDPR)",locales:["nl-BE","fr-BE"],compliance:["gdpr","eprivacy"],timezones:["Europe/Brussels"]},BG:{name:"Bulgaria",type:"country",complianceGroup:"opt-in",default:"opt-in",description:"Bulgaria (GDPR)",locales:["bg-BG"],compliance:["gdpr","eprivacy"],timezones:["Europe/Sofia"]},HR:{name:"Croatia",type:"country",complianceGroup:"opt-in",default:"opt-in",description:"Croatia (GDPR)",locales:["hr-HR"],compliance:["gdpr","eprivacy"],timezones:["Europe/Zagreb"]},CY:{name:"Cyprus",type:"country",complianceGroup:"opt-in",default:"opt-in",description:"Cyprus (GDPR)",locales:["el-CY"],compliance:["gdpr","eprivacy"],timezones:["Asia/Nicosia"]},CZ:{name:"Czechia",type:"country",complianceGroup:"opt-in",default:"opt-in",description:"Czechia (GDPR)",locales:["cs-CZ"],compliance:["gdpr","eprivacy"],timezones:["Europe/Prague"]},DK:{name:"Denmark",type:"country",complianceGroup:"opt-in",default:"opt-in",description:"Denmark (GDPR)",locales:["da-DK"],compliance:["gdpr","eprivacy"],timezones:["Europe/Copenhagen"]},EE:{name:"Estonia",type:"country",complianceGroup:"opt-in",default:"opt-in",description:"Estonia (GDPR)",locales:["et-EE"],compliance:["gdpr","eprivacy"],timezones:["Europe/Tallinn"]},FI:{name:"Finland",type:"country",complianceGroup:"opt-in",default:"opt-in",description:"Finland (GDPR)",locales:["fi-FI"],compliance:["gdpr","eprivacy"],timezones:["Europe/Helsinki"]},FR:{name:"France",type:"country",complianceGroup:"opt-in",default:"opt-in",description:"France (GDPR)",locales:["fr-FR"],compliance:["gdpr","eprivacy"],timezones:["Europe/Paris"]},DE:{name:"Germany",type:"country",complianceGroup:"opt-in",default:"opt-in",description:"Germany (GDPR)",locales:["de-DE"],compliance:["gdpr","eprivacy"],timezones:["Europe/Berlin"]},GR:{name:"Greece",type:"country",complianceGroup:"opt-in",default:"opt-in",description:"Greece (GDPR)",locales:["el-GR"],compliance:["gdpr","eprivacy"],timezones:["Europe/Athens"]},HU:{name:"Hungary",type:"country",complianceGroup:"opt-in",default:"opt-in",description:"Hungary (GDPR)",locales:["hu-HU"],compliance:["gdpr","eprivacy"],timezones:["Europe/Budapest"]},IE:{name:"Ireland",type:"country",complianceGroup:"opt-in",default:"opt-in",description:"Ireland (GDPR)",locales:["en"],compliance:["gdpr","eprivacy"],timezones:["Europe/Dublin"]},IT:{name:"Italy",type:"country",complianceGroup:"opt-in",default:"opt-in",description:"Italy (GDPR)",locales:["it-IT"],compliance:["gdpr","eprivacy"],timezones:["Europe/Rome"]},LV:{name:"Latvia",type:"country",complianceGroup:"opt-in",default:"opt-in",description:"Latvia (GDPR)",locales:["lv-LV"],compliance:["gdpr","eprivacy"],timezones:["Europe/Riga"]},LT:{name:"Lithuania",type:"country",complianceGroup:"opt-in",default:"opt-in",description:"Lithuania (GDPR)",locales:["lt-LT"],compliance:["gdpr","eprivacy"],timezones:["Europe/Vilnius"]},LU:{name:"Luxembourg",type:"country",complianceGroup:"opt-in",default:"opt-in",description:"Luxembourg (GDPR)",locales:["fr-LU","de-LU"],compliance:["gdpr","eprivacy"],timezones:["Europe/Luxembourg"]},MT:{name:"Malta",type:"country",complianceGroup:"opt-in",default:"opt-in",description:"Malta (GDPR)",locales:["mt-MT","en"],compliance:["gdpr","eprivacy"],timezones:["Europe/Malta"]},NL:{name:"Netherlands",type:"country",complianceGroup:"opt-in",default:"opt-in",description:"Netherlands (GDPR)",locales:["nl-NL"],compliance:["gdpr","eprivacy"],timezones:["Europe/Amsterdam"]},PL:{name:"Poland",type:"country",complianceGroup:"opt-in",default:"opt-in",description:"Poland (GDPR)",locales:["pl-PL"],compliance:["gdpr","eprivacy"],timezones:["Europe/Warsaw"]},PT:{name:"Portugal",type:"country",complianceGroup:"opt-in",default:"opt-in",description:"Portugal (GDPR)",locales:["pt-PT"],compliance:["gdpr","eprivacy"],timezones:["Europe/Lisbon","Atlantic/Madeira","Atlantic/Azores"]},RO:{name:"Romania",type:"country",complianceGroup:"opt-in",default:"opt-in",description:"Romania (GDPR)",locales:["ro-RO"],compliance:["gdpr","eprivacy"],timezones:["Europe/Bucharest"]},SK:{name:"Slovakia",type:"country",complianceGroup:"opt-in",default:"opt-in",description:"Slovakia (GDPR)",locales:["sk-SK"],compliance:["gdpr","eprivacy"],timezones:["Europe/Bratislava"]},SI:{name:"Slovenia",type:"country",complianceGroup:"opt-in",default:"opt-in",description:"Slovenia (GDPR)",locales:["sl-SI"],compliance:["gdpr","eprivacy"],timezones:["Europe/Ljubljana"]},ES:{name:"Spain",type:"country",complianceGroup:"opt-in",default:"opt-in",description:"Spain (GDPR)",locales:["es-ES"],compliance:["gdpr","eprivacy"],timezones:["Europe/Madrid","Africa/Ceuta","Atlantic/Canary"]},SE:{name:"Sweden",type:"country",complianceGroup:"opt-in",default:"opt-in",description:"Sweden (GDPR)",locales:["sv-SE"],compliance:["gdpr","eprivacy"],timezones:["Europe/Stockholm"]},IS:{name:"Iceland",type:"country",complianceGroup:"opt-in",default:"opt-in",description:"Iceland (GDPR via EEA)",locales:["is-IS"],compliance:["gdpr","eprivacy"],timezones:["Atlantic/Reykjavik"]},LI:{name:"Liechtenstein",type:"country",complianceGroup:"opt-in",default:"opt-in",description:"Liechtenstein (GDPR via EEA)",locales:["de-LI"],compliance:["gdpr","eprivacy"],timezones:["Europe/Vaduz"]},NO:{name:"Norway",type:"country",complianceGroup:"opt-in",default:"opt-in",description:"Norway (GDPR via EEA)",locales:["nb-NO"],compliance:["gdpr","eprivacy"],timezones:["Europe/Oslo","Arctic/Longyearbyen"]},AD:{name:"Andorra",type:"country",complianceGroup:"opt-in",default:"opt-in",description:"Andorra (GDPR-aligned)",locales:["ca-AD"],compliance:["gdpr"],timezones:["Europe/Andorra"]},AL:{name:"Albania",type:"country",complianceGroup:"opt-in",default:"opt-in",description:"Albania (GDPR-aligned)",locales:["sq-AL"],compliance:["gdpr"],timezones:["Europe/Tirane"]},BA:{name:"Bosnia and Herzegovina",type:"country",complianceGroup:"opt-in",default:"opt-in",description:"Bosnia and Herzegovina (GDPR-aligned)",locales:["bs-BA","sr-Latn-BA"],compliance:["gdpr"],timezones:["Europe/Sarajevo"]},GG:{name:"Guernsey",type:"country",complianceGroup:"opt-in",default:"opt-in",description:"Guernsey (DPA based on GDPR)",locales:["en"],compliance:["gdpr"],timezones:["Europe/Guernsey"]},GI:{name:"Gibraltar",type:"country",complianceGroup:"opt-in",default:"opt-in",description:"Gibraltar (DPA based on UK GDPR)",locales:["en"],compliance:["uk-gdpr"],timezones:["Europe/Gibraltar"]},GL:{name:"Greenland",type:"country",complianceGroup:"opt-in",default:"opt-in",description:"Greenland (Danish GDPR implementation)",locales:["da-GL"],compliance:["gdpr"],timezones:["America/Nuuk","America/Danmarkshavn","America/Scoresbysund","America/Thule"]},MC:{name:"Monaco",type:"country",complianceGroup:"opt-in",default:"opt-in",description:"Monaco (GDPR-aligned)",locales:["fr-MC"],compliance:["gdpr"],timezones:["Europe/Monaco"]},ME:{name:"Montenegro",type:"country",complianceGroup:"opt-in",default:"opt-in",description:"Montenegro (GDPR-aligned)",locales:["sr-Latn-ME"],compliance:["gdpr"],timezones:["Europe/Podgorica"]},MK:{name:"North Macedonia",type:"country",complianceGroup:"opt-in",default:"opt-in",description:"North Macedonia (GDPR-aligned)",locales:["mk-MK"],compliance:["gdpr"],timezones:["Europe/Skopje"]},RS:{name:"Serbia",type:"country",complianceGroup:"opt-in",default:"opt-in",description:"Serbia (GDPR-aligned)",locales:["sr-RS"],compliance:["gdpr"],timezones:["Europe/Belgrade"]},SM:{name:"San Marino",type:"country",complianceGroup:"opt-in",default:"opt-in",description:"San Marino (GDPR-aligned)",locales:["it-SM"],compliance:["gdpr"],timezones:["Europe/San_Marino"]},TR:{name:"T\xFCrkiye",type:"country",complianceGroup:"opt-in",default:"opt-in",description:"T\xFCrkiye (KVKK)",locales:["tr-TR"],compliance:["kvkk"],timezones:["Europe/Istanbul"]},CA:{name:"Canada",type:"country",complianceGroup:"general-privacy-consent",default:"general-privacy-consent",description:"Canada (PIPEDA / Law 25)",locales:["en","fr-CA"],compliance:["pipeda","law25"],timezones:["America/St_Johns","America/Halifax","America/Toronto","America/Winnipeg","America/Edmonton","America/Vancouver"],overriddenRegions:{QC:{name:"Quebec",type:"region",complianceGroup:"opt-in",description:"Quebec \u2014 Law 25 (GDPR-style opt-in)"}}},US:{name:"United States",type:"country",complianceGroup:"opt-out",default:"opt-out-strict",description:"United States \u2014 opt-out-strict (CPRA) used when state cannot be detected",locales:["en","es-US"],compliance:["ccpa","cpra","vcdpa","cpa-co","ctdpa","ucpa","icdpa-ia","icdpa-in","tipa","mcdpa-mt","mcdpa-mn","ocpa","tdpsa","dpdpa-de","njdpa","nhpa","ndpa-ne","modpa","kcdpa","ridtpa"],timezones:["America/New_York","America/Chicago","America/Denver","America/Phoenix","America/Los_Angeles","America/Anchorage","Pacific/Honolulu"],overriddenRegions:{CA:{name:"California",type:"region",complianceGroup:"opt-out-strict",description:"California \u2014 CPRA/CCPA"},VA:{name:"Virginia",type:"region",complianceGroup:"opt-out",description:"Virginia \u2014 VCDPA"},CO:{name:"Colorado",type:"region",complianceGroup:"opt-out",description:"Colorado \u2014 CPA",requiresSensitiveOptIn:!0},CT:{name:"Connecticut",type:"region",complianceGroup:"opt-out",description:"Connecticut \u2014 CTDPA"},UT:{name:"Utah",type:"region",complianceGroup:"opt-out",description:"Utah \u2014 UCPA"},TX:{name:"Texas",type:"region",complianceGroup:"opt-out",description:"Texas \u2014 TDPSA"},DE:{name:"Delaware",type:"region",complianceGroup:"opt-out",description:"Delaware \u2014 DPDPA"},NJ:{name:"New Jersey",type:"region",complianceGroup:"opt-out",description:"New Jersey \u2014 NJDPA"},OR:{name:"Oregon",type:"region",complianceGroup:"opt-out",description:"Oregon \u2014 OCPA"},MN:{name:"Minnesota",type:"region",complianceGroup:"opt-out",description:"Minnesota \u2014 MCDPA"},MD:{name:"Maryland",type:"region",complianceGroup:"opt-out",description:"Maryland \u2014 MODPA"},KY:{name:"Kentucky",type:"region",complianceGroup:"opt-out",description:"Kentucky \u2014 KCDPA"},TN:{name:"Tennessee",type:"region",complianceGroup:"opt-out",description:"Tennessee \u2014 TIPA"},NE:{name:"Nebraska",type:"region",complianceGroup:"opt-out",description:"Nebraska \u2014 NDPA"},IA:{name:"Iowa",type:"region",complianceGroup:"opt-out",description:"Iowa \u2014 ICDPA"},IN:{name:"Indiana",type:"region",complianceGroup:"opt-out",description:"Indiana \u2014 ICDPA"},MT:{name:"Montana",type:"region",complianceGroup:"opt-out",description:"Montana \u2014 MCDPA"},NH:{name:"New Hampshire",type:"region",complianceGroup:"opt-out",description:"New Hampshire \u2014 NHPA"},RI:{name:"Rhode Island",type:"region",complianceGroup:"opt-out",description:"Rhode Island \u2014 RIDTPA"}}},AR:{name:"Argentina",type:"country",complianceGroup:"general-privacy-consent",default:"general-privacy-consent",description:"Argentina (LPDP)",locales:["es-AR"],compliance:["lpdp-ar"],timezones:["America/Argentina/Buenos_Aires"]},BO:{name:"Bolivia",type:"country",complianceGroup:"general-privacy-consent",default:"general-privacy-consent",description:"Bolivia",locales:["es-BO"],compliance:[],timezones:["America/La_Paz"]},BR:{name:"Brazil",type:"country",complianceGroup:"opt-in-brazil",default:"opt-in-brazil",description:"Brazil (LGPD)",locales:["pt-BR"],compliance:["lgpd"],timezones:["America/Noronha","America/Sao_Paulo","America/Manaus","America/Rio_Branco"]},CL:{name:"Chile",type:"country",complianceGroup:"general-privacy-consent",default:"general-privacy-consent",description:"Chile (Law 19.628)",locales:["es-CL"],compliance:["law19628-cl"],timezones:["America/Santiago","Pacific/Easter"]},CO:{name:"Colombia",type:"country",complianceGroup:"general-privacy-consent",default:"general-privacy-consent",description:"Colombia (Law 1581)",locales:["es-CO"],compliance:["law1581-co"],timezones:["America/Bogota"]},CR:{name:"Costa Rica",type:"country",complianceGroup:"general-privacy-consent",default:"general-privacy-consent",description:"Costa Rica (LPDP)",locales:["es-CR"],compliance:["lpdp-cr"],timezones:["America/Costa_Rica"]},DO:{name:"Dominican Republic",type:"country",complianceGroup:"general-privacy-consent",default:"general-privacy-consent",description:"Dominican Republic",locales:["es-DO"],compliance:["data-protection-do"],timezones:["America/Santo_Domingo"]},EC:{name:"Ecuador",type:"country",complianceGroup:"general-privacy-consent",default:"general-privacy-consent",description:"Ecuador (LOPDP)",locales:["es-EC"],compliance:["lopdp-ec"],timezones:["America/Guayaquil","Pacific/Galapagos"]},GF:{name:"French Guiana",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"French Guiana",locales:["fr-GF"],compliance:[],timezones:["America/Cayenne"]},GT:{name:"Guatemala",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Guatemala",locales:["es-GT"],compliance:[],timezones:["America/Guatemala"]},GY:{name:"Guyana",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Guyana",locales:["en"],compliance:[],timezones:["America/Guyana"]},HN:{name:"Honduras",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Honduras",locales:["es-HN"],compliance:[],timezones:["America/Tegucigalpa"]},HT:{name:"Haiti",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Haiti",locales:["fr-HT"],compliance:[],timezones:["America/Port-au-Prince"]},JM:{name:"Jamaica",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Jamaica",locales:["en"],compliance:[],timezones:["America/Jamaica"]},MX:{name:"Mexico",type:"country",complianceGroup:"general-privacy-consent",default:"general-privacy-consent",description:"Mexico (LFPDPPP)",locales:["es-MX"],compliance:["lfpdppp"],timezones:["America/Mexico_City","America/Cancun","America/Chihuahua","America/Hermosillo","America/Tijuana"]},NI:{name:"Nicaragua",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Nicaragua",locales:["es-NI"],compliance:[],timezones:["America/Managua"]},PA:{name:"Panama",type:"country",complianceGroup:"general-privacy-consent",default:"general-privacy-consent",description:"Panama",locales:["es-PA"],compliance:["data-protection-pa"],timezones:["America/Panama"]},PE:{name:"Peru",type:"country",complianceGroup:"general-privacy-consent",default:"general-privacy-consent",description:"Peru (LPDP)",locales:["es-PE"],compliance:["lpdp-pe"],timezones:["America/Lima"]},PY:{name:"Paraguay",type:"country",complianceGroup:"general-privacy-consent",default:"general-privacy-consent",description:"Paraguay",locales:["es-PY"],compliance:[],timezones:["America/Asuncion"]},SR:{name:"Suriname",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Suriname",locales:["nl-SR"],compliance:[],timezones:["America/Paramaribo"]},SV:{name:"El Salvador",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"El Salvador",locales:["es-SV"],compliance:[],timezones:["America/El_Salvador"]},TT:{name:"Trinidad and Tobago",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Trinidad and Tobago",locales:["en"],compliance:[],timezones:["America/Port_of_Spain"]},UY:{name:"Uruguay",type:"country",complianceGroup:"general-privacy-consent",default:"general-privacy-consent",description:"Uruguay (Law 18.331)",locales:["es-UY"],compliance:["law18331-uy"],timezones:["America/Montevideo"]},VE:{name:"Venezuela",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Venezuela",locales:["es-VE"],compliance:[],timezones:["America/Caracas"]},AG:{name:"Antigua and Barbuda",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Antigua and Barbuda",locales:["en"],compliance:[],timezones:["America/Antigua"]},BB:{name:"Barbados",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Barbados",locales:["en"],compliance:[],timezones:["America/Barbados"]},BL:{name:"Saint Barth\xE9lemy",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Saint Barth\xE9lemy",locales:["fr-BL"],compliance:[],timezones:["America/St_Barthelemy"]},BM:{name:"Bermuda",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Bermuda",locales:["en"],compliance:[],timezones:["Atlantic/Bermuda"]},BS:{name:"Bahamas",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Bahamas",locales:["en"],compliance:[],timezones:["America/Nassau"]},CU:{name:"Cuba",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Cuba",locales:["es-CU"],compliance:[],timezones:["America/Havana"]},DM:{name:"Dominica",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Dominica",locales:["en"],compliance:[],timezones:["America/Dominica"]},GD:{name:"Grenada",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Grenada",locales:["en"],compliance:[],timezones:["America/Grenada"]},KN:{name:"Saint Kitts and Nevis",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Saint Kitts and Nevis",locales:["en"],compliance:[],timezones:["America/St_Kitts"]},LC:{name:"Saint Lucia",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Saint Lucia",locales:["en"],compliance:[],timezones:["America/St_Lucia"]},PM:{name:"Saint Pierre and Miquelon",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Saint Pierre and Miquelon",locales:["fr-PM"],compliance:[],timezones:["America/Miquelon"]},PR:{name:"Puerto Rico",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Puerto Rico",locales:["es-PR","en"],compliance:[],timezones:["America/Puerto_Rico"]},VC:{name:"Saint Vincent and the Grenadines",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Saint Vincent and the Grenadines",locales:["en"],compliance:[],timezones:["America/St_Vincent"]},IN:{name:"India",type:"country",complianceGroup:"opt-in-dpdpa",default:"opt-in-dpdpa",description:"India (DPDPA)",locales:["hi-IN","en","bn-IN","ta-IN"],compliance:["dpdpa"],timezones:["Asia/Kolkata","Asia/Calcutta"]},CN:{name:"China",type:"country",complianceGroup:"opt-in-china",default:"opt-in-china",description:"China (PIPL + DSL + CSL)",locales:["zh-CN"],compliance:["pipl","dsl-cn","csl-cn"],timezones:["Asia/Shanghai"]},BN:{name:"Brunei",type:"country",complianceGroup:"general-privacy-consent",default:"general-privacy-consent",description:"Brunei (Personal Data Protection Order)",locales:["ms-BN","en"],compliance:["privacy-bn"],timezones:["Asia/Brunei"]},ID:{name:"Indonesia",type:"country",complianceGroup:"general-privacy-consent",default:"general-privacy-consent",description:"Indonesia (PDP Law)",locales:["id-ID"],compliance:["pdp-id"],timezones:["Asia/Jakarta","Asia/Makassar","Asia/Jayapura"]},KH:{name:"Cambodia",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Cambodia",locales:["km-KH"],compliance:[],timezones:["Asia/Phnom_Penh"]},LA:{name:"Laos",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Laos",locales:["lo-LA"],compliance:[],timezones:["Asia/Vientiane"]},MM:{name:"Myanmar",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Myanmar",locales:["my-MM"],compliance:[],timezones:["Asia/Yangon"]},MY:{name:"Malaysia",type:"country",complianceGroup:"general-privacy-consent",default:"general-privacy-consent",description:"Malaysia (PDPA)",locales:["ms-MY","zh-MY","en"],compliance:["pdpa-my"],timezones:["Asia/Kuala_Lumpur","Asia/Kuching"]},PH:{name:"Philippines",type:"country",complianceGroup:"general-privacy-consent",default:"general-privacy-consent",description:"Philippines (DPA)",locales:["fil-PH","en"],compliance:["dpa-ph"],timezones:["Asia/Manila"]},SG:{name:"Singapore",type:"country",complianceGroup:"general-privacy-consent",default:"general-privacy-consent",description:"Singapore (PDPA)",locales:["zh-SG","ms-SG","ta-SG","en"],compliance:["pdpa-sg"],timezones:["Asia/Singapore"]},TH:{name:"Thailand",type:"country",complianceGroup:"opt-in",default:"opt-in",description:"Thailand (PDPA \u2014 GDPR-style opt-in)",locales:["th-TH"],compliance:["pdpa-th"],timezones:["Asia/Bangkok"]},TL:{name:"Timor-Leste",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Timor-Leste",locales:["pt-TL"],compliance:[],timezones:["Asia/Dili"]},VN:{name:"Vietnam",type:"country",complianceGroup:"general-privacy-consent",default:"general-privacy-consent",description:"Vietnam (PDPD)",locales:["vi-VN"],compliance:["pdpd-vn"],timezones:["Asia/Ho_Chi_Minh"]},HK:{name:"Hong Kong",type:"country",complianceGroup:"general-privacy-consent",default:"general-privacy-consent",description:"Hong Kong SAR (PDPO)",locales:["zh-HK"],compliance:["pdpl-hk"],timezones:["Asia/Hong_Kong"]},JP:{name:"Japan",type:"country",complianceGroup:"general-privacy-consent",default:"general-privacy-consent",description:"Japan (APPI)",locales:["ja-JP"],compliance:["appi"],timezones:["Asia/Tokyo"]},KP:{name:"North Korea",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"North Korea",locales:["ko-KP"],compliance:[],timezones:["Asia/Pyongyang"]},KR:{name:"South Korea",type:"country",complianceGroup:"general-privacy-consent",default:"general-privacy-consent",description:"South Korea (PIPA)",locales:["ko-KR"],compliance:["pipa-kr"],timezones:["Asia/Seoul"]},MN:{name:"Mongolia",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Mongolia",locales:["mn-MN"],compliance:[],timezones:["Asia/Ulaanbaatar","Asia/Hovd"]},MO:{name:"Macau",type:"country",complianceGroup:"general-privacy-consent",default:"general-privacy-consent",description:"Macau SAR (PDPA)",locales:["zh-MO","pt-MO"],compliance:["pdpa-mo"],timezones:["Asia/Macau"]},TW:{name:"Taiwan",type:"country",complianceGroup:"general-privacy-consent",default:"general-privacy-consent",description:"Taiwan (PDPL)",locales:["zh-TW"],compliance:["pdpl-tw"],timezones:["Asia/Taipei"]},AF:{name:"Afghanistan",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Afghanistan",locales:["fa-AF"],compliance:[],timezones:["Asia/Kabul"]},BD:{name:"Bangladesh",type:"country",complianceGroup:"general-privacy-consent",default:"general-privacy-consent",description:"Bangladesh",locales:["bn-BD"],compliance:[],timezones:["Asia/Dhaka"]},BT:{name:"Bhutan",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Bhutan",locales:["dz-BT"],compliance:[],timezones:["Asia/Thimphu"]},IO:{name:"British Indian Ocean Territory",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"British Indian Ocean Territory",locales:["en"],compliance:[],timezones:["Indian/Chagos"]},LK:{name:"Sri Lanka",type:"country",complianceGroup:"general-privacy-consent",default:"general-privacy-consent",description:"Sri Lanka",locales:["si-LK","ta-LK"],compliance:["privacy-lk"],timezones:["Asia/Colombo"]},MV:{name:"Maldives",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Maldives",locales:["dv-MV"],compliance:[],timezones:["Indian/Maldives"]},NP:{name:"Nepal",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Nepal",locales:["ne-NP"],compliance:["privacy-np"],timezones:["Asia/Kathmandu"]},PK:{name:"Pakistan",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Pakistan",locales:["ur-PK","en"],compliance:[],timezones:["Asia/Karachi"]},AM:{name:"Armenia",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Armenia",locales:["hy-AM"],compliance:[],timezones:["Asia/Yerevan"]},AZ:{name:"Azerbaijan",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Azerbaijan",locales:["az-AZ"],compliance:[],timezones:["Asia/Baku"]},GE:{name:"Georgia",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Georgia",locales:["ka-GE"],compliance:[],timezones:["Asia/Tbilisi"]},KG:{name:"Kyrgyzstan",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Kyrgyzstan",locales:["ky-KG","ru-KG"],compliance:[],timezones:["Asia/Bishkek"]},KZ:{name:"Kazakhstan",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Kazakhstan",locales:["kk-KZ","ru-KZ"],compliance:[],timezones:["Asia/Almaty","Asia/Aqtobe"]},TJ:{name:"Tajikistan",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Tajikistan",locales:["tg-TJ"],compliance:[],timezones:["Asia/Dushanbe"]},TM:{name:"Turkmenistan",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Turkmenistan",locales:["tk-TM"],compliance:[],timezones:["Asia/Ashgabat"]},UZ:{name:"Uzbekistan",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Uzbekistan",locales:["uz-UZ"],compliance:[],timezones:["Asia/Tashkent","Asia/Samarkand"]},AE:{name:"United Arab Emirates",type:"country",complianceGroup:"general-privacy-consent",default:"general-privacy-consent",description:"United Arab Emirates (UAE PDPL / DIFC DPL / ADGM DPR)",locales:["ar-AE"],compliance:["uae-pdpl","difc-dpl","adgm-dpr"],timezones:["Asia/Dubai"]},BH:{name:"Bahrain",type:"country",complianceGroup:"general-privacy-consent",default:"general-privacy-consent",description:"Bahrain (PDPL)",locales:["ar-BH"],compliance:["pdpl-bh"],timezones:["Asia/Bahrain"]},IL:{name:"Israel",type:"country",complianceGroup:"general-privacy-consent",default:"general-privacy-consent",description:"Israel (Privacy Protection Law)",locales:["he-IL","ar-IL"],compliance:["privacy-il"],timezones:["Asia/Jerusalem"]},IQ:{name:"Iraq",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Iraq",locales:["ar-IQ"],compliance:[],timezones:["Asia/Baghdad"]},IR:{name:"Iran",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Iran",locales:["fa-IR"],compliance:[],timezones:["Asia/Tehran"]},JO:{name:"Jordan",type:"country",complianceGroup:"general-privacy-consent",default:"general-privacy-consent",description:"Jordan",locales:["ar-JO"],compliance:[],timezones:["Asia/Amman"]},KW:{name:"Kuwait",type:"country",complianceGroup:"general-privacy-consent",default:"general-privacy-consent",description:"Kuwait",locales:["ar-KW"],compliance:["privacy-kw"],timezones:["Asia/Kuwait"]},LB:{name:"Lebanon",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Lebanon",locales:["ar-LB"],compliance:[],timezones:["Asia/Beirut"]},OM:{name:"Oman",type:"country",complianceGroup:"general-privacy-consent",default:"general-privacy-consent",description:"Oman (PDPL)",locales:["ar-OM"],compliance:["pdpl-om"],timezones:["Asia/Muscat"]},PS:{name:"Palestine",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Palestine",locales:["ar-PS"],compliance:[],timezones:["Asia/Gaza","Asia/Hebron"]},QA:{name:"Qatar",type:"country",complianceGroup:"general-privacy-consent",default:"general-privacy-consent",description:"Qatar (PDPL)",locales:["ar-QA"],compliance:["qpdl-qa"],timezones:["Asia/Qatar"]},SA:{name:"Saudi Arabia",type:"country",complianceGroup:"general-privacy-consent",default:"general-privacy-consent",description:"Saudi Arabia (PDPL)",locales:["ar-SA"],compliance:["pdpl-sa"],timezones:["Asia/Riyadh"]},SY:{name:"Syria",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Syria",locales:["ar-SY"],compliance:[],timezones:["Asia/Damascus"]},YE:{name:"Yemen",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Yemen",locales:["ar-YE"],compliance:[],timezones:["Asia/Aden"]},BF:{name:"Burkina Faso",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Burkina Faso",locales:["fr-BF"],compliance:[],timezones:["Africa/Ouagadougou"]},BJ:{name:"Benin",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Benin",locales:["fr-BJ"],compliance:[],timezones:["Africa/Porto-Novo"]},CI:{name:"C\xF4te d'Ivoire",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"C\xF4te d'Ivoire",locales:["fr-CI"],compliance:[],timezones:["Africa/Abidjan"]},CM:{name:"Cameroon",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Cameroon",locales:["fr-CM","en"],compliance:[],timezones:["Africa/Douala"]},CV:{name:"Cabo Verde",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Cabo Verde",locales:["pt-CV"],compliance:[],timezones:["Atlantic/Cape_Verde"]},GA:{name:"Gabon",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Gabon",locales:["fr-GA"],compliance:[],timezones:["Africa/Libreville"]},GH:{name:"Ghana",type:"country",complianceGroup:"general-privacy-consent",default:"general-privacy-consent",description:"Ghana (DPA)",locales:["en"],compliance:["dpa-gh"],timezones:["Africa/Accra"]},GM:{name:"Gambia",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Gambia",locales:["en"],compliance:[],timezones:["Africa/Banjul"]},GN:{name:"Guinea",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Guinea",locales:["fr-GN"],compliance:[],timezones:["Africa/Conakry"]},GQ:{name:"Equatorial Guinea",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Equatorial Guinea",locales:["es-GQ","fr-GQ"],compliance:[],timezones:["Africa/Malabo"]},GW:{name:"Guinea-Bissau",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Guinea-Bissau",locales:["pt-GW"],compliance:[],timezones:["Africa/Bissau"]},LR:{name:"Liberia",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Liberia",locales:["en"],compliance:[],timezones:["Africa/Monrovia"]},ML:{name:"Mali",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Mali",locales:["fr-ML"],compliance:[],timezones:["Africa/Bamako"]},MR:{name:"Mauritania",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Mauritania",locales:["ar-MR"],compliance:[],timezones:["Africa/Nouakchott"]},NE:{name:"Niger",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Niger",locales:["fr-NE"],compliance:[],timezones:["Africa/Niamey"]},NG:{name:"Nigeria",type:"country",complianceGroup:"general-privacy-consent",default:"general-privacy-consent",description:"Nigeria (NDPA)",locales:["en"],compliance:["ndpa-ng"],timezones:["Africa/Lagos"]},SL:{name:"Sierra Leone",type:"country",complianceGroup:"general-privacy-consent",default:"general-privacy-consent",description:"Sierra Leone",locales:["en"],compliance:[],timezones:["Africa/Freetown"]},SN:{name:"Senegal",type:"country",complianceGroup:"general-privacy-consent",default:"general-privacy-consent",description:"Senegal",locales:["fr-SN"],compliance:[],timezones:["Africa/Dakar"]},TG:{name:"Togo",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Togo",locales:["fr-TG"],compliance:[],timezones:["Africa/Lome"]},BI:{name:"Burundi",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Burundi",locales:["fr-BI"],compliance:[],timezones:["Africa/Bujumbura"]},DJ:{name:"Djibouti",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Djibouti",locales:["fr-DJ","ar-DJ"],compliance:[],timezones:["Africa/Djibouti"]},ER:{name:"Eritrea",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Eritrea",locales:["ti-ER"],compliance:[],timezones:["Africa/Asmara"]},ET:{name:"Ethiopia",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Ethiopia",locales:["am-ET"],compliance:[],timezones:["Africa/Addis_Ababa"]},KE:{name:"Kenya",type:"country",complianceGroup:"general-privacy-consent",default:"general-privacy-consent",description:"Kenya (DPA)",locales:["sw-KE","en"],compliance:["dpa-ke"],timezones:["Africa/Nairobi"]},KM:{name:"Comoros",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Comoros",locales:["ar-KM","fr-KM"],compliance:[],timezones:["Indian/Comoro"]},MG:{name:"Madagascar",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Madagascar",locales:["fr-MG"],compliance:[],timezones:["Indian/Antananarivo"]},MU:{name:"Mauritius",type:"country",complianceGroup:"general-privacy-consent",default:"general-privacy-consent",description:"Mauritius (DPA)",locales:["en","fr-MU"],compliance:["dpa-mu"],timezones:["Indian/Mauritius"]},MW:{name:"Malawi",type:"country",complianceGroup:"general-privacy-consent",default:"general-privacy-consent",description:"Malawi",locales:["en"],compliance:[],timezones:["Africa/Blantyre"]},MZ:{name:"Mozambique",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Mozambique",locales:["pt-MZ"],compliance:[],timezones:["Africa/Maputo"]},RW:{name:"Rwanda",type:"country",complianceGroup:"general-privacy-consent",default:"general-privacy-consent",description:"Rwanda (DPA)",locales:["rw-RW","en"],compliance:["dpa-rw"],timezones:["Africa/Kigali"]},SC:{name:"Seychelles",type:"country",complianceGroup:"general-privacy-consent",default:"general-privacy-consent",description:"Seychelles",locales:["fr-SC","en"],compliance:[],timezones:["Indian/Mahe"]},SO:{name:"Somalia",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Somalia",locales:["so-SO"],compliance:[],timezones:["Africa/Mogadishu"]},SS:{name:"South Sudan",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"South Sudan",locales:["en"],compliance:[],timezones:["Africa/Juba"]},ST:{name:"S\xE3o Tom\xE9 and Pr\xEDncipe",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"S\xE3o Tom\xE9 and Pr\xEDncipe",locales:["pt-ST"],compliance:[],timezones:["Africa/Sao_Tome"]},TZ:{name:"Tanzania",type:"country",complianceGroup:"general-privacy-consent",default:"general-privacy-consent",description:"Tanzania",locales:["sw-TZ","en"],compliance:[],timezones:["Africa/Dar_es_Salaam"]},UG:{name:"Uganda",type:"country",complianceGroup:"general-privacy-consent",default:"general-privacy-consent",description:"Uganda (DPA)",locales:["en"],compliance:["dpa-ug"],timezones:["Africa/Kampala"]},AO:{name:"Angola",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Angola",locales:["pt-AO"],compliance:[],timezones:["Africa/Luanda"]},BW:{name:"Botswana",type:"country",complianceGroup:"general-privacy-consent",default:"general-privacy-consent",description:"Botswana (DPA)",locales:["en"],compliance:["dpa-bw"],timezones:["Africa/Gaborone"]},LS:{name:"Lesotho",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Lesotho",locales:["en"],compliance:[],timezones:["Africa/Maseru"]},NA:{name:"Namibia",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Namibia",locales:["en"],compliance:[],timezones:["Africa/Windhoek"]},SZ:{name:"Eswatini",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Eswatini",locales:["en"],compliance:[],timezones:["Africa/Mbabane"]},ZA:{name:"South Africa",type:"country",complianceGroup:"general-privacy-consent",default:"general-privacy-consent",description:"South Africa (POPIA)",locales:["en","af-ZA"],compliance:["popia"],timezones:["Africa/Johannesburg"]},ZM:{name:"Zambia",type:"country",complianceGroup:"general-privacy-consent",default:"general-privacy-consent",description:"Zambia (DPA)",locales:["en"],compliance:["dpa-zm"],timezones:["Africa/Lusaka"]},ZW:{name:"Zimbabwe",type:"country",complianceGroup:"general-privacy-consent",default:"general-privacy-consent",description:"Zimbabwe (DPA)",locales:["en"],compliance:["dpa-zw"],timezones:["Africa/Harare"]},DZ:{name:"Algeria",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Algeria",locales:["ar-DZ","fr-DZ"],compliance:["dpa-dz"],timezones:["Africa/Algiers"]},EG:{name:"Egypt",type:"country",complianceGroup:"general-privacy-consent",default:"general-privacy-consent",description:"Egypt (DPA)",locales:["ar-EG"],compliance:["dpa-eg"],timezones:["Africa/Cairo"]},LY:{name:"Libya",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Libya",locales:["ar-LY"],compliance:[],timezones:["Africa/Tripoli"]},MA:{name:"Morocco",type:"country",complianceGroup:"general-privacy-consent",default:"general-privacy-consent",description:"Morocco",locales:["ar-MA","fr-MA"],compliance:["dpa-ma"],timezones:["Africa/Casablanca"]},SD:{name:"Sudan",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Sudan",locales:["ar-SD"],compliance:[],timezones:["Africa/Khartoum"]},TN:{name:"Tunisia",type:"country",complianceGroup:"general-privacy-consent",default:"general-privacy-consent",description:"Tunisia (DPA)",locales:["ar-TN","fr-TN"],compliance:["dpa-tn"],timezones:["Africa/Tunis"]},CD:{name:"DR Congo",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"DR Congo",locales:["fr-CD"],compliance:[],timezones:["Africa/Kinshasa","Africa/Lubumbashi"]},CF:{name:"Central African Republic",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Central African Republic",locales:["fr-CF"],compliance:[],timezones:["Africa/Bangui"]},CG:{name:"Republic of Congo",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Republic of Congo",locales:["fr-CG"],compliance:[],timezones:["Africa/Brazzaville"]},TD:{name:"Chad",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Chad",locales:["fr-TD","ar-TD"],compliance:[],timezones:["Africa/Ndjamena"]},BY:{name:"Belarus",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Belarus",locales:["be-BY","ru-BY"],compliance:[],timezones:["Europe/Minsk"]},MD:{name:"Moldova",type:"country",complianceGroup:"general-privacy-consent",default:"general-privacy-consent",description:"Moldova",locales:["ro-MD"],compliance:[],timezones:["Europe/Chisinau"]},RU:{name:"Russia",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Russia",locales:["ru-RU"],compliance:[],timezones:["Europe/Kaliningrad","Europe/Moscow","Europe/Samara","Asia/Yekaterinburg","Asia/Omsk","Asia/Krasnoyarsk","Asia/Irkutsk","Asia/Yakutsk","Asia/Vladivostok","Asia/Magadan","Asia/Kamchatka"]},UA:{name:"Ukraine",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Ukraine",locales:["uk-UA"],compliance:[],timezones:["Europe/Kyiv"]},VA:{name:"Holy See",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Holy See",locales:["it-VA"],compliance:[],timezones:["Europe/Vatican"]},AU:{name:"Australia",type:"country",complianceGroup:"general-privacy-consent",default:"general-privacy-consent",description:"Australia (Privacy Act)",locales:["en"],compliance:["privacy-au"],timezones:["Australia/Sydney","Australia/Brisbane","Australia/Adelaide","Australia/Darwin","Australia/Perth","Australia/Hobart"]},FJ:{name:"Fiji",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Fiji",locales:["en"],compliance:["privacy-fj"],timezones:["Pacific/Fiji"]},FM:{name:"Micronesia",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Micronesia",locales:["en"],compliance:[],timezones:["Pacific/Chuuk","Pacific/Pohnpei","Pacific/Kosrae"]},KI:{name:"Kiribati",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Kiribati",locales:["en"],compliance:[],timezones:["Pacific/Tarawa","Pacific/Enderbury","Pacific/Kiritimati"]},MH:{name:"Marshall Islands",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Marshall Islands",locales:["en"],compliance:[],timezones:["Pacific/Majuro","Pacific/Kwajalein"]},MP:{name:"Northern Mariana Islands",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Northern Mariana Islands",locales:["en"],compliance:[],timezones:["Pacific/Saipan"]},NC:{name:"New Caledonia",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"New Caledonia",locales:["fr-NC"],compliance:[],timezones:["Pacific/Noumea"]},NF:{name:"Norfolk Island",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Norfolk Island",locales:["en"],compliance:[],timezones:["Pacific/Norfolk"]},NR:{name:"Nauru",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Nauru",locales:["en"],compliance:[],timezones:["Pacific/Nauru"]},NU:{name:"Niue",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Niue",locales:["en"],compliance:[],timezones:["Pacific/Niue"]},NZ:{name:"New Zealand",type:"country",complianceGroup:"general-privacy-consent",default:"general-privacy-consent",description:"New Zealand (Privacy Act)",locales:["en"],compliance:["privacy-nz"],timezones:["Pacific/Auckland","Pacific/Chatham"]},PF:{name:"French Polynesia",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"French Polynesia",locales:["fr-PF"],compliance:[],timezones:["Pacific/Tahiti","Pacific/Marquesas","Pacific/Gambier"]},PG:{name:"Papua New Guinea",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Papua New Guinea",locales:["en"],compliance:["privacy-pg"],timezones:["Pacific/Port_Moresby","Pacific/Bougainville"]},PW:{name:"Palau",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Palau",locales:["en"],compliance:[],timezones:["Pacific/Palau"]},SB:{name:"Solomon Islands",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Solomon Islands",locales:["en"],compliance:[],timezones:["Pacific/Guadalcanal"]},TO:{name:"Tonga",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Tonga",locales:["en"],compliance:[],timezones:["Pacific/Tongatapu"]},TV:{name:"Tuvalu",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Tuvalu",locales:["en"],compliance:[],timezones:["Pacific/Funafuti"]},VU:{name:"Vanuatu",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Vanuatu",locales:["fr-VU","en"],compliance:[],timezones:["Pacific/Efate"]},WS:{name:"Samoa",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Samoa",locales:["en"],compliance:[],timezones:["Pacific/Apia"]},UK:{name:"United Kingdom",type:"country",complianceGroup:"opt-in",default:"opt-in",description:"United Kingdom (UK GDPR + PECR)",locales:["en"],compliance:["uk-gdpr","pecr"],timezones:["Europe/London"]},CH:{name:"Switzerland",type:"country",complianceGroup:"opt-in",default:"opt-in",description:"Switzerland (revFADP)",locales:["de-CH","fr-CH","it-CH"],compliance:["revfadp"],timezones:["Europe/Zurich"]}}},Nl=[...Object.values(De.countries).reduce((i,e)=>(e.compliance.forEach(t=>{i.add(t)}),i),new Set)],Ul=Object.entries(De.countries).reduce(function(i,[e,t]){return i[e]=t.name,i},{}),xl=Object.values(De.countries).reduce(function(i,e){return e.locales.forEach(t=>{i[t]=e.name}),i},{})});function Gl(i){let e=i.trim();if(!e)return;let t=si.find(o=>!o.pattern.endsWith("*")&&o.pattern===e);if(t)return t;let n=si.filter(o=>o.pattern.endsWith("*")&&e.startsWith(o.pattern.slice(0,-1)));if(n.length!==0)return n.reduce((o,s)=>s.pattern.length>o.pattern.length?s:o)}var si,Xs=I(()=>{"use strict";p();si=[{pattern:"security_storage",vendor:"Google Consent Mode v2",category:"necessary"},{pattern:"functionality_storage",vendor:"Google Consent Mode v2",category:"functional"},{pattern:"personalization_storage",vendor:"Google Consent Mode v2",category:"preferences"},{pattern:"analytics_storage",vendor:"Google Consent Mode v2",category:"analytics"},{pattern:"ad_storage",vendor:"Google Consent Mode v2",category:"marketing"},{pattern:"ad_user_data",vendor:"Google Consent Mode v2",category:"marketing"},{pattern:"ad_personalization",vendor:"Google Consent Mode v2",category:"marketing"},{pattern:"_ga",vendor:"Google Analytics",category:"analytics"},{pattern:"_ga_*",vendor:"Google Analytics 4",category:"analytics"},{pattern:"_gid",vendor:"Google Analytics",category:"analytics"},{pattern:"_gat",vendor:"Google Analytics",category:"analytics"},{pattern:"_gat_*",vendor:"Google Analytics",category:"analytics"},{pattern:"_gcl_au",vendor:"Google Ads",category:"marketing"},{pattern:"_gac_*",vendor:"Google Ads",category:"marketing"},{pattern:"_gcl_aw",vendor:"Google Ads",category:"marketing"},{pattern:"_fbp",vendor:"Meta Pixel",category:"marketing"},{pattern:"_fbc",vendor:"Meta Pixel",category:"marketing"},{pattern:"fr",vendor:"Meta Pixel",category:"marketing"},{pattern:"_hjSessionUser_*",vendor:"Hotjar",category:"analytics"},{pattern:"_hjSession_*",vendor:"Hotjar",category:"analytics"},{pattern:"_hjid",vendor:"Hotjar",category:"analytics"},{pattern:"hjViewportId",vendor:"Hotjar",category:"analytics"},{pattern:"ajs_user_id",vendor:"Segment",category:"analytics"},{pattern:"ajs_anonymous_id",vendor:"Segment",category:"analytics"},{pattern:"ajs_group_id",vendor:"Segment",category:"analytics"},{pattern:"intercom-id-*",vendor:"Intercom",category:"functional"},{pattern:"intercom-session-*",vendor:"Intercom",category:"functional"},{pattern:"intercom-device-id-*",vendor:"Intercom",category:"functional"},{pattern:"__hstc",vendor:"HubSpot",category:"marketing"},{pattern:"hubspotutk",vendor:"HubSpot",category:"marketing"},{pattern:"__hssc",vendor:"HubSpot",category:"marketing"},{pattern:"__hssrc",vendor:"HubSpot",category:"marketing"},{pattern:"mp_*",vendor:"Mixpanel",category:"analytics"},{pattern:"li_sugr",vendor:"LinkedIn Insight",category:"marketing"},{pattern:"bcookie",vendor:"LinkedIn Insight",category:"marketing"},{pattern:"lidc",vendor:"LinkedIn Insight",category:"marketing"},{pattern:"UserMatchHistory",vendor:"LinkedIn Insight",category:"marketing"},{pattern:"_ttp",vendor:"TikTok Pixel",category:"marketing"},{pattern:"_clck",vendor:"Microsoft Clarity",category:"analytics"},{pattern:"_clsk",vendor:"Microsoft Clarity",category:"analytics"},{pattern:"_pinterest_ct*",vendor:"Pinterest Tag",category:"marketing"},{pattern:"_pin_unauth",vendor:"Pinterest Tag",category:"marketing"},{pattern:"personalization_id",vendor:"X (Twitter) Pixel",category:"marketing"},{pattern:"amplitude_id_*",vendor:"Amplitude",category:"analytics"},{pattern:"__stripe_mid",vendor:"Stripe",category:"necessary"},{pattern:"__stripe_sid",vendor:"Stripe",category:"necessary"},{pattern:"__cf_bm",vendor:"Cloudflare",category:"necessary"},{pattern:"cf_clearance",vendor:"Cloudflare",category:"necessary"},{pattern:"_zendesk_*",vendor:"Zendesk",category:"functional"},{pattern:"drift_aid",vendor:"Drift",category:"functional"},{pattern:"driftt_aid",vendor:"Drift",category:"functional"},{pattern:"crisp-client*",vendor:"Crisp",category:"functional"},{pattern:"AMCV_*",vendor:"Adobe Experience Cloud",category:"analytics"},{pattern:"AMCVS_*",vendor:"Adobe Experience Cloud",category:"analytics"},{pattern:"s_cc",vendor:"Adobe Analytics",category:"analytics"},{pattern:"s_sq",vendor:"Adobe Analytics",category:"analytics"},{pattern:"s_vi",vendor:"Adobe Analytics",category:"analytics"},{pattern:"mbox",vendor:"Adobe Target",category:"preferences"},{pattern:"_mkto_trk",vendor:"Marketo",category:"marketing"},{pattern:"cto_bundle",vendor:"Criteo",category:"marketing"},{pattern:"cto_id_out",vendor:"Criteo",category:"marketing"},{pattern:"TTD_DEVICE_ID",vendor:"The Trade Desk",category:"marketing"},{pattern:"ttd_*",vendor:"The Trade Desk",category:"marketing"},{pattern:"id",vendor:"Google DoubleClick",category:"marketing"},{pattern:"IDE",vendor:"Google DoubleClick",category:"marketing"},{pattern:"DSID",vendor:"Google DoubleClick",category:"marketing"},{pattern:"KADUSERCOOKIE",vendor:"PubMatic",category:"marketing"},{pattern:"rubicon_user_*",vendor:"Rubicon Project",category:"marketing"},{pattern:"Anonymon_id",vendor:"OpenX",category:"marketing"},{pattern:"pdomid",vendor:"OpenX",category:"marketing"},{pattern:"uuid2",vendor:"AppNexus",category:"marketing"},{pattern:"icu",vendor:"AppNexus",category:"marketing"},{pattern:"_scid",vendor:"Snap Pixel",category:"marketing"},{pattern:"_sc_cspv",vendor:"Snap Pixel",category:"marketing"},{pattern:"_rdt_uuid",vendor:"Reddit Pixel",category:"marketing"},{pattern:"obuid",vendor:"Outbrain",category:"marketing"},{pattern:"t_gid",vendor:"Taboola",category:"marketing"},{pattern:"__kla_id",vendor:"Klaviyo",category:"marketing"},{pattern:"sc_anonymous_id",vendor:"Salesforce Marketing Cloud",category:"marketing"},{pattern:"vst",vendor:"Salesforce Marketing Cloud",category:"marketing"},{pattern:"visitor_id*",vendor:"Salesforce Pardot",category:"marketing"},{pattern:"piAId",vendor:"Salesforce Pardot",category:"marketing"},{pattern:"exp_last_visit",vendor:"ActiveCampaign",category:"marketing"},{pattern:"exp_tracker",vendor:"ActiveCampaign",category:"marketing"},{pattern:"_ce.s*",vendor:"Crazy Egg",category:"analytics"},{pattern:"lr_*",vendor:"LogRocket",category:"analytics"},{pattern:"_hp2_id.*",vendor:"Heap Analytics",category:"analytics"},{pattern:"_hp2_ses.*",vendor:"Heap Analytics",category:"analytics"},{pattern:"_lo_*",vendor:"Lucky Orange",category:"analytics"},{pattern:"fs_uid",vendor:"FullStory",category:"analytics"},{pattern:"_fs_*",vendor:"FullStory",category:"analytics"},{pattern:"ln_or",vendor:"LiveSession",category:"analytics"},{pattern:"_vwo_uuid*",vendor:"Visual Website Optimizer (VWO)",category:"analytics"},{pattern:"_vis_opt_*",vendor:"Visual Website Optimizer (VWO)",category:"analytics"},{pattern:"OptimizelyBuckets",vendor:"Optimizely",category:"analytics"},{pattern:"optimizelyEndUserId",vendor:"Optimizely",category:"analytics"},{pattern:"OptanonConsent",vendor:"OneTrust",category:"necessary"},{pattern:"OptanonAlertBoxClosed",vendor:"OneTrust",category:"necessary"},{pattern:"SyrenisCookieConsentDate_*",vendor:"Syrenis Cassie",category:"necessary"},{pattern:"SyrenisCookieFormConsent_*",vendor:"Syrenis Cassie",category:"necessary"},{pattern:"SyrenisCookiePrivacyLink_*",vendor:"Syrenis Cassie",category:"necessary"},{pattern:"SyrenisGtmConsent_*",vendor:"Syrenis Cassie",category:"necessary"},{pattern:"SyrenisGuid_*",vendor:"Syrenis Cassie",category:"necessary"},{pattern:"CookieConsent",vendor:"Cookiebot",category:"necessary"},{pattern:"uc_settings",vendor:"Usercentrics",category:"necessary"},{pattern:"uc_user_interaction",vendor:"Usercentrics",category:"necessary"},{pattern:"didomi_token",vendor:"Didomi",category:"necessary"},{pattern:"euconsent-v2",vendor:"IAB TCF Global Vendor List",category:"necessary"},{pattern:"cconsent",vendor:"Cookie Consent Studio",category:"necessary"},{pattern:"JSESSIONID",vendor:"New Relic",category:"necessary"},{pattern:"NRAGENT",vendor:"New Relic",category:"necessary"},{pattern:"_dd_s",vendor:"Datadog",category:"necessary"},{pattern:"dtCookie",vendor:"Dynatrace",category:"necessary"},{pattern:"dtPC",vendor:"Dynatrace",category:"necessary"},{pattern:"rxVisitor",vendor:"Dynatrace",category:"necessary"},{pattern:"ak_bmsc",vendor:"Akamai",category:"necessary"},{pattern:"_abck",vendor:"Akamai",category:"necessary"},{pattern:"vuid",vendor:"Vimeo",category:"analytics"},{pattern:"__cf_vuid",vendor:"Vimeo",category:"analytics"},{pattern:"VISITOR_INFO1_LIVE",vendor:"YouTube",category:"marketing"},{pattern:"YSC",vendor:"YouTube",category:"necessary"},{pattern:"GPS",vendor:"YouTube",category:"marketing"},{pattern:"_wistia_*",vendor:"Wistia",category:"analytics"},{pattern:"_elvr_*",vendor:"Elevar",category:"analytics"},{pattern:"stkn",vendor:"Shopify Core Analytics",category:"analytics"},{pattern:"rmStore*",vendor:"Rakuten Advertising",category:"marketing"},{pattern:"_ir_*",vendor:"Impact Radius",category:"marketing"},{pattern:"aw*",vendor:"Awin",category:"marketing"},{pattern:"bctc",vendor:"Awin",category:"marketing"},{pattern:"mcookie",vendor:"CJ Affiliate",category:"marketing"},{pattern:"_shopify_y",vendor:"Shopify",category:"analytics"},{pattern:"_shopify_s",vendor:"Shopify",category:"analytics"},{pattern:"_shopify_sa_p",vendor:"Shopify",category:"marketing"},{pattern:"shopify_sa_t",vendor:"Shopify",category:"marketing"},{pattern:"cart_sig",vendor:"Shopify",category:"necessary"},{pattern:"secure_customer_sig",vendor:"Shopify",category:"necessary"},{pattern:"wp_woocommerce_session*",vendor:"WooCommerce",category:"necessary"},{pattern:"woocommerce_items_in_cart",vendor:"WooCommerce",category:"necessary"},{pattern:"woocommerce_cart_hash",vendor:"WooCommerce",category:"necessary"},{pattern:"QSI_",vendor:"Qualtrics",category:"functional"},{pattern:"feedback_id",vendor:"SurveyMonkey",category:"functional"},{pattern:"usbl.",vendor:"Usabilla",category:"functional"}]});function er(i){return i.map(ri).join("")}function ri(i){return i.t==="text"?jl(i.v):i.t==="br"?"<br>":i.t==="a"?`<a href="${Bl(i.href)}">${i.c.map(ri).join("")}</a>`:`<${i.t}>${i.c.map(ri).join("")}</${i.t}>`}function jl(i){return i.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;")}function Bl(i){return i.replace(/"/g,"&quot;").replace(/</g,"&lt;")}function Fl(i){if(!i)return"";let e=i.trim();if(e.startsWith("["))try{return er(JSON.parse(e))}catch{}return i}function tr(i){return i.t==="text"?i.v.trim().length>0:i.t==="br"?!1:i.c.some(tr)}function $l(i){return i.replace(/<[^>]*>/g,"").trim().length>0}function on(i){if(!i)return!1;let e=i.trim();if(!e)return!1;if(e.startsWith("["))try{return JSON.parse(e).some(tr)}catch{}return $l(e)}var nr=I(()=>{"use strict";p()});function Hl(i){return new TextEncoder().encode(i)}function Vl(i){return new TextDecoder().decode(i)}function Wl(i){let e="";for(let t=0;t<i.length;t+=3){let n=i[t]??0,o=t+1<i.length?i[t+1]??0:0,s=t+2<i.length?i[t+2]??0:0;e+=st[n>>2],e+=st[(n&3)<<4|o>>4],t+1<i.length&&(e+=st[(o&15)<<2|s>>6]),t+2<i.length&&(e+=st[s&63])}return e}function ql(i){let e=new Map(st.split("").map((o,s)=>[o,s])),t=i.replace(/[^A-Za-z0-9\-_]/g,""),n=[];for(let o=0;o<t.length;o+=4){let s=e.get(t[o]??"")??0,r=e.get(t[o+1]??"")??0,a=t[o+2]!==void 0?e.get(t[o+2]):void 0,c=t[o+3]!==void 0?e.get(t[o+3]):void 0;n.push(s<<2|r>>4),a!==void 0&&n.push((r&15)<<4|a>>2),c!==void 0&&n.push(((a??0)&3)<<6|c)}return new Uint8Array(n)}function ai(i){let e={v:2,ts:Math.floor(Date.now()/100),cmpId:i.cmpId,cmpV:i.cmpVersion,cs:i.consentScreen,lang:i.consentLanguage.toUpperCase().slice(0,2),vlV:i.vendorListVersion,pc:i.purposeConsents,vc:i.vendorConsents};return Wl(Hl(JSON.stringify(e)))}function Jl(i){try{let e=JSON.parse(Vl(ql(i)));return{version:e.v,cmpId:e.cmpId,consentLanguage:e.lang,purposeConsents:Array.isArray(e.pc)?e.pc:[],vendorConsents:Array.isArray(e.vc)?e.vc:[],created:e.ts*100}}catch{return null}}var st,ir=I(()=>{"use strict";p();st="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"});function zl(i){return new TextEncoder().encode(i)}function Kl(i){return new TextDecoder().decode(i)}function Yl(i){let e="";for(let t=0;t<i.length;t+=3){let n=i[t]??0,o=t+1<i.length?i[t+1]??0:0,s=t+2<i.length?i[t+2]??0:0;e+=rt[n>>2],e+=rt[(n&3)<<4|o>>4],t+1<i.length&&(e+=rt[(o&15)<<2|s>>6]),t+2<i.length&&(e+=rt[s&63])}return e}function Ql(i){let e=new Map(rt.split("").map((o,s)=>[o,s])),t=i.replace(/[^A-Za-z0-9\-_]/g,""),n=[];for(let o=0;o<t.length;o+=4){let s=e.get(t[o]??"")??0,r=e.get(t[o+1]??"")??0,a=t[o+2]!==void 0?e.get(t[o+2]):void 0,c=t[o+3]!==void 0?e.get(t[o+3]):void 0;n.push(s<<2|r>>4),a!==void 0&&n.push((r&15)<<4|a>>2),c!==void 0&&n.push(((a??0)&3)<<6|c)}return new Uint8Array(n)}function ci(i,e){return i?e?Xl:ed:Zl}function li(i){let e={v:1,ts:Math.floor(Date.now()/100),cmpId:i.cmpId,cmpV:i.cmpVersion,sect:"usnat",saleOO:ci(i.saleApplicable,i.saleOptOut),shareOO:ci(i.sharingApplicable,i.sharingOptOut),taOO:ci(i.sharingApplicable,i.sharingOptOut),mspaCT:i.mspaCoveredTransaction?1:2,mspaOOM:i.mspaOptOutOptionMode,mspaSPM:i.mspaServiceProviderMode,...i.gpcDetected!==void 0?{gpc:i.gpcDetected}:{}};return Yl(zl(JSON.stringify(e)))}function td(i){try{let e=JSON.parse(Kl(Ql(i)));return{version:e.v,cmpId:e.cmpId,cmpVersion:e.cmpV,saleOptOut:e.saleOO,sharingOptOut:e.shareOO,targetedAdvertisingOptOut:e.taOO,...e.gpc!==void 0?{gpc:e.gpc}:{},created:e.ts*100}}catch{return null}}var rt,Zl,Xl,ed,or=I(()=>{"use strict";p();rt="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";Zl=0,Xl=1,ed=2});function id(i,e){if(e==="ltr"||e==="rtl")return e;try{let n=new Intl.Locale(i).getTextInfo?.().direction;if(n==="ltr"||n==="rtl")return n}catch{}let t=i.slice(0,2).toLowerCase();return nd.includes(t)?"rtl":"ltr"}var nd,sr=I(()=>{"use strict";p();nd=["ar","he","fa","ur","ps","sd","ug","yi"]});var rr={};Pn(rr,{COMPLIANCE_GROUPS:()=>ot,COMPLIANCE_GROUP_IDS:()=>tn,COMPLIANCE_REGULATION_IDS:()=>Nl,COMPLIANCE_VALIDATION_RULES:()=>ii,COOKIE_PURPOSES:()=>Pl,COOKIE_PURPOSE_DEFAULTS:()=>bl,COOKIE_PURPOSE_IDS:()=>nn,COUNTRY_CODES:()=>Ul,CPRA_CATEGORIES:()=>Il,DEFAULT_PROFILES:()=>en,EMBEDDED_COMPLIANCE_MAP:()=>De,GPC_OPTIONS:()=>Al,KNOWN_COOKIE_PURPOSES:()=>Qs,LEGAL_BASIS_OPTIONS:()=>Tl,LOCALES:()=>xl,TCF_PURPOSES:()=>Dl,TCF_SPECIAL_FEATURES:()=>kl,TRACKER_KNOWLEDGE_BASE:()=>si,buildCookieCategoryIndex:()=>Be,color:()=>Z,debounce:()=>_l,decodeGppString:()=>td,decodeTcString:()=>Jl,encodeGppString:()=>li,encodeTcString:()=>ai,findCategoryForCookie:()=>Ll,formatLog:()=>vl,getCookieLegalBasis:()=>Fe,hasVisibleText:()=>on,inferCookiePurpose:()=>Ol,isMandatoryCookie:()=>ni,jsonToHtml:()=>er,matchTrackerKnowledge:()=>Gl,renderContentText:()=>Fl,resolveComplianceMapOverride:()=>oi,resolveTextDirection:()=>id,statusLabel:()=>Sl,throttle:()=>wl});var ae=I(()=>{"use strict";p();zs();Ks();Ys();Zs();Xs();nr();ir();or();sr();ti()});var Qd={};Pn(Qd,{CategoryAction:()=>Cn,ConsentAction:()=>Sn,MongoDBAdapter:()=>Me,MySQLAdapter:()=>Ge,PostgreSQLAdapter:()=>je,SQLiteAdapter:()=>Ie,createConsenti:()=>Yd,dashboardDir:()=>Hd});module.exports=cc(Qd);p();var qa=require("node:events"),Ja=require("node:crypto"),We=require("node:fs/promises"),V=require("node:path"),vi=require("node:url");p();var Et=class{plugins=[];register(e){this.plugins=e}async initialize(e){for(let t of this.plugins)try{await t.initialize?.(e)}catch(n){console.warn(`[Consenti] Plugin "${t.name}" initialize failed:`,n)}}async destroy(){for(let e of this.plugins)try{await e.destroy?.()}catch(t){console.warn(`[Consenti] Plugin "${e.name}" destroy failed:`,t)}}async runBeforeConsentSave(e){let t=e;for(let n of this.plugins)if(n.beforeConsentSave)try{t=await n.beforeConsentSave(t)}catch(o){console.warn(`[Consenti] Plugin "${n.name}" beforeConsentSave failed:`,o)}return t}async runAfterConsentSave(e){for(let t of this.plugins)if(t.afterConsentSave)try{await t.afterConsentSave(e)}catch(n){console.warn(`[Consenti] Plugin "${t.name}" afterConsentSave failed:`,n)}}async runBeforeConsentUpdate(e){let t=e;for(let n of this.plugins)if(n.beforeConsentUpdate)try{t=await n.beforeConsentUpdate(t)}catch(o){console.warn(`[Consenti] Plugin "${n.name}" beforeConsentUpdate failed:`,o)}return t}async runAfterConsentUpdate(e){for(let t of this.plugins)if(t.afterConsentUpdate)try{await t.afterConsentUpdate(e)}catch(n){console.warn(`[Consenti] Plugin "${t.name}" afterConsentUpdate failed:`,n)}}async runAfterProfileFetch(e){let t=e;for(let n of this.plugins)if(n.afterProfileFetch)try{t=await n.afterProfileFetch(t)}catch(o){console.warn(`[Consenti] Plugin "${n.name}" afterProfileFetch failed:`,o)}return t}async runBeforeUserCreate(e){let t=e;for(let n of this.plugins)if(n.beforeUserCreate)try{t=await n.beforeUserCreate(t)}catch(o){console.warn(`[Consenti] Plugin "${n.name}" beforeUserCreate failed:`,o)}return t}async runAfterUserCreate(e){for(let t of this.plugins)if(t.afterUserCreate)try{await t.afterUserCreate(e)}catch(n){console.warn(`[Consenti] Plugin "${t.name}" afterUserCreate failed:`,n)}}};p();var bn=require("node:fs"),xi=require("node:path");function Mi(i,e,t={},n={},o="local"){let s={};return n.type!==void 0&&(s.type=n.type),n.gpc!==void 0&&(s.gpc=n.gpc),{appName:t.appName??"Consenti",appLogoPath:t?.appLogoPath??"/logo-dark.svg",hidePoweredBy:t.hidePoweredBy??!1,basePath:e,compliance:s,authMode:o}}function Gi(i){return`<script>(function(){function d(o){if(o&&typeof o==='object')Object.keys(o).forEach(function(k){d(o[k])});return Object.freeze(o)}Object.defineProperty(window,'__CONSENTI_CONFIG__',{value:d(${JSON.stringify(i).replace(/<\/script>/gi,"<\\/script>")}),writable:false,configurable:false,enumerable:true})})()</script>`}function Je(i,e){let t=Buffer.from(i).toString("utf-8");return t.includes("</head>")?t.replace("</head>",`${e}</head>`):t.replace("</body>",`${e}</body>`)}p();var dc="https://vendor-list.consensu.org/v3/vendor-list.json";var ve=null,ji=0,ze=null;function uc(i){return typeof i=="object"&&i!==null&&"vendors"in i&&"purposes"in i&&typeof i.vendors=="object"&&typeof i.purposes=="object"}async function Ae(){if(ve&&Date.now()-ji<6048e5)return ve;try{let i=await fetch(dc,{signal:AbortSignal.timeout(15e3)});if(!i.ok)return ve;let e=await i.json();if(!uc(e))return ve;let t=e;return ve={gvlSpecificationVersion:t.gvlSpecificationVersion,vendorListVersion:t.vendorListVersion,tcfPolicyVersion:t.tcfPolicyVersion,vendors:t.vendors,purposes:t.purposes,raw:t},ji=Date.now(),ve}catch{return ve}}function Bi(){ze||(Ae(),ze=setInterval(()=>{Ae()},6048e5))}function Fi(){ze&&(clearInterval(ze),ze=null)}p();var pc="https://vendor-list.consensu.org/v3/cmp-list.json";var Te=null,$i=0,Ke=null;function mc(i){return typeof i=="object"&&i!==null&&"cmps"in i&&typeof i.cmps=="object"}async function Ye(i=!1){if(!i&&Te&&Date.now()-$i<6048e5)return Te;try{let e=await fetch(pc,{signal:AbortSignal.timeout(15e3)});if(!e.ok)return Te;let t=await e.json();if(!mc(t))return Te;let n=t;return Te={cmpListVersion:n.cmpListVersion,lastUpdated:n.lastUpdated,cmps:n.cmps},$i=Date.now(),Te}catch{return Te}}function Hi(){Ke||(Ye(),Ke=setInterval(()=>{Ye()},6048e5))}function Vi(){Ke&&(clearInterval(Ke),Ke=null)}p();var Wi={ConsentRecord:{type:"object",properties:{id:{type:"string"},visitorId:{type:"string"},profileId:{type:"string"},locale:{type:"string"},consentJson:{type:"object",additionalProperties:{type:"string",enum:["granted","denied","objected"]}},gpcDetected:{type:"boolean"},source:{type:"string",enum:["banner","api","import"]},ageVerified:{type:"boolean"},tcfString:{type:"string"},createdAt:{type:"string",format:"date-time"},updatedAt:{type:"string",format:"date-time"}}},CreateConsentInput:{type:"object",required:["visitorId","profileId","consentJson"],properties:{visitorId:{type:"string"},profileId:{type:"string"},consentJson:{type:"object",additionalProperties:{type:"string"}},gpcDetected:{type:"boolean",default:!1},source:{type:"string",enum:["banner","api","import"],default:"banner"},ageVerified:{type:"boolean"},parentalConsentToken:{type:"string"},tcfString:{type:"string"}}}},On={openapi:"3.1.0",info:{title:"Consenti Public API",version:"0.1.0",description:"Visitor-facing endpoints for reading consent profiles and submitting/verifying consent. Rate-limited; no authentication required.",license:{name:"Apache 2.0",url:"https://www.apache.org/licenses/LICENSE-2.0"}},servers:[{url:"/consenti/api",description:"Consenti Public API"}],paths:{"/v1/profiles/{id}":{get:{tags:["Profile"],summary:"Get profile in its default locale",description:"Returns the resolved profile with banner and modal content for the profile's default locale. Includes `currentLocale`, `locales`, `cookies`, `mainBanner`, `preferenceModal`, and optionally `gpcBanner`.",parameters:[{name:"id",in:"path",required:!0,schema:{type:"string"}}],responses:{200:{description:"Resolved profile for the default locale"},404:{description:"Profile not found"}}}},"/v1/profiles/{id}/{locale}":{get:{tags:["Profile"],summary:"Get profile resolved for a specific locale",description:"Same response shape as `GET /v1/profiles/{id}` but resolved for the requested locale, falling back to the default locale for any missing translations.",parameters:[{name:"id",in:"path",required:!0,schema:{type:"string"}},{name:"locale",in:"path",required:!0,schema:{type:"string",example:"fr"}}],responses:{200:{description:"Resolved profile for the requested locale"},404:{description:"Profile not found"}}}},"/v1/consent":{post:{tags:["Consent"],summary:"Submit consent",requestBody:{required:!0,content:{"application/json":{schema:{$ref:"#/components/schemas/CreateConsentInput"}}}},responses:{200:{description:"Consent created or updated",content:{"application/json":{schema:{$ref:"#/components/schemas/ConsentRecord"}}}},400:{description:"Validation error"}}}},"/v1/consent/{visitorId}":{get:{tags:["Consent"],summary:"Get consent for visitor",parameters:[{name:"visitorId",in:"path",required:!0,schema:{type:"string"}}],responses:{200:{description:"Consent record",content:{"application/json":{schema:{$ref:"#/components/schemas/ConsentRecord"}}}},404:{description:"Not found"}}},put:{tags:["Consent"],summary:"Update consent",parameters:[{name:"visitorId",in:"path",required:!0,schema:{type:"string"}}],responses:{200:{description:"Updated consent"}}},delete:{tags:["Consent"],summary:"GDPR erasure \u2014 delete all consent data for visitor",parameters:[{name:"visitorId",in:"path",required:!0,schema:{type:"string"}}],responses:{200:{description:"Erased successfully"}}}},"/v1/consent/{visitorId}/verify":{get:{tags:["Consent"],summary:"Verify consent validity",parameters:[{name:"visitorId",in:"path",required:!0,schema:{type:"string"}}],responses:{200:{description:"Verification result"}}}},"/v1/consent/{visitorId}/parental-consent-request":{post:{tags:["Consent"],summary:"Request a parental-consent token (stateless hook)",description:"Issues a token \u2014 signed with `compliance.dataSigningHash` when configured, otherwise unsigned \u2014 for a host's own out-of-band parental-verification flow. Emits `consent.parentalConsentRequired`. Not by itself sufficient verifiable parental consent (COPPA-style VPC is left to the host).",parameters:[{name:"visitorId",in:"path",required:!0,schema:{type:"string"}}],requestBody:{required:!0,content:{"application/json":{schema:{type:"object",required:["profileId"],properties:{profileId:{type:"string"}}}}}},responses:{200:{description:"Token issued",content:{"application/json":{schema:{type:"object",properties:{token:{type:"string"}}}}}},400:{description:"Validation error"},403:{description:"Visitor ownership check failed"},404:{description:"Profile not found"}}}},"/v1/consent/parental-consent-resolve":{post:{tags:["Consent"],summary:"Resolve a parental-consent token",description:"Recovers `visitorId`/`profileId` from a token issued by the request route above and emits `consent.parentalConsentGranted` \u2014 the host's own backend listener decides what \"granted\" means for stored consent. No visitor-ownership cookie required, since this is typically called from the parent's own device. Token replay is not prevented (stateless by design).",requestBody:{required:!0,content:{"application/json":{schema:{type:"object",required:["token"],properties:{token:{type:"string"}}}}}},responses:{200:{description:"Token resolved",content:{"application/json":{schema:{type:"object",properties:{visitorId:{type:"string"},profileId:{type:"string"}}}}}},400:{description:"Validation error"},403:{description:"Invalid, tampered, or expired token"}}}},"/v1/notice-shown":{post:{tags:["Consent"],summary:"Record proof that the consent banner was shown",description:"Lightweight, fire-and-forget ping recording that the banner was rendered to a visitor, independent of whether they ever interact with it. Called automatically by `@consenti/ui` on banner mount when `api.enabled` is configured.",requestBody:{required:!0,content:{"application/json":{schema:{type:"object",required:["visitorId","profileId","locale"],properties:{visitorId:{type:"string"},profileId:{type:"string"},locale:{type:"string"}}}}}},responses:{201:{description:"Recorded"},400:{description:"Validation error"}}}}},components:{schemas:Wi}},Dn={openapi:"3.1.0",info:{title:"Consenti Admin API",version:"0.1.0",description:"Authenticated endpoints for managing profiles, consent records, users, analytics, and exports. All routes (except `/auth/login`) require `Authorization: Bearer <JWT>`. Obtain a token via `POST /auth/login`.",license:{name:"Apache 2.0",url:"https://www.apache.org/licenses/LICENSE-2.0"}},servers:[{url:"/consenti/admin/v1",description:"Consenti Admin API"}],paths:{"/auth/login":{post:{tags:["Auth"],summary:"Login with email + password",requestBody:{required:!0,content:{"application/json":{schema:{type:"object",properties:{email:{type:"string"},password:{type:"string"}}}}}},responses:{200:{description:"JWT token"}}}},"/auth/me":{get:{tags:["Auth"],summary:"Get current user",security:[{BearerAuth:[]}],responses:{200:{description:"Current admin user info"}}}},"/auth/logout":{post:{tags:["Auth"],summary:"Invalidate session",security:[{BearerAuth:[]}],responses:{200:{description:"Logged out"}}}},"/auth/refresh":{post:{tags:["Auth"],summary:"Reissue a fresh token from the current one, extending the session",description:"Used by the dashboard on user activity to implement a sliding inactivity timeout instead of a flat expiry from login.",security:[{BearerAuth:[]}],responses:{200:{description:"New JWT token"},401:{description:"Current token is missing, invalid, or already expired"}}}},"/auth/oidc/authorize":{get:{tags:["Auth"],summary:"Start OIDC authorization (PKCE)",responses:{302:{description:"Redirect to OIDC provider"}}}},"/auth/oidc/callback":{get:{tags:["Auth"],summary:"OIDC callback \u2014 exchange code for token",responses:{200:{description:"JWT token"}}}},"/auth/saml/metadata":{get:{tags:["Auth"],summary:"SAML SP metadata XML",responses:{200:{description:"SAML metadata XML",content:{"application/xml":{}}}}}},"/auth/saml/acs":{post:{tags:["Auth"],summary:"SAML Assertion Consumer Service",responses:{200:{description:"JWT token"}}}},"/auth/totp/setup":{post:{tags:["Auth"],summary:"Setup TOTP MFA",security:[{BearerAuth:[]}],responses:{200:{description:"TOTP secret and QR URL"}}}},"/auth/totp/verify":{post:{tags:["Auth"],summary:"Verify and enable TOTP",security:[{BearerAuth:[]}],responses:{200:{description:"TOTP enabled"}}}},"/profiles":{get:{tags:["Profiles"],summary:"List profiles",security:[{BearerAuth:[]}],responses:{200:{description:"Array of profiles"}}},post:{tags:["Profiles"],summary:"Create profile",security:[{BearerAuth:[]}],responses:{201:{description:"Created profile"}}}},"/consent-templates":{get:{tags:["Consent Templates"],summary:"List consent templates",description:"A Consent Template groups parameters (`cookies`, keyed by id) with the categories that own their legal basis (`categories`, keyed by id).",security:[{BearerAuth:[]}],responses:{200:{description:"Array of consent templates"}}},post:{tags:["Consent Templates"],summary:"Create consent template",security:[{BearerAuth:[]}],requestBody:{required:!0,content:{"application/json":{schema:{type:"object",required:["name","cookies","categories"],properties:{name:{type:"string"},cookies:{type:"object",description:"Keyed by parameter id."},categories:{type:"object",description:"Keyed by category id. Every parameter id must appear in exactly one category."}}}}}},responses:{201:{description:"Created consent template"},400:{description:"Validation error"}}}},"/consent-templates/{id}":{get:{tags:["Consent Templates"],summary:"Get consent template",security:[{BearerAuth:[]}],parameters:[{name:"id",in:"path",required:!0,schema:{type:"string"}}],responses:{200:{description:"Consent template"},404:{description:"Not found"}}},put:{tags:["Consent Templates"],summary:"Update consent template",security:[{BearerAuth:[]}],parameters:[{name:"id",in:"path",required:!0,schema:{type:"string"}}],responses:{200:{description:"Updated consent template"},422:{description:"Change would break compliance for profiles using this template"}}},delete:{tags:["Consent Templates"],summary:"Delete consent template",security:[{BearerAuth:[]}],parameters:[{name:"id",in:"path",required:!0,schema:{type:"string"}}],responses:{200:{description:"Deleted"},422:{description:"Template is still used by profiles"}}}},"/consent-templates/{id}/copy":{post:{tags:["Consent Templates"],summary:"Duplicate a consent template",security:[{BearerAuth:[]}],parameters:[{name:"id",in:"path",required:!0,schema:{type:"string"}}],responses:{201:{description:"Copied consent template"}}}},"/consent-templates/{id}/profile-usage":{get:{tags:["Consent Templates"],summary:"List profiles using this consent template",security:[{BearerAuth:[]}],parameters:[{name:"id",in:"path",required:!0,schema:{type:"string"}}],responses:{200:{description:"Array of profile summaries"}}}},"/consents":{get:{tags:["Consents"],summary:"List consent records",security:[{BearerAuth:[]}],parameters:[{name:"page",in:"query",schema:{type:"integer"}},{name:"profileId",in:"query",schema:{type:"string"}},{name:"from",in:"query",schema:{type:"string",format:"date"}},{name:"to",in:"query",schema:{type:"string",format:"date"}},{name:"q",in:"query",schema:{type:"string"},description:"Free-text search across visitorId, profileId, locale, source"}],responses:{200:{description:"Paginated consent records"}}}},"/stats/overview":{get:{tags:["Stats"],summary:"Overview statistics",security:[{BearerAuth:[]}],responses:{200:{description:"Totals and acceptance rates"}}}},"/stats/timeline":{get:{tags:["Stats"],summary:"Daily consent timeline",security:[{BearerAuth:[]}],parameters:[{name:"days",in:"query",schema:{type:"integer",default:30}}],responses:{200:{description:"Array of date+count"}}}},"/stats/countries":{get:{tags:["Stats"],summary:"Consent by country",security:[{BearerAuth:[]}],responses:{200:{description:"Country counts"}}}},"/stats/gpc":{get:{tags:["Stats"],summary:"GPC detection stats",security:[{BearerAuth:[]}],responses:{200:{description:"GPC rate and counts"}}}},"/export/consents":{get:{tags:["Export"],summary:"Export consent records",security:[{BearerAuth:[]}],parameters:[{name:"format",in:"query",schema:{type:"string",enum:["csv","json"]}},{name:"from",in:"query",schema:{type:"string",format:"date"}},{name:"to",in:"query",schema:{type:"string",format:"date"}}],responses:{200:{description:"CSV or JSON download"}}}},"/tenants":{get:{tags:["Sites"],summary:"List all sites/tenants",security:[{BearerAuth:[]}],responses:{200:{description:"Array of tenants"}}},post:{tags:["Sites"],summary:"Create a site/tenant",security:[{BearerAuth:[]}],requestBody:{required:!0,content:{"application/json":{schema:{type:"object",properties:{name:{type:"string"},slug:{type:"string"}},required:["name","slug"]}}}},responses:{201:{description:"Created tenant"}}}},"/tenants/{id}":{put:{tags:["Sites"],summary:"Update a site/tenant",security:[{BearerAuth:[]}],parameters:[{name:"id",in:"path",required:!0,schema:{type:"string"}}],responses:{200:{description:"Updated tenant"}}},delete:{tags:["Sites"],summary:"Delete a site/tenant",security:[{BearerAuth:[]}],parameters:[{name:"id",in:"path",required:!0,schema:{type:"string"}}],responses:{200:{description:"Deleted"}}}},"/setup/status":{get:{tags:["Setup"],summary:"Whether the first-run setup wizard has been completed for this tenant",security:[{BearerAuth:[]}],responses:{200:{description:"{ completed: boolean }"}}}},"/setup/config":{get:{tags:["Setup"],summary:"Resolved server config (secrets redacted) plus production-readiness flags",description:"The same merged `DEFAULT_CONFIG` + user config `createConsenti` computes at boot. `auth.adminPassword`, `auth.masterSecret`, `compliance.dataSigningHash`, `compliance.dataSigningHash`, storage credentials, and OIDC/SAML secrets are replaced with a redaction marker.",security:[{BearerAuth:[]}],responses:{200:{description:"{ config: object, usingJsonStorage: boolean, usingDefaultCredentials: boolean }"}}}},"/setup/compliance-groups":{get:{tags:["Setup"],summary:"The 8 built-in compliance groups with label/description/regulation metadata",security:[{BearerAuth:[]}],responses:{200:{description:"Array of compliance group descriptors"}}}},"/setup/seed-profiles":{post:{tags:["Setup"],summary:"Seed default profiles for the selected compliance groups",description:"Idempotent \u2014 skips any group that already has an active profile. `groups` must be a subset of the 8 built-in compliance group ids.",security:[{BearerAuth:[]}],requestBody:{required:!0,content:{"application/json":{schema:{type:"object",properties:{groups:{type:"array",items:{type:"string"}}},required:["groups"]}}}},responses:{200:{description:"{ seeded: string[] }"},400:{description:"groups is missing, not an array of strings, or contains an unknown compliance group id"},409:{description:"Setup has already been completed for this tenant"}}}},"/setup/complete":{post:{tags:["Setup"],summary:"Mark the first-run setup wizard as complete for this tenant",description:"Called on both wizard finish and skip. Never reset from the dashboard once true.",security:[{BearerAuth:[]}],responses:{200:{description:"Updated tenant settings"},409:{description:"Setup has already been completed for this tenant"}}}}},components:{securitySchemes:{BearerAuth:{type:"http",scheme:"bearer",bearerFormat:"JWT"}},schemas:Wi}};p();p();var v=require("node:crypto");var qi="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",gc=16;function fc(i){let e=(0,v.randomBytes)(i),t="";for(let n=0;n<i;n++)t+=qi[e[n]%qi.length];return t}function Qe(i){return`${i}_${fc(gc)}`}function z(){return Qe("prof")}function q(){return Qe("visi")}function K(){return Qe("cons")}function Y(){return Qe("ctem")}function Q(){return Qe("utem")}function hc(i){if(i.includes(":")){let t=i.split(":");for(;t.length<8;)t.push("0");return t.slice(0,3).concat(["0","0","0","0","0"]).join(":")}let e=i.split(".");return e.length===4?(e[3]="0",e.join(".")):i}function Ji(i,e=""){return(0,v.createHash)("sha256").update(e+hc(i)).digest("hex")}function zi(i){return(0,v.createHash)("sha256").update(i).digest("hex")}function le(i,e){return(0,v.createHmac)("sha256",e).update(i).digest("hex")}function Rt(i,e,t){let n=Buffer.from(le(i,t),"hex"),o=Buffer.from(e,"hex");return n.length!==o.length?!1:(0,v.timingSafeEqual)(n,o)}function Ze(i){let e=(0,v.randomBytes)(16).toString("hex"),t=(0,v.scryptSync)(i,e,64).toString("hex");return`${e}:${t}`}function Ki(i,e){let[t,n]=e.split(":");if(!t||!n)return!1;let o=(0,v.scryptSync)(i,t,64).toString("hex");return(0,v.timingSafeEqual)(Buffer.from(n,"hex"),Buffer.from(o,"hex"))}function kn(i,e,t=3600){let n=Math.floor(Date.now()/1e3),o=btoa(JSON.stringify({alg:"HS256",typ:"JWT"})).replace(/=/g,""),s=btoa(JSON.stringify({...i,iat:n,exp:n+t})).replace(/=/g,""),r=le(`${o}.${s}`,e).match(/.{2}/g).map(c=>String.fromCharCode(parseInt(c,16))).join(""),a=btoa(r).replace(/\+/g,"-").replace(/\//g,"_").replace(/=/g,"");return`${o}.${s}.${a}`}function St(i,e){let t=i.split(".");if(t.length!==3)return null;let[n,o,s]=t;if(!n||!o||!s)return null;let r=le(`${n}.${o}`,e),a=atob(s.replace(/-/g,"+").replace(/_/g,"/")),c=Array.from(a).map(u=>u.charCodeAt(0).toString(16).padStart(2,"0")).join(""),l=Buffer.from(r,"hex"),d=Buffer.from(c,"hex");if(l.length!==d.length||!(0,v.timingSafeEqual)(l,d))return null;try{let u=JSON.parse(atob(o)),m=u.exp;return typeof m=="number"&&Date.now()/1e3>m?null:u}catch{return null}}p();var de=require("node:fs"),te=require("node:path"),Yi=require("node:url"),yc={"node:sqlite":"consenti.db","better-sqlite3":"consenti.db","node-sqlite3-wasm":"consenti.db",sqlite:"consenti.db",json:"consenti-data.json",mongodb:"",mysql:"",postgresql:""},_c=(0,te.dirname)((0,Yi.fileURLToPath)(f));function wc(i){let e=i.includes("node_modules"),t=i.startsWith((0,te.resolve)(_c,"..",".."));return e||t}function me(i,e){let t=(0,te.resolve)(i),n=(0,te.extname)(t);if(n&&(console.warn(`[consenti] storage.path "${i}" looks like a file path (has extension "${n}"). Treating parent directory as storage root. Update your config to pass a directory path.`),t=(0,te.dirname)(t)),wc(t))throw new Error(`[consenti] storage.path "${t}" is inside the package installation directory. Choose a writable directory outside node_modules.`);(0,de.existsSync)(t)||(0,de.mkdirSync)(t,{recursive:!0});try{(0,de.accessSync)(t,de.constants.W_OK)}catch{throw new Error(`[consenti] storage.path "${t}" is not writable.`)}let o=(0,te.join)(t,"db"),s=(0,te.join)(t,"profiles"),r=(0,te.join)(t,"logs");(0,de.mkdirSync)(o,{recursive:!0}),(0,de.mkdirSync)(s,{recursive:!0}),(0,de.mkdirSync)(r,{recursive:!0});let a=yc[e]??"consenti.db",c=a?(0,te.join)(o,a):"";return{basePath:t,dbPath:c,profilesDir:s,logsDir:r}}p();var eo={name:"tenants",cols:[{n:"id",t:"pk"},{n:"name",t:"text"},{n:"slug",t:"text",unique:!0},{n:"created_at",t:"ts",def:"$now"},{n:"updated_at",t:"ts",def:"$now",mysqlUpd:!0}]},to={name:"profiles",cols:[{n:"id",t:"pk"},{n:"tenant_id",t:"text",ref:"tenants"},{n:"name",t:"text"},{n:"default_locale",t:"text_sm",def:"en"},{n:"version",t:"int",def:1},{n:"profile_json",t:"json_ordered"},{n:"created_at",t:"ts",def:"$now"},{n:"updated_at",t:"ts",def:"$now",mysqlUpd:!0}],idx:[{cols:["tenant_id"]}]},no={name:"consent_records",cols:[{n:"id",t:"pk"},{n:"tenant_id",t:"text",ref:"tenants"},{n:"visitor_id",t:"text"},{n:"profile_id",t:"text",ref:"profiles"},{n:"locale",t:"text_sm"},{n:"consent_json",t:"json"},{n:"gpc_detected",t:"bool",def:!1},{n:"source",t:"text_sm"},{n:"age_verified",t:"bool",def:!1},{n:"parental_consent_token",t:"longtext",null:!0},{n:"tcf_string",t:"longtext",null:!0},{n:"gpp_string",t:"longtext",null:!0},{n:"signature",t:"longtext",null:!0},{n:"created_at",t:"ts",def:"$now"},{n:"updated_at",t:"ts",def:"$now",mysqlUpd:!0}],uq:[{cols:["visitor_id","profile_id"]}],idx:[{cols:["tenant_id","created_at"]},{cols:["tenant_id","profile_id","created_at"]},{cols:["locale"]},{cols:["source"]}]},io={name:"consent_history",cols:[{n:"id",t:"pk"},{n:"tenant_id",t:"text",ref:"tenants"},{n:"consent_record_id",t:"text",ref:"consent_records"},{n:"visitor_id",t:"text"},{n:"old_json",t:"json",null:!0},{n:"new_json",t:"json"},{n:"action",t:"text_sm"},{n:"created_at",t:"ts",def:"$now"}],idx:[{cols:["visitor_id"]}]},oo={name:"visitors",cols:[{n:"id",t:"pk"},{n:"tenant_id",t:"text",ref:"tenants"},{n:"visitor_id",t:"text",unique:!0},{n:"country",t:"text_geo",null:!0},{n:"region",t:"text_md",null:!0},{n:"city",t:"text_md",null:!0},{n:"ip_hash",t:"text_hash",null:!0},{n:"user_agent_hash",t:"text_hash",null:!0},{n:"first_seen",t:"ts",def:"$now"},{n:"last_seen",t:"ts",def:"$now",mysqlUpd:!0}],idx:[{cols:["tenant_id","first_seen"]},{cols:["country"]}]},so={name:"notice_shown",cols:[{n:"id",t:"pk"},{n:"tenant_id",t:"text",ref:"tenants"},{n:"visitor_id",t:"text"},{n:"profile_id",t:"text",ref:"profiles"},{n:"locale",t:"text_sm"},{n:"created_at",t:"ts",def:"$now"}],idx:[{cols:["visitor_id"]}]},Ln={name:"users",cols:[{n:"id",t:"pk"},{n:"tenant_id",t:"text",ref:"tenants"},{n:"name",t:"text"},{n:"email",t:"text",unique:!0},{n:"password_hash",t:"text"},{n:"is_active",t:"bool",def:!0},{n:"totp_secret",t:"longtext",null:!0},{n:"totp_enabled",t:"bool",def:!1},{n:"created_at",t:"ts",def:"$now"},{n:"updated_at",t:"ts",def:"$now",mysqlUpd:!0}]},Ec={...Ln,cols:[...Ln.cols,{n:"allowed_tenants",t:"json",null:!0}]},ro={name:"roles",cols:[{n:"id",t:"pk"},{n:"tenant_id",t:"text",ref:"tenants"},{n:"name",t:"text_md"},{n:"description",t:"text",null:!0}]},ao={name:"permissions",cols:[{n:"id",t:"pk"},{n:"name",t:"text_md",unique:!0},{n:"description",t:"text",null:!0}]},co={name:"user_roles",cols:[{n:"user_id",t:"text",ref:"users"},{n:"role_id",t:"text",ref:"roles"},{n:"tenant_id",t:"text",def:"default"}],pk:["user_id","role_id","tenant_id"],idx:[{cols:["user_id"]}]},lo={name:"role_permissions",cols:[{n:"role_id",t:"text",ref:"roles"},{n:"permission_id",t:"text",ref:"permissions"}],pk:["role_id","permission_id"],idx:[{cols:["role_id"]}]},uo={name:"audit_logs",cols:[{n:"id",t:"pk"},{n:"tenant_id",t:"text",ref:"tenants"},{n:"user_id",t:"text",null:!0},{n:"action",t:"text_md"},{n:"resource_type",t:"text_md"},{n:"resource_id",t:"text",null:!0},{n:"old_data",t:"json",null:!0},{n:"new_data",t:"json",null:!0},{n:"created_at",t:"ts",def:"$now"}],idx:[{cols:["tenant_id","created_at"]},{cols:["action"]},{cols:["resource_type"]},{cols:["resource_id"]},{cols:["user_id"]}]},po={name:"api_keys",cols:[{n:"id",t:"pk"},{n:"tenant_id",t:"text",ref:"tenants",onDel:"CASCADE"},{n:"key_hash",t:"text_hash",unique:!0},{n:"name",t:"text"},{n:"is_active",t:"bool",def:!0},{n:"created_by",t:"text",null:!0},{n:"expire_by",t:"ts",null:!0},{n:"created_at",t:"ts",def:"$now"},{n:"updated_at",t:"ts",def:"$now",mysqlUpd:!0}]},mo={name:"tenant_settings",cols:[{n:"tenant_id",t:"text",ref:"tenants",onDel:"CASCADE"},{n:"allowed_origins_json",t:"json",def:"$arr"},{n:"admin_allowed_origins_json",t:"json",def:"$arr"},{n:"setup_completed",t:"bool",def:!1},{n:"profiles_seeded",t:"bool",def:!1},{n:"tcf_confirmation_json",t:"json",null:!0},{n:"gpp_confirmation_json",t:"json",null:!0},{n:"updated_at",t:"ts",def:"$now",mysqlUpd:!0}],pk:["tenant_id"]},go={name:"consent_templates",cols:[{n:"id",t:"pk"},{n:"tenant_id",t:"text",ref:"tenants",onDel:"CASCADE"},{n:"name",t:"text"},{n:"cookies_json",t:"json_ordered",def:"$obj"},{n:"categories_json",t:"json_ordered",def:"$obj"},{n:"created_at",t:"ts",def:"$now"},{n:"updated_at",t:"ts",def:"$now",mysqlUpd:!0}]},fo={name:"ui_templates",cols:[{n:"id",t:"pk"},{n:"tenant_id",t:"text",ref:"tenants",onDel:"CASCADE"},{n:"name",t:"text"},{n:"settings_json",t:"json_ordered",def:"$obj"},{n:"created_at",t:"ts",def:"$now"},{n:"updated_at",t:"ts",def:"$now",mysqlUpd:!0}]},Rc=[eo,to,no,io,oo,Ec,ro,ao,co,lo,uo,po,go,fo,mo,so],Nn=[eo,to,no,io,oo,Ln,ro,ao,co,lo,uo,po,go,fo,mo,so];function Sc(i){return i==="$now"?"DEFAULT (datetime('now'))":i==="$arr"?"DEFAULT '[]'":i==="$obj"?"DEFAULT '{}'":i===!0?"DEFAULT 1":i===!1?"DEFAULT 0":typeof i=="string"?`DEFAULT '${i}'`:`DEFAULT ${i}`}function Cc(i){if(i.t==="pk")return`${i.n} TEXT PRIMARY KEY`;let e=i.t==="int"||i.t==="bool"?"INTEGER":"TEXT",t=[`${i.n} ${e}`];return i.null||t.push("NOT NULL"),i.def!==void 0&&t.push(Sc(i.def)),i.unique&&t.push("UNIQUE"),i.ref&&(t.push(`REFERENCES ${i.ref}(id)`),i.onDel&&t.push(`ON DELETE ${i.onDel}`)),t.join(" ")}function Qi(i){let e=i.cols.map(t=>` ${Cc(t)}`);if(i.pk&&e.push(` PRIMARY KEY (${i.pk.join(", ")})`),i.uq)for(let t of i.uq)e.push(` UNIQUE(${t.cols.join(", ")})`);return`CREATE TABLE IF NOT EXISTS ${i.name} (
1
+ "use strict";var Dc=Object.create;var At=Object.defineProperty;var kc=Object.getOwnPropertyDescriptor;var Lc=Object.getOwnPropertyNames;var Nc=Object.getPrototypeOf,xc=Object.prototype.hasOwnProperty;var I=(i,e)=>()=>(i&&(e=i(i=0)),e);var Un=(i,e)=>{for(var t in e)At(i,t,{get:e[t],enumerable:!0})},Zi=(i,e,t,n)=>{if(e&&typeof e=="object"||typeof e=="function")for(let o of Lc(e))!xc.call(i,o)&&o!==t&&At(i,o,{get:()=>e[o],enumerable:!(n=kc(e,o))||n.enumerable});return i};var te=(i,e,t)=>(t=i!=null?Dc(Nc(i)):{},Zi(e||!i||!i.__esModule?At(t,"default",{value:i,enumerable:!0}):t,i)),Uc=i=>Zi(At({},"__esModule",{value:!0}),i);var Mc,h,p=I(()=>{"use strict";Mc=()=>typeof document>"u"?new URL(`file:${__filename}`).href:document.currentScript&&document.currentScript.tagName.toUpperCase()==="SCRIPT"?document.currentScript.src:new URL("main.js",document.baseURI).href,h=Mc()});var en,ri=I(()=>{"use strict";p();en={complianceGroup:"opt-in",gpcMode:"ignore",defaultLocale:"en",expiryDays:365,cookies:{security_storage:{purpose:"necessary",listenGpc:!1},functionality_storage:{purpose:"functional",listenGpc:!1},personalization_storage:{purpose:"preferences",listenGpc:!1},analytics_storage:{purpose:"analytics",listenGpc:!0},ad_storage:{purpose:"marketing",listenGpc:!0,cpraCategory:"sharing"}},translations:{en:{mainBanner:{position:"bottom",heading:"We value your privacy",htmlText:"We use cookies and similar technologies to enhance your browsing experience, analyse site traffic, and show you personalised content. Non-essential cookies require your consent under the GDPR and ePrivacy Directive.",buttons:{"accept-all":{text:"Accept All",style:"primary",action:"custom",cookies:"*"},"reject-optional":{text:"Reject Optional",style:"primary",action:"custom",cookies:"!"},"manage-preferences":{text:"Manage Preferences",style:"text",action:"manage"}}},gpcBanner:{position:"bottom",heading:"Global Privacy Control detected",htmlText:"Your browser is sending a Global Privacy Control signal. We have applied your preference and will not set non-essential cookies unless you change your settings below.",buttons:{"accept-all":{text:"Accept All",style:"primary",action:"custom",cookies:"*"},"confirm-settings":{text:"Confirm Settings",style:"primary",action:"custom",cookies:"!"},"manage-preferences":{text:"Manage Preferences",style:"text",action:"manage"}}},preferenceModal:{position:"right",heading:"Privacy Preferences",subheading:"Manage your consent settings for each category below.",htmlText:"You can choose which cookie categories you allow. Your choices apply to this site only. Essential cookies cannot be disabled as they are required for the site to function correctly.",buttons:{"accept-all":{text:"Accept All",style:"primary",action:"custom",cookies:"*"},"reject-optional":{text:"Reject Optional",style:"primary",action:"custom",cookies:"!"},"save-preferences":{text:"Save My Preferences",style:"primary",action:"submit"}},categories:{necessary:{heading:"Strictly Necessary",htmlText:"These cookies are required for the website to function and cannot be disabled. They are usually set in response to actions you take, such as setting your privacy preferences, logging in, or filling in forms.",legalBasis:"mandatory",cookies:["security_storage"]},functional:{heading:"Functional",htmlText:"These cookies enable enhanced functionality and personalisation. They may be set by us or by third-party providers whose services we have added to our pages. If you do not allow these cookies, some or all of these features may not function properly.",legalBasis:"consent",cookies:["functionality_storage","personalization_storage"]},analytics:{heading:"Analytics",htmlText:"These cookies allow us to count visits and traffic sources so we can measure and improve site performance. They help us understand which pages are most and least popular. All information collected is aggregated and therefore anonymous.",legalBasis:"consent",cookies:["analytics_storage"]},marketing:{heading:"Marketing",htmlText:"These cookies may be set through our site by advertising partners to build a profile of your interests and show you relevant adverts on other sites. They do not store personal information directly but identify your browser and device uniquely.",legalBasis:"consent",cookies:["ad_storage"]}}}}}}});var tn,ai=I(()=>{"use strict";p();tn={complianceGroup:"opt-out",gpcMode:"honor",defaultLocale:"en",expiryDays:365,cookies:{security_storage:{purpose:"necessary",listenGpc:!1},functionality_storage:{purpose:"functional",listenGpc:!0},personalization_storage:{purpose:"preferences",listenGpc:!0},analytics_storage:{purpose:"analytics",listenGpc:!0},ad_storage:{purpose:"marketing",listenGpc:!0,cpraCategory:"sharing"}},translations:{en:{mainBanner:{position:"bottom",heading:"We use cookies",htmlText:"We and our partners use cookies and similar tracking technologies to improve your experience, analyse site usage, and show relevant advertising. You may opt out of the sale or sharing of your personal data at any time.",buttons:{"accept-all":{text:"Accept All",style:"primary",action:"custom",cookies:"*"},"do-not-sell-share":{text:"Do Not Sell or Share My Personal Information",style:"secondary",action:"custom",cookies:"!"},"manage-preferences":{text:"Manage Preferences",style:"text",action:"manage"}}},gpcBanner:{position:"bottom",heading:"Your opt-out has been applied",htmlText:"Your browser sent a Global Privacy Control signal. We have automatically opted you out of the sale and sharing of your personal data as required by applicable US state privacy laws.",buttons:{"accept-all":{text:"Accept All",style:"primary",action:"custom",cookies:"*"},"confirm-opt-out":{text:"Confirm Opt-Out",style:"secondary",action:"custom",cookies:"!"},"manage-preferences":{text:"Manage Preferences",style:"text",action:"manage"}}},preferenceModal:{position:"right",heading:"Cookie Preferences",subheading:"Manage your data preferences. You may opt out of non-essential uses at any time.",htmlText:"Under applicable US state privacy laws, you have the right to opt out of the sale and sharing of your personal data. Toggle the categories below to exercise your rights.",buttons:{"accept-all":{text:"Accept All",style:"primary",action:"custom",cookies:"*"},"opt-out-all":{text:"Opt Out of All",style:"secondary",action:"custom",cookies:"!"},"save-choices":{text:"Save My Choices",style:"primary",action:"submit"}},categories:{necessary:{heading:"Strictly Necessary",htmlText:"These cookies are required for the website to operate and cannot be disabled. They do not involve the sale or sharing of personal data.",legalBasis:"mandatory",cookies:["security_storage"]},functional:{heading:"Functional",htmlText:"These cookies improve the functionality of the site. Disabling them may affect how the site operates. You may opt out at any time.",legalBasis:"consent",cookies:["functionality_storage","personalization_storage"]},analytics:{heading:"Analytics",htmlText:"Analytics cookies help us understand how visitors interact with the site. Opting out prevents your data from being included in usage statistics.",legalBasis:"consent",cookies:["analytics_storage"]},marketing:{heading:"Sale / Sharing of Personal Data",htmlText:"These cookies involve the sale or sharing of your personal data with advertising partners for targeted advertising. You have the right to opt out of this under applicable US state privacy laws.",legalBasis:"consent",cookies:["ad_storage"]}}}}}}});var nn,ci=I(()=>{"use strict";p();nn={complianceGroup:"opt-out-strict",gpcMode:"honor",defaultLocale:"en",expiryDays:365,cookies:{security_storage:{purpose:"necessary",listenGpc:!1},functionality_storage:{purpose:"functional",listenGpc:!0,cpraCategory:"sharing"},personalization_storage:{purpose:"preferences",listenGpc:!0,cpraCategory:"sharing"},analytics_storage:{purpose:"analytics",listenGpc:!0,cpraCategory:"sharing"},ad_storage:{purpose:"marketing",listenGpc:!0,cpraCategory:"sharing"},sensitive_info_storage:{purpose:"marketing",listenGpc:!0,cpraCategory:"sensitive"}},translations:{en:{mainBanner:{position:"bottom",heading:"Your California Privacy Rights",htmlText:"Under the California Privacy Rights Act (CPRA), you have the right to opt out of the sale, sharing, and use of sensitive personal information. We use cookies and tracking technologies that may involve the sale or sharing of your data with third parties.",buttons:{"accept-all":{text:"Accept All",style:"primary",action:"custom",cookies:"*"},"opt-out-sale-sharing-sensitive":{text:"Opt Out of Sale, Sharing & Sensitive Use",style:"secondary",action:"custom",cookies:"!"},manage:{text:"Manage",style:"text",action:"manage"}}},gpcBanner:{position:"bottom",heading:"GPC opt-out applied automatically",htmlText:"Your browser sent a Global Privacy Control signal. Under the CPRA, we are required to honor this as a Do Not Sell or Share My Personal Information request. Your opt-out has been applied automatically.",buttons:{"accept-all":{text:"Accept All",style:"primary",action:"custom",cookies:"*"},"confirm-opt-out":{text:"Confirm Opt-Out",style:"secondary",action:"custom",cookies:"!"},"review-choices":{text:"Review Choices",style:"text",action:"manage"}}},preferenceModal:{position:"right",heading:"Privacy Rights Center",subheading:"Manage your CPRA rights: opt out of sale, sharing, and limit the use of sensitive personal information.",htmlText:"As a California resident, you have the right under CPRA to opt out of the sale and sharing of your personal information, including for cross-context behavioral advertising, and to limit the use of your sensitive personal information. Toggle each category below to exercise your rights.",buttons:{"accept-all":{text:"Accept All",style:"primary",action:"custom",cookies:"*"},"opt-out-sale-sharing-sensitive":{text:"Opt Out of Sale, Sharing & Sensitive Use",style:"secondary",action:"custom",cookies:"!"},"save-choices":{text:"Save My Choices",style:"primary",action:"submit"}},categories:{necessary:{heading:"Strictly Necessary",htmlText:"Essential to deliver the service. These cookies are not sold or shared and cannot be disabled.",legalBasis:"mandatory",cookies:["security_storage"]},functional:{heading:"Functional & Personalisation",htmlText:"Improve site functionality and remember your preferences. May involve sharing of browsing data.",legalBasis:"consent",cookies:["functionality_storage","personalization_storage"]},analytics:{heading:"Analytics (Sharing)",htmlText:'Measure site performance. Analytics data may be shared with third-party providers, which constitutes "sharing" under CPRA.',legalBasis:"consent",cookies:["analytics_storage"]},marketing:{heading:"Sale & Sharing of Personal Data",htmlText:"Advertising and retargeting cookies that involve the sale or sharing of your personal data with third-party advertisers for cross-context behavioural advertising.",legalBasis:"consent",cookies:["ad_storage"]},sensitive:{heading:"Sensitive Personal Information",htmlText:"Some technologies may use sensitive personal information as defined by CPRA (e.g. precise geolocation, health data). You have the right to limit such use.",legalBasis:"consent",cookies:["sensitive_info_storage"]}}}}}}});var on,li=I(()=>{"use strict";p();on={complianceGroup:"opt-in-dpdpa",gpcMode:"ignore",defaultLocale:"en",expiryDays:365,cookies:{security_storage:{purpose:"necessary",listenGpc:!1},functionality_storage:{purpose:"functional",listenGpc:!1},personalization_storage:{purpose:"preferences",listenGpc:!1},analytics_storage:{purpose:"analytics",listenGpc:!1},ad_storage:{purpose:"marketing",listenGpc:!1}},translations:{en:{mainBanner:{position:"bottom",heading:"Data Protection Notice",htmlText:"We are the Data Fiduciary under India's Digital Personal Data Protection Act (DPDPA). Your explicit consent is required before we process your personal data using non-essential cookies. You may withdraw consent at any time without affecting prior processing.",buttons:{"consent-all":{text:"I Consent",style:"primary",action:"custom",cookies:"*"},"deny-all":{text:"I Do Not Consent",style:"secondary",action:"custom",cookies:"!"},"review-choices":{text:"Review Choices",style:"text",action:"manage"}}},preferenceModal:{position:"right",heading:"Consent Preferences",subheading:"Review the purposes for which we process your personal data and provide or withdraw consent for each.",htmlText:"Under the Digital Personal Data Protection Act (DPDPA) 2023, you have the right to give, manage, and withdraw consent for personal data processing. Legitimate interest is not a valid legal basis under the DPDPA \u2014 all data processing requires your explicit consent.",buttons:{"consent-all":{text:"Give Consent to All",style:"primary",action:"custom",cookies:"*"},"withdraw-all":{text:"Withdraw All Consent",style:"secondary",action:"custom",cookies:"!"},"save-choices":{text:"Save Choices",style:"secondary",action:"submit"}},categories:{necessary:{heading:"Strictly Necessary",htmlText:"Required to deliver the core service. No personal data is shared and consent is not required for these.",legalBasis:"mandatory",cookies:["security_storage"]},functional:{heading:"Functional",htmlText:"Enable enhanced features and personalisation. Your explicit consent is required under the DPDPA before we process data for these purposes.",legalBasis:"consent",cookies:["functionality_storage","personalization_storage"]},analytics:{heading:"Analytics",htmlText:"Help us understand how you interact with the site. Your consent is required before any analytics data is collected.",legalBasis:"consent",cookies:["analytics_storage"]},marketing:{heading:"Marketing & Advertising",htmlText:"Allow personalised advertising based on your browsing activity. Requires your explicit consent under the DPDPA.",legalBasis:"consent",cookies:["ad_storage"]}}}}}}});var sn,di=I(()=>{"use strict";p();sn={complianceGroup:"opt-in-china",gpcMode:"ignore",defaultLocale:"en",expiryDays:365,cookies:{security_storage:{purpose:"necessary",listenGpc:!1},functionality_storage:{purpose:"functional",listenGpc:!1},personalization_storage:{purpose:"preferences",listenGpc:!1},analytics_storage:{purpose:"analytics",listenGpc:!1},ad_storage:{purpose:"marketing",listenGpc:!1}},translations:{en:{mainBanner:{position:"bottom",heading:"Personal Information Processing Notice",htmlText:"In accordance with China's Personal Information Protection Law (PIPL), Data Security Law (DSL), and Cybersecurity Law (CSL), we process personal information only for specified, explicit, and legitimate purposes with minimum data collection. Your consent is required for non-essential cookies.",buttons:{"agree-all":{text:"Agree to All",style:"primary",action:"custom",cookies:"*"},"reject-non-necessary":{text:"Reject Non-Necessary",style:"secondary",action:"custom",cookies:"!"},"manage-preferences":{text:"Manage Preferences",style:"text",action:"manage"}}},preferenceModal:{position:"right",heading:"Personal Information Processing Settings",subheading:"Review the purpose and scope of each category of personal information processing.",htmlText:"Under the PIPL, you have the right to know, decide, and restrict the processing of your personal information. Processing is limited to the stated purposes. Cross-border transfers of your data, if any, are handled in accordance with Chapter III of the PIPL, including security assessments or standard contracts where applicable.",buttons:{"agree-all":{text:"Agree to All",style:"primary",action:"custom",cookies:"*"},"disagree-all":{text:"Disagree to All",style:"secondary",action:"custom",cookies:"!"},"confirm-settings":{text:"Confirm Settings",style:"primary",action:"submit"}},categories:{necessary:{heading:"Necessary for Service",htmlText:"Required to deliver the core service and ensure network security under the CSL. Cannot be disabled.",legalBasis:"mandatory",cookies:["security_storage"]},functional:{heading:"Functionality & Personalisation",htmlText:"Enable enhanced features. Personal information is processed only for the stated purposes and retained for no longer than necessary.",legalBasis:"consent",cookies:["functionality_storage","personalization_storage"]},analytics:{heading:"Statistical Analysis",htmlText:"Collect and analyse usage data to improve the service. Data is processed within China unless cross-border transfer requirements are satisfied.",legalBasis:"consent",cookies:["analytics_storage"]},marketing:{heading:"Targeted Advertising",htmlText:"Personalise advertisements based on your interactions. Requires explicit consent under PIPL. You may withdraw consent and object to personalised advertising at any time.",legalBasis:"consent",cookies:["ad_storage"]}}}}}}});var rn,ui=I(()=>{"use strict";p();rn={complianceGroup:"opt-in-brazil",gpcMode:"ignore",defaultLocale:"en",expiryDays:365,cookies:{security_storage:{purpose:"necessary",listenGpc:!1},functionality_storage:{purpose:"functional",listenGpc:!1},personalization_storage:{purpose:"preferences",listenGpc:!1},analytics_storage:{purpose:"analytics",listenGpc:!1},ad_storage:{purpose:"marketing",listenGpc:!1}},translations:{en:{mainBanner:{position:"bottom",heading:"We value your privacy",htmlText:"In accordance with Brazil's Lei Geral de Prote\xE7\xE3o de Dados (LGPD), we process personal data only with a valid legal basis. Non-essential cookies require your prior consent. You may withdraw consent at any time. Legitimate interest applies where noted.",buttons:{"accept-all":{text:"Accept All",style:"primary",action:"custom",cookies:"*"},"reject-optional":{text:"Reject Optional",style:"secondary",action:"custom",cookies:"!"},manage:{text:"Manage",style:"text",action:"manage"}}},preferenceModal:{position:"right",heading:"Privacy Preferences",subheading:"Review and manage your data processing preferences under the LGPD.",htmlText:"You have rights under the LGPD including: access, correction, deletion, portability, and withdrawal of consent. Categories based on legitimate interest are indicated below \u2014 you may object to these at any time.",buttons:{"accept-all":{text:"Accept All",style:"primary",action:"custom",cookies:"*"},"reject-optional":{text:"Reject Optional",style:"secondary",action:"custom",cookies:"!"},"save-preferences":{text:"Save My Preferences",style:"primary",action:"submit"}},categories:{necessary:{heading:"Strictly Necessary",htmlText:"Essential for the service to function. Legal basis: fulfillment of a contract or legal obligation. Cannot be disabled.",legalBasis:"mandatory",cookies:["security_storage"]},functional:{heading:"Functional",htmlText:"Enhance site functionality and remember your settings. Legal basis: legitimate interest (LGPD Art. 7, X). You may object to this processing at any time.",legalBasis:"legitimate_interest",legitimateInterestDescription:"Remembering a visitor's in-session preferences (e.g. layout, saved settings) is necessary to deliver the functionality they engaged with, has minimal privacy impact since no data is shared with third parties, and is limited to what a visitor would reasonably expect from using the site, per the balancing test required by LGPD Art. 10.",cookies:["functionality_storage","personalization_storage"]},analytics:{heading:"Analytics",htmlText:"Help us understand how visitors use the site so we can improve it. Legal basis: your consent.",legalBasis:"consent",cookies:["analytics_storage"]},marketing:{heading:"Marketing & Advertising",htmlText:"Personalise ads and measure campaign effectiveness. Legal basis: your consent. You may withdraw consent at any time without affecting the lawfulness of prior processing.",legalBasis:"consent",cookies:["ad_storage"]}}}}}}});var an,pi=I(()=>{"use strict";p();an={complianceGroup:"general-privacy-consent",gpcMode:"ignore",defaultLocale:"en",expiryDays:365,cookies:{security_storage:{purpose:"necessary",listenGpc:!1},functionality_storage:{purpose:"functional",listenGpc:!1},personalization_storage:{purpose:"preferences",listenGpc:!1},analytics_storage:{purpose:"analytics",listenGpc:!1},ad_storage:{purpose:"marketing",listenGpc:!1}},translations:{en:{mainBanner:{position:"bottom",heading:"We use cookies",htmlText:"We use cookies to improve your browsing experience, analyse site traffic, and show you relevant content. By continuing to use this site, you accept our use of cookies. You can manage your preferences at any time.",buttons:{"accept-all":{text:"Accept All",style:"primary",action:"custom",cookies:"*"},"reject-marketing":{text:"Reject Marketing",style:"secondary",action:"custom",cookies:["security_storage","functionality_storage","personalization_storage","analytics_storage"]},"manage-preferences":{text:"Manage Preferences",style:"text",action:"manage"}}},preferenceModal:{position:"right",heading:"Cookie Settings",subheading:"We document the legal basis for each category of cookie we use.",htmlText:"A privacy notice or consent framework applies in your jurisdiction. While a strict cookie consent banner may not be legally required, we document our legal basis for processing to follow privacy best practices.",buttons:{"accept-all":{text:"Accept All",style:"primary",action:"custom",cookies:"*"},"necessary-only":{text:"Necessary Only",style:"secondary",action:"custom",cookies:"!"},"save-preferences":{text:"Save My Settings",style:"primary",action:"submit"}},categories:{necessary:{heading:"Strictly Necessary",htmlText:"Required to deliver the service. No optional data processing takes place. Cannot be disabled.",legalBasis:"mandatory",cookies:["security_storage"]},functional:{heading:"Functional",htmlText:"Improve how the site works and remember your preferences. Legal basis: legitimate interest.",legalBasis:"legitimate_interest",legitimateInterestDescription:"Remembering a visitor's in-session preferences (e.g. layout, saved settings) is a low-privacy-impact processing activity that a visitor would reasonably expect from using the site, and is necessary to deliver the functionality they engaged with \u2014 our interest in providing it is not overridden by the visitor's privacy interest, since no data leaves the site and nothing is used for profiling or advertising.",cookies:["functionality_storage","personalization_storage"]},analytics:{heading:"Analytics",htmlText:"Help us understand usage patterns to improve the site. Legal basis: legitimate interest. Data is aggregated and anonymised where possible.",legalBasis:"legitimate_interest",legitimateInterestDescription:"Measuring aggregate, anonymised site usage to improve performance and content is a reasonable, low-risk business interest that does not identify individual visitors or feed advertising/profiling, and is proportionate to the minimal impact on visitor privacy.",cookies:["analytics_storage"]},marketing:{heading:"Marketing",htmlText:"Personalise advertising and measure campaign reach. Legal basis: your consent. You may withdraw consent at any time.",legalBasis:"consent",cookies:["ad_storage"]}}}}}}});var cn,mi=I(()=>{"use strict";p();cn={complianceGroup:"notice-only",gpcMode:"ignore",defaultLocale:"en",expiryDays:365,cookies:{security_storage:{purpose:"necessary",listenGpc:!1}},translations:{en:{mainBanner:{position:"bottom",heading:"This site uses essential cookies only",htmlText:"We use strictly necessary cookies to ensure this website functions correctly. No tracking, advertising, or analytics cookies are used. No specific cookie consent law applies in your jurisdiction.",buttons:{ok:{text:"OK",style:"primary",action:"close"}}},preferenceModal:{position:"right",heading:"Cookie Information",subheading:"We only use cookies that are strictly necessary for this site to work.",htmlText:"This site does not use optional cookies. The only cookie set is required to maintain basic security and session integrity. You cannot disable it without affecting site functionality.",buttons:{close:{text:"Close",style:"primary",action:"close"}},categories:{necessary:{heading:"Strictly Necessary",htmlText:"Required for the site to function. These cookies do not track you and cannot be disabled.",legalBasis:"mandatory",cookies:["security_storage"]}}}}}}});var as,cs=I(()=>{"use strict";p();as={mainBanner:{heading:"Wir sch\xE4tzen Ihre Privatsph\xE4re",htmlText:"Wir verwenden Cookies, um Ihre Browser-Erfahrung zu verbessern, personalisierte Inhalte oder Anzeigen bereitzustellen und unseren Datenverkehr zu analysieren. Mit dem Klicken auf <strong>Alle akzeptieren</strong> stimmen Sie der Verwendung von Cookies zu. Sie k\xF6nnen Ihre Einstellungen jederzeit \xE4ndern.",buttons:{"accept-all":"Alle akzeptieren","reject-optional":"Alle ablehnen","manage-preferences":"Einstellungen verwalten"}},gpcBanner:{heading:"Datenschutzpr\xE4ferenz erkannt",htmlText:"Ihr Browser hat ein Global Privacy Control (GPC) Signal gesendet. Wir haben Ihre Datenschutzpr\xE4ferenz ber\xFCcksichtigt.",buttons:{"accept-all":"Einstellungen \xFCberpr\xFCfen","confirm-settings":"Weiter"}},preferenceModal:{heading:"Datenschutzeinstellungen",subheading:"W\xE4hlen Sie aus, welche Cookies Sie erlauben.",htmlText:"Wir verwenden verschiedene Cookie-Typen. Sie k\xF6nnen die einzelnen Kategorien aktivieren oder deaktivieren. Notwendige Cookies k\xF6nnen nicht deaktiviert werden.",buttons:{"accept-all":"Alle akzeptieren","reject-optional":"Alle ablehnen","save-preferences":"Auswahl speichern"},categories:{"cat-necessary":{heading:"Unbedingt erforderlich",htmlText:"Diese Cookies sind f\xFCr das Funktionieren der Website unbedingt erforderlich und k\xF6nnen nicht deaktiviert werden."},"cat-functional":{heading:"Funktional",htmlText:"Erm\xF6glichen erweiterte Funktionen wie gespeicherte Pr\xE4ferenzen und Personalisierung."},"cat-preferences":{heading:"Pr\xE4ferenzen",htmlText:"Speichern Ihre pers\xF6nlichen Einstellungen und Pr\xE4ferenzen f\xFCr zuk\xFCnftige Besuche."},"cat-analytics":{heading:"Analyse",htmlText:"Helfen uns zu verstehen, wie Besucher mit unserer Website interagieren."},"cat-marketing":{heading:"Marketing",htmlText:"Werden verwendet, um Ihnen relevante Werbung anzuzeigen."}}}}});var ls,ds=I(()=>{"use strict";p();ls={mainBanner:{heading:"Valoramos su privacidad",htmlText:"Utilizamos cookies para mejorar su experiencia de navegaci\xF3n, mostrar anuncios o contenido personalizados y analizar nuestro tr\xE1fico. Al hacer clic en <strong>Aceptar todo</strong>, consiente el uso de cookies. Puede cambiar sus preferencias en cualquier momento.",buttons:{"accept-all":"Aceptar todo","reject-optional":"Rechazar todo","manage-preferences":"Gestionar preferencias"}},gpcBanner:{heading:"Preferencia de privacidad reconocida",htmlText:"Su navegador ha enviado una se\xF1al Global Privacy Control (GPC). Hemos aplicado su preferencia de privacidad.",buttons:{"accept-all":"Revisar preferencias","confirm-settings":"Continuar"}},preferenceModal:{heading:"Preferencias de privacidad",subheading:"Elija qu\xE9 cookies desea permitir.",htmlText:"Utilizamos distintos tipos de cookies. Puede activar o desactivar cada categor\xEDa. Las cookies necesarias no pueden desactivarse.",buttons:{"accept-all":"Aceptar todo","reject-optional":"Rechazar todo","save-preferences":"Guardar selecci\xF3n"},categories:{"cat-necessary":{heading:"Estrictamente necesarias",htmlText:"Estas cookies son imprescindibles para el funcionamiento del sitio web y no pueden desactivarse."},"cat-functional":{heading:"Funcionales",htmlText:"Permiten funciones avanzadas como preferencias guardadas y personalizaci\xF3n."},"cat-preferences":{heading:"Preferencias",htmlText:"Guardan su configuraci\xF3n personal y preferencias para visitas futuras."},"cat-analytics":{heading:"Anal\xEDticas",htmlText:"Nos ayudan a entender c\xF3mo los visitantes interact\xFAan con nuestro sitio web."},"cat-marketing":{heading:"Marketing",htmlText:"Se utilizan para mostrarle publicidad relevante."}}}}});var us,ps=I(()=>{"use strict";p();us={mainBanner:{heading:"Nous respectons votre vie priv\xE9e",htmlText:"Nous utilisons des cookies pour am\xE9liorer votre exp\xE9rience de navigation, afficher des publicit\xE9s ou du contenu personnalis\xE9s et analyser notre trafic. En cliquant sur <strong>Tout accepter</strong>, vous consentez \xE0 l'utilisation des cookies. Vous pouvez modifier vos pr\xE9f\xE9rences \xE0 tout moment.",buttons:{"accept-all":"Tout accepter","reject-optional":"Tout refuser","manage-preferences":"G\xE9rer les pr\xE9f\xE9rences"}},gpcBanner:{heading:"Pr\xE9f\xE9rence de confidentialit\xE9 reconnue",htmlText:"Votre navigateur a envoy\xE9 un signal Global Privacy Control (GPC). Nous avons appliqu\xE9 votre pr\xE9f\xE9rence de confidentialit\xE9.",buttons:{"accept-all":"V\xE9rifier les pr\xE9f\xE9rences","confirm-settings":"Continuer"}},preferenceModal:{heading:"Param\xE8tres de confidentialit\xE9",subheading:"Choisissez les cookies que vous souhaitez autoriser.",htmlText:"Nous utilisons diff\xE9rents types de cookies. Vous pouvez activer ou d\xE9sactiver chaque cat\xE9gorie. Les cookies n\xE9cessaires ne peuvent pas \xEAtre d\xE9sactiv\xE9s.",buttons:{"accept-all":"Tout accepter","reject-optional":"Tout refuser","save-preferences":"Enregistrer la s\xE9lection"},categories:{"cat-necessary":{heading:"Strictement n\xE9cessaires",htmlText:"Ces cookies sont indispensables au fonctionnement du site web et ne peuvent pas \xEAtre d\xE9sactiv\xE9s."},"cat-functional":{heading:"Fonctionnels",htmlText:"Permettent des fonctionnalit\xE9s avanc\xE9es comme les pr\xE9f\xE9rences enregistr\xE9es et la personnalisation."},"cat-preferences":{heading:"Pr\xE9f\xE9rences",htmlText:"Sauvegardent vos param\xE8tres personnels et pr\xE9f\xE9rences pour les visites futures."},"cat-analytics":{heading:"Analytiques",htmlText:"Nous aident \xE0 comprendre comment les visiteurs interagissent avec notre site web."},"cat-marketing":{heading:"Marketing",htmlText:"Sont utilis\xE9s pour vous afficher des publicit\xE9s pertinentes."}}}}});var ms,gs=I(()=>{"use strict";p();ms={mainBanner:{heading:"\u30D7\u30E9\u30A4\u30D0\u30B7\u30FC\u3092\u5927\u5207\u306B\u3057\u3066\u3044\u307E\u3059",htmlText:"\u30D6\u30E9\u30A6\u30B8\u30F3\u30B0\u4F53\u9A13\u306E\u5411\u4E0A\u3001\u30D1\u30FC\u30BD\u30CA\u30E9\u30A4\u30BA\u3055\u308C\u305F\u5E83\u544A\u30FB\u30B3\u30F3\u30C6\u30F3\u30C4\u306E\u8868\u793A\u3001\u30C8\u30E9\u30D5\u30A3\u30C3\u30AF\u5206\u6790\u306E\u305F\u3081\u306BCookie\u3092\u4F7F\u7528\u3057\u3066\u3044\u307E\u3059\u3002<strong>\u3059\u3079\u3066\u540C\u610F</strong>\u3092\u30AF\u30EA\u30C3\u30AF\u3059\u308B\u3053\u3068\u3067\u3001Cookie\u306E\u4F7F\u7528\u306B\u540C\u610F\u3057\u305F\u3053\u3068\u306B\u306A\u308A\u307E\u3059\u3002\u8A2D\u5B9A\u306F\u3044\u3064\u3067\u3082\u5909\u66F4\u3067\u304D\u307E\u3059\u3002",buttons:{"accept-all":"\u3059\u3079\u3066\u540C\u610F","reject-optional":"\u3059\u3079\u3066\u62D2\u5426","manage-preferences":"\u8A2D\u5B9A\u3092\u7BA1\u7406"}},gpcBanner:{heading:"\u30D7\u30E9\u30A4\u30D0\u30B7\u30FC\u8A2D\u5B9A\u304C\u691C\u51FA\u3055\u308C\u307E\u3057\u305F",htmlText:"\u30D6\u30E9\u30A6\u30B6\u304B\u3089Global Privacy Control\uFF08GPC\uFF09\u30B7\u30B0\u30CA\u30EB\u304C\u9001\u4FE1\u3055\u308C\u307E\u3057\u305F\u3002\u304A\u5BA2\u69D8\u306E\u30D7\u30E9\u30A4\u30D0\u30B7\u30FC\u8A2D\u5B9A\u3092\u9069\u7528\u3057\u307E\u3057\u305F\u3002",buttons:{"accept-all":"\u8A2D\u5B9A\u3092\u78BA\u8A8D","confirm-settings":"\u7D9A\u884C"}},preferenceModal:{heading:"\u30D7\u30E9\u30A4\u30D0\u30B7\u30FC\u8A2D\u5B9A",subheading:"\u8A31\u53EF\u3059\u308BCookie\u3092\u9078\u629E\u3057\u3066\u304F\u3060\u3055\u3044\u3002",htmlText:"\u3055\u307E\u3056\u307E\u306A\u7A2E\u985E\u306ECookie\u3092\u4F7F\u7528\u3057\u3066\u3044\u307E\u3059\u3002\u5404\u30AB\u30C6\u30B4\u30EA\u3092\u6709\u52B9\u307E\u305F\u306F\u7121\u52B9\u306B\u3059\u308B\u3053\u3068\u304C\u3067\u304D\u307E\u3059\u3002\u5FC5\u9808Cookie\u306F\u7121\u52B9\u306B\u3067\u304D\u307E\u305B\u3093\u3002",buttons:{"accept-all":"\u3059\u3079\u3066\u540C\u610F","reject-optional":"\u3059\u3079\u3066\u62D2\u5426","save-preferences":"\u9078\u629E\u3092\u4FDD\u5B58"},categories:{"cat-necessary":{heading:"\u5FC5\u9808",htmlText:"\u3053\u308C\u3089\u306ECookie\u306F\u30A6\u30A7\u30D6\u30B5\u30A4\u30C8\u306E\u6A5F\u80FD\u306B\u4E0D\u53EF\u6B20\u3067\u3042\u308A\u3001\u7121\u52B9\u306B\u3059\u308B\u3053\u3068\u306F\u3067\u304D\u307E\u305B\u3093\u3002"},"cat-functional":{heading:"\u6A5F\u80FD",htmlText:"\u4FDD\u5B58\u3055\u308C\u305F\u8A2D\u5B9A\u3084\u30D1\u30FC\u30BD\u30CA\u30E9\u30A4\u30BC\u30FC\u30B7\u30E7\u30F3\u306A\u3069\u306E\u9AD8\u5EA6\u306A\u6A5F\u80FD\u3092\u6709\u52B9\u306B\u3057\u307E\u3059\u3002"},"cat-preferences":{heading:"\u8A2D\u5B9A",htmlText:"\u5C06\u6765\u306E\u8A2A\u554F\u306E\u305F\u3081\u306B\u500B\u4EBA\u8A2D\u5B9A\u3084\u597D\u307F\u3092\u4FDD\u5B58\u3057\u307E\u3059\u3002"},"cat-analytics":{heading:"\u5206\u6790",htmlText:"\u8A2A\u554F\u8005\u304C\u3069\u306E\u3088\u3046\u306B\u30A6\u30A7\u30D6\u30B5\u30A4\u30C8\u3092\u5229\u7528\u3057\u3066\u3044\u308B\u304B\u3092\u7406\u89E3\u3059\u308B\u306E\u306B\u5F79\u7ACB\u3061\u307E\u3059\u3002"},"cat-marketing":{heading:"\u30DE\u30FC\u30B1\u30C6\u30A3\u30F3\u30B0",htmlText:"\u95A2\u9023\u3059\u308B\u5E83\u544A\u3092\u8868\u793A\u3059\u308B\u305F\u3081\u306B\u4F7F\u7528\u3055\u308C\u307E\u3059\u3002"}}}}});var fs,hs=I(()=>{"use strict";p();fs={mainBanner:{heading:"Wir verwenden Cookies",htmlText:"Wir verwenden Cookies, um unsere Dienste zu verbessern. Sie k\xF6nnen dem Verkauf oder der Weitergabe Ihrer pers\xF6nlichen Daten jederzeit widersprechen.",buttons:{"accept-all":"Alle akzeptieren","do-not-sell-share":"Nicht verkaufen oder weitergeben","manage-preferences":"Einstellungen verwalten"}},gpcBanner:{heading:"GPC erkannt \u2013 Opt-out angewendet",htmlText:"Ihr Browser hat ein Global Privacy Control Signal gesendet. Wir haben Sie vom Verkauf und der Weitergabe Ihrer Daten abgemeldet.",buttons:{"accept-all":"Einstellungen \xFCberpr\xFCfen","confirm-opt-out":"Weiter"}},preferenceModal:{heading:"Datenschutzeinstellungen",subheading:"W\xE4hlen Sie Ihre Datenschutzoptionen.",buttons:{"accept-all":"Alle akzeptieren","opt-out-all":"Nicht verkaufen oder weitergeben","save-choices":"Auswahl speichern"},categories:{"cat-necessary":{heading:"Unbedingt erforderlich",htmlText:"Diese Cookies sind f\xFCr das Funktionieren der Website unbedingt erforderlich."},"cat-functional":{heading:"Funktional",htmlText:"Erm\xF6glichen erweiterte Funktionen und Personalisierung."},"cat-preferences":{heading:"Pr\xE4ferenzen",htmlText:"Speichern Ihre Einstellungen f\xFCr zuk\xFCnftige Besuche."},"cat-analytics":{heading:"Analyse",htmlText:"Helfen uns zu verstehen, wie Besucher unsere Website nutzen."},"cat-marketing":{heading:"Werbung / Verkauf",htmlText:"Erm\xF6glichen gezielte Werbung. Sie k\xF6nnen dem Verkauf Ihrer Daten widersprechen."}}}}});var ys,_s=I(()=>{"use strict";p();ys={mainBanner:{heading:"Utilizamos cookies",htmlText:"Utilizamos cookies para mejorar nuestros servicios. Puede oponerse a la venta o al intercambio de sus datos personales en cualquier momento.",buttons:{"accept-all":"Aceptar todo","do-not-sell-share":"No vender ni compartir","manage-preferences":"Gestionar preferencias"}},gpcBanner:{heading:"GPC detectado \u2013 exclusi\xF3n aplicada",htmlText:"Su navegador ha enviado una se\xF1al Global Privacy Control. Le hemos excluido de la venta y el intercambio de sus datos.",buttons:{"accept-all":"Revisar preferencias","confirm-opt-out":"Continuar"}},preferenceModal:{heading:"Preferencias de privacidad",subheading:"Elija sus opciones de privacidad.",buttons:{"accept-all":"Aceptar todo","opt-out-all":"No vender ni compartir","save-choices":"Guardar selecci\xF3n"},categories:{"cat-necessary":{heading:"Estrictamente necesarias",htmlText:"Imprescindibles para el funcionamiento del sitio web."},"cat-functional":{heading:"Funcionales",htmlText:"Permiten funciones avanzadas y personalizaci\xF3n."},"cat-preferences":{heading:"Preferencias",htmlText:"Guardan su configuraci\xF3n para visitas futuras."},"cat-analytics":{heading:"Anal\xEDticas",htmlText:"Nos ayudan a entender c\xF3mo los visitantes utilizan nuestro sitio."},"cat-marketing":{heading:"Publicidad / Venta",htmlText:"Permiten publicidad dirigida. Puede oponerse a la venta de sus datos."}}}}});var ws,Es=I(()=>{"use strict";p();ws={mainBanner:{heading:"Nous utilisons des cookies",htmlText:"Nous utilisons des cookies pour am\xE9liorer nos services. Vous pouvez vous opposer \xE0 la vente ou au partage de vos donn\xE9es personnelles \xE0 tout moment.",buttons:{"accept-all":"Tout accepter","do-not-sell-share":"Ne pas vendre ni partager","manage-preferences":"G\xE9rer les pr\xE9f\xE9rences"}},gpcBanner:{heading:"GPC d\xE9tect\xE9 \u2013 exclusion appliqu\xE9e",htmlText:"Votre navigateur a envoy\xE9 un signal Global Privacy Control. Nous avons appliqu\xE9 votre demande de ne pas vendre ni partager vos donn\xE9es.",buttons:{"accept-all":"V\xE9rifier les pr\xE9f\xE9rences","confirm-opt-out":"Continuer"}},preferenceModal:{heading:"Param\xE8tres de confidentialit\xE9",subheading:"Choisissez vos options de confidentialit\xE9.",buttons:{"accept-all":"Tout accepter","opt-out-all":"Ne pas vendre ni partager","save-choices":"Enregistrer la s\xE9lection"},categories:{"cat-necessary":{heading:"Strictement n\xE9cessaires",htmlText:"Indispensables au fonctionnement du site web."},"cat-functional":{heading:"Fonctionnels",htmlText:"Permettent des fonctionnalit\xE9s avanc\xE9es et la personnalisation."},"cat-preferences":{heading:"Pr\xE9f\xE9rences",htmlText:"Sauvegardent vos param\xE8tres pour les visites futures."},"cat-analytics":{heading:"Analytiques",htmlText:"Nous aident \xE0 comprendre comment les visiteurs utilisent notre site."},"cat-marketing":{heading:"Publicit\xE9 / Vente",htmlText:"Permettent la publicit\xE9 cibl\xE9e. Vous pouvez vous opposer \xE0 la vente de vos donn\xE9es."}}}}});var Rs,Ss=I(()=>{"use strict";p();Rs={mainBanner:{heading:"Cookie\u3092\u4F7F\u7528\u3057\u3066\u3044\u307E\u3059",htmlText:"\u30B5\u30FC\u30D3\u30B9\u5411\u4E0A\u306E\u305F\u3081\u306BCookie\u3092\u4F7F\u7528\u3057\u3066\u3044\u307E\u3059\u3002\u500B\u4EBA\u30C7\u30FC\u30BF\u306E\u8CA9\u58F2\u3084\u5171\u6709\u306B\u306F\u3044\u3064\u3067\u3082\u7570\u8B70\u3092\u7533\u3057\u7ACB\u3066\u308B\u3053\u3068\u304C\u3067\u304D\u307E\u3059\u3002",buttons:{"accept-all":"\u3059\u3079\u3066\u540C\u610F","do-not-sell-share":"\u8CA9\u58F2\u30FB\u5171\u6709\u3057\u306A\u3044","manage-preferences":"\u8A2D\u5B9A\u3092\u7BA1\u7406"}},gpcBanner:{heading:"GPC\u691C\u51FA \u2013 \u30AA\u30D7\u30C8\u30A2\u30A6\u30C8\u9069\u7528\u6E08\u307F",htmlText:"\u30D6\u30E9\u30A6\u30B6\u304B\u3089Global Privacy Control\u30B7\u30B0\u30CA\u30EB\u304C\u9001\u4FE1\u3055\u308C\u307E\u3057\u305F\u3002\u30C7\u30FC\u30BF\u306E\u8CA9\u58F2\u304A\u3088\u3073\u5171\u6709\u304B\u3089\u30AA\u30D7\u30C8\u30A2\u30A6\u30C8\u3057\u307E\u3057\u305F\u3002",buttons:{"accept-all":"\u8A2D\u5B9A\u3092\u78BA\u8A8D","confirm-opt-out":"\u7D9A\u884C"}},preferenceModal:{heading:"\u30D7\u30E9\u30A4\u30D0\u30B7\u30FC\u8A2D\u5B9A",subheading:"\u30D7\u30E9\u30A4\u30D0\u30B7\u30FC\u30AA\u30D7\u30B7\u30E7\u30F3\u3092\u9078\u629E\u3057\u3066\u304F\u3060\u3055\u3044\u3002",buttons:{"accept-all":"\u3059\u3079\u3066\u540C\u610F","opt-out-all":"\u8CA9\u58F2\u30FB\u5171\u6709\u3057\u306A\u3044","save-choices":"\u9078\u629E\u3092\u4FDD\u5B58"},categories:{"cat-necessary":{heading:"\u5FC5\u9808",htmlText:"\u30A6\u30A7\u30D6\u30B5\u30A4\u30C8\u306E\u6A5F\u80FD\u306B\u4E0D\u53EF\u6B20\u3067\u3059\u3002"},"cat-functional":{heading:"\u6A5F\u80FD",htmlText:"\u9AD8\u5EA6\u306A\u6A5F\u80FD\u3068\u30D1\u30FC\u30BD\u30CA\u30E9\u30A4\u30BC\u30FC\u30B7\u30E7\u30F3\u3092\u6709\u52B9\u306B\u3057\u307E\u3059\u3002"},"cat-preferences":{heading:"\u8A2D\u5B9A",htmlText:"\u5C06\u6765\u306E\u8A2A\u554F\u306E\u305F\u3081\u306B\u8A2D\u5B9A\u3092\u4FDD\u5B58\u3057\u307E\u3059\u3002"},"cat-analytics":{heading:"\u5206\u6790",htmlText:"\u8A2A\u554F\u8005\u306E\u30B5\u30A4\u30C8\u5229\u7528\u72B6\u6CC1\u3092\u628A\u63E1\u3059\u308B\u306E\u306B\u5F79\u7ACB\u3061\u307E\u3059\u3002"},"cat-marketing":{heading:"\u5E83\u544A\u30FB\u8CA9\u58F2",htmlText:"\u30BF\u30FC\u30B2\u30C3\u30C8\u5E83\u544A\u3092\u53EF\u80FD\u306B\u3057\u307E\u3059\u3002\u30C7\u30FC\u30BF\u306E\u8CA9\u58F2\u306B\u7570\u8B70\u3092\u7533\u3057\u7ACB\u3066\u308B\u3053\u3068\u304C\u3067\u304D\u307E\u3059\u3002"}}}}});var vs,Cs=I(()=>{"use strict";p();vs={mainBanner:{heading:"Datenschutzrechte in Kalifornien",htmlText:"Gem\xE4\xDF dem California Privacy Rights Act (CPRA) haben Sie das Recht, dem Verkauf, der Weitergabe und der Verwendung Ihrer pers\xF6nlichen Daten zu widersprechen.",buttons:{"accept-all":"Alle akzeptieren","opt-out-sale-sharing-sensitive":"Meine Daten nicht verkaufen oder teilen",manage:"Einstellungen verwalten"}},gpcBanner:{heading:"GPC erkannt \u2013 CPRA-Opt-out angewendet",htmlText:"Ihr Global Privacy Control Signal wurde erkannt. Ihr Recht auf Opt-out gem\xE4\xDF CPRA wurde automatisch angewendet.",buttons:{"accept-all":"Einstellungen \xFCberpr\xFCfen","confirm-opt-out":"Weiter"}},preferenceModal:{heading:"Datenschutzeinstellungen (CPRA)",subheading:"Verwalten Sie Ihre Datenschutzrechte.",buttons:{"accept-all":"Alle akzeptieren","opt-out-sale-sharing-sensitive":"Meine Daten nicht verkaufen oder teilen","save-choices":"Auswahl speichern"},categories:{"cat-necessary":{heading:"Unbedingt erforderlich",htmlText:"F\xFCr den Betrieb der Website unbedingt erforderlich."},"cat-functional":{heading:"Funktional",htmlText:"Erm\xF6glichen erweiterte Funktionen."},"cat-preferences":{heading:"Pr\xE4ferenzen",htmlText:"Speichern Ihre pers\xF6nlichen Einstellungen."},"cat-analytics":{heading:"Analyse",htmlText:"Helfen uns, die Website-Nutzung zu verstehen."},"cat-marketing":{heading:"Verkauf / Weitergabe (CPRA)",htmlText:"Verkauf und Weitergabe pers\xF6nlicher Daten gem\xE4\xDF CPRA. Sie k\xF6nnen widersprechen."}}}}});var As,Ts=I(()=>{"use strict";p();As={mainBanner:{heading:"Derechos de privacidad en California",htmlText:"De acuerdo con la Ley de Derechos de Privacidad de California (CPRA), tiene derecho a oponerse a la venta, el intercambio y el uso de sus datos personales.",buttons:{"accept-all":"Aceptar todo","opt-out-sale-sharing-sensitive":"No vender ni compartir mis datos",manage:"Gestionar preferencias"}},gpcBanner:{heading:"GPC detectado \u2013 exclusi\xF3n CPRA aplicada",htmlText:"Se ha detectado su se\xF1al Global Privacy Control. Su derecho de exclusi\xF3n seg\xFAn la CPRA se ha aplicado autom\xE1ticamente.",buttons:{"accept-all":"Revisar preferencias","confirm-opt-out":"Continuar"}},preferenceModal:{heading:"Configuraci\xF3n de privacidad (CPRA)",subheading:"Administre sus derechos de privacidad.",buttons:{"accept-all":"Aceptar todo","opt-out-sale-sharing-sensitive":"No vender ni compartir mis datos","save-choices":"Guardar selecci\xF3n"},categories:{"cat-necessary":{heading:"Estrictamente necesarias",htmlText:"Imprescindibles para el funcionamiento del sitio."},"cat-functional":{heading:"Funcionales",htmlText:"Permiten funciones avanzadas."},"cat-preferences":{heading:"Preferencias",htmlText:"Guardan su configuraci\xF3n personal."},"cat-analytics":{heading:"Anal\xEDticas",htmlText:"Nos ayudan a entender el uso del sitio."},"cat-marketing":{heading:"Venta / Intercambio (CPRA)",htmlText:"Venta e intercambio de datos personales seg\xFAn la CPRA. Puede oponerse."}}}}});var Is,Ps=I(()=>{"use strict";p();Is={mainBanner:{heading:"Droits \xE0 la vie priv\xE9e en Californie",htmlText:"Conform\xE9ment au California Privacy Rights Act (CPRA), vous avez le droit de vous opposer \xE0 la vente, au partage et \xE0 l'utilisation de vos donn\xE9es personnelles.",buttons:{"accept-all":"Tout accepter","opt-out-sale-sharing-sensitive":"Ne pas vendre ni partager mes donn\xE9es",manage:"G\xE9rer les pr\xE9f\xE9rences"}},gpcBanner:{heading:"GPC d\xE9tect\xE9 \u2013 exclusion CPRA appliqu\xE9e",htmlText:"Votre signal Global Privacy Control a \xE9t\xE9 d\xE9tect\xE9. Votre droit d'exclusion selon la CPRA a \xE9t\xE9 appliqu\xE9 automatiquement.",buttons:{"accept-all":"V\xE9rifier les pr\xE9f\xE9rences","confirm-opt-out":"Continuer"}},preferenceModal:{heading:"Param\xE8tres de confidentialit\xE9 (CPRA)",subheading:"G\xE9rez vos droits \xE0 la vie priv\xE9e.",buttons:{"accept-all":"Tout accepter","opt-out-sale-sharing-sensitive":"Ne pas vendre ni partager mes donn\xE9es","save-choices":"Enregistrer la s\xE9lection"},categories:{"cat-necessary":{heading:"Strictement n\xE9cessaires",htmlText:"Indispensables au fonctionnement du site."},"cat-functional":{heading:"Fonctionnels",htmlText:"Permettent des fonctionnalit\xE9s avanc\xE9es."},"cat-preferences":{heading:"Pr\xE9f\xE9rences",htmlText:"Sauvegardent vos param\xE8tres personnels."},"cat-analytics":{heading:"Analytiques",htmlText:"Nous aident \xE0 comprendre l'utilisation du site."},"cat-marketing":{heading:"Vente / Partage (CPRA)",htmlText:"Vente et partage de donn\xE9es personnelles selon la CPRA. Vous pouvez vous y opposer."}}}}});var bs,Os=I(()=>{"use strict";p();bs={mainBanner:{heading:"\u30AB\u30EA\u30D5\u30A9\u30EB\u30CB\u30A2\u5DDE\u306E\u30D7\u30E9\u30A4\u30D0\u30B7\u30FC\u6A29",htmlText:"\u30AB\u30EA\u30D5\u30A9\u30EB\u30CB\u30A2\u30FB\u30D7\u30E9\u30A4\u30D0\u30B7\u30FC\u6A29\u6CD5\uFF08CPRA\uFF09\u306B\u57FA\u3065\u304D\u3001\u304A\u5BA2\u69D8\u306B\u306F\u500B\u4EBA\u30C7\u30FC\u30BF\u306E\u8CA9\u58F2\u30FB\u5171\u6709\u30FB\u5229\u7528\u306B\u7570\u8B70\u3092\u7533\u3057\u7ACB\u3066\u308B\u6A29\u5229\u304C\u3042\u308A\u307E\u3059\u3002",buttons:{"accept-all":"\u3059\u3079\u3066\u540C\u610F","opt-out-sale-sharing-sensitive":"\u8CA9\u58F2\u30FB\u5171\u6709\u3057\u306A\u3044",manage:"\u8A2D\u5B9A\u3092\u7BA1\u7406"}},gpcBanner:{heading:"GPC\u691C\u51FA \u2013 CPRA\u30AA\u30D7\u30C8\u30A2\u30A6\u30C8\u9069\u7528\u6E08\u307F",htmlText:"\u30D6\u30E9\u30A6\u30B6\u304B\u3089Global Privacy Control\u30B7\u30B0\u30CA\u30EB\u304C\u691C\u51FA\u3055\u308C\u307E\u3057\u305F\u3002CPRA\u306B\u57FA\u3065\u304F\u30AA\u30D7\u30C8\u30A2\u30A6\u30C8\u6A29\u304C\u81EA\u52D5\u7684\u306B\u9069\u7528\u3055\u308C\u307E\u3057\u305F\u3002",buttons:{"accept-all":"\u8A2D\u5B9A\u3092\u78BA\u8A8D","confirm-opt-out":"\u7D9A\u884C"}},preferenceModal:{heading:"\u30D7\u30E9\u30A4\u30D0\u30B7\u30FC\u8A2D\u5B9A\uFF08CPRA\uFF09",subheading:"\u30D7\u30E9\u30A4\u30D0\u30B7\u30FC\u6A29\u3092\u7BA1\u7406\u3057\u3066\u304F\u3060\u3055\u3044\u3002",buttons:{"accept-all":"\u3059\u3079\u3066\u540C\u610F","opt-out-sale-sharing-sensitive":"\u8CA9\u58F2\u30FB\u5171\u6709\u3057\u306A\u3044","save-choices":"\u9078\u629E\u3092\u4FDD\u5B58"},categories:{"cat-necessary":{heading:"\u5FC5\u9808",htmlText:"\u30A6\u30A7\u30D6\u30B5\u30A4\u30C8\u306E\u52D5\u4F5C\u306B\u4E0D\u53EF\u6B20\u3067\u3059\u3002"},"cat-functional":{heading:"\u6A5F\u80FD",htmlText:"\u9AD8\u5EA6\u306A\u6A5F\u80FD\u3092\u6709\u52B9\u306B\u3057\u307E\u3059\u3002"},"cat-preferences":{heading:"\u8A2D\u5B9A",htmlText:"\u500B\u4EBA\u8A2D\u5B9A\u3092\u4FDD\u5B58\u3057\u307E\u3059\u3002"},"cat-analytics":{heading:"\u5206\u6790",htmlText:"\u30B5\u30A4\u30C8\u5229\u7528\u72B6\u6CC1\u306E\u628A\u63E1\u306B\u5F79\u7ACB\u3066\u307E\u3059\u3002"},"cat-marketing":{heading:"\u8CA9\u58F2\u30FB\u5171\u6709\uFF08CPRA\uFF09",htmlText:"CPRA\u306B\u57FA\u3065\u304F\u500B\u4EBA\u30C7\u30FC\u30BF\u306E\u8CA9\u58F2\u304A\u3088\u3073\u5171\u6709\u3002\u7570\u8B70\u3092\u7533\u3057\u7ACB\u3066\u308B\u3053\u3068\u304C\u3067\u304D\u307E\u3059\u3002"}}}}});var Ds,ks=I(()=>{"use strict";p();Ds={mainBanner:{heading:"Datenschutzhinweis",htmlText:"Wir sind der f\xFCr die Datenverarbeitung Verantwortliche gem\xE4\xDF dem Digitalen Personaldatenschutzgesetz (DPDPA) Indiens. Ihre Einwilligung ist erforderlich, bevor wir Ihre personenbezogenen Daten verarbeiten.",buttons:{"consent-all":"Ich stimme zu","deny-all":"Ich stimme nicht zu","review-choices":"Auswahl \xFCberpr\xFCfen"}},preferenceModal:{heading:"Datenschutzeinstellungen (DPDPA)",subheading:"Bitte w\xE4hlen Sie aus, in welche Verarbeitungen Sie einwilligen.",buttons:{"consent-all":"Ich stimme zu","withdraw-all":"Ich stimme nicht zu","save-choices":"Auswahl speichern"},categories:{"cat-necessary":{heading:"Unbedingt erforderlich",htmlText:"F\xFCr den Betrieb der Website unbedingt erforderlich. Keine Einwilligung erforderlich."},"cat-functional":{heading:"Funktional",htmlText:"Erm\xF6glichen erweiterte Funktionen. Ihre Einwilligung ist gem\xE4\xDF DPDPA erforderlich."},"cat-preferences":{heading:"Pr\xE4ferenzen",htmlText:"Speichern Ihre pers\xF6nlichen Einstellungen. Einwilligung gem\xE4\xDF DPDPA erforderlich."},"cat-analytics":{heading:"Analyse",htmlText:"Helfen uns, die Website-Nutzung zu verstehen. Einwilligung gem\xE4\xDF DPDPA erforderlich."},"cat-marketing":{heading:"Marketing",htmlText:"Erm\xF6glichen personalisierte Werbung. Einwilligung gem\xE4\xDF DPDPA erforderlich."}}}}});var Ls,Ns=I(()=>{"use strict";p();Ls={mainBanner:{heading:"Aviso de protecci\xF3n de datos",htmlText:"Somos el Fiduciario de Datos seg\xFAn la Ley de Protecci\xF3n de Datos Digitales Personales (DPDPA) de India. Su consentimiento es necesario antes de que procesemos sus datos personales.",buttons:{"consent-all":"Doy mi consentimiento","deny-all":"No doy mi consentimiento","review-choices":"Revisar opciones"}},preferenceModal:{heading:"Configuraci\xF3n de privacidad (DPDPA)",subheading:"Elija en qu\xE9 procesamientos desea dar su consentimiento.",buttons:{"consent-all":"Doy mi consentimiento","withdraw-all":"No doy mi consentimiento","save-choices":"Guardar selecci\xF3n"},categories:{"cat-necessary":{heading:"Estrictamente necesarias",htmlText:"Imprescindibles para el funcionamiento del sitio. No requieren consentimiento."},"cat-functional":{heading:"Funcionales",htmlText:"Permiten funciones avanzadas. Su consentimiento es requerido seg\xFAn la DPDPA."},"cat-preferences":{heading:"Preferencias",htmlText:"Guardan su configuraci\xF3n personal. Se requiere consentimiento seg\xFAn la DPDPA."},"cat-analytics":{heading:"Anal\xEDticas",htmlText:"Nos ayudan a entender el uso del sitio. Se requiere consentimiento seg\xFAn la DPDPA."},"cat-marketing":{heading:"Marketing",htmlText:"Permiten publicidad personalizada. Se requiere consentimiento seg\xFAn la DPDPA."}}}}});var xs,Us=I(()=>{"use strict";p();xs={mainBanner:{heading:"Avis de protection des donn\xE9es",htmlText:"Nous sommes le Fiduciaire de donn\xE9es au sens de la loi indienne sur la protection des donn\xE9es personnelles num\xE9riques (DPDPA). Votre consentement est requis avant que nous traitions vos donn\xE9es personnelles.",buttons:{"consent-all":"Je consens","deny-all":"Je ne consens pas","review-choices":"Examiner les choix"}},preferenceModal:{heading:"Param\xE8tres de confidentialit\xE9 (DPDPA)",subheading:"Choisissez les traitements auxquels vous consentez.",buttons:{"consent-all":"Je consens","withdraw-all":"Je ne consens pas","save-choices":"Enregistrer la s\xE9lection"},categories:{"cat-necessary":{heading:"Strictement n\xE9cessaires",htmlText:"Indispensables au fonctionnement du site. Aucun consentement requis."},"cat-functional":{heading:"Fonctionnels",htmlText:"Permettent des fonctionnalit\xE9s avanc\xE9es. Votre consentement est requis selon la DPDPA."},"cat-preferences":{heading:"Pr\xE9f\xE9rences",htmlText:"Sauvegardent vos param\xE8tres personnels. Consentement requis selon la DPDPA."},"cat-analytics":{heading:"Analytiques",htmlText:"Nous aident \xE0 comprendre l'utilisation du site. Consentement requis selon la DPDPA."},"cat-marketing":{heading:"Marketing",htmlText:"Permettent la publicit\xE9 personnalis\xE9e. Consentement requis selon la DPDPA."}}}}});var Ms,Gs=I(()=>{"use strict";p();Ms={mainBanner:{heading:"\u30C7\u30FC\u30BF\u4FDD\u8B77\u306B\u95A2\u3059\u308B\u304A\u77E5\u3089\u305B",htmlText:"\u5F53\u793E\u306F\u30A4\u30F3\u30C9\u306E\u30C7\u30B8\u30BF\u30EB\u500B\u4EBA\u30C7\u30FC\u30BF\u4FDD\u8B77\u6CD5\uFF08DPDPA\uFF09\u306B\u57FA\u3065\u304F\u30C7\u30FC\u30BF\u53D7\u8A17\u8005\u3067\u3059\u3002\u304A\u5BA2\u69D8\u306E\u500B\u4EBA\u30C7\u30FC\u30BF\u3092\u51E6\u7406\u3059\u308B\u524D\u306B\u540C\u610F\u304C\u5FC5\u8981\u3067\u3059\u3002",buttons:{"consent-all":"\u540C\u610F\u3059\u308B","deny-all":"\u540C\u610F\u3057\u306A\u3044","review-choices":"\u9078\u629E\u3092\u78BA\u8A8D"}},preferenceModal:{heading:"\u30D7\u30E9\u30A4\u30D0\u30B7\u30FC\u8A2D\u5B9A\uFF08DPDPA\uFF09",subheading:"\u540C\u610F\u3059\u308B\u51E6\u7406\u3092\u9078\u629E\u3057\u3066\u304F\u3060\u3055\u3044\u3002",buttons:{"consent-all":"\u540C\u610F\u3059\u308B","withdraw-all":"\u540C\u610F\u3057\u306A\u3044","save-choices":"\u9078\u629E\u3092\u4FDD\u5B58"},categories:{"cat-necessary":{heading:"\u5FC5\u9808",htmlText:"\u30A6\u30A7\u30D6\u30B5\u30A4\u30C8\u306E\u52D5\u4F5C\u306B\u4E0D\u53EF\u6B20\u3067\u3059\u3002\u540C\u610F\u306F\u4E0D\u8981\u3067\u3059\u3002"},"cat-functional":{heading:"\u6A5F\u80FD",htmlText:"\u9AD8\u5EA6\u306A\u6A5F\u80FD\u3092\u6709\u52B9\u306B\u3057\u307E\u3059\u3002DPDPA\u306B\u57FA\u3065\u304D\u540C\u610F\u304C\u5FC5\u8981\u3067\u3059\u3002"},"cat-preferences":{heading:"\u8A2D\u5B9A",htmlText:"\u500B\u4EBA\u8A2D\u5B9A\u3092\u4FDD\u5B58\u3057\u307E\u3059\u3002DPDPA\u306B\u57FA\u3065\u304D\u540C\u610F\u304C\u5FC5\u8981\u3067\u3059\u3002"},"cat-analytics":{heading:"\u5206\u6790",htmlText:"\u30B5\u30A4\u30C8\u5229\u7528\u72B6\u6CC1\u306E\u628A\u63E1\u306B\u4F7F\u7528\u3057\u307E\u3059\u3002DPDPA\u306B\u57FA\u3065\u304D\u540C\u610F\u304C\u5FC5\u8981\u3067\u3059\u3002"},"cat-marketing":{heading:"\u30DE\u30FC\u30B1\u30C6\u30A3\u30F3\u30B0",htmlText:"\u30D1\u30FC\u30BD\u30CA\u30E9\u30A4\u30BA\u3055\u308C\u305F\u5E83\u544A\u3092\u53EF\u80FD\u306B\u3057\u307E\u3059\u3002DPDPA\u306B\u57FA\u3065\u304D\u540C\u610F\u304C\u5FC5\u8981\u3067\u3059\u3002"}}}}});var js,Bs=I(()=>{"use strict";p();js={mainBanner:{heading:"Hinweis zur Verarbeitung personenbezogener Daten",htmlText:"Gem\xE4\xDF dem Gesetz zum Schutz personenbezogener Daten (PIPL) m\xFCssen wir Sie vor der Verarbeitung Ihrer Daten informieren. Wir verarbeiten Daten nur zu den angegebenen Zwecken auf Grundlage Ihrer Einwilligung.",buttons:{"agree-all":"Zustimmen","reject-non-necessary":"Ablehnen","manage-preferences":"Einstellungen"}},preferenceModal:{heading:"Datenschutzeinstellungen (PIPL)",subheading:"Bitte w\xE4hlen Sie, welcher Datenverarbeitung Sie zustimmen.",buttons:{"agree-all":"Zustimmen","disagree-all":"Ablehnen","confirm-settings":"Auswahl speichern"},categories:{"cat-necessary":{heading:"Unbedingt erforderlich",htmlText:"F\xFCr den Betrieb der Website unbedingt erforderlich. Zweck: Sicherheit und grundlegende Funktionalit\xE4t."},"cat-functional":{heading:"Funktional",htmlText:"Zweck: Verbesserung der Benutzererfahrung. Einwilligung gem\xE4\xDF PIPL erforderlich."},"cat-preferences":{heading:"Pr\xE4ferenzen",htmlText:"Zweck: Speicherung personalisierter Einstellungen. Einwilligung gem\xE4\xDF PIPL erforderlich."},"cat-analytics":{heading:"Analyse",htmlText:"Zweck: Statistiken zur Website-Nutzung. Einwilligung gem\xE4\xDF PIPL erforderlich."},"cat-marketing":{heading:"Marketing",htmlText:"Zweck: Personalisierte Werbung. Einwilligung gem\xE4\xDF PIPL erforderlich."}}}}});var $s,Fs=I(()=>{"use strict";p();$s={mainBanner:{heading:"Aviso de tratamiento de informaci\xF3n personal",htmlText:"De conformidad con la Ley de Protecci\xF3n de Informaci\xF3n Personal (PIPL), debemos informarle antes de tratar sus datos. Solo procesamos datos con fines espec\xEDficos y con su consentimiento.",buttons:{"agree-all":"Aceptar","reject-non-necessary":"Rechazar","manage-preferences":"Configuraci\xF3n"}},preferenceModal:{heading:"Configuraci\xF3n de privacidad (PIPL)",subheading:"Elija qu\xE9 tratamientos de datos acepta.",buttons:{"agree-all":"Aceptar","disagree-all":"Rechazar","confirm-settings":"Guardar selecci\xF3n"},categories:{"cat-necessary":{heading:"Estrictamente necesarias",htmlText:"Imprescindibles para el sitio. Finalidad: seguridad y funcionalidad b\xE1sica."},"cat-functional":{heading:"Funcionales",htmlText:"Finalidad: mejorar la experiencia del usuario. Se requiere consentimiento seg\xFAn la PIPL."},"cat-preferences":{heading:"Preferencias",htmlText:"Finalidad: guardar configuraci\xF3n personalizada. Se requiere consentimiento seg\xFAn la PIPL."},"cat-analytics":{heading:"Anal\xEDticas",htmlText:"Finalidad: estad\xEDsticas de uso del sitio. Se requiere consentimiento seg\xFAn la PIPL."},"cat-marketing":{heading:"Marketing",htmlText:"Finalidad: publicidad personalizada. Se requiere consentimiento seg\xFAn la PIPL."}}}}});var Hs,Vs=I(()=>{"use strict";p();Hs={mainBanner:{heading:"Avis de traitement des informations personnelles",htmlText:"Conform\xE9ment \xE0 la loi sur la protection des informations personnelles (PIPL), nous devons vous informer avant tout traitement. Nous traitons les donn\xE9es \xE0 des fins sp\xE9cifiques uniquement, avec votre consentement.",buttons:{"agree-all":"Accepter","reject-non-necessary":"Refuser","manage-preferences":"Param\xE8tres"}},preferenceModal:{heading:"Param\xE8tres de confidentialit\xE9 (PIPL)",subheading:"Choisissez les traitements de donn\xE9es que vous acceptez.",buttons:{"agree-all":"Accepter","disagree-all":"Refuser","confirm-settings":"Enregistrer la s\xE9lection"},categories:{"cat-necessary":{heading:"Strictement n\xE9cessaires",htmlText:"Indispensables au site. Finalit\xE9 : s\xE9curit\xE9 et fonctionnalit\xE9 de base."},"cat-functional":{heading:"Fonctionnels",htmlText:"Finalit\xE9 : am\xE9liorer l'exp\xE9rience utilisateur. Consentement requis selon la PIPL."},"cat-preferences":{heading:"Pr\xE9f\xE9rences",htmlText:"Finalit\xE9 : sauvegarder les param\xE8tres personnalis\xE9s. Consentement requis selon la PIPL."},"cat-analytics":{heading:"Analytiques",htmlText:"Finalit\xE9 : statistiques d'utilisation du site. Consentement requis selon la PIPL."},"cat-marketing":{heading:"Marketing",htmlText:"Finalit\xE9 : publicit\xE9 personnalis\xE9e. Consentement requis selon la PIPL."}}}}});var Ws,qs=I(()=>{"use strict";p();Ws={mainBanner:{heading:"\u500B\u4EBA\u60C5\u5831\u51E6\u7406\u306B\u95A2\u3059\u308B\u304A\u77E5\u3089\u305B",htmlText:"\u500B\u4EBA\u60C5\u5831\u4FDD\u8B77\u6CD5\uFF08PIPL\uFF09\u306B\u57FA\u3065\u304D\u3001\u30C7\u30FC\u30BF\u51E6\u7406\u306E\u524D\u306B\u304A\u77E5\u3089\u305B\u3059\u308B\u7FA9\u52D9\u304C\u3042\u308A\u307E\u3059\u3002\u304A\u5BA2\u69D8\u306E\u540C\u610F\u3092\u5F97\u305F\u7279\u5B9A\u306E\u76EE\u7684\u306B\u306E\u307F\u30C7\u30FC\u30BF\u3092\u4F7F\u7528\u3057\u307E\u3059\u3002",buttons:{"agree-all":"\u540C\u610F\u3059\u308B","reject-non-necessary":"\u62D2\u5426\u3059\u308B","manage-preferences":"\u8A2D\u5B9A"}},preferenceModal:{heading:"\u30D7\u30E9\u30A4\u30D0\u30B7\u30FC\u8A2D\u5B9A\uFF08PIPL\uFF09",subheading:"\u540C\u610F\u3059\u308B\u30C7\u30FC\u30BF\u51E6\u7406\u3092\u9078\u629E\u3057\u3066\u304F\u3060\u3055\u3044\u3002",buttons:{"agree-all":"\u540C\u610F\u3059\u308B","disagree-all":"\u62D2\u5426\u3059\u308B","confirm-settings":"\u9078\u629E\u3092\u4FDD\u5B58"},categories:{"cat-necessary":{heading:"\u5FC5\u9808",htmlText:"\u30A6\u30A7\u30D6\u30B5\u30A4\u30C8\u306B\u4E0D\u53EF\u6B20\u3067\u3059\u3002\u76EE\u7684\uFF1A\u30BB\u30AD\u30E5\u30EA\u30C6\u30A3\u3068\u57FA\u672C\u6A5F\u80FD\u3002"},"cat-functional":{heading:"\u6A5F\u80FD",htmlText:"\u76EE\u7684\uFF1A\u30E6\u30FC\u30B6\u30FC\u4F53\u9A13\u306E\u5411\u4E0A\u3002PIPL\u306B\u57FA\u3065\u304D\u540C\u610F\u304C\u5FC5\u8981\u3067\u3059\u3002"},"cat-preferences":{heading:"\u8A2D\u5B9A",htmlText:"\u76EE\u7684\uFF1A\u500B\u4EBA\u8A2D\u5B9A\u306E\u4FDD\u5B58\u3002PIPL\u306B\u57FA\u3065\u304D\u540C\u610F\u304C\u5FC5\u8981\u3067\u3059\u3002"},"cat-analytics":{heading:"\u5206\u6790",htmlText:"\u76EE\u7684\uFF1A\u30B5\u30A4\u30C8\u5229\u7528\u7D71\u8A08\u3002PIPL\u306B\u57FA\u3065\u304D\u540C\u610F\u304C\u5FC5\u8981\u3067\u3059\u3002"},"cat-marketing":{heading:"\u30DE\u30FC\u30B1\u30C6\u30A3\u30F3\u30B0",htmlText:"\u76EE\u7684\uFF1A\u30D1\u30FC\u30BD\u30CA\u30E9\u30A4\u30BA\u3055\u308C\u305F\u5E83\u544A\u3002PIPL\u306B\u57FA\u3065\u304D\u540C\u610F\u304C\u5FC5\u8981\u3067\u3059\u3002"}}}}});var Js,zs=I(()=>{"use strict";p();Js={mainBanner:{heading:"Wir sch\xE4tzen Ihre Privatsph\xE4re",htmlText:"Gem\xE4\xDF dem brasilianischen Datenschutzgesetz (LGPD) verarbeiten wir Ihre personenbezogenen Daten auf Grundlage Ihrer Einwilligung oder unseres berechtigten Interesses, sofern anwendbar. Sie k\xF6nnen Ihre Wahl jederzeit \xE4ndern.",buttons:{"accept-all":"Alle akzeptieren","reject-optional":"Alle ablehnen",manage:"Verwalten"}},preferenceModal:{heading:"Datenschutzeinstellungen (LGPD)",subheading:"W\xE4hlen Sie Ihre Datenschutzoptionen.",buttons:{"accept-all":"Alle akzeptieren","reject-optional":"Alle ablehnen","save-preferences":"Auswahl speichern"},categories:{"cat-necessary":{heading:"Unbedingt erforderlich",htmlText:"F\xFCr den Betrieb der Website unbedingt erforderlich."},"cat-functional":{heading:"Funktional",htmlText:"Erm\xF6glichen erweiterte Funktionen. Rechtsgrundlage: berechtigtes Interesse (LGPD Art. 10)."},"cat-preferences":{heading:"Pr\xE4ferenzen",htmlText:"Speichern Ihre Einstellungen. Rechtsgrundlage: berechtigtes Interesse (LGPD Art. 10)."},"cat-analytics":{heading:"Analyse",htmlText:"Helfen uns, die Website-Nutzung zu verstehen. Einwilligung gem\xE4\xDF LGPD erforderlich."},"cat-marketing":{heading:"Marketing",htmlText:"Erm\xF6glichen personalisierte Werbung. Einwilligung gem\xE4\xDF LGPD erforderlich."}}}}});var Ks,Ys=I(()=>{"use strict";p();Ks={mainBanner:{heading:"Valoramos su privacidad",htmlText:"De acuerdo con la Ley General de Protecci\xF3n de Datos (LGPD) de Brasil, tratamos sus datos personales con su consentimiento o con base en inter\xE9s leg\xEDtimo cuando corresponda. Puede cambiar sus preferencias en cualquier momento.",buttons:{"accept-all":"Aceptar todo","reject-optional":"Rechazar todo",manage:"Gestionar"}},preferenceModal:{heading:"Configuraci\xF3n de privacidad (LGPD)",subheading:"Elija sus opciones de privacidad.",buttons:{"accept-all":"Aceptar todo","reject-optional":"Rechazar todo","save-preferences":"Guardar selecci\xF3n"},categories:{"cat-necessary":{heading:"Estrictamente necesarias",htmlText:"Imprescindibles para el funcionamiento del sitio."},"cat-functional":{heading:"Funcionales",htmlText:"Permiten funciones avanzadas. Base legal: inter\xE9s leg\xEDtimo (LGPD Art. 10)."},"cat-preferences":{heading:"Preferencias",htmlText:"Guardan su configuraci\xF3n. Base legal: inter\xE9s leg\xEDtimo (LGPD Art. 10)."},"cat-analytics":{heading:"Anal\xEDticas",htmlText:"Nos ayudan a comprender el uso del sitio. Se requiere consentimiento seg\xFAn la LGPD."},"cat-marketing":{heading:"Marketing",htmlText:"Permiten publicidad personalizada. Se requiere consentimiento seg\xFAn la LGPD."}}}}});var Qs,Zs=I(()=>{"use strict";p();Qs={mainBanner:{heading:"Nous respectons votre vie priv\xE9e",htmlText:"Conform\xE9ment \xE0 la loi br\xE9silienne sur la protection des donn\xE9es (LGPD), nous traitons vos donn\xE9es personnelles sur la base de votre consentement ou d'un int\xE9r\xEAt l\xE9gitime, selon le cas. Vous pouvez modifier vos pr\xE9f\xE9rences \xE0 tout moment.",buttons:{"accept-all":"Tout accepter","reject-optional":"Tout refuser",manage:"G\xE9rer"}},preferenceModal:{heading:"Param\xE8tres de confidentialit\xE9 (LGPD)",subheading:"Choisissez vos options de confidentialit\xE9.",buttons:{"accept-all":"Tout accepter","reject-optional":"Tout refuser","save-preferences":"Enregistrer la s\xE9lection"},categories:{"cat-necessary":{heading:"Strictement n\xE9cessaires",htmlText:"Indispensables au fonctionnement du site."},"cat-functional":{heading:"Fonctionnels",htmlText:"Permettent des fonctionnalit\xE9s avanc\xE9es. Base l\xE9gale : int\xE9r\xEAt l\xE9gitime (LGPD Art. 10)."},"cat-preferences":{heading:"Pr\xE9f\xE9rences",htmlText:"Sauvegardent vos param\xE8tres. Base l\xE9gale : int\xE9r\xEAt l\xE9gitime (LGPD Art. 10)."},"cat-analytics":{heading:"Analytiques",htmlText:"Nous aident \xE0 comprendre l'utilisation du site. Consentement requis selon la LGPD."},"cat-marketing":{heading:"Marketing",htmlText:"Permettent la publicit\xE9 personnalis\xE9e. Consentement requis selon la LGPD."}}}}});var Xs,er=I(()=>{"use strict";p();Xs={mainBanner:{heading:"\u30D7\u30E9\u30A4\u30D0\u30B7\u30FC\u3092\u5927\u5207\u306B\u3057\u3066\u3044\u307E\u3059",htmlText:"\u30D6\u30E9\u30B8\u30EB\u306E\u4E00\u822C\u30C7\u30FC\u30BF\u4FDD\u8B77\u6CD5\uFF08LGPD\uFF09\u306B\u57FA\u3065\u304D\u3001\u304A\u5BA2\u69D8\u306E\u540C\u610F\u307E\u305F\u306F\u6B63\u5F53\u306A\u5229\u76CA\u3092\u6839\u62E0\u3068\u3057\u3066\u500B\u4EBA\u30C7\u30FC\u30BF\u3092\u51E6\u7406\u3057\u307E\u3059\u3002\u8A2D\u5B9A\u306F\u3044\u3064\u3067\u3082\u5909\u66F4\u3067\u304D\u307E\u3059\u3002",buttons:{"accept-all":"\u3059\u3079\u3066\u540C\u610F","reject-optional":"\u3059\u3079\u3066\u62D2\u5426",manage:"\u7BA1\u7406\u3059\u308B"}},preferenceModal:{heading:"\u30D7\u30E9\u30A4\u30D0\u30B7\u30FC\u8A2D\u5B9A\uFF08LGPD\uFF09",subheading:"\u30D7\u30E9\u30A4\u30D0\u30B7\u30FC\u30AA\u30D7\u30B7\u30E7\u30F3\u3092\u9078\u629E\u3057\u3066\u304F\u3060\u3055\u3044\u3002",buttons:{"accept-all":"\u3059\u3079\u3066\u540C\u610F","reject-optional":"\u3059\u3079\u3066\u62D2\u5426","save-preferences":"\u9078\u629E\u3092\u4FDD\u5B58"},categories:{"cat-necessary":{heading:"\u5FC5\u9808",htmlText:"\u30A6\u30A7\u30D6\u30B5\u30A4\u30C8\u306E\u52D5\u4F5C\u306B\u4E0D\u53EF\u6B20\u3067\u3059\u3002"},"cat-functional":{heading:"\u6A5F\u80FD",htmlText:"\u9AD8\u5EA6\u306A\u6A5F\u80FD\u3092\u6709\u52B9\u306B\u3057\u307E\u3059\u3002\u6CD5\u7684\u6839\u62E0\uFF1A\u6B63\u5F53\u306A\u5229\u76CA\uFF08LGPD\u7B2C10\u6761\uFF09\u3002"},"cat-preferences":{heading:"\u8A2D\u5B9A",htmlText:"\u8A2D\u5B9A\u3092\u4FDD\u5B58\u3057\u307E\u3059\u3002\u6CD5\u7684\u6839\u62E0\uFF1A\u6B63\u5F53\u306A\u5229\u76CA\uFF08LGPD\u7B2C10\u6761\uFF09\u3002"},"cat-analytics":{heading:"\u5206\u6790",htmlText:"\u30B5\u30A4\u30C8\u5229\u7528\u72B6\u6CC1\u306E\u628A\u63E1\u306B\u5F79\u7ACB\u3066\u307E\u3059\u3002LGPD\u306B\u57FA\u3065\u304D\u540C\u610F\u304C\u5FC5\u8981\u3067\u3059\u3002"},"cat-marketing":{heading:"\u30DE\u30FC\u30B1\u30C6\u30A3\u30F3\u30B0",htmlText:"\u30D1\u30FC\u30BD\u30CA\u30E9\u30A4\u30BA\u3055\u308C\u305F\u5E83\u544A\u3092\u53EF\u80FD\u306B\u3057\u307E\u3059\u3002LGPD\u306B\u57FA\u3065\u304D\u540C\u610F\u304C\u5FC5\u8981\u3067\u3059\u3002"}}}}});var tr,nr=I(()=>{"use strict";p();tr={mainBanner:{heading:"Wir verwenden Cookies",htmlText:"Wir verwenden Cookies und \xE4hnliche Technologien, um unsere Dienste bereitzustellen und zu verbessern. F\xFCr Marketing-Cookies ist Ihre Einwilligung erforderlich. Andere Cookies basieren auf unserem berechtigten Interesse.",buttons:{"accept-all":"Alle akzeptieren","reject-marketing":"Marketing ablehnen","manage-preferences":"Einstellungen verwalten"}},preferenceModal:{heading:"Datenschutzeinstellungen",subheading:"W\xE4hlen Sie Ihre Cookie-Pr\xE4ferenzen.",buttons:{"accept-all":"Alle akzeptieren","necessary-only":"Marketing ablehnen","save-preferences":"Auswahl speichern"},categories:{"cat-necessary":{heading:"Unbedingt erforderlich",htmlText:"F\xFCr den Betrieb der Website unbedingt erforderlich."},"cat-functional":{heading:"Funktional",htmlText:"Erm\xF6glichen erweiterte Funktionen. Rechtsgrundlage: berechtigtes Interesse."},"cat-preferences":{heading:"Pr\xE4ferenzen",htmlText:"Speichern Ihre pers\xF6nlichen Einstellungen. Rechtsgrundlage: berechtigtes Interesse."},"cat-analytics":{heading:"Analyse",htmlText:"Helfen uns, die Website-Nutzung zu verstehen. Rechtsgrundlage: berechtigtes Interesse."},"cat-marketing":{heading:"Marketing",htmlText:"Erm\xF6glichen personalisierte Werbung. Ihre Einwilligung ist erforderlich."}}}}});var ir,or=I(()=>{"use strict";p();ir={mainBanner:{heading:"Usamos cookies",htmlText:"Utilizamos cookies y tecnolog\xEDas similares para ofrecer y mejorar nuestros servicios. Las cookies de marketing requieren su consentimiento. Las dem\xE1s se basan en inter\xE9s leg\xEDtimo.",buttons:{"accept-all":"Aceptar todo","reject-marketing":"Rechazar marketing","manage-preferences":"Gestionar preferencias"}},preferenceModal:{heading:"Configuraci\xF3n de privacidad",subheading:"Elija sus preferencias de cookies.",buttons:{"accept-all":"Aceptar todo","necessary-only":"Rechazar marketing","save-preferences":"Guardar selecci\xF3n"},categories:{"cat-necessary":{heading:"Estrictamente necesarias",htmlText:"Imprescindibles para el funcionamiento del sitio."},"cat-functional":{heading:"Funcionales",htmlText:"Permiten funciones avanzadas. Base legal: inter\xE9s leg\xEDtimo."},"cat-preferences":{heading:"Preferencias",htmlText:"Guardan su configuraci\xF3n personal. Base legal: inter\xE9s leg\xEDtimo."},"cat-analytics":{heading:"Anal\xEDticas",htmlText:"Nos ayudan a entender el uso del sitio. Base legal: inter\xE9s leg\xEDtimo."},"cat-marketing":{heading:"Marketing",htmlText:"Permiten publicidad personalizada. Se requiere su consentimiento."}}}}});var sr,rr=I(()=>{"use strict";p();sr={mainBanner:{heading:"Nous utilisons des cookies",htmlText:"Nous utilisons des cookies et des technologies similaires pour fournir et am\xE9liorer nos services. Les cookies marketing n\xE9cessitent votre consentement. Les autres reposent sur notre int\xE9r\xEAt l\xE9gitime.",buttons:{"accept-all":"Tout accepter","reject-marketing":"Refuser le marketing","manage-preferences":"G\xE9rer les pr\xE9f\xE9rences"}},preferenceModal:{heading:"Param\xE8tres de confidentialit\xE9",subheading:"Choisissez vos pr\xE9f\xE9rences en mati\xE8re de cookies.",buttons:{"accept-all":"Tout accepter","necessary-only":"Refuser le marketing","save-preferences":"Enregistrer la s\xE9lection"},categories:{"cat-necessary":{heading:"Strictement n\xE9cessaires",htmlText:"Indispensables au fonctionnement du site."},"cat-functional":{heading:"Fonctionnels",htmlText:"Permettent des fonctionnalit\xE9s avanc\xE9es. Base l\xE9gale : int\xE9r\xEAt l\xE9gitime."},"cat-preferences":{heading:"Pr\xE9f\xE9rences",htmlText:"Sauvegardent vos param\xE8tres personnels. Base l\xE9gale : int\xE9r\xEAt l\xE9gitime."},"cat-analytics":{heading:"Analytiques",htmlText:"Nous aident \xE0 comprendre l'utilisation du site. Base l\xE9gale : int\xE9r\xEAt l\xE9gitime."},"cat-marketing":{heading:"Marketing",htmlText:"Permettent la publicit\xE9 personnalis\xE9e. Votre consentement est requis."}}}}});var ar,cr=I(()=>{"use strict";p();ar={mainBanner:{heading:"Cookie\u3092\u4F7F\u7528\u3057\u3066\u3044\u307E\u3059",htmlText:"\u30B5\u30FC\u30D3\u30B9\u306E\u63D0\u4F9B\u30FB\u6539\u5584\u306E\u305F\u3081\u306BCookie\u304A\u3088\u3073\u985E\u4F3C\u6280\u8853\u3092\u4F7F\u7528\u3057\u3066\u3044\u307E\u3059\u3002\u30DE\u30FC\u30B1\u30C6\u30A3\u30F3\u30B0Cookie\u306B\u306F\u304A\u5BA2\u69D8\u306E\u540C\u610F\u304C\u5FC5\u8981\u3067\u3059\u3002\u305D\u306E\u4ED6\u306F\u6B63\u5F53\u306A\u5229\u76CA\u3092\u6839\u62E0\u3068\u3057\u3066\u3044\u307E\u3059\u3002",buttons:{"accept-all":"\u3059\u3079\u3066\u540C\u610F","reject-marketing":"\u30DE\u30FC\u30B1\u30C6\u30A3\u30F3\u30B0\u3092\u62D2\u5426","manage-preferences":"\u8A2D\u5B9A\u3092\u7BA1\u7406"}},preferenceModal:{heading:"\u30D7\u30E9\u30A4\u30D0\u30B7\u30FC\u8A2D\u5B9A",subheading:"Cookie\u306E\u8A2D\u5B9A\u3092\u9078\u629E\u3057\u3066\u304F\u3060\u3055\u3044\u3002",buttons:{"accept-all":"\u3059\u3079\u3066\u540C\u610F","necessary-only":"\u30DE\u30FC\u30B1\u30C6\u30A3\u30F3\u30B0\u3092\u62D2\u5426","save-preferences":"\u9078\u629E\u3092\u4FDD\u5B58"},categories:{"cat-necessary":{heading:"\u5FC5\u9808",htmlText:"\u30A6\u30A7\u30D6\u30B5\u30A4\u30C8\u306E\u52D5\u4F5C\u306B\u4E0D\u53EF\u6B20\u3067\u3059\u3002"},"cat-functional":{heading:"\u6A5F\u80FD",htmlText:"\u9AD8\u5EA6\u306A\u6A5F\u80FD\u3092\u6709\u52B9\u306B\u3057\u307E\u3059\u3002\u6CD5\u7684\u6839\u62E0\uFF1A\u6B63\u5F53\u306A\u5229\u76CA\u3002"},"cat-preferences":{heading:"\u8A2D\u5B9A",htmlText:"\u500B\u4EBA\u8A2D\u5B9A\u3092\u4FDD\u5B58\u3057\u307E\u3059\u3002\u6CD5\u7684\u6839\u62E0\uFF1A\u6B63\u5F53\u306A\u5229\u76CA\u3002"},"cat-analytics":{heading:"\u5206\u6790",htmlText:"\u30B5\u30A4\u30C8\u5229\u7528\u72B6\u6CC1\u306E\u628A\u63E1\u306B\u5F79\u7ACB\u3066\u307E\u3059\u3002\u6CD5\u7684\u6839\u62E0\uFF1A\u6B63\u5F53\u306A\u5229\u76CA\u3002"},"cat-marketing":{heading:"\u30DE\u30FC\u30B1\u30C6\u30A3\u30F3\u30B0",htmlText:"\u30D1\u30FC\u30BD\u30CA\u30E9\u30A4\u30BA\u3055\u308C\u305F\u5E83\u544A\u3092\u53EF\u80FD\u306B\u3057\u307E\u3059\u3002\u304A\u5BA2\u69D8\u306E\u540C\u610F\u304C\u5FC5\u8981\u3067\u3059\u3002"}}}}});var lr,dr=I(()=>{"use strict";p();lr={mainBanner:{heading:"Diese Website verwendet nur notwendige Cookies",htmlText:"Wir verwenden ausschlie\xDFlich technisch notwendige Cookies, die f\xFCr den Betrieb der Website erforderlich sind. Es werden keine Marketing- oder Analyse-Cookies eingesetzt.",buttons:{ok:"OK"}},preferenceModal:{heading:"Cookie-Informationen",buttons:{close:"Schlie\xDFen"},categories:{"cat-necessary":{heading:"Notwendige Cookies",htmlText:"Technisch notwendige Cookies, die f\xFCr den ordnungsgem\xE4\xDFen Betrieb der Website erforderlich sind. Sie k\xF6nnen nicht deaktiviert werden."}}}}});var ur,pr=I(()=>{"use strict";p();ur={mainBanner:{heading:"Este sitio solo usa cookies esenciales",htmlText:"\xDAnicamente utilizamos cookies t\xE9cnicamente necesarias para el funcionamiento del sitio. No utilizamos cookies de marketing ni anal\xEDticas.",buttons:{ok:"Aceptar"}},preferenceModal:{heading:"Informaci\xF3n sobre cookies",buttons:{close:"Cerrar"},categories:{"cat-necessary":{heading:"Cookies necesarias",htmlText:"Cookies t\xE9cnicamente necesarias para el correcto funcionamiento del sitio. No pueden desactivarse."}}}}});var mr,gr=I(()=>{"use strict";p();mr={mainBanner:{heading:"Ce site utilise uniquement des cookies essentiels",htmlText:"Nous n'utilisons que des cookies techniquement n\xE9cessaires au bon fonctionnement du site. Aucun cookie de marketing ou d'analyse n'est utilis\xE9.",buttons:{ok:"OK"}},preferenceModal:{heading:"Informations sur les cookies",buttons:{close:"Fermer"},categories:{"cat-necessary":{heading:"Cookies n\xE9cessaires",htmlText:"Cookies techniquement n\xE9cessaires au bon fonctionnement du site. Ils ne peuvent pas \xEAtre d\xE9sactiv\xE9s."}}}}});var fr,hr=I(()=>{"use strict";p();fr={mainBanner:{heading:"\u5F53\u30B5\u30A4\u30C8\u306F\u5FC5\u9808Cookie\u306E\u307F\u3092\u4F7F\u7528\u3057\u3066\u3044\u307E\u3059",htmlText:"\u30B5\u30A4\u30C8\u306E\u6B63\u5E38\u306A\u52D5\u4F5C\u306B\u5FC5\u8981\u306A\u6280\u8853\u7684Cookie\u306E\u307F\u3092\u4F7F\u7528\u3057\u3066\u3044\u307E\u3059\u3002\u30DE\u30FC\u30B1\u30C6\u30A3\u30F3\u30B0\u3084\u5206\u6790\u306ECookie\u306F\u4F7F\u7528\u3057\u3066\u3044\u307E\u305B\u3093\u3002",buttons:{ok:"OK"}},preferenceModal:{heading:"Cookie\u306B\u95A2\u3059\u308B\u60C5\u5831",buttons:{close:"\u9589\u3058\u308B"},categories:{"cat-necessary":{heading:"\u5FC5\u9808Cookie",htmlText:"\u30B5\u30A4\u30C8\u306E\u6B63\u5E38\u306A\u52D5\u4F5C\u306B\u5FC5\u8981\u306A\u6280\u8853\u7684Cookie\u3067\u3059\u3002\u7121\u52B9\u306B\u3059\u308B\u3053\u3068\u306F\u3067\u304D\u307E\u305B\u3093\u3002"}}}}});var yr={};Un(yr,{DEFAULT_PROFILES:()=>ln,GENERAL_PRIVACY_CONSENT_EN_PROFILE:()=>an,GENERIC_AGE_GATE_TEXT:()=>Jl,GENERIC_GPC_BANNER_TEXT:()=>ql,NOTICE_ONLY_EN_PROFILE:()=>cn,OPT_IN_BRAZIL_EN_PROFILE:()=>rn,OPT_IN_CHINA_EN_PROFILE:()=>sn,OPT_IN_DPDPA_EN_PROFILE:()=>on,OPT_IN_EN_PROFILE:()=>en,OPT_OUT_EN_PROFILE:()=>tn,OPT_OUT_STRICT_EN_PROFILE:()=>nn,resolveLocaleTranslation:()=>zl});function gi(i,e){let t={};for(let[n,o]of Object.entries(i))t[n]=e[n]!==void 0?{...o,text:e[n]}:o;return t}function zl(i,e){let n=ln[i]?.translations.en;if(!n)return;if(e==="en")return n;let o=Wl[i]?.[e];if(!o)return;let s={};for(let[r,a]of Object.entries(n.preferenceModal.categories)){let c=o.preferenceModal.categories[`cat-${r}`];s[r]=c?{...a,heading:c.heading,htmlText:c.htmlText}:a}return{mainBanner:{...n.mainBanner,heading:o.mainBanner.heading,htmlText:o.mainBanner.htmlText,buttons:gi(n.mainBanner.buttons,o.mainBanner.buttons)},...n.gpcBanner?{gpcBanner:o.gpcBanner?{...n.gpcBanner,heading:o.gpcBanner.heading,htmlText:o.gpcBanner.htmlText,buttons:gi(n.gpcBanner.buttons,o.gpcBanner.buttons)}:n.gpcBanner}:{},preferenceModal:{...n.preferenceModal,heading:o.preferenceModal.heading,...o.preferenceModal.subheading?{subheading:o.preferenceModal.subheading}:{},...o.preferenceModal.htmlText?{htmlText:o.preferenceModal.htmlText}:{},buttons:gi(n.preferenceModal.buttons,o.preferenceModal.buttons),categories:s}}}var ln,Wl,ql,Jl,fi=I(()=>{"use strict";p();ri();ai();ci();li();di();ui();pi();mi();cs();ds();ps();gs();hs();_s();Es();Ss();Cs();Ts();Ps();Os();ks();Ns();Us();Gs();Bs();Fs();Vs();qs();zs();Ys();Zs();er();nr();or();rr();cr();dr();pr();gr();hr();ri();ai();ci();li();di();ui();pi();mi();ln={"opt-in":en,"opt-out":tn,"opt-out-strict":nn,"opt-in-dpdpa":on,"opt-in-china":sn,"opt-in-brazil":rn,"general-privacy-consent":an,"notice-only":cn},Wl={"opt-in":{de:as,es:ls,fr:us,ja:ms},"opt-out":{de:fs,es:ys,fr:ws,ja:Rs},"opt-out-strict":{de:vs,es:As,fr:Is,ja:bs},"opt-in-dpdpa":{de:Ds,es:Ls,fr:xs,ja:Ms},"opt-in-china":{de:js,es:$s,fr:Hs,ja:Ws},"opt-in-brazil":{de:Js,es:Ks,fr:Qs,ja:Xs},"general-privacy-consent":{de:tr,es:ir,fr:sr,ja:ar},"notice-only":{de:lr,es:ur,fr:mr,ja:fr}},ql={en:{heading:"Global Privacy Control detected",htmlText:"Your browser sent a Global Privacy Control signal. We have applied your privacy preference accordingly \u2014 you can review or change your choices below."},de:{heading:"Global Privacy Control erkannt",htmlText:"Ihr Browser hat ein Global-Privacy-Control-Signal gesendet. Wir haben Ihre Datenschutzeinstellung entsprechend angewendet \u2014 Sie k\xF6nnen Ihre Auswahl unten \xFCberpr\xFCfen oder \xE4ndern."},es:{heading:"Control de privacidad global detectado",htmlText:"Su navegador envi\xF3 una se\xF1al de Global Privacy Control. Hemos aplicado su preferencia de privacidad en consecuencia; puede revisar o cambiar sus opciones a continuaci\xF3n."},fr:{heading:"Contr\xF4le de confidentialit\xE9 global d\xE9tect\xE9",htmlText:"Votre navigateur a envoy\xE9 un signal Global Privacy Control. Nous avons appliqu\xE9 votre pr\xE9f\xE9rence de confidentialit\xE9 en cons\xE9quence \u2014 vous pouvez v\xE9rifier ou modifier vos choix ci-dessous."},ja:{heading:"\u30B0\u30ED\u30FC\u30D0\u30EB\u30FB\u30D7\u30E9\u30A4\u30D0\u30B7\u30FC\u30FB\u30B3\u30F3\u30C8\u30ED\u30FC\u30EB\u3092\u691C\u51FA\u3057\u307E\u3057\u305F",htmlText:"\u304A\u4F7F\u3044\u306E\u30D6\u30E9\u30A6\u30B6\u304B\u3089Global Privacy Control\u4FE1\u53F7\u304C\u9001\u4FE1\u3055\u308C\u307E\u3057\u305F\u3002\u3053\u308C\u306B\u5FDC\u3058\u3066\u304A\u5BA2\u69D8\u306E\u30D7\u30E9\u30A4\u30D0\u30B7\u30FC\u8A2D\u5B9A\u3092\u9069\u7528\u3057\u307E\u3057\u305F\u3002\u4EE5\u4E0B\u3067\u9078\u629E\u5185\u5BB9\u3092\u78BA\u8A8D\u30FB\u5909\u66F4\u3044\u305F\u3060\u3051\u307E\u3059\u3002"}},Jl={en:{heading:"Are you 16 or older?",htmlText:"Please confirm your age before we show you cookie preferences.",confirmButtonLabel:"Yes",denyButtonLabel:"No",parentalConsent:{heading:"Parental consent required",htmlText:"Only strictly necessary cookies will be used until a parent or guardian verifies consent on your behalf.",confirmButtonLabel:"OK"}},de:{heading:"Bist du 16 Jahre oder \xE4lter?",htmlText:"Bitte best\xE4tige dein Alter, bevor wir dir die Cookie-Einstellungen anzeigen.",confirmButtonLabel:"Ja",denyButtonLabel:"Nein",parentalConsent:{heading:"Elterliche Zustimmung erforderlich",htmlText:"Bis ein Elternteil oder Erziehungsberechtigter die Zustimmung in deinem Namen best\xE4tigt, werden nur unbedingt erforderliche Cookies verwendet.",confirmButtonLabel:"OK"}},es:{heading:"\xBFTienes 16 a\xF1os o m\xE1s?",htmlText:"Confirma tu edad antes de mostrarte las preferencias de cookies.",confirmButtonLabel:"S\xED",denyButtonLabel:"No",parentalConsent:{heading:"Se requiere consentimiento parental",htmlText:"Solo se utilizar\xE1n las cookies estrictamente necesarias hasta que un padre, madre o tutor confirme el consentimiento en tu nombre.",confirmButtonLabel:"Aceptar"}},fr:{heading:"Avez-vous 16 ans ou plus\xA0?",htmlText:"Merci de confirmer votre \xE2ge avant que nous vous montrions les pr\xE9f\xE9rences de cookies.",confirmButtonLabel:"Oui",denyButtonLabel:"Non",parentalConsent:{heading:"Consentement parental requis",htmlText:"Seuls les cookies strictement n\xE9cessaires seront utilis\xE9s jusqu\u2019\xE0 ce qu\u2019un parent ou tuteur confirme son consentement en votre nom.",confirmButtonLabel:"OK"}},ja:{heading:"16\u6B73\u4EE5\u4E0A\u3067\u3059\u304B?",htmlText:"Cookie\u306E\u8A2D\u5B9A\u3092\u8868\u793A\u3059\u308B\u524D\u306B\u3001\u5E74\u9F62\u3092\u3054\u78BA\u8A8D\u304F\u3060\u3055\u3044\u3002",confirmButtonLabel:"\u306F\u3044",denyButtonLabel:"\u3044\u3044\u3048",parentalConsent:{heading:"\u4FDD\u8B77\u8005\u306E\u540C\u610F\u304C\u5FC5\u8981\u3067\u3059",htmlText:"\u4FDD\u8B77\u8005\u304C\u540C\u610F\u3092\u78BA\u8A8D\u3059\u308B\u307E\u3067\u3001\u5FC5\u8981\u6700\u5C0F\u9650\u306ECookie\u306E\u307F\u304C\u4F7F\u7528\u3055\u308C\u307E\u3059\u3002",confirmButtonLabel:"OK"}}}});function Kl(i,e){let t;return function(...n){t!==void 0&&clearTimeout(t),t=setTimeout(()=>{i.apply(this,n)},e)}}var _r=I(()=>{"use strict";p()});function Yl(i,e){let t=0;return function(...n){let o=Date.now();o-t>=e&&(t=o,i.apply(this,n))}}var wr=I(()=>{"use strict";p()});function Ql(){return typeof process>"u"||process.env.NO_COLOR?!1:process.env.FORCE_COLOR?!0:!!process.stdout?.isTTY}function we(i,e){return t=>Ql()?`\x1B[${i}m${t}\x1B[${e}m`:t}function Xl(i,e=10){let t=i.toUpperCase().padEnd(e);return Zl[i](t)}function td(i,e){let{symbol:t,paint:n}=ed[i];return`${n(t)} ${e}`}var X,Zl,ed,Er=I(()=>{"use strict";p();X={bold:we(1,22),dim:we(2,22),red:we(31,39),green:we(32,39),yellow:we(33,39),blue:we(34,39),magenta:we(35,39),cyan:we(36,39),gray:we(90,39)},Zl={pass:i=>X.bold(X.green(i)),fail:i=>X.bold(X.red(i)),error:i=>X.bold(X.red(i)),"not-applicable":i=>X.gray(i),"new-baseline":i=>X.bold(X.blue(i))};ed={info:{symbol:"\u2139",paint:X.cyan},success:{symbol:"\u2713",paint:X.green},warn:{symbol:"\u26A0",paint:X.yellow},error:{symbol:"\u2717",paint:X.red}}});function ad(i){return Rr[i.id]??"functional"}function dd(i,e){for(let t of Object.values(e))if(t.cookies.includes(i))return t}function We(i){let e=new Map;for(let t of Object.values(i))for(let n of t.cookies)e.set(n,t);return e}function qe(i,e){return e.get(i)?.legalBasis??"consent"}function hi(i,e){return qe(i,e)==="mandatory"}function _i(i,e){let t=Sr[e];return i[e]??(t!==void 0?i[t]:void 0)}function gd(i){if(!i||typeof i!="object")return!1;let e=i;if(typeof e.version!="string"||e.override!==void 0&&typeof e.override!="boolean")return!1;let t=e.countries;return!t||typeof t!="object"?!1:Object.values(t).every(n=>!!n&&typeof n=="object"&&typeof n.complianceGroup=="string")}async function wi(i,e){let t={map:Ce};if(i===void 0||i==="default")return t;let n,o;if(typeof i=="string")try{if(o=await fetch(i),!o.ok)return e(`compliance.complianceMap fetch from "${i}" failed (HTTP ${o.status}) \u2014 falling back to the embedded map.`),t;n=await o.json()}catch(r){return e(`compliance.complianceMap fetch from "${i}" failed (${r instanceof Error?r.message:String(r)}) \u2014 falling back to the embedded map.`),t}else n=i;if(!gd(n))return e(`compliance.complianceMap ${typeof i=="string"?`at "${i}"`:"object"} failed validation \u2014 falling back to the embedded map.`),t;for(let[r,a]of Object.entries(n.countries))a.overriddenRegions&&a.default===void 0&&e(`compliance.complianceMap country "${r}" has overriddenRegions but no explicit default \u2014 falling back to complianceGroup ("${a.complianceGroup}"), which may under-comply for regions not listed.`);let s={map:n.override===!1?fd(n):n};return o&&(s.response=o),s}function fd(i){let e={...Ce.countries};for(let t of Object.keys(i.countries)){let n=Sr[t];n!==void 0&&!(n in i.countries)&&delete e[n]}return Object.assign(e,i.countries),{version:i.version,countries:e}}var dn,dt,nd,id,od,un,sd,rd,Rr,cd,ld,yi,Ce,Sr,ud,pd,md,vr=I(()=>{"use strict";p();dn=["opt-in","opt-out","opt-out-strict","opt-in-dpdpa","opt-in-china","opt-in-brazil","general-privacy-consent","notice-only"],dt={"opt-out-strict":{label:"Opt-out Strict (CPRA / California)",description:"California CPRA: opt-out with sale/sharing/sensitive categories required. GPC must be honored. Stricter than general US state laws.",compliances:["cpra"],defaultGpc:"honor",gpcAutoHonor:!0,allowsLegitimateInterest:!1,allowsTcf:!1,requiresCpraCategory:!0,requiresDpdpaDisclosure:!1},"opt-out":{label:"Opt-out (US State Laws)",description:"US state privacy laws. Collect first, allow opt-out of sale/share. Covers CCPA and all state-level equivalents.",compliances:["ccpa","vcdpa","cpa-co","ctdpa","ucpa","icdpa-ia","icdpa-in","tipa","mcdpa-mt","mcdpa-mn","ocpa","tdpsa","dpdpa-de","njdpa","nhpa","ndpa-ne","modpa","kcdpa","ridtpa"],defaultGpc:"honor",gpcAutoHonor:!0,allowsLegitimateInterest:!1,allowsTcf:!1,requiresCpraCategory:!1,requiresDpdpaDisclosure:!1},"notice-only":{label:"Notice Only",description:"A privacy notice is generally sufficient. No dedicated cookie banner law is encoded for this jurisdiction.",compliances:["privacy-fj","privacy-pg"],defaultGpc:"ignore",gpcAutoHonor:!1,allowsLegitimateInterest:!0,allowsTcf:!1,requiresCpraCategory:!1,requiresDpdpaDisclosure:!1},"opt-in":{label:"Standard Opt-in (GDPR)",description:"GDPR / ePrivacy style: prior consent required before non-essential cookies. Granular consent, easy reject, easy withdrawal.",compliances:["gdpr","eprivacy","uk-gdpr","pecr","revfadp","kvkk","pdpa-th","pdpl-sa","uae-pdpl","difc-dpl","adgm-dpr","qpdl-qa","pdpl-bh","pdpl-om","law25"],defaultGpc:"ignore",gpcAutoHonor:!1,allowsLegitimateInterest:!0,allowsTcf:!0,requiresCpraCategory:!1,requiresDpdpaDisclosure:!1},"opt-in-dpdpa":{label:"Opt-in (India DPDPA)",description:"India's Digital Personal Data Protection Act. Opt-in consent with data fiduciary disclosure. No legitimate interest basis.",compliances:["dpdpa"],defaultGpc:"ignore",gpcAutoHonor:!1,allowsLegitimateInterest:!1,allowsTcf:!1,requiresCpraCategory:!1,requiresDpdpaDisclosure:!0},"opt-in-china":{label:"Opt-in (China PIPL / DSL)",description:"China PIPL + DSL + CSL: strict opt-in with purpose specification, data minimisation, and cross-border transfer controls.",compliances:["pipl","dsl-cn","csl-cn"],defaultGpc:"ignore",gpcAutoHonor:!1,allowsLegitimateInterest:!1,allowsTcf:!1,requiresCpraCategory:!1,requiresDpdpaDisclosure:!1},"opt-in-brazil":{label:"Opt-in (Brazil LGPD)",description:"Brazil LGPD: opt-in consent required. Legitimate interest is a valid basis. Analytics and advertising may differ in treatment.",compliances:["lgpd"],defaultGpc:"ignore",gpcAutoHonor:!1,allowsLegitimateInterest:!0,allowsTcf:!1,requiresCpraCategory:!1,requiresDpdpaDisclosure:!1},"general-privacy-consent":{label:"General Privacy Consent",description:"Privacy notice or consent rules exist but the jurisdiction does not have a GDPR/PECR-style strict cookie banner law. Documenting legal basis is best practice.",compliances:["pipeda","popia","appi","pipa-kr","pdpa-sg","pdpa-my","dpa-ph","pdp-id","pdpd-vn","privacy-au","privacy-nz","pdpl-hk","pdpa-mo","pdpl-tw","privacy-bn","privacy-lk","privacy-np","privacy-kw","privacy-il","ndpa-ng","dpa-ke","dpa-gh","dpa-ug","dpa-rw","dpa-mu","dpa-bw","dpa-zm","dpa-zw","dpa-eg","dpa-ma","dpa-tn","dpa-dz","lfpdppp","lpdp-ar","lpdp-pe","law1581-co","law18331-uy","law19628-cl","lopdp-ec","lpdp-cr","data-protection-pa","data-protection-do"],defaultGpc:"ignore",gpcAutoHonor:!1,allowsLegitimateInterest:!0,allowsTcf:!1,requiresCpraCategory:!1,requiresDpdpaDisclosure:!1}},nd=[{value:"ignore",label:"Ignore",description:"Do not check or respond to the GPC browser signal."},{value:"honor",label:"Honor",description:"Respect GPC as a valid opt-out signal. Show GPC variant banner once."},{value:"strict",label:"Strict",description:"Silently deny all non-mandatory cookies when GPC is detected. No banner shown."}],id=[{value:"mandatory",label:"Strictly Necessary",description:"Required for the service to function. No consent needed."},{value:"consent",label:"Consent",description:"Requires explicit user agreement. User can withdraw at any time."},{value:"legitimate_interest",label:"Legitimate Interest",description:"Based on legitimate business interest. User has the right to object."}],od=[{value:"sale",label:"Sale",description:"Sale of personal data to third parties for their own use."},{value:"sharing",label:"Sharing",description:"Sharing for cross-context behavioral advertising (even without payment)."},{value:"sensitive",label:"Sensitive",description:"Sensitive personal information (geolocation, health, race, biometrics, etc.). Requires opt-in even in California."}],un=["necessary","functional","preferences","analytics","marketing"],sd=[{value:"necessary",label:"Necessary",description:"Strictly required to deliver the service or ensure security/compliance. Always granted."},{value:"functional",label:"Functional",description:"Optional features that enhance functionality but are not essential."},{value:"preferences",label:"Preferences",description:'Remember user choices and personalize the experience ("Remember me").'},{value:"analytics",label:"Analytics",description:"Measure usage and performance to improve the product."},{value:"marketing",label:"Marketing",description:"Advertising, profiling, cross-site tracking, retargeting, ad personalization."}],rd={necessary:{legalBasis:"mandatory",listenGpc:!1},functional:{legalBasis:"legitimate_interest",listenGpc:!1},preferences:{legalBasis:"legitimate_interest",listenGpc:!1},analytics:{legalBasis:"consent",listenGpc:!0},marketing:{legalBasis:"consent",listenGpc:!0,cpraCategory:"sharing"}},Rr={security_storage:"necessary",functionality_storage:"functional",personalization_storage:"preferences",analytics_storage:"analytics",ad_storage:"marketing",ad_user_data:"marketing",ad_personalization:"marketing"};cd=[{id:1,name:"Store and/or access information on a device",description:"Cookies, device identifiers, or other information can be stored or accessed on your device."},{id:2,name:"Select basic ads",description:"Ads can be shown based on the content you're viewing, the app you're using, or your approximate location."},{id:3,name:"Create a personalised ads profile",description:"A profile can be built about you and your interests to show you personalised ads."},{id:4,name:"Select personalised ads",description:"Personalised ads can be shown to you based on a profile about you."},{id:5,name:"Create a personalised content profile",description:"A profile can be built about you and your interests to show you personalised content."},{id:6,name:"Select personalised content",description:"Personalised content can be shown to you based on a profile about you."},{id:7,name:"Measure ad performance",description:"The performance and effectiveness of ads that you see or interact with can be measured."},{id:8,name:"Measure content performance",description:"The performance and effectiveness of content that you see or interact with can be measured."},{id:9,name:"Apply market research to generate audience insights",description:"Market research can be used to learn more about the audiences who visit sites or use apps."},{id:10,name:"Develop and improve products",description:"Your data can be used to improve existing systems and software, and to develop new products."},{id:11,name:"Use limited data to select content",description:"Content can be selected based on limited data such as the website you are visiting."}],ld=[{id:1,name:"Use precise geolocation data",description:"Your precise location (within a radius of less than 500 metres) can be used."},{id:2,name:"Actively scan device characteristics for identification",description:"Your device can be identified based on a scan of your device's unique combination of characteristics."}];yi={"opt-in":{categoryErrors:[{rule:"legal-basis-required",field:"legalBasis",check:i=>!i.legalBasis,message:i=>`Category "${i}" must have a legal basis set (Consent, Legitimate Interest, or Strictly Necessary) for GDPR compliance.`}],categoryWarnings:[{rule:"legitimate-interest-balancing-test-recommended",field:"legitimateInterestDescription",check:i=>i.legalBasis==="legitimate_interest"&&!String(i.legitimateInterestDescription??"").trim(),message:i=>`Category "${i}" relies on Legitimate Interest but has no balancing-test description. GDPR Art. 6(1)(f) requires you to conduct and be able to demonstrate a Legitimate Interests Assessment \u2014 note that Art. 5(3) ePrivacy still requires consent (LI cannot substitute) for the cookie storage/access itself, so this basis should only cover the downstream processing purpose, not the placement of a non-essential cookie.`,suggestion:`Document your Legitimate Interests Assessment in the category's "Legitimate Interest Description" field.`}],cookieErrors:[],cookieWarnings:[{rule:"pre-grant-opt-in-risk",field:"preGrant",check:(i,e)=>e==="consent"&&i.preGrant===!0,message:i=>`Parameter "${i}" is pre-granted, which may violate GDPR's opt-in requirement. Only use "Pre Grant" on custom profiles targeting jurisdictions where pre-granted consent is valid.`,suggestion:'Disable "Pre Grant" unless this profile specifically targets a jurisdiction that permits pre-granted consent.'}]},"opt-out":{categoryErrors:[],categoryWarnings:[],cookieErrors:[],cookieWarnings:[{rule:"gpc-recommended",field:"listenGpc",check:(i,e)=>e!=="mandatory"&&!i.listenGpc,message:i=>`Parameter "${i}" does not listen for the GPC signal. US state privacy laws require honoring GPC for opt-out of sale/sharing.`,suggestion:'Enable "Listen for GPC signal" on this parameter.'}]},"opt-out-strict":{categoryErrors:[],categoryWarnings:[],cookieErrors:[{rule:"cpra-category-required",field:"cpraCategory",check:(i,e)=>e!=="mandatory"&&!i.cpraCategory,message:i=>`Parameter "${i}" must have a CPRA category (Sale, Sharing, or Sensitive) assigned. Required under CPRA for all non-necessary parameters.`},{rule:"gpc-strict-required",field:"listenGpc",check:i=>(i.cpraCategory==="sale"||i.cpraCategory==="sharing")&&!i.listenGpc,message:i=>`Parameter "${i}" is tagged Sale/Sharing but does not listen for the GPC signal. 11 CCR \xA77025 requires honoring GPC as a Do Not Sell/Share My Personal Information request for these parameters \u2014 this is mandatory, not optional.`}],cookieWarnings:[]},"opt-in-dpdpa":{categoryErrors:[{rule:"no-li-allowed",field:"legalBasis",check:i=>i.legalBasis==="legitimate_interest",message:i=>`Category "${i}" uses Legitimate Interest, which is not a valid legal basis under India's DPDPA. Use Consent or Strictly Necessary.`},{rule:"legal-basis-required",field:"legalBasis",check:i=>!i.legalBasis,message:i=>`Category "${i}" must have a legal basis set (Consent or Strictly Necessary) for DPDPA compliance.`}],categoryWarnings:[],cookieErrors:[],cookieWarnings:[{rule:"pre-grant-opt-in-risk",field:"preGrant",check:(i,e)=>e==="consent"&&i.preGrant===!0,message:i=>`Parameter "${i}" is pre-granted, which may violate DPDPA's opt-in requirement. Only use "Pre Grant" on custom profiles targeting jurisdictions where pre-granted consent is valid.`,suggestion:'Disable "Pre Grant" unless this profile specifically targets a jurisdiction that permits pre-granted consent.'}]},"opt-in-china":{categoryErrors:[{rule:"no-li-allowed",field:"legalBasis",check:i=>i.legalBasis==="legitimate_interest",message:i=>`Category "${i}" uses Legitimate Interest, which is not one of PIPL Article 13's enumerated legal bases. Use Consent or Strictly Necessary.`},{rule:"legal-basis-required",field:"legalBasis",check:i=>!i.legalBasis,message:i=>`Category "${i}" must have a legal basis set for China PIPL compliance. Consent is the primary valid basis.`}],categoryWarnings:[],cookieErrors:[],cookieWarnings:[{rule:"pre-grant-opt-in-risk",field:"preGrant",check:(i,e)=>e==="consent"&&i.preGrant===!0,message:i=>`Parameter "${i}" is pre-granted, which may violate PIPL's opt-in requirement. Only use "Pre Grant" on custom profiles targeting jurisdictions where pre-granted consent is valid.`,suggestion:'Disable "Pre Grant" unless this profile specifically targets a jurisdiction that permits pre-granted consent.'}]},"opt-in-brazil":{categoryErrors:[{rule:"legal-basis-required",field:"legalBasis",check:i=>!i.legalBasis,message:i=>`Category "${i}" must have a legal basis set. Brazil's LGPD requires one of ten legal bases; Consent or Legitimate Interest are most common for parameters.`}],categoryWarnings:[{rule:"legitimate-interest-balancing-test-recommended",field:"legitimateInterestDescription",check:i=>i.legalBasis==="legitimate_interest"&&!String(i.legitimateInterestDescription??"").trim(),message:i=>`Category "${i}" relies on Legitimate Interest but has no balancing-test description. LGPD Art. 10 requires the legitimate interest basis to be documented and, on request, made available to the ANPD as a Data Protection Impact Report (relat\xF3rio de impacto).`,suggestion:`Document your legitimate interest assessment in the category's "Legitimate Interest Description" field.`}],cookieErrors:[],cookieWarnings:[{rule:"pre-grant-opt-in-risk",field:"preGrant",check:(i,e)=>e==="consent"&&i.preGrant===!0,message:i=>`Parameter "${i}" is pre-granted, which may violate LGPD's opt-in requirement. Only use "Pre Grant" on custom profiles targeting jurisdictions where pre-granted consent is valid.`,suggestion:'Disable "Pre Grant" unless this profile specifically targets a jurisdiction that permits pre-granted consent.'}]},"general-privacy-consent":{categoryErrors:[],categoryWarnings:[{rule:"legal-basis-recommended",field:"legalBasis",check:i=>!i.legalBasis,message:i=>`Category "${i}" has no legal basis documented. While a strict cookie banner may not be legally required in this jurisdiction, documenting legal basis is a privacy best practice.`,suggestion:"Set a legal basis to improve compliance documentation and future-proof against stricter enforcement."},{rule:"legitimate-interest-balancing-test-recommended",field:"legitimateInterestDescription",check:i=>i.legalBasis==="legitimate_interest"&&!String(i.legitimateInterestDescription??"").trim(),message:i=>`Category "${i}" relies on Legitimate Interest but has no balancing-test description documented. Most legitimate-interest-style bases in this jurisdiction group expect a documented justification, and it future-proofs the profile against stricter enforcement.`,suggestion:`Document your legitimate interest justification in the category's "Legitimate Interest Description" field.`}],cookieErrors:[],cookieWarnings:[]},"notice-only":{categoryErrors:[],categoryWarnings:[],cookieErrors:[],cookieWarnings:[]}},Ce={version:"2026-07",countries:{AT:{name:"Austria",type:"country",complianceGroup:"opt-in",default:"opt-in",description:"Austria (GDPR)",locales:["de-AT"],compliance:["gdpr","eprivacy"],timezones:["Europe/Vienna"]},BE:{name:"Belgium",type:"country",complianceGroup:"opt-in",default:"opt-in",description:"Belgium (GDPR)",locales:["nl-BE","fr-BE"],compliance:["gdpr","eprivacy"],timezones:["Europe/Brussels"]},BG:{name:"Bulgaria",type:"country",complianceGroup:"opt-in",default:"opt-in",description:"Bulgaria (GDPR)",locales:["bg-BG"],compliance:["gdpr","eprivacy"],timezones:["Europe/Sofia"]},HR:{name:"Croatia",type:"country",complianceGroup:"opt-in",default:"opt-in",description:"Croatia (GDPR)",locales:["hr-HR"],compliance:["gdpr","eprivacy"],timezones:["Europe/Zagreb"]},CY:{name:"Cyprus",type:"country",complianceGroup:"opt-in",default:"opt-in",description:"Cyprus (GDPR)",locales:["el-CY"],compliance:["gdpr","eprivacy"],timezones:["Asia/Nicosia"]},CZ:{name:"Czechia",type:"country",complianceGroup:"opt-in",default:"opt-in",description:"Czechia (GDPR)",locales:["cs-CZ"],compliance:["gdpr","eprivacy"],timezones:["Europe/Prague"]},DK:{name:"Denmark",type:"country",complianceGroup:"opt-in",default:"opt-in",description:"Denmark (GDPR)",locales:["da-DK"],compliance:["gdpr","eprivacy"],timezones:["Europe/Copenhagen"]},EE:{name:"Estonia",type:"country",complianceGroup:"opt-in",default:"opt-in",description:"Estonia (GDPR)",locales:["et-EE"],compliance:["gdpr","eprivacy"],timezones:["Europe/Tallinn"]},FI:{name:"Finland",type:"country",complianceGroup:"opt-in",default:"opt-in",description:"Finland (GDPR)",locales:["fi-FI"],compliance:["gdpr","eprivacy"],timezones:["Europe/Helsinki"]},FR:{name:"France",type:"country",complianceGroup:"opt-in",default:"opt-in",description:"France (GDPR)",locales:["fr-FR"],compliance:["gdpr","eprivacy"],timezones:["Europe/Paris"]},DE:{name:"Germany",type:"country",complianceGroup:"opt-in",default:"opt-in",description:"Germany (GDPR)",locales:["de-DE"],compliance:["gdpr","eprivacy"],timezones:["Europe/Berlin"]},GR:{name:"Greece",type:"country",complianceGroup:"opt-in",default:"opt-in",description:"Greece (GDPR)",locales:["el-GR"],compliance:["gdpr","eprivacy"],timezones:["Europe/Athens"]},HU:{name:"Hungary",type:"country",complianceGroup:"opt-in",default:"opt-in",description:"Hungary (GDPR)",locales:["hu-HU"],compliance:["gdpr","eprivacy"],timezones:["Europe/Budapest"]},IE:{name:"Ireland",type:"country",complianceGroup:"opt-in",default:"opt-in",description:"Ireland (GDPR)",locales:["en"],compliance:["gdpr","eprivacy"],timezones:["Europe/Dublin"]},IT:{name:"Italy",type:"country",complianceGroup:"opt-in",default:"opt-in",description:"Italy (GDPR)",locales:["it-IT"],compliance:["gdpr","eprivacy"],timezones:["Europe/Rome"]},LV:{name:"Latvia",type:"country",complianceGroup:"opt-in",default:"opt-in",description:"Latvia (GDPR)",locales:["lv-LV"],compliance:["gdpr","eprivacy"],timezones:["Europe/Riga"]},LT:{name:"Lithuania",type:"country",complianceGroup:"opt-in",default:"opt-in",description:"Lithuania (GDPR)",locales:["lt-LT"],compliance:["gdpr","eprivacy"],timezones:["Europe/Vilnius"]},LU:{name:"Luxembourg",type:"country",complianceGroup:"opt-in",default:"opt-in",description:"Luxembourg (GDPR)",locales:["fr-LU","de-LU"],compliance:["gdpr","eprivacy"],timezones:["Europe/Luxembourg"]},MT:{name:"Malta",type:"country",complianceGroup:"opt-in",default:"opt-in",description:"Malta (GDPR)",locales:["mt-MT","en"],compliance:["gdpr","eprivacy"],timezones:["Europe/Malta"]},NL:{name:"Netherlands",type:"country",complianceGroup:"opt-in",default:"opt-in",description:"Netherlands (GDPR)",locales:["nl-NL"],compliance:["gdpr","eprivacy"],timezones:["Europe/Amsterdam"]},PL:{name:"Poland",type:"country",complianceGroup:"opt-in",default:"opt-in",description:"Poland (GDPR)",locales:["pl-PL"],compliance:["gdpr","eprivacy"],timezones:["Europe/Warsaw"]},PT:{name:"Portugal",type:"country",complianceGroup:"opt-in",default:"opt-in",description:"Portugal (GDPR)",locales:["pt-PT"],compliance:["gdpr","eprivacy"],timezones:["Europe/Lisbon","Atlantic/Madeira","Atlantic/Azores"]},RO:{name:"Romania",type:"country",complianceGroup:"opt-in",default:"opt-in",description:"Romania (GDPR)",locales:["ro-RO"],compliance:["gdpr","eprivacy"],timezones:["Europe/Bucharest"]},SK:{name:"Slovakia",type:"country",complianceGroup:"opt-in",default:"opt-in",description:"Slovakia (GDPR)",locales:["sk-SK"],compliance:["gdpr","eprivacy"],timezones:["Europe/Bratislava"]},SI:{name:"Slovenia",type:"country",complianceGroup:"opt-in",default:"opt-in",description:"Slovenia (GDPR)",locales:["sl-SI"],compliance:["gdpr","eprivacy"],timezones:["Europe/Ljubljana"]},ES:{name:"Spain",type:"country",complianceGroup:"opt-in",default:"opt-in",description:"Spain (GDPR)",locales:["es-ES"],compliance:["gdpr","eprivacy"],timezones:["Europe/Madrid","Africa/Ceuta","Atlantic/Canary"]},SE:{name:"Sweden",type:"country",complianceGroup:"opt-in",default:"opt-in",description:"Sweden (GDPR)",locales:["sv-SE"],compliance:["gdpr","eprivacy"],timezones:["Europe/Stockholm"]},IS:{name:"Iceland",type:"country",complianceGroup:"opt-in",default:"opt-in",description:"Iceland (GDPR via EEA)",locales:["is-IS"],compliance:["gdpr","eprivacy"],timezones:["Atlantic/Reykjavik"]},LI:{name:"Liechtenstein",type:"country",complianceGroup:"opt-in",default:"opt-in",description:"Liechtenstein (GDPR via EEA)",locales:["de-LI"],compliance:["gdpr","eprivacy"],timezones:["Europe/Vaduz"]},NO:{name:"Norway",type:"country",complianceGroup:"opt-in",default:"opt-in",description:"Norway (GDPR via EEA)",locales:["nb-NO"],compliance:["gdpr","eprivacy"],timezones:["Europe/Oslo","Arctic/Longyearbyen"]},AD:{name:"Andorra",type:"country",complianceGroup:"opt-in",default:"opt-in",description:"Andorra (GDPR-aligned)",locales:["ca-AD"],compliance:["gdpr"],timezones:["Europe/Andorra"]},AL:{name:"Albania",type:"country",complianceGroup:"opt-in",default:"opt-in",description:"Albania (GDPR-aligned)",locales:["sq-AL"],compliance:["gdpr"],timezones:["Europe/Tirane"]},BA:{name:"Bosnia and Herzegovina",type:"country",complianceGroup:"opt-in",default:"opt-in",description:"Bosnia and Herzegovina (GDPR-aligned)",locales:["bs-BA","sr-Latn-BA"],compliance:["gdpr"],timezones:["Europe/Sarajevo"]},GG:{name:"Guernsey",type:"country",complianceGroup:"opt-in",default:"opt-in",description:"Guernsey (DPA based on GDPR)",locales:["en"],compliance:["gdpr"],timezones:["Europe/Guernsey"]},GI:{name:"Gibraltar",type:"country",complianceGroup:"opt-in",default:"opt-in",description:"Gibraltar (DPA based on UK GDPR)",locales:["en"],compliance:["uk-gdpr"],timezones:["Europe/Gibraltar"]},GL:{name:"Greenland",type:"country",complianceGroup:"opt-in",default:"opt-in",description:"Greenland (Danish GDPR implementation)",locales:["da-GL"],compliance:["gdpr"],timezones:["America/Nuuk","America/Danmarkshavn","America/Scoresbysund","America/Thule"]},MC:{name:"Monaco",type:"country",complianceGroup:"opt-in",default:"opt-in",description:"Monaco (GDPR-aligned)",locales:["fr-MC"],compliance:["gdpr"],timezones:["Europe/Monaco"]},ME:{name:"Montenegro",type:"country",complianceGroup:"opt-in",default:"opt-in",description:"Montenegro (GDPR-aligned)",locales:["sr-Latn-ME"],compliance:["gdpr"],timezones:["Europe/Podgorica"]},MK:{name:"North Macedonia",type:"country",complianceGroup:"opt-in",default:"opt-in",description:"North Macedonia (GDPR-aligned)",locales:["mk-MK"],compliance:["gdpr"],timezones:["Europe/Skopje"]},RS:{name:"Serbia",type:"country",complianceGroup:"opt-in",default:"opt-in",description:"Serbia (GDPR-aligned)",locales:["sr-RS"],compliance:["gdpr"],timezones:["Europe/Belgrade"]},SM:{name:"San Marino",type:"country",complianceGroup:"opt-in",default:"opt-in",description:"San Marino (GDPR-aligned)",locales:["it-SM"],compliance:["gdpr"],timezones:["Europe/San_Marino"]},TR:{name:"T\xFCrkiye",type:"country",complianceGroup:"opt-in",default:"opt-in",description:"T\xFCrkiye (KVKK)",locales:["tr-TR"],compliance:["kvkk"],timezones:["Europe/Istanbul"]},CA:{name:"Canada",type:"country",complianceGroup:"general-privacy-consent",default:"general-privacy-consent",description:"Canada (PIPEDA / Law 25)",locales:["en","fr-CA"],compliance:["pipeda","law25"],timezones:["America/St_Johns","America/Halifax","America/Toronto","America/Winnipeg","America/Edmonton","America/Vancouver"],overriddenRegions:{QC:{name:"Quebec",type:"region",complianceGroup:"opt-in",description:"Quebec \u2014 Law 25 (GDPR-style opt-in)"}}},US:{name:"United States",type:"country",complianceGroup:"opt-out",default:"opt-out-strict",description:"United States \u2014 opt-out-strict (CPRA) used when state cannot be detected",locales:["en","es-US"],compliance:["ccpa","cpra","vcdpa","cpa-co","ctdpa","ucpa","icdpa-ia","icdpa-in","tipa","mcdpa-mt","mcdpa-mn","ocpa","tdpsa","dpdpa-de","njdpa","nhpa","ndpa-ne","modpa","kcdpa","ridtpa"],timezones:["America/New_York","America/Chicago","America/Denver","America/Phoenix","America/Los_Angeles","America/Anchorage","Pacific/Honolulu"],overriddenRegions:{CA:{name:"California",type:"region",complianceGroup:"opt-out-strict",description:"California \u2014 CPRA/CCPA"},VA:{name:"Virginia",type:"region",complianceGroup:"opt-out",description:"Virginia \u2014 VCDPA"},CO:{name:"Colorado",type:"region",complianceGroup:"opt-out",description:"Colorado \u2014 CPA",requiresSensitiveOptIn:!0},CT:{name:"Connecticut",type:"region",complianceGroup:"opt-out",description:"Connecticut \u2014 CTDPA"},UT:{name:"Utah",type:"region",complianceGroup:"opt-out",description:"Utah \u2014 UCPA"},TX:{name:"Texas",type:"region",complianceGroup:"opt-out",description:"Texas \u2014 TDPSA"},DE:{name:"Delaware",type:"region",complianceGroup:"opt-out",description:"Delaware \u2014 DPDPA"},NJ:{name:"New Jersey",type:"region",complianceGroup:"opt-out",description:"New Jersey \u2014 NJDPA"},OR:{name:"Oregon",type:"region",complianceGroup:"opt-out",description:"Oregon \u2014 OCPA"},MN:{name:"Minnesota",type:"region",complianceGroup:"opt-out",description:"Minnesota \u2014 MCDPA"},MD:{name:"Maryland",type:"region",complianceGroup:"opt-out",description:"Maryland \u2014 MODPA"},KY:{name:"Kentucky",type:"region",complianceGroup:"opt-out",description:"Kentucky \u2014 KCDPA"},TN:{name:"Tennessee",type:"region",complianceGroup:"opt-out",description:"Tennessee \u2014 TIPA"},NE:{name:"Nebraska",type:"region",complianceGroup:"opt-out",description:"Nebraska \u2014 NDPA"},IA:{name:"Iowa",type:"region",complianceGroup:"opt-out",description:"Iowa \u2014 ICDPA"},IN:{name:"Indiana",type:"region",complianceGroup:"opt-out",description:"Indiana \u2014 ICDPA"},MT:{name:"Montana",type:"region",complianceGroup:"opt-out",description:"Montana \u2014 MCDPA"},NH:{name:"New Hampshire",type:"region",complianceGroup:"opt-out",description:"New Hampshire \u2014 NHPA"},RI:{name:"Rhode Island",type:"region",complianceGroup:"opt-out",description:"Rhode Island \u2014 RIDTPA"}}},AR:{name:"Argentina",type:"country",complianceGroup:"general-privacy-consent",default:"general-privacy-consent",description:"Argentina (LPDP)",locales:["es-AR"],compliance:["lpdp-ar"],timezones:["America/Argentina/Buenos_Aires"]},BO:{name:"Bolivia",type:"country",complianceGroup:"general-privacy-consent",default:"general-privacy-consent",description:"Bolivia",locales:["es-BO"],compliance:[],timezones:["America/La_Paz"]},BR:{name:"Brazil",type:"country",complianceGroup:"opt-in-brazil",default:"opt-in-brazil",description:"Brazil (LGPD)",locales:["pt-BR"],compliance:["lgpd"],timezones:["America/Noronha","America/Sao_Paulo","America/Manaus","America/Rio_Branco"]},CL:{name:"Chile",type:"country",complianceGroup:"general-privacy-consent",default:"general-privacy-consent",description:"Chile (Law 19.628)",locales:["es-CL"],compliance:["law19628-cl"],timezones:["America/Santiago","Pacific/Easter"]},CO:{name:"Colombia",type:"country",complianceGroup:"general-privacy-consent",default:"general-privacy-consent",description:"Colombia (Law 1581)",locales:["es-CO"],compliance:["law1581-co"],timezones:["America/Bogota"]},CR:{name:"Costa Rica",type:"country",complianceGroup:"general-privacy-consent",default:"general-privacy-consent",description:"Costa Rica (LPDP)",locales:["es-CR"],compliance:["lpdp-cr"],timezones:["America/Costa_Rica"]},DO:{name:"Dominican Republic",type:"country",complianceGroup:"general-privacy-consent",default:"general-privacy-consent",description:"Dominican Republic",locales:["es-DO"],compliance:["data-protection-do"],timezones:["America/Santo_Domingo"]},EC:{name:"Ecuador",type:"country",complianceGroup:"general-privacy-consent",default:"general-privacy-consent",description:"Ecuador (LOPDP)",locales:["es-EC"],compliance:["lopdp-ec"],timezones:["America/Guayaquil","Pacific/Galapagos"]},GF:{name:"French Guiana",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"French Guiana",locales:["fr-GF"],compliance:[],timezones:["America/Cayenne"]},GT:{name:"Guatemala",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Guatemala",locales:["es-GT"],compliance:[],timezones:["America/Guatemala"]},GY:{name:"Guyana",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Guyana",locales:["en"],compliance:[],timezones:["America/Guyana"]},HN:{name:"Honduras",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Honduras",locales:["es-HN"],compliance:[],timezones:["America/Tegucigalpa"]},HT:{name:"Haiti",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Haiti",locales:["fr-HT"],compliance:[],timezones:["America/Port-au-Prince"]},JM:{name:"Jamaica",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Jamaica",locales:["en"],compliance:[],timezones:["America/Jamaica"]},MX:{name:"Mexico",type:"country",complianceGroup:"general-privacy-consent",default:"general-privacy-consent",description:"Mexico (LFPDPPP)",locales:["es-MX"],compliance:["lfpdppp"],timezones:["America/Mexico_City","America/Cancun","America/Chihuahua","America/Hermosillo","America/Tijuana"]},NI:{name:"Nicaragua",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Nicaragua",locales:["es-NI"],compliance:[],timezones:["America/Managua"]},PA:{name:"Panama",type:"country",complianceGroup:"general-privacy-consent",default:"general-privacy-consent",description:"Panama",locales:["es-PA"],compliance:["data-protection-pa"],timezones:["America/Panama"]},PE:{name:"Peru",type:"country",complianceGroup:"general-privacy-consent",default:"general-privacy-consent",description:"Peru (LPDP)",locales:["es-PE"],compliance:["lpdp-pe"],timezones:["America/Lima"]},PY:{name:"Paraguay",type:"country",complianceGroup:"general-privacy-consent",default:"general-privacy-consent",description:"Paraguay",locales:["es-PY"],compliance:[],timezones:["America/Asuncion"]},SR:{name:"Suriname",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Suriname",locales:["nl-SR"],compliance:[],timezones:["America/Paramaribo"]},SV:{name:"El Salvador",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"El Salvador",locales:["es-SV"],compliance:[],timezones:["America/El_Salvador"]},TT:{name:"Trinidad and Tobago",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Trinidad and Tobago",locales:["en"],compliance:[],timezones:["America/Port_of_Spain"]},UY:{name:"Uruguay",type:"country",complianceGroup:"general-privacy-consent",default:"general-privacy-consent",description:"Uruguay (Law 18.331)",locales:["es-UY"],compliance:["law18331-uy"],timezones:["America/Montevideo"]},VE:{name:"Venezuela",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Venezuela",locales:["es-VE"],compliance:[],timezones:["America/Caracas"]},AG:{name:"Antigua and Barbuda",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Antigua and Barbuda",locales:["en"],compliance:[],timezones:["America/Antigua"]},BB:{name:"Barbados",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Barbados",locales:["en"],compliance:[],timezones:["America/Barbados"]},BL:{name:"Saint Barth\xE9lemy",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Saint Barth\xE9lemy",locales:["fr-BL"],compliance:[],timezones:["America/St_Barthelemy"]},BM:{name:"Bermuda",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Bermuda",locales:["en"],compliance:[],timezones:["Atlantic/Bermuda"]},BS:{name:"Bahamas",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Bahamas",locales:["en"],compliance:[],timezones:["America/Nassau"]},CU:{name:"Cuba",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Cuba",locales:["es-CU"],compliance:[],timezones:["America/Havana"]},DM:{name:"Dominica",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Dominica",locales:["en"],compliance:[],timezones:["America/Dominica"]},GD:{name:"Grenada",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Grenada",locales:["en"],compliance:[],timezones:["America/Grenada"]},KN:{name:"Saint Kitts and Nevis",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Saint Kitts and Nevis",locales:["en"],compliance:[],timezones:["America/St_Kitts"]},LC:{name:"Saint Lucia",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Saint Lucia",locales:["en"],compliance:[],timezones:["America/St_Lucia"]},PM:{name:"Saint Pierre and Miquelon",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Saint Pierre and Miquelon",locales:["fr-PM"],compliance:[],timezones:["America/Miquelon"]},PR:{name:"Puerto Rico",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Puerto Rico",locales:["es-PR","en"],compliance:[],timezones:["America/Puerto_Rico"]},VC:{name:"Saint Vincent and the Grenadines",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Saint Vincent and the Grenadines",locales:["en"],compliance:[],timezones:["America/St_Vincent"]},IN:{name:"India",type:"country",complianceGroup:"opt-in-dpdpa",default:"opt-in-dpdpa",description:"India (DPDPA)",locales:["hi-IN","en","bn-IN","ta-IN"],compliance:["dpdpa"],timezones:["Asia/Kolkata","Asia/Calcutta"]},CN:{name:"China",type:"country",complianceGroup:"opt-in-china",default:"opt-in-china",description:"China (PIPL + DSL + CSL)",locales:["zh-CN"],compliance:["pipl","dsl-cn","csl-cn"],timezones:["Asia/Shanghai"]},BN:{name:"Brunei",type:"country",complianceGroup:"general-privacy-consent",default:"general-privacy-consent",description:"Brunei (Personal Data Protection Order)",locales:["ms-BN","en"],compliance:["privacy-bn"],timezones:["Asia/Brunei"]},ID:{name:"Indonesia",type:"country",complianceGroup:"general-privacy-consent",default:"general-privacy-consent",description:"Indonesia (PDP Law)",locales:["id-ID"],compliance:["pdp-id"],timezones:["Asia/Jakarta","Asia/Makassar","Asia/Jayapura"]},KH:{name:"Cambodia",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Cambodia",locales:["km-KH"],compliance:[],timezones:["Asia/Phnom_Penh"]},LA:{name:"Laos",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Laos",locales:["lo-LA"],compliance:[],timezones:["Asia/Vientiane"]},MM:{name:"Myanmar",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Myanmar",locales:["my-MM"],compliance:[],timezones:["Asia/Yangon"]},MY:{name:"Malaysia",type:"country",complianceGroup:"general-privacy-consent",default:"general-privacy-consent",description:"Malaysia (PDPA)",locales:["ms-MY","zh-MY","en"],compliance:["pdpa-my"],timezones:["Asia/Kuala_Lumpur","Asia/Kuching"]},PH:{name:"Philippines",type:"country",complianceGroup:"general-privacy-consent",default:"general-privacy-consent",description:"Philippines (DPA)",locales:["fil-PH","en"],compliance:["dpa-ph"],timezones:["Asia/Manila"]},SG:{name:"Singapore",type:"country",complianceGroup:"general-privacy-consent",default:"general-privacy-consent",description:"Singapore (PDPA)",locales:["zh-SG","ms-SG","ta-SG","en"],compliance:["pdpa-sg"],timezones:["Asia/Singapore"]},TH:{name:"Thailand",type:"country",complianceGroup:"opt-in",default:"opt-in",description:"Thailand (PDPA \u2014 GDPR-style opt-in)",locales:["th-TH"],compliance:["pdpa-th"],timezones:["Asia/Bangkok"]},TL:{name:"Timor-Leste",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Timor-Leste",locales:["pt-TL"],compliance:[],timezones:["Asia/Dili"]},VN:{name:"Vietnam",type:"country",complianceGroup:"general-privacy-consent",default:"general-privacy-consent",description:"Vietnam (PDPD)",locales:["vi-VN"],compliance:["pdpd-vn"],timezones:["Asia/Ho_Chi_Minh"]},HK:{name:"Hong Kong",type:"country",complianceGroup:"general-privacy-consent",default:"general-privacy-consent",description:"Hong Kong SAR (PDPO)",locales:["zh-HK"],compliance:["pdpl-hk"],timezones:["Asia/Hong_Kong"]},JP:{name:"Japan",type:"country",complianceGroup:"general-privacy-consent",default:"general-privacy-consent",description:"Japan (APPI)",locales:["ja-JP"],compliance:["appi"],timezones:["Asia/Tokyo"]},KP:{name:"North Korea",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"North Korea",locales:["ko-KP"],compliance:[],timezones:["Asia/Pyongyang"]},KR:{name:"South Korea",type:"country",complianceGroup:"general-privacy-consent",default:"general-privacy-consent",description:"South Korea (PIPA)",locales:["ko-KR"],compliance:["pipa-kr"],timezones:["Asia/Seoul"]},MN:{name:"Mongolia",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Mongolia",locales:["mn-MN"],compliance:[],timezones:["Asia/Ulaanbaatar","Asia/Hovd"]},MO:{name:"Macau",type:"country",complianceGroup:"general-privacy-consent",default:"general-privacy-consent",description:"Macau SAR (PDPA)",locales:["zh-MO","pt-MO"],compliance:["pdpa-mo"],timezones:["Asia/Macau"]},TW:{name:"Taiwan",type:"country",complianceGroup:"general-privacy-consent",default:"general-privacy-consent",description:"Taiwan (PDPL)",locales:["zh-TW"],compliance:["pdpl-tw"],timezones:["Asia/Taipei"]},AF:{name:"Afghanistan",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Afghanistan",locales:["fa-AF"],compliance:[],timezones:["Asia/Kabul"]},BD:{name:"Bangladesh",type:"country",complianceGroup:"general-privacy-consent",default:"general-privacy-consent",description:"Bangladesh",locales:["bn-BD"],compliance:[],timezones:["Asia/Dhaka"]},BT:{name:"Bhutan",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Bhutan",locales:["dz-BT"],compliance:[],timezones:["Asia/Thimphu"]},IO:{name:"British Indian Ocean Territory",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"British Indian Ocean Territory",locales:["en"],compliance:[],timezones:["Indian/Chagos"]},LK:{name:"Sri Lanka",type:"country",complianceGroup:"general-privacy-consent",default:"general-privacy-consent",description:"Sri Lanka",locales:["si-LK","ta-LK"],compliance:["privacy-lk"],timezones:["Asia/Colombo"]},MV:{name:"Maldives",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Maldives",locales:["dv-MV"],compliance:[],timezones:["Indian/Maldives"]},NP:{name:"Nepal",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Nepal",locales:["ne-NP"],compliance:["privacy-np"],timezones:["Asia/Kathmandu"]},PK:{name:"Pakistan",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Pakistan",locales:["ur-PK","en"],compliance:[],timezones:["Asia/Karachi"]},AM:{name:"Armenia",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Armenia",locales:["hy-AM"],compliance:[],timezones:["Asia/Yerevan"]},AZ:{name:"Azerbaijan",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Azerbaijan",locales:["az-AZ"],compliance:[],timezones:["Asia/Baku"]},GE:{name:"Georgia",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Georgia",locales:["ka-GE"],compliance:[],timezones:["Asia/Tbilisi"]},KG:{name:"Kyrgyzstan",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Kyrgyzstan",locales:["ky-KG","ru-KG"],compliance:[],timezones:["Asia/Bishkek"]},KZ:{name:"Kazakhstan",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Kazakhstan",locales:["kk-KZ","ru-KZ"],compliance:[],timezones:["Asia/Almaty","Asia/Aqtobe"]},TJ:{name:"Tajikistan",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Tajikistan",locales:["tg-TJ"],compliance:[],timezones:["Asia/Dushanbe"]},TM:{name:"Turkmenistan",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Turkmenistan",locales:["tk-TM"],compliance:[],timezones:["Asia/Ashgabat"]},UZ:{name:"Uzbekistan",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Uzbekistan",locales:["uz-UZ"],compliance:[],timezones:["Asia/Tashkent","Asia/Samarkand"]},AE:{name:"United Arab Emirates",type:"country",complianceGroup:"general-privacy-consent",default:"general-privacy-consent",description:"United Arab Emirates (UAE PDPL / DIFC DPL / ADGM DPR)",locales:["ar-AE"],compliance:["uae-pdpl","difc-dpl","adgm-dpr"],timezones:["Asia/Dubai"]},BH:{name:"Bahrain",type:"country",complianceGroup:"general-privacy-consent",default:"general-privacy-consent",description:"Bahrain (PDPL)",locales:["ar-BH"],compliance:["pdpl-bh"],timezones:["Asia/Bahrain"]},IL:{name:"Israel",type:"country",complianceGroup:"general-privacy-consent",default:"general-privacy-consent",description:"Israel (Privacy Protection Law)",locales:["he-IL","ar-IL"],compliance:["privacy-il"],timezones:["Asia/Jerusalem"]},IQ:{name:"Iraq",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Iraq",locales:["ar-IQ"],compliance:[],timezones:["Asia/Baghdad"]},IR:{name:"Iran",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Iran",locales:["fa-IR"],compliance:[],timezones:["Asia/Tehran"]},JO:{name:"Jordan",type:"country",complianceGroup:"general-privacy-consent",default:"general-privacy-consent",description:"Jordan",locales:["ar-JO"],compliance:[],timezones:["Asia/Amman"]},KW:{name:"Kuwait",type:"country",complianceGroup:"general-privacy-consent",default:"general-privacy-consent",description:"Kuwait",locales:["ar-KW"],compliance:["privacy-kw"],timezones:["Asia/Kuwait"]},LB:{name:"Lebanon",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Lebanon",locales:["ar-LB"],compliance:[],timezones:["Asia/Beirut"]},OM:{name:"Oman",type:"country",complianceGroup:"general-privacy-consent",default:"general-privacy-consent",description:"Oman (PDPL)",locales:["ar-OM"],compliance:["pdpl-om"],timezones:["Asia/Muscat"]},PS:{name:"Palestine",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Palestine",locales:["ar-PS"],compliance:[],timezones:["Asia/Gaza","Asia/Hebron"]},QA:{name:"Qatar",type:"country",complianceGroup:"general-privacy-consent",default:"general-privacy-consent",description:"Qatar (PDPL)",locales:["ar-QA"],compliance:["qpdl-qa"],timezones:["Asia/Qatar"]},SA:{name:"Saudi Arabia",type:"country",complianceGroup:"general-privacy-consent",default:"general-privacy-consent",description:"Saudi Arabia (PDPL)",locales:["ar-SA"],compliance:["pdpl-sa"],timezones:["Asia/Riyadh"]},SY:{name:"Syria",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Syria",locales:["ar-SY"],compliance:[],timezones:["Asia/Damascus"]},YE:{name:"Yemen",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Yemen",locales:["ar-YE"],compliance:[],timezones:["Asia/Aden"]},BF:{name:"Burkina Faso",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Burkina Faso",locales:["fr-BF"],compliance:[],timezones:["Africa/Ouagadougou"]},BJ:{name:"Benin",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Benin",locales:["fr-BJ"],compliance:[],timezones:["Africa/Porto-Novo"]},CI:{name:"C\xF4te d'Ivoire",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"C\xF4te d'Ivoire",locales:["fr-CI"],compliance:[],timezones:["Africa/Abidjan"]},CM:{name:"Cameroon",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Cameroon",locales:["fr-CM","en"],compliance:[],timezones:["Africa/Douala"]},CV:{name:"Cabo Verde",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Cabo Verde",locales:["pt-CV"],compliance:[],timezones:["Atlantic/Cape_Verde"]},GA:{name:"Gabon",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Gabon",locales:["fr-GA"],compliance:[],timezones:["Africa/Libreville"]},GH:{name:"Ghana",type:"country",complianceGroup:"general-privacy-consent",default:"general-privacy-consent",description:"Ghana (DPA)",locales:["en"],compliance:["dpa-gh"],timezones:["Africa/Accra"]},GM:{name:"Gambia",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Gambia",locales:["en"],compliance:[],timezones:["Africa/Banjul"]},GN:{name:"Guinea",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Guinea",locales:["fr-GN"],compliance:[],timezones:["Africa/Conakry"]},GQ:{name:"Equatorial Guinea",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Equatorial Guinea",locales:["es-GQ","fr-GQ"],compliance:[],timezones:["Africa/Malabo"]},GW:{name:"Guinea-Bissau",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Guinea-Bissau",locales:["pt-GW"],compliance:[],timezones:["Africa/Bissau"]},LR:{name:"Liberia",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Liberia",locales:["en"],compliance:[],timezones:["Africa/Monrovia"]},ML:{name:"Mali",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Mali",locales:["fr-ML"],compliance:[],timezones:["Africa/Bamako"]},MR:{name:"Mauritania",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Mauritania",locales:["ar-MR"],compliance:[],timezones:["Africa/Nouakchott"]},NE:{name:"Niger",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Niger",locales:["fr-NE"],compliance:[],timezones:["Africa/Niamey"]},NG:{name:"Nigeria",type:"country",complianceGroup:"general-privacy-consent",default:"general-privacy-consent",description:"Nigeria (NDPA)",locales:["en"],compliance:["ndpa-ng"],timezones:["Africa/Lagos"]},SL:{name:"Sierra Leone",type:"country",complianceGroup:"general-privacy-consent",default:"general-privacy-consent",description:"Sierra Leone",locales:["en"],compliance:[],timezones:["Africa/Freetown"]},SN:{name:"Senegal",type:"country",complianceGroup:"general-privacy-consent",default:"general-privacy-consent",description:"Senegal",locales:["fr-SN"],compliance:[],timezones:["Africa/Dakar"]},TG:{name:"Togo",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Togo",locales:["fr-TG"],compliance:[],timezones:["Africa/Lome"]},BI:{name:"Burundi",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Burundi",locales:["fr-BI"],compliance:[],timezones:["Africa/Bujumbura"]},DJ:{name:"Djibouti",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Djibouti",locales:["fr-DJ","ar-DJ"],compliance:[],timezones:["Africa/Djibouti"]},ER:{name:"Eritrea",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Eritrea",locales:["ti-ER"],compliance:[],timezones:["Africa/Asmara"]},ET:{name:"Ethiopia",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Ethiopia",locales:["am-ET"],compliance:[],timezones:["Africa/Addis_Ababa"]},KE:{name:"Kenya",type:"country",complianceGroup:"general-privacy-consent",default:"general-privacy-consent",description:"Kenya (DPA)",locales:["sw-KE","en"],compliance:["dpa-ke"],timezones:["Africa/Nairobi"]},KM:{name:"Comoros",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Comoros",locales:["ar-KM","fr-KM"],compliance:[],timezones:["Indian/Comoro"]},MG:{name:"Madagascar",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Madagascar",locales:["fr-MG"],compliance:[],timezones:["Indian/Antananarivo"]},MU:{name:"Mauritius",type:"country",complianceGroup:"general-privacy-consent",default:"general-privacy-consent",description:"Mauritius (DPA)",locales:["en","fr-MU"],compliance:["dpa-mu"],timezones:["Indian/Mauritius"]},MW:{name:"Malawi",type:"country",complianceGroup:"general-privacy-consent",default:"general-privacy-consent",description:"Malawi",locales:["en"],compliance:[],timezones:["Africa/Blantyre"]},MZ:{name:"Mozambique",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Mozambique",locales:["pt-MZ"],compliance:[],timezones:["Africa/Maputo"]},RW:{name:"Rwanda",type:"country",complianceGroup:"general-privacy-consent",default:"general-privacy-consent",description:"Rwanda (DPA)",locales:["rw-RW","en"],compliance:["dpa-rw"],timezones:["Africa/Kigali"]},SC:{name:"Seychelles",type:"country",complianceGroup:"general-privacy-consent",default:"general-privacy-consent",description:"Seychelles",locales:["fr-SC","en"],compliance:[],timezones:["Indian/Mahe"]},SO:{name:"Somalia",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Somalia",locales:["so-SO"],compliance:[],timezones:["Africa/Mogadishu"]},SS:{name:"South Sudan",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"South Sudan",locales:["en"],compliance:[],timezones:["Africa/Juba"]},ST:{name:"S\xE3o Tom\xE9 and Pr\xEDncipe",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"S\xE3o Tom\xE9 and Pr\xEDncipe",locales:["pt-ST"],compliance:[],timezones:["Africa/Sao_Tome"]},TZ:{name:"Tanzania",type:"country",complianceGroup:"general-privacy-consent",default:"general-privacy-consent",description:"Tanzania",locales:["sw-TZ","en"],compliance:[],timezones:["Africa/Dar_es_Salaam"]},UG:{name:"Uganda",type:"country",complianceGroup:"general-privacy-consent",default:"general-privacy-consent",description:"Uganda (DPA)",locales:["en"],compliance:["dpa-ug"],timezones:["Africa/Kampala"]},AO:{name:"Angola",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Angola",locales:["pt-AO"],compliance:[],timezones:["Africa/Luanda"]},BW:{name:"Botswana",type:"country",complianceGroup:"general-privacy-consent",default:"general-privacy-consent",description:"Botswana (DPA)",locales:["en"],compliance:["dpa-bw"],timezones:["Africa/Gaborone"]},LS:{name:"Lesotho",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Lesotho",locales:["en"],compliance:[],timezones:["Africa/Maseru"]},NA:{name:"Namibia",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Namibia",locales:["en"],compliance:[],timezones:["Africa/Windhoek"]},SZ:{name:"Eswatini",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Eswatini",locales:["en"],compliance:[],timezones:["Africa/Mbabane"]},ZA:{name:"South Africa",type:"country",complianceGroup:"general-privacy-consent",default:"general-privacy-consent",description:"South Africa (POPIA)",locales:["en","af-ZA"],compliance:["popia"],timezones:["Africa/Johannesburg"]},ZM:{name:"Zambia",type:"country",complianceGroup:"general-privacy-consent",default:"general-privacy-consent",description:"Zambia (DPA)",locales:["en"],compliance:["dpa-zm"],timezones:["Africa/Lusaka"]},ZW:{name:"Zimbabwe",type:"country",complianceGroup:"general-privacy-consent",default:"general-privacy-consent",description:"Zimbabwe (DPA)",locales:["en"],compliance:["dpa-zw"],timezones:["Africa/Harare"]},DZ:{name:"Algeria",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Algeria",locales:["ar-DZ","fr-DZ"],compliance:["dpa-dz"],timezones:["Africa/Algiers"]},EG:{name:"Egypt",type:"country",complianceGroup:"general-privacy-consent",default:"general-privacy-consent",description:"Egypt (DPA)",locales:["ar-EG"],compliance:["dpa-eg"],timezones:["Africa/Cairo"]},LY:{name:"Libya",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Libya",locales:["ar-LY"],compliance:[],timezones:["Africa/Tripoli"]},MA:{name:"Morocco",type:"country",complianceGroup:"general-privacy-consent",default:"general-privacy-consent",description:"Morocco",locales:["ar-MA","fr-MA"],compliance:["dpa-ma"],timezones:["Africa/Casablanca"]},SD:{name:"Sudan",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Sudan",locales:["ar-SD"],compliance:[],timezones:["Africa/Khartoum"]},TN:{name:"Tunisia",type:"country",complianceGroup:"general-privacy-consent",default:"general-privacy-consent",description:"Tunisia (DPA)",locales:["ar-TN","fr-TN"],compliance:["dpa-tn"],timezones:["Africa/Tunis"]},CD:{name:"DR Congo",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"DR Congo",locales:["fr-CD"],compliance:[],timezones:["Africa/Kinshasa","Africa/Lubumbashi"]},CF:{name:"Central African Republic",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Central African Republic",locales:["fr-CF"],compliance:[],timezones:["Africa/Bangui"]},CG:{name:"Republic of Congo",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Republic of Congo",locales:["fr-CG"],compliance:[],timezones:["Africa/Brazzaville"]},TD:{name:"Chad",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Chad",locales:["fr-TD","ar-TD"],compliance:[],timezones:["Africa/Ndjamena"]},BY:{name:"Belarus",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Belarus",locales:["be-BY","ru-BY"],compliance:[],timezones:["Europe/Minsk"]},MD:{name:"Moldova",type:"country",complianceGroup:"general-privacy-consent",default:"general-privacy-consent",description:"Moldova",locales:["ro-MD"],compliance:[],timezones:["Europe/Chisinau"]},RU:{name:"Russia",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Russia",locales:["ru-RU"],compliance:[],timezones:["Europe/Kaliningrad","Europe/Moscow","Europe/Samara","Asia/Yekaterinburg","Asia/Omsk","Asia/Krasnoyarsk","Asia/Irkutsk","Asia/Yakutsk","Asia/Vladivostok","Asia/Magadan","Asia/Kamchatka"]},UA:{name:"Ukraine",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Ukraine",locales:["uk-UA"],compliance:[],timezones:["Europe/Kyiv"]},VA:{name:"Holy See",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Holy See",locales:["it-VA"],compliance:[],timezones:["Europe/Vatican"]},AU:{name:"Australia",type:"country",complianceGroup:"general-privacy-consent",default:"general-privacy-consent",description:"Australia (Privacy Act)",locales:["en"],compliance:["privacy-au"],timezones:["Australia/Sydney","Australia/Brisbane","Australia/Adelaide","Australia/Darwin","Australia/Perth","Australia/Hobart"]},FJ:{name:"Fiji",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Fiji",locales:["en"],compliance:["privacy-fj"],timezones:["Pacific/Fiji"]},FM:{name:"Micronesia",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Micronesia",locales:["en"],compliance:[],timezones:["Pacific/Chuuk","Pacific/Pohnpei","Pacific/Kosrae"]},KI:{name:"Kiribati",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Kiribati",locales:["en"],compliance:[],timezones:["Pacific/Tarawa","Pacific/Enderbury","Pacific/Kiritimati"]},MH:{name:"Marshall Islands",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Marshall Islands",locales:["en"],compliance:[],timezones:["Pacific/Majuro","Pacific/Kwajalein"]},MP:{name:"Northern Mariana Islands",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Northern Mariana Islands",locales:["en"],compliance:[],timezones:["Pacific/Saipan"]},NC:{name:"New Caledonia",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"New Caledonia",locales:["fr-NC"],compliance:[],timezones:["Pacific/Noumea"]},NF:{name:"Norfolk Island",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Norfolk Island",locales:["en"],compliance:[],timezones:["Pacific/Norfolk"]},NR:{name:"Nauru",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Nauru",locales:["en"],compliance:[],timezones:["Pacific/Nauru"]},NU:{name:"Niue",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Niue",locales:["en"],compliance:[],timezones:["Pacific/Niue"]},NZ:{name:"New Zealand",type:"country",complianceGroup:"general-privacy-consent",default:"general-privacy-consent",description:"New Zealand (Privacy Act)",locales:["en"],compliance:["privacy-nz"],timezones:["Pacific/Auckland","Pacific/Chatham"]},PF:{name:"French Polynesia",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"French Polynesia",locales:["fr-PF"],compliance:[],timezones:["Pacific/Tahiti","Pacific/Marquesas","Pacific/Gambier"]},PG:{name:"Papua New Guinea",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Papua New Guinea",locales:["en"],compliance:["privacy-pg"],timezones:["Pacific/Port_Moresby","Pacific/Bougainville"]},PW:{name:"Palau",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Palau",locales:["en"],compliance:[],timezones:["Pacific/Palau"]},SB:{name:"Solomon Islands",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Solomon Islands",locales:["en"],compliance:[],timezones:["Pacific/Guadalcanal"]},TO:{name:"Tonga",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Tonga",locales:["en"],compliance:[],timezones:["Pacific/Tongatapu"]},TV:{name:"Tuvalu",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Tuvalu",locales:["en"],compliance:[],timezones:["Pacific/Funafuti"]},VU:{name:"Vanuatu",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Vanuatu",locales:["fr-VU","en"],compliance:[],timezones:["Pacific/Efate"]},WS:{name:"Samoa",type:"country",complianceGroup:"notice-only",default:"notice-only",description:"Samoa",locales:["en"],compliance:[],timezones:["Pacific/Apia"]},UK:{name:"United Kingdom",type:"country",complianceGroup:"opt-in",default:"opt-in",description:"United Kingdom (UK GDPR + PECR)",locales:["en"],compliance:["uk-gdpr","pecr"],timezones:["Europe/London"]},CH:{name:"Switzerland",type:"country",complianceGroup:"opt-in",default:"opt-in",description:"Switzerland (revFADP)",locales:["de-CH","fr-CH","it-CH"],compliance:["revfadp"],timezones:["Europe/Zurich"]}}},Sr={GB:"UK",UK:"GB"};ud=[...Object.values(Ce.countries).reduce((i,e)=>(e.compliance.forEach(t=>{i.add(t)}),i),new Set)],pd=Object.entries(Ce.countries).reduce(function(i,[e,t]){return i[e]=t.name,i},{}),md=Object.values(Ce.countries).reduce(function(i,e){return e.locales.forEach(t=>{i[t]=e.name}),i},{})});function hd(i){let e=i.trim();if(!e)return;let t=Ei.find(o=>!o.pattern.endsWith("*")&&o.pattern===e);if(t)return t;let n=Ei.filter(o=>o.pattern.endsWith("*")&&e.startsWith(o.pattern.slice(0,-1)));if(n.length!==0)return n.reduce((o,s)=>s.pattern.length>o.pattern.length?s:o)}var Ei,Cr=I(()=>{"use strict";p();Ei=[{pattern:"security_storage",vendor:"Google Consent Mode v2",category:"necessary"},{pattern:"functionality_storage",vendor:"Google Consent Mode v2",category:"functional"},{pattern:"personalization_storage",vendor:"Google Consent Mode v2",category:"preferences"},{pattern:"analytics_storage",vendor:"Google Consent Mode v2",category:"analytics"},{pattern:"ad_storage",vendor:"Google Consent Mode v2",category:"marketing"},{pattern:"ad_user_data",vendor:"Google Consent Mode v2",category:"marketing"},{pattern:"ad_personalization",vendor:"Google Consent Mode v2",category:"marketing"},{pattern:"_ga",vendor:"Google Analytics",category:"analytics"},{pattern:"_ga_*",vendor:"Google Analytics 4",category:"analytics"},{pattern:"_gid",vendor:"Google Analytics",category:"analytics"},{pattern:"_gat",vendor:"Google Analytics",category:"analytics"},{pattern:"_gat_*",vendor:"Google Analytics",category:"analytics"},{pattern:"_gcl_au",vendor:"Google Ads",category:"marketing"},{pattern:"_gac_*",vendor:"Google Ads",category:"marketing"},{pattern:"_gcl_aw",vendor:"Google Ads",category:"marketing"},{pattern:"_fbp",vendor:"Meta Pixel",category:"marketing"},{pattern:"_fbc",vendor:"Meta Pixel",category:"marketing"},{pattern:"fr",vendor:"Meta Pixel",category:"marketing"},{pattern:"_hjSessionUser_*",vendor:"Hotjar",category:"analytics"},{pattern:"_hjSession_*",vendor:"Hotjar",category:"analytics"},{pattern:"_hjid",vendor:"Hotjar",category:"analytics"},{pattern:"hjViewportId",vendor:"Hotjar",category:"analytics"},{pattern:"ajs_user_id",vendor:"Segment",category:"analytics"},{pattern:"ajs_anonymous_id",vendor:"Segment",category:"analytics"},{pattern:"ajs_group_id",vendor:"Segment",category:"analytics"},{pattern:"intercom-id-*",vendor:"Intercom",category:"functional"},{pattern:"intercom-session-*",vendor:"Intercom",category:"functional"},{pattern:"intercom-device-id-*",vendor:"Intercom",category:"functional"},{pattern:"__hstc",vendor:"HubSpot",category:"marketing"},{pattern:"hubspotutk",vendor:"HubSpot",category:"marketing"},{pattern:"__hssc",vendor:"HubSpot",category:"marketing"},{pattern:"__hssrc",vendor:"HubSpot",category:"marketing"},{pattern:"mp_*",vendor:"Mixpanel",category:"analytics"},{pattern:"li_sugr",vendor:"LinkedIn Insight",category:"marketing"},{pattern:"bcookie",vendor:"LinkedIn Insight",category:"marketing"},{pattern:"lidc",vendor:"LinkedIn Insight",category:"marketing"},{pattern:"UserMatchHistory",vendor:"LinkedIn Insight",category:"marketing"},{pattern:"_ttp",vendor:"TikTok Pixel",category:"marketing"},{pattern:"_clck",vendor:"Microsoft Clarity",category:"analytics"},{pattern:"_clsk",vendor:"Microsoft Clarity",category:"analytics"},{pattern:"_pinterest_ct*",vendor:"Pinterest Tag",category:"marketing"},{pattern:"_pin_unauth",vendor:"Pinterest Tag",category:"marketing"},{pattern:"personalization_id",vendor:"X (Twitter) Pixel",category:"marketing"},{pattern:"amplitude_id_*",vendor:"Amplitude",category:"analytics"},{pattern:"__stripe_mid",vendor:"Stripe",category:"necessary"},{pattern:"__stripe_sid",vendor:"Stripe",category:"necessary"},{pattern:"__cf_bm",vendor:"Cloudflare",category:"necessary"},{pattern:"cf_clearance",vendor:"Cloudflare",category:"necessary"},{pattern:"_zendesk_*",vendor:"Zendesk",category:"functional"},{pattern:"drift_aid",vendor:"Drift",category:"functional"},{pattern:"driftt_aid",vendor:"Drift",category:"functional"},{pattern:"crisp-client*",vendor:"Crisp",category:"functional"},{pattern:"AMCV_*",vendor:"Adobe Experience Cloud",category:"analytics"},{pattern:"AMCVS_*",vendor:"Adobe Experience Cloud",category:"analytics"},{pattern:"s_cc",vendor:"Adobe Analytics",category:"analytics"},{pattern:"s_sq",vendor:"Adobe Analytics",category:"analytics"},{pattern:"s_vi",vendor:"Adobe Analytics",category:"analytics"},{pattern:"mbox",vendor:"Adobe Target",category:"preferences"},{pattern:"_mkto_trk",vendor:"Marketo",category:"marketing"},{pattern:"cto_bundle",vendor:"Criteo",category:"marketing"},{pattern:"cto_id_out",vendor:"Criteo",category:"marketing"},{pattern:"TTD_DEVICE_ID",vendor:"The Trade Desk",category:"marketing"},{pattern:"ttd_*",vendor:"The Trade Desk",category:"marketing"},{pattern:"id",vendor:"Google DoubleClick",category:"marketing"},{pattern:"IDE",vendor:"Google DoubleClick",category:"marketing"},{pattern:"DSID",vendor:"Google DoubleClick",category:"marketing"},{pattern:"KADUSERCOOKIE",vendor:"PubMatic",category:"marketing"},{pattern:"rubicon_user_*",vendor:"Rubicon Project",category:"marketing"},{pattern:"Anonymon_id",vendor:"OpenX",category:"marketing"},{pattern:"pdomid",vendor:"OpenX",category:"marketing"},{pattern:"uuid2",vendor:"AppNexus",category:"marketing"},{pattern:"icu",vendor:"AppNexus",category:"marketing"},{pattern:"_scid",vendor:"Snap Pixel",category:"marketing"},{pattern:"_sc_cspv",vendor:"Snap Pixel",category:"marketing"},{pattern:"_rdt_uuid",vendor:"Reddit Pixel",category:"marketing"},{pattern:"obuid",vendor:"Outbrain",category:"marketing"},{pattern:"t_gid",vendor:"Taboola",category:"marketing"},{pattern:"__kla_id",vendor:"Klaviyo",category:"marketing"},{pattern:"sc_anonymous_id",vendor:"Salesforce Marketing Cloud",category:"marketing"},{pattern:"vst",vendor:"Salesforce Marketing Cloud",category:"marketing"},{pattern:"visitor_id*",vendor:"Salesforce Pardot",category:"marketing"},{pattern:"piAId",vendor:"Salesforce Pardot",category:"marketing"},{pattern:"exp_last_visit",vendor:"ActiveCampaign",category:"marketing"},{pattern:"exp_tracker",vendor:"ActiveCampaign",category:"marketing"},{pattern:"_ce.s*",vendor:"Crazy Egg",category:"analytics"},{pattern:"lr_*",vendor:"LogRocket",category:"analytics"},{pattern:"_hp2_id.*",vendor:"Heap Analytics",category:"analytics"},{pattern:"_hp2_ses.*",vendor:"Heap Analytics",category:"analytics"},{pattern:"_lo_*",vendor:"Lucky Orange",category:"analytics"},{pattern:"fs_uid",vendor:"FullStory",category:"analytics"},{pattern:"_fs_*",vendor:"FullStory",category:"analytics"},{pattern:"ln_or",vendor:"LiveSession",category:"analytics"},{pattern:"_vwo_uuid*",vendor:"Visual Website Optimizer (VWO)",category:"analytics"},{pattern:"_vis_opt_*",vendor:"Visual Website Optimizer (VWO)",category:"analytics"},{pattern:"OptimizelyBuckets",vendor:"Optimizely",category:"analytics"},{pattern:"optimizelyEndUserId",vendor:"Optimizely",category:"analytics"},{pattern:"OptanonConsent",vendor:"OneTrust",category:"necessary"},{pattern:"OptanonAlertBoxClosed",vendor:"OneTrust",category:"necessary"},{pattern:"SyrenisCookieConsentDate_*",vendor:"Syrenis Cassie",category:"necessary"},{pattern:"SyrenisCookieFormConsent_*",vendor:"Syrenis Cassie",category:"necessary"},{pattern:"SyrenisCookiePrivacyLink_*",vendor:"Syrenis Cassie",category:"necessary"},{pattern:"SyrenisGtmConsent_*",vendor:"Syrenis Cassie",category:"necessary"},{pattern:"SyrenisGuid_*",vendor:"Syrenis Cassie",category:"necessary"},{pattern:"CookieConsent",vendor:"Cookiebot",category:"necessary"},{pattern:"uc_settings",vendor:"Usercentrics",category:"necessary"},{pattern:"uc_user_interaction",vendor:"Usercentrics",category:"necessary"},{pattern:"didomi_token",vendor:"Didomi",category:"necessary"},{pattern:"euconsent-v2",vendor:"IAB TCF Global Vendor List",category:"necessary"},{pattern:"cconsent",vendor:"Cookie Consent Studio",category:"necessary"},{pattern:"JSESSIONID",vendor:"New Relic",category:"necessary"},{pattern:"NRAGENT",vendor:"New Relic",category:"necessary"},{pattern:"_dd_s",vendor:"Datadog",category:"necessary"},{pattern:"dtCookie",vendor:"Dynatrace",category:"necessary"},{pattern:"dtPC",vendor:"Dynatrace",category:"necessary"},{pattern:"rxVisitor",vendor:"Dynatrace",category:"necessary"},{pattern:"ak_bmsc",vendor:"Akamai",category:"necessary"},{pattern:"_abck",vendor:"Akamai",category:"necessary"},{pattern:"vuid",vendor:"Vimeo",category:"analytics"},{pattern:"__cf_vuid",vendor:"Vimeo",category:"analytics"},{pattern:"VISITOR_INFO1_LIVE",vendor:"YouTube",category:"marketing"},{pattern:"YSC",vendor:"YouTube",category:"necessary"},{pattern:"GPS",vendor:"YouTube",category:"marketing"},{pattern:"_wistia_*",vendor:"Wistia",category:"analytics"},{pattern:"_elvr_*",vendor:"Elevar",category:"analytics"},{pattern:"stkn",vendor:"Shopify Core Analytics",category:"analytics"},{pattern:"rmStore*",vendor:"Rakuten Advertising",category:"marketing"},{pattern:"_ir_*",vendor:"Impact Radius",category:"marketing"},{pattern:"aw*",vendor:"Awin",category:"marketing"},{pattern:"bctc",vendor:"Awin",category:"marketing"},{pattern:"mcookie",vendor:"CJ Affiliate",category:"marketing"},{pattern:"_shopify_y",vendor:"Shopify",category:"analytics"},{pattern:"_shopify_s",vendor:"Shopify",category:"analytics"},{pattern:"_shopify_sa_p",vendor:"Shopify",category:"marketing"},{pattern:"shopify_sa_t",vendor:"Shopify",category:"marketing"},{pattern:"cart_sig",vendor:"Shopify",category:"necessary"},{pattern:"secure_customer_sig",vendor:"Shopify",category:"necessary"},{pattern:"wp_woocommerce_session*",vendor:"WooCommerce",category:"necessary"},{pattern:"woocommerce_items_in_cart",vendor:"WooCommerce",category:"necessary"},{pattern:"woocommerce_cart_hash",vendor:"WooCommerce",category:"necessary"},{pattern:"QSI_",vendor:"Qualtrics",category:"functional"},{pattern:"feedback_id",vendor:"SurveyMonkey",category:"functional"},{pattern:"usbl.",vendor:"Usabilla",category:"functional"}]});function Ar(i){return i.map(Ri).join("")}function Ri(i){return i.t==="text"?yd(i.v):i.t==="br"?"<br>":i.t==="a"?`<a href="${_d(i.href)}">${i.c.map(Ri).join("")}</a>`:`<${i.t}>${i.c.map(Ri).join("")}</${i.t}>`}function yd(i){return i.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;")}function _d(i){return i.replace(/"/g,"&quot;").replace(/</g,"&lt;")}function wd(i){if(!i)return"";let e=i.trim();if(e.startsWith("["))try{return Ar(JSON.parse(e))}catch{}return i}function Tr(i){return i.t==="text"?i.v.trim().length>0:i.t==="br"?!1:i.c.some(Tr)}function Ed(i){return i.replace(/<[^>]*>/g,"").trim().length>0}function pn(i){if(!i)return!1;let e=i.trim();if(!e)return!1;if(e.startsWith("["))try{return JSON.parse(e).some(Tr)}catch{}return Ed(e)}var Ir=I(()=>{"use strict";p()});function Rd(i){return new TextEncoder().encode(i)}function Sd(i){return new TextDecoder().decode(i)}function vd(i){let e="";for(let t=0;t<i.length;t+=3){let n=i[t]??0,o=t+1<i.length?i[t+1]??0:0,s=t+2<i.length?i[t+2]??0:0;e+=ut[n>>2],e+=ut[(n&3)<<4|o>>4],t+1<i.length&&(e+=ut[(o&15)<<2|s>>6]),t+2<i.length&&(e+=ut[s&63])}return e}function Cd(i){let e=new Map(ut.split("").map((o,s)=>[o,s])),t=i.replace(/[^A-Za-z0-9\-_]/g,""),n=[];for(let o=0;o<t.length;o+=4){let s=e.get(t[o]??"")??0,r=e.get(t[o+1]??"")??0,a=t[o+2]!==void 0?e.get(t[o+2]):void 0,c=t[o+3]!==void 0?e.get(t[o+3]):void 0;n.push(s<<2|r>>4),a!==void 0&&n.push((r&15)<<4|a>>2),c!==void 0&&n.push(((a??0)&3)<<6|c)}return new Uint8Array(n)}function Si(i){let e={v:2,ts:Math.floor(Date.now()/100),cmpId:i.cmpId,cmpV:i.cmpVersion,cs:i.consentScreen,lang:i.consentLanguage.toUpperCase().slice(0,2),vlV:i.vendorListVersion,pc:i.purposeConsents,vc:i.vendorConsents};return vd(Rd(JSON.stringify(e)))}function Ad(i){try{let e=JSON.parse(Sd(Cd(i)));return{version:e.v,cmpId:e.cmpId,consentLanguage:e.lang,purposeConsents:Array.isArray(e.pc)?e.pc:[],vendorConsents:Array.isArray(e.vc)?e.vc:[],created:e.ts*100}}catch{return null}}var ut,Pr=I(()=>{"use strict";p();ut="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"});function Td(i){return new TextEncoder().encode(i)}function Id(i){return new TextDecoder().decode(i)}function Pd(i){let e="";for(let t=0;t<i.length;t+=3){let n=i[t]??0,o=t+1<i.length?i[t+1]??0:0,s=t+2<i.length?i[t+2]??0:0;e+=pt[n>>2],e+=pt[(n&3)<<4|o>>4],t+1<i.length&&(e+=pt[(o&15)<<2|s>>6]),t+2<i.length&&(e+=pt[s&63])}return e}function bd(i){let e=new Map(pt.split("").map((o,s)=>[o,s])),t=i.replace(/[^A-Za-z0-9\-_]/g,""),n=[];for(let o=0;o<t.length;o+=4){let s=e.get(t[o]??"")??0,r=e.get(t[o+1]??"")??0,a=t[o+2]!==void 0?e.get(t[o+2]):void 0,c=t[o+3]!==void 0?e.get(t[o+3]):void 0;n.push(s<<2|r>>4),a!==void 0&&n.push((r&15)<<4|a>>2),c!==void 0&&n.push(((a??0)&3)<<6|c)}return new Uint8Array(n)}function vi(i,e){return i?e?Dd:kd:Od}function Ci(i){let e={v:1,ts:Math.floor(Date.now()/100),cmpId:i.cmpId,cmpV:i.cmpVersion,sect:"usnat",saleOO:vi(i.saleApplicable,i.saleOptOut),shareOO:vi(i.sharingApplicable,i.sharingOptOut),taOO:vi(i.sharingApplicable,i.sharingOptOut),mspaCT:i.mspaCoveredTransaction?1:2,mspaOOM:i.mspaOptOutOptionMode,mspaSPM:i.mspaServiceProviderMode,...i.gpcDetected!==void 0?{gpc:i.gpcDetected}:{}};return Pd(Td(JSON.stringify(e)))}function Ld(i){try{let e=JSON.parse(Id(bd(i)));return{version:e.v,cmpId:e.cmpId,cmpVersion:e.cmpV,saleOptOut:e.saleOO,sharingOptOut:e.shareOO,targetedAdvertisingOptOut:e.taOO,...e.gpc!==void 0?{gpc:e.gpc}:{},created:e.ts*100}}catch{return null}}var pt,Od,Dd,kd,br=I(()=>{"use strict";p();pt="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";Od=0,Dd=1,kd=2});function xd(i,e){if(e==="ltr"||e==="rtl")return e;try{let n=new Intl.Locale(i).getTextInfo?.().direction;if(n==="ltr"||n==="rtl")return n}catch{}let t=i.slice(0,2).toLowerCase();return Nd.includes(t)?"rtl":"ltr"}var Nd,Or=I(()=>{"use strict";p();Nd=["ar","he","fa","ur","ps","sd","ug","yi"]});var Dr={};Un(Dr,{COMPLIANCE_GROUPS:()=>dt,COMPLIANCE_GROUP_IDS:()=>dn,COMPLIANCE_REGULATION_IDS:()=>ud,COMPLIANCE_VALIDATION_RULES:()=>yi,COOKIE_PURPOSES:()=>sd,COOKIE_PURPOSE_DEFAULTS:()=>rd,COOKIE_PURPOSE_IDS:()=>un,COUNTRY_CODES:()=>pd,CPRA_CATEGORIES:()=>od,DEFAULT_PROFILES:()=>ln,EMBEDDED_COMPLIANCE_MAP:()=>Ce,GPC_OPTIONS:()=>nd,KNOWN_COOKIE_PURPOSES:()=>Rr,LEGAL_BASIS_OPTIONS:()=>id,LOCALES:()=>md,TCF_PURPOSES:()=>cd,TCF_SPECIAL_FEATURES:()=>ld,TRACKER_KNOWLEDGE_BASE:()=>Ei,buildCookieCategoryIndex:()=>We,color:()=>X,debounce:()=>Kl,decodeGppString:()=>Ld,decodeTcString:()=>Ad,encodeGppString:()=>Ci,encodeTcString:()=>Si,findCategoryForCookie:()=>dd,findCountryEntry:()=>_i,formatLog:()=>td,getCookieLegalBasis:()=>qe,hasVisibleText:()=>pn,inferCookiePurpose:()=>ad,isMandatoryCookie:()=>hi,jsonToHtml:()=>Ar,matchTrackerKnowledge:()=>hd,renderContentText:()=>wd,resolveComplianceMapOverride:()=>wi,resolveTextDirection:()=>xd,statusLabel:()=>Xl,throttle:()=>Yl});var se=I(()=>{"use strict";p();_r();wr();Er();vr();Cr();Ir();Pr();br();Or();fi()});var bu={};Un(bu,{CategoryAction:()=>Dn,ConsentAction:()=>On,MongoDBAdapter:()=>Fe,MySQLAdapter:()=>He,PostgreSQLAdapter:()=>Ve,SQLiteAdapter:()=>De,createConsenti:()=>Pu,dashboardDir:()=>Ru});module.exports=Uc(bu);p();var Ec=require("node:events"),Rc=require("node:crypto"),Ye=require("node:fs/promises"),V=require("node:path"),$i=require("node:url");p();var Tt=class{plugins=[];register(e){this.plugins=e}async initialize(e){for(let t of this.plugins)try{await t.initialize?.(e)}catch(n){console.warn(`[Consenti] Plugin "${t.name}" initialize failed:`,n)}}async destroy(){for(let e of this.plugins)try{await e.destroy?.()}catch(t){console.warn(`[Consenti] Plugin "${e.name}" destroy failed:`,t)}}async runBeforeConsentSave(e){let t=e;for(let n of this.plugins)if(n.beforeConsentSave)try{t=await n.beforeConsentSave(t)}catch(o){console.warn(`[Consenti] Plugin "${n.name}" beforeConsentSave failed:`,o)}return t}async runAfterConsentSave(e){for(let t of this.plugins)if(t.afterConsentSave)try{await t.afterConsentSave(e)}catch(n){console.warn(`[Consenti] Plugin "${t.name}" afterConsentSave failed:`,n)}}async runBeforeConsentUpdate(e){let t=e;for(let n of this.plugins)if(n.beforeConsentUpdate)try{t=await n.beforeConsentUpdate(t)}catch(o){console.warn(`[Consenti] Plugin "${n.name}" beforeConsentUpdate failed:`,o)}return t}async runAfterConsentUpdate(e){for(let t of this.plugins)if(t.afterConsentUpdate)try{await t.afterConsentUpdate(e)}catch(n){console.warn(`[Consenti] Plugin "${t.name}" afterConsentUpdate failed:`,n)}}async runAfterProfileFetch(e){let t=e;for(let n of this.plugins)if(n.afterProfileFetch)try{t=await n.afterProfileFetch(t)}catch(o){console.warn(`[Consenti] Plugin "${n.name}" afterProfileFetch failed:`,o)}return t}async runBeforeUserCreate(e){let t=e;for(let n of this.plugins)if(n.beforeUserCreate)try{t=await n.beforeUserCreate(t)}catch(o){console.warn(`[Consenti] Plugin "${n.name}" beforeUserCreate failed:`,o)}return t}async runAfterUserCreate(e){for(let t of this.plugins)if(t.afterUserCreate)try{await t.afterUserCreate(e)}catch(n){console.warn(`[Consenti] Plugin "${t.name}" afterUserCreate failed:`,n)}}};p();var Mn=require("node:fs"),Xi=require("node:path");function eo(i,e,t={},n={},o="local"){let s={};return n.type!==void 0&&(s.type=n.type),n.gpc!==void 0&&(s.gpc=n.gpc),{appName:t.appName??"Consenti",appLogoPath:t?.appLogoPath??"/logo-dark.svg",hidePoweredBy:t.hidePoweredBy??!1,basePath:e,compliance:s,authMode:o}}function to(i){return`<script>(function(){function d(o){if(o&&typeof o==='object')Object.keys(o).forEach(function(k){d(o[k])});return Object.freeze(o)}Object.defineProperty(window,'__CONSENTI_CONFIG__',{value:d(${JSON.stringify(i).replace(/<\/script>/gi,"<\\/script>")}),writable:false,configurable:false,enumerable:true})})()</script>`}function Ze(i,e){let t=Buffer.from(i).toString("utf-8");return t.includes("</head>")?t.replace("</head>",`${e}</head>`):t.replace("</body>",`${e}</body>`)}p();var Gc="https://vendor-list.consensu.org/v3/vendor-list.json";var Pe=null,no=0,Xe=null;function jc(i){return typeof i=="object"&&i!==null&&"vendors"in i&&"purposes"in i&&typeof i.vendors=="object"&&typeof i.purposes=="object"}async function be(){if(Pe&&Date.now()-no<6048e5)return Pe;try{let i=await fetch(Gc,{signal:AbortSignal.timeout(15e3)});if(!i.ok)return Pe;let e=await i.json();if(!jc(e))return Pe;let t=e;return Pe={gvlSpecificationVersion:t.gvlSpecificationVersion,vendorListVersion:t.vendorListVersion,tcfPolicyVersion:t.tcfPolicyVersion,vendors:t.vendors,purposes:t.purposes,raw:t},no=Date.now(),Pe}catch{return Pe}}function io(){Xe||(be(),Xe=setInterval(()=>{be()},6048e5))}function oo(){Xe&&(clearInterval(Xe),Xe=null)}p();var Bc="https://vendor-list.consensu.org/v3/cmp-list.json";var Oe=null,so=0,et=null;function $c(i){return typeof i=="object"&&i!==null&&"cmps"in i&&typeof i.cmps=="object"}async function tt(i=!1){if(!i&&Oe&&Date.now()-so<6048e5)return Oe;try{let e=await fetch(Bc,{signal:AbortSignal.timeout(15e3)});if(!e.ok)return Oe;let t=await e.json();if(!$c(t))return Oe;let n=t;return Oe={cmpListVersion:n.cmpListVersion,lastUpdated:n.lastUpdated,cmps:n.cmps},so=Date.now(),Oe}catch{return Oe}}function ro(){et||(tt(),et=setInterval(()=>{tt()},6048e5))}function ao(){et&&(clearInterval(et),et=null)}p();var co={ConsentRecord:{type:"object",properties:{id:{type:"string"},visitorId:{type:"string"},profileId:{type:"string"},profileVersion:{type:"integer",description:"Profile version in force when this consent was last given; with `profileId` it pins the exact on-disk snapshot (the banner text shown). Absent on records created before it was tracked."},locale:{type:"string"},consentJson:{type:"object",additionalProperties:{type:"string",enum:["granted","denied","objected"]}},gpcDetected:{type:"boolean"},source:{type:"string",enum:["banner","api","import"]},ageVerified:{type:"boolean"},tcfString:{type:"string"},createdAt:{type:"string",format:"date-time"},updatedAt:{type:"string",format:"date-time"}}},CreateConsentInput:{type:"object",required:["visitorId","profileId","consentJson"],properties:{visitorId:{type:"string"},profileId:{type:"string"},consentJson:{type:"object",additionalProperties:{type:"string"}},gpcDetected:{type:"boolean",default:!1},source:{type:"string",enum:["banner","api","import"],default:"banner"},ageVerified:{type:"boolean"},parentalConsentToken:{type:"string"},tcfString:{type:"string"}}}},Gn={openapi:"3.1.0",info:{title:"Consenti Public API",version:"0.1.0",description:"Visitor-facing endpoints for reading consent profiles and submitting/verifying consent. Rate-limited; no authentication required.",license:{name:"Apache 2.0",url:"https://www.apache.org/licenses/LICENSE-2.0"}},servers:[{url:"/consenti/api",description:"Consenti Public API"}],paths:{"/v1/profiles/{id}":{get:{tags:["Profile"],summary:"Get profile in its default locale",description:"Returns the resolved profile with banner and modal content for the profile's default locale. Includes `currentLocale`, `locales`, `cookies`, `mainBanner`, `preferenceModal`, and optionally `gpcBanner`.",parameters:[{name:"id",in:"path",required:!0,schema:{type:"string"}}],responses:{200:{description:"Resolved profile for the default locale"},404:{description:"Profile not found"}}}},"/v1/profiles/{id}/{locale}":{get:{tags:["Profile"],summary:"Get profile resolved for a specific locale",description:"Same response shape as `GET /v1/profiles/{id}` but resolved for the requested locale, falling back to the default locale for any missing translations.",parameters:[{name:"id",in:"path",required:!0,schema:{type:"string"}},{name:"locale",in:"path",required:!0,schema:{type:"string",example:"fr"}}],responses:{200:{description:"Resolved profile for the requested locale"},404:{description:"Profile not found"}}}},"/v1/consent":{post:{tags:["Consent"],summary:"Submit consent",requestBody:{required:!0,content:{"application/json":{schema:{$ref:"#/components/schemas/CreateConsentInput"}}}},responses:{200:{description:"Consent created or updated",content:{"application/json":{schema:{$ref:"#/components/schemas/ConsentRecord"}}}},400:{description:"Validation error"}}}},"/v1/consent/{visitorId}":{get:{tags:["Consent"],summary:"Get consent for visitor",parameters:[{name:"visitorId",in:"path",required:!0,schema:{type:"string"}}],responses:{200:{description:"Consent record",content:{"application/json":{schema:{$ref:"#/components/schemas/ConsentRecord"}}}},404:{description:"Not found"}}},put:{tags:["Consent"],summary:"Update consent",parameters:[{name:"visitorId",in:"path",required:!0,schema:{type:"string"}}],responses:{200:{description:"Updated consent"}}},delete:{tags:["Consent"],summary:"GDPR erasure \u2014 delete all consent data for visitor",parameters:[{name:"visitorId",in:"path",required:!0,schema:{type:"string"}}],responses:{200:{description:"Erased successfully"}}}},"/v1/consent/{visitorId}/verify":{get:{tags:["Consent"],summary:"Verify consent validity",parameters:[{name:"visitorId",in:"path",required:!0,schema:{type:"string"}}],responses:{200:{description:"Verification result"}}}},"/v1/consent/{visitorId}/parental-consent-request":{post:{tags:["Consent"],summary:"Request a parental-consent token (stateless hook)",description:"Issues a token \u2014 signed with `compliance.dataSigningHash` when configured, otherwise unsigned \u2014 for a host's own out-of-band parental-verification flow. Emits `consent.parentalConsentRequired`. Not by itself sufficient verifiable parental consent (COPPA-style VPC is left to the host).",parameters:[{name:"visitorId",in:"path",required:!0,schema:{type:"string"}}],requestBody:{required:!0,content:{"application/json":{schema:{type:"object",required:["profileId"],properties:{profileId:{type:"string"}}}}}},responses:{200:{description:"Token issued",content:{"application/json":{schema:{type:"object",properties:{token:{type:"string"}}}}}},400:{description:"Validation error"},403:{description:"Visitor ownership check failed"},404:{description:"Profile not found"}}}},"/v1/consent/parental-consent-resolve":{post:{tags:["Consent"],summary:"Resolve a parental-consent token",description:"Recovers `visitorId`/`profileId` from a token issued by the request route above and emits `consent.parentalConsentGranted` \u2014 the host's own backend listener decides what \"granted\" means for stored consent. No visitor-ownership cookie required, since this is typically called from the parent's own device. Token replay is not prevented (stateless by design).",requestBody:{required:!0,content:{"application/json":{schema:{type:"object",required:["token"],properties:{token:{type:"string"}}}}}},responses:{200:{description:"Token resolved",content:{"application/json":{schema:{type:"object",properties:{visitorId:{type:"string"},profileId:{type:"string"}}}}}},400:{description:"Validation error"},403:{description:"Invalid, tampered, or expired token"}}}},"/v1/notice-shown":{post:{tags:["Consent"],summary:"Record proof that the consent banner was shown",description:"Lightweight, fire-and-forget ping recording that the banner was rendered to a visitor, independent of whether they ever interact with it. Called automatically by `@consenti/ui` on banner mount when `api.enabled` is configured.",requestBody:{required:!0,content:{"application/json":{schema:{type:"object",required:["visitorId","profileId","locale"],properties:{visitorId:{type:"string"},profileId:{type:"string"},locale:{type:"string"}}}}}},responses:{201:{description:"Recorded"},400:{description:"Validation error"}}}}},components:{schemas:co}},jn={openapi:"3.1.0",info:{title:"Consenti Admin API",version:"0.1.0",description:"Authenticated endpoints for managing profiles, consent records, users, analytics, and exports. All routes (except `/auth/login`) require `Authorization: Bearer <JWT>`. Obtain a token via `POST /auth/login`.",license:{name:"Apache 2.0",url:"https://www.apache.org/licenses/LICENSE-2.0"}},servers:[{url:"/consenti/admin/v1",description:"Consenti Admin API"}],paths:{"/auth/login":{post:{tags:["Auth"],summary:"Login with email + password",requestBody:{required:!0,content:{"application/json":{schema:{type:"object",properties:{email:{type:"string"},password:{type:"string"}}}}}},responses:{200:{description:"JWT token"}}}},"/auth/me":{get:{tags:["Auth"],summary:"Get current user",security:[{BearerAuth:[]}],responses:{200:{description:"Current admin user info"}}}},"/auth/logout":{post:{tags:["Auth"],summary:"Invalidate session",security:[{BearerAuth:[]}],responses:{200:{description:"Logged out"}}}},"/auth/refresh":{post:{tags:["Auth"],summary:"Reissue a fresh token from the current one, extending the session",description:"Used by the dashboard on user activity to implement a sliding inactivity timeout instead of a flat expiry from login.",security:[{BearerAuth:[]}],responses:{200:{description:"New JWT token"},401:{description:"Current token is missing, invalid, or already expired"}}}},"/auth/oidc/authorize":{get:{tags:["Auth"],summary:"Start OIDC authorization (PKCE)",responses:{302:{description:"Redirect to OIDC provider"}}}},"/auth/oidc/callback":{get:{tags:["Auth"],summary:"OIDC callback \u2014 exchange code for token",responses:{200:{description:"JWT token"}}}},"/auth/saml/metadata":{get:{tags:["Auth"],summary:"SAML SP metadata XML",responses:{200:{description:"SAML metadata XML",content:{"application/xml":{}}}}}},"/auth/saml/acs":{post:{tags:["Auth"],summary:"SAML Assertion Consumer Service",responses:{200:{description:"JWT token"}}}},"/auth/totp/setup":{post:{tags:["Auth"],summary:"Setup TOTP MFA",security:[{BearerAuth:[]}],responses:{200:{description:"TOTP secret and QR URL"}}}},"/auth/totp/verify":{post:{tags:["Auth"],summary:"Verify and enable TOTP",security:[{BearerAuth:[]}],responses:{200:{description:"TOTP enabled"}}}},"/profiles":{get:{tags:["Profiles"],summary:"List profiles",security:[{BearerAuth:[]}],responses:{200:{description:"Array of profiles"}}},post:{tags:["Profiles"],summary:"Create profile",security:[{BearerAuth:[]}],responses:{201:{description:"Created profile"}}}},"/consent-templates":{get:{tags:["Consent Templates"],summary:"List consent templates",description:"A Consent Template groups parameters (`cookies`, keyed by id) with the categories that own their legal basis (`categories`, keyed by id).",security:[{BearerAuth:[]}],responses:{200:{description:"Array of consent templates"}}},post:{tags:["Consent Templates"],summary:"Create consent template",security:[{BearerAuth:[]}],requestBody:{required:!0,content:{"application/json":{schema:{type:"object",required:["name","cookies","categories"],properties:{name:{type:"string"},cookies:{type:"object",description:"Keyed by parameter id."},categories:{type:"object",description:"Keyed by category id. Every parameter id must appear in exactly one category."}}}}}},responses:{201:{description:"Created consent template"},400:{description:"Validation error"}}}},"/consent-templates/{id}":{get:{tags:["Consent Templates"],summary:"Get consent template",security:[{BearerAuth:[]}],parameters:[{name:"id",in:"path",required:!0,schema:{type:"string"}}],responses:{200:{description:"Consent template"},404:{description:"Not found"}}},put:{tags:["Consent Templates"],summary:"Update consent template",security:[{BearerAuth:[]}],parameters:[{name:"id",in:"path",required:!0,schema:{type:"string"}}],responses:{200:{description:"Updated consent template"},422:{description:"Change would break compliance for profiles using this template"}}},delete:{tags:["Consent Templates"],summary:"Delete consent template",security:[{BearerAuth:[]}],parameters:[{name:"id",in:"path",required:!0,schema:{type:"string"}}],responses:{200:{description:"Deleted"},422:{description:"Template is still used by profiles"}}}},"/consent-templates/{id}/copy":{post:{tags:["Consent Templates"],summary:"Duplicate a consent template",security:[{BearerAuth:[]}],parameters:[{name:"id",in:"path",required:!0,schema:{type:"string"}}],responses:{201:{description:"Copied consent template"}}}},"/consent-templates/{id}/profile-usage":{get:{tags:["Consent Templates"],summary:"List profiles using this consent template",security:[{BearerAuth:[]}],parameters:[{name:"id",in:"path",required:!0,schema:{type:"string"}}],responses:{200:{description:"Array of profile summaries"}}}},"/consents":{get:{tags:["Consents"],summary:"List consent records",security:[{BearerAuth:[]}],parameters:[{name:"page",in:"query",schema:{type:"integer"}},{name:"profileId",in:"query",schema:{type:"string"}},{name:"from",in:"query",schema:{type:"string",format:"date"}},{name:"to",in:"query",schema:{type:"string",format:"date"}},{name:"q",in:"query",schema:{type:"string"},description:"Free-text search across visitorId, profileId, locale, source"}],responses:{200:{description:"Paginated consent records"}}}},"/stats/overview":{get:{tags:["Stats"],summary:"Overview statistics",security:[{BearerAuth:[]}],responses:{200:{description:"Totals and acceptance rates"}}}},"/stats/timeline":{get:{tags:["Stats"],summary:"Daily consent timeline",security:[{BearerAuth:[]}],parameters:[{name:"days",in:"query",schema:{type:"integer",default:30}}],responses:{200:{description:"Array of date+count"}}}},"/stats/countries":{get:{tags:["Stats"],summary:"Consent by country",security:[{BearerAuth:[]}],responses:{200:{description:"Country counts"}}}},"/stats/gpc":{get:{tags:["Stats"],summary:"GPC detection stats",security:[{BearerAuth:[]}],responses:{200:{description:"GPC rate and counts"}}}},"/export/consents":{get:{tags:["Export"],summary:"Export consent records",security:[{BearerAuth:[]}],parameters:[{name:"format",in:"query",schema:{type:"string",enum:["csv","json"]}},{name:"from",in:"query",schema:{type:"string",format:"date"}},{name:"to",in:"query",schema:{type:"string",format:"date"}}],responses:{200:{description:"CSV or JSON download"}}}},"/tenants":{get:{tags:["Sites"],summary:"List all sites/tenants",security:[{BearerAuth:[]}],responses:{200:{description:"Array of tenants"}}},post:{tags:["Sites"],summary:"Create a site/tenant",security:[{BearerAuth:[]}],requestBody:{required:!0,content:{"application/json":{schema:{type:"object",properties:{name:{type:"string"},slug:{type:"string"}},required:["name","slug"]}}}},responses:{201:{description:"Created tenant"}}}},"/tenants/{id}":{put:{tags:["Sites"],summary:"Update a site/tenant",security:[{BearerAuth:[]}],parameters:[{name:"id",in:"path",required:!0,schema:{type:"string"}}],responses:{200:{description:"Updated tenant"}}},delete:{tags:["Sites"],summary:"Delete a site/tenant",security:[{BearerAuth:[]}],parameters:[{name:"id",in:"path",required:!0,schema:{type:"string"}}],responses:{200:{description:"Deleted"}}}},"/setup/status":{get:{tags:["Setup"],summary:"Whether the first-run setup wizard has been completed for this tenant",security:[{BearerAuth:[]}],responses:{200:{description:"{ completed: boolean }"}}}},"/setup/config":{get:{tags:["Setup"],summary:"Resolved server config (secrets redacted) plus production-readiness flags",description:"The same merged `DEFAULT_CONFIG` + user config `createConsenti` computes at boot. `auth.adminPassword`, `auth.masterSecret`, `compliance.dataSigningHash`, `compliance.dataSigningHash`, storage credentials, and OIDC/SAML secrets are replaced with a redaction marker.",security:[{BearerAuth:[]}],responses:{200:{description:"{ config: object, usingJsonStorage: boolean, usingDefaultCredentials: boolean }"}}}},"/setup/compliance-groups":{get:{tags:["Setup"],summary:"The 8 built-in compliance groups with label/description/regulation metadata",security:[{BearerAuth:[]}],responses:{200:{description:"Array of compliance group descriptors"}}}},"/setup/seed-profiles":{post:{tags:["Setup"],summary:"Seed default profiles for the selected compliance groups",description:"Idempotent \u2014 skips any group that already has an active profile. `groups` must be a subset of the 8 built-in compliance group ids.",security:[{BearerAuth:[]}],requestBody:{required:!0,content:{"application/json":{schema:{type:"object",properties:{groups:{type:"array",items:{type:"string"}}},required:["groups"]}}}},responses:{200:{description:"{ seeded: string[] }"},400:{description:"groups is missing, not an array of strings, or contains an unknown compliance group id"},409:{description:"Setup has already been completed for this tenant"}}}},"/setup/complete":{post:{tags:["Setup"],summary:"Mark the first-run setup wizard as complete for this tenant",description:"Called on both wizard finish and skip. Never reset from the dashboard once true.",security:[{BearerAuth:[]}],responses:{200:{description:"Updated tenant settings"},409:{description:"Setup has already been completed for this tenant"}}}}},components:{securitySchemes:{BearerAuth:{type:"http",scheme:"bearer",bearerFormat:"JWT"}},schemas:co}};p();p();var C=require("node:crypto");var lo="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",Fc=16;function Hc(i){let e=(0,C.randomBytes)(i),t="";for(let n=0;n<i;n++)t+=lo[e[n]%lo.length];return t}function nt(i){return`${i}_${Hc(Fc)}`}function K(){return nt("prof")}function q(){return nt("visi")}function Y(){return nt("cons")}function Q(){return nt("ctem")}function Z(){return nt("utem")}function Vc(i){if(i.includes(":")){let t=i.split(":");for(;t.length<8;)t.push("0");return t.slice(0,3).concat(["0","0","0","0","0"]).join(":")}let e=i.split(".");return e.length===4?(e[3]="0",e.join(".")):i}function uo(i,e=""){return(0,C.createHash)("sha256").update(e+Vc(i)).digest("hex")}function po(i){return(0,C.createHash)("sha256").update(i).digest("hex")}function ue(i,e){return(0,C.createHmac)("sha256",e).update(i).digest("hex")}function It(i,e,t){let n=Buffer.from(ue(i,t),"hex"),o=Buffer.from(e,"hex");return n.length!==o.length?!1:(0,C.timingSafeEqual)(n,o)}function it(i){let e=(0,C.randomBytes)(16).toString("hex"),t=(0,C.scryptSync)(i,e,64).toString("hex");return`${e}:${t}`}function mo(i,e){let[t,n]=e.split(":");if(!t||!n)return!1;let o=(0,C.scryptSync)(i,t,64).toString("hex");return(0,C.timingSafeEqual)(Buffer.from(n,"hex"),Buffer.from(o,"hex"))}function Bn(i,e,t=3600){let n=Math.floor(Date.now()/1e3),o=btoa(JSON.stringify({alg:"HS256",typ:"JWT"})).replace(/=/g,""),s=btoa(JSON.stringify({...i,iat:n,exp:n+t})).replace(/=/g,""),r=ue(`${o}.${s}`,e).match(/.{2}/g).map(c=>String.fromCharCode(parseInt(c,16))).join(""),a=btoa(r).replace(/\+/g,"-").replace(/\//g,"_").replace(/=/g,"");return`${o}.${s}.${a}`}function Pt(i,e){let t=i.split(".");if(t.length!==3)return null;let[n,o,s]=t;if(!n||!o||!s)return null;let r=ue(`${n}.${o}`,e),a=atob(s.replace(/-/g,"+").replace(/_/g,"/")),c=Array.from(a).map(u=>u.charCodeAt(0).toString(16).padStart(2,"0")).join(""),l=Buffer.from(r,"hex"),d=Buffer.from(c,"hex");if(l.length!==d.length||!(0,C.timingSafeEqual)(l,d))return null;try{let u=JSON.parse(atob(o)),m=u.exp;return typeof m=="number"&&Date.now()/1e3>m?null:u}catch{return null}}p();var pe=require("node:fs"),ne=require("node:path"),go=require("node:url"),Wc={"node:sqlite":"consenti.db","better-sqlite3":"consenti.db","node-sqlite3-wasm":"consenti.db",sqlite:"consenti.db",json:"consenti-data.json",mongodb:"",mysql:"",postgresql:""},qc=(0,ne.dirname)((0,go.fileURLToPath)(h));function Jc(i){let e=i.includes("node_modules"),t=i.startsWith((0,ne.resolve)(qc,"..",".."));return e||t}function fe(i,e){let t=(0,ne.resolve)(i),n=(0,ne.extname)(t);if(n&&(console.warn(`[consenti] storage.path "${i}" looks like a file path (has extension "${n}"). Treating parent directory as storage root. Update your config to pass a directory path.`),t=(0,ne.dirname)(t)),Jc(t))throw new Error(`[consenti] storage.path "${t}" is inside the package installation directory. Choose a writable directory outside node_modules.`);(0,pe.existsSync)(t)||(0,pe.mkdirSync)(t,{recursive:!0});try{(0,pe.accessSync)(t,pe.constants.W_OK)}catch{throw new Error(`[consenti] storage.path "${t}" is not writable.`)}let o=(0,ne.join)(t,"db"),s=(0,ne.join)(t,"profiles"),r=(0,ne.join)(t,"logs");(0,pe.mkdirSync)(o,{recursive:!0}),(0,pe.mkdirSync)(s,{recursive:!0}),(0,pe.mkdirSync)(r,{recursive:!0});let a=Wc[e]??"consenti.db",c=a?(0,ne.join)(o,a):"";return{basePath:t,dbPath:c,profilesDir:s,logsDir:r}}p();var ho={name:"tenants",cols:[{n:"id",t:"pk"},{n:"name",t:"text"},{n:"slug",t:"text",unique:!0},{n:"created_at",t:"ts",def:"$now"},{n:"updated_at",t:"ts",def:"$now",mysqlUpd:!0}]},yo={name:"profiles",cols:[{n:"id",t:"pk"},{n:"tenant_id",t:"text",ref:"tenants"},{n:"name",t:"text"},{n:"default_locale",t:"text_sm",def:"en"},{n:"version",t:"int",def:1},{n:"profile_json",t:"json_ordered"},{n:"created_at",t:"ts",def:"$now"},{n:"updated_at",t:"ts",def:"$now",mysqlUpd:!0}],idx:[{cols:["tenant_id"]}]},_o={name:"consent_records",cols:[{n:"id",t:"pk"},{n:"tenant_id",t:"text",ref:"tenants"},{n:"visitor_id",t:"text"},{n:"profile_id",t:"text"},{n:"profile_version",t:"int",null:!0},{n:"locale",t:"text_sm"},{n:"consent_json",t:"json"},{n:"gpc_detected",t:"bool",def:!1},{n:"source",t:"text_sm"},{n:"age_verified",t:"bool",def:!1},{n:"parental_consent_token",t:"longtext",null:!0},{n:"tcf_string",t:"longtext",null:!0},{n:"gpp_string",t:"longtext",null:!0},{n:"signature",t:"longtext",null:!0},{n:"created_at",t:"ts",def:"$now"},{n:"updated_at",t:"ts",def:"$now",mysqlUpd:!0}],uq:[{cols:["visitor_id","profile_id"]}],idx:[{cols:["tenant_id","created_at"]},{cols:["tenant_id","profile_id","created_at"]},{cols:["locale"]},{cols:["source"]}]},wo={name:"consent_history",cols:[{n:"id",t:"pk"},{n:"tenant_id",t:"text",ref:"tenants"},{n:"consent_record_id",t:"text",ref:"consent_records"},{n:"visitor_id",t:"text"},{n:"profile_version",t:"int",null:!0},{n:"old_json",t:"json",null:!0},{n:"new_json",t:"json"},{n:"action",t:"text_sm"},{n:"created_at",t:"ts",def:"$now"}],idx:[{cols:["visitor_id"]}]},Eo={name:"visitors",cols:[{n:"id",t:"pk"},{n:"tenant_id",t:"text",ref:"tenants"},{n:"visitor_id",t:"text",unique:!0},{n:"country",t:"text_geo",null:!0},{n:"region",t:"text_md",null:!0},{n:"city",t:"text_md",null:!0},{n:"ip_hash",t:"text_hash",null:!0},{n:"user_agent_hash",t:"text_hash",null:!0},{n:"first_seen",t:"ts",def:"$now"},{n:"last_seen",t:"ts",def:"$now",mysqlUpd:!0}],idx:[{cols:["tenant_id","first_seen"]},{cols:["country"]}]},Ro={name:"notice_shown",cols:[{n:"id",t:"pk"},{n:"tenant_id",t:"text",ref:"tenants"},{n:"visitor_id",t:"text"},{n:"profile_id",t:"text"},{n:"locale",t:"text_sm"},{n:"created_at",t:"ts",def:"$now"}],idx:[{cols:["visitor_id"]}]},$n={name:"users",cols:[{n:"id",t:"pk"},{n:"tenant_id",t:"text",ref:"tenants"},{n:"name",t:"text"},{n:"email",t:"text",unique:!0},{n:"password_hash",t:"text"},{n:"is_active",t:"bool",def:!0},{n:"totp_secret",t:"longtext",null:!0},{n:"totp_enabled",t:"bool",def:!1},{n:"created_at",t:"ts",def:"$now"},{n:"updated_at",t:"ts",def:"$now",mysqlUpd:!0}]},zc={...$n,cols:[...$n.cols,{n:"allowed_tenants",t:"json",null:!0}]},So={name:"roles",cols:[{n:"id",t:"pk"},{n:"tenant_id",t:"text",ref:"tenants"},{n:"name",t:"text_md"},{n:"description",t:"text",null:!0}]},vo={name:"permissions",cols:[{n:"id",t:"pk"},{n:"name",t:"text_md",unique:!0},{n:"description",t:"text",null:!0}]},Co={name:"user_roles",cols:[{n:"user_id",t:"text",ref:"users"},{n:"role_id",t:"text",ref:"roles"},{n:"tenant_id",t:"text",def:"default"}],pk:["user_id","role_id","tenant_id"],idx:[{cols:["user_id"]}]},Ao={name:"role_permissions",cols:[{n:"role_id",t:"text",ref:"roles"},{n:"permission_id",t:"text",ref:"permissions"}],pk:["role_id","permission_id"],idx:[{cols:["role_id"]}]},To={name:"audit_logs",cols:[{n:"id",t:"pk"},{n:"tenant_id",t:"text",ref:"tenants"},{n:"user_id",t:"text",null:!0},{n:"action",t:"text_md"},{n:"resource_type",t:"text_md"},{n:"resource_id",t:"text",null:!0},{n:"old_data",t:"json",null:!0},{n:"new_data",t:"json",null:!0},{n:"created_at",t:"ts",def:"$now"}],idx:[{cols:["tenant_id","created_at"]},{cols:["action"]},{cols:["resource_type"]},{cols:["resource_id"]},{cols:["user_id"]}]},Io={name:"api_keys",cols:[{n:"id",t:"pk"},{n:"tenant_id",t:"text",ref:"tenants",onDel:"CASCADE"},{n:"key_hash",t:"text_hash",unique:!0},{n:"name",t:"text"},{n:"is_active",t:"bool",def:!0},{n:"created_by",t:"text",null:!0},{n:"expire_by",t:"ts",null:!0},{n:"created_at",t:"ts",def:"$now"},{n:"updated_at",t:"ts",def:"$now",mysqlUpd:!0}]},Po={name:"tenant_settings",cols:[{n:"tenant_id",t:"text",ref:"tenants",onDel:"CASCADE"},{n:"allowed_origins_json",t:"json",def:"$arr"},{n:"admin_allowed_origins_json",t:"json",def:"$arr"},{n:"setup_completed",t:"bool",def:!1},{n:"profiles_seeded",t:"bool",def:!1},{n:"tcf_confirmation_json",t:"json",null:!0},{n:"gpp_confirmation_json",t:"json",null:!0},{n:"updated_at",t:"ts",def:"$now",mysqlUpd:!0}],pk:["tenant_id"]},bo={name:"consent_templates",cols:[{n:"id",t:"pk"},{n:"tenant_id",t:"text",ref:"tenants",onDel:"CASCADE"},{n:"name",t:"text"},{n:"cookies_json",t:"json_ordered",def:"$obj"},{n:"categories_json",t:"json_ordered",def:"$obj"},{n:"created_at",t:"ts",def:"$now"},{n:"updated_at",t:"ts",def:"$now",mysqlUpd:!0}]},Oo={name:"ui_templates",cols:[{n:"id",t:"pk"},{n:"tenant_id",t:"text",ref:"tenants",onDel:"CASCADE"},{n:"name",t:"text"},{n:"settings_json",t:"json_ordered",def:"$obj"},{n:"created_at",t:"ts",def:"$now"},{n:"updated_at",t:"ts",def:"$now",mysqlUpd:!0}]},le=2,Fn="consenti_";function ce(i){return Fn+i}var Se=["schema_version","tenants","profiles","consent_records"];function Ue(i){return new Error(`[consenti] This database has Consenti ${i} from an earlier version, named without the "${Fn}" prefix (tenants, profiles, consent_records, \u2026). Consenti now only reads and writes "${Fn}*" ${i}, so starting would create an empty set next to your data. Back up the database, then rename them once with: node node_modules/@consenti/api/scripts/migrate-to-consenti-prefix.mjs --apply (it reads the same CONSENTI_DB_* environment variables; run it without --apply first to see the plan). Details: CHANGELOG 0.6.0.`)}var Vn=[ho,yo,_o,wo,Eo,zc,So,vo,Co,Ao,To,Io,bo,Oo,Po,Ro],Wn=[ho,yo,_o,wo,Eo,$n,So,vo,Co,Ao,To,Io,bo,Oo,Po,Ro];function Kc(i){return i==="$now"?"DEFAULT (datetime('now'))":i==="$arr"?"DEFAULT '[]'":i==="$obj"?"DEFAULT '{}'":i===!0?"DEFAULT 1":i===!1?"DEFAULT 0":typeof i=="string"?`DEFAULT '${i}'`:`DEFAULT ${i}`}function Yc(i){if(i.t==="pk")return`${i.n} TEXT PRIMARY KEY`;let e=i.t==="int"||i.t==="bool"?"INTEGER":"TEXT",t=[`${i.n} ${e}`];return i.null||t.push("NOT NULL"),i.def!==void 0&&t.push(Kc(i.def)),i.unique&&t.push("UNIQUE"),i.ref&&(t.push(`REFERENCES ${i.ref}(id)`),i.onDel&&t.push(`ON DELETE ${i.onDel}`)),t.join(" ")}function Hn(i){let e=i.cols.map(t=>` ${Yc(t)}`);if(i.pk&&e.push(` PRIMARY KEY (${i.pk.join(", ")})`),i.uq)for(let t of i.uq)e.push(` UNIQUE(${t.cols.join(", ")})`);return`CREATE TABLE IF NOT EXISTS ${i.name} (
2
2
  ${e.join(`,
3
3
  `)}
4
- );`}function Un(i,e){return`idx_${i.name}_${e.join("_")}`}function vc(i){return(i.idx??[]).map(e=>`CREATE INDEX IF NOT EXISTS ${Un(i,e.cols)} ON ${i.name} (${e.cols.join(", ")});`).join(`
5
- `)}function Ac(i){return i==="$now"?"DEFAULT NOW()":i==="$arr"?"DEFAULT '[]'":i==="$obj"?"DEFAULT '{}'":i===!0?"DEFAULT TRUE":i===!1?"DEFAULT FALSE":typeof i=="string"?`DEFAULT '${i}'`:`DEFAULT ${i}`}function Tc(i){if(i.t==="pk")return`${i.n} TEXT PRIMARY KEY`;let e=i.t==="json"?"JSONB":i.t==="json_ordered"?"JSON":i.t==="int"?"INTEGER":i.t==="bool"?"BOOLEAN":i.t==="ts"?"TIMESTAMPTZ":"TEXT",t=[`${i.n} ${e}`];return i.null||t.push("NOT NULL"),i.def!==void 0&&t.push(Ac(i.def)),i.unique&&t.push("UNIQUE"),i.ref&&(t.push(`REFERENCES ${i.ref}(id)`),i.onDel&&t.push(`ON DELETE ${i.onDel}`)),t.join(" ")}function Zi(i){let e=i.cols.map(t=>` ${Tc(t)}`);if(i.pk&&e.push(` PRIMARY KEY (${i.pk.join(", ")})`),i.uq)for(let t of i.uq)e.push(` UNIQUE (${t.cols.join(", ")})`);return`CREATE TABLE IF NOT EXISTS ${i.name} (
4
+ );`}function qn(i,e){return`idx_${i}_${e.join("_")}`}function Do(i){return(i.idx??[]).map(e=>`CREATE INDEX IF NOT EXISTS ${qn(i.name,e.cols)} ON ${i.name} (${e.cols.join(", ")});`).join(`
5
+ `)}function Qc(i){return i==="$now"?"DEFAULT NOW()":i==="$arr"?"DEFAULT '[]'":i==="$obj"?"DEFAULT '{}'":i===!0?"DEFAULT TRUE":i===!1?"DEFAULT FALSE":typeof i=="string"?`DEFAULT '${i}'`:`DEFAULT ${i}`}function Zc(i){if(i.t==="pk")return`${i.n} TEXT PRIMARY KEY`;let e=i.t==="json"?"JSONB":i.t==="json_ordered"?"JSON":i.t==="int"?"INTEGER":i.t==="bool"?"BOOLEAN":i.t==="ts"?"TIMESTAMPTZ":"TEXT",t=[`${i.n} ${e}`];return i.null||t.push("NOT NULL"),i.def!==void 0&&t.push(Qc(i.def)),i.unique&&t.push("UNIQUE"),i.ref&&(t.push(`REFERENCES ${ce(i.ref)}(id)`),i.onDel&&t.push(`ON DELETE ${i.onDel}`)),t.join(" ")}function fo(i){let e=i.cols.map(t=>` ${Zc(t)}`);if(i.pk&&e.push(` PRIMARY KEY (${i.pk.join(", ")})`),i.uq)for(let t of i.uq)e.push(` UNIQUE (${t.cols.join(", ")})`);return`CREATE TABLE IF NOT EXISTS ${ce(i.name)} (
6
6
  ${e.join(`,
7
7
  `)}
8
- );`}function Ic(i){return(i.idx??[]).map(e=>`CREATE INDEX IF NOT EXISTS ${Un(i,e.cols)} ON ${i.name} (${e.cols.join(", ")});`).join(`
9
- `)}var Pc={text:"VARCHAR(255)",text_sm:"VARCHAR(20)",text_md:"VARCHAR(100)",text_geo:"VARCHAR(10)",text_hash:"VARCHAR(64)",longtext:"LONGTEXT",json:"LONGTEXT",json_ordered:"LONGTEXT"};function bc(i){return i==="$now"?"DEFAULT CURRENT_TIMESTAMP":i==="$arr"?"DEFAULT ('[]')":i==="$obj"?"DEFAULT ('{}')":i===!0?"DEFAULT 1":i===!1?"DEFAULT 0":typeof i=="string"?`DEFAULT '${i}'`:`DEFAULT ${i}`}function Oc(i){if(i.t==="pk")return`${i.n} VARCHAR(64) PRIMARY KEY`;let e=i.t==="int"?"INT":i.t==="bool"?"TINYINT(1)":i.t==="ts"?"DATETIME":Pc[i.t]??"TEXT",t=[`${i.n} ${e}`];return i.null||t.push("NOT NULL"),i.def!==void 0&&t.push(bc(i.def)),i.mysqlUpd&&t.push("ON UPDATE CURRENT_TIMESTAMP"),i.unique&&t.push("UNIQUE"),i.ref&&(t.push(`REFERENCES ${i.ref}(id)`),i.onDel&&t.push(`ON DELETE ${i.onDel}`)),t.join(" ")}function Xi(i){let e=i.cols.map(t=>` ${Oc(t)}`);if(i.pk&&e.push(` PRIMARY KEY (${i.pk.join(", ")})`),i.uq)for(let t of i.uq)e.push(` UNIQUE KEY uq_${t.cols.join("_")} (${t.cols.join(", ")})`);return`CREATE TABLE IF NOT EXISTS ${i.name} (
8
+ );`}function Xc(i){return(i.idx??[]).map(e=>`CREATE INDEX IF NOT EXISTS ${qn(ce(i.name),e.cols)} ON ${ce(i.name)} (${e.cols.join(", ")});`).join(`
9
+ `)}var el={text:"VARCHAR(255)",text_sm:"VARCHAR(20)",text_md:"VARCHAR(100)",text_geo:"VARCHAR(10)",text_hash:"VARCHAR(64)",longtext:"LONGTEXT",json:"LONGTEXT",json_ordered:"LONGTEXT"};function tl(i){return i==="$now"?"DEFAULT CURRENT_TIMESTAMP":i==="$arr"?"DEFAULT ('[]')":i==="$obj"?"DEFAULT ('{}')":i===!0?"DEFAULT 1":i===!1?"DEFAULT 0":typeof i=="string"?`DEFAULT '${i}'`:`DEFAULT ${i}`}function nl(i){if(i.t==="pk")return`${i.n} VARCHAR(64) PRIMARY KEY`;let e=i.t==="int"?"INT":i.t==="bool"?"TINYINT(1)":i.t==="ts"?"DATETIME":el[i.t]??"TEXT",t=[`${i.n} ${e}`];return i.null||t.push("NOT NULL"),i.def!==void 0&&t.push(tl(i.def)),i.mysqlUpd&&t.push("ON UPDATE CURRENT_TIMESTAMP"),i.unique&&t.push("UNIQUE"),i.ref&&(t.push(`REFERENCES ${ce(i.ref)}(id)`),i.onDel&&t.push(`ON DELETE ${i.onDel}`)),t.join(" ")}function il(i){let e=i.cols.map(n=>` ${nl(n)}`);if(i.pk&&e.push(` PRIMARY KEY (${i.pk.join(", ")})`),i.uq)for(let n of i.uq)e.push(` UNIQUE KEY uq_${n.cols.join("_")} (${n.cols.join(", ")})`);let t=ce(i.name);for(let n of i.idx??[])e.push(` INDEX ${qn(t,n.cols)} (${n.cols.join(", ")})`);return`CREATE TABLE IF NOT EXISTS ${t} (
10
10
  ${e.join(`,
11
11
  `)}
12
- ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;`}function Dc(i){return(i.idx??[]).map(e=>`CREATE INDEX ${Un(i,e.cols)} ON ${i.name} (${e.cols.join(", ")});`).join(`
13
- `)}function kc(i){let e=i.map(vc).filter(Boolean).join(`
14
- `);return e?`${i.map(Qi).join(`
12
+ ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;`}function ol(i){let e=i.map(Do).filter(Boolean).join(`
13
+ `);return e?`${i.map(Hn).join(`
15
14
  `)}
16
- ${e}`:i.map(Qi).join(`
17
- `)}function Lc(i){let e=i.map(Ic).filter(Boolean).join(`
18
- `);return e?`${i.map(Zi).join(`
15
+ ${e}`:i.map(Hn).join(`
16
+ `)}function sl(i){let e=i.map(Xc).filter(Boolean).join(`
17
+ `);return e?`${i.map(fo).join(`
19
18
  `)}
20
- ${e}`:i.map(Zi).join(`
21
- `)}function Nc(i){let e=i.map(Dc).filter(Boolean).join(`
22
- `);return e?`${i.map(Xi).join(`
23
- `)}
24
- ${e}`:i.map(Xi).join(`
25
- `)}function Uc(i){let e=[];for(let t of i){for(let n of t.uq??[])e.push({table:t.name,cols:n.cols,unique:!0});for(let n of t.cols)n.unique&&e.push({table:t.name,cols:[n.n],unique:!0});for(let n of t.idx??[])e.push({table:t.name,cols:n.cols})}return e}var ho=Uc(Nn),Le=kc(Rc),yo=Lc(Nn)+`
26
- CREATE TABLE IF NOT EXISTS schema_version (version INTEGER PRIMARY KEY);
27
- `,_o=Nc(Nn)+`
28
- CREATE TABLE IF NOT EXISTS schema_version (
19
+ ${e}`:i.map(fo).join(`
20
+ `)}function rl(i){return i.map(il).join(`
21
+ `)}var ot=["consent_records","notice_shown"];function ko(i){let e=Vn.find(t=>t.name===i);if(!e)throw new Error(`Unknown table ${i}`);return e.cols.map(t=>t.n)}function Lo(i,e){let t=Vn.find(o=>o.name===i);if(!t)throw new Error(`Unknown table ${i}`);let n=e.join(", ");return{create:Hn({...t,name:`${i}_v2`}),copy:`INSERT INTO ${i}_v2 (${n}) SELECT ${n} FROM ${i};`,swap:[`DROP TABLE ${i};`,`ALTER TABLE ${i}_v2 RENAME TO ${i};`,Do(t)].filter(Boolean).join(`
22
+ `)}}function al(i){let e=[];for(let t of i){for(let n of t.uq??[])e.push({table:t.name,cols:n.cols,unique:!0});for(let n of t.cols)n.unique&&e.push({table:t.name,cols:[n.n],unique:!0});for(let n of t.idx??[])e.push({table:t.name,cols:n.cols})}return e}var No=al(Wn),Me=ol(Vn),xo=sl(Wn)+`
23
+ CREATE TABLE IF NOT EXISTS ${ce("schema_version")} (version INTEGER PRIMARY KEY);
24
+ `,Uo=rl(Wn)+`
25
+ CREATE TABLE IF NOT EXISTS ${ce("schema_version")} (
29
26
  version INT NOT NULL PRIMARY KEY
30
27
  ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
31
- `,ie={id:"default",name:"Default",slug:"default"},ne=[{id:"perm_profile_create",name:"profile:create",description:"Create profiles"},{id:"perm_profile_update",name:"profile:update",description:"Update profiles"},{id:"perm_profile_delete",name:"profile:delete",description:"Delete profiles"},{id:"perm_profile_view",name:"profile:view",description:"View profiles"},{id:"perm_consent_view",name:"consent:view",description:"View consent records"},{id:"perm_visitor_view",name:"visitor:view",description:"View visitor records"},{id:"perm_user_create",name:"user:create",description:"Create users"},{id:"perm_user_update",name:"user:update",description:"Update users"},{id:"perm_user_delete",name:"user:delete",description:"Delete users"},{id:"perm_user_view",name:"user:view",description:"View users"},{id:"perm_role_create",name:"role:create",description:"Create roles"},{id:"perm_role_update",name:"role:update",description:"Update roles"},{id:"perm_role_delete",name:"role:delete",description:"Delete roles"},{id:"perm_role_view",name:"role:view",description:"View roles"},{id:"perm_audit_view",name:"audit:view",description:"View audit logs"},{id:"perm_settings_update",name:"settings:update",description:"Update settings"},{id:"perm_export_run",name:"export:run",description:"Run data exports"},{id:"perm_stats_view",name:"stats:view",description:"View reporting and analytics"}],ge=[{id:"role_super_admin",tenantId:"default",name:"super_admin",description:"Full system access"},{id:"role_admin",tenantId:"default",name:"admin",description:"Administrative access"},{id:"role_compliance_officer",tenantId:"default",name:"compliance_officer",description:"Compliance read access"},{id:"role_viewer",tenantId:"default",name:"viewer",description:"Read-only access"}],xc=new Set(["role:delete","user:delete"]),Mc=new Set(["consent:view","visitor:view","audit:view","profile:view","export:run","stats:view"]),Gc=new Set(["consent:view","visitor:view","profile:view","stats:view"]),fe=[...ne.map(i=>({roleId:"role_super_admin",permissionId:i.id})),...ne.filter(i=>!xc.has(i.name)).map(i=>({roleId:"role_admin",permissionId:i.id})),...ne.filter(i=>Mc.has(i.name)).map(i=>({roleId:"role_compliance_officer",permissionId:i.id})),...ne.filter(i=>Gc.has(i.name)).map(i=>({roleId:"role_viewer",permissionId:i.id}))];function se(i){return`'${i.replace(/'/g,"''")}'`}function jc(){let{id:i,name:e,slug:t}=ie,n=`INSERT OR IGNORE INTO tenants (id, name, slug) VALUES (${se(i)},${se(e)},${se(t)});`,o=`INSERT OR IGNORE INTO permissions (id, name, description) VALUES
32
- ${ne.map(c=>` (${se(c.id)},${se(c.name)},${se(c.description)})`).join(`,
28
+ `,oe={id:"default",name:"Default",slug:"default"},ie=[{id:"perm_profile_create",name:"profile:create",description:"Create profiles"},{id:"perm_profile_update",name:"profile:update",description:"Update profiles"},{id:"perm_profile_delete",name:"profile:delete",description:"Delete profiles"},{id:"perm_profile_view",name:"profile:view",description:"View profiles"},{id:"perm_consent_view",name:"consent:view",description:"View consent records"},{id:"perm_visitor_view",name:"visitor:view",description:"View visitor records"},{id:"perm_user_create",name:"user:create",description:"Create users"},{id:"perm_user_update",name:"user:update",description:"Update users"},{id:"perm_user_delete",name:"user:delete",description:"Delete users"},{id:"perm_user_view",name:"user:view",description:"View users"},{id:"perm_role_create",name:"role:create",description:"Create roles"},{id:"perm_role_update",name:"role:update",description:"Update roles"},{id:"perm_role_delete",name:"role:delete",description:"Delete roles"},{id:"perm_role_view",name:"role:view",description:"View roles"},{id:"perm_audit_view",name:"audit:view",description:"View audit logs"},{id:"perm_settings_update",name:"settings:update",description:"Update settings"},{id:"perm_export_run",name:"export:run",description:"Run data exports"},{id:"perm_stats_view",name:"stats:view",description:"View reporting and analytics"}],he=[{id:"role_super_admin",tenantId:"default",name:"super_admin",description:"Full system access"},{id:"role_admin",tenantId:"default",name:"admin",description:"Administrative access"},{id:"role_compliance_officer",tenantId:"default",name:"compliance_officer",description:"Compliance read access"},{id:"role_viewer",tenantId:"default",name:"viewer",description:"Read-only access"}],cl=new Set(["role:delete","user:delete"]),ll=new Set(["consent:view","visitor:view","audit:view","profile:view","export:run","stats:view"]),dl=new Set(["consent:view","visitor:view","profile:view","stats:view"]),ye=[...ie.map(i=>({roleId:"role_super_admin",permissionId:i.id})),...ie.filter(i=>!cl.has(i.name)).map(i=>({roleId:"role_admin",permissionId:i.id})),...ie.filter(i=>ll.has(i.name)).map(i=>({roleId:"role_compliance_officer",permissionId:i.id})),...ie.filter(i=>dl.has(i.name)).map(i=>({roleId:"role_viewer",permissionId:i.id}))];function ae(i){return`'${i.replace(/'/g,"''")}'`}function ul(){let{id:i,name:e,slug:t}=oe,n=`INSERT OR IGNORE INTO tenants (id, name, slug) VALUES (${ae(i)},${ae(e)},${ae(t)});`,o=`INSERT OR IGNORE INTO permissions (id, name, description) VALUES
29
+ ${ie.map(c=>` (${ae(c.id)},${ae(c.name)},${ae(c.description)})`).join(`,
33
30
  `)};`,s=`INSERT OR IGNORE INTO roles (id, tenant_id, name, description) VALUES
34
- ${ge.map(c=>` (${se(c.id)},${se(c.tenantId)},${se(c.name)},${se(c.description)})`).join(`,
35
- `)};`,r=new Map;for(let c of fe)r.has(c.roleId)||r.set(c.roleId,[]),r.get(c.roleId).push(c.permissionId);let a=[...r.entries()].map(([c,l])=>`INSERT OR IGNORE INTO role_permissions (role_id, permission_id) VALUES
36
- ${l.map(d=>` (${se(c)},${se(d)})`).join(`,
31
+ ${he.map(c=>` (${ae(c.id)},${ae(c.tenantId)},${ae(c.name)},${ae(c.description)})`).join(`,
32
+ `)};`,r=new Map;for(let c of ye)r.has(c.roleId)||r.set(c.roleId,[]),r.get(c.roleId).push(c.permissionId);let a=[...r.entries()].map(([c,l])=>`INSERT OR IGNORE INTO role_permissions (role_id, permission_id) VALUES
33
+ ${l.map(d=>` (${ae(c)},${ae(d)})`).join(`,
37
34
  `)};`).join(`
38
35
  `);return[n,o,s,a].join(`
39
- `)}var Ne=jc();p();function j(i){return`${i.replace(/[\\%_]/g,e=>`\\${e}`)}%`}var xn=500,Ie=class i{constructor(e){this.config=e}config;db;cache=new Map;stmt(e){let t=this.cache.get(e);return t||(t=this.db.prepare(e),this.cache.set(e,t)),t}async connect(){let e=await import("better-sqlite3").catch(()=>{throw new Error("driver 'better-sqlite3' requires: npm install better-sqlite3")}),{dbPath:t}=me(this.config.path??"./consenti-data","better-sqlite3");this.db=new e.default(t),this.db.exec("PRAGMA journal_mode=WAL"),this.db.exec("PRAGMA foreign_keys=ON"),this.db.exec("PRAGMA synchronous=NORMAL"),await this.migrate()}async disconnect(){this.cache.clear(),this.db.close()}async migrate(){this.db.prepare("PRAGMA user_version").get().user_version<1&&(this.db.exec(Le),this.db.exec(Ne),this.db.exec("PRAGMA user_version = 1")),this.db.exec(`
36
+ `)}var Ge=ul();p();var bt=require("node:fs");function Mo(i,e){return i.all(`PRAGMA table_info(${e})`).map(t=>String(t.name))}function Jn(i,e){return Number(i.all(`SELECT COUNT(*) AS n FROM ${e}`)[0]?.n)}function je(i,e){let t=new Map;for(let o of ot){let s=Mo(i,o),r=new Set(ko(o)),a=s.filter(c=>!r.has(c));if(a.length>0)throw new Error(`Cannot upgrade ${o} to schema v2: it has column(s) ${a.join(", ")} that this version doesn't know, and rebuilding the table would delete them. Nothing was changed.`);t.set(o,s)}if(e&&(0,bt.existsSync)(e)){i.exec("PRAGMA wal_checkpoint(TRUNCATE)");let o=`${e}.pre-v2-${new Date().toISOString().replace(/[-:T]/g,"").slice(0,14)}.bak`;(0,bt.copyFileSync)(e,o),console.warn(`[Consenti] Upgrading the SQLite schema to v2. A copy of the database was saved to ${o} \u2014 delete it once you are happy with the upgrade.`)}let n=new Map(ot.map(o=>[o,Jn(i,o)]));i.exec("PRAGMA foreign_keys=OFF");try{i.exec("BEGIN");for(let o of ot){let{create:s,copy:r,swap:a}=Lo(o,t.get(o));i.exec(s),i.exec(r);let c=Jn(i,`${o}_v2`);if(c!==n.get(o))throw new Error(`Schema v2 upgrade aborted: ${o} had ${n.get(o)} rows but the copy has ${c}. Nothing was changed.`);i.exec(a)}Mo(i,"consent_history").includes("profile_version")||i.exec("ALTER TABLE consent_history ADD COLUMN profile_version INTEGER");for(let o of ot){let s=Jn(i,o);if(s!==n.get(o))throw new Error(`Schema v2 upgrade aborted: ${o} has ${s} rows after the upgrade, expected ${n.get(o)}. Nothing was changed.`)}i.exec("PRAGMA user_version = 2"),i.exec("COMMIT")}catch(o){try{i.exec("ROLLBACK")}catch{}throw o}finally{i.exec("PRAGMA foreign_keys=ON")}}p();function j(i){return`${i.replace(/[\\%_]/g,e=>`\\${e}`)}%`}var zn=500,De=class i{constructor(e){this.config=e}config;db;cache=new Map;dbPath="";stmt(e){let t=this.cache.get(e);return t||(t=this.db.prepare(e),this.cache.set(e,t)),t}async connect(){let e=await import("better-sqlite3").catch(()=>{throw new Error("driver 'better-sqlite3' requires: npm install better-sqlite3")}),{dbPath:t}=fe(this.config.path??"./consenti-data","better-sqlite3");this.dbPath=t,this.db=new e.default(t),this.db.exec("PRAGMA journal_mode=WAL"),this.db.exec("PRAGMA foreign_keys=ON"),this.db.exec("PRAGMA synchronous=NORMAL"),await this.migrate()}async disconnect(){this.cache.clear(),this.db.close()}async migrate(){let e=this.db.prepare("PRAGMA user_version").get();e.user_version<1?(this.db.exec(Me),this.db.exec(Ge),this.db.exec(`PRAGMA user_version = ${le}`)):e.user_version<2&&this.migrateToV2(),this.db.exec(`
40
37
  CREATE INDEX IF NOT EXISTS idx_profiles_tenant_compliance_active
41
38
  ON profiles (tenant_id, json_extract(profile_json,'$.complianceGroup'), json_extract(profile_json,'$.isActive'));
42
- `)}mapProfile(e){return{id:e.id,tenantId:e.tenant_id,name:e.name,defaultLocale:e.default_locale,version:e.version,profileJson:JSON.parse(e.profile_json),createdAt:e.created_at,updatedAt:e.updated_at}}async createProfile(e){let t=z(),n=new Date().toISOString();this.stmt("INSERT INTO profiles (id,tenant_id,name,default_locale,version,profile_json,created_at,updated_at) VALUES (?,?,?,?,?,?,?,?)").run(t,e.tenantId,e.name,e.defaultLocale,1,JSON.stringify(e.profileJson),n,n);let o=await this.getProfile(t);if(!o)throw new Error("Failed to create profile");return o}async updateProfile(e,t){if(!await this.getProfile(e))throw new Error(`Profile ${e} not found`);let o=new Date().toISOString(),s=["updated_at = ?"],r=[o];t.name!=null&&(s.push("name = ?"),r.push(t.name)),t.defaultLocale!=null&&(s.push("default_locale = ?"),r.push(t.defaultLocale)),t.profileJson!=null&&(s.push("profile_json = ?"),r.push(JSON.stringify(t.profileJson))),t.version!=null&&(s.push("version = ?"),r.push(t.version)),r.push(e),this.stmt(`UPDATE profiles SET ${s.join(", ")} WHERE id = ?`).run(...r);let a=await this.getProfile(e);if(!a)throw new Error("Failed to update profile");return a}async deleteProfile(e){this.stmt("DELETE FROM profiles WHERE id = ?").run(e)}async getProfile(e){let t=this.stmt("SELECT * FROM profiles WHERE id = ?").get(e);return t?this.mapProfile(t):null}async getProfiles(e){return this.stmt("SELECT * FROM profiles WHERE tenant_id = ? ORDER BY created_at ASC").all(e).map(n=>this.mapProfile(n))}async findActiveProfileByComplianceGroup(e,t){let n=this.stmt(`SELECT * FROM profiles WHERE tenant_id = ?
39
+ `)}migrateToV2(){je({exec:e=>this.db.exec(e),all:e=>this.db.prepare(e).all()},this.dbPath)}mapProfile(e){return{id:e.id,tenantId:e.tenant_id,name:e.name,defaultLocale:e.default_locale,version:e.version,profileJson:JSON.parse(e.profile_json),createdAt:e.created_at,updatedAt:e.updated_at}}async createProfile(e){let t=K(),n=new Date().toISOString();this.stmt("INSERT INTO profiles (id,tenant_id,name,default_locale,version,profile_json,created_at,updated_at) VALUES (?,?,?,?,?,?,?,?)").run(t,e.tenantId,e.name,e.defaultLocale,1,JSON.stringify(e.profileJson),n,n);let o=await this.getProfile(t);if(!o)throw new Error("Failed to create profile");return o}async updateProfile(e,t){if(!await this.getProfile(e))throw new Error(`Profile ${e} not found`);let o=new Date().toISOString(),s=["updated_at = ?"],r=[o];t.name!=null&&(s.push("name = ?"),r.push(t.name)),t.defaultLocale!=null&&(s.push("default_locale = ?"),r.push(t.defaultLocale)),t.profileJson!=null&&(s.push("profile_json = ?"),r.push(JSON.stringify(t.profileJson))),t.version!=null&&(s.push("version = ?"),r.push(t.version)),r.push(e),this.stmt(`UPDATE profiles SET ${s.join(", ")} WHERE id = ?`).run(...r);let a=await this.getProfile(e);if(!a)throw new Error("Failed to update profile");return a}async deleteProfile(e){this.stmt("DELETE FROM profiles WHERE id = ?").run(e)}async getProfile(e){let t=this.stmt("SELECT * FROM profiles WHERE id = ?").get(e);return t?this.mapProfile(t):null}async getProfiles(e){return this.stmt("SELECT * FROM profiles WHERE tenant_id = ? ORDER BY created_at ASC").all(e).map(n=>this.mapProfile(n))}async findActiveProfileByComplianceGroup(e,t){let n=this.stmt(`SELECT * FROM profiles WHERE tenant_id = ?
43
40
  AND (json_extract(profile_json, '$.complianceGroup') = ? OR json_extract(profile_json, '$.customComplianceGroup') = ?)
44
- AND json_extract(profile_json, '$.isActive') = 1 LIMIT 1`).get(e,t,t);return n?this.mapProfile(n):null}mapConsent(e){return{id:e.id,tenantId:e.tenant_id,visitorId:e.visitor_id,profileId:e.profile_id,locale:e.locale,consentJson:JSON.parse(e.consent_json),gpcDetected:e.gpc_detected===1,source:e.source,...e.age_verified!=null&&e.age_verified!==0?{ageVerified:!0}:{},...e.parental_consent_token!=null?{parentalConsentToken:e.parental_consent_token}:{},...e.tcf_string!=null?{tcfString:e.tcf_string}:{},...e.gpp_string!=null?{gppString:e.gpp_string}:{},...e.signature!=null?{signature:e.signature}:{},createdAt:e.created_at,updatedAt:e.updated_at}}static CONSENT_SUMMARY_COLS="id, tenant_id, visitor_id, profile_id, locale, gpc_detected, source, age_verified, created_at, updated_at";mapConsentSummary(e){return{id:e.id,tenantId:e.tenant_id,visitorId:e.visitor_id,profileId:e.profile_id,locale:e.locale,gpcDetected:e.gpc_detected===1,source:e.source,...e.age_verified!=null&&e.age_verified!==0?{ageVerified:!0}:{},createdAt:e.created_at,updatedAt:e.updated_at}}async createConsent(e){let t=K(),n=new Date().toISOString();this.stmt("INSERT INTO consent_records (id,tenant_id,visitor_id,profile_id,locale,consent_json,gpc_detected,source,age_verified,parental_consent_token,tcf_string,gpp_string,signature,created_at,updated_at) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)").run(t,e.tenantId,e.visitorId,e.profileId,e.locale,JSON.stringify(e.consentJson),e.gpcDetected?1:0,e.source,e.ageVerified?1:0,e.parentalConsentToken??null,e.tcfString??null,e.gppString??null,e.signature??null,n,n);let o=(0,v.randomUUID)();this.stmt("INSERT INTO consent_history (id,tenant_id,consent_record_id,visitor_id,old_json,new_json,action,created_at) VALUES (?,?,?,?,?,?,?,?)").run(o,e.tenantId,t,e.visitorId,null,JSON.stringify(e.consentJson),"created",n);let s=await this.getConsent(e.visitorId);if(!s)throw new Error("Failed to create consent");return s}async updateConsent(e,t){let n=await this.getConsent(e);if(!n)throw new Error(`Consent for visitor ${e} not found`);let o=new Date().toISOString(),s=["updated_at = ?","consent_json = ?"],r=[o,JSON.stringify(t.consentJson)];t.locale!=null&&(s.push("locale = ?"),r.push(t.locale)),t.gpcDetected!=null&&(s.push("gpc_detected = ?"),r.push(t.gpcDetected?1:0)),t.signature!=null&&(s.push("signature = ?"),r.push(t.signature)),r.push(e),this.stmt(`UPDATE consent_records SET ${s.join(", ")} WHERE visitor_id = ?`).run(...r);let a=(0,v.randomUUID)();this.stmt("INSERT INTO consent_history (id,tenant_id,consent_record_id,visitor_id,old_json,new_json,action,created_at) VALUES (?,?,?,?,?,?,?,?)").run(a,n.tenantId,n.id,e,JSON.stringify(n.consentJson),JSON.stringify(t.consentJson),"updated",o);let c=await this.getConsent(e);if(!c)throw new Error("Failed to update consent");return c}async deleteConsent(e){this.stmt("DELETE FROM consent_history WHERE visitor_id = ?").run(e),this.stmt("DELETE FROM consent_records WHERE visitor_id = ?").run(e)}async getConsent(e){let t=this.stmt("SELECT * FROM consent_records WHERE visitor_id = ?").get(e);return t?this.mapConsent(t):null}async getConsents(e){let t=["tenant_id = ?"],n=[e.tenantId];if(e.profileId&&(t.push("profile_id = ?"),n.push(e.profileId)),e.from&&(t.push("created_at >= ?"),n.push(e.from)),e.to&&(t.push("created_at <= ?"),n.push(e.to)),e.q){t.push("(visitor_id LIKE ? OR profile_id LIKE ? OR locale LIKE ? OR source LIKE ?) ESCAPE '\\'");let d=j(e.q);n.push(d,d,d,d)}let o=t.join(" AND "),s=e.page??1,r=Math.min(e.limit??50,xn),a=(s-1)*r,c=this.stmt(`SELECT ${i.CONSENT_SUMMARY_COLS} FROM consent_records WHERE ${o} ORDER BY created_at DESC LIMIT ? OFFSET ?`).all(...n,r,a),l=this.stmt(`SELECT COUNT(*) AS total FROM consent_records WHERE ${o}`).get(...n);return{items:c.map(d=>this.mapConsentSummary(d)),total:l.total,page:s,limit:r}}async*streamConsents(e){let n=0;for(;;){let o=this.stmt("SELECT * FROM consent_records WHERE tenant_id = ? LIMIT ? OFFSET ?").all(e.tenantId,500,n);if(o.length===0)break;for(let s of o)yield this.mapConsent(s);n+=500}}async getConsentHistory(e){return this.stmt("SELECT * FROM consent_history WHERE visitor_id = ? ORDER BY created_at ASC").all(e).map(n=>({id:n.id,tenantId:n.tenant_id,consentRecordId:n.consent_record_id,visitorId:n.visitor_id,oldJson:n.old_json!=null?JSON.parse(n.old_json):null,newJson:JSON.parse(n.new_json),action:n.action,createdAt:n.created_at}))}async createNoticeShown(e){let t=(0,v.randomUUID)(),n=new Date().toISOString();return this.stmt("INSERT INTO notice_shown (id,tenant_id,visitor_id,profile_id,locale,created_at) VALUES (?,?,?,?,?,?)").run(t,e.tenantId,e.visitorId,e.profileId,e.locale,n),{id:t,tenantId:e.tenantId,visitorId:e.visitorId,profileId:e.profileId,locale:e.locale,createdAt:n}}async getNoticeShownForVisitor(e){return this.stmt("SELECT * FROM notice_shown WHERE visitor_id = ? ORDER BY created_at DESC").all(e).map(n=>({id:n.id,tenantId:n.tenant_id,visitorId:n.visitor_id,profileId:n.profile_id,locale:n.locale,createdAt:n.created_at}))}mapVisitor(e){return{id:e.id,tenantId:e.tenant_id,visitorId:e.visitor_id,firstSeen:e.first_seen,lastSeen:e.last_seen,...e.country!=null?{country:e.country}:{},...e.region!=null?{region:e.region}:{},...e.city!=null?{city:e.city}:{},...e.ip_hash!=null?{ipHash:e.ip_hash}:{},...e.user_agent_hash!=null?{userAgentHash:e.user_agent_hash}:{}}}async createVisitor(e){let t=q(),n=new Date().toISOString();this.stmt("INSERT INTO visitors (id,tenant_id,visitor_id,country,region,city,ip_hash,user_agent_hash,first_seen,last_seen) VALUES (?,?,?,?,?,?,?,?,?,?)").run(t,e.tenantId,e.visitorId,e.country??null,e.region??null,e.city??null,e.ipHash??null,e.userAgentHash??null,n,n);let o=await this.getVisitor(e.visitorId);if(!o)throw new Error("Failed to create visitor");return o}async updateVisitor(e,t){let n=new Date().toISOString(),o=["last_seen = ?"],s=[t.lastSeen??n];t.country!=null&&(o.push("country = ?"),s.push(t.country)),t.region!=null&&(o.push("region = ?"),s.push(t.region)),t.city!=null&&(o.push("city = ?"),s.push(t.city)),s.push(e),this.stmt(`UPDATE visitors SET ${o.join(", ")} WHERE visitor_id = ?`).run(...s);let r=await this.getVisitor(e);if(!r)throw new Error(`Visitor ${e} not found`);return r}async deleteVisitor(e){this.stmt("DELETE FROM visitors WHERE visitor_id = ?").run(e)}async getVisitor(e){let t=this.stmt("SELECT * FROM visitors WHERE visitor_id = ?").get(e);return t?this.mapVisitor(t):null}async getVisitors(e){let t=["tenant_id = ?"],n=[e.tenantId];if(e.from&&(t.push("first_seen >= ?"),n.push(e.from)),e.to&&(t.push("first_seen <= ?"),n.push(e.to)),e.q){t.push("(visitor_id LIKE ? OR country LIKE ?) ESCAPE '\\'");let d=j(e.q);n.push(d,d)}let o=t.join(" AND "),s=e.page??1,r=Math.min(e.limit??50,xn),a=(s-1)*r,c=this.stmt(`SELECT * FROM visitors WHERE ${o} ORDER BY last_seen DESC LIMIT ? OFFSET ?`).all(...n,r,a),l=this.stmt(`SELECT COUNT(*) AS total FROM visitors WHERE ${o}`).get(...n);return{items:c.map(d=>this.mapVisitor(d)),total:l.total,page:s,limit:r}}mapUser(e){let t=e.allowed_tenants?JSON.parse(e.allowed_tenants):[];return{id:e.id,tenantId:e.tenant_id,name:e.name,email:e.email,passwordHash:e.password_hash,isActive:e.is_active===1,totpEnabled:e.totp_enabled===1,...e.totp_secret!=null?{totpSecret:e.totp_secret}:{},allowedTenants:t,createdAt:e.created_at,updatedAt:e.updated_at}}async createUser(e){let t=(0,v.randomUUID)(),n=new Date().toISOString(),o=e.allowedTenants?.length?JSON.stringify(e.allowedTenants):null;this.stmt("INSERT INTO users (id,tenant_id,name,email,password_hash,allowed_tenants,created_at,updated_at) VALUES (?,?,?,?,?,?,?,?)").run(t,e.tenantId,e.name,e.email,e.passwordHash,o,n,n);let s=await this.getUserByEmail(e.email);if(!s)throw new Error("Failed to create user");return s}async updateUser(e,t){let n=new Date().toISOString(),o=["updated_at = ?"],s=[n];t.name!=null&&(o.push("name = ?"),s.push(t.name)),t.email!=null&&(o.push("email = ?"),s.push(t.email)),t.passwordHash!=null&&(o.push("password_hash = ?"),s.push(t.passwordHash)),t.isActive!=null&&(o.push("is_active = ?"),s.push(t.isActive?1:0)),"totpSecret"in t&&(o.push("totp_secret = ?"),s.push(t.totpSecret??null)),t.totpEnabled!=null&&(o.push("totp_enabled = ?"),s.push(t.totpEnabled?1:0)),"allowedTenants"in t&&(o.push("allowed_tenants = ?"),s.push(t.allowedTenants?.length?JSON.stringify(t.allowedTenants):null)),s.push(e),this.stmt(`UPDATE users SET ${o.join(", ")} WHERE id = ?`).run(...s);let r=this.stmt("SELECT * FROM users WHERE id = ?").get(e);if(!r)throw new Error(`User ${e} not found`);return this.mapUser(r)}async deleteUser(e){this.stmt("DELETE FROM user_roles WHERE user_id = ?").run(e),this.stmt("DELETE FROM users WHERE id = ?").run(e)}async getUserById(e){let t=this.stmt("SELECT * FROM users WHERE id = ?").get(e);return t?this.mapUser(t):null}async getUserByEmail(e){let t=this.stmt("SELECT * FROM users WHERE email = ?").get(e);return t?this.mapUser(t):null}async getUsers(e){return this.stmt("SELECT * FROM users WHERE tenant_id = ? ORDER BY created_at ASC").all(e).map(n=>this.mapUser(n))}async countUsers(e){return(e?this.stmt("SELECT COUNT(*) as n FROM users WHERE tenant_id = ?").get(e):this.stmt("SELECT COUNT(*) as n FROM users").get())?.n??0}async getRoles(e){return this.stmt("SELECT * FROM roles WHERE tenant_id = ?").all(e).map(n=>({id:n.id,tenantId:n.tenant_id,name:n.name,...n.description!=null?{description:n.description}:{}}))}async createRole(e){let t=(0,v.randomUUID)();this.stmt("INSERT INTO roles (id,tenant_id,name,description) VALUES (?,?,?,?)").run(t,e.tenantId,e.name,e.description??null);let n=this.stmt("SELECT * FROM roles WHERE id = ?").get(t);if(!n)throw new Error("Failed to create role");return{id:n.id,tenantId:n.tenant_id,name:n.name,...n.description!=null?{description:n.description}:{}}}async updateRole(e,t){let n=[],o=[];t.name!=null&&(n.push("name = ?"),o.push(t.name)),t.description!=null&&(n.push("description = ?"),o.push(t.description)),n.length>0&&(o.push(e),this.stmt(`UPDATE roles SET ${n.join(", ")} WHERE id = ?`).run(...o));let s=this.stmt("SELECT * FROM roles WHERE id = ?").get(e);if(!s)throw new Error(`Role ${e} not found`);return{id:s.id,tenantId:s.tenant_id,name:s.name,...s.description!=null?{description:s.description}:{}}}async deleteRole(e){this.stmt("DELETE FROM role_permissions WHERE role_id = ?").run(e),this.stmt("DELETE FROM user_roles WHERE role_id = ?").run(e),this.stmt("DELETE FROM roles WHERE id = ?").run(e)}async getAllPermissions(){return this.stmt("SELECT * FROM permissions ORDER BY name ASC").all().map(t=>({id:t.id,name:t.name,...t.description!=null?{description:t.description}:{}}))}async assignPermissionToRole(e,t){this.stmt("INSERT OR IGNORE INTO role_permissions (role_id,permission_id) VALUES (?,?)").run(e,t)}async revokePermissionFromRole(e,t){this.stmt("DELETE FROM role_permissions WHERE role_id = ? AND permission_id = ?").run(e,t)}async getPermissionsForRole(e){return this.stmt("SELECT p.* FROM permissions p JOIN role_permissions rp ON rp.permission_id = p.id WHERE rp.role_id = ?").all(e).map(n=>({id:n.id,name:n.name,...n.description!=null?{description:n.description}:{}}))}async getUserRoles(e,t){return(t?this.stmt("SELECT r.* FROM roles r JOIN user_roles ur ON ur.role_id = r.id WHERE ur.user_id = ? AND ur.tenant_id = ?").all(e,t):this.stmt("SELECT r.* FROM roles r JOIN user_roles ur ON ur.role_id = r.id WHERE ur.user_id = ?").all(e)).map(o=>({id:o.id,tenantId:o.tenant_id,name:o.name,...o.description!=null?{description:o.description}:{}}))}async assignRole(e,t,n="default"){this.stmt("INSERT OR IGNORE INTO user_roles (user_id, role_id, tenant_id) VALUES (?,?,?)").run(e,t,n)}async revokeRole(e,t,n){n?this.stmt("DELETE FROM user_roles WHERE user_id = ? AND role_id = ? AND tenant_id = ?").run(e,t,n):this.stmt("DELETE FROM user_roles WHERE user_id = ? AND role_id = ?").run(e,t)}async createLog(e){let t=(0,v.randomUUID)(),n=new Date().toISOString();this.stmt("INSERT INTO audit_logs (id,tenant_id,user_id,action,resource_type,resource_id,old_data,new_data,created_at) VALUES (?,?,?,?,?,?,?,?,?)").run(t,e.tenantId,e.userId??null,e.action,e.resourceType,e.resourceId??null,e.oldData!=null?JSON.stringify(e.oldData):null,e.newData!=null?JSON.stringify(e.newData):null,n)}async getLogs(e){let t=["tenant_id = ?"],n=[e.tenantId];if(e.action&&(t.push("action = ?"),n.push(e.action)),e.resourceType&&(t.push("resource_type = ?"),n.push(e.resourceType)),e.from&&(t.push("created_at >= ?"),n.push(e.from)),e.to&&(t.push("created_at <= ?"),n.push(e.to)),e.q){t.push("(action LIKE ? OR resource_type LIKE ? OR resource_id LIKE ? OR user_id LIKE ?) ESCAPE '\\'");let d=j(e.q);n.push(d,d,d,d)}let o=t.join(" AND "),s=e.page??1,r=Math.min(e.limit??50,xn),a=(s-1)*r,c=this.stmt(`SELECT ${i.AUDIT_SUMMARY_COLS} FROM audit_logs WHERE ${o} ORDER BY created_at DESC LIMIT ? OFFSET ?`).all(...n,r,a),l=this.stmt(`SELECT COUNT(*) AS total FROM audit_logs WHERE ${o}`).get(...n);return{items:c.map(d=>this.mapAuditSummary(d)),total:l.total,page:s,limit:r}}async getAuditLogById(e){let t=this.stmt("SELECT * FROM audit_logs WHERE id = ?").get(e);return t?this.mapAuditLog(t):null}static AUDIT_SUMMARY_COLS="id, tenant_id, user_id, action, resource_type, resource_id, created_at";mapAuditSummary(e){return{id:e.id,tenantId:e.tenant_id,action:e.action,resourceType:e.resource_type,...e.user_id!=null?{userId:e.user_id}:{},...e.resource_id!=null?{resourceId:e.resource_id}:{},createdAt:e.created_at}}mapAuditLog(e){return{id:e.id,tenantId:e.tenant_id,action:e.action,resourceType:e.resource_type,createdAt:e.created_at,...e.user_id!=null?{userId:e.user_id}:{},...e.resource_id!=null?{resourceId:e.resource_id}:{},...e.old_data!=null?{oldData:JSON.parse(e.old_data)}:{},...e.new_data!=null?{newData:JSON.parse(e.new_data)}:{}}}async*streamAuditLogs(e){let t=["tenant_id = ?"],n=[e.tenantId];e.action&&(t.push("action = ?"),n.push(e.action)),e.from&&(t.push("created_at >= ?"),n.push(e.from)),e.to&&(t.push("created_at <= ?"),n.push(e.to));let o=500,s=0;for(;;){let r=this.stmt(`SELECT * FROM audit_logs WHERE ${t.join(" AND ")} ORDER BY created_at DESC LIMIT ? OFFSET ?`).all(...n,o,s);if(r.length===0)break;for(let a of r)yield this.mapAuditLog(a);s+=o}}async getOverviewStats(e){let t=this.stmt("SELECT COUNT(*) as n FROM consent_records WHERE tenant_id = ?").get(e),n=this.stmt("SELECT COUNT(*) as n FROM consent_records WHERE tenant_id = ? AND gpc_detected = 1").get(e),o=this.stmt("SELECT COUNT(*) as n FROM visitors WHERE tenant_id = ?").get(e),s=t?.n??0,r=this.stmt("SELECT consent_json FROM consent_records WHERE tenant_id = ? ORDER BY created_at DESC LIMIT 500").all(e),a=0,c=0;for(let d of r){let u=Object.values(JSON.parse(d.consent_json)),m=u.length>0?u.filter(h=>h==="granted").length/u.length:0;m>=.8?a++:m<=.2&&c++}let l=r.length||1;return{totalConsents:s,gpcDetectedCount:n?.n??0,totalVisitors:o?.n??0,acceptedPct:Math.round(a/l*100),rejectedPct:Math.round(c/l*100)}}async getCategoryStats(e){let t=this.stmt("SELECT consent_json FROM consent_records WHERE tenant_id = ? LIMIT 5000").all(e),n={};for(let o of t){let s=JSON.parse(o.consent_json);for(let[r,a]of Object.entries(s))n[r]||(n[r]={granted:0,denied:0,objected:0}),a==="granted"?n[r].granted++:a==="denied"?n[r].denied++:a==="objected"&&n[r].objected++}return n}async getTimeline(e,t=30){return this.stmt("SELECT date(created_at) as date, COUNT(*) as count FROM consent_records WHERE tenant_id = ? AND created_at >= date('now', ?) GROUP BY date(created_at) ORDER BY date ASC").all(e,`-${t} days`).map(o=>({date:o.date,count:o.count}))}async getCountries(e){return this.stmt("SELECT v.country, COUNT(*) as count FROM consent_records cr JOIN visitors v ON v.visitor_id = cr.visitor_id WHERE cr.tenant_id = ? AND v.country IS NOT NULL GROUP BY v.country ORDER BY count DESC LIMIT 50").all(e).map(n=>({country:n.country,count:n.count}))}async getGpcStats(e){let t=this.stmt("SELECT COUNT(*) as n FROM consent_records WHERE tenant_id = ?").get(e),n=this.stmt("SELECT COUNT(*) as n FROM consent_records WHERE tenant_id = ? AND gpc_detected = 1").get(e),o=t?.n??0,s=n?.n??0;return{detected:s,total:o,rate:o>0?Math.round(s/o*100):0}}async getTenants(){return this.stmt("SELECT * FROM tenants ORDER BY name ASC").all().map(t=>({id:t.id,name:t.name,slug:t.slug,createdAt:t.created_at,updatedAt:t.updated_at}))}async createTenant(e){let t=(0,v.randomUUID)(),n=new Date().toISOString();this.stmt("INSERT INTO tenants (id,name,slug,created_at,updated_at) VALUES (?,?,?,?,?)").run(t,e.name,e.slug,n,n);let o=this.stmt("SELECT * FROM tenants WHERE id = ?").get(t);if(!o)throw new Error("Failed to create tenant");return{id:o.id,name:o.name,slug:o.slug,createdAt:o.created_at,updatedAt:o.updated_at}}async updateTenant(e,t){let n=new Date().toISOString(),o=["updated_at = ?"],s=[n];t.name!=null&&(o.push("name = ?"),s.push(t.name)),t.slug!=null&&(o.push("slug = ?"),s.push(t.slug)),s.push(e),this.stmt(`UPDATE tenants SET ${o.join(", ")} WHERE id = ?`).run(...s);let r=this.stmt("SELECT * FROM tenants WHERE id = ?").get(e);if(!r)throw new Error(`Tenant ${e} not found`);return{id:r.id,name:r.name,slug:r.slug,createdAt:r.created_at,updatedAt:r.updated_at}}async deleteTenant(e){this.stmt("DELETE FROM tenants WHERE id = ?").run(e)}async getSettings(e){let t=this.stmt("SELECT allowed_origins_json, admin_allowed_origins_json, setup_completed, profiles_seeded, tcf_confirmation_json, gpp_confirmation_json FROM tenant_settings WHERE tenant_id = ?").get(e);return t?{allowedOrigins:JSON.parse(t.allowed_origins_json),adminAllowedOrigins:JSON.parse(t.admin_allowed_origins_json),setupCompleted:!!t.setup_completed,profilesSeeded:!!t.profiles_seeded,tcfConfirmation:t.tcf_confirmation_json?JSON.parse(t.tcf_confirmation_json):void 0,gppConfirmation:t.gpp_confirmation_json?JSON.parse(t.gpp_confirmation_json):void 0}:{}}async updateSettings(e,t){let o={...await this.getSettings(e),...t};return this.stmt(`INSERT INTO tenant_settings (tenant_id, allowed_origins_json, admin_allowed_origins_json, setup_completed, profiles_seeded, tcf_confirmation_json, gpp_confirmation_json, updated_at) VALUES (?,?,?,?,?,?,?,?)
45
- ON CONFLICT(tenant_id) DO UPDATE SET allowed_origins_json = excluded.allowed_origins_json, admin_allowed_origins_json = excluded.admin_allowed_origins_json, setup_completed = excluded.setup_completed, profiles_seeded = excluded.profiles_seeded, tcf_confirmation_json = excluded.tcf_confirmation_json, gpp_confirmation_json = excluded.gpp_confirmation_json, updated_at = excluded.updated_at`).run(e,JSON.stringify(o.allowedOrigins??[]),JSON.stringify(o.adminAllowedOrigins??[]),o.setupCompleted?1:0,o.profilesSeeded?1:0,o.tcfConfirmation?JSON.stringify(o.tcfConfirmation):null,o.gppConfirmation?JSON.stringify(o.gppConfirmation):null,new Date().toISOString()),this.getSettings(e)}async purgeExpiredConsents(e){let t=new Date(Date.now()-e*864e5).toISOString(),n=this.stmt("SELECT visitor_id FROM consent_records WHERE created_at < ?").all(t);for(let{visitor_id:o}of n)this.stmt("DELETE FROM consent_history WHERE visitor_id = ?").run(o),this.stmt("DELETE FROM consent_records WHERE visitor_id = ?").run(o);return n.length}mapApiKey(e){return{id:e.id,tenantId:e.tenant_id,keyHash:e.key_hash,name:e.name,isActive:e.is_active===1,...e.created_by!==null?{createdBy:e.created_by}:{},...e.expire_by!==null?{expireBy:e.expire_by}:{},createdAt:e.created_at,...e.updated_at!==null?{updatedAt:e.updated_at}:{}}}async createApiKey(e){let t=(0,v.randomUUID)(),n=new Date().toISOString();this.stmt("INSERT INTO api_keys (id,tenant_id,key_hash,name,created_by,expire_by,created_at,updated_at) VALUES (?,?,?,?,?,?,?,?)").run(t,e.tenantId,e.keyHash,e.name,e.createdBy??null,e.expireBy??null,n,n);let o=this.stmt("SELECT * FROM api_keys WHERE id = ?").get(t);if(!o)throw new Error("Failed to create API key");return this.mapApiKey(o)}async getApiKeyByHash(e){let t=this.stmt("SELECT * FROM api_keys WHERE key_hash = ? AND is_active = 1").get(e);return t?this.mapApiKey(t):null}async revokeApiKey(e){this.stmt("UPDATE api_keys SET is_active = 0, updated_at = ? WHERE id = ?").run(new Date().toISOString(),e)}async reactivateApiKey(e){let t=new Date().toISOString();this.stmt("UPDATE api_keys SET is_active = 1, updated_at = ?, expire_by = CASE WHEN expire_by <= ? THEN NULL ELSE expire_by END WHERE id = ?").run(t,t,e)}async deleteApiKey(e){this.stmt("DELETE FROM api_keys WHERE id = ?").run(e)}async getApiKeys(e){return this.stmt("SELECT * FROM api_keys WHERE tenant_id = ? ORDER BY created_at DESC").all(e).map(n=>this.mapApiKey(n))}mapConsentTemplate(e){return{id:e.id,tenantId:e.tenant_id,name:e.name,cookies:JSON.parse(e.cookies_json),categories:JSON.parse(e.categories_json),createdAt:e.created_at,updatedAt:e.updated_at}}async createConsentTemplate(e){let t=Y(),n=new Date().toISOString();return this.stmt("INSERT INTO consent_templates (id,tenant_id,name,cookies_json,categories_json,created_at,updated_at) VALUES (?,?,?,?,?,?,?)").run(t,e.tenantId,e.name,JSON.stringify(e.cookies),JSON.stringify(e.categories),n,n),this.mapConsentTemplate(this.stmt("SELECT * FROM consent_templates WHERE id = ?").get(t))}async updateConsentTemplate(e,t){let n=new Date().toISOString();t.name!==void 0&&this.stmt("UPDATE consent_templates SET name = ?, updated_at = ? WHERE id = ?").run(t.name,n,e),t.cookies!==void 0&&this.stmt("UPDATE consent_templates SET cookies_json = ?, updated_at = ? WHERE id = ?").run(JSON.stringify(t.cookies),n,e),t.categories!==void 0&&this.stmt("UPDATE consent_templates SET categories_json = ?, updated_at = ? WHERE id = ?").run(JSON.stringify(t.categories),n,e);let o=this.stmt("SELECT * FROM consent_templates WHERE id = ?").get(e);if(!o)throw new Error("Consent template not found");return this.mapConsentTemplate(o)}async deleteConsentTemplate(e){this.stmt("DELETE FROM consent_templates WHERE id = ?").run(e)}async getConsentTemplate(e){let t=this.stmt("SELECT * FROM consent_templates WHERE id = ?").get(e);return t?this.mapConsentTemplate(t):null}async getConsentTemplates(e){return this.stmt("SELECT * FROM consent_templates WHERE tenant_id = ? ORDER BY name ASC").all(e).map(n=>this.mapConsentTemplate(n))}async copyConsentTemplate(e,t){let n=await this.getConsentTemplate(e);if(!n)throw new Error("Consent template not found");return this.createConsentTemplate({tenantId:n.tenantId,name:t,cookies:n.cookies,categories:n.categories})}mapUITemplate(e){let t=JSON.parse(e.settings_json);return{id:e.id,tenantId:e.tenant_id,name:e.name,...t,createdAt:e.created_at,updatedAt:e.updated_at}}async createUITemplate(e){let t=Q(),n=new Date().toISOString(),{tenantId:o,name:s,...r}=e;return this.stmt("INSERT INTO ui_templates (id,tenant_id,name,settings_json,created_at,updated_at) VALUES (?,?,?,?,?,?)").run(t,o,s,JSON.stringify(r),n,n),this.mapUITemplate(this.stmt("SELECT * FROM ui_templates WHERE id = ?").get(t))}async updateUITemplate(e,t){let n=new Date().toISOString(),o=this.stmt("SELECT * FROM ui_templates WHERE id = ?").get(e);if(!o)throw new Error("UI template not found");t.name!==void 0&&this.stmt("UPDATE ui_templates SET name = ?, updated_at = ? WHERE id = ?").run(t.name,n,e);let{name:s,...r}=t;if(Object.keys(r).length>0){let c={...JSON.parse(o.settings_json),...r};this.stmt("UPDATE ui_templates SET settings_json = ?, updated_at = ? WHERE id = ?").run(JSON.stringify(c),n,e)}return this.mapUITemplate(this.stmt("SELECT * FROM ui_templates WHERE id = ?").get(e))}async deleteUITemplate(e){this.stmt("DELETE FROM ui_templates WHERE id = ?").run(e)}async getUITemplate(e){let t=this.stmt("SELECT * FROM ui_templates WHERE id = ?").get(e);return t?this.mapUITemplate(t):null}async getUITemplates(e){return this.stmt("SELECT * FROM ui_templates WHERE tenant_id = ? ORDER BY name ASC").all(e).map(n=>this.mapUITemplate(n))}async copyUITemplate(e,t){let n=await this.getUITemplate(e);if(!n)throw new Error("UI template not found");let{tenantId:o,mainBanner:s,gpcBanner:r,preferenceModal:a}=n;return this.createUITemplate({tenantId:o,name:t,mainBanner:s,gpcBanner:r,preferenceModal:a})}mapProfileSummary(e){return{id:e.id,name:e.name,defaultLocale:e.default_locale,complianceGroup:e.compliance_group??null,customComplianceGroup:e.custom_compliance_group??null,isActive:e.is_active===1,consentTemplateName:e.consent_template_name,uiTemplateName:e.ui_template_name,createdAt:e.created_at,updatedAt:e.updated_at}}PROFILE_SUMMARY_SQL=`
41
+ AND json_extract(profile_json, '$.isActive') = 1 LIMIT 1`).get(e,t,t);return n?this.mapProfile(n):null}mapConsent(e){return{id:e.id,tenantId:e.tenant_id,visitorId:e.visitor_id,profileId:e.profile_id,...e.profile_version!=null?{profileVersion:e.profile_version}:{},locale:e.locale,consentJson:JSON.parse(e.consent_json),gpcDetected:e.gpc_detected===1,source:e.source,...e.age_verified!=null&&e.age_verified!==0?{ageVerified:!0}:{},...e.parental_consent_token!=null?{parentalConsentToken:e.parental_consent_token}:{},...e.tcf_string!=null?{tcfString:e.tcf_string}:{},...e.gpp_string!=null?{gppString:e.gpp_string}:{},...e.signature!=null?{signature:e.signature}:{},createdAt:e.created_at,updatedAt:e.updated_at}}static CONSENT_SUMMARY_COLS="id, tenant_id, visitor_id, profile_id, locale, gpc_detected, source, age_verified, created_at, updated_at";mapConsentSummary(e){return{id:e.id,tenantId:e.tenant_id,visitorId:e.visitor_id,profileId:e.profile_id,locale:e.locale,gpcDetected:e.gpc_detected===1,source:e.source,...e.age_verified!=null&&e.age_verified!==0?{ageVerified:!0}:{},createdAt:e.created_at,updatedAt:e.updated_at}}async createConsent(e){let t=Y(),n=new Date().toISOString();this.stmt("INSERT INTO consent_records (id,tenant_id,visitor_id,profile_id,profile_version,locale,consent_json,gpc_detected,source,age_verified,parental_consent_token,tcf_string,gpp_string,signature,created_at,updated_at) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)").run(t,e.tenantId,e.visitorId,e.profileId,e.profileVersion??null,e.locale,JSON.stringify(e.consentJson),e.gpcDetected?1:0,e.source,e.ageVerified?1:0,e.parentalConsentToken??null,e.tcfString??null,e.gppString??null,e.signature??null,n,n);let o=(0,C.randomUUID)();this.stmt("INSERT INTO consent_history (id,tenant_id,consent_record_id,visitor_id,profile_version,old_json,new_json,action,created_at) VALUES (?,?,?,?,?,?,?,?,?)").run(o,e.tenantId,t,e.visitorId,e.profileVersion??null,null,JSON.stringify(e.consentJson),"created",n);let s=await this.getConsent(e.visitorId);if(!s)throw new Error("Failed to create consent");return s}async updateConsent(e,t){let n=await this.getConsent(e);if(!n)throw new Error(`Consent for visitor ${e} not found`);let o=new Date().toISOString(),s=["updated_at = ?","consent_json = ?"],r=[o,JSON.stringify(t.consentJson)];t.profileVersion!=null&&(s.push("profile_version = ?"),r.push(t.profileVersion)),t.locale!=null&&(s.push("locale = ?"),r.push(t.locale)),t.gpcDetected!=null&&(s.push("gpc_detected = ?"),r.push(t.gpcDetected?1:0)),t.signature!=null&&(s.push("signature = ?"),r.push(t.signature)),r.push(e),this.stmt(`UPDATE consent_records SET ${s.join(", ")} WHERE visitor_id = ?`).run(...r);let a=(0,C.randomUUID)();this.stmt("INSERT INTO consent_history (id,tenant_id,consent_record_id,visitor_id,profile_version,old_json,new_json,action,created_at) VALUES (?,?,?,?,?,?,?,?,?)").run(a,n.tenantId,n.id,e,t.profileVersion??n.profileVersion??null,JSON.stringify(n.consentJson),JSON.stringify(t.consentJson),"updated",o);let c=await this.getConsent(e);if(!c)throw new Error("Failed to update consent");return c}async deleteConsent(e){this.stmt("DELETE FROM consent_history WHERE visitor_id = ?").run(e),this.stmt("DELETE FROM consent_records WHERE visitor_id = ?").run(e)}async getConsent(e){let t=this.stmt("SELECT * FROM consent_records WHERE visitor_id = ?").get(e);return t?this.mapConsent(t):null}async getConsents(e){let t=["tenant_id = ?"],n=[e.tenantId];if(e.profileId&&(t.push("profile_id = ?"),n.push(e.profileId)),e.from&&(t.push("created_at >= ?"),n.push(e.from)),e.to&&(t.push("created_at <= ?"),n.push(e.to)),e.q){t.push("(visitor_id LIKE ? OR profile_id LIKE ? OR locale LIKE ? OR source LIKE ?) ESCAPE '\\'");let d=j(e.q);n.push(d,d,d,d)}let o=t.join(" AND "),s=e.page??1,r=Math.min(e.limit??50,zn),a=(s-1)*r,c=this.stmt(`SELECT ${i.CONSENT_SUMMARY_COLS} FROM consent_records WHERE ${o} ORDER BY created_at DESC LIMIT ? OFFSET ?`).all(...n,r,a),l=this.stmt(`SELECT COUNT(*) AS total FROM consent_records WHERE ${o}`).get(...n);return{items:c.map(d=>this.mapConsentSummary(d)),total:l.total,page:s,limit:r}}async*streamConsents(e){let n=0;for(;;){let o=this.stmt("SELECT * FROM consent_records WHERE tenant_id = ? LIMIT ? OFFSET ?").all(e.tenantId,500,n);if(o.length===0)break;for(let s of o)yield this.mapConsent(s);n+=500}}async getConsentHistory(e){return this.stmt("SELECT * FROM consent_history WHERE visitor_id = ? ORDER BY created_at ASC").all(e).map(n=>({id:n.id,tenantId:n.tenant_id,consentRecordId:n.consent_record_id,visitorId:n.visitor_id,...n.profile_version!=null?{profileVersion:n.profile_version}:{},oldJson:n.old_json!=null?JSON.parse(n.old_json):null,newJson:JSON.parse(n.new_json),action:n.action,createdAt:n.created_at}))}async createNoticeShown(e){let t=(0,C.randomUUID)(),n=new Date().toISOString();return this.stmt("INSERT INTO notice_shown (id,tenant_id,visitor_id,profile_id,locale,created_at) VALUES (?,?,?,?,?,?)").run(t,e.tenantId,e.visitorId,e.profileId,e.locale,n),{id:t,tenantId:e.tenantId,visitorId:e.visitorId,profileId:e.profileId,locale:e.locale,createdAt:n}}async getNoticeShownForVisitor(e){return this.stmt("SELECT * FROM notice_shown WHERE visitor_id = ? ORDER BY created_at DESC").all(e).map(n=>({id:n.id,tenantId:n.tenant_id,visitorId:n.visitor_id,profileId:n.profile_id,locale:n.locale,createdAt:n.created_at}))}mapVisitor(e){return{id:e.id,tenantId:e.tenant_id,visitorId:e.visitor_id,firstSeen:e.first_seen,lastSeen:e.last_seen,...e.country!=null?{country:e.country}:{},...e.region!=null?{region:e.region}:{},...e.city!=null?{city:e.city}:{},...e.ip_hash!=null?{ipHash:e.ip_hash}:{},...e.user_agent_hash!=null?{userAgentHash:e.user_agent_hash}:{}}}async createVisitor(e){let t=q(),n=new Date().toISOString();this.stmt("INSERT INTO visitors (id,tenant_id,visitor_id,country,region,city,ip_hash,user_agent_hash,first_seen,last_seen) VALUES (?,?,?,?,?,?,?,?,?,?)").run(t,e.tenantId,e.visitorId,e.country??null,e.region??null,e.city??null,e.ipHash??null,e.userAgentHash??null,n,n);let o=await this.getVisitor(e.visitorId);if(!o)throw new Error("Failed to create visitor");return o}async updateVisitor(e,t){let n=new Date().toISOString(),o=["last_seen = ?"],s=[t.lastSeen??n];t.country!=null&&(o.push("country = ?"),s.push(t.country)),t.region!=null&&(o.push("region = ?"),s.push(t.region)),t.city!=null&&(o.push("city = ?"),s.push(t.city)),s.push(e),this.stmt(`UPDATE visitors SET ${o.join(", ")} WHERE visitor_id = ?`).run(...s);let r=await this.getVisitor(e);if(!r)throw new Error(`Visitor ${e} not found`);return r}async deleteVisitor(e){this.stmt("DELETE FROM visitors WHERE visitor_id = ?").run(e)}async getVisitor(e){let t=this.stmt("SELECT * FROM visitors WHERE visitor_id = ?").get(e);return t?this.mapVisitor(t):null}async getVisitors(e){let t=["tenant_id = ?"],n=[e.tenantId];if(e.from&&(t.push("first_seen >= ?"),n.push(e.from)),e.to&&(t.push("first_seen <= ?"),n.push(e.to)),e.q){t.push("(visitor_id LIKE ? OR country LIKE ?) ESCAPE '\\'");let d=j(e.q);n.push(d,d)}let o=t.join(" AND "),s=e.page??1,r=Math.min(e.limit??50,zn),a=(s-1)*r,c=this.stmt(`SELECT * FROM visitors WHERE ${o} ORDER BY last_seen DESC LIMIT ? OFFSET ?`).all(...n,r,a),l=this.stmt(`SELECT COUNT(*) AS total FROM visitors WHERE ${o}`).get(...n);return{items:c.map(d=>this.mapVisitor(d)),total:l.total,page:s,limit:r}}mapUser(e){let t=e.allowed_tenants?JSON.parse(e.allowed_tenants):[];return{id:e.id,tenantId:e.tenant_id,name:e.name,email:e.email,passwordHash:e.password_hash,isActive:e.is_active===1,totpEnabled:e.totp_enabled===1,...e.totp_secret!=null?{totpSecret:e.totp_secret}:{},allowedTenants:t,createdAt:e.created_at,updatedAt:e.updated_at}}async createUser(e){let t=(0,C.randomUUID)(),n=new Date().toISOString(),o=e.allowedTenants?.length?JSON.stringify(e.allowedTenants):null;this.stmt("INSERT INTO users (id,tenant_id,name,email,password_hash,allowed_tenants,created_at,updated_at) VALUES (?,?,?,?,?,?,?,?)").run(t,e.tenantId,e.name,e.email,e.passwordHash,o,n,n);let s=await this.getUserByEmail(e.email);if(!s)throw new Error("Failed to create user");return s}async updateUser(e,t){let n=new Date().toISOString(),o=["updated_at = ?"],s=[n];t.name!=null&&(o.push("name = ?"),s.push(t.name)),t.email!=null&&(o.push("email = ?"),s.push(t.email)),t.passwordHash!=null&&(o.push("password_hash = ?"),s.push(t.passwordHash)),t.isActive!=null&&(o.push("is_active = ?"),s.push(t.isActive?1:0)),"totpSecret"in t&&(o.push("totp_secret = ?"),s.push(t.totpSecret??null)),t.totpEnabled!=null&&(o.push("totp_enabled = ?"),s.push(t.totpEnabled?1:0)),"allowedTenants"in t&&(o.push("allowed_tenants = ?"),s.push(t.allowedTenants?.length?JSON.stringify(t.allowedTenants):null)),s.push(e),this.stmt(`UPDATE users SET ${o.join(", ")} WHERE id = ?`).run(...s);let r=this.stmt("SELECT * FROM users WHERE id = ?").get(e);if(!r)throw new Error(`User ${e} not found`);return this.mapUser(r)}async deleteUser(e){this.stmt("DELETE FROM user_roles WHERE user_id = ?").run(e),this.stmt("DELETE FROM users WHERE id = ?").run(e)}async getUserById(e){let t=this.stmt("SELECT * FROM users WHERE id = ?").get(e);return t?this.mapUser(t):null}async getUserByEmail(e){let t=this.stmt("SELECT * FROM users WHERE email = ?").get(e);return t?this.mapUser(t):null}async getUsers(e){return this.stmt("SELECT * FROM users WHERE tenant_id = ? ORDER BY created_at ASC").all(e).map(n=>this.mapUser(n))}async countUsers(e){return(e?this.stmt("SELECT COUNT(*) as n FROM users WHERE tenant_id = ?").get(e):this.stmt("SELECT COUNT(*) as n FROM users").get())?.n??0}async getRoles(e){return this.stmt("SELECT * FROM roles WHERE tenant_id = ?").all(e).map(n=>({id:n.id,tenantId:n.tenant_id,name:n.name,...n.description!=null?{description:n.description}:{}}))}async createRole(e){let t=(0,C.randomUUID)();this.stmt("INSERT INTO roles (id,tenant_id,name,description) VALUES (?,?,?,?)").run(t,e.tenantId,e.name,e.description??null);let n=this.stmt("SELECT * FROM roles WHERE id = ?").get(t);if(!n)throw new Error("Failed to create role");return{id:n.id,tenantId:n.tenant_id,name:n.name,...n.description!=null?{description:n.description}:{}}}async updateRole(e,t){let n=[],o=[];t.name!=null&&(n.push("name = ?"),o.push(t.name)),t.description!=null&&(n.push("description = ?"),o.push(t.description)),n.length>0&&(o.push(e),this.stmt(`UPDATE roles SET ${n.join(", ")} WHERE id = ?`).run(...o));let s=this.stmt("SELECT * FROM roles WHERE id = ?").get(e);if(!s)throw new Error(`Role ${e} not found`);return{id:s.id,tenantId:s.tenant_id,name:s.name,...s.description!=null?{description:s.description}:{}}}async deleteRole(e){this.stmt("DELETE FROM role_permissions WHERE role_id = ?").run(e),this.stmt("DELETE FROM user_roles WHERE role_id = ?").run(e),this.stmt("DELETE FROM roles WHERE id = ?").run(e)}async getAllPermissions(){return this.stmt("SELECT * FROM permissions ORDER BY name ASC").all().map(t=>({id:t.id,name:t.name,...t.description!=null?{description:t.description}:{}}))}async assignPermissionToRole(e,t){this.stmt("INSERT OR IGNORE INTO role_permissions (role_id,permission_id) VALUES (?,?)").run(e,t)}async revokePermissionFromRole(e,t){this.stmt("DELETE FROM role_permissions WHERE role_id = ? AND permission_id = ?").run(e,t)}async getPermissionsForRole(e){return this.stmt("SELECT p.* FROM permissions p JOIN role_permissions rp ON rp.permission_id = p.id WHERE rp.role_id = ?").all(e).map(n=>({id:n.id,name:n.name,...n.description!=null?{description:n.description}:{}}))}async getUserRoles(e,t){return(t?this.stmt("SELECT r.* FROM roles r JOIN user_roles ur ON ur.role_id = r.id WHERE ur.user_id = ? AND ur.tenant_id = ?").all(e,t):this.stmt("SELECT r.* FROM roles r JOIN user_roles ur ON ur.role_id = r.id WHERE ur.user_id = ?").all(e)).map(o=>({id:o.id,tenantId:o.tenant_id,name:o.name,...o.description!=null?{description:o.description}:{}}))}async assignRole(e,t,n="default"){this.stmt("INSERT OR IGNORE INTO user_roles (user_id, role_id, tenant_id) VALUES (?,?,?)").run(e,t,n)}async revokeRole(e,t,n){n?this.stmt("DELETE FROM user_roles WHERE user_id = ? AND role_id = ? AND tenant_id = ?").run(e,t,n):this.stmt("DELETE FROM user_roles WHERE user_id = ? AND role_id = ?").run(e,t)}async createLog(e){let t=(0,C.randomUUID)(),n=new Date().toISOString();this.stmt("INSERT INTO audit_logs (id,tenant_id,user_id,action,resource_type,resource_id,old_data,new_data,created_at) VALUES (?,?,?,?,?,?,?,?,?)").run(t,e.tenantId,e.userId??null,e.action,e.resourceType,e.resourceId??null,e.oldData!=null?JSON.stringify(e.oldData):null,e.newData!=null?JSON.stringify(e.newData):null,n)}async getLogs(e){let t=["tenant_id = ?"],n=[e.tenantId];if(e.action&&(t.push("action = ?"),n.push(e.action)),e.resourceType&&(t.push("resource_type = ?"),n.push(e.resourceType)),e.from&&(t.push("created_at >= ?"),n.push(e.from)),e.to&&(t.push("created_at <= ?"),n.push(e.to)),e.q){t.push("(action LIKE ? OR resource_type LIKE ? OR resource_id LIKE ? OR user_id LIKE ?) ESCAPE '\\'");let d=j(e.q);n.push(d,d,d,d)}let o=t.join(" AND "),s=e.page??1,r=Math.min(e.limit??50,zn),a=(s-1)*r,c=this.stmt(`SELECT ${i.AUDIT_SUMMARY_COLS} FROM audit_logs WHERE ${o} ORDER BY created_at DESC LIMIT ? OFFSET ?`).all(...n,r,a),l=this.stmt(`SELECT COUNT(*) AS total FROM audit_logs WHERE ${o}`).get(...n);return{items:c.map(d=>this.mapAuditSummary(d)),total:l.total,page:s,limit:r}}async getAuditLogById(e){let t=this.stmt("SELECT * FROM audit_logs WHERE id = ?").get(e);return t?this.mapAuditLog(t):null}static AUDIT_SUMMARY_COLS="id, tenant_id, user_id, action, resource_type, resource_id, created_at";mapAuditSummary(e){return{id:e.id,tenantId:e.tenant_id,action:e.action,resourceType:e.resource_type,...e.user_id!=null?{userId:e.user_id}:{},...e.resource_id!=null?{resourceId:e.resource_id}:{},createdAt:e.created_at}}mapAuditLog(e){return{id:e.id,tenantId:e.tenant_id,action:e.action,resourceType:e.resource_type,createdAt:e.created_at,...e.user_id!=null?{userId:e.user_id}:{},...e.resource_id!=null?{resourceId:e.resource_id}:{},...e.old_data!=null?{oldData:JSON.parse(e.old_data)}:{},...e.new_data!=null?{newData:JSON.parse(e.new_data)}:{}}}async*streamAuditLogs(e){let t=["tenant_id = ?"],n=[e.tenantId];e.action&&(t.push("action = ?"),n.push(e.action)),e.from&&(t.push("created_at >= ?"),n.push(e.from)),e.to&&(t.push("created_at <= ?"),n.push(e.to));let o=500,s=0;for(;;){let r=this.stmt(`SELECT * FROM audit_logs WHERE ${t.join(" AND ")} ORDER BY created_at DESC LIMIT ? OFFSET ?`).all(...n,o,s);if(r.length===0)break;for(let a of r)yield this.mapAuditLog(a);s+=o}}async getOverviewStats(e){let t=this.stmt("SELECT COUNT(*) as n FROM consent_records WHERE tenant_id = ?").get(e),n=this.stmt("SELECT COUNT(*) as n FROM consent_records WHERE tenant_id = ? AND gpc_detected = 1").get(e),o=this.stmt("SELECT COUNT(*) as n FROM visitors WHERE tenant_id = ?").get(e),s=t?.n??0,r=this.stmt("SELECT consent_json FROM consent_records WHERE tenant_id = ? ORDER BY created_at DESC LIMIT 500").all(e),a=0,c=0;for(let d of r){let u=Object.values(JSON.parse(d.consent_json)),m=u.length>0?u.filter(f=>f==="granted").length/u.length:0;m>=.8?a++:m<=.2&&c++}let l=r.length||1;return{totalConsents:s,gpcDetectedCount:n?.n??0,totalVisitors:o?.n??0,acceptedPct:Math.round(a/l*100),rejectedPct:Math.round(c/l*100)}}async getCategoryStats(e){let t=this.stmt("SELECT consent_json FROM consent_records WHERE tenant_id = ? LIMIT 5000").all(e),n={};for(let o of t){let s=JSON.parse(o.consent_json);for(let[r,a]of Object.entries(s))n[r]||(n[r]={granted:0,denied:0,objected:0}),a==="granted"?n[r].granted++:a==="denied"?n[r].denied++:a==="objected"&&n[r].objected++}return n}async getTimeline(e,t=30){return this.stmt("SELECT date(created_at) as date, COUNT(*) as count FROM consent_records WHERE tenant_id = ? AND created_at >= date('now', ?) GROUP BY date(created_at) ORDER BY date ASC").all(e,`-${t} days`).map(o=>({date:o.date,count:o.count}))}async getCountries(e){return this.stmt("SELECT v.country, COUNT(*) as count FROM consent_records cr JOIN visitors v ON v.visitor_id = cr.visitor_id WHERE cr.tenant_id = ? AND v.country IS NOT NULL GROUP BY v.country ORDER BY count DESC LIMIT 50").all(e).map(n=>({country:n.country,count:n.count}))}async getGpcStats(e){let t=this.stmt("SELECT COUNT(*) as n FROM consent_records WHERE tenant_id = ?").get(e),n=this.stmt("SELECT COUNT(*) as n FROM consent_records WHERE tenant_id = ? AND gpc_detected = 1").get(e),o=t?.n??0,s=n?.n??0;return{detected:s,total:o,rate:o>0?Math.round(s/o*100):0}}async getTenants(){return this.stmt("SELECT * FROM tenants ORDER BY name ASC").all().map(t=>({id:t.id,name:t.name,slug:t.slug,createdAt:t.created_at,updatedAt:t.updated_at}))}async createTenant(e){let t=(0,C.randomUUID)(),n=new Date().toISOString();this.stmt("INSERT INTO tenants (id,name,slug,created_at,updated_at) VALUES (?,?,?,?,?)").run(t,e.name,e.slug,n,n);let o=this.stmt("SELECT * FROM tenants WHERE id = ?").get(t);if(!o)throw new Error("Failed to create tenant");return{id:o.id,name:o.name,slug:o.slug,createdAt:o.created_at,updatedAt:o.updated_at}}async updateTenant(e,t){let n=new Date().toISOString(),o=["updated_at = ?"],s=[n];t.name!=null&&(o.push("name = ?"),s.push(t.name)),t.slug!=null&&(o.push("slug = ?"),s.push(t.slug)),s.push(e),this.stmt(`UPDATE tenants SET ${o.join(", ")} WHERE id = ?`).run(...s);let r=this.stmt("SELECT * FROM tenants WHERE id = ?").get(e);if(!r)throw new Error(`Tenant ${e} not found`);return{id:r.id,name:r.name,slug:r.slug,createdAt:r.created_at,updatedAt:r.updated_at}}async deleteTenant(e){this.stmt("DELETE FROM tenants WHERE id = ?").run(e)}async getSettings(e){let t=this.stmt("SELECT allowed_origins_json, admin_allowed_origins_json, setup_completed, profiles_seeded, tcf_confirmation_json, gpp_confirmation_json FROM tenant_settings WHERE tenant_id = ?").get(e);return t?{allowedOrigins:JSON.parse(t.allowed_origins_json),adminAllowedOrigins:JSON.parse(t.admin_allowed_origins_json),setupCompleted:!!t.setup_completed,profilesSeeded:!!t.profiles_seeded,tcfConfirmation:t.tcf_confirmation_json?JSON.parse(t.tcf_confirmation_json):void 0,gppConfirmation:t.gpp_confirmation_json?JSON.parse(t.gpp_confirmation_json):void 0}:{}}async updateSettings(e,t){let o={...await this.getSettings(e),...t};return this.stmt(`INSERT INTO tenant_settings (tenant_id, allowed_origins_json, admin_allowed_origins_json, setup_completed, profiles_seeded, tcf_confirmation_json, gpp_confirmation_json, updated_at) VALUES (?,?,?,?,?,?,?,?)
42
+ ON CONFLICT(tenant_id) DO UPDATE SET allowed_origins_json = excluded.allowed_origins_json, admin_allowed_origins_json = excluded.admin_allowed_origins_json, setup_completed = excluded.setup_completed, profiles_seeded = excluded.profiles_seeded, tcf_confirmation_json = excluded.tcf_confirmation_json, gpp_confirmation_json = excluded.gpp_confirmation_json, updated_at = excluded.updated_at`).run(e,JSON.stringify(o.allowedOrigins??[]),JSON.stringify(o.adminAllowedOrigins??[]),o.setupCompleted?1:0,o.profilesSeeded?1:0,o.tcfConfirmation?JSON.stringify(o.tcfConfirmation):null,o.gppConfirmation?JSON.stringify(o.gppConfirmation):null,new Date().toISOString()),this.getSettings(e)}async purgeExpiredConsents(e){let t=new Date(Date.now()-e*864e5).toISOString(),n=this.stmt("SELECT visitor_id FROM consent_records WHERE created_at < ?").all(t);for(let{visitor_id:o}of n)this.stmt("DELETE FROM consent_history WHERE visitor_id = ?").run(o),this.stmt("DELETE FROM consent_records WHERE visitor_id = ?").run(o);return n.length}mapApiKey(e){return{id:e.id,tenantId:e.tenant_id,keyHash:e.key_hash,name:e.name,isActive:e.is_active===1,...e.created_by!==null?{createdBy:e.created_by}:{},...e.expire_by!==null?{expireBy:e.expire_by}:{},createdAt:e.created_at,...e.updated_at!==null?{updatedAt:e.updated_at}:{}}}async createApiKey(e){let t=(0,C.randomUUID)(),n=new Date().toISOString();this.stmt("INSERT INTO api_keys (id,tenant_id,key_hash,name,created_by,expire_by,created_at,updated_at) VALUES (?,?,?,?,?,?,?,?)").run(t,e.tenantId,e.keyHash,e.name,e.createdBy??null,e.expireBy??null,n,n);let o=this.stmt("SELECT * FROM api_keys WHERE id = ?").get(t);if(!o)throw new Error("Failed to create API key");return this.mapApiKey(o)}async getApiKeyByHash(e){let t=this.stmt("SELECT * FROM api_keys WHERE key_hash = ? AND is_active = 1").get(e);return t?this.mapApiKey(t):null}async revokeApiKey(e){this.stmt("UPDATE api_keys SET is_active = 0, updated_at = ? WHERE id = ?").run(new Date().toISOString(),e)}async reactivateApiKey(e){let t=new Date().toISOString();this.stmt("UPDATE api_keys SET is_active = 1, updated_at = ?, expire_by = CASE WHEN expire_by <= ? THEN NULL ELSE expire_by END WHERE id = ?").run(t,t,e)}async deleteApiKey(e){this.stmt("DELETE FROM api_keys WHERE id = ?").run(e)}async getApiKeys(e){return this.stmt("SELECT * FROM api_keys WHERE tenant_id = ? ORDER BY created_at DESC").all(e).map(n=>this.mapApiKey(n))}mapConsentTemplate(e){return{id:e.id,tenantId:e.tenant_id,name:e.name,cookies:JSON.parse(e.cookies_json),categories:JSON.parse(e.categories_json),createdAt:e.created_at,updatedAt:e.updated_at}}async createConsentTemplate(e){let t=Q(),n=new Date().toISOString();return this.stmt("INSERT INTO consent_templates (id,tenant_id,name,cookies_json,categories_json,created_at,updated_at) VALUES (?,?,?,?,?,?,?)").run(t,e.tenantId,e.name,JSON.stringify(e.cookies),JSON.stringify(e.categories),n,n),this.mapConsentTemplate(this.stmt("SELECT * FROM consent_templates WHERE id = ?").get(t))}async updateConsentTemplate(e,t){let n=new Date().toISOString();t.name!==void 0&&this.stmt("UPDATE consent_templates SET name = ?, updated_at = ? WHERE id = ?").run(t.name,n,e),t.cookies!==void 0&&this.stmt("UPDATE consent_templates SET cookies_json = ?, updated_at = ? WHERE id = ?").run(JSON.stringify(t.cookies),n,e),t.categories!==void 0&&this.stmt("UPDATE consent_templates SET categories_json = ?, updated_at = ? WHERE id = ?").run(JSON.stringify(t.categories),n,e);let o=this.stmt("SELECT * FROM consent_templates WHERE id = ?").get(e);if(!o)throw new Error("Consent template not found");return this.mapConsentTemplate(o)}async deleteConsentTemplate(e){this.stmt("DELETE FROM consent_templates WHERE id = ?").run(e)}async getConsentTemplate(e){let t=this.stmt("SELECT * FROM consent_templates WHERE id = ?").get(e);return t?this.mapConsentTemplate(t):null}async getConsentTemplates(e){return this.stmt("SELECT * FROM consent_templates WHERE tenant_id = ? ORDER BY name ASC").all(e).map(n=>this.mapConsentTemplate(n))}async copyConsentTemplate(e,t){let n=await this.getConsentTemplate(e);if(!n)throw new Error("Consent template not found");return this.createConsentTemplate({tenantId:n.tenantId,name:t,cookies:n.cookies,categories:n.categories})}mapUITemplate(e){let t=JSON.parse(e.settings_json);return{id:e.id,tenantId:e.tenant_id,name:e.name,...t,createdAt:e.created_at,updatedAt:e.updated_at}}async createUITemplate(e){let t=Z(),n=new Date().toISOString(),{tenantId:o,name:s,...r}=e;return this.stmt("INSERT INTO ui_templates (id,tenant_id,name,settings_json,created_at,updated_at) VALUES (?,?,?,?,?,?)").run(t,o,s,JSON.stringify(r),n,n),this.mapUITemplate(this.stmt("SELECT * FROM ui_templates WHERE id = ?").get(t))}async updateUITemplate(e,t){let n=new Date().toISOString(),o=this.stmt("SELECT * FROM ui_templates WHERE id = ?").get(e);if(!o)throw new Error("UI template not found");t.name!==void 0&&this.stmt("UPDATE ui_templates SET name = ?, updated_at = ? WHERE id = ?").run(t.name,n,e);let{name:s,...r}=t;if(Object.keys(r).length>0){let c={...JSON.parse(o.settings_json),...r};this.stmt("UPDATE ui_templates SET settings_json = ?, updated_at = ? WHERE id = ?").run(JSON.stringify(c),n,e)}return this.mapUITemplate(this.stmt("SELECT * FROM ui_templates WHERE id = ?").get(e))}async deleteUITemplate(e){this.stmt("DELETE FROM ui_templates WHERE id = ?").run(e)}async getUITemplate(e){let t=this.stmt("SELECT * FROM ui_templates WHERE id = ?").get(e);return t?this.mapUITemplate(t):null}async getUITemplates(e){return this.stmt("SELECT * FROM ui_templates WHERE tenant_id = ? ORDER BY name ASC").all(e).map(n=>this.mapUITemplate(n))}async copyUITemplate(e,t){let n=await this.getUITemplate(e);if(!n)throw new Error("UI template not found");let{tenantId:o,mainBanner:s,gpcBanner:r,preferenceModal:a}=n;return this.createUITemplate({tenantId:o,name:t,mainBanner:s,gpcBanner:r,preferenceModal:a})}mapProfileSummary(e){return{id:e.id,name:e.name,defaultLocale:e.default_locale,complianceGroup:e.compliance_group??null,customComplianceGroup:e.custom_compliance_group??null,isActive:e.is_active===1,consentTemplateName:e.consent_template_name,uiTemplateName:e.ui_template_name,createdAt:e.created_at,updatedAt:e.updated_at}}PROFILE_SUMMARY_SQL=`
46
43
  SELECT
47
44
  p.id, p.name, p.default_locale, p.created_at, p.updated_at,
48
45
  json_extract(p.profile_json, '$.complianceGroup') AS compliance_group,
@@ -55,11 +52,11 @@ ${l.map(d=>` (${se(c)},${se(d)})`).join(`,
55
52
  FROM profiles p
56
53
  LEFT JOIN consent_templates ct ON ct.id = json_extract(p.profile_json, '$.consentTemplateId')
57
54
  LEFT JOIN ui_templates ut ON ut.id = json_extract(p.profile_json, '$.uiTemplateId')
58
- `;async listProfilesSummary(e){return this.stmt(`${this.PROFILE_SUMMARY_SQL} WHERE p.tenant_id = ? ORDER BY p.created_at ASC`).all(e).map(n=>this.mapProfileSummary(n))}async findProfilesUsingConsentTemplate(e){return this.stmt(`${this.PROFILE_SUMMARY_SQL} WHERE json_extract(p.profile_json, '$.consentTemplateId') = ? ORDER BY p.name ASC`).all(e).map(n=>this.mapProfileSummary(n))}async findProfilesUsingUITemplate(e){return this.stmt(`${this.PROFILE_SUMMARY_SQL} WHERE json_extract(p.profile_json, '$.uiTemplateId') = ? ORDER BY p.name ASC`).all(e).map(n=>this.mapProfileSummary(n))}async getOptInStats(e,t){let n=["cr.tenant_id = ?"],o=[e];t.profileId&&(n.push("cr.profile_id = ?"),o.push(t.profileId)),t.from&&(n.push("cr.created_at >= ?"),o.push(t.from)),t.to&&(n.push("cr.created_at <= ?"),o.push(t.to)),t.locale&&(n.push("cr.locale = ?"),o.push(t.locale));let s=n.join(" AND "),r=this.stmt(`SELECT cr.locale, cr.consent_json FROM consent_records cr WHERE ${s}`).all(...o),a=0,c=0,l=0,d=0,u={};for(let _ of r){let w=Object.values(JSON.parse(_.consent_json)),R=w.length>0?w.filter(T=>T==="granted").length/w.length:0,C=w.length>0?w.filter(T=>T==="denied").length/w.length:0;a++;let A=_.locale;u[A]||(u[A]={total:0,granted:0,denied:0,managed:0}),u[A].total++,R>=.9?(c++,u[A].granted++):C>=.9?(l++,u[A].denied++):(d++,u[A].managed++)}let m=this.stmt(`SELECT date(cr.created_at) as d, cr.consent_json FROM consent_records cr WHERE ${s} ORDER BY d ASC`).all(...o),h=new Map;for(let _ of m){let w=h.get(_.d)??{total:0,granted:0,denied:0,managed:0},R=Object.values(JSON.parse(_.consent_json)),C=R.length>0?R.filter(T=>T==="granted").length/R.length:0,A=R.length>0?R.filter(T=>T==="denied").length/R.length:0;w.total++,C>=.9?w.granted++:A>=.9?w.denied++:w.managed++,h.set(_.d,w)}let S=Array.from(h.entries()).map(([_,w])=>({date:_,...w}));return{total:a,granted:c,denied:l,managed:d,grantedPct:a>0?Math.round(c/a*1e3)/10:0,deniedPct:a>0?Math.round(l/a*1e3)/10:0,managedPct:a>0?Math.round(d/a*1e3)/10:0,byLocale:u,byDate:S}}};p();var Mn=500,Ct=class i{constructor(e){this.config=e}config;db;cache=new Map;stmt(e){let t=this.cache.get(e);return t||(t=this.db.prepare(e),this.cache.set(e,t)),t}async connect(){let e=await import("node-sqlite3-wasm").catch(()=>{throw new Error("driver 'node-sqlite3-wasm' requires: npm install node-sqlite3-wasm")}),{dbPath:t}=me(this.config.path??"./consenti-data","node-sqlite3-wasm");this.db=new e.default.Database(t),this.db.exec("PRAGMA journal_mode=WAL"),this.db.exec("PRAGMA foreign_keys=ON"),this.db.exec("PRAGMA synchronous=NORMAL"),await this.migrate()}async disconnect(){for(let e of this.cache.values())e.finalize();this.cache.clear(),this.db.close()}async migrate(){(this.stmt("PRAGMA user_version").get()?.user_version??0)<1&&(this.db.exec(Le),this.db.exec(Ne),this.db.exec("PRAGMA user_version = 1")),this.db.exec(`
55
+ `;async listProfilesSummary(e){return this.stmt(`${this.PROFILE_SUMMARY_SQL} WHERE p.tenant_id = ? ORDER BY p.created_at ASC`).all(e).map(n=>this.mapProfileSummary(n))}async findProfilesUsingConsentTemplate(e){return this.stmt(`${this.PROFILE_SUMMARY_SQL} WHERE json_extract(p.profile_json, '$.consentTemplateId') = ? ORDER BY p.name ASC`).all(e).map(n=>this.mapProfileSummary(n))}async findProfilesUsingUITemplate(e){return this.stmt(`${this.PROFILE_SUMMARY_SQL} WHERE json_extract(p.profile_json, '$.uiTemplateId') = ? ORDER BY p.name ASC`).all(e).map(n=>this.mapProfileSummary(n))}async getOptInStats(e,t){let n=["cr.tenant_id = ?"],o=[e];t.profileId&&(n.push("cr.profile_id = ?"),o.push(t.profileId)),t.from&&(n.push("cr.created_at >= ?"),o.push(t.from)),t.to&&(n.push("cr.created_at <= ?"),o.push(t.to)),t.locale&&(n.push("cr.locale = ?"),o.push(t.locale));let s=n.join(" AND "),r=this.stmt(`SELECT cr.locale, cr.consent_json FROM consent_records cr WHERE ${s}`).all(...o),a=0,c=0,l=0,d=0,u={};for(let y of r){let E=Object.values(JSON.parse(y.consent_json)),R=E.length>0?E.filter(T=>T==="granted").length/E.length:0,v=E.length>0?E.filter(T=>T==="denied").length/E.length:0;a++;let A=y.locale;u[A]||(u[A]={total:0,granted:0,denied:0,managed:0}),u[A].total++,R>=.9?(c++,u[A].granted++):v>=.9?(l++,u[A].denied++):(d++,u[A].managed++)}let m=this.stmt(`SELECT date(cr.created_at) as d, cr.consent_json FROM consent_records cr WHERE ${s} ORDER BY d ASC`).all(...o),f=new Map;for(let y of m){let E=f.get(y.d)??{total:0,granted:0,denied:0,managed:0},R=Object.values(JSON.parse(y.consent_json)),v=R.length>0?R.filter(T=>T==="granted").length/R.length:0,A=R.length>0?R.filter(T=>T==="denied").length/R.length:0;E.total++,v>=.9?E.granted++:A>=.9?E.denied++:E.managed++,f.set(y.d,E)}let S=Array.from(f.entries()).map(([y,E])=>({date:y,...E}));return{total:a,granted:c,denied:l,managed:d,grantedPct:a>0?Math.round(c/a*1e3)/10:0,deniedPct:a>0?Math.round(l/a*1e3)/10:0,managedPct:a>0?Math.round(d/a*1e3)/10:0,byLocale:u,byDate:S}}};p();var Kn=500,Ot=class i{constructor(e){this.config=e}config;db;cache=new Map;dbPath="";stmt(e){let t=this.cache.get(e);return t||(t=this.db.prepare(e),this.cache.set(e,t)),t}async connect(){let e=await import("node-sqlite3-wasm").catch(()=>{throw new Error("driver 'node-sqlite3-wasm' requires: npm install node-sqlite3-wasm")}),{dbPath:t}=fe(this.config.path??"./consenti-data","node-sqlite3-wasm");this.dbPath=t,this.db=new e.default.Database(t),this.db.exec("PRAGMA journal_mode=WAL"),this.db.exec("PRAGMA foreign_keys=ON"),this.db.exec("PRAGMA synchronous=NORMAL"),await this.migrate()}async disconnect(){for(let e of this.cache.values())e.finalize();this.cache.clear(),this.db.close()}async migrate(){let e=this.db.prepare("PRAGMA user_version"),t=0;try{t=e.get()?.user_version??0}finally{e.finalize()}t<1?(this.db.exec(Me),this.db.exec(Ge),this.db.exec(`PRAGMA user_version = ${le}`)):t<2&&this.migrateToV2(),this.db.exec(`
59
56
  CREATE INDEX IF NOT EXISTS idx_profiles_tenant_compliance_active
60
57
  ON profiles (tenant_id, json_extract(profile_json,'$.complianceGroup'), json_extract(profile_json,'$.isActive'));
61
- `)}mapProfile(e){return{id:e.id,tenantId:e.tenant_id,name:e.name,defaultLocale:e.default_locale,version:e.version,profileJson:JSON.parse(e.profile_json),createdAt:e.created_at,updatedAt:e.updated_at}}async createProfile(e){let t=z(),n=new Date().toISOString();this.stmt("INSERT INTO profiles (id,tenant_id,name,default_locale,version,profile_json,created_at,updated_at) VALUES (?,?,?,?,?,?,?,?)").run([t,e.tenantId,e.name,e.defaultLocale,1,JSON.stringify(e.profileJson),n,n]);let o=await this.getProfile(t);if(!o)throw new Error("Failed to create profile");return o}async updateProfile(e,t){if(!await this.getProfile(e))throw new Error(`Profile ${e} not found`);let o=new Date().toISOString(),s=["updated_at = ?"],r=[o];t.name!=null&&(s.push("name = ?"),r.push(t.name)),t.defaultLocale!=null&&(s.push("default_locale = ?"),r.push(t.defaultLocale)),t.profileJson!=null&&(s.push("profile_json = ?"),r.push(JSON.stringify(t.profileJson))),t.version!=null&&(s.push("version = ?"),r.push(t.version)),r.push(e),this.stmt(`UPDATE profiles SET ${s.join(", ")} WHERE id = ?`).run(r);let a=await this.getProfile(e);if(!a)throw new Error("Failed to update profile");return a}async deleteProfile(e){this.stmt("DELETE FROM profiles WHERE id = ?").run(e)}async getProfile(e){let t=this.stmt("SELECT * FROM profiles WHERE id = ?").get(e);return t?this.mapProfile(t):null}async getProfiles(e){return this.stmt("SELECT * FROM profiles WHERE tenant_id = ? ORDER BY created_at ASC").all(e).map(n=>this.mapProfile(n))}async findActiveProfileByComplianceGroup(e,t){return(await this.getProfiles(e)).find(o=>(o.profileJson.complianceGroup===t||o.profileJson.customComplianceGroup===t)&&o.profileJson.isActive)??null}mapConsent(e){return{id:e.id,tenantId:e.tenant_id,visitorId:e.visitor_id,profileId:e.profile_id,locale:e.locale,consentJson:JSON.parse(e.consent_json),gpcDetected:e.gpc_detected===1,source:e.source,...e.age_verified!=null&&e.age_verified!==0?{ageVerified:!0}:{},...e.parental_consent_token!=null?{parentalConsentToken:e.parental_consent_token}:{},...e.tcf_string!=null?{tcfString:e.tcf_string}:{},...e.gpp_string!=null?{gppString:e.gpp_string}:{},...e.signature!=null?{signature:e.signature}:{},createdAt:e.created_at,updatedAt:e.updated_at}}static CONSENT_SUMMARY_COLS="id, tenant_id, visitor_id, profile_id, locale, gpc_detected, source, age_verified, created_at, updated_at";mapConsentSummary(e){return{id:e.id,tenantId:e.tenant_id,visitorId:e.visitor_id,profileId:e.profile_id,locale:e.locale,gpcDetected:e.gpc_detected===1,source:e.source,...e.age_verified!=null&&e.age_verified!==0?{ageVerified:!0}:{},createdAt:e.created_at,updatedAt:e.updated_at}}async createConsent(e){let t=K(),n=new Date().toISOString();this.stmt("INSERT INTO consent_records (id,tenant_id,visitor_id,profile_id,locale,consent_json,gpc_detected,source,age_verified,parental_consent_token,tcf_string,gpp_string,signature,created_at,updated_at) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)").run([t,e.tenantId,e.visitorId,e.profileId,e.locale,JSON.stringify(e.consentJson),e.gpcDetected?1:0,e.source,e.ageVerified?1:0,e.parentalConsentToken??null,e.tcfString??null,e.gppString??null,e.signature??null,n,n]);let o=(0,v.randomUUID)();this.stmt("INSERT INTO consent_history (id,tenant_id,consent_record_id,visitor_id,old_json,new_json,action,created_at) VALUES (?,?,?,?,?,?,?,?)").run([o,e.tenantId,t,e.visitorId,null,JSON.stringify(e.consentJson),"created",n]);let s=await this.getConsent(e.visitorId);if(!s)throw new Error("Failed to create consent");return s}async updateConsent(e,t){let n=await this.getConsent(e);if(!n)throw new Error(`Consent for visitor ${e} not found`);let o=new Date().toISOString(),s=["updated_at = ?","consent_json = ?"],r=[o,JSON.stringify(t.consentJson)];t.locale!=null&&(s.push("locale = ?"),r.push(t.locale)),t.gpcDetected!=null&&(s.push("gpc_detected = ?"),r.push(t.gpcDetected?1:0)),t.signature!=null&&(s.push("signature = ?"),r.push(t.signature)),r.push(e),this.stmt(`UPDATE consent_records SET ${s.join(", ")} WHERE visitor_id = ?`).run(r);let a=(0,v.randomUUID)();this.stmt("INSERT INTO consent_history (id,tenant_id,consent_record_id,visitor_id,old_json,new_json,action,created_at) VALUES (?,?,?,?,?,?,?,?)").run([a,n.tenantId,n.id,e,JSON.stringify(n.consentJson),JSON.stringify(t.consentJson),"updated",o]);let c=await this.getConsent(e);if(!c)throw new Error("Failed to update consent");return c}async deleteConsent(e){this.stmt("DELETE FROM consent_history WHERE visitor_id = ?").run(e),this.stmt("DELETE FROM consent_records WHERE visitor_id = ?").run(e)}async getConsent(e){let t=this.stmt("SELECT * FROM consent_records WHERE visitor_id = ?").get(e);return t?this.mapConsent(t):null}async getConsents(e){let t=["tenant_id = ?"],n=[e.tenantId];if(e.profileId&&(t.push("profile_id = ?"),n.push(e.profileId)),e.from&&(t.push("created_at >= ?"),n.push(e.from)),e.to&&(t.push("created_at <= ?"),n.push(e.to)),e.q){t.push("(visitor_id LIKE ? OR profile_id LIKE ? OR locale LIKE ? OR source LIKE ?) ESCAPE '\\'");let d=j(e.q);n.push(d,d,d,d)}let o=t.join(" AND "),s=e.page??1,r=Math.min(e.limit??50,Mn),a=(s-1)*r,c=this.stmt(`SELECT ${i.CONSENT_SUMMARY_COLS} FROM consent_records WHERE ${o} ORDER BY created_at DESC LIMIT ? OFFSET ?`).all([...n,r,a]),l=this.stmt(`SELECT COUNT(*) AS total FROM consent_records WHERE ${o}`).get(n);return{items:c.map(d=>this.mapConsentSummary(d)),total:l?.total??0,page:s,limit:r}}async*streamConsents(e){let n=0;for(;;){let o=this.stmt("SELECT * FROM consent_records WHERE tenant_id = ? LIMIT ? OFFSET ?").all([e.tenantId,500,n]);if(o.length===0)break;for(let s of o)yield this.mapConsent(s);n+=500}}async getConsentHistory(e){return this.stmt("SELECT * FROM consent_history WHERE visitor_id = ? ORDER BY created_at ASC").all(e).map(n=>({id:n.id,tenantId:n.tenant_id,consentRecordId:n.consent_record_id,visitorId:n.visitor_id,oldJson:n.old_json!=null?JSON.parse(n.old_json):null,newJson:JSON.parse(n.new_json),action:n.action,createdAt:n.created_at}))}async createNoticeShown(e){let t=(0,v.randomUUID)(),n=new Date().toISOString();return this.stmt("INSERT INTO notice_shown (id,tenant_id,visitor_id,profile_id,locale,created_at) VALUES (?,?,?,?,?,?)").run([t,e.tenantId,e.visitorId,e.profileId,e.locale,n]),{id:t,tenantId:e.tenantId,visitorId:e.visitorId,profileId:e.profileId,locale:e.locale,createdAt:n}}async getNoticeShownForVisitor(e){return this.stmt("SELECT * FROM notice_shown WHERE visitor_id = ? ORDER BY created_at DESC").all(e).map(n=>({id:n.id,tenantId:n.tenant_id,visitorId:n.visitor_id,profileId:n.profile_id,locale:n.locale,createdAt:n.created_at}))}mapVisitor(e){return{id:e.id,tenantId:e.tenant_id,visitorId:e.visitor_id,firstSeen:e.first_seen,lastSeen:e.last_seen,...e.country!=null?{country:e.country}:{},...e.region!=null?{region:e.region}:{},...e.city!=null?{city:e.city}:{},...e.ip_hash!=null?{ipHash:e.ip_hash}:{},...e.user_agent_hash!=null?{userAgentHash:e.user_agent_hash}:{}}}async createVisitor(e){let t=q(),n=new Date().toISOString();this.stmt("INSERT INTO visitors (id,tenant_id,visitor_id,country,region,city,ip_hash,user_agent_hash,first_seen,last_seen) VALUES (?,?,?,?,?,?,?,?,?,?)").run([t,e.tenantId,e.visitorId,e.country??null,e.region??null,e.city??null,e.ipHash??null,e.userAgentHash??null,n,n]);let o=await this.getVisitor(e.visitorId);if(!o)throw new Error("Failed to create visitor");return o}async updateVisitor(e,t){let n=new Date().toISOString(),o=["last_seen = ?"],s=[t.lastSeen??n];t.country!=null&&(o.push("country = ?"),s.push(t.country)),t.region!=null&&(o.push("region = ?"),s.push(t.region)),t.city!=null&&(o.push("city = ?"),s.push(t.city)),s.push(e),this.stmt(`UPDATE visitors SET ${o.join(", ")} WHERE visitor_id = ?`).run(s);let r=await this.getVisitor(e);if(!r)throw new Error(`Visitor ${e} not found`);return r}async deleteVisitor(e){this.stmt("DELETE FROM visitors WHERE visitor_id = ?").run(e)}async getVisitor(e){let t=this.stmt("SELECT * FROM visitors WHERE visitor_id = ?").get(e);return t?this.mapVisitor(t):null}async getVisitors(e){let t=["tenant_id = ?"],n=[e.tenantId];if(e.from&&(t.push("first_seen >= ?"),n.push(e.from)),e.to&&(t.push("first_seen <= ?"),n.push(e.to)),e.q){t.push("(visitor_id LIKE ? OR country LIKE ?) ESCAPE '\\'");let d=j(e.q);n.push(d,d)}let o=t.join(" AND "),s=e.page??1,r=Math.min(e.limit??50,Mn),a=(s-1)*r,c=this.stmt(`SELECT * FROM visitors WHERE ${o} ORDER BY last_seen DESC LIMIT ? OFFSET ?`).all([...n,r,a]),l=this.stmt(`SELECT COUNT(*) AS total FROM visitors WHERE ${o}`).get(n);return{items:c.map(d=>this.mapVisitor(d)),total:l?.total??0,page:s,limit:r}}mapUser(e){let t=e.allowed_tenants?JSON.parse(e.allowed_tenants):[];return{id:e.id,tenantId:e.tenant_id,name:e.name,email:e.email,passwordHash:e.password_hash,isActive:e.is_active===1,totpEnabled:e.totp_enabled===1,...e.totp_secret!=null?{totpSecret:e.totp_secret}:{},allowedTenants:t,createdAt:e.created_at,updatedAt:e.updated_at}}async createUser(e){let t=(0,v.randomUUID)(),n=new Date().toISOString(),o=e.allowedTenants?.length?JSON.stringify(e.allowedTenants):null;this.stmt("INSERT INTO users (id,tenant_id,name,email,password_hash,allowed_tenants,created_at,updated_at) VALUES (?,?,?,?,?,?,?,?)").run([t,e.tenantId,e.name,e.email,e.passwordHash,o,n,n]);let s=await this.getUserByEmail(e.email);if(!s)throw new Error("Failed to create user");return s}async updateUser(e,t){let n=new Date().toISOString(),o=["updated_at = ?"],s=[n];t.name!=null&&(o.push("name = ?"),s.push(t.name)),t.email!=null&&(o.push("email = ?"),s.push(t.email)),t.passwordHash!=null&&(o.push("password_hash = ?"),s.push(t.passwordHash)),t.isActive!=null&&(o.push("is_active = ?"),s.push(t.isActive?1:0)),"totpSecret"in t&&(o.push("totp_secret = ?"),s.push(t.totpSecret??null)),t.totpEnabled!=null&&(o.push("totp_enabled = ?"),s.push(t.totpEnabled?1:0)),"allowedTenants"in t&&(o.push("allowed_tenants = ?"),s.push(t.allowedTenants?.length?JSON.stringify(t.allowedTenants):null)),s.push(e),this.stmt(`UPDATE users SET ${o.join(", ")} WHERE id = ?`).run(s);let r=this.stmt("SELECT * FROM users WHERE id = ?").get(e);if(!r)throw new Error(`User ${e} not found`);return this.mapUser(r)}async deleteUser(e){this.stmt("DELETE FROM user_roles WHERE user_id = ?").run(e),this.stmt("DELETE FROM users WHERE id = ?").run(e)}async getUserById(e){let t=this.stmt("SELECT * FROM users WHERE id = ?").get(e);return t?this.mapUser(t):null}async getUserByEmail(e){let t=this.stmt("SELECT * FROM users WHERE email = ?").get(e);return t?this.mapUser(t):null}async getUsers(e){return this.stmt("SELECT * FROM users WHERE tenant_id = ? ORDER BY created_at ASC").all(e).map(n=>this.mapUser(n))}async countUsers(e){return(e?this.stmt("SELECT COUNT(*) as n FROM users WHERE tenant_id = ?").get(e):this.stmt("SELECT COUNT(*) as n FROM users").get())?.n??0}async getRoles(e){return this.stmt("SELECT * FROM roles WHERE tenant_id = ?").all(e).map(n=>({id:n.id,tenantId:n.tenant_id,name:n.name,...n.description!=null?{description:n.description}:{}}))}async createRole(e){let t=(0,v.randomUUID)();this.stmt("INSERT INTO roles (id,tenant_id,name,description) VALUES (?,?,?,?)").run([t,e.tenantId,e.name,e.description??null]);let n=this.stmt("SELECT * FROM roles WHERE id = ?").get(t);if(!n)throw new Error("Failed to create role");return{id:n.id,tenantId:n.tenant_id,name:n.name,...n.description!=null?{description:n.description}:{}}}async updateRole(e,t){let n=[],o=[];t.name!=null&&(n.push("name = ?"),o.push(t.name)),t.description!=null&&(n.push("description = ?"),o.push(t.description)),n.length>0&&(o.push(e),this.stmt(`UPDATE roles SET ${n.join(", ")} WHERE id = ?`).run(o));let s=this.stmt("SELECT * FROM roles WHERE id = ?").get(e);if(!s)throw new Error(`Role ${e} not found`);return{id:s.id,tenantId:s.tenant_id,name:s.name,...s.description!=null?{description:s.description}:{}}}async deleteRole(e){this.stmt("DELETE FROM role_permissions WHERE role_id = ?").run(e),this.stmt("DELETE FROM user_roles WHERE role_id = ?").run(e),this.stmt("DELETE FROM roles WHERE id = ?").run(e)}async getAllPermissions(){return this.stmt("SELECT * FROM permissions ORDER BY name ASC").all().map(t=>({id:t.id,name:t.name,...t.description!=null?{description:t.description}:{}}))}async assignPermissionToRole(e,t){this.stmt("INSERT OR IGNORE INTO role_permissions (role_id,permission_id) VALUES (?,?)").run([e,t])}async revokePermissionFromRole(e,t){this.stmt("DELETE FROM role_permissions WHERE role_id = ? AND permission_id = ?").run([e,t])}async getPermissionsForRole(e){return this.stmt("SELECT p.* FROM permissions p JOIN role_permissions rp ON rp.permission_id = p.id WHERE rp.role_id = ?").all(e).map(n=>({id:n.id,name:n.name,...n.description!=null?{description:n.description}:{}}))}async getUserRoles(e,t){return(t?this.stmt("SELECT r.* FROM roles r JOIN user_roles ur ON ur.role_id = r.id WHERE ur.user_id = ? AND ur.tenant_id = ?").all([e,t]):this.stmt("SELECT r.* FROM roles r JOIN user_roles ur ON ur.role_id = r.id WHERE ur.user_id = ?").all(e)).map(o=>({id:o.id,tenantId:o.tenant_id,name:o.name,...o.description!=null?{description:o.description}:{}}))}async assignRole(e,t,n="default"){this.stmt("INSERT OR IGNORE INTO user_roles (user_id, role_id, tenant_id) VALUES (?,?,?)").run([e,t,n])}async revokeRole(e,t,n){n?this.stmt("DELETE FROM user_roles WHERE user_id = ? AND role_id = ? AND tenant_id = ?").run([e,t,n]):this.stmt("DELETE FROM user_roles WHERE user_id = ? AND role_id = ?").run([e,t])}async createLog(e){let t=(0,v.randomUUID)(),n=new Date().toISOString();this.stmt("INSERT INTO audit_logs (id,tenant_id,user_id,action,resource_type,resource_id,old_data,new_data,created_at) VALUES (?,?,?,?,?,?,?,?,?)").run([t,e.tenantId,e.userId??null,e.action,e.resourceType,e.resourceId??null,e.oldData!=null?JSON.stringify(e.oldData):null,e.newData!=null?JSON.stringify(e.newData):null,n])}async getLogs(e){let t=["tenant_id = ?"],n=[e.tenantId];if(e.action&&(t.push("action = ?"),n.push(e.action)),e.resourceType&&(t.push("resource_type = ?"),n.push(e.resourceType)),e.from&&(t.push("created_at >= ?"),n.push(e.from)),e.to&&(t.push("created_at <= ?"),n.push(e.to)),e.q){t.push("(action LIKE ? OR resource_type LIKE ? OR resource_id LIKE ? OR user_id LIKE ?) ESCAPE '\\'");let d=j(e.q);n.push(d,d,d,d)}let o=t.join(" AND "),s=e.page??1,r=Math.min(e.limit??50,Mn),a=(s-1)*r,c=this.stmt(`SELECT ${i.AUDIT_SUMMARY_COLS} FROM audit_logs WHERE ${o} ORDER BY created_at DESC LIMIT ? OFFSET ?`).all([...n,r,a]),l=this.stmt(`SELECT COUNT(*) AS total FROM audit_logs WHERE ${o}`).get(n);return{items:c.map(d=>this.mapAuditSummary(d)),total:l?.total??0,page:s,limit:r}}async getAuditLogById(e){let t=this.stmt("SELECT * FROM audit_logs WHERE id = ?").get(e);return t?this.mapAuditLog(t):null}static AUDIT_SUMMARY_COLS="id, tenant_id, user_id, action, resource_type, resource_id, created_at";mapAuditSummary(e){return{id:e.id,tenantId:e.tenant_id,action:e.action,resourceType:e.resource_type,...e.user_id!=null?{userId:e.user_id}:{},...e.resource_id!=null?{resourceId:e.resource_id}:{},createdAt:e.created_at}}mapAuditLog(e){return{id:e.id,tenantId:e.tenant_id,action:e.action,resourceType:e.resource_type,createdAt:e.created_at,...e.user_id!=null?{userId:e.user_id}:{},...e.resource_id!=null?{resourceId:e.resource_id}:{},...e.old_data!=null?{oldData:JSON.parse(e.old_data)}:{},...e.new_data!=null?{newData:JSON.parse(e.new_data)}:{}}}async*streamAuditLogs(e){let t=["tenant_id = ?"],n=[e.tenantId];e.action&&(t.push("action = ?"),n.push(e.action)),e.from&&(t.push("created_at >= ?"),n.push(e.from)),e.to&&(t.push("created_at <= ?"),n.push(e.to));let o=500,s=0;for(;;){let r=this.stmt(`SELECT * FROM audit_logs WHERE ${t.join(" AND ")} ORDER BY created_at DESC LIMIT ? OFFSET ?`).all([...n,o,s]);if(r.length===0)break;for(let a of r)yield this.mapAuditLog(a);s+=o}}async getOverviewStats(e){let t=this.stmt("SELECT COUNT(*) as n FROM consent_records WHERE tenant_id = ?").get(e),n=this.stmt("SELECT COUNT(*) as n FROM consent_records WHERE tenant_id = ? AND gpc_detected = 1").get(e),o=this.stmt("SELECT COUNT(*) as n FROM visitors WHERE tenant_id = ?").get(e),s=t?.n??0,r=this.stmt("SELECT consent_json FROM consent_records WHERE tenant_id = ? ORDER BY created_at DESC LIMIT 500").all(e),a=0,c=0;for(let d of r){let u=Object.values(JSON.parse(d.consent_json)),m=u.length>0?u.filter(h=>h==="granted").length/u.length:0;m>=.8?a++:m<=.2&&c++}let l=r.length||1;return{totalConsents:s,gpcDetectedCount:n?.n??0,totalVisitors:o?.n??0,acceptedPct:Math.round(a/l*100),rejectedPct:Math.round(c/l*100)}}async getCategoryStats(e){let t=this.stmt("SELECT consent_json FROM consent_records WHERE tenant_id = ? LIMIT 5000").all(e),n={};for(let o of t){let s=JSON.parse(o.consent_json);for(let[r,a]of Object.entries(s))n[r]||(n[r]={granted:0,denied:0,objected:0}),a==="granted"?n[r].granted++:a==="denied"?n[r].denied++:a==="objected"&&n[r].objected++}return n}async getTimeline(e,t=30){return this.stmt("SELECT date(created_at) as date, COUNT(*) as count FROM consent_records WHERE tenant_id = ? AND created_at >= date('now', ?) GROUP BY date(created_at) ORDER BY date ASC").all([e,`-${t} days`]).map(o=>({date:o.date,count:o.count}))}async getCountries(e){return this.stmt("SELECT v.country, COUNT(*) as count FROM consent_records cr JOIN visitors v ON v.visitor_id = cr.visitor_id WHERE cr.tenant_id = ? AND v.country IS NOT NULL GROUP BY v.country ORDER BY count DESC LIMIT 50").all(e).map(n=>({country:n.country,count:n.count}))}async getGpcStats(e){let t=this.stmt("SELECT COUNT(*) as n FROM consent_records WHERE tenant_id = ?").get(e),n=this.stmt("SELECT COUNT(*) as n FROM consent_records WHERE tenant_id = ? AND gpc_detected = 1").get(e),o=t?.n??0,s=n?.n??0;return{detected:s,total:o,rate:o>0?Math.round(s/o*100):0}}async getTenants(){return this.stmt("SELECT * FROM tenants ORDER BY name ASC").all().map(t=>({id:t.id,name:t.name,slug:t.slug,createdAt:t.created_at,updatedAt:t.updated_at}))}async createTenant(e){let t=(0,v.randomUUID)(),n=new Date().toISOString();this.stmt("INSERT INTO tenants (id,name,slug,created_at,updated_at) VALUES (?,?,?,?,?)").run([t,e.name,e.slug,n,n]);let o=this.stmt("SELECT * FROM tenants WHERE id = ?").get(t);if(!o)throw new Error("Failed to create tenant");return{id:o.id,name:o.name,slug:o.slug,createdAt:o.created_at,updatedAt:o.updated_at}}async updateTenant(e,t){let n=new Date().toISOString(),o=["updated_at = ?"],s=[n];t.name!=null&&(o.push("name = ?"),s.push(t.name)),t.slug!=null&&(o.push("slug = ?"),s.push(t.slug)),s.push(e),this.stmt(`UPDATE tenants SET ${o.join(", ")} WHERE id = ?`).run(s);let r=this.stmt("SELECT * FROM tenants WHERE id = ?").get(e);if(!r)throw new Error(`Tenant ${e} not found`);return{id:r.id,name:r.name,slug:r.slug,createdAt:r.created_at,updatedAt:r.updated_at}}async deleteTenant(e){this.stmt("DELETE FROM tenants WHERE id = ?").run(e)}async getSettings(e){let t=this.stmt("SELECT allowed_origins_json, admin_allowed_origins_json, setup_completed, profiles_seeded, tcf_confirmation_json, gpp_confirmation_json FROM tenant_settings WHERE tenant_id = ?").get(e);return t?{allowedOrigins:JSON.parse(t.allowed_origins_json),adminAllowedOrigins:JSON.parse(t.admin_allowed_origins_json),setupCompleted:!!t.setup_completed,profilesSeeded:!!t.profiles_seeded,tcfConfirmation:t.tcf_confirmation_json?JSON.parse(t.tcf_confirmation_json):void 0,gppConfirmation:t.gpp_confirmation_json?JSON.parse(t.gpp_confirmation_json):void 0}:{}}async updateSettings(e,t){let o={...await this.getSettings(e),...t};return this.stmt(`INSERT INTO tenant_settings (tenant_id, allowed_origins_json, admin_allowed_origins_json, setup_completed, profiles_seeded, tcf_confirmation_json, gpp_confirmation_json, updated_at) VALUES (?,?,?,?,?,?,?,?)
62
- ON CONFLICT(tenant_id) DO UPDATE SET allowed_origins_json = excluded.allowed_origins_json, admin_allowed_origins_json = excluded.admin_allowed_origins_json, setup_completed = excluded.setup_completed, profiles_seeded = excluded.profiles_seeded, tcf_confirmation_json = excluded.tcf_confirmation_json, gpp_confirmation_json = excluded.gpp_confirmation_json, updated_at = excluded.updated_at`).run([e,JSON.stringify(o.allowedOrigins??[]),JSON.stringify(o.adminAllowedOrigins??[]),o.setupCompleted?1:0,o.profilesSeeded?1:0,o.tcfConfirmation?JSON.stringify(o.tcfConfirmation):null,o.gppConfirmation?JSON.stringify(o.gppConfirmation):null,new Date().toISOString()]),this.getSettings(e)}async purgeExpiredConsents(e){let t=new Date(Date.now()-e*864e5).toISOString(),n=this.stmt("SELECT visitor_id FROM consent_records WHERE created_at < ?").all(t);for(let{visitor_id:o}of n)this.stmt("DELETE FROM consent_history WHERE visitor_id = ?").run(o),this.stmt("DELETE FROM consent_records WHERE visitor_id = ?").run(o);return n.length}mapApiKey(e){return{id:e.id,tenantId:e.tenant_id,keyHash:e.key_hash,name:e.name,isActive:e.is_active===1,...e.created_by!==null?{createdBy:e.created_by}:{},...e.expire_by!==null?{expireBy:e.expire_by}:{},createdAt:e.created_at,...e.updated_at!==null?{updatedAt:e.updated_at}:{}}}async createApiKey(e){let t=(0,v.randomUUID)(),n=new Date().toISOString();this.stmt("INSERT INTO api_keys (id,tenant_id,key_hash,name,created_by,expire_by,created_at,updated_at) VALUES (?,?,?,?,?,?,?,?)").run([t,e.tenantId,e.keyHash,e.name,e.createdBy??null,e.expireBy??null,n,n]);let o=this.stmt("SELECT * FROM api_keys WHERE id = ?").get(t);if(!o)throw new Error("Failed to create API key");return this.mapApiKey(o)}async getApiKeyByHash(e){let t=this.stmt("SELECT * FROM api_keys WHERE key_hash = ? AND is_active = 1").get(e);return t?this.mapApiKey(t):null}async revokeApiKey(e){this.stmt("UPDATE api_keys SET is_active = 0, updated_at = ? WHERE id = ?").run([new Date().toISOString(),e])}async reactivateApiKey(e){let t=new Date().toISOString();this.stmt("UPDATE api_keys SET is_active = 1, updated_at = ?, expire_by = CASE WHEN expire_by <= ? THEN NULL ELSE expire_by END WHERE id = ?").run([t,t,e])}async deleteApiKey(e){this.stmt("DELETE FROM api_keys WHERE id = ?").run([e])}async getApiKeys(e){return this.stmt("SELECT * FROM api_keys WHERE tenant_id = ? ORDER BY created_at DESC").all(e).map(n=>this.mapApiKey(n))}mapConsentTemplate(e){return{id:e.id,tenantId:e.tenant_id,name:e.name,cookies:JSON.parse(e.cookies_json),categories:JSON.parse(e.categories_json),createdAt:e.created_at,updatedAt:e.updated_at}}async createConsentTemplate(e){let t=Y(),n=new Date().toISOString();return this.stmt("INSERT INTO consent_templates (id,tenant_id,name,cookies_json,categories_json,created_at,updated_at) VALUES (?,?,?,?,?,?,?)").run([t,e.tenantId,e.name,JSON.stringify(e.cookies),JSON.stringify(e.categories),n,n]),this.mapConsentTemplate(this.stmt("SELECT * FROM consent_templates WHERE id = ?").get(t))}async updateConsentTemplate(e,t){let n=new Date().toISOString();t.name!==void 0&&this.stmt("UPDATE consent_templates SET name = ?, updated_at = ? WHERE id = ?").run([t.name,n,e]),t.cookies!==void 0&&this.stmt("UPDATE consent_templates SET cookies_json = ?, updated_at = ? WHERE id = ?").run([JSON.stringify(t.cookies),n,e]),t.categories!==void 0&&this.stmt("UPDATE consent_templates SET categories_json = ?, updated_at = ? WHERE id = ?").run([JSON.stringify(t.categories),n,e]);let o=this.stmt("SELECT * FROM consent_templates WHERE id = ?").get(e);if(!o)throw new Error("Consent template not found");return this.mapConsentTemplate(o)}async deleteConsentTemplate(e){this.stmt("DELETE FROM consent_templates WHERE id = ?").run(e)}async getConsentTemplate(e){let t=this.stmt("SELECT * FROM consent_templates WHERE id = ?").get(e);return t?this.mapConsentTemplate(t):null}async getConsentTemplates(e){return this.stmt("SELECT * FROM consent_templates WHERE tenant_id = ? ORDER BY name ASC").all(e).map(n=>this.mapConsentTemplate(n))}async copyConsentTemplate(e,t){let n=await this.getConsentTemplate(e);if(!n)throw new Error("Consent template not found");return this.createConsentTemplate({tenantId:n.tenantId,name:t,cookies:n.cookies,categories:n.categories})}mapUITemplate(e){let t=JSON.parse(e.settings_json);return{id:e.id,tenantId:e.tenant_id,name:e.name,...t,createdAt:e.created_at,updatedAt:e.updated_at}}async createUITemplate(e){let t=Q(),n=new Date().toISOString(),{tenantId:o,name:s,...r}=e;return this.stmt("INSERT INTO ui_templates (id,tenant_id,name,settings_json,created_at,updated_at) VALUES (?,?,?,?,?,?)").run([t,o,s,JSON.stringify(r),n,n]),this.mapUITemplate(this.stmt("SELECT * FROM ui_templates WHERE id = ?").get(t))}async updateUITemplate(e,t){let n=new Date().toISOString(),o=this.stmt("SELECT * FROM ui_templates WHERE id = ?").get(e);if(!o)throw new Error("UI template not found");t.name!==void 0&&this.stmt("UPDATE ui_templates SET name = ?, updated_at = ? WHERE id = ?").run([t.name,n,e]);let{name:s,...r}=t;if(Object.keys(r).length>0){let c={...JSON.parse(o.settings_json),...r};this.stmt("UPDATE ui_templates SET settings_json = ?, updated_at = ? WHERE id = ?").run([JSON.stringify(c),n,e])}return this.mapUITemplate(this.stmt("SELECT * FROM ui_templates WHERE id = ?").get(e))}async deleteUITemplate(e){this.stmt("DELETE FROM ui_templates WHERE id = ?").run(e)}async getUITemplate(e){let t=this.stmt("SELECT * FROM ui_templates WHERE id = ?").get(e);return t?this.mapUITemplate(t):null}async getUITemplates(e){return this.stmt("SELECT * FROM ui_templates WHERE tenant_id = ? ORDER BY name ASC").all(e).map(n=>this.mapUITemplate(n))}async copyUITemplate(e,t){let n=await this.getUITemplate(e);if(!n)throw new Error("UI template not found");let{tenantId:o,mainBanner:s,gpcBanner:r,preferenceModal:a}=n;return this.createUITemplate({tenantId:o,name:t,mainBanner:s,gpcBanner:r,preferenceModal:a})}mapProfileSummary(e){return{id:e.id,name:e.name,defaultLocale:e.default_locale,complianceGroup:e.compliance_group??null,customComplianceGroup:e.custom_compliance_group??null,isActive:e.is_active===1,consentTemplateName:e.consent_template_name,uiTemplateName:e.ui_template_name,createdAt:e.created_at,updatedAt:e.updated_at}}PROFILE_SUMMARY_SQL=`
58
+ `)}migrateToV2(){je({exec:e=>this.db.exec(e),all:e=>{let t=this.db.prepare(e);try{return t.all()}finally{t.finalize()}}},this.dbPath)}mapProfile(e){return{id:e.id,tenantId:e.tenant_id,name:e.name,defaultLocale:e.default_locale,version:e.version,profileJson:JSON.parse(e.profile_json),createdAt:e.created_at,updatedAt:e.updated_at}}async createProfile(e){let t=K(),n=new Date().toISOString();this.stmt("INSERT INTO profiles (id,tenant_id,name,default_locale,version,profile_json,created_at,updated_at) VALUES (?,?,?,?,?,?,?,?)").run([t,e.tenantId,e.name,e.defaultLocale,1,JSON.stringify(e.profileJson),n,n]);let o=await this.getProfile(t);if(!o)throw new Error("Failed to create profile");return o}async updateProfile(e,t){if(!await this.getProfile(e))throw new Error(`Profile ${e} not found`);let o=new Date().toISOString(),s=["updated_at = ?"],r=[o];t.name!=null&&(s.push("name = ?"),r.push(t.name)),t.defaultLocale!=null&&(s.push("default_locale = ?"),r.push(t.defaultLocale)),t.profileJson!=null&&(s.push("profile_json = ?"),r.push(JSON.stringify(t.profileJson))),t.version!=null&&(s.push("version = ?"),r.push(t.version)),r.push(e),this.stmt(`UPDATE profiles SET ${s.join(", ")} WHERE id = ?`).run(r);let a=await this.getProfile(e);if(!a)throw new Error("Failed to update profile");return a}async deleteProfile(e){this.stmt("DELETE FROM profiles WHERE id = ?").run(e)}async getProfile(e){let t=this.stmt("SELECT * FROM profiles WHERE id = ?").get(e);return t?this.mapProfile(t):null}async getProfiles(e){return this.stmt("SELECT * FROM profiles WHERE tenant_id = ? ORDER BY created_at ASC").all(e).map(n=>this.mapProfile(n))}async findActiveProfileByComplianceGroup(e,t){return(await this.getProfiles(e)).find(o=>(o.profileJson.complianceGroup===t||o.profileJson.customComplianceGroup===t)&&o.profileJson.isActive)??null}mapConsent(e){return{id:e.id,tenantId:e.tenant_id,visitorId:e.visitor_id,profileId:e.profile_id,...e.profile_version!=null?{profileVersion:e.profile_version}:{},locale:e.locale,consentJson:JSON.parse(e.consent_json),gpcDetected:e.gpc_detected===1,source:e.source,...e.age_verified!=null&&e.age_verified!==0?{ageVerified:!0}:{},...e.parental_consent_token!=null?{parentalConsentToken:e.parental_consent_token}:{},...e.tcf_string!=null?{tcfString:e.tcf_string}:{},...e.gpp_string!=null?{gppString:e.gpp_string}:{},...e.signature!=null?{signature:e.signature}:{},createdAt:e.created_at,updatedAt:e.updated_at}}static CONSENT_SUMMARY_COLS="id, tenant_id, visitor_id, profile_id, locale, gpc_detected, source, age_verified, created_at, updated_at";mapConsentSummary(e){return{id:e.id,tenantId:e.tenant_id,visitorId:e.visitor_id,profileId:e.profile_id,locale:e.locale,gpcDetected:e.gpc_detected===1,source:e.source,...e.age_verified!=null&&e.age_verified!==0?{ageVerified:!0}:{},createdAt:e.created_at,updatedAt:e.updated_at}}async createConsent(e){let t=Y(),n=new Date().toISOString();this.stmt("INSERT INTO consent_records (id,tenant_id,visitor_id,profile_id,profile_version,locale,consent_json,gpc_detected,source,age_verified,parental_consent_token,tcf_string,gpp_string,signature,created_at,updated_at) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)").run([t,e.tenantId,e.visitorId,e.profileId,e.profileVersion??null,e.locale,JSON.stringify(e.consentJson),e.gpcDetected?1:0,e.source,e.ageVerified?1:0,e.parentalConsentToken??null,e.tcfString??null,e.gppString??null,e.signature??null,n,n]);let o=(0,C.randomUUID)();this.stmt("INSERT INTO consent_history (id,tenant_id,consent_record_id,visitor_id,profile_version,old_json,new_json,action,created_at) VALUES (?,?,?,?,?,?,?,?,?)").run([o,e.tenantId,t,e.visitorId,e.profileVersion??null,null,JSON.stringify(e.consentJson),"created",n]);let s=await this.getConsent(e.visitorId);if(!s)throw new Error("Failed to create consent");return s}async updateConsent(e,t){let n=await this.getConsent(e);if(!n)throw new Error(`Consent for visitor ${e} not found`);let o=new Date().toISOString(),s=["updated_at = ?","consent_json = ?"],r=[o,JSON.stringify(t.consentJson)];t.profileVersion!=null&&(s.push("profile_version = ?"),r.push(t.profileVersion)),t.locale!=null&&(s.push("locale = ?"),r.push(t.locale)),t.gpcDetected!=null&&(s.push("gpc_detected = ?"),r.push(t.gpcDetected?1:0)),t.signature!=null&&(s.push("signature = ?"),r.push(t.signature)),r.push(e),this.stmt(`UPDATE consent_records SET ${s.join(", ")} WHERE visitor_id = ?`).run(r);let a=(0,C.randomUUID)();this.stmt("INSERT INTO consent_history (id,tenant_id,consent_record_id,visitor_id,profile_version,old_json,new_json,action,created_at) VALUES (?,?,?,?,?,?,?,?,?)").run([a,n.tenantId,n.id,e,t.profileVersion??n.profileVersion??null,JSON.stringify(n.consentJson),JSON.stringify(t.consentJson),"updated",o]);let c=await this.getConsent(e);if(!c)throw new Error("Failed to update consent");return c}async deleteConsent(e){this.stmt("DELETE FROM consent_history WHERE visitor_id = ?").run(e),this.stmt("DELETE FROM consent_records WHERE visitor_id = ?").run(e)}async getConsent(e){let t=this.stmt("SELECT * FROM consent_records WHERE visitor_id = ?").get(e);return t?this.mapConsent(t):null}async getConsents(e){let t=["tenant_id = ?"],n=[e.tenantId];if(e.profileId&&(t.push("profile_id = ?"),n.push(e.profileId)),e.from&&(t.push("created_at >= ?"),n.push(e.from)),e.to&&(t.push("created_at <= ?"),n.push(e.to)),e.q){t.push("(visitor_id LIKE ? OR profile_id LIKE ? OR locale LIKE ? OR source LIKE ?) ESCAPE '\\'");let d=j(e.q);n.push(d,d,d,d)}let o=t.join(" AND "),s=e.page??1,r=Math.min(e.limit??50,Kn),a=(s-1)*r,c=this.stmt(`SELECT ${i.CONSENT_SUMMARY_COLS} FROM consent_records WHERE ${o} ORDER BY created_at DESC LIMIT ? OFFSET ?`).all([...n,r,a]),l=this.stmt(`SELECT COUNT(*) AS total FROM consent_records WHERE ${o}`).get(n);return{items:c.map(d=>this.mapConsentSummary(d)),total:l?.total??0,page:s,limit:r}}async*streamConsents(e){let n=0;for(;;){let o=this.stmt("SELECT * FROM consent_records WHERE tenant_id = ? LIMIT ? OFFSET ?").all([e.tenantId,500,n]);if(o.length===0)break;for(let s of o)yield this.mapConsent(s);n+=500}}async getConsentHistory(e){return this.stmt("SELECT * FROM consent_history WHERE visitor_id = ? ORDER BY created_at ASC").all(e).map(n=>({id:n.id,tenantId:n.tenant_id,consentRecordId:n.consent_record_id,visitorId:n.visitor_id,...n.profile_version!=null?{profileVersion:n.profile_version}:{},oldJson:n.old_json!=null?JSON.parse(n.old_json):null,newJson:JSON.parse(n.new_json),action:n.action,createdAt:n.created_at}))}async createNoticeShown(e){let t=(0,C.randomUUID)(),n=new Date().toISOString();return this.stmt("INSERT INTO notice_shown (id,tenant_id,visitor_id,profile_id,locale,created_at) VALUES (?,?,?,?,?,?)").run([t,e.tenantId,e.visitorId,e.profileId,e.locale,n]),{id:t,tenantId:e.tenantId,visitorId:e.visitorId,profileId:e.profileId,locale:e.locale,createdAt:n}}async getNoticeShownForVisitor(e){return this.stmt("SELECT * FROM notice_shown WHERE visitor_id = ? ORDER BY created_at DESC").all(e).map(n=>({id:n.id,tenantId:n.tenant_id,visitorId:n.visitor_id,profileId:n.profile_id,locale:n.locale,createdAt:n.created_at}))}mapVisitor(e){return{id:e.id,tenantId:e.tenant_id,visitorId:e.visitor_id,firstSeen:e.first_seen,lastSeen:e.last_seen,...e.country!=null?{country:e.country}:{},...e.region!=null?{region:e.region}:{},...e.city!=null?{city:e.city}:{},...e.ip_hash!=null?{ipHash:e.ip_hash}:{},...e.user_agent_hash!=null?{userAgentHash:e.user_agent_hash}:{}}}async createVisitor(e){let t=q(),n=new Date().toISOString();this.stmt("INSERT INTO visitors (id,tenant_id,visitor_id,country,region,city,ip_hash,user_agent_hash,first_seen,last_seen) VALUES (?,?,?,?,?,?,?,?,?,?)").run([t,e.tenantId,e.visitorId,e.country??null,e.region??null,e.city??null,e.ipHash??null,e.userAgentHash??null,n,n]);let o=await this.getVisitor(e.visitorId);if(!o)throw new Error("Failed to create visitor");return o}async updateVisitor(e,t){let n=new Date().toISOString(),o=["last_seen = ?"],s=[t.lastSeen??n];t.country!=null&&(o.push("country = ?"),s.push(t.country)),t.region!=null&&(o.push("region = ?"),s.push(t.region)),t.city!=null&&(o.push("city = ?"),s.push(t.city)),s.push(e),this.stmt(`UPDATE visitors SET ${o.join(", ")} WHERE visitor_id = ?`).run(s);let r=await this.getVisitor(e);if(!r)throw new Error(`Visitor ${e} not found`);return r}async deleteVisitor(e){this.stmt("DELETE FROM visitors WHERE visitor_id = ?").run(e)}async getVisitor(e){let t=this.stmt("SELECT * FROM visitors WHERE visitor_id = ?").get(e);return t?this.mapVisitor(t):null}async getVisitors(e){let t=["tenant_id = ?"],n=[e.tenantId];if(e.from&&(t.push("first_seen >= ?"),n.push(e.from)),e.to&&(t.push("first_seen <= ?"),n.push(e.to)),e.q){t.push("(visitor_id LIKE ? OR country LIKE ?) ESCAPE '\\'");let d=j(e.q);n.push(d,d)}let o=t.join(" AND "),s=e.page??1,r=Math.min(e.limit??50,Kn),a=(s-1)*r,c=this.stmt(`SELECT * FROM visitors WHERE ${o} ORDER BY last_seen DESC LIMIT ? OFFSET ?`).all([...n,r,a]),l=this.stmt(`SELECT COUNT(*) AS total FROM visitors WHERE ${o}`).get(n);return{items:c.map(d=>this.mapVisitor(d)),total:l?.total??0,page:s,limit:r}}mapUser(e){let t=e.allowed_tenants?JSON.parse(e.allowed_tenants):[];return{id:e.id,tenantId:e.tenant_id,name:e.name,email:e.email,passwordHash:e.password_hash,isActive:e.is_active===1,totpEnabled:e.totp_enabled===1,...e.totp_secret!=null?{totpSecret:e.totp_secret}:{},allowedTenants:t,createdAt:e.created_at,updatedAt:e.updated_at}}async createUser(e){let t=(0,C.randomUUID)(),n=new Date().toISOString(),o=e.allowedTenants?.length?JSON.stringify(e.allowedTenants):null;this.stmt("INSERT INTO users (id,tenant_id,name,email,password_hash,allowed_tenants,created_at,updated_at) VALUES (?,?,?,?,?,?,?,?)").run([t,e.tenantId,e.name,e.email,e.passwordHash,o,n,n]);let s=await this.getUserByEmail(e.email);if(!s)throw new Error("Failed to create user");return s}async updateUser(e,t){let n=new Date().toISOString(),o=["updated_at = ?"],s=[n];t.name!=null&&(o.push("name = ?"),s.push(t.name)),t.email!=null&&(o.push("email = ?"),s.push(t.email)),t.passwordHash!=null&&(o.push("password_hash = ?"),s.push(t.passwordHash)),t.isActive!=null&&(o.push("is_active = ?"),s.push(t.isActive?1:0)),"totpSecret"in t&&(o.push("totp_secret = ?"),s.push(t.totpSecret??null)),t.totpEnabled!=null&&(o.push("totp_enabled = ?"),s.push(t.totpEnabled?1:0)),"allowedTenants"in t&&(o.push("allowed_tenants = ?"),s.push(t.allowedTenants?.length?JSON.stringify(t.allowedTenants):null)),s.push(e),this.stmt(`UPDATE users SET ${o.join(", ")} WHERE id = ?`).run(s);let r=this.stmt("SELECT * FROM users WHERE id = ?").get(e);if(!r)throw new Error(`User ${e} not found`);return this.mapUser(r)}async deleteUser(e){this.stmt("DELETE FROM user_roles WHERE user_id = ?").run(e),this.stmt("DELETE FROM users WHERE id = ?").run(e)}async getUserById(e){let t=this.stmt("SELECT * FROM users WHERE id = ?").get(e);return t?this.mapUser(t):null}async getUserByEmail(e){let t=this.stmt("SELECT * FROM users WHERE email = ?").get(e);return t?this.mapUser(t):null}async getUsers(e){return this.stmt("SELECT * FROM users WHERE tenant_id = ? ORDER BY created_at ASC").all(e).map(n=>this.mapUser(n))}async countUsers(e){return(e?this.stmt("SELECT COUNT(*) as n FROM users WHERE tenant_id = ?").get(e):this.stmt("SELECT COUNT(*) as n FROM users").get())?.n??0}async getRoles(e){return this.stmt("SELECT * FROM roles WHERE tenant_id = ?").all(e).map(n=>({id:n.id,tenantId:n.tenant_id,name:n.name,...n.description!=null?{description:n.description}:{}}))}async createRole(e){let t=(0,C.randomUUID)();this.stmt("INSERT INTO roles (id,tenant_id,name,description) VALUES (?,?,?,?)").run([t,e.tenantId,e.name,e.description??null]);let n=this.stmt("SELECT * FROM roles WHERE id = ?").get(t);if(!n)throw new Error("Failed to create role");return{id:n.id,tenantId:n.tenant_id,name:n.name,...n.description!=null?{description:n.description}:{}}}async updateRole(e,t){let n=[],o=[];t.name!=null&&(n.push("name = ?"),o.push(t.name)),t.description!=null&&(n.push("description = ?"),o.push(t.description)),n.length>0&&(o.push(e),this.stmt(`UPDATE roles SET ${n.join(", ")} WHERE id = ?`).run(o));let s=this.stmt("SELECT * FROM roles WHERE id = ?").get(e);if(!s)throw new Error(`Role ${e} not found`);return{id:s.id,tenantId:s.tenant_id,name:s.name,...s.description!=null?{description:s.description}:{}}}async deleteRole(e){this.stmt("DELETE FROM role_permissions WHERE role_id = ?").run(e),this.stmt("DELETE FROM user_roles WHERE role_id = ?").run(e),this.stmt("DELETE FROM roles WHERE id = ?").run(e)}async getAllPermissions(){return this.stmt("SELECT * FROM permissions ORDER BY name ASC").all().map(t=>({id:t.id,name:t.name,...t.description!=null?{description:t.description}:{}}))}async assignPermissionToRole(e,t){this.stmt("INSERT OR IGNORE INTO role_permissions (role_id,permission_id) VALUES (?,?)").run([e,t])}async revokePermissionFromRole(e,t){this.stmt("DELETE FROM role_permissions WHERE role_id = ? AND permission_id = ?").run([e,t])}async getPermissionsForRole(e){return this.stmt("SELECT p.* FROM permissions p JOIN role_permissions rp ON rp.permission_id = p.id WHERE rp.role_id = ?").all(e).map(n=>({id:n.id,name:n.name,...n.description!=null?{description:n.description}:{}}))}async getUserRoles(e,t){return(t?this.stmt("SELECT r.* FROM roles r JOIN user_roles ur ON ur.role_id = r.id WHERE ur.user_id = ? AND ur.tenant_id = ?").all([e,t]):this.stmt("SELECT r.* FROM roles r JOIN user_roles ur ON ur.role_id = r.id WHERE ur.user_id = ?").all(e)).map(o=>({id:o.id,tenantId:o.tenant_id,name:o.name,...o.description!=null?{description:o.description}:{}}))}async assignRole(e,t,n="default"){this.stmt("INSERT OR IGNORE INTO user_roles (user_id, role_id, tenant_id) VALUES (?,?,?)").run([e,t,n])}async revokeRole(e,t,n){n?this.stmt("DELETE FROM user_roles WHERE user_id = ? AND role_id = ? AND tenant_id = ?").run([e,t,n]):this.stmt("DELETE FROM user_roles WHERE user_id = ? AND role_id = ?").run([e,t])}async createLog(e){let t=(0,C.randomUUID)(),n=new Date().toISOString();this.stmt("INSERT INTO audit_logs (id,tenant_id,user_id,action,resource_type,resource_id,old_data,new_data,created_at) VALUES (?,?,?,?,?,?,?,?,?)").run([t,e.tenantId,e.userId??null,e.action,e.resourceType,e.resourceId??null,e.oldData!=null?JSON.stringify(e.oldData):null,e.newData!=null?JSON.stringify(e.newData):null,n])}async getLogs(e){let t=["tenant_id = ?"],n=[e.tenantId];if(e.action&&(t.push("action = ?"),n.push(e.action)),e.resourceType&&(t.push("resource_type = ?"),n.push(e.resourceType)),e.from&&(t.push("created_at >= ?"),n.push(e.from)),e.to&&(t.push("created_at <= ?"),n.push(e.to)),e.q){t.push("(action LIKE ? OR resource_type LIKE ? OR resource_id LIKE ? OR user_id LIKE ?) ESCAPE '\\'");let d=j(e.q);n.push(d,d,d,d)}let o=t.join(" AND "),s=e.page??1,r=Math.min(e.limit??50,Kn),a=(s-1)*r,c=this.stmt(`SELECT ${i.AUDIT_SUMMARY_COLS} FROM audit_logs WHERE ${o} ORDER BY created_at DESC LIMIT ? OFFSET ?`).all([...n,r,a]),l=this.stmt(`SELECT COUNT(*) AS total FROM audit_logs WHERE ${o}`).get(n);return{items:c.map(d=>this.mapAuditSummary(d)),total:l?.total??0,page:s,limit:r}}async getAuditLogById(e){let t=this.stmt("SELECT * FROM audit_logs WHERE id = ?").get(e);return t?this.mapAuditLog(t):null}static AUDIT_SUMMARY_COLS="id, tenant_id, user_id, action, resource_type, resource_id, created_at";mapAuditSummary(e){return{id:e.id,tenantId:e.tenant_id,action:e.action,resourceType:e.resource_type,...e.user_id!=null?{userId:e.user_id}:{},...e.resource_id!=null?{resourceId:e.resource_id}:{},createdAt:e.created_at}}mapAuditLog(e){return{id:e.id,tenantId:e.tenant_id,action:e.action,resourceType:e.resource_type,createdAt:e.created_at,...e.user_id!=null?{userId:e.user_id}:{},...e.resource_id!=null?{resourceId:e.resource_id}:{},...e.old_data!=null?{oldData:JSON.parse(e.old_data)}:{},...e.new_data!=null?{newData:JSON.parse(e.new_data)}:{}}}async*streamAuditLogs(e){let t=["tenant_id = ?"],n=[e.tenantId];e.action&&(t.push("action = ?"),n.push(e.action)),e.from&&(t.push("created_at >= ?"),n.push(e.from)),e.to&&(t.push("created_at <= ?"),n.push(e.to));let o=500,s=0;for(;;){let r=this.stmt(`SELECT * FROM audit_logs WHERE ${t.join(" AND ")} ORDER BY created_at DESC LIMIT ? OFFSET ?`).all([...n,o,s]);if(r.length===0)break;for(let a of r)yield this.mapAuditLog(a);s+=o}}async getOverviewStats(e){let t=this.stmt("SELECT COUNT(*) as n FROM consent_records WHERE tenant_id = ?").get(e),n=this.stmt("SELECT COUNT(*) as n FROM consent_records WHERE tenant_id = ? AND gpc_detected = 1").get(e),o=this.stmt("SELECT COUNT(*) as n FROM visitors WHERE tenant_id = ?").get(e),s=t?.n??0,r=this.stmt("SELECT consent_json FROM consent_records WHERE tenant_id = ? ORDER BY created_at DESC LIMIT 500").all(e),a=0,c=0;for(let d of r){let u=Object.values(JSON.parse(d.consent_json)),m=u.length>0?u.filter(f=>f==="granted").length/u.length:0;m>=.8?a++:m<=.2&&c++}let l=r.length||1;return{totalConsents:s,gpcDetectedCount:n?.n??0,totalVisitors:o?.n??0,acceptedPct:Math.round(a/l*100),rejectedPct:Math.round(c/l*100)}}async getCategoryStats(e){let t=this.stmt("SELECT consent_json FROM consent_records WHERE tenant_id = ? LIMIT 5000").all(e),n={};for(let o of t){let s=JSON.parse(o.consent_json);for(let[r,a]of Object.entries(s))n[r]||(n[r]={granted:0,denied:0,objected:0}),a==="granted"?n[r].granted++:a==="denied"?n[r].denied++:a==="objected"&&n[r].objected++}return n}async getTimeline(e,t=30){return this.stmt("SELECT date(created_at) as date, COUNT(*) as count FROM consent_records WHERE tenant_id = ? AND created_at >= date('now', ?) GROUP BY date(created_at) ORDER BY date ASC").all([e,`-${t} days`]).map(o=>({date:o.date,count:o.count}))}async getCountries(e){return this.stmt("SELECT v.country, COUNT(*) as count FROM consent_records cr JOIN visitors v ON v.visitor_id = cr.visitor_id WHERE cr.tenant_id = ? AND v.country IS NOT NULL GROUP BY v.country ORDER BY count DESC LIMIT 50").all(e).map(n=>({country:n.country,count:n.count}))}async getGpcStats(e){let t=this.stmt("SELECT COUNT(*) as n FROM consent_records WHERE tenant_id = ?").get(e),n=this.stmt("SELECT COUNT(*) as n FROM consent_records WHERE tenant_id = ? AND gpc_detected = 1").get(e),o=t?.n??0,s=n?.n??0;return{detected:s,total:o,rate:o>0?Math.round(s/o*100):0}}async getTenants(){return this.stmt("SELECT * FROM tenants ORDER BY name ASC").all().map(t=>({id:t.id,name:t.name,slug:t.slug,createdAt:t.created_at,updatedAt:t.updated_at}))}async createTenant(e){let t=(0,C.randomUUID)(),n=new Date().toISOString();this.stmt("INSERT INTO tenants (id,name,slug,created_at,updated_at) VALUES (?,?,?,?,?)").run([t,e.name,e.slug,n,n]);let o=this.stmt("SELECT * FROM tenants WHERE id = ?").get(t);if(!o)throw new Error("Failed to create tenant");return{id:o.id,name:o.name,slug:o.slug,createdAt:o.created_at,updatedAt:o.updated_at}}async updateTenant(e,t){let n=new Date().toISOString(),o=["updated_at = ?"],s=[n];t.name!=null&&(o.push("name = ?"),s.push(t.name)),t.slug!=null&&(o.push("slug = ?"),s.push(t.slug)),s.push(e),this.stmt(`UPDATE tenants SET ${o.join(", ")} WHERE id = ?`).run(s);let r=this.stmt("SELECT * FROM tenants WHERE id = ?").get(e);if(!r)throw new Error(`Tenant ${e} not found`);return{id:r.id,name:r.name,slug:r.slug,createdAt:r.created_at,updatedAt:r.updated_at}}async deleteTenant(e){this.stmt("DELETE FROM tenants WHERE id = ?").run(e)}async getSettings(e){let t=this.stmt("SELECT allowed_origins_json, admin_allowed_origins_json, setup_completed, profiles_seeded, tcf_confirmation_json, gpp_confirmation_json FROM tenant_settings WHERE tenant_id = ?").get(e);return t?{allowedOrigins:JSON.parse(t.allowed_origins_json),adminAllowedOrigins:JSON.parse(t.admin_allowed_origins_json),setupCompleted:!!t.setup_completed,profilesSeeded:!!t.profiles_seeded,tcfConfirmation:t.tcf_confirmation_json?JSON.parse(t.tcf_confirmation_json):void 0,gppConfirmation:t.gpp_confirmation_json?JSON.parse(t.gpp_confirmation_json):void 0}:{}}async updateSettings(e,t){let o={...await this.getSettings(e),...t};return this.stmt(`INSERT INTO tenant_settings (tenant_id, allowed_origins_json, admin_allowed_origins_json, setup_completed, profiles_seeded, tcf_confirmation_json, gpp_confirmation_json, updated_at) VALUES (?,?,?,?,?,?,?,?)
59
+ ON CONFLICT(tenant_id) DO UPDATE SET allowed_origins_json = excluded.allowed_origins_json, admin_allowed_origins_json = excluded.admin_allowed_origins_json, setup_completed = excluded.setup_completed, profiles_seeded = excluded.profiles_seeded, tcf_confirmation_json = excluded.tcf_confirmation_json, gpp_confirmation_json = excluded.gpp_confirmation_json, updated_at = excluded.updated_at`).run([e,JSON.stringify(o.allowedOrigins??[]),JSON.stringify(o.adminAllowedOrigins??[]),o.setupCompleted?1:0,o.profilesSeeded?1:0,o.tcfConfirmation?JSON.stringify(o.tcfConfirmation):null,o.gppConfirmation?JSON.stringify(o.gppConfirmation):null,new Date().toISOString()]),this.getSettings(e)}async purgeExpiredConsents(e){let t=new Date(Date.now()-e*864e5).toISOString(),n=this.stmt("SELECT visitor_id FROM consent_records WHERE created_at < ?").all(t);for(let{visitor_id:o}of n)this.stmt("DELETE FROM consent_history WHERE visitor_id = ?").run(o),this.stmt("DELETE FROM consent_records WHERE visitor_id = ?").run(o);return n.length}mapApiKey(e){return{id:e.id,tenantId:e.tenant_id,keyHash:e.key_hash,name:e.name,isActive:e.is_active===1,...e.created_by!==null?{createdBy:e.created_by}:{},...e.expire_by!==null?{expireBy:e.expire_by}:{},createdAt:e.created_at,...e.updated_at!==null?{updatedAt:e.updated_at}:{}}}async createApiKey(e){let t=(0,C.randomUUID)(),n=new Date().toISOString();this.stmt("INSERT INTO api_keys (id,tenant_id,key_hash,name,created_by,expire_by,created_at,updated_at) VALUES (?,?,?,?,?,?,?,?)").run([t,e.tenantId,e.keyHash,e.name,e.createdBy??null,e.expireBy??null,n,n]);let o=this.stmt("SELECT * FROM api_keys WHERE id = ?").get(t);if(!o)throw new Error("Failed to create API key");return this.mapApiKey(o)}async getApiKeyByHash(e){let t=this.stmt("SELECT * FROM api_keys WHERE key_hash = ? AND is_active = 1").get(e);return t?this.mapApiKey(t):null}async revokeApiKey(e){this.stmt("UPDATE api_keys SET is_active = 0, updated_at = ? WHERE id = ?").run([new Date().toISOString(),e])}async reactivateApiKey(e){let t=new Date().toISOString();this.stmt("UPDATE api_keys SET is_active = 1, updated_at = ?, expire_by = CASE WHEN expire_by <= ? THEN NULL ELSE expire_by END WHERE id = ?").run([t,t,e])}async deleteApiKey(e){this.stmt("DELETE FROM api_keys WHERE id = ?").run([e])}async getApiKeys(e){return this.stmt("SELECT * FROM api_keys WHERE tenant_id = ? ORDER BY created_at DESC").all(e).map(n=>this.mapApiKey(n))}mapConsentTemplate(e){return{id:e.id,tenantId:e.tenant_id,name:e.name,cookies:JSON.parse(e.cookies_json),categories:JSON.parse(e.categories_json),createdAt:e.created_at,updatedAt:e.updated_at}}async createConsentTemplate(e){let t=Q(),n=new Date().toISOString();return this.stmt("INSERT INTO consent_templates (id,tenant_id,name,cookies_json,categories_json,created_at,updated_at) VALUES (?,?,?,?,?,?,?)").run([t,e.tenantId,e.name,JSON.stringify(e.cookies),JSON.stringify(e.categories),n,n]),this.mapConsentTemplate(this.stmt("SELECT * FROM consent_templates WHERE id = ?").get(t))}async updateConsentTemplate(e,t){let n=new Date().toISOString();t.name!==void 0&&this.stmt("UPDATE consent_templates SET name = ?, updated_at = ? WHERE id = ?").run([t.name,n,e]),t.cookies!==void 0&&this.stmt("UPDATE consent_templates SET cookies_json = ?, updated_at = ? WHERE id = ?").run([JSON.stringify(t.cookies),n,e]),t.categories!==void 0&&this.stmt("UPDATE consent_templates SET categories_json = ?, updated_at = ? WHERE id = ?").run([JSON.stringify(t.categories),n,e]);let o=this.stmt("SELECT * FROM consent_templates WHERE id = ?").get(e);if(!o)throw new Error("Consent template not found");return this.mapConsentTemplate(o)}async deleteConsentTemplate(e){this.stmt("DELETE FROM consent_templates WHERE id = ?").run(e)}async getConsentTemplate(e){let t=this.stmt("SELECT * FROM consent_templates WHERE id = ?").get(e);return t?this.mapConsentTemplate(t):null}async getConsentTemplates(e){return this.stmt("SELECT * FROM consent_templates WHERE tenant_id = ? ORDER BY name ASC").all(e).map(n=>this.mapConsentTemplate(n))}async copyConsentTemplate(e,t){let n=await this.getConsentTemplate(e);if(!n)throw new Error("Consent template not found");return this.createConsentTemplate({tenantId:n.tenantId,name:t,cookies:n.cookies,categories:n.categories})}mapUITemplate(e){let t=JSON.parse(e.settings_json);return{id:e.id,tenantId:e.tenant_id,name:e.name,...t,createdAt:e.created_at,updatedAt:e.updated_at}}async createUITemplate(e){let t=Z(),n=new Date().toISOString(),{tenantId:o,name:s,...r}=e;return this.stmt("INSERT INTO ui_templates (id,tenant_id,name,settings_json,created_at,updated_at) VALUES (?,?,?,?,?,?)").run([t,o,s,JSON.stringify(r),n,n]),this.mapUITemplate(this.stmt("SELECT * FROM ui_templates WHERE id = ?").get(t))}async updateUITemplate(e,t){let n=new Date().toISOString(),o=this.stmt("SELECT * FROM ui_templates WHERE id = ?").get(e);if(!o)throw new Error("UI template not found");t.name!==void 0&&this.stmt("UPDATE ui_templates SET name = ?, updated_at = ? WHERE id = ?").run([t.name,n,e]);let{name:s,...r}=t;if(Object.keys(r).length>0){let c={...JSON.parse(o.settings_json),...r};this.stmt("UPDATE ui_templates SET settings_json = ?, updated_at = ? WHERE id = ?").run([JSON.stringify(c),n,e])}return this.mapUITemplate(this.stmt("SELECT * FROM ui_templates WHERE id = ?").get(e))}async deleteUITemplate(e){this.stmt("DELETE FROM ui_templates WHERE id = ?").run(e)}async getUITemplate(e){let t=this.stmt("SELECT * FROM ui_templates WHERE id = ?").get(e);return t?this.mapUITemplate(t):null}async getUITemplates(e){return this.stmt("SELECT * FROM ui_templates WHERE tenant_id = ? ORDER BY name ASC").all(e).map(n=>this.mapUITemplate(n))}async copyUITemplate(e,t){let n=await this.getUITemplate(e);if(!n)throw new Error("UI template not found");let{tenantId:o,mainBanner:s,gpcBanner:r,preferenceModal:a}=n;return this.createUITemplate({tenantId:o,name:t,mainBanner:s,gpcBanner:r,preferenceModal:a})}mapProfileSummary(e){return{id:e.id,name:e.name,defaultLocale:e.default_locale,complianceGroup:e.compliance_group??null,customComplianceGroup:e.custom_compliance_group??null,isActive:e.is_active===1,consentTemplateName:e.consent_template_name,uiTemplateName:e.ui_template_name,createdAt:e.created_at,updatedAt:e.updated_at}}PROFILE_SUMMARY_SQL=`
63
60
  SELECT
64
61
  p.id, p.name, p.default_locale, p.created_at, p.updated_at,
65
62
  json_extract(p.profile_json, '$.complianceGroup') AS compliance_group,
@@ -72,13 +69,13 @@ ${l.map(d=>` (${se(c)},${se(d)})`).join(`,
72
69
  FROM profiles p
73
70
  LEFT JOIN consent_templates ct ON ct.id = json_extract(p.profile_json, '$.consentTemplateId')
74
71
  LEFT JOIN ui_templates ut ON ut.id = json_extract(p.profile_json, '$.uiTemplateId')
75
- `;async listProfilesSummary(e){return this.stmt(`${this.PROFILE_SUMMARY_SQL} WHERE p.tenant_id = ? ORDER BY p.created_at ASC`).all(e).map(n=>this.mapProfileSummary(n))}async findProfilesUsingConsentTemplate(e){return this.stmt(`${this.PROFILE_SUMMARY_SQL} WHERE json_extract(p.profile_json, '$.consentTemplateId') = ? ORDER BY p.name ASC`).all(e).map(n=>this.mapProfileSummary(n))}async findProfilesUsingUITemplate(e){return this.stmt(`${this.PROFILE_SUMMARY_SQL} WHERE json_extract(p.profile_json, '$.uiTemplateId') = ? ORDER BY p.name ASC`).all(e).map(n=>this.mapProfileSummary(n))}async getOptInStats(e,t){let n=["cr.tenant_id = ?"],o=[e];t.profileId&&(n.push("cr.profile_id = ?"),o.push(t.profileId)),t.from&&(n.push("cr.created_at >= ?"),o.push(t.from)),t.to&&(n.push("cr.created_at <= ?"),o.push(t.to)),t.locale&&(n.push("cr.locale = ?"),o.push(t.locale));let s=n.join(" AND "),r=this.stmt(`SELECT cr.locale, cr.consent_json FROM consent_records cr WHERE ${s}`).all(o),a=0,c=0,l=0,d=0,u={};for(let _ of r){let w=Object.values(JSON.parse(_.consent_json)),R=w.length>0?w.filter(T=>T==="granted").length/w.length:0,C=w.length>0?w.filter(T=>T==="denied").length/w.length:0;a++;let A=_.locale;u[A]||(u[A]={total:0,granted:0,denied:0,managed:0}),u[A].total++,R>=.9?(c++,u[A].granted++):C>=.9?(l++,u[A].denied++):(d++,u[A].managed++)}let m=this.stmt(`SELECT date(cr.created_at) as d, cr.consent_json FROM consent_records cr WHERE ${s} ORDER BY d ASC`).all(o),h=new Map;for(let _ of m){let w=h.get(_.d)??{total:0,granted:0,denied:0,managed:0},R=Object.values(JSON.parse(_.consent_json)),C=R.length>0?R.filter(T=>T==="granted").length/R.length:0,A=R.length>0?R.filter(T=>T==="denied").length/R.length:0;w.total++,C>=.9?w.granted++:A>=.9?w.denied++:w.managed++,h.set(_.d,w)}let S=Array.from(h.entries()).map(([_,w])=>({date:_,...w}));return{total:a,granted:c,denied:l,managed:d,grantedPct:a>0?Math.round(c/a*1e3)/10:0,deniedPct:a>0?Math.round(l/a*1e3)/10:0,managedPct:a>0?Math.round(d/a*1e3)/10:0,byLocale:u,byDate:S}}};p();var Gn=500,vt=class i{constructor(e){this.config=e}config;db;cache=new Map;stmt(e){let t=this.cache.get(e);return t||(t=this.db.prepare(e),this.cache.set(e,t)),t}async connect(){let{DatabaseSync:e}=await import("node:sqlite").catch(()=>{throw new Error(`driver 'node:sqlite' requires Node.js >= 22.5.0 (current: ${process.version})`)}),{dbPath:t}=me(this.config.path??"./consenti-data","node:sqlite");this.db=new e(t),this.db.exec("PRAGMA journal_mode=WAL"),this.db.exec("PRAGMA foreign_keys=ON"),this.db.exec("PRAGMA synchronous=NORMAL"),await this.migrate()}async disconnect(){this.cache.clear(),this.db.close()}async migrate(){this.db.prepare("PRAGMA user_version").get().user_version<1&&(this.db.exec(Le),this.db.exec(Ne),this.db.exec("PRAGMA user_version = 1")),this.db.exec(`
72
+ `;async listProfilesSummary(e){return this.stmt(`${this.PROFILE_SUMMARY_SQL} WHERE p.tenant_id = ? ORDER BY p.created_at ASC`).all(e).map(n=>this.mapProfileSummary(n))}async findProfilesUsingConsentTemplate(e){return this.stmt(`${this.PROFILE_SUMMARY_SQL} WHERE json_extract(p.profile_json, '$.consentTemplateId') = ? ORDER BY p.name ASC`).all(e).map(n=>this.mapProfileSummary(n))}async findProfilesUsingUITemplate(e){return this.stmt(`${this.PROFILE_SUMMARY_SQL} WHERE json_extract(p.profile_json, '$.uiTemplateId') = ? ORDER BY p.name ASC`).all(e).map(n=>this.mapProfileSummary(n))}async getOptInStats(e,t){let n=["cr.tenant_id = ?"],o=[e];t.profileId&&(n.push("cr.profile_id = ?"),o.push(t.profileId)),t.from&&(n.push("cr.created_at >= ?"),o.push(t.from)),t.to&&(n.push("cr.created_at <= ?"),o.push(t.to)),t.locale&&(n.push("cr.locale = ?"),o.push(t.locale));let s=n.join(" AND "),r=this.stmt(`SELECT cr.locale, cr.consent_json FROM consent_records cr WHERE ${s}`).all(o),a=0,c=0,l=0,d=0,u={};for(let y of r){let E=Object.values(JSON.parse(y.consent_json)),R=E.length>0?E.filter(T=>T==="granted").length/E.length:0,v=E.length>0?E.filter(T=>T==="denied").length/E.length:0;a++;let A=y.locale;u[A]||(u[A]={total:0,granted:0,denied:0,managed:0}),u[A].total++,R>=.9?(c++,u[A].granted++):v>=.9?(l++,u[A].denied++):(d++,u[A].managed++)}let m=this.stmt(`SELECT date(cr.created_at) as d, cr.consent_json FROM consent_records cr WHERE ${s} ORDER BY d ASC`).all(o),f=new Map;for(let y of m){let E=f.get(y.d)??{total:0,granted:0,denied:0,managed:0},R=Object.values(JSON.parse(y.consent_json)),v=R.length>0?R.filter(T=>T==="granted").length/R.length:0,A=R.length>0?R.filter(T=>T==="denied").length/R.length:0;E.total++,v>=.9?E.granted++:A>=.9?E.denied++:E.managed++,f.set(y.d,E)}let S=Array.from(f.entries()).map(([y,E])=>({date:y,...E}));return{total:a,granted:c,denied:l,managed:d,grantedPct:a>0?Math.round(c/a*1e3)/10:0,deniedPct:a>0?Math.round(l/a*1e3)/10:0,managedPct:a>0?Math.round(d/a*1e3)/10:0,byLocale:u,byDate:S}}};p();var Yn=500,Dt=class i{constructor(e){this.config=e}config;db;cache=new Map;dbPath="";stmt(e){let t=this.cache.get(e);return t||(t=this.db.prepare(e),this.cache.set(e,t)),t}async connect(){let{DatabaseSync:e}=await import("node:sqlite").catch(()=>{throw new Error(`driver 'node:sqlite' requires Node.js >= 22.5.0 (current: ${process.version})`)}),{dbPath:t}=fe(this.config.path??"./consenti-data","node:sqlite");this.dbPath=t,this.db=new e(t),this.db.exec("PRAGMA journal_mode=WAL"),this.db.exec("PRAGMA foreign_keys=ON"),this.db.exec("PRAGMA synchronous=NORMAL"),await this.migrate()}async disconnect(){this.cache.clear(),this.db.close()}async migrate(){let e=this.db.prepare("PRAGMA user_version").get();e.user_version<1?(this.db.exec(Me),this.db.exec(Ge),this.db.exec(`PRAGMA user_version = ${le}`)):e.user_version<2&&this.migrateToV2(),this.db.exec(`
76
73
  CREATE INDEX IF NOT EXISTS idx_profiles_tenant_compliance_active
77
74
  ON profiles (tenant_id, json_extract(profile_json,'$.complianceGroup'), json_extract(profile_json,'$.isActive'));
78
- `)}mapProfile(e){return{id:e.id,tenantId:e.tenant_id,name:e.name,defaultLocale:e.default_locale,version:e.version,profileJson:JSON.parse(e.profile_json),createdAt:e.created_at,updatedAt:e.updated_at}}async createProfile(e){let t=z(),n=new Date().toISOString();this.stmt("INSERT INTO profiles (id,tenant_id,name,default_locale,version,profile_json,created_at,updated_at) VALUES (?,?,?,?,?,?,?,?)").run(t,e.tenantId,e.name,e.defaultLocale,1,JSON.stringify(e.profileJson),n,n);let o=await this.getProfile(t);if(!o)throw new Error("Failed to create profile");return o}async updateProfile(e,t){if(!await this.getProfile(e))throw new Error(`Profile ${e} not found`);let o=new Date().toISOString(),s=["updated_at = ?"],r=[o];t.name!=null&&(s.push("name = ?"),r.push(t.name)),t.defaultLocale!=null&&(s.push("default_locale = ?"),r.push(t.defaultLocale)),t.profileJson!=null&&(s.push("profile_json = ?"),r.push(JSON.stringify(t.profileJson))),t.version!=null&&(s.push("version = ?"),r.push(t.version)),r.push(e),this.stmt(`UPDATE profiles SET ${s.join(", ")} WHERE id = ?`).run(...r);let a=await this.getProfile(e);if(!a)throw new Error("Failed to update profile");return a}async deleteProfile(e){this.stmt("DELETE FROM profiles WHERE id = ?").run(e)}async getProfile(e){let t=this.stmt("SELECT * FROM profiles WHERE id = ?").get(e);return t?this.mapProfile(t):null}async getProfiles(e){return this.stmt("SELECT * FROM profiles WHERE tenant_id = ? ORDER BY created_at ASC").all(e).map(n=>this.mapProfile(n))}async findActiveProfileByComplianceGroup(e,t){let n=this.stmt(`SELECT * FROM profiles WHERE tenant_id = ?
75
+ `)}migrateToV2(){je({exec:e=>this.db.exec(e),all:e=>this.db.prepare(e).all()},this.dbPath)}mapProfile(e){return{id:e.id,tenantId:e.tenant_id,name:e.name,defaultLocale:e.default_locale,version:e.version,profileJson:JSON.parse(e.profile_json),createdAt:e.created_at,updatedAt:e.updated_at}}async createProfile(e){let t=K(),n=new Date().toISOString();this.stmt("INSERT INTO profiles (id,tenant_id,name,default_locale,version,profile_json,created_at,updated_at) VALUES (?,?,?,?,?,?,?,?)").run(t,e.tenantId,e.name,e.defaultLocale,1,JSON.stringify(e.profileJson),n,n);let o=await this.getProfile(t);if(!o)throw new Error("Failed to create profile");return o}async updateProfile(e,t){if(!await this.getProfile(e))throw new Error(`Profile ${e} not found`);let o=new Date().toISOString(),s=["updated_at = ?"],r=[o];t.name!=null&&(s.push("name = ?"),r.push(t.name)),t.defaultLocale!=null&&(s.push("default_locale = ?"),r.push(t.defaultLocale)),t.profileJson!=null&&(s.push("profile_json = ?"),r.push(JSON.stringify(t.profileJson))),t.version!=null&&(s.push("version = ?"),r.push(t.version)),r.push(e),this.stmt(`UPDATE profiles SET ${s.join(", ")} WHERE id = ?`).run(...r);let a=await this.getProfile(e);if(!a)throw new Error("Failed to update profile");return a}async deleteProfile(e){this.stmt("DELETE FROM profiles WHERE id = ?").run(e)}async getProfile(e){let t=this.stmt("SELECT * FROM profiles WHERE id = ?").get(e);return t?this.mapProfile(t):null}async getProfiles(e){return this.stmt("SELECT * FROM profiles WHERE tenant_id = ? ORDER BY created_at ASC").all(e).map(n=>this.mapProfile(n))}async findActiveProfileByComplianceGroup(e,t){let n=this.stmt(`SELECT * FROM profiles WHERE tenant_id = ?
79
76
  AND (json_extract(profile_json, '$.complianceGroup') = ? OR json_extract(profile_json, '$.customComplianceGroup') = ?)
80
- AND json_extract(profile_json, '$.isActive') = 1 LIMIT 1`).get(e,t,t);return n?this.mapProfile(n):null}mapConsent(e){return{id:e.id,tenantId:e.tenant_id,visitorId:e.visitor_id,profileId:e.profile_id,locale:e.locale,consentJson:JSON.parse(e.consent_json),gpcDetected:e.gpc_detected===1,source:e.source,...e.age_verified!=null&&e.age_verified!==0?{ageVerified:!0}:{},...e.parental_consent_token!=null?{parentalConsentToken:e.parental_consent_token}:{},...e.tcf_string!=null?{tcfString:e.tcf_string}:{},...e.gpp_string!=null?{gppString:e.gpp_string}:{},...e.signature!=null?{signature:e.signature}:{},createdAt:e.created_at,updatedAt:e.updated_at}}static CONSENT_SUMMARY_COLS="id, tenant_id, visitor_id, profile_id, locale, gpc_detected, source, age_verified, created_at, updated_at";mapConsentSummary(e){return{id:e.id,tenantId:e.tenant_id,visitorId:e.visitor_id,profileId:e.profile_id,locale:e.locale,gpcDetected:e.gpc_detected===1,source:e.source,...e.age_verified!=null&&e.age_verified!==0?{ageVerified:!0}:{},createdAt:e.created_at,updatedAt:e.updated_at}}async createConsent(e){let t=K(),n=new Date().toISOString();this.stmt("INSERT INTO consent_records (id,tenant_id,visitor_id,profile_id,locale,consent_json,gpc_detected,source,age_verified,parental_consent_token,tcf_string,gpp_string,signature,created_at,updated_at) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)").run(t,e.tenantId,e.visitorId,e.profileId,e.locale,JSON.stringify(e.consentJson),e.gpcDetected?1:0,e.source,e.ageVerified?1:0,e.parentalConsentToken??null,e.tcfString??null,e.gppString??null,e.signature??null,n,n);let o=(0,v.randomUUID)();this.stmt("INSERT INTO consent_history (id,tenant_id,consent_record_id,visitor_id,old_json,new_json,action,created_at) VALUES (?,?,?,?,?,?,?,?)").run(o,e.tenantId,t,e.visitorId,null,JSON.stringify(e.consentJson),"created",n);let s=await this.getConsent(e.visitorId);if(!s)throw new Error("Failed to create consent");return s}async updateConsent(e,t){let n=await this.getConsent(e);if(!n)throw new Error(`Consent for visitor ${e} not found`);let o=new Date().toISOString(),s=["updated_at = ?","consent_json = ?"],r=[o,JSON.stringify(t.consentJson)];t.locale!=null&&(s.push("locale = ?"),r.push(t.locale)),t.gpcDetected!=null&&(s.push("gpc_detected = ?"),r.push(t.gpcDetected?1:0)),t.signature!=null&&(s.push("signature = ?"),r.push(t.signature)),r.push(e),this.stmt(`UPDATE consent_records SET ${s.join(", ")} WHERE visitor_id = ?`).run(...r);let a=(0,v.randomUUID)();this.stmt("INSERT INTO consent_history (id,tenant_id,consent_record_id,visitor_id,old_json,new_json,action,created_at) VALUES (?,?,?,?,?,?,?,?)").run(a,n.tenantId,n.id,e,JSON.stringify(n.consentJson),JSON.stringify(t.consentJson),"updated",o);let c=await this.getConsent(e);if(!c)throw new Error("Failed to update consent");return c}async deleteConsent(e){this.stmt("DELETE FROM consent_history WHERE visitor_id = ?").run(e),this.stmt("DELETE FROM consent_records WHERE visitor_id = ?").run(e)}async getConsent(e){let t=this.stmt("SELECT * FROM consent_records WHERE visitor_id = ?").get(e);return t?this.mapConsent(t):null}async getConsents(e){let t=["tenant_id = ?"],n=[e.tenantId];if(e.profileId&&(t.push("profile_id = ?"),n.push(e.profileId)),e.from&&(t.push("created_at >= ?"),n.push(e.from)),e.to&&(t.push("created_at <= ?"),n.push(e.to)),e.q){t.push("(visitor_id LIKE ? OR profile_id LIKE ? OR locale LIKE ? OR source LIKE ?) ESCAPE '\\'");let d=j(e.q);n.push(d,d,d,d)}let o=t.join(" AND "),s=e.page??1,r=Math.min(e.limit??50,Gn),a=(s-1)*r,c=this.stmt(`SELECT ${i.CONSENT_SUMMARY_COLS} FROM consent_records WHERE ${o} ORDER BY created_at DESC LIMIT ? OFFSET ?`).all(...n,r,a),l=this.stmt(`SELECT COUNT(*) AS total FROM consent_records WHERE ${o}`).get(...n);return{items:c.map(d=>this.mapConsentSummary(d)),total:l.total,page:s,limit:r}}async*streamConsents(e){let n=0;for(;;){let o=this.stmt("SELECT * FROM consent_records WHERE tenant_id = ? LIMIT ? OFFSET ?").all(e.tenantId,500,n);if(o.length===0)break;for(let s of o)yield this.mapConsent(s);n+=500}}async getConsentHistory(e){return this.stmt("SELECT * FROM consent_history WHERE visitor_id = ? ORDER BY created_at ASC").all(e).map(n=>({id:n.id,tenantId:n.tenant_id,consentRecordId:n.consent_record_id,visitorId:n.visitor_id,oldJson:n.old_json!=null?JSON.parse(n.old_json):null,newJson:JSON.parse(n.new_json),action:n.action,createdAt:n.created_at}))}async createNoticeShown(e){let t=(0,v.randomUUID)(),n=new Date().toISOString();return this.stmt("INSERT INTO notice_shown (id,tenant_id,visitor_id,profile_id,locale,created_at) VALUES (?,?,?,?,?,?)").run(t,e.tenantId,e.visitorId,e.profileId,e.locale,n),{id:t,tenantId:e.tenantId,visitorId:e.visitorId,profileId:e.profileId,locale:e.locale,createdAt:n}}async getNoticeShownForVisitor(e){return this.stmt("SELECT * FROM notice_shown WHERE visitor_id = ? ORDER BY created_at DESC").all(e).map(n=>({id:n.id,tenantId:n.tenant_id,visitorId:n.visitor_id,profileId:n.profile_id,locale:n.locale,createdAt:n.created_at}))}mapVisitor(e){return{id:e.id,tenantId:e.tenant_id,visitorId:e.visitor_id,firstSeen:e.first_seen,lastSeen:e.last_seen,...e.country!=null?{country:e.country}:{},...e.region!=null?{region:e.region}:{},...e.city!=null?{city:e.city}:{},...e.ip_hash!=null?{ipHash:e.ip_hash}:{},...e.user_agent_hash!=null?{userAgentHash:e.user_agent_hash}:{}}}async createVisitor(e){let t=q(),n=new Date().toISOString();this.stmt("INSERT INTO visitors (id,tenant_id,visitor_id,country,region,city,ip_hash,user_agent_hash,first_seen,last_seen) VALUES (?,?,?,?,?,?,?,?,?,?)").run(t,e.tenantId,e.visitorId,e.country??null,e.region??null,e.city??null,e.ipHash??null,e.userAgentHash??null,n,n);let o=await this.getVisitor(e.visitorId);if(!o)throw new Error("Failed to create visitor");return o}async updateVisitor(e,t){let n=new Date().toISOString(),o=["last_seen = ?"],s=[t.lastSeen??n];t.country!=null&&(o.push("country = ?"),s.push(t.country)),t.region!=null&&(o.push("region = ?"),s.push(t.region)),t.city!=null&&(o.push("city = ?"),s.push(t.city)),s.push(e),this.stmt(`UPDATE visitors SET ${o.join(", ")} WHERE visitor_id = ?`).run(...s);let r=await this.getVisitor(e);if(!r)throw new Error(`Visitor ${e} not found`);return r}async deleteVisitor(e){this.stmt("DELETE FROM visitors WHERE visitor_id = ?").run(e)}async getVisitor(e){let t=this.stmt("SELECT * FROM visitors WHERE visitor_id = ?").get(e);return t?this.mapVisitor(t):null}async getVisitors(e){let t=["tenant_id = ?"],n=[e.tenantId];if(e.from&&(t.push("first_seen >= ?"),n.push(e.from)),e.to&&(t.push("first_seen <= ?"),n.push(e.to)),e.q){t.push("(visitor_id LIKE ? OR country LIKE ?) ESCAPE '\\'");let d=j(e.q);n.push(d,d)}let o=t.join(" AND "),s=e.page??1,r=Math.min(e.limit??50,Gn),a=(s-1)*r,c=this.stmt(`SELECT * FROM visitors WHERE ${o} ORDER BY last_seen DESC LIMIT ? OFFSET ?`).all(...n,r,a),l=this.stmt(`SELECT COUNT(*) AS total FROM visitors WHERE ${o}`).get(...n);return{items:c.map(d=>this.mapVisitor(d)),total:l.total,page:s,limit:r}}mapUser(e){let t=e.allowed_tenants?JSON.parse(e.allowed_tenants):[];return{id:e.id,tenantId:e.tenant_id,name:e.name,email:e.email,passwordHash:e.password_hash,isActive:e.is_active===1,totpEnabled:e.totp_enabled===1,...e.totp_secret!=null?{totpSecret:e.totp_secret}:{},allowedTenants:t,createdAt:e.created_at,updatedAt:e.updated_at}}async createUser(e){let t=(0,v.randomUUID)(),n=new Date().toISOString(),o=e.allowedTenants?.length?JSON.stringify(e.allowedTenants):null;this.stmt("INSERT INTO users (id,tenant_id,name,email,password_hash,allowed_tenants,created_at,updated_at) VALUES (?,?,?,?,?,?,?,?)").run(t,e.tenantId,e.name,e.email,e.passwordHash,o,n,n);let s=await this.getUserByEmail(e.email);if(!s)throw new Error("Failed to create user");return s}async updateUser(e,t){let n=new Date().toISOString(),o=["updated_at = ?"],s=[n];t.name!=null&&(o.push("name = ?"),s.push(t.name)),t.email!=null&&(o.push("email = ?"),s.push(t.email)),t.passwordHash!=null&&(o.push("password_hash = ?"),s.push(t.passwordHash)),t.isActive!=null&&(o.push("is_active = ?"),s.push(t.isActive?1:0)),"totpSecret"in t&&(o.push("totp_secret = ?"),s.push(t.totpSecret??null)),t.totpEnabled!=null&&(o.push("totp_enabled = ?"),s.push(t.totpEnabled?1:0)),"allowedTenants"in t&&(o.push("allowed_tenants = ?"),s.push(t.allowedTenants?.length?JSON.stringify(t.allowedTenants):null)),s.push(e),this.stmt(`UPDATE users SET ${o.join(", ")} WHERE id = ?`).run(...s);let r=this.stmt("SELECT * FROM users WHERE id = ?").get(e);if(!r)throw new Error(`User ${e} not found`);return this.mapUser(r)}async deleteUser(e){this.stmt("DELETE FROM user_roles WHERE user_id = ?").run(e),this.stmt("DELETE FROM users WHERE id = ?").run(e)}async getUserById(e){let t=this.stmt("SELECT * FROM users WHERE id = ?").get(e);return t?this.mapUser(t):null}async getUserByEmail(e){let t=this.stmt("SELECT * FROM users WHERE email = ?").get(e);return t?this.mapUser(t):null}async getUsers(e){return this.stmt("SELECT * FROM users WHERE tenant_id = ? ORDER BY created_at ASC").all(e).map(n=>this.mapUser(n))}async countUsers(e){return(e?this.stmt("SELECT COUNT(*) as n FROM users WHERE tenant_id = ?").get(e):this.stmt("SELECT COUNT(*) as n FROM users").get())?.n??0}async getRoles(e){return this.stmt("SELECT * FROM roles WHERE tenant_id = ?").all(e).map(n=>({id:n.id,tenantId:n.tenant_id,name:n.name,...n.description!=null?{description:n.description}:{}}))}async createRole(e){let t=(0,v.randomUUID)();this.stmt("INSERT INTO roles (id,tenant_id,name,description) VALUES (?,?,?,?)").run(t,e.tenantId,e.name,e.description??null);let n=this.stmt("SELECT * FROM roles WHERE id = ?").get(t);if(!n)throw new Error("Failed to create role");return{id:n.id,tenantId:n.tenant_id,name:n.name,...n.description!=null?{description:n.description}:{}}}async updateRole(e,t){let n=[],o=[];t.name!=null&&(n.push("name = ?"),o.push(t.name)),t.description!=null&&(n.push("description = ?"),o.push(t.description)),n.length>0&&(o.push(e),this.stmt(`UPDATE roles SET ${n.join(", ")} WHERE id = ?`).run(...o));let s=this.stmt("SELECT * FROM roles WHERE id = ?").get(e);if(!s)throw new Error(`Role ${e} not found`);return{id:s.id,tenantId:s.tenant_id,name:s.name,...s.description!=null?{description:s.description}:{}}}async deleteRole(e){this.stmt("DELETE FROM role_permissions WHERE role_id = ?").run(e),this.stmt("DELETE FROM user_roles WHERE role_id = ?").run(e),this.stmt("DELETE FROM roles WHERE id = ?").run(e)}async getAllPermissions(){return this.stmt("SELECT * FROM permissions ORDER BY name ASC").all().map(t=>({id:t.id,name:t.name,...t.description!=null?{description:t.description}:{}}))}async assignPermissionToRole(e,t){this.stmt("INSERT OR IGNORE INTO role_permissions (role_id,permission_id) VALUES (?,?)").run(e,t)}async revokePermissionFromRole(e,t){this.stmt("DELETE FROM role_permissions WHERE role_id = ? AND permission_id = ?").run(e,t)}async getPermissionsForRole(e){return this.stmt("SELECT p.* FROM permissions p JOIN role_permissions rp ON rp.permission_id = p.id WHERE rp.role_id = ?").all(e).map(n=>({id:n.id,name:n.name,...n.description!=null?{description:n.description}:{}}))}async getUserRoles(e,t){return(t?this.stmt("SELECT r.* FROM roles r JOIN user_roles ur ON ur.role_id = r.id WHERE ur.user_id = ? AND ur.tenant_id = ?").all(e,t):this.stmt("SELECT r.* FROM roles r JOIN user_roles ur ON ur.role_id = r.id WHERE ur.user_id = ?").all(e)).map(o=>({id:o.id,tenantId:o.tenant_id,name:o.name,...o.description!=null?{description:o.description}:{}}))}async assignRole(e,t,n="default"){this.stmt("INSERT OR IGNORE INTO user_roles (user_id, role_id, tenant_id) VALUES (?,?,?)").run(e,t,n)}async revokeRole(e,t,n){n?this.stmt("DELETE FROM user_roles WHERE user_id = ? AND role_id = ? AND tenant_id = ?").run(e,t,n):this.stmt("DELETE FROM user_roles WHERE user_id = ? AND role_id = ?").run(e,t)}async createLog(e){let t=(0,v.randomUUID)(),n=new Date().toISOString();this.stmt("INSERT INTO audit_logs (id,tenant_id,user_id,action,resource_type,resource_id,old_data,new_data,created_at) VALUES (?,?,?,?,?,?,?,?,?)").run(t,e.tenantId,e.userId??null,e.action,e.resourceType,e.resourceId??null,e.oldData!=null?JSON.stringify(e.oldData):null,e.newData!=null?JSON.stringify(e.newData):null,n)}async getLogs(e){let t=["tenant_id = ?"],n=[e.tenantId];if(e.action&&(t.push("action = ?"),n.push(e.action)),e.resourceType&&(t.push("resource_type = ?"),n.push(e.resourceType)),e.from&&(t.push("created_at >= ?"),n.push(e.from)),e.to&&(t.push("created_at <= ?"),n.push(e.to)),e.q){t.push("(action LIKE ? OR resource_type LIKE ? OR resource_id LIKE ? OR user_id LIKE ?) ESCAPE '\\'");let d=j(e.q);n.push(d,d,d,d)}let o=t.join(" AND "),s=e.page??1,r=Math.min(e.limit??50,Gn),a=(s-1)*r,c=this.stmt(`SELECT ${i.AUDIT_SUMMARY_COLS} FROM audit_logs WHERE ${o} ORDER BY created_at DESC LIMIT ? OFFSET ?`).all(...n,r,a),l=this.stmt(`SELECT COUNT(*) AS total FROM audit_logs WHERE ${o}`).get(...n);return{items:c.map(d=>this.mapAuditSummary(d)),total:l.total,page:s,limit:r}}async getAuditLogById(e){let t=this.stmt("SELECT * FROM audit_logs WHERE id = ?").get(e);return t?this.mapAuditLog(t):null}static AUDIT_SUMMARY_COLS="id, tenant_id, user_id, action, resource_type, resource_id, created_at";mapAuditSummary(e){return{id:e.id,tenantId:e.tenant_id,action:e.action,resourceType:e.resource_type,...e.user_id!=null?{userId:e.user_id}:{},...e.resource_id!=null?{resourceId:e.resource_id}:{},createdAt:e.created_at}}mapAuditLog(e){return{id:e.id,tenantId:e.tenant_id,action:e.action,resourceType:e.resource_type,createdAt:e.created_at,...e.user_id!=null?{userId:e.user_id}:{},...e.resource_id!=null?{resourceId:e.resource_id}:{},...e.old_data!=null?{oldData:JSON.parse(e.old_data)}:{},...e.new_data!=null?{newData:JSON.parse(e.new_data)}:{}}}async*streamAuditLogs(e){let t=["tenant_id = ?"],n=[e.tenantId];e.action&&(t.push("action = ?"),n.push(e.action)),e.from&&(t.push("created_at >= ?"),n.push(e.from)),e.to&&(t.push("created_at <= ?"),n.push(e.to));let o=500,s=0;for(;;){let r=this.stmt(`SELECT * FROM audit_logs WHERE ${t.join(" AND ")} ORDER BY created_at DESC LIMIT ? OFFSET ?`).all(...n,o,s);if(r.length===0)break;for(let a of r)yield this.mapAuditLog(a);s+=o}}async getOverviewStats(e){let t=this.stmt("SELECT COUNT(*) as n FROM consent_records WHERE tenant_id = ?").get(e),n=this.stmt("SELECT COUNT(*) as n FROM consent_records WHERE tenant_id = ? AND gpc_detected = 1").get(e),o=this.stmt("SELECT COUNT(*) as n FROM visitors WHERE tenant_id = ?").get(e),s=t?.n??0,r=this.stmt("SELECT consent_json FROM consent_records WHERE tenant_id = ? ORDER BY created_at DESC LIMIT 500").all(e),a=0,c=0;for(let d of r){let u=Object.values(JSON.parse(d.consent_json)),m=u.length>0?u.filter(h=>h==="granted").length/u.length:0;m>=.8?a++:m<=.2&&c++}let l=r.length||1;return{totalConsents:s,gpcDetectedCount:n?.n??0,totalVisitors:o?.n??0,acceptedPct:Math.round(a/l*100),rejectedPct:Math.round(c/l*100)}}async getCategoryStats(e){let t=this.stmt("SELECT consent_json FROM consent_records WHERE tenant_id = ? LIMIT 5000").all(e),n={};for(let o of t){let s=JSON.parse(o.consent_json);for(let[r,a]of Object.entries(s))n[r]||(n[r]={granted:0,denied:0,objected:0}),a==="granted"?n[r].granted++:a==="denied"?n[r].denied++:a==="objected"&&n[r].objected++}return n}async getTimeline(e,t=30){return this.stmt("SELECT date(created_at) as date, COUNT(*) as count FROM consent_records WHERE tenant_id = ? AND created_at >= date('now', ?) GROUP BY date(created_at) ORDER BY date ASC").all(e,`-${t} days`).map(o=>({date:o.date,count:o.count}))}async getCountries(e){return this.stmt("SELECT v.country, COUNT(*) as count FROM consent_records cr JOIN visitors v ON v.visitor_id = cr.visitor_id WHERE cr.tenant_id = ? AND v.country IS NOT NULL GROUP BY v.country ORDER BY count DESC LIMIT 50").all(e).map(n=>({country:n.country,count:n.count}))}async getGpcStats(e){let t=this.stmt("SELECT COUNT(*) as n FROM consent_records WHERE tenant_id = ?").get(e),n=this.stmt("SELECT COUNT(*) as n FROM consent_records WHERE tenant_id = ? AND gpc_detected = 1").get(e),o=t?.n??0,s=n?.n??0;return{detected:s,total:o,rate:o>0?Math.round(s/o*100):0}}async getTenants(){return this.stmt("SELECT * FROM tenants ORDER BY name ASC").all().map(t=>({id:t.id,name:t.name,slug:t.slug,createdAt:t.created_at,updatedAt:t.updated_at}))}async createTenant(e){let t=(0,v.randomUUID)(),n=new Date().toISOString();this.stmt("INSERT INTO tenants (id,name,slug,created_at,updated_at) VALUES (?,?,?,?,?)").run(t,e.name,e.slug,n,n);let o=this.stmt("SELECT * FROM tenants WHERE id = ?").get(t);if(!o)throw new Error("Failed to create tenant");return{id:o.id,name:o.name,slug:o.slug,createdAt:o.created_at,updatedAt:o.updated_at}}async updateTenant(e,t){let n=new Date().toISOString(),o=["updated_at = ?"],s=[n];t.name!=null&&(o.push("name = ?"),s.push(t.name)),t.slug!=null&&(o.push("slug = ?"),s.push(t.slug)),s.push(e),this.stmt(`UPDATE tenants SET ${o.join(", ")} WHERE id = ?`).run(...s);let r=this.stmt("SELECT * FROM tenants WHERE id = ?").get(e);if(!r)throw new Error(`Tenant ${e} not found`);return{id:r.id,name:r.name,slug:r.slug,createdAt:r.created_at,updatedAt:r.updated_at}}async deleteTenant(e){this.stmt("DELETE FROM tenants WHERE id = ?").run(e)}async getSettings(e){let t=this.stmt("SELECT allowed_origins_json, admin_allowed_origins_json, setup_completed, profiles_seeded, tcf_confirmation_json, gpp_confirmation_json FROM tenant_settings WHERE tenant_id = ?").get(e);return t?{allowedOrigins:JSON.parse(t.allowed_origins_json),adminAllowedOrigins:JSON.parse(t.admin_allowed_origins_json),setupCompleted:!!t.setup_completed,profilesSeeded:!!t.profiles_seeded,tcfConfirmation:t.tcf_confirmation_json?JSON.parse(t.tcf_confirmation_json):void 0,gppConfirmation:t.gpp_confirmation_json?JSON.parse(t.gpp_confirmation_json):void 0}:{}}async updateSettings(e,t){let o={...await this.getSettings(e),...t};return this.stmt(`INSERT INTO tenant_settings (tenant_id, allowed_origins_json, admin_allowed_origins_json, setup_completed, profiles_seeded, tcf_confirmation_json, gpp_confirmation_json, updated_at) VALUES (?,?,?,?,?,?,?,?)
81
- ON CONFLICT(tenant_id) DO UPDATE SET allowed_origins_json = excluded.allowed_origins_json, admin_allowed_origins_json = excluded.admin_allowed_origins_json, setup_completed = excluded.setup_completed, profiles_seeded = excluded.profiles_seeded, tcf_confirmation_json = excluded.tcf_confirmation_json, gpp_confirmation_json = excluded.gpp_confirmation_json, updated_at = excluded.updated_at`).run(e,JSON.stringify(o.allowedOrigins??[]),JSON.stringify(o.adminAllowedOrigins??[]),o.setupCompleted?1:0,o.profilesSeeded?1:0,o.tcfConfirmation?JSON.stringify(o.tcfConfirmation):null,o.gppConfirmation?JSON.stringify(o.gppConfirmation):null,new Date().toISOString()),this.getSettings(e)}async purgeExpiredConsents(e){let t=new Date(Date.now()-e*864e5).toISOString(),n=this.stmt("SELECT visitor_id FROM consent_records WHERE created_at < ?").all(t);for(let{visitor_id:o}of n)this.stmt("DELETE FROM consent_history WHERE visitor_id = ?").run(o),this.stmt("DELETE FROM consent_records WHERE visitor_id = ?").run(o);return n.length}mapApiKey(e){return{id:e.id,tenantId:e.tenant_id,keyHash:e.key_hash,name:e.name,isActive:e.is_active===1,...e.created_by!==null?{createdBy:e.created_by}:{},...e.expire_by!==null?{expireBy:e.expire_by}:{},createdAt:e.created_at,...e.updated_at!==null?{updatedAt:e.updated_at}:{}}}async createApiKey(e){let t=(0,v.randomUUID)(),n=new Date().toISOString();this.stmt("INSERT INTO api_keys (id,tenant_id,key_hash,name,created_by,expire_by,created_at,updated_at) VALUES (?,?,?,?,?,?,?,?)").run(t,e.tenantId,e.keyHash,e.name,e.createdBy??null,e.expireBy??null,n,n);let o=this.stmt("SELECT * FROM api_keys WHERE id = ?").get(t);if(!o)throw new Error("Failed to create API key");return this.mapApiKey(o)}async getApiKeyByHash(e){let t=this.stmt("SELECT * FROM api_keys WHERE key_hash = ? AND is_active = 1").get(e);return t?this.mapApiKey(t):null}async revokeApiKey(e){this.stmt("UPDATE api_keys SET is_active = 0, updated_at = ? WHERE id = ?").run(new Date().toISOString(),e)}async reactivateApiKey(e){let t=new Date().toISOString();this.stmt("UPDATE api_keys SET is_active = 1, updated_at = ?, expire_by = CASE WHEN expire_by <= ? THEN NULL ELSE expire_by END WHERE id = ?").run(t,t,e)}async deleteApiKey(e){this.stmt("DELETE FROM api_keys WHERE id = ?").run(e)}async getApiKeys(e){return this.stmt("SELECT * FROM api_keys WHERE tenant_id = ? ORDER BY created_at DESC").all(e).map(n=>this.mapApiKey(n))}mapConsentTemplate(e){return{id:e.id,tenantId:e.tenant_id,name:e.name,cookies:JSON.parse(e.cookies_json),categories:JSON.parse(e.categories_json),createdAt:e.created_at,updatedAt:e.updated_at}}async createConsentTemplate(e){let t=Y(),n=new Date().toISOString();return this.stmt("INSERT INTO consent_templates (id,tenant_id,name,cookies_json,categories_json,created_at,updated_at) VALUES (?,?,?,?,?,?,?)").run(t,e.tenantId,e.name,JSON.stringify(e.cookies),JSON.stringify(e.categories),n,n),this.mapConsentTemplate(this.stmt("SELECT * FROM consent_templates WHERE id = ?").get(t))}async updateConsentTemplate(e,t){let n=new Date().toISOString();t.name!==void 0&&this.stmt("UPDATE consent_templates SET name = ?, updated_at = ? WHERE id = ?").run(t.name,n,e),t.cookies!==void 0&&this.stmt("UPDATE consent_templates SET cookies_json = ?, updated_at = ? WHERE id = ?").run(JSON.stringify(t.cookies),n,e),t.categories!==void 0&&this.stmt("UPDATE consent_templates SET categories_json = ?, updated_at = ? WHERE id = ?").run(JSON.stringify(t.categories),n,e);let o=this.stmt("SELECT * FROM consent_templates WHERE id = ?").get(e);if(!o)throw new Error("Consent template not found");return this.mapConsentTemplate(o)}async deleteConsentTemplate(e){this.stmt("DELETE FROM consent_templates WHERE id = ?").run(e)}async getConsentTemplate(e){let t=this.stmt("SELECT * FROM consent_templates WHERE id = ?").get(e);return t?this.mapConsentTemplate(t):null}async getConsentTemplates(e){return this.stmt("SELECT * FROM consent_templates WHERE tenant_id = ? ORDER BY name ASC").all(e).map(n=>this.mapConsentTemplate(n))}async copyConsentTemplate(e,t){let n=await this.getConsentTemplate(e);if(!n)throw new Error("Consent template not found");return this.createConsentTemplate({tenantId:n.tenantId,name:t,cookies:n.cookies,categories:n.categories})}mapUITemplate(e){let t=JSON.parse(e.settings_json);return{id:e.id,tenantId:e.tenant_id,name:e.name,...t,createdAt:e.created_at,updatedAt:e.updated_at}}async createUITemplate(e){let t=Q(),n=new Date().toISOString(),{tenantId:o,name:s,...r}=e;return this.stmt("INSERT INTO ui_templates (id,tenant_id,name,settings_json,created_at,updated_at) VALUES (?,?,?,?,?,?)").run(t,o,s,JSON.stringify(r),n,n),this.mapUITemplate(this.stmt("SELECT * FROM ui_templates WHERE id = ?").get(t))}async updateUITemplate(e,t){let n=new Date().toISOString(),o=this.stmt("SELECT * FROM ui_templates WHERE id = ?").get(e);if(!o)throw new Error("UI template not found");t.name!==void 0&&this.stmt("UPDATE ui_templates SET name = ?, updated_at = ? WHERE id = ?").run(t.name,n,e);let{name:s,...r}=t;if(Object.keys(r).length>0){let c={...JSON.parse(o.settings_json),...r};this.stmt("UPDATE ui_templates SET settings_json = ?, updated_at = ? WHERE id = ?").run(JSON.stringify(c),n,e)}return this.mapUITemplate(this.stmt("SELECT * FROM ui_templates WHERE id = ?").get(e))}async deleteUITemplate(e){this.stmt("DELETE FROM ui_templates WHERE id = ?").run(e)}async getUITemplate(e){let t=this.stmt("SELECT * FROM ui_templates WHERE id = ?").get(e);return t?this.mapUITemplate(t):null}async getUITemplates(e){return this.stmt("SELECT * FROM ui_templates WHERE tenant_id = ? ORDER BY name ASC").all(e).map(n=>this.mapUITemplate(n))}async copyUITemplate(e,t){let n=await this.getUITemplate(e);if(!n)throw new Error("UI template not found");let{tenantId:o,mainBanner:s,gpcBanner:r,preferenceModal:a}=n;return this.createUITemplate({tenantId:o,name:t,mainBanner:s,gpcBanner:r,preferenceModal:a})}mapProfileSummary(e){return{id:e.id,name:e.name,defaultLocale:e.default_locale,complianceGroup:e.compliance_group??null,customComplianceGroup:e.custom_compliance_group??null,isActive:e.is_active===1,consentTemplateName:e.consent_template_name,uiTemplateName:e.ui_template_name,createdAt:e.created_at,updatedAt:e.updated_at}}PROFILE_SUMMARY_SQL=`
77
+ AND json_extract(profile_json, '$.isActive') = 1 LIMIT 1`).get(e,t,t);return n?this.mapProfile(n):null}mapConsent(e){return{id:e.id,tenantId:e.tenant_id,visitorId:e.visitor_id,profileId:e.profile_id,...e.profile_version!=null?{profileVersion:e.profile_version}:{},locale:e.locale,consentJson:JSON.parse(e.consent_json),gpcDetected:e.gpc_detected===1,source:e.source,...e.age_verified!=null&&e.age_verified!==0?{ageVerified:!0}:{},...e.parental_consent_token!=null?{parentalConsentToken:e.parental_consent_token}:{},...e.tcf_string!=null?{tcfString:e.tcf_string}:{},...e.gpp_string!=null?{gppString:e.gpp_string}:{},...e.signature!=null?{signature:e.signature}:{},createdAt:e.created_at,updatedAt:e.updated_at}}static CONSENT_SUMMARY_COLS="id, tenant_id, visitor_id, profile_id, locale, gpc_detected, source, age_verified, created_at, updated_at";mapConsentSummary(e){return{id:e.id,tenantId:e.tenant_id,visitorId:e.visitor_id,profileId:e.profile_id,locale:e.locale,gpcDetected:e.gpc_detected===1,source:e.source,...e.age_verified!=null&&e.age_verified!==0?{ageVerified:!0}:{},createdAt:e.created_at,updatedAt:e.updated_at}}async createConsent(e){let t=Y(),n=new Date().toISOString();this.stmt("INSERT INTO consent_records (id,tenant_id,visitor_id,profile_id,profile_version,locale,consent_json,gpc_detected,source,age_verified,parental_consent_token,tcf_string,gpp_string,signature,created_at,updated_at) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)").run(t,e.tenantId,e.visitorId,e.profileId,e.profileVersion??null,e.locale,JSON.stringify(e.consentJson),e.gpcDetected?1:0,e.source,e.ageVerified?1:0,e.parentalConsentToken??null,e.tcfString??null,e.gppString??null,e.signature??null,n,n);let o=(0,C.randomUUID)();this.stmt("INSERT INTO consent_history (id,tenant_id,consent_record_id,visitor_id,profile_version,old_json,new_json,action,created_at) VALUES (?,?,?,?,?,?,?,?,?)").run(o,e.tenantId,t,e.visitorId,e.profileVersion??null,null,JSON.stringify(e.consentJson),"created",n);let s=await this.getConsent(e.visitorId);if(!s)throw new Error("Failed to create consent");return s}async updateConsent(e,t){let n=await this.getConsent(e);if(!n)throw new Error(`Consent for visitor ${e} not found`);let o=new Date().toISOString(),s=["updated_at = ?","consent_json = ?"],r=[o,JSON.stringify(t.consentJson)];t.profileVersion!=null&&(s.push("profile_version = ?"),r.push(t.profileVersion)),t.locale!=null&&(s.push("locale = ?"),r.push(t.locale)),t.gpcDetected!=null&&(s.push("gpc_detected = ?"),r.push(t.gpcDetected?1:0)),t.signature!=null&&(s.push("signature = ?"),r.push(t.signature)),r.push(e),this.stmt(`UPDATE consent_records SET ${s.join(", ")} WHERE visitor_id = ?`).run(...r);let a=(0,C.randomUUID)();this.stmt("INSERT INTO consent_history (id,tenant_id,consent_record_id,visitor_id,profile_version,old_json,new_json,action,created_at) VALUES (?,?,?,?,?,?,?,?,?)").run(a,n.tenantId,n.id,e,t.profileVersion??n.profileVersion??null,JSON.stringify(n.consentJson),JSON.stringify(t.consentJson),"updated",o);let c=await this.getConsent(e);if(!c)throw new Error("Failed to update consent");return c}async deleteConsent(e){this.stmt("DELETE FROM consent_history WHERE visitor_id = ?").run(e),this.stmt("DELETE FROM consent_records WHERE visitor_id = ?").run(e)}async getConsent(e){let t=this.stmt("SELECT * FROM consent_records WHERE visitor_id = ?").get(e);return t?this.mapConsent(t):null}async getConsents(e){let t=["tenant_id = ?"],n=[e.tenantId];if(e.profileId&&(t.push("profile_id = ?"),n.push(e.profileId)),e.from&&(t.push("created_at >= ?"),n.push(e.from)),e.to&&(t.push("created_at <= ?"),n.push(e.to)),e.q){t.push("(visitor_id LIKE ? OR profile_id LIKE ? OR locale LIKE ? OR source LIKE ?) ESCAPE '\\'");let d=j(e.q);n.push(d,d,d,d)}let o=t.join(" AND "),s=e.page??1,r=Math.min(e.limit??50,Yn),a=(s-1)*r,c=this.stmt(`SELECT ${i.CONSENT_SUMMARY_COLS} FROM consent_records WHERE ${o} ORDER BY created_at DESC LIMIT ? OFFSET ?`).all(...n,r,a),l=this.stmt(`SELECT COUNT(*) AS total FROM consent_records WHERE ${o}`).get(...n);return{items:c.map(d=>this.mapConsentSummary(d)),total:l.total,page:s,limit:r}}async*streamConsents(e){let n=0;for(;;){let o=this.stmt("SELECT * FROM consent_records WHERE tenant_id = ? LIMIT ? OFFSET ?").all(e.tenantId,500,n);if(o.length===0)break;for(let s of o)yield this.mapConsent(s);n+=500}}async getConsentHistory(e){return this.stmt("SELECT * FROM consent_history WHERE visitor_id = ? ORDER BY created_at ASC").all(e).map(n=>({id:n.id,tenantId:n.tenant_id,consentRecordId:n.consent_record_id,visitorId:n.visitor_id,...n.profile_version!=null?{profileVersion:n.profile_version}:{},oldJson:n.old_json!=null?JSON.parse(n.old_json):null,newJson:JSON.parse(n.new_json),action:n.action,createdAt:n.created_at}))}async createNoticeShown(e){let t=(0,C.randomUUID)(),n=new Date().toISOString();return this.stmt("INSERT INTO notice_shown (id,tenant_id,visitor_id,profile_id,locale,created_at) VALUES (?,?,?,?,?,?)").run(t,e.tenantId,e.visitorId,e.profileId,e.locale,n),{id:t,tenantId:e.tenantId,visitorId:e.visitorId,profileId:e.profileId,locale:e.locale,createdAt:n}}async getNoticeShownForVisitor(e){return this.stmt("SELECT * FROM notice_shown WHERE visitor_id = ? ORDER BY created_at DESC").all(e).map(n=>({id:n.id,tenantId:n.tenant_id,visitorId:n.visitor_id,profileId:n.profile_id,locale:n.locale,createdAt:n.created_at}))}mapVisitor(e){return{id:e.id,tenantId:e.tenant_id,visitorId:e.visitor_id,firstSeen:e.first_seen,lastSeen:e.last_seen,...e.country!=null?{country:e.country}:{},...e.region!=null?{region:e.region}:{},...e.city!=null?{city:e.city}:{},...e.ip_hash!=null?{ipHash:e.ip_hash}:{},...e.user_agent_hash!=null?{userAgentHash:e.user_agent_hash}:{}}}async createVisitor(e){let t=q(),n=new Date().toISOString();this.stmt("INSERT INTO visitors (id,tenant_id,visitor_id,country,region,city,ip_hash,user_agent_hash,first_seen,last_seen) VALUES (?,?,?,?,?,?,?,?,?,?)").run(t,e.tenantId,e.visitorId,e.country??null,e.region??null,e.city??null,e.ipHash??null,e.userAgentHash??null,n,n);let o=await this.getVisitor(e.visitorId);if(!o)throw new Error("Failed to create visitor");return o}async updateVisitor(e,t){let n=new Date().toISOString(),o=["last_seen = ?"],s=[t.lastSeen??n];t.country!=null&&(o.push("country = ?"),s.push(t.country)),t.region!=null&&(o.push("region = ?"),s.push(t.region)),t.city!=null&&(o.push("city = ?"),s.push(t.city)),s.push(e),this.stmt(`UPDATE visitors SET ${o.join(", ")} WHERE visitor_id = ?`).run(...s);let r=await this.getVisitor(e);if(!r)throw new Error(`Visitor ${e} not found`);return r}async deleteVisitor(e){this.stmt("DELETE FROM visitors WHERE visitor_id = ?").run(e)}async getVisitor(e){let t=this.stmt("SELECT * FROM visitors WHERE visitor_id = ?").get(e);return t?this.mapVisitor(t):null}async getVisitors(e){let t=["tenant_id = ?"],n=[e.tenantId];if(e.from&&(t.push("first_seen >= ?"),n.push(e.from)),e.to&&(t.push("first_seen <= ?"),n.push(e.to)),e.q){t.push("(visitor_id LIKE ? OR country LIKE ?) ESCAPE '\\'");let d=j(e.q);n.push(d,d)}let o=t.join(" AND "),s=e.page??1,r=Math.min(e.limit??50,Yn),a=(s-1)*r,c=this.stmt(`SELECT * FROM visitors WHERE ${o} ORDER BY last_seen DESC LIMIT ? OFFSET ?`).all(...n,r,a),l=this.stmt(`SELECT COUNT(*) AS total FROM visitors WHERE ${o}`).get(...n);return{items:c.map(d=>this.mapVisitor(d)),total:l.total,page:s,limit:r}}mapUser(e){let t=e.allowed_tenants?JSON.parse(e.allowed_tenants):[];return{id:e.id,tenantId:e.tenant_id,name:e.name,email:e.email,passwordHash:e.password_hash,isActive:e.is_active===1,totpEnabled:e.totp_enabled===1,...e.totp_secret!=null?{totpSecret:e.totp_secret}:{},allowedTenants:t,createdAt:e.created_at,updatedAt:e.updated_at}}async createUser(e){let t=(0,C.randomUUID)(),n=new Date().toISOString(),o=e.allowedTenants?.length?JSON.stringify(e.allowedTenants):null;this.stmt("INSERT INTO users (id,tenant_id,name,email,password_hash,allowed_tenants,created_at,updated_at) VALUES (?,?,?,?,?,?,?,?)").run(t,e.tenantId,e.name,e.email,e.passwordHash,o,n,n);let s=await this.getUserByEmail(e.email);if(!s)throw new Error("Failed to create user");return s}async updateUser(e,t){let n=new Date().toISOString(),o=["updated_at = ?"],s=[n];t.name!=null&&(o.push("name = ?"),s.push(t.name)),t.email!=null&&(o.push("email = ?"),s.push(t.email)),t.passwordHash!=null&&(o.push("password_hash = ?"),s.push(t.passwordHash)),t.isActive!=null&&(o.push("is_active = ?"),s.push(t.isActive?1:0)),"totpSecret"in t&&(o.push("totp_secret = ?"),s.push(t.totpSecret??null)),t.totpEnabled!=null&&(o.push("totp_enabled = ?"),s.push(t.totpEnabled?1:0)),"allowedTenants"in t&&(o.push("allowed_tenants = ?"),s.push(t.allowedTenants?.length?JSON.stringify(t.allowedTenants):null)),s.push(e),this.stmt(`UPDATE users SET ${o.join(", ")} WHERE id = ?`).run(...s);let r=this.stmt("SELECT * FROM users WHERE id = ?").get(e);if(!r)throw new Error(`User ${e} not found`);return this.mapUser(r)}async deleteUser(e){this.stmt("DELETE FROM user_roles WHERE user_id = ?").run(e),this.stmt("DELETE FROM users WHERE id = ?").run(e)}async getUserById(e){let t=this.stmt("SELECT * FROM users WHERE id = ?").get(e);return t?this.mapUser(t):null}async getUserByEmail(e){let t=this.stmt("SELECT * FROM users WHERE email = ?").get(e);return t?this.mapUser(t):null}async getUsers(e){return this.stmt("SELECT * FROM users WHERE tenant_id = ? ORDER BY created_at ASC").all(e).map(n=>this.mapUser(n))}async countUsers(e){return(e?this.stmt("SELECT COUNT(*) as n FROM users WHERE tenant_id = ?").get(e):this.stmt("SELECT COUNT(*) as n FROM users").get())?.n??0}async getRoles(e){return this.stmt("SELECT * FROM roles WHERE tenant_id = ?").all(e).map(n=>({id:n.id,tenantId:n.tenant_id,name:n.name,...n.description!=null?{description:n.description}:{}}))}async createRole(e){let t=(0,C.randomUUID)();this.stmt("INSERT INTO roles (id,tenant_id,name,description) VALUES (?,?,?,?)").run(t,e.tenantId,e.name,e.description??null);let n=this.stmt("SELECT * FROM roles WHERE id = ?").get(t);if(!n)throw new Error("Failed to create role");return{id:n.id,tenantId:n.tenant_id,name:n.name,...n.description!=null?{description:n.description}:{}}}async updateRole(e,t){let n=[],o=[];t.name!=null&&(n.push("name = ?"),o.push(t.name)),t.description!=null&&(n.push("description = ?"),o.push(t.description)),n.length>0&&(o.push(e),this.stmt(`UPDATE roles SET ${n.join(", ")} WHERE id = ?`).run(...o));let s=this.stmt("SELECT * FROM roles WHERE id = ?").get(e);if(!s)throw new Error(`Role ${e} not found`);return{id:s.id,tenantId:s.tenant_id,name:s.name,...s.description!=null?{description:s.description}:{}}}async deleteRole(e){this.stmt("DELETE FROM role_permissions WHERE role_id = ?").run(e),this.stmt("DELETE FROM user_roles WHERE role_id = ?").run(e),this.stmt("DELETE FROM roles WHERE id = ?").run(e)}async getAllPermissions(){return this.stmt("SELECT * FROM permissions ORDER BY name ASC").all().map(t=>({id:t.id,name:t.name,...t.description!=null?{description:t.description}:{}}))}async assignPermissionToRole(e,t){this.stmt("INSERT OR IGNORE INTO role_permissions (role_id,permission_id) VALUES (?,?)").run(e,t)}async revokePermissionFromRole(e,t){this.stmt("DELETE FROM role_permissions WHERE role_id = ? AND permission_id = ?").run(e,t)}async getPermissionsForRole(e){return this.stmt("SELECT p.* FROM permissions p JOIN role_permissions rp ON rp.permission_id = p.id WHERE rp.role_id = ?").all(e).map(n=>({id:n.id,name:n.name,...n.description!=null?{description:n.description}:{}}))}async getUserRoles(e,t){return(t?this.stmt("SELECT r.* FROM roles r JOIN user_roles ur ON ur.role_id = r.id WHERE ur.user_id = ? AND ur.tenant_id = ?").all(e,t):this.stmt("SELECT r.* FROM roles r JOIN user_roles ur ON ur.role_id = r.id WHERE ur.user_id = ?").all(e)).map(o=>({id:o.id,tenantId:o.tenant_id,name:o.name,...o.description!=null?{description:o.description}:{}}))}async assignRole(e,t,n="default"){this.stmt("INSERT OR IGNORE INTO user_roles (user_id, role_id, tenant_id) VALUES (?,?,?)").run(e,t,n)}async revokeRole(e,t,n){n?this.stmt("DELETE FROM user_roles WHERE user_id = ? AND role_id = ? AND tenant_id = ?").run(e,t,n):this.stmt("DELETE FROM user_roles WHERE user_id = ? AND role_id = ?").run(e,t)}async createLog(e){let t=(0,C.randomUUID)(),n=new Date().toISOString();this.stmt("INSERT INTO audit_logs (id,tenant_id,user_id,action,resource_type,resource_id,old_data,new_data,created_at) VALUES (?,?,?,?,?,?,?,?,?)").run(t,e.tenantId,e.userId??null,e.action,e.resourceType,e.resourceId??null,e.oldData!=null?JSON.stringify(e.oldData):null,e.newData!=null?JSON.stringify(e.newData):null,n)}async getLogs(e){let t=["tenant_id = ?"],n=[e.tenantId];if(e.action&&(t.push("action = ?"),n.push(e.action)),e.resourceType&&(t.push("resource_type = ?"),n.push(e.resourceType)),e.from&&(t.push("created_at >= ?"),n.push(e.from)),e.to&&(t.push("created_at <= ?"),n.push(e.to)),e.q){t.push("(action LIKE ? OR resource_type LIKE ? OR resource_id LIKE ? OR user_id LIKE ?) ESCAPE '\\'");let d=j(e.q);n.push(d,d,d,d)}let o=t.join(" AND "),s=e.page??1,r=Math.min(e.limit??50,Yn),a=(s-1)*r,c=this.stmt(`SELECT ${i.AUDIT_SUMMARY_COLS} FROM audit_logs WHERE ${o} ORDER BY created_at DESC LIMIT ? OFFSET ?`).all(...n,r,a),l=this.stmt(`SELECT COUNT(*) AS total FROM audit_logs WHERE ${o}`).get(...n);return{items:c.map(d=>this.mapAuditSummary(d)),total:l.total,page:s,limit:r}}async getAuditLogById(e){let t=this.stmt("SELECT * FROM audit_logs WHERE id = ?").get(e);return t?this.mapAuditLog(t):null}static AUDIT_SUMMARY_COLS="id, tenant_id, user_id, action, resource_type, resource_id, created_at";mapAuditSummary(e){return{id:e.id,tenantId:e.tenant_id,action:e.action,resourceType:e.resource_type,...e.user_id!=null?{userId:e.user_id}:{},...e.resource_id!=null?{resourceId:e.resource_id}:{},createdAt:e.created_at}}mapAuditLog(e){return{id:e.id,tenantId:e.tenant_id,action:e.action,resourceType:e.resource_type,createdAt:e.created_at,...e.user_id!=null?{userId:e.user_id}:{},...e.resource_id!=null?{resourceId:e.resource_id}:{},...e.old_data!=null?{oldData:JSON.parse(e.old_data)}:{},...e.new_data!=null?{newData:JSON.parse(e.new_data)}:{}}}async*streamAuditLogs(e){let t=["tenant_id = ?"],n=[e.tenantId];e.action&&(t.push("action = ?"),n.push(e.action)),e.from&&(t.push("created_at >= ?"),n.push(e.from)),e.to&&(t.push("created_at <= ?"),n.push(e.to));let o=500,s=0;for(;;){let r=this.stmt(`SELECT * FROM audit_logs WHERE ${t.join(" AND ")} ORDER BY created_at DESC LIMIT ? OFFSET ?`).all(...n,o,s);if(r.length===0)break;for(let a of r)yield this.mapAuditLog(a);s+=o}}async getOverviewStats(e){let t=this.stmt("SELECT COUNT(*) as n FROM consent_records WHERE tenant_id = ?").get(e),n=this.stmt("SELECT COUNT(*) as n FROM consent_records WHERE tenant_id = ? AND gpc_detected = 1").get(e),o=this.stmt("SELECT COUNT(*) as n FROM visitors WHERE tenant_id = ?").get(e),s=t?.n??0,r=this.stmt("SELECT consent_json FROM consent_records WHERE tenant_id = ? ORDER BY created_at DESC LIMIT 500").all(e),a=0,c=0;for(let d of r){let u=Object.values(JSON.parse(d.consent_json)),m=u.length>0?u.filter(f=>f==="granted").length/u.length:0;m>=.8?a++:m<=.2&&c++}let l=r.length||1;return{totalConsents:s,gpcDetectedCount:n?.n??0,totalVisitors:o?.n??0,acceptedPct:Math.round(a/l*100),rejectedPct:Math.round(c/l*100)}}async getCategoryStats(e){let t=this.stmt("SELECT consent_json FROM consent_records WHERE tenant_id = ? LIMIT 5000").all(e),n={};for(let o of t){let s=JSON.parse(o.consent_json);for(let[r,a]of Object.entries(s))n[r]||(n[r]={granted:0,denied:0,objected:0}),a==="granted"?n[r].granted++:a==="denied"?n[r].denied++:a==="objected"&&n[r].objected++}return n}async getTimeline(e,t=30){return this.stmt("SELECT date(created_at) as date, COUNT(*) as count FROM consent_records WHERE tenant_id = ? AND created_at >= date('now', ?) GROUP BY date(created_at) ORDER BY date ASC").all(e,`-${t} days`).map(o=>({date:o.date,count:o.count}))}async getCountries(e){return this.stmt("SELECT v.country, COUNT(*) as count FROM consent_records cr JOIN visitors v ON v.visitor_id = cr.visitor_id WHERE cr.tenant_id = ? AND v.country IS NOT NULL GROUP BY v.country ORDER BY count DESC LIMIT 50").all(e).map(n=>({country:n.country,count:n.count}))}async getGpcStats(e){let t=this.stmt("SELECT COUNT(*) as n FROM consent_records WHERE tenant_id = ?").get(e),n=this.stmt("SELECT COUNT(*) as n FROM consent_records WHERE tenant_id = ? AND gpc_detected = 1").get(e),o=t?.n??0,s=n?.n??0;return{detected:s,total:o,rate:o>0?Math.round(s/o*100):0}}async getTenants(){return this.stmt("SELECT * FROM tenants ORDER BY name ASC").all().map(t=>({id:t.id,name:t.name,slug:t.slug,createdAt:t.created_at,updatedAt:t.updated_at}))}async createTenant(e){let t=(0,C.randomUUID)(),n=new Date().toISOString();this.stmt("INSERT INTO tenants (id,name,slug,created_at,updated_at) VALUES (?,?,?,?,?)").run(t,e.name,e.slug,n,n);let o=this.stmt("SELECT * FROM tenants WHERE id = ?").get(t);if(!o)throw new Error("Failed to create tenant");return{id:o.id,name:o.name,slug:o.slug,createdAt:o.created_at,updatedAt:o.updated_at}}async updateTenant(e,t){let n=new Date().toISOString(),o=["updated_at = ?"],s=[n];t.name!=null&&(o.push("name = ?"),s.push(t.name)),t.slug!=null&&(o.push("slug = ?"),s.push(t.slug)),s.push(e),this.stmt(`UPDATE tenants SET ${o.join(", ")} WHERE id = ?`).run(...s);let r=this.stmt("SELECT * FROM tenants WHERE id = ?").get(e);if(!r)throw new Error(`Tenant ${e} not found`);return{id:r.id,name:r.name,slug:r.slug,createdAt:r.created_at,updatedAt:r.updated_at}}async deleteTenant(e){this.stmt("DELETE FROM tenants WHERE id = ?").run(e)}async getSettings(e){let t=this.stmt("SELECT allowed_origins_json, admin_allowed_origins_json, setup_completed, profiles_seeded, tcf_confirmation_json, gpp_confirmation_json FROM tenant_settings WHERE tenant_id = ?").get(e);return t?{allowedOrigins:JSON.parse(t.allowed_origins_json),adminAllowedOrigins:JSON.parse(t.admin_allowed_origins_json),setupCompleted:!!t.setup_completed,profilesSeeded:!!t.profiles_seeded,tcfConfirmation:t.tcf_confirmation_json?JSON.parse(t.tcf_confirmation_json):void 0,gppConfirmation:t.gpp_confirmation_json?JSON.parse(t.gpp_confirmation_json):void 0}:{}}async updateSettings(e,t){let o={...await this.getSettings(e),...t};return this.stmt(`INSERT INTO tenant_settings (tenant_id, allowed_origins_json, admin_allowed_origins_json, setup_completed, profiles_seeded, tcf_confirmation_json, gpp_confirmation_json, updated_at) VALUES (?,?,?,?,?,?,?,?)
78
+ ON CONFLICT(tenant_id) DO UPDATE SET allowed_origins_json = excluded.allowed_origins_json, admin_allowed_origins_json = excluded.admin_allowed_origins_json, setup_completed = excluded.setup_completed, profiles_seeded = excluded.profiles_seeded, tcf_confirmation_json = excluded.tcf_confirmation_json, gpp_confirmation_json = excluded.gpp_confirmation_json, updated_at = excluded.updated_at`).run(e,JSON.stringify(o.allowedOrigins??[]),JSON.stringify(o.adminAllowedOrigins??[]),o.setupCompleted?1:0,o.profilesSeeded?1:0,o.tcfConfirmation?JSON.stringify(o.tcfConfirmation):null,o.gppConfirmation?JSON.stringify(o.gppConfirmation):null,new Date().toISOString()),this.getSettings(e)}async purgeExpiredConsents(e){let t=new Date(Date.now()-e*864e5).toISOString(),n=this.stmt("SELECT visitor_id FROM consent_records WHERE created_at < ?").all(t);for(let{visitor_id:o}of n)this.stmt("DELETE FROM consent_history WHERE visitor_id = ?").run(o),this.stmt("DELETE FROM consent_records WHERE visitor_id = ?").run(o);return n.length}mapApiKey(e){return{id:e.id,tenantId:e.tenant_id,keyHash:e.key_hash,name:e.name,isActive:e.is_active===1,...e.created_by!==null?{createdBy:e.created_by}:{},...e.expire_by!==null?{expireBy:e.expire_by}:{},createdAt:e.created_at,...e.updated_at!==null?{updatedAt:e.updated_at}:{}}}async createApiKey(e){let t=(0,C.randomUUID)(),n=new Date().toISOString();this.stmt("INSERT INTO api_keys (id,tenant_id,key_hash,name,created_by,expire_by,created_at,updated_at) VALUES (?,?,?,?,?,?,?,?)").run(t,e.tenantId,e.keyHash,e.name,e.createdBy??null,e.expireBy??null,n,n);let o=this.stmt("SELECT * FROM api_keys WHERE id = ?").get(t);if(!o)throw new Error("Failed to create API key");return this.mapApiKey(o)}async getApiKeyByHash(e){let t=this.stmt("SELECT * FROM api_keys WHERE key_hash = ? AND is_active = 1").get(e);return t?this.mapApiKey(t):null}async revokeApiKey(e){this.stmt("UPDATE api_keys SET is_active = 0, updated_at = ? WHERE id = ?").run(new Date().toISOString(),e)}async reactivateApiKey(e){let t=new Date().toISOString();this.stmt("UPDATE api_keys SET is_active = 1, updated_at = ?, expire_by = CASE WHEN expire_by <= ? THEN NULL ELSE expire_by END WHERE id = ?").run(t,t,e)}async deleteApiKey(e){this.stmt("DELETE FROM api_keys WHERE id = ?").run(e)}async getApiKeys(e){return this.stmt("SELECT * FROM api_keys WHERE tenant_id = ? ORDER BY created_at DESC").all(e).map(n=>this.mapApiKey(n))}mapConsentTemplate(e){return{id:e.id,tenantId:e.tenant_id,name:e.name,cookies:JSON.parse(e.cookies_json),categories:JSON.parse(e.categories_json),createdAt:e.created_at,updatedAt:e.updated_at}}async createConsentTemplate(e){let t=Q(),n=new Date().toISOString();return this.stmt("INSERT INTO consent_templates (id,tenant_id,name,cookies_json,categories_json,created_at,updated_at) VALUES (?,?,?,?,?,?,?)").run(t,e.tenantId,e.name,JSON.stringify(e.cookies),JSON.stringify(e.categories),n,n),this.mapConsentTemplate(this.stmt("SELECT * FROM consent_templates WHERE id = ?").get(t))}async updateConsentTemplate(e,t){let n=new Date().toISOString();t.name!==void 0&&this.stmt("UPDATE consent_templates SET name = ?, updated_at = ? WHERE id = ?").run(t.name,n,e),t.cookies!==void 0&&this.stmt("UPDATE consent_templates SET cookies_json = ?, updated_at = ? WHERE id = ?").run(JSON.stringify(t.cookies),n,e),t.categories!==void 0&&this.stmt("UPDATE consent_templates SET categories_json = ?, updated_at = ? WHERE id = ?").run(JSON.stringify(t.categories),n,e);let o=this.stmt("SELECT * FROM consent_templates WHERE id = ?").get(e);if(!o)throw new Error("Consent template not found");return this.mapConsentTemplate(o)}async deleteConsentTemplate(e){this.stmt("DELETE FROM consent_templates WHERE id = ?").run(e)}async getConsentTemplate(e){let t=this.stmt("SELECT * FROM consent_templates WHERE id = ?").get(e);return t?this.mapConsentTemplate(t):null}async getConsentTemplates(e){return this.stmt("SELECT * FROM consent_templates WHERE tenant_id = ? ORDER BY name ASC").all(e).map(n=>this.mapConsentTemplate(n))}async copyConsentTemplate(e,t){let n=await this.getConsentTemplate(e);if(!n)throw new Error("Consent template not found");return this.createConsentTemplate({tenantId:n.tenantId,name:t,cookies:n.cookies,categories:n.categories})}mapUITemplate(e){let t=JSON.parse(e.settings_json);return{id:e.id,tenantId:e.tenant_id,name:e.name,...t,createdAt:e.created_at,updatedAt:e.updated_at}}async createUITemplate(e){let t=Z(),n=new Date().toISOString(),{tenantId:o,name:s,...r}=e;return this.stmt("INSERT INTO ui_templates (id,tenant_id,name,settings_json,created_at,updated_at) VALUES (?,?,?,?,?,?)").run(t,o,s,JSON.stringify(r),n,n),this.mapUITemplate(this.stmt("SELECT * FROM ui_templates WHERE id = ?").get(t))}async updateUITemplate(e,t){let n=new Date().toISOString(),o=this.stmt("SELECT * FROM ui_templates WHERE id = ?").get(e);if(!o)throw new Error("UI template not found");t.name!==void 0&&this.stmt("UPDATE ui_templates SET name = ?, updated_at = ? WHERE id = ?").run(t.name,n,e);let{name:s,...r}=t;if(Object.keys(r).length>0){let c={...JSON.parse(o.settings_json),...r};this.stmt("UPDATE ui_templates SET settings_json = ?, updated_at = ? WHERE id = ?").run(JSON.stringify(c),n,e)}return this.mapUITemplate(this.stmt("SELECT * FROM ui_templates WHERE id = ?").get(e))}async deleteUITemplate(e){this.stmt("DELETE FROM ui_templates WHERE id = ?").run(e)}async getUITemplate(e){let t=this.stmt("SELECT * FROM ui_templates WHERE id = ?").get(e);return t?this.mapUITemplate(t):null}async getUITemplates(e){return this.stmt("SELECT * FROM ui_templates WHERE tenant_id = ? ORDER BY name ASC").all(e).map(n=>this.mapUITemplate(n))}async copyUITemplate(e,t){let n=await this.getUITemplate(e);if(!n)throw new Error("UI template not found");let{tenantId:o,mainBanner:s,gpcBanner:r,preferenceModal:a}=n;return this.createUITemplate({tenantId:o,name:t,mainBanner:s,gpcBanner:r,preferenceModal:a})}mapProfileSummary(e){return{id:e.id,name:e.name,defaultLocale:e.default_locale,complianceGroup:e.compliance_group??null,customComplianceGroup:e.custom_compliance_group??null,isActive:e.is_active===1,consentTemplateName:e.consent_template_name,uiTemplateName:e.ui_template_name,createdAt:e.created_at,updatedAt:e.updated_at}}PROFILE_SUMMARY_SQL=`
82
79
  SELECT
83
80
  p.id, p.name, p.default_locale, p.created_at, p.updated_at,
84
81
  json_extract(p.profile_json, '$.complianceGroup') AS compliance_group,
@@ -91,50 +88,55 @@ ${l.map(d=>` (${se(c)},${se(d)})`).join(`,
91
88
  FROM profiles p
92
89
  LEFT JOIN consent_templates ct ON ct.id = json_extract(p.profile_json, '$.consentTemplateId')
93
90
  LEFT JOIN ui_templates ut ON ut.id = json_extract(p.profile_json, '$.uiTemplateId')
94
- `;async listProfilesSummary(e){return this.stmt(`${this.PROFILE_SUMMARY_SQL} WHERE p.tenant_id = ? ORDER BY p.created_at ASC`).all(e).map(n=>this.mapProfileSummary(n))}async findProfilesUsingConsentTemplate(e){return this.stmt(`${this.PROFILE_SUMMARY_SQL} WHERE json_extract(p.profile_json, '$.consentTemplateId') = ? ORDER BY p.name ASC`).all(e).map(n=>this.mapProfileSummary(n))}async findProfilesUsingUITemplate(e){return this.stmt(`${this.PROFILE_SUMMARY_SQL} WHERE json_extract(p.profile_json, '$.uiTemplateId') = ? ORDER BY p.name ASC`).all(e).map(n=>this.mapProfileSummary(n))}async getOptInStats(e,t){let n=["cr.tenant_id = ?"],o=[e];t.profileId&&(n.push("cr.profile_id = ?"),o.push(t.profileId)),t.from&&(n.push("cr.created_at >= ?"),o.push(t.from)),t.to&&(n.push("cr.created_at <= ?"),o.push(t.to)),t.locale&&(n.push("cr.locale = ?"),o.push(t.locale));let s=n.join(" AND "),r=this.stmt(`SELECT cr.locale, cr.consent_json FROM consent_records cr WHERE ${s}`).all(...o),a=0,c=0,l=0,d=0,u={};for(let _ of r){let w=JSON.parse(_.consent_json),R=Object.values(w),C=R.filter(D=>D==="granted").length,A=R.filter(D=>D==="denied").length,T=R.length>0?C/R.length:0;a++;let O=_.locale;u[O]||(u[O]={total:0,granted:0,denied:0,managed:0}),u[O].total++,T>=.9?(c++,u[O].granted++):A/(R.length||1)>=.9?(l++,u[O].denied++):(d++,u[O].managed++)}let m=this.stmt(`SELECT date(cr.created_at) as d, cr.consent_json FROM consent_records cr WHERE ${s} ORDER BY d ASC`).all(...o),h=new Map;for(let _ of m){let w=h.get(_.d)??{total:0,granted:0,denied:0,managed:0},R=JSON.parse(_.consent_json),C=Object.values(R),A=C.length>0?C.filter(O=>O==="granted").length/C.length:0,T=C.length>0?C.filter(O=>O==="denied").length/C.length:0;w.total++,A>=.9?w.granted++:T>=.9?w.denied++:w.managed++,h.set(_.d,w)}let S=Array.from(h.entries()).map(([_,w])=>({date:_,...w}));return{total:a,granted:c,denied:l,managed:d,grantedPct:a>0?Math.round(c/a*1e3)/10:0,deniedPct:a>0?Math.round(l/a*1e3)/10:0,managedPct:a>0?Math.round(d/a*1e3)/10:0,byLocale:u,byDate:S}}};p();p();function Ue(i,e,t){return i.map(n=>{let o=n.profileJson;return{id:n.id,name:n.name,defaultLocale:n.defaultLocale,complianceGroup:o.complianceGroup??null,customComplianceGroup:o.customComplianceGroup??null,isActive:o.isActive===!0,consentTemplateName:o.consentTemplateId?e.get(o.consentTemplateId)??null:null,uiTemplateName:o.uiTemplateId?t.get(o.uiTemplateId)??null:null,createdAt:n.createdAt,updatedAt:n.updatedAt}})}function xe(i){let e=()=>({total:0,granted:0,denied:0,managed:0}),t=e(),n={},o=new Map;for(let r of i){let a=Object.values(r.consentJson),c=d=>a.length>0?a.filter(u=>u===d).length/a.length:0,l=c("granted")>=.9?"granted":c("denied")>=.9?"denied":"managed";o.has(r.day)||o.set(r.day,e()),n[r.locale]??=e();for(let d of[t,n[r.locale],o.get(r.day)])d.total++,d[l]++}let s=r=>t.total>0?Math.round(r/t.total*1e3)/10:0;return{...t,grantedPct:s(t.granted),deniedPct:s(t.denied),managedPct:s(t.managed),byLocale:n,byDate:Array.from(o,([r,a])=>({date:r,...a})).sort((r,a)=>r.date.localeCompare(a.date))}}function jn(i){return i.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}function Pe(i){return{id:i._id,tenantId:i.tenant_id,name:i.name,defaultLocale:i.default_locale,version:i.version,profileJson:i.profile_json,createdAt:i.created_at,updatedAt:i.updated_at}}function At(i){return{id:i._id,tenantId:i.tenant_id,visitorId:i.visitor_id,profileId:i.profile_id,locale:i.locale,consentJson:i.consent_json,gpcDetected:i.gpc_detected,source:i.source,createdAt:i.created_at,updatedAt:i.updated_at,...i.age_verified!=null?{ageVerified:i.age_verified}:{},...i.parental_consent_token!=null?{parentalConsentToken:i.parental_consent_token}:{},...i.tcf_string!=null?{tcfString:i.tcf_string}:{},...i.gpp_string!=null?{gppString:i.gpp_string}:{},...i.signature!=null?{signature:i.signature}:{}}}var Bc={tenant_id:1,visitor_id:1,profile_id:1,locale:1,gpc_detected:1,source:1,age_verified:1,created_at:1,updated_at:1};function Fc(i){return{id:i._id,tenantId:i.tenant_id,visitorId:i.visitor_id,profileId:i.profile_id,locale:i.locale,gpcDetected:i.gpc_detected,source:i.source,createdAt:i.created_at,updatedAt:i.updated_at,...i.age_verified!=null?{ageVerified:i.age_verified}:{}}}function $c(i){return{id:i._id,tenantId:i.tenant_id,consentRecordId:i.consent_record_id,visitorId:i.visitor_id,oldJson:i.old_json,newJson:i.new_json,action:i.action,createdAt:i.created_at}}function Tt(i){return{id:i._id,tenantId:i.tenant_id,visitorId:i.visitor_id,...i.country!=null?{country:i.country}:{},...i.region!=null?{region:i.region}:{},...i.city!=null?{city:i.city}:{},...i.ip_hash!=null?{ipHash:i.ip_hash}:{},...i.user_agent_hash!=null?{userAgentHash:i.user_agent_hash}:{},firstSeen:i.first_seen,lastSeen:i.last_seen}}function Xe(i){return{id:i._id,tenantId:i.tenant_id,name:i.name,email:i.email,passwordHash:i.password_hash,isActive:i.is_active,createdAt:i.created_at,updatedAt:i.updated_at}}function It(i){return{id:i._id,tenantId:i.tenant_id,name:i.name,...i.description!=null?{description:i.description}:{}}}function wo(i){return{id:i._id,name:i.name,...i.description!=null?{description:i.description}:{}}}function Eo(i){return{id:i._id,tenantId:i.tenant_id,action:i.action,resourceType:i.resource_type,...i.user_id!=null?{userId:i.user_id}:{},...i.resource_id!=null?{resourceId:i.resource_id}:{},...i.old_data!=null?{oldData:i.old_data}:{},...i.new_data!=null?{newData:i.new_data}:{},createdAt:i.created_at}}var Hc={tenant_id:1,user_id:1,action:1,resource_type:1,resource_id:1,created_at:1};function Vc(i){return{id:i._id,tenantId:i.tenant_id,action:i.action,resourceType:i.resource_type,...i.user_id!=null?{userId:i.user_id}:{},...i.resource_id!=null?{resourceId:i.resource_id}:{},createdAt:i.created_at}}var Me=class{constructor(e){this.config=e}config;client;db;col(e){return this.db.collection(e)}async connect(){let{MongoClient:e}=await import("mongodb"),t=this.config.uri??"mongodb://localhost:27017";this.client=new e(t),await this.client.connect(),this.db=this.client.db(this.config.database??"consenti"),await this.migrate()}async disconnect(){await this.client.close()}async migrate(){await this.createIndexes(),await this.seed()}async createIndexes(){for(let{table:e,cols:t,unique:n}of ho){let o=Object.fromEntries(t.map(s=>[s,1]));await this.col(e).createIndex(o,n?{unique:!0}:void 0)}}async seed(){let{id:e,name:t,slug:n}=ie;await this.col("tenants").findOne({_id:e})||await this.col("tenants").insertOne({_id:e,name:t,slug:n});for(let s of ne){let r={_id:s.id,name:s.name,description:s.description};await this.col("permissions").updateOne({_id:s.id},{$setOnInsert:r},{upsert:!0})}for(let s of ge){let r={_id:s.id,tenant_id:s.tenantId,name:s.name,description:s.description};await this.col("roles").updateOne({_id:s.id},{$setOnInsert:r},{upsert:!0})}let o=this.col("role_permissions");for(let{roleId:s,permissionId:r}of fe)await o.updateOne({role_id:s,permission_id:r},{$setOnInsert:{role_id:s,permission_id:r}},{upsert:!0})}async createProfile(e){let t=new Date().toISOString(),o={_id:z(),tenant_id:e.tenantId,name:e.name,default_locale:e.defaultLocale,version:1,profile_json:e.profileJson,created_at:t,updated_at:t};return await this.col("profiles").insertOne(o),Pe(o)}async updateProfile(e,t){let o={updated_at:new Date().toISOString()};t.name!=null&&(o.name=t.name),t.defaultLocale!=null&&(o.default_locale=t.defaultLocale),t.profileJson!=null&&(o.profile_json=t.profileJson),t.version!=null&&(o.version=t.version);let s=await this.col("profiles").findOneAndUpdate({_id:e},{$set:o},{returnDocument:"after"});if(!s)throw new Error(`Profile ${e} not found`);return Pe(s)}async deleteProfile(e){await this.col("profiles").deleteOne({_id:e})}async getProfile(e){let t=await this.col("profiles").findOne({_id:e});return t?Pe(t):null}async getProfiles(e){return(await this.col("profiles").find({tenant_id:e}).toArray()).map(Pe)}async findActiveProfileByComplianceGroup(e,t){return(await this.getProfiles(e)).find(o=>(o.profileJson.complianceGroup===t||o.profileJson.customComplianceGroup===t)&&o.profileJson.isActive)??null}async createConsent(e){let t=new Date().toISOString(),n={_id:K(),tenant_id:e.tenantId,visitor_id:e.visitorId,profile_id:e.profileId,locale:e.locale,consent_json:e.consentJson,gpc_detected:e.gpcDetected,source:e.source,created_at:t,updated_at:t,...e.ageVerified!=null?{age_verified:e.ageVerified}:{},...e.parentalConsentToken!=null?{parental_consent_token:e.parentalConsentToken}:{},...e.tcfString!=null?{tcf_string:e.tcfString}:{},...e.gppString!=null?{gpp_string:e.gppString}:{},...e.signature!=null?{signature:e.signature}:{}};return await this.col("consent_records").insertOne(n),await this.writeHistory(n._id,e.tenantId,e.visitorId,null,e.consentJson,"created"),At(n)}async updateConsent(e,t){let n=await this.getConsent(e);if(!n)throw new Error(`Consent for visitor ${e} not found`);let s={updated_at:new Date().toISOString(),consent_json:t.consentJson};t.locale!=null&&(s.locale=t.locale),t.gpcDetected!=null&&(s.gpc_detected=t.gpcDetected),t.signature!=null&&(s.signature=t.signature);let r=await this.col("consent_records").findOneAndUpdate({visitor_id:e},{$set:s},{returnDocument:"after"});if(!r)throw new Error(`Consent for visitor ${e} not found`);return await this.writeHistory(r._id,r.tenant_id,e,n.consentJson,t.consentJson,"updated"),At(r)}async deleteConsent(e){await this.col("consent_history").deleteMany({visitor_id:e}),await this.col("consent_records").deleteOne({visitor_id:e})}async getConsent(e){let t=await this.col("consent_records").findOne({visitor_id:e});return t?At(t):null}async getConsents(e){let t=this.buildConsentFilter(e),n=e.page??1,o=e.limit??50,[s,r]=await Promise.all([this.col("consent_records").find(t,{projection:Bc}).sort({created_at:-1}).skip((n-1)*o).limit(o).toArray(),this.col("consent_records").countDocuments(t)]);return{items:s.map(Fc),total:r,page:n,limit:o}}async*streamConsents(e){let t=this.buildConsentFilter(e),n=this.col("consent_records").find(t).sort({created_at:1});for await(let o of n)yield At(o)}buildConsentFilter(e){let t={tenant_id:e.tenantId};if(e.profileId!=null&&(t.profile_id=e.profileId),e.from!=null||e.to!=null){let n={};e.from!=null&&(n.$gte=e.from),e.to!=null&&(n.$lte=e.to),t.created_at=n}if(e.q){let n={$regex:"^"+jn(e.q),$options:"i"};t.$or=[{visitor_id:n},{profile_id:n},{locale:n},{source:n}]}return t}async writeHistory(e,t,n,o,s,r){let a={_id:(0,v.randomUUID)(),tenant_id:t,consent_record_id:e,visitor_id:n,old_json:o,new_json:s,action:r,created_at:new Date().toISOString()};await this.col("consent_history").insertOne(a)}async getConsentHistory(e){return(await this.col("consent_history").find({visitor_id:e}).sort({created_at:1}).toArray()).map($c)}async createNoticeShown(e){let t={_id:(0,v.randomUUID)(),tenant_id:e.tenantId,visitor_id:e.visitorId,profile_id:e.profileId,locale:e.locale,created_at:new Date().toISOString()};return await this.col("notice_shown").insertOne(t),{id:t._id,tenantId:t.tenant_id,visitorId:t.visitor_id,profileId:t.profile_id,locale:t.locale,createdAt:t.created_at}}async getNoticeShownForVisitor(e){return(await this.col("notice_shown").find({visitor_id:e}).sort({created_at:-1}).toArray()).map(n=>({id:n._id,tenantId:n.tenant_id,visitorId:n.visitor_id,profileId:n.profile_id,locale:n.locale,createdAt:n.created_at}))}async createVisitor(e){let t=new Date().toISOString(),n={_id:q(),tenant_id:e.tenantId,visitor_id:e.visitorId,first_seen:t,last_seen:t,...e.country!=null?{country:e.country}:{},...e.region!=null?{region:e.region}:{},...e.city!=null?{city:e.city}:{},...e.ipHash!=null?{ip_hash:e.ipHash}:{},...e.userAgentHash!=null?{user_agent_hash:e.userAgentHash}:{}};return await this.col("visitors").insertOne(n),Tt(n)}async updateVisitor(e,t){let n={last_seen:t.lastSeen??new Date().toISOString()};t.country!=null&&(n.country=t.country),t.region!=null&&(n.region=t.region),t.city!=null&&(n.city=t.city);let o=await this.col("visitors").findOneAndUpdate({visitor_id:e},{$set:n},{returnDocument:"after"});if(!o)throw new Error(`Visitor ${e} not found`);return Tt(o)}async deleteVisitor(e){await this.col("visitors").deleteOne({visitor_id:e})}async getVisitor(e){let t=await this.col("visitors").findOne({visitor_id:e});return t?Tt(t):null}async getVisitors(e){let t={tenant_id:e.tenantId};if(e.from!=null||e.to!=null){let a={};e.from!=null&&(a.$gte=e.from),e.to!=null&&(a.$lte=e.to),t.first_seen=a}if(e.q){let a={$regex:"^"+jn(e.q),$options:"i"};t.$or=[{visitor_id:a},{country:a}]}let n=e.page??1,o=e.limit??50,[s,r]=await Promise.all([this.col("visitors").find(t).sort({first_seen:-1}).skip((n-1)*o).limit(o).toArray(),this.col("visitors").countDocuments(t)]);return{items:s.map(Tt),total:r,page:n,limit:o}}async getOverviewStats(e){let[t,n,o]=await Promise.all([this.col("consent_records").countDocuments({tenant_id:e}),this.col("consent_records").countDocuments({tenant_id:e,gpc_detected:!0}),this.col("visitors").countDocuments({tenant_id:e})]),s=[{$match:{tenant_id:e}},{$addFields:{values:{$objectToArray:"$consent_json"}}},{$unwind:"$values"},{$group:{_id:"$values.v",count:{$sum:1}}}],r=await this.col("consent_records").aggregate(s).toArray(),a=0,c=0,l=0;for(let d of r)l+=d.count,d._id==="granted"&&(a=d.count),d._id==="denied"&&(c=d.count);return{totalConsents:t,acceptedPct:l>0?Math.round(a/l*100):0,rejectedPct:l>0?Math.round(c/l*100):0,totalVisitors:o,gpcDetectedCount:n}}async getCategoryStats(e){let t=[{$match:{tenant_id:e}},{$addFields:{pairs:{$objectToArray:"$consent_json"}}},{$unwind:"$pairs"},{$group:{_id:{cookie:"$pairs.k",status:"$pairs.v"},count:{$sum:1}}}],n=await this.col("consent_records").aggregate(t).toArray(),o={};for(let s of n){let r=s._id.cookie;o[r]||(o[r]={granted:0,denied:0,objected:0});let a=o[r];a&&(s._id.status==="granted"&&(a.granted+=s.count),s._id.status==="denied"&&(a.denied+=s.count),s._id.status==="objected"&&(a.objected+=s.count))}return o}async getTimeline(e,t=30){let n=new Date(Date.now()-t*864e5).toISOString(),o=[{$match:{tenant_id:e,created_at:{$gte:n}}},{$group:{_id:{$substr:["$created_at",0,10]},count:{$sum:1}}},{$sort:{_id:1}}];return(await this.col("consent_records").aggregate(o).toArray()).map(r=>({date:r._id,count:r.count}))}async createUser(e){let t=new Date().toISOString(),n={_id:(0,v.randomUUID)(),tenant_id:e.tenantId,name:e.name,email:e.email,password_hash:e.passwordHash,is_active:!0,created_at:t,updated_at:t};return await this.col("users").insertOne(n),Xe(n)}async updateUser(e,t){let n={updated_at:new Date().toISOString()};t.name!=null&&(n.name=t.name),t.email!=null&&(n.email=t.email),t.passwordHash!=null&&(n.password_hash=t.passwordHash),t.isActive!=null&&(n.is_active=t.isActive);let o=await this.col("users").findOneAndUpdate({_id:e},{$set:n},{returnDocument:"after"});if(!o)throw new Error(`User ${e} not found`);return Xe(o)}async deleteUser(e){await this.col("user_roles").deleteMany({user_id:e}),await this.col("users").deleteOne({_id:e})}async getUserById(e){let t=await this.col("users").findOne({_id:e});return t?Xe(t):null}async getUserByEmail(e){let t=await this.col("users").findOne({email:e});return t?Xe(t):null}async getUsers(e){return(await this.col("users").find({tenant_id:e}).toArray()).map(Xe)}async countUsers(e){return this.col("users").countDocuments(e?{tenant_id:e}:{})}async getRoles(e){return(await this.col("roles").find({tenant_id:e}).toArray()).map(It)}async createRole(e){let t={_id:(0,v.randomUUID)(),tenant_id:e.tenantId,name:e.name,...e.description!=null?{description:e.description}:{}};return await this.col("roles").insertOne(t),It(t)}async updateRole(e,t){let n={};t.name!=null&&(n.name=t.name),t.description!=null&&(n.description=t.description);let o=await this.col("roles").findOneAndUpdate({_id:e},{$set:n},{returnDocument:"after"});if(!o)throw new Error(`Role ${e} not found`);return It(o)}async deleteRole(e){await this.col("role_permissions").deleteMany({role_id:e}),await this.col("user_roles").deleteMany({role_id:e}),await this.col("roles").deleteOne({_id:e})}async getAllPermissions(){return(await this.col("permissions").find({}).toArray()).map(wo)}async getPermissionsForRole(e){let n=(await this.col("role_permissions").find({role_id:e}).toArray()).map(s=>s.permission_id);return n.length===0?[]:(await this.col("permissions").find({_id:{$in:n}}).toArray()).map(wo)}async getUserRoles(e,t){let n=t?{user_id:e,tenant_id:t}:{user_id:e},s=(await this.col("user_roles").find(n).toArray()).map(a=>a.role_id);return s.length===0?[]:(await this.col("roles").find({_id:{$in:s}}).toArray()).map(It)}async assignRole(e,t,n="default"){await this.col("user_roles").updateOne({user_id:e,role_id:t,tenant_id:n},{$setOnInsert:{user_id:e,role_id:t,tenant_id:n}},{upsert:!0})}async revokeRole(e,t,n){n?await this.col("user_roles").deleteOne({user_id:e,role_id:t,tenant_id:n}):await this.col("user_roles").deleteMany({user_id:e,role_id:t})}async assignPermissionToRole(e,t){await this.col("role_permissions").updateOne({role_id:e,permission_id:t},{$setOnInsert:{role_id:e,permission_id:t}},{upsert:!0})}async revokePermissionFromRole(e,t){await this.col("role_permissions").deleteOne({role_id:e,permission_id:t})}async createLog(e){let t={_id:(0,v.randomUUID)(),tenant_id:e.tenantId,action:e.action,resource_type:e.resourceType,...e.userId!=null?{user_id:e.userId}:{},...e.resourceId!=null?{resource_id:e.resourceId}:{},...e.oldData!=null?{old_data:e.oldData}:{},...e.newData!=null?{new_data:e.newData}:{},created_at:new Date().toISOString()};await this.col("audit_logs").insertOne(t)}async getLogs(e){let t=this.buildAuditFilter(e),n=e.page??1,o=e.limit??50,[s,r]=await Promise.all([this.col("audit_logs").find(t,{projection:Hc}).sort({created_at:-1}).skip((n-1)*o).limit(o).toArray(),this.col("audit_logs").countDocuments(t)]);return{items:s.map(Vc),total:r,page:n,limit:o}}async getAuditLogById(e){let t=await this.col("audit_logs").findOne({_id:e});return t?Eo(t):null}async*streamAuditLogs(e){let t=this.buildAuditFilter(e),n=this.col("audit_logs").find(t).sort({created_at:1});for await(let o of n)yield Eo(o)}buildAuditFilter(e){let t={tenant_id:e.tenantId};if(e.action!=null&&(t.action=e.action),e.resourceType!=null&&(t.resource_type=e.resourceType),e.from!=null||e.to!=null){let n={};e.from!=null&&(n.$gte=e.from),e.to!=null&&(n.$lte=e.to),t.created_at=n}if(e.q){let n={$regex:"^"+jn(e.q),$options:"i"};t.$or=[{action:n},{resource_type:n},{resource_id:n},{user_id:n}]}return t}async getCountries(e){let t=[{$match:{tenant_id:e}},{$lookup:{from:"visitors",localField:"visitor_id",foreignField:"visitor_id",as:"v"}},{$unwind:"$v"},{$match:{"v.country":{$ne:null}}},{$group:{_id:"$v.country",count:{$sum:1}}},{$sort:{count:-1}},{$limit:50}];return(await this.col("consent_records").aggregate(t).toArray()).map(o=>({country:o._id,count:o.count}))}async getGpcStats(e){let t=await this.col("consent_records").countDocuments({tenant_id:e}),n=await this.col("consent_records").countDocuments({tenant_id:e,gpc_detected:!0});return{detected:n,total:t,rate:t>0?Math.round(n/t*100):0}}async getTenants(){return(await this.col("tenants").find({}).toArray()).map(t=>({id:t._id,name:t.name,slug:t.slug,createdAt:t.created_at,updatedAt:t.updated_at}))}mapApiKey(e){return{id:e._id,tenantId:e.tenant_id,keyHash:e.key_hash,name:e.name,isActive:e.is_active,...e.created_by!==void 0?{createdBy:e.created_by}:{},...e.expire_by!==void 0?{expireBy:e.expire_by}:{},createdAt:e.created_at,...e.updated_at!==void 0?{updatedAt:e.updated_at}:{}}}async createApiKey(e){let t=new Date().toISOString(),n={_id:(0,v.randomUUID)(),tenant_id:e.tenantId,key_hash:e.keyHash,name:e.name,is_active:!0,...e.createdBy!==void 0?{created_by:e.createdBy}:{},...e.expireBy!==void 0?{expire_by:e.expireBy}:{},created_at:t,updated_at:t};return await this.col("api_keys").insertOne(n),this.mapApiKey(n)}async getApiKeyByHash(e){let t=await this.col("api_keys").findOne({key_hash:e,is_active:!0});return t?this.mapApiKey(t):null}async revokeApiKey(e){await this.col("api_keys").updateOne({_id:e},{$set:{is_active:!1,updated_at:new Date().toISOString()}})}async reactivateApiKey(e){let t=await this.col("api_keys").findOne({_id:e});if(!t)return;let n=t.expire_by&&new Date(t.expire_by)<=new Date;await this.col("api_keys").updateOne({_id:e},{$set:{is_active:!0,updated_at:new Date().toISOString()},...n?{$unset:{expire_by:""}}:{}})}async deleteApiKey(e){await this.col("api_keys").deleteOne({_id:e})}async getApiKeys(e){return(await this.col("api_keys").find({tenant_id:e}).sort({created_at:-1}).toArray()).map(n=>this.mapApiKey(n))}async createTenant(e){let t=(0,v.randomUUID)(),n=new Date().toISOString(),o={_id:t,name:e.name,slug:e.slug,created_at:n,updated_at:n};return await this.col("tenants").insertOne(o),{id:t,name:e.name,slug:e.slug,createdAt:n,updatedAt:n}}async updateTenant(e,t){let o={updated_at:new Date().toISOString()};t.name!=null&&(o.name=t.name),t.slug!=null&&(o.slug=t.slug),await this.col("tenants").updateOne({_id:e},{$set:o});let s=await this.col("tenants").findOne({_id:e});if(!s)throw new Error(`Tenant ${e} not found`);return{id:s._id,name:s.name,slug:s.slug,createdAt:s.created_at,updatedAt:s.updated_at}}async deleteTenant(e){await this.col("tenants").deleteOne({_id:e})}async getSettings(e){let t=await this.col("tenant_settings").findOne({_id:e});return{...t?.allowed_origins!==void 0?{allowedOrigins:t.allowed_origins}:{},...t?.admin_allowed_origins!==void 0?{adminAllowedOrigins:t.admin_allowed_origins}:{},...t?.setup_completed!==void 0?{setupCompleted:t.setup_completed}:{},...t?.profiles_seeded!==void 0?{profilesSeeded:t.profiles_seeded}:{},...t?.tcf_confirmation!==void 0?{tcfConfirmation:t.tcf_confirmation}:{},...t?.gpp_confirmation!==void 0?{gppConfirmation:t.gpp_confirmation}:{}}}async updateSettings(e,t){let n={updated_at:new Date().toISOString()};return t.allowedOrigins!==void 0&&(n.allowed_origins=t.allowedOrigins),t.adminAllowedOrigins!==void 0&&(n.admin_allowed_origins=t.adminAllowedOrigins),t.setupCompleted!==void 0&&(n.setup_completed=t.setupCompleted),t.profilesSeeded!==void 0&&(n.profiles_seeded=t.profilesSeeded),t.tcfConfirmation!==void 0&&(n.tcf_confirmation=t.tcfConfirmation),t.gppConfirmation!==void 0&&(n.gpp_confirmation=t.gppConfirmation),await this.col("tenant_settings").updateOne({_id:e},{$set:n},{upsert:!0}),this.getSettings(e)}async purgeExpiredConsents(e){let t=new Date(Date.now()-e*864e5).toISOString(),n=await this.col("consent_records").find({created_at:{$lt:t}}).toArray();if(n.length===0)return 0;let o=n.map(s=>s.visitor_id);return await this.col("consent_history").deleteMany({visitor_id:{$in:o}}),await this.col("consent_records").deleteMany({visitor_id:{$in:o}}),n.length}mapConsentTemplate(e){return{id:e._id,tenantId:e.tenant_id,name:e.name,cookies:e.cookies_json,categories:e.categories_json,createdAt:e.created_at,updatedAt:e.updated_at}}async createConsentTemplate(e){let t=new Date().toISOString(),n={_id:Y(),tenant_id:e.tenantId,name:e.name,cookies_json:e.cookies,categories_json:e.categories,created_at:t,updated_at:t};return await this.col("consent_templates").insertOne(n),this.mapConsentTemplate(n)}async updateConsentTemplate(e,t){let n={updated_at:new Date().toISOString()};t.name!==void 0&&(n.name=t.name),t.cookies!==void 0&&(n.cookies_json=t.cookies),t.categories!==void 0&&(n.categories_json=t.categories);let o=await this.col("consent_templates").findOneAndUpdate({_id:e},{$set:n},{returnDocument:"after"});if(!o)throw new Error("Consent template not found");return this.mapConsentTemplate(o)}async deleteConsentTemplate(e){await this.col("consent_templates").deleteOne({_id:e})}async getConsentTemplate(e){let t=await this.col("consent_templates").findOne({_id:e});return t?this.mapConsentTemplate(t):null}async getConsentTemplates(e){return(await this.col("consent_templates").find({tenant_id:e}).sort({name:1}).toArray()).map(n=>this.mapConsentTemplate(n))}async copyConsentTemplate(e,t){let n=await this.getConsentTemplate(e);if(!n)throw new Error("Consent template not found");return this.createConsentTemplate({tenantId:n.tenantId,name:t,cookies:n.cookies,categories:n.categories})}mapUITemplate(e){return{id:e._id,tenantId:e.tenant_id,name:e.name,...e.settings_json,createdAt:e.created_at,updatedAt:e.updated_at}}async createUITemplate(e){let t=new Date().toISOString(),{tenantId:n,name:o,...s}=e,r={_id:Q(),tenant_id:n,name:o,settings_json:s,created_at:t,updated_at:t};return await this.col("ui_templates").insertOne(r),this.mapUITemplate(r)}async updateUITemplate(e,t){let n=await this.col("ui_templates").findOne({_id:e});if(!n)throw new Error("UI template not found");let{name:o,...s}=t,r={updated_at:new Date().toISOString()};o!==void 0&&(r.name=o),Object.keys(s).length>0&&(r.settings_json={...n.settings_json,...s});let a=await this.col("ui_templates").findOneAndUpdate({_id:e},{$set:r},{returnDocument:"after"});if(!a)throw new Error("UI template not found");return this.mapUITemplate(a)}async deleteUITemplate(e){await this.col("ui_templates").deleteOne({_id:e})}async getUITemplate(e){let t=await this.col("ui_templates").findOne({_id:e});return t?this.mapUITemplate(t):null}async getUITemplates(e){return(await this.col("ui_templates").find({tenant_id:e}).sort({name:1}).toArray()).map(n=>this.mapUITemplate(n))}async copyUITemplate(e,t){let n=await this.getUITemplate(e);if(!n)throw new Error("UI template not found");let{tenantId:o,mainBanner:s,gpcBanner:r,preferenceModal:a}=n;return this.createUITemplate({tenantId:o,name:t,mainBanner:s,gpcBanner:r,preferenceModal:a})}async toProfileSummaries(e){if(e.length===0)return[];let t=[...new Set(e.map(s=>s.tenantId))],[n,o]=await Promise.all([Promise.all(t.map(s=>this.getConsentTemplates(s))),Promise.all(t.map(s=>this.getUITemplates(s)))]);return Ue(e,new Map(n.flat().map(s=>[s.id,s.name])),new Map(o.flat().map(s=>[s.id,s.name])))}async listProfilesSummary(e){let t=await this.col("profiles").find({tenant_id:e}).sort({created_at:1}).toArray();return this.toProfileSummaries(t.map(Pe))}async findProfilesUsingConsentTemplate(e){let t=await this.col("profiles").find({"profile_json.consentTemplateId":e}).sort({name:1}).toArray();return this.toProfileSummaries(t.map(Pe))}async findProfilesUsingUITemplate(e){let t=await this.col("profiles").find({"profile_json.uiTemplateId":e}).sort({name:1}).toArray();return this.toProfileSummaries(t.map(Pe))}async getOptInStats(e,t){let n={tenant_id:e};t.profileId&&(n.profile_id=t.profileId),t.locale&&(n.locale=t.locale),(t.from||t.to)&&(n.created_at={...t.from?{$gte:t.from}:{},...t.to?{$lte:t.to}:{}});let o=await this.col("consent_records").find(n,{projection:{locale:1,consent_json:1,created_at:1}}).sort({created_at:1}).toArray();return xe(o.map(s=>({locale:s.locale,day:s.created_at.slice(0,10),consentJson:s.consent_json})))}};p();function be(i){return{id:i.id,tenantId:i.tenant_id,name:i.name,defaultLocale:i.default_locale,version:i.version,profileJson:JSON.parse(i.profile_json),createdAt:i.created_at,updatedAt:i.updated_at}}function Pt(i){return{id:i.id,tenantId:i.tenant_id,visitorId:i.visitor_id,profileId:i.profile_id,locale:i.locale,consentJson:JSON.parse(i.consent_json),gpcDetected:i.gpc_detected===1,source:i.source,createdAt:i.created_at,updatedAt:i.updated_at,...i.age_verified!=null?{ageVerified:i.age_verified===1}:{},...i.parental_consent_token!=null?{parentalConsentToken:i.parental_consent_token}:{},...i.tcf_string!=null?{tcfString:i.tcf_string}:{},...i.gpp_string!=null?{gppString:i.gpp_string}:{},...i.signature!=null?{signature:i.signature}:{}}}var Wc="id, tenant_id, visitor_id, profile_id, locale, gpc_detected, source, age_verified, created_at, updated_at";function qc(i){return{id:i.id,tenantId:i.tenant_id,visitorId:i.visitor_id,profileId:i.profile_id,locale:i.locale,gpcDetected:i.gpc_detected===1,source:i.source,createdAt:i.created_at,updatedAt:i.updated_at,...i.age_verified!=null?{ageVerified:i.age_verified===1}:{}}}function Jc(i){return{id:i.id,tenantId:i.tenant_id,consentRecordId:i.consent_record_id,visitorId:i.visitor_id,oldJson:i.old_json?JSON.parse(i.old_json):null,newJson:JSON.parse(i.new_json),action:i.action,createdAt:i.created_at}}function bt(i){return{id:i.id,tenantId:i.tenant_id,visitorId:i.visitor_id,...i.country!=null?{country:i.country}:{},...i.region!=null?{region:i.region}:{},...i.city!=null?{city:i.city}:{},...i.ip_hash!=null?{ipHash:i.ip_hash}:{},...i.user_agent_hash!=null?{userAgentHash:i.user_agent_hash}:{},firstSeen:i.first_seen,lastSeen:i.last_seen}}function et(i){return{id:i.id,tenantId:i.tenant_id,name:i.name,email:i.email,passwordHash:i.password_hash,isActive:i.is_active===1,createdAt:i.created_at,updatedAt:i.updated_at,totpEnabled:i.totp_enabled===1,...i.totp_secret!=null?{totpSecret:i.totp_secret}:{}}}function Ot(i){return{id:i.id,tenantId:i.tenant_id,name:i.name,...i.description!=null?{description:i.description}:{}}}function Ro(i){return{id:i.id,name:i.name,...i.description!=null?{description:i.description}:{}}}function So(i){return{id:i.id,tenantId:i.tenant_id,action:i.action,resourceType:i.resource_type,...i.user_id!=null?{userId:i.user_id}:{},...i.resource_id!=null?{resourceId:i.resource_id}:{},...i.old_data!=null?{oldData:JSON.parse(i.old_data)}:{},...i.new_data!=null?{newData:JSON.parse(i.new_data)}:{},createdAt:i.created_at}}var zc="id, tenant_id, user_id, action, resource_type, resource_id, created_at";function Kc(i){return{id:i.id,tenantId:i.tenant_id,action:i.action,resourceType:i.resource_type,...i.user_id!=null?{userId:i.user_id}:{},...i.resource_id!=null?{resourceId:i.resource_id}:{},createdAt:i.created_at}}var Ge=class{constructor(e){this.config=e}config;pool;async q(e,t=[]){let n=this.config.statementTimeoutMs,[o]=n?await this.pool.query({sql:e,timeout:n},t):await this.pool.query(e,t);return o}async exec(e,t=[]){let n=this.config.statementTimeoutMs,[o]=n?await this.pool.query({sql:e,timeout:n},t):await this.pool.query(e,t);return o}async connect(){let e=await import("mysql2/promise"),t=this.config;this.pool=e.createPool({...t.uri?{uri:t.uri}:{host:t.host??"localhost",port:t.port??3306,user:t.user??"root",password:t.password??"",database:t.database??"consenti"},connectionLimit:t.poolMax??10}),await this.migrate()}async disconnect(){await this.pool.end()}async migrate(){let e=await this.pool.getConnection();try{let[t]=await e.query("SHOW TABLES LIKE ?",["schema_version"]);if(t.length===0){for(let n of _o.split(";").map(o=>o.trim()).filter(Boolean))await e.query(n);await this.seed(e),await e.query("INSERT IGNORE INTO schema_version (version) VALUES (1)")}}finally{e.release()}}async seed(e){await e.query("INSERT IGNORE INTO tenants (id, name, slug) VALUES (?,?,?)",[ie.id,ie.name,ie.slug]);for(let t of ne)await e.query("INSERT IGNORE INTO permissions (id, name, description) VALUES (?,?,?)",[t.id,t.name,t.description]);for(let t of ge)await e.query("INSERT IGNORE INTO roles (id, tenant_id, name, description) VALUES (?,?,?,?)",[t.id,t.tenantId,t.name,t.description]);for(let{roleId:t,permissionId:n}of fe)await e.query("INSERT IGNORE INTO role_permissions (role_id, permission_id) VALUES (?,?)",[t,n])}async createProfile(e){let t=z();await this.exec("INSERT INTO profiles (id, tenant_id, name, default_locale, version, profile_json) VALUES (?,?,?,?,?,?)",[t,e.tenantId,e.name,e.defaultLocale,1,JSON.stringify(e.profileJson)]);let o=(await this.q("SELECT * FROM profiles WHERE id=?",[t]))[0];if(!o)throw new Error("Profile creation failed");return be(o)}async updateProfile(e,t){let n=[],o=[];t.name!=null&&(n.push("name=?"),o.push(t.name)),t.defaultLocale!=null&&(n.push("default_locale=?"),o.push(t.defaultLocale)),t.profileJson!=null&&(n.push("profile_json=?"),o.push(JSON.stringify(t.profileJson))),t.version!=null&&(n.push("version=?"),o.push(t.version)),n.length>0&&(o.push(e),await this.exec(`UPDATE profiles SET ${n.join(",")} WHERE id=?`,o));let r=(await this.q("SELECT * FROM profiles WHERE id=?",[e]))[0];if(!r)throw new Error(`Profile ${e} not found`);return be(r)}async deleteProfile(e){await this.exec("DELETE FROM profiles WHERE id=?",[e])}async getProfile(e){let t=await this.q("SELECT * FROM profiles WHERE id=?",[e]);return t[0]?be(t[0]):null}async getProfiles(e){return(await this.q("SELECT * FROM profiles WHERE tenant_id=? ORDER BY created_at DESC",[e])).map(be)}async findActiveProfileByComplianceGroup(e,t){return(await this.getProfiles(e)).find(o=>(o.profileJson.complianceGroup===t||o.profileJson.customComplianceGroup===t)&&o.profileJson.isActive)??null}async createConsent(e){let t=K();await this.exec("INSERT INTO consent_records (id, tenant_id, visitor_id, profile_id, locale, consent_json, gpc_detected, source, age_verified, parental_consent_token, tcf_string, gpp_string, signature) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?)",[t,e.tenantId,e.visitorId,e.profileId,e.locale,JSON.stringify(e.consentJson),e.gpcDetected?1:0,e.source,e.ageVerified?1:0,e.parentalConsentToken??null,e.tcfString??null,e.gppString??null,e.signature??null]);let o=(await this.q("SELECT * FROM consent_records WHERE id=?",[t]))[0];if(!o)throw new Error("Consent creation failed");return await this.writeHistory(t,e.tenantId,e.visitorId,null,e.consentJson,"created"),Pt(o)}async updateConsent(e,t){let n=await this.getConsent(e);if(!n)throw new Error(`Consent for visitor ${e} not found`);let o=["consent_json=?"],s=[JSON.stringify(t.consentJson)];t.locale!=null&&(o.push("locale=?"),s.push(t.locale)),t.gpcDetected!=null&&(o.push("gpc_detected=?"),s.push(t.gpcDetected?1:0)),t.signature!=null&&(o.push("signature=?"),s.push(t.signature)),s.push(e),await this.exec(`UPDATE consent_records SET ${o.join(",")} WHERE visitor_id=?`,s);let a=(await this.q("SELECT * FROM consent_records WHERE visitor_id=?",[e]))[0];if(!a)throw new Error(`Consent for visitor ${e} not found`);return await this.writeHistory(a.id,a.tenant_id,e,n.consentJson,t.consentJson,"updated"),Pt(a)}async deleteConsent(e){await this.exec("DELETE FROM consent_history WHERE visitor_id=?",[e]),await this.exec("DELETE FROM consent_records WHERE visitor_id=?",[e])}async getConsent(e){let t=await this.q("SELECT * FROM consent_records WHERE visitor_id=?",[e]);return t[0]?Pt(t[0]):null}async getConsents(e){let{where:t,params:n}=this.buildConsentWhere(e),o=e.page??1,s=e.limit??50,[r,a]=await Promise.all([this.q(`SELECT ${Wc} ${t} ORDER BY created_at DESC LIMIT ? OFFSET ?`,[...n,s,(o-1)*s]),this.q(`SELECT COUNT(*) AS total ${t}`,n)]);return{items:r.map(qc),total:a[0]?.total??0,page:o,limit:s}}async*streamConsents(e){let{where:t,params:n}=this.buildConsentWhere(e),o=await this.q(`SELECT * ${t} ORDER BY created_at ASC`,n);for(let s of o)yield Pt(s)}buildConsentWhere(e){let t="FROM consent_records WHERE tenant_id=?",n=[e.tenantId];if(e.profileId!=null&&(t+=" AND profile_id=?",n.push(e.profileId)),e.from!=null&&(t+=" AND created_at>=?",n.push(e.from)),e.to!=null&&(t+=" AND created_at<=?",n.push(e.to)),e.q){t+=" AND (visitor_id LIKE ? OR profile_id LIKE ? OR locale LIKE ? OR source LIKE ?) ESCAPE '\\\\'";let o=j(e.q);n.push(o,o,o,o)}return{where:t,params:n}}async writeHistory(e,t,n,o,s,r){await this.exec("INSERT INTO consent_history (id, tenant_id, consent_record_id, visitor_id, old_json, new_json, action) VALUES (?,?,?,?,?,?,?)",[(0,v.randomUUID)(),t,e,n,o?JSON.stringify(o):null,JSON.stringify(s),r])}async getConsentHistory(e){return(await this.q("SELECT * FROM consent_history WHERE visitor_id=? ORDER BY created_at ASC",[e])).map(Jc)}async createNoticeShown(e){let t=(0,v.randomUUID)();await this.exec("INSERT INTO notice_shown (id, tenant_id, visitor_id, profile_id, locale) VALUES (?,?,?,?,?)",[t,e.tenantId,e.visitorId,e.profileId,e.locale]);let o=(await this.q("SELECT * FROM notice_shown WHERE id=?",[t]))[0];return{id:o.id,tenantId:o.tenant_id,visitorId:o.visitor_id,profileId:o.profile_id,locale:o.locale,createdAt:o.created_at}}async getNoticeShownForVisitor(e){return(await this.q("SELECT * FROM notice_shown WHERE visitor_id=? ORDER BY created_at DESC",[e])).map(n=>({id:n.id,tenantId:n.tenant_id,visitorId:n.visitor_id,profileId:n.profile_id,locale:n.locale,createdAt:n.created_at}))}async createVisitor(e){let t=q();await this.exec("INSERT INTO visitors (id, tenant_id, visitor_id, country, region, city, ip_hash, user_agent_hash) VALUES (?,?,?,?,?,?,?,?)",[t,e.tenantId,e.visitorId,e.country??null,e.region??null,e.city??null,e.ipHash??null,e.userAgentHash??null]);let o=(await this.q("SELECT * FROM visitors WHERE id=?",[t]))[0];if(!o)throw new Error("Visitor creation failed");return bt(o)}async updateVisitor(e,t){let n=["last_seen=NOW()"],o=[];t.country!=null&&(n.push("country=?"),o.push(t.country)),t.region!=null&&(n.push("region=?"),o.push(t.region)),t.city!=null&&(n.push("city=?"),o.push(t.city)),o.push(e),await this.exec(`UPDATE visitors SET ${n.join(",")} WHERE visitor_id=?`,o);let r=(await this.q("SELECT * FROM visitors WHERE visitor_id=?",[e]))[0];if(!r)throw new Error(`Visitor ${e} not found`);return bt(r)}async deleteVisitor(e){await this.exec("DELETE FROM visitors WHERE visitor_id=?",[e])}async getVisitor(e){let t=await this.q("SELECT * FROM visitors WHERE visitor_id=?",[e]);return t[0]?bt(t[0]):null}async getVisitors(e){let t="FROM visitors WHERE tenant_id=?",n=[e.tenantId];if(e.from!=null&&(t+=" AND first_seen>=?",n.push(e.from)),e.to!=null&&(t+=" AND first_seen<=?",n.push(e.to)),e.q){t+=" AND (visitor_id LIKE ? OR country LIKE ?) ESCAPE '\\\\'";let c=j(e.q);n.push(c,c)}let o=e.page??1,s=e.limit??50,[r,a]=await Promise.all([this.q(`SELECT * ${t} ORDER BY first_seen DESC LIMIT ? OFFSET ?`,[...n,s,(o-1)*s]),this.q(`SELECT COUNT(*) AS total ${t}`,n)]);return{items:r.map(bt),total:a[0]?.total??0,page:o,limit:s}}async getOverviewStats(e){let[[t],[n],[o]]=await Promise.all([this.q("SELECT COUNT(*) AS total FROM consent_records WHERE tenant_id=?",[e]),this.q("SELECT COUNT(*) AS total FROM consent_records WHERE tenant_id=? AND gpc_detected=1",[e]),this.q("SELECT COUNT(*) AS total FROM visitors WHERE tenant_id=?",[e])]),s=t?.total??0,r=n?.total??0,a=o?.total??0,c=await this.q(`SELECT jt.status, COUNT(*) AS count
95
- FROM consent_records cr
91
+ `;async listProfilesSummary(e){return this.stmt(`${this.PROFILE_SUMMARY_SQL} WHERE p.tenant_id = ? ORDER BY p.created_at ASC`).all(e).map(n=>this.mapProfileSummary(n))}async findProfilesUsingConsentTemplate(e){return this.stmt(`${this.PROFILE_SUMMARY_SQL} WHERE json_extract(p.profile_json, '$.consentTemplateId') = ? ORDER BY p.name ASC`).all(e).map(n=>this.mapProfileSummary(n))}async findProfilesUsingUITemplate(e){return this.stmt(`${this.PROFILE_SUMMARY_SQL} WHERE json_extract(p.profile_json, '$.uiTemplateId') = ? ORDER BY p.name ASC`).all(e).map(n=>this.mapProfileSummary(n))}async getOptInStats(e,t){let n=["cr.tenant_id = ?"],o=[e];t.profileId&&(n.push("cr.profile_id = ?"),o.push(t.profileId)),t.from&&(n.push("cr.created_at >= ?"),o.push(t.from)),t.to&&(n.push("cr.created_at <= ?"),o.push(t.to)),t.locale&&(n.push("cr.locale = ?"),o.push(t.locale));let s=n.join(" AND "),r=this.stmt(`SELECT cr.locale, cr.consent_json FROM consent_records cr WHERE ${s}`).all(...o),a=0,c=0,l=0,d=0,u={};for(let y of r){let E=JSON.parse(y.consent_json),R=Object.values(E),v=R.filter(x=>x==="granted").length,A=R.filter(x=>x==="denied").length,T=R.length>0?v/R.length:0;a++;let P=y.locale;u[P]||(u[P]={total:0,granted:0,denied:0,managed:0}),u[P].total++,T>=.9?(c++,u[P].granted++):A/(R.length||1)>=.9?(l++,u[P].denied++):(d++,u[P].managed++)}let m=this.stmt(`SELECT date(cr.created_at) as d, cr.consent_json FROM consent_records cr WHERE ${s} ORDER BY d ASC`).all(...o),f=new Map;for(let y of m){let E=f.get(y.d)??{total:0,granted:0,denied:0,managed:0},R=JSON.parse(y.consent_json),v=Object.values(R),A=v.length>0?v.filter(P=>P==="granted").length/v.length:0,T=v.length>0?v.filter(P=>P==="denied").length/v.length:0;E.total++,A>=.9?E.granted++:T>=.9?E.denied++:E.managed++,f.set(y.d,E)}let S=Array.from(f.entries()).map(([y,E])=>({date:y,...E}));return{total:a,granted:c,denied:l,managed:d,grantedPct:a>0?Math.round(c/a*1e3)/10:0,deniedPct:a>0?Math.round(l/a*1e3)/10:0,managedPct:a>0?Math.round(d/a*1e3)/10:0,byLocale:u,byDate:S}}};p();p();function Be(i,e,t){return i.map(n=>{let o=n.profileJson;return{id:n.id,name:n.name,defaultLocale:n.defaultLocale,complianceGroup:o.complianceGroup??null,customComplianceGroup:o.customComplianceGroup??null,isActive:o.isActive===!0,consentTemplateName:o.consentTemplateId?e.get(o.consentTemplateId)??null:null,uiTemplateName:o.uiTemplateId?t.get(o.uiTemplateId)??null:null,createdAt:n.createdAt,updatedAt:n.updatedAt}})}function $e(i){let e=()=>({total:0,granted:0,denied:0,managed:0}),t=e(),n={},o=new Map;for(let r of i){let a=Object.values(r.consentJson),c=d=>a.length>0?a.filter(u=>u===d).length/a.length:0,l=c("granted")>=.9?"granted":c("denied")>=.9?"denied":"managed";o.has(r.day)||o.set(r.day,e()),n[r.locale]??=e();for(let d of[t,n[r.locale],o.get(r.day)])d.total++,d[l]++}let s=r=>t.total>0?Math.round(r/t.total*1e3)/10:0;return{...t,grantedPct:s(t.granted),deniedPct:s(t.denied),managedPct:s(t.managed),byLocale:n,byDate:Array.from(o,([r,a])=>({date:r,...a})).sort((r,a)=>r.date.localeCompare(a.date))}}function Qn(i){return i.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}function ke(i){return{id:i._id,tenantId:i.tenant_id,name:i.name,defaultLocale:i.default_locale,version:i.version,profileJson:i.profile_json,createdAt:i.created_at,updatedAt:i.updated_at}}function kt(i){return{id:i._id,tenantId:i.tenant_id,visitorId:i.visitor_id,profileId:i.profile_id,...i.profile_version!=null?{profileVersion:i.profile_version}:{},locale:i.locale,consentJson:i.consent_json,gpcDetected:i.gpc_detected,source:i.source,createdAt:i.created_at,updatedAt:i.updated_at,...i.age_verified!=null?{ageVerified:i.age_verified}:{},...i.parental_consent_token!=null?{parentalConsentToken:i.parental_consent_token}:{},...i.tcf_string!=null?{tcfString:i.tcf_string}:{},...i.gpp_string!=null?{gppString:i.gpp_string}:{},...i.signature!=null?{signature:i.signature}:{}}}var pl={tenant_id:1,visitor_id:1,profile_id:1,locale:1,gpc_detected:1,source:1,age_verified:1,created_at:1,updated_at:1};function ml(i){return{id:i._id,tenantId:i.tenant_id,visitorId:i.visitor_id,profileId:i.profile_id,locale:i.locale,gpcDetected:i.gpc_detected,source:i.source,createdAt:i.created_at,updatedAt:i.updated_at,...i.age_verified!=null?{ageVerified:i.age_verified}:{}}}function gl(i){return{id:i._id,tenantId:i.tenant_id,consentRecordId:i.consent_record_id,visitorId:i.visitor_id,oldJson:i.old_json,newJson:i.new_json,...i.profile_version!=null?{profileVersion:i.profile_version}:{},action:i.action,createdAt:i.created_at}}function Lt(i){return{id:i._id,tenantId:i.tenant_id,visitorId:i.visitor_id,...i.country!=null?{country:i.country}:{},...i.region!=null?{region:i.region}:{},...i.city!=null?{city:i.city}:{},...i.ip_hash!=null?{ipHash:i.ip_hash}:{},...i.user_agent_hash!=null?{userAgentHash:i.user_agent_hash}:{},firstSeen:i.first_seen,lastSeen:i.last_seen}}function st(i){return{id:i._id,tenantId:i.tenant_id,name:i.name,email:i.email,passwordHash:i.password_hash,isActive:i.is_active,createdAt:i.created_at,updatedAt:i.updated_at}}function Nt(i){return{id:i._id,tenantId:i.tenant_id,name:i.name,...i.description!=null?{description:i.description}:{}}}function Go(i){return{id:i._id,name:i.name,...i.description!=null?{description:i.description}:{}}}function jo(i){return{id:i._id,tenantId:i.tenant_id,action:i.action,resourceType:i.resource_type,...i.user_id!=null?{userId:i.user_id}:{},...i.resource_id!=null?{resourceId:i.resource_id}:{},...i.old_data!=null?{oldData:i.old_data}:{},...i.new_data!=null?{newData:i.new_data}:{},createdAt:i.created_at}}var fl={tenant_id:1,user_id:1,action:1,resource_type:1,resource_id:1,created_at:1};function hl(i){return{id:i._id,tenantId:i.tenant_id,action:i.action,resourceType:i.resource_type,...i.user_id!=null?{userId:i.user_id}:{},...i.resource_id!=null?{resourceId:i.resource_id}:{},createdAt:i.created_at}}var Fe=class{constructor(e){this.config=e}config;client;db;col(e){return this.db.collection(ce(e))}async connect(){let{MongoClient:e}=await import("mongodb"),t=this.config.uri??"mongodb://localhost:27017";this.client=new e(t,{maxPoolSize:this.config.poolMax??5}),await this.client.connect(),this.db=this.client.db(this.config.database??"consenti"),await this.migrate()}async disconnect(){await this.client.close()}async migrate(){await this.refuseLegacyCollections(),await this.createIndexes(),await this.seed()}async refuseLegacyCollections(){let e;try{e=new Set((await this.db.listCollections({},{nameOnly:!0}).toArray()).map(n=>n.name))}catch{return}let t=Se.filter(n=>n!=="schema_version");if(!e.has(ce("tenants"))&&t.every(n=>e.has(n)))throw Ue("collections")}async createIndexes(){for(let{table:e,cols:t,unique:n}of No){let o=Object.fromEntries(t.map(s=>[s,1]));await this.col(e).createIndex(o,n?{unique:!0}:void 0)}}async seed(){let e=async(s,r,a)=>{try{await this.col(s).updateOne(r,{$setOnInsert:a},{upsert:!0})}catch(c){if(c.code!==11e3)throw c}},{id:t,name:n,slug:o}=oe;await e("tenants",{_id:t},{_id:t,name:n,slug:o});for(let s of ie)await e("permissions",{_id:s.id},{_id:s.id,name:s.name,description:s.description});for(let s of he)await e("roles",{_id:s.id},{_id:s.id,tenant_id:s.tenantId,name:s.name,description:s.description});for(let{roleId:s,permissionId:r}of ye)await e("role_permissions",{role_id:s,permission_id:r},{role_id:s,permission_id:r})}async createProfile(e){let t=new Date().toISOString(),o={_id:K(),tenant_id:e.tenantId,name:e.name,default_locale:e.defaultLocale,version:1,profile_json:e.profileJson,created_at:t,updated_at:t};return await this.col("profiles").insertOne(o),ke(o)}async updateProfile(e,t){let o={updated_at:new Date().toISOString()};t.name!=null&&(o.name=t.name),t.defaultLocale!=null&&(o.default_locale=t.defaultLocale),t.profileJson!=null&&(o.profile_json=t.profileJson),t.version!=null&&(o.version=t.version);let s=await this.col("profiles").findOneAndUpdate({_id:e},{$set:o},{returnDocument:"after"});if(!s)throw new Error(`Profile ${e} not found`);return ke(s)}async deleteProfile(e){await this.col("profiles").deleteOne({_id:e})}async getProfile(e){let t=await this.col("profiles").findOne({_id:e});return t?ke(t):null}async getProfiles(e){return(await this.col("profiles").find({tenant_id:e}).toArray()).map(ke)}async findActiveProfileByComplianceGroup(e,t){return(await this.getProfiles(e)).find(o=>(o.profileJson.complianceGroup===t||o.profileJson.customComplianceGroup===t)&&o.profileJson.isActive)??null}async createConsent(e){let t=new Date().toISOString(),n={_id:Y(),tenant_id:e.tenantId,visitor_id:e.visitorId,profile_id:e.profileId,...e.profileVersion!=null?{profile_version:e.profileVersion}:{},locale:e.locale,consent_json:e.consentJson,gpc_detected:e.gpcDetected,source:e.source,created_at:t,updated_at:t,...e.ageVerified!=null?{age_verified:e.ageVerified}:{},...e.parentalConsentToken!=null?{parental_consent_token:e.parentalConsentToken}:{},...e.tcfString!=null?{tcf_string:e.tcfString}:{},...e.gppString!=null?{gpp_string:e.gppString}:{},...e.signature!=null?{signature:e.signature}:{}};return await this.col("consent_records").insertOne(n),await this.writeHistory(n._id,e.tenantId,e.visitorId,null,e.consentJson,"created",e.profileVersion),kt(n)}async updateConsent(e,t){let n=await this.getConsent(e);if(!n)throw new Error(`Consent for visitor ${e} not found`);let s={updated_at:new Date().toISOString(),consent_json:t.consentJson};t.profileVersion!=null&&(s.profile_version=t.profileVersion),t.locale!=null&&(s.locale=t.locale),t.gpcDetected!=null&&(s.gpc_detected=t.gpcDetected),t.signature!=null&&(s.signature=t.signature);let r=await this.col("consent_records").findOneAndUpdate({visitor_id:e},{$set:s},{returnDocument:"after"});if(!r)throw new Error(`Consent for visitor ${e} not found`);return await this.writeHistory(r._id,r.tenant_id,e,n.consentJson,t.consentJson,"updated",t.profileVersion??n.profileVersion),kt(r)}async deleteConsent(e){await this.col("consent_history").deleteMany({visitor_id:e}),await this.col("consent_records").deleteOne({visitor_id:e})}async getConsent(e){let t=await this.col("consent_records").findOne({visitor_id:e});return t?kt(t):null}async getConsents(e){let t=this.buildConsentFilter(e),n=e.page??1,o=e.limit??50,[s,r]=await Promise.all([this.col("consent_records").find(t,{projection:pl}).sort({created_at:-1}).skip((n-1)*o).limit(o).toArray(),this.col("consent_records").countDocuments(t)]);return{items:s.map(ml),total:r,page:n,limit:o}}async*streamConsents(e){let t=this.buildConsentFilter(e),n=this.col("consent_records").find(t).sort({created_at:1});for await(let o of n)yield kt(o)}buildConsentFilter(e){let t={tenant_id:e.tenantId};if(e.profileId!=null&&(t.profile_id=e.profileId),e.from!=null||e.to!=null){let n={};e.from!=null&&(n.$gte=e.from),e.to!=null&&(n.$lte=e.to),t.created_at=n}if(e.q){let n={$regex:"^"+Qn(e.q),$options:"i"};t.$or=[{visitor_id:n},{profile_id:n},{locale:n},{source:n}]}return t}async writeHistory(e,t,n,o,s,r,a){let c={_id:(0,C.randomUUID)(),tenant_id:t,consent_record_id:e,visitor_id:n,old_json:o,new_json:s,...a!=null?{profile_version:a}:{},action:r,created_at:new Date().toISOString()};await this.col("consent_history").insertOne(c)}async getConsentHistory(e){return(await this.col("consent_history").find({visitor_id:e}).sort({created_at:1}).toArray()).map(gl)}async createNoticeShown(e){let t={_id:(0,C.randomUUID)(),tenant_id:e.tenantId,visitor_id:e.visitorId,profile_id:e.profileId,locale:e.locale,created_at:new Date().toISOString()};return await this.col("notice_shown").insertOne(t),{id:t._id,tenantId:t.tenant_id,visitorId:t.visitor_id,profileId:t.profile_id,locale:t.locale,createdAt:t.created_at}}async getNoticeShownForVisitor(e){return(await this.col("notice_shown").find({visitor_id:e}).sort({created_at:-1}).toArray()).map(n=>({id:n._id,tenantId:n.tenant_id,visitorId:n.visitor_id,profileId:n.profile_id,locale:n.locale,createdAt:n.created_at}))}async createVisitor(e){let t=new Date().toISOString(),n={_id:q(),tenant_id:e.tenantId,visitor_id:e.visitorId,first_seen:t,last_seen:t,...e.country!=null?{country:e.country}:{},...e.region!=null?{region:e.region}:{},...e.city!=null?{city:e.city}:{},...e.ipHash!=null?{ip_hash:e.ipHash}:{},...e.userAgentHash!=null?{user_agent_hash:e.userAgentHash}:{}};return await this.col("visitors").insertOne(n),Lt(n)}async updateVisitor(e,t){let n={last_seen:t.lastSeen??new Date().toISOString()};t.country!=null&&(n.country=t.country),t.region!=null&&(n.region=t.region),t.city!=null&&(n.city=t.city);let o=await this.col("visitors").findOneAndUpdate({visitor_id:e},{$set:n},{returnDocument:"after"});if(!o)throw new Error(`Visitor ${e} not found`);return Lt(o)}async deleteVisitor(e){await this.col("visitors").deleteOne({visitor_id:e})}async getVisitor(e){let t=await this.col("visitors").findOne({visitor_id:e});return t?Lt(t):null}async getVisitors(e){let t={tenant_id:e.tenantId};if(e.from!=null||e.to!=null){let a={};e.from!=null&&(a.$gte=e.from),e.to!=null&&(a.$lte=e.to),t.first_seen=a}if(e.q){let a={$regex:"^"+Qn(e.q),$options:"i"};t.$or=[{visitor_id:a},{country:a}]}let n=e.page??1,o=e.limit??50,[s,r]=await Promise.all([this.col("visitors").find(t).sort({first_seen:-1}).skip((n-1)*o).limit(o).toArray(),this.col("visitors").countDocuments(t)]);return{items:s.map(Lt),total:r,page:n,limit:o}}async getOverviewStats(e){let[t,n,o]=await Promise.all([this.col("consent_records").countDocuments({tenant_id:e}),this.col("consent_records").countDocuments({tenant_id:e,gpc_detected:!0}),this.col("visitors").countDocuments({tenant_id:e})]),s=[{$match:{tenant_id:e}},{$addFields:{values:{$objectToArray:"$consent_json"}}},{$unwind:"$values"},{$group:{_id:"$values.v",count:{$sum:1}}}],r=await this.col("consent_records").aggregate(s).toArray(),a=0,c=0,l=0;for(let d of r)l+=d.count,d._id==="granted"&&(a=d.count),d._id==="denied"&&(c=d.count);return{totalConsents:t,acceptedPct:l>0?Math.round(a/l*100):0,rejectedPct:l>0?Math.round(c/l*100):0,totalVisitors:o,gpcDetectedCount:n}}async getCategoryStats(e){let t=[{$match:{tenant_id:e}},{$addFields:{pairs:{$objectToArray:"$consent_json"}}},{$unwind:"$pairs"},{$group:{_id:{cookie:"$pairs.k",status:"$pairs.v"},count:{$sum:1}}}],n=await this.col("consent_records").aggregate(t).toArray(),o={};for(let s of n){let r=s._id.cookie;o[r]||(o[r]={granted:0,denied:0,objected:0});let a=o[r];a&&(s._id.status==="granted"&&(a.granted+=s.count),s._id.status==="denied"&&(a.denied+=s.count),s._id.status==="objected"&&(a.objected+=s.count))}return o}async getTimeline(e,t=30){let n=new Date(Date.now()-t*864e5).toISOString(),o=[{$match:{tenant_id:e,created_at:{$gte:n}}},{$group:{_id:{$substr:["$created_at",0,10]},count:{$sum:1}}},{$sort:{_id:1}}];return(await this.col("consent_records").aggregate(o).toArray()).map(r=>({date:r._id,count:r.count}))}async createUser(e){let t=new Date().toISOString(),n={_id:(0,C.randomUUID)(),tenant_id:e.tenantId,name:e.name,email:e.email,password_hash:e.passwordHash,is_active:!0,created_at:t,updated_at:t};return await this.col("users").insertOne(n),st(n)}async updateUser(e,t){let n={updated_at:new Date().toISOString()};t.name!=null&&(n.name=t.name),t.email!=null&&(n.email=t.email),t.passwordHash!=null&&(n.password_hash=t.passwordHash),t.isActive!=null&&(n.is_active=t.isActive);let o=await this.col("users").findOneAndUpdate({_id:e},{$set:n},{returnDocument:"after"});if(!o)throw new Error(`User ${e} not found`);return st(o)}async deleteUser(e){await this.col("user_roles").deleteMany({user_id:e}),await this.col("users").deleteOne({_id:e})}async getUserById(e){let t=await this.col("users").findOne({_id:e});return t?st(t):null}async getUserByEmail(e){let t=await this.col("users").findOne({email:e});return t?st(t):null}async getUsers(e){return(await this.col("users").find({tenant_id:e}).toArray()).map(st)}async countUsers(e){return this.col("users").countDocuments(e?{tenant_id:e}:{})}async getRoles(e){return(await this.col("roles").find({tenant_id:e}).toArray()).map(Nt)}async createRole(e){let t={_id:(0,C.randomUUID)(),tenant_id:e.tenantId,name:e.name,...e.description!=null?{description:e.description}:{}};return await this.col("roles").insertOne(t),Nt(t)}async updateRole(e,t){let n={};t.name!=null&&(n.name=t.name),t.description!=null&&(n.description=t.description);let o=await this.col("roles").findOneAndUpdate({_id:e},{$set:n},{returnDocument:"after"});if(!o)throw new Error(`Role ${e} not found`);return Nt(o)}async deleteRole(e){await this.col("role_permissions").deleteMany({role_id:e}),await this.col("user_roles").deleteMany({role_id:e}),await this.col("roles").deleteOne({_id:e})}async getAllPermissions(){return(await this.col("permissions").find({}).toArray()).map(Go)}async getPermissionsForRole(e){let n=(await this.col("role_permissions").find({role_id:e}).toArray()).map(s=>s.permission_id);return n.length===0?[]:(await this.col("permissions").find({_id:{$in:n}}).toArray()).map(Go)}async getUserRoles(e,t){let n=t?{user_id:e,tenant_id:t}:{user_id:e},s=(await this.col("user_roles").find(n).toArray()).map(a=>a.role_id);return s.length===0?[]:(await this.col("roles").find({_id:{$in:s}}).toArray()).map(Nt)}async assignRole(e,t,n="default"){await this.col("user_roles").updateOne({user_id:e,role_id:t,tenant_id:n},{$setOnInsert:{user_id:e,role_id:t,tenant_id:n}},{upsert:!0})}async revokeRole(e,t,n){n?await this.col("user_roles").deleteOne({user_id:e,role_id:t,tenant_id:n}):await this.col("user_roles").deleteMany({user_id:e,role_id:t})}async assignPermissionToRole(e,t){await this.col("role_permissions").updateOne({role_id:e,permission_id:t},{$setOnInsert:{role_id:e,permission_id:t}},{upsert:!0})}async revokePermissionFromRole(e,t){await this.col("role_permissions").deleteOne({role_id:e,permission_id:t})}async createLog(e){let t={_id:(0,C.randomUUID)(),tenant_id:e.tenantId,action:e.action,resource_type:e.resourceType,...e.userId!=null?{user_id:e.userId}:{},...e.resourceId!=null?{resource_id:e.resourceId}:{},...e.oldData!=null?{old_data:e.oldData}:{},...e.newData!=null?{new_data:e.newData}:{},created_at:new Date().toISOString()};await this.col("audit_logs").insertOne(t)}async getLogs(e){let t=this.buildAuditFilter(e),n=e.page??1,o=e.limit??50,[s,r]=await Promise.all([this.col("audit_logs").find(t,{projection:fl}).sort({created_at:-1}).skip((n-1)*o).limit(o).toArray(),this.col("audit_logs").countDocuments(t)]);return{items:s.map(hl),total:r,page:n,limit:o}}async getAuditLogById(e){let t=await this.col("audit_logs").findOne({_id:e});return t?jo(t):null}async*streamAuditLogs(e){let t=this.buildAuditFilter(e),n=this.col("audit_logs").find(t).sort({created_at:1});for await(let o of n)yield jo(o)}buildAuditFilter(e){let t={tenant_id:e.tenantId};if(e.action!=null&&(t.action=e.action),e.resourceType!=null&&(t.resource_type=e.resourceType),e.from!=null||e.to!=null){let n={};e.from!=null&&(n.$gte=e.from),e.to!=null&&(n.$lte=e.to),t.created_at=n}if(e.q){let n={$regex:"^"+Qn(e.q),$options:"i"};t.$or=[{action:n},{resource_type:n},{resource_id:n},{user_id:n}]}return t}async getCountries(e){let t=[{$match:{tenant_id:e}},{$lookup:{from:ce("visitors"),localField:"visitor_id",foreignField:"visitor_id",as:"v"}},{$unwind:"$v"},{$match:{"v.country":{$ne:null}}},{$group:{_id:"$v.country",count:{$sum:1}}},{$sort:{count:-1}},{$limit:50}];return(await this.col("consent_records").aggregate(t).toArray()).map(o=>({country:o._id,count:o.count}))}async getGpcStats(e){let t=await this.col("consent_records").countDocuments({tenant_id:e}),n=await this.col("consent_records").countDocuments({tenant_id:e,gpc_detected:!0});return{detected:n,total:t,rate:t>0?Math.round(n/t*100):0}}async getTenants(){return(await this.col("tenants").find({}).toArray()).map(t=>({id:t._id,name:t.name,slug:t.slug,createdAt:t.created_at,updatedAt:t.updated_at}))}mapApiKey(e){return{id:e._id,tenantId:e.tenant_id,keyHash:e.key_hash,name:e.name,isActive:e.is_active,...e.created_by!==void 0?{createdBy:e.created_by}:{},...e.expire_by!==void 0?{expireBy:e.expire_by}:{},createdAt:e.created_at,...e.updated_at!==void 0?{updatedAt:e.updated_at}:{}}}async createApiKey(e){let t=new Date().toISOString(),n={_id:(0,C.randomUUID)(),tenant_id:e.tenantId,key_hash:e.keyHash,name:e.name,is_active:!0,...e.createdBy!==void 0?{created_by:e.createdBy}:{},...e.expireBy!==void 0?{expire_by:e.expireBy}:{},created_at:t,updated_at:t};return await this.col("api_keys").insertOne(n),this.mapApiKey(n)}async getApiKeyByHash(e){let t=await this.col("api_keys").findOne({key_hash:e,is_active:!0});return t?this.mapApiKey(t):null}async revokeApiKey(e){await this.col("api_keys").updateOne({_id:e},{$set:{is_active:!1,updated_at:new Date().toISOString()}})}async reactivateApiKey(e){let t=await this.col("api_keys").findOne({_id:e});if(!t)return;let n=t.expire_by&&new Date(t.expire_by)<=new Date;await this.col("api_keys").updateOne({_id:e},{$set:{is_active:!0,updated_at:new Date().toISOString()},...n?{$unset:{expire_by:""}}:{}})}async deleteApiKey(e){await this.col("api_keys").deleteOne({_id:e})}async getApiKeys(e){return(await this.col("api_keys").find({tenant_id:e}).sort({created_at:-1}).toArray()).map(n=>this.mapApiKey(n))}async createTenant(e){let t=(0,C.randomUUID)(),n=new Date().toISOString(),o={_id:t,name:e.name,slug:e.slug,created_at:n,updated_at:n};return await this.col("tenants").insertOne(o),{id:t,name:e.name,slug:e.slug,createdAt:n,updatedAt:n}}async updateTenant(e,t){let o={updated_at:new Date().toISOString()};t.name!=null&&(o.name=t.name),t.slug!=null&&(o.slug=t.slug),await this.col("tenants").updateOne({_id:e},{$set:o});let s=await this.col("tenants").findOne({_id:e});if(!s)throw new Error(`Tenant ${e} not found`);return{id:s._id,name:s.name,slug:s.slug,createdAt:s.created_at,updatedAt:s.updated_at}}async deleteTenant(e){await this.col("tenants").deleteOne({_id:e})}async getSettings(e){let t=await this.col("tenant_settings").findOne({_id:e});return{...t?.allowed_origins!==void 0?{allowedOrigins:t.allowed_origins}:{},...t?.admin_allowed_origins!==void 0?{adminAllowedOrigins:t.admin_allowed_origins}:{},...t?.setup_completed!==void 0?{setupCompleted:t.setup_completed}:{},...t?.profiles_seeded!==void 0?{profilesSeeded:t.profiles_seeded}:{},...t?.tcf_confirmation!==void 0?{tcfConfirmation:t.tcf_confirmation}:{},...t?.gpp_confirmation!==void 0?{gppConfirmation:t.gpp_confirmation}:{}}}async updateSettings(e,t){let n={updated_at:new Date().toISOString()};return t.allowedOrigins!==void 0&&(n.allowed_origins=t.allowedOrigins),t.adminAllowedOrigins!==void 0&&(n.admin_allowed_origins=t.adminAllowedOrigins),t.setupCompleted!==void 0&&(n.setup_completed=t.setupCompleted),t.profilesSeeded!==void 0&&(n.profiles_seeded=t.profilesSeeded),t.tcfConfirmation!==void 0&&(n.tcf_confirmation=t.tcfConfirmation),t.gppConfirmation!==void 0&&(n.gpp_confirmation=t.gppConfirmation),await this.col("tenant_settings").updateOne({_id:e},{$set:n},{upsert:!0}),this.getSettings(e)}async purgeExpiredConsents(e){let t=new Date(Date.now()-e*864e5).toISOString(),n=await this.col("consent_records").find({created_at:{$lt:t}}).toArray();if(n.length===0)return 0;let o=n.map(s=>s.visitor_id);return await this.col("consent_history").deleteMany({visitor_id:{$in:o}}),await this.col("consent_records").deleteMany({visitor_id:{$in:o}}),n.length}mapConsentTemplate(e){return{id:e._id,tenantId:e.tenant_id,name:e.name,cookies:e.cookies_json,categories:e.categories_json,createdAt:e.created_at,updatedAt:e.updated_at}}async createConsentTemplate(e){let t=new Date().toISOString(),n={_id:Q(),tenant_id:e.tenantId,name:e.name,cookies_json:e.cookies,categories_json:e.categories,created_at:t,updated_at:t};return await this.col("consent_templates").insertOne(n),this.mapConsentTemplate(n)}async updateConsentTemplate(e,t){let n={updated_at:new Date().toISOString()};t.name!==void 0&&(n.name=t.name),t.cookies!==void 0&&(n.cookies_json=t.cookies),t.categories!==void 0&&(n.categories_json=t.categories);let o=await this.col("consent_templates").findOneAndUpdate({_id:e},{$set:n},{returnDocument:"after"});if(!o)throw new Error("Consent template not found");return this.mapConsentTemplate(o)}async deleteConsentTemplate(e){await this.col("consent_templates").deleteOne({_id:e})}async getConsentTemplate(e){let t=await this.col("consent_templates").findOne({_id:e});return t?this.mapConsentTemplate(t):null}async getConsentTemplates(e){return(await this.col("consent_templates").find({tenant_id:e}).sort({name:1}).toArray()).map(n=>this.mapConsentTemplate(n))}async copyConsentTemplate(e,t){let n=await this.getConsentTemplate(e);if(!n)throw new Error("Consent template not found");return this.createConsentTemplate({tenantId:n.tenantId,name:t,cookies:n.cookies,categories:n.categories})}mapUITemplate(e){return{id:e._id,tenantId:e.tenant_id,name:e.name,...e.settings_json,createdAt:e.created_at,updatedAt:e.updated_at}}async createUITemplate(e){let t=new Date().toISOString(),{tenantId:n,name:o,...s}=e,r={_id:Z(),tenant_id:n,name:o,settings_json:s,created_at:t,updated_at:t};return await this.col("ui_templates").insertOne(r),this.mapUITemplate(r)}async updateUITemplate(e,t){let n=await this.col("ui_templates").findOne({_id:e});if(!n)throw new Error("UI template not found");let{name:o,...s}=t,r={updated_at:new Date().toISOString()};o!==void 0&&(r.name=o),Object.keys(s).length>0&&(r.settings_json={...n.settings_json,...s});let a=await this.col("ui_templates").findOneAndUpdate({_id:e},{$set:r},{returnDocument:"after"});if(!a)throw new Error("UI template not found");return this.mapUITemplate(a)}async deleteUITemplate(e){await this.col("ui_templates").deleteOne({_id:e})}async getUITemplate(e){let t=await this.col("ui_templates").findOne({_id:e});return t?this.mapUITemplate(t):null}async getUITemplates(e){return(await this.col("ui_templates").find({tenant_id:e}).sort({name:1}).toArray()).map(n=>this.mapUITemplate(n))}async copyUITemplate(e,t){let n=await this.getUITemplate(e);if(!n)throw new Error("UI template not found");let{tenantId:o,mainBanner:s,gpcBanner:r,preferenceModal:a}=n;return this.createUITemplate({tenantId:o,name:t,mainBanner:s,gpcBanner:r,preferenceModal:a})}async toProfileSummaries(e){if(e.length===0)return[];let t=[...new Set(e.map(s=>s.tenantId))],[n,o]=await Promise.all([Promise.all(t.map(s=>this.getConsentTemplates(s))),Promise.all(t.map(s=>this.getUITemplates(s)))]);return Be(e,new Map(n.flat().map(s=>[s.id,s.name])),new Map(o.flat().map(s=>[s.id,s.name])))}async listProfilesSummary(e){let t=await this.col("profiles").find({tenant_id:e}).sort({created_at:1}).toArray();return this.toProfileSummaries(t.map(ke))}async findProfilesUsingConsentTemplate(e){let t=await this.col("profiles").find({"profile_json.consentTemplateId":e}).sort({name:1}).toArray();return this.toProfileSummaries(t.map(ke))}async findProfilesUsingUITemplate(e){let t=await this.col("profiles").find({"profile_json.uiTemplateId":e}).sort({name:1}).toArray();return this.toProfileSummaries(t.map(ke))}async getOptInStats(e,t){let n={tenant_id:e};t.profileId&&(n.profile_id=t.profileId),t.locale&&(n.locale=t.locale),(t.from||t.to)&&(n.created_at={...t.from?{$gte:t.from}:{},...t.to?{$lte:t.to}:{}});let o=await this.col("consent_records").find(n,{projection:{locale:1,consent_json:1,created_at:1}}).sort({created_at:1}).toArray();return $e(o.map(s=>({locale:s.locale,day:s.created_at.slice(0,10),consentJson:s.consent_json})))}};p();function Le(i){return{id:i.id,tenantId:i.tenant_id,name:i.name,defaultLocale:i.default_locale,version:i.version,profileJson:JSON.parse(i.profile_json),createdAt:i.created_at,updatedAt:i.updated_at}}function xt(i){return{id:i.id,tenantId:i.tenant_id,visitorId:i.visitor_id,profileId:i.profile_id,...i.profile_version!=null?{profileVersion:i.profile_version}:{},locale:i.locale,consentJson:JSON.parse(i.consent_json),gpcDetected:i.gpc_detected===1,source:i.source,createdAt:i.created_at,updatedAt:i.updated_at,...i.age_verified!=null?{ageVerified:i.age_verified===1}:{},...i.parental_consent_token!=null?{parentalConsentToken:i.parental_consent_token}:{},...i.tcf_string!=null?{tcfString:i.tcf_string}:{},...i.gpp_string!=null?{gppString:i.gpp_string}:{},...i.signature!=null?{signature:i.signature}:{}}}var yl="id, tenant_id, visitor_id, profile_id, locale, gpc_detected, source, age_verified, created_at, updated_at";function _l(i){return{id:i.id,tenantId:i.tenant_id,visitorId:i.visitor_id,profileId:i.profile_id,locale:i.locale,gpcDetected:i.gpc_detected===1,source:i.source,createdAt:i.created_at,updatedAt:i.updated_at,...i.age_verified!=null?{ageVerified:i.age_verified===1}:{}}}function wl(i){return{id:i.id,tenantId:i.tenant_id,consentRecordId:i.consent_record_id,visitorId:i.visitor_id,...i.profile_version!=null?{profileVersion:i.profile_version}:{},oldJson:i.old_json?JSON.parse(i.old_json):null,newJson:JSON.parse(i.new_json),action:i.action,createdAt:i.created_at}}function Ut(i){return{id:i.id,tenantId:i.tenant_id,visitorId:i.visitor_id,...i.country!=null?{country:i.country}:{},...i.region!=null?{region:i.region}:{},...i.city!=null?{city:i.city}:{},...i.ip_hash!=null?{ipHash:i.ip_hash}:{},...i.user_agent_hash!=null?{userAgentHash:i.user_agent_hash}:{},firstSeen:i.first_seen,lastSeen:i.last_seen}}function rt(i){return{id:i.id,tenantId:i.tenant_id,name:i.name,email:i.email,passwordHash:i.password_hash,isActive:i.is_active===1,createdAt:i.created_at,updatedAt:i.updated_at,totpEnabled:i.totp_enabled===1,...i.totp_secret!=null?{totpSecret:i.totp_secret}:{}}}function Mt(i){return{id:i.id,tenantId:i.tenant_id,name:i.name,...i.description!=null?{description:i.description}:{}}}function Bo(i){return{id:i.id,name:i.name,...i.description!=null?{description:i.description}:{}}}function $o(i){return{id:i.id,tenantId:i.tenant_id,action:i.action,resourceType:i.resource_type,...i.user_id!=null?{userId:i.user_id}:{},...i.resource_id!=null?{resourceId:i.resource_id}:{},...i.old_data!=null?{oldData:JSON.parse(i.old_data)}:{},...i.new_data!=null?{newData:JSON.parse(i.new_data)}:{},createdAt:i.created_at}}var El="id, tenant_id, user_id, action, resource_type, resource_id, created_at";function Rl(i){return{id:i.id,tenantId:i.tenant_id,action:i.action,resourceType:i.resource_type,...i.user_id!=null?{userId:i.user_id}:{},...i.resource_id!=null?{resourceId:i.resource_id}:{},createdAt:i.created_at}}function Zn(i=new Date){return i.toISOString().slice(0,19).replace("T"," ")}var He=class{constructor(e){this.config=e}config;pool;async q(e,t=[]){let n=this.config.statementTimeoutMs,[o]=n?await this.pool.query({sql:e,timeout:n},t):await this.pool.query(e,t);return o}async exec(e,t=[]){let n=this.config.statementTimeoutMs,[o]=n?await this.pool.query({sql:e,timeout:n},t):await this.pool.query(e,t);return o}async connect(){let e=await import("mysql2/promise"),t=this.config;this.pool=e.createPool({...t.uri?{uri:t.uri}:{host:t.host??"localhost",port:t.port??3306,user:t.user??"root",password:t.password??"",database:t.database??"consenti"},connectionLimit:t.poolMax??5}),await this.migrate()}async disconnect(){await this.pool.end()}async migrate(){let e=await this.pool.getConnection(),t="CONCAT('consenti_schema_', IFNULL(DATABASE(), ''))";try{let[[n]]=await e.query(`SELECT GET_LOCK(${t}, 60) AS got`);if(n?.got!==1)throw new Error("[consenti] Timed out waiting for another Consenti instance to finish setting up the database schema.");let[o]=await e.query("SELECT TABLE_NAME AS name FROM information_schema.TABLES WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME IN (?)",[["consenti_schema_version",...Se]]),s=new Set(o.map(r=>String(r.name)));if(!s.has("consenti_schema_version")&&Se.every(r=>s.has(r)))throw Ue("tables");if(s.has("consenti_schema_version")){let[r]=await e.query("SELECT MAX(version) AS version FROM consenti_schema_version");if((r[0]?.version??0)<2)try{await this.migrateToV2(e)}catch(a){throw new Error(`Upgrading the database schema to v2 failed: ${a instanceof Error?a.message:String(a)}. The database user needs the ALTER privilege. This step only changes table structure, never rows, and is safe to re-run: fix the cause and start again.`,{cause:a})}}else{try{for(let r of Uo.split(";").map(a=>a.trim()).filter(Boolean))await e.query(r);await this.seed(e)}catch(r){throw new Error(`Creating the Consenti tables failed: ${r instanceof Error?r.message:String(r)}. The database user needs SELECT, INSERT, UPDATE, DELETE, CREATE, ALTER, INDEX and REFERENCES on this database (it never creates databases or users). Safe to re-run: fix the cause and start again.`,{cause:r})}await e.query("INSERT IGNORE INTO consenti_schema_version (version) VALUES (?)",[le])}}finally{try{await e.query(`SELECT RELEASE_LOCK(${t})`)}catch{}e.release()}}async migrateToV2(e){let[t]=await e.query(`SELECT TABLE_NAME AS tbl, CONSTRAINT_NAME AS name FROM information_schema.KEY_COLUMN_USAGE
92
+ WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME IN ('consenti_consent_records','consenti_notice_shown')
93
+ AND COLUMN_NAME = 'profile_id' AND REFERENCED_TABLE_NAME = 'consenti_profiles'`);for(let n of t)await e.query(`ALTER TABLE \`${String(n.tbl)}\` DROP FOREIGN KEY \`${String(n.name).replace(/`/g,"``")}\``);for(let n of["consenti_consent_records","consenti_consent_history"]){let[o]=await e.query(`SELECT 1 FROM information_schema.COLUMNS
94
+ WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = ? AND COLUMN_NAME = 'profile_version'`,[n]);o.length===0&&await e.query(`ALTER TABLE ${n} ADD COLUMN profile_version INT NULL`)}await e.query("INSERT IGNORE INTO consenti_schema_version (version) VALUES (?)",[le])}async seed(e){await e.query("INSERT IGNORE INTO consenti_tenants (id, name, slug) VALUES (?,?,?)",[oe.id,oe.name,oe.slug]);for(let t of ie)await e.query("INSERT IGNORE INTO consenti_permissions (id, name, description) VALUES (?,?,?)",[t.id,t.name,t.description]);for(let t of he)await e.query("INSERT IGNORE INTO consenti_roles (id, tenant_id, name, description) VALUES (?,?,?,?)",[t.id,t.tenantId,t.name,t.description]);for(let{roleId:t,permissionId:n}of ye)await e.query("INSERT IGNORE INTO consenti_role_permissions (role_id, permission_id) VALUES (?,?)",[t,n])}async createProfile(e){let t=K();await this.exec("INSERT INTO consenti_profiles (id, tenant_id, name, default_locale, version, profile_json) VALUES (?,?,?,?,?,?)",[t,e.tenantId,e.name,e.defaultLocale,1,JSON.stringify(e.profileJson)]);let o=(await this.q("SELECT * FROM consenti_profiles WHERE id=?",[t]))[0];if(!o)throw new Error("Profile creation failed");return Le(o)}async updateProfile(e,t){let n=[],o=[];t.name!=null&&(n.push("name=?"),o.push(t.name)),t.defaultLocale!=null&&(n.push("default_locale=?"),o.push(t.defaultLocale)),t.profileJson!=null&&(n.push("profile_json=?"),o.push(JSON.stringify(t.profileJson))),t.version!=null&&(n.push("version=?"),o.push(t.version)),n.length>0&&(o.push(e),await this.exec(`UPDATE consenti_profiles SET ${n.join(",")} WHERE id=?`,o));let r=(await this.q("SELECT * FROM consenti_profiles WHERE id=?",[e]))[0];if(!r)throw new Error(`Profile ${e} not found`);return Le(r)}async deleteProfile(e){await this.exec("DELETE FROM consenti_profiles WHERE id=?",[e])}async getProfile(e){let t=await this.q("SELECT * FROM consenti_profiles WHERE id=?",[e]);return t[0]?Le(t[0]):null}async getProfiles(e){return(await this.q("SELECT * FROM consenti_profiles WHERE tenant_id=? ORDER BY created_at DESC",[e])).map(Le)}async findActiveProfileByComplianceGroup(e,t){return(await this.getProfiles(e)).find(o=>(o.profileJson.complianceGroup===t||o.profileJson.customComplianceGroup===t)&&o.profileJson.isActive)??null}async createConsent(e){let t=Y();await this.exec("INSERT INTO consenti_consent_records (id, tenant_id, visitor_id, profile_id, profile_version, locale, consent_json, gpc_detected, source, age_verified, parental_consent_token, tcf_string, gpp_string, signature) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?)",[t,e.tenantId,e.visitorId,e.profileId,e.profileVersion??null,e.locale,JSON.stringify(e.consentJson),e.gpcDetected?1:0,e.source,e.ageVerified?1:0,e.parentalConsentToken??null,e.tcfString??null,e.gppString??null,e.signature??null]);let o=(await this.q("SELECT * FROM consenti_consent_records WHERE id=?",[t]))[0];if(!o)throw new Error("Consent creation failed");return await this.writeHistory(t,e.tenantId,e.visitorId,null,e.consentJson,"created",e.profileVersion??null),xt(o)}async updateConsent(e,t){let n=await this.getConsent(e);if(!n)throw new Error(`Consent for visitor ${e} not found`);let o=["consent_json=?"],s=[JSON.stringify(t.consentJson)];t.profileVersion!=null&&(o.push("profile_version=?"),s.push(t.profileVersion)),t.locale!=null&&(o.push("locale=?"),s.push(t.locale)),t.gpcDetected!=null&&(o.push("gpc_detected=?"),s.push(t.gpcDetected?1:0)),t.signature!=null&&(o.push("signature=?"),s.push(t.signature)),s.push(e),await this.exec(`UPDATE consenti_consent_records SET ${o.join(",")} WHERE visitor_id=?`,s);let a=(await this.q("SELECT * FROM consenti_consent_records WHERE visitor_id=?",[e]))[0];if(!a)throw new Error(`Consent for visitor ${e} not found`);return await this.writeHistory(a.id,a.tenant_id,e,n.consentJson,t.consentJson,"updated",t.profileVersion??n.profileVersion??null),xt(a)}async deleteConsent(e){await this.exec("DELETE FROM consenti_consent_history WHERE visitor_id=?",[e]),await this.exec("DELETE FROM consenti_consent_records WHERE visitor_id=?",[e])}async getConsent(e){let t=await this.q("SELECT * FROM consenti_consent_records WHERE visitor_id=?",[e]);return t[0]?xt(t[0]):null}async getConsents(e){let{where:t,params:n}=this.buildConsentWhere(e),o=e.page??1,s=e.limit??50,[r,a]=await Promise.all([this.q(`SELECT ${yl} ${t} ORDER BY created_at DESC LIMIT ? OFFSET ?`,[...n,s,(o-1)*s]),this.q(`SELECT COUNT(*) AS total ${t}`,n)]);return{items:r.map(_l),total:a[0]?.total??0,page:o,limit:s}}async*streamConsents(e){let{where:t,params:n}=this.buildConsentWhere(e),o=await this.q(`SELECT * ${t} ORDER BY created_at ASC`,n);for(let s of o)yield xt(s)}buildConsentWhere(e){let t="FROM consenti_consent_records WHERE tenant_id=?",n=[e.tenantId];if(e.profileId!=null&&(t+=" AND profile_id=?",n.push(e.profileId)),e.from!=null&&(t+=" AND created_at>=?",n.push(e.from)),e.to!=null&&(t+=" AND created_at<=?",n.push(e.to)),e.q){t+=" AND (visitor_id LIKE ? OR profile_id LIKE ? OR locale LIKE ? OR source LIKE ?)";let o=j(e.q);n.push(o,o,o,o)}return{where:t,params:n}}async writeHistory(e,t,n,o,s,r,a){await this.exec("INSERT INTO consenti_consent_history (id, tenant_id, consent_record_id, visitor_id, profile_version, old_json, new_json, action) VALUES (?,?,?,?,?,?,?,?)",[(0,C.randomUUID)(),t,e,n,a,o?JSON.stringify(o):null,JSON.stringify(s),r])}async getConsentHistory(e){return(await this.q("SELECT * FROM consenti_consent_history WHERE visitor_id=? ORDER BY created_at ASC",[e])).map(wl)}async createNoticeShown(e){let t=(0,C.randomUUID)();await this.exec("INSERT INTO consenti_notice_shown (id, tenant_id, visitor_id, profile_id, locale) VALUES (?,?,?,?,?)",[t,e.tenantId,e.visitorId,e.profileId,e.locale]);let o=(await this.q("SELECT * FROM consenti_notice_shown WHERE id=?",[t]))[0];return{id:o.id,tenantId:o.tenant_id,visitorId:o.visitor_id,profileId:o.profile_id,locale:o.locale,createdAt:o.created_at}}async getNoticeShownForVisitor(e){return(await this.q("SELECT * FROM consenti_notice_shown WHERE visitor_id=? ORDER BY created_at DESC",[e])).map(n=>({id:n.id,tenantId:n.tenant_id,visitorId:n.visitor_id,profileId:n.profile_id,locale:n.locale,createdAt:n.created_at}))}async createVisitor(e){let t=q();await this.exec("INSERT INTO consenti_visitors (id, tenant_id, visitor_id, country, region, city, ip_hash, user_agent_hash) VALUES (?,?,?,?,?,?,?,?)",[t,e.tenantId,e.visitorId,e.country??null,e.region??null,e.city??null,e.ipHash??null,e.userAgentHash??null]);let o=(await this.q("SELECT * FROM consenti_visitors WHERE id=?",[t]))[0];if(!o)throw new Error("Visitor creation failed");return Ut(o)}async updateVisitor(e,t){let n=["last_seen=NOW()"],o=[];t.country!=null&&(n.push("country=?"),o.push(t.country)),t.region!=null&&(n.push("region=?"),o.push(t.region)),t.city!=null&&(n.push("city=?"),o.push(t.city)),o.push(e),await this.exec(`UPDATE consenti_visitors SET ${n.join(",")} WHERE visitor_id=?`,o);let r=(await this.q("SELECT * FROM consenti_visitors WHERE visitor_id=?",[e]))[0];if(!r)throw new Error(`Visitor ${e} not found`);return Ut(r)}async deleteVisitor(e){await this.exec("DELETE FROM consenti_visitors WHERE visitor_id=?",[e])}async getVisitor(e){let t=await this.q("SELECT * FROM consenti_visitors WHERE visitor_id=?",[e]);return t[0]?Ut(t[0]):null}async getVisitors(e){let t="FROM consenti_visitors WHERE tenant_id=?",n=[e.tenantId];if(e.from!=null&&(t+=" AND first_seen>=?",n.push(e.from)),e.to!=null&&(t+=" AND first_seen<=?",n.push(e.to)),e.q){t+=" AND (visitor_id LIKE ? OR country LIKE ?)";let c=j(e.q);n.push(c,c)}let o=e.page??1,s=e.limit??50,[r,a]=await Promise.all([this.q(`SELECT * ${t} ORDER BY first_seen DESC LIMIT ? OFFSET ?`,[...n,s,(o-1)*s]),this.q(`SELECT COUNT(*) AS total ${t}`,n)]);return{items:r.map(Ut),total:a[0]?.total??0,page:o,limit:s}}async getOverviewStats(e){let[[t],[n],[o]]=await Promise.all([this.q("SELECT COUNT(*) AS total FROM consenti_consent_records WHERE tenant_id=?",[e]),this.q("SELECT COUNT(*) AS total FROM consenti_consent_records WHERE tenant_id=? AND gpc_detected=1",[e]),this.q("SELECT COUNT(*) AS total FROM consenti_visitors WHERE tenant_id=?",[e])]),s=t?.total??0,r=n?.total??0,a=o?.total??0,c=await this.q(`SELECT jt.status, COUNT(*) AS count
95
+ FROM consenti_consent_records cr
96
96
  JOIN JSON_TABLE(cr.consent_json, '$.*' COLUMNS (status VARCHAR(20) PATH '$')) AS jt
97
97
  WHERE cr.tenant_id=?
98
98
  GROUP BY jt.status`,[e]),l=0,d=0,u=0;for(let m of c)u+=m.count,m.status==="granted"&&(l=m.count),m.status==="denied"&&(d=m.count);return{totalConsents:s,acceptedPct:u>0?Math.round(l/u*100):0,rejectedPct:u>0?Math.round(d/u*100):0,totalVisitors:a,gpcDetectedCount:r}}async getCategoryStats(e){let t=await this.q(`SELECT jt.cookie_id, jt.status, COUNT(*) AS count
99
- FROM consent_records cr
99
+ FROM consenti_consent_records cr
100
100
  JOIN JSON_TABLE(cr.consent_json, '$.*' COLUMNS (NESTED PATH '$' COLUMNS (
101
101
  cookie_id VARCHAR(100) PATH '$.k',
102
102
  status VARCHAR(20) PATH '$.v'
103
103
  ))) AS jt
104
104
  WHERE cr.tenant_id=?
105
105
  GROUP BY jt.cookie_id, jt.status`,[e]),n={};for(let o of t){n[o.cookie_id]||(n[o.cookie_id]={granted:0,denied:0,objected:0});let s=n[o.cookie_id];s&&(o.status==="granted"&&(s.granted+=o.count),o.status==="denied"&&(s.denied+=o.count),o.status==="objected"&&(s.objected+=o.count))}return n}async getTimeline(e,t=30){let n=new Date(Date.now()-t*864e5).toISOString().slice(0,10);return(await this.q(`SELECT DATE_FORMAT(created_at, '%Y-%m-%d') AS date, COUNT(*) AS count
106
- FROM consent_records WHERE tenant_id=? AND created_at>=?
107
- GROUP BY DATE_FORMAT(created_at, '%Y-%m-%d') ORDER BY date ASC`,[e,n])).map(s=>({date:s.date,count:s.count}))}async createUser(e){let t=(0,v.randomUUID)();await this.exec("INSERT INTO users (id, tenant_id, name, email, password_hash) VALUES (?,?,?,?,?)",[t,e.tenantId,e.name,e.email,e.passwordHash]);let o=(await this.q("SELECT * FROM users WHERE id=?",[t]))[0];if(!o)throw new Error("User creation failed");return et(o)}async updateUser(e,t){let n=[],o=[];t.name!=null&&(n.push("name=?"),o.push(t.name)),t.email!=null&&(n.push("email=?"),o.push(t.email)),t.passwordHash!=null&&(n.push("password_hash=?"),o.push(t.passwordHash)),t.isActive!=null&&(n.push("is_active=?"),o.push(t.isActive?1:0)),n.length>0&&(o.push(e),await this.exec(`UPDATE users SET ${n.join(",")} WHERE id=?`,o));let r=(await this.q("SELECT * FROM users WHERE id=?",[e]))[0];if(!r)throw new Error(`User ${e} not found`);return et(r)}async deleteUser(e){await this.exec("DELETE FROM user_roles WHERE user_id=?",[e]),await this.exec("DELETE FROM users WHERE id=?",[e])}async getUserById(e){let t=await this.q("SELECT * FROM users WHERE id=?",[e]);return t[0]?et(t[0]):null}async getUserByEmail(e){let t=await this.q("SELECT * FROM users WHERE email=?",[e]);return t[0]?et(t[0]):null}async getUsers(e){return(await this.q("SELECT * FROM users WHERE tenant_id=? ORDER BY created_at DESC",[e])).map(et)}async countUsers(e){return(e?await this.q("SELECT COUNT(*) AS total FROM users WHERE tenant_id=?",[e]):await this.q("SELECT COUNT(*) AS total FROM users"))[0]?.total??0}async getRoles(e){return(await this.q("SELECT * FROM roles WHERE tenant_id=?",[e])).map(Ot)}async createRole(e){let t=(0,v.randomUUID)();await this.exec("INSERT INTO roles (id, tenant_id, name, description) VALUES (?,?,?,?)",[t,e.tenantId,e.name,e.description??null]);let o=(await this.q("SELECT * FROM roles WHERE id=?",[t]))[0];if(!o)throw new Error("Role creation failed");return Ot(o)}async updateRole(e,t){let n=[],o=[];t.name!=null&&(n.push("name=?"),o.push(t.name)),t.description!=null&&(n.push("description=?"),o.push(t.description)),n.length>0&&(o.push(e),await this.exec(`UPDATE roles SET ${n.join(",")} WHERE id=?`,o));let r=(await this.q("SELECT * FROM roles WHERE id=?",[e]))[0];if(!r)throw new Error(`Role ${e} not found`);return Ot(r)}async deleteRole(e){await this.exec("DELETE FROM role_permissions WHERE role_id=?",[e]),await this.exec("DELETE FROM user_roles WHERE role_id=?",[e]),await this.exec("DELETE FROM roles WHERE id=?",[e])}async getAllPermissions(){return(await this.q("SELECT * FROM permissions ORDER BY name")).map(Ro)}async getPermissionsForRole(e){return(await this.q("SELECT p.* FROM permissions p JOIN role_permissions rp ON p.id=rp.permission_id WHERE rp.role_id=?",[e])).map(Ro)}async getUserRoles(e,t){return(t?await this.q("SELECT r.* FROM roles r JOIN user_roles ur ON r.id=ur.role_id WHERE ur.user_id=? AND ur.tenant_id=?",[e,t]):await this.q("SELECT r.* FROM roles r JOIN user_roles ur ON r.id=ur.role_id WHERE ur.user_id=?",[e])).map(Ot)}async assignRole(e,t,n="default"){await this.exec("INSERT IGNORE INTO user_roles (user_id, role_id, tenant_id) VALUES (?,?,?)",[e,t,n])}async revokeRole(e,t,n){n?await this.exec("DELETE FROM user_roles WHERE user_id=? AND role_id=? AND tenant_id=?",[e,t,n]):await this.exec("DELETE FROM user_roles WHERE user_id=? AND role_id=?",[e,t])}async assignPermissionToRole(e,t){await this.exec("INSERT IGNORE INTO role_permissions (role_id, permission_id) VALUES (?,?)",[e,t])}async revokePermissionFromRole(e,t){await this.exec("DELETE FROM role_permissions WHERE role_id=? AND permission_id=?",[e,t])}async createLog(e){await this.exec("INSERT INTO audit_logs (id, tenant_id, user_id, action, resource_type, resource_id, old_data, new_data) VALUES (?,?,?,?,?,?,?,?)",[(0,v.randomUUID)(),e.tenantId,e.userId??null,e.action,e.resourceType,e.resourceId??null,e.oldData!=null?JSON.stringify(e.oldData):null,e.newData!=null?JSON.stringify(e.newData):null])}async getLogs(e){let{where:t,params:n}=this.buildAuditWhere(e),o=e.page??1,s=e.limit??50,[r,a]=await Promise.all([this.q(`SELECT ${zc} ${t} ORDER BY created_at DESC LIMIT ? OFFSET ?`,[...n,s,(o-1)*s]),this.q(`SELECT COUNT(*) AS total ${t}`,n)]);return{items:r.map(Kc),total:a[0]?.total??0,page:o,limit:s}}async getAuditLogById(e){let t=await this.q("SELECT * FROM audit_logs WHERE id=?",[e]);return t[0]?So(t[0]):null}async*streamAuditLogs(e){let{where:t,params:n}=this.buildAuditWhere(e),o=await this.q(`SELECT * ${t} ORDER BY created_at ASC`,n);for(let s of o)yield So(s)}buildAuditWhere(e){let t="FROM audit_logs WHERE tenant_id=?",n=[e.tenantId];if(e.action!=null&&(t+=" AND action=?",n.push(e.action)),e.resourceType!=null&&(t+=" AND resource_type=?",n.push(e.resourceType)),e.from!=null&&(t+=" AND created_at>=?",n.push(e.from)),e.to!=null&&(t+=" AND created_at<=?",n.push(e.to)),e.q){t+=" AND (action LIKE ? OR resource_type LIKE ? OR resource_id LIKE ? OR user_id LIKE ?) ESCAPE '\\\\'";let o=j(e.q);n.push(o,o,o,o)}return{where:t,params:n}}async getCountries(e){return(await this.q(`SELECT v.country, COUNT(*) AS count FROM consent_records cr
108
- JOIN visitors v ON v.visitor_id=cr.visitor_id
106
+ FROM consenti_consent_records WHERE tenant_id=? AND created_at>=?
107
+ GROUP BY DATE_FORMAT(created_at, '%Y-%m-%d') ORDER BY date ASC`,[e,n])).map(s=>({date:s.date,count:s.count}))}async createUser(e){let t=(0,C.randomUUID)();await this.exec("INSERT INTO consenti_users (id, tenant_id, name, email, password_hash) VALUES (?,?,?,?,?)",[t,e.tenantId,e.name,e.email,e.passwordHash]);let o=(await this.q("SELECT * FROM consenti_users WHERE id=?",[t]))[0];if(!o)throw new Error("User creation failed");return rt(o)}async updateUser(e,t){let n=[],o=[];t.name!=null&&(n.push("name=?"),o.push(t.name)),t.email!=null&&(n.push("email=?"),o.push(t.email)),t.passwordHash!=null&&(n.push("password_hash=?"),o.push(t.passwordHash)),t.isActive!=null&&(n.push("is_active=?"),o.push(t.isActive?1:0)),n.length>0&&(o.push(e),await this.exec(`UPDATE consenti_users SET ${n.join(",")} WHERE id=?`,o));let r=(await this.q("SELECT * FROM consenti_users WHERE id=?",[e]))[0];if(!r)throw new Error(`User ${e} not found`);return rt(r)}async deleteUser(e){await this.exec("DELETE FROM consenti_user_roles WHERE user_id=?",[e]),await this.exec("DELETE FROM consenti_users WHERE id=?",[e])}async getUserById(e){let t=await this.q("SELECT * FROM consenti_users WHERE id=?",[e]);return t[0]?rt(t[0]):null}async getUserByEmail(e){let t=await this.q("SELECT * FROM consenti_users WHERE email=?",[e]);return t[0]?rt(t[0]):null}async getUsers(e){return(await this.q("SELECT * FROM consenti_users WHERE tenant_id=? ORDER BY created_at DESC",[e])).map(rt)}async countUsers(e){return(e?await this.q("SELECT COUNT(*) AS total FROM consenti_users WHERE tenant_id=?",[e]):await this.q("SELECT COUNT(*) AS total FROM consenti_users"))[0]?.total??0}async getRoles(e){return(await this.q("SELECT * FROM consenti_roles WHERE tenant_id=?",[e])).map(Mt)}async createRole(e){let t=(0,C.randomUUID)();await this.exec("INSERT INTO consenti_roles (id, tenant_id, name, description) VALUES (?,?,?,?)",[t,e.tenantId,e.name,e.description??null]);let o=(await this.q("SELECT * FROM consenti_roles WHERE id=?",[t]))[0];if(!o)throw new Error("Role creation failed");return Mt(o)}async updateRole(e,t){let n=[],o=[];t.name!=null&&(n.push("name=?"),o.push(t.name)),t.description!=null&&(n.push("description=?"),o.push(t.description)),n.length>0&&(o.push(e),await this.exec(`UPDATE consenti_roles SET ${n.join(",")} WHERE id=?`,o));let r=(await this.q("SELECT * FROM consenti_roles WHERE id=?",[e]))[0];if(!r)throw new Error(`Role ${e} not found`);return Mt(r)}async deleteRole(e){await this.exec("DELETE FROM consenti_role_permissions WHERE role_id=?",[e]),await this.exec("DELETE FROM consenti_user_roles WHERE role_id=?",[e]),await this.exec("DELETE FROM consenti_roles WHERE id=?",[e])}async getAllPermissions(){return(await this.q("SELECT * FROM consenti_permissions ORDER BY name")).map(Bo)}async getPermissionsForRole(e){return(await this.q("SELECT p.* FROM consenti_permissions p JOIN consenti_role_permissions rp ON p.id=rp.permission_id WHERE rp.role_id=?",[e])).map(Bo)}async getUserRoles(e,t){return(t?await this.q("SELECT r.* FROM consenti_roles r JOIN consenti_user_roles ur ON r.id=ur.role_id WHERE ur.user_id=? AND ur.tenant_id=?",[e,t]):await this.q("SELECT r.* FROM consenti_roles r JOIN consenti_user_roles ur ON r.id=ur.role_id WHERE ur.user_id=?",[e])).map(Mt)}async assignRole(e,t,n="default"){await this.exec("INSERT IGNORE INTO consenti_user_roles (user_id, role_id, tenant_id) VALUES (?,?,?)",[e,t,n])}async revokeRole(e,t,n){n?await this.exec("DELETE FROM consenti_user_roles WHERE user_id=? AND role_id=? AND tenant_id=?",[e,t,n]):await this.exec("DELETE FROM consenti_user_roles WHERE user_id=? AND role_id=?",[e,t])}async assignPermissionToRole(e,t){await this.exec("INSERT IGNORE INTO consenti_role_permissions (role_id, permission_id) VALUES (?,?)",[e,t])}async revokePermissionFromRole(e,t){await this.exec("DELETE FROM consenti_role_permissions WHERE role_id=? AND permission_id=?",[e,t])}async createLog(e){await this.exec("INSERT INTO consenti_audit_logs (id, tenant_id, user_id, action, resource_type, resource_id, old_data, new_data) VALUES (?,?,?,?,?,?,?,?)",[(0,C.randomUUID)(),e.tenantId,e.userId??null,e.action,e.resourceType,e.resourceId??null,e.oldData!=null?JSON.stringify(e.oldData):null,e.newData!=null?JSON.stringify(e.newData):null])}async getLogs(e){let{where:t,params:n}=this.buildAuditWhere(e),o=e.page??1,s=e.limit??50,[r,a]=await Promise.all([this.q(`SELECT ${El} ${t} ORDER BY created_at DESC LIMIT ? OFFSET ?`,[...n,s,(o-1)*s]),this.q(`SELECT COUNT(*) AS total ${t}`,n)]);return{items:r.map(Rl),total:a[0]?.total??0,page:o,limit:s}}async getAuditLogById(e){let t=await this.q("SELECT * FROM consenti_audit_logs WHERE id=?",[e]);return t[0]?$o(t[0]):null}async*streamAuditLogs(e){let{where:t,params:n}=this.buildAuditWhere(e),o=await this.q(`SELECT * ${t} ORDER BY created_at ASC`,n);for(let s of o)yield $o(s)}buildAuditWhere(e){let t="FROM consenti_audit_logs WHERE tenant_id=?",n=[e.tenantId];if(e.action!=null&&(t+=" AND action=?",n.push(e.action)),e.resourceType!=null&&(t+=" AND resource_type=?",n.push(e.resourceType)),e.from!=null&&(t+=" AND created_at>=?",n.push(e.from)),e.to!=null&&(t+=" AND created_at<=?",n.push(e.to)),e.q){t+=" AND (action LIKE ? OR resource_type LIKE ? OR resource_id LIKE ? OR user_id LIKE ?)";let o=j(e.q);n.push(o,o,o,o)}return{where:t,params:n}}async getCountries(e){return(await this.q(`SELECT v.country, COUNT(*) AS count FROM consenti_consent_records cr
108
+ JOIN consenti_visitors v ON v.visitor_id=cr.visitor_id
109
109
  WHERE cr.tenant_id=? AND v.country IS NOT NULL
110
- GROUP BY v.country ORDER BY count DESC LIMIT 50`,[e])).map(n=>({country:n.country,count:n.count}))}async getGpcStats(e){let[t]=await this.q("SELECT COUNT(*) AS total FROM consent_records WHERE tenant_id=?",[e]),[n]=await this.q("SELECT COUNT(*) AS total FROM consent_records WHERE tenant_id=? AND gpc_detected=1",[e]),o=t?.total??0,s=n?.total??0;return{detected:s,total:o,rate:o>0?Math.round(s/o*100):0}}async getTenants(){return(await this.q("SELECT * FROM tenants ORDER BY name ASC",[])).map(t=>({id:t.id,name:t.name,slug:t.slug,createdAt:t.created_at,updatedAt:t.updated_at}))}mapApiKey(e){return{id:e.id,tenantId:e.tenant_id,keyHash:e.key_hash,name:e.name,isActive:e.is_active===1,...e.created_by!==null?{createdBy:e.created_by}:{},...e.expire_by!==null?{expireBy:e.expire_by}:{},createdAt:e.created_at,...e.updated_at!==null?{updatedAt:e.updated_at}:{}}}async createApiKey(e){let t=(0,v.randomUUID)();await this.exec("INSERT INTO api_keys (id, tenant_id, key_hash, name, created_by, expire_by) VALUES (?,?,?,?,?,?)",[t,e.tenantId,e.keyHash,e.name,e.createdBy??null,e.expireBy??null]);let o=(await this.q("SELECT * FROM api_keys WHERE id=?",[t]))[0];if(!o)throw new Error("Failed to create API key");return this.mapApiKey(o)}async getApiKeyByHash(e){let n=(await this.q("SELECT * FROM api_keys WHERE key_hash=? AND is_active=1",[e]))[0];return n?this.mapApiKey(n):null}async revokeApiKey(e){await this.exec("UPDATE api_keys SET is_active=0, updated_at=NOW() WHERE id=?",[e])}async reactivateApiKey(e){await this.exec("UPDATE api_keys SET is_active=1, updated_at=NOW(), expire_by=CASE WHEN expire_by <= NOW() THEN NULL ELSE expire_by END WHERE id=?",[e])}async deleteApiKey(e){await this.exec("DELETE FROM api_keys WHERE id=?",[e])}async getApiKeys(e){return(await this.q("SELECT * FROM api_keys WHERE tenant_id=? ORDER BY created_at DESC",[e])).map(n=>this.mapApiKey(n))}async createTenant(e){let t=(0,v.randomUUID)(),n=new Date().toISOString();await this.exec("INSERT INTO tenants (id, name, slug, created_at, updated_at) VALUES (?,?,?,?,?)",[t,e.name,e.slug,n,n]);let s=(await this.q("SELECT * FROM tenants WHERE id=?",[t]))[0];if(!s)throw new Error("Failed to create tenant");return{id:s.id,name:s.name,slug:s.slug,createdAt:s.created_at,updatedAt:s.updated_at}}async updateTenant(e,t){let n=new Date().toISOString(),o=["updated_at=?"],s=[n];t.name!=null&&(o.push("name=?"),s.push(t.name)),t.slug!=null&&(o.push("slug=?"),s.push(t.slug)),s.push(e),await this.exec(`UPDATE tenants SET ${o.join(",")} WHERE id=?`,s);let a=(await this.q("SELECT * FROM tenants WHERE id=?",[e]))[0];if(!a)throw new Error(`Tenant ${e} not found`);return{id:a.id,name:a.name,slug:a.slug,createdAt:a.created_at,updatedAt:a.updated_at}}async getSettings(e){let n=(await this.q("SELECT allowed_origins_json, admin_allowed_origins_json, setup_completed, profiles_seeded, tcf_confirmation_json, gpp_confirmation_json FROM tenant_settings WHERE tenant_id=?",[e]))[0];return n?{allowedOrigins:JSON.parse(n.allowed_origins_json),adminAllowedOrigins:JSON.parse(n.admin_allowed_origins_json),setupCompleted:!!n.setup_completed,profilesSeeded:!!n.profiles_seeded,tcfConfirmation:n.tcf_confirmation_json?JSON.parse(n.tcf_confirmation_json):void 0,gppConfirmation:n.gpp_confirmation_json?JSON.parse(n.gpp_confirmation_json):void 0}:{}}async updateSettings(e,t){let o={...await this.getSettings(e),...t};return await this.exec(`INSERT INTO tenant_settings (tenant_id, allowed_origins_json, admin_allowed_origins_json, setup_completed, profiles_seeded, tcf_confirmation_json, gpp_confirmation_json, updated_at) VALUES (?,?,?,?,?,?,?,NOW())
111
- ON DUPLICATE KEY UPDATE allowed_origins_json=VALUES(allowed_origins_json), admin_allowed_origins_json=VALUES(admin_allowed_origins_json), setup_completed=VALUES(setup_completed), profiles_seeded=VALUES(profiles_seeded), tcf_confirmation_json=VALUES(tcf_confirmation_json), gpp_confirmation_json=VALUES(gpp_confirmation_json), updated_at=NOW()`,[e,JSON.stringify(o.allowedOrigins??[]),JSON.stringify(o.adminAllowedOrigins??[]),o.setupCompleted?1:0,o.profilesSeeded?1:0,o.tcfConfirmation?JSON.stringify(o.tcfConfirmation):null,o.gppConfirmation?JSON.stringify(o.gppConfirmation):null]),this.getSettings(e)}async deleteTenant(e){await this.exec("DELETE FROM tenants WHERE id=?",[e])}async purgeExpiredConsents(e){let t=new Date(Date.now()-e*864e5).toISOString(),n=await this.q("SELECT visitor_id FROM consent_records WHERE created_at < ?",[t]);if(n.length===0)return 0;let o=n.map(r=>r.visitor_id),s=o.map(()=>"?").join(",");return await this.exec(`DELETE FROM consent_history WHERE visitor_id IN (${s})`,o),await this.exec(`DELETE FROM consent_records WHERE visitor_id IN (${s})`,o),o.length}mapConsentTemplate(e){return{id:e.id,tenantId:e.tenant_id,name:e.name,cookies:JSON.parse(e.cookies_json),categories:JSON.parse(e.categories_json),createdAt:e.created_at,updatedAt:e.updated_at}}async createConsentTemplate(e){let t=Y();await this.exec("INSERT INTO consent_templates (id, tenant_id, name, cookies_json, categories_json) VALUES (?,?,?,?,?)",[t,e.tenantId,e.name,JSON.stringify(e.cookies),JSON.stringify(e.categories)]);let n=await this.getConsentTemplate(t);if(!n)throw new Error("Consent template creation failed");return n}async updateConsentTemplate(e,t){let n=[],o=[];t.name!==void 0&&(n.push("name=?"),o.push(t.name)),t.cookies!==void 0&&(n.push("cookies_json=?"),o.push(JSON.stringify(t.cookies))),t.categories!==void 0&&(n.push("categories_json=?"),o.push(JSON.stringify(t.categories))),n.length>0&&await this.exec(`UPDATE consent_templates SET ${n.join(",")} WHERE id=?`,[...o,e]);let s=await this.getConsentTemplate(e);if(!s)throw new Error("Consent template not found");return s}async deleteConsentTemplate(e){await this.exec("DELETE FROM consent_templates WHERE id=?",[e])}async getConsentTemplate(e){let t=await this.q("SELECT * FROM consent_templates WHERE id=?",[e]);return t[0]?this.mapConsentTemplate(t[0]):null}async getConsentTemplates(e){return(await this.q("SELECT * FROM consent_templates WHERE tenant_id=? ORDER BY name ASC",[e])).map(n=>this.mapConsentTemplate(n))}async copyConsentTemplate(e,t){let n=await this.getConsentTemplate(e);if(!n)throw new Error("Consent template not found");return this.createConsentTemplate({tenantId:n.tenantId,name:t,cookies:n.cookies,categories:n.categories})}mapUITemplate(e){let t=JSON.parse(e.settings_json);return{id:e.id,tenantId:e.tenant_id,name:e.name,...t,createdAt:e.created_at,updatedAt:e.updated_at}}async createUITemplate(e){let t=Q(),{tenantId:n,name:o,...s}=e;await this.exec("INSERT INTO ui_templates (id, tenant_id, name, settings_json) VALUES (?,?,?,?)",[t,n,o,JSON.stringify(s)]);let r=await this.getUITemplate(t);if(!r)throw new Error("UI template creation failed");return r}async updateUITemplate(e,t){let o=(await this.q("SELECT * FROM ui_templates WHERE id=?",[e]))[0];if(!o)throw new Error("UI template not found");let{name:s,...r}=t,a=[],c=[];if(s!==void 0&&(a.push("name=?"),c.push(s)),Object.keys(r).length>0){let d={...JSON.parse(o.settings_json),...r};a.push("settings_json=?"),c.push(JSON.stringify(d))}a.length>0&&await this.exec(`UPDATE ui_templates SET ${a.join(",")} WHERE id=?`,[...c,e]);let l=await this.getUITemplate(e);if(!l)throw new Error("UI template not found");return l}async deleteUITemplate(e){await this.exec("DELETE FROM ui_templates WHERE id=?",[e])}async getUITemplate(e){let t=await this.q("SELECT * FROM ui_templates WHERE id=?",[e]);return t[0]?this.mapUITemplate(t[0]):null}async getUITemplates(e){return(await this.q("SELECT * FROM ui_templates WHERE tenant_id=? ORDER BY name ASC",[e])).map(n=>this.mapUITemplate(n))}async copyUITemplate(e,t){let n=await this.getUITemplate(e);if(!n)throw new Error("UI template not found");let{tenantId:o,mainBanner:s,gpcBanner:r,preferenceModal:a}=n;return this.createUITemplate({tenantId:o,name:t,mainBanner:s,gpcBanner:r,preferenceModal:a})}async toProfileSummaries(e){if(e.length===0)return[];let t=[...new Set(e.map(s=>s.tenantId))],[n,o]=await Promise.all([Promise.all(t.map(s=>this.getConsentTemplates(s))),Promise.all(t.map(s=>this.getUITemplates(s)))]);return Ue(e,new Map(n.flat().map(s=>[s.id,s.name])),new Map(o.flat().map(s=>[s.id,s.name])))}async listProfilesSummary(e){let t=await this.q("SELECT * FROM profiles WHERE tenant_id=? ORDER BY created_at ASC",[e]);return this.toProfileSummaries(t.map(be))}async findProfilesUsingConsentTemplate(e){let t=await this.q("SELECT * FROM profiles WHERE JSON_UNQUOTE(JSON_EXTRACT(profile_json, '$.consentTemplateId'))=? ORDER BY name ASC",[e]);return this.toProfileSummaries(t.map(be))}async findProfilesUsingUITemplate(e){let t=await this.q("SELECT * FROM profiles WHERE JSON_UNQUOTE(JSON_EXTRACT(profile_json, '$.uiTemplateId'))=? ORDER BY name ASC",[e]);return this.toProfileSummaries(t.map(be))}async getOptInStats(e,t){let n="tenant_id=?",o=[e];t.profileId&&(n+=" AND profile_id=?",o.push(t.profileId)),t.from&&(n+=" AND created_at>=?",o.push(t.from)),t.to&&(n+=" AND created_at<=?",o.push(t.to)),t.locale&&(n+=" AND locale=?",o.push(t.locale));let s=await this.q(`SELECT locale, DATE_FORMAT(created_at, '%Y-%m-%d') AS day, consent_json FROM consent_records WHERE ${n} ORDER BY created_at ASC`,o);return xe(s.map(r=>({locale:r.locale,day:r.day,consentJson:JSON.parse(r.consent_json)})))}};p();function Oe(i){return{id:i.id,tenantId:i.tenant_id,name:i.name,defaultLocale:i.default_locale,version:i.version,profileJson:i.profile_json,createdAt:i.created_at,updatedAt:i.updated_at}}function Dt(i){return{id:i.id,tenantId:i.tenant_id,visitorId:i.visitor_id,profileId:i.profile_id,locale:i.locale,consentJson:i.consent_json,gpcDetected:i.gpc_detected,source:i.source,createdAt:i.created_at,updatedAt:i.updated_at,...i.age_verified!=null?{ageVerified:i.age_verified}:{},...i.parental_consent_token!=null?{parentalConsentToken:i.parental_consent_token}:{},...i.tcf_string!=null?{tcfString:i.tcf_string}:{},...i.gpp_string!=null?{gppString:i.gpp_string}:{},...i.signature!=null?{signature:i.signature}:{}}}var Yc="id, tenant_id, visitor_id, profile_id, locale, gpc_detected, source, age_verified, created_at, updated_at";function Qc(i){return{id:i.id,tenantId:i.tenant_id,visitorId:i.visitor_id,profileId:i.profile_id,locale:i.locale,gpcDetected:i.gpc_detected,source:i.source,createdAt:i.created_at,updatedAt:i.updated_at,...i.age_verified!=null?{ageVerified:i.age_verified}:{}}}function Zc(i){return{id:i.id,tenantId:i.tenant_id,consentRecordId:i.consent_record_id,visitorId:i.visitor_id,oldJson:i.old_json,newJson:i.new_json,action:i.action,createdAt:i.created_at}}function kt(i){return{id:i.id,tenantId:i.tenant_id,visitorId:i.visitor_id,...i.country!=null?{country:i.country}:{},...i.region!=null?{region:i.region}:{},...i.city!=null?{city:i.city}:{},...i.ip_hash!=null?{ipHash:i.ip_hash}:{},...i.user_agent_hash!=null?{userAgentHash:i.user_agent_hash}:{},firstSeen:i.first_seen,lastSeen:i.last_seen}}function tt(i){return{id:i.id,tenantId:i.tenant_id,name:i.name,email:i.email,passwordHash:i.password_hash,isActive:i.is_active,createdAt:i.created_at,updatedAt:i.updated_at,totpEnabled:i.totp_enabled??!1,...i.totp_secret!=null?{totpSecret:i.totp_secret}:{}}}function nt(i){return{id:i.id,tenantId:i.tenant_id,name:i.name,...i.description!=null?{description:i.description}:{}}}function Co(i){return{id:i.id,name:i.name,...i.description!=null?{description:i.description}:{}}}function vo(i){return{id:i.id,tenantId:i.tenant_id,action:i.action,resourceType:i.resource_type,...i.user_id!=null?{userId:i.user_id}:{},...i.resource_id!=null?{resourceId:i.resource_id}:{},...i.old_data!=null?{oldData:i.old_data}:{},...i.new_data!=null?{newData:i.new_data}:{},createdAt:i.created_at}}var Xc="id, tenant_id, user_id, action, resource_type, resource_id, created_at";function el(i){return{id:i.id,tenantId:i.tenant_id,action:i.action,resourceType:i.resource_type,...i.user_id!=null?{userId:i.user_id}:{},...i.resource_id!=null?{resourceId:i.resource_id}:{},createdAt:i.created_at}}var je=class{constructor(e){this.config=e}config;pool;async q(e,t=[]){return(await this.pool.query(e,t)).rows}async connect(){let t=(await import("pg")).default.Pool,n=this.config,o=n.uri?{connectionString:n.uri}:{host:n.host??"localhost",port:n.port??5432,user:n.user??"postgres",password:n.password??"",database:n.database??"consenti"};o.max=n.poolMax??10,n.statementTimeoutMs!=null&&(o.statement_timeout=n.statementTimeoutMs),n.idleInTransactionTimeoutMs!=null&&(o.idle_in_transaction_session_timeout=n.idleInTransactionTimeoutMs),this.pool=new t(o),await this.migrate()}async disconnect(){await this.pool.end()}async migrate(){let e=await this.pool.connect();try{let t=0;try{t=(await e.query("SELECT version FROM schema_version ORDER BY version DESC LIMIT 1")).rows[0]?.version??0}catch{}if(t===0){await e.query("BEGIN");try{for(let n of yo.split(";").map(o=>o.trim()).filter(Boolean))await e.query(n);await this.seedTx(e),await e.query("INSERT INTO schema_version (version) VALUES (1) ON CONFLICT DO NOTHING"),await e.query("COMMIT")}catch(n){throw await e.query("ROLLBACK"),n}}}finally{e.release()}}async seedTx(e){await e.query("INSERT INTO tenants (id, name, slug) VALUES ($1,$2,$3) ON CONFLICT DO NOTHING",[ie.id,ie.name,ie.slug]);for(let t of ne)await e.query("INSERT INTO permissions (id, name, description) VALUES ($1,$2,$3) ON CONFLICT DO NOTHING",[t.id,t.name,t.description]);for(let t of ge)await e.query("INSERT INTO roles (id, tenant_id, name, description) VALUES ($1,$2,$3,$4) ON CONFLICT DO NOTHING",[t.id,t.tenantId,t.name,t.description]);for(let{roleId:t,permissionId:n}of fe)await e.query("INSERT INTO role_permissions VALUES ($1,$2) ON CONFLICT DO NOTHING",[t,n])}async createProfile(e){let t=z(),o=(await this.q(`INSERT INTO profiles (id, tenant_id, name, default_locale, version, profile_json)
112
- VALUES ($1,$2,$3,$4,$5,$6::json) RETURNING *`,[t,e.tenantId,e.name,e.defaultLocale,1,JSON.stringify(e.profileJson)]))[0];if(!o)throw new Error("Profile creation failed");return Oe(o)}async updateProfile(e,t){let n=["updated_at = NOW()"],o=[],s=1;t.name!=null&&(n.push(`name=$${s++}`),o.push(t.name)),t.defaultLocale!=null&&(n.push(`default_locale=$${s++}`),o.push(t.defaultLocale)),t.profileJson!=null&&(n.push(`profile_json=$${s++}::json`),o.push(JSON.stringify(t.profileJson))),t.version!=null&&(n.push(`version=$${s++}`),o.push(t.version)),o.push(e);let a=(await this.q(`UPDATE profiles SET ${n.join(",")} WHERE id=$${s} RETURNING *`,o))[0];if(!a)throw new Error(`Profile ${e} not found`);return Oe(a)}async deleteProfile(e){await this.q("DELETE FROM profiles WHERE id=$1",[e])}async getProfile(e){let t=await this.q("SELECT * FROM profiles WHERE id=$1",[e]);return t[0]?Oe(t[0]):null}async getProfiles(e){return(await this.q("SELECT * FROM profiles WHERE tenant_id=$1 ORDER BY created_at DESC",[e])).map(Oe)}async findActiveProfileByComplianceGroup(e,t){return(await this.getProfiles(e)).find(o=>(o.profileJson.complianceGroup===t||o.profileJson.customComplianceGroup===t)&&o.profileJson.isActive)??null}async createConsent(e){let t=K(),o=(await this.q(`INSERT INTO consent_records (id, tenant_id, visitor_id, profile_id, locale, consent_json, gpc_detected, source, age_verified, parental_consent_token, tcf_string, gpp_string, signature)
113
- VALUES ($1,$2,$3,$4,$5,$6::jsonb,$7,$8,$9,$10,$11,$12,$13) RETURNING *`,[t,e.tenantId,e.visitorId,e.profileId,e.locale,JSON.stringify(e.consentJson),e.gpcDetected,e.source,e.ageVerified??!1,e.parentalConsentToken??null,e.tcfString??null,e.gppString??null,e.signature??null]))[0];if(!o)throw new Error("Consent creation failed");return await this.writeHistory(t,e.tenantId,e.visitorId,null,e.consentJson,"created"),Dt(o)}async updateConsent(e,t){let n=await this.getConsent(e);if(!n)throw new Error(`Consent for visitor ${e} not found`);let o=["consent_json=$1::jsonb","updated_at=NOW()"],s=[JSON.stringify(t.consentJson)],r=2;t.locale!=null&&(o.push(`locale=$${r++}`),s.push(t.locale)),t.gpcDetected!=null&&(o.push(`gpc_detected=$${r++}`),s.push(t.gpcDetected)),t.signature!=null&&(o.push(`signature=$${r++}`),s.push(t.signature)),s.push(e);let c=(await this.q(`UPDATE consent_records SET ${o.join(",")} WHERE visitor_id=$${r} RETURNING *`,s))[0];if(!c)throw new Error(`Consent for visitor ${e} not found`);return await this.writeHistory(c.id,c.tenant_id,e,n.consentJson,t.consentJson,"updated"),Dt(c)}async deleteConsent(e){await this.q("DELETE FROM consent_history WHERE visitor_id=$1",[e]),await this.q("DELETE FROM consent_records WHERE visitor_id=$1",[e])}async getConsent(e){let t=await this.q("SELECT * FROM consent_records WHERE visitor_id=$1",[e]);return t[0]?Dt(t[0]):null}async getConsents(e){let{where:t,params:n,nextIdx:o}=this.buildConsentWhere(e),s=e.page??1,r=e.limit??50,[a,c]=await Promise.all([this.q(`SELECT ${Yc} ${t} ORDER BY created_at DESC LIMIT $${o} OFFSET $${o+1}`,[...n,r,(s-1)*r]),this.q(`SELECT COUNT(*)::int AS total ${t}`,n)]);return{items:a.map(Qc),total:Number(c[0]?.total??0),page:s,limit:r}}async*streamConsents(e){let{where:t,params:n}=this.buildConsentWhere(e),o=await this.q(`SELECT * ${t} ORDER BY created_at ASC`,n);for(let s of o)yield Dt(s)}buildConsentWhere(e){let t="FROM consent_records WHERE tenant_id=$1",n=[e.tenantId],o=2;return e.profileId!=null&&(t+=` AND profile_id=$${o++}`,n.push(e.profileId)),e.from!=null&&(t+=` AND created_at>=$${o++}`,n.push(e.from)),e.to!=null&&(t+=` AND created_at<=$${o++}`,n.push(e.to)),e.q&&(t+=` AND (visitor_id ILIKE $${o} OR profile_id ILIKE $${o} OR locale ILIKE $${o} OR source ILIKE $${o}) ESCAPE '\\'`,n.push(j(e.q)),o++),{where:t,params:n,nextIdx:o}}async writeHistory(e,t,n,o,s,r){await this.q(`INSERT INTO consent_history (id, tenant_id, consent_record_id, visitor_id, old_json, new_json, action)
114
- VALUES ($1,$2,$3,$4,$5::jsonb,$6::jsonb,$7)`,[(0,v.randomUUID)(),t,e,n,o?JSON.stringify(o):null,JSON.stringify(s),r])}async getConsentHistory(e){return(await this.q("SELECT * FROM consent_history WHERE visitor_id=$1 ORDER BY created_at ASC",[e])).map(Zc)}async createNoticeShown(e){let t=(0,v.randomUUID)(),o=(await this.q(`INSERT INTO notice_shown (id, tenant_id, visitor_id, profile_id, locale)
115
- VALUES ($1,$2,$3,$4,$5) RETURNING *`,[t,e.tenantId,e.visitorId,e.profileId,e.locale]))[0];return{id:o.id,tenantId:o.tenant_id,visitorId:o.visitor_id,profileId:o.profile_id,locale:o.locale,createdAt:o.created_at}}async getNoticeShownForVisitor(e){return(await this.q("SELECT * FROM notice_shown WHERE visitor_id=$1 ORDER BY created_at DESC",[e])).map(n=>({id:n.id,tenantId:n.tenant_id,visitorId:n.visitor_id,profileId:n.profile_id,locale:n.locale,createdAt:n.created_at}))}async createVisitor(e){let t=q(),o=(await this.q(`INSERT INTO visitors (id, tenant_id, visitor_id, country, region, city, ip_hash, user_agent_hash)
116
- VALUES ($1,$2,$3,$4,$5,$6,$7,$8) RETURNING *`,[t,e.tenantId,e.visitorId,e.country??null,e.region??null,e.city??null,e.ipHash??null,e.userAgentHash??null]))[0];if(!o)throw new Error("Visitor creation failed");return kt(o)}async updateVisitor(e,t){let n=["last_seen=NOW()"],o=[],s=1;t.country!=null&&(n.push(`country=$${s++}`),o.push(t.country)),t.region!=null&&(n.push(`region=$${s++}`),o.push(t.region)),t.city!=null&&(n.push(`city=$${s++}`),o.push(t.city)),o.push(e);let a=(await this.q(`UPDATE visitors SET ${n.join(",")} WHERE visitor_id=$${s} RETURNING *`,o))[0];if(!a)throw new Error(`Visitor ${e} not found`);return kt(a)}async deleteVisitor(e){await this.q("DELETE FROM visitors WHERE visitor_id=$1",[e])}async getVisitor(e){let t=await this.q("SELECT * FROM visitors WHERE visitor_id=$1",[e]);return t[0]?kt(t[0]):null}async getVisitors(e){let t="FROM visitors WHERE tenant_id=$1",n=[e.tenantId],o=2;e.from!=null&&(t+=` AND first_seen>=$${o++}`,n.push(e.from)),e.to!=null&&(t+=` AND first_seen<=$${o++}`,n.push(e.to)),e.q&&(t+=` AND (visitor_id ILIKE $${o} OR country ILIKE $${o}) ESCAPE '\\'`,n.push(j(e.q)),o++);let s=e.page??1,r=e.limit??50,[a,c]=await Promise.all([this.q(`SELECT * ${t} ORDER BY first_seen DESC LIMIT $${o} OFFSET $${o+1}`,[...n,r,(s-1)*r]),this.q(`SELECT COUNT(*)::int AS total ${t}`,n)]);return{items:a.map(kt),total:Number(c[0]?.total??0),page:s,limit:r}}async getOverviewStats(e){let[[t],[n],[o]]=await Promise.all([this.q("SELECT COUNT(*)::int AS total FROM consent_records WHERE tenant_id=$1",[e]),this.q("SELECT COUNT(*)::int AS total FROM consent_records WHERE tenant_id=$1 AND gpc_detected=true",[e]),this.q("SELECT COUNT(*)::int AS total FROM visitors WHERE tenant_id=$1",[e])]),s=Number(t?.total??0),r=Number(n?.total??0),a=Number(o?.total??0),c=await this.q(`SELECT val AS status, COUNT(*)::int AS count
117
- FROM consent_records cr,
110
+ GROUP BY v.country ORDER BY count DESC LIMIT 50`,[e])).map(n=>({country:n.country,count:n.count}))}async getGpcStats(e){let[t]=await this.q("SELECT COUNT(*) AS total FROM consenti_consent_records WHERE tenant_id=?",[e]),[n]=await this.q("SELECT COUNT(*) AS total FROM consenti_consent_records WHERE tenant_id=? AND gpc_detected=1",[e]),o=t?.total??0,s=n?.total??0;return{detected:s,total:o,rate:o>0?Math.round(s/o*100):0}}async getTenants(){return(await this.q("SELECT * FROM consenti_tenants ORDER BY name ASC",[])).map(t=>({id:t.id,name:t.name,slug:t.slug,createdAt:t.created_at,updatedAt:t.updated_at}))}mapApiKey(e){return{id:e.id,tenantId:e.tenant_id,keyHash:e.key_hash,name:e.name,isActive:e.is_active===1,...e.created_by!==null?{createdBy:e.created_by}:{},...e.expire_by!==null?{expireBy:e.expire_by}:{},createdAt:e.created_at,...e.updated_at!==null?{updatedAt:e.updated_at}:{}}}async createApiKey(e){let t=(0,C.randomUUID)();await this.exec("INSERT INTO consenti_api_keys (id, tenant_id, key_hash, name, created_by, expire_by) VALUES (?,?,?,?,?,?)",[t,e.tenantId,e.keyHash,e.name,e.createdBy??null,e.expireBy??null]);let o=(await this.q("SELECT * FROM consenti_api_keys WHERE id=?",[t]))[0];if(!o)throw new Error("Failed to create API key");return this.mapApiKey(o)}async getApiKeyByHash(e){let n=(await this.q("SELECT * FROM consenti_api_keys WHERE key_hash=? AND is_active=1",[e]))[0];return n?this.mapApiKey(n):null}async revokeApiKey(e){await this.exec("UPDATE consenti_api_keys SET is_active=0, updated_at=NOW() WHERE id=?",[e])}async reactivateApiKey(e){await this.exec("UPDATE consenti_api_keys SET is_active=1, updated_at=NOW(), expire_by=CASE WHEN expire_by <= NOW() THEN NULL ELSE expire_by END WHERE id=?",[e])}async deleteApiKey(e){await this.exec("DELETE FROM consenti_api_keys WHERE id=?",[e])}async getApiKeys(e){return(await this.q("SELECT * FROM consenti_api_keys WHERE tenant_id=? ORDER BY created_at DESC",[e])).map(n=>this.mapApiKey(n))}async createTenant(e){let t=(0,C.randomUUID)(),n=Zn();await this.exec("INSERT INTO consenti_tenants (id, name, slug, created_at, updated_at) VALUES (?,?,?,?,?)",[t,e.name,e.slug,n,n]);let s=(await this.q("SELECT * FROM consenti_tenants WHERE id=?",[t]))[0];if(!s)throw new Error("Failed to create tenant");return{id:s.id,name:s.name,slug:s.slug,createdAt:s.created_at,updatedAt:s.updated_at}}async updateTenant(e,t){let n=Zn(),o=["updated_at=?"],s=[n];t.name!=null&&(o.push("name=?"),s.push(t.name)),t.slug!=null&&(o.push("slug=?"),s.push(t.slug)),s.push(e),await this.exec(`UPDATE consenti_tenants SET ${o.join(",")} WHERE id=?`,s);let a=(await this.q("SELECT * FROM consenti_tenants WHERE id=?",[e]))[0];if(!a)throw new Error(`Tenant ${e} not found`);return{id:a.id,name:a.name,slug:a.slug,createdAt:a.created_at,updatedAt:a.updated_at}}async getSettings(e){let n=(await this.q("SELECT allowed_origins_json, admin_allowed_origins_json, setup_completed, profiles_seeded, tcf_confirmation_json, gpp_confirmation_json FROM consenti_tenant_settings WHERE tenant_id=?",[e]))[0];return n?{allowedOrigins:JSON.parse(n.allowed_origins_json),adminAllowedOrigins:JSON.parse(n.admin_allowed_origins_json),setupCompleted:!!n.setup_completed,profilesSeeded:!!n.profiles_seeded,tcfConfirmation:n.tcf_confirmation_json?JSON.parse(n.tcf_confirmation_json):void 0,gppConfirmation:n.gpp_confirmation_json?JSON.parse(n.gpp_confirmation_json):void 0}:{}}async updateSettings(e,t){let o={...await this.getSettings(e),...t};return await this.exec(`INSERT INTO consenti_tenant_settings (tenant_id, allowed_origins_json, admin_allowed_origins_json, setup_completed, profiles_seeded, tcf_confirmation_json, gpp_confirmation_json, updated_at) VALUES (?,?,?,?,?,?,?,NOW())
111
+ ON DUPLICATE KEY UPDATE allowed_origins_json=VALUES(allowed_origins_json), admin_allowed_origins_json=VALUES(admin_allowed_origins_json), setup_completed=VALUES(setup_completed), profiles_seeded=VALUES(profiles_seeded), tcf_confirmation_json=VALUES(tcf_confirmation_json), gpp_confirmation_json=VALUES(gpp_confirmation_json), updated_at=NOW()`,[e,JSON.stringify(o.allowedOrigins??[]),JSON.stringify(o.adminAllowedOrigins??[]),o.setupCompleted?1:0,o.profilesSeeded?1:0,o.tcfConfirmation?JSON.stringify(o.tcfConfirmation):null,o.gppConfirmation?JSON.stringify(o.gppConfirmation):null]),this.getSettings(e)}async deleteTenant(e){await this.exec("DELETE FROM consenti_tenants WHERE id=?",[e])}async purgeExpiredConsents(e){let t=Zn(new Date(Date.now()-e*864e5)),n=await this.q("SELECT visitor_id FROM consenti_consent_records WHERE created_at < ?",[t]);if(n.length===0)return 0;let o=n.map(r=>r.visitor_id),s=o.map(()=>"?").join(",");return await this.exec(`DELETE FROM consenti_consent_history WHERE visitor_id IN (${s})`,o),await this.exec(`DELETE FROM consenti_consent_records WHERE visitor_id IN (${s})`,o),o.length}mapConsentTemplate(e){return{id:e.id,tenantId:e.tenant_id,name:e.name,cookies:JSON.parse(e.cookies_json),categories:JSON.parse(e.categories_json),createdAt:e.created_at,updatedAt:e.updated_at}}async createConsentTemplate(e){let t=Q();await this.exec("INSERT INTO consenti_consent_templates (id, tenant_id, name, cookies_json, categories_json) VALUES (?,?,?,?,?)",[t,e.tenantId,e.name,JSON.stringify(e.cookies),JSON.stringify(e.categories)]);let n=await this.getConsentTemplate(t);if(!n)throw new Error("Consent template creation failed");return n}async updateConsentTemplate(e,t){let n=[],o=[];t.name!==void 0&&(n.push("name=?"),o.push(t.name)),t.cookies!==void 0&&(n.push("cookies_json=?"),o.push(JSON.stringify(t.cookies))),t.categories!==void 0&&(n.push("categories_json=?"),o.push(JSON.stringify(t.categories))),n.length>0&&await this.exec(`UPDATE consenti_consent_templates SET ${n.join(",")} WHERE id=?`,[...o,e]);let s=await this.getConsentTemplate(e);if(!s)throw new Error("Consent template not found");return s}async deleteConsentTemplate(e){await this.exec("DELETE FROM consenti_consent_templates WHERE id=?",[e])}async getConsentTemplate(e){let t=await this.q("SELECT * FROM consenti_consent_templates WHERE id=?",[e]);return t[0]?this.mapConsentTemplate(t[0]):null}async getConsentTemplates(e){return(await this.q("SELECT * FROM consenti_consent_templates WHERE tenant_id=? ORDER BY name ASC",[e])).map(n=>this.mapConsentTemplate(n))}async copyConsentTemplate(e,t){let n=await this.getConsentTemplate(e);if(!n)throw new Error("Consent template not found");return this.createConsentTemplate({tenantId:n.tenantId,name:t,cookies:n.cookies,categories:n.categories})}mapUITemplate(e){let t=JSON.parse(e.settings_json);return{id:e.id,tenantId:e.tenant_id,name:e.name,...t,createdAt:e.created_at,updatedAt:e.updated_at}}async createUITemplate(e){let t=Z(),{tenantId:n,name:o,...s}=e;await this.exec("INSERT INTO consenti_ui_templates (id, tenant_id, name, settings_json) VALUES (?,?,?,?)",[t,n,o,JSON.stringify(s)]);let r=await this.getUITemplate(t);if(!r)throw new Error("UI template creation failed");return r}async updateUITemplate(e,t){let o=(await this.q("SELECT * FROM consenti_ui_templates WHERE id=?",[e]))[0];if(!o)throw new Error("UI template not found");let{name:s,...r}=t,a=[],c=[];if(s!==void 0&&(a.push("name=?"),c.push(s)),Object.keys(r).length>0){let d={...JSON.parse(o.settings_json),...r};a.push("settings_json=?"),c.push(JSON.stringify(d))}a.length>0&&await this.exec(`UPDATE consenti_ui_templates SET ${a.join(",")} WHERE id=?`,[...c,e]);let l=await this.getUITemplate(e);if(!l)throw new Error("UI template not found");return l}async deleteUITemplate(e){await this.exec("DELETE FROM consenti_ui_templates WHERE id=?",[e])}async getUITemplate(e){let t=await this.q("SELECT * FROM consenti_ui_templates WHERE id=?",[e]);return t[0]?this.mapUITemplate(t[0]):null}async getUITemplates(e){return(await this.q("SELECT * FROM consenti_ui_templates WHERE tenant_id=? ORDER BY name ASC",[e])).map(n=>this.mapUITemplate(n))}async copyUITemplate(e,t){let n=await this.getUITemplate(e);if(!n)throw new Error("UI template not found");let{tenantId:o,mainBanner:s,gpcBanner:r,preferenceModal:a}=n;return this.createUITemplate({tenantId:o,name:t,mainBanner:s,gpcBanner:r,preferenceModal:a})}async toProfileSummaries(e){if(e.length===0)return[];let t=[...new Set(e.map(s=>s.tenantId))],[n,o]=await Promise.all([Promise.all(t.map(s=>this.getConsentTemplates(s))),Promise.all(t.map(s=>this.getUITemplates(s)))]);return Be(e,new Map(n.flat().map(s=>[s.id,s.name])),new Map(o.flat().map(s=>[s.id,s.name])))}async listProfilesSummary(e){let t=await this.q("SELECT * FROM consenti_profiles WHERE tenant_id=? ORDER BY created_at ASC",[e]);return this.toProfileSummaries(t.map(Le))}async findProfilesUsingConsentTemplate(e){let t=await this.q("SELECT * FROM consenti_profiles WHERE JSON_UNQUOTE(JSON_EXTRACT(profile_json, '$.consentTemplateId'))=? ORDER BY name ASC",[e]);return this.toProfileSummaries(t.map(Le))}async findProfilesUsingUITemplate(e){let t=await this.q("SELECT * FROM consenti_profiles WHERE JSON_UNQUOTE(JSON_EXTRACT(profile_json, '$.uiTemplateId'))=? ORDER BY name ASC",[e]);return this.toProfileSummaries(t.map(Le))}async getOptInStats(e,t){let n="tenant_id=?",o=[e];t.profileId&&(n+=" AND profile_id=?",o.push(t.profileId)),t.from&&(n+=" AND created_at>=?",o.push(t.from)),t.to&&(n+=" AND created_at<=?",o.push(t.to)),t.locale&&(n+=" AND locale=?",o.push(t.locale));let s=await this.q(`SELECT locale, DATE_FORMAT(created_at, '%Y-%m-%d') AS day, consent_json FROM consenti_consent_records WHERE ${n} ORDER BY created_at ASC`,o);return $e(s.map(r=>({locale:r.locale,day:r.day,consentJson:JSON.parse(r.consent_json)})))}};p();function Ne(i){return{id:i.id,tenantId:i.tenant_id,name:i.name,defaultLocale:i.default_locale,version:i.version,profileJson:i.profile_json,createdAt:i.created_at,updatedAt:i.updated_at}}function Gt(i){return{id:i.id,tenantId:i.tenant_id,visitorId:i.visitor_id,profileId:i.profile_id,...i.profile_version!=null?{profileVersion:i.profile_version}:{},locale:i.locale,consentJson:i.consent_json,gpcDetected:i.gpc_detected,source:i.source,createdAt:i.created_at,updatedAt:i.updated_at,...i.age_verified!=null?{ageVerified:i.age_verified}:{},...i.parental_consent_token!=null?{parentalConsentToken:i.parental_consent_token}:{},...i.tcf_string!=null?{tcfString:i.tcf_string}:{},...i.gpp_string!=null?{gppString:i.gpp_string}:{},...i.signature!=null?{signature:i.signature}:{}}}var Sl="id, tenant_id, visitor_id, profile_id, locale, gpc_detected, source, age_verified, created_at, updated_at";function vl(i){return{id:i.id,tenantId:i.tenant_id,visitorId:i.visitor_id,profileId:i.profile_id,locale:i.locale,gpcDetected:i.gpc_detected,source:i.source,createdAt:i.created_at,updatedAt:i.updated_at,...i.age_verified!=null?{ageVerified:i.age_verified}:{}}}function Cl(i){return{id:i.id,tenantId:i.tenant_id,consentRecordId:i.consent_record_id,visitorId:i.visitor_id,...i.profile_version!=null?{profileVersion:i.profile_version}:{},oldJson:i.old_json,newJson:i.new_json,action:i.action,createdAt:i.created_at}}function jt(i){return{id:i.id,tenantId:i.tenant_id,visitorId:i.visitor_id,...i.country!=null?{country:i.country}:{},...i.region!=null?{region:i.region}:{},...i.city!=null?{city:i.city}:{},...i.ip_hash!=null?{ipHash:i.ip_hash}:{},...i.user_agent_hash!=null?{userAgentHash:i.user_agent_hash}:{},firstSeen:i.first_seen,lastSeen:i.last_seen}}function at(i){return{id:i.id,tenantId:i.tenant_id,name:i.name,email:i.email,passwordHash:i.password_hash,isActive:i.is_active,createdAt:i.created_at,updatedAt:i.updated_at,totpEnabled:i.totp_enabled??!1,...i.totp_secret!=null?{totpSecret:i.totp_secret}:{}}}function ct(i){return{id:i.id,tenantId:i.tenant_id,name:i.name,...i.description!=null?{description:i.description}:{}}}function Fo(i){return{id:i.id,name:i.name,...i.description!=null?{description:i.description}:{}}}function Ho(i){return{id:i.id,tenantId:i.tenant_id,action:i.action,resourceType:i.resource_type,...i.user_id!=null?{userId:i.user_id}:{},...i.resource_id!=null?{resourceId:i.resource_id}:{},...i.old_data!=null?{oldData:i.old_data}:{},...i.new_data!=null?{newData:i.new_data}:{},createdAt:i.created_at}}var Al="id, tenant_id, user_id, action, resource_type, resource_id, created_at";function Tl(i){return{id:i.id,tenantId:i.tenant_id,action:i.action,resourceType:i.resource_type,...i.user_id!=null?{userId:i.user_id}:{},...i.resource_id!=null?{resourceId:i.resource_id}:{},createdAt:i.created_at}}var Ve=class{constructor(e){this.config=e}config;pool;async q(e,t=[]){return(await this.pool.query(e,t)).rows}async connect(){let t=(await import("pg")).default.Pool,n=this.config,o=n.uri?{connectionString:n.uri}:{host:n.host??"localhost",port:n.port??5432,user:n.user??"postgres",password:n.password??"",database:n.database??"consenti"};o.max=n.poolMax??5,n.statementTimeoutMs!=null&&(o.statement_timeout=n.statementTimeoutMs),n.idleInTransactionTimeoutMs!=null&&(o.idle_in_transaction_session_timeout=n.idleInTransactionTimeoutMs),this.pool=new t(o),await this.migrate()}async disconnect(){await this.pool.end()}async migrate(){let e=await this.pool.connect();await e.query("SELECT pg_advisory_lock(hashtext('consenti_schema'))");try{let t=await e.query("SELECT n AS name, to_regclass(n) IS NOT NULL AS found FROM unnest($1::text[]) AS n",[["consenti_schema_version",...Se]]),n=new Set(t.rows.filter(s=>s.found).map(s=>s.name));if(!n.has("consenti_schema_version")&&Se.every(s=>n.has(s)))throw Ue("tables");let o=0;if(n.has("consenti_schema_version")&&(o=(await e.query("SELECT version FROM consenti_schema_version ORDER BY version DESC LIMIT 1")).rows[0]?.version??0),o===0){await e.query("BEGIN");try{for(let s of xo.split(";").map(r=>r.trim()).filter(Boolean))await e.query(s);await this.seedTx(e),await e.query("INSERT INTO consenti_schema_version (version) VALUES ($1) ON CONFLICT DO NOTHING",[le]),await e.query("COMMIT")}catch(s){throw await e.query("ROLLBACK"),new Error(`Creating the Consenti tables failed: ${s instanceof Error?s.message:String(s)}. The database user needs CREATE on the schema it connects to (normally "public" \u2014 the database owner has it) plus SELECT, INSERT, UPDATE and DELETE; it never creates databases, schemas or extensions. Nothing was changed (one transaction, rolled back): fix the cause and start again.`,{cause:s})}}else if(o<2)try{await this.migrateToV2(e)}catch(s){throw new Error(`Upgrading the database schema to v2 failed: ${s instanceof Error?s.message:String(s)}. The database user must own the tables (or be a superuser). Nothing was changed \u2014 the upgrade runs in one transaction and was rolled back; fix the cause and start again.`,{cause:s})}}finally{try{await e.query("SELECT pg_advisory_unlock(hashtext('consenti_schema'))")}catch{}e.release()}}async migrateToV2(e){await e.query("BEGIN");try{let t=await e.query(`SELECT c.conrelid::regclass::text AS tbl, c.conname AS name FROM pg_constraint c
112
+ WHERE c.contype = 'f' AND c.confrelid = to_regclass('consenti_profiles')
113
+ AND c.conrelid IN (to_regclass('consenti_consent_records'), to_regclass('consenti_notice_shown'))`);for(let n of t.rows)await e.query(`ALTER TABLE ${n.tbl} DROP CONSTRAINT "${n.name.replace(/"/g,'""')}"`);await e.query("ALTER TABLE consenti_consent_records ADD COLUMN IF NOT EXISTS profile_version INTEGER"),await e.query("ALTER TABLE consenti_consent_history ADD COLUMN IF NOT EXISTS profile_version INTEGER"),await e.query("INSERT INTO consenti_schema_version (version) VALUES ($1) ON CONFLICT DO NOTHING",[le]),await e.query("COMMIT")}catch(t){throw await e.query("ROLLBACK"),t}}async seedTx(e){await e.query("INSERT INTO consenti_tenants (id, name, slug) VALUES ($1,$2,$3) ON CONFLICT DO NOTHING",[oe.id,oe.name,oe.slug]);for(let t of ie)await e.query("INSERT INTO consenti_permissions (id, name, description) VALUES ($1,$2,$3) ON CONFLICT DO NOTHING",[t.id,t.name,t.description]);for(let t of he)await e.query("INSERT INTO consenti_roles (id, tenant_id, name, description) VALUES ($1,$2,$3,$4) ON CONFLICT DO NOTHING",[t.id,t.tenantId,t.name,t.description]);for(let{roleId:t,permissionId:n}of ye)await e.query("INSERT INTO consenti_role_permissions VALUES ($1,$2) ON CONFLICT DO NOTHING",[t,n])}async createProfile(e){let t=K(),o=(await this.q(`INSERT INTO consenti_profiles (id, tenant_id, name, default_locale, version, profile_json)
114
+ VALUES ($1,$2,$3,$4,$5,$6::json) RETURNING *`,[t,e.tenantId,e.name,e.defaultLocale,1,JSON.stringify(e.profileJson)]))[0];if(!o)throw new Error("Profile creation failed");return Ne(o)}async updateProfile(e,t){let n=["updated_at = NOW()"],o=[],s=1;t.name!=null&&(n.push(`name=$${s++}`),o.push(t.name)),t.defaultLocale!=null&&(n.push(`default_locale=$${s++}`),o.push(t.defaultLocale)),t.profileJson!=null&&(n.push(`profile_json=$${s++}::json`),o.push(JSON.stringify(t.profileJson))),t.version!=null&&(n.push(`version=$${s++}`),o.push(t.version)),o.push(e);let a=(await this.q(`UPDATE consenti_profiles SET ${n.join(",")} WHERE id=$${s} RETURNING *`,o))[0];if(!a)throw new Error(`Profile ${e} not found`);return Ne(a)}async deleteProfile(e){await this.q("DELETE FROM consenti_profiles WHERE id=$1",[e])}async getProfile(e){let t=await this.q("SELECT * FROM consenti_profiles WHERE id=$1",[e]);return t[0]?Ne(t[0]):null}async getProfiles(e){return(await this.q("SELECT * FROM consenti_profiles WHERE tenant_id=$1 ORDER BY created_at DESC",[e])).map(Ne)}async findActiveProfileByComplianceGroup(e,t){return(await this.getProfiles(e)).find(o=>(o.profileJson.complianceGroup===t||o.profileJson.customComplianceGroup===t)&&o.profileJson.isActive)??null}async createConsent(e){let t=Y(),o=(await this.q(`INSERT INTO consenti_consent_records (id, tenant_id, visitor_id, profile_id, profile_version, locale, consent_json, gpc_detected, source, age_verified, parental_consent_token, tcf_string, gpp_string, signature)
115
+ VALUES ($1,$2,$3,$4,$5,$6,$7::jsonb,$8,$9,$10,$11,$12,$13,$14) RETURNING *`,[t,e.tenantId,e.visitorId,e.profileId,e.profileVersion??null,e.locale,JSON.stringify(e.consentJson),e.gpcDetected,e.source,e.ageVerified??!1,e.parentalConsentToken??null,e.tcfString??null,e.gppString??null,e.signature??null]))[0];if(!o)throw new Error("Consent creation failed");return await this.writeHistory(t,e.tenantId,e.visitorId,null,e.consentJson,"created",e.profileVersion??null),Gt(o)}async updateConsent(e,t){let n=await this.getConsent(e);if(!n)throw new Error(`Consent for visitor ${e} not found`);let o=["consent_json=$1::jsonb","updated_at=NOW()"],s=[JSON.stringify(t.consentJson)],r=2;t.profileVersion!=null&&(o.push(`profile_version=$${r++}`),s.push(t.profileVersion)),t.locale!=null&&(o.push(`locale=$${r++}`),s.push(t.locale)),t.gpcDetected!=null&&(o.push(`gpc_detected=$${r++}`),s.push(t.gpcDetected)),t.signature!=null&&(o.push(`signature=$${r++}`),s.push(t.signature)),s.push(e);let c=(await this.q(`UPDATE consenti_consent_records SET ${o.join(",")} WHERE visitor_id=$${r} RETURNING *`,s))[0];if(!c)throw new Error(`Consent for visitor ${e} not found`);return await this.writeHistory(c.id,c.tenant_id,e,n.consentJson,t.consentJson,"updated",t.profileVersion??n.profileVersion??null),Gt(c)}async deleteConsent(e){await this.q("DELETE FROM consenti_consent_history WHERE visitor_id=$1",[e]),await this.q("DELETE FROM consenti_consent_records WHERE visitor_id=$1",[e])}async getConsent(e){let t=await this.q("SELECT * FROM consenti_consent_records WHERE visitor_id=$1",[e]);return t[0]?Gt(t[0]):null}async getConsents(e){let{where:t,params:n,nextIdx:o}=this.buildConsentWhere(e),s=e.page??1,r=e.limit??50,[a,c]=await Promise.all([this.q(`SELECT ${Sl} ${t} ORDER BY created_at DESC LIMIT $${o} OFFSET $${o+1}`,[...n,r,(s-1)*r]),this.q(`SELECT COUNT(*)::int AS total ${t}`,n)]);return{items:a.map(vl),total:Number(c[0]?.total??0),page:s,limit:r}}async*streamConsents(e){let{where:t,params:n}=this.buildConsentWhere(e),o=await this.q(`SELECT * ${t} ORDER BY created_at ASC`,n);for(let s of o)yield Gt(s)}buildConsentWhere(e){let t="FROM consenti_consent_records WHERE tenant_id=$1",n=[e.tenantId],o=2;return e.profileId!=null&&(t+=` AND profile_id=$${o++}`,n.push(e.profileId)),e.from!=null&&(t+=` AND created_at>=$${o++}`,n.push(e.from)),e.to!=null&&(t+=` AND created_at<=$${o++}`,n.push(e.to)),e.q&&(t+=` AND (visitor_id ILIKE $${o} OR profile_id ILIKE $${o} OR locale ILIKE $${o} OR source ILIKE $${o})`,n.push(j(e.q)),o++),{where:t,params:n,nextIdx:o}}async writeHistory(e,t,n,o,s,r,a){await this.q(`INSERT INTO consenti_consent_history (id, tenant_id, consent_record_id, visitor_id, profile_version, old_json, new_json, action)
116
+ VALUES ($1,$2,$3,$4,$5,$6::jsonb,$7::jsonb,$8)`,[(0,C.randomUUID)(),t,e,n,a,o?JSON.stringify(o):null,JSON.stringify(s),r])}async getConsentHistory(e){return(await this.q("SELECT * FROM consenti_consent_history WHERE visitor_id=$1 ORDER BY created_at ASC",[e])).map(Cl)}async createNoticeShown(e){let t=(0,C.randomUUID)(),o=(await this.q(`INSERT INTO consenti_notice_shown (id, tenant_id, visitor_id, profile_id, locale)
117
+ VALUES ($1,$2,$3,$4,$5) RETURNING *`,[t,e.tenantId,e.visitorId,e.profileId,e.locale]))[0];return{id:o.id,tenantId:o.tenant_id,visitorId:o.visitor_id,profileId:o.profile_id,locale:o.locale,createdAt:o.created_at}}async getNoticeShownForVisitor(e){return(await this.q("SELECT * FROM consenti_notice_shown WHERE visitor_id=$1 ORDER BY created_at DESC",[e])).map(n=>({id:n.id,tenantId:n.tenant_id,visitorId:n.visitor_id,profileId:n.profile_id,locale:n.locale,createdAt:n.created_at}))}async createVisitor(e){let t=q(),o=(await this.q(`INSERT INTO consenti_visitors (id, tenant_id, visitor_id, country, region, city, ip_hash, user_agent_hash)
118
+ VALUES ($1,$2,$3,$4,$5,$6,$7,$8) RETURNING *`,[t,e.tenantId,e.visitorId,e.country??null,e.region??null,e.city??null,e.ipHash??null,e.userAgentHash??null]))[0];if(!o)throw new Error("Visitor creation failed");return jt(o)}async updateVisitor(e,t){let n=["last_seen=NOW()"],o=[],s=1;t.country!=null&&(n.push(`country=$${s++}`),o.push(t.country)),t.region!=null&&(n.push(`region=$${s++}`),o.push(t.region)),t.city!=null&&(n.push(`city=$${s++}`),o.push(t.city)),o.push(e);let a=(await this.q(`UPDATE consenti_visitors SET ${n.join(",")} WHERE visitor_id=$${s} RETURNING *`,o))[0];if(!a)throw new Error(`Visitor ${e} not found`);return jt(a)}async deleteVisitor(e){await this.q("DELETE FROM consenti_visitors WHERE visitor_id=$1",[e])}async getVisitor(e){let t=await this.q("SELECT * FROM consenti_visitors WHERE visitor_id=$1",[e]);return t[0]?jt(t[0]):null}async getVisitors(e){let t="FROM consenti_visitors WHERE tenant_id=$1",n=[e.tenantId],o=2;e.from!=null&&(t+=` AND first_seen>=$${o++}`,n.push(e.from)),e.to!=null&&(t+=` AND first_seen<=$${o++}`,n.push(e.to)),e.q&&(t+=` AND (visitor_id ILIKE $${o} OR country ILIKE $${o})`,n.push(j(e.q)),o++);let s=e.page??1,r=e.limit??50,[a,c]=await Promise.all([this.q(`SELECT * ${t} ORDER BY first_seen DESC LIMIT $${o} OFFSET $${o+1}`,[...n,r,(s-1)*r]),this.q(`SELECT COUNT(*)::int AS total ${t}`,n)]);return{items:a.map(jt),total:Number(c[0]?.total??0),page:s,limit:r}}async getOverviewStats(e){let[[t],[n],[o]]=await Promise.all([this.q("SELECT COUNT(*)::int AS total FROM consenti_consent_records WHERE tenant_id=$1",[e]),this.q("SELECT COUNT(*)::int AS total FROM consenti_consent_records WHERE tenant_id=$1 AND gpc_detected=true",[e]),this.q("SELECT COUNT(*)::int AS total FROM consenti_visitors WHERE tenant_id=$1",[e])]),s=Number(t?.total??0),r=Number(n?.total??0),a=Number(o?.total??0),c=await this.q(`SELECT val AS status, COUNT(*)::int AS count
119
+ FROM consenti_consent_records cr,
118
120
  jsonb_each_text(cr.consent_json) AS kv(key, val)
119
121
  WHERE cr.tenant_id=$1
120
122
  GROUP BY val`,[e]),l=0,d=0,u=0;for(let m of c)u+=Number(m.count),m.status==="granted"&&(l=Number(m.count)),m.status==="denied"&&(d=Number(m.count));return{totalConsents:s,acceptedPct:u>0?Math.round(l/u*100):0,rejectedPct:u>0?Math.round(d/u*100):0,totalVisitors:a,gpcDetectedCount:r}}async getCategoryStats(e){let t=await this.q(`SELECT kv.key AS cookie_id, kv.val AS status, COUNT(*)::int AS count
121
- FROM consent_records cr,
123
+ FROM consenti_consent_records cr,
122
124
  jsonb_each_text(cr.consent_json) AS kv(key, val)
123
125
  WHERE cr.tenant_id=$1
124
126
  GROUP BY kv.key, kv.val`,[e]),n={};for(let o of t){n[o.cookie_id]||(n[o.cookie_id]={granted:0,denied:0,objected:0});let s=n[o.cookie_id];s&&(o.status==="granted"&&(s.granted+=Number(o.count)),o.status==="denied"&&(s.denied+=Number(o.count)),o.status==="objected"&&(s.objected+=Number(o.count)))}return n}async getTimeline(e,t=30){let n=new Date(Date.now()-t*864e5).toISOString();return(await this.q(`SELECT to_char(created_at, 'YYYY-MM-DD') AS date, COUNT(*)::int AS count
125
- FROM consent_records
127
+ FROM consenti_consent_records
126
128
  WHERE tenant_id=$1 AND created_at>=$2
127
129
  GROUP BY to_char(created_at, 'YYYY-MM-DD')
128
- ORDER BY date ASC`,[e,n])).map(s=>({date:s.date,count:Number(s.count)}))}async createUser(e){let t=(0,v.randomUUID)(),o=(await this.q("INSERT INTO users (id, tenant_id, name, email, password_hash) VALUES ($1,$2,$3,$4,$5) RETURNING *",[t,e.tenantId,e.name,e.email,e.passwordHash]))[0];if(!o)throw new Error("User creation failed");return tt(o)}async updateUser(e,t){let n=["updated_at=NOW()"],o=[],s=1;t.name!=null&&(n.push(`name=$${s++}`),o.push(t.name)),t.email!=null&&(n.push(`email=$${s++}`),o.push(t.email)),t.passwordHash!=null&&(n.push(`password_hash=$${s++}`),o.push(t.passwordHash)),t.isActive!=null&&(n.push(`is_active=$${s++}`),o.push(t.isActive)),o.push(e);let a=(await this.q(`UPDATE users SET ${n.join(",")} WHERE id=$${s} RETURNING *`,o))[0];if(!a)throw new Error(`User ${e} not found`);return tt(a)}async deleteUser(e){await this.q("DELETE FROM user_roles WHERE user_id=$1",[e]),await this.q("DELETE FROM users WHERE id=$1",[e])}async getUserById(e){let t=await this.q("SELECT * FROM users WHERE id=$1",[e]);return t[0]?tt(t[0]):null}async getUserByEmail(e){let t=await this.q("SELECT * FROM users WHERE email=$1",[e]);return t[0]?tt(t[0]):null}async getUsers(e){return(await this.q("SELECT * FROM users WHERE tenant_id=$1 ORDER BY created_at DESC",[e])).map(tt)}async countUsers(e){let t=e?await this.q("SELECT COUNT(*)::int AS total FROM users WHERE tenant_id=$1",[e]):await this.q("SELECT COUNT(*)::int AS total FROM users");return Number(t[0]?.total??0)}async getRoles(e){return(await this.q("SELECT * FROM roles WHERE tenant_id=$1",[e])).map(nt)}async createRole(e){let t=(0,v.randomUUID)(),o=(await this.q("INSERT INTO roles (id, tenant_id, name, description) VALUES ($1,$2,$3,$4) RETURNING *",[t,e.tenantId,e.name,e.description??null]))[0];if(!o)throw new Error("Role creation failed");return nt(o)}async updateRole(e,t){let n=[],o=[],s=1;if(t.name!=null&&(n.push(`name=$${s++}`),o.push(t.name)),t.description!=null&&(n.push(`description=$${s++}`),o.push(t.description)),n.length===0){let l=(await this.q("SELECT * FROM roles WHERE id=$1",[e]))[0];if(!l)throw new Error(`Role ${e} not found`);return nt(l)}o.push(e);let a=(await this.q(`UPDATE roles SET ${n.join(",")} WHERE id=$${s} RETURNING *`,o))[0];if(!a)throw new Error(`Role ${e} not found`);return nt(a)}async deleteRole(e){await this.q("DELETE FROM role_permissions WHERE role_id=$1",[e]),await this.q("DELETE FROM user_roles WHERE role_id=$1",[e]),await this.q("DELETE FROM roles WHERE id=$1",[e])}async getAllPermissions(){return(await this.q("SELECT * FROM permissions ORDER BY name")).map(Co)}async getPermissionsForRole(e){return(await this.q("SELECT p.* FROM permissions p JOIN role_permissions rp ON p.id=rp.permission_id WHERE rp.role_id=$1",[e])).map(Co)}async getUserRoles(e,t){return(t?await this.q("SELECT r.* FROM roles r JOIN user_roles ur ON r.id=ur.role_id WHERE ur.user_id=$1 AND ur.tenant_id=$2",[e,t]):await this.q("SELECT r.* FROM roles r JOIN user_roles ur ON r.id=ur.role_id WHERE ur.user_id=$1",[e])).map(nt)}async assignRole(e,t,n="default"){await this.q("INSERT INTO user_roles (user_id, role_id, tenant_id) VALUES ($1,$2,$3) ON CONFLICT DO NOTHING",[e,t,n])}async revokeRole(e,t,n){n?await this.q("DELETE FROM user_roles WHERE user_id=$1 AND role_id=$2 AND tenant_id=$3",[e,t,n]):await this.q("DELETE FROM user_roles WHERE user_id=$1 AND role_id=$2",[e,t])}async assignPermissionToRole(e,t){await this.q("INSERT INTO role_permissions (role_id, permission_id) VALUES ($1,$2) ON CONFLICT DO NOTHING",[e,t])}async revokePermissionFromRole(e,t){await this.q("DELETE FROM role_permissions WHERE role_id=$1 AND permission_id=$2",[e,t])}async createLog(e){await this.q(`INSERT INTO audit_logs (id, tenant_id, user_id, action, resource_type, resource_id, old_data, new_data)
129
- VALUES ($1,$2,$3,$4,$5,$6,$7::jsonb,$8::jsonb)`,[(0,v.randomUUID)(),e.tenantId,e.userId??null,e.action,e.resourceType,e.resourceId??null,e.oldData!=null?JSON.stringify(e.oldData):null,e.newData!=null?JSON.stringify(e.newData):null])}async getLogs(e){let{where:t,params:n,nextIdx:o}=this.buildAuditWhere(e),s=e.page??1,r=e.limit??50,[a,c]=await Promise.all([this.q(`SELECT ${Xc} ${t} ORDER BY created_at DESC LIMIT $${o} OFFSET $${o+1}`,[...n,r,(s-1)*r]),this.q(`SELECT COUNT(*)::int AS total ${t}`,n)]);return{items:a.map(el),total:Number(c[0]?.total??0),page:s,limit:r}}async getAuditLogById(e){let t=await this.q("SELECT * FROM audit_logs WHERE id=$1",[e]);return t[0]?vo(t[0]):null}async*streamAuditLogs(e){let{where:t,params:n}=this.buildAuditWhere(e),o=await this.q(`SELECT * ${t} ORDER BY created_at ASC`,n);for(let s of o)yield vo(s)}buildAuditWhere(e){let t="FROM audit_logs WHERE tenant_id=$1",n=[e.tenantId],o=2;return e.action!=null&&(t+=` AND action=$${o++}`,n.push(e.action)),e.resourceType!=null&&(t+=` AND resource_type=$${o++}`,n.push(e.resourceType)),e.from!=null&&(t+=` AND created_at>=$${o++}`,n.push(e.from)),e.to!=null&&(t+=` AND created_at<=$${o++}`,n.push(e.to)),e.q&&(t+=` AND (action ILIKE $${o} OR resource_type ILIKE $${o} OR resource_id ILIKE $${o} OR user_id ILIKE $${o}) ESCAPE '\\'`,n.push(j(e.q)),o++),{where:t,params:n,nextIdx:o}}async getCountries(e){return(await this.q(`SELECT v.country, COUNT(*)::int AS count FROM consent_records cr
130
- JOIN visitors v ON v.visitor_id=cr.visitor_id
130
+ ORDER BY date ASC`,[e,n])).map(s=>({date:s.date,count:Number(s.count)}))}async createUser(e){let t=(0,C.randomUUID)(),o=(await this.q("INSERT INTO consenti_users (id, tenant_id, name, email, password_hash) VALUES ($1,$2,$3,$4,$5) RETURNING *",[t,e.tenantId,e.name,e.email,e.passwordHash]))[0];if(!o)throw new Error("User creation failed");return at(o)}async updateUser(e,t){let n=["updated_at=NOW()"],o=[],s=1;t.name!=null&&(n.push(`name=$${s++}`),o.push(t.name)),t.email!=null&&(n.push(`email=$${s++}`),o.push(t.email)),t.passwordHash!=null&&(n.push(`password_hash=$${s++}`),o.push(t.passwordHash)),t.isActive!=null&&(n.push(`is_active=$${s++}`),o.push(t.isActive)),o.push(e);let a=(await this.q(`UPDATE consenti_users SET ${n.join(",")} WHERE id=$${s} RETURNING *`,o))[0];if(!a)throw new Error(`User ${e} not found`);return at(a)}async deleteUser(e){await this.q("DELETE FROM consenti_user_roles WHERE user_id=$1",[e]),await this.q("DELETE FROM consenti_users WHERE id=$1",[e])}async getUserById(e){let t=await this.q("SELECT * FROM consenti_users WHERE id=$1",[e]);return t[0]?at(t[0]):null}async getUserByEmail(e){let t=await this.q("SELECT * FROM consenti_users WHERE email=$1",[e]);return t[0]?at(t[0]):null}async getUsers(e){return(await this.q("SELECT * FROM consenti_users WHERE tenant_id=$1 ORDER BY created_at DESC",[e])).map(at)}async countUsers(e){let t=e?await this.q("SELECT COUNT(*)::int AS total FROM consenti_users WHERE tenant_id=$1",[e]):await this.q("SELECT COUNT(*)::int AS total FROM consenti_users");return Number(t[0]?.total??0)}async getRoles(e){return(await this.q("SELECT * FROM consenti_roles WHERE tenant_id=$1",[e])).map(ct)}async createRole(e){let t=(0,C.randomUUID)(),o=(await this.q("INSERT INTO consenti_roles (id, tenant_id, name, description) VALUES ($1,$2,$3,$4) RETURNING *",[t,e.tenantId,e.name,e.description??null]))[0];if(!o)throw new Error("Role creation failed");return ct(o)}async updateRole(e,t){let n=[],o=[],s=1;if(t.name!=null&&(n.push(`name=$${s++}`),o.push(t.name)),t.description!=null&&(n.push(`description=$${s++}`),o.push(t.description)),n.length===0){let l=(await this.q("SELECT * FROM consenti_roles WHERE id=$1",[e]))[0];if(!l)throw new Error(`Role ${e} not found`);return ct(l)}o.push(e);let a=(await this.q(`UPDATE consenti_roles SET ${n.join(",")} WHERE id=$${s} RETURNING *`,o))[0];if(!a)throw new Error(`Role ${e} not found`);return ct(a)}async deleteRole(e){await this.q("DELETE FROM consenti_role_permissions WHERE role_id=$1",[e]),await this.q("DELETE FROM consenti_user_roles WHERE role_id=$1",[e]),await this.q("DELETE FROM consenti_roles WHERE id=$1",[e])}async getAllPermissions(){return(await this.q("SELECT * FROM consenti_permissions ORDER BY name")).map(Fo)}async getPermissionsForRole(e){return(await this.q("SELECT p.* FROM consenti_permissions p JOIN consenti_role_permissions rp ON p.id=rp.permission_id WHERE rp.role_id=$1",[e])).map(Fo)}async getUserRoles(e,t){return(t?await this.q("SELECT r.* FROM consenti_roles r JOIN consenti_user_roles ur ON r.id=ur.role_id WHERE ur.user_id=$1 AND ur.tenant_id=$2",[e,t]):await this.q("SELECT r.* FROM consenti_roles r JOIN consenti_user_roles ur ON r.id=ur.role_id WHERE ur.user_id=$1",[e])).map(ct)}async assignRole(e,t,n="default"){await this.q("INSERT INTO consenti_user_roles (user_id, role_id, tenant_id) VALUES ($1,$2,$3) ON CONFLICT DO NOTHING",[e,t,n])}async revokeRole(e,t,n){n?await this.q("DELETE FROM consenti_user_roles WHERE user_id=$1 AND role_id=$2 AND tenant_id=$3",[e,t,n]):await this.q("DELETE FROM consenti_user_roles WHERE user_id=$1 AND role_id=$2",[e,t])}async assignPermissionToRole(e,t){await this.q("INSERT INTO consenti_role_permissions (role_id, permission_id) VALUES ($1,$2) ON CONFLICT DO NOTHING",[e,t])}async revokePermissionFromRole(e,t){await this.q("DELETE FROM consenti_role_permissions WHERE role_id=$1 AND permission_id=$2",[e,t])}async createLog(e){await this.q(`INSERT INTO consenti_audit_logs (id, tenant_id, user_id, action, resource_type, resource_id, old_data, new_data)
131
+ VALUES ($1,$2,$3,$4,$5,$6,$7::jsonb,$8::jsonb)`,[(0,C.randomUUID)(),e.tenantId,e.userId??null,e.action,e.resourceType,e.resourceId??null,e.oldData!=null?JSON.stringify(e.oldData):null,e.newData!=null?JSON.stringify(e.newData):null])}async getLogs(e){let{where:t,params:n,nextIdx:o}=this.buildAuditWhere(e),s=e.page??1,r=e.limit??50,[a,c]=await Promise.all([this.q(`SELECT ${Al} ${t} ORDER BY created_at DESC LIMIT $${o} OFFSET $${o+1}`,[...n,r,(s-1)*r]),this.q(`SELECT COUNT(*)::int AS total ${t}`,n)]);return{items:a.map(Tl),total:Number(c[0]?.total??0),page:s,limit:r}}async getAuditLogById(e){let t=await this.q("SELECT * FROM consenti_audit_logs WHERE id=$1",[e]);return t[0]?Ho(t[0]):null}async*streamAuditLogs(e){let{where:t,params:n}=this.buildAuditWhere(e),o=await this.q(`SELECT * ${t} ORDER BY created_at ASC`,n);for(let s of o)yield Ho(s)}buildAuditWhere(e){let t="FROM consenti_audit_logs WHERE tenant_id=$1",n=[e.tenantId],o=2;return e.action!=null&&(t+=` AND action=$${o++}`,n.push(e.action)),e.resourceType!=null&&(t+=` AND resource_type=$${o++}`,n.push(e.resourceType)),e.from!=null&&(t+=` AND created_at>=$${o++}`,n.push(e.from)),e.to!=null&&(t+=` AND created_at<=$${o++}`,n.push(e.to)),e.q&&(t+=` AND (action ILIKE $${o} OR resource_type ILIKE $${o} OR resource_id ILIKE $${o} OR user_id ILIKE $${o})`,n.push(j(e.q)),o++),{where:t,params:n,nextIdx:o}}async getCountries(e){return(await this.q(`SELECT v.country, COUNT(*)::int AS count FROM consenti_consent_records cr
132
+ JOIN consenti_visitors v ON v.visitor_id=cr.visitor_id
131
133
  WHERE cr.tenant_id=$1 AND v.country IS NOT NULL
132
- GROUP BY v.country ORDER BY count DESC LIMIT 50`,[e])).map(n=>({country:n.country,count:Number(n.count)}))}async getGpcStats(e){let[t]=await this.q("SELECT COUNT(*)::int AS total FROM consent_records WHERE tenant_id=$1",[e]),[n]=await this.q("SELECT COUNT(*)::int AS total FROM consent_records WHERE tenant_id=$1 AND gpc_detected=TRUE",[e]),o=Number(t?.total??0),s=Number(n?.total??0);return{detected:s,total:o,rate:o>0?Math.round(s/o*100):0}}async getTenants(){return(await this.q("SELECT * FROM tenants ORDER BY name ASC",[])).map(t=>({id:t.id,name:t.name,slug:t.slug,createdAt:t.created_at,updatedAt:t.updated_at}))}mapApiKey(e){return{id:e.id,tenantId:e.tenant_id,keyHash:e.key_hash,name:e.name,isActive:e.is_active,...e.created_by!==null?{createdBy:e.created_by}:{},...e.expire_by!==null?{expireBy:e.expire_by}:{},createdAt:e.created_at,...e.updated_at!==null?{updatedAt:e.updated_at}:{}}}async createApiKey(e){let t=(0,v.randomUUID)(),o=(await this.q("INSERT INTO api_keys (id, tenant_id, key_hash, name, created_by, expire_by) VALUES ($1,$2,$3,$4,$5,$6) RETURNING *",[t,e.tenantId,e.keyHash,e.name,e.createdBy??null,e.expireBy??null]))[0];if(!o)throw new Error("Failed to create API key");return this.mapApiKey(o)}async getApiKeyByHash(e){let n=(await this.q("SELECT * FROM api_keys WHERE key_hash=$1 AND is_active=TRUE",[e]))[0];return n?this.mapApiKey(n):null}async revokeApiKey(e){await this.q("UPDATE api_keys SET is_active=FALSE, updated_at=NOW() WHERE id=$1",[e])}async reactivateApiKey(e){await this.q("UPDATE api_keys SET is_active=TRUE, updated_at=NOW(), expire_by=CASE WHEN expire_by <= NOW() THEN NULL ELSE expire_by END WHERE id=$1",[e])}async deleteApiKey(e){await this.q("DELETE FROM api_keys WHERE id=$1",[e])}async getApiKeys(e){return(await this.q("SELECT * FROM api_keys WHERE tenant_id=$1 ORDER BY created_at DESC",[e])).map(n=>this.mapApiKey(n))}async createTenant(e){let t=(0,v.randomUUID)(),n=new Date().toISOString(),s=(await this.q("INSERT INTO tenants (id, name, slug, created_at, updated_at) VALUES ($1,$2,$3,$4,$5) RETURNING *",[t,e.name,e.slug,n,n]))[0];if(!s)throw new Error("Failed to create tenant");return{id:s.id,name:s.name,slug:s.slug,createdAt:s.created_at,updatedAt:s.updated_at}}async updateTenant(e,t){let n=new Date().toISOString(),o=["updated_at=$1"],s=[n],r=2;t.name!=null&&(o.push(`name=$${r++}`),s.push(t.name)),t.slug!=null&&(o.push(`slug=$${r++}`),s.push(t.slug)),s.push(e);let c=(await this.q(`UPDATE tenants SET ${o.join(",")} WHERE id=$${r} RETURNING *`,s))[0];if(!c)throw new Error(`Tenant ${e} not found`);return{id:c.id,name:c.name,slug:c.slug,createdAt:c.created_at,updatedAt:c.updated_at}}async deleteTenant(e){await this.q("DELETE FROM tenants WHERE id=$1",[e])}async getSettings(e){let n=(await this.q("SELECT allowed_origins_json, admin_allowed_origins_json, setup_completed, profiles_seeded, tcf_confirmation_json, gpp_confirmation_json FROM tenant_settings WHERE tenant_id=$1",[e]))[0];return n?{allowedOrigins:n.allowed_origins_json,adminAllowedOrigins:n.admin_allowed_origins_json,setupCompleted:n.setup_completed,profilesSeeded:n.profiles_seeded,...n.tcf_confirmation_json?{tcfConfirmation:n.tcf_confirmation_json}:{},...n.gpp_confirmation_json?{gppConfirmation:n.gpp_confirmation_json}:{}}:{}}async updateSettings(e,t){let o={...await this.getSettings(e),...t};return await this.q(`INSERT INTO tenant_settings (tenant_id, allowed_origins_json, admin_allowed_origins_json, setup_completed, profiles_seeded, tcf_confirmation_json, gpp_confirmation_json, updated_at) VALUES ($1,$2::jsonb,$3::jsonb,$4,$5,$6::jsonb,$7::jsonb,NOW())
133
- ON CONFLICT (tenant_id) DO UPDATE SET allowed_origins_json=$2::jsonb, admin_allowed_origins_json=$3::jsonb, setup_completed=$4, profiles_seeded=$5, tcf_confirmation_json=$6::jsonb, gpp_confirmation_json=$7::jsonb, updated_at=NOW()`,[e,JSON.stringify(o.allowedOrigins??[]),JSON.stringify(o.adminAllowedOrigins??[]),o.setupCompleted??!1,o.profilesSeeded??!1,o.tcfConfirmation?JSON.stringify(o.tcfConfirmation):null,o.gppConfirmation?JSON.stringify(o.gppConfirmation):null]),this.getSettings(e)}async purgeExpiredConsents(e){let t=new Date(Date.now()-e*864e5).toISOString(),n=await this.q("SELECT visitor_id FROM consent_records WHERE created_at < $1",[t]);if(n.length===0)return 0;let o=n.map(r=>r.visitor_id),s=o.map((r,a)=>`$${a+1}`).join(",");return await this.q(`DELETE FROM consent_history WHERE visitor_id IN (${s})`,o),await this.q(`DELETE FROM consent_records WHERE visitor_id IN (${s})`,o),o.length}mapConsentTemplate(e){return{id:e.id,tenantId:e.tenant_id,name:e.name,cookies:e.cookies_json,categories:e.categories_json,createdAt:e.created_at,updatedAt:e.updated_at}}async createConsentTemplate(e){let n=(await this.q(`INSERT INTO consent_templates (id, tenant_id, name, cookies_json, categories_json)
134
- VALUES ($1,$2,$3,$4::json,$5::json) RETURNING *`,[Y(),e.tenantId,e.name,JSON.stringify(e.cookies),JSON.stringify(e.categories)]))[0];if(!n)throw new Error("Consent template creation failed");return this.mapConsentTemplate(n)}async updateConsentTemplate(e,t){let n=["updated_at = NOW()"],o=[],s=1;t.name!==void 0&&(n.push(`name=$${s++}`),o.push(t.name)),t.cookies!==void 0&&(n.push(`cookies_json=$${s++}::json`),o.push(JSON.stringify(t.cookies))),t.categories!==void 0&&(n.push(`categories_json=$${s++}::json`),o.push(JSON.stringify(t.categories)));let a=(await this.q(`UPDATE consent_templates SET ${n.join(",")} WHERE id=$${s} RETURNING *`,[...o,e]))[0];if(!a)throw new Error("Consent template not found");return this.mapConsentTemplate(a)}async deleteConsentTemplate(e){await this.q("DELETE FROM consent_templates WHERE id=$1",[e])}async getConsentTemplate(e){let t=await this.q("SELECT * FROM consent_templates WHERE id=$1",[e]);return t[0]?this.mapConsentTemplate(t[0]):null}async getConsentTemplates(e){return(await this.q("SELECT * FROM consent_templates WHERE tenant_id=$1 ORDER BY name ASC",[e])).map(n=>this.mapConsentTemplate(n))}async copyConsentTemplate(e,t){let n=await this.getConsentTemplate(e);if(!n)throw new Error("Consent template not found");return this.createConsentTemplate({tenantId:n.tenantId,name:t,cookies:n.cookies,categories:n.categories})}mapUITemplate(e){return{id:e.id,tenantId:e.tenant_id,name:e.name,...e.settings_json,createdAt:e.created_at,updatedAt:e.updated_at}}async createUITemplate(e){let{tenantId:t,name:n,...o}=e,r=(await this.q("INSERT INTO ui_templates (id, tenant_id, name, settings_json) VALUES ($1,$2,$3,$4::json) RETURNING *",[Q(),t,n,JSON.stringify(o)]))[0];if(!r)throw new Error("UI template creation failed");return this.mapUITemplate(r)}async updateUITemplate(e,t){let n=await this.q("SELECT * FROM ui_templates WHERE id=$1",[e]);if(!n[0])throw new Error("UI template not found");let{name:o,...s}=t,r=["updated_at = NOW()"],a=[],c=1;o!==void 0&&(r.push(`name=$${c++}`),a.push(o)),Object.keys(s).length>0&&(r.push(`settings_json=$${c++}::json`),a.push(JSON.stringify({...n[0].settings_json,...s})));let d=(await this.q(`UPDATE ui_templates SET ${r.join(",")} WHERE id=$${c} RETURNING *`,[...a,e]))[0];if(!d)throw new Error("UI template not found");return this.mapUITemplate(d)}async deleteUITemplate(e){await this.q("DELETE FROM ui_templates WHERE id=$1",[e])}async getUITemplate(e){let t=await this.q("SELECT * FROM ui_templates WHERE id=$1",[e]);return t[0]?this.mapUITemplate(t[0]):null}async getUITemplates(e){return(await this.q("SELECT * FROM ui_templates WHERE tenant_id=$1 ORDER BY name ASC",[e])).map(n=>this.mapUITemplate(n))}async copyUITemplate(e,t){let n=await this.getUITemplate(e);if(!n)throw new Error("UI template not found");let{tenantId:o,mainBanner:s,gpcBanner:r,preferenceModal:a}=n;return this.createUITemplate({tenantId:o,name:t,mainBanner:s,gpcBanner:r,preferenceModal:a})}async toProfileSummaries(e){if(e.length===0)return[];let t=[...new Set(e.map(s=>s.tenantId))],[n,o]=await Promise.all([Promise.all(t.map(s=>this.getConsentTemplates(s))),Promise.all(t.map(s=>this.getUITemplates(s)))]);return Ue(e,new Map(n.flat().map(s=>[s.id,s.name])),new Map(o.flat().map(s=>[s.id,s.name])))}async listProfilesSummary(e){let t=await this.q("SELECT * FROM profiles WHERE tenant_id=$1 ORDER BY created_at ASC",[e]);return this.toProfileSummaries(t.map(Oe))}async findProfilesUsingConsentTemplate(e){let t=await this.q("SELECT * FROM profiles WHERE profile_json->>'consentTemplateId'=$1 ORDER BY name ASC",[e]);return this.toProfileSummaries(t.map(Oe))}async findProfilesUsingUITemplate(e){let t=await this.q("SELECT * FROM profiles WHERE profile_json->>'uiTemplateId'=$1 ORDER BY name ASC",[e]);return this.toProfileSummaries(t.map(Oe))}async getOptInStats(e,t){let n="tenant_id=$1",o=[e];t.profileId&&(o.push(t.profileId),n+=` AND profile_id=$${o.length}`),t.from&&(o.push(t.from),n+=` AND created_at>=$${o.length}`),t.to&&(o.push(t.to),n+=` AND created_at<=$${o.length}`),t.locale&&(o.push(t.locale),n+=` AND locale=$${o.length}`);let s=await this.q(`SELECT locale, to_char(created_at, 'YYYY-MM-DD') AS day, consent_json FROM consent_records WHERE ${n} ORDER BY created_at ASC`,o);return xe(s.map(r=>({locale:r.locale,day:r.day,consentJson:r.consent_json})))}};p();var Ee=require("node:fs/promises"),he=require("node:crypto");var tl=500;function Bn(){return{_version:1,tenants:[],profiles:[],consents:[],consent_history:[],visitors:[],users:[],roles:[],permissions:[],user_roles:[],role_permissions:[],audit_logs:[],consent_templates:[],ui_templates:[],api_keys:[],settings:{},notice_shown:[]}}function Fn(i,e,t){let n=Math.min(t,tl),o=(e-1)*n;return i.slice(o,o+n)}function nl(i){let{id:e,tenantId:t,visitorId:n,profileId:o,locale:s,gpcDetected:r,source:a,ageVerified:c,createdAt:l,updatedAt:d}=i;return{id:e,tenantId:t,visitorId:n,profileId:o,locale:s,gpcDetected:r,source:a,...c!=null?{ageVerified:c}:{},createdAt:l,updatedAt:d}}function il(i){let{id:e,tenantId:t,userId:n,action:o,resourceType:s,resourceId:r,createdAt:a}=i;return{id:e,tenantId:t,action:o,resourceType:s,createdAt:a,...n!=null?{userId:n}:{},...r!=null?{resourceId:r}:{}}}var Lt=class{constructor(e){this.config=e}config;db=Bn();filePath="";writeQueue=Promise.resolve();scheduleWrite(){this.writeQueue=this.writeQueue.then(async()=>{await(0,Ee.mkdir)(this.filePath.replace(/\/[^/]+$/,""),{recursive:!0});let e=`${this.filePath}.tmp`;await(0,Ee.writeFile)(e,JSON.stringify(this.db),"utf8"),await(0,Ee.rename)(e,this.filePath)}).catch(e=>{console.warn("[Consenti] JSON store write failed:",e)})}async connect(){let{dbPath:e}=me(this.config.path??"./consenti-data","json");this.filePath=e;try{let t=await(0,Ee.readFile)(this.filePath,"utf8");this.db={...Bn(),...JSON.parse(t)}}catch{this.db=Bn()}await this.migrate()}async disconnect(){await this.writeQueue}async migrate(){this.seed()}seed(){let e=new Date().toISOString(),{id:t,name:n,slug:o}=ie;this.db.tenants.find(s=>s.id===t)||this.db.tenants.push({id:t,name:n,slug:o,createdAt:e,updatedAt:e});for(let s of ne)this.db.permissions.find(r=>r.id===s.id)||this.db.permissions.push({id:s.id,name:s.name,description:s.description});for(let s of ge)this.db.roles.find(r=>r.id===s.id)||this.db.roles.push({id:s.id,tenantId:s.tenantId,name:s.name,description:s.description});for(let s of fe)this.db.role_permissions.find(r=>r.roleId===s.roleId&&r.permissionId===s.permissionId)||this.db.role_permissions.push(s);this.scheduleWrite()}async createProfile(e){let t=new Date().toISOString(),o={id:z(),tenantId:e.tenantId,name:e.name,defaultLocale:e.defaultLocale,version:1,profileJson:e.profileJson,createdAt:t,updatedAt:t};return this.db.profiles.push(o),this.scheduleWrite(),o}async updateProfile(e,t){let n=this.db.profiles.findIndex(r=>r.id===e);if(n===-1)throw new Error(`Profile ${e} not found`);let s={...this.db.profiles[n],...t.name!=null&&{name:t.name},...t.defaultLocale!=null&&{defaultLocale:t.defaultLocale},...t.profileJson!=null&&{profileJson:t.profileJson},...t.version!=null&&{version:t.version},updatedAt:new Date().toISOString()};return this.db.profiles[n]=s,this.scheduleWrite(),s}async deleteProfile(e){this.db.profiles=this.db.profiles.filter(t=>t.id!==e),this.scheduleWrite()}async getProfile(e){return this.db.profiles.find(t=>t.id===e)??null}async getProfiles(e){return this.db.profiles.filter(t=>t.tenantId===e).sort((t,n)=>t.createdAt.localeCompare(n.createdAt))}async findActiveProfileByComplianceGroup(e,t){return this.db.profiles.find(n=>n.tenantId===e&&(n.profileJson.complianceGroup===t||n.profileJson.customComplianceGroup===t)&&n.profileJson.isActive)??null}async createConsent(e){let t=new Date().toISOString(),n=K(),o={id:n,tenantId:e.tenantId,visitorId:e.visitorId,profileId:e.profileId,locale:e.locale,consentJson:e.consentJson,gpcDetected:e.gpcDetected??!1,source:e.source,...e.ageVerified!=null&&{ageVerified:e.ageVerified},...e.parentalConsentToken!=null&&{parentalConsentToken:e.parentalConsentToken},...e.tcfString!=null&&{tcfString:e.tcfString},...e.gppString!=null&&{gppString:e.gppString},...e.signature!=null&&{signature:e.signature},createdAt:t,updatedAt:t};return this.db.consents.push(o),this.db.consent_history.push({id:(0,he.randomUUID)(),tenantId:e.tenantId,consentRecordId:n,visitorId:e.visitorId,oldJson:null,newJson:e.consentJson,action:"created",createdAt:t}),this.scheduleWrite(),o}async updateConsent(e,t){let n=this.db.consents.findIndex(a=>a.visitorId===e);if(n===-1)throw new Error(`Consent for visitor ${e} not found`);let o=this.db.consents[n],s=new Date().toISOString(),r={...o,consentJson:t.consentJson,...t.locale!=null&&{locale:t.locale},...t.gpcDetected!=null&&{gpcDetected:t.gpcDetected},...t.signature!=null&&{signature:t.signature},updatedAt:s};return this.db.consents[n]=r,this.db.consent_history.push({id:(0,he.randomUUID)(),tenantId:o.tenantId,consentRecordId:o.id,visitorId:e,oldJson:o.consentJson,newJson:t.consentJson,action:"updated",createdAt:s}),this.scheduleWrite(),r}async deleteConsent(e){this.db.consent_history=this.db.consent_history.filter(t=>t.visitorId!==e),this.db.consents=this.db.consents.filter(t=>t.visitorId!==e),this.scheduleWrite()}async getConsent(e){return this.db.consents.find(t=>t.visitorId===e)??null}async getConsents(e){let t=this.db.consents.filter(s=>s.tenantId===e.tenantId);if(e.profileId&&(t=t.filter(s=>s.profileId===e.profileId)),e.from&&(t=t.filter(s=>s.createdAt>=e.from)),e.to&&(t=t.filter(s=>s.createdAt<=e.to)),e.q){let s=e.q.toLowerCase();t=t.filter(r=>r.visitorId.toLowerCase().startsWith(s)||r.profileId.toLowerCase().startsWith(s)||r.locale.toLowerCase().startsWith(s)||r.source.toLowerCase().startsWith(s))}t.sort((s,r)=>r.createdAt.localeCompare(s.createdAt));let n=e.page??1,o=e.limit??50;return{items:Fn(t,n,o).map(nl),total:t.length,page:n,limit:o}}async*streamConsents(e){for(let t of this.db.consents.filter(n=>n.tenantId===e.tenantId))yield t}async getConsentHistory(e){return this.db.consent_history.filter(t=>t.visitorId===e).sort((t,n)=>t.createdAt.localeCompare(n.createdAt))}async createNoticeShown(e){let t={id:(0,he.randomUUID)(),tenantId:e.tenantId,visitorId:e.visitorId,profileId:e.profileId,locale:e.locale,createdAt:new Date().toISOString()};return this.db.notice_shown.push(t),this.scheduleWrite(),t}async getNoticeShownForVisitor(e){return this.db.notice_shown.filter(t=>t.visitorId===e).sort((t,n)=>n.createdAt.localeCompare(t.createdAt))}async createVisitor(e){let t=new Date().toISOString(),n={id:q(),tenantId:e.tenantId,visitorId:e.visitorId,firstSeen:t,lastSeen:t,...e.country!=null&&{country:e.country},...e.region!=null&&{region:e.region},...e.city!=null&&{city:e.city},...e.ipHash!=null&&{ipHash:e.ipHash},...e.userAgentHash!=null&&{userAgentHash:e.userAgentHash}};return this.db.visitors.push(n),this.scheduleWrite(),n}async updateVisitor(e,t){let n=this.db.visitors.findIndex(r=>r.visitorId===e);if(n===-1)throw new Error(`Visitor ${e} not found`);let s={...this.db.visitors[n],lastSeen:t.lastSeen??new Date().toISOString(),...t.country!=null&&{country:t.country},...t.region!=null&&{region:t.region},...t.city!=null&&{city:t.city}};return this.db.visitors[n]=s,this.scheduleWrite(),s}async deleteVisitor(e){this.db.visitors=this.db.visitors.filter(t=>t.visitorId!==e),this.scheduleWrite()}async getVisitor(e){return this.db.visitors.find(t=>t.visitorId===e)??null}async getVisitors(e){let t=this.db.visitors.filter(s=>s.tenantId===e.tenantId);if(e.from&&(t=t.filter(s=>s.firstSeen>=e.from)),e.to&&(t=t.filter(s=>s.firstSeen<=e.to)),e.q){let s=e.q.toLowerCase();t=t.filter(r=>r.visitorId.toLowerCase().startsWith(s)||(r.country?.toLowerCase().startsWith(s)??!1))}t.sort((s,r)=>r.lastSeen.localeCompare(s.lastSeen));let n=e.page??1,o=e.limit??50;return{items:Fn(t,n,o),total:t.length,page:n,limit:o}}async createUser(e){let t=new Date().toISOString(),n={id:(0,he.randomUUID)(),tenantId:e.tenantId,name:e.name,email:e.email,passwordHash:e.passwordHash,isActive:!0,allowedTenants:e.allowedTenants??[],createdAt:t,updatedAt:t};return this.db.users.push(n),this.scheduleWrite(),n}async updateUser(e,t){let n=this.db.users.findIndex(r=>r.id===e);if(n===-1)throw new Error(`User ${e} not found`);let s={...this.db.users[n],...t.name!=null&&{name:t.name},...t.email!=null&&{email:t.email},...t.passwordHash!=null&&{passwordHash:t.passwordHash},...t.isActive!=null&&{isActive:t.isActive},..."totpSecret"in t&&t.totpSecret!=null&&{totpSecret:t.totpSecret},...t.totpEnabled!=null&&{totpEnabled:t.totpEnabled},..."allowedTenants"in t&&{allowedTenants:t.allowedTenants??[]},updatedAt:new Date().toISOString()};return this.db.users[n]=s,this.scheduleWrite(),s}async deleteUser(e){this.db.user_roles=this.db.user_roles.filter(t=>t.userId!==e),this.db.users=this.db.users.filter(t=>t.id!==e),this.scheduleWrite()}async getUserById(e){return this.db.users.find(t=>t.id===e)??null}async getUserByEmail(e){return this.db.users.find(t=>t.email===e)??null}async getUsers(e){return this.db.users.filter(t=>t.tenantId===e).sort((t,n)=>t.createdAt.localeCompare(n.createdAt))}async countUsers(e){return e?this.db.users.filter(t=>t.tenantId===e).length:this.db.users.length}async getRoles(e){return this.db.roles.filter(t=>t.tenantId===e)}async createRole(e){let t={id:(0,he.randomUUID)(),tenantId:e.tenantId,name:e.name,...e.description!=null&&{description:e.description}};return this.db.roles.push(t),this.scheduleWrite(),t}async updateRole(e,t){let n=this.db.roles.findIndex(s=>s.id===e);if(n===-1)throw new Error(`Role ${e} not found`);let o={...this.db.roles[n],...t.name!=null&&{name:t.name},...t.description!=null&&{description:t.description}};return this.db.roles[n]=o,this.scheduleWrite(),o}async deleteRole(e){this.db.role_permissions=this.db.role_permissions.filter(t=>t.roleId!==e),this.db.user_roles=this.db.user_roles.filter(t=>t.roleId!==e),this.db.roles=this.db.roles.filter(t=>t.id!==e),this.scheduleWrite()}async getAllPermissions(){return[...this.db.permissions].sort((e,t)=>e.name.localeCompare(t.name))}async getPermissionsForRole(e){let t=new Set(this.db.role_permissions.filter(n=>n.roleId===e).map(n=>n.permissionId));return this.db.permissions.filter(n=>t.has(n.id))}async getUserRoles(e,t){let n=this.db.user_roles.filter(s=>s.userId===e);t&&(n=n.filter(s=>s.tenantId===t));let o=new Set(n.map(s=>s.roleId));return this.db.roles.filter(s=>o.has(s.id))}async assignRole(e,t,n="default"){this.db.user_roles.find(o=>o.userId===e&&o.roleId===t&&o.tenantId===n)||(this.db.user_roles.push({userId:e,roleId:t,tenantId:n}),this.scheduleWrite())}async revokeRole(e,t,n){this.db.user_roles=this.db.user_roles.filter(o=>!(o.userId===e&&o.roleId===t&&(n==null||o.tenantId===n))),this.scheduleWrite()}async assignPermissionToRole(e,t){this.db.role_permissions.find(n=>n.roleId===e&&n.permissionId===t)||(this.db.role_permissions.push({roleId:e,permissionId:t}),this.scheduleWrite())}async revokePermissionFromRole(e,t){this.db.role_permissions=this.db.role_permissions.filter(n=>!(n.roleId===e&&n.permissionId===t)),this.scheduleWrite()}async createLog(e){let t={id:(0,he.randomUUID)(),tenantId:e.tenantId,action:e.action,resourceType:e.resourceType,createdAt:new Date().toISOString(),...e.userId!=null&&{userId:e.userId},...e.resourceId!=null&&{resourceId:e.resourceId},...e.oldData!=null&&{oldData:e.oldData},...e.newData!=null&&{newData:e.newData}};this.db.audit_logs.push(t),this.scheduleWrite()}async getLogs(e){let t=this.db.audit_logs.filter(s=>s.tenantId===e.tenantId);if(e.action&&(t=t.filter(s=>s.action===e.action)),e.resourceType&&(t=t.filter(s=>s.resourceType===e.resourceType)),e.from&&(t=t.filter(s=>s.createdAt>=e.from)),e.to&&(t=t.filter(s=>s.createdAt<=e.to)),e.q){let s=e.q.toLowerCase();t=t.filter(r=>r.action.toLowerCase().startsWith(s)||r.resourceType.toLowerCase().startsWith(s)||(r.resourceId?.toLowerCase().startsWith(s)??!1)||(r.userId?.toLowerCase().startsWith(s)??!1))}t.sort((s,r)=>r.createdAt.localeCompare(s.createdAt));let n=e.page??1,o=e.limit??50;return{items:Fn(t,n,o).map(il),total:t.length,page:n,limit:o}}async getAuditLogById(e){return this.db.audit_logs.find(t=>t.id===e)??null}async*streamAuditLogs(e){let t=this.db.audit_logs.filter(n=>n.tenantId===e.tenantId);e.action&&(t=t.filter(n=>n.action===e.action)),e.from&&(t=t.filter(n=>n.createdAt>=e.from)),e.to&&(t=t.filter(n=>n.createdAt<=e.to)),t.sort((n,o)=>o.createdAt.localeCompare(n.createdAt));for(let n of t)yield n}async getOverviewStats(e){let t=this.db.consents.filter(a=>a.tenantId===e),n=t.slice(-500),o=0,s=0;for(let a of n){let c=Object.values(a.consentJson),l=c.length>0?c.filter(d=>d==="granted").length/c.length:0;l>=.8?o++:l<=.2&&s++}let r=n.length||1;return{totalConsents:t.length,gpcDetectedCount:t.filter(a=>a.gpcDetected).length,totalVisitors:this.db.visitors.filter(a=>a.tenantId===e).length,acceptedPct:Math.round(o/r*100),rejectedPct:Math.round(s/r*100)}}async getCategoryStats(e){let t={};for(let n of this.db.consents.filter(o=>o.tenantId===e).slice(0,5e3))for(let[o,s]of Object.entries(n.consentJson))t[o]||(t[o]={granted:0,denied:0,objected:0}),s==="granted"?t[o].granted++:s==="denied"?t[o].denied++:s==="objected"&&t[o].objected++;return t}async getTimeline(e,t=30){let n=new Date(Date.now()-t*864e5).toISOString().slice(0,10),o=new Map;for(let s of this.db.consents.filter(r=>r.tenantId===e&&r.createdAt.slice(0,10)>=n)){let r=s.createdAt.slice(0,10);o.set(r,(o.get(r)??0)+1)}return[...o.entries()].sort(([s],[r])=>s.localeCompare(r)).map(([s,r])=>({date:s,count:r}))}async getCountries(e){let t=new Set(this.db.consents.filter(o=>o.tenantId===e).map(o=>o.visitorId)),n=new Map;for(let o of this.db.visitors.filter(s=>t.has(s.visitorId)&&s.country)){let s=o.country;n.set(s,(n.get(s)??0)+1)}return[...n.entries()].sort(([,o],[,s])=>s-o).slice(0,50).map(([o,s])=>({country:o,count:s}))}async getGpcStats(e){let t=this.db.consents.filter(s=>s.tenantId===e),n=t.filter(s=>s.gpcDetected).length,o=t.length;return{detected:n,total:o,rate:o>0?Math.round(n/o*100):0}}async getTenants(){return[...this.db.tenants].sort((e,t)=>e.name.localeCompare(t.name))}async createTenant(e){let t=new Date().toISOString(),n={id:(0,he.randomUUID)(),name:e.name,slug:e.slug,createdAt:t,updatedAt:t};return this.db.tenants.push(n),this.scheduleWrite(),n}async updateTenant(e,t){let n=this.db.tenants.findIndex(r=>r.id===e);if(n===-1)throw new Error(`Tenant ${e} not found`);let o=new Date().toISOString(),s={...this.db.tenants[n],...t.name!=null&&{name:t.name},...t.slug!=null&&{slug:t.slug},updatedAt:o};return this.db.tenants[n]=s,this.scheduleWrite(),s}async deleteTenant(e){this.db.tenants=this.db.tenants.filter(t=>t.id!==e),this.scheduleWrite()}async getSettings(e){return this.db.settings[e]??{}}async updateSettings(e,t){let n={...this.db.settings[e]??{},...t};return this.db.settings[e]=n,this.scheduleWrite(),n}async purgeExpiredConsents(e){let t=new Date(Date.now()-e*864e5).toISOString(),n=new Set(this.db.consents.filter(o=>o.createdAt<t).map(o=>o.visitorId));return n.size===0?0:(this.db.consent_history=this.db.consent_history.filter(o=>!n.has(o.visitorId)),this.db.consents=this.db.consents.filter(o=>!n.has(o.visitorId)),this.scheduleWrite(),n.size)}async createApiKey(e){let t=new Date().toISOString(),n={id:(0,he.randomUUID)(),tenantId:e.tenantId,keyHash:e.keyHash,name:e.name,isActive:!0,...e.createdBy!==void 0?{createdBy:e.createdBy}:{},...e.expireBy!==void 0?{expireBy:e.expireBy}:{},createdAt:t,updatedAt:t};return this.db.api_keys.push(n),this.scheduleWrite(),n}async getApiKeyByHash(e){return this.db.api_keys.find(t=>t.keyHash===e&&t.isActive)??null}async revokeApiKey(e){let t=this.db.api_keys.find(n=>n.id===e);t&&(t.isActive=!1,t.updatedAt=new Date().toISOString(),this.scheduleWrite())}async reactivateApiKey(e){let t=this.db.api_keys.find(n=>n.id===e);t&&(t.isActive=!0,t.expireBy&&new Date(t.expireBy)<=new Date&&delete t.expireBy,t.updatedAt=new Date().toISOString(),this.scheduleWrite())}async deleteApiKey(e){let t=this.db.api_keys.findIndex(n=>n.id===e);t!==-1&&(this.db.api_keys.splice(t,1),this.scheduleWrite())}async getApiKeys(e){return this.db.api_keys.filter(t=>t.tenantId===e).sort((t,n)=>n.createdAt.localeCompare(t.createdAt))}async createConsentTemplate(e){let t=new Date().toISOString(),n={id:Y(),tenantId:e.tenantId,name:e.name,cookies:e.cookies,categories:e.categories,createdAt:t,updatedAt:t};return this.db.consent_templates.push(n),this.scheduleWrite(),n}async updateConsentTemplate(e,t){let n=this.db.consent_templates.findIndex(r=>r.id===e);if(n===-1)throw new Error("Consent template not found");let o=new Date().toISOString(),s={...this.db.consent_templates[n],...t.name!==void 0&&{name:t.name},...t.cookies!==void 0&&{cookies:t.cookies},...t.categories!==void 0&&{categories:t.categories},updatedAt:o};return this.db.consent_templates[n]=s,this.scheduleWrite(),s}async deleteConsentTemplate(e){this.db.consent_templates=this.db.consent_templates.filter(t=>t.id!==e),this.scheduleWrite()}async getConsentTemplate(e){return this.db.consent_templates.find(t=>t.id===e)??null}async getConsentTemplates(e){return this.db.consent_templates.filter(t=>t.tenantId===e).sort((t,n)=>t.name.localeCompare(n.name))}async copyConsentTemplate(e,t){let n=await this.getConsentTemplate(e);if(!n)throw new Error("Consent template not found");return this.createConsentTemplate({tenantId:n.tenantId,name:t,cookies:n.cookies,categories:n.categories})}async createUITemplate(e){let t=new Date().toISOString(),{tenantId:n,name:o,...s}=e,r={id:Q(),tenantId:n,name:o,...s,createdAt:t,updatedAt:t};return this.db.ui_templates.push(r),this.scheduleWrite(),r}async updateUITemplate(e,t){let n=this.db.ui_templates.findIndex(c=>c.id===e);if(n===-1)throw new Error("UI template not found");let{name:o,...s}=t,r=new Date().toISOString(),a={...this.db.ui_templates[n],...t.name!==void 0&&{name:t.name},...s,updatedAt:r};return this.db.ui_templates[n]=a,this.scheduleWrite(),a}async deleteUITemplate(e){this.db.ui_templates=this.db.ui_templates.filter(t=>t.id!==e),this.scheduleWrite()}async getUITemplate(e){return this.db.ui_templates.find(t=>t.id===e)??null}async getUITemplates(e){return this.db.ui_templates.filter(t=>t.tenantId===e).sort((t,n)=>t.name.localeCompare(n.name))}async copyUITemplate(e,t){let n=await this.getUITemplate(e);if(!n)throw new Error("UI template not found");let{tenantId:o,mainBanner:s,gpcBanner:r,preferenceModal:a}=n;return this.createUITemplate({tenantId:o,name:t,...s!==void 0&&{mainBanner:s},...r!==void 0&&{gpcBanner:r},...a!==void 0&&{preferenceModal:a}})}profileToSummary(e){let t=e.profileJson,n=t.consentTemplateId?this.db.consent_templates.find(s=>s.id===t.consentTemplateId):null,o=t.uiTemplateId?this.db.ui_templates.find(s=>s.id===t.uiTemplateId):null;return{id:e.id,name:e.name,defaultLocale:e.defaultLocale,complianceGroup:t.complianceGroup??null,customComplianceGroup:t.customComplianceGroup??null,isActive:t.isActive??!1,consentTemplateName:n?.name??null,uiTemplateName:o?.name??null,createdAt:e.createdAt,updatedAt:e.updatedAt}}async listProfilesSummary(e){return this.db.profiles.filter(t=>t.tenantId===e).sort((t,n)=>t.createdAt.localeCompare(n.createdAt)).map(t=>this.profileToSummary(t))}async findProfilesUsingConsentTemplate(e){return this.db.profiles.filter(t=>t.profileJson.consentTemplateId===e).sort((t,n)=>t.name.localeCompare(n.name)).map(t=>this.profileToSummary(t))}async findProfilesUsingUITemplate(e){return this.db.profiles.filter(t=>t.profileJson.uiTemplateId===e).sort((t,n)=>t.name.localeCompare(n.name)).map(t=>this.profileToSummary(t))}async getOptInStats(e,t){let n=this.db.consents.filter(u=>u.tenantId===e);t.profileId&&(n=n.filter(u=>u.profileId===t.profileId)),t.from&&(n=n.filter(u=>u.createdAt>=t.from)),t.to&&(n=n.filter(u=>u.createdAt<=t.to)),t.locale&&(n=n.filter(u=>u.locale===t.locale));let o=0,s=0,r=0,a=0,c={},l=new Map;for(let u of n){let m=Object.values(u.consentJson),h=m.length>0?m.filter(C=>C==="granted").length/m.length:0,S=m.length>0?m.filter(C=>C==="denied").length/m.length:0;o++;let _=u.locale;c[_]||(c[_]={total:0,granted:0,denied:0,managed:0}),c[_].total++;let w=u.createdAt.slice(0,10),R=l.get(w)??{total:0,granted:0,denied:0,managed:0};R.total++,h>=.9?(s++,c[_].granted++,R.granted++):S>=.9?(r++,c[_].denied++,R.denied++):(a++,c[_].managed++,R.managed++),l.set(w,R)}let d=Array.from(l.entries()).sort(([u],[m])=>u.localeCompare(m)).map(([u,m])=>({date:u,...m}));return{total:o,granted:s,denied:r,managed:a,grantedPct:o>0?Math.round(s/o*1e3)/10:0,deniedPct:o>0?Math.round(r/o*1e3)/10:0,managedPct:o>0?Math.round(a/o*1e3)/10:0,byLocale:c,byDate:d}}};p();var Nt=class{constructor(e){this.adapter=e}adapter;create(e){return this.adapter.createProfile(e)}update(e,t){return this.adapter.updateProfile(e,t)}delete(e){return this.adapter.deleteProfile(e)}get(e){return this.adapter.getProfile(e)}list(e){return this.adapter.getProfiles(e)}findActiveByComplianceGroup(e,t){return this.adapter.findActiveProfileByComplianceGroup(e,t)}};p();var Ut=class{constructor(e){this.adapter=e}adapter;create(e){return this.adapter.createConsent(e)}update(e,t){return this.adapter.updateConsent(e,t)}delete(e){return this.adapter.deleteConsent(e)}get(e){return this.adapter.getConsent(e)}list(e){return this.adapter.getConsents(e)}};p();var xt=class{constructor(e){this.adapter=e}adapter;create(e){return this.adapter.createVisitor(e)}update(e,t){return this.adapter.updateVisitor(e,t)}delete(e){return this.adapter.deleteVisitor(e)}get(e){return this.adapter.getVisitor(e)}};p();var Mt=class{constructor(e){this.adapter=e}adapter;create(e){return this.adapter.createNoticeShown(e)}getForVisitor(e){return this.adapter.getNoticeShownForVisitor(e)}};p();var Gt=class{constructor(e){this.adapter=e}adapter;log(e){return this.adapter.createLog(e)}list(e){return this.adapter.getLogs(e)}get(e){return this.adapter.getAuditLogById(e)}};p();p();var jt=class{constructor(e,t=500,n=6e4){this.ttlMs=e;this.maxEntries=t;this.sweepTimer=setInterval(()=>this.sweep(),n),this.sweepTimer.unref?.()}ttlMs;maxEntries;store=new Map;sweepTimer=null;get(e){let t=this.store.get(e);if(t){if(Date.now()>t.expiresAt){this.store.delete(e);return}return t.value}}set(e,t){if(this.store.size>=this.maxEntries&&!this.store.has(e)){let n=this.store.keys().next().value;n!==void 0&&this.store.delete(n)}this.store.set(e,{value:t,expiresAt:Date.now()+this.ttlMs})}sweep(){let e=Date.now();for(let[t,n]of this.store)e>n.expiresAt&&this.store.delete(t)}dispose(){this.sweepTimer&&clearInterval(this.sweepTimer),this.sweepTimer=null}};var ol=3e4,Bt=class{constructor(e){this.storage=e}storage;cache=new jt(ol);async getOverview(e){return this.cached(`overview:${e}`,()=>this.storage.getOverviewStats(e))}async getCategories(e){return this.cached(`categories:${e}`,()=>this.storage.getCategoryStats(e))}async getTimeline(e,t){return this.cached(`timeline:${e}:${t}`,()=>this.storage.getTimeline(e,t))}async getCountries(e){return this.cached(`countries:${e}`,()=>this.storage.getCountries(e))}async getGpc(e){return this.cached(`gpc:${e}`,()=>this.storage.getGpcStats(e))}async getTenants(){return this.storage.getTenants()}dispose(){this.cache.dispose()}async cached(e,t){let n=this.cache.get(e);if(n!==void 0)return n;let o=await t();return this.cache.set(e,o),o}};p();var Ft=class{constructor(e){this.adapter=e}adapter;getById(e){return this.adapter.getUserById(e)}getByEmail(e){return this.adapter.getUserByEmail(e)}list(e){return this.adapter.getUsers(e)}create(e){return this.adapter.createUser(e)}update(e,t){return this.adapter.updateUser(e,t)}delete(e){return this.adapter.deleteUser(e)}getRoles(e,t){return this.adapter.getUserRoles(e,t)}assignRole(e,t,n){return this.adapter.assignRole(e,t,n)}revokeRole(e,t,n){return this.adapter.revokeRole(e,t,n)}};p();var F=require("node:fs"),X=require("node:path");p();var Lo=require("node:worker_threads"),No=require("node:url"),Wt=require("node:path"),Uo=require("node:fs");p();var U=require("node:fs"),re=require("node:path"),Oo=require("node:crypto");p();var it=require("node:crypto");function $n(i){return(0,it.createHash)("sha256").update(i).digest("hex")}function $t(i,e){return(0,it.createHmac)("sha256",i).update(e).digest()}function sl(i){let e=i.toISOString().replace(/[-:]/g,"").slice(0,15)+"Z";return{amzDate:e,dateStamp:e.slice(0,8)}}function rl(i,e,t,n){let o=$t(`AWS4${i}`,e),s=$t(o,t),r=$t(s,n);return $t(r,"aws4_request")}function Ao(i){let{method:e,key:t,body:n,contentType:o,config:s}=i,r=new Date,{amzDate:a,dateStamp:c}=sl(r),l=`${s.bucketName}.s3.${s.region}.amazonaws.com`,d=$n(n?Buffer.isBuffer(n)?n:Buffer.from(n,"utf8"):""),u={host:l,"x-amz-date":a,"x-amz-content-sha256":d};s.sessionToken&&(u["x-amz-security-token"]=s.sessionToken),o&&e==="PUT"&&(u["content-type"]=o);let m=Object.keys(u).sort(),h=m.map(O=>`${O}:${u[O]}
135
- `).join(""),S=m.join(";"),_=[e,`/${encodeURIComponent(t).replace(/%2F/g,"/")}`,"",h,S,d].join(`
136
- `),w=`${c}/${s.region}/s3/aws4_request`,R=["AWS4-HMAC-SHA256",a,w,$n(_)].join(`
137
- `),C=rl(s.secretAccessKey,c,s.region,"s3"),A=(0,it.createHmac)("sha256",C).update(R).digest("hex"),T=[`AWS4-HMAC-SHA256 Credential=${s.accessKeyId}/${w}`,`SignedHeaders=${S}`,`Signature=${A}`].join(", ");return{...u,authorization:T}}function To(i,e){let t=encodeURIComponent(i).replace(/%2F/g,"/");return`https://${e.bucketName}.s3.${e.region}.amazonaws.com/${t}`}async function Ht(i,e,t,n="application/json"){let o=Ao({method:"PUT",key:i,body:e,contentType:n,config:t}),s=typeof e=="string"?e:e.toString("utf8"),r=await fetch(To(i,t),{method:"PUT",headers:{...o,"content-length":String(Buffer.byteLength(s,"utf8"))},body:s});if(!r.ok){let a=await r.text().catch(()=>"");throw new Error(`S3 PUT ${i} failed: ${r.status} ${a}`)}}async function Io(i,e){let t=Ao({method:"DELETE",key:i,config:e}),n=await fetch(To(i,e),{method:"DELETE",headers:t});if(!n.ok&&n.status!==404){let o=await n.text().catch(()=>"");throw new Error(`S3 DELETE ${i} failed: ${n.status} ${o}`)}}function Vn(i,e){return(0,re.join)(i,"profiles",e)}function Hn(i,e,t,n){return(0,re.join)(Vn(i,e),t,String(n))}function Do(i,e,t){return(0,re.join)(Vn(i,e),t)}function Vt(i,e,t){return`profiles/${i}/${e}/${t}.json`}function Po(i,e){let t=i+".tmp";(0,U.writeFileSync)(t,e,"utf8"),JSON.parse(e),(0,U.renameSync)(t,i)}var al=["gpcMode","complianceGroup","darkMode","allowReceipt","enhanceAccessibility","showFooterMetadata","allowedOrigins","complianceConfig","dpdpa","ageGate","hidePoweredBy"];function cl(i){let e={};for(let t of al){let n=i[t];n!==void 0&&(e[t]=n)}return e}async function bo(i){let{storagePath:e,tenantId:t,profileId:n,version:o,profile:s,localeContent:r,previousVersion:a,s3Config:c}=i,l=Hn(e,t,n,o);(0,U.mkdirSync)(l,{recursive:!0});let{locales:d,defaultLocale:u,cookies:m,expiryDays:h}=s;for(let S of d){let _,w=r[S];if(w){let C={id:s.id,version:o,defaultLocale:u,currentLocale:S,locales:d,cookies:m,...h!==void 0?{expiryDays:h}:{},...cl(s),mainBanner:w.mainBanner,...w.gpcBanner?{gpcBanner:w.gpcBanner}:{},preferenceModal:w.preferenceModal,...w.ageGateModal?{ageGateModal:w.ageGateModal}:{}};_=JSON.stringify(C,null,2)}else if(a!==void 0){let C=(0,re.join)(Hn(e,t,n,a),`${S}.json`);if(!(0,U.existsSync)(C))continue;_=(0,U.readFileSync)(C,"utf8")}else continue;let R=(0,re.join)(l,`${S}.json`);Po(R,_),S===u&&Po((0,re.join)(l,"default.json"),_),c?.enabled&&(await Ht(Vt(t,`${n}/${o}`,S),_,c),S===u&&await Ht(Vt(t,`${n}/${o}`,"default"),_,c))}if(!(0,U.existsSync)((0,re.join)(l,"default.json"))){let S=d.includes(u)?u:d[0]??"";if(S){let _=(0,re.join)(l,`${S}.json`);(0,U.existsSync)(_)&&(0,U.copyFileSync)(_,(0,re.join)(l,"default.json"))}}}function ll(i){(0,U.existsSync)(i)&&((0,U.lstatSync)(i).isSymbolicLink()||(0,U.rmSync)(i,{recursive:!0,force:!0}))}async function dl(i){let{storagePath:e,tenantId:t,profileId:n,version:o,complianceGroup:s,s3Config:r}=i,a=(0,re.resolve)(Hn(e,t,n,o)),c=Do(e,t,s);(0,U.mkdirSync)(Vn(e,t),{recursive:!0}),ll(c);let l=`${c}.new-${(0,Oo.randomUUID)().slice(0,8)}`;if((0,U.symlinkSync)(a,l,"junction"),(0,U.renameSync)(l,c),r?.enabled){let d=JSON.stringify({profileId:n,version:o});await Ht(Vt(t,s,"pointer"),d,r)}}async function ul(i){let{storagePath:e,tenantId:t,complianceGroup:n,s3Config:o}=i,s=Do(e,t,n);(0,U.existsSync)(s)&&((0,U.lstatSync)(s).isSymbolicLink()?(0,U.unlinkSync)(s):(0,U.rmSync)(s,{recursive:!0,force:!0})),o?.enabled&&await Io(Vt(t,n,"pointer"),o)}async function ko(i){i.action==="write"?await bo(i):i.action==="activate"?(await bo(i),await dl(i)):i.action==="deactivate"&&await ul(i)}var pl=(0,Wt.dirname)((0,No.fileURLToPath)(f)),xo=(0,Wt.join)(pl,"profile-json.worker.js"),ml=!(0,Uo.existsSync)(xo);async function Wn(i){if(ml){await ko(i);return}return new Promise((e,t)=>{let n=new Lo.Worker(xo);n.postMessage(i),n.once("message",o=>{n.terminate(),o.ok?e():t(new Error(`[profile-worker] ${o.action} failed: ${o.error}`))}),n.once("error",o=>{n.terminate(),t(o)})})}function di(i,e){if(!e)return i;let t={...i};for(let[n,o]of Object.entries(e))t[n]&&(t[n]={...t[n],...o});return t}function ar(i){return{...i.gpcMode!==void 0?{gpcMode:i.gpcMode}:{},...i.complianceGroup!==void 0?{complianceGroup:i.complianceGroup}:{},...i.darkMode!==void 0?{darkMode:i.darkMode}:{},...i.allowReceipt!==void 0?{allowReceipt:i.allowReceipt}:{},...i.enhanceAccessibility!==void 0?{enhanceAccessibility:i.enhanceAccessibility}:{},...i.showFooterMetadata!==void 0?{showFooterMetadata:i.showFooterMetadata}:{},...i.allowedOrigins!==void 0?{allowedOrigins:i.allowedOrigins}:{},...i.complianceConfig!==void 0?{complianceConfig:i.complianceConfig}:{},...i.dpdpa!==void 0?{dpdpa:i.dpdpa}:{},...i.ageGate!==void 0?{ageGate:i.ageGate}:{},...i.hidePoweredBy!==void 0?{hidePoweredBy:i.hidePoweredBy}:{}}}var sn=class{constructor(e,t,n="default",o,s,r,a,c,l){this.profiles=e;this.audit=t;this.tenantId=n;this.storage=o;this.eventBus=s;this.localeCache=r;this.profilesDir=a;this.handleCache=c;this.s3Config=l}profiles;audit;tenantId;storage;eventBus;localeCache;profilesDir;handleCache;s3Config;versionsRootDir(e){return(0,X.join)(this.profilesDir??"",this.tenantId,e)}complianceGroupDir(e){return(0,X.join)(this.profilesDir??"",this.tenantId,e)}groupKey(e){return e.complianceGroup||e.customComplianceGroup||""}profileFilePaths(e,t){let n=this.complianceGroupDir(e);return t.map(o=>(0,X.join)(n,`${o}.json`)).concat((0,X.join)(n,"default.json"))}async resolveCookies(e){let t=e.cookies??{};if(e.consentTemplateId&&this.storage){let n=await this.storage.getConsentTemplate(e.consentTemplateId);n&&(t=n.cookies)}return di(t,e.cookiesOverride)}async writeLocaleFiles(e,t,n,o){if(!this.profilesDir)return;let s=e.profileJson,r=await this.resolveCookies(s),a=s.locales?.length?s.locales:[e.defaultLocale],c={[e.defaultLocale]:{mainBanner:s.mainBanner,...s.gpcBanner?{gpcBanner:s.gpcBanner}:{},preferenceModal:s.preferenceModal,...s.ageGateModal?{ageGateModal:s.ageGateModal}:{}},...t??{}},l=s.isActive??!1,u={action:l?"activate":"write",storagePath:(0,X.join)(this.profilesDir,".."),tenantId:this.tenantId,profileId:e.id,version:e.version,complianceGroup:n,profile:{id:e.id,defaultLocale:e.defaultLocale,locales:a,cookies:r,...s.expiryDays!==void 0?{expiryDays:s.expiryDays}:{},...ar(s)},localeContent:c,...o!==void 0?{previousVersion:o}:{},...this.s3Config?.enabled?{s3Config:this.s3Config}:{}};if(await Wn(u),l){let m=this.profileFilePaths(n,a);this.handleCache?.(m,e.id,!0),this.eventBus?.emit("cache:purge",{paths:m,profileId:e.id})}}async create(e){let{localeContent:t,...n}=e,o=await this.profiles.create({...n,tenantId:this.tenantId});if(await this.audit.log({tenantId:this.tenantId,action:"profile:created",resourceType:"profile",resourceId:o.id,newData:{profileId:o.id,version:o.version,complianceGroup:this.groupKey(o.profileJson)}}),this.eventBus?.emit("profile:created",o),this.profilesDir){let s=this.groupKey(o.profileJson);await this.writeLocaleFiles(o,t,s,void 0);let r=o.profileJson.locales?.length?o.profileJson.locales:[o.defaultLocale],a=this.profileFilePaths(s,r);this.handleCache?.(a,o.id,!1),this.eventBus?.emit("cache:warm",{paths:a,profileId:o.id})}return o}async copy(e,t){let n=await this.profiles.get(e);if(!n)throw new Error(`Profile ${e} not found`);let o=n.profileJson.locales?.length?n.profileJson.locales:[n.defaultLocale],s={};for(let r of o){if(r===n.defaultLocale)continue;let a=await this.getVersionFile(e,String(n.version),r);if(a)try{let c=JSON.parse(a);s[r]={mainBanner:c.mainBanner,...c.gpcBanner?{gpcBanner:c.gpcBanner}:{},preferenceModal:c.preferenceModal}}catch{}}return this.create({name:t??`Copy of ${n.name}`,defaultLocale:n.defaultLocale,profileJson:{...n.profileJson,isActive:!1},...Object.keys(s).length>0?{localeContent:s}:{}})}async update(e,t){let n=await this.profiles.get(e);if(!n)throw new Error(`Profile ${e} not found`);let{localeContent:o,...s}=t,r=s.profileJson?.isActive??n.profileJson.isActive,a=s.profileJson?{...s.profileJson,...r!==void 0?{isActive:r}:{}}:n.profileJson,c=await this.profiles.update(e,{name:s.name??n.name,defaultLocale:s.defaultLocale??n.defaultLocale,profileJson:a,version:n.version+1});if(this.localeCache?.invalidate(e),await this.audit.log({tenantId:this.tenantId,action:"profile:updated",resourceType:"profile",resourceId:c.id,oldData:{profileId:n.id,version:n.version},newData:{profileId:c.id,version:c.version,complianceGroup:this.groupKey(c.profileJson)}}),this.eventBus?.emit("profile:updated",{previous:n,current:c}),this.profilesDir){let l=this.groupKey(c.profileJson);await this.writeLocaleFiles(c,o,l,n.version)}return c}async delete(e){let t=await this.profiles.get(e);if(await this.profiles.delete(e),this.localeCache?.invalidate(e),await this.audit.log({tenantId:this.tenantId,action:"profile:deleted",resourceType:"profile",resourceId:e,...t!=null?{oldData:{profileId:t.id,version:t.version}}:{}}),this.eventBus?.emit("profile:deleted",{id:e,previous:t}),this.profilesDir&&t){let n=this.groupKey(t.profileJson);if((t.profileJson.isActive??!1)&&n){let s=t.profileJson.locales?.length?t.profileJson.locales:[t.defaultLocale];await this.runDeactivate(n);let r=this.profileFilePaths(n,s);this.handleCache?.(r,e,!0),this.eventBus?.emit("cache:purge",{paths:r,profileId:e})}}}async activate(e){let t=await this.profiles.get(e);if(!t)throw new Error(`Profile ${e} not found`);let n=this.groupKey(t.profileJson),o=await this.profiles.update(e,{profileJson:{...t.profileJson,isActive:!0}});return this.localeCache?.invalidate(e),this.profilesDir&&n&&await this.writeLocaleFiles(o,void 0,n,t.version),await this.audit.log({tenantId:this.tenantId,action:"profile.activated",resourceType:"profile",resourceId:e}),this.eventBus?.emit("profile.activated",o),o}async deactivate(e){let t=await this.profiles.get(e);if(!t)throw new Error(`Profile ${e} not found`);let n=this.groupKey(t.profileJson),o=await this.profiles.update(e,{profileJson:{...t.profileJson,isActive:!1}});if(this.localeCache?.invalidate(e),this.profilesDir&&n){let s=t.profileJson.locales?.length?t.profileJson.locales:[t.defaultLocale];await this.runDeactivate(n);let r=this.profileFilePaths(n,s);this.handleCache?.(r,e,!0),this.eventBus?.emit("cache:purge",{paths:r,profileId:e})}return await this.audit.log({tenantId:this.tenantId,action:"profile.deactivated",resourceType:"profile",resourceId:e}),this.eventBus?.emit("profile.deactivated",o),o}async runDeactivate(e){if(!this.profilesDir)return;let t={action:"deactivate",storagePath:(0,X.join)(this.profilesDir,".."),tenantId:this.tenantId,profileId:"",version:0,complianceGroup:e,profile:{id:"",defaultLocale:"",locales:[],cookies:{}},localeContent:{},...this.s3Config?.enabled?{s3Config:this.s3Config}:{}};await Wn(t)}async get(e){return this.profiles.get(e)}async getResolved(e,t){let n=await this.profiles.get(e);if(!n)return null;let o=t??n.defaultLocale;if(this.localeCache){let u=this.localeCache.read(e,o);if(u)return u}let s=n.profileJson,r=await this.resolveCookies(s),a=s.locales?.length?s.locales:[n.defaultLocale],l={mainBanner:s.mainBanner,...s.gpcBanner?{gpcBanner:s.gpcBanner}:{},preferenceModal:s.preferenceModal,...s.ageGateModal?{ageGateModal:s.ageGateModal}:{}};if(o!==n.defaultLocale){let u=await this.getVersionFile(e,String(n.version),o);if(u)try{let m=JSON.parse(u);l={mainBanner:m.mainBanner,...m.gpcBanner?{gpcBanner:m.gpcBanner}:{},preferenceModal:m.preferenceModal,...m.ageGateModal?{ageGateModal:m.ageGateModal}:{}}}catch{}}let d={id:n.id,version:n.version,defaultLocale:n.defaultLocale,currentLocale:o,locales:a,cookies:r,...s.expiryDays!==void 0?{expiryDays:s.expiryDays}:{},...ar(s),...l};if(this.localeCache)try{this.localeCache.write(e,o,d)}catch(u){console.warn(`[Consenti] locale cache write failed for ${e}/${o}:`,u)}return d}findActiveByComplianceGroup(e){return this.profiles.findActiveByComplianceGroup(this.tenantId,e)}list(){return this.profiles.list(this.tenantId)}listSummary(){return this.storage?this.storage.listProfilesSummary(this.tenantId):Promise.resolve([])}async listVersions(e){if(!this.profilesDir)return[];let t=this.versionsRootDir(e);if(!(0,F.existsSync)(t))return[];let n=[];try{let o=(0,F.readdirSync)(t,{withFileTypes:!0});for(let s of o){if(!s.isDirectory())continue;let r=Number(s.name);if(!Number.isInteger(r))continue;let a=(0,X.join)(t,s.name),c=(0,F.readdirSync)(a).filter(d=>d.endsWith(".json")&&d!=="default.json").map(d=>d.replace(".json","")),l;try{l=(0,F.statSync)(a).mtime.toISOString()}catch{l=new Date().toISOString()}n.push({version:r,createdAt:l,locales:c})}}catch{return[]}return n.sort((o,s)=>s.version-o.version)}async getVersionFile(e,t,n){if(!this.profilesDir)return null;let o=(0,X.join)(this.versionsRootDir(e),t),s=(0,X.join)(o,`${n}.json`);if(!(0,F.existsSync)(s)){let r=(0,X.join)(o,"default.json");return(0,F.existsSync)(r)?(0,F.readFileSync)(r,"utf8"):null}return(0,F.readFileSync)(s,"utf8")}async listArchivedProfiles(){if(!this.profilesDir)return[];let e=(0,X.join)(this.profilesDir,this.tenantId);if(!(0,F.existsSync)(e))return[];let t=new Set((await this.profiles.list(this.tenantId)).map(s=>s.id)),n=[],o;try{o=(0,F.readdirSync)(e,{withFileTypes:!0})}catch{return[]}for(let s of o){if(!s.isDirectory()||t.has(s.name))continue;let r=(0,X.join)(e,s.name);if((0,F.lstatSync)(r).isSymbolicLink())continue;let a;try{a=(0,F.readdirSync)(r,{withFileTypes:!0})}catch{continue}let c=a.filter(d=>d.isDirectory()&&Number.isInteger(Number(d.name)));if(c.length===0)continue;let l=new Date(0).toISOString();for(let d of c)try{let u=(0,F.statSync)((0,X.join)(r,d.name)).mtime.toISOString();u>l&&(l=u)}catch{}n.push({id:s.name,versionCount:c.length,lastModified:l})}return n.sort((s,r)=>r.lastModified.localeCompare(s.lastModified))}toTemplateButtonMap(e){let t={};for(let[n,o]of Object.entries(e))t[n]={type:o.style,action:o.action,...o.cookies!==void 0?{cookies:o.cookies}:{}};return t}buildSeedUiTemplatePayload(e){let t={position:e.mainBanner.position,buttons:this.toTemplateButtonMap(e.mainBanner.buttons),...e.mainBanner.showClose!==void 0?{showClose:e.mainBanner.showClose}:{},...e.mainBanner.showLocaleSwitcher!==void 0?{showLocaleSwitcher:e.mainBanner.showLocaleSwitcher}:{}},n=e.gpcBanner?{position:e.gpcBanner.position,buttons:this.toTemplateButtonMap(e.gpcBanner.buttons),...e.gpcBanner.showClose!==void 0?{showClose:e.gpcBanner.showClose}:{},...e.gpcBanner.showLocaleSwitcher!==void 0?{showLocaleSwitcher:e.gpcBanner.showLocaleSwitcher}:{}}:t,o={buttons:this.toTemplateButtonMap(e.preferenceModal.buttons),...e.preferenceModal.position!==void 0?{position:e.preferenceModal.position}:{},...e.preferenceModal.persistent!==void 0?{persistent:e.preferenceModal.persistent}:{}};return{mainBanner:t,gpcBanner:n,preferenceModal:o}}async getOrCreateSeedTemplates(e,t,n){if(!this.storage)throw new Error("Storage adapter required to seed templates");let o=`Default \u2014 ${e}`,r=(await this.storage.getConsentTemplates(this.tenantId)).find(l=>l.name===o)??await this.storage.createConsentTemplate({tenantId:this.tenantId,name:o,cookies:t.cookies,categories:n.preferenceModal.categories}),c=(await this.storage.getUITemplates(this.tenantId)).find(l=>l.name===o)??await this.storage.createUITemplate({tenantId:this.tenantId,name:o,...this.buildSeedUiTemplatePayload(n)});return{consentTemplateId:r.id,uiTemplateId:c.id}}async seedDefaultProfile(e){if(await this.profiles.findActiveByComplianceGroup(this.tenantId,e))return;let{DEFAULT_PROFILES:n,resolveLocaleTranslation:o}=await Promise.resolve().then(()=>(ti(),Js)),s=n[e];if(!s)return;let r=s.translations.en;if(!r)return;let a=["de","es","fr","ja"],c=["en",...a.filter(m=>o(e,m)!==void 0)],l={};for(let m of a){let h=o(e,m);h&&(l[m]={mainBanner:h.mainBanner,...h.gpcBanner?{gpcBanner:h.gpcBanner}:{},preferenceModal:h.preferenceModal})}let{consentTemplateId:d,uiTemplateId:u}=await this.getOrCreateSeedTemplates(e,{cookies:s.cookies},r);await this.create({name:`Default \u2014 ${e}`,defaultLocale:s.defaultLocale,profileJson:{id:(0,v.randomUUID)(),defaultLocale:s.defaultLocale,complianceGroup:s.complianceGroup,gpcMode:s.gpcMode,cookies:s.cookies,consentTemplateId:d,uiTemplateId:u,...s.expiryDays!==void 0?{expiryDays:s.expiryDays}:{},locales:c,mainBanner:r.mainBanner,...r.gpcBanner?{gpcBanner:r.gpcBanner}:{},preferenceModal:r.preferenceModal,isActive:!0},...Object.keys(l).length>0?{localeContent:l}:{}})}async seedAllDefaults(){let{COMPLIANCE_GROUP_IDS:e}=await Promise.resolve().then(()=>(ae(),rr));await Promise.all(e.map(t=>this.seedDefaultProfile(t)))}};p();p();var cr={"Europe/Amsterdam":"NL","Europe/Andorra":"AD","Europe/Athens":"GR","Europe/Belgrade":"RS","Europe/Berlin":"DE","Europe/Bratislava":"SK","Europe/Brussels":"BE","Europe/Bucharest":"RO","Europe/Budapest":"HU","Europe/Busingen":"DE","Europe/Chisinau":"MD","Europe/Copenhagen":"DK","Europe/Dublin":"IE","Europe/Gibraltar":"GI","Europe/Guernsey":"GG","Europe/Helsinki":"FI","Europe/Isle_of_Man":"IM","Europe/Istanbul":"TR","Europe/Jersey":"JE","Europe/Kaliningrad":"RU","Europe/Kiev":"UA","Europe/Kyiv":"UA","Europe/Lisbon":"PT","Europe/Ljubljana":"SI","Europe/London":"GB","Europe/Luxembourg":"LU","Europe/Madrid":"ES","Europe/Malta":"MT","Europe/Mariehamn":"FI","Europe/Minsk":"BY","Europe/Monaco":"MC","Europe/Moscow":"RU","Europe/Nicosia":"CY","Europe/Oslo":"NO","Europe/Paris":"FR","Europe/Podgorica":"ME","Europe/Prague":"CZ","Europe/Riga":"LV","Europe/Rome":"IT","Europe/Samara":"RU","Europe/San_Marino":"SM","Europe/Sarajevo":"BA","Europe/Saratov":"RU","Europe/Simferopol":"UA","Europe/Skopje":"MK","Europe/Sofia":"BG","Europe/Stockholm":"SE","Europe/Tallinn":"EE","Europe/Tirane":"AL","Europe/Ulyanovsk":"RU","Europe/Uzhgorod":"UA","Europe/Vaduz":"LI","Europe/Vatican":"VA","Europe/Vienna":"AT","Europe/Vilnius":"LT","Europe/Volgograd":"RU","Europe/Warsaw":"PL","Europe/Zagreb":"HR","Europe/Zaporozhye":"UA","Europe/Zurich":"CH","Atlantic/Reykjavik":"IS","Atlantic/Faroe":"FO","America/New_York":"US","America/Chicago":"US","America/Denver":"US","America/Los_Angeles":"US","America/Anchorage":"US","America/Adak":"US","America/Honolulu":"US","America/Phoenix":"US","America/Detroit":"US","America/Indiana/Indianapolis":"US","America/Indiana/Knox":"US","America/Indiana/Marengo":"US","America/Indiana/Petersburg":"US","America/Indiana/Tell_City":"US","America/Indiana/Vevay":"US","America/Indiana/Vincennes":"US","America/Indiana/Winamac":"US","America/Kentucky/Louisville":"US","America/Kentucky/Monticello":"US","America/North_Dakota/Beulah":"US","America/North_Dakota/Center":"US","America/North_Dakota/New_Salem":"US","America/Boise":"US","America/Menominee":"US","America/Nome":"US","America/Sitka":"US","America/Yakutat":"US","America/Juneau":"US","America/Metlakatla":"US","America/Toronto":"CA","America/Vancouver":"CA","America/Winnipeg":"CA","America/Halifax":"CA","America/St_Johns":"CA","America/Edmonton":"CA","America/Regina":"CA","America/Whitehorse":"CA","America/Yellowknife":"CA","America/Iqaluit":"CA","America/Moncton":"CA","America/Glace_Bay":"CA","America/Goose_Bay":"CA","America/Swift_Current":"CA","America/Dawson":"CA","America/Cambridge_Bay":"CA","America/Dawson_Creek":"CA","America/Fort_Nelson":"CA","America/Creston":"CA","America/Rankin_Inlet":"CA","America/Resolute":"CA","America/Pangnirtung":"CA","America/Nipigon":"CA","America/Mexico_City":"MX","America/Cancun":"MX","America/Monterrey":"MX","America/Merida":"MX","America/Chihuahua":"MX","America/Hermosillo":"MX","America/Mazatlan":"MX","America/Ojinaga":"MX","America/Bahia_Banderas":"MX","America/Matamoros":"MX","America/Tijuana":"MX","America/Sao_Paulo":"BR","America/Manaus":"BR","America/Belem":"BR","America/Fortaleza":"BR","America/Recife":"BR","America/Maceio":"BR","America/Bahia":"BR","America/Porto_Velho":"BR","America/Boa_Vista":"BR","America/Campo_Grande":"BR","America/Cuiaba":"BR","America/Santarem":"BR","America/Rio_Branco":"BR","America/Eirunepe":"BR","America/Noronha":"BR","America/Argentina/Buenos_Aires":"AR","America/Argentina/Cordoba":"AR","America/Argentina/Salta":"AR","America/Argentina/Jujuy":"AR","America/Argentina/Tucuman":"AR","America/Argentina/Catamarca":"AR","America/Argentina/La_Rioja":"AR","America/Argentina/San_Juan":"AR","America/Argentina/Mendoza":"AR","America/Argentina/San_Luis":"AR","America/Argentina/Rio_Gallegos":"AR","America/Argentina/Ushuaia":"AR","America/Bogota":"CO","America/Lima":"PE","America/Santiago":"CL","America/Caracas":"VE","America/La_Paz":"BO","America/Asuncion":"PY","America/Montevideo":"UY","America/Guayaquil":"EC","America/Guyana":"GY","America/Paramaribo":"SR","America/Cayenne":"GF","America/Panama":"PA","America/Costa_Rica":"CR","America/Guatemala":"GT","America/El_Salvador":"SV","America/Tegucigalpa":"HN","America/Managua":"NI","America/Belize":"BZ","America/Havana":"CU","America/Jamaica":"JM","America/Nassau":"BS","America/Port_of_Spain":"TT","America/Santo_Domingo":"DO","America/Port-au-Prince":"HT","America/Barbados":"BB","America/Martinique":"MQ","America/Guadeloupe":"GP","America/Puerto_Rico":"PR","America/St_Kitts":"KN","Asia/Kolkata":"IN","Asia/Calcutta":"IN","Asia/Karachi":"PK","Asia/Dhaka":"BD","Asia/Colombo":"LK","Asia/Kathmandu":"NP","Asia/Kabul":"AF","Asia/Tokyo":"JP","Asia/Seoul":"KR","Asia/Shanghai":"CN","Asia/Hong_Kong":"HK","Asia/Macau":"MO","Asia/Taipei":"TW","Asia/Ulaanbaatar":"MN","Asia/Choibalsan":"MN","Asia/Hovd":"MN","Asia/Singapore":"SG","Asia/Bangkok":"TH","Asia/Jakarta":"ID","Asia/Kuala_Lumpur":"MY","Asia/Manila":"PH","Asia/Ho_Chi_Minh":"VN","Asia/Saigon":"VN","Asia/Phnom_Penh":"KH","Asia/Vientiane":"LA","Asia/Rangoon":"MM","Asia/Yangon":"MM","Asia/Pontianak":"ID","Asia/Makassar":"ID","Asia/Jayapura":"ID","Asia/Kuching":"MY","Asia/Brunei":"BN","Asia/Dili":"TL","Asia/Tashkent":"UZ","Asia/Almaty":"KZ","Asia/Qyzylorda":"KZ","Asia/Aqtau":"KZ","Asia/Aqtobe":"KZ","Asia/Atyrau":"KZ","Asia/Oral":"KZ","Asia/Ashgabat":"TM","Asia/Dushanbe":"TJ","Asia/Bishkek":"KG","Asia/Yekaterinburg":"RU","Asia/Tehran":"IR","Asia/Baghdad":"IQ","Asia/Riyadh":"SA","Asia/Dubai":"AE","Asia/Kuwait":"KW","Asia/Qatar":"QA","Asia/Bahrain":"BH","Asia/Muscat":"OM","Asia/Beirut":"LB","Asia/Jerusalem":"IL","Asia/Tel_Aviv":"IL","Asia/Amman":"JO","Asia/Damascus":"SY","Asia/Nicosia":"CY","Asia/Famagusta":"CY","Asia/Baku":"AZ","Asia/Yerevan":"AM","Asia/Tbilisi":"GE","Asia/Samarkand":"UZ","Africa/Cairo":"EG","Africa/Casablanca":"MA","Africa/Lagos":"NG","Africa/Nairobi":"KE","Africa/Johannesburg":"ZA","Africa/Addis_Ababa":"ET","Africa/Algiers":"DZ","Africa/Tunis":"TN","Africa/Tripoli":"LY","Africa/Khartoum":"SD","Africa/Accra":"GH","Africa/Dar_es_Salaam":"TZ","Africa/Abidjan":"CI","Africa/Bamako":"ML","Africa/Banjul":"GM","Africa/Conakry":"GN","Africa/Dakar":"SN","Africa/Freetown":"SL","Africa/Lome":"TG","Africa/Monrovia":"LR","Africa/Nouakchott":"MR","Africa/Ouagadougou":"BF","Africa/Sao_Tome":"ST","Africa/Bissau":"GW","Africa/Bangui":"CF","Africa/Brazzaville":"CG","Africa/Douala":"CM","Africa/Kinshasa":"CD","Africa/Libreville":"GA","Africa/Luanda":"AO","Africa/Malabo":"GQ","Africa/Ndjamena":"TD","Africa/Niamey":"NE","Africa/Porto-Novo":"BJ","Africa/Blantyre":"MW","Africa/Bujumbura":"BI","Africa/Gaborone":"BW","Africa/Harare":"ZW","Africa/Kampala":"UG","Africa/Kigali":"RW","Africa/Lubumbashi":"CD","Africa/Lusaka":"ZM","Africa/Maputo":"MZ","Africa/Maseru":"LS","Africa/Mbabane":"SZ","Africa/Mogadishu":"SO","Africa/Windhoek":"NA","Africa/Asmara":"ER","Africa/Djibouti":"DJ","Africa/El_Aaiun":"EH","Africa/Juba":"SS","Africa/Ceuta":"ES","Australia/Sydney":"AU","Australia/Melbourne":"AU","Australia/Brisbane":"AU","Australia/Perth":"AU","Australia/Adelaide":"AU","Australia/Darwin":"AU","Australia/Hobart":"AU","Australia/Canberra":"AU","Australia/Broken_Hill":"AU","Australia/Lord_Howe":"AU","Australia/Lindeman":"AU","Australia/Eucla":"AU","Pacific/Auckland":"NZ","Pacific/Chatham":"NZ","Pacific/Fiji":"FJ","Pacific/Port_Moresby":"PG","Pacific/Bougainville":"PG","Pacific/Guam":"GU","Pacific/Saipan":"MP","Pacific/Pago_Pago":"AS","Pacific/Apia":"WS","Pacific/Tongatapu":"TO","Pacific/Fakaofo":"TK","Pacific/Niue":"NU","Pacific/Rarotonga":"CK","Pacific/Tahiti":"PF","Pacific/Marquesas":"PF","Pacific/Gambier":"PF","Pacific/Honolulu":"US","Pacific/Johnston":"US","Pacific/Midway":"UM","Pacific/Wake":"UM","Pacific/Tarawa":"KI","Pacific/Enderbury":"KI","Pacific/Kiritimati":"KI","Pacific/Efate":"VU","Pacific/Guadalcanal":"SB","Pacific/Noumea":"NC","Pacific/Nauru":"NR","Pacific/Palau":"PW","Pacific/Chuuk":"FM","Pacific/Pohnpei":"FM","Pacific/Kosrae":"FM","Pacific/Majuro":"MH","Pacific/Kwajalein":"MH","Pacific/Funafuti":"TV","Pacific/Wallis":"WF","Asia/Novosibirsk":"RU","Asia/Omsk":"RU","Asia/Krasnoyarsk":"RU","Asia/Irkutsk":"RU","Asia/Chita":"RU","Asia/Yakutsk":"RU","Asia/Khandyga":"RU","Asia/Vladivostok":"RU","Asia/Ust-Nera":"RU","Asia/Magadan":"RU","Asia/Sakhalin":"RU","Asia/Srednekolymsk":"RU","Asia/Kamchatka":"RU","Asia/Anadyr":"RU"};var od={ar:"SA",cs:"CZ",da:"DK",de:"DE",el:"GR",fi:"FI",fr:"FR",he:"IL",hi:"IN",hu:"HU",id:"ID",it:"IT",ja:"JP",ko:"KR",nl:"NL",no:"NO",pl:"PL",pt:"BR",ro:"RO",ru:"RU",sv:"SE",th:"TH",tr:"TR",uk:"UA",vi:"VN",zh:"CN"},rn=class{constructor(e,t){this.map=t;this.provider=e??"default",this.provider==="default"&&console.warn("[Consenti] geoDataProvider is unset (using the timezone/language heuristic) \u2014 this cannot resolve US state-level regions (California, Colorado, etc.), so US visitors always fall back to the country-level default (the strictest group, opt-out-strict) rather than their actual state law. Configure a geoip-capable provider (geoip, hosted-geoip-lite, or maxmind) for accurate US state routing in production.")}map;provider;setMap(e){this.map=e}async resolve(e){let t="",n,o,s=null,r;if(typeof this.provider=="function"){let l=await this.provider(e);t=l.country??"",n=l.region??void 0,s=l.locale,r=l.complianceGroup??void 0}else switch(this.provider){case"default":({country:t}=rd(e.timezone)),t||({country:t,region:n}=sd(e.language));break;case"geoip":({country:t,region:n}=await ad(e.ip));break;case"hosted-geoip-lite":({country:t,region:n}=await ld(e.ip));break;case"maxmind":({country:t,region:n}=await cd(e.ip));break}let a={country:t,complianceGroup:r??this.resolveGroup(t,n)};return n!==void 0&&(a.region=n),o!==void 0&&(a.regulation=o),s!==null&&(a.locale=s),this.resolveRequiresSensitiveOptIn(t,n)&&(a.requiresSensitiveOptIn=!0),a}countryEntry(e){return this.map.countries[e]}resolveGroup(e,t){if(!e)return"";let n=this.countryEntry(e);return n?t!==void 0?n.overriddenRegions?.[t]?.complianceGroup??n.complianceGroup:n.default??n.complianceGroup:""}resolveRequiresSensitiveOptIn(e,t){return!e||t===void 0?!1:this.countryEntry(e)?.overriddenRegions?.[t]?.requiresSensitiveOptIn===!0}};function sd(i){let t=(i.split(",")[0]?.trim().split(";")[0]?.trim()??"").split("-");if(t.length>=2){let o=(t[t.length-1]??"").toUpperCase();if(/^[A-Z]{2}$/.test(o))return{country:o}}return{country:od[(t[0]??"").toLowerCase()]??""}}function rd(i){return{country:cr[i]??""}}async function ad(i){if(!i)return{country:""};try{let t=(await import("geoip-lite")).lookup(i),n={country:t?.country??""},o=t?.region;return o&&(n.region=o),n}catch{return console.warn("[Consenti] geoip-lite not installed \u2014 country detection skipped. Run: npm install geoip-lite"),{country:""}}}async function cd(i){if(!i)return{country:""};try{let e=await import("maxmind"),t=process.env.MAXMIND_DB_PATH??"./GeoLite2-City.mmdb",o=(await e.open(t)).get(i),s=o?.country?.iso_code??"",r=o?.subdivisions?.[0]?.iso_code,a={country:s};return r&&(a.region=r),a}catch{return console.warn("[Consenti] maxmind not available \u2014 country detection skipped. See HOW_TO_MAXMIND.md"),{country:""}}}async function ld(i){return i?new Promise(e=>{import("node:https").then(({default:t})=>{let n=`https://ipinfo.io/${encodeURIComponent(i)}/json`,o=t.get(n,{timeout:3e3},s=>{let r=[];s.on("data",a=>r.push(a)),s.on("end",()=>{try{let a=JSON.parse(Buffer.concat(r).toString()),c={country:a.country??""};a.region&&(c.region=a.region),e(c)}catch{e({country:""})}})});o.on("error",()=>e({country:""})),o.on("timeout",()=>{o.destroy(),e({country:""})})}).catch(()=>e({country:""}))}):{country:""}}p();ae();var dd=1440*60*1e3;function ud(i){let e=i?.headers.get("cache-control")?.match(/max-age=(\d+)/)?.[1];if(e){let n=parseInt(e,10)*1e3;if(!isNaN(n)&&n>0)return n}let t=i?.headers.get("expires");if(t){let n=Date.parse(t)-Date.now();if(!isNaN(n)&&n>0)return n}return dd}function lr(i,e){let t,n=async()=>{let{map:o,response:s}=await oi(i,r=>console.error("[Consenti]",r));e.setMap(o),typeof i=="string"&&(t=setTimeout(()=>{n()},ud(s)),t.unref())};return n(),{stop:()=>{t&&clearTimeout(t)}}}p();var Re=require("node:fs"),ui=require("node:path");p();var H=require("node:fs"),dr=require("node:path");function ur(i,e,t){let n=i+".bak",o=i+".tmp";(0,H.mkdirSync)((0,dr.dirname)(i),{recursive:!0});let s=(0,H.existsSync)(i);s&&(0,H.copyFileSync)(i,n);try{(0,H.writeFileSync)(o,JSON.stringify(e,null,2),"utf8");let r=JSON.parse((0,H.readFileSync)(o,"utf8"));if(!t(r))throw new Error("Schema validation failed for "+i);if((0,H.renameSync)(o,i),s)try{(0,H.unlinkSync)(n)}catch{}}catch(r){if(s)try{(0,H.copyFileSync)(n,i),(0,H.unlinkSync)(n)}catch{}try{(0,H.unlinkSync)(o)}catch{}throw r}}function pr(i){return typeof i=="object"&&i!==null&&typeof i.id=="string"&&typeof i.version=="number"}var an=class{constructor(e){this.dir=e}dir;read(e,t){let n=this.path(e,t);if(!(0,Re.existsSync)(n))return null;try{let o=JSON.parse((0,Re.readFileSync)(n,"utf8"));return pr(o)?o:null}catch{return null}}write(e,t,n){ur(this.path(e,t),n,pr)}rebuild(e,t){for(let[n,o]of t)try{this.write(e,n,o)}catch(s){console.warn(`[Consenti] locale cache rebuild failed for ${e}/${n}:`,s)}}invalidate(e){try{let t=`${e}_`;for(let n of(0,Re.readdirSync)(this.dir))if(n.startsWith(t)&&n.endsWith(".json"))try{(0,Re.unlinkSync)((0,ui.join)(this.dir,n))}catch{}}catch{}}path(e,t){return(0,ui.join)(this.dir,`${e}_${t}.json`)}};p();p();ae();function mr(i,e,t){let n=[];for(let[o,s]of Object.entries(i.consentJson)){if(!e[o])continue;let r=Fe(o,t);r==="mandatory"&&s!=="granted"&&n.push(`Cookie "${o}" is mandatory and cannot be "${s}"`),s==="objected"&&r!=="legitimate_interest"&&n.push(`Cookie "${o}" has legal basis "${r}" \u2014 'objected' is only valid for 'legitimate_interest'`)}return{valid:n.length===0,errors:n}}function pi(i,e,t,n,o){let s={};for(let[r,a]of Object.entries(i)){if(ni(r,e)){s[r]="granted";continue}if(o==="cpra"){if(a.cpraCategory==="sensitive"){let l=t[r];s[r]=l==="granted"||l==="denied"||l==="objected"?l:"denied";continue}if(n&&(a.cpraCategory==="sale"||a.cpraCategory==="sharing")){s[r]="denied";continue}}if(n&&a.listenGpc&&o!=="dpdpa"){s[r]="denied";continue}let c=t[r];c==="granted"||c==="denied"||c==="objected"?s[r]=c:s[r]="denied"}return s}function mi(i){let e=Object.keys(i.consentJson).sort().map(t=>`${t}=${i.consentJson[t]}`).join(",");return`${i.tenantId}|${i.visitorId}|${i.profileId}|${i.locale}|${e}`}function gr(i,e,t,n){let o=[];return(!t||t.id!==e.id)&&o.push("profile_changed"),pd(i,e)&&o.push("consent_expired"),n&&i.signature&&le(mi(i),n)!==i.signature&&o.push("hmac_invalid"),{valid:o.length===0,reasons:o,...t?{currentProfileId:t.id}:{},consentProfileId:e.id}}function fr(i,e){let t=new Set,n=new Set;for(let[o,s]of Object.entries(i))if(e[o]==="granted"){s.tcfVendorId&&t.add(s.tcfVendorId);for(let r of s.tcfPurposes??[])n.add(r)}return{vendorConsents:[...t].sort((o,s)=>o-s),purposeConsents:[...n].sort((o,s)=>o-s)}}function pd(i,e){let t=e.profileJson.expiryDays;if(!t)return!1;let o=new Date(i.createdAt).getTime()+t*24*60*60*1e3;return Date.now()>o}ae();p();var hr=!1,cn=null,yr=!1;async function md(){if(hr)return cn;hr=!0;try{cn=await import("@iabtechlabtcf/core")}catch{cn=null}return cn}function gd(i,e){let t=new Set,n=new Set;for(let o of i){let s=e.vendors[String(o)];if(s?.legIntPurposes?.length){t.add(o);for(let r of s.legIntPurposes)n.add(r)}}return{vendorLegitimateInterests:[...t].sort((o,s)=>o-s),purposeLegitimateInterests:[...n].sort((o,s)=>o-s)}}async function _r(i){let e=await md();if(!e)return yr||(yr=!0,console.warn('[consenti] TCF is enabled but the optional "@iabtechlabtcf/core" dependency is not installed. Falling back to a simplified, non-spec-compliant TC string. Run `npm install @iabtechlabtcf/core` to produce real IAB-spec binary TC strings.')),null;let{TCModel:t,TCString:n,GVL:o}=e,s=new o(i.gvl.raw),r=new t(s);r.cmpId=i.cmpId,r.cmpVersion=i.cmpVersion,r.consentScreen=i.consentScreen,r.consentLanguage=i.consentLanguage,r.publisherCountryCode=i.publisherCC,r.isServiceSpecific=i.isServiceSpecific,r.purposeConsents.set(i.purposeConsents),r.vendorConsents.set(i.vendorConsents);let{vendorLegitimateInterests:a,purposeLegitimateInterests:c}=gd(i.vendorConsents,i.gvl);return r.purposeLegitimateInterests.set(c),r.vendorLegitimateInterests.set(a),r.vendorsDisclosed.set(i.vendorConsents),n.encode(r)}p();var wr=require("node:crypto");function at(i){let e=Object.keys(i).sort().map(t=>`${t}=${i[t]??""}`).join("&");return(0,wr.createHash)("sha256").update(e).digest("hex")}function ue(i,e,t){return i?t?t.configHash===at(e):!1:!0}p();ae();var Er=!1,ln=null,Rr=!1;async function fd(){if(Er)return ln;Er=!0;try{ln=await import("@iabgpp/cmpapi")}catch{ln=null}return ln}var Sr=0,Cr=1,hd=2;function dn(i){return i?Cr:Sr}function gi(i,e){return i?e?Cr:hd:Sr}async function yd(i){let e=await fd();if(!e)return null;let{GppModel:t}=e,n=new t;return n.setFieldValue("usnat","SharingNotice",dn(i.sharingApplicable)),n.setFieldValue("usnat","SaleOptOutNotice",dn(i.saleApplicable)),n.setFieldValue("usnat","SharingOptOutNotice",dn(i.sharingApplicable)),n.setFieldValue("usnat","TargetedAdvertisingOptOutNotice",dn(i.sharingApplicable)),n.setFieldValue("usnat","SaleOptOut",gi(i.saleApplicable,i.saleOptOut)),n.setFieldValue("usnat","SharingOptOut",gi(i.sharingApplicable,i.sharingOptOut)),n.setFieldValue("usnat","TargetedAdvertisingOptOut",gi(i.sharingApplicable,i.sharingOptOut)),n.setFieldValue("usnat","MspaCoveredTransaction",i.mspaCoveredTransaction?1:2),n.setFieldValue("usnat","MspaOptOutOptionMode",i.mspaOptOutOptionMode),n.setFieldValue("usnat","MspaServiceProviderMode",i.mspaServiceProviderMode),i.gpcDetected!==void 0&&(n.setFieldValue("usnat","GpcSegmentIncluded",!0),n.setFieldValue("usnat","Gpc",i.gpcDetected)),n.encode()}async function vr(i){let e=await yd(i);return e||(Rr||(Rr=!0,console.warn('[consenti] GPP is enabled but the optional "@iabgpp/cmpapi" dependency is not installed. Falling back to a simplified, non-spec-compliant GPP string. Run `npm install @iabgpp/cmpapi` to produce real IAB-spec binary GPP strings.')),li(i))}var un=class{constructor(e,t,n,o,s="default",r,a,c,l,d,u,m){this.consents=e;this.visitors=t;this.profiles=n;this.audit=o;this.tenantId=s;this.compliance=r;this.pluginEngine=a;this.eventBus=c;this.tcfConfig=l;this.storage=d;this.dataSigningHash=u;this.gppConfig=m}consents;visitors;profiles;audit;tenantId;compliance;pluginEngine;eventBus;tcfConfig;storage;dataSigningHash;gppConfig;sign(e){if(this.dataSigningHash)return le(mi(e),this.dataSigningHash)}async isTcfConfirmed(){if(!this.tcfConfig?.enabled)return!0;if(!this.storage)return!1;let e=await this.storage.getSettings(this.tenantId);return ue(!0,{cmpId:this.tcfConfig.cmpId,cmpVersion:this.tcfConfig.cmpVersion,publisherCC:this.tcfConfig.publisherCC},e.tcfConfirmation)}async isGppConfirmed(){if(!this.gppConfig?.enabled)return!0;if(!this.storage)return!1;let e=await this.storage.getSettings(this.tenantId);return ue(!0,{cmpId:this.gppConfig.cmpId,cmpVersion:this.gppConfig.cmpVersion},e.gppConfirmation)}async resolveTemplateData(e){let t=!e.cookies,n=!e.preferenceModal?.categories,o=(t||n)&&e.consentTemplateId&&this.storage?await this.storage.getConsentTemplate(e.consentTemplateId):null;return{cookies:e.cookies??(o?di(o.cookies,e.cookiesOverride):{}),categories:e.preferenceModal?.categories??o?.categories??{}}}async create(e){let t=await this.profiles.get(e.profileId);if(!t)throw new Error(`Profile ${e.profileId} not found`);let n=t.profileJson.regulation,{cookies:o,categories:s}=await this.resolveTemplateData(t.profileJson),r=Be(s),a=e.consentJson;if(e.gpcDetected&&this.compliance?.gpc!==!1&&n!=="dpdpa"){a={...a};for(let[N,ce]of Object.entries(o))n==="cpra"?(ce.cpraCategory==="sale"||ce.cpraCategory==="sharing")&&(a[N]="denied"):ce.listenGpc&&(a[N]="denied")}let c=mr({...e,consentJson:a},o,r);if(!c.valid)throw new Error(c.errors.join("; "));let l=pi(o,r,a,e.gpcDetected,n),d,u=this.tcfConfig,m=u?.enabled&&Object.values(o).some(N=>N.tcfVendorId),h=m?await this.isTcfConfirmed():!0;if(u&&m&&!h)console.error(`[Consenti] TCF is enabled (cmpId=${u.cmpId}, cmpVersion=${u.cmpVersion}) but this registration is unconfirmed \u2014 treating TCF as disabled for this consent write (no tcfString generated). Confirm the current cmpId/cmpVersion in the dashboard's TCF Registration panel to re-enable.`);else if(u&&m){let N=await Ae(),{vendorConsents:ce,purposeConsents:oe}=fr(o,l),qe=e.locale?.slice(0,2)??"en";d=u.publisherCC&&N?await _r({cmpId:u.cmpId,cmpVersion:u.cmpVersion,consentScreen:1,consentLanguage:qe,publisherCC:u.publisherCC,isServiceSpecific:!0,purposeConsents:oe,vendorConsents:ce,gvl:N})??void 0:void 0,d||(d=ai({cmpId:u.cmpId,cmpVersion:u.cmpVersion,consentScreen:1,consentLanguage:qe,vendorListVersion:N?.vendorListVersion??0,purposeConsents:oe,vendorConsents:ce}))}let S,_=this.gppConfig,w=Object.values(o).some(N=>N.cpraCategory==="sale"),R=Object.values(o).some(N=>N.cpraCategory==="sharing"),C=_?.enabled&&(w||R),A=C?await this.isGppConfirmed():!0;if(_&&C&&!A)console.error(`[Consenti] GPP is enabled (cmpId=${_.cmpId}, cmpVersion=${_.cmpVersion}) but this registration is unconfirmed \u2014 treating GPP as disabled for this consent write (no gppString generated). Confirm the current cmpId/cmpVersion in the dashboard's GPP Registration panel to re-enable.`);else if(_&&C){let N=!w||Object.entries(o).filter(([,oe])=>oe.cpraCategory==="sale").every(([oe])=>l[oe]!=="granted"),ce=!R||Object.entries(o).filter(([,oe])=>oe.cpraCategory==="sharing").every(([oe])=>l[oe]!=="granted");S=await vr({cmpId:_.cmpId,cmpVersion:_.cmpVersion,mspaCoveredTransaction:_.mspaCoveredTransaction,mspaOptOutOptionMode:_.mspaOptOutOptionMode,mspaServiceProviderMode:_.mspaServiceProviderMode,saleOptOut:N,saleApplicable:w,sharingOptOut:ce,sharingApplicable:R,gpcDetected:e.gpcDetected})}let T=this.sign({tenantId:this.tenantId,visitorId:e.visitorId,profileId:e.profileId,locale:e.locale,consentJson:l}),O={...e,tenantId:this.tenantId,consentJson:l,...d?{tcfString:d}:{},...S?{gppString:S}:{},...T?{signature:T}:{}};this.pluginEngine&&(O=await this.pluginEngine.runBeforeConsentSave(O));let D=await this.consents.get(e.visitorId),G;if(D){let N=await(this.pluginEngine?this.pluginEngine.runBeforeConsentUpdate({consentJson:l,locale:e.locale,gpcDetected:e.gpcDetected,...T?{signature:T}:{}}):Promise.resolve({consentJson:l,locale:e.locale,gpcDetected:e.gpcDetected,...T?{signature:T}:{}}));G=await this.consents.update(e.visitorId,N)}else G=await this.consents.create(O);return await this.audit.log({tenantId:this.tenantId,action:D?"consent:updated":"consent:created",resourceType:"consent",resourceId:G.id,...D!=null?{oldData:D}:{},newData:G}),D?(this.eventBus?.emit("consent:updated",{previous:D,current:G}),await this.pluginEngine?.runAfterConsentUpdate(G)):(this.eventBus?.emit("consent:created",G),await this.pluginEngine?.runAfterConsentSave(G)),G}async update(e,t){let n=await this.consents.get(e);if(!n)throw new Error(`Consent for visitor ${e} not found`);let o=await this.profiles.get(n.profileId);if(!o)throw new Error(`Profile ${n.profileId} not found`);let s=o.profileJson.regulation,{cookies:r,categories:a}=await this.resolveTemplateData(o.profileJson),c=Be(a),l=t.gpcDetected??n.gpcDetected,d=t.consentJson;if(l&&this.compliance?.gpc!==!1&&s!=="dpdpa"){d={...d};for(let[w,R]of Object.entries(r))s==="cpra"?(R.cpraCategory==="sale"||R.cpraCategory==="sharing")&&(d[w]="denied"):R.listenGpc&&(d[w]="denied")}let u=pi(r,c,d,l,s),m=this.sign({tenantId:this.tenantId,visitorId:e,profileId:n.profileId,locale:t.locale??n.locale,consentJson:u}),h={consentJson:u,...t.locale!==void 0?{locale:t.locale}:{},...t.gpcDetected!==void 0?{gpcDetected:t.gpcDetected}:{},...m?{signature:m}:{}},S=await(this.pluginEngine?this.pluginEngine.runBeforeConsentUpdate(h):Promise.resolve(h)),_=await this.consents.update(e,S);return await this.audit.log({tenantId:this.tenantId,action:"consent:updated",resourceType:"consent",resourceId:_.id,oldData:n,newData:_}),this.eventBus?.emit("consent:updated",{previous:n,current:_}),await this.pluginEngine?.runAfterConsentUpdate(_),_}get(e){return this.consents.get(e)}async verify(e){let t=await this.consents.get(e);if(!t)return{valid:!1,reasons:["profile_changed"]};let n=await this.profiles.get(t.profileId);if(!n)return{valid:!1,reasons:["profile_changed"]};let o=n.profileJson.complianceGroup,s=o?await this.profiles.findActiveByComplianceGroup(this.tenantId,o):null;return gr(t,n,s,this.dataSigningHash)}async erase(e){let t=await this.consents.get(e);await this.consents.delete(e),await this.visitors.delete(e),await this.audit.log({tenantId:this.tenantId,action:"consent:erased",resourceType:"consent",resourceId:e,...t!=null?{oldData:t}:{}}),this.eventBus?.emit("consent:erased",{visitorId:e})}};p();var pn=class{constructor(e,t="default",n,o=""){this.visitors=e;this.tenantId=t;this.eventBus=n;this.dataSigningHash=o}visitors;tenantId;eventBus;dataSigningHash;async upsert(e){if(await this.visitors.get(e.visitorId))return this.visitors.update(e.visitorId,{...e.country!=null?{country:e.country}:{},...e.region!=null?{region:e.region}:{},...e.city!=null?{city:e.city}:{}});let n={tenantId:this.tenantId,visitorId:e.visitorId,...e.country!=null?{country:e.country}:{},...e.region!=null?{region:e.region}:{},...e.city!=null?{city:e.city}:{},...e.ip?{ipHash:Ji(e.ip,this.dataSigningHash)}:{},...e.userAgent?{userAgentHash:zi(e.userAgent)}:{}},o=await this.visitors.create(n);return this.eventBus?.emit("visitor:created",o),o}};p();var mn=class{constructor(e,t="default"){this.notices=e;this.tenantId=t}notices;tenantId;recordShown(e){return this.notices.create({tenantId:this.tenantId,...e})}getForVisitor(e){return this.notices.getForVisitor(e)}};p();var gn=class{constructor(e,t,n="default"){this.users=e;this.audit=t;this.tenantId=n}users;audit;tenantId;safe(e){let{passwordHash:t,...n}=e;return n}async create(e,t){let n=await this.users.create({tenantId:this.tenantId,name:e.name,email:e.email,passwordHash:Ze(e.password),...e.allowedTenants?{allowedTenants:e.allowedTenants}:{}});return e.roleId&&await this.users.assignRole(n.id,e.roleId),await this.audit.log({tenantId:this.tenantId,...t!=null?{userId:t}:{},action:"user.created",resourceType:"user",resourceId:n.id,newData:this.safe(n)}),this.safe(n)}async update(e,t,n){let o=await this.users.getById(e);if(!o)throw new Error(`User ${e} not found`);let s={};t.name!=null&&(s.name=t.name),t.email!=null&&(s.email=t.email),t.isActive!=null&&(s.isActive=t.isActive),t.password&&(s.passwordHash=Ze(t.password)),t.allowedTenants!=null&&(s.allowedTenants=t.allowedTenants);let r=await this.users.update(e,s);return await this.audit.log({tenantId:this.tenantId,...n!=null?{userId:n}:{},action:"user.updated",resourceType:"user",resourceId:e,oldData:this.safe(o),newData:this.safe(r)}),this.safe(r)}async delete(e,t){let n=await this.users.getById(e);await this.users.delete(e),await this.audit.log({tenantId:this.tenantId,...t!=null?{userId:t}:{},action:"user.deleted",resourceType:"user",resourceId:e,...n!=null?{oldData:this.safe(n)}:{}})}async get(e){let t=await this.users.getById(e);return t?this.safe(t):null}async list(){return(await this.users.list(this.tenantId)).map(t=>this.safe(t))}getRoles(e,t){return this.users.getRoles(e,t)}assignRole(e,t,n){return this.users.assignRole(e,t,n)}revokeRole(e,t,n){return this.users.revokeRole(e,t,n)}};p();var Ar=15*6e4,_d=5,Tr=1800,fn=class{constructor(e,t){this.storage=e;this.secret=t;setInterval(()=>{let n=Date.now();for(let[o,s]of this.loginAttempts)n>=s.resetAt&&this.loginAttempts.delete(o)},Ar).unref()}storage;secret;loginAttempts=new Map;async bootstrap(e,t){if(await this.storage.countUsers("default")>0)return null;if(t.length<12)throw new Error("[Consenti] bootstrap: admin password must be at least 12 characters");t.length<16&&console.warn("[Consenti] bootstrap: admin password is shorter than 16 characters \u2014 consider using a longer password");let o=Ze(t),s=await this.storage.createUser({tenantId:"default",name:"Admin",email:e,passwordHash:o});return await this.storage.assignRole(s.id,"role_super_admin"),s}async login(e,t){let n=Date.now(),o=this.loginAttempts.get(e);if(o&&n<o.resetAt&&o.count>=_d)return null;let s=await this.storage.getUserByEmail(e);if(!s||!s.isActive||!Ki(t,s.passwordHash)){let l=this.loginAttempts.get(e);return!l||n>=l.resetAt?this.loginAttempts.set(e,{count:1,resetAt:n+Ar}):l.count+=1,null}this.loginAttempts.delete(e);let r=await this.storage.getUserRoles(s.id),a=await Promise.all(r.map(l=>this.storage.getPermissionsForRole(l.id))),c=[...new Set(a.flat().map(l=>l.name))];return kn({sub:s.id,email:s.email,roles:r.map(l=>l.name),permissions:c,allowedTenants:s.allowedTenants??[]},this.secret,Tr)}signToken(e){return kn(e,this.secret,Tr)}verify(e){return St(e,this.secret)}async getUser(e){let t=this.verify(e);if(!t)return null;let n=t.sub;return typeof n!="string"?null:this.storage.getUserById(n)}};p();p();var ct=class extends Error{constructor(){super("Payload Too Large")}};function wd(i,e){let t=i.socket?.remoteAddress??"";if(!e?.length||!e.includes(t))return t;let n=i.headers["x-forwarded-for"];return typeof n=="string"?n.split(",")[0]?.trim()??t:Array.isArray(n)?n[0]?.trim()??t:t}function y(i,e){return new Response(JSON.stringify(e),{status:i,headers:{"Content-Type":"application/json"}})}async function P(i){if(!(i.headers.get("content-type")??"").includes("application/json"))return null;try{return await i.json()}catch{return null}}function M(i,e){return i.searchParams.get(e)??void 0}function hn(i,e,t){let n=i.searchParams.get(e);if(!n)return t;let o=parseInt(n,10);return isNaN(o)?t:o}var Ir=500;function $e(i,e=50){let t=hn(i,"limit",e);return t<1||t>Ir?{error:`limit must be between 1 and ${Ir}`}:{page:Math.max(1,hn(i,"page",1)),limit:t}}async function Pr(i,e=1048576,t){let o=i.headers["x-forwarded-proto"]==="https"?"https":"http",s=i.headers.host??"localhost",r=new URL(i.url??"/",`${o}://${s}`),a=new Headers;for(let[d,u]of Object.entries(i.headers))if(u)if(Array.isArray(u))for(let m of u)a.append(d,m);else a.set(d,u);a.set("x-real-ip",wd(i,t));let c=null,l=(i.method??"GET").toUpperCase();if(l!=="GET"&&l!=="HEAD"){let d=[],u=0;for await(let m of i){if(u+=m.length,u>e)throw new ct;d.push(m)}d.length>0&&(c=Buffer.concat(d))}return new Request(r.toString(),{method:l,headers:a,body:c})}async function br(i,e){e.statusCode=i.status;let t=typeof i.headers.getSetCookie=="function"?i.headers.getSetCookie():i.headers.get("set-cookie")?[i.headers.get("set-cookie")]:[];i.headers.forEach((n,o)=>{o.toLowerCase()!=="set-cookie"&&e.setHeader(o,n)});for(let n of t)e.appendHeader("set-cookie",n);if(i.body){let n=i.body.getReader();try{for(;;){let{done:o,value:s}=await n.read();if(o)break;e.write(Buffer.from(s))}}finally{n.releaseLock()}e.end()}else e.end()}p();function g(i,e,t){let n={error:e};return t!=null&&(n.details=t),new Response(JSON.stringify(n),{status:i,headers:{"Content-Type":"application/json"}})}async function E(i){try{return await i()}catch(e){let t=e instanceof Error?e.message:"Internal Server Error";return g(500,"Internal Server Error",process.env.NODE_ENV!=="production"?t:void 0)}}var ke=require("node:fs"),lt=require("node:path"),Ed="public, max-age=3600, stale-while-revalidate=60",Or={"Content-Type":"application/json","Cache-Control":Ed};function Rd(i){let e=(0,ke.readFileSync)(i,"utf8");return new Response(e,{headers:Or})}function Sd(i,e,t){return new Response(null,{status:303,headers:{Location:`${i}/profiles/${e}/${t}/default`}})}function Dr(i,e,t,n=""){return{"GET /profiles/:tenantId/:complianceGroupOrProfileId/:locale":async(o,s)=>E(async()=>{let{tenantId:r,complianceGroupOrProfileId:a,locale:c}=s;if(!r||!a||!c)return g(400,"Missing path parameters");if(t){let d=(0,lt.join)(t,r,a,`${c}.json`);if((0,ke.existsSync)(d))return Rd(d);let u=(0,lt.join)(t,r,a,"default.json");if((0,ke.existsSync)(u))return Sd(n,r,a)}let l=await i.getResolved(a,c);return l?y(200,l):g(404,"Profile not found")}),"GET /profiles/:tenantId/:profileId/:entryId/:locale":async(o,s)=>E(async()=>{let{profileId:r,entryId:a,locale:c}=s;if(!r||!a||!c)return g(400,"Missing path parameters");let l=await i.getVersionFile(r,a,c);return l?new Response(l,{headers:Or}):g(404,"Version not found")}),"GET /resolve-profile":async(o,s)=>E(async()=>{if(!e)return g(501,"Geo compliance routing not configured");let r=new URL(o.url),a=o.headers.get("x-forwarded-for")?.split(",")[0]?.trim()??o.headers.get("x-real-ip")??"",c=r.searchParams.get("tz")??"",l=r.searchParams.get("lang")??o.headers.get("accept-language")??"",d=r.searchParams.get("locale")??"",u=r.searchParams.get("data");if(u)try{let D=JSON.parse(Buffer.from(u,"base64").toString("utf8"));D.timezone&&(c=D.timezone),D.language&&(l=D.language),D.locale&&(d=D.locale)}catch{}let m=await e.resolve({ip:a,language:l,timezone:c}),h=m.requiresSensitiveOptIn?{requiresSensitiveOptIn:!0}:{};if(!m.complianceGroup)return y(200,{path:null,complianceGroup:"opt-in",locale:d||"en",found:!1,...h});let S=await i.findActiveByComplianceGroup(m.complianceGroup);if(!S)return y(200,{path:null,complianceGroup:m.complianceGroup,locale:d||"en",found:!1,...h});let _=S.profileJson.locales??[],w=S.defaultLocale;if(d&&_.includes(d))w=d;else if(_.length>0){let D=(d||l).split("-")[0]??"",G=_.find(N=>N===D||N.startsWith(`${D}-`));G&&(w=G)}let R=m.complianceGroup,C=S.tenantId,A=!1,T=t?(0,lt.join)(t,C,R,`${w}.json`):"";if(t&&(0,ke.existsSync)(T))A=!0;else if(t){let D=(0,lt.join)(t,C,R,`${S.defaultLocale}.json`);(0,ke.existsSync)(D)&&(w=S.defaultLocale,T=D,A=!0)}let O=A?`${n}/profiles/${C}/${R}/${w}`:null;return y(200,{path:O,complianceGroup:R,locale:w,found:A,...h})}),"GET /profiles/:id":async(o,s)=>E(async()=>{let r=s.id;if(!r)return g(400,"Missing profile id");let a=await i.getResolved(r);return a?y(200,a):g(404,"Profile not found")}),"GET /profiles/:id/:locale":async(o,s)=>E(async()=>{let{id:r,locale:a}=s;if(!r)return g(400,"Missing profile id");let c=await i.getResolved(r,a);return c?y(200,c):g(404,"Profile not found")}),"GET /profiles/auto/:locale":async(o,s)=>E(async()=>{if(!e)return g(501,"Geo compliance routing not configured");let r=s.locale??"en",a=new URL(o.url),c=o.headers.get("x-forwarded-for")?.split(",")[0]?.trim()??o.headers.get("x-real-ip")??"",l=a.searchParams.get("tz")??"",d=o.headers.get("accept-language")??a.searchParams.get("lang")??"",u=await e.resolve({ip:c,language:d,timezone:l});if(!u.complianceGroup)return g(404,"Could not resolve compliance group for this location");let m=await i.findActiveByComplianceGroup(u.complianceGroup);if(!m)return g(404,`No active profile found for compliance group: ${u.complianceGroup}`);let h=await i.getResolved(m.id,r);return h?y(200,{...h,resolvedComplianceGroup:u.complianceGroup,...u.requiresSensitiveOptIn?{requiresSensitiveOptIn:!0}:{}}):g(404,"Profile not found")})}}p();p();function kr(){return process.env.NODE_ENV==="production"?"SameSite=None; Secure":"SameSite=Lax"}function Cd(i,e,t){let n=le(`${i}.${e}`,t);return`${e}.${n}`}function fi(i,e,t){let n=`consenti_${i}`,o=Cd(i,e,t);return`${n}=${o}; ${kr()}; Path=/; Max-Age=31536000`}function Lr(i){return`${`consenti_${i}`}=; ${kr()}; Path=/; Max-Age=0`}function Nr(i,e,t){let n=i.split(".");if(n.length!==2)return!1;let[o,s]=n;return!o||!s?!1:Rt(`${e}.${o}`,s,t)}p();var yn="pcon_";function vd(i){return Buffer.from(JSON.stringify(i),"utf8").toString("base64url")}function Ad(i){try{let e=JSON.parse(Buffer.from(i,"base64url").toString("utf8"));return typeof e.visitorId!="string"||typeof e.profileId!="string"||typeof e.issuedAt!="number"?null:{visitorId:e.visitorId,profileId:e.profileId,issuedAt:e.issuedAt}}catch{return null}}function Ur(i,e,t){let n={visitorId:i,profileId:e,issuedAt:Math.round(Date.now()/1e3)},o=vd(n);if(!t)return`${yn}${o}`;let s=le(o,t);return`${yn}${o}.${s}`}function xr(i,e,t){if(!i.startsWith(yn))return{valid:!1,reason:"malformed"};let n=i.slice(yn.length),o=n.indexOf("."),s=o===-1?n:n.slice(0,o),r=o===-1?void 0:n.slice(o+1);if(e&&(!r||!Rt(s,r,e)))return{valid:!1,reason:"invalid_signature"};let a=Ad(s);return a?t>0&&Math.round(Date.now()/1e3)-a.issuedAt>t*24*60*60?{valid:!1,reason:"expired"}:{valid:!0,visitorId:a.visitorId,profileId:a.profileId}:{valid:!1,reason:"malformed"}}p();function Td(i){if(!i.includes("://"))return i;try{return new URL(i).hostname}catch{return i}}function Mr(i,e){let t;try{t=new URL(i).hostname}catch{return!1}return e.some(n=>{if(n.startsWith("*.")){let o=n.slice(1);return t===n.slice(2)||t.endsWith(o)}return t===Td(n)})}function Gr(i,e){let t=i??"*";return e&&e.length>0&&i&&(t=Mr(i,e)?i:"null"),{"Access-Control-Allow-Origin":t,"Access-Control-Allow-Methods":"GET, POST, PUT, DELETE, OPTIONS","Access-Control-Allow-Headers":"Content-Type, Authorization","Access-Control-Max-Age":"86400","Access-Control-Allow-Credentials":"true"}}function jr(i){if(i.method==="OPTIONS"){let e=i.headers.get("origin");return new Response(null,{status:204,headers:Gr(e)})}return null}function dt(i,e){let t=e.headers.get("origin"),n=Gr(t),o=new Headers(i.headers);for(let[s,r]of Object.entries(n))o.set(s,r);return new Response(i.body,{status:i.status,statusText:i.statusText,headers:o})}function _n(i,e){if(e.length===0)return!0;let t=i.headers.get("origin");return t?Mr(t,e):!0}var Id=["default-src 'self'","script-src 'self' https://unpkg.com","style-src 'self' https://unpkg.com 'unsafe-inline'","img-src 'self' data:","font-src 'self'","connect-src 'self'","frame-ancestors 'none'","base-uri 'self'","form-action 'self'"].join("; ");function hi(i){let e=new Headers(i.headers);return e.set("X-Content-Type-Options","nosniff"),e.set("X-Frame-Options","DENY"),e.set("Referrer-Policy","no-referrer"),e.set("Permissions-Policy","interest-cohort=()"),e.set("Content-Security-Policy",Id),e.set("Strict-Transport-Security","max-age=63072000; includeSubDomains; preload"),new Response(i.body,{status:i.status,statusText:i.statusText,headers:e})}p();var Pd=new Set(["granted","denied","objected"]);function Br(i){let e=Object.entries(i);for(let[t,n]of e){if(!t)return{valid:!1,error:"consentJson keys must be non-empty strings"};if(!Pd.has(n))return{valid:!1,error:`consentJson value "${String(n)}" is invalid; must be granted, denied, or objected`}}return{valid:!0}}function Fr(i){if(!i||typeof i!="object")return{valid:!1,error:"Request body must be a JSON object"};let e=i;return typeof e.profileId!="string"||!e.profileId?{valid:!1,error:"profileId is required"}:!e.consentJson||typeof e.consentJson!="object"||Array.isArray(e.consentJson)?{valid:!1,error:"consentJson must be an object"}:Br(e.consentJson)}function $r(i){if(!i||typeof i!="object")return{valid:!1,error:"Request body must be a JSON object"};let e=i;return!e.consentJson||typeof e.consentJson!="object"||Array.isArray(e.consentJson)?{valid:!1,error:"consentJson must be an object"}:Br(e.consentJson)}function Hr(i,e,t){return{tenantId:t,visitorId:e,profileId:i.profileId,locale:typeof i.locale=="string"?i.locale:"en",consentJson:i.consentJson,gpcDetected:!!i.gpcDetected,source:i.source??"banner",...typeof i.ageVerified=="boolean"?{ageVerified:i.ageVerified}:{},...typeof i.parentalConsentToken=="string"?{parentalConsentToken:i.parentalConsentToken}:{}}}function Vr(i){let e={consentJson:i.consentJson};return typeof i.locale=="string"&&(e.locale=i.locale),i.gpcDetected!=null&&(e.gpcDetected=!!i.gpcDetected),e}function ut(i,e,t){let n=i.headers.get("cookie")??"",o=`consenti_${e}`;return n.split(";").some(r=>{let a=r.trim(),c=a.indexOf("=");return c===-1||a.slice(0,c)!==o?!1:Nr(a.slice(c+1),e,t)})?null:g(403,"Forbidden")}function Wr(i,e,t,n=async()=>"default",o,s="",r,a=7){return{"POST /consent":async(c,l)=>E(async()=>{let d=await P(c),u=Fr(d);if(!u.valid)return g(400,u.error??"Invalid request");let m=d,h=typeof m.profileId=="string"?m.profileId:null;if(!h)return g(400,"profileId is required");let S=await t.get(h);if(!S)return g(404,"Profile not found");let _=await n(c),R=S.profileJson.allowedOrigins??[];if(R.length===0&&o&&(R=(await o.getSettings(_)).allowedOrigins??[]),!_n(c,R))return g(403,"Origin not allowed for this profile");let C=typeof m.visitorId=="string"?m.visitorId:q(),A=c.headers.get("x-real-ip")??"",T=c.headers.get("user-agent")??"";await e.upsert({visitorId:C,ip:A,userAgent:T});let O=Hr(m,C,_),D=await i.create(O),G=fi(C,D.id,s);return new Response(JSON.stringify(D),{status:201,headers:{"Content-Type":"application/json","Set-Cookie":G}})}),"PUT /consent/:visitorId":async(c,l)=>E(async()=>{let d=l.visitorId;if(!d)return g(400,"Missing visitorId");let u=ut(c,d,s);if(u)return u;let m=await P(c),h=$r(m);if(!h.valid)return g(400,h.error??"Invalid request");let S=Vr(m),_=await i.update(d,S),w=fi(d,_.id,s);return new Response(JSON.stringify(_),{status:200,headers:{"Content-Type":"application/json","Set-Cookie":w}})}),"GET /consent/:visitorId":async(c,l)=>E(async()=>{let d=l.visitorId;if(!d)return g(400,"Missing visitorId");let u=ut(c,d,s);if(u)return u;let m=await i.get(d);return m?new Response(JSON.stringify(m),{status:200,headers:{"Content-Type":"application/json"}}):g(404,"Consent not found")}),"GET /consent/:visitorId/verify":async(c,l)=>E(async()=>{let d=l.visitorId;if(!d)return g(400,"Missing visitorId");let u=ut(c,d,s);if(u)return u;let m=await i.verify(d);return new Response(JSON.stringify(m),{status:200,headers:{"Content-Type":"application/json"}})}),"DELETE /consent/:visitorId":async(c,l)=>E(async()=>{let d=l.visitorId;if(!d)return g(400,"Missing visitorId");let u=ut(c,d,s);if(u)return u;let m=await i.get(d);await i.erase(d);let h={"Content-Type":"application/json"};return m&&(h["Set-Cookie"]=Lr(d)),new Response(JSON.stringify({success:!0}),{status:200,headers:h})}),"POST /consent/:visitorId/parental-consent-request":async(c,l)=>E(async()=>{let d=l.visitorId;if(!d)return g(400,"Missing visitorId");let u=ut(c,d,s);if(u)return u;let m=await P(c),h=typeof m.profileId=="string"?m.profileId:null;if(!h)return g(400,"profileId is required");if(!await t.get(h))return g(404,"Profile not found");let S=Ur(d,h,s),_=Math.round(Date.now()/1e3);return r?.emit("consent.parentalConsentRequired",{visitorId:d,profileId:h,token:S,issuedAt:_}),y(200,{token:S})}),"POST /consent/parental-consent-resolve":async c=>E(async()=>{let l=await P(c),d=typeof l.token=="string"?l.token:null;if(!d)return g(400,"token is required");let u=xr(d,s,a);return u.valid?(r?.emit("consent.parentalConsentGranted",{visitorId:u.visitorId,profileId:u.profileId}),y(200,{visitorId:u.visitorId,profileId:u.profileId})):g(403,`Invalid or expired token (${u.reason})`)})}}p();var bd=!1;function qr(i){return{"POST /notice-shown":async(e,t)=>E(async()=>{if(!bd)return g(404,"Not found");let n=await P(e);if(!n||typeof n!="object")return g(400,"Request body must be a JSON object");let o=n,s=typeof o.visitorId=="string"?o.visitorId:"",r=typeof o.profileId=="string"?o.profileId:"",a=typeof o.locale=="string"?o.locale:"";if(!s)return g(400,"visitorId is required");if(!r)return g(400,"profileId is required");if(!a)return g(400,"locale is required");let c=await i.recordShown({visitorId:s,profileId:r,locale:a});return new Response(JSON.stringify({success:!0,id:c.id}),{status:201,headers:{"Content-Type":"application/json"}})})}}p();function Jr(i,e){return{"GET /tcf/status":async(t,n)=>E(async()=>{if(!e?.enabled)return y(200,{blocked:!1});let o=await i.getSettings("default"),s=ue(!0,{cmpId:e.cmpId,cmpVersion:e.cmpVersion,publisherCC:e.publisherCC},o.tcfConfirmation);return y(200,{blocked:!s})})}}p();function zr(i,e){return{"GET /gpp/status":async(t,n)=>E(async()=>{if(!e?.enabled)return y(200,{blocked:!1});let o=await i.getSettings("default"),s=ue(!0,{cmpId:e.cmpId,cmpVersion:e.cmpVersion},o.gppConfirmation);return y(200,{blocked:!s})})}}p();var wi=require("node:crypto");p();var Kr=require("node:crypto");async function b(i,e,t,n){let o=i.headers.get("authorization"),s=o?.startsWith("Bearer ")?o.slice(7):null;if(!s)return null;if(s.startsWith("ck_")){let r=(0,Kr.createHash)("sha256").update(s).digest("hex"),a=await e.getApiKeyByHash(r);if(!a||!a.isActive)return null;if(a.expireBy&&new Date(a.expireBy)<=new Date)return await e.revokeApiKey(a.id).catch(()=>{}),null;let c=(await e.getAllPermissions()).map(l=>l.name);return{sub:`apikey:${a.id}`,email:a.name,roles:["api_key"],permissions:c,allowedTenants:[a.tenantId]}}if(t.mode==="local"||t.mode==="jwt"){let r=St(s,n);if(!r)return null;let a=r.sub,c=r.email,l=r.roles,d=r.permissions,u=r.allowedTenants;return typeof a!="string"||typeof c!="string"?null:{sub:a,email:c,roles:Array.isArray(l)?l:[],permissions:Array.isArray(d)?d:[],allowedTenants:Array.isArray(u)?u:[]}}if(t.mode==="custom"&&t.validateUser){let r=await t.validateUser(i);if(!r)return null;let a=await e.getUserRoles(r.id),c=await Promise.all(a.map(d=>e.getPermissionsForRole(d.id))),l=[...new Set(c.flat().map(d=>d.name))];return{sub:r.id,email:r.email,roles:a.map(d=>d.name),permissions:l,allowedTenants:[]}}return null}function k(i,e){return i?e&&!i.permissions.includes(e)?g(403,"Forbidden"):null:g(401,"Unauthorized")}p();var wn=require("node:crypto");function Yr(i){return i.toString("base64").replace(/\+/g,"-").replace(/\//g,"_").replace(/=/g,"")}function Qr(i){return Buffer.from(i.replace(/-/g,"+").replace(/_/g,"/"),"base64").toString("utf8")}function Zr(){let i=Yr((0,wn.randomBytes)(32)),e=Yr((0,wn.createHash)("sha256").update(i).digest());return{verifier:i,challenge:e}}async function yi(i){let e=await fetch(`${i}/.well-known/openid-configuration`,{signal:AbortSignal.timeout(1e4)});if(!e.ok)throw new Error(`OIDC discovery failed for ${i}: ${e.status}`);return e.json()}function Xr(i,e,t,n,o){let s=new URLSearchParams({response_type:"code",client_id:i.clientId,redirect_uri:i.redirectUri,scope:"openid email profile",state:t,nonce:n,code_challenge:o,code_challenge_method:"S256"});return`${e}?${s.toString()}`}async function ea(i,e,t,n){let o=new URLSearchParams({grant_type:"authorization_code",client_id:i.clientId,client_secret:i.clientSecret,redirect_uri:i.redirectUri,code:t,code_verifier:n}),s=await fetch(e,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:o.toString(),signal:AbortSignal.timeout(1e4)});if(!s.ok){let r=await s.text();throw new Error(`OIDC token exchange failed: ${r}`)}return s.json()}async function ta(i,e){let t=i.split(".");if(t.length!==3)throw new Error("Invalid ID token format");let n=JSON.parse(Qr(t[0])),o=n.alg??"RS256",s=await fetch(e,{signal:AbortSignal.timeout(1e4)});if(!s.ok)throw new Error(`Failed to fetch JWKS: ${s.status}`);let r=await s.json(),a=n.kid?r.keys.find(R=>R.kid===n.kid):r.keys.find(R=>R.use==="sig")??r.keys[0];if(!a)throw new Error("No matching key in JWKS");let c;if(o==="RS256"||o==="RS384"||o==="RS512"){let R=o==="RS256"?"SHA-256":o==="RS384"?"SHA-384":"SHA-512";c=await globalThis.crypto.subtle.importKey("jwk",a,{name:"RSASSA-PKCS1-v1_5",hash:{name:R}},!1,["verify"])}else if(o==="ES256"||o==="ES384"||o==="ES512"){let R=o==="ES256"?"P-256":o==="ES384"?"P-384":"P-521";c=await globalThis.crypto.subtle.importKey("jwk",a,{name:"ECDSA",namedCurve:R},!1,["verify"])}else throw new Error(`Unsupported OIDC token algorithm: ${o}`);let l=new TextEncoder().encode(`${t[0]}.${t[1]}`),d=(4-t[2].length%4)%4,u=t[2].replace(/-/g,"+").replace(/_/g,"/")+"=".repeat(d),m=Uint8Array.from(atob(u),R=>R.charCodeAt(0)),h=o.startsWith("ES")?{name:"ECDSA",hash:{name:`SHA-${o.slice(2)}`}}:{name:"RSASSA-PKCS1-v1_5"};if(!await globalThis.crypto.subtle.verify(h,c,m,l))throw new Error("ID token signature verification failed");let _=JSON.parse(Qr(t[1])),w=Math.floor(Date.now()/1e3);if(typeof _.exp=="number"&&_.exp<w)throw new Error("ID token has expired");return _}function na(i,e){let t=e?.email??"email",n=i[t];if(typeof n!="string")throw new Error("OIDC token missing email claim");return n}function ia(i,e){let t=e?.roles??"consenti_roles",n=i[t];return Array.isArray(n)?n.filter(o=>typeof o=="string"):[]}var pt=new Map;setInterval(()=>{let i=Date.now();for(let[e,t]of pt)t.expiresAt<i&&pt.delete(e)},5*6e4).unref();function oa(i,e,t){pt.set(i,{verifier:e,nonce:t,expiresAt:Date.now()+10*6e4})}function sa(i){let e=pt.get(i);return pt.delete(i),!e||e.expiresAt<Date.now()?null:{verifier:e.verifier,nonce:e.nonce}}p();function Od(i){return i.replace(/&/g,"&amp;").replace(/"/g,"&quot;").replace(/</g,"&lt;").replace(/>/g,"&gt;")}function ra(i){return`<?xml version="1.0" encoding="UTF-8"?>
134
+ GROUP BY v.country ORDER BY count DESC LIMIT 50`,[e])).map(n=>({country:n.country,count:Number(n.count)}))}async getGpcStats(e){let[t]=await this.q("SELECT COUNT(*)::int AS total FROM consenti_consent_records WHERE tenant_id=$1",[e]),[n]=await this.q("SELECT COUNT(*)::int AS total FROM consenti_consent_records WHERE tenant_id=$1 AND gpc_detected=TRUE",[e]),o=Number(t?.total??0),s=Number(n?.total??0);return{detected:s,total:o,rate:o>0?Math.round(s/o*100):0}}async getTenants(){return(await this.q("SELECT * FROM consenti_tenants ORDER BY name ASC",[])).map(t=>({id:t.id,name:t.name,slug:t.slug,createdAt:t.created_at,updatedAt:t.updated_at}))}mapApiKey(e){return{id:e.id,tenantId:e.tenant_id,keyHash:e.key_hash,name:e.name,isActive:e.is_active,...e.created_by!==null?{createdBy:e.created_by}:{},...e.expire_by!==null?{expireBy:e.expire_by}:{},createdAt:e.created_at,...e.updated_at!==null?{updatedAt:e.updated_at}:{}}}async createApiKey(e){let t=(0,C.randomUUID)(),o=(await this.q("INSERT INTO consenti_api_keys (id, tenant_id, key_hash, name, created_by, expire_by) VALUES ($1,$2,$3,$4,$5,$6) RETURNING *",[t,e.tenantId,e.keyHash,e.name,e.createdBy??null,e.expireBy??null]))[0];if(!o)throw new Error("Failed to create API key");return this.mapApiKey(o)}async getApiKeyByHash(e){let n=(await this.q("SELECT * FROM consenti_api_keys WHERE key_hash=$1 AND is_active=TRUE",[e]))[0];return n?this.mapApiKey(n):null}async revokeApiKey(e){await this.q("UPDATE consenti_api_keys SET is_active=FALSE, updated_at=NOW() WHERE id=$1",[e])}async reactivateApiKey(e){await this.q("UPDATE consenti_api_keys SET is_active=TRUE, updated_at=NOW(), expire_by=CASE WHEN expire_by <= NOW() THEN NULL ELSE expire_by END WHERE id=$1",[e])}async deleteApiKey(e){await this.q("DELETE FROM consenti_api_keys WHERE id=$1",[e])}async getApiKeys(e){return(await this.q("SELECT * FROM consenti_api_keys WHERE tenant_id=$1 ORDER BY created_at DESC",[e])).map(n=>this.mapApiKey(n))}async createTenant(e){let t=(0,C.randomUUID)(),n=new Date().toISOString(),s=(await this.q("INSERT INTO consenti_tenants (id, name, slug, created_at, updated_at) VALUES ($1,$2,$3,$4,$5) RETURNING *",[t,e.name,e.slug,n,n]))[0];if(!s)throw new Error("Failed to create tenant");return{id:s.id,name:s.name,slug:s.slug,createdAt:s.created_at,updatedAt:s.updated_at}}async updateTenant(e,t){let n=new Date().toISOString(),o=["updated_at=$1"],s=[n],r=2;t.name!=null&&(o.push(`name=$${r++}`),s.push(t.name)),t.slug!=null&&(o.push(`slug=$${r++}`),s.push(t.slug)),s.push(e);let c=(await this.q(`UPDATE consenti_tenants SET ${o.join(",")} WHERE id=$${r} RETURNING *`,s))[0];if(!c)throw new Error(`Tenant ${e} not found`);return{id:c.id,name:c.name,slug:c.slug,createdAt:c.created_at,updatedAt:c.updated_at}}async deleteTenant(e){await this.q("DELETE FROM consenti_tenants WHERE id=$1",[e])}async getSettings(e){let n=(await this.q("SELECT allowed_origins_json, admin_allowed_origins_json, setup_completed, profiles_seeded, tcf_confirmation_json, gpp_confirmation_json FROM consenti_tenant_settings WHERE tenant_id=$1",[e]))[0];return n?{allowedOrigins:n.allowed_origins_json,adminAllowedOrigins:n.admin_allowed_origins_json,setupCompleted:n.setup_completed,profilesSeeded:n.profiles_seeded,...n.tcf_confirmation_json?{tcfConfirmation:n.tcf_confirmation_json}:{},...n.gpp_confirmation_json?{gppConfirmation:n.gpp_confirmation_json}:{}}:{}}async updateSettings(e,t){let o={...await this.getSettings(e),...t};return await this.q(`INSERT INTO consenti_tenant_settings (tenant_id, allowed_origins_json, admin_allowed_origins_json, setup_completed, profiles_seeded, tcf_confirmation_json, gpp_confirmation_json, updated_at) VALUES ($1,$2::jsonb,$3::jsonb,$4,$5,$6::jsonb,$7::jsonb,NOW())
135
+ ON CONFLICT (tenant_id) DO UPDATE SET allowed_origins_json=$2::jsonb, admin_allowed_origins_json=$3::jsonb, setup_completed=$4, profiles_seeded=$5, tcf_confirmation_json=$6::jsonb, gpp_confirmation_json=$7::jsonb, updated_at=NOW()`,[e,JSON.stringify(o.allowedOrigins??[]),JSON.stringify(o.adminAllowedOrigins??[]),o.setupCompleted??!1,o.profilesSeeded??!1,o.tcfConfirmation?JSON.stringify(o.tcfConfirmation):null,o.gppConfirmation?JSON.stringify(o.gppConfirmation):null]),this.getSettings(e)}async purgeExpiredConsents(e){let t=new Date(Date.now()-e*864e5).toISOString(),n=await this.q("SELECT visitor_id FROM consenti_consent_records WHERE created_at < $1",[t]);if(n.length===0)return 0;let o=n.map(r=>r.visitor_id),s=o.map((r,a)=>`$${a+1}`).join(",");return await this.q(`DELETE FROM consenti_consent_history WHERE visitor_id IN (${s})`,o),await this.q(`DELETE FROM consenti_consent_records WHERE visitor_id IN (${s})`,o),o.length}mapConsentTemplate(e){return{id:e.id,tenantId:e.tenant_id,name:e.name,cookies:e.cookies_json,categories:e.categories_json,createdAt:e.created_at,updatedAt:e.updated_at}}async createConsentTemplate(e){let n=(await this.q(`INSERT INTO consenti_consent_templates (id, tenant_id, name, cookies_json, categories_json)
136
+ VALUES ($1,$2,$3,$4::json,$5::json) RETURNING *`,[Q(),e.tenantId,e.name,JSON.stringify(e.cookies),JSON.stringify(e.categories)]))[0];if(!n)throw new Error("Consent template creation failed");return this.mapConsentTemplate(n)}async updateConsentTemplate(e,t){let n=["updated_at = NOW()"],o=[],s=1;t.name!==void 0&&(n.push(`name=$${s++}`),o.push(t.name)),t.cookies!==void 0&&(n.push(`cookies_json=$${s++}::json`),o.push(JSON.stringify(t.cookies))),t.categories!==void 0&&(n.push(`categories_json=$${s++}::json`),o.push(JSON.stringify(t.categories)));let a=(await this.q(`UPDATE consenti_consent_templates SET ${n.join(",")} WHERE id=$${s} RETURNING *`,[...o,e]))[0];if(!a)throw new Error("Consent template not found");return this.mapConsentTemplate(a)}async deleteConsentTemplate(e){await this.q("DELETE FROM consenti_consent_templates WHERE id=$1",[e])}async getConsentTemplate(e){let t=await this.q("SELECT * FROM consenti_consent_templates WHERE id=$1",[e]);return t[0]?this.mapConsentTemplate(t[0]):null}async getConsentTemplates(e){return(await this.q("SELECT * FROM consenti_consent_templates WHERE tenant_id=$1 ORDER BY name ASC",[e])).map(n=>this.mapConsentTemplate(n))}async copyConsentTemplate(e,t){let n=await this.getConsentTemplate(e);if(!n)throw new Error("Consent template not found");return this.createConsentTemplate({tenantId:n.tenantId,name:t,cookies:n.cookies,categories:n.categories})}mapUITemplate(e){return{id:e.id,tenantId:e.tenant_id,name:e.name,...e.settings_json,createdAt:e.created_at,updatedAt:e.updated_at}}async createUITemplate(e){let{tenantId:t,name:n,...o}=e,r=(await this.q("INSERT INTO consenti_ui_templates (id, tenant_id, name, settings_json) VALUES ($1,$2,$3,$4::json) RETURNING *",[Z(),t,n,JSON.stringify(o)]))[0];if(!r)throw new Error("UI template creation failed");return this.mapUITemplate(r)}async updateUITemplate(e,t){let n=await this.q("SELECT * FROM consenti_ui_templates WHERE id=$1",[e]);if(!n[0])throw new Error("UI template not found");let{name:o,...s}=t,r=["updated_at = NOW()"],a=[],c=1;o!==void 0&&(r.push(`name=$${c++}`),a.push(o)),Object.keys(s).length>0&&(r.push(`settings_json=$${c++}::json`),a.push(JSON.stringify({...n[0].settings_json,...s})));let d=(await this.q(`UPDATE consenti_ui_templates SET ${r.join(",")} WHERE id=$${c} RETURNING *`,[...a,e]))[0];if(!d)throw new Error("UI template not found");return this.mapUITemplate(d)}async deleteUITemplate(e){await this.q("DELETE FROM consenti_ui_templates WHERE id=$1",[e])}async getUITemplate(e){let t=await this.q("SELECT * FROM consenti_ui_templates WHERE id=$1",[e]);return t[0]?this.mapUITemplate(t[0]):null}async getUITemplates(e){return(await this.q("SELECT * FROM consenti_ui_templates WHERE tenant_id=$1 ORDER BY name ASC",[e])).map(n=>this.mapUITemplate(n))}async copyUITemplate(e,t){let n=await this.getUITemplate(e);if(!n)throw new Error("UI template not found");let{tenantId:o,mainBanner:s,gpcBanner:r,preferenceModal:a}=n;return this.createUITemplate({tenantId:o,name:t,mainBanner:s,gpcBanner:r,preferenceModal:a})}async toProfileSummaries(e){if(e.length===0)return[];let t=[...new Set(e.map(s=>s.tenantId))],[n,o]=await Promise.all([Promise.all(t.map(s=>this.getConsentTemplates(s))),Promise.all(t.map(s=>this.getUITemplates(s)))]);return Be(e,new Map(n.flat().map(s=>[s.id,s.name])),new Map(o.flat().map(s=>[s.id,s.name])))}async listProfilesSummary(e){let t=await this.q("SELECT * FROM consenti_profiles WHERE tenant_id=$1 ORDER BY created_at ASC",[e]);return this.toProfileSummaries(t.map(Ne))}async findProfilesUsingConsentTemplate(e){let t=await this.q("SELECT * FROM consenti_profiles WHERE profile_json->>'consentTemplateId'=$1 ORDER BY name ASC",[e]);return this.toProfileSummaries(t.map(Ne))}async findProfilesUsingUITemplate(e){let t=await this.q("SELECT * FROM consenti_profiles WHERE profile_json->>'uiTemplateId'=$1 ORDER BY name ASC",[e]);return this.toProfileSummaries(t.map(Ne))}async getOptInStats(e,t){let n="tenant_id=$1",o=[e];t.profileId&&(o.push(t.profileId),n+=` AND profile_id=$${o.length}`),t.from&&(o.push(t.from),n+=` AND created_at>=$${o.length}`),t.to&&(o.push(t.to),n+=` AND created_at<=$${o.length}`),t.locale&&(o.push(t.locale),n+=` AND locale=$${o.length}`);let s=await this.q(`SELECT locale, to_char(created_at, 'YYYY-MM-DD') AS day, consent_json FROM consenti_consent_records WHERE ${n} ORDER BY created_at ASC`,o);return $e(s.map(r=>({locale:r.locale,day:r.day,consentJson:r.consent_json})))}};p();var ve=require("node:fs/promises"),_e=require("node:crypto"),Vo=require("node:path");var Il=500;function Xn(){return{_version:1,tenants:[],profiles:[],consents:[],consent_history:[],visitors:[],users:[],roles:[],permissions:[],user_roles:[],role_permissions:[],audit_logs:[],consent_templates:[],ui_templates:[],api_keys:[],settings:{},notice_shown:[]}}function ei(i,e,t){let n=Math.min(t,Il),o=(e-1)*n;return i.slice(o,o+n)}function Pl(i){let{id:e,tenantId:t,visitorId:n,profileId:o,locale:s,gpcDetected:r,source:a,ageVerified:c,createdAt:l,updatedAt:d}=i;return{id:e,tenantId:t,visitorId:n,profileId:o,locale:s,gpcDetected:r,source:a,...c!=null?{ageVerified:c}:{},createdAt:l,updatedAt:d}}function bl(i){let{id:e,tenantId:t,userId:n,action:o,resourceType:s,resourceId:r,createdAt:a}=i;return{id:e,tenantId:t,action:o,resourceType:s,createdAt:a,...n!=null?{userId:n}:{},...r!=null?{resourceId:r}:{}}}var Bt=class{constructor(e){this.config=e}config;db=Xn();filePath="";writeQueue=Promise.resolve();scheduleWrite(){this.writeQueue=this.writeQueue.then(async()=>{await(0,ve.mkdir)((0,Vo.dirname)(this.filePath),{recursive:!0});let e=`${this.filePath}.tmp`;await(0,ve.writeFile)(e,JSON.stringify(this.db),"utf8"),await(0,ve.rename)(e,this.filePath)}).catch(e=>{console.warn("[Consenti] JSON store write failed:",e)})}async connect(){let{dbPath:e}=fe(this.config.path??"./consenti-data","json");this.filePath=e;try{let t=await(0,ve.readFile)(this.filePath,"utf8");this.db={...Xn(),...JSON.parse(t)}}catch{this.db=Xn()}await this.migrate()}async disconnect(){await this.writeQueue}async migrate(){this.seed()}seed(){let e=new Date().toISOString(),{id:t,name:n,slug:o}=oe;this.db.tenants.find(s=>s.id===t)||this.db.tenants.push({id:t,name:n,slug:o,createdAt:e,updatedAt:e});for(let s of ie)this.db.permissions.find(r=>r.id===s.id)||this.db.permissions.push({id:s.id,name:s.name,description:s.description});for(let s of he)this.db.roles.find(r=>r.id===s.id)||this.db.roles.push({id:s.id,tenantId:s.tenantId,name:s.name,description:s.description});for(let s of ye)this.db.role_permissions.find(r=>r.roleId===s.roleId&&r.permissionId===s.permissionId)||this.db.role_permissions.push(s);this.scheduleWrite()}async createProfile(e){let t=new Date().toISOString(),o={id:K(),tenantId:e.tenantId,name:e.name,defaultLocale:e.defaultLocale,version:1,profileJson:e.profileJson,createdAt:t,updatedAt:t};return this.db.profiles.push(o),this.scheduleWrite(),o}async updateProfile(e,t){let n=this.db.profiles.findIndex(r=>r.id===e);if(n===-1)throw new Error(`Profile ${e} not found`);let s={...this.db.profiles[n],...t.name!=null&&{name:t.name},...t.defaultLocale!=null&&{defaultLocale:t.defaultLocale},...t.profileJson!=null&&{profileJson:t.profileJson},...t.version!=null&&{version:t.version},updatedAt:new Date().toISOString()};return this.db.profiles[n]=s,this.scheduleWrite(),s}async deleteProfile(e){this.db.profiles=this.db.profiles.filter(t=>t.id!==e),this.scheduleWrite()}async getProfile(e){return this.db.profiles.find(t=>t.id===e)??null}async getProfiles(e){return this.db.profiles.filter(t=>t.tenantId===e).sort((t,n)=>t.createdAt.localeCompare(n.createdAt))}async findActiveProfileByComplianceGroup(e,t){return this.db.profiles.find(n=>n.tenantId===e&&(n.profileJson.complianceGroup===t||n.profileJson.customComplianceGroup===t)&&n.profileJson.isActive)??null}async createConsent(e){let t=new Date().toISOString(),n=Y(),o={id:n,tenantId:e.tenantId,visitorId:e.visitorId,profileId:e.profileId,...e.profileVersion!=null&&{profileVersion:e.profileVersion},locale:e.locale,consentJson:e.consentJson,gpcDetected:e.gpcDetected??!1,source:e.source,...e.ageVerified!=null&&{ageVerified:e.ageVerified},...e.parentalConsentToken!=null&&{parentalConsentToken:e.parentalConsentToken},...e.tcfString!=null&&{tcfString:e.tcfString},...e.gppString!=null&&{gppString:e.gppString},...e.signature!=null&&{signature:e.signature},createdAt:t,updatedAt:t};return this.db.consents.push(o),this.db.consent_history.push({id:(0,_e.randomUUID)(),tenantId:e.tenantId,consentRecordId:n,visitorId:e.visitorId,...e.profileVersion!=null&&{profileVersion:e.profileVersion},oldJson:null,newJson:e.consentJson,action:"created",createdAt:t}),this.scheduleWrite(),o}async updateConsent(e,t){let n=this.db.consents.findIndex(a=>a.visitorId===e);if(n===-1)throw new Error(`Consent for visitor ${e} not found`);let o=this.db.consents[n],s=new Date().toISOString(),r={...o,consentJson:t.consentJson,...t.profileVersion!=null&&{profileVersion:t.profileVersion},...t.locale!=null&&{locale:t.locale},...t.gpcDetected!=null&&{gpcDetected:t.gpcDetected},...t.signature!=null&&{signature:t.signature},updatedAt:s};return this.db.consents[n]=r,this.db.consent_history.push({id:(0,_e.randomUUID)(),tenantId:o.tenantId,consentRecordId:o.id,visitorId:e,...(t.profileVersion??o.profileVersion)!=null&&{profileVersion:t.profileVersion??o.profileVersion},oldJson:o.consentJson,newJson:t.consentJson,action:"updated",createdAt:s}),this.scheduleWrite(),r}async deleteConsent(e){this.db.consent_history=this.db.consent_history.filter(t=>t.visitorId!==e),this.db.consents=this.db.consents.filter(t=>t.visitorId!==e),this.scheduleWrite()}async getConsent(e){return this.db.consents.find(t=>t.visitorId===e)??null}async getConsents(e){let t=this.db.consents.filter(s=>s.tenantId===e.tenantId);if(e.profileId&&(t=t.filter(s=>s.profileId===e.profileId)),e.from&&(t=t.filter(s=>s.createdAt>=e.from)),e.to&&(t=t.filter(s=>s.createdAt<=e.to)),e.q){let s=e.q.toLowerCase();t=t.filter(r=>r.visitorId.toLowerCase().startsWith(s)||r.profileId.toLowerCase().startsWith(s)||r.locale.toLowerCase().startsWith(s)||r.source.toLowerCase().startsWith(s))}t.sort((s,r)=>r.createdAt.localeCompare(s.createdAt));let n=e.page??1,o=e.limit??50;return{items:ei(t,n,o).map(Pl),total:t.length,page:n,limit:o}}async*streamConsents(e){for(let t of this.db.consents.filter(n=>n.tenantId===e.tenantId))yield t}async getConsentHistory(e){return this.db.consent_history.filter(t=>t.visitorId===e).sort((t,n)=>t.createdAt.localeCompare(n.createdAt))}async createNoticeShown(e){let t={id:(0,_e.randomUUID)(),tenantId:e.tenantId,visitorId:e.visitorId,profileId:e.profileId,locale:e.locale,createdAt:new Date().toISOString()};return this.db.notice_shown.push(t),this.scheduleWrite(),t}async getNoticeShownForVisitor(e){return this.db.notice_shown.filter(t=>t.visitorId===e).sort((t,n)=>n.createdAt.localeCompare(t.createdAt))}async createVisitor(e){let t=new Date().toISOString(),n={id:q(),tenantId:e.tenantId,visitorId:e.visitorId,firstSeen:t,lastSeen:t,...e.country!=null&&{country:e.country},...e.region!=null&&{region:e.region},...e.city!=null&&{city:e.city},...e.ipHash!=null&&{ipHash:e.ipHash},...e.userAgentHash!=null&&{userAgentHash:e.userAgentHash}};return this.db.visitors.push(n),this.scheduleWrite(),n}async updateVisitor(e,t){let n=this.db.visitors.findIndex(r=>r.visitorId===e);if(n===-1)throw new Error(`Visitor ${e} not found`);let s={...this.db.visitors[n],lastSeen:t.lastSeen??new Date().toISOString(),...t.country!=null&&{country:t.country},...t.region!=null&&{region:t.region},...t.city!=null&&{city:t.city}};return this.db.visitors[n]=s,this.scheduleWrite(),s}async deleteVisitor(e){this.db.visitors=this.db.visitors.filter(t=>t.visitorId!==e),this.scheduleWrite()}async getVisitor(e){return this.db.visitors.find(t=>t.visitorId===e)??null}async getVisitors(e){let t=this.db.visitors.filter(s=>s.tenantId===e.tenantId);if(e.from&&(t=t.filter(s=>s.firstSeen>=e.from)),e.to&&(t=t.filter(s=>s.firstSeen<=e.to)),e.q){let s=e.q.toLowerCase();t=t.filter(r=>r.visitorId.toLowerCase().startsWith(s)||(r.country?.toLowerCase().startsWith(s)??!1))}t.sort((s,r)=>r.lastSeen.localeCompare(s.lastSeen));let n=e.page??1,o=e.limit??50;return{items:ei(t,n,o),total:t.length,page:n,limit:o}}async createUser(e){let t=new Date().toISOString(),n={id:(0,_e.randomUUID)(),tenantId:e.tenantId,name:e.name,email:e.email,passwordHash:e.passwordHash,isActive:!0,allowedTenants:e.allowedTenants??[],createdAt:t,updatedAt:t};return this.db.users.push(n),this.scheduleWrite(),n}async updateUser(e,t){let n=this.db.users.findIndex(r=>r.id===e);if(n===-1)throw new Error(`User ${e} not found`);let s={...this.db.users[n],...t.name!=null&&{name:t.name},...t.email!=null&&{email:t.email},...t.passwordHash!=null&&{passwordHash:t.passwordHash},...t.isActive!=null&&{isActive:t.isActive},..."totpSecret"in t&&t.totpSecret!=null&&{totpSecret:t.totpSecret},...t.totpEnabled!=null&&{totpEnabled:t.totpEnabled},..."allowedTenants"in t&&{allowedTenants:t.allowedTenants??[]},updatedAt:new Date().toISOString()};return this.db.users[n]=s,this.scheduleWrite(),s}async deleteUser(e){this.db.user_roles=this.db.user_roles.filter(t=>t.userId!==e),this.db.users=this.db.users.filter(t=>t.id!==e),this.scheduleWrite()}async getUserById(e){return this.db.users.find(t=>t.id===e)??null}async getUserByEmail(e){return this.db.users.find(t=>t.email===e)??null}async getUsers(e){return this.db.users.filter(t=>t.tenantId===e).sort((t,n)=>t.createdAt.localeCompare(n.createdAt))}async countUsers(e){return e?this.db.users.filter(t=>t.tenantId===e).length:this.db.users.length}async getRoles(e){return this.db.roles.filter(t=>t.tenantId===e)}async createRole(e){let t={id:(0,_e.randomUUID)(),tenantId:e.tenantId,name:e.name,...e.description!=null&&{description:e.description}};return this.db.roles.push(t),this.scheduleWrite(),t}async updateRole(e,t){let n=this.db.roles.findIndex(s=>s.id===e);if(n===-1)throw new Error(`Role ${e} not found`);let o={...this.db.roles[n],...t.name!=null&&{name:t.name},...t.description!=null&&{description:t.description}};return this.db.roles[n]=o,this.scheduleWrite(),o}async deleteRole(e){this.db.role_permissions=this.db.role_permissions.filter(t=>t.roleId!==e),this.db.user_roles=this.db.user_roles.filter(t=>t.roleId!==e),this.db.roles=this.db.roles.filter(t=>t.id!==e),this.scheduleWrite()}async getAllPermissions(){return[...this.db.permissions].sort((e,t)=>e.name.localeCompare(t.name))}async getPermissionsForRole(e){let t=new Set(this.db.role_permissions.filter(n=>n.roleId===e).map(n=>n.permissionId));return this.db.permissions.filter(n=>t.has(n.id))}async getUserRoles(e,t){let n=this.db.user_roles.filter(s=>s.userId===e);t&&(n=n.filter(s=>s.tenantId===t));let o=new Set(n.map(s=>s.roleId));return this.db.roles.filter(s=>o.has(s.id))}async assignRole(e,t,n="default"){this.db.user_roles.find(o=>o.userId===e&&o.roleId===t&&o.tenantId===n)||(this.db.user_roles.push({userId:e,roleId:t,tenantId:n}),this.scheduleWrite())}async revokeRole(e,t,n){this.db.user_roles=this.db.user_roles.filter(o=>!(o.userId===e&&o.roleId===t&&(n==null||o.tenantId===n))),this.scheduleWrite()}async assignPermissionToRole(e,t){this.db.role_permissions.find(n=>n.roleId===e&&n.permissionId===t)||(this.db.role_permissions.push({roleId:e,permissionId:t}),this.scheduleWrite())}async revokePermissionFromRole(e,t){this.db.role_permissions=this.db.role_permissions.filter(n=>!(n.roleId===e&&n.permissionId===t)),this.scheduleWrite()}async createLog(e){let t={id:(0,_e.randomUUID)(),tenantId:e.tenantId,action:e.action,resourceType:e.resourceType,createdAt:new Date().toISOString(),...e.userId!=null&&{userId:e.userId},...e.resourceId!=null&&{resourceId:e.resourceId},...e.oldData!=null&&{oldData:e.oldData},...e.newData!=null&&{newData:e.newData}};this.db.audit_logs.push(t),this.scheduleWrite()}async getLogs(e){let t=this.db.audit_logs.filter(s=>s.tenantId===e.tenantId);if(e.action&&(t=t.filter(s=>s.action===e.action)),e.resourceType&&(t=t.filter(s=>s.resourceType===e.resourceType)),e.from&&(t=t.filter(s=>s.createdAt>=e.from)),e.to&&(t=t.filter(s=>s.createdAt<=e.to)),e.q){let s=e.q.toLowerCase();t=t.filter(r=>r.action.toLowerCase().startsWith(s)||r.resourceType.toLowerCase().startsWith(s)||(r.resourceId?.toLowerCase().startsWith(s)??!1)||(r.userId?.toLowerCase().startsWith(s)??!1))}t.sort((s,r)=>r.createdAt.localeCompare(s.createdAt));let n=e.page??1,o=e.limit??50;return{items:ei(t,n,o).map(bl),total:t.length,page:n,limit:o}}async getAuditLogById(e){return this.db.audit_logs.find(t=>t.id===e)??null}async*streamAuditLogs(e){let t=this.db.audit_logs.filter(n=>n.tenantId===e.tenantId);e.action&&(t=t.filter(n=>n.action===e.action)),e.from&&(t=t.filter(n=>n.createdAt>=e.from)),e.to&&(t=t.filter(n=>n.createdAt<=e.to)),t.sort((n,o)=>o.createdAt.localeCompare(n.createdAt));for(let n of t)yield n}async getOverviewStats(e){let t=this.db.consents.filter(a=>a.tenantId===e),n=t.slice(-500),o=0,s=0;for(let a of n){let c=Object.values(a.consentJson),l=c.length>0?c.filter(d=>d==="granted").length/c.length:0;l>=.8?o++:l<=.2&&s++}let r=n.length||1;return{totalConsents:t.length,gpcDetectedCount:t.filter(a=>a.gpcDetected).length,totalVisitors:this.db.visitors.filter(a=>a.tenantId===e).length,acceptedPct:Math.round(o/r*100),rejectedPct:Math.round(s/r*100)}}async getCategoryStats(e){let t={};for(let n of this.db.consents.filter(o=>o.tenantId===e).slice(0,5e3))for(let[o,s]of Object.entries(n.consentJson))t[o]||(t[o]={granted:0,denied:0,objected:0}),s==="granted"?t[o].granted++:s==="denied"?t[o].denied++:s==="objected"&&t[o].objected++;return t}async getTimeline(e,t=30){let n=new Date(Date.now()-t*864e5).toISOString().slice(0,10),o=new Map;for(let s of this.db.consents.filter(r=>r.tenantId===e&&r.createdAt.slice(0,10)>=n)){let r=s.createdAt.slice(0,10);o.set(r,(o.get(r)??0)+1)}return[...o.entries()].sort(([s],[r])=>s.localeCompare(r)).map(([s,r])=>({date:s,count:r}))}async getCountries(e){let t=new Set(this.db.consents.filter(o=>o.tenantId===e).map(o=>o.visitorId)),n=new Map;for(let o of this.db.visitors.filter(s=>t.has(s.visitorId)&&s.country)){let s=o.country;n.set(s,(n.get(s)??0)+1)}return[...n.entries()].sort(([,o],[,s])=>s-o).slice(0,50).map(([o,s])=>({country:o,count:s}))}async getGpcStats(e){let t=this.db.consents.filter(s=>s.tenantId===e),n=t.filter(s=>s.gpcDetected).length,o=t.length;return{detected:n,total:o,rate:o>0?Math.round(n/o*100):0}}async getTenants(){return[...this.db.tenants].sort((e,t)=>e.name.localeCompare(t.name))}async createTenant(e){let t=new Date().toISOString(),n={id:(0,_e.randomUUID)(),name:e.name,slug:e.slug,createdAt:t,updatedAt:t};return this.db.tenants.push(n),this.scheduleWrite(),n}async updateTenant(e,t){let n=this.db.tenants.findIndex(r=>r.id===e);if(n===-1)throw new Error(`Tenant ${e} not found`);let o=new Date().toISOString(),s={...this.db.tenants[n],...t.name!=null&&{name:t.name},...t.slug!=null&&{slug:t.slug},updatedAt:o};return this.db.tenants[n]=s,this.scheduleWrite(),s}async deleteTenant(e){this.db.tenants=this.db.tenants.filter(t=>t.id!==e),this.scheduleWrite()}async getSettings(e){return this.db.settings[e]??{}}async updateSettings(e,t){let n={...this.db.settings[e]??{},...t};return this.db.settings[e]=n,this.scheduleWrite(),n}async purgeExpiredConsents(e){let t=new Date(Date.now()-e*864e5).toISOString(),n=new Set(this.db.consents.filter(o=>o.createdAt<t).map(o=>o.visitorId));return n.size===0?0:(this.db.consent_history=this.db.consent_history.filter(o=>!n.has(o.visitorId)),this.db.consents=this.db.consents.filter(o=>!n.has(o.visitorId)),this.scheduleWrite(),n.size)}async createApiKey(e){let t=new Date().toISOString(),n={id:(0,_e.randomUUID)(),tenantId:e.tenantId,keyHash:e.keyHash,name:e.name,isActive:!0,...e.createdBy!==void 0?{createdBy:e.createdBy}:{},...e.expireBy!==void 0?{expireBy:e.expireBy}:{},createdAt:t,updatedAt:t};return this.db.api_keys.push(n),this.scheduleWrite(),n}async getApiKeyByHash(e){return this.db.api_keys.find(t=>t.keyHash===e&&t.isActive)??null}async revokeApiKey(e){let t=this.db.api_keys.find(n=>n.id===e);t&&(t.isActive=!1,t.updatedAt=new Date().toISOString(),this.scheduleWrite())}async reactivateApiKey(e){let t=this.db.api_keys.find(n=>n.id===e);t&&(t.isActive=!0,t.expireBy&&new Date(t.expireBy)<=new Date&&delete t.expireBy,t.updatedAt=new Date().toISOString(),this.scheduleWrite())}async deleteApiKey(e){let t=this.db.api_keys.findIndex(n=>n.id===e);t!==-1&&(this.db.api_keys.splice(t,1),this.scheduleWrite())}async getApiKeys(e){return this.db.api_keys.filter(t=>t.tenantId===e).sort((t,n)=>n.createdAt.localeCompare(t.createdAt))}async createConsentTemplate(e){let t=new Date().toISOString(),n={id:Q(),tenantId:e.tenantId,name:e.name,cookies:e.cookies,categories:e.categories,createdAt:t,updatedAt:t};return this.db.consent_templates.push(n),this.scheduleWrite(),n}async updateConsentTemplate(e,t){let n=this.db.consent_templates.findIndex(r=>r.id===e);if(n===-1)throw new Error("Consent template not found");let o=new Date().toISOString(),s={...this.db.consent_templates[n],...t.name!==void 0&&{name:t.name},...t.cookies!==void 0&&{cookies:t.cookies},...t.categories!==void 0&&{categories:t.categories},updatedAt:o};return this.db.consent_templates[n]=s,this.scheduleWrite(),s}async deleteConsentTemplate(e){this.db.consent_templates=this.db.consent_templates.filter(t=>t.id!==e),this.scheduleWrite()}async getConsentTemplate(e){return this.db.consent_templates.find(t=>t.id===e)??null}async getConsentTemplates(e){return this.db.consent_templates.filter(t=>t.tenantId===e).sort((t,n)=>t.name.localeCompare(n.name))}async copyConsentTemplate(e,t){let n=await this.getConsentTemplate(e);if(!n)throw new Error("Consent template not found");return this.createConsentTemplate({tenantId:n.tenantId,name:t,cookies:n.cookies,categories:n.categories})}async createUITemplate(e){let t=new Date().toISOString(),{tenantId:n,name:o,...s}=e,r={id:Z(),tenantId:n,name:o,...s,createdAt:t,updatedAt:t};return this.db.ui_templates.push(r),this.scheduleWrite(),r}async updateUITemplate(e,t){let n=this.db.ui_templates.findIndex(c=>c.id===e);if(n===-1)throw new Error("UI template not found");let{name:o,...s}=t,r=new Date().toISOString(),a={...this.db.ui_templates[n],...t.name!==void 0&&{name:t.name},...s,updatedAt:r};return this.db.ui_templates[n]=a,this.scheduleWrite(),a}async deleteUITemplate(e){this.db.ui_templates=this.db.ui_templates.filter(t=>t.id!==e),this.scheduleWrite()}async getUITemplate(e){return this.db.ui_templates.find(t=>t.id===e)??null}async getUITemplates(e){return this.db.ui_templates.filter(t=>t.tenantId===e).sort((t,n)=>t.name.localeCompare(n.name))}async copyUITemplate(e,t){let n=await this.getUITemplate(e);if(!n)throw new Error("UI template not found");let{tenantId:o,mainBanner:s,gpcBanner:r,preferenceModal:a}=n;return this.createUITemplate({tenantId:o,name:t,...s!==void 0&&{mainBanner:s},...r!==void 0&&{gpcBanner:r},...a!==void 0&&{preferenceModal:a}})}profileToSummary(e){let t=e.profileJson,n=t.consentTemplateId?this.db.consent_templates.find(s=>s.id===t.consentTemplateId):null,o=t.uiTemplateId?this.db.ui_templates.find(s=>s.id===t.uiTemplateId):null;return{id:e.id,name:e.name,defaultLocale:e.defaultLocale,complianceGroup:t.complianceGroup??null,customComplianceGroup:t.customComplianceGroup??null,isActive:t.isActive??!1,consentTemplateName:n?.name??null,uiTemplateName:o?.name??null,createdAt:e.createdAt,updatedAt:e.updatedAt}}async listProfilesSummary(e){return this.db.profiles.filter(t=>t.tenantId===e).sort((t,n)=>t.createdAt.localeCompare(n.createdAt)).map(t=>this.profileToSummary(t))}async findProfilesUsingConsentTemplate(e){return this.db.profiles.filter(t=>t.profileJson.consentTemplateId===e).sort((t,n)=>t.name.localeCompare(n.name)).map(t=>this.profileToSummary(t))}async findProfilesUsingUITemplate(e){return this.db.profiles.filter(t=>t.profileJson.uiTemplateId===e).sort((t,n)=>t.name.localeCompare(n.name)).map(t=>this.profileToSummary(t))}async getOptInStats(e,t){let n=this.db.consents.filter(u=>u.tenantId===e);t.profileId&&(n=n.filter(u=>u.profileId===t.profileId)),t.from&&(n=n.filter(u=>u.createdAt>=t.from)),t.to&&(n=n.filter(u=>u.createdAt<=t.to)),t.locale&&(n=n.filter(u=>u.locale===t.locale));let o=0,s=0,r=0,a=0,c={},l=new Map;for(let u of n){let m=Object.values(u.consentJson),f=m.length>0?m.filter(v=>v==="granted").length/m.length:0,S=m.length>0?m.filter(v=>v==="denied").length/m.length:0;o++;let y=u.locale;c[y]||(c[y]={total:0,granted:0,denied:0,managed:0}),c[y].total++;let E=u.createdAt.slice(0,10),R=l.get(E)??{total:0,granted:0,denied:0,managed:0};R.total++,f>=.9?(s++,c[y].granted++,R.granted++):S>=.9?(r++,c[y].denied++,R.denied++):(a++,c[y].managed++,R.managed++),l.set(E,R)}let d=Array.from(l.entries()).sort(([u],[m])=>u.localeCompare(m)).map(([u,m])=>({date:u,...m}));return{total:o,granted:s,denied:r,managed:a,grantedPct:o>0?Math.round(s/o*1e3)/10:0,deniedPct:o>0?Math.round(r/o*1e3)/10:0,managedPct:o>0?Math.round(a/o*1e3)/10:0,byLocale:c,byDate:d}}};p();var $t=class{constructor(e){this.adapter=e}adapter;create(e){return this.adapter.createProfile(e)}update(e,t){return this.adapter.updateProfile(e,t)}delete(e){return this.adapter.deleteProfile(e)}get(e){return this.adapter.getProfile(e)}list(e){return this.adapter.getProfiles(e)}findActiveByComplianceGroup(e,t){return this.adapter.findActiveProfileByComplianceGroup(e,t)}};p();var Ft=class{constructor(e){this.adapter=e}adapter;create(e){return this.adapter.createConsent(e)}update(e,t){return this.adapter.updateConsent(e,t)}delete(e){return this.adapter.deleteConsent(e)}get(e){return this.adapter.getConsent(e)}list(e){return this.adapter.getConsents(e)}};p();var Ht=class{constructor(e){this.adapter=e}adapter;create(e){return this.adapter.createVisitor(e)}update(e,t){return this.adapter.updateVisitor(e,t)}delete(e){return this.adapter.deleteVisitor(e)}get(e){return this.adapter.getVisitor(e)}};p();var Vt=class{constructor(e){this.adapter=e}adapter;create(e){return this.adapter.createNoticeShown(e)}getForVisitor(e){return this.adapter.getNoticeShownForVisitor(e)}};p();var Wt=class{constructor(e){this.adapter=e}adapter;log(e){return this.adapter.createLog(e)}list(e){return this.adapter.getLogs(e)}get(e){return this.adapter.getAuditLogById(e)}};p();p();var qt=class{constructor(e,t=500,n=6e4){this.ttlMs=e;this.maxEntries=t;this.sweepTimer=setInterval(()=>this.sweep(),n),this.sweepTimer.unref?.()}ttlMs;maxEntries;store=new Map;sweepTimer=null;get(e){let t=this.store.get(e);if(t){if(Date.now()>t.expiresAt){this.store.delete(e);return}return t.value}}set(e,t){if(this.store.size>=this.maxEntries&&!this.store.has(e)){let n=this.store.keys().next().value;n!==void 0&&this.store.delete(n)}this.store.set(e,{value:t,expiresAt:Date.now()+this.ttlMs})}sweep(){let e=Date.now();for(let[t,n]of this.store)e>n.expiresAt&&this.store.delete(t)}dispose(){this.sweepTimer&&clearInterval(this.sweepTimer),this.sweepTimer=null}};var Ol=3e4,Jt=class{constructor(e){this.storage=e}storage;cache=new qt(Ol);async getOverview(e){return this.cached(`overview:${e}`,()=>this.storage.getOverviewStats(e))}async getCategories(e){return this.cached(`categories:${e}`,()=>this.storage.getCategoryStats(e))}async getTimeline(e,t){return this.cached(`timeline:${e}:${t}`,()=>this.storage.getTimeline(e,t))}async getCountries(e){return this.cached(`countries:${e}`,()=>this.storage.getCountries(e))}async getGpc(e){return this.cached(`gpc:${e}`,()=>this.storage.getGpcStats(e))}async getTenants(){return this.storage.getTenants()}dispose(){this.cache.dispose()}async cached(e,t){let n=this.cache.get(e);if(n!==void 0)return n;let o=await t();return this.cache.set(e,o),o}};p();var zt=class{constructor(e){this.adapter=e}adapter;getById(e){return this.adapter.getUserById(e)}getByEmail(e){return this.adapter.getUserByEmail(e)}list(e){return this.adapter.getUsers(e)}create(e){return this.adapter.createUser(e)}update(e,t){return this.adapter.updateUser(e,t)}delete(e){return this.adapter.deleteUser(e)}getRoles(e,t){return this.adapter.getUserRoles(e,t)}assignRole(e,t,n){return this.adapter.assignRole(e,t,n)}revokeRole(e,t,n){return this.adapter.revokeRole(e,t,n)}};p();var $=require("node:fs"),ee=require("node:path");p();var is=require("node:worker_threads"),os=require("node:url"),Xt=require("node:path"),ss=require("node:fs");p();var U=require("node:fs"),de=require("node:path"),Xo=require("node:crypto");p();var lt=require("node:crypto");function ti(i){return(0,lt.createHash)("sha256").update(i).digest("hex")}function Kt(i,e){return(0,lt.createHmac)("sha256",i).update(e).digest()}function Dl(i){let e=i.toISOString().replace(/[-:]/g,"").slice(0,15)+"Z";return{amzDate:e,dateStamp:e.slice(0,8)}}function kl(i,e,t,n){let o=Kt(`AWS4${i}`,e),s=Kt(o,t),r=Kt(s,n);return Kt(r,"aws4_request")}function Wo(i){let{method:e,key:t,body:n,contentType:o,config:s}=i,r=new Date,{amzDate:a,dateStamp:c}=Dl(r),l=`${s.bucketName}.s3.${s.region}.amazonaws.com`,d=ti(n?Buffer.isBuffer(n)?n:Buffer.from(n,"utf8"):""),u={host:l,"x-amz-date":a,"x-amz-content-sha256":d};s.sessionToken&&(u["x-amz-security-token"]=s.sessionToken),o&&e==="PUT"&&(u["content-type"]=o);let m=Object.keys(u).sort(),f=m.map(P=>`${P}:${u[P]}
137
+ `).join(""),S=m.join(";"),y=[e,`/${encodeURIComponent(t).replace(/%2F/g,"/")}`,"",f,S,d].join(`
138
+ `),E=`${c}/${s.region}/s3/aws4_request`,R=["AWS4-HMAC-SHA256",a,E,ti(y)].join(`
139
+ `),v=kl(s.secretAccessKey,c,s.region,"s3"),A=(0,lt.createHmac)("sha256",v).update(R).digest("hex"),T=[`AWS4-HMAC-SHA256 Credential=${s.accessKeyId}/${E}`,`SignedHeaders=${S}`,`Signature=${A}`].join(", ");return{...u,authorization:T}}function qo(i,e){let t=encodeURIComponent(i).replace(/%2F/g,"/");return`https://${e.bucketName}.s3.${e.region}.amazonaws.com/${t}`}async function Yt(i,e,t,n="application/json"){let o=Wo({method:"PUT",key:i,body:e,contentType:n,config:t}),s=typeof e=="string"?e:e.toString("utf8"),r=await fetch(qo(i,t),{method:"PUT",headers:{...o,"content-length":String(Buffer.byteLength(s,"utf8"))},body:s});if(!r.ok){let a=await r.text().catch(()=>"");throw new Error(`S3 PUT ${i} failed: ${r.status} ${a}`)}}async function Jo(i,e){let t=Wo({method:"DELETE",key:i,config:e}),n=await fetch(qo(i,e),{method:"DELETE",headers:t});if(!n.ok&&n.status!==404){let o=await n.text().catch(()=>"");throw new Error(`S3 DELETE ${i} failed: ${n.status} ${o}`)}}p();var Ll=/^[a-z0-9][a-z0-9_-]{0,63}$/,Nl=/^[A-Za-z]{2,3}(?:-[A-Za-z0-9]{2,8}){0,3}$/,Yo=/^(?:con|prn|aux|nul|com[1-9]|lpt[1-9])$/i,xl="prof_";function ni(i){return typeof i=="string"&&Ll.test(i)&&!Yo.test(i)&&!i.startsWith(xl)}function zo(i){return typeof i=="string"&&Nl.test(i)&&!Yo.test(i)}var Ul='must be 1-64 lowercase letters, digits, "-" or "_", start with a letter or digit, and not be a reserved name or start with "prof_"',Ko='must be a language tag such as "en" or "pt-BR"';function Qt(i){let{defaultLocale:e,complianceGroup:t,customComplianceGroup:n,locales:o,localeContentKeys:s}=i;if(e!==void 0&&!zo(e))return`defaultLocale ${Ko}`;for(let[l,d]of[["complianceGroup",t],["customComplianceGroup",n]])if(d!=null&&d!==""&&!ni(d))return`${l} ${Ul}`;let r=[...Array.isArray(o)?o:[],...s??[]];if(o!==void 0&&!Array.isArray(o))return"locales must be an array";let a=r.find(l=>!zo(l));if(a!==void 0)return`locale ${JSON.stringify(a)} ${Ko}`;let c=new Set;for(let l of Array.isArray(o)?o:[]){let d=l.toLowerCase();if(c.has(d))return`locale "${l}" is listed twice (locale codes are compared case-insensitively)`;c.add(d)}return null}function oi(i,e){return(0,de.join)(i,"profiles",e)}function ii(i,e,t,n){return(0,de.join)(oi(i,e),t,String(n))}function es(i,e,t){return(0,de.join)(oi(i,e),t)}function Zt(i,e,t){return`profiles/${i}/${e}/${t}.json`}function Ml(i){let e=Qt({defaultLocale:i.profile.defaultLocale,locales:i.profile.locales,localeContentKeys:Object.keys(i.localeContent)});if(e)throw new Error(`Refusing to write profile files: ${e}`)}function ts(i){if(!ni(i))throw new Error(`Refusing to touch the live profile directory for compliance group ${JSON.stringify(i)}`)}function Qo(i,e){let t=i+".tmp";(0,U.writeFileSync)(t,e,"utf8"),JSON.parse(e),(0,U.renameSync)(t,i)}var Gl=["gpcMode","complianceGroup","darkMode","allowReceipt","enhanceAccessibility","showFooterMetadata","allowedOrigins","complianceConfig","dpdpa","ageGate","hidePoweredBy"];function jl(i){let e={};for(let t of Gl){let n=i[t];n!==void 0&&(e[t]=n)}return e}async function Zo(i){let{storagePath:e,tenantId:t,profileId:n,version:o,profile:s,localeContent:r,previousVersion:a,s3Config:c}=i;Ml(i);let l=ii(e,t,n,o);(0,U.mkdirSync)(l,{recursive:!0});let{locales:d,defaultLocale:u,cookies:m,expiryDays:f}=s;for(let S of d){let y,E=r[S];if(E){let v={id:s.id,version:o,defaultLocale:u,currentLocale:S,locales:d,cookies:m,...f!==void 0?{expiryDays:f}:{},...jl(s),mainBanner:E.mainBanner,...E.gpcBanner?{gpcBanner:E.gpcBanner}:{},preferenceModal:E.preferenceModal,...E.ageGateModal?{ageGateModal:E.ageGateModal}:{}};y=JSON.stringify(v,null,2)}else if(a!==void 0){let v=(0,de.join)(ii(e,t,n,a),`${S}.json`);if(!(0,U.existsSync)(v))continue;y=(0,U.readFileSync)(v,"utf8")}else continue;let R=(0,de.join)(l,`${S}.json`);Qo(R,y),S===u&&Qo((0,de.join)(l,"default.json"),y),c?.enabled&&(await Yt(Zt(t,`${n}/${o}`,S),y,c),S===u&&await Yt(Zt(t,`${n}/${o}`,"default"),y,c))}if(!(0,U.existsSync)((0,de.join)(l,"default.json"))){let S=d.includes(u)?u:d[0]??"";if(S){let y=(0,de.join)(l,`${S}.json`);(0,U.existsSync)(y)&&(0,U.copyFileSync)(y,(0,de.join)(l,"default.json"))}}}function Bl(i){(0,U.existsSync)(i)&&((0,U.lstatSync)(i).isSymbolicLink()||(0,U.rmSync)(i,{recursive:!0,force:!0}))}async function $l(i){let{storagePath:e,tenantId:t,profileId:n,version:o,complianceGroup:s,s3Config:r}=i;ts(s);let a=(0,de.resolve)(ii(e,t,n,o)),c=es(e,t,s);(0,U.mkdirSync)(oi(e,t),{recursive:!0}),Bl(c);let l=`${c}.new-${(0,Xo.randomUUID)().slice(0,8)}`;(0,U.symlinkSync)(a,l,"junction");try{if(process.platform==="win32")try{(0,U.unlinkSync)(c)}catch(d){if(d.code!=="ENOENT")throw d}(0,U.renameSync)(l,c)}catch(d){try{(0,U.unlinkSync)(l)}catch{}throw d}if(r?.enabled){let d=JSON.stringify({profileId:n,version:o});await Yt(Zt(t,s,"pointer"),d,r)}}async function Fl(i){let{storagePath:e,tenantId:t,complianceGroup:n,s3Config:o}=i;ts(n);let s=es(e,t,n);(0,U.existsSync)(s)&&((0,U.lstatSync)(s).isSymbolicLink()?(0,U.unlinkSync)(s):(0,U.rmSync)(s,{recursive:!0,force:!0})),o?.enabled&&await Jo(Zt(t,n,"pointer"),o)}async function ns(i){i.action==="write"?await Zo(i):i.action==="activate"?(await Zo(i),await $l(i)):i.action==="deactivate"&&await Fl(i)}var Hl=(0,Xt.dirname)((0,os.fileURLToPath)(h)),rs=(0,Xt.join)(Hl,"profile-json.worker.js"),Vl=!(0,ss.existsSync)(rs);async function si(i){if(Vl){await ns(i);return}return new Promise((e,t)=>{let n=new is.Worker(rs);n.postMessage(i),n.once("message",o=>{n.terminate(),o.ok?e():t(new Error(`[profile-worker] ${o.action} failed: ${o.error}`))}),n.once("error",o=>{n.terminate(),t(o)})})}function Ai(i,e){if(!e)return i;let t={...i};for(let[n,o]of Object.entries(e))t[n]&&(t[n]={...t[n],...o});return t}function kr(i){return{...i.gpcMode!==void 0?{gpcMode:i.gpcMode}:{},...i.complianceGroup!==void 0?{complianceGroup:i.complianceGroup}:{},...i.darkMode!==void 0?{darkMode:i.darkMode}:{},...i.allowReceipt!==void 0?{allowReceipt:i.allowReceipt}:{},...i.enhanceAccessibility!==void 0?{enhanceAccessibility:i.enhanceAccessibility}:{},...i.showFooterMetadata!==void 0?{showFooterMetadata:i.showFooterMetadata}:{},...i.allowedOrigins!==void 0?{allowedOrigins:i.allowedOrigins}:{},...i.complianceConfig!==void 0?{complianceConfig:i.complianceConfig}:{},...i.dpdpa!==void 0?{dpdpa:i.dpdpa}:{},...i.ageGate!==void 0?{ageGate:i.ageGate}:{},...i.hidePoweredBy!==void 0?{hidePoweredBy:i.hidePoweredBy}:{}}}var mn=class{constructor(e,t,n="default",o,s,r,a,c,l){this.profiles=e;this.audit=t;this.tenantId=n;this.storage=o;this.eventBus=s;this.localeCache=r;this.profilesDir=a;this.handleCache=c;this.s3Config=l}profiles;audit;tenantId;storage;eventBus;localeCache;profilesDir;handleCache;s3Config;versionsRootDir(e){return(0,ee.join)(this.profilesDir??"",this.tenantId,e)}complianceGroupDir(e){return(0,ee.join)(this.profilesDir??"",this.tenantId,e)}groupKey(e){return e.complianceGroup||e.customComplianceGroup||""}profileFilePaths(e,t){let n=this.complianceGroupDir(e);return t.map(o=>(0,ee.join)(n,`${o}.json`)).concat((0,ee.join)(n,"default.json"))}async resolveCookies(e){let t=e.cookies??{};if(e.consentTemplateId&&this.storage){let n=await this.storage.getConsentTemplate(e.consentTemplateId);n&&(t=n.cookies)}return Ai(t,e.cookiesOverride)}async writeLocaleFiles(e,t,n,o){if(!this.profilesDir)return;let s=e.profileJson,r=await this.resolveCookies(s),a=s.locales?.length?s.locales:[e.defaultLocale],c={[e.defaultLocale]:{mainBanner:s.mainBanner,...s.gpcBanner?{gpcBanner:s.gpcBanner}:{},preferenceModal:s.preferenceModal,...s.ageGateModal?{ageGateModal:s.ageGateModal}:{}},...t??{}},l=(s.isActive??!1)&&n!=="",u={action:l?"activate":"write",storagePath:(0,ee.join)(this.profilesDir,".."),tenantId:this.tenantId,profileId:e.id,version:e.version,complianceGroup:n,profile:{id:e.id,defaultLocale:e.defaultLocale,locales:a,cookies:r,...s.expiryDays!==void 0?{expiryDays:s.expiryDays}:{},...kr(s)},localeContent:c,...o!==void 0?{previousVersion:o}:{},...this.s3Config?.enabled?{s3Config:this.s3Config}:{}};if(await si(u),l){let m=this.profileFilePaths(n,a);this.handleCache?.(m,e.id,!0),this.eventBus?.emit("cache:purge",{paths:m,profileId:e.id})}}async create(e,t){let{localeContent:n,...o}=e,s=await this.profiles.create({...o,tenantId:this.tenantId});if(await this.audit.log({tenantId:this.tenantId,...t!=null?{userId:t}:{},action:"profile:created",resourceType:"profile",resourceId:s.id,newData:{profileId:s.id,version:s.version,complianceGroup:this.groupKey(s.profileJson)}}),this.eventBus?.emit("profile:created",s),this.profilesDir){let r=this.groupKey(s.profileJson);await this.writeLocaleFiles(s,n,r,void 0);let a=s.profileJson.locales?.length?s.profileJson.locales:[s.defaultLocale],c=this.profileFilePaths(r,a);this.handleCache?.(c,s.id,!1),this.eventBus?.emit("cache:warm",{paths:c,profileId:s.id})}return s}async copy(e,t,n){let o=await this.profiles.get(e);if(!o)throw new Error(`Profile ${e} not found`);let s=o.profileJson.locales?.length?o.profileJson.locales:[o.defaultLocale],r={};for(let a of s){if(a===o.defaultLocale)continue;let c=await this.getVersionFile(e,String(o.version),a);if(c)try{let l=JSON.parse(c);r[a]={mainBanner:l.mainBanner,...l.gpcBanner?{gpcBanner:l.gpcBanner}:{},preferenceModal:l.preferenceModal}}catch{}}return this.create({name:t??`Copy of ${o.name}`,defaultLocale:o.defaultLocale,profileJson:{...o.profileJson,isActive:!1},...Object.keys(r).length>0?{localeContent:r}:{}},n)}async update(e,t,n){let o=await this.profiles.get(e);if(!o)throw new Error(`Profile ${e} not found`);let{localeContent:s,...r}=t,a=r.profileJson?.isActive??o.profileJson.isActive,c=r.profileJson?{...r.profileJson,...a!==void 0?{isActive:a}:{}}:o.profileJson,l=await this.profiles.update(e,{name:r.name??o.name,defaultLocale:r.defaultLocale??o.defaultLocale,profileJson:c,version:o.version+1});if(this.localeCache?.invalidate(e),await this.audit.log({tenantId:this.tenantId,...n!=null?{userId:n}:{},action:"profile:updated",resourceType:"profile",resourceId:l.id,oldData:{profileId:o.id,version:o.version},newData:{profileId:l.id,version:l.version,complianceGroup:this.groupKey(l.profileJson)}}),this.eventBus?.emit("profile:updated",{previous:o,current:l}),this.profilesDir){let d=this.groupKey(l.profileJson);await this.writeLocaleFiles(l,s,d,o.version)}return l}async delete(e,t){let n=await this.profiles.get(e);if(await this.profiles.delete(e),this.localeCache?.invalidate(e),await this.audit.log({tenantId:this.tenantId,...t!=null?{userId:t}:{},action:"profile:deleted",resourceType:"profile",resourceId:e,...n!=null?{oldData:{profileId:n.id,version:n.version,name:n.name,complianceGroup:this.groupKey(n.profileJson),wasActive:n.profileJson.isActive??!1}}:{}}),this.eventBus?.emit("profile:deleted",{id:e,previous:n}),this.profilesDir&&n){let o=this.groupKey(n.profileJson);if((n.profileJson.isActive??!1)&&o){let r=n.profileJson.locales?.length?n.profileJson.locales:[n.defaultLocale];await this.runDeactivate(o);let a=this.profileFilePaths(o,r);this.handleCache?.(a,e,!0),this.eventBus?.emit("cache:purge",{paths:a,profileId:e})}}}async activate(e,t){let n=await this.profiles.get(e);if(!n)throw new Error(`Profile ${e} not found`);let o=this.groupKey(n.profileJson),s=await this.profiles.update(e,{profileJson:{...n.profileJson,isActive:!0}});return this.localeCache?.invalidate(e),this.profilesDir&&o&&await this.writeLocaleFiles(s,void 0,o,n.version),await this.audit.log({tenantId:this.tenantId,...t!=null?{userId:t}:{},action:"profile.activated",resourceType:"profile",resourceId:e}),this.eventBus?.emit("profile.activated",s),s}async deactivate(e,t){let n=await this.profiles.get(e);if(!n)throw new Error(`Profile ${e} not found`);let o=this.groupKey(n.profileJson),s=await this.profiles.update(e,{profileJson:{...n.profileJson,isActive:!1}});if(this.localeCache?.invalidate(e),this.profilesDir&&o){let r=n.profileJson.locales?.length?n.profileJson.locales:[n.defaultLocale];await this.runDeactivate(o);let a=this.profileFilePaths(o,r);this.handleCache?.(a,e,!0),this.eventBus?.emit("cache:purge",{paths:a,profileId:e})}return await this.audit.log({tenantId:this.tenantId,...t!=null?{userId:t}:{},action:"profile.deactivated",resourceType:"profile",resourceId:e}),this.eventBus?.emit("profile.deactivated",s),s}async runDeactivate(e){if(!this.profilesDir)return;let t={action:"deactivate",storagePath:(0,ee.join)(this.profilesDir,".."),tenantId:this.tenantId,profileId:"",version:0,complianceGroup:e,profile:{id:"",defaultLocale:"",locales:[],cookies:{}},localeContent:{},...this.s3Config?.enabled?{s3Config:this.s3Config}:{}};await si(t)}async get(e){return this.profiles.get(e)}async getResolved(e,t){let n=await this.profiles.get(e);if(!n)return null;let o=t??n.defaultLocale;if(this.localeCache){let u=this.localeCache.read(e,o);if(u)return u}let s=n.profileJson,r=await this.resolveCookies(s),a=s.locales?.length?s.locales:[n.defaultLocale],l={mainBanner:s.mainBanner,...s.gpcBanner?{gpcBanner:s.gpcBanner}:{},preferenceModal:s.preferenceModal,...s.ageGateModal?{ageGateModal:s.ageGateModal}:{}};if(o!==n.defaultLocale){let u=await this.getVersionFile(e,String(n.version),o);if(u)try{let m=JSON.parse(u);l={mainBanner:m.mainBanner,...m.gpcBanner?{gpcBanner:m.gpcBanner}:{},preferenceModal:m.preferenceModal,...m.ageGateModal?{ageGateModal:m.ageGateModal}:{}}}catch{}}let d={id:n.id,version:n.version,defaultLocale:n.defaultLocale,currentLocale:o,locales:a,cookies:r,...s.expiryDays!==void 0?{expiryDays:s.expiryDays}:{},...kr(s),...l};if(this.localeCache)try{this.localeCache.write(e,o,d)}catch(u){console.warn(`[Consenti] locale cache write failed for ${e}/${o}:`,u)}return d}findActiveByComplianceGroup(e){return this.profiles.findActiveByComplianceGroup(this.tenantId,e)}list(){return this.profiles.list(this.tenantId)}listSummary(){return this.storage?this.storage.listProfilesSummary(this.tenantId):Promise.resolve([])}async listVersions(e){if(!this.profilesDir)return[];let t=this.versionsRootDir(e);if(!(0,$.existsSync)(t))return[];let n=[];try{let o=(0,$.readdirSync)(t,{withFileTypes:!0});for(let s of o){if(!s.isDirectory())continue;let r=Number(s.name);if(!Number.isInteger(r))continue;let a=(0,ee.join)(t,s.name),c=(0,$.readdirSync)(a).filter(d=>d.endsWith(".json")&&d!=="default.json").map(d=>d.replace(".json","")),l;try{l=(0,$.statSync)(a).mtime.toISOString()}catch{l=new Date().toISOString()}n.push({version:r,createdAt:l,locales:c})}}catch{return[]}return n.sort((o,s)=>s.version-o.version)}async getArchivedSnapshot(e,t){let n=await this.listVersions(e),o=n.find(r=>r.version===t)??n[0];if(!o)return null;let s=await this.getVersionFile(e,String(o.version),"default");if(!s)return null;try{return JSON.parse(s)}catch{return null}}async getVersionFile(e,t,n){if(!this.profilesDir)return null;let o=(0,ee.join)(this.versionsRootDir(e),t),s=(0,ee.join)(o,`${n}.json`);if(!(0,$.existsSync)(s)){let r=(0,ee.join)(o,"default.json");return(0,$.existsSync)(r)?(0,$.readFileSync)(r,"utf8"):null}return(0,$.readFileSync)(s,"utf8")}async listArchivedProfiles(){if(!this.profilesDir)return[];let e=(0,ee.join)(this.profilesDir,this.tenantId);if(!(0,$.existsSync)(e))return[];let t=new Set((await this.profiles.list(this.tenantId)).map(s=>s.id)),n=[],o;try{o=(0,$.readdirSync)(e,{withFileTypes:!0})}catch{return[]}for(let s of o){if(!s.isDirectory()||t.has(s.name))continue;let r=(0,ee.join)(e,s.name);if((0,$.lstatSync)(r).isSymbolicLink())continue;let a;try{a=(0,$.readdirSync)(r,{withFileTypes:!0})}catch{continue}let c=a.filter(d=>d.isDirectory()&&Number.isInteger(Number(d.name)));if(c.length===0)continue;let l=new Date(0).toISOString();for(let d of c)try{let u=(0,$.statSync)((0,ee.join)(r,d.name)).mtime.toISOString();u>l&&(l=u)}catch{}n.push({id:s.name,versionCount:c.length,lastModified:l})}return n.sort((s,r)=>r.lastModified.localeCompare(s.lastModified))}toTemplateButtonMap(e){let t={};for(let[n,o]of Object.entries(e))t[n]={type:o.style,action:o.action,...o.cookies!==void 0?{cookies:o.cookies}:{}};return t}buildSeedUiTemplatePayload(e){let t={position:e.mainBanner.position,buttons:this.toTemplateButtonMap(e.mainBanner.buttons),...e.mainBanner.showClose!==void 0?{showClose:e.mainBanner.showClose}:{},...e.mainBanner.showLocaleSwitcher!==void 0?{showLocaleSwitcher:e.mainBanner.showLocaleSwitcher}:{}},n=e.gpcBanner?{position:e.gpcBanner.position,buttons:this.toTemplateButtonMap(e.gpcBanner.buttons),...e.gpcBanner.showClose!==void 0?{showClose:e.gpcBanner.showClose}:{},...e.gpcBanner.showLocaleSwitcher!==void 0?{showLocaleSwitcher:e.gpcBanner.showLocaleSwitcher}:{}}:t,o={buttons:this.toTemplateButtonMap(e.preferenceModal.buttons),...e.preferenceModal.position!==void 0?{position:e.preferenceModal.position}:{},...e.preferenceModal.persistent!==void 0?{persistent:e.preferenceModal.persistent}:{}};return{mainBanner:t,gpcBanner:n,preferenceModal:o}}async getOrCreateSeedTemplates(e,t,n){if(!this.storage)throw new Error("Storage adapter required to seed templates");let o=`Default \u2014 ${e}`,r=(await this.storage.getConsentTemplates(this.tenantId)).find(l=>l.name===o)??await this.storage.createConsentTemplate({tenantId:this.tenantId,name:o,cookies:t.cookies,categories:n.preferenceModal.categories}),c=(await this.storage.getUITemplates(this.tenantId)).find(l=>l.name===o)??await this.storage.createUITemplate({tenantId:this.tenantId,name:o,...this.buildSeedUiTemplatePayload(n)});return{consentTemplateId:r.id,uiTemplateId:c.id}}async seedDefaultProfile(e){if(await this.profiles.findActiveByComplianceGroup(this.tenantId,e))return;let{DEFAULT_PROFILES:n,resolveLocaleTranslation:o}=await Promise.resolve().then(()=>(fi(),yr)),s=n[e];if(!s)return;let r=s.translations.en;if(!r)return;let a=["de","es","fr","ja"],c=["en",...a.filter(m=>o(e,m)!==void 0)],l={};for(let m of a){let f=o(e,m);f&&(l[m]={mainBanner:f.mainBanner,...f.gpcBanner?{gpcBanner:f.gpcBanner}:{},preferenceModal:f.preferenceModal})}let{consentTemplateId:d,uiTemplateId:u}=await this.getOrCreateSeedTemplates(e,{cookies:s.cookies},r);await this.create({name:`Default \u2014 ${e}`,defaultLocale:s.defaultLocale,profileJson:{id:(0,C.randomUUID)(),defaultLocale:s.defaultLocale,complianceGroup:s.complianceGroup,gpcMode:s.gpcMode,cookies:s.cookies,consentTemplateId:d,uiTemplateId:u,...s.expiryDays!==void 0?{expiryDays:s.expiryDays}:{},locales:c,mainBanner:r.mainBanner,...r.gpcBanner?{gpcBanner:r.gpcBanner}:{},preferenceModal:r.preferenceModal,isActive:!0},...Object.keys(l).length>0?{localeContent:l}:{}})}async seedAllDefaults(){let{COMPLIANCE_GROUP_IDS:e}=await Promise.resolve().then(()=>(se(),Dr));await Promise.all(e.map(t=>this.seedDefaultProfile(t)))}};p();se();p();var Lr={"Europe/Amsterdam":"NL","Europe/Andorra":"AD","Europe/Athens":"GR","Europe/Belgrade":"RS","Europe/Berlin":"DE","Europe/Bratislava":"SK","Europe/Brussels":"BE","Europe/Bucharest":"RO","Europe/Budapest":"HU","Europe/Busingen":"DE","Europe/Chisinau":"MD","Europe/Copenhagen":"DK","Europe/Dublin":"IE","Europe/Gibraltar":"GI","Europe/Guernsey":"GG","Europe/Helsinki":"FI","Europe/Isle_of_Man":"IM","Europe/Istanbul":"TR","Europe/Jersey":"JE","Europe/Kaliningrad":"RU","Europe/Kiev":"UA","Europe/Kyiv":"UA","Europe/Lisbon":"PT","Europe/Ljubljana":"SI","Europe/London":"GB","Europe/Luxembourg":"LU","Europe/Madrid":"ES","Europe/Malta":"MT","Europe/Mariehamn":"FI","Europe/Minsk":"BY","Europe/Monaco":"MC","Europe/Moscow":"RU","Europe/Nicosia":"CY","Europe/Oslo":"NO","Europe/Paris":"FR","Europe/Podgorica":"ME","Europe/Prague":"CZ","Europe/Riga":"LV","Europe/Rome":"IT","Europe/Samara":"RU","Europe/San_Marino":"SM","Europe/Sarajevo":"BA","Europe/Saratov":"RU","Europe/Simferopol":"UA","Europe/Skopje":"MK","Europe/Sofia":"BG","Europe/Stockholm":"SE","Europe/Tallinn":"EE","Europe/Tirane":"AL","Europe/Ulyanovsk":"RU","Europe/Uzhgorod":"UA","Europe/Vaduz":"LI","Europe/Vatican":"VA","Europe/Vienna":"AT","Europe/Vilnius":"LT","Europe/Volgograd":"RU","Europe/Warsaw":"PL","Europe/Zagreb":"HR","Europe/Zaporozhye":"UA","Europe/Zurich":"CH","Atlantic/Reykjavik":"IS","Atlantic/Faroe":"FO","America/New_York":"US","America/Chicago":"US","America/Denver":"US","America/Los_Angeles":"US","America/Anchorage":"US","America/Adak":"US","America/Honolulu":"US","America/Phoenix":"US","America/Detroit":"US","America/Indiana/Indianapolis":"US","America/Indiana/Knox":"US","America/Indiana/Marengo":"US","America/Indiana/Petersburg":"US","America/Indiana/Tell_City":"US","America/Indiana/Vevay":"US","America/Indiana/Vincennes":"US","America/Indiana/Winamac":"US","America/Kentucky/Louisville":"US","America/Kentucky/Monticello":"US","America/North_Dakota/Beulah":"US","America/North_Dakota/Center":"US","America/North_Dakota/New_Salem":"US","America/Boise":"US","America/Menominee":"US","America/Nome":"US","America/Sitka":"US","America/Yakutat":"US","America/Juneau":"US","America/Metlakatla":"US","America/Toronto":"CA","America/Vancouver":"CA","America/Winnipeg":"CA","America/Halifax":"CA","America/St_Johns":"CA","America/Edmonton":"CA","America/Regina":"CA","America/Whitehorse":"CA","America/Yellowknife":"CA","America/Iqaluit":"CA","America/Moncton":"CA","America/Glace_Bay":"CA","America/Goose_Bay":"CA","America/Swift_Current":"CA","America/Dawson":"CA","America/Cambridge_Bay":"CA","America/Dawson_Creek":"CA","America/Fort_Nelson":"CA","America/Creston":"CA","America/Rankin_Inlet":"CA","America/Resolute":"CA","America/Pangnirtung":"CA","America/Nipigon":"CA","America/Mexico_City":"MX","America/Cancun":"MX","America/Monterrey":"MX","America/Merida":"MX","America/Chihuahua":"MX","America/Hermosillo":"MX","America/Mazatlan":"MX","America/Ojinaga":"MX","America/Bahia_Banderas":"MX","America/Matamoros":"MX","America/Tijuana":"MX","America/Sao_Paulo":"BR","America/Manaus":"BR","America/Belem":"BR","America/Fortaleza":"BR","America/Recife":"BR","America/Maceio":"BR","America/Bahia":"BR","America/Porto_Velho":"BR","America/Boa_Vista":"BR","America/Campo_Grande":"BR","America/Cuiaba":"BR","America/Santarem":"BR","America/Rio_Branco":"BR","America/Eirunepe":"BR","America/Noronha":"BR","America/Argentina/Buenos_Aires":"AR","America/Argentina/Cordoba":"AR","America/Argentina/Salta":"AR","America/Argentina/Jujuy":"AR","America/Argentina/Tucuman":"AR","America/Argentina/Catamarca":"AR","America/Argentina/La_Rioja":"AR","America/Argentina/San_Juan":"AR","America/Argentina/Mendoza":"AR","America/Argentina/San_Luis":"AR","America/Argentina/Rio_Gallegos":"AR","America/Argentina/Ushuaia":"AR","America/Bogota":"CO","America/Lima":"PE","America/Santiago":"CL","America/Caracas":"VE","America/La_Paz":"BO","America/Asuncion":"PY","America/Montevideo":"UY","America/Guayaquil":"EC","America/Guyana":"GY","America/Paramaribo":"SR","America/Cayenne":"GF","America/Panama":"PA","America/Costa_Rica":"CR","America/Guatemala":"GT","America/El_Salvador":"SV","America/Tegucigalpa":"HN","America/Managua":"NI","America/Belize":"BZ","America/Havana":"CU","America/Jamaica":"JM","America/Nassau":"BS","America/Port_of_Spain":"TT","America/Santo_Domingo":"DO","America/Port-au-Prince":"HT","America/Barbados":"BB","America/Martinique":"MQ","America/Guadeloupe":"GP","America/Puerto_Rico":"PR","America/St_Kitts":"KN","Asia/Kolkata":"IN","Asia/Calcutta":"IN","Asia/Karachi":"PK","Asia/Dhaka":"BD","Asia/Colombo":"LK","Asia/Kathmandu":"NP","Asia/Kabul":"AF","Asia/Tokyo":"JP","Asia/Seoul":"KR","Asia/Shanghai":"CN","Asia/Hong_Kong":"HK","Asia/Macau":"MO","Asia/Taipei":"TW","Asia/Ulaanbaatar":"MN","Asia/Choibalsan":"MN","Asia/Hovd":"MN","Asia/Singapore":"SG","Asia/Bangkok":"TH","Asia/Jakarta":"ID","Asia/Kuala_Lumpur":"MY","Asia/Manila":"PH","Asia/Ho_Chi_Minh":"VN","Asia/Saigon":"VN","Asia/Phnom_Penh":"KH","Asia/Vientiane":"LA","Asia/Rangoon":"MM","Asia/Yangon":"MM","Asia/Pontianak":"ID","Asia/Makassar":"ID","Asia/Jayapura":"ID","Asia/Kuching":"MY","Asia/Brunei":"BN","Asia/Dili":"TL","Asia/Tashkent":"UZ","Asia/Almaty":"KZ","Asia/Qyzylorda":"KZ","Asia/Aqtau":"KZ","Asia/Aqtobe":"KZ","Asia/Atyrau":"KZ","Asia/Oral":"KZ","Asia/Ashgabat":"TM","Asia/Dushanbe":"TJ","Asia/Bishkek":"KG","Asia/Yekaterinburg":"RU","Asia/Tehran":"IR","Asia/Baghdad":"IQ","Asia/Riyadh":"SA","Asia/Dubai":"AE","Asia/Kuwait":"KW","Asia/Qatar":"QA","Asia/Bahrain":"BH","Asia/Muscat":"OM","Asia/Beirut":"LB","Asia/Jerusalem":"IL","Asia/Tel_Aviv":"IL","Asia/Amman":"JO","Asia/Damascus":"SY","Asia/Nicosia":"CY","Asia/Famagusta":"CY","Asia/Baku":"AZ","Asia/Yerevan":"AM","Asia/Tbilisi":"GE","Asia/Samarkand":"UZ","Africa/Cairo":"EG","Africa/Casablanca":"MA","Africa/Lagos":"NG","Africa/Nairobi":"KE","Africa/Johannesburg":"ZA","Africa/Addis_Ababa":"ET","Africa/Algiers":"DZ","Africa/Tunis":"TN","Africa/Tripoli":"LY","Africa/Khartoum":"SD","Africa/Accra":"GH","Africa/Dar_es_Salaam":"TZ","Africa/Abidjan":"CI","Africa/Bamako":"ML","Africa/Banjul":"GM","Africa/Conakry":"GN","Africa/Dakar":"SN","Africa/Freetown":"SL","Africa/Lome":"TG","Africa/Monrovia":"LR","Africa/Nouakchott":"MR","Africa/Ouagadougou":"BF","Africa/Sao_Tome":"ST","Africa/Bissau":"GW","Africa/Bangui":"CF","Africa/Brazzaville":"CG","Africa/Douala":"CM","Africa/Kinshasa":"CD","Africa/Libreville":"GA","Africa/Luanda":"AO","Africa/Malabo":"GQ","Africa/Ndjamena":"TD","Africa/Niamey":"NE","Africa/Porto-Novo":"BJ","Africa/Blantyre":"MW","Africa/Bujumbura":"BI","Africa/Gaborone":"BW","Africa/Harare":"ZW","Africa/Kampala":"UG","Africa/Kigali":"RW","Africa/Lubumbashi":"CD","Africa/Lusaka":"ZM","Africa/Maputo":"MZ","Africa/Maseru":"LS","Africa/Mbabane":"SZ","Africa/Mogadishu":"SO","Africa/Windhoek":"NA","Africa/Asmara":"ER","Africa/Djibouti":"DJ","Africa/El_Aaiun":"EH","Africa/Juba":"SS","Africa/Ceuta":"ES","Australia/Sydney":"AU","Australia/Melbourne":"AU","Australia/Brisbane":"AU","Australia/Perth":"AU","Australia/Adelaide":"AU","Australia/Darwin":"AU","Australia/Hobart":"AU","Australia/Canberra":"AU","Australia/Broken_Hill":"AU","Australia/Lord_Howe":"AU","Australia/Lindeman":"AU","Australia/Eucla":"AU","Pacific/Auckland":"NZ","Pacific/Chatham":"NZ","Pacific/Fiji":"FJ","Pacific/Port_Moresby":"PG","Pacific/Bougainville":"PG","Pacific/Guam":"GU","Pacific/Saipan":"MP","Pacific/Pago_Pago":"AS","Pacific/Apia":"WS","Pacific/Tongatapu":"TO","Pacific/Fakaofo":"TK","Pacific/Niue":"NU","Pacific/Rarotonga":"CK","Pacific/Tahiti":"PF","Pacific/Marquesas":"PF","Pacific/Gambier":"PF","Pacific/Honolulu":"US","Pacific/Johnston":"US","Pacific/Midway":"UM","Pacific/Wake":"UM","Pacific/Tarawa":"KI","Pacific/Enderbury":"KI","Pacific/Kiritimati":"KI","Pacific/Efate":"VU","Pacific/Guadalcanal":"SB","Pacific/Noumea":"NC","Pacific/Nauru":"NR","Pacific/Palau":"PW","Pacific/Chuuk":"FM","Pacific/Pohnpei":"FM","Pacific/Kosrae":"FM","Pacific/Majuro":"MH","Pacific/Kwajalein":"MH","Pacific/Funafuti":"TV","Pacific/Wallis":"WF","Asia/Novosibirsk":"RU","Asia/Omsk":"RU","Asia/Krasnoyarsk":"RU","Asia/Irkutsk":"RU","Asia/Chita":"RU","Asia/Yakutsk":"RU","Asia/Khandyga":"RU","Asia/Vladivostok":"RU","Asia/Ust-Nera":"RU","Asia/Magadan":"RU","Asia/Sakhalin":"RU","Asia/Srednekolymsk":"RU","Asia/Kamchatka":"RU","Asia/Anadyr":"RU"};var Ud={ar:"SA",cs:"CZ",da:"DK",de:"DE",el:"GR",fi:"FI",fr:"FR",he:"IL",hi:"IN",hu:"HU",id:"ID",it:"IT",ja:"JP",ko:"KR",nl:"NL",no:"NO",pl:"PL",pt:"BR",ro:"RO",ru:"RU",sv:"SE",th:"TH",tr:"TR",uk:"UA",vi:"VN",zh:"CN"},gn=class{constructor(e,t){this.map=t;this.provider=e??"default",this.provider==="default"&&console.warn("[Consenti] geoDataProvider is unset (using the timezone/language heuristic) \u2014 this cannot resolve US state-level regions (California, Colorado, etc.), so US visitors always fall back to the country-level default (the strictest group, opt-out-strict) rather than their actual state law. Configure a geoip-capable provider (geoip, hosted-geoip-lite, or maxmind) for accurate US state routing in production.")}map;provider;setMap(e){this.map=e}async resolve(e){let t="",n,o,s=null,r;if(typeof this.provider=="function"){let l=await this.provider(e);t=l.country??"",n=l.region??void 0,s=l.locale,r=l.complianceGroup??void 0}else switch(this.provider){case"default":({country:t}=Gd(e.timezone)),t||({country:t,region:n}=Md(e.language));break;case"geoip":({country:t,region:n}=await jd(e.ip));break;case"hosted-geoip-lite":({country:t,region:n}=await $d(e.ip));break;case"maxmind":({country:t,region:n}=await Bd(e.ip));break}let a={country:t,complianceGroup:r??this.resolveGroup(t,n)};return n!==void 0&&(a.region=n),o!==void 0&&(a.regulation=o),s!==null&&(a.locale=s),this.resolveRequiresSensitiveOptIn(t,n)&&(a.requiresSensitiveOptIn=!0),a}countryEntry(e){let t=this.map.countries;return _i(t,e)}resolveGroup(e,t){if(!e)return"";let n=this.countryEntry(e);return n?t!==void 0?n.overriddenRegions?.[t]?.complianceGroup??n.complianceGroup:n.default??n.complianceGroup:""}resolveRequiresSensitiveOptIn(e,t){return!e||t===void 0?!1:this.countryEntry(e)?.overriddenRegions?.[t]?.requiresSensitiveOptIn===!0}};function Md(i){let t=(i.split(",")[0]?.trim().split(";")[0]?.trim()??"").split("-");if(t.length>=2){let o=(t[t.length-1]??"").toUpperCase();if(/^[A-Z]{2}$/.test(o))return{country:o}}return{country:Ud[(t[0]??"").toLowerCase()]??""}}function Gd(i){return{country:Lr[i]??""}}async function jd(i){if(!i)return{country:""};try{let t=(await import("geoip-lite")).lookup(i),n={country:t?.country??""},o=t?.region;return o&&(n.region=o),n}catch{return console.warn("[Consenti] geoip-lite not installed \u2014 country detection skipped. Run: npm install geoip-lite"),{country:""}}}async function Bd(i){if(!i)return{country:""};try{let e=await import("maxmind"),t=process.env.MAXMIND_DB_PATH??"./GeoLite2-City.mmdb",o=(await e.open(t)).get(i),s=o?.country?.iso_code??"",r=o?.subdivisions?.[0]?.iso_code,a={country:s};return r&&(a.region=r),a}catch{return console.warn("[Consenti] maxmind not available \u2014 country detection skipped. See HOW_TO_MAXMIND.md"),{country:""}}}async function $d(i){return i?new Promise(e=>{import("node:https").then(({default:t})=>{let n=`https://ipinfo.io/${encodeURIComponent(i)}/json`,o=t.get(n,{timeout:3e3},s=>{let r=[];s.on("data",a=>r.push(a)),s.on("end",()=>{try{let a=JSON.parse(Buffer.concat(r).toString()),c={country:a.country??""};a.region&&(c.region=a.region),e(c)}catch{e({country:""})}})});o.on("error",()=>e({country:""})),o.on("timeout",()=>{o.destroy(),e({country:""})})}).catch(()=>e({country:""}))}):{country:""}}p();se();var Fd=1440*60*1e3;function Hd(i){let e=i?.headers.get("cache-control")?.match(/max-age=(\d+)/)?.[1];if(e){let n=parseInt(e,10)*1e3;if(!isNaN(n)&&n>0)return n}let t=i?.headers.get("expires");if(t){let n=Date.parse(t)-Date.now();if(!isNaN(n)&&n>0)return n}return Fd}function Nr(i,e){let t,n=async()=>{let{map:o,response:s}=await wi(i,r=>console.error("[Consenti]",r));e.setMap(o),typeof i=="string"&&(t=setTimeout(()=>{n()},Hd(s)),t.unref())};return n(),{stop:()=>{t&&clearTimeout(t)}}}p();var Ae=require("node:fs"),Ti=require("node:path");p();var H=require("node:fs"),xr=require("node:path");function Ur(i,e,t){let n=i+".bak",o=i+".tmp";(0,H.mkdirSync)((0,xr.dirname)(i),{recursive:!0});let s=(0,H.existsSync)(i);s&&(0,H.copyFileSync)(i,n);try{(0,H.writeFileSync)(o,JSON.stringify(e,null,2),"utf8");let r=JSON.parse((0,H.readFileSync)(o,"utf8"));if(!t(r))throw new Error("Schema validation failed for "+i);if((0,H.renameSync)(o,i),s)try{(0,H.unlinkSync)(n)}catch{}}catch(r){if(s)try{(0,H.copyFileSync)(n,i),(0,H.unlinkSync)(n)}catch{}try{(0,H.unlinkSync)(o)}catch{}throw r}}function Mr(i){return typeof i=="object"&&i!==null&&typeof i.id=="string"&&typeof i.version=="number"}var fn=class{constructor(e){this.dir=e}dir;read(e,t){let n=this.path(e,t);if(!(0,Ae.existsSync)(n))return null;try{let o=JSON.parse((0,Ae.readFileSync)(n,"utf8"));return Mr(o)?o:null}catch{return null}}write(e,t,n){Ur(this.path(e,t),n,Mr)}rebuild(e,t){for(let[n,o]of t)try{this.write(e,n,o)}catch(s){console.warn(`[Consenti] locale cache rebuild failed for ${e}/${n}:`,s)}}invalidate(e){try{let t=`${e}_`;for(let n of(0,Ae.readdirSync)(this.dir))if(n.startsWith(t)&&n.endsWith(".json"))try{(0,Ae.unlinkSync)((0,Ti.join)(this.dir,n))}catch{}}catch{}}path(e,t){return(0,Ti.join)(this.dir,`${e}_${t}.json`)}};p();p();se();function Gr(i,e,t){let n=[];for(let[o,s]of Object.entries(i.consentJson)){if(!e[o])continue;let r=qe(o,t);r==="mandatory"&&s!=="granted"&&n.push(`Cookie "${o}" is mandatory and cannot be "${s}"`),s==="objected"&&r!=="legitimate_interest"&&n.push(`Cookie "${o}" has legal basis "${r}" \u2014 'objected' is only valid for 'legitimate_interest'`)}return{valid:n.length===0,errors:n}}function Ii(i,e,t,n,o){let s={};for(let[r,a]of Object.entries(i)){if(hi(r,e)){s[r]="granted";continue}if(o==="cpra"){if(a.cpraCategory==="sensitive"){let l=t[r];s[r]=l==="granted"||l==="denied"||l==="objected"?l:"denied";continue}if(n&&(a.cpraCategory==="sale"||a.cpraCategory==="sharing")){s[r]="denied";continue}}if(n&&a.listenGpc&&o!=="dpdpa"){s[r]="denied";continue}let c=t[r];c==="granted"||c==="denied"||c==="objected"?s[r]=c:s[r]="denied"}return s}function Pi(i){let e=Object.keys(i.consentJson).sort().map(t=>`${t}=${i.consentJson[t]}`).join(",");return`${i.tenantId}|${i.visitorId}|${i.profileId}|${i.locale}|${e}`}function jr(i,e,t,n){let o=[];return(!t||t.id!==e.id)&&o.push("profile_changed"),Vd(i,e)&&o.push("consent_expired"),n&&i.signature&&ue(Pi(i),n)!==i.signature&&o.push("hmac_invalid"),{valid:o.length===0,reasons:o,...t?{currentProfileId:t.id}:{},consentProfileId:e.id}}function Br(i,e){let t=new Set,n=new Set;for(let[o,s]of Object.entries(i))if(e[o]==="granted"){s.tcfVendorId&&t.add(s.tcfVendorId);for(let r of s.tcfPurposes??[])n.add(r)}return{vendorConsents:[...t].sort((o,s)=>o-s),purposeConsents:[...n].sort((o,s)=>o-s)}}function Vd(i,e){let{expiryDays:t}=e;if(!t)return!1;let o=new Date(i.createdAt).getTime()+t*24*60*60*1e3;return Date.now()>o}se();p();var $r=!1,hn=null,Fr=!1;async function Wd(){if($r)return hn;$r=!0;try{hn=await import("@iabtechlabtcf/core")}catch{hn=null}return hn}function qd(i,e){let t=new Set,n=new Set;for(let o of i){let s=e.vendors[String(o)];if(s?.legIntPurposes?.length){t.add(o);for(let r of s.legIntPurposes)n.add(r)}}return{vendorLegitimateInterests:[...t].sort((o,s)=>o-s),purposeLegitimateInterests:[...n].sort((o,s)=>o-s)}}async function Hr(i){let e=await Wd();if(!e)return Fr||(Fr=!0,console.warn('[consenti] TCF is enabled but the optional "@iabtechlabtcf/core" dependency is not installed. Falling back to a simplified, non-spec-compliant TC string. Run `npm install @iabtechlabtcf/core` to produce real IAB-spec binary TC strings.')),null;let{TCModel:t,TCString:n,GVL:o}=e,s=new o(i.gvl.raw),r=new t(s);r.cmpId=i.cmpId,r.cmpVersion=i.cmpVersion,r.consentScreen=i.consentScreen,r.consentLanguage=i.consentLanguage,r.publisherCountryCode=i.publisherCC,r.isServiceSpecific=i.isServiceSpecific,r.purposeConsents.set(i.purposeConsents),r.vendorConsents.set(i.vendorConsents);let{vendorLegitimateInterests:a,purposeLegitimateInterests:c}=qd(i.vendorConsents,i.gvl);return r.purposeLegitimateInterests.set(c),r.vendorLegitimateInterests.set(a),r.vendorsDisclosed.set(i.vendorConsents),n.encode(r)}p();var Vr=require("node:crypto");function mt(i){let e=Object.keys(i).sort().map(t=>`${t}=${i[t]??""}`).join("&");return(0,Vr.createHash)("sha256").update(e).digest("hex")}function me(i,e,t){return i?t?t.configHash===mt(e):!1:!0}p();se();var Wr=!1,yn=null,qr=!1;async function Jd(){if(Wr)return yn;Wr=!0;try{yn=await import("@iabgpp/cmpapi")}catch{yn=null}return yn}var Jr=0,zr=1,zd=2;function _n(i){return i?zr:Jr}function bi(i,e){return i?e?zr:zd:Jr}async function Kd(i){let e=await Jd();if(!e)return null;let{GppModel:t}=e,n=new t;return n.setFieldValue("usnat","SharingNotice",_n(i.sharingApplicable)),n.setFieldValue("usnat","SaleOptOutNotice",_n(i.saleApplicable)),n.setFieldValue("usnat","SharingOptOutNotice",_n(i.sharingApplicable)),n.setFieldValue("usnat","TargetedAdvertisingOptOutNotice",_n(i.sharingApplicable)),n.setFieldValue("usnat","SaleOptOut",bi(i.saleApplicable,i.saleOptOut)),n.setFieldValue("usnat","SharingOptOut",bi(i.sharingApplicable,i.sharingOptOut)),n.setFieldValue("usnat","TargetedAdvertisingOptOut",bi(i.sharingApplicable,i.sharingOptOut)),n.setFieldValue("usnat","MspaCoveredTransaction",i.mspaCoveredTransaction?1:2),n.setFieldValue("usnat","MspaOptOutOptionMode",i.mspaOptOutOptionMode),n.setFieldValue("usnat","MspaServiceProviderMode",i.mspaServiceProviderMode),i.gpcDetected!==void 0&&(n.setFieldValue("usnat","GpcSegmentIncluded",!0),n.setFieldValue("usnat","Gpc",i.gpcDetected)),n.encode()}async function Kr(i){let e=await Kd(i);return e||(qr||(qr=!0,console.warn('[consenti] GPP is enabled but the optional "@iabgpp/cmpapi" dependency is not installed. Falling back to a simplified, non-spec-compliant GPP string. Run `npm install @iabgpp/cmpapi` to produce real IAB-spec binary GPP strings.')),Ci(i))}var wn=class{constructor(e,t,n,o,s="default",r,a,c,l,d,u,m,f){this.consents=e;this.visitors=t;this.profiles=n;this.audit=o;this.tenantId=s;this.compliance=r;this.pluginEngine=a;this.eventBus=c;this.tcfConfig=l;this.storage=d;this.dataSigningHash=u;this.gppConfig=m;this.archivedSnapshot=f}consents;visitors;profiles;audit;tenantId;compliance;pluginEngine;eventBus;tcfConfig;storage;dataSigningHash;gppConfig;archivedSnapshot;sign(e){if(this.dataSigningHash)return ue(Pi(e),this.dataSigningHash)}async isTcfConfirmed(){if(!this.tcfConfig?.enabled)return!0;if(!this.storage)return!1;let e=await this.storage.getSettings(this.tenantId);return me(!0,{cmpId:this.tcfConfig.cmpId,cmpVersion:this.tcfConfig.cmpVersion,publisherCC:this.tcfConfig.publisherCC},e.tcfConfirmation)}async isGppConfirmed(){if(!this.gppConfig?.enabled)return!0;if(!this.storage)return!1;let e=await this.storage.getSettings(this.tenantId);return me(!0,{cmpId:this.gppConfig.cmpId,cmpVersion:this.gppConfig.cmpVersion},e.gppConfirmation)}async resolveTemplateData(e){let t=!e.cookies,n=!e.preferenceModal?.categories,o=(t||n)&&e.consentTemplateId&&this.storage?await this.storage.getConsentTemplate(e.consentTemplateId):null;return{cookies:e.cookies??(o?Ai(o.cookies,e.cookiesOverride):{}),categories:e.preferenceModal?.categories??o?.categories??{}}}async create(e){let t=await this.profiles.get(e.profileId);if(!t)throw new Error(`Profile ${e.profileId} not found`);let n=t.profileJson.regulation,{cookies:o,categories:s}=await this.resolveTemplateData(t.profileJson),r=We(s),a=e.consentJson;if(e.gpcDetected&&this.compliance?.gpc!==!1&&n!=="dpdpa"){a={...a};for(let[N,z]of Object.entries(o))n==="cpra"?(z.cpraCategory==="sale"||z.cpraCategory==="sharing")&&(a[N]="denied"):z.listenGpc&&(a[N]="denied")}let c=Gr({...e,consentJson:a},o,r);if(!c.valid)throw new Error(c.errors.join("; "));let l=Ii(o,r,a,e.gpcDetected,n),d,u=this.tcfConfig,m=u?.enabled&&Object.values(o).some(N=>N.tcfVendorId),f=m?await this.isTcfConfirmed():!0;if(u&&m&&!f)console.error(`[Consenti] TCF is enabled (cmpId=${u.cmpId}, cmpVersion=${u.cmpVersion}) but this registration is unconfirmed \u2014 treating TCF as disabled for this consent write (no tcfString generated). Confirm the current cmpId/cmpVersion in the dashboard's TCF Registration panel to re-enable.`);else if(u&&m){let N=await be(),{vendorConsents:z,purposeConsents:re}=Br(o,l),Qe=e.locale?.slice(0,2)??"en";d=u.publisherCC&&N?await Hr({cmpId:u.cmpId,cmpVersion:u.cmpVersion,consentScreen:1,consentLanguage:Qe,publisherCC:u.publisherCC,isServiceSpecific:!0,purposeConsents:re,vendorConsents:z,gvl:N})??void 0:void 0,d||(d=Si({cmpId:u.cmpId,cmpVersion:u.cmpVersion,consentScreen:1,consentLanguage:Qe,vendorListVersion:N?.vendorListVersion??0,purposeConsents:re,vendorConsents:z}))}let S,y=this.gppConfig,E=Object.values(o).some(N=>N.cpraCategory==="sale"),R=Object.values(o).some(N=>N.cpraCategory==="sharing"),v=y?.enabled&&(E||R),A=v?await this.isGppConfirmed():!0;if(y&&v&&!A)console.error(`[Consenti] GPP is enabled (cmpId=${y.cmpId}, cmpVersion=${y.cmpVersion}) but this registration is unconfirmed \u2014 treating GPP as disabled for this consent write (no gppString generated). Confirm the current cmpId/cmpVersion in the dashboard's GPP Registration panel to re-enable.`);else if(y&&v){let N=!E||Object.entries(o).filter(([,re])=>re.cpraCategory==="sale").every(([re])=>l[re]!=="granted"),z=!R||Object.entries(o).filter(([,re])=>re.cpraCategory==="sharing").every(([re])=>l[re]!=="granted");S=await Kr({cmpId:y.cmpId,cmpVersion:y.cmpVersion,mspaCoveredTransaction:y.mspaCoveredTransaction,mspaOptOutOptionMode:y.mspaOptOutOptionMode,mspaServiceProviderMode:y.mspaServiceProviderMode,saleOptOut:N,saleApplicable:E,sharingOptOut:z,sharingApplicable:R,gpcDetected:e.gpcDetected})}let T=this.sign({tenantId:this.tenantId,visitorId:e.visitorId,profileId:e.profileId,locale:e.locale,consentJson:l}),P={...e,tenantId:this.tenantId,consentJson:l,...d?{tcfString:d}:{},...S?{gppString:S}:{},...T?{signature:T}:{}};this.pluginEngine&&(P=await this.pluginEngine.runBeforeConsentSave(P)),P={...P,profileVersion:t.version};let x=await this.consents.get(e.visitorId),L;if(x){let N=await(this.pluginEngine?this.pluginEngine.runBeforeConsentUpdate({consentJson:l,locale:e.locale,gpcDetected:e.gpcDetected,...T?{signature:T}:{}}):Promise.resolve({consentJson:l,locale:e.locale,gpcDetected:e.gpcDetected,...T?{signature:T}:{}}));L=await this.consents.update(e.visitorId,{...N,profileVersion:t.version})}else L=await this.consents.create(P);return await this.audit.log({tenantId:this.tenantId,action:x?"consent:updated":"consent:created",resourceType:"consent",resourceId:L.id,...x!=null?{oldData:x}:{},newData:L}),x?(this.eventBus?.emit("consent:updated",{previous:x,current:L}),await this.pluginEngine?.runAfterConsentUpdate(L)):(this.eventBus?.emit("consent:created",L),await this.pluginEngine?.runAfterConsentSave(L)),L}async update(e,t){let n=await this.consents.get(e);if(!n)throw new Error(`Consent for visitor ${e} not found`);let o=await this.profiles.get(n.profileId);if(!o)throw new Error(`Profile ${n.profileId} not found`);let s=o.profileJson.regulation,{cookies:r,categories:a}=await this.resolveTemplateData(o.profileJson),c=We(a),l=t.gpcDetected??n.gpcDetected,d=t.consentJson;if(l&&this.compliance?.gpc!==!1&&s!=="dpdpa"){d={...d};for(let[E,R]of Object.entries(r))s==="cpra"?(R.cpraCategory==="sale"||R.cpraCategory==="sharing")&&(d[E]="denied"):R.listenGpc&&(d[E]="denied")}let u=Ii(r,c,d,l,s),m=this.sign({tenantId:this.tenantId,visitorId:e,profileId:n.profileId,locale:t.locale??n.locale,consentJson:u}),f={consentJson:u,...t.locale!==void 0?{locale:t.locale}:{},...t.gpcDetected!==void 0?{gpcDetected:t.gpcDetected}:{},...m?{signature:m}:{}},S=await(this.pluginEngine?this.pluginEngine.runBeforeConsentUpdate(f):Promise.resolve(f)),y=await this.consents.update(e,{...S,profileVersion:o.version});return await this.audit.log({tenantId:this.tenantId,action:"consent:updated",resourceType:"consent",resourceId:y.id,oldData:n,newData:y}),this.eventBus?.emit("consent:updated",{previous:n,current:y}),await this.pluginEngine?.runAfterConsentUpdate(y),y}get(e){return this.consents.get(e)}async verify(e){let t=await this.consents.get(e);if(!t)return{valid:!1,reasons:["profile_changed"]};let n=await this.profiles.get(t.profileId),o=n?null:await this.archivedSnapshot?.(t.profileId,t.profileVersion)??null;if(!n&&!o)return{valid:!1,reasons:["profile_changed"]};let s=n?{id:n.id,expiryDays:n.profileJson.expiryDays}:{id:t.profileId,expiryDays:o?.expiryDays},r=n?n.profileJson.complianceGroup:o?.complianceGroup,a=r?await this.profiles.findActiveByComplianceGroup(this.tenantId,r):null;return jr(t,s,a,this.dataSigningHash)}async erase(e){let t=await this.consents.get(e);await this.consents.delete(e),await this.visitors.delete(e),await this.audit.log({tenantId:this.tenantId,action:"consent:erased",resourceType:"consent",resourceId:e,...t!=null?{oldData:t}:{}}),this.eventBus?.emit("consent:erased",{visitorId:e})}};p();var En=class{constructor(e,t="default",n,o=""){this.visitors=e;this.tenantId=t;this.eventBus=n;this.dataSigningHash=o}visitors;tenantId;eventBus;dataSigningHash;async upsert(e){if(await this.visitors.get(e.visitorId))return this.visitors.update(e.visitorId,{...e.country!=null?{country:e.country}:{},...e.region!=null?{region:e.region}:{},...e.city!=null?{city:e.city}:{}});let n={tenantId:this.tenantId,visitorId:e.visitorId,...e.country!=null?{country:e.country}:{},...e.region!=null?{region:e.region}:{},...e.city!=null?{city:e.city}:{},...e.ip?{ipHash:uo(e.ip,this.dataSigningHash)}:{},...e.userAgent?{userAgentHash:po(e.userAgent)}:{}},o=await this.visitors.create(n);return this.eventBus?.emit("visitor:created",o),o}};p();var Rn=class{constructor(e,t="default"){this.notices=e;this.tenantId=t}notices;tenantId;recordShown(e){return this.notices.create({tenantId:this.tenantId,...e})}getForVisitor(e){return this.notices.getForVisitor(e)}};p();var Sn=class{constructor(e,t,n="default"){this.users=e;this.audit=t;this.tenantId=n}users;audit;tenantId;safe(e){let{passwordHash:t,...n}=e;return n}async create(e,t){let n=await this.users.create({tenantId:this.tenantId,name:e.name,email:e.email,passwordHash:it(e.password),...e.allowedTenants?{allowedTenants:e.allowedTenants}:{}});return e.roleId&&await this.users.assignRole(n.id,e.roleId),await this.audit.log({tenantId:this.tenantId,...t!=null?{userId:t}:{},action:"user.created",resourceType:"user",resourceId:n.id,newData:this.safe(n)}),this.safe(n)}async update(e,t,n){let o=await this.users.getById(e);if(!o)throw new Error(`User ${e} not found`);let s={};t.name!=null&&(s.name=t.name),t.email!=null&&(s.email=t.email),t.isActive!=null&&(s.isActive=t.isActive),t.password&&(s.passwordHash=it(t.password)),t.allowedTenants!=null&&(s.allowedTenants=t.allowedTenants);let r=await this.users.update(e,s);return await this.audit.log({tenantId:this.tenantId,...n!=null?{userId:n}:{},action:"user.updated",resourceType:"user",resourceId:e,oldData:this.safe(o),newData:this.safe(r)}),this.safe(r)}async delete(e,t){let n=await this.users.getById(e);await this.users.delete(e),await this.audit.log({tenantId:this.tenantId,...t!=null?{userId:t}:{},action:"user.deleted",resourceType:"user",resourceId:e,...n!=null?{oldData:this.safe(n)}:{}})}async get(e){let t=await this.users.getById(e);return t?this.safe(t):null}async list(){return(await this.users.list(this.tenantId)).map(t=>this.safe(t))}getRoles(e,t){return this.users.getRoles(e,t)}assignRole(e,t,n){return this.users.assignRole(e,t,n)}revokeRole(e,t,n){return this.users.revokeRole(e,t,n)}};p();var Yr=15*6e4,Yd=5,Qr=1800,vn=class{constructor(e,t){this.storage=e;this.secret=t;setInterval(()=>{let n=Date.now();for(let[o,s]of this.loginAttempts)n>=s.resetAt&&this.loginAttempts.delete(o)},Yr).unref()}storage;secret;loginAttempts=new Map;async bootstrap(e,t){if(await this.storage.countUsers("default")>0)return null;if(t.length<12)throw new Error("[Consenti] bootstrap: admin password must be at least 12 characters");t.length<16&&console.warn("[Consenti] bootstrap: admin password is shorter than 16 characters \u2014 consider using a longer password");let o=it(t),s=await this.storage.createUser({tenantId:"default",name:"Admin",email:e,passwordHash:o});return await this.storage.assignRole(s.id,"role_super_admin"),s}async login(e,t){let n=Date.now(),o=this.loginAttempts.get(e);if(o&&n<o.resetAt&&o.count>=Yd)return null;let s=await this.storage.getUserByEmail(e);if(!s||!s.isActive||!mo(t,s.passwordHash)){let l=this.loginAttempts.get(e);return!l||n>=l.resetAt?this.loginAttempts.set(e,{count:1,resetAt:n+Yr}):l.count+=1,null}this.loginAttempts.delete(e);let r=await this.storage.getUserRoles(s.id),a=await Promise.all(r.map(l=>this.storage.getPermissionsForRole(l.id))),c=[...new Set(a.flat().map(l=>l.name))];return Bn({sub:s.id,email:s.email,roles:r.map(l=>l.name),permissions:c,allowedTenants:s.allowedTenants??[]},this.secret,Qr)}signToken(e){return Bn(e,this.secret,Qr)}verify(e){return Pt(e,this.secret)}async getUser(e){let t=this.verify(e);if(!t)return null;let n=t.sub;return typeof n!="string"?null:this.storage.getUserById(n)}};p();p();var gt=class extends Error{constructor(){super("Payload Too Large")}};function Qd(i,e){let t=i.socket?.remoteAddress??"";if(!e?.length||!e.includes(t))return t;let n=i.headers["x-forwarded-for"];return typeof n=="string"?n.split(",")[0]?.trim()??t:Array.isArray(n)?n[0]?.trim()??t:t}function _(i,e){return new Response(JSON.stringify(e),{status:i,headers:{"Content-Type":"application/json"}})}async function b(i){if(!(i.headers.get("content-type")??"").includes("application/json"))return null;try{return await i.json()}catch{return null}}function G(i,e){return i.searchParams.get(e)??void 0}function Cn(i,e,t){let n=i.searchParams.get(e);if(!n)return t;let o=parseInt(n,10);return isNaN(o)?t:o}var Zr=500;function Je(i,e=50){let t=Cn(i,"limit",e);return t<1||t>Zr?{error:`limit must be between 1 and ${Zr}`}:{page:Math.max(1,Cn(i,"page",1)),limit:t}}async function Xr(i,e=1048576,t){let o=i.headers["x-forwarded-proto"]==="https"?"https":"http",s=i.headers.host??"localhost",r=new URL(i.url??"/",`${o}://${s}`),a=new Headers;for(let[d,u]of Object.entries(i.headers))if(u)if(Array.isArray(u))for(let m of u)a.append(d,m);else a.set(d,u);a.set("x-real-ip",Qd(i,t));let c=null,l=(i.method??"GET").toUpperCase();if(l!=="GET"&&l!=="HEAD"){let d=[],u=0;for await(let m of i){if(u+=m.length,u>e)throw new gt;d.push(m)}d.length>0&&(c=Buffer.concat(d))}return new Request(r.toString(),{method:l,headers:a,body:c})}async function ea(i,e){e.statusCode=i.status;let t=typeof i.headers.getSetCookie=="function"?i.headers.getSetCookie():i.headers.get("set-cookie")?[i.headers.get("set-cookie")]:[];i.headers.forEach((n,o)=>{o.toLowerCase()!=="set-cookie"&&e.setHeader(o,n)});for(let n of t)e.appendHeader("set-cookie",n);if(i.body){let n=i.body.getReader();try{for(;;){let{done:o,value:s}=await n.read();if(o)break;e.write(Buffer.from(s))}}finally{n.releaseLock()}e.end()}else e.end()}p();function ta(i){if(typeof i!="string")return;let e=i.trim();return e.length>0&&e.length<=35?e:void 0}function Oi(i){if(!Array.isArray(i))return[];let e=[];for(let t of i){let n=ta(t);if(n&&e.push(n),e.length===20)break}return e}function Di(i){return Oi(i.split(",").map(e=>e.split(";")[0]))}function na(i){return ta(i)??""}p();function g(i,e,t){let n={error:e};return t!=null&&(n.details=t),new Response(JSON.stringify(n),{status:i,headers:{"Content-Type":"application/json"}})}async function w(i){try{return await i()}catch(e){let t=e instanceof Error?e.message:"Internal Server Error";return g(500,"Internal Server Error",process.env.NODE_ENV!=="production"?t:void 0)}}var xe=require("node:fs"),ft=require("node:path"),Zd="public, max-age=3600, stale-while-revalidate=60",ia={"Content-Type":"application/json","Cache-Control":Zd};function Xd(i){let e=(0,xe.readFileSync)(i,"utf8");return new Response(e,{headers:ia})}function eu(i,e,t){return new Response(null,{status:303,headers:{Location:`${i}/profiles/${e}/${t}/default`}})}function oa(i,e,t,n=""){return{"GET /profiles/:tenantId/:complianceGroupOrProfileId/:locale":async(o,s)=>w(async()=>{let{tenantId:r,complianceGroupOrProfileId:a,locale:c}=s;if(!r||!a||!c)return g(400,"Missing path parameters");if(t){let d=(0,ft.join)(t,r,a,`${c}.json`);if((0,xe.existsSync)(d))return Xd(d);let u=(0,ft.join)(t,r,a,"default.json");if((0,xe.existsSync)(u))return eu(n,r,a)}let l=await i.getResolved(a,c);return l?_(200,l):g(404,"Profile not found")}),"GET /profiles/:tenantId/:profileId/:entryId/:locale":async(o,s)=>w(async()=>{let{profileId:r,entryId:a,locale:c}=s;if(!r||!a||!c)return g(400,"Missing path parameters");let l=await i.getVersionFile(r,a,c);return l?new Response(l,{headers:ia}):g(404,"Version not found")}),"GET /resolve-profile":async(o,s)=>w(async()=>{if(!e)return g(501,"Geo compliance routing not configured");let r=new URL(o.url),a=o.headers.get("x-forwarded-for")?.split(",")[0]?.trim()??o.headers.get("x-real-ip")??"",c=r.searchParams.get("tz")??"",l=r.searchParams.get("lang")??o.headers.get("accept-language")??"",d=r.searchParams.get("locale")??"",u=Di(r.searchParams.get("lang")??o.headers.get("accept-language")??""),m=r.searchParams.get("data");if(m)try{let L=JSON.parse(Buffer.from(m,"base64").toString("utf8"));L.timezone&&(c=L.timezone),L.language&&(l=L.language),L.locale&&(d=L.locale);let N=Oi(L.languages);N.length>0&&(u=N)}catch{}let f=await e.resolve({ip:a,language:l,languages:u,timezone:c,locale:na(d)}),S=f.requiresSensitiveOptIn?{requiresSensitiveOptIn:!0}:{};if(!f.complianceGroup)return _(200,{path:null,complianceGroup:"opt-in",locale:d||"en",found:!1,...S});let y=await i.findActiveByComplianceGroup(f.complianceGroup);if(!y)return _(200,{path:null,complianceGroup:f.complianceGroup,locale:d||"en",found:!1,...S});let E=y.profileJson.locales??[],R=y.defaultLocale;if(d&&E.includes(d))R=d;else if(E.length>0){let L=(d||l).split("-")[0]??"",N=E.find(z=>z===L||z.startsWith(`${L}-`));N&&(R=N)}let v=f.complianceGroup,A=y.tenantId,T=!1,P=t?(0,ft.join)(t,A,v,`${R}.json`):"";if(t&&(0,xe.existsSync)(P))T=!0;else if(t){let L=(0,ft.join)(t,A,v,`${y.defaultLocale}.json`);(0,xe.existsSync)(L)&&(R=y.defaultLocale,P=L,T=!0)}let x=T?`${n}/profiles/${A}/${v}/${R}`:null;return _(200,{path:x,complianceGroup:v,locale:R,found:T,...S})}),"GET /profiles/:id":async(o,s)=>w(async()=>{let r=s.id;if(!r)return g(400,"Missing profile id");let a=await i.getResolved(r);return a?_(200,a):g(404,"Profile not found")}),"GET /profiles/:id/:locale":async(o,s)=>w(async()=>{let{id:r,locale:a}=s;if(!r)return g(400,"Missing profile id");let c=await i.getResolved(r,a);return c?_(200,c):g(404,"Profile not found")}),"GET /profiles/auto/:locale":async(o,s)=>w(async()=>{if(!e)return g(501,"Geo compliance routing not configured");let r=s.locale??"en",a=new URL(o.url),c=o.headers.get("x-forwarded-for")?.split(",")[0]?.trim()??o.headers.get("x-real-ip")??"",l=a.searchParams.get("tz")??"",d=o.headers.get("accept-language")??a.searchParams.get("lang")??"",u=await e.resolve({ip:c,language:d,languages:Di(d),timezone:l,locale:r});if(!u.complianceGroup)return g(404,"Could not resolve compliance group for this location");let m=await i.findActiveByComplianceGroup(u.complianceGroup);if(!m)return g(404,`No active profile found for compliance group: ${u.complianceGroup}`);let f=await i.getResolved(m.id,r);return f?_(200,{...f,resolvedComplianceGroup:u.complianceGroup,...u.requiresSensitiveOptIn?{requiresSensitiveOptIn:!0}:{}}):g(404,"Profile not found")})}}p();p();function sa(){return process.env.NODE_ENV==="production"?"SameSite=None; Secure":"SameSite=Lax"}function tu(i,e,t){let n=ue(`${i}.${e}`,t);return`${e}.${n}`}function ki(i,e,t){let n=`consenti_${i}`,o=tu(i,e,t);return`${n}=${o}; ${sa()}; Path=/; Max-Age=31536000`}function ra(i){return`${`consenti_${i}`}=; ${sa()}; Path=/; Max-Age=0`}function aa(i,e,t){let n=i.split(".");if(n.length!==2)return!1;let[o,s]=n;return!o||!s?!1:It(`${e}.${o}`,s,t)}p();var An="pcon_";function nu(i){return Buffer.from(JSON.stringify(i),"utf8").toString("base64url")}function iu(i){try{let e=JSON.parse(Buffer.from(i,"base64url").toString("utf8"));return typeof e.visitorId!="string"||typeof e.profileId!="string"||typeof e.issuedAt!="number"?null:{visitorId:e.visitorId,profileId:e.profileId,issuedAt:e.issuedAt}}catch{return null}}function ca(i,e,t){let n={visitorId:i,profileId:e,issuedAt:Math.round(Date.now()/1e3)},o=nu(n);if(!t)return`${An}${o}`;let s=ue(o,t);return`${An}${o}.${s}`}function la(i,e,t){if(!i.startsWith(An))return{valid:!1,reason:"malformed"};let n=i.slice(An.length),o=n.indexOf("."),s=o===-1?n:n.slice(0,o),r=o===-1?void 0:n.slice(o+1);if(e&&(!r||!It(s,r,e)))return{valid:!1,reason:"invalid_signature"};let a=iu(s);return a?t>0&&Math.round(Date.now()/1e3)-a.issuedAt>t*24*60*60?{valid:!1,reason:"expired"}:{valid:!0,visitorId:a.visitorId,profileId:a.profileId}:{valid:!1,reason:"malformed"}}p();function ou(i){if(!i.includes("://"))return i;try{return new URL(i).hostname}catch{return i}}function da(i,e){let t;try{t=new URL(i).hostname}catch{return!1}return e.some(n=>{if(n.startsWith("*.")){let o=n.slice(1);return t===n.slice(2)||t.endsWith(o)}return t===ou(n)})}function ua(i,e){let t=i??"*";return e&&e.length>0&&i&&(t=da(i,e)?i:"null"),{"Access-Control-Allow-Origin":t,"Access-Control-Allow-Methods":"GET, POST, PUT, DELETE, OPTIONS","Access-Control-Allow-Headers":"Content-Type, Authorization","Access-Control-Max-Age":"86400","Access-Control-Allow-Credentials":"true"}}function pa(i){if(i.method==="OPTIONS"){let e=i.headers.get("origin");return new Response(null,{status:204,headers:ua(e)})}return null}function ht(i,e){let t=e.headers.get("origin"),n=ua(t),o=new Headers(i.headers);for(let[s,r]of Object.entries(n))o.set(s,r);return new Response(i.body,{status:i.status,statusText:i.statusText,headers:o})}function Tn(i,e){if(e.length===0)return!0;let t=i.headers.get("origin");return t?da(t,e):!0}var su=["default-src 'self'","script-src 'self' https://unpkg.com","style-src 'self' https://unpkg.com 'unsafe-inline'","img-src 'self' data:","font-src 'self'","connect-src 'self'","frame-ancestors 'none'","base-uri 'self'","form-action 'self'"].join("; ");function Li(i){let e=new Headers(i.headers);return e.set("X-Content-Type-Options","nosniff"),e.set("X-Frame-Options","DENY"),e.set("Referrer-Policy","no-referrer"),e.set("Permissions-Policy","interest-cohort=()"),e.set("Content-Security-Policy",su),e.set("Strict-Transport-Security","max-age=63072000; includeSubDomains; preload"),new Response(i.body,{status:i.status,statusText:i.statusText,headers:e})}p();var ru=new Set(["granted","denied","objected"]);function ma(i){let e=Object.entries(i);for(let[t,n]of e){if(!t)return{valid:!1,error:"consentJson keys must be non-empty strings"};if(!ru.has(n))return{valid:!1,error:`consentJson value "${String(n)}" is invalid; must be granted, denied, or objected`}}return{valid:!0}}function ga(i){if(!i||typeof i!="object")return{valid:!1,error:"Request body must be a JSON object"};let e=i;return typeof e.profileId!="string"||!e.profileId?{valid:!1,error:"profileId is required"}:!e.consentJson||typeof e.consentJson!="object"||Array.isArray(e.consentJson)?{valid:!1,error:"consentJson must be an object"}:ma(e.consentJson)}function fa(i){if(!i||typeof i!="object")return{valid:!1,error:"Request body must be a JSON object"};let e=i;return!e.consentJson||typeof e.consentJson!="object"||Array.isArray(e.consentJson)?{valid:!1,error:"consentJson must be an object"}:ma(e.consentJson)}function ha(i,e,t){return{tenantId:t,visitorId:e,profileId:i.profileId,locale:typeof i.locale=="string"?i.locale:"en",consentJson:i.consentJson,gpcDetected:!!i.gpcDetected,source:i.source??"banner",...typeof i.ageVerified=="boolean"?{ageVerified:i.ageVerified}:{},...typeof i.parentalConsentToken=="string"?{parentalConsentToken:i.parentalConsentToken}:{}}}function ya(i){let e={consentJson:i.consentJson};return typeof i.locale=="string"&&(e.locale=i.locale),i.gpcDetected!=null&&(e.gpcDetected=!!i.gpcDetected),e}function yt(i,e,t){let n=i.headers.get("cookie")??"",o=`consenti_${e}`;return n.split(";").some(r=>{let a=r.trim(),c=a.indexOf("=");return c===-1||a.slice(0,c)!==o?!1:aa(a.slice(c+1),e,t)})?null:g(403,"Forbidden")}function _a(i,e,t,n=async()=>"default",o,s="",r,a=7){return{"POST /consent":async(c,l)=>w(async()=>{let d=await b(c),u=ga(d);if(!u.valid)return g(400,u.error??"Invalid request");let m=d,f=typeof m.profileId=="string"?m.profileId:null;if(!f)return g(400,"profileId is required");let S=await t.get(f);if(!S)return g(404,"Profile not found");let y=await n(c),R=S.profileJson.allowedOrigins??[];if(R.length===0&&o&&(R=(await o.getSettings(y)).allowedOrigins??[]),!Tn(c,R))return g(403,"Origin not allowed for this profile");let v=typeof m.visitorId=="string"?m.visitorId:q(),A=c.headers.get("x-real-ip")??"",T=c.headers.get("user-agent")??"";await e.upsert({visitorId:v,ip:A,userAgent:T});let P=ha(m,v,y),x=await i.create(P),L=ki(v,x.id,s);return new Response(JSON.stringify(x),{status:201,headers:{"Content-Type":"application/json","Set-Cookie":L}})}),"PUT /consent/:visitorId":async(c,l)=>w(async()=>{let d=l.visitorId;if(!d)return g(400,"Missing visitorId");let u=yt(c,d,s);if(u)return u;let m=await b(c),f=fa(m);if(!f.valid)return g(400,f.error??"Invalid request");let S=ya(m),y=await i.update(d,S),E=ki(d,y.id,s);return new Response(JSON.stringify(y),{status:200,headers:{"Content-Type":"application/json","Set-Cookie":E}})}),"GET /consent/:visitorId":async(c,l)=>w(async()=>{let d=l.visitorId;if(!d)return g(400,"Missing visitorId");let u=yt(c,d,s);if(u)return u;let m=await i.get(d);return m?new Response(JSON.stringify(m),{status:200,headers:{"Content-Type":"application/json"}}):g(404,"Consent not found")}),"GET /consent/:visitorId/verify":async(c,l)=>w(async()=>{let d=l.visitorId;if(!d)return g(400,"Missing visitorId");let u=yt(c,d,s);if(u)return u;let m=await i.verify(d);return new Response(JSON.stringify(m),{status:200,headers:{"Content-Type":"application/json"}})}),"DELETE /consent/:visitorId":async(c,l)=>w(async()=>{let d=l.visitorId;if(!d)return g(400,"Missing visitorId");let u=yt(c,d,s);if(u)return u;let m=await i.get(d);await i.erase(d);let f={"Content-Type":"application/json"};return m&&(f["Set-Cookie"]=ra(d)),new Response(JSON.stringify({success:!0}),{status:200,headers:f})}),"POST /consent/:visitorId/parental-consent-request":async(c,l)=>w(async()=>{let d=l.visitorId;if(!d)return g(400,"Missing visitorId");let u=yt(c,d,s);if(u)return u;let m=await b(c),f=typeof m.profileId=="string"?m.profileId:null;if(!f)return g(400,"profileId is required");if(!await t.get(f))return g(404,"Profile not found");let S=ca(d,f,s),y=Math.round(Date.now()/1e3);return r?.emit("consent.parentalConsentRequired",{visitorId:d,profileId:f,token:S,issuedAt:y}),_(200,{token:S})}),"POST /consent/parental-consent-resolve":async c=>w(async()=>{let l=await b(c),d=typeof l.token=="string"?l.token:null;if(!d)return g(400,"token is required");let u=la(d,s,a);return u.valid?(r?.emit("consent.parentalConsentGranted",{visitorId:u.visitorId,profileId:u.profileId}),_(200,{visitorId:u.visitorId,profileId:u.profileId})):g(403,`Invalid or expired token (${u.reason})`)})}}p();var au=!1;function wa(i){return{"POST /notice-shown":async(e,t)=>w(async()=>{if(!au)return g(404,"Not found");let n=await b(e);if(!n||typeof n!="object")return g(400,"Request body must be a JSON object");let o=n,s=typeof o.visitorId=="string"?o.visitorId:"",r=typeof o.profileId=="string"?o.profileId:"",a=typeof o.locale=="string"?o.locale:"";if(!s)return g(400,"visitorId is required");if(!r)return g(400,"profileId is required");if(!a)return g(400,"locale is required");let c=await i.recordShown({visitorId:s,profileId:r,locale:a});return new Response(JSON.stringify({success:!0,id:c.id}),{status:201,headers:{"Content-Type":"application/json"}})})}}p();function Ea(i,e){return{"GET /tcf/status":async(t,n)=>w(async()=>{if(!e?.enabled)return _(200,{blocked:!1});let o=await i.getSettings("default"),s=me(!0,{cmpId:e.cmpId,cmpVersion:e.cmpVersion,publisherCC:e.publisherCC},o.tcfConfirmation);return _(200,{blocked:!s})})}}p();function Ra(i,e){return{"GET /gpp/status":async(t,n)=>w(async()=>{if(!e?.enabled)return _(200,{blocked:!1});let o=await i.getSettings("default"),s=me(!0,{cmpId:e.cmpId,cmpVersion:e.cmpVersion},o.gppConfirmation);return _(200,{blocked:!s})})}}p();var Ui=require("node:crypto");p();var Sa=require("node:crypto");async function O(i,e,t,n){let o=i.headers.get("authorization"),s=o?.startsWith("Bearer ")?o.slice(7):null;if(!s)return null;if(s.startsWith("ck_")){let r=(0,Sa.createHash)("sha256").update(s).digest("hex"),a=await e.getApiKeyByHash(r);if(!a||!a.isActive)return null;if(a.expireBy&&new Date(a.expireBy)<=new Date)return await e.revokeApiKey(a.id).catch(()=>{}),null;let c=(await e.getAllPermissions()).map(l=>l.name);return{sub:`apikey:${a.id}`,email:a.name,roles:["api_key"],permissions:c,allowedTenants:[a.tenantId]}}if(t.mode==="local"||t.mode==="jwt"){let r=Pt(s,n);if(!r)return null;let a=r.sub,c=r.email,l=r.roles,d=r.permissions,u=r.allowedTenants;return typeof a!="string"||typeof c!="string"?null:{sub:a,email:c,roles:Array.isArray(l)?l:[],permissions:Array.isArray(d)?d:[],allowedTenants:Array.isArray(u)?u:[]}}if(t.mode==="custom"&&t.validateUser){let r=await t.validateUser(i);if(!r)return null;let a=await e.getUserRoles(r.id),c=await Promise.all(a.map(d=>e.getPermissionsForRole(d.id))),l=[...new Set(c.flat().map(d=>d.name))];return{sub:r.id,email:r.email,roles:a.map(d=>d.name),permissions:l,allowedTenants:[]}}return null}function k(i,e){return i?e&&!i.permissions.includes(e)?g(403,"Forbidden"):null:g(401,"Unauthorized")}p();var In=require("node:crypto");function va(i){return i.toString("base64").replace(/\+/g,"-").replace(/\//g,"_").replace(/=/g,"")}function Ca(i){return Buffer.from(i.replace(/-/g,"+").replace(/_/g,"/"),"base64").toString("utf8")}function Aa(){let i=va((0,In.randomBytes)(32)),e=va((0,In.createHash)("sha256").update(i).digest());return{verifier:i,challenge:e}}async function Ni(i){let e=await fetch(`${i}/.well-known/openid-configuration`,{signal:AbortSignal.timeout(1e4)});if(!e.ok)throw new Error(`OIDC discovery failed for ${i}: ${e.status}`);return e.json()}function Ta(i,e,t,n,o){let s=new URLSearchParams({response_type:"code",client_id:i.clientId,redirect_uri:i.redirectUri,scope:"openid email profile",state:t,nonce:n,code_challenge:o,code_challenge_method:"S256"});return`${e}?${s.toString()}`}async function Ia(i,e,t,n){let o=new URLSearchParams({grant_type:"authorization_code",client_id:i.clientId,client_secret:i.clientSecret,redirect_uri:i.redirectUri,code:t,code_verifier:n}),s=await fetch(e,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:o.toString(),signal:AbortSignal.timeout(1e4)});if(!s.ok){let r=await s.text();throw new Error(`OIDC token exchange failed: ${r}`)}return s.json()}async function Pa(i,e){let t=i.split(".");if(t.length!==3)throw new Error("Invalid ID token format");let n=JSON.parse(Ca(t[0])),o=n.alg??"RS256",s=await fetch(e,{signal:AbortSignal.timeout(1e4)});if(!s.ok)throw new Error(`Failed to fetch JWKS: ${s.status}`);let r=await s.json(),a=n.kid?r.keys.find(R=>R.kid===n.kid):r.keys.find(R=>R.use==="sig")??r.keys[0];if(!a)throw new Error("No matching key in JWKS");let c;if(o==="RS256"||o==="RS384"||o==="RS512"){let R=o==="RS256"?"SHA-256":o==="RS384"?"SHA-384":"SHA-512";c=await globalThis.crypto.subtle.importKey("jwk",a,{name:"RSASSA-PKCS1-v1_5",hash:{name:R}},!1,["verify"])}else if(o==="ES256"||o==="ES384"||o==="ES512"){let R=o==="ES256"?"P-256":o==="ES384"?"P-384":"P-521";c=await globalThis.crypto.subtle.importKey("jwk",a,{name:"ECDSA",namedCurve:R},!1,["verify"])}else throw new Error(`Unsupported OIDC token algorithm: ${o}`);let l=new TextEncoder().encode(`${t[0]}.${t[1]}`),d=(4-t[2].length%4)%4,u=t[2].replace(/-/g,"+").replace(/_/g,"/")+"=".repeat(d),m=Uint8Array.from(atob(u),R=>R.charCodeAt(0)),f=o.startsWith("ES")?{name:"ECDSA",hash:{name:`SHA-${o.slice(2)}`}}:{name:"RSASSA-PKCS1-v1_5"};if(!await globalThis.crypto.subtle.verify(f,c,m,l))throw new Error("ID token signature verification failed");let y=JSON.parse(Ca(t[1])),E=Math.floor(Date.now()/1e3);if(typeof y.exp=="number"&&y.exp<E)throw new Error("ID token has expired");return y}function ba(i,e){let t=e?.email??"email",n=i[t];if(typeof n!="string")throw new Error("OIDC token missing email claim");return n}function Oa(i,e){let t=e?.roles??"consenti_roles",n=i[t];return Array.isArray(n)?n.filter(o=>typeof o=="string"):[]}var _t=new Map;setInterval(()=>{let i=Date.now();for(let[e,t]of _t)t.expiresAt<i&&_t.delete(e)},5*6e4).unref();function Da(i,e,t){_t.set(i,{verifier:e,nonce:t,expiresAt:Date.now()+10*6e4})}function ka(i){let e=_t.get(i);return _t.delete(i),!e||e.expiresAt<Date.now()?null:{verifier:e.verifier,nonce:e.nonce}}p();function cu(i){return i.replace(/&/g,"&amp;").replace(/"/g,"&quot;").replace(/</g,"&lt;").replace(/>/g,"&gt;")}function La(i){return`<?xml version="1.0" encoding="UTF-8"?>
138
140
  <EntityDescriptor xmlns="urn:oasis:names:tc:SAML:2.0:metadata"
139
141
  entityID="saml:sp:consenti">
140
142
  <SPSSODescriptor
@@ -144,19 +146,19 @@ ${l.map(d=>` (${se(c)},${se(d)})`).join(`,
144
146
  <NameIDFormat>urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress</NameIDFormat>
145
147
  <AssertionConsumerService
146
148
  Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"
147
- Location="${Od(i.callbackUrl)}"
149
+ Location="${cu(i.callbackUrl)}"
148
150
  index="0"
149
151
  isDefault="true"/>
150
152
  </SPSSODescriptor>
151
- </EntityDescriptor>`}async function aa(i,e){let t;try{t=await import("samlify")}catch{return console.warn("[Consenti] samlify is not installed. Install it to use SAML auth mode."),null}try{let n=t.ServiceProvider({entityID:"saml:sp:consenti",assertionConsumerService:[{Binding:"urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST",Location:e.callbackUrl}]}),o=t.IdentityProvider({entityID:e.issuer,singleSignOnService:[{Binding:"urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect",Location:e.entryPoint}],signingCert:e.cert}),s=await n.parseLoginResponse(o,"post",{body:{SAMLResponse:i}}),r=s.extract.nameID,a=s.extract.attributes.roles,c=Array.isArray(a)?a.filter(l=>typeof l=="string"):[];return{email:r,roles:c}}catch(n){return console.warn("[Consenti] SAML response validation failed:",n),null}}p();var He=require("node:crypto"),_i="ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";function Dd(i){let e="",t=0,n=0;for(let o of i)for(n=n<<8|o,t+=8;t>=5;)e+=_i[n>>>t-5&31],t-=5;return t>0&&(e+=_i[n<<5-t&31]),e}function kd(i){let e=i.toUpperCase().replace(/[^A-Z2-7]/g,""),t=[],n=0,o=0;for(let s of e){let r=_i.indexOf(s);r<0||(o=o<<5|r,n+=5,n>=8&&(t.push(o>>>n-8&255),n-=8))}return Buffer.from(t)}function Ld(i,e){let t=Buffer.alloc(8),n=e;for(let a=7;a>=0;a--)t[a]=n&255,n=Math.floor(n/256);let o=(0,He.createHmac)("sha1",i).update(t).digest(),s=o[o.length-1]&15,r=(o[s]&127)<<24|(o[s+1]&255)<<16|(o[s+2]&255)<<8|o[s+3]&255;return String(r%1e6).padStart(6,"0")}function ca(){return Dd((0,He.randomBytes)(20))}var En=new Map;setInterval(()=>{let i=Date.now();for(let[e,t]of En)i>=t&&En.delete(e)},9e4).unref();function la(i,e,t=1){if(En.has(e))return!1;let n=Math.floor(Date.now()/3e4),o=kd(i),s=Buffer.from(e);for(let r=-t;r<=t;r++){let a=Buffer.from(Ld(o,n+r));if(a.length===s.length&&(0,He.timingSafeEqual)(a,s))return En.set(e,Date.now()+9e4),!0}return!1}function da(i,e,t="Consenti"){let n=encodeURIComponent(`${t}:${e}`),o=new URLSearchParams({secret:i,issuer:t,algorithm:"SHA1",digits:"6",period:"30"});return`otpauth://totp/${n}?${o.toString()}`}function ua(i){return i.toString("base64").replace(/\+/g,"-").replace(/\//g,"_").replace(/=/g,"")}function pa(i,e,t,n,o){function s(r){if(!o)return null;let a=r.headers.get("x-real-ip")??"";return o.checkRequest(a)?null:g(429,"Too Many Requests")}return{"POST /auth/login":async(r,a)=>E(async()=>{let c=s(r);if(c)return c;if(t.mode!=="local")return g(400,"Login not available in this auth mode");let l=await P(r);if(!l||typeof l!="object")return g(400,"Invalid body");let d=l;if(typeof d.email!="string"||typeof d.password!="string")return g(400,"email and password are required");let u=await i.login(d.email,d.password);return u?y(200,{token:u}):g(401,"Invalid credentials")}),"GET /auth/me":async(r,a)=>E(async()=>{let c=await b(r,e,t,n);if(!c)return g(401,"Unauthorized");let l=await e.getUserById(c.sub);if(!l)return g(401,"User not found");let d=await e.getUserRoles(l.id);return y(200,{id:l.id,email:l.email,name:l.name,isActive:l.isActive,totpEnabled:l.totpEnabled??!1,roles:d.map(u=>u.name),permissions:c.permissions})}),"POST /auth/logout":async(r,a)=>E(async()=>y(200,{success:!0})),"POST /auth/refresh":async(r,a)=>E(async()=>{let c=await b(r,e,t,n);if(!c)return g(401,"Unauthorized");let l=i.signToken({sub:c.sub,email:c.email,roles:c.roles,permissions:c.permissions,allowedTenants:c.allowedTenants});return y(200,{token:l})}),"GET /auth/oidc/authorize":async(r,a)=>E(async()=>{if(t.mode!=="oidc"||!t.oidc)return g(400,"OIDC not configured");let c=await yi(t.oidc.issuer),l=ua((0,wi.randomBytes)(16)),d=ua((0,wi.randomBytes)(16)),{verifier:u,challenge:m}=Zr();oa(l,u,d);let h=Xr(t.oidc,c.authorization_endpoint,l,d,m);return new Response(null,{status:302,headers:{Location:h}})}),"GET /auth/oidc/callback":async(r,a)=>E(async()=>{if(t.mode!=="oidc"||!t.oidc)return g(400,"OIDC not configured");let c=new URL(r.url),l=c.searchParams.get("code"),d=c.searchParams.get("state");if(!l||!d)return g(400,"Missing code or state");let u=sa(d);if(!u)return g(400,"Invalid or expired state");let m=await yi(t.oidc.issuer),h=await ea(t.oidc,m.token_endpoint,l,u.verifier),S=await ta(h.id_token,m.jwks_uri),_=na(S,t.oidc.claimsMapping),w=ia(S,t.oidc.claimsMapping),R=await e.getUserByEmail(_);if(R||(R=await e.createUser({tenantId:"default",name:_,email:_,passwordHash:""})),w.length>0){let O=await e.getRoles("default");for(let D of w){let G=O.find(N=>N.name===D);G&&await e.assignRole(R.id,G.id).catch(()=>{})}}let C=await e.getUserRoles(R.id),A=[];for(let O of C){let D=await e.getPermissionsForRole(O.id);A.push(...D.map(G=>G.name))}let T=i.signToken({sub:R.id,email:R.email,roles:C.map(O=>O.name),permissions:[...new Set(A)]});return y(200,{token:T})}),"GET /auth/saml/metadata":async(r,a)=>E(async()=>{if(t.mode!=="saml"||!t.saml)return g(400,"SAML not configured");let c=ra(t.saml);return new Response(c,{status:200,headers:{"Content-Type":"application/xml"}})}),"POST /auth/saml/acs":async(r,a)=>E(async()=>{let c=s(r);if(c)return c;if(t.mode!=="saml"||!t.saml)return g(400,"SAML not configured");let d=new URLSearchParams(await r.text()).get("SAMLResponse");if(typeof d!="string")return g(400,"Missing SAMLResponse");let u=await aa(d,t.saml);if(!u)return g(401,"SAML validation failed");let m=await e.getUserByEmail(u.email);m||(m=await e.createUser({tenantId:"default",name:u.email,email:u.email,passwordHash:""}));let h=await e.getUserRoles(m.id),S=[];for(let w of h){let R=await e.getPermissionsForRole(w.id);S.push(...R.map(C=>C.name))}let _=i.signToken({sub:m.id,email:m.email,roles:h.map(w=>w.name),permissions:[...new Set(S)]});return y(200,{token:_})}),"POST /auth/totp/setup":async(r,a)=>E(async()=>{let c=await b(r,e,t,n);if(!c)return g(401,"Unauthorized");let l=await e.getUserById(c.sub);if(!l)return g(401,"User not found");let d=ca(),u=da(d,l.email);return await e.updateUser(l.id,{totpSecret:d,totpEnabled:!1}),y(200,{qrUrl:u,message:"Scan QR code, then verify with POST /auth/totp/verify"})}),"POST /auth/totp/verify":async(r,a)=>E(async()=>{let c=s(r);if(c)return c;let l=await b(r,e,t,n);if(!l)return g(401,"Unauthorized");let d=await e.getUserById(l.sub);if(!d)return g(401,"User not found");if(!d.totpSecret)return g(400,"TOTP not set up \u2014 call POST /auth/totp/setup first");let u=await P(r);if(!u||typeof u!="object")return g(400,"Invalid body");let m=u;return typeof m.token!="string"?g(400,"token is required"):la(d.totpSecret,m.token)?(await e.updateUser(d.id,{totpEnabled:!0}),y(200,{success:!0,message:"TOTP enabled successfully"})):g(400,"Invalid TOTP token")}),"POST /auth/totp/disable":async(r,a)=>E(async()=>{let c=await b(r,e,t,n);if(!c)return g(401,"Unauthorized");let l=await e.getUserById(c.sub);return l?(await e.updateUser(l.id,{totpSecret:null,totpEnabled:!1}),y(200,{success:!0,message:"TOTP disabled"})):g(401,"User not found")})}}p();ae();p();function ma(i){if(!i||typeof i!="object")return{valid:!1,error:"Request body must be a JSON object"};let e=i;if(typeof e.name!="string"||!e.name)return{valid:!1,error:"name is required"};if(typeof e.defaultLocale!="string"||!e.defaultLocale)return{valid:!1,error:"defaultLocale is required"};if(!e.profileJson||typeof e.profileJson!="object")return{valid:!1,error:"profileJson is required"};let t=e.profileJson;return typeof t.consentTemplateId!="string"||!t.consentTemplateId?{valid:!1,error:"profileJson.consentTemplateId is required"}:typeof t.uiTemplateId!="string"||!t.uiTemplateId?{valid:!1,error:"profileJson.uiTemplateId is required"}:{valid:!0}}function ga(i){return!i||typeof i!="object"?{valid:!1,error:"Request body must be a JSON object"}:{valid:!0}}function fa(i,e){return{tenantId:e,name:i.name,defaultLocale:i.defaultLocale,profileJson:i.profileJson,...i.localeContent!=null?{localeContent:i.localeContent}:{}}}function ha(i){let e={};return typeof i.name=="string"&&(e.name=i.name),typeof i.defaultLocale=="string"&&(e.defaultLocale=i.defaultLocale),i.profileJson!=null&&(e.profileJson=i.profileJson),i.localeContent!=null&&(e.localeContent=i.localeContent),e}p();ae();function Ve(i,e,t){let n=ii[t];if(!n)return{valid:!0,errors:[],warnings:[]};let o=[],s=[],r=Be(e);for(let[a,c]of Object.entries(e)){let l=c;for(let d of n.categoryErrors)d.check(l,void 0)&&o.push({cookieId:a,field:d.field,message:d.message(a),rule:d.rule});for(let d of n.categoryWarnings)d.check(l,void 0)&&s.push({cookieId:a,field:d.field,message:d.message(a),suggestion:d.suggestion})}for(let[a,c]of Object.entries(i)){let l=c,d=Fe(a,r);for(let u of n.cookieErrors)u.check(l,d)&&o.push({cookieId:a,field:u.field,message:u.message(a),rule:u.rule});for(let u of n.cookieWarnings)u.check(l,d)&&s.push({cookieId:a,field:u.field,message:u.message(a),suggestion:u.suggestion})}return{valid:o.length===0,errors:o,warnings:s}}p();ae();function ya(i,e,t){let n=[];on(t.htmlText)||n.push({locale:i,section:e,field:"htmlText",message:"Body text is required"});for(let[o,s]of Object.entries(t.buttons))s.text?.trim()||n.push({locale:i,section:e,field:`buttons.${o}`,message:`Label for button "${o}" is required`});return n}function Nd(i,e){let t=[];e.heading?.trim()||t.push({locale:i,section:"preferenceModal",field:"heading",message:"Heading is required"}),on(e.htmlText)||t.push({locale:i,section:"preferenceModal",field:"htmlText",message:"Intro text is required"});for(let[n,o]of Object.entries(e.buttons))o.text?.trim()||t.push({locale:i,section:"preferenceModal",field:`buttons.${n}`,message:`Label for button "${n}" is required`});for(let[n,o]of Object.entries(e.categories))o.heading?.trim()||t.push({locale:i,section:"preferenceModal",field:`categories.${n}.heading`,message:`Heading for category "${n}" is required`});return t}function Ei(i){let e=[];for(let[t,n]of Object.entries(i))e.push(...ya(t,"mainBanner",n.mainBanner)),n.gpcBanner&&e.push(...ya(t,"gpcBanner",n.gpcBanner)),e.push(...Nd(t,n.preferenceModal));return{valid:e.length===0,errors:e}}function _a(i,e){let t={...e};return i?.defaultLocale&&i.mainBanner&&i.preferenceModal&&(t[i.defaultLocale]={mainBanner:i.mainBanner,...i.gpcBanner?{gpcBanner:i.gpcBanner}:{},preferenceModal:i.preferenceModal}),t}function wa(i,e,t,n){async function o(r,a){let c=await b(r,e,t,n);return{user:c,denied:k(c,a)}}function s(r,a){return r?r.allowedTenants.length===0||r.allowedTenants.includes(a):!1}return{"GET /profiles":async(r,a)=>E(async()=>{let{user:c,denied:l}=await o(r,"profile:view");return l||(s(c,"default")?new URL(r.url).searchParams.get("summary")==="1"?y(200,await i.listSummary()):y(200,await i.list()):y(200,[]))}),"GET /profiles/archived":async(r,a)=>E(async()=>{let{denied:c}=await o(r,"profile:view");return c||y(200,await i.listArchivedProfiles())}),"GET /profiles/:id":async(r,a)=>E(async()=>{let{denied:c}=await o(r,"profile:view");if(c)return c;let l=await i.get(a.id??"");return l?y(200,l):g(404,"Profile not found")}),"POST /profiles/validate":async(r,a)=>E(async()=>{let{denied:c}=await o(r,"profile:view");if(c)return c;let l=await P(r);return!l.complianceGroup||!l.cookies||typeof l.cookies!="object"||!l.categories||typeof l.categories!="object"?g(400,"complianceGroup, cookies, and categories are required"):y(200,Ve(l.cookies,l.categories,l.complianceGroup))}),"GET /compliance-coverage":async(r,a)=>E(async()=>{let{denied:c}=await o(r,"profile:view");if(c)return c;let l={};for(let[d,u]of Object.entries(ot)){let m=await i.findActiveByComplianceGroup(d);l[d]={label:u.label,compliances:u.compliances,activeProfile:m?{id:m.id,name:m.name}:null}}return y(200,{groups:l})}),"POST /profiles":async(r,a)=>E(async()=>{let{denied:c}=await o(r,"profile:create");if(c)return c;let l=await P(r),d=ma(l);if(!d.valid)return g(400,d.error??"Invalid body");let u=fa(l,"default"),m=Ei(_a(u.profileJson,u.localeContent));if(!m.valid)return g(422,"Profile content is missing required fields",{errors:m.errors});let h=u.profileJson.complianceGroup,S=u.profileJson.customComplianceGroup,_=typeof l.choice=="string"?l.choice:void 0;if(h){let R=u.profileJson.cookies??{},C=u.profileJson.preferenceModal?.categories??{},A=Ve(R,C,h);if(!A.valid)return g(422,"Profile does not meet compliance requirements",{errors:A.errors,warnings:A.warnings});let T=await i.findActiveByComplianceGroup(h);if(T){if(!_)return y(200,{conflict:{id:T.id,name:T.name},requiresChoice:!0});_==="deactivate"?(await i.deactivate(T.id),u.profileJson.isActive=!0):_==="inactive"&&(u.profileJson.isActive=!1)}let O=await i.create(u);return y(201,{profile:O,warnings:A.warnings})}if(S){let R=await i.findActiveByComplianceGroup(S);if(R){if(!_)return y(200,{conflict:{id:R.id,name:R.name},requiresChoice:!0});_==="deactivate"?(await i.deactivate(R.id),u.profileJson.isActive=!0):_==="inactive"&&(u.profileJson.isActive=!1)}}let w=await i.create(u);return y(201,w)}),"PUT /profiles/:id":async(r,a)=>E(async()=>{let{denied:c}=await o(r,"profile:update");if(c)return c;let l=a.id??"",d=await P(r),u=ga(d);if(!u.valid)return g(400,u.error??"Invalid body");let m=ha(d),h=_a(m.profileJson,m.localeContent);if(Object.keys(h).length>0){let C=Ei(h);if(!C.valid)return g(422,"Profile content is missing required fields",{errors:C.errors})}let S=m.profileJson?.complianceGroup,_=m.profileJson?.customComplianceGroup,w=typeof d.choice=="string"?d.choice:void 0;if(S){let C=m.profileJson?.cookies??{},A=m.profileJson?.preferenceModal?.categories??{},T=Ve(C,A,S);if(!T.valid)return g(422,"Profile does not meet compliance requirements",{errors:T.errors,warnings:T.warnings});let O=await i.findActiveByComplianceGroup(S);if(O&&O.id!==l){if(!w)return y(200,{conflict:{id:O.id,name:O.name},requiresChoice:!0});w==="deactivate"?(await i.deactivate(O.id),m.profileJson.isActive=!0):w==="inactive"&&(m.profileJson.isActive=!1)}let D=await i.update(l,m);return y(200,{profile:D,warnings:T.warnings})}if(_){let C=await i.findActiveByComplianceGroup(_);if(C&&C.id!==l){if(!w)return y(200,{conflict:{id:C.id,name:C.name},requiresChoice:!0});w==="deactivate"?(await i.deactivate(C.id),m.profileJson.isActive=!0):w==="inactive"&&(m.profileJson.isActive=!1)}}let R=await i.update(l,m);return y(200,R)}),"DELETE /profiles/:id":async(r,a)=>E(async()=>{let{denied:c}=await o(r,"profile:delete");return c||(await i.delete(a.id??""),y(200,{success:!0}))}),"POST /profiles/:id/copy":async(r,a)=>E(async()=>{let{denied:c}=await o(r,"profile:create");if(c)return c;let l=a.id??"";if(!await i.get(l))return g(404,"Profile not found");let u=await P(r),m=typeof u?.name=="string"?u.name:void 0,h=await i.copy(l,m);return y(201,h)}),"POST /profiles/:id/activate":async(r,a)=>E(async()=>{let{denied:c}=await o(r,"profile:update");if(c)return c;let l=a.id??"",d=await P(r),u=typeof d?.choice=="string"?d.choice:void 0,m=await i.get(l);if(!m)return g(404,"Profile not found");let h=m.profileJson,S=h.complianceGroup||h.customComplianceGroup;if(S){let w=await i.findActiveByComplianceGroup(S);if(w&&w.id!==l){if(!u)return y(200,{conflict:{id:w.id,name:w.name},requiresChoice:!0});u==="deactivate"&&await i.deactivate(w.id)}}let _=await i.activate(l);return y(200,_)}),"POST /profiles/:id/deactivate":async(r,a)=>E(async()=>{let{denied:c}=await o(r,"profile:update");if(c)return c;let l=await i.deactivate(a.id??"");return y(200,l)}),"GET /profiles/:id/versions":async(r,a)=>E(async()=>{let{denied:c}=await o(r,"profile:view");return c||y(200,await i.listVersions(a.id??""))}),"GET /profiles/:id/versions/:entryId":async(r,a)=>E(async()=>{let{denied:c}=await o(r,"profile:view");if(c)return c;let d=new URL(r.url).searchParams.get("locale")??"default",u=a.entryId??"";if(!u)return g(400,"Invalid version id");let m=await i.getVersionFile(a.id??"",u,d);return m?new Response(m,{headers:{"Content-Type":"application/json"}}):g(404,"Version file not found")})}}p();function Ea(i,e,t){async function n(o,s){let r=await b(o,i,e,t);return{user:r,denied:k(r,s)}}return{"GET /consents":async(o,s)=>E(async()=>{let{user:r,denied:a}=await n(o,"consent:view");if(a)return a;if(r?.allowedTenants.length&&!r.allowedTenants.includes("default"))return y(200,{items:[],total:0,page:1,limit:50});let c=new URL(o.url),l=M(c,"profileId"),d=M(c,"from"),u=M(c,"to"),m=M(c,"q"),h=$e(c);if("error"in h)return g(400,h.error);let{page:S,limit:_}=h,w={tenantId:"default",page:S,limit:_,...l!==void 0?{profileId:l}:{},...d!==void 0?{from:d}:{},...u!==void 0?{to:u}:{},...m!==void 0?{q:m}:{}},R=await i.getConsents(w);return y(200,R)}),"GET /consents/:visitorId":async(o,s)=>E(async()=>{let{user:r,denied:a}=await n(o,"consent:view");if(a)return a;if(r?.allowedTenants.length&&!r.allowedTenants.includes("default"))return g(403,"Forbidden");let c=await i.getConsent(s.visitorId??"");return c?y(200,c):g(404,"Consent not found")}),"GET /consents/:visitorId/history":async(o,s)=>E(async()=>{let{user:r,denied:a}=await n(o,"consent:view");if(a)return a;if(r?.allowedTenants.length&&!r.allowedTenants.includes("default"))return g(403,"Forbidden");let c=await i.getConsentHistory(s.visitorId??"");return y(200,c)})}}p();var Ud=!1;function Ra(i,e,t){async function n(o,s){let r=await b(o,i,e,t);return{user:r,denied:k(r,s)}}return{"GET /visitors":async(o,s)=>E(async()=>{let{user:r,denied:a}=await n(o,"visitor:view");if(a)return a;if(r?.allowedTenants.length&&!r.allowedTenants.includes("default"))return y(200,{items:[],total:0,page:1,limit:50});let c=new URL(o.url),l=M(c,"from"),d=M(c,"to"),u=M(c,"q"),m=$e(c);if("error"in m)return g(400,m.error);let{page:h,limit:S}=m,_={tenantId:"default",page:h,limit:S,...l!==void 0?{from:l}:{},...d!==void 0?{to:d}:{},...u!==void 0?{q:u}:{}},w=await i.getVisitors(_);return y(200,w)}),"GET /visitors/:visitorId/notice-shown":async(o,s)=>E(async()=>{if(!Ud)return g(404,"Not found");let{denied:r}=await n(o,"visitor:view");if(r)return r;let a=await i.getNoticeShownForVisitor(s.visitorId??"");return y(200,a)})}}p();var Sa="role_super_admin";function Ca(i,e,t,n){async function o(r,a){let c=await b(r,e,t,n);return{user:c,denied:k(c,a)}}async function s(r){return(await i.getRoles(r)).some(c=>c.id===Sa)}return{"GET /users":async(r,a)=>E(async()=>{let{denied:c}=await o(r,"user:view");if(c)return c;let l=await i.list(),d=await Promise.all(l.map(async u=>({...u,roles:(await i.getRoles(u.id)).map(m=>({id:m.id,name:m.name}))})));return y(200,d)}),"GET /users/:id":async(r,a)=>E(async()=>{let{denied:c}=await o(r,"user:view");if(c)return c;let l=await i.get(a.id??"");if(!l)return g(404,"User not found");let d=await i.getRoles(l.id);return y(200,{...l,roles:d.map(u=>({id:u.id,name:u.name}))})}),"POST /users":async(r,a)=>E(async()=>{let{user:c,denied:l}=await o(r,"user:create");if(l)return l;let d=await P(r);if(!d||typeof d!="object")return g(400,"Invalid body");let u=d;if(typeof u.name!="string"||!u.name)return g(400,"name is required");if(typeof u.email!="string"||!u.email)return g(400,"email is required");if(typeof u.password!="string"||!u.password)return g(400,"password is required");if(u.password.length<12)return g(400,"password must be at least 12 characters");let m=await i.create({name:u.name,email:u.email,password:u.password,...typeof u.roleId=="string"?{roleId:u.roleId}:{},...Array.isArray(u.allowedTenants)?{allowedTenants:u.allowedTenants}:{}},c.sub);return y(201,m)}),"PUT /users/:id":async(r,a)=>E(async()=>{let{user:c,denied:l}=await o(r,"user:update");if(l)return l;let d=a.id??"";if(d!==c.sub&&await s(d))return g(403,"Super admin users cannot be modified");let u=await P(r);if(!u||typeof u!="object")return g(400,"Invalid body");let m=u;if(typeof m.password=="string"&&m.password.length<12)return g(400,"password must be at least 12 characters");let h=await i.update(d,{...typeof m.name=="string"?{name:m.name}:{},...typeof m.email=="string"?{email:m.email}:{},...m.isActive!=null?{isActive:!!m.isActive}:{},...typeof m.password=="string"?{password:m.password}:{},...Array.isArray(m.allowedTenants)?{allowedTenants:m.allowedTenants}:{}},c.sub);return y(200,h)}),"DELETE /users/:id":async(r,a)=>E(async()=>{let{user:c,denied:l}=await o(r,"user:delete");if(l)return l;let d=a.id??"";return d===c.sub?g(400,"Cannot delete your own account"):await s(d)?g(403,"Super admin users cannot be deleted"):(await i.delete(d,c.sub),y(200,{success:!0}))}),"POST /users/:id/roles":async(r,a)=>E(async()=>{let{user:c,denied:l}=await o(r,"role:update");if(l)return l;let d=await P(r);if(!d||typeof d!="object")return g(400,"Invalid body");let u=d;if(typeof u.roleId!="string")return g(400,"roleId is required");let m=typeof u.tenantId=="string"?u.tenantId:void 0;return await i.assignRole(a.id??"",u.roleId,m),await e.createLog({tenantId:"default",userId:c.sub,action:"user.role_assigned",resourceType:"user",...a.id!=null?{resourceId:a.id}:{},newData:{roleId:u.roleId}}),y(200,{success:!0})}),"DELETE /users/:id/roles/:roleId":async(r,a)=>E(async()=>{let{user:c,denied:l}=await o(r,"role:update");if(l)return l;if(a.roleId===Sa)return g(403,"The super_admin role cannot be revoked");let u=new URL(r.url).searchParams.get("tenantId")??void 0;return await i.revokeRole(a.id??"",a.roleId??"",u),await e.createLog({tenantId:"default",userId:c.sub,action:"user.role_revoked",resourceType:"user",...a.id!=null?{resourceId:a.id}:{},oldData:{roleId:a.roleId}}),y(200,{success:!0})})}}p();var Rn="role_super_admin";function va(i,e,t){async function n(o,s){let r=await b(o,i,e,t);return{user:r,denied:k(r,s)}}return{"GET /roles":async(o,s)=>E(async()=>{let{denied:r}=await n(o,"role:view");if(r)return r;let a=await i.getRoles("default");return y(200,a)}),"GET /roles/:id/permissions":async(o,s)=>E(async()=>{let{denied:r}=await n(o,"role:view");if(r)return r;let a=await i.getPermissionsForRole(s.id??"");return y(200,a)}),"POST /roles":async(o,s)=>E(async()=>{let{user:r,denied:a}=await n(o,"role:create");if(a)return a;let c=await P(o);if(!c||typeof c!="object")return g(400,"Invalid body");let l=c;if(typeof l.name!="string"||!l.name)return g(400,"name is required");let d=await i.createRole({tenantId:"default",name:l.name,...typeof l.description=="string"?{description:l.description}:{}});return await i.createLog({tenantId:"default",userId:r.sub,action:"role.created",resourceType:"role",resourceId:d.id,newData:d}),y(201,d)}),"PUT /roles/:id":async(o,s)=>E(async()=>{let{user:r,denied:a}=await n(o,"role:update");if(a)return a;if(s.id===Rn)return g(403,"The super_admin role cannot be modified");let c=await P(o);if(!c||typeof c!="object")return g(400,"Invalid body");let l=c,d=await i.updateRole(s.id??"",{...typeof l.name=="string"?{name:l.name}:{},...typeof l.description=="string"?{description:l.description}:{}});return await i.createLog({tenantId:"default",userId:r.sub,action:"role.updated",resourceType:"role",resourceId:d.id,newData:d}),y(200,d)}),"DELETE /roles/:id":async(o,s)=>E(async()=>{let{user:r,denied:a}=await n(o,"role:delete");return a||(s.id===Rn?g(403,"The super_admin role cannot be deleted"):(await i.deleteRole(s.id??""),await i.createLog({tenantId:"default",userId:r.sub,action:"role.deleted",resourceType:"role",...s.id!=null?{resourceId:s.id}:{}}),y(200,{success:!0})))}),"GET /permissions":async(o,s)=>E(async()=>{let{denied:r}=await n(o,"role:view");if(r)return r;let a=await i.getAllPermissions();return y(200,a)}),"POST /roles/:id/permissions":async(o,s)=>E(async()=>{let{denied:r}=await n(o,"role:update");if(r)return r;if(s.id===Rn)return g(403,"The super_admin role cannot be modified");let a=await P(o);if(!a||typeof a!="object")return g(400,"Invalid body");let c=a;return typeof c.permissionId!="string"?g(400,"permissionId is required"):(await i.assignPermissionToRole(s.id??"",c.permissionId),y(200,{success:!0}))}),"DELETE /roles/:id/permissions/:permissionId":async(o,s)=>E(async()=>{let{denied:r}=await n(o,"role:update");return r||(s.id===Rn?g(403,"The super_admin role cannot be modified"):(await i.revokePermissionFromRole(s.id??"",s.permissionId??""),y(200,{success:!0})))})}}p();function Aa(i,e,t){async function n(o,s){let r=await b(o,i,e,t);return{user:r,denied:k(r,s)}}return{"GET /audit":async(o,s)=>E(async()=>{let{user:r,denied:a}=await n(o,"audit:view");if(a)return a;if(r?.allowedTenants.length&&!r.allowedTenants.includes("default"))return y(200,{items:[],total:0,page:1,limit:50});let c=new URL(o.url),l=M(c,"action"),d=M(c,"resourceType"),u=M(c,"from"),m=M(c,"to"),h=M(c,"q"),S=$e(c);if("error"in S)return g(400,S.error);let{page:_,limit:w}=S,R={tenantId:"default",page:_,limit:w,...l!==void 0?{action:l}:{},...d!==void 0?{resourceType:d}:{},...u!==void 0?{from:u}:{},...m!==void 0?{to:m}:{},...h!==void 0?{q:h}:{}},C=await i.getLogs(R);return y(200,C)}),"GET /audit/:id":async(o,s)=>E(async()=>{let{user:r,denied:a}=await n(o,"audit:view");if(a)return a;if(r?.allowedTenants.length&&!r.allowedTenants.includes("default"))return g(403,"Forbidden");let c=await i.getAuditLogById(s.id??"");return!c||c.tenantId!=="default"?g(404,"Audit log entry not found"):y(200,c)})}}p();function Ta(i,e,t,n){async function o(s){let r=await b(s,i,t,n);return{denied:k(r,"consent:view")}}return{"GET /stats/overview":async(s,r)=>E(async()=>{let{denied:a}=await o(s);if(a)return a;let c=await e.getOverview("default");return y(200,c)}),"GET /stats/categories":async(s,r)=>E(async()=>{let{denied:a}=await o(s);if(a)return a;let c=await e.getCategories("default");return y(200,c)}),"GET /stats/timeline":async(s,r)=>E(async()=>{let{denied:a}=await o(s);if(a)return a;let c=new URL(s.url),l=hn(c,"days",30),d=await e.getTimeline("default",l);return y(200,d)}),"GET /stats/countries":async(s,r)=>E(async()=>{let{denied:a}=await o(s);if(a)return a;let c=await e.getCountries("default");return y(200,c)}),"GET /stats/gpc":async(s,r)=>E(async()=>{let{denied:a}=await o(s);if(a)return a;let c=await e.getGpc("default");return y(200,c)}),"GET /stats/aggregate":async(s,r)=>E(async()=>{let{denied:a}=await o(s);if(a)return a;let c=await e.getTenants(),l=await Promise.all(c.map(async u=>{let m=await e.getOverview(u.id);return{tenantId:u.id,tenantName:u.name,...m}})),d=l.reduce((u,m)=>({totalConsents:u.totalConsents+m.totalConsents,totalVisitors:u.totalVisitors+m.totalVisitors,gpcDetectedCount:u.gpcDetectedCount+m.gpcDetectedCount}),{totalConsents:0,totalVisitors:0,gpcDetectedCount:0});return y(200,{aggregate:d,perTenant:l})})}}p();function Ri(i){let e=i==null?"":String(i);return e.includes(",")||e.includes('"')||e.includes(`
152
- `)?`"${e.replace(/"/g,'""')}"`:e}function xd(i){return[i.id,i.visitorId,i.profileId,i.locale,JSON.stringify(i.consentJson),i.gpcDetected?"1":"0",i.source,i.signature??"",i.createdAt,i.updatedAt].map(Ri).join(",")+`
153
- `}function Md(i){return[i.id,i.userId??"",i.action,i.resourceType,i.resourceId??"",i.createdAt].map(Ri).join(",")+`
154
- `}function Ia(i,e,t,n){async function o(s){let r=await b(s,i,e,t);return{denied:k(r,"export:run")}}return{"GET /export/consents":async(s,r)=>E(async()=>{let{denied:a}=await o(s);if(a)return a;let c=new URL(s.url),l=M(c,"format")??"csv",d=M(c,"profileId"),u=M(c,"from"),m=M(c,"to"),h={tenantId:"default",...d!==void 0?{profileId:d}:{},...u!==void 0?{from:u}:{},...m!==void 0?{to:m}:{}};if(l==="json"){let R=[];for await(let C of i.streamConsents(h))R.push(C);return new Response(JSON.stringify(R),{status:200,headers:{"Content-Type":"application/json","Content-Disposition":'attachment; filename="consents.json"'}})}let S=new TextEncoder,_=`id,visitor_id,profile_id,locale,consent_json,gpc_detected,source,signature,created_at,updated_at
155
- `,w=new ReadableStream({async start(R){R.enqueue(S.encode(_));for await(let C of i.streamConsents(h))R.enqueue(S.encode(xd(C)));R.close()}});return new Response(w,{status:200,headers:{"Content-Type":"text/csv; charset=utf-8","Content-Disposition":'attachment; filename="consents.csv"'}})}),"GET /export/consents/xlsx":async(s,r)=>E(async()=>{let{denied:a}=await o(s);if(a)return a;let c=null;try{c=await import("xlsx")}catch{return new Response(JSON.stringify({error:"xlsx peer dependency not installed. Run: npm install xlsx"}),{status:501,headers:{"Content-Type":"application/json"}})}if(!c)return new Response(null,{status:501});let l=new URL(s.url),d=l.searchParams.get("profileId")??void 0,u=l.searchParams.get("from")??void 0,m=l.searchParams.get("to")??void 0,h={tenantId:"default",...d!==void 0?{profileId:d}:{},...u!==void 0?{from:u}:{},...m!==void 0?{to:m}:{}},S=[];for await(let C of i.streamConsents(h))S.push({id:C.id,visitor_id:C.visitorId,profile_id:C.profileId,locale:C.locale,consent_json:JSON.stringify(C.consentJson),gpc_detected:C.gpcDetected?1:0,age_verified:C.ageVerified?1:0,tcf_string:C.tcfString??"",signature:C.signature??"",source:C.source,created_at:C.createdAt,updated_at:C.updatedAt});let _=c.utils.book_new(),w=c.utils.json_to_sheet(S);c.utils.book_append_sheet(_,w,"Consents");let R=c.write(_,{type:"buffer",bookType:"xlsx"});return new Response(R,{status:200,headers:{"Content-Type":"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet","Content-Disposition":'attachment; filename="consents.xlsx"'}})}),"GET /export/translations/:profileId":async(s,r)=>E(async()=>{let{denied:a}=await o(s);if(a)return a;let c=r.profileId??"",l=await i.getProfile(c);if(!l)return g(404,"Profile not found");let d=l.profileJson,u=d.locales?.length?d.locales:[l.defaultLocale],m={};for(let S of u){if(S===l.defaultLocale){m[S]={mainBanner:d.mainBanner,...d.gpcBanner?{gpcBanner:d.gpcBanner}:{},preferenceModal:d.preferenceModal};continue}let _=await n.getVersionFile(c,String(l.version),S);if(_)try{let w=JSON.parse(_);m[S]={mainBanner:w.mainBanner,...w.gpcBanner?{gpcBanner:w.gpcBanner}:{},preferenceModal:w.preferenceModal}}catch{}}if(Object.keys(m).length===0)return new Response(`locale,field,value
156
- `,{status:200,headers:{"Content-Type":"text/csv; charset=utf-8","Content-Disposition":`attachment; filename="${c}-translations.csv"`}});let h=["locale,section,field,value"];for(let[S,_]of Object.entries(m))for(let[w,R]of Object.entries(_))if(typeof R=="object"&&R!==null)for(let[C,A]of Object.entries(R))typeof A=="string"&&h.push([S,w,C,A].map(Ri).join(","));return new Response(h.join(`
153
+ </EntityDescriptor>`}async function Na(i,e){let t;try{t=await import("samlify")}catch{return console.warn("[Consenti] samlify is not installed. Install it to use SAML auth mode."),null}try{let n=t.ServiceProvider({entityID:"saml:sp:consenti",assertionConsumerService:[{Binding:"urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST",Location:e.callbackUrl}]}),o=t.IdentityProvider({entityID:e.issuer,singleSignOnService:[{Binding:"urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect",Location:e.entryPoint}],signingCert:e.cert}),s=await n.parseLoginResponse(o,"post",{body:{SAMLResponse:i}}),r=s.extract.nameID,a=s.extract.attributes.roles,c=Array.isArray(a)?a.filter(l=>typeof l=="string"):[];return{email:r,roles:c}}catch(n){return console.warn("[Consenti] SAML response validation failed:",n),null}}p();var ze=require("node:crypto"),xi="ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";function lu(i){let e="",t=0,n=0;for(let o of i)for(n=n<<8|o,t+=8;t>=5;)e+=xi[n>>>t-5&31],t-=5;return t>0&&(e+=xi[n<<5-t&31]),e}function du(i){let e=i.toUpperCase().replace(/[^A-Z2-7]/g,""),t=[],n=0,o=0;for(let s of e){let r=xi.indexOf(s);r<0||(o=o<<5|r,n+=5,n>=8&&(t.push(o>>>n-8&255),n-=8))}return Buffer.from(t)}function uu(i,e){let t=Buffer.alloc(8),n=e;for(let a=7;a>=0;a--)t[a]=n&255,n=Math.floor(n/256);let o=(0,ze.createHmac)("sha1",i).update(t).digest(),s=o[o.length-1]&15,r=(o[s]&127)<<24|(o[s+1]&255)<<16|(o[s+2]&255)<<8|o[s+3]&255;return String(r%1e6).padStart(6,"0")}function xa(){return lu((0,ze.randomBytes)(20))}var Pn=new Map;setInterval(()=>{let i=Date.now();for(let[e,t]of Pn)i>=t&&Pn.delete(e)},9e4).unref();function Ua(i,e,t=1){if(Pn.has(e))return!1;let n=Math.floor(Date.now()/3e4),o=du(i),s=Buffer.from(e);for(let r=-t;r<=t;r++){let a=Buffer.from(uu(o,n+r));if(a.length===s.length&&(0,ze.timingSafeEqual)(a,s))return Pn.set(e,Date.now()+9e4),!0}return!1}function Ma(i,e,t="Consenti"){let n=encodeURIComponent(`${t}:${e}`),o=new URLSearchParams({secret:i,issuer:t,algorithm:"SHA1",digits:"6",period:"30"});return`otpauth://totp/${n}?${o.toString()}`}function Ga(i){return i.toString("base64").replace(/\+/g,"-").replace(/\//g,"_").replace(/=/g,"")}function ja(i,e,t,n,o){function s(r){if(!o)return null;let a=r.headers.get("x-real-ip")??"";return o.checkRequest(a)?null:g(429,"Too Many Requests")}return{"POST /auth/login":async(r,a)=>w(async()=>{let c=s(r);if(c)return c;if(t.mode!=="local")return g(400,"Login not available in this auth mode");let l=await b(r);if(!l||typeof l!="object")return g(400,"Invalid body");let d=l;if(typeof d.email!="string"||typeof d.password!="string")return g(400,"email and password are required");let u=await i.login(d.email,d.password);return u?_(200,{token:u}):g(401,"Invalid credentials")}),"GET /auth/me":async(r,a)=>w(async()=>{let c=await O(r,e,t,n);if(!c)return g(401,"Unauthorized");let l=await e.getUserById(c.sub);if(!l)return g(401,"User not found");let d=await e.getUserRoles(l.id);return _(200,{id:l.id,email:l.email,name:l.name,isActive:l.isActive,totpEnabled:l.totpEnabled??!1,roles:d.map(u=>u.name),permissions:c.permissions})}),"POST /auth/logout":async(r,a)=>w(async()=>_(200,{success:!0})),"POST /auth/refresh":async(r,a)=>w(async()=>{let c=await O(r,e,t,n);if(!c)return g(401,"Unauthorized");let l=i.signToken({sub:c.sub,email:c.email,roles:c.roles,permissions:c.permissions,allowedTenants:c.allowedTenants});return _(200,{token:l})}),"GET /auth/oidc/authorize":async(r,a)=>w(async()=>{if(t.mode!=="oidc"||!t.oidc)return g(400,"OIDC not configured");let c=await Ni(t.oidc.issuer),l=Ga((0,Ui.randomBytes)(16)),d=Ga((0,Ui.randomBytes)(16)),{verifier:u,challenge:m}=Aa();Da(l,u,d);let f=Ta(t.oidc,c.authorization_endpoint,l,d,m);return new Response(null,{status:302,headers:{Location:f}})}),"GET /auth/oidc/callback":async(r,a)=>w(async()=>{if(t.mode!=="oidc"||!t.oidc)return g(400,"OIDC not configured");let c=new URL(r.url),l=c.searchParams.get("code"),d=c.searchParams.get("state");if(!l||!d)return g(400,"Missing code or state");let u=ka(d);if(!u)return g(400,"Invalid or expired state");let m=await Ni(t.oidc.issuer),f=await Ia(t.oidc,m.token_endpoint,l,u.verifier),S=await Pa(f.id_token,m.jwks_uri),y=ba(S,t.oidc.claimsMapping),E=Oa(S,t.oidc.claimsMapping),R=await e.getUserByEmail(y);if(R||(R=await e.createUser({tenantId:"default",name:y,email:y,passwordHash:""})),E.length>0){let P=await e.getRoles("default");for(let x of E){let L=P.find(N=>N.name===x);L&&await e.assignRole(R.id,L.id).catch(()=>{})}}let v=await e.getUserRoles(R.id),A=[];for(let P of v){let x=await e.getPermissionsForRole(P.id);A.push(...x.map(L=>L.name))}let T=i.signToken({sub:R.id,email:R.email,roles:v.map(P=>P.name),permissions:[...new Set(A)]});return _(200,{token:T})}),"GET /auth/saml/metadata":async(r,a)=>w(async()=>{if(t.mode!=="saml"||!t.saml)return g(400,"SAML not configured");let c=La(t.saml);return new Response(c,{status:200,headers:{"Content-Type":"application/xml"}})}),"POST /auth/saml/acs":async(r,a)=>w(async()=>{let c=s(r);if(c)return c;if(t.mode!=="saml"||!t.saml)return g(400,"SAML not configured");let d=new URLSearchParams(await r.text()).get("SAMLResponse");if(typeof d!="string")return g(400,"Missing SAMLResponse");let u=await Na(d,t.saml);if(!u)return g(401,"SAML validation failed");let m=await e.getUserByEmail(u.email);m||(m=await e.createUser({tenantId:"default",name:u.email,email:u.email,passwordHash:""}));let f=await e.getUserRoles(m.id),S=[];for(let E of f){let R=await e.getPermissionsForRole(E.id);S.push(...R.map(v=>v.name))}let y=i.signToken({sub:m.id,email:m.email,roles:f.map(E=>E.name),permissions:[...new Set(S)]});return _(200,{token:y})}),"POST /auth/totp/setup":async(r,a)=>w(async()=>{let c=await O(r,e,t,n);if(!c)return g(401,"Unauthorized");let l=await e.getUserById(c.sub);if(!l)return g(401,"User not found");let d=xa(),u=Ma(d,l.email);return await e.updateUser(l.id,{totpSecret:d,totpEnabled:!1}),_(200,{qrUrl:u,message:"Scan QR code, then verify with POST /auth/totp/verify"})}),"POST /auth/totp/verify":async(r,a)=>w(async()=>{let c=s(r);if(c)return c;let l=await O(r,e,t,n);if(!l)return g(401,"Unauthorized");let d=await e.getUserById(l.sub);if(!d)return g(401,"User not found");if(!d.totpSecret)return g(400,"TOTP not set up \u2014 call POST /auth/totp/setup first");let u=await b(r);if(!u||typeof u!="object")return g(400,"Invalid body");let m=u;return typeof m.token!="string"?g(400,"token is required"):Ua(d.totpSecret,m.token)?(await e.updateUser(d.id,{totpEnabled:!0}),_(200,{success:!0,message:"TOTP enabled successfully"})):g(400,"Invalid TOTP token")}),"POST /auth/totp/disable":async(r,a)=>w(async()=>{let c=await O(r,e,t,n);if(!c)return g(401,"Unauthorized");let l=await e.getUserById(c.sub);return l?(await e.updateUser(l.id,{totpSecret:null,totpEnabled:!1}),_(200,{success:!0,message:"TOTP disabled"})):g(401,"User not found")})}}p();se();p();function Ba(i){let e=i.profileJson&&typeof i.profileJson=="object"?i.profileJson:{},t=i.localeContent&&typeof i.localeContent=="object"?Object.keys(i.localeContent):[];return Qt({defaultLocale:i.defaultLocale,complianceGroup:e.complianceGroup,customComplianceGroup:e.customComplianceGroup,locales:e.locales,localeContentKeys:t})}function $a(i){if(!i||typeof i!="object")return{valid:!1,error:"Request body must be a JSON object"};let e=i;if(typeof e.name!="string"||!e.name)return{valid:!1,error:"name is required"};if(typeof e.defaultLocale!="string"||!e.defaultLocale)return{valid:!1,error:"defaultLocale is required"};if(!e.profileJson||typeof e.profileJson!="object")return{valid:!1,error:"profileJson is required"};let t=e.profileJson;if(typeof t.consentTemplateId!="string"||!t.consentTemplateId)return{valid:!1,error:"profileJson.consentTemplateId is required"};if(typeof t.uiTemplateId!="string"||!t.uiTemplateId)return{valid:!1,error:"profileJson.uiTemplateId is required"};let n=Ba(e);return n?{valid:!1,error:n}:{valid:!0}}function Fa(i){if(!i||typeof i!="object")return{valid:!1,error:"Request body must be a JSON object"};let e=Ba(i);return e?{valid:!1,error:e}:{valid:!0}}function Ha(i,e){return{tenantId:e,name:i.name,defaultLocale:i.defaultLocale,profileJson:i.profileJson,...i.localeContent!=null?{localeContent:i.localeContent}:{}}}function Va(i){let e={};return typeof i.name=="string"&&(e.name=i.name),typeof i.defaultLocale=="string"&&(e.defaultLocale=i.defaultLocale),i.profileJson!=null&&(e.profileJson=i.profileJson),i.localeContent!=null&&(e.localeContent=i.localeContent),e}p();se();function Ke(i,e,t){let n=yi[t];if(!n)return{valid:!0,errors:[],warnings:[]};let o=[],s=[],r=We(e);for(let[a,c]of Object.entries(e)){let l=c;for(let d of n.categoryErrors)d.check(l,void 0)&&o.push({cookieId:a,field:d.field,message:d.message(a),rule:d.rule});for(let d of n.categoryWarnings)d.check(l,void 0)&&s.push({cookieId:a,field:d.field,message:d.message(a),suggestion:d.suggestion})}for(let[a,c]of Object.entries(i)){let l=c,d=qe(a,r);for(let u of n.cookieErrors)u.check(l,d)&&o.push({cookieId:a,field:u.field,message:u.message(a),rule:u.rule});for(let u of n.cookieWarnings)u.check(l,d)&&s.push({cookieId:a,field:u.field,message:u.message(a),suggestion:u.suggestion})}return{valid:o.length===0,errors:o,warnings:s}}p();se();function Wa(i,e,t){let n=[];pn(t.htmlText)||n.push({locale:i,section:e,field:"htmlText",message:"Body text is required"});for(let[o,s]of Object.entries(t.buttons))s.text?.trim()||n.push({locale:i,section:e,field:`buttons.${o}`,message:`Label for button "${o}" is required`});return n}function pu(i,e){let t=[];e.heading?.trim()||t.push({locale:i,section:"preferenceModal",field:"heading",message:"Heading is required"}),pn(e.htmlText)||t.push({locale:i,section:"preferenceModal",field:"htmlText",message:"Intro text is required"});for(let[n,o]of Object.entries(e.buttons))o.text?.trim()||t.push({locale:i,section:"preferenceModal",field:`buttons.${n}`,message:`Label for button "${n}" is required`});for(let[n,o]of Object.entries(e.categories))o.heading?.trim()||t.push({locale:i,section:"preferenceModal",field:`categories.${n}.heading`,message:`Heading for category "${n}" is required`});return t}function Mi(i){let e=[];for(let[t,n]of Object.entries(i))e.push(...Wa(t,"mainBanner",n.mainBanner)),n.gpcBanner&&e.push(...Wa(t,"gpcBanner",n.gpcBanner)),e.push(...pu(t,n.preferenceModal));return{valid:e.length===0,errors:e}}function qa(i,e){let t={...e};return i?.defaultLocale&&i.mainBanner&&i.preferenceModal&&(t[i.defaultLocale]={mainBanner:i.mainBanner,...i.gpcBanner?{gpcBanner:i.gpcBanner}:{},preferenceModal:i.preferenceModal}),t}function Ja(i,e,t,n){async function o(r,a){let c=await O(r,e,t,n);return{user:c,denied:k(c,a)}}function s(r,a){return r?r.allowedTenants.length===0||r.allowedTenants.includes(a):!1}return{"GET /profiles":async(r,a)=>w(async()=>{let{user:c,denied:l}=await o(r,"profile:view");return l||(s(c,"default")?new URL(r.url).searchParams.get("summary")==="1"?_(200,await i.listSummary()):_(200,await i.list()):_(200,[]))}),"GET /profiles/archived":async(r,a)=>w(async()=>{let{denied:c}=await o(r,"profile:view");return c||_(200,await i.listArchivedProfiles())}),"GET /profiles/:id":async(r,a)=>w(async()=>{let{denied:c}=await o(r,"profile:view");if(c)return c;let l=await i.get(a.id??"");return l?_(200,l):g(404,"Profile not found")}),"POST /profiles/validate":async(r,a)=>w(async()=>{let{denied:c}=await o(r,"profile:view");if(c)return c;let l=await b(r);return!l.complianceGroup||!l.cookies||typeof l.cookies!="object"||!l.categories||typeof l.categories!="object"?g(400,"complianceGroup, cookies, and categories are required"):_(200,Ke(l.cookies,l.categories,l.complianceGroup))}),"GET /compliance-coverage":async(r,a)=>w(async()=>{let{denied:c}=await o(r,"profile:view");if(c)return c;let l={};for(let[d,u]of Object.entries(dt)){let m=await i.findActiveByComplianceGroup(d);l[d]={label:u.label,compliances:u.compliances,activeProfile:m?{id:m.id,name:m.name}:null}}return _(200,{groups:l})}),"POST /profiles":async(r,a)=>w(async()=>{let{user:c,denied:l}=await o(r,"profile:create");if(l)return l;let d=await b(r),u=$a(d);if(!u.valid)return g(400,u.error??"Invalid body");let m=Ha(d,"default"),f=Mi(qa(m.profileJson,m.localeContent));if(!f.valid)return g(422,"Profile content is missing required fields",{errors:f.errors});let S=m.profileJson.complianceGroup,y=m.profileJson.customComplianceGroup,E=typeof d.choice=="string"?d.choice:void 0;if(S){let v=m.profileJson.cookies??{},A=m.profileJson.preferenceModal?.categories??{},T=Ke(v,A,S);if(!T.valid)return g(422,"Profile does not meet compliance requirements",{errors:T.errors,warnings:T.warnings});let P=await i.findActiveByComplianceGroup(S);if(P){if(!E)return _(200,{conflict:{id:P.id,name:P.name},requiresChoice:!0});E==="deactivate"?(await i.deactivate(P.id,c?.sub),m.profileJson.isActive=!0):E==="inactive"&&(m.profileJson.isActive=!1)}let x=await i.create(m,c?.sub);return _(201,{profile:x,warnings:T.warnings})}if(y){let v=await i.findActiveByComplianceGroup(y);if(v){if(!E)return _(200,{conflict:{id:v.id,name:v.name},requiresChoice:!0});E==="deactivate"?(await i.deactivate(v.id,c?.sub),m.profileJson.isActive=!0):E==="inactive"&&(m.profileJson.isActive=!1)}}let R=await i.create(m,c?.sub);return _(201,R)}),"PUT /profiles/:id":async(r,a)=>w(async()=>{let{user:c,denied:l}=await o(r,"profile:update");if(l)return l;let d=a.id??"",u=await b(r),m=Fa(u);if(!m.valid)return g(400,m.error??"Invalid body");let f=Va(u),S=qa(f.profileJson,f.localeContent);if(Object.keys(S).length>0){let A=Mi(S);if(!A.valid)return g(422,"Profile content is missing required fields",{errors:A.errors})}let y=f.profileJson?.complianceGroup,E=f.profileJson?.customComplianceGroup,R=typeof u.choice=="string"?u.choice:void 0;if(y){let A=f.profileJson?.cookies??{},T=f.profileJson?.preferenceModal?.categories??{},P=Ke(A,T,y);if(!P.valid)return g(422,"Profile does not meet compliance requirements",{errors:P.errors,warnings:P.warnings});let x=await i.findActiveByComplianceGroup(y);if(x&&x.id!==d){if(!R)return _(200,{conflict:{id:x.id,name:x.name},requiresChoice:!0});R==="deactivate"?(await i.deactivate(x.id,c?.sub),f.profileJson.isActive=!0):R==="inactive"&&(f.profileJson.isActive=!1)}let L=await i.update(d,f,c?.sub);return _(200,{profile:L,warnings:P.warnings})}if(E){let A=await i.findActiveByComplianceGroup(E);if(A&&A.id!==d){if(!R)return _(200,{conflict:{id:A.id,name:A.name},requiresChoice:!0});R==="deactivate"?(await i.deactivate(A.id,c?.sub),f.profileJson.isActive=!0):R==="inactive"&&(f.profileJson.isActive=!1)}}let v=await i.update(d,f,c?.sub);return _(200,v)}),"DELETE /profiles/:id":async(r,a)=>w(async()=>{let{user:c,denied:l}=await o(r,"profile:delete");return l||(await i.delete(a.id??"",c?.sub),_(200,{success:!0}))}),"POST /profiles/:id/copy":async(r,a)=>w(async()=>{let{user:c,denied:l}=await o(r,"profile:create");if(l)return l;let d=a.id??"";if(!await i.get(d))return g(404,"Profile not found");let m=await b(r),f=typeof m?.name=="string"?m.name:void 0,S=await i.copy(d,f,c?.sub);return _(201,S)}),"POST /profiles/:id/activate":async(r,a)=>w(async()=>{let{user:c,denied:l}=await o(r,"profile:update");if(l)return l;let d=a.id??"",u=await b(r),m=typeof u?.choice=="string"?u.choice:void 0,f=await i.get(d);if(!f)return g(404,"Profile not found");let S=f.profileJson,y=S.complianceGroup||S.customComplianceGroup;if(y){let R=await i.findActiveByComplianceGroup(y);if(R&&R.id!==d){if(!m)return _(200,{conflict:{id:R.id,name:R.name},requiresChoice:!0});m==="deactivate"&&await i.deactivate(R.id,c?.sub)}}let E=await i.activate(d,c?.sub);return _(200,E)}),"POST /profiles/:id/deactivate":async(r,a)=>w(async()=>{let{user:c,denied:l}=await o(r,"profile:update");if(l)return l;let d=await i.deactivate(a.id??"",c?.sub);return _(200,d)}),"GET /profiles/:id/versions":async(r,a)=>w(async()=>{let{denied:c}=await o(r,"profile:view");return c||_(200,await i.listVersions(a.id??""))}),"GET /profiles/:id/versions/:entryId":async(r,a)=>w(async()=>{let{denied:c}=await o(r,"profile:view");if(c)return c;let d=new URL(r.url).searchParams.get("locale")??"default",u=a.entryId??"";if(!u)return g(400,"Invalid version id");let m=await i.getVersionFile(a.id??"",u,d);return m?new Response(m,{headers:{"Content-Type":"application/json"}}):g(404,"Version file not found")})}}p();function za(i,e,t){async function n(o,s){let r=await O(o,i,e,t);return{user:r,denied:k(r,s)}}return{"GET /consents":async(o,s)=>w(async()=>{let{user:r,denied:a}=await n(o,"consent:view");if(a)return a;if(r?.allowedTenants.length&&!r.allowedTenants.includes("default"))return _(200,{items:[],total:0,page:1,limit:50});let c=new URL(o.url),l=G(c,"profileId"),d=G(c,"from"),u=G(c,"to"),m=G(c,"q"),f=Je(c);if("error"in f)return g(400,f.error);let{page:S,limit:y}=f,E={tenantId:"default",page:S,limit:y,...l!==void 0?{profileId:l}:{},...d!==void 0?{from:d}:{},...u!==void 0?{to:u}:{},...m!==void 0?{q:m}:{}},R=await i.getConsents(E);return _(200,R)}),"GET /consents/:visitorId":async(o,s)=>w(async()=>{let{user:r,denied:a}=await n(o,"consent:view");if(a)return a;if(r?.allowedTenants.length&&!r.allowedTenants.includes("default"))return g(403,"Forbidden");let c=await i.getConsent(s.visitorId??"");return c?_(200,c):g(404,"Consent not found")}),"GET /consents/:visitorId/history":async(o,s)=>w(async()=>{let{user:r,denied:a}=await n(o,"consent:view");if(a)return a;if(r?.allowedTenants.length&&!r.allowedTenants.includes("default"))return g(403,"Forbidden");let c=await i.getConsentHistory(s.visitorId??"");return _(200,c)})}}p();var mu=!1;function Ka(i,e,t){async function n(o,s){let r=await O(o,i,e,t);return{user:r,denied:k(r,s)}}return{"GET /visitors":async(o,s)=>w(async()=>{let{user:r,denied:a}=await n(o,"visitor:view");if(a)return a;if(r?.allowedTenants.length&&!r.allowedTenants.includes("default"))return _(200,{items:[],total:0,page:1,limit:50});let c=new URL(o.url),l=G(c,"from"),d=G(c,"to"),u=G(c,"q"),m=Je(c);if("error"in m)return g(400,m.error);let{page:f,limit:S}=m,y={tenantId:"default",page:f,limit:S,...l!==void 0?{from:l}:{},...d!==void 0?{to:d}:{},...u!==void 0?{q:u}:{}},E=await i.getVisitors(y);return _(200,E)}),"GET /visitors/:visitorId/notice-shown":async(o,s)=>w(async()=>{if(!mu)return g(404,"Not found");let{denied:r}=await n(o,"visitor:view");if(r)return r;let a=await i.getNoticeShownForVisitor(s.visitorId??"");return _(200,a)})}}p();var Ya="role_super_admin";function Qa(i,e,t,n){async function o(r,a){let c=await O(r,e,t,n);return{user:c,denied:k(c,a)}}async function s(r){return(await i.getRoles(r)).some(c=>c.id===Ya)}return{"GET /users":async(r,a)=>w(async()=>{let{denied:c}=await o(r,"user:view");if(c)return c;let l=await i.list(),d=await Promise.all(l.map(async u=>({...u,roles:(await i.getRoles(u.id)).map(m=>({id:m.id,name:m.name}))})));return _(200,d)}),"GET /users/:id":async(r,a)=>w(async()=>{let{denied:c}=await o(r,"user:view");if(c)return c;let l=await i.get(a.id??"");if(!l)return g(404,"User not found");let d=await i.getRoles(l.id);return _(200,{...l,roles:d.map(u=>({id:u.id,name:u.name}))})}),"POST /users":async(r,a)=>w(async()=>{let{user:c,denied:l}=await o(r,"user:create");if(l)return l;let d=await b(r);if(!d||typeof d!="object")return g(400,"Invalid body");let u=d;if(typeof u.name!="string"||!u.name)return g(400,"name is required");if(typeof u.email!="string"||!u.email)return g(400,"email is required");if(typeof u.password!="string"||!u.password)return g(400,"password is required");if(u.password.length<12)return g(400,"password must be at least 12 characters");let m=await i.create({name:u.name,email:u.email,password:u.password,...typeof u.roleId=="string"?{roleId:u.roleId}:{},...Array.isArray(u.allowedTenants)?{allowedTenants:u.allowedTenants}:{}},c.sub);return _(201,m)}),"PUT /users/:id":async(r,a)=>w(async()=>{let{user:c,denied:l}=await o(r,"user:update");if(l)return l;let d=a.id??"";if(d!==c.sub&&await s(d))return g(403,"Super admin users cannot be modified");let u=await b(r);if(!u||typeof u!="object")return g(400,"Invalid body");let m=u;if(typeof m.password=="string"&&m.password.length<12)return g(400,"password must be at least 12 characters");let f=await i.update(d,{...typeof m.name=="string"?{name:m.name}:{},...typeof m.email=="string"?{email:m.email}:{},...m.isActive!=null?{isActive:!!m.isActive}:{},...typeof m.password=="string"?{password:m.password}:{},...Array.isArray(m.allowedTenants)?{allowedTenants:m.allowedTenants}:{}},c.sub);return _(200,f)}),"DELETE /users/:id":async(r,a)=>w(async()=>{let{user:c,denied:l}=await o(r,"user:delete");if(l)return l;let d=a.id??"";return d===c.sub?g(400,"Cannot delete your own account"):await s(d)?g(403,"Super admin users cannot be deleted"):(await i.delete(d,c.sub),_(200,{success:!0}))}),"POST /users/:id/roles":async(r,a)=>w(async()=>{let{user:c,denied:l}=await o(r,"role:update");if(l)return l;let d=await b(r);if(!d||typeof d!="object")return g(400,"Invalid body");let u=d;if(typeof u.roleId!="string")return g(400,"roleId is required");let m=typeof u.tenantId=="string"?u.tenantId:void 0;return await i.assignRole(a.id??"",u.roleId,m),await e.createLog({tenantId:"default",userId:c.sub,action:"user.role_assigned",resourceType:"user",...a.id!=null?{resourceId:a.id}:{},newData:{roleId:u.roleId}}),_(200,{success:!0})}),"DELETE /users/:id/roles/:roleId":async(r,a)=>w(async()=>{let{user:c,denied:l}=await o(r,"role:update");if(l)return l;if(a.roleId===Ya)return g(403,"The super_admin role cannot be revoked");let u=new URL(r.url).searchParams.get("tenantId")??void 0;return await i.revokeRole(a.id??"",a.roleId??"",u),await e.createLog({tenantId:"default",userId:c.sub,action:"user.role_revoked",resourceType:"user",...a.id!=null?{resourceId:a.id}:{},oldData:{roleId:a.roleId}}),_(200,{success:!0})})}}p();var bn="role_super_admin";function Za(i,e,t){async function n(o,s){let r=await O(o,i,e,t);return{user:r,denied:k(r,s)}}return{"GET /roles":async(o,s)=>w(async()=>{let{denied:r}=await n(o,"role:view");if(r)return r;let a=await i.getRoles("default");return _(200,a)}),"GET /roles/:id/permissions":async(o,s)=>w(async()=>{let{denied:r}=await n(o,"role:view");if(r)return r;let a=await i.getPermissionsForRole(s.id??"");return _(200,a)}),"POST /roles":async(o,s)=>w(async()=>{let{user:r,denied:a}=await n(o,"role:create");if(a)return a;let c=await b(o);if(!c||typeof c!="object")return g(400,"Invalid body");let l=c;if(typeof l.name!="string"||!l.name)return g(400,"name is required");let d=await i.createRole({tenantId:"default",name:l.name,...typeof l.description=="string"?{description:l.description}:{}});return await i.createLog({tenantId:"default",userId:r.sub,action:"role.created",resourceType:"role",resourceId:d.id,newData:d}),_(201,d)}),"PUT /roles/:id":async(o,s)=>w(async()=>{let{user:r,denied:a}=await n(o,"role:update");if(a)return a;if(s.id===bn)return g(403,"The super_admin role cannot be modified");let c=await b(o);if(!c||typeof c!="object")return g(400,"Invalid body");let l=c,d=await i.updateRole(s.id??"",{...typeof l.name=="string"?{name:l.name}:{},...typeof l.description=="string"?{description:l.description}:{}});return await i.createLog({tenantId:"default",userId:r.sub,action:"role.updated",resourceType:"role",resourceId:d.id,newData:d}),_(200,d)}),"DELETE /roles/:id":async(o,s)=>w(async()=>{let{user:r,denied:a}=await n(o,"role:delete");return a||(s.id===bn?g(403,"The super_admin role cannot be deleted"):(await i.deleteRole(s.id??""),await i.createLog({tenantId:"default",userId:r.sub,action:"role.deleted",resourceType:"role",...s.id!=null?{resourceId:s.id}:{}}),_(200,{success:!0})))}),"GET /permissions":async(o,s)=>w(async()=>{let{denied:r}=await n(o,"role:view");if(r)return r;let a=await i.getAllPermissions();return _(200,a)}),"POST /roles/:id/permissions":async(o,s)=>w(async()=>{let{denied:r}=await n(o,"role:update");if(r)return r;if(s.id===bn)return g(403,"The super_admin role cannot be modified");let a=await b(o);if(!a||typeof a!="object")return g(400,"Invalid body");let c=a;return typeof c.permissionId!="string"?g(400,"permissionId is required"):(await i.assignPermissionToRole(s.id??"",c.permissionId),_(200,{success:!0}))}),"DELETE /roles/:id/permissions/:permissionId":async(o,s)=>w(async()=>{let{denied:r}=await n(o,"role:update");return r||(s.id===bn?g(403,"The super_admin role cannot be modified"):(await i.revokePermissionFromRole(s.id??"",s.permissionId??""),_(200,{success:!0})))})}}p();function Xa(i,e,t){async function n(o,s){let r=await O(o,i,e,t);return{user:r,denied:k(r,s)}}return{"GET /audit":async(o,s)=>w(async()=>{let{user:r,denied:a}=await n(o,"audit:view");if(a)return a;if(r?.allowedTenants.length&&!r.allowedTenants.includes("default"))return _(200,{items:[],total:0,page:1,limit:50});let c=new URL(o.url),l=G(c,"action"),d=G(c,"resourceType"),u=G(c,"from"),m=G(c,"to"),f=G(c,"q"),S=Je(c);if("error"in S)return g(400,S.error);let{page:y,limit:E}=S,R={tenantId:"default",page:y,limit:E,...l!==void 0?{action:l}:{},...d!==void 0?{resourceType:d}:{},...u!==void 0?{from:u}:{},...m!==void 0?{to:m}:{},...f!==void 0?{q:f}:{}},v=await i.getLogs(R);return _(200,v)}),"GET /audit/:id":async(o,s)=>w(async()=>{let{user:r,denied:a}=await n(o,"audit:view");if(a)return a;if(r?.allowedTenants.length&&!r.allowedTenants.includes("default"))return g(403,"Forbidden");let c=await i.getAuditLogById(s.id??"");return!c||c.tenantId!=="default"?g(404,"Audit log entry not found"):_(200,c)})}}p();function ec(i,e,t,n){async function o(s){let r=await O(s,i,t,n);return{denied:k(r,"consent:view")}}return{"GET /stats/overview":async(s,r)=>w(async()=>{let{denied:a}=await o(s);if(a)return a;let c=await e.getOverview("default");return _(200,c)}),"GET /stats/categories":async(s,r)=>w(async()=>{let{denied:a}=await o(s);if(a)return a;let c=await e.getCategories("default");return _(200,c)}),"GET /stats/timeline":async(s,r)=>w(async()=>{let{denied:a}=await o(s);if(a)return a;let c=new URL(s.url),l=Cn(c,"days",30),d=await e.getTimeline("default",l);return _(200,d)}),"GET /stats/countries":async(s,r)=>w(async()=>{let{denied:a}=await o(s);if(a)return a;let c=await e.getCountries("default");return _(200,c)}),"GET /stats/gpc":async(s,r)=>w(async()=>{let{denied:a}=await o(s);if(a)return a;let c=await e.getGpc("default");return _(200,c)}),"GET /stats/aggregate":async(s,r)=>w(async()=>{let{denied:a}=await o(s);if(a)return a;let c=await e.getTenants(),l=await Promise.all(c.map(async u=>{let m=await e.getOverview(u.id);return{tenantId:u.id,tenantName:u.name,...m}})),d=l.reduce((u,m)=>({totalConsents:u.totalConsents+m.totalConsents,totalVisitors:u.totalVisitors+m.totalVisitors,gpcDetectedCount:u.gpcDetectedCount+m.gpcDetectedCount}),{totalConsents:0,totalVisitors:0,gpcDetectedCount:0});return _(200,{aggregate:d,perTenant:l})})}}p();function Gi(i){let e=i==null?"":String(i);return e.includes(",")||e.includes('"')||e.includes(`
154
+ `)?`"${e.replace(/"/g,'""')}"`:e}function gu(i){return[i.id,i.visitorId,i.profileId,i.locale,JSON.stringify(i.consentJson),i.gpcDetected?"1":"0",i.source,i.signature??"",i.createdAt,i.updatedAt,i.profileVersion??""].map(Gi).join(",")+`
155
+ `}function fu(i){return[i.id,i.userId??"",i.action,i.resourceType,i.resourceId??"",i.createdAt].map(Gi).join(",")+`
156
+ `}function tc(i,e,t,n){async function o(s){let r=await O(s,i,e,t);return{denied:k(r,"export:run")}}return{"GET /export/consents":async(s,r)=>w(async()=>{let{denied:a}=await o(s);if(a)return a;let c=new URL(s.url),l=G(c,"format")??"csv",d=G(c,"profileId"),u=G(c,"from"),m=G(c,"to"),f={tenantId:"default",...d!==void 0?{profileId:d}:{},...u!==void 0?{from:u}:{},...m!==void 0?{to:m}:{}};if(l==="json"){let R=[];for await(let v of i.streamConsents(f))R.push(v);return new Response(JSON.stringify(R),{status:200,headers:{"Content-Type":"application/json","Content-Disposition":'attachment; filename="consents.json"'}})}let S=new TextEncoder,y=`id,visitor_id,profile_id,locale,consent_json,gpc_detected,source,signature,created_at,updated_at,profile_version
157
+ `,E=new ReadableStream({async start(R){R.enqueue(S.encode(y));for await(let v of i.streamConsents(f))R.enqueue(S.encode(gu(v)));R.close()}});return new Response(E,{status:200,headers:{"Content-Type":"text/csv; charset=utf-8","Content-Disposition":'attachment; filename="consents.csv"'}})}),"GET /export/consents/xlsx":async(s,r)=>w(async()=>{let{denied:a}=await o(s);if(a)return a;let c=null;try{c=await import("xlsx")}catch{return new Response(JSON.stringify({error:"xlsx peer dependency not installed. Run: npm install xlsx"}),{status:501,headers:{"Content-Type":"application/json"}})}if(!c)return new Response(null,{status:501});let l=new URL(s.url),d=l.searchParams.get("profileId")??void 0,u=l.searchParams.get("from")??void 0,m=l.searchParams.get("to")??void 0,f={tenantId:"default",...d!==void 0?{profileId:d}:{},...u!==void 0?{from:u}:{},...m!==void 0?{to:m}:{}},S=[];for await(let v of i.streamConsents(f))S.push({id:v.id,visitor_id:v.visitorId,profile_id:v.profileId,profile_version:v.profileVersion??"",locale:v.locale,consent_json:JSON.stringify(v.consentJson),gpc_detected:v.gpcDetected?1:0,age_verified:v.ageVerified?1:0,tcf_string:v.tcfString??"",signature:v.signature??"",source:v.source,created_at:v.createdAt,updated_at:v.updatedAt});let y=c.utils.book_new(),E=c.utils.json_to_sheet(S);c.utils.book_append_sheet(y,E,"Consents");let R=c.write(y,{type:"buffer",bookType:"xlsx"});return new Response(R,{status:200,headers:{"Content-Type":"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet","Content-Disposition":'attachment; filename="consents.xlsx"'}})}),"GET /export/translations/:profileId":async(s,r)=>w(async()=>{let{denied:a}=await o(s);if(a)return a;let c=r.profileId??"",l=await i.getProfile(c);if(!l)return g(404,"Profile not found");let d=l.profileJson,u=d.locales?.length?d.locales:[l.defaultLocale],m={};for(let S of u){if(S===l.defaultLocale){m[S]={mainBanner:d.mainBanner,...d.gpcBanner?{gpcBanner:d.gpcBanner}:{},preferenceModal:d.preferenceModal};continue}let y=await n.getVersionFile(c,String(l.version),S);if(y)try{let E=JSON.parse(y);m[S]={mainBanner:E.mainBanner,...E.gpcBanner?{gpcBanner:E.gpcBanner}:{},preferenceModal:E.preferenceModal}}catch{}}if(Object.keys(m).length===0)return new Response(`locale,field,value
158
+ `,{status:200,headers:{"Content-Type":"text/csv; charset=utf-8","Content-Disposition":`attachment; filename="${c}-translations.csv"`}});let f=["locale,section,field,value"];for(let[S,y]of Object.entries(m))for(let[E,R]of Object.entries(y))if(typeof R=="object"&&R!==null)for(let[v,A]of Object.entries(R))typeof A=="string"&&f.push([S,E,v,A].map(Gi).join(","));return new Response(f.join(`
157
159
  `)+`
158
- `,{status:200,headers:{"Content-Type":"text/csv; charset=utf-8","Content-Disposition":`attachment; filename="${c}-translations.csv"`}})}),"GET /export/audit":async(s,r)=>E(async()=>{let{denied:a}=await o(s);if(a)return a;let c=new URL(s.url),l=M(c,"format")??"csv",d=M(c,"from"),u=M(c,"to"),m={tenantId:"default",...d!==void 0?{from:d}:{},...u!==void 0?{to:u}:{}};if(l==="json"){let w=[];for await(let R of i.streamAuditLogs(m))w.push(R);return new Response(JSON.stringify(w),{status:200,headers:{"Content-Type":"application/json","Content-Disposition":'attachment; filename="audit.json"'}})}let h=new TextEncoder,S=`id,user_id,action,resource_type,resource_id,created_at
159
- `,_=new ReadableStream({async start(w){w.enqueue(h.encode(S));for await(let R of i.streamAuditLogs(m))w.enqueue(h.encode(Md(R)));w.close()}});return new Response(_,{status:200,headers:{"Content-Type":"text/csv; charset=utf-8","Content-Disposition":'attachment; filename="audit.csv"'}})})}}p();var mt=require("node:crypto");function Gd(){let i=`ck_live_${(0,mt.randomBytes)(12).toString("hex")}${(0,mt.randomBytes)(12).toString("hex")}`,e=(0,mt.createHash)("sha256").update(i).digest("hex");return{raw:i,hash:e}}function Pa(i,e,t){async function n(o){let s=await b(o,i,e,t);return{user:s,denied:k(s,"settings:update")}}return{"GET /apikeys":async(o,s)=>E(async()=>{let{denied:r}=await n(o);if(r)return r;let a=await i.getApiKeys("default"),c=new Date,l=await Promise.all(a.map(async d=>{let u=d.isActive&&!!d.expireBy&&new Date(d.expireBy)<=c;return u&&await i.revokeApiKey(d.id).catch(()=>{}),{id:d.id,name:d.name,isActive:u?!1:d.isActive,createdAt:d.createdAt,updatedAt:d.updatedAt,...d.createdBy!==void 0?{createdBy:d.createdBy}:{},...d.expireBy!==void 0?{expireBy:d.expireBy}:{}}}));return y(200,l)}),"POST /apikeys":async(o,s)=>E(async()=>{let{user:r,denied:a}=await n(o);if(a)return a;let c=await o.json();if(!c.name)return y(400,{error:"name is required"});if(c.expireBy!==void 0&&Number.isNaN(new Date(c.expireBy).getTime()))return y(400,{error:"expireBy must be a valid date"});let{raw:l,hash:d}=Gd(),u=await i.createApiKey({tenantId:c.tenantId??"default",name:c.name,keyHash:d,...r?{createdBy:r.sub}:{},...c.expireBy!==void 0?{expireBy:c.expireBy}:{}});return y(201,{id:u.id,name:u.name,key:l,createdAt:u.createdAt})}),"DELETE /apikeys/:id":async(o,s)=>E(async()=>{let{denied:r}=await n(o);return r||(await i.revokeApiKey(s.id??""),new Response(null,{status:204}))}),"POST /apikeys/:id/reactivate":async(o,s)=>E(async()=>{let{denied:r}=await n(o);return r||(await i.reactivateApiKey(s.id??""),new Response(null,{status:204}))}),"DELETE /apikeys/:id/permanent":async(o,s)=>E(async()=>{let{denied:r}=await n(o);return r||(await i.deleteApiKey(s.id??""),new Response(null,{status:204}))})}}p();function ba(i,e,t){async function n(o,s){let r=await b(o,i,e,t);return{user:r,denied:k(r,s)}}return{"GET /tenants":async(o,s)=>E(async()=>{let{denied:r}=await n(o,"settings:update");if(r)return r;let a=await i.getTenants();return y(200,a)}),"POST /tenants":async(o,s)=>E(async()=>{let{denied:r}=await n(o,"settings:update");if(r)return r;let a=await P(o);if(!a||typeof a!="object")return g(400,"Invalid body");let c=a;if(typeof c.name!="string"||typeof c.slug!="string")return g(400,"name and slug are required");let l=await i.createTenant({name:c.name,slug:c.slug});return y(201,l)}),"PUT /tenants/:id":async(o,s)=>E(async()=>{let{denied:r}=await n(o,"settings:update");if(r)return r;let a=await P(o);if(!a||typeof a!="object")return g(400,"Invalid body");let c=a,l=await i.updateTenant(s.id??"",{...typeof c.name=="string"?{name:c.name}:{},...typeof c.slug=="string"?{slug:c.slug}:{}});return y(200,l)}),"DELETE /tenants/:id":async(o,s)=>E(async()=>{let{denied:r}=await n(o,"settings:update");if(r)return r;let a=s.id??"";return a==="default"?g(400,"Cannot delete the default tenant"):(await i.deleteTenant(a),y(200,{success:!0}))})}}p();function Oa(i,e,t){async function n(o){let s=await b(o,i,e,t);return{user:s,denied:k(s,"settings:update")}}return{"GET /settings":async(o,s)=>E(async()=>{let{denied:r}=await n(o);if(r)return r;let a=await i.getSettings("default");return y(200,a)}),"PATCH /settings":async(o,s)=>E(async()=>{let{denied:r}=await n(o);if(r)return r;let a=await P(o);if(!a||typeof a!="object")return g(400,"Invalid body");let c=a;if(c.allowedOrigins!==void 0&&!Array.isArray(c.allowedOrigins))return g(400,"allowedOrigins must be an array of strings");if(c.adminAllowedOrigins!==void 0&&!Array.isArray(c.adminAllowedOrigins))return g(400,"adminAllowedOrigins must be an array of strings");let l=await i.updateSettings("default",{...c.allowedOrigins!==void 0?{allowedOrigins:c.allowedOrigins}:{},...c.adminAllowedOrigins!==void 0?{adminAllowedOrigins:c.adminAllowedOrigins}:{}});return y(200,l)})}}p();function Da(i,e,t,n){async function o(r){let a=await b(r,i,e,t);return{user:a,denied:k(a,"consent:view")}}async function s(r){let a=await b(r,i,e,t);return{user:a,denied:k(a,"settings:update")}}return{"GET /tcf/vendors":async(r,a)=>E(async()=>{let{denied:c}=await o(r);if(c)return c;let l=await Ae();if(!l)return y(503,{error:"GVL not available. Enable tcf.enabled in config."});let d=new URL(r.url),u=d.searchParams.get("q")?.toLowerCase(),m=Math.max(1,parseInt(d.searchParams.get("page")??"1",10)),h=Math.min(200,Math.max(1,parseInt(d.searchParams.get("limit")??"100",10))),S=Object.values(l.vendors),_=u?S.filter(T=>T.name.toLowerCase().includes(u)):S,w=_.length,R=Math.max(1,Math.ceil(w/h)),C=Math.min(m,R),A=(C-1)*h;return y(200,{vendorListVersion:l.vendorListVersion,total:w,page:C,totalPages:R,vendors:_.slice(A,A+h)})}),"GET /tcf/purposes":async(r,a)=>E(async()=>{let{denied:c}=await o(r);if(c)return c;let l=await Ae();return l?y(200,{purposes:Object.values(l.purposes)}):y(503,{error:"GVL not available. Enable tcf.enabled in config."})}),"GET /tcf/registration-status":async(r,a)=>E(async()=>{let{denied:c}=await s(r);if(c)return c;if(!n)return y(200,{enabled:!1,confirmed:!0});let l=await i.getSettings("default"),d=ue(n.enabled,{cmpId:n.cmpId,cmpVersion:n.cmpVersion,publisherCC:n.publisherCC},l.tcfConfirmation),m=new URL(r.url).searchParams.get("refresh")==="true",h=n.enabled?await Ye(m):null,S=h?.cmps[String(n.cmpId)];return y(200,{enabled:n.enabled,cmpId:n.cmpId,cmpVersion:n.cmpVersion,...n.publisherCC?{publisherCC:n.publisherCC}:{},confirmed:d,...l.tcfConfirmation?{confirmedAt:l.tcfConfirmation.confirmedAt,confirmedBy:l.tcfConfirmation.confirmedBy}:{},...h?{cmpListVersion:h.cmpListVersion}:{},...n.enabled?{cmpListEntry:{found:!!S,deregistered:!!S?.deletedDate,...S?.deletedDate?{deletedDate:S.deletedDate}:{}}}:{}})}),"POST /tcf/confirm-registration":async(r,a)=>E(async()=>{let{user:c,denied:l}=await s(r);if(l)return l;if(!n?.enabled)return g(400,"TCF is not enabled in the server config \u2014 nothing to confirm.");if(!(await P(r))?.acknowledge)return g(400,"acknowledge: true is required to confirm TCF registration.");let m=(await Ye())?.cmps[String(n.cmpId)];if(m?.deletedDate)return g(409,`cmpId ${n.cmpId} was deregistered on ${m.deletedDate} per IAB's CMP List. Registration confirmation blocked.`);if(!m)return g(404,`cmpId ${n.cmpId} was not found in the cached CMP List. Registration can take time to propagate after signing up with IAB Europe \u2014 try "Refresh Status" and confirm again shortly.`);let h=at({cmpId:n.cmpId,cmpVersion:n.cmpVersion,publisherCC:n.publisherCC}),S=await i.updateSettings("default",{tcfConfirmation:{configHash:h,confirmedAt:new Date().toISOString(),confirmedBy:c.sub}});return y(200,{confirmed:!0,tcfConfirmation:S.tcfConfirmation})})}}p();function ka(i,e,t,n){async function o(s){let r=await b(s,i,e,t);return{user:r,denied:k(r,"settings:update")}}return{"GET /gpp/registration-status":async(s,r)=>E(async()=>{let{denied:a}=await o(s);if(a)return a;if(!n)return y(200,{enabled:!1,confirmed:!0});let c=await i.getSettings("default"),l=ue(n.enabled,{cmpId:n.cmpId,cmpVersion:n.cmpVersion},c.gppConfirmation);return y(200,{enabled:n.enabled,cmpId:n.cmpId,cmpVersion:n.cmpVersion,confirmed:l,...c.gppConfirmation?{confirmedAt:c.gppConfirmation.confirmedAt,confirmedBy:c.gppConfirmation.confirmedBy}:{}})}),"POST /gpp/confirm-registration":async(s,r)=>E(async()=>{let{user:a,denied:c}=await o(s);if(c)return c;if(!n?.enabled)return g(400,"GPP is not enabled in the server config \u2014 nothing to confirm.");if(!(await P(s))?.acknowledge)return g(400,"acknowledge: true is required to confirm GPP registration.");let d=at({cmpId:n.cmpId,cmpVersion:n.cmpVersion}),u=await i.updateSettings("default",{gppConfirmation:{configHash:d,confirmedAt:new Date().toISOString(),confirmedBy:a.sub}});return y(200,{confirmed:!0,gppConfirmation:u.gppConfirmation})})}}p();p();ae();var La=["mandatory","consent","legitimate_interest"],Na=["sale","sharing","sensitive"];function jd(i){if(!i||typeof i!="object"||Array.isArray(i))return{valid:!1,error:"cookies must be an object keyed by parameter id"};for(let[e,t]of Object.entries(i)){if(!e.trim())return{valid:!1,error:"cookie id must be non-empty"};if(!t||typeof t!="object")return{valid:!1,error:`cookies["${e}"] must be an object`};let n=t;if(!nn.includes(n.purpose))return{valid:!1,error:`cookies["${e}"].purpose must be one of: ${nn.join(", ")}`};if(typeof n.listenGpc!="boolean")return{valid:!1,error:`cookies["${e}"].listenGpc must be a boolean`};if(n.preGrant!==void 0&&typeof n.preGrant!="boolean")return{valid:!1,error:`cookies["${e}"].preGrant must be a boolean`};if(n.cpraCategory!==void 0&&!Na.includes(n.cpraCategory))return{valid:!1,error:`cookies["${e}"].cpraCategory must be one of: ${Na.join(", ")}`}}return{valid:!0}}function Bd(i){if(!i||typeof i!="object"||Array.isArray(i))return{valid:!1,error:"categories must be an object keyed by category id"};let e=Object.entries(i);if(e.length===0)return{valid:!1,error:"at least one category is required"};for(let[t,n]of e){if(!n||typeof n!="object")return{valid:!1,error:`categories["${t}"] must be an object`};let o=n;if(typeof o.heading!="string"||!o.heading.trim())return{valid:!1,error:`categories["${t}"].heading is required`};if(typeof o.htmlText!="string")return{valid:!1,error:`categories["${t}"].htmlText is required`};if(!La.includes(o.legalBasis))return{valid:!1,error:`categories["${t}"].legalBasis must be one of: ${La.join(", ")}`};if(!Array.isArray(o.cookies))return{valid:!1,error:`categories["${t}"].cookies must be an array of parameter ids`}}return{valid:!0}}function Fd(i,e){let t=new Map;for(let n of Object.keys(i))t.set(n,0);for(let n of Object.values(e))for(let o of n.cookies)t.set(o,(t.get(o)??0)+1);for(let[n,o]of t){if(o===0)return{valid:!1,error:`Parameter "${n}" is not assigned to any category`};if(o>1)return{valid:!1,error:`Parameter "${n}" is assigned to more than one category`}}return{valid:!0}}function $d(i,e){let t=new Map;for(let[o,s]of Object.entries(e))for(let r of s.cookies)t.set(r,o);let n=[];for(let[o,s]of Object.entries(i)){let r=t.get(o);if(!r)continue;let a=e[r].legalBasis,c=s.purpose;if(a==="mandatory"&&c!=="necessary")return{valid:!1,error:`Parameter "${o}" has purpose "${c??"unknown"}" but is assigned to a Strictly Necessary category \u2014 this grants a tracking parameter with no consent gate.`};a!=="mandatory"&&c==="necessary"&&n.push(`Parameter "${o}" has purpose "necessary" but is assigned to a non-mandatory category \u2014 this may break site functionality since it can be denied.`)}return{valid:!0,...n.length>0?{warnings:n}:{}}}function Si(i,e){let t=jd(i);if(!t.valid)return t;let n=Bd(e);if(!n.valid)return n;let o=i,s=e,r=Fd(o,s);return r.valid?$d(o,s):r}function Ua(i,e,t,n="default"){async function o(s,r){let a=await b(s,i,e,t);return{user:a,denied:k(a,r)}}return{"GET /consent-templates":async s=>E(async()=>{let{denied:r}=await o(s,"profile:view");return r||y(200,await i.getConsentTemplates(n))}),"GET /consent-templates/:id":async(s,r)=>E(async()=>{let{denied:a}=await o(s,"profile:view");if(a)return a;let c=await i.getConsentTemplate(r.id);return c?y(200,c):g(404,"Consent template not found")}),"POST /consent-templates":async s=>E(async()=>{let{denied:r}=await o(s,"profile:create");if(r)return r;let a=await P(s);if(!a?.name||typeof a.name!="string")return g(400,"name is required");let c=Si(a.cookies,a.categories);if(!c.valid)return g(400,c.error);let l=await i.createConsentTemplate({tenantId:n,name:a.name,cookies:a.cookies,categories:a.categories});return y(201,l)}),"PUT /consent-templates/:id":async(s,r)=>E(async()=>{let{denied:a}=await o(s,"profile:update");if(a)return a;let c=r.id,l=await P(s),d=await i.getConsentTemplate(c);if(!d)return g(404,"Consent template not found");let u={};l?.name!==void 0&&typeof l.name=="string"&&(u.name=l.name);let m=l?.cookies!==void 0,h=l?.categories!==void 0,S=m?l.cookies:d.cookies,_=h?l.categories:d.categories;if(m||h){let R=Si(S,_);if(!R.valid)return g(400,R.error);m&&(u.cookies=S),h&&(u.categories=_);let C=await i.findProfilesUsingConsentTemplate(c),A=[];for(let T of C){if(!T.complianceGroup)continue;Ve(S,_,T.complianceGroup).valid||A.push({id:T.id,name:T.name,complianceGroup:T.complianceGroup})}if(A.length>0)return g(422,"This change would break compliance for affected profiles",{blockingProfiles:A})}let w=await i.updateConsentTemplate(c,u);return y(200,w)}),"DELETE /consent-templates/:id":async(s,r)=>E(async()=>{let{denied:a}=await o(s,"profile:delete");if(a)return a;let c=r.id,l=await i.findProfilesUsingConsentTemplate(c);return l.length>0?g(422,"Cannot delete: template is used by profiles",{profiles:l.map(d=>({id:d.id,name:d.name,isActive:d.isActive}))}):(await i.deleteConsentTemplate(c),y(200,{ok:!0}))}),"POST /consent-templates/:id/copy":async(s,r)=>E(async()=>{let{denied:a}=await o(s,"profile:create");if(a)return a;let c=await P(s),l=await i.getConsentTemplate(r.id);if(!l)return g(404,"Consent template not found");let d=typeof c?.name=="string"&&c.name.trim()?c.name.trim():`${l.name} (Copy)`,u=await i.copyConsentTemplate(r.id,d);return y(201,u)}),"GET /consent-templates/:id/profile-usage":async(s,r)=>E(async()=>{let{denied:a}=await o(s,"profile:view");if(a)return a;let c=await i.findProfilesUsingConsentTemplate(r.id);return y(200,c)})}}p();function xa(i,e,t,n="default"){async function o(s,r){let a=await b(s,i,e,t);return{user:a,denied:k(a,r)}}return{"GET /ui-templates":async s=>E(async()=>{let{denied:r}=await o(s,"profile:view");return r||y(200,await i.getUITemplates(n))}),"GET /ui-templates/:id":async(s,r)=>E(async()=>{let{denied:a}=await o(s,"profile:view");if(a)return a;let c=await i.getUITemplate(r.id);return c?y(200,c):g(404,"UI template not found")}),"POST /ui-templates":async s=>E(async()=>{let{denied:r}=await o(s,"profile:create");if(r)return r;let a=await P(s);if(!a?.name||typeof a.name!="string")return g(400,"name is required");if(!a.mainBanner||!a.gpcBanner||!a.preferenceModal)return g(400,"mainBanner, gpcBanner, and preferenceModal are required");let c=await i.createUITemplate({tenantId:n,name:a.name,mainBanner:a.mainBanner,gpcBanner:a.gpcBanner,preferenceModal:a.preferenceModal});return y(201,c)}),"PUT /ui-templates/:id":async(s,r)=>E(async()=>{let{denied:a}=await o(s,"profile:update");if(a)return a;let c=await P(s),l={};typeof c?.name=="string"&&(l.name=c.name),c?.mainBanner&&(l.mainBanner=c.mainBanner),c?.gpcBanner&&(l.gpcBanner=c.gpcBanner),c?.preferenceModal&&(l.preferenceModal=c.preferenceModal);let d=await i.updateUITemplate(r.id,l);return y(200,d)}),"DELETE /ui-templates/:id":async(s,r)=>E(async()=>{let{denied:a}=await o(s,"profile:delete");if(a)return a;let c=r.id,l=await i.findProfilesUsingUITemplate(c);return l.length>0?g(422,"Cannot delete: template is used by profiles",{profiles:l.map(d=>({id:d.id,name:d.name,isActive:d.isActive}))}):(await i.deleteUITemplate(c),y(200,{ok:!0}))}),"POST /ui-templates/:id/copy":async(s,r)=>E(async()=>{let{denied:a}=await o(s,"profile:create");if(a)return a;let c=await P(s),l=await i.getUITemplate(r.id);if(!l)return g(404,"UI template not found");let d=typeof c?.name=="string"&&c.name.trim()?c.name.trim():`${l.name} (Copy)`,u=await i.copyUITemplate(r.id,d);return y(201,u)}),"GET /ui-templates/:id/profile-usage":async(s,r)=>E(async()=>{let{denied:a}=await o(s,"profile:view");if(a)return a;let c=await i.findProfilesUsingUITemplate(r.id);return y(200,c)})}}p();function Ma(i,e,t,n="default"){async function o(s,r){let a=await b(s,i,e,t);return{user:a,denied:k(a,r)}}return{"GET /analytics/opt-in":async(s,r)=>E(async()=>{let{denied:a}=await o(s,"stats:view");if(a)return a;let c=new URL(s.url),l=c.searchParams.get("tenantId")??n,d={},u=c.searchParams.get("profileId"),m=c.searchParams.get("complianceGroup"),h=c.searchParams.get("from"),S=c.searchParams.get("to"),_=c.searchParams.get("locale");u&&(d.profileId=u),m&&(d.complianceGroup=m),h&&(d.from=h),S&&(d.to=S),_&&(d.locale=_);let w=await i.getOptInStats(l,d);return y(200,w)})}}p();ae();p();var _e="\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022";function Ga(i){let e=i.storage,t=i.auth,n=i.compliance,o=i.dashboard;return{basePath:i.basePath,dashboard:typeof o=="object"?{enabled:o.enabled,path:o.path}:o,...e?{storage:{driver:e.driver,...e.path!==void 0?{path:e.path}:{},...e.uri!==void 0?{uri:_e}:{},...e.database!==void 0?{database:e.database}:{},...e.host!==void 0?{host:e.host}:{},...e.port!==void 0?{port:e.port}:{},...e.user!==void 0?{user:e.user}:{},...e.password!==void 0?{password:_e}:{},...e.poolMax!==void 0?{poolMax:e.poolMax}:{},...e.statementTimeoutMs!==void 0?{statementTimeoutMs:e.statementTimeoutMs}:{},...e.idleInTransactionTimeoutMs!==void 0?{idleInTransactionTimeoutMs:e.idleInTransactionTimeoutMs}:{}}}:{},...t?{auth:{mode:t.mode,...t.adminEmail!==void 0?{adminEmail:t.adminEmail}:{},...t.adminPassword!==void 0?{adminPassword:_e}:{},...t.masterSecret!==void 0?{masterSecret:_e}:{},...t.oidc?{oidc:{issuer:t.oidc.issuer,clientId:t.oidc.clientId,clientSecret:_e,redirectUri:t.oidc.redirectUri}}:{},...t.saml?{saml:{issuer:t.saml.issuer,entryPoint:t.saml.entryPoint,cert:_e,callbackUrl:t.saml.callbackUrl}}:{}}}:{},...i.rateLimit?{rateLimit:i.rateLimit}:{},...n?{compliance:{...n.type!==void 0?{type:n.type}:{},...n.gpc!==void 0?{gpc:n.gpc}:{},...n.geoDataProvider!==void 0?{geoDataProvider:typeof n.geoDataProvider=="function"?"<custom function>":n.geoDataProvider}:{},...n.complianceMap!==void 0?{complianceMap:typeof n.complianceMap=="object"?`<custom map, ${Object.keys(n.complianceMap.countries).length} countries>`:n.complianceMap}:{},...n.tcf?{tcf:n.tcf}:{},...n.gpp?{gpp:n.gpp}:{},...n.dataRetention?{dataRetention:n.dataRetention}:{},...n.parentalConsentTokenTtlDays!==void 0?{parentalConsentTokenTtlDays:n.parentalConsentTokenTtlDays}:{},...n.dataSigningHash!==void 0?{dataSigningHash:_e}:{}}}:{},...i.multiTenant?{multiTenant:i.multiTenant}:{},...i.plugins?{plugins:{count:i.plugins.length}}:{},...i.maxBodySize!==void 0?{maxBodySize:i.maxBodySize}:{},...i.trustedProxies?{trustedProxies:i.trustedProxies}:{},...i.branding?{branding:i.branding}:{},...i.s3Api?{s3Api:{enabled:i.s3Api.enabled,region:i.s3Api.region,bucketName:i.s3Api.bucketName,accessKeyId:_e,secretAccessKey:_e}}:{}}}function ja(i,e,t,n,o,s){async function r(c){let l=await b(c,e,t,n);return{denied:k(l,"settings:update")}}async function a(){return(await e.getSettings("default")).setupCompleted===!0?g(409,"Setup has already been completed"):null}return{"GET /setup/status":async(c,l)=>E(async()=>{let{denied:d}=await r(c);if(d)return d;let u=await e.getSettings("default");return y(200,{completed:u.setupCompleted===!0})}),"GET /setup/config":async(c,l)=>E(async()=>{let{denied:d}=await r(c);return d||y(200,{config:Ga(o),...s})}),"GET /setup/compliance-groups":async(c,l)=>E(async()=>{let{denied:d}=await r(c);if(d)return d;let u=tn.map(m=>({id:m,...ot[m]}));return y(200,u)}),"POST /setup/seed-profiles":async(c,l)=>E(async()=>{let{denied:d}=await r(c);if(d)return d;let u=await a();if(u)return u;let h=(await P(c))?.groups;if(!Array.isArray(h)||h.some(_=>typeof _!="string"))return g(400,"groups must be an array of compliance group ids");let S=h.filter(_=>!tn.includes(_));return S.length>0?g(400,`Unknown compliance group id(s): ${S.join(", ")}`):(await Promise.all(h.map(_=>i.seedDefaultProfile(_))),await e.updateSettings("default",{profilesSeeded:!0}),y(200,{seeded:h}))}),"POST /setup/complete":async(c,l)=>E(async()=>{let{denied:d}=await r(c);if(d)return d;let u=await a();if(u)return u;if((await e.getSettings("default")).profilesSeeded!==!0)return g(409,"POST /setup/seed-profiles must be called at least once (an empty groups: [] call is a valid pass) before setup can be completed");let h=await e.updateSettings("default",{setupCompleted:!0});return y(200,h)})}}p();var Ba=require("node:crypto");async function Fa(i,e,t){let n=i.headers.get("authorization");if(!n?.startsWith("Bearer ck_"))return t;let o=n.slice(7),s=(0,Ba.createHash)("sha256").update(o).digest("hex"),r=await e.getApiKeyByHash(s);return!r||!r.isActive?t:r.expireBy&&new Date(r.expireBy)<=new Date?(await e.revokeApiKey(r.id).catch(()=>{}),t):r.tenantId}p();var gt=class{constructor(e=6e4,t=60){this.windowMs=e;this.maxRequests=t;setInterval(()=>{let n=Date.now();for(let[o,s]of this.store)n>=s.resetAt&&this.store.delete(o)},this.windowMs).unref()}windowMs;maxRequests;store=new Map;check(e){let t=Date.now(),n=this.store.get(e);return!n||t>=n.resetAt?(this.store.set(e,{count:1,resetAt:t+this.windowMs}),!0):(n.count+=1,n.count<=this.maxRequests)}checkRequest(e,t){return this.check(`ip:${e}`)?t?this.check(`profile:${t}`):!0:!1}};ae();p();p();var Sn=class{constructor(e){this.options=e;e.eventBus.on("consent:created",this.onCreated),e.eventBus.on("consent:updated",this.onUpdated)}options;onCreated=e=>this.fire(e,void 0);onUpdated=({previous:e,current:t})=>this.fire(t,e);fire(e,t){let n=e.consentJson[this.options.id]??"denied",o=t?.consentJson[this.options.id]??"denied";if(n===o)return;let s={visitorId:e.visitorId,cookieId:this.options.id,status:n,record:e};n==="granted"?this.options.onGrant?.(s):this.options.onDeny?.(s)}destroy(){this.options.eventBus.off("consent:created",this.onCreated),this.options.eventBus.off("consent:updated",this.onUpdated)}};p();function $a(i,e){return e.length>0&&e.every(t=>i[t]==="granted")}var Cn=class{constructor(e){this.options=e;e.eventBus.on("consent:created",this.onCreated),e.eventBus.on("consent:updated",this.onUpdated)}options;onCreated=e=>{this.fire(e,void 0)};onUpdated=({previous:e,current:t})=>{this.fire(t,e)};async fire(e,t){let o=(await this.options.profiles.getResolved(e.profileId))?.preferenceModal.categories[this.options.categoryId]?.cookies??[];if(o.length===0)return;let s=$a(e.consentJson,o)?"granted":"denied",r=t&&$a(t.consentJson,o)?"granted":"denied";if(s===r)return;let a={visitorId:e.visitorId,categoryId:this.options.categoryId,status:s,record:e};s==="granted"?this.options.onGrant?.(a):this.options.onDeny?.(a)}destroy(){this.options.eventBus.off("consent:created",this.onCreated),this.options.eventBus.off("consent:updated",this.onUpdated)}};var Ci=(0,V.dirname)((0,vi.fileURLToPath)(f)),Hd=(0,vi.fileURLToPath)(new URL("./dashboard",f)),za={".html":"text/html; charset=utf-8",".js":"application/javascript; charset=utf-8",".mjs":"application/javascript; charset=utf-8",".css":"text/css; charset=utf-8",".json":"application/json",".png":"image/png",".svg":"image/svg+xml",".ico":"image/x-icon",".woff2":"font/woff2",".woff":"font/woff",".ttf":"font/ttf"};async function Vd(i,e,t,n,o){let s=i.slice(e.length)||"/";if(s.startsWith("/api/")||s.startsWith("/admin/"))return!1;let r=s==="/"||s===""||!(0,V.extname)(s)?(0,V.join)(t,"index.html"):(0,V.join)(t,s);if(!r.startsWith(t))return!1;try{let a=await(0,We.readFile)(r),c=(0,V.extname)(r).toLowerCase(),l=c===".html"||c==="",d=za[c]??"application/octet-stream";return n.writeHead(200,{"Content-Type":d}),n.end(l?Je(a,o):a),!0}catch{return!1}}async function Ha(i,e){try{let t=await(0,We.readFile)(i);return new Response(t,{headers:{"Content-Type":e,"Cache-Control":"public, max-age=3600"}})}catch{return new Response("Not Found",{status:404})}}function Wd(i){let e=[],t=i.split("/").map(n=>n.startsWith(":")?(e.push(n.slice(1)),"([^/]+)"):n.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"));return{pattern:new RegExp(`^${t.join("\\/")}$`),paramNames:e}}function qd(i){let t=`<!DOCTYPE html>
160
+ `,{status:200,headers:{"Content-Type":"text/csv; charset=utf-8","Content-Disposition":`attachment; filename="${c}-translations.csv"`}})}),"GET /export/audit":async(s,r)=>w(async()=>{let{denied:a}=await o(s);if(a)return a;let c=new URL(s.url),l=G(c,"format")??"csv",d=G(c,"from"),u=G(c,"to"),m={tenantId:"default",...d!==void 0?{from:d}:{},...u!==void 0?{to:u}:{}};if(l==="json"){let E=[];for await(let R of i.streamAuditLogs(m))E.push(R);return new Response(JSON.stringify(E),{status:200,headers:{"Content-Type":"application/json","Content-Disposition":'attachment; filename="audit.json"'}})}let f=new TextEncoder,S=`id,user_id,action,resource_type,resource_id,created_at
161
+ `,y=new ReadableStream({async start(E){E.enqueue(f.encode(S));for await(let R of i.streamAuditLogs(m))E.enqueue(f.encode(fu(R)));E.close()}});return new Response(y,{status:200,headers:{"Content-Type":"text/csv; charset=utf-8","Content-Disposition":'attachment; filename="audit.csv"'}})})}}p();var wt=require("node:crypto");function hu(){let i=`ck_live_${(0,wt.randomBytes)(12).toString("hex")}${(0,wt.randomBytes)(12).toString("hex")}`,e=(0,wt.createHash)("sha256").update(i).digest("hex");return{raw:i,hash:e}}function nc(i,e,t){async function n(o){let s=await O(o,i,e,t);return{user:s,denied:k(s,"settings:update")}}return{"GET /apikeys":async(o,s)=>w(async()=>{let{denied:r}=await n(o);if(r)return r;let a=await i.getApiKeys("default"),c=new Date,l=await Promise.all(a.map(async d=>{let u=d.isActive&&!!d.expireBy&&new Date(d.expireBy)<=c;return u&&await i.revokeApiKey(d.id).catch(()=>{}),{id:d.id,name:d.name,isActive:u?!1:d.isActive,createdAt:d.createdAt,updatedAt:d.updatedAt,...d.createdBy!==void 0?{createdBy:d.createdBy}:{},...d.expireBy!==void 0?{expireBy:d.expireBy}:{}}}));return _(200,l)}),"POST /apikeys":async(o,s)=>w(async()=>{let{user:r,denied:a}=await n(o);if(a)return a;let c=await o.json();if(!c.name)return _(400,{error:"name is required"});if(c.expireBy!==void 0&&Number.isNaN(new Date(c.expireBy).getTime()))return _(400,{error:"expireBy must be a valid date"});let{raw:l,hash:d}=hu(),u=await i.createApiKey({tenantId:c.tenantId??"default",name:c.name,keyHash:d,...r?{createdBy:r.sub}:{},...c.expireBy!==void 0?{expireBy:c.expireBy}:{}});return _(201,{id:u.id,name:u.name,key:l,createdAt:u.createdAt})}),"DELETE /apikeys/:id":async(o,s)=>w(async()=>{let{denied:r}=await n(o);return r||(await i.revokeApiKey(s.id??""),new Response(null,{status:204}))}),"POST /apikeys/:id/reactivate":async(o,s)=>w(async()=>{let{denied:r}=await n(o);return r||(await i.reactivateApiKey(s.id??""),new Response(null,{status:204}))}),"DELETE /apikeys/:id/permanent":async(o,s)=>w(async()=>{let{denied:r}=await n(o);return r||(await i.deleteApiKey(s.id??""),new Response(null,{status:204}))})}}p();function ic(i,e,t){async function n(o,s){let r=await O(o,i,e,t);return{user:r,denied:k(r,s)}}return{"GET /tenants":async(o,s)=>w(async()=>{let{denied:r}=await n(o,"settings:update");if(r)return r;let a=await i.getTenants();return _(200,a)}),"POST /tenants":async(o,s)=>w(async()=>{let{denied:r}=await n(o,"settings:update");if(r)return r;let a=await b(o);if(!a||typeof a!="object")return g(400,"Invalid body");let c=a;if(typeof c.name!="string"||typeof c.slug!="string")return g(400,"name and slug are required");let l=await i.createTenant({name:c.name,slug:c.slug});return _(201,l)}),"PUT /tenants/:id":async(o,s)=>w(async()=>{let{denied:r}=await n(o,"settings:update");if(r)return r;let a=await b(o);if(!a||typeof a!="object")return g(400,"Invalid body");let c=a,l=await i.updateTenant(s.id??"",{...typeof c.name=="string"?{name:c.name}:{},...typeof c.slug=="string"?{slug:c.slug}:{}});return _(200,l)}),"DELETE /tenants/:id":async(o,s)=>w(async()=>{let{denied:r}=await n(o,"settings:update");if(r)return r;let a=s.id??"";return a==="default"?g(400,"Cannot delete the default tenant"):(await i.deleteTenant(a),_(200,{success:!0}))})}}p();function oc(i,e,t){async function n(o){let s=await O(o,i,e,t);return{user:s,denied:k(s,"settings:update")}}return{"GET /settings":async(o,s)=>w(async()=>{let{denied:r}=await n(o);if(r)return r;let a=await i.getSettings("default");return _(200,a)}),"PATCH /settings":async(o,s)=>w(async()=>{let{denied:r}=await n(o);if(r)return r;let a=await b(o);if(!a||typeof a!="object")return g(400,"Invalid body");let c=a;if(c.allowedOrigins!==void 0&&!Array.isArray(c.allowedOrigins))return g(400,"allowedOrigins must be an array of strings");if(c.adminAllowedOrigins!==void 0&&!Array.isArray(c.adminAllowedOrigins))return g(400,"adminAllowedOrigins must be an array of strings");let l=await i.updateSettings("default",{...c.allowedOrigins!==void 0?{allowedOrigins:c.allowedOrigins}:{},...c.adminAllowedOrigins!==void 0?{adminAllowedOrigins:c.adminAllowedOrigins}:{}});return _(200,l)})}}p();function sc(i,e,t,n){async function o(r){let a=await O(r,i,e,t);return{user:a,denied:k(a,"consent:view")}}async function s(r){let a=await O(r,i,e,t);return{user:a,denied:k(a,"settings:update")}}return{"GET /tcf/vendors":async(r,a)=>w(async()=>{let{denied:c}=await o(r);if(c)return c;let l=await be();if(!l)return _(503,{error:"GVL not available. Enable tcf.enabled in config."});let d=new URL(r.url),u=d.searchParams.get("q")?.toLowerCase(),m=Math.max(1,parseInt(d.searchParams.get("page")??"1",10)),f=Math.min(200,Math.max(1,parseInt(d.searchParams.get("limit")??"100",10))),S=Object.values(l.vendors),y=u?S.filter(T=>T.name.toLowerCase().includes(u)):S,E=y.length,R=Math.max(1,Math.ceil(E/f)),v=Math.min(m,R),A=(v-1)*f;return _(200,{vendorListVersion:l.vendorListVersion,total:E,page:v,totalPages:R,vendors:y.slice(A,A+f)})}),"GET /tcf/purposes":async(r,a)=>w(async()=>{let{denied:c}=await o(r);if(c)return c;let l=await be();return l?_(200,{purposes:Object.values(l.purposes)}):_(503,{error:"GVL not available. Enable tcf.enabled in config."})}),"GET /tcf/registration-status":async(r,a)=>w(async()=>{let{denied:c}=await s(r);if(c)return c;if(!n)return _(200,{enabled:!1,confirmed:!0});let l=await i.getSettings("default"),d=me(n.enabled,{cmpId:n.cmpId,cmpVersion:n.cmpVersion,publisherCC:n.publisherCC},l.tcfConfirmation),m=new URL(r.url).searchParams.get("refresh")==="true",f=n.enabled?await tt(m):null,S=f?.cmps[String(n.cmpId)];return _(200,{enabled:n.enabled,cmpId:n.cmpId,cmpVersion:n.cmpVersion,...n.publisherCC?{publisherCC:n.publisherCC}:{},confirmed:d,...l.tcfConfirmation?{confirmedAt:l.tcfConfirmation.confirmedAt,confirmedBy:l.tcfConfirmation.confirmedBy}:{},...f?{cmpListVersion:f.cmpListVersion}:{},...n.enabled?{cmpListEntry:{found:!!S,deregistered:!!S?.deletedDate,...S?.deletedDate?{deletedDate:S.deletedDate}:{}}}:{}})}),"POST /tcf/confirm-registration":async(r,a)=>w(async()=>{let{user:c,denied:l}=await s(r);if(l)return l;if(!n?.enabled)return g(400,"TCF is not enabled in the server config \u2014 nothing to confirm.");if(!(await b(r))?.acknowledge)return g(400,"acknowledge: true is required to confirm TCF registration.");let m=(await tt())?.cmps[String(n.cmpId)];if(m?.deletedDate)return g(409,`cmpId ${n.cmpId} was deregistered on ${m.deletedDate} per IAB's CMP List. Registration confirmation blocked.`);if(!m)return g(404,`cmpId ${n.cmpId} was not found in the cached CMP List. Registration can take time to propagate after signing up with IAB Europe \u2014 try "Refresh Status" and confirm again shortly.`);let f=mt({cmpId:n.cmpId,cmpVersion:n.cmpVersion,publisherCC:n.publisherCC}),S=await i.updateSettings("default",{tcfConfirmation:{configHash:f,confirmedAt:new Date().toISOString(),confirmedBy:c.sub}});return _(200,{confirmed:!0,tcfConfirmation:S.tcfConfirmation})})}}p();function rc(i,e,t,n){async function o(s){let r=await O(s,i,e,t);return{user:r,denied:k(r,"settings:update")}}return{"GET /gpp/registration-status":async(s,r)=>w(async()=>{let{denied:a}=await o(s);if(a)return a;if(!n)return _(200,{enabled:!1,confirmed:!0});let c=await i.getSettings("default"),l=me(n.enabled,{cmpId:n.cmpId,cmpVersion:n.cmpVersion},c.gppConfirmation);return _(200,{enabled:n.enabled,cmpId:n.cmpId,cmpVersion:n.cmpVersion,confirmed:l,...c.gppConfirmation?{confirmedAt:c.gppConfirmation.confirmedAt,confirmedBy:c.gppConfirmation.confirmedBy}:{}})}),"POST /gpp/confirm-registration":async(s,r)=>w(async()=>{let{user:a,denied:c}=await o(s);if(c)return c;if(!n?.enabled)return g(400,"GPP is not enabled in the server config \u2014 nothing to confirm.");if(!(await b(s))?.acknowledge)return g(400,"acknowledge: true is required to confirm GPP registration.");let d=mt({cmpId:n.cmpId,cmpVersion:n.cmpVersion}),u=await i.updateSettings("default",{gppConfirmation:{configHash:d,confirmedAt:new Date().toISOString(),confirmedBy:a.sub}});return _(200,{confirmed:!0,gppConfirmation:u.gppConfirmation})})}}p();p();se();var ac=["mandatory","consent","legitimate_interest"],cc=["sale","sharing","sensitive"];function yu(i){if(!i||typeof i!="object"||Array.isArray(i))return{valid:!1,error:"cookies must be an object keyed by parameter id"};for(let[e,t]of Object.entries(i)){if(!e.trim())return{valid:!1,error:"cookie id must be non-empty"};if(!t||typeof t!="object")return{valid:!1,error:`cookies["${e}"] must be an object`};let n=t;if(!un.includes(n.purpose))return{valid:!1,error:`cookies["${e}"].purpose must be one of: ${un.join(", ")}`};if(typeof n.listenGpc!="boolean")return{valid:!1,error:`cookies["${e}"].listenGpc must be a boolean`};if(n.preGrant!==void 0&&typeof n.preGrant!="boolean")return{valid:!1,error:`cookies["${e}"].preGrant must be a boolean`};if(n.cpraCategory!==void 0&&!cc.includes(n.cpraCategory))return{valid:!1,error:`cookies["${e}"].cpraCategory must be one of: ${cc.join(", ")}`}}return{valid:!0}}function _u(i){if(!i||typeof i!="object"||Array.isArray(i))return{valid:!1,error:"categories must be an object keyed by category id"};let e=Object.entries(i);if(e.length===0)return{valid:!1,error:"at least one category is required"};for(let[t,n]of e){if(!n||typeof n!="object")return{valid:!1,error:`categories["${t}"] must be an object`};let o=n;if(typeof o.heading!="string"||!o.heading.trim())return{valid:!1,error:`categories["${t}"].heading is required`};if(typeof o.htmlText!="string")return{valid:!1,error:`categories["${t}"].htmlText is required`};if(!ac.includes(o.legalBasis))return{valid:!1,error:`categories["${t}"].legalBasis must be one of: ${ac.join(", ")}`};if(!Array.isArray(o.cookies))return{valid:!1,error:`categories["${t}"].cookies must be an array of parameter ids`}}return{valid:!0}}function wu(i,e){let t=new Map;for(let n of Object.keys(i))t.set(n,0);for(let n of Object.values(e))for(let o of n.cookies)t.set(o,(t.get(o)??0)+1);for(let[n,o]of t){if(o===0)return{valid:!1,error:`Parameter "${n}" is not assigned to any category`};if(o>1)return{valid:!1,error:`Parameter "${n}" is assigned to more than one category`}}return{valid:!0}}function Eu(i,e){let t=new Map;for(let[o,s]of Object.entries(e))for(let r of s.cookies)t.set(r,o);let n=[];for(let[o,s]of Object.entries(i)){let r=t.get(o);if(!r)continue;let a=e[r].legalBasis,c=s.purpose;if(a==="mandatory"&&c!=="necessary")return{valid:!1,error:`Parameter "${o}" has purpose "${c??"unknown"}" but is assigned to a Strictly Necessary category \u2014 this grants a tracking parameter with no consent gate.`};a!=="mandatory"&&c==="necessary"&&n.push(`Parameter "${o}" has purpose "necessary" but is assigned to a non-mandatory category \u2014 this may break site functionality since it can be denied.`)}return{valid:!0,...n.length>0?{warnings:n}:{}}}function ji(i,e){let t=yu(i);if(!t.valid)return t;let n=_u(e);if(!n.valid)return n;let o=i,s=e,r=wu(o,s);return r.valid?Eu(o,s):r}function lc(i,e,t,n="default"){async function o(s,r){let a=await O(s,i,e,t);return{user:a,denied:k(a,r)}}return{"GET /consent-templates":async s=>w(async()=>{let{denied:r}=await o(s,"profile:view");return r||_(200,await i.getConsentTemplates(n))}),"GET /consent-templates/:id":async(s,r)=>w(async()=>{let{denied:a}=await o(s,"profile:view");if(a)return a;let c=await i.getConsentTemplate(r.id);return c?_(200,c):g(404,"Consent template not found")}),"POST /consent-templates":async s=>w(async()=>{let{denied:r}=await o(s,"profile:create");if(r)return r;let a=await b(s);if(!a?.name||typeof a.name!="string")return g(400,"name is required");let c=ji(a.cookies,a.categories);if(!c.valid)return g(400,c.error);let l=await i.createConsentTemplate({tenantId:n,name:a.name,cookies:a.cookies,categories:a.categories});return _(201,l)}),"PUT /consent-templates/:id":async(s,r)=>w(async()=>{let{denied:a}=await o(s,"profile:update");if(a)return a;let c=r.id,l=await b(s),d=await i.getConsentTemplate(c);if(!d)return g(404,"Consent template not found");let u={};l?.name!==void 0&&typeof l.name=="string"&&(u.name=l.name);let m=l?.cookies!==void 0,f=l?.categories!==void 0,S=m?l.cookies:d.cookies,y=f?l.categories:d.categories;if(m||f){let R=ji(S,y);if(!R.valid)return g(400,R.error);m&&(u.cookies=S),f&&(u.categories=y);let v=await i.findProfilesUsingConsentTemplate(c),A=[];for(let T of v){if(!T.complianceGroup)continue;Ke(S,y,T.complianceGroup).valid||A.push({id:T.id,name:T.name,complianceGroup:T.complianceGroup})}if(A.length>0)return g(422,"This change would break compliance for affected profiles",{blockingProfiles:A})}let E=await i.updateConsentTemplate(c,u);return _(200,E)}),"DELETE /consent-templates/:id":async(s,r)=>w(async()=>{let{denied:a}=await o(s,"profile:delete");if(a)return a;let c=r.id,l=await i.findProfilesUsingConsentTemplate(c);return l.length>0?g(422,"Cannot delete: template is used by profiles",{profiles:l.map(d=>({id:d.id,name:d.name,isActive:d.isActive}))}):(await i.deleteConsentTemplate(c),_(200,{ok:!0}))}),"POST /consent-templates/:id/copy":async(s,r)=>w(async()=>{let{denied:a}=await o(s,"profile:create");if(a)return a;let c=await b(s),l=await i.getConsentTemplate(r.id);if(!l)return g(404,"Consent template not found");let d=typeof c?.name=="string"&&c.name.trim()?c.name.trim():`${l.name} (Copy)`,u=await i.copyConsentTemplate(r.id,d);return _(201,u)}),"GET /consent-templates/:id/profile-usage":async(s,r)=>w(async()=>{let{denied:a}=await o(s,"profile:view");if(a)return a;let c=await i.findProfilesUsingConsentTemplate(r.id);return _(200,c)})}}p();function dc(i,e,t,n="default"){async function o(s,r){let a=await O(s,i,e,t);return{user:a,denied:k(a,r)}}return{"GET /ui-templates":async s=>w(async()=>{let{denied:r}=await o(s,"profile:view");return r||_(200,await i.getUITemplates(n))}),"GET /ui-templates/:id":async(s,r)=>w(async()=>{let{denied:a}=await o(s,"profile:view");if(a)return a;let c=await i.getUITemplate(r.id);return c?_(200,c):g(404,"UI template not found")}),"POST /ui-templates":async s=>w(async()=>{let{denied:r}=await o(s,"profile:create");if(r)return r;let a=await b(s);if(!a?.name||typeof a.name!="string")return g(400,"name is required");if(!a.mainBanner||!a.gpcBanner||!a.preferenceModal)return g(400,"mainBanner, gpcBanner, and preferenceModal are required");let c=await i.createUITemplate({tenantId:n,name:a.name,mainBanner:a.mainBanner,gpcBanner:a.gpcBanner,preferenceModal:a.preferenceModal});return _(201,c)}),"PUT /ui-templates/:id":async(s,r)=>w(async()=>{let{denied:a}=await o(s,"profile:update");if(a)return a;let c=await b(s),l={};typeof c?.name=="string"&&(l.name=c.name),c?.mainBanner&&(l.mainBanner=c.mainBanner),c?.gpcBanner&&(l.gpcBanner=c.gpcBanner),c?.preferenceModal&&(l.preferenceModal=c.preferenceModal);let d=await i.updateUITemplate(r.id,l);return _(200,d)}),"DELETE /ui-templates/:id":async(s,r)=>w(async()=>{let{denied:a}=await o(s,"profile:delete");if(a)return a;let c=r.id,l=await i.findProfilesUsingUITemplate(c);return l.length>0?g(422,"Cannot delete: template is used by profiles",{profiles:l.map(d=>({id:d.id,name:d.name,isActive:d.isActive}))}):(await i.deleteUITemplate(c),_(200,{ok:!0}))}),"POST /ui-templates/:id/copy":async(s,r)=>w(async()=>{let{denied:a}=await o(s,"profile:create");if(a)return a;let c=await b(s),l=await i.getUITemplate(r.id);if(!l)return g(404,"UI template not found");let d=typeof c?.name=="string"&&c.name.trim()?c.name.trim():`${l.name} (Copy)`,u=await i.copyUITemplate(r.id,d);return _(201,u)}),"GET /ui-templates/:id/profile-usage":async(s,r)=>w(async()=>{let{denied:a}=await o(s,"profile:view");if(a)return a;let c=await i.findProfilesUsingUITemplate(r.id);return _(200,c)})}}p();function uc(i,e,t,n="default"){async function o(s,r){let a=await O(s,i,e,t);return{user:a,denied:k(a,r)}}return{"GET /analytics/opt-in":async(s,r)=>w(async()=>{let{denied:a}=await o(s,"stats:view");if(a)return a;let c=new URL(s.url),l=c.searchParams.get("tenantId")??n,d={},u=c.searchParams.get("profileId"),m=c.searchParams.get("complianceGroup"),f=c.searchParams.get("from"),S=c.searchParams.get("to"),y=c.searchParams.get("locale");u&&(d.profileId=u),m&&(d.complianceGroup=m),f&&(d.from=f),S&&(d.to=S),y&&(d.locale=y);let E=await i.getOptInStats(l,d);return _(200,E)})}}p();se();p();var Ee="\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022";function pc(i){let e=i.storage,t=i.auth,n=i.compliance,o=i.dashboard;return{basePath:i.basePath,dashboard:typeof o=="object"?{enabled:o.enabled,path:o.path}:o,...e?{storage:{driver:e.driver,...e.path!==void 0?{path:e.path}:{},...e.uri!==void 0?{uri:Ee}:{},...e.database!==void 0?{database:e.database}:{},...e.host!==void 0?{host:e.host}:{},...e.port!==void 0?{port:e.port}:{},...e.user!==void 0?{user:e.user}:{},...e.password!==void 0?{password:Ee}:{},...e.poolMax!==void 0?{poolMax:e.poolMax}:{},...e.statementTimeoutMs!==void 0?{statementTimeoutMs:e.statementTimeoutMs}:{},...e.idleInTransactionTimeoutMs!==void 0?{idleInTransactionTimeoutMs:e.idleInTransactionTimeoutMs}:{}}}:{},...t?{auth:{mode:t.mode,...t.adminEmail!==void 0?{adminEmail:t.adminEmail}:{},...t.adminPassword!==void 0?{adminPassword:Ee}:{},...t.masterSecret!==void 0?{masterSecret:Ee}:{},...t.oidc?{oidc:{issuer:t.oidc.issuer,clientId:t.oidc.clientId,clientSecret:Ee,redirectUri:t.oidc.redirectUri}}:{},...t.saml?{saml:{issuer:t.saml.issuer,entryPoint:t.saml.entryPoint,cert:Ee,callbackUrl:t.saml.callbackUrl}}:{}}}:{},...i.rateLimit?{rateLimit:i.rateLimit}:{},...n?{compliance:{...n.type!==void 0?{type:n.type}:{},...n.gpc!==void 0?{gpc:n.gpc}:{},...n.geoDataProvider!==void 0?{geoDataProvider:typeof n.geoDataProvider=="function"?"<custom function>":n.geoDataProvider}:{},...n.complianceMap!==void 0?{complianceMap:typeof n.complianceMap=="object"?`<custom map, ${Object.keys(n.complianceMap.countries).length} countries, ${n.complianceMap.override===!1?"merged over":"replaces"} the embedded map>`:n.complianceMap}:{},...n.tcf?{tcf:n.tcf}:{},...n.gpp?{gpp:n.gpp}:{},...n.dataRetention?{dataRetention:n.dataRetention}:{},...n.parentalConsentTokenTtlDays!==void 0?{parentalConsentTokenTtlDays:n.parentalConsentTokenTtlDays}:{},...n.dataSigningHash!==void 0?{dataSigningHash:Ee}:{}}}:{},...i.multiTenant?{multiTenant:i.multiTenant}:{},...i.plugins?{plugins:{count:i.plugins.length}}:{},...i.maxBodySize!==void 0?{maxBodySize:i.maxBodySize}:{},...i.trustedProxies?{trustedProxies:i.trustedProxies}:{},...i.branding?{branding:i.branding}:{},...i.s3Api?{s3Api:{enabled:i.s3Api.enabled,region:i.s3Api.region,bucketName:i.s3Api.bucketName,accessKeyId:Ee,secretAccessKey:Ee}}:{}}}function mc(i,e,t,n,o,s){async function r(c){let l=await O(c,e,t,n);return{denied:k(l,"settings:update")}}async function a(){return(await e.getSettings("default")).setupCompleted===!0?g(409,"Setup has already been completed"):null}return{"GET /setup/status":async(c,l)=>w(async()=>{let{denied:d}=await r(c);if(d)return d;let u=await e.getSettings("default");return _(200,{completed:u.setupCompleted===!0})}),"GET /setup/config":async(c,l)=>w(async()=>{let{denied:d}=await r(c);return d||_(200,{config:pc(o),...s})}),"GET /setup/compliance-groups":async(c,l)=>w(async()=>{let{denied:d}=await r(c);if(d)return d;let u=dn.map(m=>({id:m,...dt[m]}));return _(200,u)}),"POST /setup/seed-profiles":async(c,l)=>w(async()=>{let{denied:d}=await r(c);if(d)return d;let u=await a();if(u)return u;let f=(await b(c))?.groups;if(!Array.isArray(f)||f.some(y=>typeof y!="string"))return g(400,"groups must be an array of compliance group ids");let S=f.filter(y=>!dn.includes(y));return S.length>0?g(400,`Unknown compliance group id(s): ${S.join(", ")}`):(await Promise.all(f.map(y=>i.seedDefaultProfile(y))),await e.updateSettings("default",{profilesSeeded:!0}),_(200,{seeded:f}))}),"POST /setup/complete":async(c,l)=>w(async()=>{let{denied:d}=await r(c);if(d)return d;let u=await a();if(u)return u;if((await e.getSettings("default")).profilesSeeded!==!0)return g(409,"POST /setup/seed-profiles must be called at least once (an empty groups: [] call is a valid pass) before setup can be completed");let f=await e.updateSettings("default",{setupCompleted:!0});return _(200,f)})}}p();var gc=require("node:crypto");async function fc(i,e,t){let n=i.headers.get("authorization");if(!n?.startsWith("Bearer ck_"))return t;let o=n.slice(7),s=(0,gc.createHash)("sha256").update(o).digest("hex"),r=await e.getApiKeyByHash(s);return!r||!r.isActive?t:r.expireBy&&new Date(r.expireBy)<=new Date?(await e.revokeApiKey(r.id).catch(()=>{}),t):r.tenantId}p();var Et=class{constructor(e=6e4,t=60){this.windowMs=e;this.maxRequests=t;setInterval(()=>{let n=Date.now();for(let[o,s]of this.store)n>=s.resetAt&&this.store.delete(o)},this.windowMs).unref()}windowMs;maxRequests;store=new Map;check(e){let t=Date.now(),n=this.store.get(e);return!n||t>=n.resetAt?(this.store.set(e,{count:1,resetAt:t+this.windowMs}),!0):(n.count+=1,n.count<=this.maxRequests)}checkRequest(e,t){return this.check(`ip:${e}`)?t?this.check(`profile:${t}`):!0:!1}};se();p();p();var On=class{constructor(e){this.options=e;e.eventBus.on("consent:created",this.onCreated),e.eventBus.on("consent:updated",this.onUpdated)}options;onCreated=e=>this.fire(e,void 0);onUpdated=({previous:e,current:t})=>this.fire(t,e);fire(e,t){let n=e.consentJson[this.options.id]??"denied",o=t?.consentJson[this.options.id]??"denied";if(n===o)return;let s={visitorId:e.visitorId,cookieId:this.options.id,status:n,record:e};n==="granted"?this.options.onGrant?.(s):this.options.onDeny?.(s)}destroy(){this.options.eventBus.off("consent:created",this.onCreated),this.options.eventBus.off("consent:updated",this.onUpdated)}};p();function hc(i,e){return e.length>0&&e.every(t=>i[t]==="granted")}var Dn=class{constructor(e){this.options=e;e.eventBus.on("consent:created",this.onCreated),e.eventBus.on("consent:updated",this.onUpdated)}options;onCreated=e=>{this.fire(e,void 0)};onUpdated=({previous:e,current:t})=>{this.fire(t,e)};async fire(e,t){let o=(await this.options.profiles.getResolved(e.profileId))?.preferenceModal.categories[this.options.categoryId]?.cookies??[];if(o.length===0)return;let s=hc(e.consentJson,o)?"granted":"denied",r=t&&hc(t.consentJson,o)?"granted":"denied";if(s===r)return;let a={visitorId:e.visitorId,categoryId:this.options.categoryId,status:s,record:e};s==="granted"?this.options.onGrant?.(a):this.options.onDeny?.(a)}destroy(){this.options.eventBus.off("consent:created",this.onCreated),this.options.eventBus.off("consent:updated",this.onUpdated)}};var Bi=(0,V.dirname)((0,$i.fileURLToPath)(h)),Ru=(0,$i.fileURLToPath)(new URL("./dashboard",h)),Sc={".html":"text/html; charset=utf-8",".js":"application/javascript; charset=utf-8",".mjs":"application/javascript; charset=utf-8",".css":"text/css; charset=utf-8",".json":"application/json",".png":"image/png",".svg":"image/svg+xml",".ico":"image/x-icon",".woff2":"font/woff2",".woff":"font/woff",".ttf":"font/ttf"};async function Su(i,e,t,n,o){let s=i.slice(e.length)||"/";if(s.startsWith("/api/")||s.startsWith("/admin/"))return!1;let r=s==="/"||s===""||!(0,V.extname)(s)?(0,V.join)(t,"index.html"):(0,V.join)(t,s);if(!r.startsWith(t))return!1;try{let a=await(0,Ye.readFile)(r),c=(0,V.extname)(r).toLowerCase(),l=c===".html"||c==="",d=Sc[c]??"application/octet-stream";return n.writeHead(200,{"Content-Type":d}),n.end(l?Ze(a,o):a),!0}catch{return!1}}async function yc(i,e){try{let t=await(0,Ye.readFile)(i);return new Response(t,{headers:{"Content-Type":e,"Cache-Control":"public, max-age=3600"}})}catch{return new Response("Not Found",{status:404})}}function vu(i){let e=[],t=i.split("/").map(n=>n.startsWith(":")?(e.push(n.slice(1)),"([^/]+)"):n.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"));return{pattern:new RegExp(`^${t.join("\\/")}$`),paramNames:e}}function Cu(i){let t=`<!DOCTYPE html>
160
162
  <html lang="en">
161
163
  <head>
162
164
  <meta charset="UTF-8">
@@ -191,13 +193,13 @@ ${l.map(d=>` (${se(c)},${se(d)})`).join(`,
191
193
  </a>
192
194
  </div>
193
195
  </body>
194
- </html>`;return new Response(t,{status:404,headers:{"Content-Type":"text/html; charset=utf-8"}})}function Jd(i,e,t,n,o){let s=[];for(let r of e)for(let[a,c]of Object.entries(r.routes)){let l=a.indexOf(" "),d=a.slice(0,l).toUpperCase(),u=a.slice(l+1),{pattern:m,paramNames:h}=Wd(`${r.prefix}${u}`);s.push({method:d,pattern:m,paramNames:h,handler:c,rateLimit:r.rateLimit??!1,originCheck:r.originCheck??!1})}return async r=>{let a=jr(r);if(a)return a;let l=new URL(r.url).pathname,d=r.method.toUpperCase();if(t&&s.find(h=>h.rateLimit&&l.match(h.pattern))){let h=r.headers.get("x-real-ip")??"";if(!t.checkRequest(h))return dt(g(429,"Too Many Requests"),r)}for(let m of s){if(m.method!==d)continue;let h=l.match(m.pattern);if(!h)continue;if(m.originCheck){let w=await o(r),{adminAllowedOrigins:R}=await n.getSettings(w);if(!_n(r,R??[]))return dt(g(403,"Origin not allowed for the admin API"),r)}let S={};m.paramNames.forEach((w,R)=>{let C=h[R+1];C!=null&&(S[w]=C)});let _=await m.handler(r,S);return hi(dt(_,r))}let u=l.startsWith(i)&&!l.startsWith(`${i}/api/`)&&!l.startsWith(`${i}/admin/`);return hi(dt(u?qd(i):g(404,"Not Found"),r))}}function Va(i){return typeof i=="object"&&i!==null&&!Array.isArray(i)}function Ka(i,e){let t={...i};for(let n of Object.keys(e)){let o=e[n],s=t[n];o!==void 0&&Va(o)&&Va(s)?t[n]=Ka(s,o):o!==void 0&&(t[n]=o)}return t}var zd={dashboard:!0,basePath:process.env.CONSENTI_BASE_PATH??"/consenti",...process.env.CONSENTI_MAX_BODY_SIZE?{maxBodySize:Number(process.env.CONSENTI_MAX_BODY_SIZE)}:{},storage:{driver:process.env.CONSENTI_DB_DRIVER??"json",path:process.env.CONSENTI_DB_PATH??"./consenti-data.json",...process.env.CONSENTI_DB_URI?{uri:process.env.CONSENTI_DB_URI}:{},...process.env.CONSENTI_DB_DATABASE?{database:process.env.CONSENTI_DB_DATABASE}:{},...process.env.CONSENTI_DB_HOST?{host:process.env.CONSENTI_DB_HOST}:{},...process.env.CONSENTI_DB_PORT?{port:Number(process.env.CONSENTI_DB_PORT)}:{},...process.env.CONSENTI_DB_USER?{user:process.env.CONSENTI_DB_USER}:{},...process.env.CONSENTI_DB_PASSWORD?{password:process.env.CONSENTI_DB_PASSWORD}:{}},auth:{mode:"local",adminEmail:process.env.CONSENTI_ADMIN_EMAIL??"user@consenti.dev",adminPassword:process.env.CONSENTI_ADMIN_PASSWORD??"Consenti@123",...process.env.CONSENTI_ADMIN_MASTER_SECRET?{masterSecret:process.env.CONSENTI_ADMIN_MASTER_SECRET}:{}},...process.env.CONSENTI_DATA_SIGNING_HASH?{compliance:{dataSigningHash:process.env.CONSENTI_DATA_SIGNING_HASH}}:{},rateLimit:{windowMs:process.env.CONSENTI_RATE_LIMIT_WINDOW_MS?Number(process.env.CONSENTI_RATE_LIMIT_WINDOW_MS):6e4,maxRequests:process.env.CONSENTI_RATE_LIMIT_MAX_REQUESTS?Number(process.env.CONSENTI_RATE_LIMIT_MAX_REQUESTS):60},branding:{appLogoPath:"./logo-dark.svg",appName:"Consenti",hidePoweredBy:!1}};function Wa(){return(0,Ja.randomBytes)(32).toString("hex")}function Kd(i){switch(i.driver){case"mongodb":return new Me(i);case"mysql":return new Ge(i);case"postgresql":return new je(i);case"node:sqlite":return new vt(i);case"better-sqlite3":case"sqlite":return new Ie(i);case"node-sqlite3-wasm":return new Ct(i);default:return new Lt(i)}}function Yd(i){let e=Ka(zd,i),t=e.storage?.driver==="json",n=!i.auth&&!process.env.CONSENTI_ADMIN_PASSWORD;if(process.env.NODE_ENV==="production"){let L=[];if(n&&L.push('auth.adminPassword / CONSENTI_ADMIN_PASSWORD (currently the published default "Consenti@123")'),e.auth?.masterSecret||L.push("auth.masterSecret / CONSENTI_ADMIN_MASTER_SECRET"),e.compliance?.dataSigningHash||L.push("compliance.dataSigningHash / CONSENTI_DATA_SIGNING_HASH"),L.length>0)throw new Error(`[Consenti] Refusing to boot with NODE_ENV=production while unset or default: ${L.join("; ")}. These are fine to leave auto-generated for a local trial, but not for production \u2014 set them explicitly. See SECURITY.md.`)}t&&console.warn("[Consenti] Using the JSON file storage driver \u2014 fine for development, but switch to a database driver (node:sqlite, postgresql, mysql, mongodb) for production. Set storage.driver or CONSENTI_DB_DRIVER."),n&&console.warn("[Consenti] No auth config or CONSENTI_ADMIN_PASSWORD env var \u2014 using demo credentials. Set CONSENTI_ADMIN_EMAIL and CONSENTI_ADMIN_PASSWORD before going to production.");let o=e.storage,s=e.auth;s.masterSecret||(s.masterSecret=Wa(),console.warn("[Consenti] auth.masterSecret not set \u2014 generated a random one for this process. Admin sessions will be invalidated on every restart. Set auth.masterSecret or CONSENTI_ADMIN_MASTER_SECRET for production."));let a=me(o.path??"./consenti-data",o.driver??"json").profilesDir,c=Kd(o),l=new qa.EventEmitter,d=new Nt(c),u=new Ut(c),m=new xt(c),h=new Mt(c),S=new Gt(c),_=new Ft(c),w=new Bt(c),R=new Et;e.plugins?.length&&R.register(e.plugins),e.compliance||(e.compliance={});let C=e.compliance;C.dataSigningHash||(C.dataSigningHash=Wa(),console.warn("[Consenti] compliance.dataSigningHash not set \u2014 generated a random one for this process. Ownership cookies, parental-consent tokens, and stored consent-record signatures will all be invalidated on every restart. Set compliance.dataSigningHash or CONSENTI_DATA_SIGNING_HASH for production."));let A=C.type??"auto",T=A==="auto",O=e.localeJsonCache?.enabled?new an(e.localeJsonCache.dir):void 0,D=T?new rn(C.geoDataProvider??"default",De):void 0,G=D?lr(C.complianceMap,D):void 0;A==="auto"&&!C.geoDataProvider&&console.info("[Consenti] compliance.geoDataProvider not set \u2014 defaulting to timezone+language heuristic"),A!=="auto"&&C.geoDataProvider&&console.warn("[Consenti] compliance.geoDataProvider is ignored when compliance.type is a fixed group"),A!=="auto"&&C.complianceMap&&console.warn("[Consenti] compliance.complianceMap is ignored when compliance.type is a fixed group");let N=new sn(d,S,"default",c,l,O,a,e.handleCache,e.s3Api),ce=new pn(m,"default",l,C.dataSigningHash),oe=new mn(h,"default"),qe=new un(u,m,d,S,"default",e.compliance,R,l,C.tcf,c,C.dataSigningHash,C.gpp),Ai=new gn(_,S),B=s.masterSecret??"",Ti=new fn(c,B),vn=e.rateLimit,Ya=vn.enabled===!1?null:new gt(vn.windowMs,vn.maxRequests),Qa=new gt(15*6e4,10),Ii=e.multiTenant?.enabled===!0?L=>Fa(L,c,"default"):async L=>"default",$=e.basePath,Pi=`${$}/api/v1`,bi=`${$}/admin/v1`,An=`${$}/api`,ft=!!e.dashboard,Se=(0,V.join)(Ci,"dashboard"),ht=ft?Gi(Mi(Se,$,e.branding,e.compliance,s.mode)):"",Oi=`<!DOCTYPE html><html><head><title>Consenti API Docs</title>
196
+ </html>`;return new Response(t,{status:404,headers:{"Content-Type":"text/html; charset=utf-8"}})}function Au(i,e,t,n,o){let s=[];for(let r of e)for(let[a,c]of Object.entries(r.routes)){let l=a.indexOf(" "),d=a.slice(0,l).toUpperCase(),u=a.slice(l+1),{pattern:m,paramNames:f}=vu(`${r.prefix}${u}`);s.push({method:d,pattern:m,paramNames:f,handler:c,rateLimit:r.rateLimit??!1,originCheck:r.originCheck??!1})}return async r=>{let a=pa(r);if(a)return a;let l=new URL(r.url).pathname,d=r.method.toUpperCase();if(t&&s.find(f=>f.rateLimit&&l.match(f.pattern))){let f=r.headers.get("x-real-ip")??"";if(!t.checkRequest(f))return ht(g(429,"Too Many Requests"),r)}for(let m of s){if(m.method!==d)continue;let f=l.match(m.pattern);if(!f)continue;if(m.originCheck){let E=await o(r),{adminAllowedOrigins:R}=await n.getSettings(E);if(!Tn(r,R??[]))return ht(g(403,"Origin not allowed for the admin API"),r)}let S={};m.paramNames.forEach((E,R)=>{let v=f[R+1];v!=null&&(S[E]=v)});let y=await m.handler(r,S);return Li(ht(y,r))}let u=l.startsWith(i)&&!l.startsWith(`${i}/api/`)&&!l.startsWith(`${i}/admin/`);return Li(ht(u?Cu(i):g(404,"Not Found"),r))}}function _c(i){return typeof i=="object"&&i!==null&&!Array.isArray(i)}function vc(i,e){let t={...i};for(let n of Object.keys(e)){let o=e[n],s=t[n];o!==void 0&&_c(o)&&_c(s)?t[n]=vc(s,o):o!==void 0&&(t[n]=o)}return t}var Tu={dashboard:!0,basePath:process.env.CONSENTI_BASE_PATH??"/consenti",...process.env.CONSENTI_MAX_BODY_SIZE?{maxBodySize:Number(process.env.CONSENTI_MAX_BODY_SIZE)}:{},storage:{driver:process.env.CONSENTI_DB_DRIVER??"json",path:process.env.CONSENTI_DB_PATH??"./consenti-data.json",...process.env.CONSENTI_DB_URI?{uri:process.env.CONSENTI_DB_URI}:{},...process.env.CONSENTI_DB_DATABASE?{database:process.env.CONSENTI_DB_DATABASE}:{},...process.env.CONSENTI_DB_HOST?{host:process.env.CONSENTI_DB_HOST}:{},...process.env.CONSENTI_DB_PORT?{port:Number(process.env.CONSENTI_DB_PORT)}:{},...process.env.CONSENTI_DB_USER?{user:process.env.CONSENTI_DB_USER}:{},...process.env.CONSENTI_DB_PASSWORD?{password:process.env.CONSENTI_DB_PASSWORD}:{}},auth:{mode:"local",adminEmail:process.env.CONSENTI_ADMIN_EMAIL??"user@consenti.dev",adminPassword:process.env.CONSENTI_ADMIN_PASSWORD??"Consenti@123",...process.env.CONSENTI_ADMIN_MASTER_SECRET?{masterSecret:process.env.CONSENTI_ADMIN_MASTER_SECRET}:{}},...process.env.CONSENTI_DATA_SIGNING_HASH?{compliance:{dataSigningHash:process.env.CONSENTI_DATA_SIGNING_HASH}}:{},rateLimit:{windowMs:process.env.CONSENTI_RATE_LIMIT_WINDOW_MS?Number(process.env.CONSENTI_RATE_LIMIT_WINDOW_MS):6e4,maxRequests:process.env.CONSENTI_RATE_LIMIT_MAX_REQUESTS?Number(process.env.CONSENTI_RATE_LIMIT_MAX_REQUESTS):60},branding:{appLogoPath:"./logo-dark.svg",appName:"Consenti",hidePoweredBy:!1}};function wc(){return(0,Rc.randomBytes)(32).toString("hex")}function Iu(i){switch(i.driver){case"mongodb":return new Fe(i);case"mysql":return new He(i);case"postgresql":return new Ve(i);case"node:sqlite":return new Dt(i);case"better-sqlite3":case"sqlite":return new De(i);case"node-sqlite3-wasm":return new Ot(i);default:return new Bt(i)}}function Pu(i){let e=vc(Tu,i),t=e.storage?.driver==="json",n=!i.auth&&!process.env.CONSENTI_ADMIN_PASSWORD;if(process.env.NODE_ENV==="production"){let D=[];if(n&&D.push('auth.adminPassword / CONSENTI_ADMIN_PASSWORD (currently the published default "Consenti@123")'),e.auth?.masterSecret||D.push("auth.masterSecret / CONSENTI_ADMIN_MASTER_SECRET"),e.compliance?.dataSigningHash||D.push("compliance.dataSigningHash / CONSENTI_DATA_SIGNING_HASH"),D.length>0)throw new Error(`[Consenti] Refusing to boot with NODE_ENV=production while unset or default: ${D.join("; ")}. These are fine to leave auto-generated for a local trial, but not for production \u2014 set them explicitly. See SECURITY.md.`)}t&&console.warn("[Consenti] Using the JSON file storage driver \u2014 fine for development, but switch to a database driver (node:sqlite, postgresql, mysql, mongodb) for production. Set storage.driver or CONSENTI_DB_DRIVER."),n&&console.warn("[Consenti] No auth config or CONSENTI_ADMIN_PASSWORD env var \u2014 using demo credentials. Set CONSENTI_ADMIN_EMAIL and CONSENTI_ADMIN_PASSWORD before going to production.");let o=e.storage,s=e.auth;s.masterSecret||(s.masterSecret=wc(),console.warn("[Consenti] auth.masterSecret not set \u2014 generated a random one for this process. Admin sessions will be invalidated on every restart. Set auth.masterSecret or CONSENTI_ADMIN_MASTER_SECRET for production."));let a=fe(o.path??"./consenti-data",o.driver??"json").profilesDir,c=Iu(o),l=new Ec.EventEmitter,d=new $t(c),u=new Ft(c),m=new Ht(c),f=new Vt(c),S=new Wt(c),y=new zt(c),E=new Jt(c),R=new Tt;e.plugins?.length&&R.register(e.plugins),e.compliance||(e.compliance={});let v=e.compliance;v.dataSigningHash||(v.dataSigningHash=wc(),console.warn("[Consenti] compliance.dataSigningHash not set \u2014 generated a random one for this process. Ownership cookies, parental-consent tokens, and stored consent-record signatures will all be invalidated on every restart. Set compliance.dataSigningHash or CONSENTI_DATA_SIGNING_HASH for production."));let A=v.type??"auto",T=A==="auto",P=e.localeJsonCache?.enabled?new fn(e.localeJsonCache.dir):void 0,x=T?new gn(v.geoDataProvider??"default",Ce):void 0,L=x?Nr(v.complianceMap,x):void 0;A==="auto"&&!v.geoDataProvider&&console.info("[Consenti] compliance.geoDataProvider not set \u2014 defaulting to timezone+language heuristic"),A!=="auto"&&v.geoDataProvider&&console.warn("[Consenti] compliance.geoDataProvider is ignored when compliance.type is a fixed group"),A!=="auto"&&v.complianceMap&&console.warn("[Consenti] compliance.complianceMap is ignored when compliance.type is a fixed group");let N=new mn(d,S,"default",c,l,P,a,e.handleCache,e.s3Api),z=new En(m,"default",l,v.dataSigningHash),re=new Rn(f,"default"),Qe=new wn(u,m,d,S,"default",e.compliance,R,l,v.tcf,c,v.dataSigningHash,v.gpp,(D,M)=>N.getArchivedSnapshot(D,M)),Fi=new Sn(y,S),B=s.masterSecret??"",Hi=new vn(c,B),kn=e.rateLimit,Cc=kn.enabled===!1?null:new Et(kn.windowMs,kn.maxRequests),Ac=new Et(15*6e4,10),Vi=e.multiTenant?.enabled===!0?D=>fc(D,c,"default"):async D=>"default",F=e.basePath,Wi=`${F}/api/v1`,qi=`${F}/admin/v1`,Ln=`${F}/api`,Rt=!!e.dashboard,Te=(0,V.join)(Bi,"dashboard"),St=Rt?to(eo(Te,F,e.branding,e.compliance,s.mode)):"",Ji=`<!DOCTYPE html><html><head><title>Consenti API Docs</title>
195
197
  <link rel="stylesheet" href="https://unpkg.com/swagger-ui-dist@5.17.14/swagger-ui.css" crossorigin="anonymous"></head>
196
198
  <body><div id="swagger-ui"></div>
197
199
  <script src="https://unpkg.com/swagger-ui-dist@5.17.14/swagger-ui-bundle.js" crossorigin="anonymous"></script>
198
200
  <script src="https://unpkg.com/swagger-ui-dist@5.17.14/swagger-ui-standalone-preset.js" crossorigin="anonymous"></script>
199
- <script>SwaggerUIBundle({urls:[{url:'${An}/openapi.json',name:'Public API (/consenti/api)'},{url:'${An}/openapi-admin.json',name:'Admin API (/consenti/admin)'}],'urls.primaryName':'Public API (/consenti/api)',dom_id:'#swagger-ui',presets:[SwaggerUIBundle.presets.apis,SwaggerUIStandalonePreset],layout:'StandaloneLayout'})</script>
200
- </body></html>`,Za=`User-agent: *
201
- Disallow: ${$}/
202
- `,Di=Jd($,[{prefix:An,rateLimit:!1,routes:{"GET /docs":async()=>new Response(Oi,{headers:{"Content-Type":"text/html; charset=utf-8"}}),"GET /openapi.json":async()=>new Response(JSON.stringify(On,null,2),{headers:{"Content-Type":"application/json"}}),"GET /openapi-admin.json":async()=>new Response(JSON.stringify(Dn,null,2),{headers:{"Content-Type":"application/json"}})}},{prefix:"",rateLimit:!1,routes:{"GET /robots.txt":async()=>new Response(Za,{headers:{"Content-Type":"text/plain; charset=utf-8"}})}},{prefix:Pi,rateLimit:!0,routes:{...Dr(N,D,a,Pi),...Wr(qe,ce,N,Ii,c,C.dataSigningHash,l,C.parentalConsentTokenTtlDays??7),...qr(oe),...Jr(c,C.tcf),...zr(c,C.gpp)}},{prefix:bi,rateLimit:!1,routes:{"GET /widget.js":async()=>Ha((0,V.join)(Ci,"widget","widget.js"),"application/javascript; charset=utf-8"),"GET /widget.css":async()=>Ha((0,V.join)(Ci,"widget","widget.css"),"text/css; charset=utf-8")}},{prefix:bi,rateLimit:!1,originCheck:!0,routes:{...pa(Ti,c,s,B,Qa),...wa(N,c,s,B),...Ea(c,s,B),...Ra(c,s,B),...Ca(Ai,c,s,B),...va(c,s,B),...Aa(c,s,B),...Ta(c,w,s,B),...Ia(c,s,B,N),...Pa(c,s,B),...ba(c,s,B),...Oa(c,s,B),...Da(c,s,B,C.tcf),...ka(c,s,B,C.gpp),...Ua(c,s,B),...xa(c,s,B),...Ma(c,s,B),...ja(N,c,s,B,e,{usingJsonStorage:t,usingDefaultCredentials:n})}}],Ya,c,Ii),Tn=null,ki,Li,Xa=new Promise((L,x)=>{ki=L,Li=x});c.connect().then(async()=>{if(s.mode==="local"&&s.adminEmail&&s.adminPassword&&await Ti.bootstrap(s.adminEmail,s.adminPassword),await R.initialize({storage:c,config:e}),l.emit("ready"),ki(),C.tcf?.enabled&&(Bi(),Hi()),C.dataRetention?.purgeAfterDays){let L=C.dataRetention.purgeAfterDays,x=()=>c.purgeExpiredConsents(L).then(W=>{W>0&&console.warn(`[consenti] Purged ${W} consent records older than ${L} days`)}).catch(W=>console.warn("[consenti] Data retention purge failed:",W));x(),Tn=setInterval(()=>{x()},1440*6e4)}}).catch(L=>{console.warn("[consenti] Storage connection failed:",L),Li(L)});async function In(L,x){try{let pe=L.headers["x-forwarded-proto"]==="https"?"https":"http",Ce=L.headers.host??"localhost",J=new URL(L.url??"/",`${pe}://${Ce}`);if(ft&&J.pathname.startsWith($)&&await Vd(J.pathname,$,Se,x,ht))return;let we=await Pr(L,e.maxBodySize,e.trustedProxies),yt=await Di(we);if(J.pathname===`${$}/api/openapi.json`){x.writeHead(200,{"Content-Type":"application/json"}),x.end(JSON.stringify(On,null,2));return}if(J.pathname===`${$}/api/openapi-admin.json`){x.writeHead(200,{"Content-Type":"application/json"}),x.end(JSON.stringify(Dn,null,2));return}if(J.pathname===`${$}/api/docs`){x.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),x.end(Oi);return}if(yt.status===404&&ft&&J.pathname.startsWith($)&&!J.pathname.startsWith($+"/api/")&&!J.pathname.startsWith($+"/admin/"))try{let _t=await(0,We.readFile)((0,V.join)(Se,"index.html"));x.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),x.end(Je(_t,ht));return}catch{}await br(yt,x)}catch(W){x.headersSent||(W instanceof ct?(x.writeHead(413,{"Content-Type":"application/json"}),x.end(JSON.stringify({error:"Payload Too Large"}))):(x.writeHead(500,{"Content-Type":"application/json"}),x.end(JSON.stringify({error:"Internal Server Error"}))))}}function ec(L,x,W){let Ce=L.headers["x-forwarded-proto"]==="https"?"https":"http",J=L.headers.host??"localhost",{pathname:we}=new URL(L.url??"/",`${Ce}://${J}`);if(we!=="/robots.txt"&&!we.startsWith($)){W();return}In(L,x).then(()=>{x.writableEnded||W()}).catch(W)}function tc(L,x){return In(L,x)}let Ni=async(L,x)=>{L.all("/*",async(W,pe)=>{await In(W.raw,pe.raw),pe.hijack()})};return Object.defineProperty(Ni,Symbol.for("skip-override"),{value:!0}),{router:ec,handler:tc,fastifyHandler:Ni,honoApp:{fetch:async L=>{if(ft){let W=new URL(L.url).pathname;if(W.startsWith($)){let pe=W.slice($.length)||"/";if(!pe.startsWith("/api/")&&!pe.startsWith("/admin/")){let Ce=(0,V.extname)(pe)?(0,V.join)(Se,pe):(0,V.join)(Se,"index.html");if(!Ce.startsWith(Se))return new Response("Forbidden",{status:403});try{let J=await(0,We.readFile)(Ce),we=(0,V.extname)(Ce).toLowerCase(),yt=we===".html"||we==="",_t=za[we]??"application/octet-stream",nc=yt?Je(J,ht):J;return new Response(nc,{headers:{"Content-Type":_t}})}catch{try{let J=await(0,We.readFile)((0,V.join)(Se,"index.html"));return new Response(Je(J,ht),{headers:{"Content-Type":"text/html; charset=utf-8"}})}catch{return new Response("Dashboard not built. Run: npm run build --workspace=apps/api",{status:404,headers:{"Content-Type":"text/plain"}})}}}}}return Di(L)}},services:{profile:N,consent:qe,visitor:ce,user:Ai},storage:c,eventBus:l,ready:Xa,destroy:async()=>{Tn&&clearInterval(Tn),w.dispose(),C.tcf?.enabled&&(Fi(),Vi()),G?.stop(),await R.destroy()}}}0&&(module.exports={CategoryAction,ConsentAction,MongoDBAdapter,MySQLAdapter,PostgreSQLAdapter,SQLiteAdapter,createConsenti,dashboardDir});
201
+ <script>SwaggerUIBundle({urls:[{url:'${Ln}/openapi.json',name:'Public API (/consenti/api)'},{url:'${Ln}/openapi-admin.json',name:'Admin API (/consenti/admin)'}],'urls.primaryName':'Public API (/consenti/api)',dom_id:'#swagger-ui',presets:[SwaggerUIBundle.presets.apis,SwaggerUIStandalonePreset],layout:'StandaloneLayout'})</script>
202
+ </body></html>`,Tc=`User-agent: *
203
+ Disallow: ${F}/
204
+ `,zi=Au(F,[{prefix:Ln,rateLimit:!1,routes:{"GET /docs":async()=>new Response(Ji,{headers:{"Content-Type":"text/html; charset=utf-8"}}),"GET /openapi.json":async()=>new Response(JSON.stringify(Gn,null,2),{headers:{"Content-Type":"application/json"}}),"GET /openapi-admin.json":async()=>new Response(JSON.stringify(jn,null,2),{headers:{"Content-Type":"application/json"}})}},{prefix:"",rateLimit:!1,routes:{"GET /robots.txt":async()=>new Response(Tc,{headers:{"Content-Type":"text/plain; charset=utf-8"}})}},{prefix:Wi,rateLimit:!0,routes:{...oa(N,x,a,Wi),..._a(Qe,z,N,Vi,c,v.dataSigningHash,l,v.parentalConsentTokenTtlDays??7),...wa(re),...Ea(c,v.tcf),...Ra(c,v.gpp)}},{prefix:qi,rateLimit:!1,routes:{"GET /widget.js":async()=>yc((0,V.join)(Bi,"widget","widget.js"),"application/javascript; charset=utf-8"),"GET /widget.css":async()=>yc((0,V.join)(Bi,"widget","widget.css"),"text/css; charset=utf-8")}},{prefix:qi,rateLimit:!1,originCheck:!0,routes:{...ja(Hi,c,s,B,Ac),...Ja(N,c,s,B),...za(c,s,B),...Ka(c,s,B),...Qa(Fi,c,s,B),...Za(c,s,B),...Xa(c,s,B),...ec(c,E,s,B),...tc(c,s,B,N),...nc(c,s,B),...ic(c,s,B),...oc(c,s,B),...sc(c,s,B,v.tcf),...rc(c,s,B,v.gpp),...lc(c,s,B),...dc(c,s,B),...uc(c,s,B),...mc(N,c,s,B,e,{usingJsonStorage:t,usingDefaultCredentials:n})}}],Cc,c,Vi),Nn=null,Ki,Yi,Ic=new Promise((D,M)=>{Ki=D,Yi=M});c.connect().then(async()=>{if(s.mode==="local"&&s.adminEmail&&s.adminPassword&&await Hi.bootstrap(s.adminEmail,s.adminPassword),await R.initialize({storage:c,config:e}),l.emit("ready"),Ki(),v.tcf?.enabled&&(io(),ro()),v.dataRetention?.purgeAfterDays){let D=v.dataRetention.purgeAfterDays,M=()=>c.purgeExpiredConsents(D).then(W=>{W>0&&console.warn(`[consenti] Purged ${W} consent records older than ${D} days`)}).catch(W=>console.warn("[consenti] Data retention purge failed:",W));M(),Nn=setInterval(()=>{M()},1440*6e4)}}).catch(D=>{console.warn("[consenti] Storage connection failed:",D),Yi(D)});async function xn(D,M){try{let ge=D.headers["x-forwarded-proto"]==="https"?"https":"http",Ie=D.headers.host??"localhost",J=new URL(D.url??"/",`${ge}://${Ie}`);if(Rt&&J.pathname.startsWith(F)&&await Su(J.pathname,F,Te,M,St))return;let Re=await Xr(D,e.maxBodySize,e.trustedProxies),vt=await zi(Re);if(J.pathname===`${F}/api/openapi.json`){M.writeHead(200,{"Content-Type":"application/json"}),M.end(JSON.stringify(Gn,null,2));return}if(J.pathname===`${F}/api/openapi-admin.json`){M.writeHead(200,{"Content-Type":"application/json"}),M.end(JSON.stringify(jn,null,2));return}if(J.pathname===`${F}/api/docs`){M.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),M.end(Ji);return}if(vt.status===404&&Rt&&J.pathname.startsWith(F)&&!J.pathname.startsWith(F+"/api/")&&!J.pathname.startsWith(F+"/admin/"))try{let Ct=await(0,Ye.readFile)((0,V.join)(Te,"index.html"));M.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),M.end(Ze(Ct,St));return}catch{}await ea(vt,M)}catch(W){M.headersSent||(W instanceof gt?(M.writeHead(413,{"Content-Type":"application/json"}),M.end(JSON.stringify({error:"Payload Too Large"}))):(M.writeHead(500,{"Content-Type":"application/json"}),M.end(JSON.stringify({error:"Internal Server Error"}))))}}function Pc(D,M,W){let Ie=D.headers["x-forwarded-proto"]==="https"?"https":"http",J=D.headers.host??"localhost",{pathname:Re}=new URL(D.url??"/",`${Ie}://${J}`);if(Re!=="/robots.txt"&&!Re.startsWith(F)){W();return}xn(D,M).then(()=>{M.writableEnded||W()}).catch(W)}function bc(D,M){return xn(D,M)}let Qi=async(D,M)=>{D.all("/*",async(W,ge)=>{await xn(W.raw,ge.raw),ge.hijack()})};return Object.defineProperty(Qi,Symbol.for("skip-override"),{value:!0}),{router:Pc,handler:bc,fastifyHandler:Qi,honoApp:{fetch:async D=>{if(Rt){let W=new URL(D.url).pathname;if(W.startsWith(F)){let ge=W.slice(F.length)||"/";if(!ge.startsWith("/api/")&&!ge.startsWith("/admin/")){let Ie=(0,V.extname)(ge)?(0,V.join)(Te,ge):(0,V.join)(Te,"index.html");if(!Ie.startsWith(Te))return new Response("Forbidden",{status:403});try{let J=await(0,Ye.readFile)(Ie),Re=(0,V.extname)(Ie).toLowerCase(),vt=Re===".html"||Re==="",Ct=Sc[Re]??"application/octet-stream",Oc=vt?Ze(J,St):J;return new Response(Oc,{headers:{"Content-Type":Ct}})}catch{try{let J=await(0,Ye.readFile)((0,V.join)(Te,"index.html"));return new Response(Ze(J,St),{headers:{"Content-Type":"text/html; charset=utf-8"}})}catch{return new Response("Dashboard not built. Run: npm run build --workspace=apps/api",{status:404,headers:{"Content-Type":"text/plain"}})}}}}}return zi(D)}},services:{profile:N,consent:Qe,visitor:z,user:Fi},storage:c,eventBus:l,ready:Ic,destroy:async()=>{Nn&&clearInterval(Nn),E.dispose(),v.tcf?.enabled&&(oo(),ao()),L?.stop(),await R.destroy()}}}0&&(module.exports={CategoryAction,ConsentAction,MongoDBAdapter,MySQLAdapter,PostgreSQLAdapter,SQLiteAdapter,createConsenti,dashboardDir});
203
205
  //# sourceMappingURL=index.cjs.map