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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (136) hide show
  1. package/dist/common/src/collections/CollectionRegistry.d.ts +8 -0
  2. package/dist/common/src/util/entities.d.ts +22 -0
  3. package/dist/common/src/util/relations.d.ts +14 -4
  4. package/dist/common/src/util/resolutions.d.ts +1 -1
  5. package/dist/index.es.js +1254 -591
  6. package/dist/index.es.js.map +1 -1
  7. package/dist/index.umd.js +1254 -591
  8. package/dist/index.umd.js.map +1 -1
  9. package/dist/server-postgresql/src/PostgresBackendDriver.d.ts +17 -29
  10. package/dist/server-postgresql/src/auth/services.d.ts +7 -3
  11. package/dist/server-postgresql/src/collections/PostgresCollectionRegistry.d.ts +1 -1
  12. package/dist/server-postgresql/src/connection.d.ts +34 -1
  13. package/dist/server-postgresql/src/data-transformer.d.ts +26 -4
  14. package/dist/server-postgresql/src/databasePoolManager.d.ts +2 -2
  15. package/dist/server-postgresql/src/schema/auth-schema.d.ts +139 -38
  16. package/dist/server-postgresql/src/schema/doctor-cli.d.ts +2 -0
  17. package/dist/server-postgresql/src/schema/doctor.d.ts +43 -0
  18. package/dist/server-postgresql/src/schema/generate-drizzle-schema-logic.d.ts +1 -1
  19. package/dist/server-postgresql/src/schema/test-schema.d.ts +24 -0
  20. package/dist/server-postgresql/src/services/EntityFetchService.d.ts +22 -8
  21. package/dist/server-postgresql/src/services/EntityPersistService.d.ts +1 -1
  22. package/dist/server-postgresql/src/services/RelationService.d.ts +11 -5
  23. package/dist/server-postgresql/src/services/entity-helpers.d.ts +16 -2
  24. package/dist/server-postgresql/src/services/entityService.d.ts +8 -6
  25. package/dist/server-postgresql/src/services/realtimeService.d.ts +2 -0
  26. package/dist/server-postgresql/src/utils/drizzle-conditions.d.ts +2 -2
  27. package/dist/types/src/controllers/auth.d.ts +2 -0
  28. package/dist/types/src/controllers/client.d.ts +119 -7
  29. package/dist/types/src/controllers/collection_registry.d.ts +4 -3
  30. package/dist/types/src/controllers/customization_controller.d.ts +7 -1
  31. package/dist/types/src/controllers/data.d.ts +34 -7
  32. package/dist/types/src/controllers/data_driver.d.ts +20 -28
  33. package/dist/types/src/controllers/database_admin.d.ts +2 -2
  34. package/dist/types/src/controllers/email.d.ts +34 -0
  35. package/dist/types/src/controllers/index.d.ts +1 -0
  36. package/dist/types/src/controllers/local_config_persistence.d.ts +4 -4
  37. package/dist/types/src/controllers/navigation.d.ts +5 -5
  38. package/dist/types/src/controllers/registry.d.ts +6 -3
  39. package/dist/types/src/controllers/side_entity_controller.d.ts +7 -6
  40. package/dist/types/src/controllers/storage.d.ts +24 -26
  41. package/dist/types/src/rebase_context.d.ts +8 -4
  42. package/dist/types/src/types/backend.d.ts +4 -1
  43. package/dist/types/src/types/builders.d.ts +5 -4
  44. package/dist/types/src/types/chips.d.ts +1 -1
  45. package/dist/types/src/types/collections.d.ts +169 -125
  46. package/dist/types/src/types/cron.d.ts +102 -0
  47. package/dist/types/src/types/data_source.d.ts +1 -1
  48. package/dist/types/src/types/entity_actions.d.ts +8 -8
  49. package/dist/types/src/types/entity_callbacks.d.ts +15 -15
  50. package/dist/types/src/types/entity_link_builder.d.ts +1 -1
  51. package/dist/types/src/types/entity_overrides.d.ts +2 -1
  52. package/dist/types/src/types/entity_views.d.ts +8 -8
  53. package/dist/types/src/types/export_import.d.ts +3 -3
  54. package/dist/types/src/types/index.d.ts +1 -0
  55. package/dist/types/src/types/plugins.d.ts +72 -18
  56. package/dist/types/src/types/properties.d.ts +118 -33
  57. package/dist/types/src/types/relations.d.ts +1 -1
  58. package/dist/types/src/types/slots.d.ts +30 -6
  59. package/dist/types/src/types/translations.d.ts +44 -0
  60. package/dist/types/src/types/user_management_delegate.d.ts +1 -0
  61. package/drizzle-test/0000_woozy_junta.sql +6 -0
  62. package/drizzle-test/0001_youthful_arachne.sql +1 -0
  63. package/drizzle-test/0002_lively_dragon_lord.sql +2 -0
  64. package/drizzle-test/0003_mean_king_cobra.sql +2 -0
  65. package/drizzle-test/meta/0000_snapshot.json +47 -0
  66. package/drizzle-test/meta/0001_snapshot.json +48 -0
  67. package/drizzle-test/meta/0002_snapshot.json +38 -0
  68. package/drizzle-test/meta/0003_snapshot.json +48 -0
  69. package/drizzle-test/meta/_journal.json +34 -0
  70. package/drizzle-test-out/0000_tan_trauma.sql +6 -0
  71. package/drizzle-test-out/0001_rapid_drax.sql +1 -0
  72. package/drizzle-test-out/meta/0000_snapshot.json +44 -0
  73. package/drizzle-test-out/meta/0001_snapshot.json +54 -0
  74. package/drizzle-test-out/meta/_journal.json +20 -0
  75. package/drizzle.test.config.ts +10 -0
  76. package/package.json +88 -89
  77. package/scratch.ts +41 -0
  78. package/src/PostgresBackendDriver.ts +63 -79
  79. package/src/PostgresBootstrapper.ts +7 -8
  80. package/src/auth/ensure-tables.ts +158 -86
  81. package/src/auth/services.ts +109 -50
  82. package/src/cli.ts +259 -16
  83. package/src/collections/PostgresCollectionRegistry.ts +6 -6
  84. package/src/connection.ts +70 -48
  85. package/src/data-transformer.ts +155 -116
  86. package/src/databasePoolManager.ts +6 -5
  87. package/src/history/HistoryService.ts +3 -12
  88. package/src/interfaces.ts +3 -3
  89. package/src/schema/auth-schema.ts +26 -3
  90. package/src/schema/doctor-cli.ts +47 -0
  91. package/src/schema/doctor.ts +595 -0
  92. package/src/schema/generate-drizzle-schema-logic.ts +204 -57
  93. package/src/schema/generate-drizzle-schema.ts +6 -6
  94. package/src/schema/test-schema.ts +11 -0
  95. package/src/services/BranchService.ts +5 -5
  96. package/src/services/EntityFetchService.ts +317 -188
  97. package/src/services/EntityPersistService.ts +15 -17
  98. package/src/services/RelationService.ts +299 -37
  99. package/src/services/entity-helpers.ts +39 -13
  100. package/src/services/entityService.ts +11 -9
  101. package/src/services/realtimeService.ts +58 -29
  102. package/src/utils/drizzle-conditions.ts +25 -24
  103. package/src/websocket.ts +52 -21
  104. package/test/auth-services.test.ts +131 -39
  105. package/test/batch-many-to-many-regression.test.ts +573 -0
  106. package/test/branchService.test.ts +22 -12
  107. package/test/data-transformer-hardening.test.ts +417 -0
  108. package/test/data-transformer.test.ts +175 -0
  109. package/test/doctor.test.ts +182 -0
  110. package/test/entityService.errors.test.ts +31 -16
  111. package/test/entityService.relations.test.ts +155 -59
  112. package/test/entityService.subcollection-search.test.ts +107 -57
  113. package/test/entityService.test.ts +105 -47
  114. package/test/generate-drizzle-schema.test.ts +262 -69
  115. package/test/historyService.test.ts +31 -16
  116. package/test/n-plus-one-regression.test.ts +314 -0
  117. package/test/postgresDataDriver.test.ts +260 -168
  118. package/test/realtimeService.test.ts +70 -39
  119. package/test/relation-pipeline-gaps.test.ts +637 -0
  120. package/test/relations.test.ts +492 -39
  121. package/test-drizzle-bug.ts +18 -0
  122. package/test-drizzle-out/0000_cultured_freak.sql +7 -0
  123. package/test-drizzle-out/0001_tiresome_professor_monster.sql +1 -0
  124. package/test-drizzle-out/meta/0000_snapshot.json +55 -0
  125. package/test-drizzle-out/meta/0001_snapshot.json +63 -0
  126. package/test-drizzle-out/meta/_journal.json +20 -0
  127. package/test-drizzle-prompt.sh +2 -0
  128. package/test-policy-prompt.sh +3 -0
  129. package/test-programmatic.ts +30 -0
  130. package/test-programmatic2.ts +59 -0
  131. package/test-schema-no-policies.ts +12 -0
  132. package/test_drizzle_mock.js +2 -2
  133. package/test_find_changed.mjs +3 -1
  134. package/test_hash.js +14 -0
  135. package/tsconfig.json +1 -1
  136. package/vite.config.ts +5 -5
