@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.
- package/dist/common/src/collections/CollectionRegistry.d.ts +8 -0
- package/dist/common/src/util/entities.d.ts +22 -0
- package/dist/common/src/util/relations.d.ts +14 -4
- package/dist/common/src/util/resolutions.d.ts +1 -1
- package/dist/index.es.js +1254 -591
- package/dist/index.es.js.map +1 -1
- package/dist/index.umd.js +1254 -591
- package/dist/index.umd.js.map +1 -1
- package/dist/server-postgresql/src/PostgresBackendDriver.d.ts +17 -29
- package/dist/server-postgresql/src/auth/services.d.ts +7 -3
- package/dist/server-postgresql/src/collections/PostgresCollectionRegistry.d.ts +1 -1
- package/dist/server-postgresql/src/connection.d.ts +34 -1
- package/dist/server-postgresql/src/data-transformer.d.ts +26 -4
- package/dist/server-postgresql/src/databasePoolManager.d.ts +2 -2
- package/dist/server-postgresql/src/schema/auth-schema.d.ts +139 -38
- package/dist/server-postgresql/src/schema/doctor-cli.d.ts +2 -0
- package/dist/server-postgresql/src/schema/doctor.d.ts +43 -0
- package/dist/server-postgresql/src/schema/generate-drizzle-schema-logic.d.ts +1 -1
- package/dist/server-postgresql/src/schema/test-schema.d.ts +24 -0
- package/dist/server-postgresql/src/services/EntityFetchService.d.ts +22 -8
- package/dist/server-postgresql/src/services/EntityPersistService.d.ts +1 -1
- package/dist/server-postgresql/src/services/RelationService.d.ts +11 -5
- package/dist/server-postgresql/src/services/entity-helpers.d.ts +16 -2
- package/dist/server-postgresql/src/services/entityService.d.ts +8 -6
- package/dist/server-postgresql/src/services/realtimeService.d.ts +2 -0
- package/dist/server-postgresql/src/utils/drizzle-conditions.d.ts +2 -2
- package/dist/types/src/controllers/auth.d.ts +2 -0
- package/dist/types/src/controllers/client.d.ts +119 -7
- package/dist/types/src/controllers/collection_registry.d.ts +4 -3
- package/dist/types/src/controllers/customization_controller.d.ts +7 -1
- package/dist/types/src/controllers/data.d.ts +34 -7
- package/dist/types/src/controllers/data_driver.d.ts +20 -28
- package/dist/types/src/controllers/database_admin.d.ts +2 -2
- package/dist/types/src/controllers/email.d.ts +34 -0
- package/dist/types/src/controllers/index.d.ts +1 -0
- package/dist/types/src/controllers/local_config_persistence.d.ts +4 -4
- package/dist/types/src/controllers/navigation.d.ts +5 -5
- package/dist/types/src/controllers/registry.d.ts +6 -3
- package/dist/types/src/controllers/side_entity_controller.d.ts +7 -6
- package/dist/types/src/controllers/storage.d.ts +24 -26
- package/dist/types/src/rebase_context.d.ts +8 -4
- package/dist/types/src/types/backend.d.ts +4 -1
- package/dist/types/src/types/builders.d.ts +5 -4
- package/dist/types/src/types/chips.d.ts +1 -1
- package/dist/types/src/types/collections.d.ts +169 -125
- package/dist/types/src/types/cron.d.ts +102 -0
- package/dist/types/src/types/data_source.d.ts +1 -1
- package/dist/types/src/types/entity_actions.d.ts +8 -8
- package/dist/types/src/types/entity_callbacks.d.ts +15 -15
- package/dist/types/src/types/entity_link_builder.d.ts +1 -1
- package/dist/types/src/types/entity_overrides.d.ts +2 -1
- package/dist/types/src/types/entity_views.d.ts +8 -8
- package/dist/types/src/types/export_import.d.ts +3 -3
- package/dist/types/src/types/index.d.ts +1 -0
- package/dist/types/src/types/plugins.d.ts +72 -18
- package/dist/types/src/types/properties.d.ts +118 -33
- package/dist/types/src/types/relations.d.ts +1 -1
- package/dist/types/src/types/slots.d.ts +30 -6
- package/dist/types/src/types/translations.d.ts +44 -0
- package/dist/types/src/types/user_management_delegate.d.ts +1 -0
- package/drizzle-test/0000_woozy_junta.sql +6 -0
- package/drizzle-test/0001_youthful_arachne.sql +1 -0
- package/drizzle-test/0002_lively_dragon_lord.sql +2 -0
- package/drizzle-test/0003_mean_king_cobra.sql +2 -0
- package/drizzle-test/meta/0000_snapshot.json +47 -0
- package/drizzle-test/meta/0001_snapshot.json +48 -0
- package/drizzle-test/meta/0002_snapshot.json +38 -0
- package/drizzle-test/meta/0003_snapshot.json +48 -0
- package/drizzle-test/meta/_journal.json +34 -0
- package/drizzle-test-out/0000_tan_trauma.sql +6 -0
- package/drizzle-test-out/0001_rapid_drax.sql +1 -0
- package/drizzle-test-out/meta/0000_snapshot.json +44 -0
- package/drizzle-test-out/meta/0001_snapshot.json +54 -0
- package/drizzle-test-out/meta/_journal.json +20 -0
- package/drizzle.test.config.ts +10 -0
- package/package.json +88 -89
- package/scratch.ts +41 -0
- package/src/PostgresBackendDriver.ts +63 -79
- package/src/PostgresBootstrapper.ts +7 -8
- package/src/auth/ensure-tables.ts +158 -86
- package/src/auth/services.ts +109 -50
- package/src/cli.ts +259 -16
- package/src/collections/PostgresCollectionRegistry.ts +6 -6
- package/src/connection.ts +70 -48
- package/src/data-transformer.ts +155 -116
- package/src/databasePoolManager.ts +6 -5
- package/src/history/HistoryService.ts +3 -12
- package/src/interfaces.ts +3 -3
- package/src/schema/auth-schema.ts +26 -3
- package/src/schema/doctor-cli.ts +47 -0
- package/src/schema/doctor.ts +595 -0
- package/src/schema/generate-drizzle-schema-logic.ts +204 -57
- package/src/schema/generate-drizzle-schema.ts +6 -6
- package/src/schema/test-schema.ts +11 -0
- package/src/services/BranchService.ts +5 -5
- package/src/services/EntityFetchService.ts +317 -188
- package/src/services/EntityPersistService.ts +15 -17
- package/src/services/RelationService.ts +299 -37
- package/src/services/entity-helpers.ts +39 -13
- package/src/services/entityService.ts +11 -9
- package/src/services/realtimeService.ts +58 -29
- package/src/utils/drizzle-conditions.ts +25 -24
- package/src/websocket.ts +52 -21
- package/test/auth-services.test.ts +131 -39
- package/test/batch-many-to-many-regression.test.ts +573 -0
- package/test/branchService.test.ts +22 -12
- package/test/data-transformer-hardening.test.ts +417 -0
- package/test/data-transformer.test.ts +175 -0
- package/test/doctor.test.ts +182 -0
- package/test/entityService.errors.test.ts +31 -16
- package/test/entityService.relations.test.ts +155 -59
- package/test/entityService.subcollection-search.test.ts +107 -57
- package/test/entityService.test.ts +105 -47
- package/test/generate-drizzle-schema.test.ts +262 -69
- package/test/historyService.test.ts +31 -16
- package/test/n-plus-one-regression.test.ts +314 -0
- package/test/postgresDataDriver.test.ts +260 -168
- package/test/realtimeService.test.ts +70 -39
- package/test/relation-pipeline-gaps.test.ts +637 -0
- package/test/relations.test.ts +492 -39
- package/test-drizzle-bug.ts +18 -0
- package/test-drizzle-out/0000_cultured_freak.sql +7 -0
- package/test-drizzle-out/0001_tiresome_professor_monster.sql +1 -0
- package/test-drizzle-out/meta/0000_snapshot.json +55 -0
- package/test-drizzle-out/meta/0001_snapshot.json +63 -0
- package/test-drizzle-out/meta/_journal.json +20 -0
- package/test-drizzle-prompt.sh +2 -0
- package/test-policy-prompt.sh +3 -0
- package/test-programmatic.ts +30 -0
- package/test-programmatic2.ts +59 -0
- package/test-schema-no-policies.ts +12 -0
- package/test_drizzle_mock.js +2 -2
- package/test_find_changed.mjs +3 -1
- package/test_hash.js +14 -0
- package/tsconfig.json +1 -1
- 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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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 =
|
|
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
|
-
*
|
|
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 =
|
|
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
|
-
/**
|
|
56
|
-
|
|
57
|
-
|
|
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
|
|
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:
|
|
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
|
|
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
|
-
*
|
|
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
|
-
*
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
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,
|
|
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
|
|
11
|
+
collection?: EntityCollection<M>;
|
|
12
12
|
}
|
|
13
13
|
/**
|
|
14
14
|
* @internal
|
|
15
15
|
*/
|
|
16
|
-
export type ListenEntityProps<M extends Record<string,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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
|
|
62
|
-
filterValues: FilterValues<
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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
|
|
11
|
-
export { isSQLAdmin, isDocumentAdmin, isSchemaAdmin
|
|
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,
|
|
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,
|
|
13
|
-
getCollectionConfig: <M extends Record<string,
|
|
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
|
|
137
|
-
* https://
|
|
138
|
-
* e.g. '
|
|
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
|
|
3
|
-
import {
|
|
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
|
}
|