@rebasepro/server-postgresql 0.0.1-canary.4d4fb3e → 0.0.1-canary.ca2cb6e

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 (136) hide show
  1. package/dist/common/src/collections/CollectionRegistry.d.ts +8 -0
  2. package/dist/common/src/util/entities.d.ts +22 -0
  3. package/dist/common/src/util/relations.d.ts +14 -4
  4. package/dist/common/src/util/resolutions.d.ts +1 -1
  5. package/dist/index.es.js +1254 -591
  6. package/dist/index.es.js.map +1 -1
  7. package/dist/index.umd.js +1254 -591
  8. package/dist/index.umd.js.map +1 -1
  9. package/dist/server-postgresql/src/PostgresBackendDriver.d.ts +17 -29
  10. package/dist/server-postgresql/src/auth/services.d.ts +7 -3
  11. package/dist/server-postgresql/src/collections/PostgresCollectionRegistry.d.ts +1 -1
  12. package/dist/server-postgresql/src/connection.d.ts +34 -1
  13. package/dist/server-postgresql/src/data-transformer.d.ts +26 -4
  14. package/dist/server-postgresql/src/databasePoolManager.d.ts +2 -2
  15. package/dist/server-postgresql/src/schema/auth-schema.d.ts +139 -38
  16. package/dist/server-postgresql/src/schema/doctor-cli.d.ts +2 -0
  17. package/dist/server-postgresql/src/schema/doctor.d.ts +43 -0
  18. package/dist/server-postgresql/src/schema/generate-drizzle-schema-logic.d.ts +1 -1
  19. package/dist/server-postgresql/src/schema/test-schema.d.ts +24 -0
  20. package/dist/server-postgresql/src/services/EntityFetchService.d.ts +22 -8
  21. package/dist/server-postgresql/src/services/EntityPersistService.d.ts +1 -1
  22. package/dist/server-postgresql/src/services/RelationService.d.ts +11 -5
  23. package/dist/server-postgresql/src/services/entity-helpers.d.ts +16 -2
  24. package/dist/server-postgresql/src/services/entityService.d.ts +8 -6
  25. package/dist/server-postgresql/src/services/realtimeService.d.ts +2 -0
  26. package/dist/server-postgresql/src/utils/drizzle-conditions.d.ts +2 -2
  27. package/dist/types/src/controllers/auth.d.ts +2 -0
  28. package/dist/types/src/controllers/client.d.ts +119 -7
  29. package/dist/types/src/controllers/collection_registry.d.ts +4 -3
  30. package/dist/types/src/controllers/customization_controller.d.ts +7 -1
  31. package/dist/types/src/controllers/data.d.ts +34 -7
  32. package/dist/types/src/controllers/data_driver.d.ts +20 -28
  33. package/dist/types/src/controllers/database_admin.d.ts +2 -2
  34. package/dist/types/src/controllers/email.d.ts +34 -0
  35. package/dist/types/src/controllers/index.d.ts +1 -0
  36. package/dist/types/src/controllers/local_config_persistence.d.ts +4 -4
  37. package/dist/types/src/controllers/navigation.d.ts +5 -5
  38. package/dist/types/src/controllers/registry.d.ts +6 -3
  39. package/dist/types/src/controllers/side_entity_controller.d.ts +7 -6
  40. package/dist/types/src/controllers/storage.d.ts +24 -26
  41. package/dist/types/src/rebase_context.d.ts +8 -4
  42. package/dist/types/src/types/backend.d.ts +4 -1
  43. package/dist/types/src/types/builders.d.ts +5 -4
  44. package/dist/types/src/types/chips.d.ts +1 -1
  45. package/dist/types/src/types/collections.d.ts +169 -125
  46. package/dist/types/src/types/cron.d.ts +102 -0
  47. package/dist/types/src/types/data_source.d.ts +1 -1
  48. package/dist/types/src/types/entity_actions.d.ts +8 -8
  49. package/dist/types/src/types/entity_callbacks.d.ts +15 -15
  50. package/dist/types/src/types/entity_link_builder.d.ts +1 -1
  51. package/dist/types/src/types/entity_overrides.d.ts +2 -1
  52. package/dist/types/src/types/entity_views.d.ts +8 -8
  53. package/dist/types/src/types/export_import.d.ts +3 -3
  54. package/dist/types/src/types/index.d.ts +1 -0
  55. package/dist/types/src/types/plugins.d.ts +72 -18
  56. package/dist/types/src/types/properties.d.ts +118 -33
  57. package/dist/types/src/types/relations.d.ts +1 -1
  58. package/dist/types/src/types/slots.d.ts +30 -6
  59. package/dist/types/src/types/translations.d.ts +44 -0
  60. package/dist/types/src/types/user_management_delegate.d.ts +1 -0
  61. package/drizzle-test/0000_woozy_junta.sql +6 -0
  62. package/drizzle-test/0001_youthful_arachne.sql +1 -0
  63. package/drizzle-test/0002_lively_dragon_lord.sql +2 -0
  64. package/drizzle-test/0003_mean_king_cobra.sql +2 -0
  65. package/drizzle-test/meta/0000_snapshot.json +47 -0
  66. package/drizzle-test/meta/0001_snapshot.json +48 -0
  67. package/drizzle-test/meta/0002_snapshot.json +38 -0
  68. package/drizzle-test/meta/0003_snapshot.json +48 -0
  69. package/drizzle-test/meta/_journal.json +34 -0
  70. package/drizzle-test-out/0000_tan_trauma.sql +6 -0
  71. package/drizzle-test-out/0001_rapid_drax.sql +1 -0
  72. package/drizzle-test-out/meta/0000_snapshot.json +44 -0
  73. package/drizzle-test-out/meta/0001_snapshot.json +54 -0
  74. package/drizzle-test-out/meta/_journal.json +20 -0
  75. package/drizzle.test.config.ts +10 -0
  76. package/package.json +88 -89
  77. package/scratch.ts +41 -0
  78. package/src/PostgresBackendDriver.ts +63 -79
  79. package/src/PostgresBootstrapper.ts +7 -8
  80. package/src/auth/ensure-tables.ts +158 -86
  81. package/src/auth/services.ts +109 -50
  82. package/src/cli.ts +259 -16
  83. package/src/collections/PostgresCollectionRegistry.ts +6 -6
  84. package/src/connection.ts +70 -48
  85. package/src/data-transformer.ts +155 -116
  86. package/src/databasePoolManager.ts +6 -5
  87. package/src/history/HistoryService.ts +3 -12
  88. package/src/interfaces.ts +3 -3
  89. package/src/schema/auth-schema.ts +26 -3
  90. package/src/schema/doctor-cli.ts +47 -0
  91. package/src/schema/doctor.ts +595 -0
  92. package/src/schema/generate-drizzle-schema-logic.ts +204 -57
  93. package/src/schema/generate-drizzle-schema.ts +6 -6
  94. package/src/schema/test-schema.ts +11 -0
  95. package/src/services/BranchService.ts +5 -5
  96. package/src/services/EntityFetchService.ts +317 -188
  97. package/src/services/EntityPersistService.ts +15 -17
  98. package/src/services/RelationService.ts +299 -37
  99. package/src/services/entity-helpers.ts +39 -13
  100. package/src/services/entityService.ts +11 -9
  101. package/src/services/realtimeService.ts +58 -29
  102. package/src/utils/drizzle-conditions.ts +25 -24
  103. package/src/websocket.ts +52 -21
  104. package/test/auth-services.test.ts +131 -39
  105. package/test/batch-many-to-many-regression.test.ts +573 -0
  106. package/test/branchService.test.ts +22 -12
  107. package/test/data-transformer-hardening.test.ts +417 -0
  108. package/test/data-transformer.test.ts +175 -0
  109. package/test/doctor.test.ts +182 -0
  110. package/test/entityService.errors.test.ts +31 -16
  111. package/test/entityService.relations.test.ts +155 -59
  112. package/test/entityService.subcollection-search.test.ts +107 -57
  113. package/test/entityService.test.ts +105 -47
  114. package/test/generate-drizzle-schema.test.ts +262 -69
  115. package/test/historyService.test.ts +31 -16
  116. package/test/n-plus-one-regression.test.ts +314 -0
  117. package/test/postgresDataDriver.test.ts +260 -168
  118. package/test/realtimeService.test.ts +70 -39
  119. package/test/relation-pipeline-gaps.test.ts +637 -0
  120. package/test/relations.test.ts +492 -39
  121. package/test-drizzle-bug.ts +18 -0
  122. package/test-drizzle-out/0000_cultured_freak.sql +7 -0
  123. package/test-drizzle-out/0001_tiresome_professor_monster.sql +1 -0
  124. package/test-drizzle-out/meta/0000_snapshot.json +55 -0
  125. package/test-drizzle-out/meta/0001_snapshot.json +63 -0
  126. package/test-drizzle-out/meta/_journal.json +20 -0
  127. package/test-drizzle-prompt.sh +2 -0
  128. package/test-policy-prompt.sh +3 -0
  129. package/test-programmatic.ts +30 -0
  130. package/test-programmatic2.ts +59 -0
  131. package/test-schema-no-policies.ts +12 -0
  132. package/test_drizzle_mock.js +2 -2
  133. package/test_find_changed.mjs +3 -1
  134. package/test_hash.js +14 -0
  135. package/tsconfig.json +1 -1
  136. package/vite.config.ts +5 -5
