@rebasepro/server-core 0.2.4 → 0.2.5

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.
@@ -1,12 +1,9 @@
1
- import { PostgresCollection } from "@rebasepro/types";
1
+ import type { PostgresCollection } from "@rebasepro/types";
2
2
  /**
3
- * Default users collection definition.
3
+ * Default users collection.
4
4
  *
5
- * Shared between the admin UI (for navigation/display) and the backend
6
- * (for schema generation). Both consumers prepend this to the developer's
7
- * collections array and rely on generic slug-based deduplication
8
- * (Map keyed by slug, last-write-wins) so that developer-defined
9
- * collections with the same slug override this default — no hardcoded
10
- * string checks required.
5
+ * Prepended to the developer's collections array by the admin and server.
6
+ * Slug-based dedup (Map keyed by slug, last-write-wins) lets developers
7
+ * override by defining their own collection with `slug: "users"`.
11
8
  */
12
9
  export declare const defaultUsersCollection: PostgresCollection;
package/dist/index.es.js CHANGED
@@ -2547,6 +2547,142 @@ class CollectionRegistry {
2547
2547
  };
2548
2548
  }
2549
2549
  }
2550
+ const defaultUsersCollection = {
2551
+ name: "Users",
2552
+ singularName: "User",
2553
+ slug: "users",
2554
+ table: "users",
2555
+ schema: "rebase",
2556
+ icon: "Users",
2557
+ group: "Settings",
2558
+ openEntityMode: "dialog",
2559
+ disableDefaultActions: ["copy"],
2560
+ sort: ["createdAt", "desc"],
2561
+ properties: {
2562
+ id: {
2563
+ name: "ID",
2564
+ type: "string",
2565
+ isId: "uuid",
2566
+ ui: {
2567
+ readOnly: true
2568
+ }
2569
+ },
2570
+ email: {
2571
+ name: "Email",
2572
+ type: "string",
2573
+ validation: {
2574
+ required: true,
2575
+ unique: true
2576
+ }
2577
+ },
2578
+ displayName: {
2579
+ name: "Name",
2580
+ type: "string",
2581
+ columnName: "display_name",
2582
+ validation: {
2583
+ required: true
2584
+ }
2585
+ },
2586
+ photoURL: {
2587
+ name: "Photo URL",
2588
+ type: "string",
2589
+ columnName: "photo_url",
2590
+ url: "image"
2591
+ },
2592
+ roles: {
2593
+ name: "Roles",
2594
+ type: "array",
2595
+ columnType: "text[]",
2596
+ of: {
2597
+ name: "Role",
2598
+ type: "string",
2599
+ enum: {
2600
+ admin: "Admin",
2601
+ editor: "Editor",
2602
+ viewer: "Viewer"
2603
+ }
2604
+ }
2605
+ },
2606
+ passwordHash: {
2607
+ name: "Password Hash",
2608
+ type: "string",
2609
+ columnName: "password_hash",
2610
+ ui: {
2611
+ hideFromCollection: true,
2612
+ disabled: {
2613
+ hidden: true
2614
+ }
2615
+ }
2616
+ },
2617
+ emailVerified: {
2618
+ name: "Email Verified",
2619
+ type: "boolean",
2620
+ columnName: "email_verified",
2621
+ defaultValue: false,
2622
+ ui: {
2623
+ hideFromCollection: true,
2624
+ disabled: {
2625
+ hidden: true
2626
+ }
2627
+ }
2628
+ },
2629
+ emailVerificationToken: {
2630
+ name: "Email Verification Token",
2631
+ type: "string",
2632
+ columnName: "email_verification_token",
2633
+ ui: {
2634
+ hideFromCollection: true,
2635
+ disabled: {
2636
+ hidden: true
2637
+ }
2638
+ }
2639
+ },
2640
+ emailVerificationSentAt: {
2641
+ name: "Email Verification Sent At",
2642
+ type: "date",
2643
+ columnName: "email_verification_sent_at",
2644
+ ui: {
2645
+ hideFromCollection: true,
2646
+ disabled: {
2647
+ hidden: true
2648
+ }
2649
+ }
2650
+ },
2651
+ metadata: {
2652
+ name: "Metadata",
2653
+ type: "map",
2654
+ defaultValue: {},
2655
+ ui: {
2656
+ hideFromCollection: true,
2657
+ disabled: {
2658
+ hidden: true
2659
+ }
2660
+ }
2661
+ },
2662
+ createdAt: {
2663
+ name: "Created At",
2664
+ type: "date",
2665
+ columnName: "created_at",
2666
+ ui: {
2667
+ readOnly: true
2668
+ }
2669
+ },
2670
+ updatedAt: {
2671
+ name: "Updated At",
2672
+ type: "date",
2673
+ columnName: "updated_at",
2674
+ autoValue: "on_update",
2675
+ ui: {
2676
+ hideFromCollection: true,
2677
+ disabled: {
2678
+ hidden: true
2679
+ }
2680
+ }
2681
+ }
2682
+ },
2683
+ listProperties: ["displayName", "email", "roles", "createdAt"],
2684
+ propertiesOrder: ["id", "email", "displayName", "roles", "createdAt"]
2685
+ };
2550
2686
  function mapOperator$1(op) {
2551
2687
  switch (op) {
2552
2688
  case "==":
@@ -13035,11 +13171,6 @@ function createAdminRoutes(config) {
13035
13171
  const results = await Promise.all(users.map((u) => applyUserAfterRead(u, ctx)));
13036
13172
  return results.filter((u) => u !== null);
13037
13173
  }
13038
- async function applyRoleAfterReadBatch(roles, ctx) {
13039
- if (!hooks?.roles?.afterRead) return roles;
13040
- const results = await Promise.all(roles.map((r) => hooks.roles.afterRead(r, ctx)));
13041
- return results.filter((r) => r !== null);
13042
- }
13043
13174
  function toAdminUser(u, roles) {
13044
13175
  return {
13045
13176
  uid: u.id,
@@ -13398,90 +13529,6 @@ function createAdminRoutes(config) {
13398
13529
  success: true
13399
13530
  });
13400
13531
  });
13401
- router.get("/roles", requireAdmin, async (c) => {
13402
- const roles = await authRepo.listRoles();
13403
- const hookCtx = buildHookContext(c, "GET");
13404
- let adminRoles = roles.map((r) => ({
13405
- id: r.id,
13406
- name: r.name,
13407
- isAdmin: r.isAdmin,
13408
- defaultPermissions: r.defaultPermissions
13409
- }));
13410
- adminRoles = await applyRoleAfterReadBatch(adminRoles, hookCtx);
13411
- return c.json({
13412
- roles: adminRoles
13413
- });
13414
- });
13415
- router.get("/roles/:roleId", requireAdmin, async (c) => {
13416
- const roleId = c.req.param("roleId");
13417
- const role = await authRepo.getRoleById(roleId);
13418
- if (!role) {
13419
- throw ApiError.notFound("Role not found");
13420
- }
13421
- return c.json({
13422
- role
13423
- });
13424
- });
13425
- router.post("/roles", requireAdmin, async (c) => {
13426
- const body = await c.req.json();
13427
- const {
13428
- id,
13429
- name: name2,
13430
- isAdmin,
13431
- defaultPermissions
13432
- } = body;
13433
- if (!id || !name2) {
13434
- throw ApiError.badRequest("Role ID and name are required", "INVALID_INPUT");
13435
- }
13436
- const existing = await authRepo.getRoleById(id);
13437
- if (existing) {
13438
- throw ApiError.conflict("Role already exists", "ROLE_EXISTS");
13439
- }
13440
- const role = await authRepo.createRole({
13441
- id,
13442
- name: name2,
13443
- isAdmin: isAdmin ?? false,
13444
- defaultPermissions: defaultPermissions ?? null
13445
- });
13446
- return c.json({
13447
- role
13448
- }, 201);
13449
- });
13450
- router.put("/roles/:roleId", requireAdmin, async (c) => {
13451
- const roleId = c.req.param("roleId");
13452
- const body = await c.req.json();
13453
- const {
13454
- name: name2,
13455
- isAdmin,
13456
- defaultPermissions
13457
- } = body;
13458
- const existing = await authRepo.getRoleById(roleId);
13459
- if (!existing) {
13460
- throw ApiError.notFound("Role not found");
13461
- }
13462
- const role = await authRepo.updateRole(roleId, {
13463
- name: name2,
13464
- isAdmin,
13465
- defaultPermissions
13466
- });
13467
- return c.json({
13468
- role
13469
- });
13470
- });
13471
- router.delete("/roles/:roleId", requireAdmin, async (c) => {
13472
- const roleId = c.req.param("roleId");
13473
- if (["admin", "editor", "viewer"].includes(roleId)) {
13474
- throw ApiError.badRequest("Cannot delete built-in roles", "BUILTIN_ROLE");
13475
- }
13476
- const existing = await authRepo.getRoleById(roleId);
13477
- if (!existing) {
13478
- throw ApiError.notFound("Role not found");
13479
- }
13480
- await authRepo.deleteRole(roleId);
13481
- return c.json({
13482
- success: true
13483
- });
13484
- });
13485
13532
  return router;
13486
13533
  }
