@rebasepro/server-mongo 0.9.1-canary.ff338b5 → 0.10.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.
@@ -7,14 +7,14 @@
7
7
  import { Db, ChangeStream } from "mongodb";
8
8
  import { RealtimeProvider, CollectionSubscriptionConfig, SingleSubscriptionConfig } from "@rebasepro/types";
9
9
  import { WebSocket } from "ws";
10
- import { MongoDriver } from "./MongoDriver";
10
+ import type { MongoDriver } from "./MongoDriver";
11
11
  interface Subscription {
12
12
  type: "collection" | "single";
13
13
  config: CollectionSubscriptionConfig | SingleSubscriptionConfig;
14
14
  changeStream?: ChangeStream;
15
15
  callback?: (data: any) => void;
16
16
  authContext?: {
17
- userId: string;
17
+ uid: string;
18
18
  roles: string[];
19
19
  };
20
20
  }
@@ -41,7 +41,7 @@ export declare class MongoRealtimeService implements RealtimeProvider {
41
41
  */
42
42
  subscribeToCollection(subscriptionId: string, config: CollectionSubscriptionConfig & {
43
43
  authContext?: {
44
- userId: string;
44
+ uid: string;
45
45
  roles: string[];
46
46
  };
47
47
  }, callback?: (rows: Record<string, unknown>[]) => void): void;
@@ -54,7 +54,7 @@ export declare class MongoRealtimeService implements RealtimeProvider {
54
54
  */
55
55
  subscribeToOne(subscriptionId: string, config: SingleSubscriptionConfig & {
56
56
  authContext?: {
57
- userId: string;
57
+ uid: string;
58
58
  roles: string[];
59
59
  };
60
60
  }, callback?: (row: Record<string, unknown> | null) => void): void;
@@ -95,7 +95,7 @@ export declare class MongoRealtimeService implements RealtimeProvider {
95
95
  payload?: any;
96
96
  subscriptionId?: string;
97
97
  }, _authContext?: {
98
- userId: string;
98
+ uid: string;
99
99
  roles: unknown[];
100
100
  }): Promise<void>;
101
101
  }
@@ -1 +1 @@
1
- {"version":3,"file":"MongoRealtimeService.d.ts","sourceRoot":"","sources":["../../src/services/MongoRealtimeService.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"MongoRealtimeService.d.ts","sourceRoot":"","sources":["../../src/services/MongoRealtimeService.ts"],"names":[],"mappings":"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"}
@@ -81,7 +81,7 @@ function createMongoWebSocket(server, realtimeService, driver, authConfig, admin
81
81
  type: "AUTH_SUCCESS",
82
82
  requestId,
83
83
  payload: {
84
- userId: user.userId,
84
+ uid: user.uid,
85
85
  roles: user.roles
86
86
  }
87
87
  }));
