@getstrata/core 0.5.56 → 0.5.58

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. package/README.md +1 -1
  2. package/dist/{domain/abilities.d.ts → core/auth/abilityCatalog.d.ts} +9 -1
  3. package/dist/core/auth/accessControl.d.ts +1 -1
  4. package/dist/core/auth/membershipContext.d.ts +6 -4
  5. package/dist/core/auth/membershipService.d.ts +5 -6
  6. package/dist/core/contracts/authUserDirectory.d.ts +11 -0
  7. package/dist/core/contracts/membership.d.ts +20 -0
  8. package/dist/core/http/clientIp.d.ts +3 -0
  9. package/dist/core/jobs/dispatchWebhookJob.d.ts +2 -0
  10. package/dist/core/tenant/tenancyConfig.d.ts +5 -0
  11. package/dist/core/tenant/tenantMiddleware.d.ts +1 -1
  12. package/dist/entries/auth/membershipMiddleware.js +21 -161
  13. package/dist/entries/auth/membershipScope.js +20 -160
  14. package/dist/entries/auth/membershipService.js +21 -161
  15. package/dist/entries/auth/scimAuthMiddleware.js +22 -4
  16. package/dist/entries/auth/sessionGuard.js +12 -258
  17. package/dist/entries/http/clientIp.js +19 -0
  18. package/dist/entries/http/csrfMiddleware.js +2 -1
  19. package/dist/entries/http/csrfToken.js +2 -1
  20. package/dist/entries/http/loginThrottleMiddleware.js +18 -1
  21. package/dist/entries/http/memoryThrottleMiddleware.js +16 -1
  22. package/dist/entries/http/response.js +28 -297
  23. package/dist/entries/http/scimThrottleMiddleware.js +40 -1
  24. package/dist/entries/http/throttleMiddleware.js +18 -1
  25. package/dist/entries/http/webErrorResponse.js +28 -297
  26. package/dist/entries/jobs/dispatchWebhookJob.js +111 -5
  27. package/dist/entries/logging/requestLoggingMiddleware.js +16 -1
  28. package/dist/entries/security/scimTenantTokens.js +1 -4
  29. package/dist/entries/tenant/tenancyConfig.js +12 -0
  30. package/dist/entries/tenant/tenantDatabaseScope.js +11 -0
  31. package/dist/entries/view.js +26 -295
  32. package/dist/framework/public-api.d.ts +4 -1
  33. package/dist/index.js +2186 -2243
  34. package/package.json +12 -2
  35. package/dist/config/database.d.ts +0 -10
  36. package/dist/db/connection/createConnection.d.ts +0 -6
  37. package/dist/db/connection/index.d.ts +0 -11
  38. package/dist/domain/auth.d.ts +0 -4
  39. package/dist/domain/scim.d.ts +0 -9
  40. package/dist/modules/organization/memberRepository.d.ts +0 -14
  41. package/dist/modules/organization/memberTypes.d.ts +0 -9
  42. package/dist/modules/user/apiTokenRepository.d.ts +0 -8
  43. package/dist/modules/user/apiTokenTable.d.ts +0 -3
  44. package/dist/modules/user/authService.d.ts +0 -23
  45. package/dist/modules/user/notificationRepository.d.ts +0 -6
  46. package/dist/modules/user/notificationService.d.ts +0 -25
  47. package/dist/modules/user/notificationTable.d.ts +0 -3
  48. package/dist/modules/user/notificationTypes.d.ts +0 -12
  49. package/dist/modules/user/oauthIdentityRepository.d.ts +0 -9
  50. package/dist/modules/user/provider.d.ts +0 -11
  51. package/dist/modules/user/repository.d.ts +0 -13
  52. package/dist/modules/user/table.d.ts +0 -3
  53. package/dist/modules/user/tokenService.d.ts +0 -29
  54. package/dist/modules/user/types.d.ts +0 -46
