@aphexcms/postgresql-adapter 0.1.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.
@@ -0,0 +1,161 @@
1
+ import type { drizzle } from 'drizzle-orm/postgres-js';
2
+ import type { DatabaseAdapter, DatabaseProvider, SchemaType } from '@aphexcms/cms-core/server';
3
+ import type { CMSSchema } from './schema.js';
4
+ /**
5
+ * Combined PostgreSQL adapter that implements the full DatabaseAdapter interface
6
+ * Composes document, asset, user profile, schema, and organization adapters
7
+ */
8
+ export declare class PostgreSQLAdapter implements DatabaseAdapter {
9
+ private db;
10
+ private tables;
11
+ private documentAdapter;
12
+ private assetAdapter;
13
+ private userProfileAdapter;
14
+ private schemaAdapter;
15
+ private organizationAdapter;
16
+ readonly rlsEnabled: boolean;
17
+ readonly hierarchyEnabled: boolean;
18
+ constructor(config: {
19
+ db: ReturnType<typeof drizzle>;
20
+ tables: CMSSchema;
21
+ multiTenancy?: {
22
+ enableRLS?: boolean;
23
+ enableHierarchy?: boolean;
24
+ };
25
+ });
26
+ findManyDoc(organizationId: string, filters?: any): Promise<import("@aphexcms/cms-core").Document[]>;
27
+ findByDocId(organizationId: string, id: string, depth?: number): Promise<import("@aphexcms/cms-core").Document | null>;
28
+ createDocument(data: any): Promise<import("@aphexcms/cms-core").Document>;
29
+ updateDocDraft(organizationId: string, id: string, data: any, updatedBy?: string): Promise<import("@aphexcms/cms-core").Document | null>;
30
+ deleteDocById(organizationId: string, id: string): Promise<boolean>;
31
+ publishDoc(organizationId: string, id: string): Promise<import("@aphexcms/cms-core").Document | null>;
32
+ unpublishDoc(organizationId: string, id: string): Promise<import("@aphexcms/cms-core").Document | null>;
33
+ countDocsByType(organizationId: string, type: string): Promise<number>;
34
+ getDocCountsByType(organizationId: string): Promise<Record<string, number>>;
35
+ createAsset(data: any): Promise<import("@aphexcms/cms-core").Asset>;
36
+ findAssetById(organizationId: string, id: string): Promise<import("@aphexcms/cms-core").Asset | null>;
37
+ findAssetByIdGlobal(id: string): Promise<import("@aphexcms/cms-core").Asset | null>;
38
+ findAssets(organizationId: string, filters?: any): Promise<import("@aphexcms/cms-core").Asset[]>;
39
+ updateAsset(organizationId: string, id: string, data: any): Promise<import("@aphexcms/cms-core").Asset | null>;
40
+ deleteAsset(organizationId: string, id: string): Promise<boolean>;
41
+ countAssets(organizationId: string): Promise<number>;
42
+ countAssetsByType(organizationId: string): Promise<Record<string, number>>;
43
+ getTotalAssetsSize(organizationId: string): Promise<number>;
44
+ createUserProfile(data: any): Promise<import("@aphexcms/cms-core").UserProfile>;
45
+ findUserProfileById(userId: string): Promise<import("@aphexcms/cms-core").UserProfile | null>;
46
+ deleteUserProfile(userId: string): Promise<boolean>;
47
+ /**
48
+ * Check if any user profiles exist (for detecting first user)
49
+ */
50
+ hasAnyUserProfiles(): Promise<boolean>;
51
+ registerSchemaType(schemaType: SchemaType): Promise<void>;
52
+ getSchemaType(name: string): Promise<SchemaType | null>;
53
+ listDocumentTypes(): Promise<Array<{
54
+ name: string;
55
+ title: string;
56
+ description?: string;
57
+ }>>;
58
+ listObjectTypes(): Promise<Array<{
59
+ name: string;
60
+ title: string;
61
+ description?: string;
62
+ }>>;
63
+ listSchemas(): Promise<SchemaType[]>;
64
+ deleteSchemaType(name: string): Promise<void>;
65
+ createOrganization(data: any): Promise<import("@aphexcms/cms-core").Organization>;
66
+ findOrganizationById(id: string): Promise<import("@aphexcms/cms-core").Organization | null>;
67
+ findOrganizationBySlug(slug: string): Promise<import("@aphexcms/cms-core").Organization | null>;
68
+ updateOrganization(id: string, data: any): Promise<import("@aphexcms/cms-core").Organization | null>;
69
+ deleteOrganization(id: string): Promise<boolean>;
70
+ addMember(data: any): Promise<import("@aphexcms/cms-core").OrganizationMember>;
71
+ removeMember(organizationId: string, userId: string): Promise<boolean>;
72
+ removeAllMembers(organizationId: string): Promise<boolean>;
73
+ updateMemberRole(organizationId: string, userId: string, role: 'owner' | 'admin' | 'editor' | 'viewer'): Promise<import("@aphexcms/cms-core").OrganizationMember | null>;
74
+ findUserMembership(userId: string, organizationId: string): Promise<import("@aphexcms/cms-core").OrganizationMember | null>;
75
+ findUserOrganizations(userId: string): Promise<import("@aphexcms/cms-core").OrganizationMembership[]>;
76
+ findOrganizationMembers(organizationId: string): Promise<import("@aphexcms/cms-core").OrganizationMember[]>;
77
+ createInvitation(data: any): Promise<import("@aphexcms/cms-core").Invitation>;
78
+ findInvitationByToken(token: string): Promise<import("@aphexcms/cms-core").Invitation | null>;
79
+ findOrganizationInvitations(organizationId: string): Promise<import("@aphexcms/cms-core").Invitation[]>;
80
+ findInvitationsByEmail(email: string): Promise<import("@aphexcms/cms-core").Invitation[]>;
81
+ acceptInvitation(token: string, userId: string): Promise<import("@aphexcms/cms-core").OrganizationMember>;
82
+ deleteInvitation(id: string): Promise<boolean>;
83
+ removeAllInvitations(organizationId: string): Promise<boolean>;
84
+ cleanupExpiredInvitations(): Promise<number>;
85
+ updateUserSession(userId: string, organizationId: string): Promise<void>;
86
+ findUserSession(userId: string): Promise<import("@aphexcms/cms-core").UserSession | null>;
87
+ deleteUserSession(userId: string): Promise<boolean>;
88
+ /**
89
+ * Initialize RLS by enabling or disabling it on content tables based on config
90
+ * Call this after running migrations to set up RLS according to your configuration
91
+ */
92
+ initializeRLS(): Promise<void>;
93
+ /**
94
+ * Execute a function within a transaction with organization context set for RLS
95
+ * This ensures SET LOCAL is properly scoped and won't leak between requests in connection pooling
96
+ *
97
+ * @param organizationId - The organization ID to set as context
98
+ * @param fn - Function to execute within the transaction context
99
+ * @returns The result of the function
100
+ *
101
+ * @example
102
+ * const documents = await adapter.withOrgContext(auth.organizationId, async () => {
103
+ * return adapter.findManyDoc(auth.organizationId, { type: 'post' });
104
+ * });
105
+ */
106
+ withOrgContext<T>(organizationId: string, fn: () => Promise<T>): Promise<T>;
107
+ /**
108
+ * Get all child organizations for a given parent organization
109
+ * Used for parent-child hierarchy access control
110
+ * @param parentOrganizationId - The parent organization ID
111
+ * @returns Array of child organization IDs
112
+ */
113
+ getChildOrganizations(parentOrganizationId: string): Promise<string[]>;
114
+ disconnect(): Promise<void>;
115
+ isHealthy(): Promise<boolean>;
116
+ }
117
+ export { PostgreSQLDocumentAdapter } from './document-adapter.js';
118
+ export { PostgreSQLAssetAdapter } from './asset-adapter.js';
119
+ export { cmsSchema } from './schema.js';
120
+ export type { CMSSchema } from './schema.js';
121
+ export { documents, assets, schemaTypes, documentStatusEnum, schemaTypeEnum } from './schema.js';
122
+ export type { Document, NewDocument, Asset, NewAsset, SchemaType, NewSchemaType } from '@aphexcms/cms-core/server';
123
+ /**
124
+ * PostgreSQL-specific configuration options
125
+ */
126
+ export interface PostgreSQLConfig {
127
+ /** Pre-initialized postgres client (recommended for connection pooling) */
128
+ client?: any;
129
+ /** Connection string (if not providing client) */
130
+ connectionString?: string;
131
+ /** Connection pool options (if using connectionString) */
132
+ options?: {
133
+ max?: number;
134
+ idle_timeout?: number;
135
+ connect_timeout?: number;
136
+ [key: string]: any;
137
+ };
138
+ /** Multi-tenancy configuration */
139
+ multiTenancy?: {
140
+ /** Enable Row-Level Security (RLS) policies (default: true) */
141
+ enableRLS?: boolean;
142
+ /** Enable parent-child organization hierarchy (default: true) */
143
+ enableHierarchy?: boolean;
144
+ };
145
+ }
146
+ /**
147
+ * Create a PostgreSQL database provider with type-safe configuration
148
+ *
149
+ * @example
150
+ * // With pre-initialized client (recommended)
151
+ * const provider = createPostgreSQLProvider({ client: myPostgresClient });
152
+ *
153
+ * @example
154
+ * // With connection string
155
+ * const provider = createPostgreSQLProvider({
156
+ * connectionString: 'postgres://...',
157
+ * options: { max: 10, idle_timeout: 20 }
158
+ * });
159
+ */
160
+ export declare function createPostgreSQLProvider(config: PostgreSQLConfig): DatabaseProvider;
161
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/index.js ADDED
@@ -0,0 +1,450 @@
1
+ import postgres from 'postgres';
2
+ import { drizzle as drizzlePostgres } from 'drizzle-orm/postgres-js';
3
+ import { sql } from 'drizzle-orm';
4
+ import { eq } from 'drizzle-orm';
5
+ import { PostgreSQLDocumentAdapter } from './document-adapter.js';
6
+ import { PostgreSQLAssetAdapter } from './asset-adapter.js';
7
+ import { PostgreSQLUserProfileAdapter } from './user-adapter.js';
8
+ import { PostgreSQLSchemaAdapter } from './schema-adapter.js';
9
+ import { PostgreSQLOrganizationAdapter } from './organization-adapter.js';
10
+ import { cmsSchema } from './schema.js';
11
+ /**
12
+ * Combined PostgreSQL adapter that implements the full DatabaseAdapter interface
13
+ * Composes document, asset, user profile, schema, and organization adapters
14
+ */
15
+ export class PostgreSQLAdapter {
16
+ db;
17
+ tables;
18
+ documentAdapter;
19
+ assetAdapter;
20
+ userProfileAdapter;
21
+ schemaAdapter;
22
+ organizationAdapter;
23
+ rlsEnabled;
24
+ hierarchyEnabled;
25
+ constructor(config) {
26
+ this.db = config.db;
27
+ this.tables = config.tables;
28
+ // Multi-tenancy config with defaults
29
+ this.rlsEnabled = config.multiTenancy?.enableRLS ?? true;
30
+ this.hierarchyEnabled = config.multiTenancy?.enableHierarchy ?? true;
31
+ // Pass the Drizzle instance and tables to all adapters
32
+ this.documentAdapter = new PostgreSQLDocumentAdapter(this.db, this.tables);
33
+ this.assetAdapter = new PostgreSQLAssetAdapter(this.db, this.tables);
34
+ this.userProfileAdapter = new PostgreSQLUserProfileAdapter(this.db, this.tables);
35
+ this.schemaAdapter = new PostgreSQLSchemaAdapter(this.db, this.tables);
36
+ this.organizationAdapter = new PostgreSQLOrganizationAdapter(this.db, this.tables);
37
+ }
38
+ // Document operations - delegate to document adapter with RLS context
39
+ async findManyDoc(organizationId, filters) {
40
+ return this.withOrgContext(organizationId, async () => {
41
+ // If hierarchy is enabled and no explicit filterOrganizationIds provided,
42
+ // include child organizations in the query
43
+ if (this.hierarchyEnabled && !filters?.filterOrganizationIds) {
44
+ const childOrgIds = await this.getChildOrganizations(organizationId);
45
+ const orgIds = [organizationId, ...childOrgIds];
46
+ return this.documentAdapter.findManyDoc(organizationId, {
47
+ ...filters,
48
+ filterOrganizationIds: orgIds
49
+ });
50
+ }
51
+ return this.documentAdapter.findManyDoc(organizationId, filters);
52
+ });
53
+ }
54
+ async findByDocId(organizationId, id, depth) {
55
+ return this.withOrgContext(organizationId, async () => {
56
+ // Try to find in current org first
57
+ let document = await this.documentAdapter.findByDocId(organizationId, id, depth);
58
+ // If not found and hierarchy is enabled, try child organizations
59
+ if (!document && this.hierarchyEnabled) {
60
+ const childOrgIds = await this.getChildOrganizations(organizationId);
61
+ for (const childOrgId of childOrgIds) {
62
+ document = await this.documentAdapter.findByDocId(childOrgId, id, depth);
63
+ if (document)
64
+ break;
65
+ }
66
+ }
67
+ return document;
68
+ });
69
+ }
70
+ async createDocument(data) {
71
+ return this.withOrgContext(data.organizationId, () => this.documentAdapter.createDocument(data));
72
+ }
73
+ async updateDocDraft(organizationId, id, data, updatedBy) {
74
+ return this.withOrgContext(organizationId, async () => {
75
+ // Try to update in current org first
76
+ let document = await this.documentAdapter.updateDocDraft(organizationId, id, data, updatedBy);
77
+ // If not found and hierarchy is enabled, try child organizations
78
+ if (!document && this.hierarchyEnabled) {
79
+ const childOrgIds = await this.getChildOrganizations(organizationId);
80
+ for (const childOrgId of childOrgIds) {
81
+ document = await this.documentAdapter.updateDocDraft(childOrgId, id, data, updatedBy);
82
+ if (document)
83
+ break;
84
+ }
85
+ }
86
+ return document;
87
+ });
88
+ }
89
+ async deleteDocById(organizationId, id) {
90
+ return this.withOrgContext(organizationId, async () => {
91
+ // Try to delete in current org first
92
+ let deleted = await this.documentAdapter.deleteDocById(organizationId, id);
93
+ // If not found and hierarchy is enabled, try child organizations
94
+ if (!deleted && this.hierarchyEnabled) {
95
+ const childOrgIds = await this.getChildOrganizations(organizationId);
96
+ for (const childOrgId of childOrgIds) {
97
+ deleted = await this.documentAdapter.deleteDocById(childOrgId, id);
98
+ if (deleted)
99
+ break;
100
+ }
101
+ }
102
+ return deleted;
103
+ });
104
+ }
105
+ async publishDoc(organizationId, id) {
106
+ return this.withOrgContext(organizationId, async () => {
107
+ // Try to publish in current org first
108
+ let document = await this.documentAdapter.publishDoc(organizationId, id);
109
+ // If not found and hierarchy is enabled, try child organizations
110
+ if (!document && this.hierarchyEnabled) {
111
+ const childOrgIds = await this.getChildOrganizations(organizationId);
112
+ for (const childOrgId of childOrgIds) {
113
+ document = await this.documentAdapter.publishDoc(childOrgId, id);
114
+ if (document)
115
+ break;
116
+ }
117
+ }
118
+ return document;
119
+ });
120
+ }
121
+ async unpublishDoc(organizationId, id) {
122
+ return this.withOrgContext(organizationId, async () => {
123
+ // Try to unpublish in current org first
124
+ let document = await this.documentAdapter.unpublishDoc(organizationId, id);
125
+ // If not found and hierarchy is enabled, try child organizations
126
+ if (!document && this.hierarchyEnabled) {
127
+ const childOrgIds = await this.getChildOrganizations(organizationId);
128
+ for (const childOrgId of childOrgIds) {
129
+ document = await this.documentAdapter.unpublishDoc(childOrgId, id);
130
+ if (document)
131
+ break;
132
+ }
133
+ }
134
+ return document;
135
+ });
136
+ }
137
+ async countDocsByType(organizationId, type) {
138
+ return this.withOrgContext(organizationId, async () => {
139
+ let count = await this.documentAdapter.countDocsByType(organizationId, type);
140
+ // If hierarchy is enabled, add child org counts
141
+ if (this.hierarchyEnabled) {
142
+ const childOrgIds = await this.getChildOrganizations(organizationId);
143
+ for (const childOrgId of childOrgIds) {
144
+ const childCount = await this.documentAdapter.countDocsByType(childOrgId, type);
145
+ count += childCount;
146
+ }
147
+ }
148
+ return count;
149
+ });
150
+ }
151
+ async getDocCountsByType(organizationId) {
152
+ return this.withOrgContext(organizationId, async () => {
153
+ const counts = await this.documentAdapter.getDocCountsByType(organizationId);
154
+ // If hierarchy is enabled, add child org counts
155
+ if (this.hierarchyEnabled) {
156
+ const childOrgIds = await this.getChildOrganizations(organizationId);
157
+ for (const childOrgId of childOrgIds) {
158
+ const childCounts = await this.documentAdapter.getDocCountsByType(childOrgId);
159
+ // Merge counts
160
+ for (const [type, count] of Object.entries(childCounts)) {
161
+ counts[type] = (counts[type] || 0) + count;
162
+ }
163
+ }
164
+ }
165
+ return counts;
166
+ });
167
+ }
168
+ // Asset operations - delegate to asset adapter with RLS context
169
+ async createAsset(data) {
170
+ return this.withOrgContext(data.organizationId, () => this.assetAdapter.createAsset(data));
171
+ }
172
+ async findAssetById(organizationId, id) {
173
+ return this.withOrgContext(organizationId, () => this.assetAdapter.findAssetById(organizationId, id));
174
+ }
175
+ async findAssetByIdGlobal(id) {
176
+ // Bypass RLS - call adapter directly without org context
177
+ return this.assetAdapter.findAssetByIdGlobal(id);
178
+ }
179
+ async findAssets(organizationId, filters) {
180
+ return this.withOrgContext(organizationId, () => this.assetAdapter.findAssets(organizationId, filters));
181
+ }
182
+ async updateAsset(organizationId, id, data) {
183
+ return this.withOrgContext(organizationId, () => this.assetAdapter.updateAsset(organizationId, id, data));
184
+ }
185
+ async deleteAsset(organizationId, id) {
186
+ return this.withOrgContext(organizationId, () => this.assetAdapter.deleteAsset(organizationId, id));
187
+ }
188
+ async countAssets(organizationId) {
189
+ return this.withOrgContext(organizationId, () => this.assetAdapter.countAssets(organizationId));
190
+ }
191
+ async countAssetsByType(organizationId) {
192
+ return this.withOrgContext(organizationId, () => this.assetAdapter.countAssetsByType(organizationId));
193
+ }
194
+ async getTotalAssetsSize(organizationId) {
195
+ return this.withOrgContext(organizationId, () => this.assetAdapter.getTotalAssetsSize(organizationId));
196
+ }
197
+ // User Profile operations - delegate to user profile adapter
198
+ async createUserProfile(data) {
199
+ return this.userProfileAdapter.createUserProfile(data);
200
+ }
201
+ async findUserProfileById(userId) {
202
+ return this.userProfileAdapter.findUserProfileById(userId);
203
+ }
204
+ async deleteUserProfile(userId) {
205
+ return this.userProfileAdapter.deleteUserProfile(userId);
206
+ }
207
+ /**
208
+ * Check if any user profiles exist (for detecting first user)
209
+ */
210
+ async hasAnyUserProfiles() {
211
+ const result = await this.db.select().from(this.tables.userProfiles).limit(1);
212
+ return result.length > 0;
213
+ }
214
+ // Schema operations - delegate to schema adapter
215
+ async registerSchemaType(schemaType) {
216
+ return this.schemaAdapter.registerSchemaType(schemaType);
217
+ }
218
+ async getSchemaType(name) {
219
+ return this.schemaAdapter.getSchemaType(name);
220
+ }
221
+ async listDocumentTypes() {
222
+ return this.schemaAdapter.listDocumentTypes();
223
+ }
224
+ async listObjectTypes() {
225
+ return this.schemaAdapter.listObjectTypes();
226
+ }
227
+ async listSchemas() {
228
+ return this.schemaAdapter.listSchemas();
229
+ }
230
+ async deleteSchemaType(name) {
231
+ return this.schemaAdapter.deleteSchemaType(name);
232
+ }
233
+ // Organization operations - delegate to organization adapter
234
+ async createOrganization(data) {
235
+ return this.organizationAdapter.createOrganization(data);
236
+ }
237
+ async findOrganizationById(id) {
238
+ return this.organizationAdapter.findOrganizationById(id);
239
+ }
240
+ async findOrganizationBySlug(slug) {
241
+ return this.organizationAdapter.findOrganizationBySlug(slug);
242
+ }
243
+ async updateOrganization(id, data) {
244
+ return this.organizationAdapter.updateOrganization(id, data);
245
+ }
246
+ async deleteOrganization(id) {
247
+ return this.organizationAdapter.deleteOrganization(id);
248
+ }
249
+ async addMember(data) {
250
+ return this.organizationAdapter.addMember(data);
251
+ }
252
+ async removeMember(organizationId, userId) {
253
+ return this.organizationAdapter.removeMember(organizationId, userId);
254
+ }
255
+ async removeAllMembers(organizationId) {
256
+ return this.organizationAdapter.removeAllMembers(organizationId);
257
+ }
258
+ async updateMemberRole(organizationId, userId, role) {
259
+ return this.organizationAdapter.updateMemberRole(organizationId, userId, role);
260
+ }
261
+ async findUserMembership(userId, organizationId) {
262
+ return this.organizationAdapter.findUserMembership(userId, organizationId);
263
+ }
264
+ async findUserOrganizations(userId) {
265
+ return this.organizationAdapter.findUserOrganizations(userId);
266
+ }
267
+ async findOrganizationMembers(organizationId) {
268
+ return this.organizationAdapter.findOrganizationMembers(organizationId);
269
+ }
270
+ async createInvitation(data) {
271
+ return this.organizationAdapter.createInvitation(data);
272
+ }
273
+ async findInvitationByToken(token) {
274
+ return this.organizationAdapter.findInvitationByToken(token);
275
+ }
276
+ async findOrganizationInvitations(organizationId) {
277
+ return this.organizationAdapter.findOrganizationInvitations(organizationId);
278
+ }
279
+ async findInvitationsByEmail(email) {
280
+ return this.organizationAdapter.findInvitationsByEmail(email);
281
+ }
282
+ async acceptInvitation(token, userId) {
283
+ return this.organizationAdapter.acceptInvitation(token, userId);
284
+ }
285
+ async deleteInvitation(id) {
286
+ return this.organizationAdapter.deleteInvitation(id);
287
+ }
288
+ async removeAllInvitations(organizationId) {
289
+ return this.organizationAdapter.removeAllInvitations(organizationId);
290
+ }
291
+ async cleanupExpiredInvitations() {
292
+ return this.organizationAdapter.cleanupExpiredInvitations();
293
+ }
294
+ async updateUserSession(userId, organizationId) {
295
+ return this.organizationAdapter.updateUserSession(userId, organizationId);
296
+ }
297
+ async findUserSession(userId) {
298
+ return this.organizationAdapter.findUserSession(userId);
299
+ }
300
+ async deleteUserSession(userId) {
301
+ return this.organizationAdapter.deleteUserSession(userId);
302
+ }
303
+ // Multi-tenancy RLS helper methods
304
+ /**
305
+ * Initialize RLS by enabling or disabling it on content tables based on config
306
+ * Call this after running migrations to set up RLS according to your configuration
307
+ */
308
+ async initializeRLS() {
309
+ const action = this.rlsEnabled ? 'ENABLE' : 'DISABLE';
310
+ try {
311
+ await this.db.execute(sql.raw(`ALTER TABLE cms_documents ${action} ROW LEVEL SECURITY`));
312
+ await this.db.execute(sql.raw(`ALTER TABLE cms_assets ${action} ROW LEVEL SECURITY`));
313
+ console.log(`[PostgreSQLAdapter]: RLS ${action}D on content tables`);
314
+ }
315
+ catch (error) {
316
+ console.error(`[PostgreSQLAdapter]: Failed to ${action} RLS:`, error);
317
+ throw error;
318
+ }
319
+ }
320
+ /**
321
+ * Execute a function within a transaction with organization context set for RLS
322
+ * This ensures SET LOCAL is properly scoped and won't leak between requests in connection pooling
323
+ *
324
+ * @param organizationId - The organization ID to set as context
325
+ * @param fn - Function to execute within the transaction context
326
+ * @returns The result of the function
327
+ *
328
+ * @example
329
+ * const documents = await adapter.withOrgContext(auth.organizationId, async () => {
330
+ * return adapter.findManyDoc(auth.organizationId, { type: 'post' });
331
+ * });
332
+ */
333
+ async withOrgContext(organizationId, fn) {
334
+ if (!this.rlsEnabled) {
335
+ // If RLS is disabled, just execute the function directly
336
+ return fn();
337
+ }
338
+ // Validate organizationId is a valid UUID to prevent SQL injection
339
+ const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
340
+ if (!uuidRegex.test(organizationId)) {
341
+ throw new Error('Invalid organization ID format');
342
+ }
343
+ // Use Drizzle's transaction API - SET LOCAL is automatically cleared on commit
344
+ return this.db.transaction(async (tx) => {
345
+ // Set the organization context for this transaction
346
+ // Note: SET LOCAL doesn't support parameterized queries, so we use sql.raw()
347
+ // The organizationId is validated as a UUID above to prevent SQL injection
348
+ await tx.execute(sql.raw(`SET LOCAL app.organization_id = '${organizationId}'`));
349
+ // Execute the provided function
350
+ // Note: The function should use the same db adapter, the transaction context applies to the connection
351
+ return fn();
352
+ });
353
+ }
354
+ /**
355
+ * Get all child organizations for a given parent organization
356
+ * Used for parent-child hierarchy access control
357
+ * @param parentOrganizationId - The parent organization ID
358
+ * @returns Array of child organization IDs
359
+ */
360
+ async getChildOrganizations(parentOrganizationId) {
361
+ if (!this.hierarchyEnabled) {
362
+ return []; // No hierarchy support
363
+ }
364
+ try {
365
+ const children = await this.db
366
+ .select({ id: this.tables.organizations.id })
367
+ .from(this.tables.organizations)
368
+ .where(eq(this.tables.organizations.parentOrganizationId, parentOrganizationId));
369
+ return children.map((child) => child.id);
370
+ }
371
+ catch (error) {
372
+ console.error('[PostgreSQLAdapter]: Failed to get child organizations:', error);
373
+ throw error;
374
+ }
375
+ }
376
+ // Connection management
377
+ async disconnect() {
378
+ // Connection is managed by the app, not the adapter
379
+ // This method is here for interface compatibility
380
+ }
381
+ // Health check
382
+ async isHealthy() {
383
+ try {
384
+ // Simple health check - try a basic query
385
+ await this.db.select().from(this.tables.organizations).limit(1);
386
+ return true;
387
+ }
388
+ catch (error) {
389
+ console.error('Database health check failed:', error);
390
+ return false;
391
+ }
392
+ }
393
+ }
394
+ // Re-export for convenience
395
+ export { PostgreSQLDocumentAdapter } from './document-adapter.js';
396
+ export { PostgreSQLAssetAdapter } from './asset-adapter.js';
397
+ // Export schema (table definitions for Drizzle)
398
+ export { cmsSchema } from './schema.js';
399
+ // Export individual schema tables for app usage
400
+ export { documents, assets, schemaTypes, documentStatusEnum, schemaTypeEnum } from './schema.js';
401
+ /**
402
+ * PostgreSQL database provider
403
+ */
404
+ class PostgreSQLProvider {
405
+ name = 'postgresql';
406
+ config;
407
+ constructor(config) {
408
+ this.config = config;
409
+ }
410
+ createAdapter() {
411
+ // If client is provided directly, use it with drizzle
412
+ if (this.config.client) {
413
+ const db = drizzlePostgres(this.config.client, { schema: cmsSchema });
414
+ return new PostgreSQLAdapter({
415
+ db,
416
+ tables: cmsSchema,
417
+ multiTenancy: this.config.multiTenancy
418
+ });
419
+ }
420
+ // Otherwise create a new postgres client from connection string
421
+ if (!this.config.connectionString) {
422
+ throw new Error('PostgreSQL adapter requires either a client or connectionString');
423
+ }
424
+ const client = postgres(this.config.connectionString, this.config.options);
425
+ const db = drizzlePostgres(client, { schema: cmsSchema });
426
+ return new PostgreSQLAdapter({
427
+ db,
428
+ tables: cmsSchema,
429
+ multiTenancy: this.config.multiTenancy
430
+ });
431
+ }
432
+ }
433
+ /**
434
+ * Create a PostgreSQL database provider with type-safe configuration
435
+ *
436
+ * @example
437
+ * // With pre-initialized client (recommended)
438
+ * const provider = createPostgreSQLProvider({ client: myPostgresClient });
439
+ *
440
+ * @example
441
+ * // With connection string
442
+ * const provider = createPostgreSQLProvider({
443
+ * connectionString: 'postgres://...',
444
+ * options: { max: 10, idle_timeout: 20 }
445
+ * });
446
+ */
447
+ export function createPostgreSQLProvider(config) {
448
+ return new PostgreSQLProvider(config);
449
+ }
450
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}