@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,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<
|
|
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",
|
|
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",
|
|
83
|
-
|
|
84
|
-
|
|
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",
|
|
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",
|
|
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:
|
|
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
|
|
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,
|
|
194
|
+
jest.spyOn(collectionRegistry, "getCollectionByPath").mockImplementation((path: string) => {
|
|
188
195
|
switch (path) {
|
|
189
|
-
case
|
|
196
|
+
case "tags":
|
|
190
197
|
return tagsCollection;
|
|
191
|
-
case
|
|
198
|
+
case "posts":
|
|
192
199
|
return postsCollection;
|
|
193
|
-
case
|
|
200
|
+
case "authors":
|
|
194
201
|
return authorsCollection;
|
|
195
|
-
case
|
|
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,
|
|
209
|
+
jest.spyOn(collectionRegistry, "getTable").mockImplementation((tableName: string) => {
|
|
203
210
|
switch (tableName) {
|
|
204
|
-
case
|
|
211
|
+
case "tags":
|
|
205
212
|
return mockTagsTable;
|
|
206
|
-
case
|
|
213
|
+
case "posts":
|
|
207
214
|
return mockPostsTable;
|
|
208
|
-
case
|
|
215
|
+
case "authors":
|
|
209
216
|
return mockAuthorsTable;
|
|
210
|
-
case
|
|
217
|
+
case "comments":
|
|
211
218
|
return mockCommentsTable;
|
|
212
|
-
case
|
|
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,
|
|
221
|
-
{ operator:
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
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,
|
|
240
|
-
|
|
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
|
|
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,
|
|
269
|
-
|
|
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
|
|
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,
|
|
294
|
-
|
|
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
|
|
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,
|
|
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
|
|
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:
|
|
324
|
-
|
|
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,
|
|
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
|
|
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,
|
|
365
|
-
|
|
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
|
|
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,
|
|
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,
|
|
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
|
|
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,
|
|
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
|
|
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,
|
|
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,
|
|
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
|
|
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,
|
|
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
|
|
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", {
|