@rebasepro/server-postgresql 0.2.3 → 0.2.5
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/default-collections.d.ts +9 -0
- package/dist/common/src/collections/index.d.ts +1 -0
- package/dist/common/src/util/permissions.d.ts +1 -0
- package/dist/index.es.js +1075 -470
- package/dist/index.es.js.map +1 -1
- package/dist/index.umd.js +1071 -466
- package/dist/index.umd.js.map +1 -1
- package/dist/server-postgresql/src/PostgresBackendDriver.d.ts +3 -1
- package/dist/server-postgresql/src/PostgresBootstrapper.d.ts +1 -0
- package/dist/server-postgresql/src/auth/services.d.ts +48 -31
- package/dist/server-postgresql/src/connection.d.ts +25 -0
- package/dist/server-postgresql/src/schema/auth-schema.d.ts +2135 -41
- package/dist/server-postgresql/src/services/EntityFetchService.d.ts +4 -0
- package/dist/server-postgresql/src/services/EntityPersistService.d.ts +4 -0
- package/dist/server-postgresql/src/services/entityService.d.ts +6 -0
- package/dist/server-postgresql/src/services/realtimeService.d.ts +20 -0
- package/dist/server-postgresql/src/utils/drizzle-conditions.d.ts +18 -0
- package/dist/types/src/controllers/auth.d.ts +4 -26
- package/dist/types/src/controllers/client.d.ts +25 -43
- package/dist/types/src/controllers/collection_registry.d.ts +1 -1
- package/dist/types/src/controllers/data.d.ts +4 -0
- package/dist/types/src/controllers/data_driver.d.ts +23 -0
- package/dist/types/src/controllers/registry.d.ts +5 -4
- package/dist/types/src/rebase_context.d.ts +1 -1
- package/dist/types/src/types/auth_adapter.d.ts +5 -60
- package/dist/types/src/types/backend.d.ts +2 -2
- package/dist/types/src/types/backend_hooks.d.ts +2 -17
- package/dist/types/src/types/collections.d.ts +0 -4
- package/dist/types/src/types/component_ref.d.ts +1 -1
- package/dist/types/src/types/cron.d.ts +1 -1
- package/dist/types/src/types/entity_views.d.ts +1 -0
- package/dist/types/src/types/export_import.d.ts +1 -1
- package/dist/types/src/types/formex.d.ts +2 -2
- package/dist/types/src/types/properties.d.ts +9 -7
- package/dist/types/src/types/translations.d.ts +28 -12
- package/dist/types/src/types/user_management_delegate.d.ts +22 -57
- package/dist/types/src/users/index.d.ts +0 -1
- package/dist/types/src/users/user.d.ts +0 -1
- package/package.json +6 -6
- package/src/PostgresBackendDriver.ts +14 -2
- package/src/PostgresBootstrapper.ts +30 -20
- package/src/auth/ensure-tables.ts +116 -103
- package/src/auth/services.ts +347 -177
- package/src/connection.ts +77 -0
- package/src/data-transformer.ts +2 -2
- package/src/schema/auth-schema.ts +85 -75
- package/src/schema/doctor.ts +44 -3
- package/src/schema/generate-drizzle-schema-logic.ts +33 -3
- package/src/schema/generate-drizzle-schema.ts +6 -6
- package/src/schema/introspect-db-logic.ts +7 -0
- package/src/services/EntityFetchService.ts +69 -10
- package/src/services/EntityPersistService.ts +9 -0
- package/src/services/entityService.ts +9 -0
- package/src/services/realtimeService.ts +214 -2
- package/src/utils/drizzle-conditions.ts +74 -2
- package/src/websocket.ts +10 -2
- package/test/auth-services.test.ts +10 -166
- package/test/doctor.test.ts +6 -2
- package/test/drizzle-conditions.test.ts +168 -0
- package/vite.config.ts +1 -1
- package/dist/server-postgresql/src/schema/default-collections.d.ts +0 -2
- package/dist/types/src/users/roles.d.ts +0 -22
- package/src/schema/default-collections.ts +0 -69
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { NodePgDatabase } from "drizzle-orm/node-postgres";
|
|
2
|
-
import { UserService,
|
|
2
|
+
import { UserService, RefreshTokenService, PasswordResetTokenService, Role } from "../src/auth/services";
|
|
3
3
|
import { users, refreshTokens, passwordResetTokens } from "../src/schema/auth-schema";
|
|
4
4
|
import { UserData } from "@rebasepro/server-core";
|
|
5
5
|
|
|
@@ -37,6 +37,7 @@ function mockUserData(overrides: Partial<UserData>): UserData {
|
|
|
37
37
|
createdAt: expect.any(Date),
|
|
38
38
|
updatedAt: expect.any(Date),
|
|
39
39
|
metadata: {},
|
|
40
|
+
isAnonymous: false,
|
|
40
41
|
...overrides
|
|
41
42
|
};
|
|
42
43
|
}
|
|
@@ -343,20 +344,7 @@ describe("Auth Services", () => {
|
|
|
343
344
|
describe("getUserRoles", () => {
|
|
344
345
|
it("should return roles for user", async () => {
|
|
345
346
|
mockExecute.mockResolvedValueOnce({
|
|
346
|
-
rows: [
|
|
347
|
-
{ id: "admin",
|
|
348
|
-
name: "Admin",
|
|
349
|
-
is_admin: true,
|
|
350
|
-
default_permissions: null,
|
|
351
|
-
collection_permissions: null,
|
|
352
|
-
config: null },
|
|
353
|
-
{ id: "editor",
|
|
354
|
-
name: "Editor",
|
|
355
|
-
is_admin: false,
|
|
356
|
-
default_permissions: { edit: true },
|
|
357
|
-
collection_permissions: null,
|
|
358
|
-
config: null }
|
|
359
|
-
]
|
|
347
|
+
rows: [{ roles: ["admin", "editor"] }]
|
|
360
348
|
});
|
|
361
349
|
|
|
362
350
|
const roles = await userService.getUserRoles("user-123");
|
|
@@ -364,11 +352,10 @@ describe("Auth Services", () => {
|
|
|
364
352
|
expect(roles).toHaveLength(2);
|
|
365
353
|
expect(roles[0]).toEqual({
|
|
366
354
|
id: "admin",
|
|
367
|
-
name: "
|
|
355
|
+
name: "admin",
|
|
368
356
|
isAdmin: true,
|
|
369
357
|
defaultPermissions: null,
|
|
370
|
-
collectionPermissions: null
|
|
371
|
-
config: null
|
|
358
|
+
collectionPermissions: null
|
|
372
359
|
});
|
|
373
360
|
});
|
|
374
361
|
});
|
|
@@ -376,14 +363,7 @@ describe("Auth Services", () => {
|
|
|
376
363
|
describe("getUserRoleIds", () => {
|
|
377
364
|
it("should return role IDs for user", async () => {
|
|
378
365
|
mockExecute.mockResolvedValueOnce({
|
|
379
|
-
rows: [
|
|
380
|
-
{ id: "admin",
|
|
381
|
-
name: "Admin",
|
|
382
|
-
is_admin: true,
|
|
383
|
-
default_permissions: null,
|
|
384
|
-
collection_permissions: null,
|
|
385
|
-
config: null }
|
|
386
|
-
]
|
|
366
|
+
rows: [{ roles: ["admin"] }]
|
|
387
367
|
});
|
|
388
368
|
|
|
389
369
|
const roleIds = await userService.getUserRoleIds("user-123");
|
|
@@ -396,10 +376,7 @@ describe("Auth Services", () => {
|
|
|
396
376
|
it("should delete existing and insert new roles", async () => {
|
|
397
377
|
await userService.setUserRoles("user-123", ["admin", "editor"]);
|
|
398
378
|
|
|
399
|
-
// First call deletes existing roles
|
|
400
379
|
expect(mockExecute).toHaveBeenCalled();
|
|
401
|
-
// Subsequent calls insert new roles
|
|
402
|
-
expect(mockExecute.mock.calls.length).toBeGreaterThanOrEqual(1);
|
|
403
380
|
});
|
|
404
381
|
});
|
|
405
382
|
|
|
@@ -411,7 +388,7 @@ describe("Auth Services", () => {
|
|
|
411
388
|
});
|
|
412
389
|
|
|
413
390
|
it("should use editor as default role", async () => {
|
|
414
|
-
await userService.assignDefaultRole("user-123");
|
|
391
|
+
await userService.assignDefaultRole("user-123", "editor");
|
|
415
392
|
|
|
416
393
|
expect(mockExecute).toHaveBeenCalled();
|
|
417
394
|
});
|
|
@@ -422,12 +399,7 @@ describe("Auth Services", () => {
|
|
|
422
399
|
const mockUser = { id: "user-123", email: "test@example.com" };
|
|
423
400
|
mockSelectWhere.mockResolvedValueOnce([mockUser]);
|
|
424
401
|
mockExecute.mockResolvedValueOnce({
|
|
425
|
-
rows: [{
|
|
426
|
-
name: "Admin",
|
|
427
|
-
is_admin: true,
|
|
428
|
-
default_permissions: null,
|
|
429
|
-
collection_permissions: null,
|
|
430
|
-
config: null }]
|
|
402
|
+
rows: [{ roles: ["admin"] }]
|
|
431
403
|
});
|
|
432
404
|
|
|
433
405
|
const result = await userService.getUserWithRoles("user-123");
|
|
@@ -435,11 +407,10 @@ describe("Auth Services", () => {
|
|
|
435
407
|
expect(result).toEqual({
|
|
436
408
|
user: mockUserData({}),
|
|
437
409
|
roles: [{ id: "admin",
|
|
438
|
-
name: "
|
|
410
|
+
name: "admin",
|
|
439
411
|
isAdmin: true,
|
|
440
412
|
defaultPermissions: null,
|
|
441
|
-
collectionPermissions: null
|
|
442
|
-
config: null }]
|
|
413
|
+
collectionPermissions: null }]
|
|
443
414
|
});
|
|
444
415
|
});
|
|
445
416
|
|
|
@@ -477,133 +448,6 @@ describe("Auth Services", () => {
|
|
|
477
448
|
});
|
|
478
449
|
});
|
|
479
450
|
|
|
480
|
-
describe("RoleService", () => {
|
|
481
|
-
let roleService: RoleService;
|
|
482
|
-
|
|
483
|
-
beforeEach(() => {
|
|
484
|
-
roleService = new RoleService(db);
|
|
485
|
-
});
|
|
486
|
-
|
|
487
|
-
describe("getRoleById", () => {
|
|
488
|
-
it("should return role when found", async () => {
|
|
489
|
-
mockExecute.mockResolvedValueOnce({
|
|
490
|
-
rows: [{ id: "admin",
|
|
491
|
-
name: "Admin",
|
|
492
|
-
is_admin: true,
|
|
493
|
-
default_permissions: null,
|
|
494
|
-
collection_permissions: null,
|
|
495
|
-
config: null }]
|
|
496
|
-
});
|
|
497
|
-
|
|
498
|
-
const result = await roleService.getRoleById("admin");
|
|
499
|
-
|
|
500
|
-
expect(result).toEqual({
|
|
501
|
-
id: "admin",
|
|
502
|
-
name: "Admin",
|
|
503
|
-
isAdmin: true,
|
|
504
|
-
defaultPermissions: null,
|
|
505
|
-
collectionPermissions: null,
|
|
506
|
-
config: null
|
|
507
|
-
});
|
|
508
|
-
});
|
|
509
|
-
|
|
510
|
-
it("should return null when role not found", async () => {
|
|
511
|
-
mockExecute.mockResolvedValueOnce({ rows: [] });
|
|
512
|
-
|
|
513
|
-
const result = await roleService.getRoleById("nonexistent");
|
|
514
|
-
|
|
515
|
-
expect(result).toBeNull();
|
|
516
|
-
});
|
|
517
|
-
});
|
|
518
|
-
|
|
519
|
-
describe("listRoles", () => {
|
|
520
|
-
it("should return all roles", async () => {
|
|
521
|
-
mockExecute.mockResolvedValueOnce({
|
|
522
|
-
rows: [
|
|
523
|
-
{ id: "admin",
|
|
524
|
-
name: "Admin",
|
|
525
|
-
is_admin: true,
|
|
526
|
-
default_permissions: null,
|
|
527
|
-
collection_permissions: null,
|
|
528
|
-
config: null },
|
|
529
|
-
{ id: "editor",
|
|
530
|
-
name: "Editor",
|
|
531
|
-
is_admin: false,
|
|
532
|
-
default_permissions: null,
|
|
533
|
-
collection_permissions: null,
|
|
534
|
-
config: null }
|
|
535
|
-
]
|
|
536
|
-
});
|
|
537
|
-
|
|
538
|
-
const roles = await roleService.listRoles();
|
|
539
|
-
|
|
540
|
-
expect(roles).toHaveLength(2);
|
|
541
|
-
});
|
|
542
|
-
});
|
|
543
|
-
|
|
544
|
-
describe("createRole", () => {
|
|
545
|
-
it("should create a role", async () => {
|
|
546
|
-
mockExecute.mockResolvedValueOnce({
|
|
547
|
-
rows: [{ id: "custom",
|
|
548
|
-
name: "Custom Role",
|
|
549
|
-
is_admin: false,
|
|
550
|
-
default_permissions: null,
|
|
551
|
-
collection_permissions: null,
|
|
552
|
-
config: null }]
|
|
553
|
-
});
|
|
554
|
-
|
|
555
|
-
const role = await roleService.createRole({
|
|
556
|
-
id: "custom",
|
|
557
|
-
name: "Custom Role",
|
|
558
|
-
defaultPermissions: null,
|
|
559
|
-
config: null
|
|
560
|
-
});
|
|
561
|
-
|
|
562
|
-
expect(role.id).toBe("custom");
|
|
563
|
-
expect(role.name).toBe("Custom Role");
|
|
564
|
-
});
|
|
565
|
-
});
|
|
566
|
-
|
|
567
|
-
describe("updateRole", () => {
|
|
568
|
-
it("should update a role", async () => {
|
|
569
|
-
mockExecute
|
|
570
|
-
.mockResolvedValueOnce({ rows: [{ id: "admin",
|
|
571
|
-
name: "Admin",
|
|
572
|
-
is_admin: true,
|
|
573
|
-
default_permissions: null,
|
|
574
|
-
collection_permissions: null,
|
|
575
|
-
config: null }] })
|
|
576
|
-
.mockResolvedValueOnce({ rows: [] })
|
|
577
|
-
.mockResolvedValueOnce({ rows: [{ id: "admin",
|
|
578
|
-
name: "Super Admin",
|
|
579
|
-
is_admin: true,
|
|
580
|
-
default_permissions: null,
|
|
581
|
-
collection_permissions: null,
|
|
582
|
-
config: null }] });
|
|
583
|
-
|
|
584
|
-
const result = await roleService.updateRole("admin", { name: "Super Admin" });
|
|
585
|
-
|
|
586
|
-
expect(result?.name).toBe("Super Admin");
|
|
587
|
-
});
|
|
588
|
-
|
|
589
|
-
it("should return null when role not found", async () => {
|
|
590
|
-
mockExecute.mockResolvedValueOnce({ rows: [] });
|
|
591
|
-
|
|
592
|
-
const result = await roleService.updateRole("nonexistent", { name: "Test" });
|
|
593
|
-
|
|
594
|
-
expect(result).toBeNull();
|
|
595
|
-
});
|
|
596
|
-
});
|
|
597
|
-
|
|
598
|
-
describe("deleteRole", () => {
|
|
599
|
-
it("should delete a role", async () => {
|
|
600
|
-
await roleService.deleteRole("custom");
|
|
601
|
-
|
|
602
|
-
expect(mockExecute).toHaveBeenCalled();
|
|
603
|
-
});
|
|
604
|
-
});
|
|
605
|
-
});
|
|
606
|
-
|
|
607
451
|
describe("RefreshTokenService", () => {
|
|
608
452
|
let refreshTokenService: RefreshTokenService;
|
|
609
453
|
|
package/test/doctor.test.ts
CHANGED
|
@@ -135,8 +135,12 @@ columnType: "time" } as DateProperty)).toBe("time without time zone");
|
|
|
135
135
|
it("should map json types correctly", () => {
|
|
136
136
|
expect(getExpectedColumnType({ type: "map" })).toBe("jsonb");
|
|
137
137
|
expect(getExpectedColumnType({ type: "array" })).toBe("jsonb");
|
|
138
|
-
expect(getExpectedColumnType({ type: "array",
|
|
139
|
-
|
|
138
|
+
expect(getExpectedColumnType({ type: "array", columnType: "json" } as ArrayProperty)).toBe("json");
|
|
139
|
+
|
|
140
|
+
// Native array element type mappings
|
|
141
|
+
expect(getExpectedColumnType({ type: "array", of: { type: "string" } } as ArrayProperty)).toBe("ARRAY");
|
|
142
|
+
expect(getExpectedColumnType({ type: "array", of: { type: "number", validation: { integer: true } } } as ArrayProperty)).toBe("ARRAY");
|
|
143
|
+
expect(getExpectedColumnType({ type: "array", of: { type: "boolean" } } as ArrayProperty)).toBe("ARRAY");
|
|
140
144
|
});
|
|
141
145
|
|
|
142
146
|
it("should map enum string to USER-DEFINED", () => {
|
|
@@ -893,3 +893,171 @@ describe("DrizzleConditionBuilder - Many-to-Many Relations", () => {
|
|
|
893
893
|
});
|
|
894
894
|
});
|
|
895
895
|
});
|
|
896
|
+
|
|
897
|
+
describe("DrizzleConditionBuilder - Filter Operators", () => {
|
|
898
|
+
// Mock table for filter tests
|
|
899
|
+
const mockUsersTable = pgTable("users", {
|
|
900
|
+
id: serial("id").primaryKey(),
|
|
901
|
+
name: varchar("name").notNull(),
|
|
902
|
+
email: varchar("email").notNull(),
|
|
903
|
+
age: integer("age")
|
|
904
|
+
});
|
|
905
|
+
|
|
906
|
+
describe("buildSingleFilterCondition - array-contains", () => {
|
|
907
|
+
it("should generate a non-null condition for a single value", () => {
|
|
908
|
+
const condition = DrizzleConditionBuilder.buildSingleFilterCondition(
|
|
909
|
+
mockUsersTable.name,
|
|
910
|
+
"array-contains",
|
|
911
|
+
"featured"
|
|
912
|
+
);
|
|
913
|
+
expect(condition).not.toBeNull();
|
|
914
|
+
});
|
|
915
|
+
});
|
|
916
|
+
|
|
917
|
+
describe("buildSingleFilterCondition - array-contains-any", () => {
|
|
918
|
+
it("should generate a non-null condition for an array of values", () => {
|
|
919
|
+
const condition = DrizzleConditionBuilder.buildSingleFilterCondition(
|
|
920
|
+
mockUsersTable.name,
|
|
921
|
+
"array-contains-any",
|
|
922
|
+
["featured", "popular", "trending"]
|
|
923
|
+
);
|
|
924
|
+
expect(condition).not.toBeNull();
|
|
925
|
+
});
|
|
926
|
+
|
|
927
|
+
it("should fallback to array-contains for a single (non-array) value", () => {
|
|
928
|
+
const condition = DrizzleConditionBuilder.buildSingleFilterCondition(
|
|
929
|
+
mockUsersTable.name,
|
|
930
|
+
"array-contains-any",
|
|
931
|
+
"featured"
|
|
932
|
+
);
|
|
933
|
+
expect(condition).not.toBeNull();
|
|
934
|
+
});
|
|
935
|
+
});
|
|
936
|
+
|
|
937
|
+
describe("buildSingleFilterCondition - not-in", () => {
|
|
938
|
+
it("should generate a non-null condition for an array of values", () => {
|
|
939
|
+
const condition = DrizzleConditionBuilder.buildSingleFilterCondition(
|
|
940
|
+
mockUsersTable.age,
|
|
941
|
+
"not-in",
|
|
942
|
+
[1, 2, 3]
|
|
943
|
+
);
|
|
944
|
+
expect(condition).not.toBeNull();
|
|
945
|
+
});
|
|
946
|
+
|
|
947
|
+
it("should return null for empty array", () => {
|
|
948
|
+
const condition = DrizzleConditionBuilder.buildSingleFilterCondition(
|
|
949
|
+
mockUsersTable.age,
|
|
950
|
+
"not-in",
|
|
951
|
+
[]
|
|
952
|
+
);
|
|
953
|
+
expect(condition).toBeNull();
|
|
954
|
+
});
|
|
955
|
+
|
|
956
|
+
it("should return null for non-array value", () => {
|
|
957
|
+
const condition = DrizzleConditionBuilder.buildSingleFilterCondition(
|
|
958
|
+
mockUsersTable.age,
|
|
959
|
+
"not-in",
|
|
960
|
+
42
|
|
961
|
+
);
|
|
962
|
+
expect(condition).toBeNull();
|
|
963
|
+
});
|
|
964
|
+
});
|
|
965
|
+
|
|
966
|
+
describe("buildSingleFilterCondition - existing operators", () => {
|
|
967
|
+
it("should generate a condition for equality", () => {
|
|
968
|
+
const condition = DrizzleConditionBuilder.buildSingleFilterCondition(
|
|
969
|
+
mockUsersTable.name,
|
|
970
|
+
"==",
|
|
971
|
+
"alice"
|
|
972
|
+
);
|
|
973
|
+
expect(condition).not.toBeNull();
|
|
974
|
+
});
|
|
975
|
+
|
|
976
|
+
it("should generate IS NULL for equality with null", () => {
|
|
977
|
+
const condition = DrizzleConditionBuilder.buildSingleFilterCondition(
|
|
978
|
+
mockUsersTable.name,
|
|
979
|
+
"==",
|
|
980
|
+
null
|
|
981
|
+
);
|
|
982
|
+
expect(condition).not.toBeNull();
|
|
983
|
+
});
|
|
984
|
+
|
|
985
|
+
it("should generate IS NOT NULL for inequality with null", () => {
|
|
986
|
+
const condition = DrizzleConditionBuilder.buildSingleFilterCondition(
|
|
987
|
+
mockUsersTable.name,
|
|
988
|
+
"!=",
|
|
989
|
+
null
|
|
990
|
+
);
|
|
991
|
+
expect(condition).not.toBeNull();
|
|
992
|
+
});
|
|
993
|
+
|
|
994
|
+
it("should handle in operator with array", () => {
|
|
995
|
+
const condition = DrizzleConditionBuilder.buildSingleFilterCondition(
|
|
996
|
+
mockUsersTable.age,
|
|
997
|
+
"in",
|
|
998
|
+
[18, 21, 25]
|
|
999
|
+
);
|
|
1000
|
+
expect(condition).not.toBeNull();
|
|
1001
|
+
});
|
|
1002
|
+
|
|
1003
|
+
it("should return null for in operator with empty array", () => {
|
|
1004
|
+
const condition = DrizzleConditionBuilder.buildSingleFilterCondition(
|
|
1005
|
+
mockUsersTable.age,
|
|
1006
|
+
"in",
|
|
1007
|
+
[]
|
|
1008
|
+
);
|
|
1009
|
+
expect(condition).toBeNull();
|
|
1010
|
+
});
|
|
1011
|
+
|
|
1012
|
+
it("should warn and return null for unsupported operators", () => {
|
|
1013
|
+
const warnSpy = jest.spyOn(console, "warn").mockImplementation(() => {});
|
|
1014
|
+
const condition = DrizzleConditionBuilder.buildSingleFilterCondition(
|
|
1015
|
+
mockUsersTable.age,
|
|
1016
|
+
"unknown-op" as any,
|
|
1017
|
+
42
|
|
1018
|
+
);
|
|
1019
|
+
expect(condition).toBeNull();
|
|
1020
|
+
expect(warnSpy).toHaveBeenCalledWith("Unsupported filter operation: unknown-op");
|
|
1021
|
+
warnSpy.mockRestore();
|
|
1022
|
+
});
|
|
1023
|
+
});
|
|
1024
|
+
|
|
1025
|
+
describe("buildFilterConditions - integration with array operators", () => {
|
|
1026
|
+
it("should build filter with array-contains operator", () => {
|
|
1027
|
+
const conditions = DrizzleConditionBuilder.buildFilterConditions(
|
|
1028
|
+
{ name: ["array-contains", "featured"] },
|
|
1029
|
+
mockUsersTable,
|
|
1030
|
+
"users"
|
|
1031
|
+
);
|
|
1032
|
+
expect(conditions).toHaveLength(1);
|
|
1033
|
+
});
|
|
1034
|
+
|
|
1035
|
+
it("should build filter with array-contains-any operator", () => {
|
|
1036
|
+
const conditions = DrizzleConditionBuilder.buildFilterConditions(
|
|
1037
|
+
{ name: ["array-contains-any", ["featured", "popular"]] },
|
|
1038
|
+
mockUsersTable,
|
|
1039
|
+
"users"
|
|
1040
|
+
);
|
|
1041
|
+
expect(conditions).toHaveLength(1);
|
|
1042
|
+
});
|
|
1043
|
+
|
|
1044
|
+
it("should build filter with not-in operator", () => {
|
|
1045
|
+
const conditions = DrizzleConditionBuilder.buildFilterConditions(
|
|
1046
|
+
{ age: ["not-in", [1, 2, 3]] },
|
|
1047
|
+
mockUsersTable,
|
|
1048
|
+
"users"
|
|
1049
|
+
);
|
|
1050
|
+
expect(conditions).toHaveLength(1);
|
|
1051
|
+
});
|
|
1052
|
+
|
|
1053
|
+
it("should skip not-in filter with empty array", () => {
|
|
1054
|
+
const conditions = DrizzleConditionBuilder.buildFilterConditions(
|
|
1055
|
+
{ age: ["not-in", []] },
|
|
1056
|
+
mockUsersTable,
|
|
1057
|
+
"users"
|
|
1058
|
+
);
|
|
1059
|
+
expect(conditions).toHaveLength(0);
|
|
1060
|
+
});
|
|
1061
|
+
});
|
|
1062
|
+
});
|
|
1063
|
+
|
package/vite.config.ts
CHANGED
|
@@ -33,7 +33,7 @@ const isExternal = (id: string) => {
|
|
|
33
33
|
// Externalize only deps the consumer app explicitly installs
|
|
34
34
|
if (CONSUMER_EXTERNALS.some(ext => id === ext || id.startsWith(ext + "/"))) return true;
|
|
35
35
|
// Externalize Node built-ins
|
|
36
|
-
if (["fs", "path", "url", "util", "crypto", "http", "https", "net", "tls", "stream", "events", "os", "child_process", "buffer", "assert", "node:"].some(b => id === b || id.startsWith("node:") || id.startsWith(b + "/"))) return true;
|
|
36
|
+
if (["fs", "path", "url", "util", "crypto", "http", "https", "net", "tls", "stream", "events", "os", "child_process", "buffer", "assert", "dns", "zlib", "querystring", "node:"].some(b => id === b || id.startsWith("node:") || id.startsWith(b + "/"))) return true;
|
|
37
37
|
// Inline everything else (jsonwebtoken, ws, zod, etc.)
|
|
38
38
|
return false;
|
|
39
39
|
};
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
export type Role = {
|
|
2
|
-
/**
|
|
3
|
-
* ID of the role
|
|
4
|
-
*/
|
|
5
|
-
id: string;
|
|
6
|
-
/**
|
|
7
|
-
* Name of the role
|
|
8
|
-
*/
|
|
9
|
-
name: string;
|
|
10
|
-
/**
|
|
11
|
-
* If this flag is true, the user can perform any action
|
|
12
|
-
*/
|
|
13
|
-
isAdmin?: boolean;
|
|
14
|
-
/**
|
|
15
|
-
* Permissions related to editing the collections
|
|
16
|
-
*/
|
|
17
|
-
config?: {
|
|
18
|
-
createCollections?: boolean;
|
|
19
|
-
editCollections?: boolean | "own";
|
|
20
|
-
deleteCollections?: boolean | "own";
|
|
21
|
-
};
|
|
22
|
-
};
|
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
import { PostgresCollection } from "@rebasepro/types";
|
|
2
|
-
|
|
3
|
-
export const defaultUsersCollection: PostgresCollection = {
|
|
4
|
-
name: "Users",
|
|
5
|
-
singularName: "User",
|
|
6
|
-
slug: "users",
|
|
7
|
-
table: "users",
|
|
8
|
-
schema: "rebase",
|
|
9
|
-
icon: "Users",
|
|
10
|
-
group: "Settings",
|
|
11
|
-
properties: {
|
|
12
|
-
id: {
|
|
13
|
-
name: "ID",
|
|
14
|
-
type: "string",
|
|
15
|
-
isId: "uuid"
|
|
16
|
-
},
|
|
17
|
-
email: {
|
|
18
|
-
name: "Email",
|
|
19
|
-
type: "string",
|
|
20
|
-
validation: { required: true, unique: true }
|
|
21
|
-
},
|
|
22
|
-
password_hash: {
|
|
23
|
-
name: "Password Hash",
|
|
24
|
-
type: "string",
|
|
25
|
-
ui: { hideFromCollection: true }
|
|
26
|
-
},
|
|
27
|
-
display_name: {
|
|
28
|
-
name: "Display Name",
|
|
29
|
-
type: "string"
|
|
30
|
-
},
|
|
31
|
-
photo_url: {
|
|
32
|
-
name: "Photo URL",
|
|
33
|
-
type: "string"
|
|
34
|
-
},
|
|
35
|
-
email_verified: {
|
|
36
|
-
name: "Email Verified",
|
|
37
|
-
type: "boolean",
|
|
38
|
-
defaultValue: false
|
|
39
|
-
},
|
|
40
|
-
email_verification_token: {
|
|
41
|
-
name: "Email Verification Token",
|
|
42
|
-
type: "string",
|
|
43
|
-
ui: { hideFromCollection: true }
|
|
44
|
-
},
|
|
45
|
-
email_verification_sent_at: {
|
|
46
|
-
name: "Email Verification Sent At",
|
|
47
|
-
type: "date",
|
|
48
|
-
ui: { hideFromCollection: true }
|
|
49
|
-
},
|
|
50
|
-
metadata: {
|
|
51
|
-
name: "Metadata",
|
|
52
|
-
type: "map",
|
|
53
|
-
defaultValue: {},
|
|
54
|
-
ui: { hideFromCollection: true }
|
|
55
|
-
},
|
|
56
|
-
created_at: {
|
|
57
|
-
name: "Created At",
|
|
58
|
-
type: "date",
|
|
59
|
-
autoValue: "on_create",
|
|
60
|
-
ui: { readOnly: true, hideFromCollection: true }
|
|
61
|
-
},
|
|
62
|
-
updated_at: {
|
|
63
|
-
name: "Updated At",
|
|
64
|
-
type: "date",
|
|
65
|
-
autoValue: "on_update",
|
|
66
|
-
ui: { readOnly: true, hideFromCollection: true }
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
};
|