Skip to content

Commit 38c7b25

Browse files
committed
Lazy loading of plugin
1 parent 73ad39a commit 38c7b25

2 files changed

Lines changed: 87 additions & 3 deletions

File tree

apps/webapp/app/services/rbac.server.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,6 @@ async function getSessionUserId(request: Request): Promise<string | null> {
77
return id ?? null;
88
}
99

10-
export const rbac = await plugin.create(prisma, { getSessionUserId });
10+
// plugin.create() is synchronous — returns a lazy controller that loads the enterprise plugin
11+
// on first call. Top-level await is not used because CJS output format does not support it.
12+
export const rbac = plugin.create(prisma, { getSessionUserId });

internal-packages/rbac/src/index.ts

Lines changed: 84 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
import type {
2+
Permission,
3+
Role,
4+
RbacResource,
25
RoleBaseAccessController,
36
RoleBasedAccessControlPlugin,
47
} from "@trigger.dev/plugins";
@@ -8,8 +11,16 @@ export type { RoleBaseAccessController };
811

912
type RbacHelpers = { getSessionUserId: (request: Request) => Promise<string | null> };
1013

11-
class RoleBaseAccess {
12-
async create(prisma: PrismaClient, helpers: RbacHelpers): Promise<RoleBaseAccessController> {
14+
// Loads the enterprise plugin lazily; falls back to the OSS implementation if not installed.
15+
// Synchronous create() avoids top-level await (not supported in the webapp's CJS build).
16+
class LazyController implements RoleBaseAccessController {
17+
private readonly _init: Promise<RoleBaseAccessController>;
18+
19+
constructor(prisma: PrismaClient, helpers: RbacHelpers) {
20+
this._init = this.load(prisma, helpers);
21+
}
22+
23+
private async load(prisma: PrismaClient, helpers: RbacHelpers): Promise<RoleBaseAccessController> {
1324
try {
1425
const moduleName = "@triggerdotdev/plugins/rbac";
1526
const module = await import(moduleName);
@@ -19,6 +30,77 @@ class RoleBaseAccess {
1930
return new RoleBaseAccessFallback(prisma).create(helpers);
2031
}
2132
}
33+
34+
private async c(): Promise<RoleBaseAccessController> {
35+
return this._init;
36+
}
37+
38+
async authenticateBearer(...args: Parameters<RoleBaseAccessController["authenticateBearer"]>) {
39+
return (await this.c()).authenticateBearer(...args);
40+
}
41+
42+
async authenticateSession(...args: Parameters<RoleBaseAccessController["authenticateSession"]>) {
43+
return (await this.c()).authenticateSession(...args);
44+
}
45+
46+
async authenticateAuthorizeBearer(...args: Parameters<RoleBaseAccessController["authenticateAuthorizeBearer"]>) {
47+
return (await this.c()).authenticateAuthorizeBearer(...args);
48+
}
49+
50+
async authenticateAuthorizeSession(...args: Parameters<RoleBaseAccessController["authenticateAuthorizeSession"]>) {
51+
return (await this.c()).authenticateAuthorizeSession(...args);
52+
}
53+
54+
async allPermissions(...args: Parameters<RoleBaseAccessController["allPermissions"]>): Promise<Permission[]> {
55+
return (await this.c()).allPermissions(...args);
56+
}
57+
58+
async allRoles(...args: Parameters<RoleBaseAccessController["allRoles"]>): Promise<Role[]> {
59+
return (await this.c()).allRoles(...args);
60+
}
61+
62+
async createRole(...args: Parameters<RoleBaseAccessController["createRole"]>): Promise<Role> {
63+
return (await this.c()).createRole(...args);
64+
}
65+
66+
async updateRole(...args: Parameters<RoleBaseAccessController["updateRole"]>): Promise<Role> {
67+
return (await this.c()).updateRole(...args);
68+
}
69+
70+
async deleteRole(...args: Parameters<RoleBaseAccessController["deleteRole"]>): Promise<void> {
71+
return (await this.c()).deleteRole(...args);
72+
}
73+
74+
async getUserRole(...args: Parameters<RoleBaseAccessController["getUserRole"]>): Promise<Role | null> {
75+
return (await this.c()).getUserRole(...args);
76+
}
77+
78+
async setUserRole(...args: Parameters<RoleBaseAccessController["setUserRole"]>): Promise<void> {
79+
return (await this.c()).setUserRole(...args);
80+
}
81+
82+
async removeUserRole(...args: Parameters<RoleBaseAccessController["removeUserRole"]>): Promise<void> {
83+
return (await this.c()).removeUserRole(...args);
84+
}
85+
86+
async getTokenRole(...args: Parameters<RoleBaseAccessController["getTokenRole"]>): Promise<Role | null> {
87+
return (await this.c()).getTokenRole(...args);
88+
}
89+
90+
async setTokenRole(...args: Parameters<RoleBaseAccessController["setTokenRole"]>): Promise<void> {
91+
return (await this.c()).setTokenRole(...args);
92+
}
93+
94+
async removeTokenRole(...args: Parameters<RoleBaseAccessController["removeTokenRole"]>): Promise<void> {
95+
return (await this.c()).removeTokenRole(...args);
96+
}
97+
}
98+
99+
class RoleBaseAccess {
100+
// Synchronous — returns a lazy controller that loads the enterprise plugin on first call.
101+
create(prisma: PrismaClient, helpers: RbacHelpers): RoleBaseAccessController {
102+
return new LazyController(prisma, helpers);
103+
}
22104
}
23105

24106
const loader = new RoleBaseAccess();

0 commit comments

Comments
 (0)