@@ -1,5 +1,6 @@
1
1
  import { EntityService } from "../src/services/entityService";
2
2
  import { NodePgDatabase } from "drizzle-orm/node-postgres";
3
+ import { SQL } from "drizzle-orm";
3
4
  import { EntityCollection } from "@rebasepro/types";
4
5
  import { PostgresCollectionRegistry } from "../src/collections/PostgresCollectionRegistry";
5
6
  const collectionRegistry = new PostgresCollectionRegistry();
@@ -7,7 +8,7 @@ import { DrizzleConditionBuilder } from "../src/utils/drizzle-conditions";
7
8
 
8
9
  describe("EntityService - Subcollection Search Tests", () => {
9
10
  let entityService: EntityService;
10
- let db: jest.Mocked<NodePgDatabase<any>>;
11
+ let db: jest.Mocked<NodePgDatabase<Record<string, unknown>>>;
11
12
 
12
13
  // Mock tables for subcollection search scenarios
13
14
  const mockTagsTable = {
@@ -57,7 +58,8 @@ describe("EntityService - Subcollection Search Tests", () => {
57
58
  id: { type: "number" },
58
59
  name: { type: "string" },
59
60
  description: { type: "string" },
60
- posts: { type: "relation", relationName: "posts" }
61
+ posts: { type: "relation",
62
+ relationName: "posts" }
61
63
  },
62
64
  relations: [
63
65
  {
@@ -79,9 +81,12 @@ describe("EntityService - Subcollection Search Tests", () => {
79
81
  id: { type: "number" },
80
82
  title: { type: "string" },
81
83
  content: { type: "string" },
82
- tag: { type: "relation", relationName: "tag" },
83
- author: { type: "relation", relationName: "author" },
84
- comments: { type: "relation", relationName: "comments" }
84
+ tag: { type: "relation",
85
+ relationName: "tag" },
86
+ author: { type: "relation",
87
+ relationName: "author" },
88
+ comments: { type: "relation",
89
+ relationName: "comments" }
85
90
  },
86
91
  relations: [
87
92
  {
@@ -118,7 +123,8 @@ describe("EntityService - Subcollection Search Tests", () => {
118
123
  name: { type: "string" },
119
124
  email: { type: "string" },
120
125
  bio: { type: "string" },
121
- posts: { type: "relation", relationName: "posts" }
126
+ posts: { type: "relation",
127
+ relationName: "posts" }
122
128
  },
123
129
  relations: [
124
130
  {
@@ -140,7 +146,8 @@ describe("EntityService - Subcollection Search Tests", () => {
140
146
  id: { type: "number" },
141
147
  content: { type: "string" },
142
148
  author_name: { type: "string" },
143
- post: { type: "relation", relationName: "post" }
149
+ post: { type: "relation",
150
+ relationName: "post" }
144
151
  },
145
152
  relations: [
146
153
  {
@@ -155,7 +162,7 @@ describe("EntityService - Subcollection Search Tests", () => {
155
162
  };
156
163
 
157
164
  // Helper function to create a proper mock query builder
158
- function createMockQueryBuilder(mockResults: any[]) {
165
+ function createMockQueryBuilder(mockResults: Record<string, unknown>[]) {
159
166
  const mockQueryBuilder = {
160
167
  from: jest.fn().mockReturnThis(),
161
168
  where: jest.fn().mockReturnThis(),
@@ -179,37 +186,37 @@ describe("EntityService - Subcollection Search Tests", () => {
179
186
  insert: jest.fn(),
180
187
  update: jest.fn(),
181
188
  transaction: jest.fn()
182
- } as any;
189
+ } as unknown as jest.Mocked<NodePgDatabase<Record<string, unknown>>>;
183
190
 
184
191
  entityService = new EntityService(db, collectionRegistry);
185
192
 
186
193
  // Mock collection registry
187
- jest.spyOn(collectionRegistry, 'getCollectionByPath').mockImplementation((path: string) => {
194
+ jest.spyOn(collectionRegistry, "getCollectionByPath").mockImplementation((path: string) => {
188
195
  switch (path) {
189
- case 'tags':
196
+ case "tags":
190
197
  return tagsCollection;
191
- case 'posts':
198
+ case "posts":
192
199
  return postsCollection;
193
- case 'authors':
200
+ case "authors":
194
201
  return authorsCollection;
195
- case 'comments':
202
+ case "comments":
196
203
  return commentsCollection;
197
204
  default:
198
205
  throw new Error(`Collection not found: ${path}`);
199
206
  }
200
207
  });
201
208
 
202
- jest.spyOn(collectionRegistry, 'getTable').mockImplementation((tableName: string) => {
209
+ jest.spyOn(collectionRegistry, "getTable").mockImplementation((tableName: string) => {
203
210
  switch (tableName) {
204
- case 'tags':
211
+ case "tags":
205
212
  return mockTagsTable;
206
- case 'posts':
213
+ case "posts":
207
214
  return mockPostsTable;
208
- case 'authors':
215
+ case "authors":
209
216
  return mockAuthorsTable;
210
- case 'comments':
217
+ case "comments":
211
218
  return mockCommentsTable;
212
- case 'posts_tags':
219
+ case "posts_tags":
213
220
  return mockPostsTagsTable;
214
221
  default:
215
222
  return null;
@@ -217,15 +224,19 @@ describe("EntityService - Subcollection Search Tests", () => {
217
224
  });
218
225
 
219
226
  // Mock DrizzleConditionBuilder with more realistic behavior
220
- jest.spyOn(DrizzleConditionBuilder, 'buildSearchConditions').mockReturnValue([
221
- { operator: 'ilike', column: 'title', value: '%searchterm%' },
222
- { operator: 'ilike', column: 'content', value: '%searchterm%' }
223
- ] as any);
224
-
225
- jest.spyOn(DrizzleConditionBuilder, 'combineConditionsWithOr').mockReturnValue({ combined: 'search_conditions' } as any);
226
- jest.spyOn(DrizzleConditionBuilder, 'combineConditionsWithAnd').mockReturnValue({ combined: 'all_conditions' } as any);
227
- jest.spyOn(DrizzleConditionBuilder, 'buildRelationQuery').mockImplementation((query) => query);
228
- jest.spyOn(DrizzleConditionBuilder, 'buildFilterConditions').mockReturnValue([]);
227
+ jest.spyOn(DrizzleConditionBuilder, "buildSearchConditions").mockReturnValue([
228
+ { operator: "ilike",
229
+ column: "title",
230
+ value: "%searchterm%" },
231
+ { operator: "ilike",
232
+ column: "content",
233
+ value: "%searchterm%" }
234
+ ] as unknown as SQL[]);
235
+
236
+ jest.spyOn(DrizzleConditionBuilder, "combineConditionsWithOr").mockReturnValue({ combined: "search_conditions" } as unknown as SQL);
237
+ jest.spyOn(DrizzleConditionBuilder, "combineConditionsWithAnd").mockReturnValue({ combined: "all_conditions" } as unknown as SQL);
238
+ jest.spyOn(DrizzleConditionBuilder, "buildRelationQuery").mockImplementation((query) => query);
239
+ jest.spyOn(DrizzleConditionBuilder, "buildFilterConditions").mockReturnValue([]);
229
240
  });
230
241
 
231
242
  afterEach(() => {
@@ -236,12 +247,18 @@ describe("EntityService - Subcollection Search Tests", () => {
236
247
  it("should handle search in one-to-many inverse relation subcollection", async () => {
237
248
  // Scenario: Search posts under a specific tag (tags/19/posts)
238
249
  const mockResults = [
239
- { id: 1, title: "Mental Health Tips", content: "Content about mental health", tag_id: 19 },
240
- { id: 2, title: "Mental Wellness", content: "More mental health content", tag_id: 19 }
250
+ { id: 1,
251
+ title: "Mental Health Tips",
252
+ content: "Content about mental health",
253
+ tag_id: 19 },
254
+ { id: 2,
255
+ title: "Mental Wellness",
256
+ content: "More mental health content",
257
+ tag_id: 19 }
241
258
  ];
242
259
 
243
260
  const mockQueryBuilder = createMockQueryBuilder(mockResults);
244
- db.select.mockReturnValue(mockQueryBuilder as any);
261
+ db.select.mockReturnValue(mockQueryBuilder as unknown as ReturnType<typeof db.select>);
245
262
 
246
263
  const result = await entityService.fetchCollection("tags/19/posts", {
247
264
  searchString: "mental",
@@ -265,12 +282,18 @@ describe("EntityService - Subcollection Search Tests", () => {
265
282
  it("should handle search in many-to-one owning relation subcollection", async () => {
266
283
  // Scenario: Search posts under a specific author (authors/5/posts)
267
284
  const mockResults = [
268
- { id: 10, title: "Mental Strategies", content: "Author's take on mental health", author_id: 5 },
269
- { id: 11, title: "Mindfulness Guide", content: "Mental wellness guide", author_id: 5 }
285
+ { id: 10,
286
+ title: "Mental Strategies",
287
+ content: "Author's take on mental health",
288
+ author_id: 5 },
289
+ { id: 11,
290
+ title: "Mindfulness Guide",
291
+ content: "Mental wellness guide",
292
+ author_id: 5 }
270
293
  ];
271
294
 
272
295
  const mockQueryBuilder = createMockQueryBuilder(mockResults);
273
- db.select.mockReturnValue(mockQueryBuilder as any);
296
+ db.select.mockReturnValue(mockQueryBuilder as unknown as ReturnType<typeof db.select>);
274
297
 
275
298
  const result = await entityService.fetchCollection("authors/5/posts", {
276
299
  searchString: "mental",
@@ -290,12 +313,18 @@ describe("EntityService - Subcollection Search Tests", () => {
290
313
  it("should handle search in nested subcollection (posts/123/comments)", async () => {
291
314
  // Scenario: Search comments under a specific post (posts/123/comments)
292
315
  const mockResults = [
293
- { id: 1, content: "Great mental health advice!", author_name: "John", post_id: 123 },
294
- { id: 2, content: "Mental wellness is important", author_name: "Jane", post_id: 123 }
316
+ { id: 1,
317
+ content: "Great mental health advice!",
318
+ author_name: "John",
319
+ post_id: 123 },
320
+ { id: 2,
321
+ content: "Mental wellness is important",
322
+ author_name: "Jane",
323
+ post_id: 123 }
295
324
  ];
296
325
 
297
326
  const mockQueryBuilder = createMockQueryBuilder(mockResults);
298
- db.select.mockReturnValue(mockQueryBuilder as any);
327
+ db.select.mockReturnValue(mockQueryBuilder as unknown as ReturnType<typeof db.select>);
299
328
 
300
329
  const result = await entityService.fetchCollection("posts/123/comments", {
301
330
  searchString: "mental",
@@ -313,15 +342,20 @@ describe("EntityService - Subcollection Search Tests", () => {
313
342
  it("should combine search conditions with existing filters", async () => {
314
343
  // Scenario: Search with both searchString and filter
315
344
  const mockResults = [
316
- { id: 1, title: "Mental Health", content: "Published content", tag_id: 19 }
345
+ { id: 1,
346
+ title: "Mental Health",
347
+ content: "Published content",
348
+ tag_id: 19 }
317
349
  ];
318
350
 
319
351
  const mockQueryBuilder = createMockQueryBuilder(mockResults);
320
- db.select.mockReturnValue(mockQueryBuilder as any);
352
+ db.select.mockReturnValue(mockQueryBuilder as unknown as ReturnType<typeof db.select>);
321
353
 
322
354
  // Mock buildFilterConditions to return some filter conditions to ensure AND combination
323
- const mockFilterConditions = [{ operator: 'eq', column: 'title', value: 'Mental Health' }] as any;
324
- jest.spyOn(DrizzleConditionBuilder, 'buildFilterConditions').mockReturnValue(mockFilterConditions);
355
+ const mockFilterConditions = [{ operator: "eq",
356
+ column: "title",
357
+ value: "Mental Health" }] as unknown as SQL[];
358
+ jest.spyOn(DrizzleConditionBuilder, "buildFilterConditions").mockReturnValue(mockFilterConditions);
325
359
 
326
360
  const result = await entityService.fetchCollection("tags/19/posts", {
327
361
  searchString: "mental",
@@ -342,11 +376,11 @@ describe("EntityService - Subcollection Search Tests", () => {
342
376
 
343
377
  it("should handle empty search results gracefully", async () => {
344
378
  // When buildSearchConditions returns empty array, the query still runs without search conditions
345
- jest.spyOn(DrizzleConditionBuilder, 'buildSearchConditions').mockReturnValue([]);
379
+ jest.spyOn(DrizzleConditionBuilder, "buildSearchConditions").mockReturnValue([]);
346
380
 
347
381
  // Still need to mock db.select to return a query builder that returns empty results
348
382
  const mockQueryBuilder = createMockQueryBuilder([]);
349
- db.select.mockReturnValue(mockQueryBuilder as any);
383
+ db.select.mockReturnValue(mockQueryBuilder as unknown as ReturnType<typeof db.select>);
350
384
 
351
385
  const result = await entityService.fetchCollection("tags/19/posts", {
352
386
  searchString: "nonexistent",
@@ -361,19 +395,26 @@ describe("EntityService - Subcollection Search Tests", () => {
361
395
 
362
396
  it("should handle search with ordering and pagination", async () => {
363
397
  const mockResults = [
364
- { id: 3, title: "Mental Health Z", content: "Content Z", tag_id: 19 },
365
- { id: 1, title: "Mental Health A", content: "Content A", tag_id: 19 }
398
+ { id: 3,
399
+ title: "Mental Health Z",
400
+ content: "Content Z",
401
+ tag_id: 19 },
402
+ { id: 1,
403
+ title: "Mental Health A",
404
+ content: "Content A",
405
+ tag_id: 19 }
366
406
  ];
367
407
 
368
408
  const mockQueryBuilder = createMockQueryBuilder(mockResults);
369
- db.select.mockReturnValue(mockQueryBuilder as any);
409
+ db.select.mockReturnValue(mockQueryBuilder as unknown as ReturnType<typeof db.select>);
370
410
 
371
411
  const result = await entityService.fetchCollection("tags/19/posts", {
372
412
  searchString: "mental",
373
413
  orderBy: "title",
374
414
  order: "asc",
375
415
  limit: 10,
376
- startAfter: { id: 5, title: "Mental Health B" }
416
+ startAfter: { id: 5,
417
+ title: "Mental Health B" }
377
418
  });
378
419
 
379
420
  // Verify search was processed
@@ -388,11 +429,14 @@ describe("EntityService - Subcollection Search Tests", () => {
388
429
  describe("searchEntities with subcollection paths", () => {
389
430
  it("should handle direct search on subcollection using searchEntities method", async () => {
390
431
  const mockResults = [
391
- { id: 1, title: "Mental Health Guide", content: "Comprehensive guide", tag_id: 19 }
432
+ { id: 1,
433
+ title: "Mental Health Guide",
434
+ content: "Comprehensive guide",
435
+ tag_id: 19 }
392
436
  ];
393
437
 
394
438
  const mockQueryBuilder = createMockQueryBuilder(mockResults);
395
- db.select.mockReturnValue(mockQueryBuilder as any);
439
+ db.select.mockReturnValue(mockQueryBuilder as unknown as ReturnType<typeof db.select>);
396
440
 
397
441
  // searchEntities calls fetchEntitiesWithConditions which doesn't handle subcollection paths
398
442
  // It would need to be called with just the base collection path
@@ -412,11 +456,14 @@ describe("EntityService - Subcollection Search Tests", () => {
412
456
  describe("fetchRelatedEntities with search", () => {
413
457
  it("should pass search parameters correctly to fetchEntitiesUsingJoins", async () => {
414
458
  const mockResults = [
415
- { id: 1, title: "Mental Health Post", content: "Content", tag_id: 19 }
459
+ { id: 1,
460
+ title: "Mental Health Post",
461
+ content: "Content",
462
+ tag_id: 19 }
416
463
  ];
417
464
 
418
465
  const mockQueryBuilder = createMockQueryBuilder(mockResults);
419
- db.select.mockReturnValue(mockQueryBuilder as any);
466
+ db.select.mockReturnValue(mockQueryBuilder as unknown as ReturnType<typeof db.select>);
420
467
 
421
468
  // Test fetchRelatedEntities directly with search
422
469
  const result = await entityService.fetchRelatedEntities("tags", 19, "posts", {
@@ -445,7 +492,7 @@ describe("EntityService - Subcollection Search Tests", () => {
445
492
  const mockCollection = { ...tagsCollection };
446
493
  mockCollection.relations = [];
447
494
 
448
- jest.spyOn(collectionRegistry, 'getCollectionByPath').mockReturnValue(mockCollection);
495
+ jest.spyOn(collectionRegistry, "getCollectionByPath").mockReturnValue(mockCollection);
449
496
 
450
497
  await expect(entityService.fetchCollection("tags/19/nonexistent", {
451
498
  searchString: "test"
@@ -454,11 +501,11 @@ describe("EntityService - Subcollection Search Tests", () => {
454
501
 
455
502
  it("should handle search in collection with no searchable properties", async () => {
456
503
  // Mock buildSearchConditions to return empty array
457
- jest.spyOn(DrizzleConditionBuilder, 'buildSearchConditions').mockReturnValue([]);
504
+ jest.spyOn(DrizzleConditionBuilder, "buildSearchConditions").mockReturnValue([]);
458
505
 
459
506
  // Still need to mock db.select even though it might not be called, to avoid errors
460
507
  const mockQueryBuilder = createMockQueryBuilder([]);
461
- db.select.mockReturnValue(mockQueryBuilder as any);
508
+ db.select.mockReturnValue(mockQueryBuilder as unknown as ReturnType<typeof db.select>);
462
509
 
463
510
  const result = await entityService.fetchCollection("tags/19/posts", {
464
511
  searchString: "mental"
@@ -477,7 +524,10 @@ describe("EntityService - Subcollection Search Tests", () => {
477
524
  describe("Performance and optimization", () => {
478
525
  it("should use proper limit when searching (default 50 for search)", async () => {
479
526
  const mockResults = [
480
- { id: 1, title: "Mental Health", content: "Content", tag_id: 19 }
527
+ { id: 1,
528
+ title: "Mental Health",
529
+ content: "Content",
530
+ tag_id: 19 }
481
531
  ];
482
532
 
483
533
  const mockLimit = jest.fn().mockReturnThis();
@@ -491,7 +541,7 @@ describe("EntityService - Subcollection Search Tests", () => {
491
541
  then: jest.fn((resolve) => resolve(mockResults))
492
542
  };
493
543
 
494
- db.select.mockReturnValue(mockQueryBuilder as any);
544
+ db.select.mockReturnValue(mockQueryBuilder as unknown as ReturnType<typeof db.select>);
495
545
 
496
546
  // Test without explicit limit - the system uses different behavior for subcollections
497
547
  await entityService.fetchCollection("tags/19/posts", {