@@ -1,4 +1,4 @@
1
- import { PgTable } from "drizzle-orm/pg-core";
1
+ import { PgTable, AnyPgColumn } from "drizzle-orm/pg-core";
2
2
  import { EntityCollection } from "@rebasepro/types";
3
3
  import { PostgresCollectionRegistry } from "../collections/PostgresCollectionRegistry";
4
4
  /**
@@ -8,17 +8,31 @@ import { PostgresCollectionRegistry } from "../collections/PostgresCollectionReg
8
8
  * All functions that need collection/table lookups require an explicit
9
9
  * `PostgresCollectionRegistry` instance — there is no global singleton.
10
10
  */
11
+ /**
12
+ * Interface for Drizzle column metadata introspection.
13
+ * Replaces unsafe `as unknown as Record<string, unknown>` double-cast chains.
14
+ */
15
+ export interface DrizzleColumnMeta {
16
+ columnType?: string;
17
+ dataType?: string;
18
+ primary?: boolean;
19
+ }
20
+ /** Safely extract Drizzle column metadata from a column object. */
21
+ export declare function getColumnMeta(col: AnyPgColumn): DrizzleColumnMeta;
11
22
  export declare function getCollectionByPath(collectionPath: string, registry: PostgresCollectionRegistry): EntityCollection;
