@authhero/multi-tenancy 13.13.3 → 13.15.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.
- package/README.md +46 -0
- package/dist/multi-tenancy.cjs +1 -1
- package/dist/multi-tenancy.d.ts +25763 -2645
- package/dist/multi-tenancy.mjs +817 -777
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -117,6 +117,52 @@ const config: AuthHeroConfig = {
|
|
|
117
117
|
};
|
|
118
118
|
```
|
|
119
119
|
|
|
120
|
+
## Migration Guide
|
|
121
|
+
|
|
122
|
+
### Migrating from Legacy Settings Inheritance
|
|
123
|
+
|
|
124
|
+
If you're using the deprecated settings inheritance functions, migrate to the new runtime fallback API:
|
|
125
|
+
|
|
126
|
+
#### Before (Deprecated)
|
|
127
|
+
|
|
128
|
+
```typescript
|
|
129
|
+
import {
|
|
130
|
+
withSettingsInheritance,
|
|
131
|
+
SettingsInheritanceConfig,
|
|
132
|
+
} from "@authhero/multi-tenancy";
|
|
133
|
+
|
|
134
|
+
const config: SettingsInheritanceConfig = {
|
|
135
|
+
controlPlaneTenantId: "main",
|
|
136
|
+
controlPlaneClientId: "main-client",
|
|
137
|
+
};
|
|
138
|
+
|
|
139
|
+
const adapters = withSettingsInheritance(baseAdapters, config);
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
#### After (Current)
|
|
143
|
+
|
|
144
|
+
```typescript
|
|
145
|
+
import {
|
|
146
|
+
withRuntimeFallback,
|
|
147
|
+
RuntimeFallbackConfig,
|
|
148
|
+
} from "@authhero/multi-tenancy";
|
|
149
|
+
|
|
150
|
+
const config: RuntimeFallbackConfig = {
|
|
151
|
+
controlPlaneTenantId: "main",
|
|
152
|
+
controlPlaneClientId: "main-client",
|
|
153
|
+
};
|
|
154
|
+
|
|
155
|
+
const adapters = withRuntimeFallback(baseAdapters, config);
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
**What changed:**
|
|
159
|
+
|
|
160
|
+
- `withSettingsInheritance` → `withRuntimeFallback`
|
|
161
|
+
- `createSettingsInheritanceAdapter` → `createRuntimeFallbackAdapter`
|
|
162
|
+
- `SettingsInheritanceConfig` → `RuntimeFallbackConfig`
|
|
163
|
+
|
|
164
|
+
The functionality remains identical - this is purely a naming change to better reflect that settings are inherited at runtime without copying data between tenants.
|
|
165
|
+
|
|
120
166
|
## License
|
|
121
167
|
|
|
122
168
|
MIT
|
package/dist/multi-tenancy.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var Z=Object.defineProperty;var H=(e,t,s)=>t in e?Z(e,t,{enumerable:!0,configurable:!0,writable:!0,value:s}):e[t]=s;var D=(e,t,s)=>H(e,typeof t!="symbol"?t+"":t,s);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const N=require("hono"),T=require("authhero"),C=require("@hono/zod-openapi"),I=require("@authhero/adapter-interfaces");var v=class extends Error{constructor(t=500,s){super(s==null?void 0:s.message,{cause:s==null?void 0:s.cause});D(this,"res");D(this,"status");this.res=s==null?void 0:s.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 U(e){const{controlPlaneTenantId:t,requireOrganizationMatch:s=!0}=e;return{async onTenantAccessValidation(a,i){if(i===t)return!0;if(s){const n=a.var.org_name,d=a.var.organization_id,l=n||d;return l?l===i:!1}return!0}}}function E(e,t,s,a){if(t===s)return!0;const i=a||e;return i?i===t:!1}function K(e){return{async resolveDataAdapters(t){try{return await e.getAdapters(t)}catch(s){console.error(`Failed to resolve data adapters for tenant ${t}:`,s);return}}}}function G(e){return{async beforeCreate(t,s){return!s.audience&&s.id?{...s,audience:T.getTenantAudience(s.id)}:s},async afterCreate(t,s){const{accessControl:a,databaseIsolation:i,settingsInheritance:n}=e;a&&t.ctx&&await x(t,s,a),i!=null&&i.onProvision&&await i.onProvision(s.id),(n==null?void 0:n.inheritFromControlPlane)!==!1&&t.ctx&&await ae(t,s,e)},async beforeDelete(t,s){const{accessControl:a,databaseIsolation:i}=e;if(a)try{const d=(await t.adapters.organizations.list(a.controlPlaneTenantId)).organizations.find(l=>l.name===s);d&&await t.adapters.organizations.remove(a.controlPlaneTenantId,d.id)}catch(n){console.warn(`Failed to remove organization for tenant ${s}:`,n)}if(i!=null&&i.onDeprovision)try{await i.onDeprovision(s)}catch(n){console.warn(`Failed to deprovision database for tenant ${s}:`,n)}}}}async function x(e,t,s){const{controlPlaneTenantId:a,defaultPermissions:i,defaultRoles:n,issuer:d,adminRoleName:l="Tenant Admin",adminRoleDescription:c="Full access to all tenant management operations",addCreatorToOrganization:r=!0}=s,f=await e.adapters.organizations.create(a,{name:t.id,display_name:t.friendly_name||t.id});let u;if(d&&(u=await te(e,a,l,c)),r&&e.ctx){const o=e.ctx.var.user;if(o!=null&&o.sub&&!await ee(e,a,o.sub))try{await e.adapters.userOrganizations.create(a,{user_id:o.sub,organization_id:f.id}),u&&await e.adapters.userRoles.create(a,o.sub,u,f.id)}catch(g){console.warn(`Failed to add creator ${o.sub} to organization ${f.id}:`,g)}}n&&n.length>0&&console.log(`Would assign roles ${n.join(", ")} to organization ${f.id}`),i&&i.length>0&&console.log(`Would grant permissions ${i.join(", ")} to organization ${f.id}`)}async function ee(e,t,s){const a=await e.adapters.userRoles.list(t,s,void 0,"");for(const i of a)if((await e.adapters.rolePermissions.list(t,i.id,{per_page:1e3})).some(l=>l.permission_name==="admin:organizations"))return!0;return!1}async function te(e,t,s,a){const n=(await e.adapters.roles.list(t,{})).roles.find(r=>r.name===s);if(n)return n.id;const d=await e.adapters.roles.create(t,{name:s,description:a}),l=T.MANAGEMENT_API_AUDIENCE,c=T.MANAGEMENT_API_SCOPES.map(r=>({role_id:d.id,resource_server_identifier:l,permission_name:r.value}));return await e.adapters.rolePermissions.assign(t,d.id,c),d.id}async function ae(e,t,s){const{accessControl:a,settingsInheritance:i}=s;if(!a)return;const n=await e.adapters.tenants.get(a.controlPlaneTenantId);if(!n)return;let d={...n};const l=["id","created_at","updated_at","friendly_name","audience","sender_email","sender_name"];for(const c of l)delete d[c];if(i!=null&&i.inheritedKeys){const c={};for(const r of i.inheritedKeys)r in n&&!l.includes(r)&&(c[r]=n[r]);d=c}if(i!=null&&i.excludedKeys)for(const c of i.excludedKeys)delete d[c];i!=null&&i.transformSettings&&(d=i.transformSettings(d,t.id)),Object.keys(d).length>0&&await e.adapters.tenants.update(t.id,d)}function B(e){const{controlPlaneTenantId:t,getChildTenantIds:s,getAdapters:a,shouldSync:i=()=>!0,transformForSync:n}=e;async function d(r,f,u){return(await r.resourceServers.list(f,{q:`identifier:${u}`,per_page:1})).resource_servers[0]??null}async function l(r,f){const u=await s();await Promise.all(u.map(async o=>{try{const p=await a(o),h={...n?n(r,o):{name:r.name,identifier:r.identifier,scopes:r.scopes,signing_alg:r.signing_alg,signing_secret:r.signing_secret,token_lifetime:r.token_lifetime,token_lifetime_for_web:r.token_lifetime_for_web,skip_consent_for_verifiable_first_party_clients:r.skip_consent_for_verifiable_first_party_clients,allow_offline_access:r.allow_offline_access,verificationKey:r.verificationKey,options:r.options},is_system:!0};if(f==="create"){const A=await d(p,o,r.identifier);A&&A.id?await p.resourceServers.update(o,A.id,h):await p.resourceServers.create(o,h)}else{const A=await d(p,o,r.identifier);A&&A.id?await p.resourceServers.update(o,A.id,h):await p.resourceServers.create(o,h)}}catch(p){console.error(`Failed to sync resource server "${r.identifier}" to tenant "${o}":`,p)}}))}async function c(r){const f=await s();await Promise.all(f.map(async u=>{try{const o=await a(u),p=await d(o,u,r);p&&p.id&&await o.resourceServers.remove(u,p.id)}catch(o){console.error(`Failed to delete resource server "${r}" from tenant "${u}":`,o)}}))}return{afterCreate:async(r,f)=>{r.tenantId===t&&i(f)&&await l(f,"create")},afterUpdate:async(r,f,u)=>{r.tenantId===t&&i(u)&&await l(u,"update")},afterDelete:async(r,f)=>{r.tenantId===t&&await c(f)}}}function W(e){const{controlPlaneTenantId:t,getControlPlaneAdapters:s,getAdapters:a,shouldSync:i=()=>!0,transformForSync:n}=e;return{async afterCreate(d,l){if(l.id!==t)try{const c=await s(),r=await a(l.id),f=await T.fetchAll(u=>c.resourceServers.list(t,u),"resource_servers",{cursorField:"id",pageSize:100});await Promise.all(f.filter(u=>i(u)).map(async u=>{const o=u;try{const p=n?n(o,l.id):{name:o.name,identifier:o.identifier,scopes:o.scopes,signing_alg:o.signing_alg,signing_secret:o.signing_secret,token_lifetime:o.token_lifetime,token_lifetime_for_web:o.token_lifetime_for_web,skip_consent_for_verifiable_first_party_clients:o.skip_consent_for_verifiable_first_party_clients,allow_offline_access:o.allow_offline_access,verificationKey:o.verificationKey,options:o.options};await r.resourceServers.create(l.id,{...p,is_system:!0})}catch(p){console.error(`Failed to sync resource server "${o.identifier}" to new tenant "${l.id}":`,p)}}))}catch(c){console.error(`Failed to sync resource servers to new tenant "${l.id}":`,c)}}}}function L(e){const{controlPlaneTenantId:t,getChildTenantIds:s,getAdapters:a,shouldSync:i=()=>!0,transformForSync:n}=e;async function d(c,r,f){return(await c.roles.list(r,{q:`name:${f}`,per_page:1})).roles[0]??null}async function l(c,r){const f=await s();await Promise.all(f.map(async u=>{try{const o=await a(u),g={...n?n(c,u):{name:c.name,description:c.description},is_system:!0};if(r==="create"){const h=await d(o,u,c.name);h&&h.id?await o.roles.update(u,h.id,g):await o.roles.create(u,g)}else{const h=await d(o,u,c.name);h&&h.id?await o.roles.update(u,h.id,g):await o.roles.create(u,g)}}catch(o){console.error(`Failed to sync role "${c.name}" to tenant "${u}":`,o)}}))}return{afterCreate:async(c,r)=>{c.tenantId===t&&i(r)&&await l(r,"create")},afterUpdate:async(c,r,f)=>{c.tenantId===t&&i(f)&&await l(f,"update")},afterDelete:async(c,r)=>{c.tenantId===t&&console.warn(`Role ${r} was deleted from control plane. Child tenant roles with matching names should be deleted manually or implement role name tracking.`)}}}function Q(e){const{controlPlaneTenantId:t,getControlPlaneAdapters:s,getAdapters:a,shouldSync:i=()=>!0,transformForSync:n,syncPermissions:d=!0}=e;return{async afterCreate(l,c){if(c.id!==t)try{const r=await s(),f=await a(c.id),u=await T.fetchAll(p=>r.roles.list(t,p),"roles",{cursorField:"id",pageSize:100}),o=new Map;if(await Promise.all(u.filter(p=>i(p)).map(async p=>{const g=p;try{const h=n?n(g,c.id):{name:g.name,description:g.description},A=await f.roles.create(c.id,{...h,is_system:!0});o.set(g.id,A.id)}catch(h){console.error(`Failed to sync role "${g.name}" to new tenant "${c.id}":`,h)}})),d)for(const[p,g]of o)try{const h=await r.rolePermissions.list(t,p,{});h.length>0&&await f.rolePermissions.assign(c.id,g,h.map(A=>({role_id:g,resource_server_identifier:A.resource_server_identifier,permission_name:A.permission_name})))}catch(h){console.error(`Failed to sync permissions for role to new tenant "${c.id}":`,h)}}catch(r){console.error(`Failed to sync roles to new tenant "${c.id}":`,r)}}}}function O(e,t){const s=new C.OpenAPIHono;return s.openapi(C.createRoute({tags:["tenants"],method:"get",path:"/",request:{query:I.auth0QuerySchema},security:[{Bearer:[]}],responses:{200:{content:{"application/json":{schema:C.z.object({tenants:C.z.array(I.tenantSchema),start:C.z.number().optional(),limit:C.z.number().optional(),length:C.z.number().optional()})}},description:"List of tenants"}}}),async a=>{var p,g,h,A;const i=a.req.valid("query"),{page:n,per_page:d,include_totals:l,q:c}=i,r=a.var.user,f=(r==null?void 0:r.permissions)||[];if(f.includes("auth:read")||f.includes("admin:organizations")){const S=await a.env.data.tenants.list({page:n,per_page:d,include_totals:l,q:c});return l?a.json({tenants:S.tenants,start:((p=S.totals)==null?void 0:p.start)??0,limit:((g=S.totals)==null?void 0:g.limit)??d,length:S.tenants.length}):a.json({tenants:S.tenants})}if(e.accessControl&&(r!=null&&r.sub)){const S=e.accessControl.controlPlaneTenantId,z=(await T.fetchAll(M=>a.env.data.userOrganizations.listUserOrganizations(S,r.sub,M),"organizations")).map(M=>M.name);if(z.length===0)return l?a.json({tenants:[],start:0,limit:d??50,length:0}):a.json({tenants:[]});const $=z.length,F=n??0,P=d??50,w=F*P,m=z.slice(w,w+P);if(m.length===0)return l?a.json({tenants:[],start:w,limit:P,length:$}):a.json({tenants:[]});const y=m.map(M=>`id:${M}`).join(" OR "),_=c?`(${y}) AND (${c})`:y,b=await a.env.data.tenants.list({q:_,per_page:P,include_totals:!1});return l?a.json({tenants:b.tenants,start:w,limit:P,length:$}):a.json({tenants:b.tenants})}const o=await a.env.data.tenants.list({page:n,per_page:d,include_totals:l,q:c});return l?a.json({tenants:o.tenants,start:((h=o.totals)==null?void 0:h.start)??0,limit:((A=o.totals)==null?void 0:A.limit)??d,length:o.tenants.length}):a.json({tenants:o.tenants})}),s.openapi(C.createRoute({tags:["tenants"],method:"post",path:"/",request:{body:{content:{"application/json":{schema:I.tenantInsertSchema}}}},security:[{Bearer:[]}],responses:{201:{content:{"application/json":{schema:I.tenantSchema}},description:"Tenant created"},400:{description:"Validation error"},409:{description:"Tenant with this ID already exists"}}}),async a=>{var c,r;const i=a.var.user;if(!(i!=null&&i.sub))throw new v(401,{message:"Authentication required to create tenants"});let n=a.req.valid("json");const d={adapters:a.env.data,ctx:a};(c=t.tenants)!=null&&c.beforeCreate&&(n=await t.tenants.beforeCreate(d,n));const l=await a.env.data.tenants.create(n);return(r=t.tenants)!=null&&r.afterCreate&&await t.tenants.afterCreate(d,l),a.json(l,201)}),s.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 a=>{var l,c;const{id:i}=a.req.valid("param");if(e.accessControl){const r=a.var.user,f=e.accessControl.controlPlaneTenantId;if(!(r!=null&&r.sub))throw new v(401,{message:"Authentication required"});if(i===f)throw new v(403,{message:"Cannot delete the control plane"});if(!(await T.fetchAll(p=>a.env.data.userOrganizations.listUserOrganizations(f,r.sub,p),"organizations")).some(p=>p.name===i))throw new v(403,{message:"Access denied to this tenant"})}if(!await a.env.data.tenants.get(i))throw new v(404,{message:"Tenant not found"});const d={adapters:a.env.data,ctx:a};return(l=t.tenants)!=null&&l.beforeDelete&&await t.tenants.beforeDelete(d,i),await a.env.data.tenants.remove(i),(c=t.tenants)!=null&&c.afterDelete&&await t.tenants.afterDelete(d,i),a.body(null,204)}),s}function ne(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:s,type:a}of t){const i=e.match(s);if(i&&i[1])return{type:a,id:i[1]}}return null}async function re(e,t,s){try{switch(s.type){case"resource_server":{const a=await e.resourceServers.get(t,s.id);return(a==null?void 0:a.is_system)===!0}case"role":{const a=await e.roles.get(t,s.id);return(a==null?void 0:a.is_system)===!0}case"connection":{const a=await e.connections.get(t,s.id);return(a==null?void 0:a.is_system)===!0}default:return!1}}catch{return!1}}function se(e){return{resource_server:"resource server",role:"role",connection:"connection"}[e]}function V(){return async(e,t)=>{if(!["PATCH","PUT","DELETE"].includes(e.req.method))return t();const s=ne(e.req.path);if(!s)return t();const a=e.var.tenant_id||e.req.header("x-tenant-id")||e.req.header("tenant-id");if(!a)return t();if(await re(e.env.data,a,s))throw new v(403,{message:`This ${se(s.type)} is a system resource and cannot be modified. Make changes in the control plane instead.`});return t()}}function k(e){return async(t,s)=>{if(!e.accessControl)return s();const a=t.var.tenant_id,i=t.var.organization_id;if(!a)throw new v(400,{message:"Tenant ID not found in request"});if(!E(i,a,e.accessControl.controlPlaneTenantId))throw new v(403,{message:`Access denied to tenant ${a}`});return s()}}function J(e){return async(t,s)=>{if(!e.subdomainRouting)return s();const{baseDomain:a,reservedSubdomains:i=[],resolveSubdomain:n}=e.subdomainRouting,d=t.req.header("host")||"";let l=null;if(d.endsWith(a)){const r=d.slice(0,-(a.length+1));r&&!r.includes(".")&&(l=r)}if(l&&i.includes(l)&&(l=null),!l)return e.accessControl&&t.set("tenant_id",e.accessControl.controlPlaneTenantId),s();let c=null;if(n)c=await n(l);else if(e.subdomainRouting.useOrganizations!==!1&&e.accessControl)try{const r=await t.env.data.organizations.get(e.accessControl.controlPlaneTenantId,l);r&&(c=r.id)}catch{}if(!c)throw new v(404,{message:`Tenant not found for subdomain: ${l}`});return t.set("tenant_id",c),s()}}function X(e){return async(t,s)=>{if(!e.databaseIsolation)return s();const a=t.var.tenant_id;if(!a)throw new v(400,{message:"Tenant ID not found in request"});try{const i=await e.databaseIsolation.getAdapters(a);t.env.data=i}catch(i){throw console.error(`Failed to resolve database for tenant ${a}:`,i),new v(500,{message:"Failed to resolve tenant database"})}return s()}}function j(e){const t=J(e),s=k(e),a=X(e);return async(i,n)=>(await t(i,async()=>{}),await s(i,async()=>{}),await a(i,async()=>{}),n())}function ie(e){const t=R(e);return{name:"multi-tenancy",middleware:j(e),hooks:t,routes:[{path:"/management",handler:O(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 R(e){const t=e.accessControl?U(e.accessControl):{},s=e.databaseIsolation?K(e.databaseIsolation):{},a=G(e);return{...t,...s,tenants:a}}function Y(e){const t=new N.Hono,s=R(e);return t.route("/tenants",O(e,s)),t}function oe(e){return{hooks:R(e),middleware:j(e),app:Y(e),config:e}}function ce(e){const{controlPlaneTenantId:t="control_plane",syncResourceServers:s=!0,syncRoles:a=!0,multiTenancy:i,entityHooks:n,...d}=e,l={...i,accessControl:{controlPlaneTenantId:t,requireOrganizationMatch:!1,defaultPermissions:["tenant:admin"],...i==null?void 0:i.accessControl}},c=R(l);let r,f;s&&(r=B({controlPlaneTenantId:t,getChildTenantIds:async()=>(await T.fetchAll(m=>e.dataAdapter.tenants.list(m),"tenants",{cursorField:"id",pageSize:100})).filter(m=>m.id!==t).map(m=>m.id),getAdapters:async w=>e.dataAdapter}),f=W({controlPlaneTenantId:t,getControlPlaneAdapters:async()=>e.dataAdapter,getAdapters:async w=>e.dataAdapter}));let u,o;a&&(u=L({controlPlaneTenantId:t,getChildTenantIds:async()=>(await T.fetchAll(m=>e.dataAdapter.tenants.list(m),"tenants",{cursorField:"id",pageSize:100})).filter(m=>m.id!==t).map(m=>m.id),getAdapters:async w=>e.dataAdapter}),o=Q({controlPlaneTenantId:t,getControlPlaneAdapters:async()=>e.dataAdapter,getAdapters:async w=>e.dataAdapter,syncPermissions:!0}));const p=async(w,m,...y)=>{const _=[];if(w)try{await w(...y)}catch(b){_.push(b instanceof Error?b:new Error(String(b)))}if(m)try{await m(...y)}catch(b){_.push(b instanceof Error?b:new Error(String(b)))}if(_.length===1)throw _[0];if(_.length>1)throw new AggregateError(_,`Multiple hook errors: ${_.map(b=>b.message).join("; ")}`)},g=async(w,...m)=>{const y=[];for(const _ of w)if(_)try{await _(...m)}catch(b){y.push(b instanceof Error?b:new Error(String(b)))}if(y.length===1)throw y[0];if(y.length>1)throw new AggregateError(y,`Multiple hook errors: ${y.map(_=>_.message).join("; ")}`)},h={...n,resourceServers:r?{...n==null?void 0:n.resourceServers,afterCreate:async(w,m)=>{var y;await p((y=n==null?void 0:n.resourceServers)==null?void 0:y.afterCreate,r==null?void 0:r.afterCreate,w,m)},afterUpdate:async(w,m,y)=>{var _;await p((_=n==null?void 0:n.resourceServers)==null?void 0:_.afterUpdate,r==null?void 0:r.afterUpdate,w,m,y)},afterDelete:async(w,m)=>{var y;await p((y=n==null?void 0:n.resourceServers)==null?void 0:y.afterDelete,r==null?void 0:r.afterDelete,w,m)}}:n==null?void 0:n.resourceServers,roles:u?{...n==null?void 0:n.roles,afterCreate:async(w,m)=>{var y;await p((y=n==null?void 0:n.roles)==null?void 0:y.afterCreate,u==null?void 0:u.afterCreate,w,m)},afterUpdate:async(w,m,y)=>{var _;await p((_=n==null?void 0:n.roles)==null?void 0:_.afterUpdate,u==null?void 0:u.afterUpdate,w,m,y)},afterDelete:async(w,m)=>{var y;await p((y=n==null?void 0:n.roles)==null?void 0:y.afterDelete,u==null?void 0:u.afterDelete,w,m)}}:n==null?void 0:n.roles,tenants:f||o?{...n==null?void 0:n.tenants,afterCreate:async(w,m)=>{var y;await g([(y=n==null?void 0:n.tenants)==null?void 0:y.afterCreate,f==null?void 0:f.afterCreate,o==null?void 0:o.afterCreate],w,m)}}:n==null?void 0:n.tenants},A={...c,tenants:f||o?{...c.tenants,afterCreate:async(w,m)=>{var y;(y=c.tenants)!=null&&y.afterCreate&&await c.tenants.afterCreate(w,m),await g([f==null?void 0:f.afterCreate,o==null?void 0:o.afterCreate],w,m)}}:c.tenants},S=O(l,A),q=T.init({...d,entityHooks:h,managementApiExtensions:[...d.managementApiExtensions||[],{path:"/tenants",router:S}]}),{app:z,managementApp:$,...F}=q,P=new N.Hono;return P.onError((w,m)=>w instanceof v?w.getResponse():(console.error(w),m.json({message:"Internal Server Error"},500))),P.use("/api/v2/*",V()),P.route("/",z),{app:P,managementApp:$,...F,multiTenancyConfig:l,multiTenancyHooks:c}}Object.defineProperty(exports,"MANAGEMENT_API_SCOPES",{enumerable:!0,get:()=>T.MANAGEMENT_API_SCOPES});Object.defineProperty(exports,"fetchAll",{enumerable:!0,get:()=>T.fetchAll});Object.defineProperty(exports,"seed",{enumerable:!0,get:()=>T.seed});exports.createAccessControlHooks=U;exports.createAccessControlMiddleware=k;exports.createDatabaseHooks=K;exports.createDatabaseMiddleware=X;exports.createMultiTenancy=Y;exports.createMultiTenancyHooks=R;exports.createMultiTenancyMiddleware=j;exports.createMultiTenancyPlugin=ie;exports.createProtectSyncedMiddleware=V;exports.createProvisioningHooks=G;exports.createResourceServerSyncHooks=B;exports.createRoleSyncHooks=L;exports.createSubdomainMiddleware=J;exports.createTenantResourceServerSyncHooks=W;exports.createTenantRoleSyncHooks=Q;exports.createTenantsOpenAPIRouter=O;exports.init=ce;exports.setupMultiTenancy=oe;exports.validateTenantAccess=E;
|
|
1
|
+
"use strict";var pe=Object.defineProperty;var fe=(t,e,n)=>e in t?pe(t,e,{enumerable:!0,configurable:!0,writable:!0,value:n}):t[e]=n;var G=(t,e,n)=>fe(t,typeof e!="symbol"?e+"":e,n);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const ee=require("hono"),P=require("authhero"),I=require("@hono/zod-openapi"),D=require("@authhero/adapter-interfaces");var S=class extends Error{constructor(e=500,n){super(n==null?void 0:n.message,{cause:n==null?void 0:n.cause});G(this,"res");G(this,"status");this.res=n==null?void 0:n.res,this.status=e}getResponse(){return this.res?new Response(this.res.body,{status:this.status,headers:this.res.headers}):new Response(this.message,{status:this.status})}};function te(t){const{controlPlaneTenantId:e,requireOrganizationMatch:n=!0}=t;return{async onTenantAccessValidation(a,r){if(r===e)return!0;if(n){const l=a.var.org_name,s=a.var.organization_id,i=l||s;return i?i===r:!1}return!0}}}function ne(t,e,n,a){if(e===n)return!0;const r=a||t;return r?r===e:!1}function re(t){return{async resolveDataAdapters(e){try{return await t.getAdapters(e)}catch(n){console.error(`Failed to resolve data adapters for tenant ${e}:`,n);return}}}}function ae(t){return{async beforeCreate(e,n){return!n.audience&&n.id?{...n,audience:P.getTenantAudience(n.id)}:n},async afterCreate(e,n){const{accessControl:a,databaseIsolation:r}=t;a&&e.ctx&&await we(e,n,a),r!=null&&r.onProvision&&await r.onProvision(n.id)},async beforeDelete(e,n){const{accessControl:a,databaseIsolation:r}=t;if(a)try{const s=(await e.adapters.organizations.list(a.controlPlaneTenantId)).organizations.find(i=>i.name===n);s&&await e.adapters.organizations.remove(a.controlPlaneTenantId,s.id)}catch(l){console.warn(`Failed to remove organization for tenant ${n}:`,l)}if(r!=null&&r.onDeprovision)try{await r.onDeprovision(n)}catch(l){console.warn(`Failed to deprovision database for tenant ${n}:`,l)}}}}async function we(t,e,n){const{controlPlaneTenantId:a,defaultPermissions:r,defaultRoles:l,issuer:s,adminRoleName:i="Tenant Admin",adminRoleDescription:p="Full access to all tenant management operations",addCreatorToOrganization:o=!0}=n,c=await t.adapters.organizations.create(a,{name:e.id,display_name:e.friendly_name||e.id});let u;if(s&&(u=await he(t,a,i,p)),o&&t.ctx){const d=t.ctx.var.user;if(d!=null&&d.sub&&!await ge(t,a,d.sub))try{await t.adapters.userOrganizations.create(a,{user_id:d.sub,organization_id:c.id}),u&&await t.adapters.userRoles.create(a,d.sub,u,c.id)}catch(f){console.warn(`Failed to add creator ${d.sub} to organization ${c.id}:`,f)}}l&&l.length>0&&console.log(`Would assign roles ${l.join(", ")} to organization ${c.id}`),r&&r.length>0&&console.log(`Would grant permissions ${r.join(", ")} to organization ${c.id}`)}async function ge(t,e,n){const a=await t.adapters.userRoles.list(e,n,void 0,"");for(const r of a)if((await t.adapters.rolePermissions.list(e,r.id,{per_page:1e3})).some(i=>i.permission_name==="admin:organizations"))return!0;return!1}async function he(t,e,n,a){const l=(await t.adapters.roles.list(e,{})).roles.find(o=>o.name===n);if(l)return l.id;const s=await t.adapters.roles.create(e,{name:n,description:a}),i=P.MANAGEMENT_API_AUDIENCE,p=P.MANAGEMENT_API_SCOPES.map(o=>({role_id:s.id,resource_server_identifier:i,permission_name:o.value}));return await t.adapters.rolePermissions.assign(e,s.id,p),s.id}const ve=["client_id","client_secret","app_secret","kid","team_id","twilio_sid","twilio_token"];function K(t,e,n=()=>!0){const{controlPlaneTenantId:a,getChildTenantIds:r,getAdapters:l}=t,s=new Map;async function i(c,u,d){return(await e(c).list(u,{q:`name:${d}`,per_page:1}))[0]??null}async function p(c){const u=await r(),d=e(await l(a));await Promise.all(u.map(async m=>{try{const f=await l(m),w=e(f),h={...d.transform(c),is_system:!0},v=await i(f,m,c.name),_=v?w.getId(v):void 0;if(v&&_){const T=w.preserveOnUpdate?w.preserveOnUpdate(v,h):h;await w.update(m,_,T)}else await w.create(m,h)}catch(f){console.error(`Failed to sync ${d.listKey} "${c.name}" to tenant "${m}":`,f)}}))}async function o(c){const u=await r();await Promise.all(u.map(async d=>{try{const m=await l(d),f=e(m),w=await i(m,d,c),g=w?f.getId(w):void 0;w&&g&&await f.remove(d,g)}catch(m){console.error(`Failed to delete entity "${c}" from tenant "${d}":`,m)}}))}return{afterCreate:async(c,u)=>{c.tenantId===a&&n(u)&&await p(u)},afterUpdate:async(c,u,d)=>{c.tenantId===a&&n(d)&&await p(d)},beforeDelete:async(c,u)=>{if(c.tenantId!==a)return;const m=await e(c.adapters).get(c.tenantId,u);m&&n(m)&&s.set(u,m)},afterDelete:async(c,u)=>{if(c.tenantId!==a)return;const d=s.get(u);d&&(s.delete(u),await o(d.name))}}}function L(t,e,n=()=>!0){const{controlPlaneTenantId:a,getControlPlaneAdapters:r,getAdapters:l}=t;return{async afterCreate(s,i){if(i.id!==a)try{const p=await r(),o=await l(i.id),c=e(p),u=e(o),d=await P.fetchAll(m=>c.listPaginated(a,m),c.listKey,{cursorField:"id",pageSize:100});await Promise.all(d.filter(m=>n(m)).map(async m=>{try{const f=c.transform(m);await u.create(i.id,{...f,is_system:!0})}catch(f){console.error(`Failed to sync entity to new tenant "${i.id}":`,f)}}))}catch(p){console.error(`Failed to sync entities to new tenant "${i.id}":`,p)}}}}const E=t=>({list:async(e,n)=>(await t.resourceServers.list(e,n)).resource_servers,listPaginated:(e,n)=>t.resourceServers.list(e,n),get:(e,n)=>t.resourceServers.get(e,n),create:(e,n)=>t.resourceServers.create(e,n),update:(e,n,a)=>t.resourceServers.update(e,n,a),remove:(e,n)=>t.resourceServers.remove(e,n),listKey:"resource_servers",getId:e=>e.id,transform:e=>({name:e.name,identifier:e.identifier,scopes:e.scopes,signing_alg:e.signing_alg,token_lifetime:e.token_lifetime,token_lifetime_for_web:e.token_lifetime_for_web})}),H=t=>({list:async(e,n)=>(await t.roles.list(e,n)).roles,listPaginated:(e,n)=>t.roles.list(e,n),get:(e,n)=>t.roles.get(e,n),create:(e,n)=>t.roles.create(e,n),update:(e,n,a)=>t.roles.update(e,n,a),remove:(e,n)=>t.roles.remove(e,n),listKey:"roles",getId:e=>e.id,transform:e=>({name:e.name,description:e.description})}),x=t=>({list:async(e,n)=>(await t.connections.list(e,n)).connections,listPaginated:(e,n)=>t.connections.list(e,n),get:(e,n)=>t.connections.get(e,n),create:(e,n)=>t.connections.create(e,n),update:(e,n,a)=>t.connections.update(e,n,a),remove:(e,n)=>t.connections.remove(e,n),listKey:"connections",getId:e=>e.id,transform:e=>{const n=e.options?{...e.options}:{};for(const a of ve)delete n[a];return{name:e.name,display_name:e.display_name,strategy:e.strategy,options:n,response_type:e.response_type,response_mode:e.response_mode,is_domain_connection:e.is_domain_connection,show_as_button:e.show_as_button,metadata:e.metadata}},preserveOnUpdate:(e,n)=>{const a=e.options||{};return{...n,options:{...n.options,client_id:a.client_id,client_secret:a.client_secret,app_secret:a.app_secret,kid:a.kid,team_id:a.team_id,twilio_sid:a.twilio_sid,twilio_token:a.twilio_token}}}});function se(t){const{sync:e={},filters:n={}}=t,a=e.resourceServers??!0,r=e.roles??!0,l=e.connections??!0,s=a?K(t,E,n.resourceServers):void 0,i=r?K(t,H,n.roles):void 0,p=l?K(t,x,n.connections):void 0,o=a?L(t,E,n.resourceServers):void 0,c=r?L(t,H,n.roles):void 0,u=l?L(t,x,n.connections):void 0,d=r?{async afterCreate(w,g){var h;if(g.id!==t.controlPlaneTenantId){await((h=c==null?void 0:c.afterCreate)==null?void 0:h.call(c,w,g));try{const v=await t.getControlPlaneAdapters(),_=await t.getAdapters(g.id),T=await P.fetchAll(b=>v.roles.list(t.controlPlaneTenantId,b),"roles",{cursorField:"id",pageSize:100}),M=new Map;for(const b of T.filter(y=>{var A;return((A=n.roles)==null?void 0:A.call(n,y))??!0})){const y=await m(_,g.id,b.name);y&&M.set(b.name,y.id)}for(const b of T.filter(y=>{var A;return((A=n.roles)==null?void 0:A.call(n,y))??!0})){const y=M.get(b.name);if(y)try{const A=await v.rolePermissions.list(t.controlPlaneTenantId,b.id,{});A.length>0&&await _.rolePermissions.assign(g.id,y,A.map(O=>({role_id:y,resource_server_identifier:O.resource_server_identifier,permission_name:O.permission_name})))}catch(A){console.error(`Failed to sync permissions for role "${b.name}" to tenant "${g.id}":`,A)}}}catch(v){console.error(`Failed to sync role permissions to tenant "${g.id}":`,v)}}}}:void 0;async function m(w,g,h){return(await w.roles.list(g,{q:`name:${h}`,per_page:1})).roles[0]??null}return{entityHooks:{resourceServers:s,roles:i,connections:p},tenantHooks:{async afterCreate(w,g){const h=[o==null?void 0:o.afterCreate,(d==null?void 0:d.afterCreate)??(c==null?void 0:c.afterCreate),u==null?void 0:u.afterCreate],v=[];for(const _ of h)if(_)try{await _(w,g)}catch(T){v.push(T instanceof Error?T:new Error(String(T)))}if(v.length===1)throw v[0];if(v.length>1)throw new AggregateError(v,v.map(_=>_.message).join("; "))}}}}function N(t,e){const n=new I.OpenAPIHono;return n.openapi(I.createRoute({tags:["tenants"],method:"get",path:"/",request:{query:D.auth0QuerySchema},security:[{Bearer:[]}],responses:{200:{content:{"application/json":{schema:I.z.object({tenants:I.z.array(D.tenantSchema),start:I.z.number().optional(),limit:I.z.number().optional(),length:I.z.number().optional()})}},description:"List of tenants"}}}),async a=>{var m,f,w,g;const r=a.req.valid("query"),{page:l,per_page:s,include_totals:i,q:p}=r,o=a.var.user,c=(o==null?void 0:o.permissions)||[];if(c.includes("auth:read")||c.includes("admin:organizations")){const h=await a.env.data.tenants.list({page:l,per_page:s,include_totals:i,q:p});return i?a.json({tenants:h.tenants,start:((m=h.totals)==null?void 0:m.start)??0,limit:((f=h.totals)==null?void 0:f.limit)??s,length:h.tenants.length}):a.json({tenants:h.tenants})}if(t.accessControl&&(o!=null&&o.sub)){const h=t.accessControl.controlPlaneTenantId,_=(await P.fetchAll(R=>a.env.data.userOrganizations.listUserOrganizations(h,o.sub,R),"organizations")).map(R=>R.name);if(_.length===0)return i?a.json({tenants:[],start:0,limit:s??50,length:0}):a.json({tenants:[]});const T=_.length,M=l??0,b=s??50,y=M*b,A=_.slice(y,y+b);if(A.length===0)return i?a.json({tenants:[],start:y,limit:b,length:T}):a.json({tenants:[]});const O=A.map(R=>`id:${R}`).join(" OR "),j=p?`(${O}) AND (${p})`:O,q=await a.env.data.tenants.list({q:j,per_page:b,include_totals:!1});return i?a.json({tenants:q.tenants,start:y,limit:b,length:T}):a.json({tenants:q.tenants})}const d=await a.env.data.tenants.list({page:l,per_page:s,include_totals:i,q:p});return i?a.json({tenants:d.tenants,start:((w=d.totals)==null?void 0:w.start)??0,limit:((g=d.totals)==null?void 0:g.limit)??s,length:d.tenants.length}):a.json({tenants:d.tenants})}),n.openapi(I.createRoute({tags:["tenants"],method:"post",path:"/",request:{body:{content:{"application/json":{schema:D.tenantInsertSchema}}}},security:[{Bearer:[]}],responses:{201:{content:{"application/json":{schema:D.tenantSchema}},description:"Tenant created"},400:{description:"Validation error"},409:{description:"Tenant with this ID already exists"}}}),async a=>{var p,o;const r=a.var.user;if(!(r!=null&&r.sub))throw new S(401,{message:"Authentication required to create tenants"});let l=a.req.valid("json");const s={adapters:a.env.data,ctx:a};(p=e.tenants)!=null&&p.beforeCreate&&(l=await e.tenants.beforeCreate(s,l));const i=await a.env.data.tenants.create(l);return(o=e.tenants)!=null&&o.afterCreate&&await e.tenants.afterCreate(s,i),a.json(i,201)}),n.openapi(I.createRoute({tags:["tenants"],method:"delete",path:"/{id}",request:{params:I.z.object({id:I.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 a=>{var i,p;const{id:r}=a.req.valid("param");if(t.accessControl){const o=a.var.user,c=t.accessControl.controlPlaneTenantId;if(!(o!=null&&o.sub))throw new S(401,{message:"Authentication required"});if(r===c)throw new S(403,{message:"Cannot delete the control plane"});if(!(await P.fetchAll(m=>a.env.data.userOrganizations.listUserOrganizations(c,o.sub,m),"organizations")).some(m=>m.name===r))throw new S(403,{message:"Access denied to this tenant"})}if(!await a.env.data.tenants.get(r))throw new S(404,{message:"Tenant not found"});const s={adapters:a.env.data,ctx:a};return(i=e.tenants)!=null&&i.beforeDelete&&await e.tenants.beforeDelete(s,r),await a.env.data.tenants.remove(r),(p=e.tenants)!=null&&p.afterDelete&&await e.tenants.afterDelete(s,r),a.body(null,204)}),n}function _e(t){const e=[{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:a}of e){const r=t.match(n);if(r&&r[1])return{type:a,id:r[1]}}return null}async function ye(t,e,n){try{switch(n.type){case"resource_server":{const a=await t.resourceServers.get(e,n.id);return(a==null?void 0:a.is_system)===!0}case"role":{const a=await t.roles.get(e,n.id);return(a==null?void 0:a.is_system)===!0}case"connection":{const a=await t.connections.get(e,n.id);return(a==null?void 0:a.is_system)===!0}default:return!1}}catch{return!1}}function be(t){return{resource_server:"resource server",role:"role",connection:"connection"}[t]}function oe(){return async(t,e)=>{if(!["PATCH","PUT","DELETE"].includes(t.req.method))return e();const n=_e(t.req.path);if(!n)return e();const a=t.var.tenant_id||t.req.header("x-tenant-id")||t.req.header("tenant-id");if(!a)return e();if(await ye(t.env.data,a,n))throw new S(403,{message:`This ${be(n.type)} is a system resource and cannot be modified. Make changes in the control plane instead.`});return e()}}function V(t,e){const{controlPlaneTenantId:n,controlPlaneClientId:a}=e;return{...t,legacyClients:{...t.legacyClients,get:async r=>{var u;const l=await t.legacyClients.get(r);if(!l)return null;const s=a?await t.legacyClients.get(a):void 0,i=await t.connections.list(l.tenant.id),p=n?await t.connections.list(n):{connections:[]},o=i.connections.map(d=>{var w;const m=(w=p.connections)==null?void 0:w.find(g=>g.name===d.name);if(!(m!=null&&m.options))return d;const f=D.connectionSchema.parse({...m||{},...d});return f.options=D.connectionOptionsSchema.parse({...m.options||{},...d.options}),f}).filter(d=>d),c={...(s==null?void 0:s.tenant)||{},...l.tenant};return!l.tenant.audience&&((u=s==null?void 0:s.tenant)!=null&&u.audience)&&(c.audience=s.tenant.audience),{...l,web_origins:[...(s==null?void 0:s.web_origins)||[],...l.web_origins||[]],allowed_logout_urls:[...(s==null?void 0:s.allowed_logout_urls)||[],...l.allowed_logout_urls||[]],callbacks:[...(s==null?void 0:s.callbacks)||[],...l.callbacks||[]],connections:o,tenant:c}}},connections:{...t.connections,get:async(r,l)=>{const s=await t.connections.get(r,l);if(!s||!n)return s;const i=await t.connections.get(n,l);if(!i)return s;const p=D.connectionSchema.parse({...i,...s});return p.options=D.connectionOptionsSchema.parse({...i.options||{},...s.options}),p},list:async(r,l)=>{const s=await t.connections.list(r,l);if(!n||r===n)return s;const i=await t.connections.list(n),p=s.connections.map(o=>{var d;const c=(d=i.connections)==null?void 0:d.find(m=>m.name===o.name);if(!(c!=null&&c.options))return o;const u=D.connectionSchema.parse({...c,...o});return u.options=D.connectionOptionsSchema.parse({...c.options||{},...o.options}),u});return{...s,connections:p}}}}}function ie(t,e){return V(t,e)}const Ae=V,Te=ie;function ce(t){return async(e,n)=>{if(!t.accessControl)return n();const a=e.var.tenant_id,r=e.var.organization_id;if(!a)throw new S(400,{message:"Tenant ID not found in request"});if(!ne(r,a,t.accessControl.controlPlaneTenantId))throw new S(403,{message:`Access denied to tenant ${a}`});return n()}}function le(t){return async(e,n)=>{if(!t.subdomainRouting)return n();const{baseDomain:a,reservedSubdomains:r=[],resolveSubdomain:l}=t.subdomainRouting,s=e.req.header("host")||"";let i=null;if(s.endsWith(a)){const o=s.slice(0,-(a.length+1));o&&!o.includes(".")&&(i=o)}if(i&&r.includes(i)&&(i=null),!i)return t.accessControl&&e.set("tenant_id",t.accessControl.controlPlaneTenantId),n();let p=null;if(l)p=await l(i);else if(t.subdomainRouting.useOrganizations!==!1&&t.accessControl)try{const o=await e.env.data.organizations.get(t.accessControl.controlPlaneTenantId,i);o&&(p=o.id)}catch{}if(!p)throw new S(404,{message:`Tenant not found for subdomain: ${i}`});return e.set("tenant_id",p),n()}}function de(t){return async(e,n)=>{if(!t.databaseIsolation)return n();const a=e.var.tenant_id;if(!a)throw new S(400,{message:"Tenant ID not found in request"});try{const r=await t.databaseIsolation.getAdapters(a);e.env.data=r}catch(r){throw console.error(`Failed to resolve database for tenant ${a}:`,r),new S(500,{message:"Failed to resolve tenant database"})}return n()}}function W(t){const e=le(t),n=ce(t),a=de(t);return async(r,l)=>(await e(r,async()=>{}),await n(r,async()=>{}),await a(r,async()=>{}),l())}function Ce(t){const e=F(t);return{name:"multi-tenancy",middleware:W(t),hooks:e,routes:[{path:"/management",handler:N(t,e)}],onRegister:async()=>{console.log("Multi-tenancy plugin registered"),t.accessControl&&console.log(` - Access control enabled (control plane: ${t.accessControl.controlPlaneTenantId})`),t.subdomainRouting&&console.log(` - Subdomain routing enabled (base domain: ${t.subdomainRouting.baseDomain})`),t.databaseIsolation&&console.log(" - Database isolation enabled")}}}function F(t){const e=t.accessControl?te(t.accessControl):{},n=t.databaseIsolation?re(t.databaseIsolation):{},a=ae(t);return{...e,...n,tenants:a}}function ue(t){const e=new ee.Hono,n=F(t);return e.route("/tenants",N(t,n)),e}function Se(t){return{hooks:F(t),middleware:W(t),app:ue(t),config:t}}function Ie(t){var T,M,b,y,A,O,j,q,R,Q,J,X,Y,Z,k;const{controlPlaneTenantId:e="control_plane",sync:n,multiTenancy:a,entityHooks:r,...l}=t,s={...a,accessControl:{controlPlaneTenantId:e,requireOrganizationMatch:!1,defaultPermissions:["tenant:admin"],...a==null?void 0:a.accessControl}},i=F(s),p=((T=a==null?void 0:a.databaseIsolation)==null?void 0:T.getAdapters)??(async()=>t.dataAdapter),{entityHooks:o,tenantHooks:c}=se({controlPlaneTenantId:e,getChildTenantIds:async()=>(await P.fetchAll(C=>t.dataAdapter.tenants.list(C),"tenants",{cursorField:"id",pageSize:100})).filter(C=>C.id!==e).map(C=>C.id),getAdapters:p,getControlPlaneAdapters:async()=>p(e),sync:n});function u(z,C){if(!(!z&&!C))return z?C?async(...me)=>{const $=[];for(const U of[z,C])try{await U(...me)}catch(B){$.push(B instanceof Error?B:new Error(String(B)))}if($.length===1)throw $[0];if($.length>1)throw new AggregateError($,$.map(U=>U.message).join("; "))}:z:C}const d={...r,resourceServers:o!=null&&o.resourceServers?{...r==null?void 0:r.resourceServers,afterCreate:u((M=r==null?void 0:r.resourceServers)==null?void 0:M.afterCreate,o.resourceServers.afterCreate),afterUpdate:u((b=r==null?void 0:r.resourceServers)==null?void 0:b.afterUpdate,o.resourceServers.afterUpdate),beforeDelete:u((y=r==null?void 0:r.resourceServers)==null?void 0:y.beforeDelete,o.resourceServers.beforeDelete),afterDelete:u((A=r==null?void 0:r.resourceServers)==null?void 0:A.afterDelete,o.resourceServers.afterDelete)}:r==null?void 0:r.resourceServers,roles:o!=null&&o.roles?{...r==null?void 0:r.roles,afterCreate:u((O=r==null?void 0:r.roles)==null?void 0:O.afterCreate,o.roles.afterCreate),afterUpdate:u((j=r==null?void 0:r.roles)==null?void 0:j.afterUpdate,o.roles.afterUpdate),beforeDelete:u((q=r==null?void 0:r.roles)==null?void 0:q.beforeDelete,o.roles.beforeDelete),afterDelete:u((R=r==null?void 0:r.roles)==null?void 0:R.afterDelete,o.roles.afterDelete)}:r==null?void 0:r.roles,connections:o!=null&&o.connections?{...r==null?void 0:r.connections,afterCreate:u((Q=r==null?void 0:r.connections)==null?void 0:Q.afterCreate,o.connections.afterCreate),afterUpdate:u((J=r==null?void 0:r.connections)==null?void 0:J.afterUpdate,o.connections.afterUpdate),beforeDelete:u((X=r==null?void 0:r.connections)==null?void 0:X.beforeDelete,o.connections.beforeDelete),afterDelete:u((Y=r==null?void 0:r.connections)==null?void 0:Y.afterDelete,o.connections.afterDelete)}:r==null?void 0:r.connections,tenants:c?{...r==null?void 0:r.tenants,afterCreate:u((Z=r==null?void 0:r.tenants)==null?void 0:Z.afterCreate,c.afterCreate)}:r==null?void 0:r.tenants},m={...i,tenants:c?{...i.tenants,afterCreate:u((k=i.tenants)==null?void 0:k.afterCreate,c.afterCreate)}:i.tenants},f=N(s,m),w=P.init({...l,entityHooks:d,managementApiExtensions:[...l.managementApiExtensions||[],{path:"/tenants",router:f}]}),{app:g,managementApp:h,...v}=w,_=new ee.Hono;return _.onError((z,C)=>z instanceof S?z.getResponse():(console.error(z),C.json({message:"Internal Server Error"},500))),_.use("/api/v2/*",oe()),_.route("/",g),{app:_,managementApp:h,...v,multiTenancyConfig:s,multiTenancyHooks:i}}exports.createAccessControlHooks=te;exports.createAccessControlMiddleware=ce;exports.createDatabaseHooks=re;exports.createDatabaseMiddleware=de;exports.createMultiTenancy=ue;exports.createMultiTenancyHooks=F;exports.createMultiTenancyMiddleware=W;exports.createMultiTenancyPlugin=Ce;exports.createProtectSyncedMiddleware=oe;exports.createProvisioningHooks=ae;exports.createRuntimeFallbackAdapter=V;exports.createSettingsInheritanceAdapter=Ae;exports.createSubdomainMiddleware=le;exports.createSyncHooks=se;exports.createTenantsOpenAPIRouter=N;exports.init=Ie;exports.setupMultiTenancy=Se;exports.validateTenantAccess=ne;exports.withRuntimeFallback=ie;exports.withSettingsInheritance=Te;Object.keys(P).forEach(t=>{t!=="default"&&!Object.prototype.hasOwnProperty.call(exports,t)&&Object.defineProperty(exports,t,{enumerable:!0,get:()=>P[t]})});
|