@rebasepro/server-postgresql 0.0.1-canary.09e5ec5

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 (196) 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 +56 -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 +58 -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 +22 -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 +11298 -0
  26. package/dist/index.es.js.map +1 -0
  27. package/dist/index.umd.js +11306 -0
  28. package/dist/index.umd.js.map +1 -0
  29. package/dist/server-postgresql/src/PostgresBackendDriver.d.ts +100 -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 +192 -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 +40 -0
  36. package/dist/server-postgresql/src/data-transformer.d.ts +58 -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 +868 -0
  43. package/dist/server-postgresql/src/schema/doctor-cli.d.ts +2 -0
  44. package/dist/server-postgresql/src/schema/doctor.d.ts +43 -0
  45. package/dist/server-postgresql/src/schema/generate-drizzle-schema-logic.d.ts +2 -0
  46. package/dist/server-postgresql/src/schema/generate-drizzle-schema.d.ts +1 -0
  47. package/dist/server-postgresql/src/schema/introspect-db-logic.d.ts +82 -0
  48. package/dist/server-postgresql/src/schema/introspect-db.d.ts +1 -0
  49. package/dist/server-postgresql/src/schema/test-schema.d.ts +24 -0
  50. package/dist/server-postgresql/src/services/BranchService.d.ts +47 -0
  51. package/dist/server-postgresql/src/services/EntityFetchService.d.ts +209 -0
  52. package/dist/server-postgresql/src/services/EntityPersistService.d.ts +41 -0
  53. package/dist/server-postgresql/src/services/RelationService.d.ts +98 -0
  54. package/dist/server-postgresql/src/services/entity-helpers.d.ts +38 -0
  55. package/dist/server-postgresql/src/services/entityService.d.ts +104 -0
  56. package/dist/server-postgresql/src/services/index.d.ts +4 -0
  57. package/dist/server-postgresql/src/services/realtimeService.d.ts +188 -0
  58. package/dist/server-postgresql/src/utils/drizzle-conditions.d.ts +116 -0
  59. package/dist/server-postgresql/src/websocket.d.ts +5 -0
  60. package/dist/types/src/controllers/analytics_controller.d.ts +7 -0
  61. package/dist/types/src/controllers/auth.d.ts +119 -0
  62. package/dist/types/src/controllers/client.d.ts +170 -0
  63. package/dist/types/src/controllers/collection_registry.d.ts +45 -0
  64. package/dist/types/src/controllers/customization_controller.d.ts +60 -0
  65. package/dist/types/src/controllers/data.d.ts +168 -0
  66. package/dist/types/src/controllers/data_driver.d.ts +160 -0
  67. package/dist/types/src/controllers/database_admin.d.ts +11 -0
  68. package/dist/types/src/controllers/dialogs_controller.d.ts +36 -0
  69. package/dist/types/src/controllers/effective_role.d.ts +4 -0
  70. package/dist/types/src/controllers/email.d.ts +34 -0
  71. package/dist/types/src/controllers/index.d.ts +18 -0
  72. package/dist/types/src/controllers/local_config_persistence.d.ts +20 -0
  73. package/dist/types/src/controllers/navigation.d.ts +213 -0
  74. package/dist/types/src/controllers/registry.d.ts +54 -0
  75. package/dist/types/src/controllers/side_dialogs_controller.d.ts +67 -0
  76. package/dist/types/src/controllers/side_entity_controller.d.ts +90 -0
  77. package/dist/types/src/controllers/snackbar.d.ts +24 -0
  78. package/dist/types/src/controllers/storage.d.ts +171 -0
  79. package/dist/types/src/index.d.ts +4 -0
  80. package/dist/types/src/rebase_context.d.ts +105 -0
  81. package/dist/types/src/types/backend.d.ts +536 -0
  82. package/dist/types/src/types/builders.d.ts +15 -0
  83. package/dist/types/src/types/chips.d.ts +5 -0
  84. package/dist/types/src/types/collections.d.ts +856 -0
  85. package/dist/types/src/types/cron.d.ts +102 -0
  86. package/dist/types/src/types/data_source.d.ts +64 -0
  87. package/dist/types/src/types/entities.d.ts +145 -0
  88. package/dist/types/src/types/entity_actions.d.ts +98 -0
  89. package/dist/types/src/types/entity_callbacks.d.ts +173 -0
  90. package/dist/types/src/types/entity_link_builder.d.ts +7 -0
  91. package/dist/types/src/types/entity_overrides.d.ts +10 -0
  92. package/dist/types/src/types/entity_views.d.ts +61 -0
  93. package/dist/types/src/types/export_import.d.ts +21 -0
  94. package/dist/types/src/types/index.d.ts +23 -0
  95. package/dist/types/src/types/locales.d.ts +4 -0
  96. package/dist/types/src/types/modify_collections.d.ts +5 -0
  97. package/dist/types/src/types/plugins.d.ts +279 -0
  98. package/dist/types/src/types/properties.d.ts +1176 -0
  99. package/dist/types/src/types/property_config.d.ts +70 -0
  100. package/dist/types/src/types/relations.d.ts +336 -0
  101. package/dist/types/src/types/slots.d.ts +252 -0
  102. package/dist/types/src/types/translations.d.ts +870 -0
  103. package/dist/types/src/types/user_management_delegate.d.ts +121 -0
  104. package/dist/types/src/types/websockets.d.ts +78 -0
  105. package/dist/types/src/users/index.d.ts +2 -0
  106. package/dist/types/src/users/roles.d.ts +22 -0
  107. package/dist/types/src/users/user.d.ts +46 -0
  108. package/drizzle-test/0000_woozy_junta.sql +6 -0
  109. package/drizzle-test/0001_youthful_arachne.sql +1 -0
  110. package/drizzle-test/0002_lively_dragon_lord.sql +2 -0
  111. package/drizzle-test/0003_mean_king_cobra.sql +2 -0
  112. package/drizzle-test/meta/0000_snapshot.json +47 -0
  113. package/drizzle-test/meta/0001_snapshot.json +48 -0
  114. package/drizzle-test/meta/0002_snapshot.json +38 -0
  115. package/drizzle-test/meta/0003_snapshot.json +48 -0
  116. package/drizzle-test/meta/_journal.json +34 -0
  117. package/drizzle-test-out/0000_tan_trauma.sql +6 -0
  118. package/drizzle-test-out/0001_rapid_drax.sql +1 -0
  119. package/drizzle-test-out/meta/0000_snapshot.json +44 -0
  120. package/drizzle-test-out/meta/0001_snapshot.json +54 -0
  121. package/drizzle-test-out/meta/_journal.json +20 -0
  122. package/drizzle.test.config.ts +10 -0
  123. package/jest-all.log +3128 -0
  124. package/jest.log +49 -0
  125. package/package.json +92 -0
  126. package/scratch.ts +41 -0
  127. package/src/PostgresBackendDriver.ts +1008 -0
  128. package/src/PostgresBootstrapper.ts +231 -0
  129. package/src/auth/ensure-tables.ts +381 -0
  130. package/src/auth/services.ts +799 -0
  131. package/src/cli.ts +648 -0
  132. package/src/collections/PostgresCollectionRegistry.ts +96 -0
  133. package/src/connection.ts +84 -0
  134. package/src/data-transformer.ts +608 -0
  135. package/src/databasePoolManager.ts +85 -0
  136. package/src/history/HistoryService.ts +248 -0
  137. package/src/history/ensure-history-table.ts +45 -0
  138. package/src/index.ts +13 -0
  139. package/src/interfaces.ts +60 -0
  140. package/src/schema/auth-schema.ts +169 -0
  141. package/src/schema/doctor-cli.ts +47 -0
  142. package/src/schema/doctor.ts +595 -0
  143. package/src/schema/generate-drizzle-schema-logic.ts +765 -0
  144. package/src/schema/generate-drizzle-schema.ts +151 -0
  145. package/src/schema/introspect-db-logic.ts +542 -0
  146. package/src/schema/introspect-db.ts +211 -0
  147. package/src/schema/test-schema.ts +11 -0
  148. package/src/services/BranchService.ts +237 -0
  149. package/src/services/EntityFetchService.ts +1576 -0
  150. package/src/services/EntityPersistService.ts +349 -0
  151. package/src/services/RelationService.ts +1274 -0
  152. package/src/services/entity-helpers.ts +147 -0
  153. package/src/services/entityService.ts +211 -0
  154. package/src/services/index.ts +13 -0
  155. package/src/services/realtimeService.ts +1034 -0
  156. package/src/utils/drizzle-conditions.ts +1000 -0
  157. package/src/websocket.ts +518 -0
  158. package/test/auth-services.test.ts +661 -0
  159. package/test/batch-many-to-many-regression.test.ts +573 -0
  160. package/test/branchService.test.ts +367 -0
  161. package/test/data-transformer-hardening.test.ts +417 -0
  162. package/test/data-transformer.test.ts +175 -0
  163. package/test/doctor.test.ts +182 -0
  164. package/test/drizzle-conditions.test.ts +895 -0
  165. package/test/entityService.errors.test.ts +367 -0
  166. package/test/entityService.relations.test.ts +1008 -0
  167. package/test/entityService.subcollection-search.test.ts +566 -0
  168. package/test/entityService.test.ts +1035 -0
  169. package/test/generate-drizzle-schema.test.ts +988 -0
  170. package/test/historyService.test.ts +141 -0
  171. package/test/introspect-db-generation.test.ts +436 -0
  172. package/test/introspect-db-utils.test.ts +389 -0
  173. package/test/n-plus-one-regression.test.ts +314 -0
  174. package/test/postgresDataDriver.test.ts +648 -0
  175. package/test/realtimeService.test.ts +307 -0
  176. package/test/relation-pipeline-gaps.test.ts +637 -0
  177. package/test/relations.test.ts +1115 -0
  178. package/test/unmapped-tables-safety.test.ts +345 -0
  179. package/test-drizzle-bug.ts +18 -0
  180. package/test-drizzle-out/0000_cultured_freak.sql +7 -0
  181. package/test-drizzle-out/0001_tiresome_professor_monster.sql +1 -0
  182. package/test-drizzle-out/meta/0000_snapshot.json +55 -0
  183. package/test-drizzle-out/meta/0001_snapshot.json +63 -0
  184. package/test-drizzle-out/meta/_journal.json +20 -0
  185. package/test-drizzle-prompt.sh +2 -0
  186. package/test-policy-prompt.sh +3 -0
  187. package/test-programmatic.ts +30 -0
  188. package/test-programmatic2.ts +59 -0
  189. package/test-schema-no-policies.ts +12 -0
  190. package/test_drizzle_mock.js +3 -0
  191. package/test_find_changed.mjs +32 -0
  192. package/test_hash.js +14 -0
  193. package/test_output.txt +3145 -0
  194. package/tsconfig.json +49 -0
  195. package/tsconfig.prod.json +20 -0
  196. package/vite.config.ts +82 -0
