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

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 (147) hide show
  1. package/LICENSE +6 -0
  2. package/README.md +106 -0
  3. package/build-errors.txt +37 -0
  4. package/dist/common/src/collections/CollectionRegistry.d.ts +48 -0
  5. package/dist/common/src/collections/index.d.ts +1 -0
  6. package/dist/common/src/data/buildRebaseData.d.ts +14 -0
  7. package/dist/common/src/index.d.ts +3 -0
  8. package/dist/common/src/util/builders.d.ts +57 -0
  9. package/dist/common/src/util/callbacks.d.ts +6 -0
  10. package/dist/common/src/util/collections.d.ts +11 -0
  11. package/dist/common/src/util/common.d.ts +2 -0
  12. package/dist/common/src/util/conditions.d.ts +26 -0
  13. package/dist/common/src/util/entities.d.ts +36 -0
  14. package/dist/common/src/util/enums.d.ts +3 -0
  15. package/dist/common/src/util/index.d.ts +16 -0
  16. package/dist/common/src/util/navigation_from_path.d.ts +34 -0
  17. package/dist/common/src/util/navigation_utils.d.ts +20 -0
  18. package/dist/common/src/util/parent_references_from_path.d.ts +6 -0
  19. package/dist/common/src/util/paths.d.ts +14 -0
  20. package/dist/common/src/util/permissions.d.ts +5 -0
  21. package/dist/common/src/util/references.d.ts +2 -0
  22. package/dist/common/src/util/relations.d.ts +12 -0
  23. package/dist/common/src/util/resolutions.d.ts +72 -0
  24. package/dist/common/src/util/storage.d.ts +24 -0
  25. package/dist/index.es.js +10635 -0
  26. package/dist/index.es.js.map +1 -0
  27. package/dist/index.umd.js +10643 -0
  28. package/dist/index.umd.js.map +1 -0
  29. package/dist/server-postgresql/src/PostgresBackendDriver.d.ts +112 -0
  30. package/dist/server-postgresql/src/PostgresBootstrapper.d.ts +40 -0
  31. package/dist/server-postgresql/src/auth/ensure-tables.d.ts +6 -0
  32. package/dist/server-postgresql/src/auth/services.d.ts +188 -0
  33. package/dist/server-postgresql/src/cli.d.ts +1 -0
  34. package/dist/server-postgresql/src/collections/PostgresCollectionRegistry.d.ts +43 -0
  35. package/dist/server-postgresql/src/connection.d.ts +7 -0
  36. package/dist/server-postgresql/src/data-transformer.d.ts +36 -0
  37. package/dist/server-postgresql/src/databasePoolManager.d.ts +20 -0
  38. package/dist/server-postgresql/src/history/HistoryService.d.ts +71 -0
  39. package/dist/server-postgresql/src/history/ensure-history-table.d.ts +7 -0
  40. package/dist/server-postgresql/src/index.d.ts +13 -0
  41. package/dist/server-postgresql/src/interfaces.d.ts +18 -0
  42. package/dist/server-postgresql/src/schema/auth-schema.d.ts +767 -0
  43. package/dist/server-postgresql/src/schema/generate-drizzle-schema-logic.d.ts +2 -0
  44. package/dist/server-postgresql/src/schema/generate-drizzle-schema.d.ts +1 -0
  45. package/dist/server-postgresql/src/services/BranchService.d.ts +47 -0
  46. package/dist/server-postgresql/src/services/EntityFetchService.d.ts +195 -0
  47. package/dist/server-postgresql/src/services/EntityPersistService.d.ts +41 -0
  48. package/dist/server-postgresql/src/services/RelationService.d.ts +92 -0
  49. package/dist/server-postgresql/src/services/entity-helpers.d.ts +24 -0
  50. package/dist/server-postgresql/src/services/entityService.d.ts +102 -0
  51. package/dist/server-postgresql/src/services/index.d.ts +4 -0
  52. package/dist/server-postgresql/src/services/realtimeService.d.ts +186 -0
  53. package/dist/server-postgresql/src/utils/drizzle-conditions.d.ts +116 -0
  54. package/dist/server-postgresql/src/websocket.d.ts +5 -0
  55. package/dist/types/src/controllers/analytics_controller.d.ts +7 -0
  56. package/dist/types/src/controllers/auth.d.ts +117 -0
  57. package/dist/types/src/controllers/client.d.ts +58 -0
  58. package/dist/types/src/controllers/collection_registry.d.ts +44 -0
  59. package/dist/types/src/controllers/customization_controller.d.ts +54 -0
  60. package/dist/types/src/controllers/data.d.ts +141 -0
  61. package/dist/types/src/controllers/data_driver.d.ts +168 -0
  62. package/dist/types/src/controllers/database_admin.d.ts +11 -0
  63. package/dist/types/src/controllers/dialogs_controller.d.ts +36 -0
  64. package/dist/types/src/controllers/effective_role.d.ts +4 -0
  65. package/dist/types/src/controllers/index.d.ts +17 -0
  66. package/dist/types/src/controllers/local_config_persistence.d.ts +20 -0
  67. package/dist/types/src/controllers/navigation.d.ts +213 -0
  68. package/dist/types/src/controllers/registry.d.ts +51 -0
  69. package/dist/types/src/controllers/side_dialogs_controller.d.ts +67 -0
  70. package/dist/types/src/controllers/side_entity_controller.d.ts +89 -0
  71. package/dist/types/src/controllers/snackbar.d.ts +24 -0
  72. package/dist/types/src/controllers/storage.d.ts +173 -0
  73. package/dist/types/src/index.d.ts +4 -0
  74. package/dist/types/src/rebase_context.d.ts +101 -0
  75. package/dist/types/src/types/backend.d.ts +533 -0
  76. package/dist/types/src/types/builders.d.ts +14 -0
  77. package/dist/types/src/types/chips.d.ts +5 -0
  78. package/dist/types/src/types/collections.d.ts +812 -0
  79. package/dist/types/src/types/data_source.d.ts +64 -0
  80. package/dist/types/src/types/entities.d.ts +145 -0
  81. package/dist/types/src/types/entity_actions.d.ts +98 -0
  82. package/dist/types/src/types/entity_callbacks.d.ts +173 -0
  83. package/dist/types/src/types/entity_link_builder.d.ts +7 -0
  84. package/dist/types/src/types/entity_overrides.d.ts +9 -0
  85. package/dist/types/src/types/entity_views.d.ts +61 -0
  86. package/dist/types/src/types/export_import.d.ts +21 -0
  87. package/dist/types/src/types/index.d.ts +22 -0
  88. package/dist/types/src/types/locales.d.ts +4 -0
  89. package/dist/types/src/types/modify_collections.d.ts +5 -0
  90. package/dist/types/src/types/plugins.d.ts +225 -0
  91. package/dist/types/src/types/properties.d.ts +1091 -0
  92. package/dist/types/src/types/property_config.d.ts +70 -0
  93. package/dist/types/src/types/relations.d.ts +336 -0
  94. package/dist/types/src/types/slots.d.ts +228 -0
  95. package/dist/types/src/types/translations.d.ts +826 -0
  96. package/dist/types/src/types/user_management_delegate.d.ts +120 -0
  97. package/dist/types/src/types/websockets.d.ts +78 -0
  98. package/dist/types/src/users/index.d.ts +2 -0
  99. package/dist/types/src/users/roles.d.ts +22 -0
  100. package/dist/types/src/users/user.d.ts +46 -0
  101. package/jest-all.log +3128 -0
  102. package/jest.log +49 -0
  103. package/package.json +93 -0
  104. package/src/PostgresBackendDriver.ts +1024 -0
  105. package/src/PostgresBootstrapper.ts +232 -0
  106. package/src/auth/ensure-tables.ts +309 -0
  107. package/src/auth/services.ts +740 -0
  108. package/src/cli.ts +347 -0
  109. package/src/collections/PostgresCollectionRegistry.ts +96 -0
  110. package/src/connection.ts +62 -0
  111. package/src/data-transformer.ts +569 -0
  112. package/src/databasePoolManager.ts +84 -0
  113. package/src/history/HistoryService.ts +257 -0
  114. package/src/history/ensure-history-table.ts +45 -0
  115. package/src/index.ts +13 -0
  116. package/src/interfaces.ts +60 -0
  117. package/src/schema/auth-schema.ts +146 -0
  118. package/src/schema/generate-drizzle-schema-logic.ts +618 -0
  119. package/src/schema/generate-drizzle-schema.ts +151 -0
  120. package/src/services/BranchService.ts +237 -0
  121. package/src/services/EntityFetchService.ts +1447 -0
  122. package/src/services/EntityPersistService.ts +351 -0
  123. package/src/services/RelationService.ts +1012 -0
  124. package/src/services/entity-helpers.ts +121 -0
  125. package/src/services/entityService.ts +209 -0
  126. package/src/services/index.ts +13 -0
  127. package/src/services/realtimeService.ts +1005 -0
  128. package/src/utils/drizzle-conditions.ts +999 -0
  129. package/src/websocket.ts +487 -0
  130. package/test/auth-services.test.ts +569 -0
  131. package/test/branchService.test.ts +357 -0
  132. package/test/drizzle-conditions.test.ts +895 -0
  133. package/test/entityService.errors.test.ts +352 -0
  134. package/test/entityService.relations.test.ts +912 -0
  135. package/test/entityService.subcollection-search.test.ts +516 -0
  136. package/test/entityService.test.ts +977 -0
  137. package/test/generate-drizzle-schema.test.ts +795 -0
  138. package/test/historyService.test.ts +126 -0
  139. package/test/postgresDataDriver.test.ts +556 -0
  140. package/test/realtimeService.test.ts +276 -0
  141. package/test/relations.test.ts +662 -0
  142. package/test_drizzle_mock.js +3 -0
  143. package/test_find_changed.mjs +30 -0
  144. package/test_output.txt +3145 -0
  145. package/tsconfig.json +49 -0
  146. package/tsconfig.prod.json +20 -0
  147. package/vite.config.ts +82 -0