13487
13534
  function createBuiltinAuthAdapter(config) {
@@ -13525,8 +13572,7 @@ function createBuiltinAuthAdapter(config) {
13525
13572
  const extendedPayload = payload;
13526
13573
  let roles = payload.roles || [];
13527
13574
  try {
13528
- const userRoles = await authRepository.getUserRoles(payload.userId);
13529
- roles = userRoles.map((r) => r.id);
13575
+ roles = await authRepository.getUserRoleIds(payload.userId);
13530
13576
  } catch {
13531
13577
  }
13532
13578
  const isAdmin = roles.some((r) => r === "admin" || r === "schema-admin");
@@ -13556,8 +13602,7 @@ function createBuiltinAuthAdapter(config) {
13556
13602
  const extendedPayload = payload;
13557
13603
  let roles = payload.roles || [];
13558
13604
  try {
13559
- const userRoles = await authRepository.getUserRoles(payload.userId);
13560
- roles = userRoles.map((r) => r.id);
13605
+ roles = await authRepository.getUserRoleIds(payload.userId);
13561
13606
  } catch {
13562
13607
  }
13563
13608
  const isAdmin = roles.some((r) => r === "admin" || r === "schema-admin");
@@ -13571,7 +13616,6 @@ function createBuiltinAuthAdapter(config) {
13571
13616
  };
13572
13617
  },
13573
13618
  userManagement: createUserManagementFromRepo(authRepository, resolvedOps, authHooks),
13574
- roleManagement: createRoleManagementFromRepo(authRepository),
13575
13619
  createAuthRoutes() {
13576
13620
  return createAuthRoutes({
13577
13621
  authRepo: authRepository,
@@ -13687,43 +13731,13 @@ function createUserManagementFromRepo(repo, resolvedOps, authHooks) {
13687
13731
  }
13688
13732
  },
13689
13733
  async getUserRoles(userId) {
13690
- const roles = await repo.getUserRoles(userId);
13691
- return roles.map(toAuthRoleData);
13734
+ return repo.getUserRoleIds(userId);
13692
13735
  },
13693
13736
  async setUserRoles(userId, roleIds) {
13694
13737
  await repo.setUserRoles(userId, roleIds);
13695
13738
  }
13696
13739
  };
13697
13740
  }
13698
- function createRoleManagementFromRepo(repo) {
13699
- return {
13700
- async listRoles() {
13701
- const roles = await repo.listRoles();
13702
- return roles.map(toAuthRoleData);
13703
- },
13704
- async getRoleById(id) {
13705
- const role = await repo.getRoleById(id);
13706
- return role ? toAuthRoleData(role) : null;
13707
- },
13708
- async createRole(data) {
13709
- const role = await repo.createRole({
13710
- id: data.id,
13711
- name: data.name,
13712
- isAdmin: data.isAdmin,
13713
- defaultPermissions: data.defaultPermissions,
13714
- collectionPermissions: data.collectionPermissions
13715
- });
13716
- return toAuthRoleData(role);
13717
- },
13718
- async updateRole(id, data) {
13719
- const role = await repo.updateRole(id, data);
13720
- return role ? toAuthRoleData(role) : null;
13721
- },
13722
- async deleteRole(id) {
13723
- await repo.deleteRole(id);
13724
- }
13725
- };
13726
- }
13727
13741
  function toAuthUserData(user) {
13728
13742
  return {
13729
13743
  id: user.id,
@@ -13736,15 +13750,6 @@ function toAuthUserData(user) {
13736
13750
  updatedAt: user.updatedAt
13737
13751
  };
13738
13752
  }
13739
- function toAuthRoleData(role) {
13740
- return {
13741
- id: role.id,
13742
- name: role.name,
13743
- isAdmin: role.isAdmin,
13744
- defaultPermissions: role.defaultPermissions,
13745
- collectionPermissions: role.collectionPermissions
13746
- };
13747
- }
13748
13753
  function configureLogLevel(logLevel) {
13749
13754
  const LOG_LEVEL = logLevel || process.env.LOG_LEVEL || "info";
13750
13755
  const logLevels = {
@@ -24927,7 +24932,6 @@ function createCustomAuthAdapter(options2) {
24927
24932
  verifyRequest: options2.verifyRequest,
24928
24933
  verifyToken: resolvedVerifyToken,
24929
24934
  userManagement: options2.userManagement,
24930
- roleManagement: options2.roleManagement,
24931
24935
  getCapabilities() {
24932
24936
  return defaultCapabilities;
24933
24937
  }
@@ -26927,33 +26931,6 @@ function createAdmin(transport, options2) {
26927
26931
  method: "DELETE"
26928
26932
  });
26929
26933
  }
26930
- async function listRoles() {
26931
- return transport.request(adminPath + "/roles", {
26932
- method: "GET"
26933
- });
26934
- }
26935
- async function getRole(roleId) {
26936
- return transport.request(adminPath + "/roles/" + encodeURIComponent(roleId), {
26937
- method: "GET"
26938
- });
26939
- }
26940
- async function createRole(data) {
26941
- return transport.request(adminPath + "/roles", {
26942
- method: "POST",
26943
- body: JSON.stringify(data)
26944
- });
26945
- }
26946
- async function updateRole(roleId, data) {
26947
- return transport.request(adminPath + "/roles/" + encodeURIComponent(roleId), {
26948
- method: "PUT",
26949
- body: JSON.stringify(data)
26950
- });
26951
- }
26952
- async function deleteRole(roleId) {
26953
- return transport.request(adminPath + "/roles/" + encodeURIComponent(roleId), {
26954
- method: "DELETE"
26955
- });
26956
- }
26957
26934
  async function bootstrap() {
26958
26935
  return transport.request(adminPath + "/bootstrap", {
26959
26936
  method: "POST"
@@ -26966,11 +26943,6 @@ function createAdmin(transport, options2) {
26966
26943
  createUser,
26967
26944
  updateUser,
26968
26945
  deleteUser,
26969
- listRoles,
26970
- getRole,
26971
- createRole,
26972
- updateRole,
26973
- deleteRole,
26974
26946
  bootstrap
26975
26947
  };
26976
26948
  }
@@ -38515,6 +38487,9 @@ async function _initializeRebaseBackend(config) {
38515
38487
  dir: config.collectionsDir
38516
38488
  });
38517
38489
  }
38490
+ if (config.auth) {
38491
+ activeCollections = Array.from(new Map([defaultUsersCollection, ...activeCollections].map((c) => [c.slug, c])).values());
38492
+ }
38518
38493
  const realtimeServices = {};
38519
38494
  const delegates = {};
38520
38495
  let bootstrappers = config.bootstrappers || [];
@@ -38583,8 +38558,7 @@ async function _initializeRebaseBackend(config) {
38583
38558
  id: authAdapter.id
38584
38559
  });
38585
38560
  authConfigResult = {
38586
- userService: authAdapter.userManagement ?? {},
38587
- roleService: authAdapter.roleManagement ?? {}
38561
+ userService: authAdapter.userManagement ?? {}
38588
38562
  };
38589
38563
  } else {
38590
38564
  const safeAuthConfig = config.auth;
@@ -38930,6 +38904,13 @@ async function _initializeRebaseBackend(config) {
38930
38904
  configured: emailService.isConfigured()
38931
38905
  });
38932
38906
  }
38907
+ const driverAdmin = defaultBootstrapper.getAdmin?.(defaultDriverResult);
38908
+ if (isSQLAdmin(driverAdmin)) {
38909
+ Object.assign(serverClient, {
38910
+ sql: (query, options2) => driverAdmin.executeSql(query, options2)
38911
+ });
38912
+ logger.info("SQL capability attached to singleton");
38913
+ }
38933
38914
  _initRebase(serverClient);
38934
38915
  logger.info("Rebase singleton initialized");
38935
38916
  if (defaultDriverResult.internals) {