@@ -0,0 +1,367 @@
1
+ import { EntityService } from "../src/services/entityService";
2
+ import { NodePgDatabase } from "drizzle-orm/node-postgres";
3
+ import { EntityCollection } from "@rebasepro/types";
4
+ import { PostgresCollectionRegistry } from "../src/collections/PostgresCollectionRegistry";
5
+ const collectionRegistry = new PostgresCollectionRegistry();
6
+
7
+ describe("EntityService - Error Handling & Edge Cases", () => {
8
+ let entityService: EntityService;
9
+ let db: jest.Mocked<NodePgDatabase<any>>;
10
+
11
+ const mockTable = {
12
+ id: { name: "id",
13
+ dataType: "number" },
14
+ name: { name: "name" },
15
+ _def: { tableName: "test_table" }
16
+ };
17
+
18
+ const testCollection: EntityCollection = {
19
+ slug: "test",
20
+ name: "Test Collection",
21
+ table: "test_table",
22
+ properties: {
23
+ id: { type: "number" },
24
+ name: { type: "string" }
25
+ },
26
+ idField: "id"
27
+ };
28
+
29
+ beforeEach(() => {
30
+ jest.clearAllMocks();
31
+
32
+ jest.spyOn(collectionRegistry, "getCollectionByPath").mockImplementation(path => {
33
+ if (path === "test" || path === "test_table") return testCollection;
34
+ return undefined;
35
+ });
36
+
37
+ jest.spyOn(collectionRegistry, "getTable").mockImplementation(tableName => {
38
+ if (tableName === "test_table") return mockTable as any;
39
+ return undefined;
40
+ });
41
+
42
+ db = {
43
+ select: jest.fn().mockReturnThis(),
44
+ from: jest.fn().mockReturnThis(),
45
+ where: jest.fn().mockReturnThis(),
46
+ $dynamic: jest.fn().mockReturnThis(),
47
+ limit: jest.fn().mockReturnThis(),
48
+ orderBy: jest.fn().mockReturnThis(),
49
+ innerJoin: jest.fn().mockReturnThis(),
50
+ insert: jest.fn().mockReturnThis(),
51
+ values: jest.fn().mockReturnThis(),
52
+ returning: jest.fn().mockResolvedValue([]),
53
+ update: jest.fn().mockReturnThis(),
54
+ set: jest.fn().mockReturnThis(),
55
+ delete: jest.fn().mockReturnThis(),
56
+ transaction: jest.fn((callback) => callback(db))
57
+ } as any;
58
+
59
+ // Add a then method to make the db object awaitable when the query chain ends
60
+ (db as any).then = jest.fn((resolve) => resolve([]));
61
+
62
+ entityService = new EntityService(db, collectionRegistry);
63
+ });
64
+
65
+ describe("Collection Registry Errors", () => {
66
+ it("should throw error when collection is not found", async () => {
67
+ await expect(
68
+ entityService.fetchEntity("nonexistent", 1)
69
+ ).rejects.toThrow("Collection not found: nonexistent");
70
+ });
71
+
72
+ it("should throw error when table is not found for collection", async () => {
73
+ jest.spyOn(collectionRegistry, "getTable").mockReturnValue(undefined);
74
+
75
+ await expect(
76
+ entityService.fetchEntity("test", 1)
77
+ ).rejects.toThrow("Table not found for collection");
78
+ });
79
+
80
+
81
+ });
82
+
83
+ describe("ID Type Validation", () => {
84
+ it("should handle valid numeric ID strings", async () => {
85
+ const mockEntity = { id: 123,
86
+ name: "Test" };
87
+ db.limit.mockResolvedValue([mockEntity]);
88
+
89
+ const entity = await entityService.fetchEntity("test", "123");
90
+ expect(entity?.id).toBe("123");
91
+ });
92
+
93
+ it("should throw error for invalid numeric ID", async () => {
94
+ await expect(
95
+ entityService.fetchEntity("test", "invalid-number")
96
+ ).rejects.toThrow("Invalid numeric ID: invalid-number");
97
+ });
98
+
99
+ it("should handle zero as valid ID", async () => {
100
+ const mockEntity = { id: 0,
101
+ name: "Test" };
102
+ db.limit.mockResolvedValue([mockEntity]);
103
+
104
+ const entity = await entityService.fetchEntity("test", 0);
105
+ expect(entity?.id).toBe("0");
106
+ });
107
+
108
+ it("should handle negative numbers as valid ID", async () => {
109
+ const mockEntity = { id: -1,
110
+ name: "Test" };
111
+ db.limit.mockResolvedValue([mockEntity]);
112
+
113
+ const entity = await entityService.fetchEntity("test", -1);
114
+ expect(entity?.id).toBe("-1");
115
+ });
116
+ });
117
+
118
+ describe("Database Operation Errors", () => {
119
+ it("should propagate database connection errors on fetch", async () => {
120
+ const dbError = new Error("Connection timeout");
121
+ db.limit.mockRejectedValue(dbError);
122
+
123
+ await expect(
124
+ entityService.fetchEntity("test", 1)
125
+ ).rejects.toThrow("Connection timeout");
126
+ });
127
+
128
+ it("should propagate database errors on save", async () => {
129
+ const dbError = new Error("Constraint violation");
130
+ db.returning.mockRejectedValue(dbError);
131
+
132
+ await expect(
133
+ entityService.saveEntity("test", { name: "Test" })
134
+ ).rejects.toThrow("Constraint violation");
135
+ });
136
+
137
+ it("should propagate database errors on delete", async () => {
138
+ const dbError = new Error("Foreign key constraint");
139
+ // Fix: Mock the delete method since deleteEntity doesn't use returning()
140
+ db.delete.mockReturnValue({
141
+ where: jest.fn().mockRejectedValue(dbError)
142
+ } as any);
143
+
144
+ await expect(
145
+ entityService.deleteEntity("test", 1)
146
+ ).rejects.toThrow("Foreign key constraint");
147
+ });
148
+
149
+ it("should handle transaction rollback scenarios", async () => {
150
+ const transactionError = new Error("Transaction failed");
151
+ db.transaction.mockImplementation((callback) => {
152
+ throw transactionError;
153
+ });
154
+
155
+ await expect(
156
+ entityService.saveEntity("test", { name: "Test" })
157
+ ).rejects.toThrow("Transaction failed");
158
+ });
159
+ });
160
+
161
+ describe("Path Validation", () => {
162
+ it("should reject paths with even number of segments", async () => {
163
+ await expect(
164
+ entityService.fetchCollection("collection/id", {})
165
+ ).rejects.toThrow("Invalid relation path: collection/id");
166
+ });
167
+
168
+ it("should reject single segment paths (not nested)", async () => {
169
+ // Single collection paths should work fine, but let's test the path parsing logic
170
+ const entities = await entityService.fetchCollection("test", {});
171
+ expect(entities).toBeDefined(); // Should work for single collection
172
+ });
173
+
174
+ it("should reject empty path segments", async () => {
175
+ await expect(
176
+ entityService.fetchCollection("collection//relation", {})
177
+ ).rejects.toThrow("Invalid relation path");
178
+ });
179
+ });
180
+
181
+ describe("Concurrent Operations", () => {
182
+ it("should handle multiple simultaneous reads", async () => {
183
+ const mockEntity = { id: 1,
184
+ name: "Test" };
185
+ db.limit.mockResolvedValue([mockEntity]);
186
+
187
+ const promises = Array(10).fill(0).map(() =>
188
+ entityService.fetchEntity("test", 1)
189
+ );
190
+
191
+ const results = await Promise.all(promises);
192
+
193
+ expect(results).toHaveLength(10);
194
+ results.forEach(result => {
195
+ expect(result?.id).toBe("1");
196
+ });
197
+ });
198
+
199
+ it("should handle race conditions in write operations", async () => {
200
+ db.returning.mockResolvedValue([{ id: 1 }]);
201
+ db.limit.mockResolvedValue([{ id: 1,
202
+ name: "Updated" }]);
203
+
204
+ const promises = Array(5).fill(0).map((_, i) =>
205
+ entityService.saveEntity("test", { name: `Update ${i}` }, 1)
206
+ );
207
+
208
+ const results = await Promise.all(promises);
209
+
210
+ expect(results).toHaveLength(5);
211
+ // All should succeed due to transaction handling
212
+ });
213
+ });
214
+
215
+ describe("Memory and Performance", () => {
216
+ it("should handle large result sets without memory issues", async () => {
217
+ const largeResultSet = Array(1000).fill(0).map((_, i) => ({
218
+ id: i,
219
+ name: `Entity ${i}`
220
+ }));
221
+ db.orderBy.mockResolvedValue(largeResultSet);
222
+
223
+ const entities = await entityService.fetchCollection("test", {});
224
+
225
+ expect(entities).toHaveLength(1000);
226
+ expect(entities[0].values.name).toBe("Entity 0");
227
+ expect(entities[999].values.name).toBe("Entity 999");
228
+ });
229
+
230
+ it("should handle pagination correctly for large datasets", async () => {
231
+ const mockEntities = Array(50).fill(0).map((_, i) => ({
232
+ id: i + 1,
233
+ name: `Entity ${i + 1}`
234
+ }));
235
+ // Override the then method to return our mock data for this specific test
236
+ (db as any).then = jest.fn((resolve) => resolve(mockEntities.slice(0, 20)));
237
+
238
+ const entities = await entityService.fetchCollection("test", {
239
+ limit: 20
240
+ });
241
+
242
+ expect(entities).toHaveLength(20);
243
+ expect(db.limit).toHaveBeenCalledWith(20);
244
+ });
245
+ });
246
+
247
+ describe("Data Integrity", () => {
248
+ it("should validate required fields are present", async () => {
249
+ const incompleteEntity = {}; // Missing required fields
250
+
251
+ db.returning.mockResolvedValue([{ id: 1 }]);
252
+ db.limit.mockResolvedValue([{ id: 1,
253
+ name: null }]);
254
+
255
+ // The service should handle validation at the collection level
256
+ // This test verifies the service doesn't crash with incomplete data
257
+ const entity = await entityService.saveEntity("test", incompleteEntity);
258
+ expect(entity.id).toBe("1");
259
+ });
260
+
261
+ it("should handle NULL values in database correctly", async () => {
262
+ const mockEntity = { id: 1,
263
+ name: null };
264
+ db.limit.mockResolvedValue([mockEntity]);
265
+
266
+ const entity = await entityService.fetchEntity("test", 1);
267
+ expect(entity?.values.name).toBeNull();
268
+ });
269
+
270
+ it("should handle undefined values in input data", async () => {
271
+ const entityWithUndefined = { name: undefined };
272
+
273
+ db.returning.mockResolvedValue([{ id: 1 }]);
274
+ db.limit.mockResolvedValue([{ id: 1,
275
+ name: null }]);
276
+
277
+ const entity = await entityService.saveEntity("test", entityWithUndefined);
278
+ expect(entity.id).toBe("1");
279
+ });
280
+ });
281
+
282
+ describe("Security and Validation", () => {
283
+ it("should handle SQL injection attempts in IDs safely", async () => {
284
+ const maliciousId = "1; DROP TABLE test_table;--";
285
+
286
+ // The service should handle this safely through parameterized queries
287
+ // This test should not throw an error because of proper parameterization
288
+ const mockEntity = { id: 1,
289
+ name: "Safe" };
290
+ db.limit.mockResolvedValue([mockEntity]);
291
+
292
+ const entity = await entityService.fetchEntity("test", maliciousId);
293
+ expect(entity).toBeDefined(); // Should work safely
294
+ });
295
+
296
+ it("should handle extremely long input values", async () => {
297
+ const veryLongString = "a".repeat(10000);
298
+ const entityWithLongValue = { name: veryLongString };
299
+
300
+ db.returning.mockResolvedValue([{ id: 1 }]);
301
+ db.limit.mockResolvedValue([{ id: 1,
302
+ name: veryLongString }]);
303
+
304
+ const entity = await entityService.saveEntity("test", entityWithLongValue);
305
+ expect(entity.values.name).toBe(veryLongString);
306
+ });
307
+
308
+ it("should handle special characters in string values", async () => {
309
+ const specialChars = "!@#$%^&*()_+-=[]{}|;':\",./<>?`~";
310
+ const entityWithSpecialChars = { name: specialChars };
311
+
312
+ db.returning.mockResolvedValue([{ id: 1 }]);
313
+ db.limit.mockResolvedValue([{ id: 1,
314
+ name: specialChars }]);
315
+
316
+ const entity = await entityService.saveEntity("test", entityWithSpecialChars);
317
+ expect(entity.values.name).toBe(specialChars);
318
+ });
319
+ });
320
+
321
+ describe("Edge Case Data Types", () => {
322
+ it("should handle boolean false values correctly", async () => {
323
+ const booleanCollection = {
324
+ ...testCollection,
325
+ properties: {
326
+ id: { type: "number" },
327
+ active: { type: "boolean" }
328
+ }
329
+ };
330
+ jest.spyOn(collectionRegistry, "getCollectionByPath").mockReturnValue(booleanCollection);
331
+
332
+ const mockEntity = { id: 1,
333
+ active: false };
334
+ db.limit.mockResolvedValue([mockEntity]);
335
+
336
+ const entity = await entityService.fetchEntity("test", 1);
337
+ expect(entity?.values.active).toBe(false);
338
+ });
339
+
340
+ it("should handle zero values correctly", async () => {
341
+ const numericCollection = {
342
+ ...testCollection,
343
+ properties: {
344
+ id: { type: "number" },
345
+ count: { type: "number" }
346
+ }
347
+ };
348
+ jest.spyOn(collectionRegistry, "getCollectionByPath").mockReturnValue(numericCollection);
349
+
350
+ const mockEntity = { id: 1,
351
+ count: 0 };
352
+ db.limit.mockResolvedValue([mockEntity]);
353
+
354
+ const entity = await entityService.fetchEntity("test", 1);
355
+ expect(entity?.values.count).toBe(0);
356
+ });
357
+
358
+ it("should handle empty string values correctly", async () => {
359
+ const mockEntity = { id: 1,
360
+ name: "" };
361
+ db.limit.mockResolvedValue([mockEntity]);
362
+
363
+ const entity = await entityService.fetchEntity("test", 1);
364
+ expect(entity?.values.name).toBe("");
365
+ });
366
+ });
367
+ });