@rebasepro/server-postgresql 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.
Files changed (37) hide show
  1. package/dist/common/src/collections/default-collections.d.ts +5 -8
  2. package/dist/index.es.js +286 -365
  3. package/dist/index.es.js.map +1 -1
  4. package/dist/index.umd.js +283 -362
  5. package/dist/index.umd.js.map +1 -1
  6. package/dist/server-postgresql/src/PostgresBackendDriver.d.ts +2 -0
  7. package/dist/server-postgresql/src/auth/services.d.ts +6 -31
  8. package/dist/server-postgresql/src/schema/auth-schema.d.ts +87 -340
  9. package/dist/server-postgresql/src/services/EntityPersistService.d.ts +4 -0
  10. package/dist/server-postgresql/src/services/entityService.d.ts +4 -0
  11. package/dist/types/src/controllers/auth.d.ts +2 -2
  12. package/dist/types/src/controllers/client.d.ts +25 -40
  13. package/dist/types/src/controllers/data.d.ts +4 -0
  14. package/dist/types/src/controllers/data_driver.d.ts +5 -0
  15. package/dist/types/src/types/auth_adapter.d.ts +3 -56
  16. package/dist/types/src/types/backend.d.ts +2 -2
  17. package/dist/types/src/types/backend_hooks.d.ts +2 -17
  18. package/dist/types/src/types/properties.d.ts +7 -5
  19. package/dist/types/src/types/user_management_delegate.d.ts +16 -53
  20. package/dist/types/src/users/index.d.ts +0 -1
  21. package/dist/types/src/users/user.d.ts +0 -1
  22. package/package.json +6 -6
  23. package/src/PostgresBackendDriver.ts +10 -0
  24. package/src/PostgresBootstrapper.ts +3 -12
  25. package/src/auth/ensure-tables.ts +52 -101
  26. package/src/auth/services.ts +71 -170
  27. package/src/schema/auth-schema.ts +13 -69
  28. package/src/schema/doctor.ts +44 -3
  29. package/src/schema/generate-drizzle-schema-logic.ts +33 -3
  30. package/src/schema/introspect-db-logic.ts +7 -0
  31. package/src/services/EntityPersistService.ts +9 -0
  32. package/src/services/entityService.ts +7 -0
  33. package/test/auth-services.test.ts +7 -150
  34. package/test/doctor.test.ts +6 -2
  35. package/dist/server-postgresql/src/schema/default-collections.d.ts +0 -2
  36. package/dist/types/src/users/roles.d.ts +0 -14
  37. package/src/schema/default-collections.ts +0 -69
package/dist/index.es.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { Pool, Client } from "pg";
2
2
  import { drizzle } from "drizzle-orm/node-postgres";
3
3
  import { sql, inArray, eq, and, or, ilike, asc, desc, gt, lt, getTableName as getTableName$1, count, relations, isTable } from "drizzle-orm";
4
- import { PgVarchar, PgText, PgChar, pgSchema, pgTable, timestamp, jsonb, boolean, varchar, uuid, primaryKey, unique, getTableConfig } from "drizzle-orm/pg-core";
4
+ import { PgVarchar, PgText, PgChar, pgSchema, pgTable, timestamp, jsonb, text, boolean, varchar, uuid, unique, getTableConfig } from "drizzle-orm/pg-core";
5
5
  import { createHash, randomUUID } from "crypto";
6
6
  import * as fs from "fs";
7
7
  import { promises } from "fs";