12
23
  export declare function getTableForCollection(collection: EntityCollection, registry: PostgresCollectionRegistry): PgTable<any>;
13
24
  export declare function getPrimaryKeys(collection: EntityCollection, registry: PostgresCollectionRegistry): {
14
25
  fieldName: string;
15
26
  type: "string" | "number";
27
+ isUUID?: boolean;
16
28
  }[];
17
29
  export declare function parseIdValues(idValue: string | number, primaryKeys: {
18
30
  fieldName: string;
19
31
  type: "string" | "number";
32
+ isUUID?: boolean;
20
33
  }[]): Record<string, string | number>;
21
- export declare function buildCompositeId(values: Record<string, any>, primaryKeys: {
34
+ export declare function buildCompositeId(values: Record<string, unknown>, primaryKeys: {
22
35
  fieldName: string;
23
36
  type: "string" | "number";
37
+ isUUID?: boolean;
24
38
  }[]): string;
@@ -29,15 +29,16 @@ export declare class EntityService implements EntityRepository {
29
29
  /**
30
30
  * Fetch a single entity by ID
31
31
  */
32
- fetchEntity<M extends Record<string, any>>(collectionPath: string, entityId: string | number, databaseId?: string): Promise<Entity<M> | undefined>;
32
+ fetchEntity<M extends Record<string, unknown>>(collectionPath: string, entityId: string | number, databaseId?: string): Promise<Entity<M> | undefined>;
33
33
  /**
34
34
  * Fetch a collection of entities with optional filtering, ordering, and pagination
35
35
  */
36
- fetchCollection<M extends Record<string, any>>(collectionPath: string, options?: {
36
+ fetchCollection<M extends Record<string, unknown>>(collectionPath: string, options?: {
37
37
  filter?: FilterValues<Extract<keyof M, string>>;
38
38
  orderBy?: string;
39
39
  order?: "desc" | "asc";
40
40
  limit?: number;
41
+ offset?: number;
41
42
  startAfter?: Record<string, unknown>;
42
43
  searchString?: string;
43
44
  databaseId?: string;
@@ -45,7 +46,7 @@ export declare class EntityService implements EntityRepository {
45
46
  /**
46
47
  * Search entities by text
47
48
  */
48
- searchEntities<M extends Record<string, any>>(collectionPath: string, searchString: string, options?: {
49
+ searchEntities<M extends Record<string, unknown>>(collectionPath: string, searchString: string, options?: {
49
50
  filter?: FilterValues<Extract<keyof M, string>>;
50
51
  orderBy?: string;
51
52
  order?: "desc" | "asc";
@@ -55,8 +56,9 @@ export declare class EntityService implements EntityRepository {
55
56
  /**
56
57
  * Count entities in a collection
57
58
  */
58
- countEntities<M extends Record<string, any>>(collectionPath: string, options?: {
59
+ countEntities<M extends Record<string, unknown>>(collectionPath: string, options?: {
59
60
  filter?: FilterValues<Extract<keyof M, string>>;
61
+ searchString?: string;
60
62
  databaseId?: string;
61
63
  }): Promise<number>;
62
64
  /**
@@ -66,7 +68,7 @@ export declare class EntityService implements EntityRepository {
66
68
  /**
67
69
  * Fetch entities related to a parent entity
68
70
  */
69
- fetchRelatedEntities<M extends Record<string, any>>(parentCollectionPath: string, parentEntityId: string | number, relationKey: string, options?: {
71
+ fetchRelatedEntities<M extends Record<string, unknown>>(parentCollectionPath: string, parentEntityId: string | number, relationKey: string, options?: {
70
72
  filter?: FilterValues<Extract<keyof M, string>>;
71
73
  orderBy?: string;
72
74
  order?: "desc" | "asc";
@@ -78,7 +80,7 @@ export declare class EntityService implements EntityRepository {
78
80
  /**
79
81
  * Save an entity (create or update)
80
82
  */
81
- saveEntity<M extends Record<string, any>>(collectionPath: string, values: Partial<M>, entityId?: string | number, databaseId?: string): Promise<Entity<M>>;
83
+ saveEntity<M extends Record<string, unknown>>(collectionPath: string, values: Partial<M>, entityId?: string | number, databaseId?: string): Promise<Entity<M>>;
82
84
  /**
83
85
  * Delete an entity by ID
84
86
  */
@@ -55,6 +55,7 @@ export declare class RealtimeService extends EventEmitter implements RealtimePro
55
55
  orderBy?: string;
56
56
  order?: "desc" | "asc";
57
57
  limit?: number;
58
+ offset?: number;
58
59
  startAfter?: Record<string, unknown>;
59
60
  databaseId?: string;
60
61
  searchString?: string;
@@ -71,6 +72,7 @@ export declare class RealtimeService extends EventEmitter implements RealtimePro
71
72
  orderBy?: string;
72
73
  order?: "desc" | "asc";
73
74
  limit?: number;
75
+ offset?: number;
74
76
  startAfter?: Record<string, unknown>;
75
77
  databaseId?: string;
76
78
  searchString?: string;
@@ -21,7 +21,7 @@ export declare class DrizzleConditionBuilder {
21
21
  /**
22
22
  * Build filter conditions from FilterValues
23
23
  */
24
- static buildFilterConditions<M extends Record<string, any>>(filter: FilterValues<Extract<keyof M, string>>, table: PgTable<any>, collectionPath: string): SQL[];
24
+ static buildFilterConditions<M extends Record<string, unknown>>(filter: FilterValues<Extract<keyof M, string>>, table: PgTable<any>, collectionPath: string): SQL[];
25
25
  /**
26
26
  * Build a single filter condition for a specific operator and value
27
27
  */
@@ -71,7 +71,7 @@ export declare class DrizzleConditionBuilder {
71
71
  /**
72
72
  * Build search conditions for text fields
73
73
  */
74
- static buildSearchConditions(searchString: string, properties: Record<string, any>, table: PgTable<any>): SQL[];
74
+ static buildSearchConditions(searchString: string, properties: Record<string, unknown>, table: PgTable<any>): SQL[];
75
75
  /**
76
76
  * Build a unique field check condition
77
77
  */
@@ -15,6 +15,8 @@ export interface AuthCapabilities {
15
15
  sessionManagement?: boolean;
16
16
  profileUpdate?: boolean;
17
17
  emailVerification?: boolean;
18
+ /** List of enabled OAuth provider IDs (e.g. ["google", "github", "discord"]) */
19
+ enabledProviders?: string[];
18
20
  }
19
21
  /**
20
22
  * Controller for retrieving the logged user or performing auth related operations.
@@ -1,9 +1,10 @@
1
1
  import { User } from "../users";
2
2
  import { RebaseData } from "./data";
3
+ import { EmailService } from "./email";
3
4
  /**
4
5
  * Event type for authentication state changes
5
6
  */
6
- export type AuthChangeEvent = 'SIGNED_IN' | 'SIGNED_OUT' | 'TOKEN_REFRESHED' | 'USER_UPDATED';
7
+ export type AuthChangeEvent = "SIGNED_IN" | "SIGNED_OUT" | "TOKEN_REFRESHED" | "USER_UPDATED";
7
8
  /**
8
9
  * Standard session interface representing an authenticated state
9
10
  */
@@ -39,20 +40,131 @@ export interface AuthClient {
39
40
  * Manually refresh the session token
40
41
  */
41
42
  refreshSession(): Promise<RebaseSession>;
42
- [key: string]: any;
43
43
  }
44
44
  /**
45
- * Overarching abstraction that unites Data, Auth, and Storage.
45
+ * User record as returned by the Admin API.
46
+ * @group Admin
47
+ */
48
+ export interface AdminUser {
49
+ uid: string;
50
+ email: string;
51
+ displayName: string | null;
52
+ photoURL: string | null;
53
+ provider: string;
54
+ roles: string[];
55
+ createdAt: string;
56
+ updatedAt: string;
57
+ }
58
+ /**
59
+ * Role record as returned by the Admin API.
60
+ * @group Admin
61
+ */
62
+ export interface AdminRole {
63
+ id: string;
64
+ name: string;
65
+ isAdmin: boolean;
66
+ defaultPermissions: Record<string, unknown> | null;
67
+ config: Record<string, unknown> | null;
68
+ }
69
+ /**
70
+ * Client-side Admin API interface.
71
+ * Provides user and role management operations.
72
+ * @group Admin
73
+ */
74
+ export interface AdminAPI {
75
+ listUsers(): Promise<{
76
+ users: AdminUser[];
77
+ }>;
78
+ listUsersPaginated(options?: {
79
+ search?: string;
80
+ limit?: number;
81
+ offset?: number;
82
+ orderBy?: string;
83
+ orderDir?: "asc" | "desc";
84
+ }): Promise<{
85
+ users: AdminUser[];
86
+ total: number;
87
+ limit: number;
88
+ offset: number;
89
+ }>;
90
+ getUser(userId: string): Promise<{
91
+ user: AdminUser;
92
+ }>;
93
+ createUser(data: {
94
+ email: string;
95
+ displayName?: string;
96
+ password?: string;
97
+ roles?: string[];
98
+ }): Promise<{
99
+ user: AdminUser;
100
+ }>;
101
+ updateUser(userId: string, data: {
102
+ email?: string;
103
+ displayName?: string;
104
+ password?: string;
105
+ roles?: string[];
106
+ }): Promise<{
107
+ user: AdminUser;
108
+ }>;
109
+ deleteUser(userId: string): Promise<{
110
+ success: boolean;
111
+ }>;
112
+ listRoles(): Promise<{
113
+ roles: AdminRole[];
114
+ }>;
115
+ getRole(roleId: string): Promise<{
116
+ role: AdminRole;
117
+ }>;
118
+ createRole(data: {
119
+ id: string;
120
+ name: string;
121
+ isAdmin?: boolean;
122
+ defaultPermissions?: Record<string, unknown>;
123
+ config?: Record<string, unknown>;
124
+ }): Promise<{
125
+ role: AdminRole;
126
+ }>;
127
+ updateRole(roleId: string, data: {
128
+ name?: string;
129
+ isAdmin?: boolean;
130
+ defaultPermissions?: Record<string, unknown>;
131
+ config?: Record<string, unknown>;
132
+ }): Promise<{
133
+ role: AdminRole;
134
+ }>;
135
+ deleteRole(roleId: string): Promise<{
136
+ success: boolean;
137
+ }>;
138
+ bootstrap(): Promise<{
139
+ success: boolean;
140
+ message: string;
141
+ user: {
142
+ uid: string;
143
+ roles: string[];
144
+ };
145
+ }>;
146
+ }
147
+ /**
148
+ * Overarching abstraction that unites Data, Auth, Storage, and Email.
46
149
  * Adapters for Supabase or Firebase simply need to implement this interface.
47
150
  */
48
- export interface RebaseClient<DB = any> {
151
+ export interface RebaseClient<DB = unknown> {
49
152
  /** Unified Data access layer */
50
153
  data: RebaseData;
51
154
  /** Unified Authentication layer */
52
155
  auth: AuthClient;
53
156
  /** Unified Storage layer */
54
157
  storage?: StorageSource;
55
- /** Optional admin panel specific tasks */
56
- admin?: any;
57
- [key: string]: any;
158
+ /**
159
+ * Server-side email service.
160
+ *
161
+ * Available when SMTP (or a custom `sendEmail` function) is configured
162
+ * in the backend auth config. `undefined` when email is not configured.
163
+ *
164
+ * > **Note:** This is only available on the server-side `rebase` singleton.
165
+ * > The client-side SDK does not include an email service.
166
+ */
167
+ email?: EmailService;
168
+ /** Admin API for user and role management */
169
+ admin?: AdminAPI;
58
170
  }
@@ -1,9 +1,10 @@
1
- import { EntityCollection, EntityReference } from "../types";
1
+ import type { EntityCollection } from "../types/collections";
2
+ import type { EntityReference } from "../types/entities";
2
3
  /**
3
4
  * Controller that provides access to the registered entity collections.
4
5
  * @group Models
5
6
  */
6
- export type CollectionRegistryController<EC extends EntityCollection = EntityCollection<any>> = {
7
+ export type CollectionRegistryController<DB = Record<string, unknown>, EC extends EntityCollection = EntityCollection<any>> = {
7
8
  /**
8
9
  * List of the mapped collections in the CMS.
9
10
  * Each entry relates to a collection in the root database.
@@ -19,7 +20,7 @@ export type CollectionRegistryController<EC extends EntityCollection = EntityCol
19
20
  * Get the collection configuration for a given path.
20
21
  * The collection is resolved from the given path or alias.
21
22
  */
22
- getCollection: (slugOrPath: string, includeUserOverride?: boolean) => EC | undefined;
23
+ getCollection: <K extends keyof DB>(slugOrPath: Extract<K, string>, includeUserOverride?: boolean) => EC | undefined;
23
24
  /**
24
25
  * Get the raw, un-normalized collection configuration.
25
26
  * This bypasses the `CollectionRegistry` normalization (such as injecting `relation` instances).
@@ -1,5 +1,11 @@
1
1
  import React from "react";
2
- import { EntityLinkBuilder, Locale, EntityAction, EntityCustomView, RebasePlugin, PropertyConfig, SlotContribution } from "../types";
2
+ import type { EntityLinkBuilder } from "../types/entity_link_builder";
3
+ import type { Locale } from "../types/locales";
4
+ import type { EntityAction } from "../types/entity_actions";
5
+ import type { EntityCustomView } from "../types/entity_views";
6
+ import type { RebasePlugin } from "../types/plugins";
7
+ import type { PropertyConfig } from "../types/property_config";
8
+ import type { SlotContribution } from "../types/slots";
3
9
  export type CustomizationController = {
4
10
  /**
5
11
  * Builder for generating utility links for entities
@@ -6,6 +6,19 @@ import { Entity, EntityValues } from "../types/entities";
6
6
  *
7
7
  * @group Data
8
8
  */
9
+ /**
10
+ * A where-clause value for a single field.
11
+ *
12
+ * Supports three syntaxes:
13
+ * 1. **Equality shorthand**: raw JS values — `null`, `"active"`, `42`, `true`
14
+ * 2. **Tuple syntax**: `[operator, value]` — `[">", 18]`, `["in", ["a","b"]]`
15
+ * 3. **PostgREST string**: `"eq.published"`, `"gte.18"`, `"in.(a,b)"`
16
+ *
17
+ * @group Data
18
+ */
19
+ export type WhereFieldValue = string | number | boolean | null | [WhereFilterOpShort, any];
20
+ /** Short operator strings accepted in the tuple syntax. */
21
+ export type WhereFilterOpShort = "==" | "!=" | ">" | ">=" | "<" | "<=" | "eq" | "neq" | "gt" | "gte" | "lt" | "lte" | "in" | "nin" | "not-in" | "array-contains" | "array-contains-any" | "cs" | "csa";
9
22
  export interface FindParams {
10
23
  /** Maximum number of items to return (default: 20) */
11
24
  limit?: number;
@@ -14,16 +27,30 @@ export interface FindParams {
14
27
  /** Page number (1-indexed), alternative to offset */
15
28
  page?: number;
16
29
  /**
17
- * PostgREST-style filter object.
18
- * Keys are field names, values use "operator.value" format.
19
- * Operators: eq, neq, gt, gte, lt, lte, in, nin, cs (array-contains), csa (array-contains-any)
30
+ * Filter object. Supports multiple syntaxes per field:
20
31
  *
21
- * @example
32
+ * **Equality shorthand** — raw JS values (null, string, number, boolean):
33
+ * ```ts
34
+ * { company_profile_id: null }
35
+ * { status: "active" }
36
+ * { age: 18 }
37
+ * ```
38
+ *
39
+ * **Tuple syntax** — `[operator, value]`:
40
+ * ```ts
41
+ * { age: [">=", 18] }
42
+ * { role: ["in", ["admin", "editor"]] }
43
+ * { deleted_at: ["!=", null] }
44
+ * ```
45
+ *
46
+ * **PostgREST string syntax** (original format):
47
+ * ```ts
22
48
  * { status: "eq.published" }
23
49
  * { age: "gte.18" }
24
50
  * { role: "in.(admin,editor)" }
51
+ * ```
25
52
  */
26
- where?: Record<string, string>;
53
+ where?: Record<string, WhereFieldValue>;
27
54
  /**
28
55
  * Sort order. Format: "field:direction".
29
56
  * @example "created_at:desc", "name:asc"
@@ -38,7 +65,7 @@ export interface FindParams {
38
65
  * Paginated response from a collection query.
39
66
  * @group Data
40
67
  */
41
- export interface FindResponse<M extends Record<string, any> = any> {
68
+ export interface FindResponse<M extends Record<string, unknown> = Record<string, unknown>> {
42
69
  /** Array of entities matching the query */
43
70
  data: Entity<M>[];
44
71
  /** Pagination metadata */
@@ -58,7 +85,7 @@ export interface FindResponse<M extends Record<string, any> = any> {
58
85
  *
59
86
  * @group Data
60
87
  */
61
- export interface CollectionAccessor<M extends Record<string, any> = any> {
88
+ export interface CollectionAccessor<M extends Record<string, unknown> = Record<string, unknown>> {
62
89
  /**
63
90
  * Find multiple records with optional filtering, pagination, and sorting.
64
91
  */
@@ -1,30 +1,31 @@
1
- import { Entity, EntityCollection, EntityStatus, EntityValues, FilterValues } from "../types";
2
- import { RebaseContext } from "../rebase_context";
3
- import { TableMetadata } from "../types/websockets";
1
+ import type { Entity, EntityStatus, EntityValues } from "../types/entities";
2
+ import type { EntityCollection, FilterValues } from "../types/collections";
3
+ import type { RebaseContext } from "../rebase_context";
4
4
  /**
5
5
  * @internal
6
6
  */
7
- export interface FetchEntityProps<M extends Record<string, any> = any> {
7
+ export interface FetchEntityProps<M extends Record<string, unknown> = Record<string, unknown>> {
8
8
  path: string;
9
9
  entityId: string | number;
10
10
  databaseId?: string;
11
- collection?: EntityCollection<M, any>;
11
+ collection?: EntityCollection<M>;
12
12
  }
13
13
  /**
14
14
  * @internal
15
15
  */
16
- export type ListenEntityProps<M extends Record<string, any> = any> = FetchEntityProps<M> & {
16
+ export type ListenEntityProps<M extends Record<string, unknown> = Record<string, unknown>> = FetchEntityProps<M> & {
17
17
  onUpdate: (entity: Entity<M> | null) => void;
18
18
  onError?: (error: Error) => void;
19
19
  };
20
20
  /**
21
21
  * @internal
22
22
  */
23
- export interface FetchCollectionProps<M extends Record<string, any> = any> {
23
+ export interface FetchCollectionProps<M extends Record<string, unknown> = Record<string, unknown>> {
24
24
  path: string;
25
25
  collection?: EntityCollection<M>;
26
26
  filter?: FilterValues<Extract<keyof M, string>>;
27
27
  limit?: number;
28
+ offset?: number;
28
29
  startAfter?: unknown;
29
30
  orderBy?: string;
30
31
  searchString?: string;
@@ -33,14 +34,14 @@ export interface FetchCollectionProps<M extends Record<string, any> = any> {
33
34
  /**
34
35
  * @internal
35
36
  */
36
- export type ListenCollectionProps<M extends Record<string, any> = any> = FetchCollectionProps<M> & {
37
+ export type ListenCollectionProps<M extends Record<string, unknown> = Record<string, unknown>> = FetchCollectionProps<M> & {
37
38
  onUpdate: (entities: Entity<M>[]) => void;
38
39
  onError?: (error: Error) => void;
39
40
  };
40
41
  /**
41
42
  * @internal
42
43
  */
43
- export interface SaveEntityProps<M extends Record<string, any> = any> {
44
+ export interface SaveEntityProps<M extends Record<string, unknown> = Record<string, unknown>> {
44
45
  path: string;
45
46
  values: Partial<EntityValues<M>>;
46
47
  entityId?: string | number;
@@ -51,15 +52,15 @@ export interface SaveEntityProps<M extends Record<string, any> = any> {
51
52
  /**
52
53
  * @internal
53
54
  */
54
- export interface DeleteEntityProps<M extends Record<string, any> = any> {
55
+ export interface DeleteEntityProps<M extends Record<string, unknown> = Record<string, unknown>> {
55
56
  entity: Entity<M>;
56
57
  collection?: EntityCollection<M>;
57
58
  }
58
59
  export type FilterCombinationValidProps = {
59
60
  path: string;
60
61
  databaseId?: string;
61
- collection: EntityCollection<any>;
62
- filterValues: FilterValues<any>;
62
+ collection: EntityCollection;
63
+ filterValues: FilterValues<string>;
63
64
  sortBy?: [string, "asc" | "desc"];
64
65
  };
65
66
  /**
@@ -81,36 +82,36 @@ export interface DataDriver {
81
82
  * @param props
82
83
  * @return Promise of entities
83
84
  */
84
- fetchCollection<M extends Record<string, any> = any>(props: FetchCollectionProps<M>): Promise<Entity<M>[]>;
85
+ fetchCollection<M extends Record<string, unknown> = Record<string, unknown>>(props: FetchCollectionProps<M>): Promise<Entity<M>[]>;
85
86
  /**
86
87
  * Listen to a collection in a given path. If you don't implement this method
87
88
  * `fetchCollection` will be used instead, with no real time updates.
88
89
  * @param props
89
90
  * @return Function to cancel subscription
90
91
  */
91
- listenCollection?<M extends Record<string, any> = any>(props: ListenCollectionProps<M>): () => void;
92
+ listenCollection?<M extends Record<string, unknown> = Record<string, unknown>>(props: ListenCollectionProps<M>): () => void;
92
93
  /**
93
94
  * Retrieve an entity given a path and a collection
94
95
  * @param props
95
96
  */
96
- fetchEntity<M extends Record<string, any> = any>(props: FetchEntityProps<M>): Promise<Entity<M> | undefined>;
97
+ fetchEntity<M extends Record<string, unknown> = Record<string, unknown>>(props: FetchEntityProps<M>): Promise<Entity<M> | undefined>;
97
98
  /**
98
99
  * Get realtime updates on one entity.
99
100
  * @param props
100
101
  * @return Function to cancel subscription
101
102
  */
102
- listenEntity?<M extends Record<string, any> = any>(props: ListenEntityProps<M>): () => void;
103
+ listenEntity?<M extends Record<string, unknown> = Record<string, unknown>>(props: ListenEntityProps<M>): () => void;
103
104
  /**
104
105
  * Save entity to the specified path
105
106
  * @param props
106
107
  */
107
- saveEntity<M extends Record<string, any> = any>(props: SaveEntityProps<M>): Promise<Entity<M>>;
108
+ saveEntity<M extends Record<string, unknown> = Record<string, unknown>>(props: SaveEntityProps<M>): Promise<Entity<M>>;
108
109
  /**
109
110
  * Delete an entity
110
111
  * @param props
111
112
  * @return was the whole deletion flow successful
112
113
  */
113
- deleteEntity<M extends Record<string, any> = any>(props: DeleteEntityProps<M>): Promise<void>;
114
+ deleteEntity<M extends Record<string, unknown> = Record<string, unknown>>(props: DeleteEntityProps<M>): Promise<void>;
114
115
  /**
115
116
  * Check if the given property is unique in the given collection
116
117
  * @param path Collection path
@@ -124,7 +125,7 @@ export interface DataDriver {
124
125
  /**
125
126
  * Count the number of entities in a collection
126
127
  */
127
- countEntities?<M extends Record<string, any> = any>(props: FetchCollectionProps<M>): Promise<number>;
128
+ countEntities?<M extends Record<string, unknown> = Record<string, unknown>>(props: FetchCollectionProps<M>): Promise<number>;
128
129
  /**
129
130
  * Check if the given filter combination is valid
130
131
  * @param props
@@ -156,13 +157,4 @@ export interface DataDriver {
156
157
  * @see SchemaAdmin
157
158
  */
158
159
  admin?: import("../types/backend").DatabaseAdmin;
159
- executeSql?(sql: string, options?: {
160
- database?: string;
161
- role?: string;
162
- }): Promise<Record<string, unknown>[]>;
163
- fetchAvailableDatabases?(): Promise<string[]>;
164
- fetchAvailableRoles?(): Promise<string[]>;
165
- fetchCurrentDatabase?(): Promise<string | undefined>;
166
- fetchUnmappedTables?(mappedPaths?: string[]): Promise<string[]>;
167
- fetchTableMetadata?(tableName: string): Promise<TableMetadata>;
168
160
  }
@@ -7,5 +7,5 @@
7
7
  *
8
8
  * @group Admin
9
9
  */
10
- export type { SQLAdmin, DocumentAdmin, SchemaAdmin, DatabaseAdmin, HealthCheckResult, } from "../types/backend";
11
- export { isSQLAdmin, isDocumentAdmin, isSchemaAdmin, } from "../types/backend";
10
+ export type { SQLAdmin, DocumentAdmin, SchemaAdmin, DatabaseAdmin, HealthCheckResult } from "../types/backend";
11
+ export { isSQLAdmin, isDocumentAdmin, isSchemaAdmin } from "../types/backend";
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Email service types — portable interface shared by RebaseClient and server-core.
3
+ *
4
+ * The concrete SMTP implementation lives in `@rebasepro/server-core/email`.
5
+ * This file provides only the consumer-facing contract so that it can be
6
+ * referenced from `RebaseClient` without dragging in nodemailer.
7
+ */
8
+ /**
9
+ * Options for sending an email via the Rebase email service.
10
+ */
11
+ export interface EmailSendOptions {
12
+ /** Recipient email address(es). */
13
+ to: string | string[];
14
+ /** Email subject line. */
15
+ subject: string;
16
+ /** HTML body content. */
17
+ html: string;
18
+ /** Optional plain-text fallback. */
19
+ text?: string;
20
+ /** Optional reply-to address. */
21
+ replyTo?: string;
22
+ }
23
+ /**
24
+ * Abstraction over an email delivery backend.
25
+ *
26
+ * Implementations may use SMTP, AWS SES, Resend, Postmark, or any other
27
+ * provider — consumers only interact through this interface.
28
+ */
29
+ export interface EmailService {
30
+ /** Send a single email. */
31
+ send(options: EmailSendOptions): Promise<void>;
32
+ /** Returns `true` when the service has valid credentials / is ready to send. */
33
+ isConfigured(): boolean;
34
+ }
@@ -8,6 +8,7 @@ export * from "./local_config_persistence";
8
8
  export * from "./navigation";
9
9
  export * from "./effective_role";
10
10
  export * from "./storage";
11
+ export * from "./email";
11
12
  export * from "./client";
12
13
  export * from "./customization_controller";
13
14
  export * from "./side_entity_controller";
@@ -1,16 +1,16 @@
1
- import { EntityCollection } from "../types";
1
+ import type { EntityCollection } from "../types/collections";
2
2
  /**
3
3
  * @group Models
4
4
  */
5
- export type PartialEntityCollection<M extends Record<string, any> = any> = Partial<EntityCollection<M>>;
5
+ export type PartialEntityCollection<M extends Record<string, unknown> = Record<string, unknown>> = Partial<EntityCollection<M>>;
6
6
  /**
7
7
  * This interface is in charge of defining the controller that persists
8
8
  * modifications to a collection or collection, and retrieves them back from
9
9
  * a data source, such as local storage or Firestore.
10
10
  */
11
11
  export interface UserConfigurationPersistence {
12
- onCollectionModified: <M extends Record<string, any> = any>(path: string, partialCollection: PartialEntityCollection<M>) => void;
13
- getCollectionConfig: <M extends Record<string, any> = any>(path: string) => PartialEntityCollection<M>;
12
+ onCollectionModified: <M extends Record<string, unknown> = Record<string, unknown>>(path: string, partialCollection: PartialEntityCollection<M>) => void;
13
+ getCollectionConfig: <M extends Record<string, unknown> = Record<string, unknown>>(path: string) => PartialEntityCollection<M>;
14
14
  recentlyVisitedPaths: string[];
15
15
  setRecentlyVisitedPaths: (paths: string[]) => void;
16
16
  favouritePaths: string[];
@@ -1,6 +1,6 @@
1
1
  import React from "react";
2
- import { EntityCollection } from "../types/collections";
3
- import { RebasePlugin } from "../types/plugins";
2
+ import type { EntityCollection } from "../types/collections";
3
+ import type { RebasePlugin } from "../types/plugins";
4
4
  /**
5
5
  * Controller that handles URL path building and resolution.
6
6
  * @group Models
@@ -133,9 +133,9 @@ export interface AppView {
133
133
  description?: string;
134
134
  /**
135
135
  * Icon key to use in this view.
136
- * You can use any of the icons in the Material specs:
137
- * https://fonts.google.com/icons
138
- * e.g. 'account_tree' or 'person'
136
+ * You can use any of the icons in the Lucide specs:
137
+ * https://lucide.dev/icons/
138
+ * e.g. 'ShoppingCart' or 'User'
139
139
  * Find all the icons in https://rebase.pro/docs/icons
140
140
  */
141
141
  icon?: string | React.ReactNode;
@@ -1,6 +1,9 @@
1
1
  import { ReactNode } from "react";
2
- import { EntityCollection, EntityCollectionsBuilder, EntityCustomView, EntityAction } from "../types";
3
- import { AppView } from "./navigation";
2
+ import type { EntityCollection } from "../types/collections";
3
+ import type { EntityCollectionsBuilder } from "../types/builders";
4
+ import type { EntityCustomView } from "../types/entity_views";
5
+ import type { EntityAction } from "../types/entity_actions";
6
+ import type { AppView } from "./navigation";
4
7
  /**
5
8
  * Options to enable the built-in collection editor.
6
9
  * When provided to `<RebaseCMS>`, the editor is auto-wired as a native feature.
@@ -31,7 +34,7 @@ export interface RebaseCMSConfig<EC extends EntityCollection = any> {
31
34
  collectionEditor?: boolean | CollectionEditorOptions;
32
35
  }
33
36
  export interface RebaseStudioConfig {
34
- tools?: ("sql" | "js" | "rls" | "schema" | "storage")[];
37
+ tools?: ("sql" | "js" | "rls" | "schema" | "storage" | "cron" | "schema-visualizer" | "branches" | "api")[];
35
38
  homePage?: ReactNode;
36
39
  devViews?: AppView[];
37
40
  }