@authhero/multi-tenancy 14.19.1 → 14.20.1

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.
@@ -1 +1 @@
1
- "use strict";var ce=Object.defineProperty;var le=(e,t,n)=>t in e?ce(e,t,{enumerable:!0,configurable:!0,writable:!0,value:n}):e[t]=n;var k=(e,t,n)=>le(e,typeof t!="symbol"?t+"":t,n);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const ue=require("hono"),_=require("authhero"),T=require("@hono/zod-openapi");function J(e){const{controlPlaneTenantId:t,requireOrganizationMatch:n=!0}=e;return{async onTenantAccessValidation(r,a){if(a===t)return!0;if(n){const s=r.var.org_name,c=r.var.organization_id,i=s||c;return i?i.toLowerCase()===a.toLowerCase():!1}return!0}}}function X(e,t,n,r){if(t===n)return!0;const a=r||e;return a?a.toLowerCase()===t.toLowerCase():!1}function Y(e){return{async resolveDataAdapters(t){try{return await e.getAdapters(t)}catch(n){console.error(`Failed to resolve data adapters for tenant ${t}:`,n);return}}}}function de(e){return`urn:authhero:tenant:${e.toLowerCase()}`}function N(e){return{async beforeCreate(t,n){return!n.audience&&n.id?{...n,audience:de(n.id)}:n},async afterCreate(t,n){const{accessControl:r,databaseIsolation:a}=e;r&&t.ctx&&await fe(t,n,r),a!=null&&a.onProvision&&await a.onProvision(n.id)},async beforeDelete(t,n){const{accessControl:r,databaseIsolation:a}=e;if(r)try{const c=(await t.adapters.organizations.list(r.controlPlaneTenantId)).organizations.find(i=>i.name===n);c&&await t.adapters.organizations.remove(r.controlPlaneTenantId,c.id)}catch(s){console.warn(`Failed to remove organization for tenant ${n}:`,s)}if(a!=null&&a.onDeprovision)try{await a.onDeprovision(n)}catch(s){console.warn(`Failed to deprovision database for tenant ${n}:`,s)}}}}async function fe(e,t,n){const{controlPlaneTenantId:r,defaultPermissions:a,defaultRoles:s,issuer:c,adminRoleName:i="Tenant Admin",adminRoleDescription:u="Full access to all tenant management operations",addCreatorToOrganization:o=!0}=n,l=await e.adapters.organizations.create(r,{name:t.id,display_name:t.friendly_name||t.id});let g;if(c&&(g=await ge(e,r,i,u)),o&&e.ctx){const d=e.ctx.var.user;if(d!=null&&d.sub&&!await me(e,r,d.sub))try{await e.adapters.userOrganizations.create(r,{user_id:d.sub,organization_id:l.id}),g&&await e.adapters.userRoles.create(r,d.sub,g,l.id)}catch(m){console.warn(`Failed to add creator ${d.sub} to organization ${l.id}:`,m)}}s&&s.length>0&&console.log(`Would assign roles ${s.join(", ")} to organization ${l.id}`),a&&a.length>0&&console.log(`Would grant permissions ${a.join(", ")} to organization ${l.id}`)}async function me(e,t,n){const r=await e.adapters.userRoles.list(t,n,void 0,"");for(const a of r)if((await e.adapters.rolePermissions.list(t,a.id,{per_page:1e3})).some(i=>i.permission_name==="admin:organizations"))return!0;return!1}async function ge(e,t,n,r){const s=(await e.adapters.roles.list(t,{})).roles.find(o=>o.name===n);if(s)return s.id;const c=await e.adapters.roles.create(t,{name:n,description:r}),i=_.MANAGEMENT_API_AUDIENCE,u=_.MANAGEMENT_API_SCOPES.map(o=>({role_id:c.id,resource_server_identifier:i,permission_name:o.value}));return await e.adapters.rolePermissions.assign(t,c.id,u),c.id}function U(e,t,n=()=>!0){const{controlPlaneTenantId:r,getChildTenantIds:a,getAdapters:s}=e,c=new Map;async function i(l,g,d){return(await t(l).list(g,{q:`name:${d}`,per_page:1}))[0]??null}async function u(l){const g=await a(),d=t(await s(r));await Promise.all(g.map(async f=>{try{const m=await s(f),w=t(m),y={...d.transform(l),is_system:!0},C=await i(m,f,l.name),P=C?w.getId(C):void 0;if(C&&P){const S=w.preserveOnUpdate?w.preserveOnUpdate(C,y):y;await w.update(f,P,S)}else await w.create(f,y)}catch(m){console.error(`Failed to sync ${d.listKey} "${l.name}" to tenant "${f}":`,m)}}))}async function o(l){const g=await a();await Promise.all(g.map(async d=>{try{const f=await s(d),m=t(f),w=await i(f,d,l),b=w?m.getId(w):void 0;w&&b&&await m.remove(d,b)}catch(f){console.error(`Failed to delete entity "${l}" from tenant "${d}":`,f)}}))}return{afterCreate:async(l,g)=>{l.tenantId===r&&n(g)&&await u(g)},afterUpdate:async(l,g,d)=>{l.tenantId===r&&n(d)&&await u(d)},beforeDelete:async(l,g)=>{if(l.tenantId!==r)return;const f=await t(l.adapters).get(l.tenantId,g);f&&n(f)&&c.set(g,f)},afterDelete:async(l,g)=>{if(l.tenantId!==r)return;const d=c.get(g);d&&(c.delete(g),await o(d.name))}}}function G(e,t,n=()=>!0){const{controlPlaneTenantId:r,getControlPlaneAdapters:a,getAdapters:s}=e;return{async afterCreate(c,i){if(i.id!==r)try{const u=await a(),o=await s(i.id),l=t(u),g=t(o),d=await _.fetchAll(f=>l.listPaginated(r,f),l.listKey,{cursorField:"id",pageSize:100});await Promise.all(d.filter(f=>n(f)).map(async f=>{try{const m=l.transform(f);await g.create(i.id,{...m,is_system:!0})}catch(m){console.error(`Failed to sync entity to new tenant "${i.id}":`,m)}}))}catch(u){console.error(`Failed to sync entities to new tenant "${i.id}":`,u)}}}}const L=e=>({list:async(t,n)=>(await e.resourceServers.list(t,n)).resource_servers,listPaginated:(t,n)=>e.resourceServers.list(t,n),get:(t,n)=>e.resourceServers.get(t,n),create:(t,n)=>e.resourceServers.create(t,n),update:(t,n,r)=>e.resourceServers.update(t,n,r),remove:(t,n)=>e.resourceServers.remove(t,n),listKey:"resource_servers",getId:t=>t.id,transform:t=>({id:t.id,name:t.name,identifier:t.identifier,scopes:t.scopes,signing_alg:t.signing_alg,token_lifetime:t.token_lifetime,token_lifetime_for_web:t.token_lifetime_for_web})}),W=e=>({list:async(t,n)=>(await e.roles.list(t,n)).roles,listPaginated:(t,n)=>e.roles.list(t,n),get:(t,n)=>e.roles.get(t,n),create:(t,n)=>e.roles.create(t,n),update:(t,n,r)=>e.roles.update(t,n,r),remove:(t,n)=>e.roles.remove(t,n),listKey:"roles",getId:t=>t.id,transform:t=>({id:t.id,name:t.name,description:t.description})});function K(e){var t;return((t=e.metadata)==null?void 0:t.sync)!==!1}function Z(e){const{sync:t={},filters:n={}}=e,r=t.resourceServers??!0,a=t.roles??!0,s=m=>K(m)?n.resourceServers?n.resourceServers(m):!0:!1,c=m=>K(m)?n.roles?n.roles(m):!0:!1,i=r?U(e,L,s):void 0,u=a?U(e,W,c):void 0,o=r?G(e,L,s):void 0,l=a?G(e,W,c):void 0,g=a?{async afterCreate(m,w){var b;if(w.id!==e.controlPlaneTenantId){await((b=l==null?void 0:l.afterCreate)==null?void 0:b.call(l,m,w));try{const y=await e.getControlPlaneAdapters(),C=await e.getAdapters(w.id),P=await _.fetchAll(p=>y.roles.list(e.controlPlaneTenantId,p),"roles",{cursorField:"id",pageSize:100}),S=new Map;for(const p of P.filter(A=>{var h;return((h=n.roles)==null?void 0:h.call(n,A))??!0})){const A=await d(C,w.id,p.name);A&&S.set(p.name,A.id)}for(const p of P.filter(A=>{var h;return((h=n.roles)==null?void 0:h.call(n,A))??!0})){const A=S.get(p.name);if(A)try{const h=await y.rolePermissions.list(e.controlPlaneTenantId,p.id,{});h.length>0&&await C.rolePermissions.assign(w.id,A,h.map(R=>({role_id:A,resource_server_identifier:R.resource_server_identifier,permission_name:R.permission_name})))}catch(h){console.error(`Failed to sync permissions for role "${p.name}" to tenant "${w.id}":`,h)}}}catch(y){console.error(`Failed to sync role permissions to tenant "${w.id}":`,y)}}}}:void 0;async function d(m,w,b){return(await m.roles.list(w,{q:`name:${b}`,per_page:1})).roles[0]??null}return{entityHooks:{resourceServers:i,roles:u},tenantHooks:{async afterCreate(m,w){const b=[o==null?void 0:o.afterCreate,(g==null?void 0:g.afterCreate)??(l==null?void 0:l.afterCreate)],y=[];for(const C of b)if(C)try{await C(m,w)}catch(P){y.push(P instanceof Error?P:new Error(String(P)))}if(y.length===1)throw y[0];if(y.length>1)throw new AggregateError(y,y.map(C=>C.message).join("; "))}}}}var I=class extends Error{constructor(t=500,n){super(n==null?void 0:n.message,{cause:n==null?void 0:n.cause});k(this,"res");k(this,"status");this.res=n==null?void 0:n.res,this.status=t}getResponse(){return this.res?new Response(this.res.body,{status:this.status,headers:this.res.headers}):new Response(this.message,{status:this.status})}};function q(e,t){const n=new T.OpenAPIHono;return n.openapi(T.createRoute({tags:["tenants"],method:"get",path:"/",request:{query:_.auth0QuerySchema},security:[{Bearer:[]}],responses:{200:{content:{"application/json":{schema:T.z.object({tenants:T.z.array(_.tenantSchema),start:T.z.number().optional(),limit:T.z.number().optional(),length:T.z.number().optional()})}},description:"List of tenants"}}}),async r=>{var m,w,b,y,C,P;const a=r.req.valid("query"),{page:s,per_page:c,include_totals:i,q:u}=a,o=r.var.user,l=(o==null?void 0:o.permissions)||[];if(l.includes("auth:read")||l.includes("admin:organizations")){const S=await r.env.data.tenants.list({page:s,per_page:c,include_totals:i,q:u});return i?r.json({tenants:S.tenants,start:((m=S.totals)==null?void 0:m.start)??0,limit:((w=S.totals)==null?void 0:w.limit)??c,length:S.tenants.length}):r.json({tenants:S.tenants})}const d=((b=e.accessControl)==null?void 0:b.controlPlaneTenantId)??((y=r.env.data.multiTenancyConfig)==null?void 0:y.controlPlaneTenantId);if(d&&(o!=null&&o.sub)){const p=(await _.fetchAll(M=>r.env.data.userOrganizations.listUserOrganizations(d,o.sub,M),"organizations")).map(M=>M.name);if(p.length===0)return i?r.json({tenants:[],start:0,limit:c??50,length:0}):r.json({tenants:[]});const A=p.length,h=s??0,R=c??50,F=h*R,D=p.slice(F,F+R);if(D.length===0)return i?r.json({tenants:[],start:F,limit:R,length:A}):r.json({tenants:[]});const z=D.map(M=>`id:${M}`).join(" OR "),v=u?`(${z}) AND (${u})`:z,$=await r.env.data.tenants.list({q:v,per_page:R,include_totals:!1});return i?r.json({tenants:$.tenants,start:F,limit:R,length:A}):r.json({tenants:$.tenants})}const f=await r.env.data.tenants.list({page:s,per_page:c,include_totals:i,q:u});return i?r.json({tenants:f.tenants,start:((C=f.totals)==null?void 0:C.start)??0,limit:((P=f.totals)==null?void 0:P.limit)??c,length:f.tenants.length}):r.json({tenants:f.tenants})}),n.openapi(T.createRoute({tags:["tenants"],method:"post",path:"/",request:{body:{content:{"application/json":{schema:_.tenantInsertSchema}}}},security:[{Bearer:[]}],responses:{201:{content:{"application/json":{schema:_.tenantSchema}},description:"Tenant created"},400:{description:"Validation error"},409:{description:"Tenant with this ID already exists"}}}),async r=>{var u,o;const a=r.var.user;if(!(a!=null&&a.sub))throw new I(401,{message:"Authentication required to create tenants"});let s=r.req.valid("json");const c={adapters:r.env.data,ctx:r};(u=t.tenants)!=null&&u.beforeCreate&&(s=await t.tenants.beforeCreate(c,s));const i=await r.env.data.tenants.create(s);return(o=t.tenants)!=null&&o.afterCreate&&await t.tenants.afterCreate(c,i),r.json(i,201)}),n.openapi(T.createRoute({tags:["tenants"],method:"delete",path:"/{id}",request:{params:T.z.object({id:T.z.string()})},security:[{Bearer:["delete:tenants"]}],responses:{204:{description:"Tenant deleted"},403:{description:"Access denied or cannot delete the control plane"},404:{description:"Tenant not found"}}}),async r=>{var u,o,l,g;const{id:a}=r.req.valid("param"),s=((u=e.accessControl)==null?void 0:u.controlPlaneTenantId)??((o=r.env.data.multiTenancyConfig)==null?void 0:o.controlPlaneTenantId);if(s){const d=r.var.user;if(!(d!=null&&d.sub))throw new I(401,{message:"Authentication required"});if(a===s)throw new I(403,{message:"Cannot delete the control plane"});if(!(await _.fetchAll(w=>r.env.data.userOrganizations.listUserOrganizations(s,d.sub,w),"organizations")).some(w=>w.name===a))throw new I(403,{message:"Access denied to this tenant"})}if(!await r.env.data.tenants.get(a))throw new I(404,{message:"Tenant not found"});const i={adapters:r.env.data,ctx:r};return(l=t.tenants)!=null&&l.beforeDelete&&await t.tenants.beforeDelete(i,a),await r.env.data.tenants.remove(a),(g=t.tenants)!=null&&g.afterDelete&&await t.tenants.afterDelete(i,a),r.body(null,204)}),n.openapi(T.createRoute({tags:["tenants","settings"],method:"get",path:"/settings",request:{headers:T.z.object({"tenant-id":T.z.string().optional()})},security:[{Bearer:["read:tenants","auth:read"]}],responses:{200:{content:{"application/json":{schema:_.tenantSchema}},description:"Current tenant settings"}}}),async r=>{const a=await r.env.data.tenants.get(r.var.tenant_id);if(!a)throw new I(404,{message:"Tenant not found"});return r.json(a)}),n.openapi(T.createRoute({tags:["tenants","settings"],method:"patch",path:"/settings",request:{headers:T.z.object({"tenant-id":T.z.string().optional()}),body:{content:{"application/json":{schema:T.z.object(_.tenantInsertSchema.shape).partial()}}}},security:[{Bearer:["update:tenants","auth:write"]}],responses:{200:{content:{"application/json":{schema:_.tenantSchema}},description:"Updated tenant settings"}}}),async r=>{const a=r.req.valid("json"),{id:s,...c}=a,i=await r.env.data.tenants.get(r.var.tenant_id);if(!i)throw new I(404,{message:"Tenant not found"});const u=_.deepMergePatch(i,c);await r.env.data.tenants.update(r.var.tenant_id,u);const o=await r.env.data.tenants.get(r.var.tenant_id);if(!o)throw new I(500,{message:"Failed to retrieve updated tenant"});return r.json(o)}),n}function we(e){const t=[{pattern:/\/api\/v2\/resource-servers\/([^/]+)$/,type:"resource_server"},{pattern:/\/api\/v2\/roles\/([^/]+)$/,type:"role"},{pattern:/\/api\/v2\/connections\/([^/]+)$/,type:"connection"}];for(const{pattern:n,type:r}of t){const a=e.match(n);if(a&&a[1])return{type:r,id:a[1]}}return null}async function pe(e,t,n){try{switch(n.type){case"resource_server":{const r=await e.resourceServers.get(t,n.id);return(r==null?void 0:r.is_system)===!0}case"role":{const r=await e.roles.get(t,n.id);return(r==null?void 0:r.is_system)===!0}case"connection":{const r=await e.connections.get(t,n.id);return(r==null?void 0:r.is_system)===!0}default:return!1}}catch{return!1}}function he(e){return{resource_server:"resource server",role:"role",connection:"connection"}[e]}function x(){return async(e,t)=>{if(!["PATCH","PUT","DELETE"].includes(e.req.method))return t();const n=we(e.req.path);if(!n)return t();const r=e.var.tenant_id||e.req.header("x-tenant-id")||e.req.header("tenant-id");if(!r)return t();if(await pe(e.env.data,r,n))throw new I(403,{message:`This ${he(n.type)} is a system resource and cannot be modified. Make changes in the control plane instead.`});return t()}}function E(e,t){const n=t.find(a=>a.strategy===e.strategy);if(!(n!=null&&n.options))return e;const r=_.connectionSchema.passthrough().parse({...n,...e});return r.options=_.connectionOptionsSchema.passthrough().parse({...n.options||{},...e.options}),r}function j(e,t){const n=[...t||[],...e||[]];return[...new Set(n)]}function ye(e,t){if(!(t!=null&&t.length))return e||[];if(!(e!=null&&e.length))return t;const n=new Map;for(const r of t)n.set(r.value,r);for(const r of e)n.set(r.value,r);return Array.from(n.values())}function Q(e,t){return t?{...e,scopes:ye(e.scopes,t.scopes)}:e}function V(e,t){return t?{...e,callbacks:j(e.callbacks,t.callbacks),web_origins:j(e.web_origins,t.web_origins),allowed_logout_urls:j(e.allowed_logout_urls,t.allowed_logout_urls),allowed_origins:j(e.allowed_origins,t.allowed_origins)}:e}function ee(e,t){return{...e.resourceServers,get:async(n,r)=>{const a=await e.resourceServers.get(n,r);if(!a||!t||n===t||!a.is_system)return a;const s=await e.resourceServers.get(t,r);return Q(a,s)},list:async(n,r)=>{const a=await e.resourceServers.list(n,r);if(!t||n===t)return a;const s=t,c=a.resource_servers.filter(o=>!!(o.is_system&&o.id)).map(o=>o.id);if(c.length===0)return a;const i=new Map;await Promise.all(c.map(async o=>{const l=await e.resourceServers.get(s,o);l&&i.set(o,l)}));const u=a.resource_servers.map(o=>o.is_system&&o.id?Q(o,i.get(o.id)??null):o);return{...a,resource_servers:u}}}}function te(e,t){return{...e,resourceServers:ee(e,t.controlPlaneTenantId)}}function ne(e,t){const{controlPlaneTenantId:n,controlPlaneClientId:r}=t;return{...e,multiTenancyConfig:{controlPlaneTenantId:n,controlPlaneClientId:r},connections:{...e.connections,get:async(a,s)=>{const c=await e.connections.get(a,s);if(!c||!n||a===n)return c;const i=await e.connections.list(n);return E(c,i.connections||[])},list:async(a,s)=>{const c=await e.connections.list(a,s);if(!n||a===n)return c;const i=await e.connections.list(n),u=c.connections.map(o=>E(o,i.connections||[]));return{...c,connections:u}}},clientConnections:{...e.clientConnections,listByClient:async(a,s)=>{let c=await e.clientConnections.listByClient(a,s);if(c.length===0&&(c=(await e.connections.list(a)).connections||[]),!n||a===n)return c;const i=await e.connections.list(n);return c.map(u=>E(u,i.connections||[]))}},clients:{...e.clients,get:async(a,s)=>{const c=await e.clients.get(a,s);if(!c)return null;if(!n||!r||a===n&&s===r)return c;const i=await e.clients.get(n,r);return V(c,i)},getByClientId:async a=>{const s=await e.clients.getByClientId(a);if(!s)return null;if(!n||!r||s.tenant_id===n&&s.client_id===r)return s;const c=await e.clients.get(n,r);return{...V(s,c),tenant_id:s.tenant_id}}},emailProviders:{...e.emailProviders,get:async a=>{const s=await e.emailProviders.get(a);return s||(!n||a===n?null:e.emailProviders.get(n))}},resourceServers:ee(e,n)}}function B(e,t){return ne(e,t)}function re(e){return async(t,n)=>{const r=t.var.user;return(r==null?void 0:r.tenant_id)===e&&r.org_name&&t.set("tenant_id",r.org_name),n()}}function ae(e){return async(t,n)=>{if(!e.accessControl)return n();const{controlPlaneTenantId:r}=e.accessControl,a=t.var.org_name,s=t.var.organization_id,c=a||s;let i=t.var.tenant_id;const u=t.var.user,l=(u!=null&&u.aud?Array.isArray(u.aud)?u.aud:[u.aud]:[]).includes(_.MANAGEMENT_API_AUDIENCE);if(!i&&c&&l&&(t.set("tenant_id",c),i=c),!i)throw new I(400,{message:"Tenant ID not found in request"});if(!X(s,i,r,a))throw new I(403,{message:`Access denied to tenant ${i}`});return n()}}function se(e){return async(t,n)=>{if(!e.subdomainRouting)return n();const{baseDomain:r,reservedSubdomains:a=[],resolveSubdomain:s}=e.subdomainRouting,c=t.req.header("x-forwarded-host")||t.req.header("host")||"";let i=null;if(c.endsWith(r)){const o=c.slice(0,-(r.length+1));o&&!o.includes(".")&&(i=o)}if(i&&a.includes(i)&&(i=null),!i)return e.accessControl&&t.set("tenant_id",e.accessControl.controlPlaneTenantId),n();let u=null;if(s)u=await s(i);else if(e.subdomainRouting.useOrganizations!==!1&&e.accessControl)try{const o=await t.env.data.organizations.get(e.accessControl.controlPlaneTenantId,i);o&&(u=o.id)}catch{}if(!u)throw new I(404,{message:`Tenant not found for subdomain: ${i}`});return t.set("tenant_id",u),n()}}function oe(e){return async(t,n)=>{if(!e.databaseIsolation)return n();const r=t.var.tenant_id;if(!r)throw new I(400,{message:"Tenant ID not found in request"});try{const a=await e.databaseIsolation.getAdapters(r);t.env.data=a}catch(a){throw console.error(`Failed to resolve database for tenant ${r}:`,a),new I(500,{message:"Failed to resolve tenant database"})}return n()}}function H(e){const t=se(e),n=ae(e),r=oe(e);return async(a,s)=>(await t(a,async()=>{}),await n(a,async()=>{}),await r(a,async()=>{}),s())}function ve(e){const{dataAdapter:t,controlPlane:n,controlPlane:{tenantId:r="control_plane",clientId:a}={},sync:s={resourceServers:!0,roles:!0},defaultPermissions:c=["tenant:admin"],requireOrganizationMatch:i=!1,managementApiExtensions:u=[],entityHooks:o,getChildTenantIds:l,getAdapters:g,...d}=e;let f=t,m=t;n&&(f=B(t,{controlPlaneTenantId:r,controlPlaneClientId:a}),m={...te(t,{controlPlaneTenantId:r}),multiTenancyConfig:{controlPlaneTenantId:r,controlPlaneClientId:a}});const w=s!==!1,b=w?{resourceServers:s.resourceServers??!0,roles:s.roles??!0}:{resourceServers:!1,roles:!1},P={controlPlaneTenantId:r,getChildTenantIds:l??(async()=>(await _.fetchAll(v=>f.tenants.list(v),"tenants",{cursorField:"id",pageSize:100})).filter(v=>v.id!==r).map(v=>v.id)),getAdapters:g??(async()=>f),getControlPlaneAdapters:async()=>f,sync:b},{entityHooks:S,tenantHooks:p}=Z(P),A={resourceServers:[S.resourceServers,...(o==null?void 0:o.resourceServers)??[]],roles:[S.roles,...(o==null?void 0:o.roles)??[]],connections:(o==null?void 0:o.connections)??[],tenants:(o==null?void 0:o.tenants)??[],rolePermissions:(o==null?void 0:o.rolePermissions)??[]},h=N({accessControl:{controlPlaneTenantId:r,requireOrganizationMatch:i,defaultPermissions:c}}),F=q({accessControl:{controlPlaneTenantId:r,requireOrganizationMatch:i,defaultPermissions:c}},{tenants:{async beforeCreate(z,v){return h.beforeCreate&&(v=await h.beforeCreate(z,v)),p.beforeCreate&&(v=await p.beforeCreate(z,v)),v},async afterCreate(z,v){var $,M;await(($=h.afterCreate)==null?void 0:$.call(h,z,v)),await((M=p.afterCreate)==null?void 0:M.call(p,z,v))},async beforeDelete(z,v){var $,M;await(($=h.beforeDelete)==null?void 0:$.call(h,z,v)),await((M=p.beforeDelete)==null?void 0:M.call(p,z,v))}}}),{app:D}=_.init({dataAdapter:f,managementDataAdapter:m,...d,entityHooks:A,managementApiExtensions:[...u,{path:"/tenants",router:F}]});return D.use("/api/v2/*",re(r)),w&&D.use("/api/v2/*",x()),{app:D,controlPlaneTenantId:r}}function _e(e){const t=O(e);return{name:"multi-tenancy",middleware:H(e),hooks:t,routes:[{path:"/management",handler:q(e,t)}],onRegister:async()=>{console.log("Multi-tenancy plugin registered"),e.accessControl&&console.log(` - Access control enabled (control plane: ${e.accessControl.controlPlaneTenantId})`),e.subdomainRouting&&console.log(` - Subdomain routing enabled (base domain: ${e.subdomainRouting.baseDomain})`),e.databaseIsolation&&console.log(" - Database isolation enabled")}}}function O(e){const t=e.accessControl?J(e.accessControl):{},n=e.databaseIsolation?Y(e.databaseIsolation):{},r=N(e);return{...t,...n,tenants:r}}function ie(e){const t=new ue.Hono,n=O(e);return t.route("/tenants",q(e,n)),t}function Te(e){return{hooks:O(e),middleware:H(e),app:ie(e),config:e,wrapAdapters:(t,n)=>{var r;return B(t,{controlPlaneTenantId:(r=e.accessControl)==null?void 0:r.controlPlaneTenantId,controlPlaneClientId:n==null?void 0:n.controlPlaneClientId})}}}exports.createAccessControlHooks=J;exports.createAccessControlMiddleware=ae;exports.createControlPlaneTenantMiddleware=re;exports.createDatabaseHooks=Y;exports.createDatabaseMiddleware=oe;exports.createMultiTenancy=ie;exports.createMultiTenancyHooks=O;exports.createMultiTenancyMiddleware=H;exports.createMultiTenancyPlugin=_e;exports.createProtectSyncedMiddleware=x;exports.createProvisioningHooks=N;exports.createRuntimeFallbackAdapter=ne;exports.createSubdomainMiddleware=se;exports.createSyncHooks=Z;exports.createTenantsOpenAPIRouter=q;exports.initMultiTenant=ve;exports.setupMultiTenancy=Te;exports.validateTenantAccess=X;exports.withRuntimeFallback=B;exports.withSystemResourceServerInheritance=te;
1
+ "use strict";var le=Object.defineProperty;var ue=(e,t,n)=>t in e?le(e,t,{enumerable:!0,configurable:!0,writable:!0,value:n}):e[t]=n;var O=(e,t,n)=>ue(e,typeof t!="symbol"?t+"":t,n);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const de=require("hono"),_=require("authhero"),C=require("@hono/zod-openapi");function X(e){const{controlPlaneTenantId:t,requireOrganizationMatch:n=!0}=e;return{async onTenantAccessValidation(r,a){if(a===t)return!0;if(n){const s=r.var.org_name,i=r.var.organization_id,c=s||i;return c?c.toLowerCase()===a.toLowerCase():!1}return!0}}}function Y(e,t,n,r){if(t===n)return!0;const a=r||e;return a?a.toLowerCase()===t.toLowerCase():!1}function Z(e){return{async resolveDataAdapters(t){try{return await e.getAdapters(t)}catch(n){console.error(`Failed to resolve data adapters for tenant ${t}:`,n);return}}}}function fe(e){return`urn:authhero:tenant:${e.toLowerCase()}`}function N(e){return{async beforeCreate(t,n){return!n.audience&&n.id?{...n,audience:fe(n.id)}:n},async afterCreate(t,n){const{accessControl:r,databaseIsolation:a}=e;r&&t.ctx&&await me(t,n,r),a!=null&&a.onProvision&&await a.onProvision(n.id)},async beforeDelete(t,n){const{accessControl:r,databaseIsolation:a}=e;if(r)try{const i=(await t.adapters.organizations.list(r.controlPlaneTenantId)).organizations.find(c=>c.name===n);i&&await t.adapters.organizations.remove(r.controlPlaneTenantId,i.id)}catch(s){console.warn(`Failed to remove organization for tenant ${n}:`,s)}if(a!=null&&a.onDeprovision)try{await a.onDeprovision(n)}catch(s){console.warn(`Failed to deprovision database for tenant ${n}:`,s)}}}}async function me(e,t,n){const{controlPlaneTenantId:r,defaultPermissions:a,defaultRoles:s,issuer:i,adminRoleName:c="Tenant Admin",adminRoleDescription:u="Full access to all tenant management operations",addCreatorToOrganization:o=!0}=n,l=await e.adapters.organizations.create(r,{name:t.id,display_name:t.friendly_name||t.id});let g;if(i&&(g=await we(e,r,c,u)),o&&e.ctx){const d=e.ctx.var.user;if(d!=null&&d.sub&&!await ge(e,r,d.sub))try{await e.adapters.userOrganizations.create(r,{user_id:d.sub,organization_id:l.id}),g&&await e.adapters.userRoles.create(r,d.sub,g,l.id)}catch(m){console.warn(`Failed to add creator ${d.sub} to organization ${l.id}:`,m)}}s&&s.length>0&&console.log(`Would assign roles ${s.join(", ")} to organization ${l.id}`),a&&a.length>0&&console.log(`Would grant permissions ${a.join(", ")} to organization ${l.id}`)}async function ge(e,t,n){const r=await e.adapters.userRoles.list(t,n,void 0,"");for(const a of r)if((await e.adapters.rolePermissions.list(t,a.id,{per_page:1e3})).some(c=>c.permission_name==="admin:organizations"))return!0;return!1}async function we(e,t,n,r){const s=(await e.adapters.roles.list(t,{})).roles.find(o=>o.name===n);if(s)return s.id;const i=await e.adapters.roles.create(t,{name:n,description:r}),c=_.MANAGEMENT_API_AUDIENCE,u=_.MANAGEMENT_API_SCOPES.map(o=>({role_id:i.id,resource_server_identifier:c,permission_name:o.value}));return await e.adapters.rolePermissions.assign(t,i.id,u),i.id}function U(e,t,n=()=>!0){const{controlPlaneTenantId:r,getChildTenantIds:a,getAdapters:s}=e,i=new Map;async function c(l,g,d){return(await t(l).list(g,{q:`name:${d}`,per_page:1}))[0]??null}async function u(l){const g=await a(),d=t(await s(r));await Promise.all(g.map(async f=>{try{const m=await s(f),w=t(m),y={...d.transform(l),is_system:!0},T=await c(m,f,l.name),A=T?w.getId(T):void 0;if(T&&A){const S=w.preserveOnUpdate?w.preserveOnUpdate(T,y):y;await w.update(f,A,S)}else await w.create(f,y)}catch(m){console.error(`Failed to sync ${d.listKey} "${l.name}" to tenant "${f}":`,m)}}))}async function o(l){const g=await a();await Promise.all(g.map(async d=>{try{const f=await s(d),m=t(f),w=await c(f,d,l),b=w?m.getId(w):void 0;w&&b&&await m.remove(d,b)}catch(f){console.error(`Failed to delete entity "${l}" from tenant "${d}":`,f)}}))}return{afterCreate:async(l,g)=>{l.tenantId===r&&n(g)&&await u(g)},afterUpdate:async(l,g,d)=>{l.tenantId===r&&n(d)&&await u(d)},beforeDelete:async(l,g)=>{if(l.tenantId!==r)return;const f=await t(l.adapters).get(l.tenantId,g);f&&n(f)&&i.set(g,f)},afterDelete:async(l,g)=>{if(l.tenantId!==r)return;const d=i.get(g);d&&(i.delete(g),await o(d.name))}}}function G(e,t,n=()=>!0){const{controlPlaneTenantId:r,getControlPlaneAdapters:a,getAdapters:s}=e;return{async afterCreate(i,c){if(c.id!==r)try{const u=await a(),o=await s(c.id),l=t(u),g=t(o),d=await _.fetchAll(f=>l.listPaginated(r,f),l.listKey,{cursorField:"id",pageSize:100});await Promise.all(d.filter(f=>n(f)).map(async f=>{try{const m=l.transform(f);await g.create(c.id,{...m,is_system:!0})}catch(m){console.error(`Failed to sync entity to new tenant "${c.id}":`,m)}}))}catch(u){console.error(`Failed to sync entities to new tenant "${c.id}":`,u)}}}}const W=e=>({list:async(t,n)=>(await e.resourceServers.list(t,n)).resource_servers,listPaginated:(t,n)=>e.resourceServers.list(t,n),get:(t,n)=>e.resourceServers.get(t,n),create:(t,n)=>e.resourceServers.create(t,n),update:(t,n,r)=>e.resourceServers.update(t,n,r),remove:(t,n)=>e.resourceServers.remove(t,n),listKey:"resource_servers",getId:t=>t.id,transform:t=>({id:t.id,name:t.name,identifier:t.identifier,scopes:t.scopes,signing_alg:t.signing_alg,token_lifetime:t.token_lifetime,token_lifetime_for_web:t.token_lifetime_for_web})}),L=e=>({list:async(t,n)=>(await e.roles.list(t,n)).roles,listPaginated:(t,n)=>e.roles.list(t,n),get:(t,n)=>e.roles.get(t,n),create:(t,n)=>e.roles.create(t,n),update:(t,n,r)=>e.roles.update(t,n,r),remove:(t,n)=>e.roles.remove(t,n),listKey:"roles",getId:t=>t.id,transform:t=>({id:t.id,name:t.name,description:t.description})});function K(e){var t;return((t=e.metadata)==null?void 0:t.sync)!==!1}function x(e){const{sync:t={},filters:n={}}=e,r=t.resourceServers??!0,a=t.roles??!0,s=m=>K(m)?n.resourceServers?n.resourceServers(m):!0:!1,i=m=>K(m)?n.roles?n.roles(m):!0:!1,c=r?U(e,W,s):void 0,u=a?U(e,L,i):void 0,o=r?G(e,W,s):void 0,l=a?G(e,L,i):void 0,g=a?{async afterCreate(m,w){var b;if(w.id!==e.controlPlaneTenantId){await((b=l==null?void 0:l.afterCreate)==null?void 0:b.call(l,m,w));try{const y=await e.getControlPlaneAdapters(),T=await e.getAdapters(w.id),A=await _.fetchAll(h=>y.roles.list(e.controlPlaneTenantId,h),"roles",{cursorField:"id",pageSize:100}),S=new Map;for(const h of A.filter(P=>{var p;return((p=n.roles)==null?void 0:p.call(n,P))??!0})){const P=await d(T,w.id,h.name);P&&S.set(h.name,P.id)}for(const h of A.filter(P=>{var p;return((p=n.roles)==null?void 0:p.call(n,P))??!0})){const P=S.get(h.name);if(P)try{const p=await y.rolePermissions.list(e.controlPlaneTenantId,h.id,{});p.length>0&&await T.rolePermissions.assign(w.id,P,p.map(R=>({role_id:P,resource_server_identifier:R.resource_server_identifier,permission_name:R.permission_name})))}catch(p){console.error(`Failed to sync permissions for role "${h.name}" to tenant "${w.id}":`,p)}}}catch(y){console.error(`Failed to sync role permissions to tenant "${w.id}":`,y)}}}}:void 0;async function d(m,w,b){return(await m.roles.list(w,{q:`name:${b}`,per_page:1})).roles[0]??null}return{entityHooks:{resourceServers:c,roles:u},tenantHooks:{async afterCreate(m,w){const b=[o==null?void 0:o.afterCreate,(g==null?void 0:g.afterCreate)??(l==null?void 0:l.afterCreate)],y=[];for(const T of b)if(T)try{await T(m,w)}catch(A){y.push(A instanceof Error?A:new Error(String(A)))}if(y.length===1)throw y[0];if(y.length>1)throw new AggregateError(y,y.map(T=>T.message).join("; "))}}}}var I=class extends Error{constructor(t=500,n){super(n==null?void 0:n.message,{cause:n==null?void 0:n.cause});O(this,"res");O(this,"status");this.res=n==null?void 0:n.res,this.status=t}getResponse(){return this.res?new Response(this.res.body,{status:this.status,headers:this.res.headers}):new Response(this.message,{status:this.status})}};function D(e,t){const n=new C.OpenAPIHono;return n.openapi(C.createRoute({tags:["tenants"],method:"get",path:"/",request:{query:_.auth0QuerySchema},security:[{Bearer:[]}],responses:{200:{content:{"application/json":{schema:C.z.object({tenants:C.z.array(_.tenantSchema),start:C.z.number().optional(),limit:C.z.number().optional(),length:C.z.number().optional()})}},description:"List of tenants"}}}),async r=>{var m,w,b,y,T,A;const a=r.req.valid("query"),{page:s,per_page:i,include_totals:c,q:u}=a,o=r.var.user,l=(o==null?void 0:o.permissions)||[];if(l.includes("auth:read")||l.includes("admin:organizations")){const S=await r.env.data.tenants.list({page:s,per_page:i,include_totals:c,q:u});return c?r.json({tenants:S.tenants,start:((m=S.totals)==null?void 0:m.start)??0,limit:((w=S.totals)==null?void 0:w.limit)??i,length:S.tenants.length}):r.json({tenants:S.tenants})}const d=((b=e.accessControl)==null?void 0:b.controlPlaneTenantId)??((y=r.env.data.multiTenancyConfig)==null?void 0:y.controlPlaneTenantId);if(d&&(o!=null&&o.sub)){const h=(await _.fetchAll(M=>r.env.data.userOrganizations.listUserOrganizations(d,o.sub,M),"organizations")).map(M=>M.name);if(h.length===0)return c?r.json({tenants:[],start:0,limit:i??50,length:0}):r.json({tenants:[]});const P=h.length,p=s??0,R=i??50,$=p*R,j=h.slice($,$+R);if(j.length===0)return c?r.json({tenants:[],start:$,limit:R,length:P}):r.json({tenants:[]});const z=j.map(M=>`id:${M}`).join(" OR "),v=u?`(${z}) AND (${u})`:z,k=await r.env.data.tenants.list({q:v,per_page:R,include_totals:!1});return c?r.json({tenants:k.tenants,start:$,limit:R,length:P}):r.json({tenants:k.tenants})}const f=await r.env.data.tenants.list({page:s,per_page:i,include_totals:c,q:u});return c?r.json({tenants:f.tenants,start:((T=f.totals)==null?void 0:T.start)??0,limit:((A=f.totals)==null?void 0:A.limit)??i,length:f.tenants.length}):r.json({tenants:f.tenants})}),n.openapi(C.createRoute({tags:["tenants"],method:"post",path:"/",request:{body:{content:{"application/json":{schema:_.tenantInsertSchema}}}},security:[{Bearer:[]}],responses:{201:{content:{"application/json":{schema:_.tenantSchema}},description:"Tenant created"},400:{description:"Validation error"},409:{description:"Tenant with this ID already exists"}}}),async r=>{var u,o;const a=r.var.user;if(!(a!=null&&a.sub))throw new I(401,{message:"Authentication required to create tenants"});let s=r.req.valid("json");const i={adapters:r.env.data,ctx:r};(u=t.tenants)!=null&&u.beforeCreate&&(s=await t.tenants.beforeCreate(i,s));const c=await r.env.data.tenants.create(s);return(o=t.tenants)!=null&&o.afterCreate&&await t.tenants.afterCreate(i,c),r.json(c,201)}),n.openapi(C.createRoute({tags:["tenants"],method:"delete",path:"/{id}",request:{params:C.z.object({id:C.z.string()})},security:[{Bearer:["delete:tenants"]}],responses:{204:{description:"Tenant deleted"},403:{description:"Access denied or cannot delete the control plane"},404:{description:"Tenant not found"}}}),async r=>{var u,o,l,g;const{id:a}=r.req.valid("param"),s=((u=e.accessControl)==null?void 0:u.controlPlaneTenantId)??((o=r.env.data.multiTenancyConfig)==null?void 0:o.controlPlaneTenantId);if(s){const d=r.var.user;if(!(d!=null&&d.sub))throw new I(401,{message:"Authentication required"});if(a===s)throw new I(403,{message:"Cannot delete the control plane"});if(!(await _.fetchAll(w=>r.env.data.userOrganizations.listUserOrganizations(s,d.sub,w),"organizations")).some(w=>w.name===a))throw new I(403,{message:"Access denied to this tenant"})}if(!await r.env.data.tenants.get(a))throw new I(404,{message:"Tenant not found"});const c={adapters:r.env.data,ctx:r};return(l=t.tenants)!=null&&l.beforeDelete&&await t.tenants.beforeDelete(c,a),await r.env.data.tenants.remove(a),(g=t.tenants)!=null&&g.afterDelete&&await t.tenants.afterDelete(c,a),r.body(null,204)}),n.openapi(C.createRoute({tags:["tenants","settings"],method:"get",path:"/settings",request:{headers:C.z.object({"tenant-id":C.z.string().optional()})},security:[{Bearer:["read:tenants","auth:read"]}],responses:{200:{content:{"application/json":{schema:_.tenantSchema}},description:"Current tenant settings"}}}),async r=>{const a=await r.env.data.tenants.get(r.var.tenant_id);if(!a)throw new I(404,{message:"Tenant not found"});return r.json(a)}),n.openapi(C.createRoute({tags:["tenants","settings"],method:"patch",path:"/settings",request:{headers:C.z.object({"tenant-id":C.z.string().optional()}),body:{content:{"application/json":{schema:C.z.object(_.tenantInsertSchema.shape).partial()}}}},security:[{Bearer:["update:tenants","auth:write"]}],responses:{200:{content:{"application/json":{schema:_.tenantSchema}},description:"Updated tenant settings"}}}),async r=>{const a=r.req.valid("json"),{id:s,...i}=a,c=await r.env.data.tenants.get(r.var.tenant_id);if(!c)throw new I(404,{message:"Tenant not found"});const u=_.deepMergePatch(c,i);await r.env.data.tenants.update(r.var.tenant_id,u);const o=await r.env.data.tenants.get(r.var.tenant_id);if(!o)throw new I(500,{message:"Failed to retrieve updated tenant"});return r.json(o)}),n}function he(e){const t=[{pattern:/\/api\/v2\/resource-servers\/([^/]+)$/,type:"resource_server"},{pattern:/\/api\/v2\/roles\/([^/]+)$/,type:"role"},{pattern:/\/api\/v2\/connections\/([^/]+)$/,type:"connection"}];for(const{pattern:n,type:r}of t){const a=e.match(n);if(a&&a[1])return{type:r,id:a[1]}}return null}async function pe(e,t,n){try{switch(n.type){case"resource_server":{const r=await e.resourceServers.get(t,n.id);return(r==null?void 0:r.is_system)===!0}case"role":{const r=await e.roles.get(t,n.id);return(r==null?void 0:r.is_system)===!0}case"connection":{const r=await e.connections.get(t,n.id);return(r==null?void 0:r.is_system)===!0}default:return!1}}catch{return!1}}function ye(e){return{resource_server:"resource server",role:"role",connection:"connection"}[e]}function ee(){return async(e,t)=>{if(!["PATCH","PUT","DELETE"].includes(e.req.method))return t();const n=he(e.req.path);if(!n)return t();const r=e.var.tenant_id||e.req.header("x-tenant-id")||e.req.header("tenant-id");if(!r)return t();if(await pe(e.env.data,r,n))throw new I(403,{message:`This ${ye(n.type)} is a system resource and cannot be modified. Make changes in the control plane instead.`});return t()}}function E(e,t){const n=t.find(a=>a.strategy===e.strategy);if(!(n!=null&&n.options))return e;const r=_.connectionSchema.passthrough().parse({...n,...e});return r.options=_.connectionOptionsSchema.passthrough().parse({...n.options||{},...e.options}),r}function F(e,t){const n=[...t||[],...e||[]];return[...new Set(n)]}function ve(e,t){if(!(t!=null&&t.length))return e||[];if(!(e!=null&&e.length))return t;const n=new Map;for(const r of t)n.set(r.value,r);for(const r of e)n.set(r.value,r);return Array.from(n.values())}function Q(e,t){return t?{...e,scopes:ve(e.scopes,t.scopes)}:e}function V(e,t){return t?{...e,callbacks:F(e.callbacks,t.callbacks),web_origins:F(e.web_origins,t.web_origins),allowed_logout_urls:F(e.allowed_logout_urls,t.allowed_logout_urls),allowed_origins:F(e.allowed_origins,t.allowed_origins)}:e}function te(e,t){return{...e.resourceServers,get:async(n,r)=>{const a=await e.resourceServers.get(n,r);if(!a||!t||n===t||!a.is_system)return a;const s=await e.resourceServers.get(t,r);return Q(a,s)},list:async(n,r)=>{const a=await e.resourceServers.list(n,r);if(!t||n===t)return a;const s=t,i=a.resource_servers.filter(o=>!!(o.is_system&&o.id)).map(o=>o.id);if(i.length===0)return a;const c=new Map;await Promise.all(i.map(async o=>{const l=await e.resourceServers.get(s,o);l&&c.set(o,l)}));const u=a.resource_servers.map(o=>o.is_system&&o.id?Q(o,c.get(o.id)??null):o);return{...a,resource_servers:u}}}}function ne(e,t){return{...e,resourceServers:te(e,t.controlPlaneTenantId)}}function re(e,t){const{controlPlaneTenantId:n,controlPlaneClientId:r}=t;return{...e,multiTenancyConfig:{controlPlaneTenantId:n,controlPlaneClientId:r},connections:{...e.connections,get:async(a,s)=>{const i=await e.connections.get(a,s);if(!i||!n||a===n)return i;const c=await e.connections.list(n);return E(i,c.connections||[])},list:async(a,s)=>{const i=await e.connections.list(a,s);if(!n||a===n)return i;const c=await e.connections.list(n),u=i.connections.map(o=>E(o,c.connections||[]));return{...i,connections:u}}},clientConnections:{...e.clientConnections,listByClient:async(a,s)=>{let i=await e.clientConnections.listByClient(a,s);if(i.length===0&&(i=(await e.connections.list(a)).connections||[]),!n||a===n)return i;const c=await e.connections.list(n);return i.map(u=>E(u,c.connections||[]))}},clients:{...e.clients,get:async(a,s)=>{const i=await e.clients.get(a,s);if(!i)return null;if(!n||!r||a===n&&s===r)return i;const c=await e.clients.get(n,r);return V(i,c)},getByClientId:async a=>{const s=await e.clients.getByClientId(a);if(!s)return null;if(!n||!r||s.tenant_id===n&&s.client_id===r)return s;const i=await e.clients.get(n,r);return{...V(s,i),tenant_id:s.tenant_id}}},emailProviders:{...e.emailProviders,get:async a=>{const s=await e.emailProviders.get(a);return s||(!n||a===n?null:e.emailProviders.get(n))}},resourceServers:te(e,n),hooks:_e(e,n)}}function J(e){if(!e||typeof e!="object")return!1;const t=e.metadata;return!t||typeof t!="object"?!1:t.inheritable===!0}function _e(e,t){return{...e.hooks,list:async(n,r)=>{const a=await e.hooks.list(n,r);if(!t||n===t)return a;const i=((await e.hooks.list(t,r)).hooks||[]).filter(J);if(i.length===0)return a;const c=new Set((a.hooks||[]).map(o=>o.hook_id)),u=i.filter(o=>!c.has(o.hook_id));return{...a,hooks:[...a.hooks||[],...u],length:typeof a.length=="number"?a.length+u.length:a.length}},get:async(n,r)=>{const a=await e.hooks.get(n,r);if(a||!t||n===t)return a;const s=await e.hooks.get(t,r);return s&&J(s)?s:null}}}function H(e,t){return re(e,t)}function ae(e){return async(t,n)=>{const r=t.var.user;return(r==null?void 0:r.tenant_id)===e&&r.org_name&&t.set("tenant_id",r.org_name),n()}}function se(e){return async(t,n)=>{if(!e.accessControl)return n();const{controlPlaneTenantId:r}=e.accessControl,a=t.var.org_name,s=t.var.organization_id,i=a||s;let c=t.var.tenant_id;const u=t.var.user,l=(u!=null&&u.aud?Array.isArray(u.aud)?u.aud:[u.aud]:[]).includes(_.MANAGEMENT_API_AUDIENCE);if(!c&&i&&l&&(t.set("tenant_id",i),c=i),!c)throw new I(400,{message:"Tenant ID not found in request"});if(!Y(s,c,r,a))throw new I(403,{message:`Access denied to tenant ${c}`});return n()}}function oe(e){return async(t,n)=>{if(!e.subdomainRouting)return n();const{baseDomain:r,reservedSubdomains:a=[],resolveSubdomain:s}=e.subdomainRouting,i=t.req.header("x-forwarded-host")||t.req.header("host")||"";let c=null;if(i.endsWith(r)){const o=i.slice(0,-(r.length+1));o&&!o.includes(".")&&(c=o)}if(c&&a.includes(c)&&(c=null),!c)return e.accessControl&&t.set("tenant_id",e.accessControl.controlPlaneTenantId),n();let u=null;if(s)u=await s(c);else if(e.subdomainRouting.useOrganizations!==!1&&e.accessControl)try{const o=await t.env.data.organizations.get(e.accessControl.controlPlaneTenantId,c);o&&(u=o.id)}catch{}if(!u)throw new I(404,{message:`Tenant not found for subdomain: ${c}`});return t.set("tenant_id",u),n()}}function ie(e){return async(t,n)=>{if(!e.databaseIsolation)return n();const r=t.var.tenant_id;if(!r)throw new I(400,{message:"Tenant ID not found in request"});try{const a=await e.databaseIsolation.getAdapters(r);t.env.data=a}catch(a){throw console.error(`Failed to resolve database for tenant ${r}:`,a),new I(500,{message:"Failed to resolve tenant database"})}return n()}}function B(e){const t=oe(e),n=se(e),r=ie(e);return async(a,s)=>(await t(a,async()=>{}),await n(a,async()=>{}),await r(a,async()=>{}),s())}function Ce(e){const{dataAdapter:t,controlPlane:n,controlPlane:{tenantId:r="control_plane",clientId:a}={},sync:s={resourceServers:!0,roles:!0},defaultPermissions:i=["tenant:admin"],requireOrganizationMatch:c=!1,managementApiExtensions:u=[],entityHooks:o,getChildTenantIds:l,getAdapters:g,...d}=e;let f=t,m=t;n&&(f=H(t,{controlPlaneTenantId:r,controlPlaneClientId:a}),m={...ne(t,{controlPlaneTenantId:r}),multiTenancyConfig:{controlPlaneTenantId:r,controlPlaneClientId:a}});const w=s!==!1,b=w?{resourceServers:s.resourceServers??!0,roles:s.roles??!0}:{resourceServers:!1,roles:!1},A={controlPlaneTenantId:r,getChildTenantIds:l??(async()=>(await _.fetchAll(v=>f.tenants.list(v),"tenants",{cursorField:"id",pageSize:100})).filter(v=>v.id!==r).map(v=>v.id)),getAdapters:g??(async()=>f),getControlPlaneAdapters:async()=>f,sync:b},{entityHooks:S,tenantHooks:h}=x(A),P={resourceServers:[S.resourceServers,...(o==null?void 0:o.resourceServers)??[]],roles:[S.roles,...(o==null?void 0:o.roles)??[]],connections:(o==null?void 0:o.connections)??[],tenants:(o==null?void 0:o.tenants)??[],rolePermissions:(o==null?void 0:o.rolePermissions)??[]},p=N({accessControl:{controlPlaneTenantId:r,requireOrganizationMatch:c,defaultPermissions:i}}),$=D({accessControl:{controlPlaneTenantId:r,requireOrganizationMatch:c,defaultPermissions:i}},{tenants:{async beforeCreate(z,v){return p.beforeCreate&&(v=await p.beforeCreate(z,v)),h.beforeCreate&&(v=await h.beforeCreate(z,v)),v},async afterCreate(z,v){var k,M;await((k=p.afterCreate)==null?void 0:k.call(p,z,v)),await((M=h.afterCreate)==null?void 0:M.call(h,z,v))},async beforeDelete(z,v){var k,M;await((k=p.beforeDelete)==null?void 0:k.call(p,z,v)),await((M=h.beforeDelete)==null?void 0:M.call(h,z,v))}}}),{app:j}=_.init({dataAdapter:f,managementDataAdapter:m,...d,entityHooks:P,managementApiExtensions:[...u,{path:"/tenants",router:$}]});return j.use("/api/v2/*",ae(r)),w&&j.use("/api/v2/*",ee()),{app:j,controlPlaneTenantId:r}}function Te(e){const t=q(e);return{name:"multi-tenancy",middleware:B(e),hooks:t,routes:[{path:"/management",handler:D(e,t)}],onRegister:async()=>{console.log("Multi-tenancy plugin registered"),e.accessControl&&console.log(` - Access control enabled (control plane: ${e.accessControl.controlPlaneTenantId})`),e.subdomainRouting&&console.log(` - Subdomain routing enabled (base domain: ${e.subdomainRouting.baseDomain})`),e.databaseIsolation&&console.log(" - Database isolation enabled")}}}function q(e){const t=e.accessControl?X(e.accessControl):{},n=e.databaseIsolation?Z(e.databaseIsolation):{},r=N(e);return{...t,...n,tenants:r}}function ce(e){const t=new de.Hono,n=q(e);return t.route("/tenants",D(e,n)),t}function be(e){return{hooks:q(e),middleware:B(e),app:ce(e),config:e,wrapAdapters:(t,n)=>{var r;return H(t,{controlPlaneTenantId:(r=e.accessControl)==null?void 0:r.controlPlaneTenantId,controlPlaneClientId:n==null?void 0:n.controlPlaneClientId})}}}exports.createAccessControlHooks=X;exports.createAccessControlMiddleware=se;exports.createControlPlaneTenantMiddleware=ae;exports.createDatabaseHooks=Z;exports.createDatabaseMiddleware=ie;exports.createMultiTenancy=ce;exports.createMultiTenancyHooks=q;exports.createMultiTenancyMiddleware=B;exports.createMultiTenancyPlugin=Te;exports.createProtectSyncedMiddleware=ee;exports.createProvisioningHooks=N;exports.createRuntimeFallbackAdapter=re;exports.createSubdomainMiddleware=oe;exports.createSyncHooks=x;exports.createTenantsOpenAPIRouter=D;exports.initMultiTenant=Ce;exports.setupMultiTenancy=be;exports.validateTenantAccess=Y;exports.withRuntimeFallback=H;exports.withSystemResourceServerInheritance=ne;
@@ -1,30 +1,30 @@
1
- var ee = Object.defineProperty;
2
- var te = (e, t, n) => t in e ? ee(e, t, { enumerable: !0, configurable: !0, writable: !0, value: n }) : e[t] = n;
3
- var E = (e, t, n) => te(e, typeof t != "symbol" ? t + "" : t, n);
4
- import { Hono as ne } from "hono";
5
- import { MANAGEMENT_API_SCOPES as re, MANAGEMENT_API_AUDIENCE as J, fetchAll as D, auth0QuerySchema as ae, tenantSchema as q, tenantInsertSchema as U, deepMergePatch as se, connectionSchema as oe, connectionOptionsSchema as ie, init as ce } from "authhero";
6
- import { OpenAPIHono as le, createRoute as M, z as I } from "@hono/zod-openapi";
7
- function ue(e) {
1
+ var te = Object.defineProperty;
2
+ var ne = (e, t, n) => t in e ? te(e, t, { enumerable: !0, configurable: !0, writable: !0, value: n }) : e[t] = n;
3
+ var O = (e, t, n) => ne(e, typeof t != "symbol" ? t + "" : t, n);
4
+ import { Hono as re } from "hono";
5
+ import { MANAGEMENT_API_SCOPES as ae, MANAGEMENT_API_AUDIENCE as X, fetchAll as D, auth0QuerySchema as se, tenantSchema as q, tenantInsertSchema as U, deepMergePatch as oe, connectionSchema as ie, connectionOptionsSchema as ce, init as le } from "authhero";
6
+ import { OpenAPIHono as ue, createRoute as M, z as I } from "@hono/zod-openapi";
7
+ function de(e) {
8
8
  const { controlPlaneTenantId: t, requireOrganizationMatch: n = !0 } = e;
9
9
  return {
10
10
  async onTenantAccessValidation(r, a) {
11
11
  if (a === t)
12
12
  return !0;
13
13
  if (n) {
14
- const s = r.var.org_name, c = r.var.organization_id, i = s || c;
15
- return i ? i.toLowerCase() === a.toLowerCase() : !1;
14
+ const s = r.var.org_name, i = r.var.organization_id, c = s || i;
15
+ return c ? c.toLowerCase() === a.toLowerCase() : !1;
16
16
  }
17
17
  return !0;
18
18
  }
19
19
  };
20
20
  }
21
- function de(e, t, n, r) {
21
+ function fe(e, t, n, r) {
22
22
  if (t === n)
23
23
  return !0;
24
24
  const a = r || e;
25
25
  return a ? a.toLowerCase() === t.toLowerCase() : !1;
26
26
  }
27
- function fe(e) {
27
+ function me(e) {
28
28
  return {
29
29
  async resolveDataAdapters(t) {
30
30
  try {
@@ -39,31 +39,31 @@ function fe(e) {
39
39
  }
40
40
  };
41
41
  }
42
- function me(e) {
42
+ function ge(e) {
43
43
  return `urn:authhero:tenant:${e.toLowerCase()}`;
44
44
  }
45
- function X(e) {
45
+ function Y(e) {
46
46
  return {
47
47
  async beforeCreate(t, n) {
48
48
  return !n.audience && n.id ? {
49
49
  ...n,
50
- audience: me(n.id)
50
+ audience: ge(n.id)
51
51
  } : n;
52
52
  },
53
53
  async afterCreate(t, n) {
54
54
  const { accessControl: r, databaseIsolation: a } = e;
55
- r && t.ctx && await ge(t, n, r), a != null && a.onProvision && await a.onProvision(n.id);
55
+ r && t.ctx && await we(t, n, r), a != null && a.onProvision && await a.onProvision(n.id);
56
56
  },
57
57
  async beforeDelete(t, n) {
58
58
  const { accessControl: r, databaseIsolation: a } = e;
59
59
  if (r)
60
60
  try {
61
- const c = (await t.adapters.organizations.list(
61
+ const i = (await t.adapters.organizations.list(
62
62
  r.controlPlaneTenantId
63
- )).organizations.find((i) => i.name === n);
64
- c && await t.adapters.organizations.remove(
63
+ )).organizations.find((c) => c.name === n);
64
+ i && await t.adapters.organizations.remove(
65
65
  r.controlPlaneTenantId,
66
- c.id
66
+ i.id
67
67
  );
68
68
  } catch (s) {
69
69
  console.warn(
@@ -83,13 +83,13 @@ function X(e) {
83
83
  }
84
84
  };
85
85
  }
86
- async function ge(e, t, n) {
86
+ async function we(e, t, n) {
87
87
  const {
88
88
  controlPlaneTenantId: r,
89
89
  defaultPermissions: a,
90
90
  defaultRoles: s,
91
- issuer: c,
92
- adminRoleName: i = "Tenant Admin",
91
+ issuer: i,
92
+ adminRoleName: c = "Tenant Admin",
93
93
  adminRoleDescription: u = "Full access to all tenant management operations",
94
94
  addCreatorToOrganization: o = !0
95
95
  } = n, l = await e.adapters.organizations.create(
@@ -100,14 +100,14 @@ async function ge(e, t, n) {
100
100
  }
101
101
  );
102
102
  let g;
103
- if (c && (g = await pe(
103
+ if (i && (g = await pe(
104
104
  e,
105
105
  r,
106
- i,
106
+ c,
107
107
  u
108
108
  )), o && e.ctx) {
109
109
  const d = e.ctx.var.user;
110
- if (d != null && d.sub && !await we(
110
+ if (d != null && d.sub && !await he(
111
111
  e,
112
112
  r,
113
113
  d.sub
@@ -136,7 +136,7 @@ async function ge(e, t, n) {
136
136
  `Would grant permissions ${a.join(", ")} to organization ${l.id}`
137
137
  );
138
138
  }
139
- async function we(e, t, n) {
139
+ async function he(e, t, n) {
140
140
  const r = await e.adapters.userRoles.list(
141
141
  t,
142
142
  n,
@@ -150,7 +150,7 @@ async function we(e, t, n) {
150
150
  a.id,
151
151
  { per_page: 1e3 }
152
152
  )).some(
153
- (i) => i.permission_name === "admin:organizations"
153
+ (c) => c.permission_name === "admin:organizations"
154
154
  ))
155
155
  return !0;
156
156
  return !1;
@@ -159,23 +159,23 @@ async function pe(e, t, n, r) {
159
159
  const s = (await e.adapters.roles.list(t, {})).roles.find((o) => o.name === n);
160
160
  if (s)
161
161
  return s.id;
162
- const c = await e.adapters.roles.create(t, {
162
+ const i = await e.adapters.roles.create(t, {
163
163
  name: n,
164
164
  description: r
165
- }), i = J, u = re.map((o) => ({
166
- role_id: c.id,
167
- resource_server_identifier: i,
165
+ }), c = X, u = ae.map((o) => ({
166
+ role_id: i.id,
167
+ resource_server_identifier: c,
168
168
  permission_name: o.value
169
169
  }));
170
170
  return await e.adapters.rolePermissions.assign(
171
171
  t,
172
- c.id,
172
+ i.id,
173
173
  u
174
- ), c.id;
174
+ ), i.id;
175
175
  }
176
176
  function G(e, t, n = () => !0) {
177
- const { controlPlaneTenantId: r, getChildTenantIds: a, getAdapters: s } = e, c = /* @__PURE__ */ new Map();
178
- async function i(l, g, d) {
177
+ const { controlPlaneTenantId: r, getChildTenantIds: a, getAdapters: s } = e, i = /* @__PURE__ */ new Map();
178
+ async function c(l, g, d) {
179
179
  return (await t(l).list(g, {
180
180
  q: `name:${d}`,
181
181
  per_page: 1
@@ -189,7 +189,7 @@ function G(e, t, n = () => !0) {
189
189
  const m = await s(f), w = t(m), y = {
190
190
  ...d.transform(l),
191
191
  is_system: !0
192
- }, _ = await i(m, f, l.name), b = _ ? w.getId(_) : void 0;
192
+ }, _ = await c(m, f, l.name), b = _ ? w.getId(_) : void 0;
193
193
  if (_ && b) {
194
194
  const P = w.preserveOnUpdate ? w.preserveOnUpdate(_, y) : y;
195
195
  await w.update(f, b, P);
@@ -209,7 +209,7 @@ function G(e, t, n = () => !0) {
209
209
  await Promise.all(
210
210
  g.map(async (d) => {
211
211
  try {
212
- const f = await s(d), m = t(f), w = await i(f, d, l), C = w ? m.getId(w) : void 0;
212
+ const f = await s(d), m = t(f), w = await c(f, d, l), C = w ? m.getId(w) : void 0;
213
213
  w && C && await m.remove(d, C);
214
214
  } catch (f) {
215
215
  console.error(
@@ -230,22 +230,22 @@ function G(e, t, n = () => !0) {
230
230
  beforeDelete: async (l, g) => {
231
231
  if (l.tenantId !== r) return;
232
232
  const f = await t(l.adapters).get(l.tenantId, g);
233
- f && n(f) && c.set(g, f);
233
+ f && n(f) && i.set(g, f);
234
234
  },
235
235
  afterDelete: async (l, g) => {
236
236
  if (l.tenantId !== r) return;
237
- const d = c.get(g);
238
- d && (c.delete(g), await o(d.name));
237
+ const d = i.get(g);
238
+ d && (i.delete(g), await o(d.name));
239
239
  }
240
240
  };
241
241
  }
242
- function L(e, t, n = () => !0) {
242
+ function H(e, t, n = () => !0) {
243
243
  const { controlPlaneTenantId: r, getControlPlaneAdapters: a, getAdapters: s } = e;
244
244
  return {
245
- async afterCreate(c, i) {
246
- if (i.id !== r)
245
+ async afterCreate(i, c) {
246
+ if (c.id !== r)
247
247
  try {
248
- const u = await a(), o = await s(i.id), l = t(u), g = t(o), d = await D(
248
+ const u = await a(), o = await s(c.id), l = t(u), g = t(o), d = await D(
249
249
  (f) => l.listPaginated(r, f),
250
250
  l.listKey,
251
251
  { cursorField: "id", pageSize: 100 }
@@ -254,13 +254,13 @@ function L(e, t, n = () => !0) {
254
254
  d.filter((f) => n(f)).map(async (f) => {
255
255
  try {
256
256
  const m = l.transform(f);
257
- await g.create(i.id, {
257
+ await g.create(c.id, {
258
258
  ...m,
259
259
  is_system: !0
260
260
  });
261
261
  } catch (m) {
262
262
  console.error(
263
- `Failed to sync entity to new tenant "${i.id}":`,
263
+ `Failed to sync entity to new tenant "${c.id}":`,
264
264
  m
265
265
  );
266
266
  }
@@ -268,7 +268,7 @@ function L(e, t, n = () => !0) {
268
268
  );
269
269
  } catch (u) {
270
270
  console.error(
271
- `Failed to sync entities to new tenant "${i.id}":`,
271
+ `Failed to sync entities to new tenant "${c.id}":`,
272
272
  u
273
273
  );
274
274
  }
@@ -293,7 +293,7 @@ const W = (e) => ({
293
293
  token_lifetime: t.token_lifetime,
294
294
  token_lifetime_for_web: t.token_lifetime_for_web
295
295
  })
296
- }), H = (e) => ({
296
+ }), L = (e) => ({
297
297
  list: async (t, n) => (await e.roles.list(t, n)).roles,
298
298
  listPaginated: (t, n) => e.roles.list(t, n),
299
299
  get: (t, n) => e.roles.get(t, n),
@@ -312,19 +312,19 @@ function K(e) {
312
312
  var t;
313
313
  return ((t = e.metadata) == null ? void 0 : t.sync) !== !1;
314
314
  }
315
- function he(e) {
316
- const { sync: t = {}, filters: n = {} } = e, r = t.resourceServers ?? !0, a = t.roles ?? !0, s = (m) => K(m) ? n.resourceServers ? n.resourceServers(m) : !0 : !1, c = (m) => K(m) ? n.roles ? n.roles(m) : !0 : !1, i = r ? G(
315
+ function ye(e) {
316
+ const { sync: t = {}, filters: n = {} } = e, r = t.resourceServers ?? !0, a = t.roles ?? !0, s = (m) => K(m) ? n.resourceServers ? n.resourceServers(m) : !0 : !1, i = (m) => K(m) ? n.roles ? n.roles(m) : !0 : !1, c = r ? G(
317
317
  e,
318
318
  W,
319
319
  s
320
- ) : void 0, u = a ? G(e, H, c) : void 0, o = r ? L(
320
+ ) : void 0, u = a ? G(e, L, i) : void 0, o = r ? H(
321
321
  e,
322
322
  W,
323
323
  s
324
- ) : void 0, l = a ? L(
324
+ ) : void 0, l = a ? H(
325
325
  e,
326
- H,
327
- c
326
+ L,
327
+ i
328
328
  ) : void 0, g = a ? {
329
329
  async afterCreate(m, w) {
330
330
  var C;
@@ -332,53 +332,53 @@ function he(e) {
332
332
  await ((C = l == null ? void 0 : l.afterCreate) == null ? void 0 : C.call(l, m, w));
333
333
  try {
334
334
  const y = await e.getControlPlaneAdapters(), _ = await e.getAdapters(w.id), b = await D(
335
- (p) => y.roles.list(
335
+ (h) => y.roles.list(
336
336
  e.controlPlaneTenantId,
337
- p
337
+ h
338
338
  ),
339
339
  "roles",
340
340
  { cursorField: "id", pageSize: 100 }
341
341
  ), P = /* @__PURE__ */ new Map();
342
- for (const p of b.filter(
342
+ for (const h of b.filter(
343
343
  (T) => {
344
- var h;
345
- return ((h = n.roles) == null ? void 0 : h.call(n, T)) ?? !0;
344
+ var p;
345
+ return ((p = n.roles) == null ? void 0 : p.call(n, T)) ?? !0;
346
346
  }
347
347
  )) {
348
348
  const T = await d(
349
349
  _,
350
350
  w.id,
351
- p.name
351
+ h.name
352
352
  );
353
- T && P.set(p.name, T.id);
353
+ T && P.set(h.name, T.id);
354
354
  }
355
- for (const p of b.filter(
355
+ for (const h of b.filter(
356
356
  (T) => {
357
- var h;
358
- return ((h = n.roles) == null ? void 0 : h.call(n, T)) ?? !0;
357
+ var p;
358
+ return ((p = n.roles) == null ? void 0 : p.call(n, T)) ?? !0;
359
359
  }
360
360
  )) {
361
- const T = P.get(p.name);
361
+ const T = P.get(h.name);
362
362
  if (T)
363
363
  try {
364
- const h = await y.rolePermissions.list(
364
+ const p = await y.rolePermissions.list(
365
365
  e.controlPlaneTenantId,
366
- p.id,
366
+ h.id,
367
367
  {}
368
368
  );
369
- h.length > 0 && await _.rolePermissions.assign(
369
+ p.length > 0 && await _.rolePermissions.assign(
370
370
  w.id,
371
371
  T,
372
- h.map((z) => ({
372
+ p.map((z) => ({
373
373
  role_id: T,
374
374
  resource_server_identifier: z.resource_server_identifier,
375
375
  permission_name: z.permission_name
376
376
  }))
377
377
  );
378
- } catch (h) {
378
+ } catch (p) {
379
379
  console.error(
380
- `Failed to sync permissions for role "${p.name}" to tenant "${w.id}":`,
381
- h
380
+ `Failed to sync permissions for role "${h.name}" to tenant "${w.id}":`,
381
+ p
382
382
  );
383
383
  }
384
384
  }
@@ -399,7 +399,7 @@ function he(e) {
399
399
  }
400
400
  return {
401
401
  entityHooks: {
402
- resourceServers: i,
402
+ resourceServers: c,
403
403
  roles: u
404
404
  },
405
405
  tenantHooks: {
@@ -433,8 +433,8 @@ var A = class extends Error {
433
433
  */
434
434
  constructor(t = 500, n) {
435
435
  super(n == null ? void 0 : n.message, { cause: n == null ? void 0 : n.cause });
436
- E(this, "res");
437
- E(this, "status");
436
+ O(this, "res");
437
+ O(this, "status");
438
438
  this.res = n == null ? void 0 : n.res, this.status = t;
439
439
  }
440
440
  /**
@@ -452,14 +452,14 @@ var A = class extends Error {
452
452
  }
453
453
  };
454
454
  function N(e, t) {
455
- const n = new le();
455
+ const n = new ue();
456
456
  return n.openapi(
457
457
  M({
458
458
  tags: ["tenants"],
459
459
  method: "get",
460
460
  path: "/",
461
461
  request: {
462
- query: ae
462
+ query: se
463
463
  },
464
464
  security: [
465
465
  {
@@ -484,24 +484,24 @@ function N(e, t) {
484
484
  }),
485
485
  async (r) => {
486
486
  var m, w, C, y, _, b;
487
- const a = r.req.valid("query"), { page: s, per_page: c, include_totals: i, q: u } = a, o = r.var.user, l = (o == null ? void 0 : o.permissions) || [];
487
+ const a = r.req.valid("query"), { page: s, per_page: i, include_totals: c, q: u } = a, o = r.var.user, l = (o == null ? void 0 : o.permissions) || [];
488
488
  if (l.includes("auth:read") || l.includes("admin:organizations")) {
489
489
  const P = await r.env.data.tenants.list({
490
490
  page: s,
491
- per_page: c,
492
- include_totals: i,
491
+ per_page: i,
492
+ include_totals: c,
493
493
  q: u
494
494
  });
495
- return i ? r.json({
495
+ return c ? r.json({
496
496
  tenants: P.tenants,
497
497
  start: ((m = P.totals) == null ? void 0 : m.start) ?? 0,
498
- limit: ((w = P.totals) == null ? void 0 : w.limit) ?? c,
498
+ limit: ((w = P.totals) == null ? void 0 : w.limit) ?? i,
499
499
  length: P.tenants.length
500
500
  }) : r.json({ tenants: P.tenants });
501
501
  }
502
502
  const d = ((C = e.accessControl) == null ? void 0 : C.controlPlaneTenantId) ?? ((y = r.env.data.multiTenancyConfig) == null ? void 0 : y.controlPlaneTenantId);
503
503
  if (d && (o != null && o.sub)) {
504
- const p = (await D(
504
+ const h = (await D(
505
505
  (R) => r.env.data.userOrganizations.listUserOrganizations(
506
506
  d,
507
507
  o.sub,
@@ -509,44 +509,44 @@ function N(e, t) {
509
509
  ),
510
510
  "organizations"
511
511
  )).map((R) => R.name);
512
- if (p.length === 0)
513
- return i ? r.json({
512
+ if (h.length === 0)
513
+ return c ? r.json({
514
514
  tenants: [],
515
515
  start: 0,
516
- limit: c ?? 50,
516
+ limit: i ?? 50,
517
517
  length: 0
518
518
  }) : r.json({ tenants: [] });
519
- const T = p.length, h = s ?? 0, z = c ?? 50, F = h * z, j = p.slice(F, F + z);
520
- if (j.length === 0)
521
- return i ? r.json({
519
+ const T = h.length, p = s ?? 0, z = i ?? 50, j = p * z, F = h.slice(j, j + z);
520
+ if (F.length === 0)
521
+ return c ? r.json({
522
522
  tenants: [],
523
- start: F,
523
+ start: j,
524
524
  limit: z,
525
525
  length: T
526
526
  }) : r.json({ tenants: [] });
527
- const S = j.map((R) => `id:${R}`).join(" OR "), v = u ? `(${S}) AND (${u})` : S, $ = await r.env.data.tenants.list({
527
+ const S = F.map((R) => `id:${R}`).join(" OR "), v = u ? `(${S}) AND (${u})` : S, $ = await r.env.data.tenants.list({
528
528
  q: v,
529
529
  per_page: z,
530
530
  include_totals: !1
531
531
  // We calculate totals from accessibleTenantIds
532
532
  });
533
- return i ? r.json({
533
+ return c ? r.json({
534
534
  tenants: $.tenants,
535
- start: F,
535
+ start: j,
536
536
  limit: z,
537
537
  length: T
538
538
  }) : r.json({ tenants: $.tenants });
539
539
  }
540
540
  const f = await r.env.data.tenants.list({
541
541
  page: s,
542
- per_page: c,
543
- include_totals: i,
542
+ per_page: i,
543
+ include_totals: c,
544
544
  q: u
545
545
  });
546
- return i ? r.json({
546
+ return c ? r.json({
547
547
  tenants: f.tenants,
548
548
  start: ((_ = f.totals) == null ? void 0 : _.start) ?? 0,
549
- limit: ((b = f.totals) == null ? void 0 : b.limit) ?? c,
549
+ limit: ((b = f.totals) == null ? void 0 : b.limit) ?? i,
550
550
  length: f.tenants.length
551
551
  }) : r.json({ tenants: f.tenants });
552
552
  }
@@ -594,13 +594,13 @@ function N(e, t) {
594
594
  message: "Authentication required to create tenants"
595
595
  });
596
596
  let s = r.req.valid("json");
597
- const c = {
597
+ const i = {
598
598
  adapters: r.env.data,
599
599
  ctx: r
600
600
  };
601
- (u = t.tenants) != null && u.beforeCreate && (s = await t.tenants.beforeCreate(c, s));
602
- const i = await r.env.data.tenants.create(s);
603
- return (o = t.tenants) != null && o.afterCreate && await t.tenants.afterCreate(c, i), r.json(i, 201);
601
+ (u = t.tenants) != null && u.beforeCreate && (s = await t.tenants.beforeCreate(i, s));
602
+ const c = await r.env.data.tenants.create(s);
603
+ return (o = t.tenants) != null && o.afterCreate && await t.tenants.afterCreate(i, c), r.json(c, 201);
604
604
  }
605
605
  ), n.openapi(
606
606
  M({
@@ -658,11 +658,11 @@ function N(e, t) {
658
658
  throw new A(404, {
659
659
  message: "Tenant not found"
660
660
  });
661
- const i = {
661
+ const c = {
662
662
  adapters: r.env.data,
663
663
  ctx: r
664
664
  };
665
- return (l = t.tenants) != null && l.beforeDelete && await t.tenants.beforeDelete(i, a), await r.env.data.tenants.remove(a), (g = t.tenants) != null && g.afterDelete && await t.tenants.afterDelete(i, a), r.body(null, 204);
665
+ return (l = t.tenants) != null && l.beforeDelete && await t.tenants.beforeDelete(c, a), await r.env.data.tenants.remove(a), (g = t.tenants) != null && g.afterDelete && await t.tenants.afterDelete(c, a), r.body(null, 204);
666
666
  }
667
667
  ), n.openapi(
668
668
  M({
@@ -732,12 +732,12 @@ function N(e, t) {
732
732
  }
733
733
  }),
734
734
  async (r) => {
735
- const a = r.req.valid("json"), { id: s, ...c } = a, i = await r.env.data.tenants.get(r.var.tenant_id);
736
- if (!i)
735
+ const a = r.req.valid("json"), { id: s, ...i } = a, c = await r.env.data.tenants.get(r.var.tenant_id);
736
+ if (!c)
737
737
  throw new A(404, {
738
738
  message: "Tenant not found"
739
739
  });
740
- const u = se(i, c);
740
+ const u = oe(c, i);
741
741
  await r.env.data.tenants.update(r.var.tenant_id, u);
742
742
  const o = await r.env.data.tenants.get(r.var.tenant_id);
743
743
  if (!o)
@@ -748,7 +748,7 @@ function N(e, t) {
748
748
  }
749
749
  ), n;
750
750
  }
751
- function ye(e) {
751
+ function ve(e) {
752
752
  const t = [
753
753
  {
754
754
  pattern: /\/api\/v2\/resource-servers\/([^/]+)$/,
@@ -764,7 +764,7 @@ function ye(e) {
764
764
  }
765
765
  return null;
766
766
  }
767
- async function ve(e, t, n) {
767
+ async function _e(e, t, n) {
768
768
  try {
769
769
  switch (n.type) {
770
770
  case "resource_server": {
@@ -786,50 +786,50 @@ async function ve(e, t, n) {
786
786
  return !1;
787
787
  }
788
788
  }
789
- function _e(e) {
789
+ function Ce(e) {
790
790
  return {
791
791
  resource_server: "resource server",
792
792
  role: "role",
793
793
  connection: "connection"
794
794
  }[e];
795
795
  }
796
- function Ce() {
796
+ function Te() {
797
797
  return async (e, t) => {
798
798
  if (!["PATCH", "PUT", "DELETE"].includes(e.req.method))
799
799
  return t();
800
- const n = ye(e.req.path);
800
+ const n = ve(e.req.path);
801
801
  if (!n)
802
802
  return t();
803
803
  const r = e.var.tenant_id || e.req.header("x-tenant-id") || e.req.header("tenant-id");
804
804
  if (!r)
805
805
  return t();
806
- if (await ve(e.env.data, r, n))
806
+ if (await _e(e.env.data, r, n))
807
807
  throw new A(403, {
808
- message: `This ${_e(n.type)} is a system resource and cannot be modified. Make changes in the control plane instead.`
808
+ message: `This ${Ce(n.type)} is a system resource and cannot be modified. Make changes in the control plane instead.`
809
809
  });
810
810
  return t();
811
811
  };
812
812
  }
813
- function k(e, t) {
813
+ function E(e, t) {
814
814
  const n = t.find(
815
815
  (a) => a.strategy === e.strategy
816
816
  );
817
817
  if (!(n != null && n.options))
818
818
  return e;
819
- const r = oe.passthrough().parse({
819
+ const r = ie.passthrough().parse({
820
820
  ...n,
821
821
  ...e
822
822
  });
823
- return r.options = ie.passthrough().parse({
823
+ return r.options = ce.passthrough().parse({
824
824
  ...n.options || {},
825
825
  ...e.options
826
826
  }), r;
827
827
  }
828
- function O(e, t) {
828
+ function k(e, t) {
829
829
  const n = [...t || [], ...e || []];
830
830
  return [...new Set(n)];
831
831
  }
832
- function Te(e, t) {
832
+ function be(e, t) {
833
833
  if (!(t != null && t.length))
834
834
  return e || [];
835
835
  if (!(e != null && e.length))
@@ -844,7 +844,7 @@ function Te(e, t) {
844
844
  function Q(e, t) {
845
845
  return t ? {
846
846
  ...e,
847
- scopes: Te(
847
+ scopes: be(
848
848
  e.scopes,
849
849
  t.scopes
850
850
  )
@@ -853,22 +853,22 @@ function Q(e, t) {
853
853
  function V(e, t) {
854
854
  return t ? {
855
855
  ...e,
856
- callbacks: O(e.callbacks, t.callbacks),
857
- web_origins: O(
856
+ callbacks: k(e.callbacks, t.callbacks),
857
+ web_origins: k(
858
858
  e.web_origins,
859
859
  t.web_origins
860
860
  ),
861
- allowed_logout_urls: O(
861
+ allowed_logout_urls: k(
862
862
  e.allowed_logout_urls,
863
863
  t.allowed_logout_urls
864
864
  ),
865
- allowed_origins: O(
865
+ allowed_origins: k(
866
866
  e.allowed_origins,
867
867
  t.allowed_origins
868
868
  )
869
869
  } : e;
870
870
  }
871
- function Y(e, t) {
871
+ function Z(e, t) {
872
872
  return {
873
873
  ...e.resourceServers,
874
874
  get: async (n, r) => {
@@ -878,35 +878,35 @@ function Y(e, t) {
878
878
  );
879
879
  if (!a || !t || n === t || !a.is_system)
880
880
  return a;
881
- const s = await e.resourceServers.get(t, r);
881
+ const s = await e.resourceServers.get(
882
+ t,
883
+ r
884
+ );
882
885
  return Q(
883
886
  a,
884
887
  s
885
888
  );
886
889
  },
887
890
  list: async (n, r) => {
888
- const a = await e.resourceServers.list(
889
- n,
890
- r
891
- );
891
+ const a = await e.resourceServers.list(n, r);
892
892
  if (!t || n === t)
893
893
  return a;
894
- const s = t, c = a.resource_servers.filter(
894
+ const s = t, i = a.resource_servers.filter(
895
895
  (o) => !!(o.is_system && o.id)
896
896
  ).map((o) => o.id);
897
- if (c.length === 0)
897
+ if (i.length === 0)
898
898
  return a;
899
- const i = /* @__PURE__ */ new Map();
899
+ const c = /* @__PURE__ */ new Map();
900
900
  await Promise.all(
901
- c.map(async (o) => {
901
+ i.map(async (o) => {
902
902
  const l = await e.resourceServers.get(s, o);
903
- l && i.set(o, l);
903
+ l && c.set(o, l);
904
904
  })
905
905
  );
906
906
  const u = a.resource_servers.map(
907
907
  (o) => o.is_system && o.id ? Q(
908
908
  o,
909
- i.get(o.id) ?? null
909
+ c.get(o.id) ?? null
910
910
  ) : o
911
911
  );
912
912
  return {
@@ -916,16 +916,16 @@ function Y(e, t) {
916
916
  }
917
917
  };
918
918
  }
919
- function be(e, t) {
919
+ function Pe(e, t) {
920
920
  return {
921
921
  ...e,
922
- resourceServers: Y(
922
+ resourceServers: Z(
923
923
  e,
924
924
  t.controlPlaneTenantId
925
925
  )
926
926
  };
927
927
  }
928
- function Pe(e, t) {
928
+ function Ae(e, t) {
929
929
  const { controlPlaneTenantId: n, controlPlaneClientId: r } = t;
930
930
  return {
931
931
  ...e,
@@ -937,30 +937,30 @@ function Pe(e, t) {
937
937
  connections: {
938
938
  ...e.connections,
939
939
  get: async (a, s) => {
940
- const c = await e.connections.get(
940
+ const i = await e.connections.get(
941
941
  a,
942
942
  s
943
943
  );
944
- if (!c || !n || a === n)
945
- return c;
946
- const i = await e.connections.list(n);
947
- return k(
948
- c,
949
- i.connections || []
944
+ if (!i || !n || a === n)
945
+ return i;
946
+ const c = await e.connections.list(n);
947
+ return E(
948
+ i,
949
+ c.connections || []
950
950
  );
951
951
  },
952
952
  list: async (a, s) => {
953
- const c = await e.connections.list(a, s);
953
+ const i = await e.connections.list(a, s);
954
954
  if (!n || a === n)
955
- return c;
956
- const i = await e.connections.list(n), u = c.connections.map(
957
- (o) => k(
955
+ return i;
956
+ const c = await e.connections.list(n), u = i.connections.map(
957
+ (o) => E(
958
958
  o,
959
- i.connections || []
959
+ c.connections || []
960
960
  )
961
961
  );
962
962
  return {
963
- ...c,
963
+ ...i,
964
964
  connections: u
965
965
  };
966
966
  }
@@ -968,17 +968,17 @@ function Pe(e, t) {
968
968
  clientConnections: {
969
969
  ...e.clientConnections,
970
970
  listByClient: async (a, s) => {
971
- let c = await e.clientConnections.listByClient(
971
+ let i = await e.clientConnections.listByClient(
972
972
  a,
973
973
  s
974
974
  );
975
- if (c.length === 0 && (c = (await e.connections.list(a)).connections || []), !n || a === n)
976
- return c;
977
- const i = await e.connections.list(n);
978
- return c.map(
979
- (u) => k(
975
+ if (i.length === 0 && (i = (await e.connections.list(a)).connections || []), !n || a === n)
976
+ return i;
977
+ const c = await e.connections.list(n);
978
+ return i.map(
979
+ (u) => E(
980
980
  u,
981
- i.connections || []
981
+ c.connections || []
982
982
  )
983
983
  );
984
984
  }
@@ -986,16 +986,16 @@ function Pe(e, t) {
986
986
  clients: {
987
987
  ...e.clients,
988
988
  get: async (a, s) => {
989
- const c = await e.clients.get(a, s);
990
- if (!c)
989
+ const i = await e.clients.get(a, s);
990
+ if (!i)
991
991
  return null;
992
992
  if (!n || !r || a === n && s === r)
993
- return c;
994
- const i = await e.clients.get(
993
+ return i;
994
+ const c = await e.clients.get(
995
995
  n,
996
996
  r
997
997
  );
998
- return V(c, i);
998
+ return V(i, c);
999
999
  },
1000
1000
  getByClientId: async (a) => {
1001
1001
  const s = await e.clients.getByClientId(a);
@@ -1003,12 +1003,12 @@ function Pe(e, t) {
1003
1003
  return null;
1004
1004
  if (!n || !r || s.tenant_id === n && s.client_id === r)
1005
1005
  return s;
1006
- const c = await e.clients.get(
1006
+ const i = await e.clients.get(
1007
1007
  n,
1008
1008
  r
1009
1009
  );
1010
1010
  return {
1011
- ...V(s, c),
1011
+ ...V(s, i),
1012
1012
  tenant_id: s.tenant_id
1013
1013
  };
1014
1014
  }
@@ -1020,48 +1020,90 @@ function Pe(e, t) {
1020
1020
  return s || (!n || a === n ? null : e.emailProviders.get(n));
1021
1021
  }
1022
1022
  },
1023
- resourceServers: Y(
1023
+ resourceServers: Z(
1024
1024
  e,
1025
1025
  n
1026
- )
1026
+ ),
1027
+ hooks: Se(e, n)
1027
1028
  // Note: Additional adapters can be extended here for runtime fallback:
1028
1029
  // - promptSettings: Fall back to control plane prompts
1029
1030
  // - branding: Fall back to control plane branding/themes
1030
1031
  };
1031
1032
  }
1032
- function Z(e, t) {
1033
- return Pe(e, t);
1033
+ function J(e) {
1034
+ if (!e || typeof e != "object") return !1;
1035
+ const t = e.metadata;
1036
+ return !t || typeof t != "object" ? !1 : t.inheritable === !0;
1037
+ }
1038
+ function Se(e, t) {
1039
+ return {
1040
+ ...e.hooks,
1041
+ list: async (n, r) => {
1042
+ const a = await e.hooks.list(n, r);
1043
+ if (!t || n === t)
1044
+ return a;
1045
+ const i = ((await e.hooks.list(
1046
+ t,
1047
+ r
1048
+ )).hooks || []).filter(
1049
+ J
1050
+ );
1051
+ if (i.length === 0)
1052
+ return a;
1053
+ const c = new Set(
1054
+ (a.hooks || []).map((o) => o.hook_id)
1055
+ ), u = i.filter((o) => !c.has(o.hook_id));
1056
+ return {
1057
+ ...a,
1058
+ hooks: [...a.hooks || [], ...u],
1059
+ length: typeof a.length == "number" ? a.length + u.length : a.length
1060
+ };
1061
+ },
1062
+ get: async (n, r) => {
1063
+ const a = await e.hooks.get(n, r);
1064
+ if (a || !t || n === t)
1065
+ return a;
1066
+ const s = await e.hooks.get(
1067
+ t,
1068
+ r
1069
+ );
1070
+ return s && J(s) ? s : null;
1071
+ }
1072
+ };
1073
+ }
1074
+ function x(e, t) {
1075
+ return Ae(e, t);
1034
1076
  }
1035
- function Ae(e) {
1077
+ function Ie(e) {
1036
1078
  return async (t, n) => {
1037
1079
  const r = t.var.user;
1038
1080
  return (r == null ? void 0 : r.tenant_id) === e && r.org_name && t.set("tenant_id", r.org_name), n();
1039
1081
  };
1040
1082
  }
1041
- function Se(e) {
1083
+ function Re(e) {
1042
1084
  return async (t, n) => {
1043
1085
  if (!e.accessControl)
1044
1086
  return n();
1045
- const { controlPlaneTenantId: r } = e.accessControl, a = t.var.org_name, s = t.var.organization_id, c = a || s;
1046
- let i = t.var.tenant_id;
1047
- const u = t.var.user, l = (u != null && u.aud ? Array.isArray(u.aud) ? u.aud : [u.aud] : []).includes(J);
1048
- if (!i && c && l && (t.set("tenant_id", c), i = c), !i)
1087
+ const { controlPlaneTenantId: r } = e.accessControl, a = t.var.org_name, s = t.var.organization_id, i = a || s;
1088
+ let c = t.var.tenant_id;
1089
+ const u = t.var.user, l = (u != null && u.aud ? Array.isArray(u.aud) ? u.aud : [u.aud] : []).includes(X);
1090
+ if (!c && i && l && (t.set("tenant_id", i), c = i), !c)
1049
1091
  throw new A(400, {
1050
1092
  message: "Tenant ID not found in request"
1051
1093
  });
1052
- if (!de(
1094
+ if (!fe(
1053
1095
  s,
1054
- i,
1096
+ c,
1055
1097
  r,
1056
1098
  a
1057
1099
  ))
1058
1100
  throw new A(403, {
1059
- message: `Access denied to tenant ${i}`
1101
+ message: `Access denied to tenant ${c}`
1060
1102
  });
1061
1103
  return n();
1062
1104
  };
1063
1105
  }
1064
- function Ie(e) {
1106
+ function ze(e) {
1065
1107
  return async (t, n) => {
1066
1108
  if (!e.subdomainRouting)
1067
1109
  return n();
@@ -1069,34 +1111,34 @@ function Ie(e) {
1069
1111
  baseDomain: r,
1070
1112
  reservedSubdomains: a = [],
1071
1113
  resolveSubdomain: s
1072
- } = e.subdomainRouting, c = t.req.header("x-forwarded-host") || t.req.header("host") || "";
1073
- let i = null;
1074
- if (c.endsWith(r)) {
1075
- const o = c.slice(0, -(r.length + 1));
1076
- o && !o.includes(".") && (i = o);
1114
+ } = e.subdomainRouting, i = t.req.header("x-forwarded-host") || t.req.header("host") || "";
1115
+ let c = null;
1116
+ if (i.endsWith(r)) {
1117
+ const o = i.slice(0, -(r.length + 1));
1118
+ o && !o.includes(".") && (c = o);
1077
1119
  }
1078
- if (i && a.includes(i) && (i = null), !i)
1120
+ if (c && a.includes(c) && (c = null), !c)
1079
1121
  return e.accessControl && t.set("tenant_id", e.accessControl.controlPlaneTenantId), n();
1080
1122
  let u = null;
1081
1123
  if (s)
1082
- u = await s(i);
1124
+ u = await s(c);
1083
1125
  else if (e.subdomainRouting.useOrganizations !== !1 && e.accessControl)
1084
1126
  try {
1085
1127
  const o = await t.env.data.organizations.get(
1086
1128
  e.accessControl.controlPlaneTenantId,
1087
- i
1129
+ c
1088
1130
  );
1089
1131
  o && (u = o.id);
1090
1132
  } catch {
1091
1133
  }
1092
1134
  if (!u)
1093
1135
  throw new A(404, {
1094
- message: `Tenant not found for subdomain: ${i}`
1136
+ message: `Tenant not found for subdomain: ${c}`
1095
1137
  });
1096
1138
  return t.set("tenant_id", u), n();
1097
1139
  };
1098
1140
  }
1099
- function Re(e) {
1141
+ function $e(e) {
1100
1142
  return async (t, n) => {
1101
1143
  if (!e.databaseIsolation)
1102
1144
  return n();
@@ -1119,14 +1161,14 @@ function Re(e) {
1119
1161
  return n();
1120
1162
  };
1121
1163
  }
1122
- function x(e) {
1123
- const t = Ie(e), n = Se(e), r = Re(e);
1164
+ function ee(e) {
1165
+ const t = ze(e), n = Re(e), r = $e(e);
1124
1166
  return async (a, s) => (await t(a, async () => {
1125
1167
  }), await n(a, async () => {
1126
1168
  }), await r(a, async () => {
1127
1169
  }), s());
1128
1170
  }
1129
- function De(e) {
1171
+ function ke(e) {
1130
1172
  const {
1131
1173
  dataAdapter: t,
1132
1174
  controlPlane: n,
@@ -1135,8 +1177,8 @@ function De(e) {
1135
1177
  clientId: a
1136
1178
  } = {},
1137
1179
  sync: s = { resourceServers: !0, roles: !0 },
1138
- defaultPermissions: c = ["tenant:admin"],
1139
- requireOrganizationMatch: i = !1,
1180
+ defaultPermissions: i = ["tenant:admin"],
1181
+ requireOrganizationMatch: c = !1,
1140
1182
  managementApiExtensions: u = [],
1141
1183
  entityHooks: o,
1142
1184
  getChildTenantIds: l,
@@ -1144,11 +1186,11 @@ function De(e) {
1144
1186
  ...d
1145
1187
  } = e;
1146
1188
  let f = t, m = t;
1147
- n && (f = Z(t, {
1189
+ n && (f = x(t, {
1148
1190
  controlPlaneTenantId: r,
1149
1191
  controlPlaneClientId: a
1150
1192
  }), m = {
1151
- ...be(t, {
1193
+ ...Pe(t, {
1152
1194
  controlPlaneTenantId: r
1153
1195
  }),
1154
1196
  multiTenancyConfig: {
@@ -1169,7 +1211,7 @@ function De(e) {
1169
1211
  getAdapters: g ?? (async () => f),
1170
1212
  getControlPlaneAdapters: async () => f,
1171
1213
  sync: C
1172
- }, { entityHooks: P, tenantHooks: p } = he(b), T = {
1214
+ }, { entityHooks: P, tenantHooks: h } = ye(b), T = {
1173
1215
  resourceServers: [
1174
1216
  P.resourceServers,
1175
1217
  ...(o == null ? void 0 : o.resourceServers) ?? []
@@ -1178,54 +1220,54 @@ function De(e) {
1178
1220
  connections: (o == null ? void 0 : o.connections) ?? [],
1179
1221
  tenants: (o == null ? void 0 : o.tenants) ?? [],
1180
1222
  rolePermissions: (o == null ? void 0 : o.rolePermissions) ?? []
1181
- }, h = X({
1223
+ }, p = Y({
1182
1224
  accessControl: {
1183
1225
  controlPlaneTenantId: r,
1184
- requireOrganizationMatch: i,
1185
- defaultPermissions: c
1226
+ requireOrganizationMatch: c,
1227
+ defaultPermissions: i
1186
1228
  }
1187
- }), F = N(
1229
+ }), j = N(
1188
1230
  {
1189
1231
  accessControl: {
1190
1232
  controlPlaneTenantId: r,
1191
- requireOrganizationMatch: i,
1192
- defaultPermissions: c
1233
+ requireOrganizationMatch: c,
1234
+ defaultPermissions: i
1193
1235
  }
1194
1236
  },
1195
1237
  { tenants: {
1196
1238
  async beforeCreate(S, v) {
1197
- return h.beforeCreate && (v = await h.beforeCreate(S, v)), p.beforeCreate && (v = await p.beforeCreate(S, v)), v;
1239
+ return p.beforeCreate && (v = await p.beforeCreate(S, v)), h.beforeCreate && (v = await h.beforeCreate(S, v)), v;
1198
1240
  },
1199
1241
  async afterCreate(S, v) {
1200
1242
  var $, R;
1201
- await (($ = h.afterCreate) == null ? void 0 : $.call(h, S, v)), await ((R = p.afterCreate) == null ? void 0 : R.call(p, S, v));
1243
+ await (($ = p.afterCreate) == null ? void 0 : $.call(p, S, v)), await ((R = h.afterCreate) == null ? void 0 : R.call(h, S, v));
1202
1244
  },
1203
1245
  async beforeDelete(S, v) {
1204
1246
  var $, R;
1205
- await (($ = h.beforeDelete) == null ? void 0 : $.call(h, S, v)), await ((R = p.beforeDelete) == null ? void 0 : R.call(p, S, v));
1247
+ await (($ = p.beforeDelete) == null ? void 0 : $.call(p, S, v)), await ((R = h.beforeDelete) == null ? void 0 : R.call(h, S, v));
1206
1248
  }
1207
1249
  } }
1208
- ), { app: j } = ce({
1250
+ ), { app: F } = le({
1209
1251
  dataAdapter: f,
1210
1252
  managementDataAdapter: m,
1211
1253
  ...d,
1212
1254
  entityHooks: T,
1213
1255
  managementApiExtensions: [
1214
1256
  ...u,
1215
- { path: "/tenants", router: F }
1257
+ { path: "/tenants", router: j }
1216
1258
  ]
1217
1259
  });
1218
- return j.use(
1260
+ return F.use(
1219
1261
  "/api/v2/*",
1220
- Ae(r)
1221
- ), w && j.use("/api/v2/*", Ce()), { app: j, controlPlaneTenantId: r };
1262
+ Ie(r)
1263
+ ), w && F.use("/api/v2/*", Te()), { app: F, controlPlaneTenantId: r };
1222
1264
  }
1223
- function qe(e) {
1265
+ function Oe(e) {
1224
1266
  const t = B(e);
1225
1267
  return {
1226
1268
  name: "multi-tenancy",
1227
1269
  // Apply multi-tenancy middleware for subdomain routing, database resolution, etc.
1228
- middleware: x(e),
1270
+ middleware: ee(e),
1229
1271
  // Provide lifecycle hooks
1230
1272
  hooks: t,
1231
1273
  // Mount tenant management routes
@@ -1246,22 +1288,22 @@ function qe(e) {
1246
1288
  };
1247
1289
  }
1248
1290
  function B(e) {
1249
- const t = e.accessControl ? ue(e.accessControl) : {}, n = e.databaseIsolation ? fe(e.databaseIsolation) : {}, r = X(e);
1291
+ const t = e.accessControl ? de(e.accessControl) : {}, n = e.databaseIsolation ? me(e.databaseIsolation) : {}, r = Y(e);
1250
1292
  return {
1251
1293
  ...t,
1252
1294
  ...n,
1253
1295
  tenants: r
1254
1296
  };
1255
1297
  }
1256
- function ze(e) {
1257
- const t = new ne(), n = B(e);
1298
+ function je(e) {
1299
+ const t = new re(), n = B(e);
1258
1300
  return t.route("/tenants", N(e, n)), t;
1259
1301
  }
1260
- function Oe(e) {
1302
+ function Ee(e) {
1261
1303
  return {
1262
1304
  hooks: B(e),
1263
- middleware: x(e),
1264
- app: ze(e),
1305
+ middleware: ee(e),
1306
+ app: je(e),
1265
1307
  config: e,
1266
1308
  /**
1267
1309
  * Wraps data adapters with runtime fallback from the control plane.
@@ -1273,7 +1315,7 @@ function Oe(e) {
1273
1315
  */
1274
1316
  wrapAdapters: (t, n) => {
1275
1317
  var r;
1276
- return Z(t, {
1318
+ return x(t, {
1277
1319
  controlPlaneTenantId: (r = e.accessControl) == null ? void 0 : r.controlPlaneTenantId,
1278
1320
  controlPlaneClientId: n == null ? void 0 : n.controlPlaneClientId
1279
1321
  });
@@ -1281,24 +1323,24 @@ function Oe(e) {
1281
1323
  };
1282
1324
  }
1283
1325
  export {
1284
- ue as createAccessControlHooks,
1285
- Se as createAccessControlMiddleware,
1286
- Ae as createControlPlaneTenantMiddleware,
1287
- fe as createDatabaseHooks,
1288
- Re as createDatabaseMiddleware,
1289
- ze as createMultiTenancy,
1326
+ de as createAccessControlHooks,
1327
+ Re as createAccessControlMiddleware,
1328
+ Ie as createControlPlaneTenantMiddleware,
1329
+ me as createDatabaseHooks,
1330
+ $e as createDatabaseMiddleware,
1331
+ je as createMultiTenancy,
1290
1332
  B as createMultiTenancyHooks,
1291
- x as createMultiTenancyMiddleware,
1292
- qe as createMultiTenancyPlugin,
1293
- Ce as createProtectSyncedMiddleware,
1294
- X as createProvisioningHooks,
1295
- Pe as createRuntimeFallbackAdapter,
1296
- Ie as createSubdomainMiddleware,
1297
- he as createSyncHooks,
1333
+ ee as createMultiTenancyMiddleware,
1334
+ Oe as createMultiTenancyPlugin,
1335
+ Te as createProtectSyncedMiddleware,
1336
+ Y as createProvisioningHooks,
1337
+ Ae as createRuntimeFallbackAdapter,
1338
+ ze as createSubdomainMiddleware,
1339
+ ye as createSyncHooks,
1298
1340
  N as createTenantsOpenAPIRouter,
1299
- De as initMultiTenant,
1300
- Oe as setupMultiTenancy,
1301
- de as validateTenantAccess,
1302
- Z as withRuntimeFallback,
1303
- be as withSystemResourceServerInheritance
1341
+ ke as initMultiTenant,
1342
+ Ee as setupMultiTenancy,
1343
+ fe as validateTenantAccess,
1344
+ x as withRuntimeFallback,
1345
+ Pe as withSystemResourceServerInheritance
1304
1346
  };
@@ -1 +1 @@
1
- {"version":3,"file":"settings-inheritance.d.ts","sourceRoot":"","sources":["../../../src/middleware/settings-inheritance.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,YAAY,EAOb,MAAM,UAAU,CAAC;AAoNlB;;;;;;;;GAQG;AACH,wBAAgB,mCAAmC,CACjD,YAAY,EAAE,YAAY,EAC1B,MAAM,EAAE;IAAE,oBAAoB,CAAC,EAAE,MAAM,CAAA;CAAE,GACxC,YAAY,CAQd;AAED;;;;GAIG;AACH,MAAM,WAAW,qBAAqB;IACpC;;;;OAIG;IACH,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAE9B;;;;OAIG;IACH,oBAAoB,CAAC,EAAE,MAAM,CAAC;CAC/B;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,wBAAgB,4BAA4B,CAC1C,YAAY,EAAE,YAAY,EAC1B,MAAM,EAAE,qBAAqB,GAC5B,YAAY,CAyMd;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,mBAAmB,CACjC,YAAY,EAAE,YAAY,EAC1B,MAAM,EAAE,qBAAqB,GAC5B,YAAY,CAEd"}
1
+ {"version":3,"file":"settings-inheritance.d.ts","sourceRoot":"","sources":["../../../src/middleware/settings-inheritance.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,YAAY,EAOb,MAAM,UAAU,CAAC;AAmNlB;;;;;;;;GAQG;AACH,wBAAgB,mCAAmC,CACjD,YAAY,EAAE,YAAY,EAC1B,MAAM,EAAE;IAAE,oBAAoB,CAAC,EAAE,MAAM,CAAA;CAAE,GACxC,YAAY,CAQd;AAED;;;;GAIG;AACH,MAAM,WAAW,qBAAqB;IACpC;;;;OAIG;IACH,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAE9B;;;;OAIG;IACH,oBAAoB,CAAC,EAAE,MAAM,CAAC;CAC/B;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,wBAAgB,4BAA4B,CAC1C,YAAY,EAAE,YAAY,EAC1B,MAAM,EAAE,qBAAqB,GAC5B,YAAY,CA2Md;AA2FD;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,mBAAmB,CACjC,YAAY,EAAE,YAAY,EAC1B,MAAM,EAAE,qBAAqB,GAC5B,YAAY,CAEd"}
package/package.json CHANGED
@@ -11,7 +11,7 @@
11
11
  "type": "git",
12
12
  "url": "https://github.com/markusahlstrand/authhero"
13
13
  },
14
- "version": "14.19.1",
14
+ "version": "14.20.1",
15
15
  "description": "Multi-tenancy support for AuthHero with organization-based access control and per-tenant database isolation",
16
16
  "files": [
17
17
  "dist"
@@ -36,9 +36,9 @@
36
36
  "typescript": "^5.6.0",
37
37
  "vite": "^6.0.0",
38
38
  "vitest": "^2.1.0",
39
- "@authhero/kysely-adapter": "10.123.0",
40
- "@authhero/adapter-interfaces": "1.3.0",
41
- "authhero": "4.96.0"
39
+ "@authhero/kysely-adapter": "10.131.4",
40
+ "authhero": "4.107.0",
41
+ "@authhero/adapter-interfaces": "1.10.2"
42
42
  },
43
43
  "dependencies": {
44
44
  "zod": "^3.24.0"