package/README.md CHANGED
@@ -82,7 +82,7 @@ import type { Migration } from "@getstrata/core/database/migrations/types";
82
82
  Package name: **`@getstrata/core`** (npm org [`@getstrata`](https://www.npmjs.com/org/getstrata)).
83
83
 
84
84
  1. Add `NPM_TOKEN` to GitHub repository secrets.
85
- 2. Tag a release: `git tag v0.5.13 && git push origin v0.5.13`
85
+ 2. Tag a release: `git tag v0.5.58 && git push origin v0.5.58`
86
86
  3. [Release workflow](../../.github/workflows/release.yml) builds and runs `npm publish --access public`.
87
87
 
88
88
  Previously published as `@eyk-workhub/framework@0.1.0`, deprecated in favor of this package.
@@ -1,5 +1,13 @@
1
1
  declare const MEMBER_ABILITIES: readonly ["organizations:read", "projects:read", "projects:create", "tasks:read", "tasks:create", "comments:read", "comments:create", "attachments:read", "attachments:create", "auth:tokens:read", "auth:tokens:write"];
2
2
  declare const ADMIN_ABILITIES: readonly ["organizations:read", "projects:read", "projects:create", "tasks:read", "tasks:create", "comments:read", "comments:create", "attachments:read", "attachments:create", "auth:tokens:read", "auth:tokens:write", "organizations:create", "organizations:update", "organizations:delete", "projects:update", "projects:delete", "tasks:update", "tasks:delete", "comments:update", "comments:delete", "attachments:delete", "webhooks:read", "webhooks:write", "audit:read"];
3
3
  declare const PLATFORM_ADMIN_ABILITIES: readonly ["*"];
4
+ interface AbilityCatalog {
5
+ member: readonly string[];
6
+ admin: readonly string[];
7
+ resolveForRole(role: string | null | undefined): string[];
8
+ }
4
9
  declare function resolveAbilitiesForRole(role: string | null | undefined): string[];
5
- export { ADMIN_ABILITIES, MEMBER_ABILITIES, PLATFORM_ADMIN_ABILITIES, resolveAbilitiesForRole };
10
+ declare function configureAbilityCatalog(next: AbilityCatalog): void;
11
+ declare function abilityCatalog(): AbilityCatalog;
12
+ export type { AbilityCatalog };
13
+ export { ADMIN_ABILITIES, abilityCatalog, configureAbilityCatalog, MEMBER_ABILITIES, PLATFORM_ADMIN_ABILITIES, resolveAbilitiesForRole, };
@@ -1,4 +1,4 @@
1
- import type { OrganizationMemberRole } from "../../modules/organization/memberTypes";
1
+ import type { OrganizationMemberRole } from "../contracts/membership";
2
2
  import { type AuthUser } from "./authContext";
3
3
  declare const ROLE_RANK: Record<OrganizationMemberRole, number>;
4
4
  declare function isGlobalAdmin(user: AuthUser | null): boolean;
@@ -1,15 +1,17 @@
1
- import OrganizationMemberRepository from "../../modules/organization/memberRepository";
2
- import type { OrganizationMemberRole } from "../../modules/organization/memberTypes";
1
+ import type { MembershipLookup, OrganizationMemberRole } from "../contracts/membership";
3
2
  type MembershipContext = {
4
3
  organizationIds: number[];
5
4
  rolesByOrganizationId: Map<number, OrganizationMemberRole>;
6
5
  };
7
6
  declare const membershipContext: import("node:async_hooks").AsyncLocalStorage<MembershipContext>;
8
- declare const membershipRepository: OrganizationMemberRepository;
7
+ declare let membershipRepository: MembershipLookup;
8
+ declare function configureMembershipLookup(lookup: MembershipLookup): void;
9
+ declare function resolveMembershipLookup(): MembershipLookup;
10
+ declare function resetMembershipLookupForTests(): void;
9
11
  declare function runWithMembershipContext<T>(callback: () => T | Promise<T>): Promise<T | Promise<T>>;
10
12
  declare function currentOrgRole(organizationId: number): OrganizationMemberRole | null;
11
13
  declare function hasOrgMembership(organizationId: number): boolean;
12
14
  declare function currentOrganizationIds(): number[];
13
15
  declare function hasMinimumOrgRole(organizationId: number, minimum: OrganizationMemberRole): boolean;
14
16
  export type { MembershipContext };
15
- export { currentOrganizationIds, currentOrgRole, hasMinimumOrgRole, hasOrgMembership, membershipContext, membershipRepository, runWithMembershipContext, };
17
+ export { configureMembershipLookup, currentOrganizationIds, currentOrgRole, hasMinimumOrgRole, hasOrgMembership, membershipContext, membershipRepository, resetMembershipLookupForTests, resolveMembershipLookup, runWithMembershipContext, };
@@ -1,7 +1,6 @@
1
- import type { OrganizationMemberRole } from "../../modules/organization/memberTypes";
1
+ import type { MembershipLookup, OrganizationMemberRole } from "../contracts/membership";
2
2
  import { type AuthUser } from "./authContext";
3
- import { membershipRepository as defaultMembershipRepository } from "./membershipContext";
4
- type MembershipRepositoryLike = Pick<typeof defaultMembershipRepository, "listForUser" | "findMembership" | "listForOrganization" | "addMember" | "removeMember">;
3
+ type MembershipRepositoryLike = MembershipLookup;
5
4
  declare class MembershipService {
6
5
  private readonly members;
7
6
  constructor(members?: MembershipRepositoryLike);
@@ -10,13 +9,13 @@ declare class MembershipService {
10
9
  requireOrgAccess(organizationId: number, minimumRole?: OrganizationMemberRole, user?: AuthUser | null): Promise<OrganizationMemberRole>;
11
10
  filterAccessibleOrganizationIds(organizationIds: number[], user?: AuthUser | null): Promise<number[]>;
12
11
  addOwnerOnOrganizationCreate(organizationId: number, userId: number): Promise<void>;
13
- listMembersForOrganization(organizationId: number): Promise<import("../../modules/organization/memberTypes").OrganizationMemberRecord[]>;
12
+ listMembersForOrganization(organizationId: number): Promise<import("../contracts/membership").MembershipRecord[]>;
14
13
  addMember(input: {
15
14
  organizationId: number;
16
15
  userId: number;
17
16
  role?: OrganizationMemberRole;
18
- }): Promise<import("../../modules/organization/memberTypes").OrganizationMemberRecord>;
19
- removeMember(organizationId: number, userId: number): Promise<boolean>;
17
+ }): Promise<import("../contracts/membership").MembershipRecord>;
18
+ removeMember(organizationId: number, userId: number): Promise<unknown>;
20
19
  }
21
20
  export type { MembershipRepositoryLike };
22
21
  export default MembershipService;
@@ -0,0 +1,11 @@
1
+ import type { AuthUser } from "../auth/authContext";
2
+ interface AuthUserRecord {
3
+ id: number;
4
+ email?: string | null;
5
+ role: string;
6
+ }
7
+ interface AuthUserDirectory {
8
+ resolveUserFromToken(token: string): Promise<AuthUser | null>;
9
+ findByIdOrThrow(id: number): Promise<AuthUserRecord>;
10
+ }
11
+ export type { AuthUserDirectory, AuthUserRecord };
@@ -0,0 +1,20 @@
1
+ type OrganizationMemberRole = "owner" | "admin" | "member";
2
+ interface MembershipRecord {
3
+ id: number;
4
+ organization_id: number;
5
+ user_id: number;
6
+ role: OrganizationMemberRole;
7
+ created_at: Date;
8
+ }
9
+ interface MembershipLookup {
10
+ listForUser(userId: number): Promise<MembershipRecord[]>;
11
+ findMembership(userId: number, organizationId: number): Promise<MembershipRecord | null>;
12
+ listForOrganization(organizationId: number): Promise<MembershipRecord[]>;
13
+ addMember(input: {
14
+ organizationId: number;
15
+ userId: number;
16
+ role?: OrganizationMemberRole;
17
+ }): Promise<MembershipRecord>;
18
+ removeMember(organizationId: number, userId: number): Promise<unknown>;
19
+ }
20
+ export type { MembershipLookup, MembershipRecord, OrganizationMemberRole };
@@ -0,0 +1,3 @@
1
+ declare function trustForwardedFor(env?: Record<string, string | undefined>): boolean;
2
+ declare function readClientIp(request: Request, env?: Record<string, string | undefined>): string | undefined;
3
+ export { readClientIp, trustForwardedFor };
@@ -1,6 +1,7 @@
1
1
  import { Job } from "../queue";
2
2
  interface DispatchWebhookPayload {
3
3
  webhookId: number;
4
+ tenantId: number;
4
5
  event: string;
5
6
  payload: Record<string, unknown>;
6
7
  }
@@ -8,6 +9,7 @@ declare class DispatchWebhookJob extends Job<DispatchWebhookPayload> {
8
9
  readonly maxAttempts = 3;
9
10
  readonly backoffMs = 2000;
10
11
  handle(payload: DispatchWebhookPayload): Promise<void>;
12
+ private deliver;
11
13
  }
12
14
  export { DispatchWebhookJob };
13
15
  export default DispatchWebhookJob;
@@ -0,0 +1,5 @@
1
+ type TenancyDriver = "rls" | "none";
2
+ declare function readTenancyDriver(env?: Record<string, string | undefined>): TenancyDriver;
3
+ declare function isTenancyEnabled(env?: Record<string, string | undefined>): boolean;
4
+ export type { TenancyDriver };
5
+ export { isTenancyEnabled, readTenancyDriver };
@@ -1,4 +1,4 @@
1
- import type { TenantContext } from "./tenantContext";
1
+ import { type TenantContext } from "./tenantContext";
2
2
  declare const DEFAULT_TENANT: TenantContext;
3
3
  declare function resolveUserTenantId(userId: number): Promise<number>;
4
4
  declare function auditChecksum(payload: Record<string, unknown>): string;
@@ -1,17 +1,4 @@
1
1
  // @bun
2
- // ../../src/config/database.ts
3
- function readInteger(name, fallback) {
4
- const parsed = Number.parseInt(process.env[name] ?? String(fallback), 10);
5
- return Number.isInteger(parsed) && parsed >= 0 ? parsed : fallback;
6
- }
7
- var databaseConfig = {
8
- url: process.env.DATABASE_URL ?? "",
9
- poolMax: readInteger("DB_POOL_MAX", 10),
10
- idleTimeoutSeconds: readInteger("DB_POOL_IDLE_TIMEOUT", 30),
11
- maxLifetimeSeconds: readInteger("DB_POOL_MAX_LIFETIME", 3600),
12
- connectionTimeoutSeconds: readInteger("DB_CONNECTION_TIMEOUT", 10)
13
- };
14
-
15
2
  // ../../src/core/runtime/asyncContextStore.ts
16
3
  import { AsyncLocalStorage } from "async_hooks";
17
4
  function createAsyncContextStore(key) {
@@ -26,153 +13,6 @@ function createAsyncContextStore(key) {
26
13
  return store;
27
14
  }
28
15
 
29
- // ../../src/core/database/connectionContext.ts
30
- var activeConnection = createAsyncContextStore("@getstrata/databaseConnectionContext");
31
- function runWithDatabaseConnection(connection, callback) {
32
- return activeConnection.run(connection, callback);
33
- }
34
- function getActiveDatabaseConnection(fallback) {
35
- return activeConnection.getStore() ?? fallback;
36
- }
37
- function hasActiveDatabaseConnection() {
38
- return activeConnection.getStore() !== undefined;
39
- }
40
-
41
- // ../../src/core/database/queryProxy.ts
42
- var POOL_CONNECTION_METHODS = new Set(["begin", "close", "connect"]);
43
- function createDatabaseQueryProxy(pool) {
44
- function resolveDatabase() {
45
- return getActiveDatabaseConnection(pool);
46
- }
47
- function resolveDatabaseForProperty(property) {
48
- if (typeof property === "string" && POOL_CONNECTION_METHODS.has(property)) {
49
- return pool;
50
- }
51
- return resolveDatabase();
52
- }
53
- return new Proxy(function database() {}, {
54
- apply(_target, _thisArg, args) {
55
- return resolveDatabase()(...args);
56
- },
57
- get(_target, property) {
58
- const connection = resolveDatabaseForProperty(property);
59
- const value = connection[property];
60
- return typeof value === "function" ? value.bind(connection) : value;
61
- }
62
- });
63
- }
64
-
65
- // ../../src/core/database/defaultConnection.ts
66
- var defaultPool = {
67
- connection: null
68
- };
69
- var defaultQuery = {
70
- connection: null
71
- };
72
- function registerDefaultDatabasePool(connection) {
73
- defaultPool.connection = connection;
74
- defaultQuery.connection = createDatabaseQueryProxy(connection);
75
- }
76
- function getDefaultDatabaseQuery() {
77
- if (!defaultQuery.connection) {
78
- throw new Error("Default database query handle is not registered. Call registerDefaultDatabasePool() during app bootstrap.");
79
- }
80
- return defaultQuery.connection;
81
- }
82
-
83
- // ../../src/db/connection/createConnection.ts
84
- var {SQL } = globalThis.Bun;
85
- function createDatabaseConnection(config) {
86
- if (!config.url) {
87
- throw new Error("DATABASE_URL is not configured. Set DATABASE_URL before starting the app or running integration tests.");
88
- }
89
- return new SQL({
90
- url: config.url,
91
- max: config.poolMax,
92
- idleTimeout: config.idleTimeoutSeconds,
93
- maxLifetime: config.maxLifetimeSeconds,
94
- connectionTimeout: config.connectionTimeoutSeconds
95
- });
96
- }
97
-
98
- // ../../src/db/connection/index.ts
99
- var connectionHolder = {
100
- connection: null
101
- };
102
- function getDatabase() {
103
- if (!connectionHolder.connection) {
104
- connectionHolder.connection = createDatabaseConnection(databaseConfig);
105
- registerDefaultDatabasePool(connectionHolder.connection);
106
- }
107
- return connectionHolder.connection;
108
- }
109
- function getDb() {
110
- getDatabase();
111
- return getDefaultDatabaseQuery();
112
- }
113
- var db = new Proxy(function database() {}, {
114
- apply(_target, _thisArg, args) {
115
- return getDb()(...args);
116
- },
117
- get(_target, property) {
118
- const connection = getDb();
119
- const value = connection[property];
120
- return typeof value === "function" ? value.bind(connection) : value;
121
- }
122
- });
123
- var connection_default = db;
124
-
125
- // ../../src/modules/organization/memberRepository.ts
126
- class OrganizationMemberRepository {
127
- constructor() {}
128
- async findMembership(userId, organizationId) {
129
- const rows = await connection_default`
130
- SELECT id, organization_id, user_id, role, created_at
131
- FROM organization_member
132
- WHERE user_id = ${userId} AND organization_id = ${organizationId}
133
- LIMIT 1
134
- `;
135
- return rows[0] ?? null;
136
- }
137
- async listForUser(userId) {
138
- return await connection_default`
139
- SELECT id, organization_id, user_id, role, created_at
140
- FROM organization_member
141
- WHERE user_id = ${userId}
142
- ORDER BY organization_id
143
- `;
144
- }
145
- async listForOrganization(organizationId) {
146
- return await connection_default`
147
- SELECT id, organization_id, user_id, role, created_at
148
- FROM organization_member
149
- WHERE organization_id = ${organizationId}
150
- ORDER BY id
151
- `;
152
- }
153
- async addMember(input) {
154
- const rows = await connection_default`
155
- INSERT INTO organization_member (organization_id, user_id, role)
156
- VALUES (${input.organizationId}, ${input.userId}, ${input.role ?? "member"})
157
- RETURNING id, organization_id, user_id, role, created_at
158
- `;
159
- const row = rows[0];
160
- if (!row) {
161
- throw new Error("Organization member insert did not return a row.");
162
- }
163
- return row;
164
- }
165
- async removeMember(organizationId, userId) {
166
- const rows = await connection_default`
167
- DELETE FROM organization_member
168
- WHERE organization_id = ${organizationId} AND user_id = ${userId}
169
- RETURNING id
170
- `;
171
- return rows.length > 0;
172
- }
173
- }
174
- var memberRepository_default = OrganizationMemberRepository;
175
-
176
16
  // ../../src/core/auth/accessControl.ts
177
17
  import { ForbiddenError } from "@getstrata/core/errors/http";
178
18
 
@@ -214,7 +54,27 @@ function resolveUserId(user) {
214
54
 
215
55
  // ../../src/core/auth/membershipContext.ts
216
56
  var membershipContext = createAsyncContextStore("@getstrata/membershipContext");
217
- var membershipRepository = new memberRepository_default;
57
+ var uninitializedMembershipLookup = {
58
+ async listForUser() {
59
+ return [];
60
+ },
61
+ async findMembership() {
62
+ return null;
63
+ },
64
+ async listForOrganization() {
65
+ return [];
66
+ },
67
+ async addMember() {
68
+ throw new Error("configureMembershipLookup() must be called before mutating memberships.");
69
+ },
70
+ async removeMember() {
71
+ throw new Error("configureMembershipLookup() must be called before mutating memberships.");
72
+ }
73
+ };
74
+ var membershipRepository = uninitializedMembershipLookup;
75
+ function resolveMembershipLookup() {
76
+ return membershipRepository;
77
+ }
218
78
  async function runWithMembershipContext(callback) {
219
79
  const user = currentAuthUser();
220
80
  if (!user || isGlobalAdmin(user)) {
@@ -56,169 +56,29 @@ function resolveUserId(user) {
56
56
  return userId;
57
57
  }
58
58
 
59
- // ../../src/config/database.ts
60
- function readInteger(name, fallback) {
61
- const parsed = Number.parseInt(process.env[name] ?? String(fallback), 10);
62
- return Number.isInteger(parsed) && parsed >= 0 ? parsed : fallback;
63
- }
64
- var databaseConfig = {
65
- url: process.env.DATABASE_URL ?? "",
66
- poolMax: readInteger("DB_POOL_MAX", 10),
67
- idleTimeoutSeconds: readInteger("DB_POOL_IDLE_TIMEOUT", 30),
68
- maxLifetimeSeconds: readInteger("DB_POOL_MAX_LIFETIME", 3600),
69
- connectionTimeoutSeconds: readInteger("DB_CONNECTION_TIMEOUT", 10)
70
- };
71
-
72
- // ../../src/core/database/connectionContext.ts
73
- var activeConnection = createAsyncContextStore("@getstrata/databaseConnectionContext");
74
- function runWithDatabaseConnection(connection, callback) {
75
- return activeConnection.run(connection, callback);
76
- }
77
- function getActiveDatabaseConnection(fallback) {
78
- return activeConnection.getStore() ?? fallback;
79
- }
80
- function hasActiveDatabaseConnection() {
81
- return activeConnection.getStore() !== undefined;
82
- }
83
-
84
- // ../../src/core/database/queryProxy.ts
85
- var POOL_CONNECTION_METHODS = new Set(["begin", "close", "connect"]);
86
- function createDatabaseQueryProxy(pool) {
87
- function resolveDatabase() {
88
- return getActiveDatabaseConnection(pool);
89
- }
90
- function resolveDatabaseForProperty(property) {
91
- if (typeof property === "string" && POOL_CONNECTION_METHODS.has(property)) {
92
- return pool;
93
- }
94
- return resolveDatabase();
95
- }
96
- return new Proxy(function database() {}, {
97
- apply(_target, _thisArg, args) {
98
- return resolveDatabase()(...args);
99
- },
100
- get(_target, property) {
101
- const connection = resolveDatabaseForProperty(property);
102
- const value = connection[property];
103
- return typeof value === "function" ? value.bind(connection) : value;
104
- }
105
- });
106
- }
107
-
108
- // ../../src/core/database/defaultConnection.ts
109
- var defaultPool = {
110
- connection: null
111
- };
112
- var defaultQuery = {
113
- connection: null
114
- };
115
- function registerDefaultDatabasePool(connection) {
116
- defaultPool.connection = connection;
117
- defaultQuery.connection = createDatabaseQueryProxy(connection);
118
- }
119
- function getDefaultDatabaseQuery() {
120
- if (!defaultQuery.connection) {
121
- throw new Error("Default database query handle is not registered. Call registerDefaultDatabasePool() during app bootstrap.");
122
- }
123
- return defaultQuery.connection;
124
- }
125
-
126
- // ../../src/db/connection/createConnection.ts
127
- var {SQL } = globalThis.Bun;
128
- function createDatabaseConnection(config) {
129
- if (!config.url) {
130
- throw new Error("DATABASE_URL is not configured. Set DATABASE_URL before starting the app or running integration tests.");
131
- }
132
- return new SQL({
133
- url: config.url,
134
- max: config.poolMax,
135
- idleTimeout: config.idleTimeoutSeconds,
136
- maxLifetime: config.maxLifetimeSeconds,
137
- connectionTimeout: config.connectionTimeoutSeconds
138
- });
139
- }
140
-
141
- // ../../src/db/connection/index.ts
142
- var connectionHolder = {
143
- connection: null
144
- };
145
- function getDatabase() {
146
- if (!connectionHolder.connection) {
147
- connectionHolder.connection = createDatabaseConnection(databaseConfig);
148
- registerDefaultDatabasePool(connectionHolder.connection);
149
- }
150
- return connectionHolder.connection;
151
- }
152
- function getDb() {
153
- getDatabase();
154
- return getDefaultDatabaseQuery();
155
- }
156
- var db = new Proxy(function database() {}, {
157
- apply(_target, _thisArg, args) {
158
- return getDb()(...args);
59
+ // ../../src/core/auth/membershipContext.ts
60
+ var membershipContext = createAsyncContextStore("@getstrata/membershipContext");
61
+ var uninitializedMembershipLookup = {
62
+ async listForUser() {
63
+ return [];
159
64
  },
160
- get(_target, property) {
161
- const connection = getDb();
162
- const value = connection[property];
163
- return typeof value === "function" ? value.bind(connection) : value;
164
- }
165
- });
166
- var connection_default = db;
167
-
168
- // ../../src/modules/organization/memberRepository.ts
169
- class OrganizationMemberRepository {
170
- constructor() {}
171
- async findMembership(userId, organizationId) {
172
- const rows = await connection_default`
173
- SELECT id, organization_id, user_id, role, created_at
174
- FROM organization_member
175
- WHERE user_id = ${userId} AND organization_id = ${organizationId}
176
- LIMIT 1
177
- `;
178
- return rows[0] ?? null;
179
- }
180
- async listForUser(userId) {
181
- return await connection_default`
182
- SELECT id, organization_id, user_id, role, created_at
183
- FROM organization_member
184
- WHERE user_id = ${userId}
185
- ORDER BY organization_id
186
- `;
187
- }
188
- async listForOrganization(organizationId) {
189
- return await connection_default`
190
- SELECT id, organization_id, user_id, role, created_at
191
- FROM organization_member
192
- WHERE organization_id = ${organizationId}
193
- ORDER BY id
194
- `;
195
- }
196
- async addMember(input) {
197
- const rows = await connection_default`
198
- INSERT INTO organization_member (organization_id, user_id, role)
199
- VALUES (${input.organizationId}, ${input.userId}, ${input.role ?? "member"})
200
- RETURNING id, organization_id, user_id, role, created_at
201
- `;
202
- const row = rows[0];
203
- if (!row) {
204
- throw new Error("Organization member insert did not return a row.");
205
- }
206
- return row;
207
- }
208
- async removeMember(organizationId, userId) {
209
- const rows = await connection_default`
210
- DELETE FROM organization_member
211
- WHERE organization_id = ${organizationId} AND user_id = ${userId}
212
- RETURNING id
213
- `;
214
- return rows.length > 0;
65
+ async findMembership() {
66
+ return null;
67
+ },
68
+ async listForOrganization() {
69
+ return [];
70
+ },
71
+ async addMember() {
72
+ throw new Error("configureMembershipLookup() must be called before mutating memberships.");
73
+ },
74
+ async removeMember() {
75
+ throw new Error("configureMembershipLookup() must be called before mutating memberships.");
215
76
  }
77
+ };
78
+ var membershipRepository = uninitializedMembershipLookup;
79
+ function resolveMembershipLookup() {
80
+ return membershipRepository;
216
81
  }
217
- var memberRepository_default = OrganizationMemberRepository;
218
-
219
- // ../../src/core/auth/membershipContext.ts
220
- var membershipContext = createAsyncContextStore("@getstrata/membershipContext");
221
- var membershipRepository = new memberRepository_default;
222
82
  async function runWithMembershipContext(callback) {
223
83
  const user = currentAuthUser();
224
84
  if (!user || isGlobalAdmin(user)) {