@@ -2719,11 +2719,17 @@ const defaultUsersCollection = {
2719
2719
  schema: "rebase",
2720
2720
  icon: "Users",
2721
2721
  group: "Settings",
2722
+ openEntityMode: "dialog",
2723
+ disableDefaultActions: ["copy"],
2724
+ sort: ["createdAt", "desc"],
2722
2725
  properties: {
2723
2726
  id: {
2724
2727
  name: "ID",
2725
2728
  type: "string",
2726
- isId: "uuid"
2729
+ isId: "uuid",
2730
+ ui: {
2731
+ readOnly: true
2732
+ }
2727
2733
  },
2728
2734
  email: {
2729
2735
  name: "Email",
@@ -2733,38 +2739,77 @@ const defaultUsersCollection = {
2733
2739
  unique: true
2734
2740
  }
2735
2741
  },
2736
- password_hash: {
2737
- name: "Password Hash",
2742
+ displayName: {
2743
+ name: "Name",
2738
2744
  type: "string",
2739
- ui: {
2740
- hideFromCollection: true
2745
+ columnName: "display_name",
2746
+ validation: {
2747
+ required: true
2741
2748
  }
2742
2749
  },
2743
- display_name: {
2744
- name: "Display Name",
2745
- type: "string"
2746
- },
2747
- photo_url: {
2750
+ photoURL: {
2748
2751
  name: "Photo URL",
2749
- type: "string"
2752
+ type: "string",
2753
+ columnName: "photo_url",
2754
+ url: "image"
2750
2755
  },
2751
- email_verified: {
2756
+ roles: {
2757
+ name: "Roles",
2758
+ type: "array",
2759
+ columnType: "text[]",
2760
+ of: {
2761
+ name: "Role",
2762
+ type: "string",
2763
+ enum: {
2764
+ admin: "Admin",
2765
+ editor: "Editor",
2766
+ viewer: "Viewer"
2767
+ }
2768
+ }
2769
+ },
2770
+ passwordHash: {
2771
+ name: "Password Hash",
2772
+ type: "string",
2773
+ columnName: "password_hash",
2774
+ ui: {
2775
+ hideFromCollection: true,
2776
+ disabled: {
2777
+ hidden: true
2778
+ }
2779
+ }
2780
+ },
2781
+ emailVerified: {
2752
2782
  name: "Email Verified",
2753
2783
  type: "boolean",
2754
- defaultValue: false
2784
+ columnName: "email_verified",
2785
+ defaultValue: false,
2786
+ ui: {
2787
+ hideFromCollection: true,
2788
+ disabled: {
2789
+ hidden: true
2790
+ }
2791
+ }
2755
2792
  },
2756
- email_verification_token: {
2793
+ emailVerificationToken: {
2757
2794
  name: "Email Verification Token",
2758
2795
  type: "string",
2796
+ columnName: "email_verification_token",
2759
2797
  ui: {
2760
- hideFromCollection: true
2798
+ hideFromCollection: true,
2799
+ disabled: {
2800
+ hidden: true
2801
+ }
2761
2802
  }
2762
2803
  },
2763
- email_verification_sent_at: {
2804
+ emailVerificationSentAt: {
2764
2805
  name: "Email Verification Sent At",
2765
2806
  type: "date",
2807
+ columnName: "email_verification_sent_at",
2766
2808
  ui: {
2767
- hideFromCollection: true
2809
+ hideFromCollection: true,
2810
+ disabled: {
2811
+ hidden: true
2812
+ }
2768
2813
  }
2769
2814
  },
2770
2815
  metadata: {
@@ -2772,28 +2817,35 @@ const defaultUsersCollection = {
2772
2817
  type: "map",
2773
2818
  defaultValue: {},
2774
2819
  ui: {
2775
- hideFromCollection: true
2820
+ hideFromCollection: true,
2821
+ disabled: {
2822
+ hidden: true
2823
+ }
2776
2824
  }
2777
2825
  },
2778
- created_at: {
2826
+ createdAt: {
2779
2827
  name: "Created At",
2780
2828
  type: "date",
2781
- autoValue: "on_create",
2829
+ columnName: "created_at",
2782
2830
  ui: {
2783
- readOnly: true,
2784
- hideFromCollection: true
2831
+ readOnly: true
2785
2832
  }
2786
2833
  },
2787
- updated_at: {
2834
+ updatedAt: {
2788
2835
  name: "Updated At",
2789
2836
  type: "date",
2837
+ columnName: "updated_at",
2790
2838
  autoValue: "on_update",
2791
2839
  ui: {
2792
- readOnly: true,
2793
- hideFromCollection: true
2840
+ hideFromCollection: true,
2841
+ disabled: {
2842
+ hidden: true
2843
+ }
2794
2844
  }
2795
2845
  }
2796
- }
2846
+ },
2847
+ listProperties: ["displayName", "email", "roles", "createdAt"],
2848
+ propertiesOrder: ["id", "email", "displayName", "roles", "createdAt"]
2797
2849
  };
2798
2850
  function mapOperator(op) {
2799
2851
  switch (op) {
@@ -3041,6 +3093,9 @@ function createDriverAccessor(driver, slug) {
3041
3093
  }
3042
3094
  });
3043
3095
  },
3096
+ deleteAll: driver.deleteAll ? async () => {
3097
+ return driver.deleteAll(slug);
3098
+ } : void 0,
3044
3099
  count: driver.countEntities ? async (params) => {
3045
3100
  return driver.countEntities({
3046
3101
  path: slug,
@@ -6305,6 +6360,14 @@ class EntityPersistService {
6305
6360
  const parsedId = parsedIdObj[idInfo.fieldName];
6306
6361
  await this.db.delete(table).where(eq(idField, parsedId));
6307
6362
  }
6363
+ /**
6364
+ * Delete all entities from a collection
6365
+ */
6366
+ async deleteAll(collectionPath, _databaseId) {
6367
+ const collection = getCollectionByPath(collectionPath, this.registry);
6368
+ const table = getTableForCollection(collection, this.registry);
6369
+ await this.db.delete(table);
6370
+ }
6308
6371
  /**
6309
6372
  * Save an entity (create or update)
6310
6373
  */
@@ -6636,6 +6699,12 @@ class EntityService {
6636
6699
  async deleteEntity(collectionPath, entityId, databaseId) {
6637
6700
  return this.persistService.deleteEntity(collectionPath, entityId, databaseId);
6638
6701
  }
6702
+ /**
6703
+ * Delete all entities from a collection
6704
+ */
6705
+ async deleteAll(collectionPath, databaseId) {
6706
+ return this.persistService.deleteAll(collectionPath, databaseId);
6707
+ }
6639
6708
  /**
6640
6709
  * Execute raw SQL
6641
6710
  */
@@ -7336,6 +7405,10 @@ class PostgresBackendDriver {
7336
7405
  await this.realtimeService.notifyEntityUpdate(entity.path, entity.id.toString(), null, entity.databaseId || resolvedCollection?.databaseId);
7337
7406
  }
7338
7407
  }
7408
+ async deleteAll(path2) {
7409
+ await this.entityService.deleteAll(path2);
7410
+ await this.realtimeService.notifyEntityUpdate(path2, "*", null);
7411
+ }
7339
7412
  async checkUniqueField(path2, name, value, entityId, collection) {
7340
7413
  return this.entityService.checkUniqueField(path2, name, value, entityId, collection?.databaseId);
7341
7414
  }
@@ -7605,11 +7678,11 @@ class AuthenticatedPostgresBackendDriver {
7605
7678
  console.warn("[DataDriver] User ID (uid) is missing for authenticated delegate. Using 'anonymous'. User object:", this.user);
7606
7679
  userId = "anonymous";
7607
7680
  }
7608
- const userRoles2 = this.user?.roles ?? [];
7681
+ const userRoles = this.user?.roles ?? [];
7609
7682
  if (!this.user?.roles) {
7610
7683
  console.warn("[DataDriver] User roles are missing for authenticated delegate. Using empty array. User object:", this.user);
7611
7684
  }
7612
- const normalizedRoles = userRoles2.map((r) => typeof r === "string" ? r : r?.id ?? String(r));
7685
+ const normalizedRoles = userRoles.map((r) => typeof r === "string" ? r : r?.id ?? String(r));
7613
7686
  const rolesString = normalizedRoles.join(",");
7614
7687
  await tx.execute(sql`
7615
7688
  SELECT
@@ -7617,7 +7690,7 @@ class AuthenticatedPostgresBackendDriver {
7617
7690
  set_config('app.user_roles', ${rolesString}, true),
7618
7691
  set_config('app.jwt', ${JSON.stringify({
7619
7692
  sub: userId,
7620
- roles: userRoles2
7693
+ roles: userRoles
7621
7694
  })}, true)
7622
7695
  `);
7623
7696
  const txEntityService = new EntityService(tx, this.delegate.registry);
@@ -7672,6 +7745,9 @@ class AuthenticatedPostgresBackendDriver {
7672
7745
  async deleteEntity(props) {
7673
7746
  return this.withTransaction((delegate) => delegate.deleteEntity(props));
7674
7747
  }
7748
+ async deleteAll(path2) {
7749
+ return this.delegate.deleteAll(path2);
7750
+ }
7675
7751
  async checkUniqueField(path2, name, value, entityId, collection) {
7676
7752
  return this.withTransaction((delegate) => delegate.checkUniqueField(path2, name, value, entityId, collection));
7677
7753
  }
@@ -7751,11 +7827,10 @@ class DatabasePoolManager {
7751
7827
  this.pools.clear();
7752
7828
  }
7753
7829
  }
7754
- function createAuthSchema(rolesSchemaName = "rebase", usersSchemaName = "rebase") {
7755
- const rolesSchema = rolesSchemaName === "public" ? null : pgSchema(rolesSchemaName);
7830
+ function createAuthSchema(usersSchemaName = "rebase") {
7756
7831
  const usersSchema2 = usersSchemaName === "public" ? null : pgSchema(usersSchemaName);
7757
- const rolesTableCreator = rolesSchema ? rolesSchema.table.bind(rolesSchema) : pgTable;
7758
- const usersTableCreator = usersSchema2 ? usersSchema2.table.bind(usersSchema2) : pgTable;
7832
+ const tableCreator = usersSchema2 ? usersSchema2.table.bind(usersSchema2) : pgTable;
7833
+ const usersTableCreator = tableCreator;
7759
7834
  const users2 = usersTableCreator("users", {
7760
7835
  id: uuid("id").defaultRandom().primaryKey(),
7761
7836
  email: varchar("email", {
@@ -7777,37 +7852,12 @@ function createAuthSchema(rolesSchemaName = "rebase", usersSchemaName = "rebase"
7777
7852
  }),
7778
7853
  emailVerificationSentAt: timestamp("email_verification_sent_at"),
7779
7854
  isAnonymous: boolean("is_anonymous").default(false).notNull(),
7855
+ roles: text("roles").array().default([]).notNull(),
7780
7856
  metadata: jsonb("metadata").$type().default({}).notNull(),
7781
7857
  createdAt: timestamp("created_at").defaultNow().notNull(),
7782
7858
  updatedAt: timestamp("updated_at").defaultNow().notNull()
7783
7859
  });
7784
- const roles2 = rolesTableCreator("roles", {
7785
- id: varchar("id", {
7786
- length: 50
7787
- }).primaryKey(),
7788
- // 'admin', 'editor', 'viewer'
7789
- name: varchar("name", {
7790
- length: 100
7791
- }).notNull(),
7792
- isAdmin: boolean("is_admin").default(false).notNull(),
7793
- defaultPermissions: jsonb("default_permissions").$type(),
7794
- collectionPermissions: jsonb("collection_permissions").$type()
7795
- });
7796
- const userRoles2 = rolesTableCreator("user_roles", {
7797
- userId: uuid("user_id").notNull().references(() => users2.id, {
7798
- onDelete: "cascade"
7799
- }),
7800
- roleId: varchar("role_id", {
7801
- length: 50
7802
- }).notNull().references(() => roles2.id, {
7803
- onDelete: "cascade"
7804
- })
7805
- }, (table) => ({
7806
- pk: primaryKey({
7807
- columns: [table.userId, table.roleId]
7808
- })
7809
- }));
7810
- const refreshTokens2 = rolesTableCreator("refresh_tokens", {
7860
+ const refreshTokens2 = tableCreator("refresh_tokens", {
7811
7861
  id: uuid("id").defaultRandom().primaryKey(),
7812
7862
  userId: uuid("user_id").notNull().references(() => users2.id, {
7813
7863
  onDelete: "cascade"
@@ -7826,7 +7876,7 @@ function createAuthSchema(rolesSchemaName = "rebase", usersSchemaName = "rebase"
7826
7876
  }, (table) => ({
7827
7877
  uniqueDeviceSession: unique("unique_device_session").on(table.userId, table.userAgent, table.ipAddress)
7828
7878
  }));
7829
- const passwordResetTokens2 = rolesTableCreator("password_reset_tokens", {
7879
+ const passwordResetTokens2 = tableCreator("password_reset_tokens", {
7830
7880
  id: uuid("id").defaultRandom().primaryKey(),
7831
7881
  userId: uuid("user_id").notNull().references(() => users2.id, {
7832
7882
  onDelete: "cascade"
@@ -7838,14 +7888,14 @@ function createAuthSchema(rolesSchemaName = "rebase", usersSchemaName = "rebase"
7838
7888
  usedAt: timestamp("used_at"),
7839
7889
  createdAt: timestamp("created_at").defaultNow().notNull()
7840
7890
  });
7841
- const appConfig2 = rolesTableCreator("app_config", {
7891
+ const appConfig2 = tableCreator("app_config", {
7842
7892
  key: varchar("key", {
7843
7893
  length: 100
7844
7894
  }).primaryKey(),
7845
7895
  value: jsonb("value").notNull(),
7846
7896
  updatedAt: timestamp("updated_at").defaultNow().notNull()
7847
7897
  });
7848
- const userIdentities2 = rolesTableCreator("user_identities", {
7898
+ const userIdentities2 = tableCreator("user_identities", {
7849
7899
  id: uuid("id").defaultRandom().primaryKey(),
7850
7900
  userId: uuid("user_id").notNull().references(() => users2.id, {
7851
7901
  onDelete: "cascade"
@@ -7863,7 +7913,7 @@ function createAuthSchema(rolesSchemaName = "rebase", usersSchemaName = "rebase"
7863
7913
  }, (table) => ({
7864
7914
  uniqueProviderId: unique("unique_provider_id").on(table.provider, table.providerId)
7865
7915
  }));
7866
- const mfaFactors2 = rolesTableCreator("mfa_factors", {
7916
+ const mfaFactors2 = tableCreator("mfa_factors", {
7867
7917
  id: uuid("id").defaultRandom().primaryKey(),
7868
7918
  userId: uuid("user_id").notNull().references(() => users2.id, {
7869
7919
  onDelete: "cascade"
@@ -7882,7 +7932,7 @@ function createAuthSchema(rolesSchemaName = "rebase", usersSchemaName = "rebase"
7882
7932
  createdAt: timestamp("created_at").defaultNow().notNull(),
7883
7933
  updatedAt: timestamp("updated_at").defaultNow().notNull()
7884
7934
  });
7885
- const mfaChallenges2 = rolesTableCreator("mfa_challenges", {
7935
+ const mfaChallenges2 = tableCreator("mfa_challenges", {
7886
7936
  id: uuid("id").defaultRandom().primaryKey(),
7887
7937
  factorId: uuid("factor_id").notNull().references(() => mfaFactors2.id, {
7888
7938
  onDelete: "cascade"
@@ -7894,7 +7944,7 @@ function createAuthSchema(rolesSchemaName = "rebase", usersSchemaName = "rebase"
7894
7944
  }),
7895
7945
  expiresAt: timestamp("expires_at").notNull()
7896
7946
  });
7897
- const recoveryCodes2 = rolesTableCreator("recovery_codes", {
7947
+ const recoveryCodes2 = tableCreator("recovery_codes", {
7898
7948
  id: uuid("id").defaultRandom().primaryKey(),
7899
7949
  userId: uuid("user_id").notNull().references(() => users2.id, {
7900
7950
  onDelete: "cascade"
@@ -7906,11 +7956,8 @@ function createAuthSchema(rolesSchemaName = "rebase", usersSchemaName = "rebase"
7906
7956
  createdAt: timestamp("created_at").defaultNow().notNull()
7907
7957
  });
7908
7958
  return {
7909
- rolesSchema,
7910
7959
  usersSchema: usersSchema2,
7911
7960
  users: users2,
7912
- roles: roles2,
7913
- userRoles: userRoles2,
7914
7961
  refreshTokens: refreshTokens2,
7915
7962
  passwordResetTokens: passwordResetTokens2,
7916
7963
  appConfig: appConfig2,
@@ -7920,12 +7967,9 @@ function createAuthSchema(rolesSchemaName = "rebase", usersSchemaName = "rebase"
7920
7967
  recoveryCodes: recoveryCodes2
7921
7968
  };
7922
7969
  }
7923
- const defaultAuthSchema = createAuthSchema("rebase", "rebase");
7924
- const rebaseSchema = defaultAuthSchema.rolesSchema;
7970
+ const defaultAuthSchema = createAuthSchema("rebase");
7925
7971
  const usersSchema = defaultAuthSchema.usersSchema;
7926
7972
  const users = defaultAuthSchema.users;
7927
- const roles = defaultAuthSchema.roles;
7928
- const userRoles = defaultAuthSchema.userRoles;
7929
7973
  const refreshTokens = defaultAuthSchema.refreshTokens;
7930
7974
  const passwordResetTokens = defaultAuthSchema.passwordResetTokens;
7931
7975
  const appConfig = defaultAuthSchema.appConfig;
@@ -7936,30 +7980,12 @@ const recoveryCodes = defaultAuthSchema.recoveryCodes;
7936
7980
  const usersRelations = relations(users, ({
7937
7981
  many
7938
7982
  }) => ({
7939
- userRoles: many(userRoles),
7940
7983
  refreshTokens: many(refreshTokens),
7941
7984
  passwordResetTokens: many(passwordResetTokens),
7942
7985
  userIdentities: many(userIdentities),
7943
7986
  mfaFactors: many(mfaFactors),
7944
7987
  recoveryCodes: many(recoveryCodes)
7945
7988
  }));
7946
- const rolesRelations = relations(roles, ({
7947
- many
7948
- }) => ({
7949
- userRoles: many(userRoles)
7950
- }));
7951
- const userRolesRelations = relations(userRoles, ({
7952
- one
7953
- }) => ({
7954
- user: one(users, {
7955
- fields: [userRoles.userId],
7956
- references: [users.id]
7957
- }),
7958
- role: one(roles, {
7959
- fields: [userRoles.roleId],
7960
- references: [roles.id]
7961
- })
7962
- }));
7963
7989
  const refreshTokensRelations = relations(refreshTokens, ({
7964
7990
  one
7965
7991
  }) => ({
@@ -8066,6 +8092,8 @@ const getDrizzleColumn = (propName, prop, collection, collections) => {
8066
8092
  columnDefinition = `${enumName}("${colName}")`;
8067
8093
  } else if ("isId" in stringProp && stringProp.isId === "uuid") {
8068
8094
  columnDefinition = `uuid("${colName}")`;
8095
+ } else if (stringProp.columnType === "uuid") {
8096
+ columnDefinition = `uuid("${colName}")`;
8069
8097
  } else if (stringProp.columnType === "text") {
8070
8098
  columnDefinition = `text("${colName}")`;
8071
8099
  } else if (stringProp.columnType === "char") {
@@ -8133,11 +8161,38 @@ const getDrizzleColumn = (propName, prop, collection, collections) => {
8133
8161
  }
8134
8162
  break;
8135
8163
  }
8136
- case "map":
8164
+ case "map": {
8165
+ const mapProp = prop;
8166
+ if (mapProp.columnType === "json") {
8167
+ columnDefinition = `json("${colName}")`;
8168
+ } else {
8169
+ columnDefinition = `jsonb("${colName}")`;
8170
+ }
8171
+ break;
8172
+ }
8137
8173
  case "array": {
8138
- const arrayOrMapProp = prop;
8139
- if (arrayOrMapProp.columnType === "json") {
8174
+ const arrayProp = prop;
8175
+ let colType = arrayProp.columnType;
8176
+ if (!colType && arrayProp.of && !Array.isArray(arrayProp.of)) {
8177
+ const ofProp = arrayProp.of;
8178
+ if (ofProp.type === "string") {
8179
+ colType = "text[]";
8180
+ } else if (ofProp.type === "number") {
8181
+ colType = ofProp.validation?.integer ? "integer[]" : "numeric[]";
8182
+ } else if (ofProp.type === "boolean") {
8183
+ colType = "boolean[]";
8184
+ }
8185
+ }
8186
+ if (colType === "json") {
8140
8187
  columnDefinition = `json("${colName}")`;
8188
+ } else if (colType === "text[]") {
8189
+ columnDefinition = `text("${colName}").array()`;
8190
+ } else if (colType === "integer[]") {
8191
+ columnDefinition = `integer("${colName}").array()`;
8192
+ } else if (colType === "boolean[]") {
8193
+ columnDefinition = `boolean("${colName}").array()`;
8194
+ } else if (colType === "numeric[]") {
8195
+ columnDefinition = `numeric("${colName}").array()`;
8141
8196
  } else {
8142
8197
  columnDefinition = `jsonb("${colName}")`;
8143
8198
  }
@@ -8221,8 +8276,8 @@ const resolveRawSql = (expression) => {
8221
8276
  const resolved = expression.replace(/\{(\w+)\}/g, (_, col) => col);
8222
8277
  return `sql\`${resolved}\``;
8223
8278
  };
8224
- const wrapWithRoleCheck = (clause, roles2) => {
8225
- const rolesArrayString = `ARRAY[${roles2.map((r) => `'${r}'`).join(",")}]`;
8279
+ const wrapWithRoleCheck = (clause, roles) => {
8280
+ const rolesArrayString = `ARRAY[${roles.map((r) => `'${r}'`).join(",")}]`;
8226
8281
  const roleCondition = `string_to_array(auth.roles(), ',') @> ${rolesArrayString}`;
8227
8282
  return `sql\`(${unwrapSql(clause)}) AND (${roleCondition})\``;
8228
8283
  };
@@ -8275,22 +8330,22 @@ const generatePolicyCode = (collection, rule, index) => {
8275
8330
  };
8276
8331
  const generateSinglePolicyCode = (collection, rule, operation, policyName) => {
8277
8332
  const mode = rule.mode ?? "permissive";
8278
- const roles2 = rule.roles ? [...rule.roles].sort() : void 0;
8333
+ const roles = rule.roles ? [...rule.roles].sort() : void 0;
8279
8334
  const needsUsing = operation !== "insert";
8280
8335
  const needsWithCheck = operation !== "select" && operation !== "delete";
8281
8336
  let usingClause = needsUsing ? buildUsingClause(rule, collection) : null;
8282
8337
  let withCheckClause = needsWithCheck ? buildWithCheckClause(rule, collection) : null;
8283
- if (roles2 && roles2.length > 0) {
8338
+ if (roles && roles.length > 0) {
8284
8339
  if (usingClause) {
8285
- usingClause = wrapWithRoleCheck(usingClause, roles2);
8340
+ usingClause = wrapWithRoleCheck(usingClause, roles);
8286
8341
  } else if (needsUsing) {
8287
- const rolesArrayString = `ARRAY[${roles2.map((r) => `'${r}'`).join(",")}]`;
8342
+ const rolesArrayString = `ARRAY[${roles.map((r) => `'${r}'`).join(",")}]`;
8288
8343
  usingClause = `sql\`string_to_array(auth.roles(), ',') @> ${rolesArrayString}\``;
8289
8344
  }
8290
8345
  if (withCheckClause) {
8291
- withCheckClause = wrapWithRoleCheck(withCheckClause, roles2);
8346
+ withCheckClause = wrapWithRoleCheck(withCheckClause, roles);
8292
8347
  } else if (needsWithCheck) {
8293
- const rolesArrayString = `ARRAY[${roles2.map((r) => `'${r}'`).join(",")}]`;
8348
+ const rolesArrayString = `ARRAY[${roles.map((r) => `'${r}'`).join(",")}]`;
8294
8349
  withCheckClause = `sql\`string_to_array(auth.roles(), ',') @> ${rolesArrayString}\``;
8295
8350
  }
8296
8351
  }
@@ -8613,7 +8668,7 @@ ${tableRelations.join(",\n")}
8613
8668
  schemaContent += tablesExport + enumsExport + relationsExport;
8614
8669
  return schemaContent;
8615
8670
  };
8616
- const formatTerminalText = (text, options = {}) => {
8671
+ const formatTerminalText = (text2, options = {}) => {
8617
8672
  let codes = "";
8618
8673
  if (options.bold) codes += "\x1B[1m";
8619
8674
  if (options.backgroundColor) {
@@ -8640,7 +8695,7 @@ const formatTerminalText = (text, options = {}) => {
8640
8695
  };
8641
8696
  codes += textColors[options.textColor];
8642
8697
  }
8643
- return `${codes}${text}\x1B[0m`;
8698
+ return `${codes}${text2}\x1B[0m`;
8644
8699
  };
8645
8700
  const runGeneration = async (collectionsFilePath, outputPath) => {
8646
8701
  try {
@@ -10024,15 +10079,15 @@ function createPostgresWebSocket(server, realtimeService, driver, authConfig, au
10024
10079
  wsDebug("👤 [WebSocket Server] Processing FETCH_ROLES request");
10025
10080
  const delegate = await getScopedDelegate();
10026
10081
  const admin = delegate.admin;
10027
- let roles2 = [];
10082
+ let roles = [];
10028
10083
  if (isSQLAdmin(admin) && admin.fetchAvailableRoles) {
10029
- roles2 = await admin.fetchAvailableRoles();
10084
+ roles = await admin.fetchAvailableRoles();
10030
10085
  }
10031
- wsDebug(`👤 [WebSocket Server] Fetched ${roles2.length} roles.`);
10086
+ wsDebug(`👤 [WebSocket Server] Fetched ${roles.length} roles.`);
10032
10087
  const response = {
10033
10088
  type: "FETCH_ROLES_SUCCESS",
10034
10089
  payload: {
10035
- roles: roles2
10090
+ roles
10036
10091
  },
10037
10092
  requestId
10038
10093
  };
@@ -10286,37 +10341,6 @@ class PostgresCollectionRegistry extends CollectionRegistry {
10286
10341
  return collection.relations.map((r) => r.relationName || r.localKey || "").filter(Boolean);
10287
10342
  }
10288
10343
  }
10289
- const DEFAULT_ROLES = [{
10290
- id: "admin",
10291
- name: "Admin",
10292
- is_admin: true,
10293
- default_permissions: {
10294
- read: true,
10295
- create: true,
10296
- edit: true,
10297
- delete: true
10298
- }
10299
- }, {
10300
- id: "editor",
10301
- name: "Editor",
10302
- is_admin: false,
10303
- default_permissions: {
10304
- read: true,
10305
- create: true,
10306
- edit: true,
10307
- delete: true
10308
- }
10309
- }, {
10310
- id: "viewer",
10311
- name: "Viewer",
10312
- is_admin: false,
10313
- default_permissions: {
10314
- read: true,
10315
- create: false,
10316
- edit: false,
10317
- delete: false
10318
- }
10319
- }];
10320
10344
  async function ensureAuthTablesExist(db, registry) {
10321
10345
  logger.info("🔍 Checking auth tables...");
10322
10346
  try {
@@ -10345,26 +10369,15 @@ async function ensureAuthTablesExist(db, registry) {
10345
10369
  }
10346
10370
  }
10347
10371
  }
10348
- let rolesSchema = "rebase";
10349
- if (registry) {
10350
- const rolesTable = registry.getTable("roles");
10351
- if (rolesTable) {
10352
- rolesSchema = getTableConfig(rolesTable).schema || "public";
10353
- }
10354
- }
10355
10372
  if (usersSchema2 !== "public") {
10356
10373
  await db.execute(sql`CREATE SCHEMA IF NOT EXISTS ${sql.raw(usersSchema2)}`);
10357
10374
  }
10358
- if (rolesSchema !== "public" && rolesSchema !== usersSchema2) {
10359
- await db.execute(sql`CREATE SCHEMA IF NOT EXISTS ${sql.raw(rolesSchema)}`);
10360
- }
10361
10375
  await db.execute(sql`CREATE SCHEMA IF NOT EXISTS rebase`);
10362
- const userIdentitiesTable = `"${rolesSchema}"."user_identities"`;
10363
- const rolesTableName = `"${rolesSchema}"."roles"`;
10364
- const userRolesTableName = `"${rolesSchema}"."user_roles"`;
10365
- const refreshTokensTableName = `"${rolesSchema}"."refresh_tokens"`;
10366
- const passwordResetTokensTableName = `"${rolesSchema}"."password_reset_tokens"`;
10367
- const appConfigTableName = `"${rolesSchema}"."app_config"`;
10376
+ const authSchema = usersSchema2 === "public" ? "rebase" : usersSchema2;
10377
+ const userIdentitiesTable = `"${authSchema}"."user_identities"`;
10378
+ const refreshTokensTableName = `"${authSchema}"."refresh_tokens"`;
10379
+ const passwordResetTokensTableName = `"${authSchema}"."password_reset_tokens"`;
10380
+ const appConfigTableName = `"${authSchema}"."app_config"`;
10368
10381
  await db.execute(sql`
10369
10382
  CREATE TABLE IF NOT EXISTS ${sql.raw(userIdentitiesTable)} (
10370
10383
  id TEXT PRIMARY KEY DEFAULT gen_random_uuid()::text,
@@ -10381,27 +10394,6 @@ async function ensureAuthTablesExist(db, registry) {
10381
10394
  CREATE INDEX IF NOT EXISTS idx_user_identities_user
10382
10395
  ON ${sql.raw(userIdentitiesTable)}(user_id)
10383
10396
  `);
10384
- await db.execute(sql`
10385
- CREATE TABLE IF NOT EXISTS ${sql.raw(rolesTableName)} (
10386
- id TEXT PRIMARY KEY,
10387
- name TEXT NOT NULL,
10388
- is_admin BOOLEAN DEFAULT FALSE,
10389
- default_permissions JSONB,
10390
- collection_permissions JSONB,
10391
- created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
10392
- )
10393
- `);
10394
- await db.execute(sql`
10395
- CREATE TABLE IF NOT EXISTS ${sql.raw(userRolesTableName)} (
10396
- user_id ${sql.raw(userIdType)} NOT NULL REFERENCES ${sql.raw(usersTableName)}(id) ON DELETE CASCADE,
10397
- role_id TEXT NOT NULL REFERENCES ${sql.raw(rolesTableName)}(id) ON DELETE CASCADE,
10398
- PRIMARY KEY (user_id, role_id)
10399
- )
10400
- `);
10401
- await db.execute(sql`
10402
- CREATE INDEX IF NOT EXISTS idx_user_roles_user
10403
- ON ${sql.raw(userRolesTableName)}(user_id)
10404
- `);
10405
10397
  await db.execute(sql`
10406
10398
  CREATE TABLE IF NOT EXISTS ${sql.raw(refreshTokensTableName)} (
10407
10399
  id TEXT PRIMARY KEY DEFAULT gen_random_uuid()::text,
@@ -10469,14 +10461,43 @@ async function ensureAuthTablesExist(db, registry) {
10469
10461
  $$ LANGUAGE sql STABLE
10470
10462
  `);
10471
10463
  });
10472
- await seedDefaultRoles(db, rolesTableName);
10473
10464
  await db.execute(sql`
10474
10465
  ALTER TABLE ${sql.raw(usersTableName)}
10475
10466
  ADD COLUMN IF NOT EXISTS is_anonymous BOOLEAN DEFAULT FALSE
10476
10467
  `);
10477
- const mfaFactorsTableName = `"${rolesSchema}"."mfa_factors"`;
10478
- const mfaChallengesTableName = `"${rolesSchema}"."mfa_challenges"`;
10479
- const recoveryCodesTableName = `"${rolesSchema}"."recovery_codes"`;
10468
+ await db.execute(sql`
10469
+ ALTER TABLE ${sql.raw(usersTableName)}
10470
+ ADD COLUMN IF NOT EXISTS roles TEXT[] DEFAULT '{}' NOT NULL
10471
+ `);
10472
+ try {
10473
+ const legacyCheck = await db.execute(sql`
10474
+ SELECT EXISTS (
10475
+ SELECT 1 FROM information_schema.tables
10476
+ WHERE table_schema = 'rebase' AND table_name = 'user_roles'
10477
+ ) AS has_user_roles
10478
+ `);
10479
+ const hasLegacyTables = legacyCheck.rows[0].has_user_roles;
10480
+ if (hasLegacyTables) {
10481
+ logger.info("🔄 Migrating roles from legacy user_roles table...");
10482
+ await db.execute(sql`
10483
+ UPDATE ${sql.raw(usersTableName)} u
10484
+ SET roles = COALESCE((
10485
+ SELECT array_agg(ur.role_id)
10486
+ FROM "rebase"."user_roles" ur
10487
+ WHERE ur.user_id = u.id
10488
+ ), '{}')
10489
+ WHERE u.roles = '{}' OR u.roles IS NULL
10490
+ `);
10491
+ await db.execute(sql`DROP TABLE IF EXISTS "rebase"."user_roles" CASCADE`);
10492
+ await db.execute(sql`DROP TABLE IF EXISTS "rebase"."roles" CASCADE`);
10493
+ logger.info("✅ Legacy roles tables migrated and dropped");
10494
+ }
10495
+ } catch (migrationError) {
10496
+ logger.warn(`⚠️ Legacy roles migration skipped: ${migrationError instanceof Error ? migrationError.message : String(migrationError)}`);
10497
+ }
10498
+ const mfaFactorsTableName = `"${authSchema}"."mfa_factors"`;
10499
+ const mfaChallengesTableName = `"${authSchema}"."mfa_challenges"`;
10500
+ const recoveryCodesTableName = `"${authSchema}"."recovery_codes"`;
10480
10501
  await db.execute(sql`
10481
10502
  CREATE TABLE IF NOT EXISTS ${sql.raw(mfaFactorsTableName)} (
10482
10503
  id TEXT PRIMARY KEY DEFAULT gen_random_uuid()::text,
@@ -10528,28 +10549,6 @@ async function ensureAuthTablesExist(db, registry) {
10528
10549
  logger.warn("⚠️ Continuing without creating auth tables.");
10529
10550
  }
10530
10551
  }
10531
- async function seedDefaultRoles(db, rolesTableName) {
10532
- const result = await db.execute(sql`SELECT COUNT(*) as count FROM ${sql.raw(rolesTableName)}`);
10533
- const count2 = parseInt(result.rows[0]?.count || "0", 10);
10534
- if (count2 > 0) {
10535
- logger.info(`📋 Found ${count2} existing roles`);
10536
- return;
10537
- }
10538
- logger.info("🌱 Seeding default roles...");
10539
- for (const role of DEFAULT_ROLES) {
10540
- await db.execute(sql`
10541
- INSERT INTO ${sql.raw(rolesTableName)} (id, name, is_admin, default_permissions)
10542
- VALUES (
10543
- ${role.id},
10544
- ${role.name},
10545
- ${role.is_admin},
10546
- ${JSON.stringify(role.default_permissions)}::jsonb
10547
- )
10548
- ON CONFLICT (id) DO NOTHING
10549
- `);
10550
- }
10551
- logger.info("✅ Default roles created: admin, editor, viewer");
10552
- }
10553
10552
  function getColumnKey(table, ...keys2) {
10554
10553
  if (!table) return void 0;
10555
10554
  for (const key of keys2) {
@@ -10569,24 +10568,18 @@ function getColumn(table, ...keys2) {
10569
10568
  class UserService {
10570
10569
  constructor(db, tableOrTables) {
10571
10570
  this.db = db;
10572
- if (tableOrTables && (tableOrTables.users || tableOrTables.roles)) {
10571
+ if (tableOrTables && tableOrTables.users) {
10573
10572
  const tables = tableOrTables;
10574
10573
  this.usersTable = tables.users || users;
10575
10574
  this.userIdentitiesTable = tables.userIdentities || userIdentities;
10576
- this.userRolesTable = tables.userRoles || userRoles;
10577
- this.rolesTable = tables.roles || roles;
10578
10575
  } else {
10579
10576
  const table = tableOrTables;
10580
10577
  this.usersTable = table || users;
10581
10578
  this.userIdentitiesTable = userIdentities;
10582
- this.userRolesTable = userRoles;
10583
- this.rolesTable = roles;
10584
10579
  }
10585
10580
  }
10586
10581
  usersTable;
10587
10582
  userIdentitiesTable;
10588
- userRolesTable;
10589
- rolesTable;
10590
10583
  getQualifiedUsersTableName() {
10591
10584
  const name = getTableName$1(this.usersTable);
10592
10585
  const schema = getTableConfig(this.usersTable).schema || "public";
@@ -10608,7 +10601,7 @@ class UserService {
10608
10601
  const metadata = {
10609
10602
  ...row.metadata || {}
10610
10603
  };
10611
- const knownKeys = /* @__PURE__ */ new Set(["id", "uid", "email", "password_hash", "passwordHash", "display_name", "displayName", "photo_url", "photoUrl", "photoURL", "email_verified", "emailVerified", "email_verification_token", "emailVerificationToken", "email_verification_sent_at", "emailVerificationSentAt", "is_anonymous", "isAnonymous", "created_at", "createdAt", "updated_at", "updatedAt", "metadata"]);
10604
+ const knownKeys = /* @__PURE__ */ new Set(["id", "uid", "email", "password_hash", "passwordHash", "display_name", "displayName", "photo_url", "photoUrl", "photoURL", "email_verified", "emailVerified", "email_verification_token", "emailVerificationToken", "email_verification_sent_at", "emailVerificationSentAt", "is_anonymous", "isAnonymous", "roles", "created_at", "createdAt", "updated_at", "updatedAt", "metadata"]);
10612
10605
  for (const [key, val] of Object.entries(row)) {
10613
10606
  if (!knownKeys.has(key)) {
10614
10607
  const camelKey = camelCase(key);
@@ -10759,19 +10752,18 @@ class UserService {
10759
10752
  const displayNameCol = getColumn(this.usersTable, "displayName", "display_name");
10760
10753
  const displayNameColumn = displayNameCol ? displayNameCol.name : "display_name";
10761
10754
  const idCol = getColumn(this.usersTable, "id");
10762
- const idColumn = idCol ? idCol.name : "id";
10755
+ idCol ? idCol.name : "id";
10763
10756
  const usersTableName = this.getQualifiedUsersTableName();
10764
- const rolesSchema = getTableConfig(this.userRolesTable).schema || "public";
10765
10757
  const conditions = [];
10766
10758
  if (roleId) {
10767
- conditions.push(sql`EXISTS (SELECT 1 FROM ${sql.raw(`"${rolesSchema}"."user_roles"`)} ur WHERE ur.user_id = ${sql.raw(usersTableName)}.${sql.raw(idColumn)} AND ur.role_id = ${roleId})`);
10759
+ conditions.push(sql`${roleId} = ANY(${sql.raw(usersTableName)}.roles)`);
10768
10760
  }
10769
10761
  if (search) {
10770
10762
  const pattern = `%${search}%`;
10771
10763
  conditions.push(sql`(${sql.raw(usersTableName)}.${sql.raw(emailColumn)} ILIKE ${pattern} OR ${sql.raw(usersTableName)}.${sql.raw(displayNameColumn)} ILIKE ${pattern})`);
10772
10764
  }
10773
10765
  const whereClause = conditions.length > 0 ? sql`WHERE ${sql.join(conditions, sql` AND `)}` : sql``;
10774
- const orderByClause = roleId ? sql`ORDER BY ${sql.raw(usersTableName)}.${sql.raw(orderColumn)} ${direction}` : sql`ORDER BY (SELECT count(*) FROM ${sql.raw(`"${rolesSchema}"."user_roles"`)} ur WHERE ur.user_id = ${sql.raw(usersTableName)}.${sql.raw(idColumn)}) DESC, ${sql.raw(usersTableName)}.${sql.raw(orderColumn)} ${direction}`;
10766
+ const orderByClause = roleId ? sql`ORDER BY ${sql.raw(usersTableName)}.${sql.raw(orderColumn)} ${direction}` : sql`ORDER BY array_length(${sql.raw(usersTableName)}.roles, 1) DESC NULLS LAST, ${sql.raw(usersTableName)}.${sql.raw(orderColumn)} ${direction}`;
10775
10767
  const countResult = await this.db.execute(sql`
10776
10768
  SELECT count(*)::int as total FROM ${sql.raw(usersTableName)}
10777
10769
  ${whereClause}
@@ -10845,54 +10837,57 @@ class UserService {
10845
10837
  return row ? this.mapRowToUser(row) : null;
10846
10838
  }
10847
10839
  /**
10848
- * Get roles for a user from database
10840
+ * Get roles for a user from database (inline TEXT[] column)
10849
10841
  */
10850
10842
  async getUserRoles(userId) {
10851
- const rolesSchema = getTableConfig(this.rolesTable).schema || "public";
10843
+ const usersTableName = this.getQualifiedUsersTableName();
10852
10844
  const result = await this.db.execute(sql`
10853
- SELECT r.id, r.name, r.is_admin, r.default_permissions, r.collection_permissions
10854
- FROM ${sql.raw(`"${rolesSchema}"."roles"`)} r
10855
- INNER JOIN ${sql.raw(`"${rolesSchema}"."user_roles"`)} ur ON r.id = ur.role_id
10856
- WHERE ur.user_id = ${userId}
10845
+ SELECT roles FROM ${sql.raw(usersTableName)} WHERE id = ${userId}
10857
10846
  `);
10858
- return result.rows.map((row) => ({
10859
- id: row.id,
10860
- name: row.name,
10861
- isAdmin: row.is_admin,
10862
- defaultPermissions: row.default_permissions,
10863
- collectionPermissions: row.collection_permissions
10847
+ if (result.rows.length === 0) return [];
10848
+ const row = result.rows[0];
10849
+ const roleIds = row.roles ?? [];
10850
+ return roleIds.map((id) => ({
10851
+ id,
10852
+ name: id,
10853
+ isAdmin: id === "admin",
10854
+ defaultPermissions: null,
10855
+ collectionPermissions: null
10864
10856
  }));
10865
10857
  }
10866
10858
  /**
10867
10859
  * Get role IDs for a user
10868
10860
  */
10869
10861
  async getUserRoleIds(userId) {
10870
- const roles2 = await this.getUserRoles(userId);
10871
- return roles2.map((r) => r.id);
10862
+ const usersTableName = this.getQualifiedUsersTableName();
10863
+ const result = await this.db.execute(sql`
10864
+ SELECT roles FROM ${sql.raw(usersTableName)} WHERE id = ${userId}
10865
+ `);
10866
+ if (result.rows.length === 0) return [];
10867
+ const row = result.rows[0];
10868
+ return row.roles ?? [];
10872
10869
  }
10873
10870
  /**
10874
- * Set roles for a user
10871
+ * Set roles for a user (replaces existing roles)
10875
10872
  */
10876
10873
  async setUserRoles(userId, roleIds) {
10877
- const rolesSchema = getTableConfig(this.userRolesTable).schema || "public";
10878
- await this.db.execute(sql`DELETE FROM ${sql.raw(`"${rolesSchema}"."user_roles"`)} WHERE user_id = ${userId}`);
10879
- for (const roleId of roleIds) {
10880
- await this.db.execute(sql`
10881
- INSERT INTO ${sql.raw(`"${rolesSchema}"."user_roles"`)} (user_id, role_id)
10882
- VALUES (${userId}, ${roleId})
10883
- ON CONFLICT DO NOTHING
10884
- `);
10885
- }
10874
+ const usersTableName = this.getQualifiedUsersTableName();
10875
+ const rolesArray = `{${roleIds.join(",")}}`;
10876
+ await this.db.execute(sql`
10877
+ UPDATE ${sql.raw(usersTableName)}
10878
+ SET roles = ${rolesArray}::text[], updated_at = NOW()
10879
+ WHERE id = ${userId}
10880
+ `);
10886
10881
  }
10887
10882
  /**
10888
- * Assign a specific role to new user
10883
+ * Assign a specific role to new user (appends if not present)
10889
10884
  */
10890
10885
  async assignDefaultRole(userId, roleId) {
10891
- const rolesSchema = getTableConfig(this.userRolesTable).schema || "public";
10886
+ const usersTableName = this.getQualifiedUsersTableName();
10892
10887
  await this.db.execute(sql`
10893
- INSERT INTO ${sql.raw(`"${rolesSchema}"."user_roles"`)} (user_id, role_id)
10894
- VALUES (${userId}, ${roleId})
10895
- ON CONFLICT DO NOTHING
10888
+ UPDATE ${sql.raw(usersTableName)}
10889
+ SET roles = array_append(roles, ${roleId}), updated_at = NOW()
10890
+ WHERE id = ${userId} AND NOT (${roleId} = ANY(roles))
10896
10891
  `);
10897
10892
  }
10898
10893
  /**
@@ -10901,101 +10896,12 @@ class UserService {
10901
10896
  async getUserWithRoles(userId) {
10902
10897
  const user = await this.getUserById(userId);
10903
10898
  if (!user) return null;
10904
- const roles2 = await this.getUserRoles(userId);
10899
+ const roles = await this.getUserRoles(userId);
10905
10900
  return {
10906
10901
  user,
10907
- roles: roles2
10908
- };
10909
- }
10910
- }
10911
- class RoleService {
10912
- constructor(db, tableOrTables) {
10913
- this.db = db;
10914
- if (tableOrTables && (tableOrTables.roles || tableOrTables.users)) {
10915
- this.rolesTable = tableOrTables.roles || roles;
10916
- } else {
10917
- this.rolesTable = tableOrTables || roles;
10918
- }
10919
- }
10920
- rolesTable;
10921
- getQualifiedRolesTableName() {
10922
- const name = getTableName$1(this.rolesTable);
10923
- const schema = getTableConfig(this.rolesTable).schema || "public";
10924
- return `"${schema}"."${name}"`;
10925
- }
10926
- async getRoleById(id) {
10927
- const tableName = this.getQualifiedRolesTableName();
10928
- const result = await this.db.execute(sql`
10929
- SELECT id, name, is_admin, default_permissions, collection_permissions
10930
- FROM ${sql.raw(tableName)}
10931
- WHERE id = ${id}
10932
- `);
10933
- if (result.rows.length === 0) return null;
10934
- const row = result.rows[0];
10935
- return {
10936
- id: row.id,
10937
- name: row.name,
10938
- isAdmin: row.is_admin,
10939
- defaultPermissions: row.default_permissions,
10940
- collectionPermissions: row.collection_permissions
10941
- };
10942
- }
10943
- async listRoles() {
10944
- const tableName = this.getQualifiedRolesTableName();
10945
- const result = await this.db.execute(sql`
10946
- SELECT id, name, is_admin, default_permissions, collection_permissions
10947
- FROM ${sql.raw(tableName)}
10948
- ORDER BY name
10949
- `);
10950
- return result.rows.map((row) => ({
10951
- id: row.id,
10952
- name: row.name,
10953
- isAdmin: row.is_admin,
10954
- defaultPermissions: row.default_permissions,
10955
- collectionPermissions: row.collection_permissions
10956
- }));
10957
- }
10958
- async createRole(data) {
10959
- const tableName = this.getQualifiedRolesTableName();
10960
- const result = await this.db.execute(sql`
10961
- INSERT INTO ${sql.raw(tableName)} (id, name, is_admin, default_permissions, collection_permissions)
10962
- VALUES (
10963
- ${data.id},
10964
- ${data.name},
10965
- ${data.isAdmin ?? false},
10966
- ${data.defaultPermissions ? JSON.stringify(data.defaultPermissions) : null}::jsonb,
10967
- ${data.collectionPermissions ? JSON.stringify(data.collectionPermissions) : null}::jsonb
10968
- )
10969
- RETURNING id, name, is_admin, default_permissions, collection_permissions
10970
- `);
10971
- const row = result.rows[0];
10972
- return {
10973
- id: row.id,
10974
- name: row.name,
10975
- isAdmin: row.is_admin,
10976
- defaultPermissions: row.default_permissions,
10977
- collectionPermissions: row.collection_permissions
10902
+ roles
10978
10903
  };
10979
10904
  }
10980
- async updateRole(id, data) {
10981
- const existing = await this.getRoleById(id);
10982
- if (!existing) return null;
10983
- const tableName = this.getQualifiedRolesTableName();
10984
- await this.db.execute(sql`
10985
- UPDATE ${sql.raw(tableName)}
10986
- SET
10987
- name = ${data.name ?? existing.name},
10988
- is_admin = ${data.isAdmin ?? existing.isAdmin},
10989
- default_permissions = ${data.defaultPermissions ? JSON.stringify(data.defaultPermissions) : JSON.stringify(existing.defaultPermissions)}::jsonb,
10990
- collection_permissions = ${data.collectionPermissions !== void 0 ? data.collectionPermissions ? JSON.stringify(data.collectionPermissions) : null : existing.collectionPermissions ? JSON.stringify(existing.collectionPermissions) : null}::jsonb
10991
- WHERE id = ${id}
10992
- `);
10993
- return this.getRoleById(id);
10994
- }
10995
- async deleteRole(id) {
10996
- const tableName = this.getQualifiedRolesTableName();
10997
- await this.db.execute(sql`DELETE FROM ${sql.raw(tableName)} WHERE id = ${id}`);
10998
- }
10999
10905
  }
11000
10906
  class RefreshTokenService {
11001
10907
  constructor(db, tableOrTables) {
@@ -11191,11 +11097,9 @@ class PostgresAuthRepository {
11191
11097
  constructor(db, tableOrTables) {
11192
11098
  this.db = db;
11193
11099
  this.userService = new UserService(db, tableOrTables);
11194
- this.roleService = new RoleService(db, tableOrTables);
11195
11100
  this.tokenRepository = new PostgresTokenRepository(db, tableOrTables);
11196
11101
  }
11197
11102
  userService;
11198
- roleService;
11199
11103
  tokenRepository;
11200
11104
  // User operations (delegate to UserService)
11201
11105
  async createUser(data) {
@@ -11255,25 +11159,56 @@ class PostgresAuthRepository {
11255
11159
  async getUserWithRoles(userId) {
11256
11160
  return this.userService.getUserWithRoles(userId);
11257
11161
  }
11258
- // Role operations (delegate to RoleService)
11162
+ // Role operations (roles are inline on users, synthesized from string IDs)
11259
11163
  async getRoleById(id) {
11260
- return this.roleService.getRoleById(id);
11164
+ return {
11165
+ id,
11166
+ name: id,
11167
+ isAdmin: id === "admin",
11168
+ defaultPermissions: null,
11169
+ collectionPermissions: null
11170
+ };
11261
11171
  }
11262
11172
  async listRoles() {
11263
- return this.roleService.listRoles();
11173
+ return [{
11174
+ id: "admin",
11175
+ name: "Admin",
11176
+ isAdmin: true,
11177
+ defaultPermissions: null,
11178
+ collectionPermissions: null
11179
+ }, {
11180
+ id: "editor",
11181
+ name: "Editor",
11182
+ isAdmin: false,
11183
+ defaultPermissions: null,
11184
+ collectionPermissions: null
11185
+ }, {
11186
+ id: "viewer",
11187
+ name: "Viewer",
11188
+ isAdmin: false,
11189
+ defaultPermissions: null,
11190
+ collectionPermissions: null
11191
+ }];
11192
+ }
11193
+ async createRole(_data) {
11194
+ return {
11195
+ id: _data.id,
11196
+ name: _data.name,
11197
+ isAdmin: _data.isAdmin ?? false,
11198
+ defaultPermissions: _data.defaultPermissions ?? null,
11199
+ collectionPermissions: _data.collectionPermissions ?? null
11200
+ };
11264
11201
  }
11265
- async createRole(data) {
11266
- return this.roleService.createRole({
11267
- ...data,
11202
+ async updateRole(id, data) {
11203
+ return {
11204
+ id,
11205
+ name: data.name ?? id,
11206
+ isAdmin: data.isAdmin ?? id === "admin",
11268
11207
  defaultPermissions: data.defaultPermissions ?? null,
11269
11208
  collectionPermissions: data.collectionPermissions ?? null
11270
- });
11271
- }
11272
- async updateRole(id, data) {
11273
- return this.roleService.updateRole(id, data);
11209
+ };
11274
11210
  }
11275
- async deleteRole(id) {
11276
- await this.roleService.deleteRole(id);
11211
+ async deleteRole(_id) {
11277
11212
  }
11278
11213
  // Token operations (delegate to PostgresTokenRepository)
11279
11214
  async createRefreshToken(userId, tokenHash, expiresAt, userAgent, ipAddress) {
@@ -11829,28 +11764,19 @@ function createPostgresBootstrapper(pgConfig) {
11829
11764
  emailService = createEmailService(authConfig.email);
11830
11765
  }
11831
11766
  const customUsersTable = registry?.getTable("users");
11832
- const customRolesTable = registry?.getTable("roles");
11833
11767
  let usersSchemaName = "rebase";
11834
- let rolesSchemaName = "rebase";
11835
11768
  if (customUsersTable) {
11836
11769
  usersSchemaName = getTableConfig(customUsersTable).schema || "public";
11837
11770
  }
11838
- if (customRolesTable) {
11839
- rolesSchemaName = getTableConfig(customRolesTable).schema || "public";
11840
- }
11841
- const authTables = createAuthSchema(rolesSchemaName, usersSchemaName);
11771
+ const authTables = createAuthSchema(usersSchemaName);
11842
11772
  if (customUsersTable) {
11843
11773
  authTables.users = customUsersTable;
11844
11774
  }
11845
- if (customRolesTable) {
11846
- authTables.roles = customRolesTable;
11847
- }
11848
11775
  const userService = new UserService(db, authTables);
11849
- const roleService = new RoleService(db, authTables);
11850
11776
  const authRepository = new PostgresAuthRepository(db, authTables);
11851
11777
  return {
11852
11778
  userService,
11853
- roleService,
11779
+ roleService: userService,
11854
11780
  emailService,
11855
11781
  authRepository
11856
11782
  };
@@ -11955,17 +11881,12 @@ export {
11955
11881
  mfaFactorsRelations,
11956
11882
  passwordResetTokens,
11957
11883
  passwordResetTokensRelations,
11958
- rebaseSchema,
11959
11884
  recoveryCodes,
11960
11885
  recoveryCodesRelations,
11961
11886
  refreshTokens,
11962
11887
  refreshTokensRelations,
11963
- roles,
11964
- rolesRelations,
11965
11888
  userIdentities,
11966
11889
  userIdentitiesRelations,
11967
- userRoles,
11968
- userRolesRelations,
11969
11890
  users,
11970
11891
  usersRelations,
11971
11892
  usersSchema