@@ -0,0 +1,2 @@
1
+ import { EntityCollection } from "@rebasepro/types";
2
+ export declare const generateSchema: (collections: EntityCollection[]) => Promise<string>;
@@ -0,0 +1,47 @@
1
+ /**
2
+ * BranchService
3
+ *
4
+ * Manages database branching by creating/deleting PostgreSQL databases
5
+ * using `CREATE DATABASE ... TEMPLATE`. Branch metadata is stored in the
6
+ * `rebase.branches` table in the default (main) database, following the
7
+ * same `rebase` schema convention used by entity_history, auth, etc.
8
+ */
9
+ import { BranchInfo } from "@rebasepro/types";
10
+ import { DrizzleClient } from "../interfaces";
11
+ import { DatabasePoolManager } from "../databasePoolManager";
12
+ export declare class BranchService {
13
+ private db;
14
+ private poolManager;
15
+ constructor(db: DrizzleClient, poolManager: DatabasePoolManager);
16
+ /**
17
+ * Ensure the `rebase.branches` metadata table exists in the default database.
18
+ * Idempotent — safe to call on every startup.
19
+ */
20
+ ensureBranchMetadataTable(): Promise<void>;
21
+ /**
22
+ * Create a new branch database by templating the source database.
23
+ *
24
+ * Uses `CREATE DATABASE ... TEMPLATE` for an instant, full-fidelity copy
25
+ * of both schema and data.
26
+ *
27
+ * @param name User-facing branch name (e.g., "feature_auth")
28
+ * @param options.source Source database to clone; defaults to the main database.
29
+ */
30
+ createBranch(name: string, options?: {
31
+ source?: string;
32
+ }): Promise<BranchInfo>;
33
+ /**
34
+ * Delete a branch database and remove its metadata.
35
+ * Cannot delete the main/default database.
36
+ */
37
+ deleteBranch(name: string): Promise<void>;
38
+ /**
39
+ * List all branches recorded in the metadata table.
40
+ * Optionally fetches database sizes from pg_database.
41
+ */
42
+ listBranches(): Promise<BranchInfo[]>;
43
+ /**
44
+ * Get info about a specific branch.
45
+ */
46
+ getBranchInfo(name: string): Promise<BranchInfo | undefined>;
47
+ }
@@ -0,0 +1,195 @@
1
+ import { SQL } from "drizzle-orm";
2
+ import { PgTable } from "drizzle-orm/pg-core";
3
+ import { Entity, FilterValues } from "@rebasepro/types";
4
+ import { RelationService } from "./RelationService";
5
+ import { DrizzleClient } from "../interfaces";
6
+ import { PostgresCollectionRegistry } from "../collections/PostgresCollectionRegistry";
7
+ /**
8
+ * Service for handling all entity read operations.
9
+ * Handles fetching, searching, counting, and filtering entities.
10
+ */
11
+ export declare class EntityFetchService {
12
+ private db;
13
+ private registry;
14
+ private relationService;
15
+ constructor(db: DrizzleClient, registry: PostgresCollectionRegistry);
16
+ /**
17
+ * Get the relational query builder for a given table name.
18
+ * Safely narrows the DrizzleClient union type to access db.query[tableName].
19
+ */
20
+ private getQueryBuilder;
21
+ /**
22
+ * Build filter conditions from FilterValues
23
+ * Delegates to DrizzleConditionBuilder.buildFilterConditions
24
+ */
25
+ buildFilterConditions<M extends Record<string, any>>(filter: FilterValues<Extract<keyof M, string>>, table: PgTable<any>, collectionPath: string): SQL[];
26
+ /**
27
+ * Build the `with` config for Drizzle's relational query API.
28
+ * Converts collection relations to a Drizzle-compatible `with` object.
29
+ *
30
+ * When `include` is provided, only those relations are loaded.
31
+ * When `include` is absent, ALL relations are loaded (CMS path).
32
+ *
33
+ * Automatically detects many-to-many junction tables and nests
34
+ * the target relation so actual entity data is returned.
35
+ */
36
+ private buildWithConfig;
37
+ /**
38
+ * Detect if a many-to-many relation uses a junction table in the Drizzle schema.
39
+ */
40
+ private isJunctionRelation;
41
+ /**
42
+ * Get the Drizzle relation name on the junction table that points to the actual target entity.
43
+ * For example, for posts_tags junction, this returns "tag_id" (the relation pointing to tags).
44
+ */
45
+ private getJunctionTargetRelationName;
46
+ /**
47
+ * Convert a db.query result row (with nested relation objects) to an Entity<M>.
48
+ * Handles:
49
+ * - The { id, path, values } wrapping
50
+ * - Type normalization (dates, numbers, NaN) via normalizeDbValues
51
+ * - Converting nested relation objects to { id, path, __type: "relation" } for CMS
52
+ * - Flattening junction-table many-to-many results
53
+ */
54
+ private drizzleResultToEntity;
55
+ /**
56
+ * Post-fetch joinPath relations for a single entity.
57
+ * joinPath relations cannot be expressed via Drizzle's `with` config,
58
+ * so they must be loaded separately after the primary query.
59
+ */
60
+ private resolveJoinPathRelations;
61
+ /**
62
+ * Post-fetch joinPath relations for a batch of entities.
63
+ * Uses batch fetching to avoid N+1 queries for list views.
64
+ */
65
+ private resolveJoinPathRelationsBatch;
66
+ /**
67
+ * Convert a db.query result row to a flat REST-style object with populated relations.
68
+ */
69
+ private drizzleResultToRestRow;
70
+ /**
71
+ * Build db.query-compatible options from standard fetch options.
72
+ * Handles filter, search, orderBy, limit, and cursor-based pagination.
73
+ */
74
+ private buildDrizzleQueryOptions;
75
+ /**
76
+ * Extract cursor pagination conditions from startAfter options.
77
+ */
78
+ private buildCursorConditions;
79
+ /**
80
+ * Fetch a single entity by ID
81
+ */
82
+ fetchEntity<M extends Record<string, any>>(collectionPath: string, entityId: string | number, databaseId?: string): Promise<Entity<M> | undefined>;
83
+ /**
84
+ * Unified method to fetch entities with optional search functionality
85
+ */
86
+ fetchEntitiesWithConditions<M extends Record<string, any>>(collectionPath: string, options?: {
87
+ filter?: FilterValues<Extract<keyof M, string>>;
88
+ orderBy?: string;
89
+ order?: "desc" | "asc";
90
+ limit?: number;
91
+ startAfter?: Record<string, unknown>;
92
+ searchString?: string;
93
+ databaseId?: string;
94
+ }): Promise<Entity<M>[]>;
95
+ /**
96
+ * Fallback path used when db.query is unavailable.
97
+ * The primary path uses drizzleResultToEntity which handles relation
98
+ * mapping without N+1 queries.
99
+ *
100
+ * Process raw database results into Entity objects with relations.
101
+ */
102
+ private processEntityResults;
103
+ /**
104
+ * Fetch a collection of entities
105
+ */
106
+ fetchCollection<M extends Record<string, any>>(collectionPath: string, options?: {
107
+ filter?: FilterValues<Extract<keyof M, string>>;
108
+ orderBy?: string;
109
+ order?: "desc" | "asc";
110
+ limit?: number;
111
+ startAfter?: Record<string, unknown>;
112
+ searchString?: string;
113
+ databaseId?: string;
114
+ }): Promise<Entity<M>[]>;
115
+ /**
116
+ * Search entities by text
117
+ */
118
+ searchEntities<M extends Record<string, any>>(collectionPath: string, searchString: string, options?: {
119
+ filter?: FilterValues<Extract<keyof M, string>>;
120
+ orderBy?: string;
121
+ order?: "desc" | "asc";
122
+ limit?: number;
123
+ databaseId?: string;
124
+ }): Promise<Entity<M>[]>;
125
+ /**
126
+ * Fetch collection from multi-segment path
127
+ */
128
+ private fetchCollectionFromPath;
129
+ /**
130
+ * Count entities in a collection
131
+ */
132
+ countEntities<M extends Record<string, any>>(collectionPath: string, options?: {
133
+ filter?: FilterValues<Extract<keyof M, string>>;
134
+ databaseId?: string;
135
+ }): Promise<number>;
136
+ /**
137
+ * Count entities from multi-segment path
138
+ */
139
+ private countEntitiesFromPath;
140
+ /**
141
+ * Check if a field value is unique
142
+ */
143
+ checkUniqueField(collectionPath: string, fieldName: string, value: unknown, excludeEntityId?: string, _databaseId?: string): Promise<boolean>;
144
+ /**
145
+ * Get the RelationService instance for external use
146
+ */
147
+ getRelationService(): RelationService;
148
+ /**
149
+ * Fetch a collection of entities with optional relation includes.
150
+ * When `include` is provided, only the specified relations are populated
151
+ * with full entity data (not just { id, path, __type }).
152
+ * When `include` is absent, no relation queries are made (fast path).
153
+ *
154
+ * @param include - Array of relation keys to populate, or ["*"] for all
155
+ */
156
+ fetchCollectionForRest<M extends Record<string, any>>(collectionPath: string, options?: {
157
+ filter?: FilterValues<Extract<keyof M, string>>;
158
+ orderBy?: string;
159
+ order?: "desc" | "asc";
160
+ limit?: number;
161
+ startAfter?: Record<string, unknown>;
162
+ searchString?: string;
163
+ databaseId?: string;
164
+ }, include?: string[]): Promise<Record<string, unknown>[]>;
165
+ /**
166
+ * Fetch a single entity with optional relation includes for REST API.
167
+ */
168
+ fetchEntityForRest<M extends Record<string, any>>(collectionPath: string, entityId: string | number, include?: string[], databaseId?: string): Promise<Record<string, unknown> | null>;
169
+ /**
170
+ * Fetch raw rows without any relation processing (for REST fast path)
171
+ */
172
+ private fetchEntitiesWithConditionsRaw;
173
+ /**
174
+ * Check if the Drizzle instance has the relational query API available
175
+ * for a given collection path.
176
+ * Note: Primary path now uses inline `getQueryBuilder()` checks.
177
+ */
178
+ private hasDrizzleQueryAPI;
179
+ /**
180
+ * Attempt to use Drizzle's relational query API (db.query.<table>.findMany)
181
+ * for efficient JOIN-based relation loading.
182
+ * Returns null if the API is not available or the query fails.
183
+ * Note: Primary path now uses `buildWithConfig` + `buildDrizzleQueryOptions`.
184
+ */
185
+ private fetchWithDrizzleQuery;
186
+ /**
187
+ * Fallback path used when db.query is unavailable.
188
+ * The primary path uses db.query.findMany with `with` config, which
189
+ * loads all relations in a single query.
190
+ *
191
+ * Batch fetch many-to-many related entities for multiple parent IDs.
192
+ * Groups results by parent ID to avoid N+1.
193
+ */
194
+ private batchFetchManyRelatedEntities;
195
+ }
@@ -0,0 +1,41 @@
1
+ import { Entity } from "@rebasepro/types";
2
+ import { RelationService } from "./RelationService";
3
+ import { EntityFetchService } from "./EntityFetchService";
4
+ import { DrizzleClient } from "../interfaces";
5
+ import { PostgresCollectionRegistry } from "../collections/PostgresCollectionRegistry";
6
+ /**
7
+ * Service for handling all entity write operations.
8
+ * Handles saving, deleting, and updating entities.
9
+ */
10
+ export declare class EntityPersistService {
11
+ private db;
12
+ private registry;
13
+ private relationService;
14
+ private fetchService;
15
+ constructor(db: DrizzleClient, registry: PostgresCollectionRegistry);
16
+ /**
17
+ * Delete an entity by ID
18
+ */
19
+ deleteEntity(collectionPath: string, entityId: string | number, _databaseId?: string): Promise<void>;
20
+ /**
21
+ * Save an entity (create or update)
22
+ */
23
+ saveEntity<M extends Record<string, any>>(collectionPath: string, values: Partial<M>, entityId?: string | number, databaseId?: string): Promise<Entity<M>>;
24
+ /**
25
+ * Get the RelationService instance for external use
26
+ */
27
+ getRelationService(): RelationService;
28
+ /**
29
+ * Get the FetchService instance for external use
30
+ */
31
+ getFetchService(): EntityFetchService;
32
+ /**
33
+ * Translate raw PostgreSQL / Drizzle errors into user-friendly messages.
34
+ */
35
+ private toUserFriendlyError;
36
+ /**
37
+ * Extract the underlying PostgreSQL error from a Drizzle wrapper.
38
+ * Drizzle wraps PG errors in a `cause` property.
39
+ */
40
+ private extractPgError;
41
+ }
@@ -0,0 +1,92 @@
1
+ import { DrizzleClient } from "../interfaces";
2
+ import { Entity, EntityCollection, FilterValues, Relation } from "@rebasepro/types";
3
+ import { PostgresCollectionRegistry } from "../collections/PostgresCollectionRegistry";
4
+ /**
5
+ * Service for handling all relation-related operations.
6
+ * Handles fetching, updating, and managing entity relations.
7
+ */
8
+ export declare class RelationService {
9
+ private db;
10
+ private registry;
11
+ constructor(db: DrizzleClient, registry: PostgresCollectionRegistry);
12
+ /**
13
+ * Fetch entities related to a parent entity through a specific relation
14
+ */
15
+ fetchRelatedEntities<M extends Record<string, any>>(parentCollectionPath: string, parentEntityId: string | number, relationKey: string, options?: {
16
+ filter?: FilterValues<Extract<keyof M, string>>;
17
+ orderBy?: string;
18
+ order?: "desc" | "asc";
19
+ limit?: number;
20
+ startAfter?: Record<string, unknown>;
21
+ searchString?: string;
22
+ databaseId?: string;
23
+ }): Promise<Entity<M>[]>;
24
+ /**
25
+ * Fetch entities using join paths for complex relations
26
+ */
27
+ fetchEntitiesUsingJoins<M extends Record<string, any>>(parentCollection: EntityCollection, parentEntityId: string | number, relation: Relation, options?: {
28
+ filter?: FilterValues<Extract<keyof M, string>>;
29
+ orderBy?: string;
30
+ order?: "desc" | "asc";
31
+ limit?: number;
32
+ startAfter?: Record<string, unknown>;
33
+ searchString?: string;
34
+ databaseId?: string;
35
+ }): Promise<Entity<M>[]>;
36
+ /**
37
+ * Count related entities for a parent entity
38
+ */
39
+ countRelatedEntities<M extends Record<string, any>>(parentCollectionPath: string, parentEntityId: string | number, relationKey: string, options?: {
40
+ filter?: FilterValues<Extract<keyof M, string>>;
41
+ databaseId?: string;
42
+ }): Promise<number>;
43
+ /**
44
+ * Batch fetch related entities for multiple parent entities to avoid N+1 queries
45
+ */
46
+ batchFetchRelatedEntities(parentCollectionPath: string, parentEntityIds: (string | number)[], _relationKey: string, relation: Relation): Promise<Map<string | number, Entity<Record<string, unknown>>>>;
47
+ /**
48
+ * Update many-to-many and junction relations
49
+ */
50
+ updateRelationsUsingJoins<M extends Record<string, any>>(tx: DrizzleClient, collection: EntityCollection, entityId: string | number, relationValues: Partial<M>): Promise<void>;
51
+ /**
52
+ * Update inverse relations (where FK is on the target table)
53
+ */
54
+ updateInverseRelations(tx: DrizzleClient, sourceCollection: EntityCollection, sourceEntityId: string | number, inverseRelationUpdates: Array<{
55
+ relationKey: string;
56
+ relation: Relation;
57
+ newValue: unknown;
58
+ currentEntityId?: string | number;
59
+ }>): Promise<void>;
60
+ /**
61
+ * Handle inverse relations with joinPath
62
+ */
63
+ private updateInverseJoinPathRelation;
64
+ /**
65
+ * Handle many-to-many inverse relation updates using junction tables
66
+ */
67
+ private updateManyToManyInverseRelation;
68
+ /**
69
+ * Update one-to-one relations that use joinPath
70
+ */
71
+ updateJoinPathOneToOneRelations(tx: DrizzleClient, parentCollection: EntityCollection, parentEntityId: string | number, updates: Array<{
72
+ relationKey: string;
73
+ relation: Relation;
74
+ newTargetId: string | number | null;
75
+ }>): Promise<void>;
76
+ /**
77
+ * Resolve joinPath write mapping for one-to-one relations
78
+ */
79
+ resolveJoinPathWriteMapping(parentCollection: EntityCollection, relation: Relation): {
80
+ targetFKColName: string;
81
+ parentSourceColName: string;
82
+ };
83
+ /**
84
+ * Handle junction table creation for many-to-many path-based saves
85
+ */
86
+ handleJunctionTableCreation(tx: DrizzleClient, newEntityId: string | number, junctionTableInfo: {
87
+ parentCollection: EntityCollection;
88
+ parentId: string | number;
89
+ relation: Relation;
90
+ relationKey: string;
91
+ }): Promise<void>;
92
+ }
@@ -0,0 +1,24 @@
1
+ import { PgTable } from "drizzle-orm/pg-core";
2
+ import { EntityCollection } from "@rebasepro/types";
3
+ import { PostgresCollectionRegistry } from "../collections/PostgresCollectionRegistry";
4
+ /**
5
+ * Shared helper functions for entity operations.
6
+ * These are used by EntityFetchService, EntityPersistService, and RelationService.
7
+ *
8
+ * All functions that need collection/table lookups require an explicit
9
+ * `PostgresCollectionRegistry` instance — there is no global singleton.
10
+ */
11
+ export declare function getCollectionByPath(collectionPath: string, registry: PostgresCollectionRegistry): EntityCollection;
12
+ export declare function getTableForCollection(collection: EntityCollection, registry: PostgresCollectionRegistry): PgTable<any>;
13
+ export declare function getPrimaryKeys(collection: EntityCollection, registry: PostgresCollectionRegistry): {
14
+ fieldName: string;
15
+ type: "string" | "number";
16
+ }[];
17
+ export declare function parseIdValues(idValue: string | number, primaryKeys: {
18
+ fieldName: string;
19
+ type: "string" | "number";
20
+ }[]): Record<string, string | number>;
21
+ export declare function buildCompositeId(values: Record<string, any>, primaryKeys: {
22
+ fieldName: string;
23
+ type: "string" | "number";
24
+ }[]): string;
@@ -0,0 +1,102 @@
1
+ import { Entity, FilterValues } from "@rebasepro/types";
2
+ import { EntityFetchService } from "./EntityFetchService";
3
+ import { EntityPersistService } from "./EntityPersistService";
4
+ import { RelationService } from "./RelationService";
5
+ import { EntityRepository, DrizzleClient } from "../interfaces";
6
+ import { PostgresCollectionRegistry } from "../collections/PostgresCollectionRegistry";
7
+ export { sanitizeAndConvertDates, serializeDataToServer, parseDataFromServer } from "../data-transformer";
8
+ export { EntityFetchService } from "./EntityFetchService";
9
+ export { EntityPersistService } from "./EntityPersistService";
10
+ export { RelationService } from "./RelationService";
11
+ export * from "../interfaces";
12
+ /**
13
+ * EntityService - Facade for entity operations.
14
+ *
15
+ * This class provides a unified API for entity CRUD operations by delegating
16
+ * to specialized services:
17
+ * - EntityFetchService: Read operations (fetch, search, count)
18
+ * - EntityPersistService: Write operations (save, delete)
19
+ * - RelationService: Relation operations (fetch related, update relations)
20
+ *
21
+ * Implements the EntityRepository interface for database abstraction.
22
+ */
23
+ export declare class EntityService implements EntityRepository {
24
+ private db;
25
+ private registry;
26
+ private fetchService;
27
+ private persistService;
28
+ constructor(db: DrizzleClient, registry: PostgresCollectionRegistry);
29
+ /**
30
+ * Fetch a single entity by ID
31
+ */
32
+ fetchEntity<M extends Record<string, any>>(collectionPath: string, entityId: string | number, databaseId?: string): Promise<Entity<M> | undefined>;
33
+ /**
34
+ * Fetch a collection of entities with optional filtering, ordering, and pagination
35
+ */
36
+ fetchCollection<M extends Record<string, any>>(collectionPath: string, options?: {
37
+ filter?: FilterValues<Extract<keyof M, string>>;
38
+ orderBy?: string;
39
+ order?: "desc" | "asc";
40
+ limit?: number;
41
+ startAfter?: Record<string, unknown>;
42
+ searchString?: string;
43
+ databaseId?: string;
44
+ }): Promise<Entity<M>[]>;
45
+ /**
46
+ * Search entities by text
47
+ */
48
+ searchEntities<M extends Record<string, any>>(collectionPath: string, searchString: string, options?: {
49
+ filter?: FilterValues<Extract<keyof M, string>>;
50
+ orderBy?: string;
51
+ order?: "desc" | "asc";
52
+ limit?: number;
53
+ databaseId?: string;
54
+ }): Promise<Entity<M>[]>;
55
+ /**
56
+ * Count entities in a collection
57
+ */
58
+ countEntities<M extends Record<string, any>>(collectionPath: string, options?: {
59
+ filter?: FilterValues<Extract<keyof M, string>>;
60
+ databaseId?: string;
61
+ }): Promise<number>;
62
+ /**
63
+ * Check if a field value is unique in a collection
64
+ */
65
+ checkUniqueField(collectionPath: string, fieldName: string, value: unknown, excludeEntityId?: string, databaseId?: string): Promise<boolean>;
66
+ /**
67
+ * Fetch entities related to a parent entity
68
+ */
69
+ fetchRelatedEntities<M extends Record<string, any>>(parentCollectionPath: string, parentEntityId: string | number, relationKey: string, options?: {
70
+ filter?: FilterValues<Extract<keyof M, string>>;
71
+ orderBy?: string;
72
+ order?: "desc" | "asc";
73
+ limit?: number;
74
+ startAfter?: Record<string, unknown>;
75
+ searchString?: string;
76
+ databaseId?: string;
77
+ }): Promise<Entity<M>[]>;
78
+ /**
79
+ * Save an entity (create or update)
80
+ */
81
+ saveEntity<M extends Record<string, any>>(collectionPath: string, values: Partial<M>, entityId?: string | number, databaseId?: string): Promise<Entity<M>>;
82
+ /**
83
+ * Delete an entity by ID
84
+ */
85
+ deleteEntity(collectionPath: string, entityId: string | number, databaseId?: string): Promise<void>;
86
+ /**
87
+ * Execute raw SQL
88
+ */
89
+ executeSql(sqlText: string): Promise<Record<string, unknown>[]>;
90
+ /**
91
+ * Get the underlying EntityFetchService for advanced use
92
+ */
93
+ getFetchService(): EntityFetchService;
94
+ /**
95
+ * Get the underlying EntityPersistService for advanced use
96
+ */
97
+ getPersistService(): EntityPersistService;
98
+ /**
99
+ * Get the underlying RelationService for advanced use
100
+ */
101
+ getRelationService(): RelationService;
102
+ }
@@ -0,0 +1,4 @@
1
+ export { EntityFetchService } from "./EntityFetchService";
2
+ export { EntityPersistService } from "./EntityPersistService";
3
+ export { RelationService } from "./RelationService";
4
+ export { getCollectionByPath, getTableForCollection, getPrimaryKeys, parseIdValues, buildCompositeId } from "./entity-helpers";