@@ -119,7 +119,7 @@ function createMongoWebSocket(server, realtimeService, driver, authConfig, admin
119
119
  const session = clientSessions.get(clientId);
120
120
  if (session?.user && isDriverWithAuth(driver)) try {
121
121
  const userForAuth = {
122
- uid: session.user.userId,
122
+ uid: session.user.uid,
123
123
  email: session.user.email ?? "",
124
124
  displayName: session.user.displayName ?? "",
125
125
  photoURL: session.user.photoURL ?? "",
@@ -249,7 +249,7 @@ function createMongoWebSocket(server, realtimeService, driver, authConfig, admin
249
249
  case "unsubscribe": {
250
250
  const session = clientSessions.get(clientId);
251
251
  const authContext = session?.user ? {
252
- userId: session.user.userId,
252
+ uid: session.user.uid,
253
253
  roles: session.user.roles ?? []
254
254
  } : void 0;
255
255
  await realtimeService.handleClientMessage(clientId, {
@@ -278,4 +278,4 @@ function createMongoWebSocket(server, realtimeService, driver, authConfig, admin
278
278
  //#endregion
279
279
  export { createMongoWebSocket };
280
280
 
281
- //# sourceMappingURL=websocket-DQlwCHFq.js.map
281
+ //# sourceMappingURL=websocket-CoKu1mvm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"websocket-CoKu1mvm.js","names":[],"sources":["../src/websocket.ts"],"sourcesContent":["import { RealtimeProvider, DataDriver, FetchCollectionProps, FetchOneProps, SaveProps, DeleteProps, TableMetadata, DatabaseAdmin, isSchemaAdmin, isDocumentAdmin, User } from \"@rebasepro/types\";\nimport { WebSocketServer, WebSocket } from \"ws\";\nimport { Server } from \"http\";\nimport { inspect } from \"util\";\nimport type { AccessTokenPayload } from \"@rebasepro/server\";\nimport { extractUserFromToken } from \"@rebasepro/server\";\nimport type { RebaseAuthConfig } from \"@rebasepro/server\";\nimport { MongoRealtimeService } from \"./services/MongoRealtimeService\";\nimport { MongoDriver } from \"./services/MongoDriver\";\nimport { logger } from \"@rebasepro/server\";\n\ninterface DriverWithAuth extends DataDriver {\n withAuth(user: Record<string, unknown>): Promise<DataDriver>;\n}\n\nfunction isDriverWithAuth(driver: DataDriver): driver is DriverWithAuth {\n return \"withAuth\" in driver && typeof (driver as Record<string, unknown>).withAuth === \"function\";\n}\n\ninterface ClientSession {\n ws: WebSocket;\n user?: AccessTokenPayload;\n authenticated: boolean;\n messageCount: number;\n messageWindowStart: number;\n}\n\nconst clientSessions = new Map<string, ClientSession>();\nconst WS_RATE_LIMIT = 2000;\nconst WS_RATE_WINDOW_MS = 60_000;\n\nconst ADMIN_ONLY_TYPES = new Set([\n \"EXECUTE_SQL\",\n \"FETCH_DATABASES\",\n \"FETCH_ROLES\",\n \"FETCH_UNMAPPED_TABLES\",\n \"FETCH_TABLE_METADATA\",\n \"FETCH_CURRENT_DATABASE\",\n \"CREATE_BRANCH\",\n \"DELETE_BRANCH\",\n \"LIST_BRANCHES\"\n]);\n\nfunction isAdminSession(session: ClientSession | undefined): boolean {\n if (!session?.user?.roles) return false;\n return session.user.roles.includes(\"admin\");\n}\n\nexport function createMongoWebSocket(\n server: Server,\n realtimeService: MongoRealtimeService,\n driver: MongoDriver,\n authConfig?: RebaseAuthConfig,\n admin?: DatabaseAdmin\n) {\n const isProduction = process.env.NODE_ENV === \"production\";\n const wsDebug = (...args: unknown[]) => { if (!isProduction) console.debug(...args); };\n const wss = new WebSocketServer({ server });\n\n wss.on(\"error\", (err: NodeJS.ErrnoException) => {\n if (err.code === \"EADDRINUSE\") return;\n logger.error(\"❌ [WebSocket Server] Error\", { error: err });\n });\n\n const requireAuth = authConfig?.requireAuth !== false && authConfig?.jwtSecret;\n\n wss.on(\"connection\", (ws) => {\n const clientId = `client_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`;\n wsDebug(`WebSocket client connected: ${clientId}`);\n\n clientSessions.set(clientId, { ws,\nauthenticated: !requireAuth,\nmessageCount: 0,\nmessageWindowStart: Date.now() });\n realtimeService.addClient(clientId, ws);\n\n ws.on(\"close\", () => {\n wsDebug(`WebSocket client disconnected: ${clientId}`);\n clientSessions.delete(clientId);\n });\n\n ws.on(\"message\", async (message) => {\n let requestId: string | undefined;\n try {\n const { type, payload, requestId: reqId } = JSON.parse(message.toString());\n requestId = reqId;\n\n wsDebug(`[WS] ${clientId} → ${type}`, requestId ? `(${requestId})` : \"\");\n\n const sendError = (errType: \"ERROR\" | \"AUTH_ERROR\", code: string, msg: string) => {\n ws.send(JSON.stringify({ type: errType,\nrequestId,\npayload: { error: { message: msg,\ncode } } }));\n };\n\n if (type === \"AUTHENTICATE\") {\n const { token } = payload || {};\n if (!token) {\n sendError(\"AUTH_ERROR\", \"INVALID_INPUT\", \"Token is required\");\n return;\n }\n\n const user = extractUserFromToken(token);\n if (user) {\n const session = clientSessions.get(clientId);\n if (session) {\n session.user = user;\n session.authenticated = true;\n }\n ws.send(JSON.stringify({ type: \"AUTH_SUCCESS\",\nrequestId,\npayload: { uid: user.uid,\nroles: user.roles } }));\n } else {\n sendError(\"AUTH_ERROR\", \"INVALID_TOKEN\", \"Invalid or expired token\");\n }\n return;\n }\n\n if (requireAuth) {\n const session = clientSessions.get(clientId);\n if (!session?.authenticated) {\n sendError(\"ERROR\", \"UNAUTHORIZED\", \"Authentication required\");\n return;\n }\n }\n\n {\n const session = clientSessions.get(clientId);\n if (session) {\n const now = Date.now();\n if (now - session.messageWindowStart > WS_RATE_WINDOW_MS) {\n session.messageCount = 0;\n session.messageWindowStart = now;\n }\n session.messageCount++;\n if (session.messageCount > WS_RATE_LIMIT) {\n sendError(\"ERROR\", \"RATE_LIMITED\", \"Too many requests. Please slow down.\");\n return;\n }\n }\n }\n\n if (ADMIN_ONLY_TYPES.has(type)) {\n const session = clientSessions.get(clientId);\n if (!isAdminSession(session)) {\n sendError(\"ERROR\", \"FORBIDDEN\", \"Admin access required for this operation\");\n return;\n }\n }\n\n const getScopedDelegate = async (): Promise<DataDriver> => {\n const session = clientSessions.get(clientId);\n if (session?.user && isDriverWithAuth(driver)) {\n try {\n const userForAuth: User = {\n uid: session.user.uid,\n email: session.user.email ?? \"\",\n displayName: session.user.displayName ?? \"\",\n photoURL: session.user.photoURL ?? \"\",\n providerId: \"jwt\",\n isAnonymous: false,\n roles: session.user.roles ?? []\n };\n return await driver.withAuth(userForAuth);\n } catch (e) {\n logger.error(\"Failed to create authenticated delegate for WS request\", { error: e });\n return driver;\n }\n }\n return driver;\n };\n\n switch (type) {\n case \"FETCH_COLLECTION\": {\n const request: FetchCollectionProps = payload;\n const delegate = await getScopedDelegate();\n const rows = await delegate.fetchCollection(request);\n ws.send(JSON.stringify({ type: \"FETCH_COLLECTION_SUCCESS\",\npayload: { rows },\nrequestId }));\n break;\n }\n case \"FETCH_ONE\": {\n const request: FetchOneProps = payload;\n const delegate = await getScopedDelegate();\n const row = await delegate.fetchOne(request);\n ws.send(JSON.stringify({ type: \"FETCH_ONE_SUCCESS\",\npayload: { row },\nrequestId }));\n break;\n }\n case \"SAVE\": {\n const request: SaveProps = payload;\n const delegate = await getScopedDelegate();\n const row = await delegate.save(request);\n ws.send(JSON.stringify({ type: \"SAVE_SUCCESS\",\npayload: { row },\nrequestId }));\n break;\n }\n case \"DELETE\": {\n const request: DeleteProps = payload;\n const delegate = await getScopedDelegate();\n await delegate.delete(request);\n ws.send(JSON.stringify({ type: \"DELETE_SUCCESS\",\npayload: { success: true },\nrequestId }));\n break;\n }\n case \"CHECK_UNIQUE_FIELD\": {\n const { path, name, value, id, collection } = payload;\n const delegate = await getScopedDelegate();\n const isUnique = await delegate.checkUniqueField(path, name, value, id, collection);\n ws.send(JSON.stringify({ type: \"CHECK_UNIQUE_FIELD_SUCCESS\",\npayload: { isUnique },\nrequestId }));\n break;\n }\n case \"COUNT\": {\n const request: FetchCollectionProps = payload;\n const delegate = await getScopedDelegate();\n const count = await delegate.count!(request);\n ws.send(JSON.stringify({ type: \"COUNT_SUCCESS\",\npayload: { count },\nrequestId }));\n break;\n }\n case \"EXECUTE_SQL\": {\n const { sql, options } = payload;\n if (admin && isDocumentAdmin(admin) && admin.executeAggregate) {\n const result = await admin.executeAggregate(sql as Record<string, unknown>[]);\n ws.send(JSON.stringify({ type: \"EXECUTE_SQL_SUCCESS\",\npayload: { result },\nrequestId }));\n } else {\n ws.send(JSON.stringify({ type: \"ERROR\",\nrequestId,\npayload: { error: { message: \"SQL execution not supported for this driver\",\ncode: \"NOT_SUPPORTED\" } } }));\n }\n break;\n }\n case \"FETCH_UNMAPPED_TABLES\": {\n if (admin && isSchemaAdmin(admin)) {\n const tables = await admin.fetchUnmappedTables?.(payload?.mappedPaths) || [];\n ws.send(JSON.stringify({ type: \"FETCH_UNMAPPED_TABLES_SUCCESS\",\npayload: { tables },\nrequestId }));\n } else {\n ws.send(JSON.stringify({ type: \"FETCH_UNMAPPED_TABLES_SUCCESS\",\npayload: { tables: [] },\nrequestId }));\n }\n break;\n }\n case \"FETCH_TABLE_METADATA\": {\n const { tableName } = payload;\n if (admin && isSchemaAdmin(admin)) {\n const metadata = await admin.fetchTableMetadata?.(tableName);\n ws.send(JSON.stringify({ type: \"FETCH_TABLE_METADATA_SUCCESS\",\npayload: { metadata },\nrequestId }));\n } else {\n ws.send(JSON.stringify({ type: \"FETCH_TABLE_METADATA_SUCCESS\",\npayload: { metadata: null },\nrequestId }));\n }\n break;\n }\n case \"subscribe_collection\":\n case \"subscribe_one\":\n case \"unsubscribe\": {\n const session = clientSessions.get(clientId);\n const authContext = session?.user ? { uid: session.user.uid,\nroles: session.user.roles ?? [] } : undefined;\n await realtimeService.handleClientMessage(clientId, {\n type,\n payload,\n subscriptionId: payload?.subscriptionId\n }, authContext);\n break;\n }\n default:\n logger.error(\"❌ [WebSocket Server] Unknown message type\", { detail: type });\n }\n } catch (error: unknown) {\n const errorMessage = process.env.NODE_ENV === \"production\" ? \"An unexpected error occurred\" : (error instanceof Error ? error.message : \"An unexpected error occurred\");\n ws.send(JSON.stringify({ type: \"ERROR\",\nrequestId,\npayload: { error: { message: errorMessage,\ncode: \"INTERNAL_ERROR\" } } }));\n }\n });\n });\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@rebasepro/server-mongo",
3
3
  "type": "module",
4
- "version": "0.9.1-canary.ff338b5",
4
+ "version": "0.10.0",
5
5
  "description": "MongoDB backend for Rebase",
6
6
  "funding": {
7
7
  "url": "https://github.com/sponsors/rebaseco"
@@ -40,9 +40,9 @@
40
40
  "dependencies": {
41
41
  "mongodb": "^7.3.0",
42
42
  "ws": "^8.21.0",
43
- "@rebasepro/common": "0.9.1-canary.ff338b5",
44
- "@rebasepro/types": "0.9.1-canary.ff338b5",
45
- "@rebasepro/utils": "0.9.1-canary.ff338b5"
43
+ "@rebasepro/common": "0.10.0",
44
+ "@rebasepro/types": "0.10.0",
45
+ "@rebasepro/utils": "0.10.0"
46
46
  },
47
47
  "devDependencies": {
48
48
  "@types/jest": "^30.0.0",
@@ -55,7 +55,7 @@
55
55
  "vite": "^8.0.16"
56
56
  },
57
57
  "peerDependencies": {
58
- "@rebasepro/server": "0.9.1-canary.ff338b5"
58
+ "@rebasepro/server": "0.10.0"
59
59
  },
60
60
  "peerDependenciesMeta": {
61
61
  "@rebasepro/server": {
@@ -93,14 +93,14 @@ export class MongoUserService implements UserRepository {
93
93
  const identity = await this.identitiesCollection.findOne({ provider,
94
94
  providerId });
95
95
  if (!identity) return null;
96
- return this.getUserById(identity.userId);
96
+ return this.getUserById(identity.uid);
97
97
  }
98
98
 
99
- async getUserIdentities(userId: string): Promise<UserIdentityData[]> {
100
- const docs = await this.identitiesCollection.find({ userId }).toArray();
99
+ async getUserIdentities(uid: string): Promise<UserIdentityData[]> {
100
+ const docs = await this.identitiesCollection.find({ uid }).toArray();
101
101
  return docs.map(doc => ({
102
102
  id: doc.id,
103
- userId: doc.userId,
103
+ uid: doc.uid,
104
104
  provider: doc.provider,
105
105
  providerId: doc.providerId,
106
106
  profileData: doc.profileData ?? null,
@@ -109,7 +109,7 @@ providerId });
109
109
  }));
110
110
  }
111
111
 
112
- async linkUserIdentity(userId: string, provider: string, providerId: string, profileData?: Record<string, unknown>): Promise<void> {
112
+ async linkUserIdentity(uid: string, provider: string, providerId: string, profileData?: Record<string, unknown>): Promise<void> {
113
113
  const now = new Date();
114
114
  await this.identitiesCollection.updateOne(
115
115
  { provider,
@@ -118,7 +118,7 @@ providerId },
118
118
  $setOnInsert: {
119
119
  _id: new ObjectId().toString(),
120
120
  id: new ObjectId().toString(),
121
- userId,
121
+ uid,
122
122
  provider,
123
123
  providerId,
124
124
  createdAt: now
@@ -143,8 +143,8 @@ updatedAt: new Date() };
143
143
 
144
144
  async deleteUser(id: string): Promise<void> {
145
145
  await this.collection.deleteOne({ id });
146
- await this.identitiesCollection.deleteMany({ userId: id });
147
- await this.userRolesCollection.deleteMany({ userId: id });
146
+ await this.identitiesCollection.deleteMany({ uid: id });
147
+ await this.userRolesCollection.deleteMany({ uid: id });
148
148
  }
149
149
 
150
150
  async listUsers(): Promise<UserData[]> {
@@ -174,7 +174,7 @@ $options: "i" } }
174
174
 
175
175
  if (roleId) {
176
176
  const userRoles = await this.userRolesCollection.find({ roleId }).toArray();
177
- const userIds = userRoles.map(ur => ur.userId);
177
+ const userIds = userRoles.map(ur => ur.uid);
178
178
  query.id = { $in: userIds };
179
179
  }
180
180
 
@@ -223,8 +223,8 @@ updatedAt: new Date() } }
223
223
  return doc ? toUser(doc) : null;
224
224
  }
225
225
 
226
- async getUserRoles(userId: string): Promise<RoleData[]> {
227
- const userRoles = await this.userRolesCollection.find({ userId }).toArray();
226
+ async getUserRoles(uid: string): Promise<RoleData[]> {
227
+ const userRoles = await this.userRolesCollection.find({ uid }).toArray();
228
228
  const roleIds = userRoles.map(ur => ur.roleId);
229
229
  if (roleIds.length === 0) return [];
230
230
 
@@ -238,38 +238,38 @@ updatedAt: new Date() } }
238
238
  }));
239
239
  }
240
240
 
241
- async getUserRoleIds(userId: string): Promise<string[]> {
242
- const userRoles = await this.userRolesCollection.find({ userId }).toArray();
241
+ async getUserRoleIds(uid: string): Promise<string[]> {
242
+ const userRoles = await this.userRolesCollection.find({ uid }).toArray();
243
243
  return userRoles.map(ur => ur.roleId);
244
244
  }
245
245
 
246
- async setUserRoles(userId: string, roleIds: string[]): Promise<void> {
247
- await this.userRolesCollection.deleteMany({ userId });
246
+ async setUserRoles(uid: string, roleIds: string[]): Promise<void> {
247
+ await this.userRolesCollection.deleteMany({ uid });
248
248
  if (roleIds.length > 0) {
249
249
  const docs = roleIds.map(roleId => ({
250
250
  _id: new ObjectId().toString(),
251
- userId,
251
+ uid,
252
252
  roleId
253
253
  }));
254
254
  await this.userRolesCollection.insertMany(docs);
255
255
  }
256
256
  }
257
257
 
258
- async assignDefaultRole(userId: string, roleId: string): Promise<void> {
258
+ async assignDefaultRole(uid: string, roleId: string): Promise<void> {
259
259
  await this.userRolesCollection.updateOne(
260
- { userId,
260
+ { uid,
261
261
  roleId },
262
262
  { $setOnInsert: { _id: new ObjectId().toString(),
263
- userId,
263
+ uid,
264
264
  roleId } },
265
265
  { upsert: true }
266
266
  );
267
267
  }
268
268
 
269
- async getUserWithRoles(userId: string): Promise<{ user: UserData; roles: RoleData[] } | null> {
270
- const user = await this.getUserById(userId);
269
+ async getUserWithRoles(uid: string): Promise<{ user: UserData; roles: RoleData[] } | null> {
270
+ const user = await this.getUserById(uid);
271
271
  if (!user) return null;
272
- const roles = await this.getUserRoles(userId);
272
+ const roles = await this.getUserRoles(uid);
273
273
  return { user,
274
274
  roles };
275
275
  }
@@ -336,12 +336,12 @@ export class MongoRefreshTokenService {
336
336
  return this.db.collection<MongoDoc>("rebase_refresh_tokens");
337
337
  }
338
338
 
339
- async createToken(userId: string, tokenHash: string, expiresAt: Date, userAgent?: string, ipAddress?: string): Promise<void> {
339
+ async createToken(uid: string, tokenHash: string, expiresAt: Date, userAgent?: string, ipAddress?: string): Promise<void> {
340
340
  const safeUserAgent = userAgent || "";
341
341
  const safeIpAddress = ipAddress || "";
342
342
 
343
343
  await this.collection.deleteMany({
344
- userId,
344
+ uid,
345
345
  userAgent: safeUserAgent,
346
346
  ipAddress: safeIpAddress
347
347
  });
@@ -349,7 +349,7 @@ export class MongoRefreshTokenService {
349
349
  await this.collection.insertOne({
350
350
  _id: new ObjectId().toString(),
351
351
  id: new ObjectId().toString(),
352
- userId,
352
+ uid,
353
353
  tokenHash,
354
354
  expiresAt,
355
355
  createdAt: new Date(),
@@ -363,7 +363,7 @@ export class MongoRefreshTokenService {
363
363
  if (!doc) return null;
364
364
  return {
365
365
  id: doc.id,
366
- userId: doc.userId,
366
+ uid: doc.uid,
367
367
  tokenHash: doc.tokenHash,
368
368
  expiresAt: new Date(doc.expiresAt),
369
369
  createdAt: new Date(doc.createdAt),
@@ -376,15 +376,15 @@ export class MongoRefreshTokenService {
376
376
  await this.collection.deleteOne({ tokenHash });
377
377
  }
378
378
 
379
- async deleteAllForUser(userId: string): Promise<void> {
380
- await this.collection.deleteMany({ userId });
379
+ async deleteAllForUser(uid: string): Promise<void> {
380
+ await this.collection.deleteMany({ uid });
381
381
  }
382
382
 
383
- async listForUser(userId: string): Promise<RefreshTokenInfo[]> {
384
- const docs = await this.collection.find({ userId }).sort({ createdAt: 1 }).toArray();
383
+ async listForUser(uid: string): Promise<RefreshTokenInfo[]> {
384
+ const docs = await this.collection.find({ uid }).sort({ createdAt: 1 }).toArray();
385
385
  return docs.map(doc => ({
386
386
  id: doc.id,
387
- userId: doc.userId,
387
+ uid: doc.uid,
388
388
  tokenHash: doc.tokenHash,
389
389
  expiresAt: new Date(doc.expiresAt),
390
390
  createdAt: new Date(doc.createdAt),
@@ -393,9 +393,9 @@ export class MongoRefreshTokenService {
393
393
  }));
394
394
  }
395
395
 
396
- async deleteById(id: string, userId: string): Promise<void> {
396
+ async deleteById(id: string, uid: string): Promise<void> {
397
397
  await this.collection.deleteOne({ id,
398
- userId });
398
+ uid });
399
399
  }
400
400
  }
401
401
 
@@ -406,20 +406,20 @@ export class MongoPasswordResetTokenService {
406
406
  return this.db.collection<MongoDoc>("rebase_password_reset_tokens");
407
407
  }
408
408
 
409
- async createToken(userId: string, tokenHash: string, expiresAt: Date): Promise<void> {
410
- await this.collection.deleteMany({ userId,
409
+ async createToken(uid: string, tokenHash: string, expiresAt: Date): Promise<void> {
410
+ await this.collection.deleteMany({ uid,
411
411
  usedAt: null });
412
412
 
413
413
  await this.collection.insertOne({
414
414
  _id: new ObjectId().toString(),
415
- userId,
415
+ uid,
416
416
  tokenHash,
417
417
  expiresAt,
418
418
  usedAt: null
419
419
  });
420
420
  }
421
421
 
422
- async findValidByHash(tokenHash: string): Promise<{ userId: string; expiresAt: Date } | null> {
422
+ async findValidByHash(tokenHash: string): Promise<{ uid: string; expiresAt: Date } | null> {
423
423
  const doc = await this.collection.findOne({
424
424
  tokenHash,
425
425
  usedAt: null,
@@ -429,7 +429,7 @@ usedAt: null });
429
429
  if (!doc) return null;
430
430
 
431
431
  return {
432
- userId: doc.userId,
432
+ uid: doc.uid,
433
433
  expiresAt: new Date(doc.expiresAt)
434
434
  };
435
435
  }
@@ -441,8 +441,8 @@ usedAt: null });
441
441
  );
442
442
  }
443
443
 
444
- async deleteAllForUser(userId: string): Promise<void> {
445
- await this.collection.deleteMany({ userId });
444
+ async deleteAllForUser(uid: string): Promise<void> {
445
+ await this.collection.deleteMany({ uid });
446
446
  }
447
447
 
448
448
  async deleteExpired(): Promise<void> {
@@ -459,8 +459,8 @@ export class MongoTokenRepository implements TokenRepository {
459
459
  this.passwordResetTokenService = new MongoPasswordResetTokenService(db);
460
460
  }
461
461
 
462
- async createRefreshToken(userId: string, tokenHash: string, expiresAt: Date, userAgent?: string, ipAddress?: string): Promise<void> {
463
- await this.refreshTokenService.createToken(userId, tokenHash, expiresAt, userAgent, ipAddress);
462
+ async createRefreshToken(uid: string, tokenHash: string, expiresAt: Date, userAgent?: string, ipAddress?: string): Promise<void> {
463
+ await this.refreshTokenService.createToken(uid, tokenHash, expiresAt, userAgent, ipAddress);
464
464
  }
465
465
 
466
466
  async findRefreshTokenByHash(tokenHash: string): Promise<RefreshTokenInfo | null> {
@@ -471,20 +471,20 @@ export class MongoTokenRepository implements TokenRepository {
471
471
  await this.refreshTokenService.deleteByHash(tokenHash);
472
472
  }
473
473
 
474
- async deleteAllRefreshTokensForUser(userId: string): Promise<void> {
475
- await this.refreshTokenService.deleteAllForUser(userId);
474
+ async deleteAllRefreshTokensForUser(uid: string): Promise<void> {
475
+ await this.refreshTokenService.deleteAllForUser(uid);
476
476
  }
477
477
 
478
- async listRefreshTokensForUser(userId: string): Promise<RefreshTokenInfo[]> {
479
- return this.refreshTokenService.listForUser(userId);
478
+ async listRefreshTokensForUser(uid: string): Promise<RefreshTokenInfo[]> {
479
+ return this.refreshTokenService.listForUser(uid);
480
480
  }
481
481
 
482
- async deleteRefreshTokenById(id: string, userId: string): Promise<void> {
483
- await this.refreshTokenService.deleteById(id, userId);
482
+ async deleteRefreshTokenById(id: string, uid: string): Promise<void> {
483
+ await this.refreshTokenService.deleteById(id, uid);
484
484
  }
485
485
 
486
- async createPasswordResetToken(userId: string, tokenHash: string, expiresAt: Date): Promise<void> {
487
- await this.passwordResetTokenService.createToken(userId, tokenHash, expiresAt);
486
+ async createPasswordResetToken(uid: string, tokenHash: string, expiresAt: Date): Promise<void> {
487
+ await this.passwordResetTokenService.createToken(uid, tokenHash, expiresAt);
488
488
  }
489
489
 
490
490
  async findValidPasswordResetToken(tokenHash: string): Promise<PasswordResetTokenInfo | null> {
@@ -495,8 +495,8 @@ export class MongoTokenRepository implements TokenRepository {
495
495
  await this.passwordResetTokenService.markAsUsed(tokenHash);
496
496
  }
497
497
 
498
- async deleteAllPasswordResetTokensForUser(userId: string): Promise<void> {
499
- await this.passwordResetTokenService.deleteAllForUser(userId);
498
+ async deleteAllPasswordResetTokensForUser(uid: string): Promise<void> {
499
+ await this.passwordResetTokenService.deleteAllForUser(uid);
500
500
  }
501
501
 
502
502
  async deleteExpiredTokens(): Promise<void> {
@@ -505,17 +505,17 @@ export class MongoTokenRepository implements TokenRepository {
505
505
 
506
506
  // Magic link token operations
507
507
 
508
- async createMagicLinkToken(userId: string, tokenHash: string, expiresAt: Date): Promise<void> {
508
+ async createMagicLinkToken(uid: string, tokenHash: string, expiresAt: Date): Promise<void> {
509
509
  const col = this.db.collection("magic_link_tokens");
510
- await col.deleteMany({ userId, usedAt: null });
511
- await col.insertOne({ userId, tokenHash, expiresAt, usedAt: null, createdAt: new Date() });
510
+ await col.deleteMany({ uid, usedAt: null });
511
+ await col.insertOne({ uid, tokenHash, expiresAt, usedAt: null, createdAt: new Date() });
512
512
  }
513
513
 
514
514
  async findValidMagicLinkToken(tokenHash: string): Promise<MagicLinkTokenInfo | null> {
515
515
  const col = this.db.collection("magic_link_tokens");
516
516
  const doc = await col.findOne({ tokenHash, usedAt: null, expiresAt: { $gt: new Date() } });
517
517
  if (!doc) return null;
518
- return { userId: doc.userId as string, expiresAt: doc.expiresAt as Date };
518
+ return { uid: doc.uid as string, expiresAt: doc.expiresAt as Date };
519
519
  }
520
520
 
521
521
  async markMagicLinkTokenUsed(tokenHash: string): Promise<void> {
@@ -551,12 +551,12 @@ export class MongoAuthRepository implements AuthRepository {
551
551
  return this.userService.getUserByIdentity(provider, providerId);
552
552
  }
553
553
 
554
- async getUserIdentities(userId: string): Promise<UserIdentityData[]> {
555
- return this.userService.getUserIdentities(userId);
554
+ async getUserIdentities(uid: string): Promise<UserIdentityData[]> {
555
+ return this.userService.getUserIdentities(uid);
556
556
  }
557
557
 
558
- async linkUserIdentity(userId: string, provider: string, providerId: string, profileData?: Record<string, unknown>): Promise<void> {
559
- return this.userService.linkUserIdentity(userId, provider, providerId, profileData);
558
+ async linkUserIdentity(uid: string, provider: string, providerId: string, profileData?: Record<string, unknown>): Promise<void> {
559
+ return this.userService.linkUserIdentity(uid, provider, providerId, profileData);
560
560
  }
561
561
 
562
562
  async updateUser(id: string, data: Partial<Omit<CreateUserData, "id">>): Promise<UserData | null> {
@@ -591,24 +591,24 @@ export class MongoAuthRepository implements AuthRepository {
591
591
  return this.userService.getUserByVerificationToken(token);
592
592
  }
593
593
 
594
- async getUserRoles(userId: string): Promise<RoleData[]> {
595
- return this.userService.getUserRoles(userId);
594
+ async getUserRoles(uid: string): Promise<RoleData[]> {
595
+ return this.userService.getUserRoles(uid);
596
596
  }
597
597
 
598
- async getUserRoleIds(userId: string): Promise<string[]> {
599
- return this.userService.getUserRoleIds(userId);
598
+ async getUserRoleIds(uid: string): Promise<string[]> {
599
+ return this.userService.getUserRoleIds(uid);
600
600
  }
601
601
 
602
- async setUserRoles(userId: string, roleIds: string[]): Promise<void> {
603
- await this.userService.setUserRoles(userId, roleIds);
602
+ async setUserRoles(uid: string, roleIds: string[]): Promise<void> {
603
+ await this.userService.setUserRoles(uid, roleIds);
604
604
  }
605
605
 
606
- async assignDefaultRole(userId: string, roleId: string): Promise<void> {
607
- await this.userService.assignDefaultRole(userId, roleId);
606
+ async assignDefaultRole(uid: string, roleId: string): Promise<void> {
607
+ await this.userService.assignDefaultRole(uid, roleId);
608
608
  }
609
609
 
610
- async getUserWithRoles(userId: string): Promise<{ user: UserData; roles: RoleData[] } | null> {
611
- return this.userService.getUserWithRoles(userId);
610
+ async getUserWithRoles(uid: string): Promise<{ user: UserData; roles: RoleData[] } | null> {
611
+ return this.userService.getUserWithRoles(uid);
612
612
  }
613
613
 
614
614
  async getRoleById(id: string): Promise<RoleData | null> {
@@ -631,8 +631,8 @@ export class MongoAuthRepository implements AuthRepository {
631
631
  await this.roleService.deleteRole(id);
632
632
  }
633
633
 
634
- async createRefreshToken(userId: string, tokenHash: string, expiresAt: Date, userAgent?: string, ipAddress?: string): Promise<void> {
635
- await this.tokenRepository.createRefreshToken(userId, tokenHash, expiresAt, userAgent, ipAddress);
634
+ async createRefreshToken(uid: string, tokenHash: string, expiresAt: Date, userAgent?: string, ipAddress?: string): Promise<void> {
635
+ await this.tokenRepository.createRefreshToken(uid, tokenHash, expiresAt, userAgent, ipAddress);
636
636
  }
637
637
 
638
638
  async findRefreshTokenByHash(tokenHash: string): Promise<RefreshTokenInfo | null> {
@@ -643,20 +643,20 @@ export class MongoAuthRepository implements AuthRepository {
643
643
  await this.tokenRepository.deleteRefreshToken(tokenHash);
644
644
  }
645
645
 
646
- async deleteAllRefreshTokensForUser(userId: string): Promise<void> {
647
- await this.tokenRepository.deleteAllRefreshTokensForUser(userId);
646
+ async deleteAllRefreshTokensForUser(uid: string): Promise<void> {
647
+ await this.tokenRepository.deleteAllRefreshTokensForUser(uid);
648
648
  }
649
649
 
650
- async listRefreshTokensForUser(userId: string): Promise<RefreshTokenInfo[]> {
651
- return this.tokenRepository.listRefreshTokensForUser(userId);
650
+ async listRefreshTokensForUser(uid: string): Promise<RefreshTokenInfo[]> {
651
+ return this.tokenRepository.listRefreshTokensForUser(uid);
652
652
  }
653
653
 
654
- async deleteRefreshTokenById(id: string, userId: string): Promise<void> {
655
- await this.tokenRepository.deleteRefreshTokenById(id, userId);
654
+ async deleteRefreshTokenById(id: string, uid: string): Promise<void> {
655
+ await this.tokenRepository.deleteRefreshTokenById(id, uid);
656
656
  }
657
657
 
658
- async createPasswordResetToken(userId: string, tokenHash: string, expiresAt: Date): Promise<void> {
659
- await this.tokenRepository.createPasswordResetToken(userId, tokenHash, expiresAt);
658
+ async createPasswordResetToken(uid: string, tokenHash: string, expiresAt: Date): Promise<void> {
659
+ await this.tokenRepository.createPasswordResetToken(uid, tokenHash, expiresAt);
660
660
  }
661
661
 
662
662
  async findValidPasswordResetToken(tokenHash: string): Promise<PasswordResetTokenInfo | null> {
@@ -667,8 +667,8 @@ export class MongoAuthRepository implements AuthRepository {
667
667
  await this.tokenRepository.markPasswordResetTokenUsed(tokenHash);
668
668
  }
669
669
 
670
- async deleteAllPasswordResetTokensForUser(userId: string): Promise<void> {
671
- await this.tokenRepository.deleteAllPasswordResetTokensForUser(userId);
670
+ async deleteAllPasswordResetTokensForUser(uid: string): Promise<void> {
671
+ await this.tokenRepository.deleteAllPasswordResetTokensForUser(uid);
672
672
  }
673
673
 
674
674
  async deleteExpiredTokens(): Promise<void> {
@@ -677,8 +677,8 @@ export class MongoAuthRepository implements AuthRepository {
677
677
 
678
678
  // Magic link token operations
679
679
 
680
- async createMagicLinkToken(userId: string, tokenHash: string, expiresAt: Date): Promise<void> {
681
- await this.tokenRepository.createMagicLinkToken(userId, tokenHash, expiresAt);
680
+ async createMagicLinkToken(uid: string, tokenHash: string, expiresAt: Date): Promise<void> {
681
+ await this.tokenRepository.createMagicLinkToken(uid, tokenHash, expiresAt);
682
682
  }
683
683
 
684
684
  async findValidMagicLinkToken(tokenHash: string): Promise<MagicLinkTokenInfo | null> {
@@ -690,10 +690,10 @@ export class MongoAuthRepository implements AuthRepository {
690
690
  }
691
691
 
692
692
  // MFA Repository Stub
693
- async createMfaFactor(userId: string, factorType: "totp", secretEncrypted: string, friendlyName?: string): Promise<MfaFactor> {
693
+ async createMfaFactor(uid: string, factorType: "totp", secretEncrypted: string, friendlyName?: string): Promise<MfaFactor> {
694
694
  throw new Error("MFA is not implemented for MongoDB");
695
695
  }
696
- async getMfaFactors(userId: string): Promise<MfaFactor[]> {
696
+ async getMfaFactors(uid: string): Promise<MfaFactor[]> {
697
697
  return [];
698
698
  }
699
699
  async getMfaFactorById(factorId: string): Promise<(MfaFactor & { secretEncrypted: string }) | null> {
@@ -702,7 +702,7 @@ export class MongoAuthRepository implements AuthRepository {
702
702
  async verifyMfaFactor(factorId: string): Promise<void> {
703
703
  throw new Error("MFA is not implemented for MongoDB");
704
704
  }
705
- async deleteMfaFactor(factorId: string, userId: string): Promise<void> {
705
+ async deleteMfaFactor(factorId: string, uid: string): Promise<void> {
706
706
  throw new Error("MFA is not implemented for MongoDB");
707
707
  }
708
708
  async createMfaChallenge(factorId: string, ipAddress?: string): Promise<MfaChallengeInfo> {
@@ -714,19 +714,19 @@ export class MongoAuthRepository implements AuthRepository {
714
714
  async verifyMfaChallenge(challengeId: string): Promise<void> {
715
715
  throw new Error("MFA is not implemented for MongoDB");
716
716
  }
717
- async createRecoveryCodes(userId: string, codeHashes: string[]): Promise<void> {
717
+ async createRecoveryCodes(uid: string, codeHashes: string[]): Promise<void> {
718
718
  throw new Error("MFA is not implemented for MongoDB");
719
719
  }
720
- async useRecoveryCode(userId: string, codeHash: string): Promise<boolean> {
720
+ async useRecoveryCode(uid: string, codeHash: string): Promise<boolean> {
721
721
  return false;
722
722
  }
723
- async getUnusedRecoveryCodeCount(userId: string): Promise<number> {
723
+ async getUnusedRecoveryCodeCount(uid: string): Promise<number> {
724
724
  return 0;
725
725
  }
726
- async deleteAllRecoveryCodes(userId: string): Promise<void> {
726
+ async deleteAllRecoveryCodes(uid: string): Promise<void> {
727
727
  // No-op
728
728
  }
729
- async hasVerifiedMfaFactors(userId: string): Promise<boolean> {
729
+ async hasVerifiedMfaFactors(uid: string): Promise<boolean> {
730
730
  return false;
731
731
  }
732
732
  }
@@ -781,7 +781,7 @@ export class AuthenticatedMongoDriver implements DataDriver {
781
781
 
782
782
  listenCollection<M extends Record<string, any>>(props: ListenCollectionProps<M>): () => void {
783
783
  const unsubscribe = this.delegate.listenCollection(props);
784
- const authContext = { userId: this.user.uid,
784
+ const authContext = { uid: this.user.uid,
785
785
  roles: this.user.roles ?? [] };
786
786
  const subscriptions = this.delegate.getRealtimeService().getSubscriptions();
787
787
  const lastEntry = Array.from(subscriptions.entries()).pop();
@@ -806,7 +806,7 @@ roles: this.user.roles ?? [] };
806
806
 
807
807
  listenOne<M extends Record<string, any>>(props: ListenOneProps<M>): () => void {
808
808
  const unsubscribe = this.delegate.listenOne(props);
809
- const authContext = { userId: this.user.uid,
809
+ const authContext = { uid: this.user.uid,
810
810
  roles: this.user.roles ?? [] };
811
811
  const subscriptions = this.delegate.getRealtimeService().getSubscriptions();
812
812
  const lastEntry = Array.from(subscriptions.entries()).pop();