@rebasepro/server-postgresql 0.2.5 → 0.4.0
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/data/query_builder.d.ts +6 -2
- package/dist/index.es.js +93 -213
- package/dist/index.es.js.map +1 -1
- package/dist/index.umd.js +92 -212
- package/dist/index.umd.js.map +1 -1
- package/dist/server-postgresql/src/auth/ensure-tables.d.ts +7 -4
- package/dist/server-postgresql/src/services/EntityFetchService.d.ts +2 -1
- package/dist/server-postgresql/src/utils/drizzle-conditions.d.ts +5 -1
- package/dist/types/src/controllers/data.d.ts +17 -3
- package/dist/types/src/controllers/email.d.ts +2 -0
- package/dist/types/src/types/collections.d.ts +9 -5
- package/dist/types/src/types/entity_views.d.ts +19 -28
- package/dist/types/src/types/properties.d.ts +2 -2
- package/package.json +6 -6
- package/src/PostgresBootstrapper.ts +22 -9
- package/src/auth/ensure-tables.ts +30 -28
- package/src/schema/generate-drizzle-schema.ts +2 -6
- package/src/services/EntityFetchService.ts +13 -1
- package/src/utils/drizzle-conditions.ts +40 -5
- package/src/websocket.ts +1 -3
- package/test/relation-pipeline-gaps.test.ts +315 -0
package/dist/index.umd.js
CHANGED
|
@@ -2719,166 +2719,6 @@
|
|
|
2719
2719
|
};
|
|
2720
2720
|
}
|
|
2721
2721
|
}
|
|
2722
|
-
const defaultUsersCollection = {
|
|
2723
|
-
name: "Users",
|
|
2724
|
-
singularName: "User",
|
|
2725
|
-
slug: "users",
|
|
2726
|
-
table: "users",
|
|
2727
|
-
schema: "rebase",
|
|
2728
|
-
icon: "Users",
|
|
2729
|
-
group: "Settings",
|
|
2730
|
-
openEntityMode: "dialog",
|
|
2731
|
-
disableDefaultActions: ["copy"],
|
|
2732
|
-
sort: ["createdAt", "desc"],
|
|
2733
|
-
properties: {
|
|
2734
|
-
id: {
|
|
2735
|
-
name: "ID",
|
|
2736
|
-
type: "string",
|
|
2737
|
-
isId: "uuid",
|
|
2738
|
-
ui: {
|
|
2739
|
-
readOnly: true
|
|
2740
|
-
}
|
|
2741
|
-
},
|
|
2742
|
-
email: {
|
|
2743
|
-
name: "Email",
|
|
2744
|
-
type: "string",
|
|
2745
|
-
validation: {
|
|
2746
|
-
required: true,
|
|
2747
|
-
unique: true
|
|
2748
|
-
}
|
|
2749
|
-
},
|
|
2750
|
-
displayName: {
|
|
2751
|
-
name: "Name",
|
|
2752
|
-
type: "string",
|
|
2753
|
-
columnName: "display_name",
|
|
2754
|
-
validation: {
|
|
2755
|
-
required: true
|
|
2756
|
-
}
|
|
2757
|
-
},
|
|
2758
|
-
photoURL: {
|
|
2759
|
-
name: "Photo URL",
|
|
2760
|
-
type: "string",
|
|
2761
|
-
columnName: "photo_url",
|
|
2762
|
-
url: "image"
|
|
2763
|
-
},
|
|
2764
|
-
roles: {
|
|
2765
|
-
name: "Roles",
|
|
2766
|
-
type: "array",
|
|
2767
|
-
columnType: "text[]",
|
|
2768
|
-
of: {
|
|
2769
|
-
name: "Role",
|
|
2770
|
-
type: "string",
|
|
2771
|
-
enum: {
|
|
2772
|
-
admin: "Admin",
|
|
2773
|
-
editor: "Editor",
|
|
2774
|
-
viewer: "Viewer"
|
|
2775
|
-
}
|
|
2776
|
-
}
|
|
2777
|
-
},
|
|
2778
|
-
passwordHash: {
|
|
2779
|
-
name: "Password Hash",
|
|
2780
|
-
type: "string",
|
|
2781
|
-
columnName: "password_hash",
|
|
2782
|
-
ui: {
|
|
2783
|
-
hideFromCollection: true,
|
|
2784
|
-
disabled: {
|
|
2785
|
-
hidden: true
|
|
2786
|
-
}
|
|
2787
|
-
}
|
|
2788
|
-
},
|
|
2789
|
-
emailVerified: {
|
|
2790
|
-
name: "Email Verified",
|
|
2791
|
-
type: "boolean",
|
|
2792
|
-
columnName: "email_verified",
|
|
2793
|
-
defaultValue: false,
|
|
2794
|
-
ui: {
|
|
2795
|
-
hideFromCollection: true,
|
|
2796
|
-
disabled: {
|
|
2797
|
-
hidden: true
|
|
2798
|
-
}
|
|
2799
|
-
}
|
|
2800
|
-
},
|
|
2801
|
-
emailVerificationToken: {
|
|
2802
|
-
name: "Email Verification Token",
|
|
2803
|
-
type: "string",
|
|
2804
|
-
columnName: "email_verification_token",
|
|
2805
|
-
ui: {
|
|
2806
|
-
hideFromCollection: true,
|
|
2807
|
-
disabled: {
|
|
2808
|
-
hidden: true
|
|
2809
|
-
}
|
|
2810
|
-
}
|
|
2811
|
-
},
|
|
2812
|
-
emailVerificationSentAt: {
|
|
2813
|
-
name: "Email Verification Sent At",
|
|
2814
|
-
type: "date",
|
|
2815
|
-
columnName: "email_verification_sent_at",
|
|
2816
|
-
ui: {
|
|
2817
|
-
hideFromCollection: true,
|
|
2818
|
-
disabled: {
|
|
2819
|
-
hidden: true
|
|
2820
|
-
}
|
|
2821
|
-
}
|
|
2822
|
-
},
|
|
2823
|
-
metadata: {
|
|
2824
|
-
name: "Metadata",
|
|
2825
|
-
type: "map",
|
|
2826
|
-
defaultValue: {},
|
|
2827
|
-
ui: {
|
|
2828
|
-
hideFromCollection: true,
|
|
2829
|
-
disabled: {
|
|
2830
|
-
hidden: true
|
|
2831
|
-
}
|
|
2832
|
-
}
|
|
2833
|
-
},
|
|
2834
|
-
createdAt: {
|
|
2835
|
-
name: "Created At",
|
|
2836
|
-
type: "date",
|
|
2837
|
-
columnName: "created_at",
|
|
2838
|
-
ui: {
|
|
2839
|
-
readOnly: true
|
|
2840
|
-
}
|
|
2841
|
-
},
|
|
2842
|
-
updatedAt: {
|
|
2843
|
-
name: "Updated At",
|
|
2844
|
-
type: "date",
|
|
2845
|
-
columnName: "updated_at",
|
|
2846
|
-
autoValue: "on_update",
|
|
2847
|
-
ui: {
|
|
2848
|
-
hideFromCollection: true,
|
|
2849
|
-
disabled: {
|
|
2850
|
-
hidden: true
|
|
2851
|
-
}
|
|
2852
|
-
}
|
|
2853
|
-
}
|
|
2854
|
-
},
|
|
2855
|
-
listProperties: ["displayName", "email", "roles", "createdAt"],
|
|
2856
|
-
propertiesOrder: ["id", "email", "displayName", "roles", "createdAt"]
|
|
2857
|
-
};
|
|
2858
|
-
function mapOperator(op) {
|
|
2859
|
-
switch (op) {
|
|
2860
|
-
case "==":
|
|
2861
|
-
return "eq";
|
|
2862
|
-
case "!=":
|
|
2863
|
-
return "neq";
|
|
2864
|
-
case ">":
|
|
2865
|
-
return "gt";
|
|
2866
|
-
case ">=":
|
|
2867
|
-
return "gte";
|
|
2868
|
-
case "<":
|
|
2869
|
-
return "lt";
|
|
2870
|
-
case "<=":
|
|
2871
|
-
return "lte";
|
|
2872
|
-
case "array-contains":
|
|
2873
|
-
return "cs";
|
|
2874
|
-
case "array-contains-any":
|
|
2875
|
-
return "csa";
|
|
2876
|
-
case "not-in":
|
|
2877
|
-
return "nin";
|
|
2878
|
-
default:
|
|
2879
|
-
return op;
|
|
2880
|
-
}
|
|
2881
|
-
}
|
|
2882
2722
|
class QueryBuilder {
|
|
2883
2723
|
constructor(collection) {
|
|
2884
2724
|
this.collection = collection;
|
|
@@ -2886,23 +2726,30 @@
|
|
|
2886
2726
|
params = {
|
|
2887
2727
|
where: {}
|
|
2888
2728
|
};
|
|
2889
|
-
|
|
2890
|
-
|
|
2891
|
-
|
|
2892
|
-
|
|
2893
|
-
|
|
2894
|
-
where(column, operator, value) {
|
|
2729
|
+
where(columnOrCondition, operator, value) {
|
|
2730
|
+
if (typeof columnOrCondition === "object" && columnOrCondition !== null && "type" in columnOrCondition) {
|
|
2731
|
+
this.params.logical = columnOrCondition;
|
|
2732
|
+
return this;
|
|
2733
|
+
}
|
|
2895
2734
|
if (!this.params.where) {
|
|
2896
2735
|
this.params.where = {};
|
|
2897
2736
|
}
|
|
2898
|
-
const
|
|
2899
|
-
|
|
2900
|
-
|
|
2901
|
-
|
|
2902
|
-
|
|
2903
|
-
|
|
2737
|
+
const column = columnOrCondition;
|
|
2738
|
+
const condition = [operator, value];
|
|
2739
|
+
const existing = this.params.where[column];
|
|
2740
|
+
if (existing === void 0) {
|
|
2741
|
+
this.params.where[column] = condition;
|
|
2742
|
+
} else if (Array.isArray(existing) && existing.length > 0 && Array.isArray(existing[0])) {
|
|
2743
|
+
this.params.where[column].push(condition);
|
|
2744
|
+
} else {
|
|
2745
|
+
let firstCondition;
|
|
2746
|
+
if (Array.isArray(existing) && existing.length === 2 && typeof existing[0] === "string") {
|
|
2747
|
+
firstCondition = existing;
|
|
2748
|
+
} else {
|
|
2749
|
+
firstCondition = ["==", existing];
|
|
2750
|
+
}
|
|
2751
|
+
this.params.where[column] = [firstCondition, condition];
|
|
2904
2752
|
}
|
|
2905
|
-
this.params.where[column] = mappedOp === "eq" ? String(formattedValue) : `${mappedOp}.${formattedValue}`;
|
|
2906
2753
|
return this;
|
|
2907
2754
|
}
|
|
2908
2755
|
/**
|
|
@@ -3004,10 +2851,13 @@
|
|
|
3004
2851
|
filter[field] = ["==", rawValue];
|
|
3005
2852
|
continue;
|
|
3006
2853
|
}
|
|
3007
|
-
if (Array.isArray(rawValue)
|
|
3008
|
-
const [
|
|
3009
|
-
const
|
|
3010
|
-
|
|
2854
|
+
if (Array.isArray(rawValue)) {
|
|
2855
|
+
const conditions = Array.isArray(rawValue[0]) ? rawValue : [rawValue];
|
|
2856
|
+
const mappedConditions = conditions.map(([rawOp, val]) => {
|
|
2857
|
+
const mappedOp = operatorMap[rawOp] ?? "==";
|
|
2858
|
+
return [mappedOp, val];
|
|
2859
|
+
});
|
|
2860
|
+
filter[field] = Array.isArray(rawValue[0]) ? mappedConditions : mappedConditions[0];
|
|
3011
2861
|
continue;
|
|
3012
2862
|
}
|
|
3013
2863
|
if (typeof rawValue === "string") {
|
|
@@ -3145,8 +2995,12 @@
|
|
|
3145
2995
|
});
|
|
3146
2996
|
} : void 0,
|
|
3147
2997
|
// Fluent Query Builder
|
|
3148
|
-
where(
|
|
3149
|
-
|
|
2998
|
+
where(columnOrCondition, operator, value) {
|
|
2999
|
+
const builder = new QueryBuilder(accessor);
|
|
3000
|
+
if (typeof columnOrCondition === "object") {
|
|
3001
|
+
return builder.where(columnOrCondition);
|
|
3002
|
+
}
|
|
3003
|
+
return builder.where(columnOrCondition, operator, value);
|
|
3150
3004
|
},
|
|
3151
3005
|
orderBy(column, ascending) {
|
|
3152
3006
|
return new QueryBuilder(accessor).orderBy(column, ascending);
|
|
@@ -3197,7 +3051,6 @@
|
|
|
3197
3051
|
const conditions = [];
|
|
3198
3052
|
for (const [field, filterParam] of Object.entries(filter)) {
|
|
3199
3053
|
if (!filterParam) continue;
|
|
3200
|
-
const [op, value] = filterParam;
|
|
3201
3054
|
let fieldColumn = table[field];
|
|
3202
3055
|
if (!fieldColumn) {
|
|
3203
3056
|
const relationKey = `${field}_id`;
|
|
@@ -3209,13 +3062,39 @@
|
|
|
3209
3062
|
console.warn(`Filtering by field '${field}', but it does not exist in table for collection '${collectionPath}'`);
|
|
3210
3063
|
continue;
|
|
3211
3064
|
}
|
|
3212
|
-
const
|
|
3213
|
-
|
|
3214
|
-
|
|
3065
|
+
const paramsList = Array.isArray(filterParam) && filterParam.length > 0 && Array.isArray(filterParam[0]) ? filterParam : [filterParam];
|
|
3066
|
+
for (const [op, value] of paramsList) {
|
|
3067
|
+
const condition = this.buildSingleFilterCondition(fieldColumn, op, value);
|
|
3068
|
+
if (condition) {
|
|
3069
|
+
conditions.push(condition);
|
|
3070
|
+
}
|
|
3215
3071
|
}
|
|
3216
3072
|
}
|
|
3217
3073
|
return conditions;
|
|
3218
3074
|
}
|
|
3075
|
+
/**
|
|
3076
|
+
* Build logical conditions recursively from LogicalCondition or FilterCondition
|
|
3077
|
+
*/
|
|
3078
|
+
static buildLogicalConditions(cond, table, collectionPath) {
|
|
3079
|
+
if ("type" in cond) {
|
|
3080
|
+
const subSQLs = cond.conditions.map((c) => this.buildLogicalConditions(c, table, collectionPath)).filter((sql2) => sql2 !== null);
|
|
3081
|
+
if (subSQLs.length === 0) return null;
|
|
3082
|
+
return (cond.type === "or" ? drizzleOrm.or(...subSQLs) : drizzleOrm.and(...subSQLs)) ?? null;
|
|
3083
|
+
} else {
|
|
3084
|
+
let fieldColumn = table[cond.column];
|
|
3085
|
+
if (!fieldColumn) {
|
|
3086
|
+
const relationKey = `${cond.column}_id`;
|
|
3087
|
+
if (relationKey in table) {
|
|
3088
|
+
fieldColumn = table[relationKey];
|
|
3089
|
+
}
|
|
3090
|
+
}
|
|
3091
|
+
if (!fieldColumn) {
|
|
3092
|
+
console.warn(`Filtering by field '${cond.column}', but it does not exist in table for collection '${collectionPath}'`);
|
|
3093
|
+
return null;
|
|
3094
|
+
}
|
|
3095
|
+
return this.buildSingleFilterCondition(fieldColumn, cond.operator, cond.value);
|
|
3096
|
+
}
|
|
3097
|
+
}
|
|
3219
3098
|
/**
|
|
3220
3099
|
* Build a single filter condition for a specific operator and value
|
|
3221
3100
|
*/
|
|
@@ -5612,6 +5491,10 @@
|
|
|
5612
5491
|
const filterConditions = this.buildFilterConditions(options.filter, table, collectionPath);
|
|
5613
5492
|
if (filterConditions.length > 0) allConditions.push(...filterConditions);
|
|
5614
5493
|
}
|
|
5494
|
+
if (options.logical) {
|
|
5495
|
+
const logicalCondition = DrizzleConditionBuilder.buildLogicalConditions(options.logical, table, collectionPath);
|
|
5496
|
+
if (logicalCondition) allConditions.push(logicalCondition);
|
|
5497
|
+
}
|
|
5615
5498
|
if (options.startAfter) {
|
|
5616
5499
|
const cursorConditions = this.buildCursorConditions(table, idField, idInfo, options, collectionPath);
|
|
5617
5500
|
if (cursorConditions.length > 0) allConditions.push(...cursorConditions);
|
|
@@ -5783,6 +5666,10 @@
|
|
|
5783
5666
|
const filterConditions = this.buildFilterConditions(options.filter, table, collectionPath);
|
|
5784
5667
|
if (filterConditions.length > 0) allConditions.push(...filterConditions);
|
|
5785
5668
|
}
|
|
5669
|
+
if (options.logical) {
|
|
5670
|
+
const logicalCondition = DrizzleConditionBuilder.buildLogicalConditions(options.logical, table, collectionPath);
|
|
5671
|
+
if (logicalCondition) allConditions.push(logicalCondition);
|
|
5672
|
+
}
|
|
5786
5673
|
if (vectorMeta?.filter) {
|
|
5787
5674
|
allConditions.push(vectorMeta.filter);
|
|
5788
5675
|
}
|
|
@@ -8741,7 +8628,6 @@ ${tableRelations.join(",\n")}
|
|
|
8741
8628
|
if (!collections || !Array.isArray(collections)) {
|
|
8742
8629
|
collections = [];
|
|
8743
8630
|
}
|
|
8744
|
-
collections = Array.from(new Map([defaultUsersCollection, ...collections].map((c) => [c.slug, c])).values());
|
|
8745
8631
|
collections.sort((a, b) => a.slug.localeCompare(b.slug));
|
|
8746
8632
|
const schemaContent = await generateSchema(collections);
|
|
8747
8633
|
if (outputPath) {
|
|
@@ -10349,31 +10235,23 @@ ${tableRelations.join(",\n")}
|
|
|
10349
10235
|
return collection.relations.map((r) => r.relationName || r.localKey || "").filter(Boolean);
|
|
10350
10236
|
}
|
|
10351
10237
|
}
|
|
10352
|
-
async function ensureAuthTablesExist(db,
|
|
10238
|
+
async function ensureAuthTablesExist(db, collection) {
|
|
10353
10239
|
serverCore.logger.info("🔍 Checking auth tables...");
|
|
10354
10240
|
try {
|
|
10355
|
-
let usersTableName = '"users"';
|
|
10241
|
+
let usersTableName = '"rebase"."users"';
|
|
10356
10242
|
let userIdType = "TEXT";
|
|
10357
|
-
let usersSchema2 = "
|
|
10358
|
-
if (
|
|
10359
|
-
const
|
|
10360
|
-
|
|
10361
|
-
|
|
10362
|
-
|
|
10363
|
-
|
|
10364
|
-
|
|
10365
|
-
|
|
10366
|
-
|
|
10367
|
-
|
|
10368
|
-
|
|
10369
|
-
const columnType = meta.columnType;
|
|
10370
|
-
if (columnType === "PgUUID") {
|
|
10371
|
-
userIdType = "UUID";
|
|
10372
|
-
} else if (columnType === "PgSerial" || columnType === "PgInteger") {
|
|
10373
|
-
userIdType = "INTEGER";
|
|
10374
|
-
} else if (columnType === "PgBigInt" || columnType === "PgBigSerial") {
|
|
10375
|
-
userIdType = "BIGINT";
|
|
10376
|
-
}
|
|
10243
|
+
let usersSchema2 = "rebase";
|
|
10244
|
+
if (collection) {
|
|
10245
|
+
const rawTable = "table" in collection && typeof collection.table === "string" ? collection.table : collection.slug;
|
|
10246
|
+
usersSchema2 = "schema" in collection && typeof collection.schema === "string" ? collection.schema : "public";
|
|
10247
|
+
usersTableName = usersSchema2 === "public" ? `"${rawTable}"` : `"${usersSchema2}"."${rawTable}"`;
|
|
10248
|
+
const idProp = collection.properties?.id;
|
|
10249
|
+
if (idProp) {
|
|
10250
|
+
const isId = "isId" in idProp ? idProp.isId : void 0;
|
|
10251
|
+
if (isId === "uuid") {
|
|
10252
|
+
userIdType = "UUID";
|
|
10253
|
+
} else if (isId === "autoincrement") {
|
|
10254
|
+
userIdType = "INTEGER";
|
|
10377
10255
|
}
|
|
10378
10256
|
}
|
|
10379
10257
|
}
|
|
@@ -11766,19 +11644,21 @@ ${tableRelations.join(",\n")}
|
|
|
11766
11644
|
const internals = driverResult.internals;
|
|
11767
11645
|
const db = internals.db;
|
|
11768
11646
|
const registry = internals.registry;
|
|
11769
|
-
|
|
11647
|
+
const authCollection = authConfig.collection;
|
|
11648
|
+
await ensureAuthTablesExist(db, authCollection);
|
|
11770
11649
|
let emailService;
|
|
11771
11650
|
if (authConfig.email) {
|
|
11772
11651
|
emailService = serverCore.createEmailService(authConfig.email);
|
|
11773
11652
|
}
|
|
11774
|
-
const
|
|
11653
|
+
const tableName = authCollection ? "table" in authCollection && typeof authCollection.table === "string" ? authCollection.table : authCollection.slug : void 0;
|
|
11654
|
+
const usersTable = tableName ? registry.getTable(tableName) : void 0;
|
|
11775
11655
|
let usersSchemaName = "rebase";
|
|
11776
|
-
if (
|
|
11777
|
-
usersSchemaName =
|
|
11656
|
+
if (authCollection && "schema" in authCollection && typeof authCollection.schema === "string") {
|
|
11657
|
+
usersSchemaName = authCollection.schema;
|
|
11778
11658
|
}
|
|
11779
11659
|
const authTables = createAuthSchema(usersSchemaName);
|
|
11780
|
-
if (
|
|
11781
|
-
authTables.users =
|
|
11660
|
+
if (usersTable) {
|
|
11661
|
+
authTables.users = usersTable;
|
|
11782
11662
|
}
|
|
11783
11663
|
const userService = new UserService(db, authTables);
|
|
11784
11664
|
const authRepository = new PostgresAuthRepository(db, authTables);
|