@rebasepro/server-postgresql 0.1.0 → 0.2.1
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/LICENSE +22 -6
- package/dist/common/src/util/entities.d.ts +2 -2
- package/dist/common/src/util/relations.d.ts +1 -1
- package/dist/index.es.js +1250 -1665
- package/dist/index.es.js.map +1 -1
- package/dist/index.umd.js +1196 -1611
- package/dist/index.umd.js.map +1 -1
- package/dist/server-postgresql/src/PostgresAdapter.d.ts +6 -0
- package/dist/server-postgresql/src/PostgresBackendDriver.d.ts +2 -1
- package/dist/server-postgresql/src/PostgresBootstrapper.d.ts +0 -5
- package/dist/server-postgresql/src/auth/ensure-tables.d.ts +2 -1
- package/dist/server-postgresql/src/auth/services.d.ts +37 -15
- package/dist/server-postgresql/src/index.d.ts +1 -0
- package/dist/server-postgresql/src/schema/auth-schema.d.ts +43 -856
- package/dist/server-postgresql/src/schema/default-collections.d.ts +2 -0
- package/dist/server-postgresql/src/schema/doctor.d.ts +10 -1
- package/dist/server-postgresql/src/schema/introspect-db-logic.d.ts +1 -0
- package/dist/server-postgresql/src/services/entity-helpers.d.ts +1 -1
- package/dist/server-postgresql/src/services/realtimeService.d.ts +12 -0
- package/dist/server-postgresql/src/websocket.d.ts +2 -1
- package/dist/types/src/controllers/auth.d.ts +9 -8
- package/dist/types/src/controllers/client.d.ts +3 -0
- package/dist/types/src/types/auth_adapter.d.ts +356 -0
- package/dist/types/src/types/collections.d.ts +67 -2
- package/dist/types/src/types/database_adapter.d.ts +94 -0
- package/dist/types/src/types/entity_actions.d.ts +7 -1
- package/dist/types/src/types/entity_callbacks.d.ts +1 -1
- package/dist/types/src/types/entity_views.d.ts +36 -1
- package/dist/types/src/types/index.d.ts +2 -0
- package/dist/types/src/types/plugins.d.ts +1 -1
- package/dist/types/src/types/properties.d.ts +24 -5
- package/dist/types/src/types/property_config.d.ts +6 -2
- package/dist/types/src/types/relations.d.ts +1 -1
- package/dist/types/src/types/translations.d.ts +8 -0
- package/dist/types/src/users/user.d.ts +5 -0
- package/package.json +21 -15
- package/src/PostgresAdapter.ts +59 -0
- package/src/PostgresBackendDriver.ts +57 -8
- package/src/PostgresBootstrapper.ts +35 -15
- package/src/auth/ensure-tables.ts +82 -189
- package/src/auth/services.ts +421 -170
- package/src/cli.ts +44 -13
- package/src/data-transformer.ts +78 -8
- package/src/history/HistoryService.ts +25 -2
- package/src/index.ts +1 -0
- package/src/schema/auth-schema.ts +130 -98
- package/src/schema/default-collections.ts +68 -0
- package/src/schema/doctor-cli.ts +5 -1
- package/src/schema/doctor.ts +85 -8
- package/src/schema/generate-drizzle-schema-logic.ts +74 -27
- package/src/schema/generate-drizzle-schema.ts +13 -3
- package/src/schema/introspect-db-inference.ts +5 -5
- package/src/schema/introspect-db-logic.ts +9 -2
- package/src/schema/introspect-db.ts +14 -3
- package/src/services/EntityFetchService.ts +5 -5
- package/src/services/RelationService.ts +2 -2
- package/src/services/entity-helpers.ts +1 -1
- package/src/services/realtimeService.ts +145 -136
- package/src/utils/drizzle-conditions.ts +16 -2
- package/src/websocket.ts +113 -37
- package/test/auth-services.test.ts +163 -74
- package/test/data-transformer-hardening.test.ts +57 -0
- package/test/data-transformer.test.ts +43 -0
- package/test/generate-drizzle-schema.test.ts +7 -5
- package/test/introspect-db-utils.test.ts +4 -1
- package/test/postgresDataDriver.test.ts +17 -0
- package/test/realtimeService.test.ts +7 -7
- package/test/websocket.test.ts +139 -0
- package/examples/sdk-demo/node_modules/esbuild/LICENSE.md +0 -21
- package/examples/sdk-demo/node_modules/esbuild/README.md +0 -3
- package/examples/sdk-demo/node_modules/esbuild/bin/esbuild +0 -223
- package/examples/sdk-demo/node_modules/esbuild/install.js +0 -289
- package/examples/sdk-demo/node_modules/esbuild/lib/main.d.ts +0 -716
- package/examples/sdk-demo/node_modules/esbuild/lib/main.js +0 -2242
- package/examples/sdk-demo/node_modules/esbuild/package.json +0 -49
package/dist/index.es.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Pool, Client } from "pg";
|
|
2
2
|
import { drizzle } from "drizzle-orm/node-postgres";
|
|
3
|
-
import { sql, inArray, eq
|
|
4
|
-
import { pgSchema, timestamp, varchar, boolean, uuid,
|
|
3
|
+
import { sql, inArray, eq, and, or, ilike, asc, desc, gt, lt, getTableName as getTableName$1, count, relations, isTable } from "drizzle-orm";
|
|
4
|
+
import { PgVarchar, PgText, PgChar, pgSchema, pgTable, timestamp, jsonb, varchar, boolean, uuid, primaryKey, unique, getTableConfig } from "drizzle-orm/pg-core";
|
|
5
5
|
import { createHash, randomUUID } from "crypto";
|
|
6
6
|
import * as fs from "fs";
|
|
7
7
|
import { promises } from "fs";
|
|
@@ -51,6 +51,12 @@ function createPostgresDatabaseConnection(connectionString, schema, poolConfig)
|
|
|
51
51
|
connectionString
|
|
52
52
|
};
|
|
53
53
|
}
|
|
54
|
+
class Vector {
|
|
55
|
+
value;
|
|
56
|
+
constructor(value) {
|
|
57
|
+
this.value = value;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
54
60
|
function isPostgresCollection(collection) {
|
|
55
61
|
return !collection.driver || collection.driver === "postgres";
|
|
56
62
|
}
|
|
@@ -127,19 +133,25 @@ const DEFAULT_ONE_OF_VALUE = "value";
|
|
|
127
133
|
const tokenizeRegex = /[A-Z]{2,}(?=[A-Z][a-z]|\b)|[A-Z]?[a-z]+|[0-9]+(?:[a-z](?![a-z]))?|[A-Z]/g;
|
|
128
134
|
const snakeCaseRegex = tokenizeRegex;
|
|
129
135
|
const toSnakeCase = (str) => {
|
|
136
|
+
if (!str || typeof str !== "string") return "";
|
|
130
137
|
const regExpMatchArray = str.match(snakeCaseRegex);
|
|
131
138
|
if (!regExpMatchArray) return "";
|
|
132
139
|
return regExpMatchArray.map((x) => x.toLowerCase()).join("_");
|
|
133
140
|
};
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
141
|
+
function camelCase(str) {
|
|
142
|
+
if (!str) return "";
|
|
143
|
+
if (str.length === 1) return str.toLowerCase();
|
|
144
|
+
const parts = str.split(/[-_ ]+/).filter(Boolean);
|
|
145
|
+
if (parts.length === 0) return "";
|
|
146
|
+
return parts[0].toLowerCase() + // Transform remaining parts to have first letter uppercase
|
|
147
|
+
parts.slice(1).map((part) => part.charAt(0).toUpperCase() + part.substring(1).toLowerCase()).join("");
|
|
137
148
|
}
|
|
149
|
+
var commonjsGlobal = typeof globalThis !== "undefined" ? globalThis : typeof window !== "undefined" ? window : typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : {};
|
|
138
150
|
function commonjsRequire(path2) {
|
|
139
151
|
throw new Error('Could not dynamically require "' + path2 + '". Please configure the dynamicRequireTargets or/and ignoreDynamicRequires option of @rollup/plugin-commonjs appropriately for this require call to work.');
|
|
140
152
|
}
|
|
141
153
|
var object_hash = { exports: {} };
|
|
142
|
-
(function(module, exports
|
|
154
|
+
(function(module, exports) {
|
|
143
155
|
!function(e) {
|
|
144
156
|
module.exports = e();
|
|
145
157
|
}(function() {
|
|
@@ -921,7 +933,23 @@ var object_hash = { exports: {} };
|
|
|
921
933
|
}, { buffer: 3, lYpoI2: 11 }] }, {}, [1])(1);
|
|
922
934
|
});
|
|
923
935
|
})(object_hash);
|
|
924
|
-
function
|
|
936
|
+
function deepClone(value) {
|
|
937
|
+
if (value === null || value === void 0) return value;
|
|
938
|
+
if (typeof value === "function") return value;
|
|
939
|
+
if (typeof value !== "object") return value;
|
|
940
|
+
if (Array.isArray(value)) {
|
|
941
|
+
return value.map((item) => deepClone(item));
|
|
942
|
+
}
|
|
943
|
+
if (Object.getPrototypeOf(value) !== Object.prototype) {
|
|
944
|
+
return value;
|
|
945
|
+
}
|
|
946
|
+
const result = {};
|
|
947
|
+
for (const key of Object.keys(value)) {
|
|
948
|
+
result[key] = deepClone(value[key]);
|
|
949
|
+
}
|
|
950
|
+
return result;
|
|
951
|
+
}
|
|
952
|
+
function isObject(item) {
|
|
925
953
|
return !!item && typeof item === "object" && !Array.isArray(item);
|
|
926
954
|
}
|
|
927
955
|
function isPlainObject(obj) {
|
|
@@ -932,13 +960,13 @@ function isPlainObject(obj) {
|
|
|
932
960
|
return proto === Object.prototype;
|
|
933
961
|
}
|
|
934
962
|
function mergeDeep(target, source, ignoreUndefined = false) {
|
|
935
|
-
if (!isObject
|
|
963
|
+
if (!isObject(target)) {
|
|
936
964
|
return target;
|
|
937
965
|
}
|
|
938
966
|
const output = {
|
|
939
967
|
...target
|
|
940
968
|
};
|
|
941
|
-
if (!isObject
|
|
969
|
+
if (!isObject(source)) {
|
|
942
970
|
return output;
|
|
943
971
|
}
|
|
944
972
|
for (const key in source) {
|
|
@@ -979,7 +1007,7 @@ function mergeDeep(target, source, ignoreUndefined = false) {
|
|
|
979
1007
|
} else {
|
|
980
1008
|
output[key] = sourceValue;
|
|
981
1009
|
}
|
|
982
|
-
} else if (isObject
|
|
1010
|
+
} else if (isObject(sourceValue)) {
|
|
983
1011
|
output[key] = sourceValue;
|
|
984
1012
|
} else {
|
|
985
1013
|
output[key] = sourceValue;
|
|
@@ -1242,14 +1270,56 @@ const buildPropertyCallbacks = (properties) => {
|
|
|
1242
1270
|
}
|
|
1243
1271
|
return Object.keys(propertyCallbacks).length > 0 ? propertyCallbacks : void 0;
|
|
1244
1272
|
};
|
|
1245
|
-
function sanitizeRelation(relation, sourceCollection) {
|
|
1273
|
+
function sanitizeRelation(relation, sourceCollection, resolveCollection) {
|
|
1246
1274
|
if (!relation.target) {
|
|
1247
1275
|
throw new Error("Relation is missing a `target` collection.");
|
|
1248
1276
|
}
|
|
1249
|
-
const
|
|
1277
|
+
const rawTarget = relation.target;
|
|
1278
|
+
let targetCollection;
|
|
1279
|
+
if (typeof rawTarget === "string") {
|
|
1280
|
+
if (resolveCollection) {
|
|
1281
|
+
targetCollection = resolveCollection(rawTarget);
|
|
1282
|
+
}
|
|
1283
|
+
if (!targetCollection) {
|
|
1284
|
+
targetCollection = {
|
|
1285
|
+
slug: rawTarget,
|
|
1286
|
+
name: rawTarget
|
|
1287
|
+
};
|
|
1288
|
+
}
|
|
1289
|
+
} else if (typeof rawTarget === "function") {
|
|
1290
|
+
const evaluated = rawTarget();
|
|
1291
|
+
if (typeof evaluated === "string") {
|
|
1292
|
+
if (resolveCollection) {
|
|
1293
|
+
targetCollection = resolveCollection(evaluated);
|
|
1294
|
+
}
|
|
1295
|
+
if (!targetCollection) {
|
|
1296
|
+
targetCollection = {
|
|
1297
|
+
slug: evaluated,
|
|
1298
|
+
name: evaluated
|
|
1299
|
+
};
|
|
1300
|
+
}
|
|
1301
|
+
} else {
|
|
1302
|
+
targetCollection = evaluated;
|
|
1303
|
+
}
|
|
1304
|
+
}
|
|
1305
|
+
if (!targetCollection) {
|
|
1306
|
+
throw new Error("Relation is missing a valid `target` collection.");
|
|
1307
|
+
}
|
|
1250
1308
|
const newRelation = {
|
|
1251
1309
|
...relation
|
|
1252
1310
|
};
|
|
1311
|
+
newRelation.target = () => {
|
|
1312
|
+
if (typeof rawTarget === "string") {
|
|
1313
|
+
return resolveCollection && resolveCollection(rawTarget) || targetCollection;
|
|
1314
|
+
} else if (typeof rawTarget === "function") {
|
|
1315
|
+
const evaluated = rawTarget();
|
|
1316
|
+
if (typeof evaluated === "string") {
|
|
1317
|
+
return resolveCollection && resolveCollection(evaluated) || targetCollection;
|
|
1318
|
+
}
|
|
1319
|
+
return evaluated;
|
|
1320
|
+
}
|
|
1321
|
+
return targetCollection;
|
|
1322
|
+
};
|
|
1253
1323
|
if (!newRelation.relationName) {
|
|
1254
1324
|
newRelation.relationName = toSnakeCase(targetCollection.slug);
|
|
1255
1325
|
}
|
|
@@ -1302,6 +1372,17 @@ function sanitizeRelation(relation, sourceCollection) {
|
|
|
1302
1372
|
break;
|
|
1303
1373
|
}
|
|
1304
1374
|
}
|
|
1375
|
+
if (!isManyToManyInverse && targetCollection.properties) {
|
|
1376
|
+
for (const [propKey, prop] of Object.entries(targetCollection.properties)) {
|
|
1377
|
+
if (prop.type !== "relation") continue;
|
|
1378
|
+
const relProp = prop;
|
|
1379
|
+
const relName = relProp.relationName || propKey;
|
|
1380
|
+
if (relName === newRelation.inverseRelationName && relProp.cardinality === "many" && (relProp.direction === "owning" || !relProp.direction)) {
|
|
1381
|
+
isManyToManyInverse = true;
|
|
1382
|
+
break;
|
|
1383
|
+
}
|
|
1384
|
+
}
|
|
1385
|
+
}
|
|
1305
1386
|
} catch (e) {
|
|
1306
1387
|
}
|
|
1307
1388
|
}
|
|
@@ -1424,8 +1505,8 @@ function findRelation(resolvedRelations, key) {
|
|
|
1424
1505
|
return void 0;
|
|
1425
1506
|
}
|
|
1426
1507
|
var logic = { exports: {} };
|
|
1427
|
-
(function(module, exports
|
|
1428
|
-
(function(
|
|
1508
|
+
(function(module, exports) {
|
|
1509
|
+
(function(root, factory) {
|
|
1429
1510
|
{
|
|
1430
1511
|
module.exports = factory();
|
|
1431
1512
|
}
|
|
@@ -1793,7 +1874,7 @@ var logic = { exports: {} };
|
|
|
1793
1874
|
});
|
|
1794
1875
|
})(logic);
|
|
1795
1876
|
const { getOwnPropertyNames, getOwnPropertySymbols } = Object;
|
|
1796
|
-
const { hasOwnProperty
|
|
1877
|
+
const { hasOwnProperty } = Object.prototype;
|
|
1797
1878
|
function combineComparators(comparatorA, comparatorB) {
|
|
1798
1879
|
return function isEqual(a, b, state) {
|
|
1799
1880
|
return comparatorA(a, b, state) && comparatorB(a, b, state);
|
|
@@ -1823,12 +1904,12 @@ function getStrictProperties(object) {
|
|
|
1823
1904
|
}
|
|
1824
1905
|
const hasOwn = (
|
|
1825
1906
|
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
1826
|
-
Object.hasOwn || ((object, property) => hasOwnProperty
|
|
1907
|
+
Object.hasOwn || ((object, property) => hasOwnProperty.call(object, property))
|
|
1827
1908
|
);
|
|
1828
1909
|
const PREACT_VNODE = "__v";
|
|
1829
1910
|
const PREACT_OWNER = "__o";
|
|
1830
1911
|
const REACT_OWNER = "_owner";
|
|
1831
|
-
const { getOwnPropertyDescriptor, keys
|
|
1912
|
+
const { getOwnPropertyDescriptor, keys } = Object;
|
|
1832
1913
|
const sameValueEqual = (
|
|
1833
1914
|
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
1834
1915
|
Object.is || function sameValueEqual2(a, b) {
|
|
@@ -1906,9 +1987,9 @@ function areMapsEqual(a, b, state) {
|
|
|
1906
1987
|
return true;
|
|
1907
1988
|
}
|
|
1908
1989
|
function areObjectsEqual(a, b, state) {
|
|
1909
|
-
const properties = keys
|
|
1990
|
+
const properties = keys(a);
|
|
1910
1991
|
let index = properties.length;
|
|
1911
|
-
if (keys
|
|
1992
|
+
if (keys(b).length !== index) {
|
|
1912
1993
|
return false;
|
|
1913
1994
|
}
|
|
1914
1995
|
while (index-- > 0) {
|
|
@@ -2181,7 +2262,7 @@ function createSupportedComparatorMap({ areArrayBuffersEqual: areArrayBuffersEqu
|
|
|
2181
2262
|
"[object Uint32Array]": areTypedArraysEqual2
|
|
2182
2263
|
};
|
|
2183
2264
|
}
|
|
2184
|
-
const deepEqual = createCustomEqual();
|
|
2265
|
+
const deepEqual$1 = createCustomEqual();
|
|
2185
2266
|
createCustomEqual({ strict: true });
|
|
2186
2267
|
createCustomEqual({ circular: true });
|
|
2187
2268
|
createCustomEqual({
|
|
@@ -2211,982 +2292,6 @@ function createCustomEqual(options = {}) {
|
|
|
2211
2292
|
const equals = createCustomInternalComparator ? createCustomInternalComparator(comparator) : createInternalEqualityComparator(comparator);
|
|
2212
2293
|
return createIsEqual({ circular, comparator, createState, equals, strict });
|
|
2213
2294
|
}
|
|
2214
|
-
function listCacheClear$1() {
|
|
2215
|
-
this.__data__ = [];
|
|
2216
|
-
this.size = 0;
|
|
2217
|
-
}
|
|
2218
|
-
var _listCacheClear = listCacheClear$1;
|
|
2219
|
-
function eq$2(value, other) {
|
|
2220
|
-
return value === other || value !== value && other !== other;
|
|
2221
|
-
}
|
|
2222
|
-
var eq_1 = eq$2;
|
|
2223
|
-
var eq$1 = eq_1;
|
|
2224
|
-
function assocIndexOf$4(array, key) {
|
|
2225
|
-
var length = array.length;
|
|
2226
|
-
while (length--) {
|
|
2227
|
-
if (eq$1(array[length][0], key)) {
|
|
2228
|
-
return length;
|
|
2229
|
-
}
|
|
2230
|
-
}
|
|
2231
|
-
return -1;
|
|
2232
|
-
}
|
|
2233
|
-
var _assocIndexOf = assocIndexOf$4;
|
|
2234
|
-
var assocIndexOf$3 = _assocIndexOf;
|
|
2235
|
-
var arrayProto = Array.prototype;
|
|
2236
|
-
var splice = arrayProto.splice;
|
|
2237
|
-
function listCacheDelete$1(key) {
|
|
2238
|
-
var data = this.__data__, index = assocIndexOf$3(data, key);
|
|
2239
|
-
if (index < 0) {
|
|
2240
|
-
return false;
|
|
2241
|
-
}
|
|
2242
|
-
var lastIndex = data.length - 1;
|
|
2243
|
-
if (index == lastIndex) {
|
|
2244
|
-
data.pop();
|
|
2245
|
-
} else {
|
|
2246
|
-
splice.call(data, index, 1);
|
|
2247
|
-
}
|
|
2248
|
-
--this.size;
|
|
2249
|
-
return true;
|
|
2250
|
-
}
|
|
2251
|
-
var _listCacheDelete = listCacheDelete$1;
|
|
2252
|
-
var assocIndexOf$2 = _assocIndexOf;
|
|
2253
|
-
function listCacheGet$1(key) {
|
|
2254
|
-
var data = this.__data__, index = assocIndexOf$2(data, key);
|
|
2255
|
-
return index < 0 ? void 0 : data[index][1];
|
|
2256
|
-
}
|
|
2257
|
-
var _listCacheGet = listCacheGet$1;
|
|
2258
|
-
var assocIndexOf$1 = _assocIndexOf;
|
|
2259
|
-
function listCacheHas$1(key) {
|
|
2260
|
-
return assocIndexOf$1(this.__data__, key) > -1;
|
|
2261
|
-
}
|
|
2262
|
-
var _listCacheHas = listCacheHas$1;
|
|
2263
|
-
var assocIndexOf = _assocIndexOf;
|
|
2264
|
-
function listCacheSet$1(key, value) {
|
|
2265
|
-
var data = this.__data__, index = assocIndexOf(data, key);
|
|
2266
|
-
if (index < 0) {
|
|
2267
|
-
++this.size;
|
|
2268
|
-
data.push([key, value]);
|
|
2269
|
-
} else {
|
|
2270
|
-
data[index][1] = value;
|
|
2271
|
-
}
|
|
2272
|
-
return this;
|
|
2273
|
-
}
|
|
2274
|
-
var _listCacheSet = listCacheSet$1;
|
|
2275
|
-
var listCacheClear = _listCacheClear, listCacheDelete = _listCacheDelete, listCacheGet = _listCacheGet, listCacheHas = _listCacheHas, listCacheSet = _listCacheSet;
|
|
2276
|
-
function ListCache$4(entries) {
|
|
2277
|
-
var index = -1, length = entries == null ? 0 : entries.length;
|
|
2278
|
-
this.clear();
|
|
2279
|
-
while (++index < length) {
|
|
2280
|
-
var entry = entries[index];
|
|
2281
|
-
this.set(entry[0], entry[1]);
|
|
2282
|
-
}
|
|
2283
|
-
}
|
|
2284
|
-
ListCache$4.prototype.clear = listCacheClear;
|
|
2285
|
-
ListCache$4.prototype["delete"] = listCacheDelete;
|
|
2286
|
-
ListCache$4.prototype.get = listCacheGet;
|
|
2287
|
-
ListCache$4.prototype.has = listCacheHas;
|
|
2288
|
-
ListCache$4.prototype.set = listCacheSet;
|
|
2289
|
-
var _ListCache = ListCache$4;
|
|
2290
|
-
var ListCache$3 = _ListCache;
|
|
2291
|
-
function stackClear$1() {
|
|
2292
|
-
this.__data__ = new ListCache$3();
|
|
2293
|
-
this.size = 0;
|
|
2294
|
-
}
|
|
2295
|
-
var _stackClear = stackClear$1;
|
|
2296
|
-
function stackDelete$1(key) {
|
|
2297
|
-
var data = this.__data__, result = data["delete"](key);
|
|
2298
|
-
this.size = data.size;
|
|
2299
|
-
return result;
|
|
2300
|
-
}
|
|
2301
|
-
var _stackDelete = stackDelete$1;
|
|
2302
|
-
function stackGet$1(key) {
|
|
2303
|
-
return this.__data__.get(key);
|
|
2304
|
-
}
|
|
2305
|
-
var _stackGet = stackGet$1;
|
|
2306
|
-
function stackHas$1(key) {
|
|
2307
|
-
return this.__data__.has(key);
|
|
2308
|
-
}
|
|
2309
|
-
var _stackHas = stackHas$1;
|
|
2310
|
-
var freeGlobal$1 = typeof commonjsGlobal == "object" && commonjsGlobal && commonjsGlobal.Object === Object && commonjsGlobal;
|
|
2311
|
-
var _freeGlobal = freeGlobal$1;
|
|
2312
|
-
var freeGlobal = _freeGlobal;
|
|
2313
|
-
var freeSelf = typeof self == "object" && self && self.Object === Object && self;
|
|
2314
|
-
var root$8 = freeGlobal || freeSelf || Function("return this")();
|
|
2315
|
-
var _root = root$8;
|
|
2316
|
-
var root$7 = _root;
|
|
2317
|
-
var Symbol$4 = root$7.Symbol;
|
|
2318
|
-
var _Symbol = Symbol$4;
|
|
2319
|
-
var Symbol$3 = _Symbol;
|
|
2320
|
-
var objectProto$c = Object.prototype;
|
|
2321
|
-
var hasOwnProperty$9 = objectProto$c.hasOwnProperty;
|
|
2322
|
-
var nativeObjectToString$1 = objectProto$c.toString;
|
|
2323
|
-
var symToStringTag$1 = Symbol$3 ? Symbol$3.toStringTag : void 0;
|
|
2324
|
-
function getRawTag$1(value) {
|
|
2325
|
-
var isOwn = hasOwnProperty$9.call(value, symToStringTag$1), tag = value[symToStringTag$1];
|
|
2326
|
-
try {
|
|
2327
|
-
value[symToStringTag$1] = void 0;
|
|
2328
|
-
var unmasked = true;
|
|
2329
|
-
} catch (e) {
|
|
2330
|
-
}
|
|
2331
|
-
var result = nativeObjectToString$1.call(value);
|
|
2332
|
-
if (unmasked) {
|
|
2333
|
-
if (isOwn) {
|
|
2334
|
-
value[symToStringTag$1] = tag;
|
|
2335
|
-
} else {
|
|
2336
|
-
delete value[symToStringTag$1];
|
|
2337
|
-
}
|
|
2338
|
-
}
|
|
2339
|
-
return result;
|
|
2340
|
-
}
|
|
2341
|
-
var _getRawTag = getRawTag$1;
|
|
2342
|
-
var objectProto$b = Object.prototype;
|
|
2343
|
-
var nativeObjectToString = objectProto$b.toString;
|
|
2344
|
-
function objectToString$1(value) {
|
|
2345
|
-
return nativeObjectToString.call(value);
|
|
2346
|
-
}
|
|
2347
|
-
var _objectToString = objectToString$1;
|
|
2348
|
-
var Symbol$2 = _Symbol, getRawTag = _getRawTag, objectToString = _objectToString;
|
|
2349
|
-
var nullTag = "[object Null]", undefinedTag = "[object Undefined]";
|
|
2350
|
-
var symToStringTag = Symbol$2 ? Symbol$2.toStringTag : void 0;
|
|
2351
|
-
function baseGetTag$4(value) {
|
|
2352
|
-
if (value == null) {
|
|
2353
|
-
return value === void 0 ? undefinedTag : nullTag;
|
|
2354
|
-
}
|
|
2355
|
-
return symToStringTag && symToStringTag in Object(value) ? getRawTag(value) : objectToString(value);
|
|
2356
|
-
}
|
|
2357
|
-
var _baseGetTag = baseGetTag$4;
|
|
2358
|
-
function isObject$5(value) {
|
|
2359
|
-
var type = typeof value;
|
|
2360
|
-
return value != null && (type == "object" || type == "function");
|
|
2361
|
-
}
|
|
2362
|
-
var isObject_1 = isObject$5;
|
|
2363
|
-
var baseGetTag$3 = _baseGetTag, isObject$4 = isObject_1;
|
|
2364
|
-
var asyncTag = "[object AsyncFunction]", funcTag$2 = "[object Function]", genTag$1 = "[object GeneratorFunction]", proxyTag = "[object Proxy]";
|
|
2365
|
-
function isFunction$2(value) {
|
|
2366
|
-
if (!isObject$4(value)) {
|
|
2367
|
-
return false;
|
|
2368
|
-
}
|
|
2369
|
-
var tag = baseGetTag$3(value);
|
|
2370
|
-
return tag == funcTag$2 || tag == genTag$1 || tag == asyncTag || tag == proxyTag;
|
|
2371
|
-
}
|
|
2372
|
-
var isFunction_1 = isFunction$2;
|
|
2373
|
-
var root$6 = _root;
|
|
2374
|
-
var coreJsData$1 = root$6["__core-js_shared__"];
|
|
2375
|
-
var _coreJsData = coreJsData$1;
|
|
2376
|
-
var coreJsData = _coreJsData;
|
|
2377
|
-
var maskSrcKey = function() {
|
|
2378
|
-
var uid = /[^.]+$/.exec(coreJsData && coreJsData.keys && coreJsData.keys.IE_PROTO || "");
|
|
2379
|
-
return uid ? "Symbol(src)_1." + uid : "";
|
|
2380
|
-
}();
|
|
2381
|
-
function isMasked$1(func) {
|
|
2382
|
-
return !!maskSrcKey && maskSrcKey in func;
|
|
2383
|
-
}
|
|
2384
|
-
var _isMasked = isMasked$1;
|
|
2385
|
-
var funcProto$1 = Function.prototype;
|
|
2386
|
-
var funcToString$1 = funcProto$1.toString;
|
|
2387
|
-
function toSource$2(func) {
|
|
2388
|
-
if (func != null) {
|
|
2389
|
-
try {
|
|
2390
|
-
return funcToString$1.call(func);
|
|
2391
|
-
} catch (e) {
|
|
2392
|
-
}
|
|
2393
|
-
try {
|
|
2394
|
-
return func + "";
|
|
2395
|
-
} catch (e) {
|
|
2396
|
-
}
|
|
2397
|
-
}
|
|
2398
|
-
return "";
|
|
2399
|
-
}
|
|
2400
|
-
var _toSource = toSource$2;
|
|
2401
|
-
var isFunction$1 = isFunction_1, isMasked = _isMasked, isObject$3 = isObject_1, toSource$1 = _toSource;
|
|
2402
|
-
var reRegExpChar = /[\\^$.*+?()[\]{}|]/g;
|
|
2403
|
-
var reIsHostCtor = /^\[object .+?Constructor\]$/;
|
|
2404
|
-
var funcProto = Function.prototype, objectProto$a = Object.prototype;
|
|
2405
|
-
var funcToString = funcProto.toString;
|
|
2406
|
-
var hasOwnProperty$8 = objectProto$a.hasOwnProperty;
|
|
2407
|
-
var reIsNative = RegExp(
|
|
2408
|
-
"^" + funcToString.call(hasOwnProperty$8).replace(reRegExpChar, "\\$&").replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g, "$1.*?") + "$"
|
|
2409
|
-
);
|
|
2410
|
-
function baseIsNative$1(value) {
|
|
2411
|
-
if (!isObject$3(value) || isMasked(value)) {
|
|
2412
|
-
return false;
|
|
2413
|
-
}
|
|
2414
|
-
var pattern = isFunction$1(value) ? reIsNative : reIsHostCtor;
|
|
2415
|
-
return pattern.test(toSource$1(value));
|
|
2416
|
-
}
|
|
2417
|
-
var _baseIsNative = baseIsNative$1;
|
|
2418
|
-
function getValue$1(object, key) {
|
|
2419
|
-
return object == null ? void 0 : object[key];
|
|
2420
|
-
}
|
|
2421
|
-
var _getValue = getValue$1;
|
|
2422
|
-
var baseIsNative = _baseIsNative, getValue = _getValue;
|
|
2423
|
-
function getNative$7(object, key) {
|
|
2424
|
-
var value = getValue(object, key);
|
|
2425
|
-
return baseIsNative(value) ? value : void 0;
|
|
2426
|
-
}
|
|
2427
|
-
var _getNative = getNative$7;
|
|
2428
|
-
var getNative$6 = _getNative, root$5 = _root;
|
|
2429
|
-
var Map$4 = getNative$6(root$5, "Map");
|
|
2430
|
-
var _Map = Map$4;
|
|
2431
|
-
var getNative$5 = _getNative;
|
|
2432
|
-
var nativeCreate$4 = getNative$5(Object, "create");
|
|
2433
|
-
var _nativeCreate = nativeCreate$4;
|
|
2434
|
-
var nativeCreate$3 = _nativeCreate;
|
|
2435
|
-
function hashClear$1() {
|
|
2436
|
-
this.__data__ = nativeCreate$3 ? nativeCreate$3(null) : {};
|
|
2437
|
-
this.size = 0;
|
|
2438
|
-
}
|
|
2439
|
-
var _hashClear = hashClear$1;
|
|
2440
|
-
function hashDelete$1(key) {
|
|
2441
|
-
var result = this.has(key) && delete this.__data__[key];
|
|
2442
|
-
this.size -= result ? 1 : 0;
|
|
2443
|
-
return result;
|
|
2444
|
-
}
|
|
2445
|
-
var _hashDelete = hashDelete$1;
|
|
2446
|
-
var nativeCreate$2 = _nativeCreate;
|
|
2447
|
-
var HASH_UNDEFINED$1 = "__lodash_hash_undefined__";
|
|
2448
|
-
var objectProto$9 = Object.prototype;
|
|
2449
|
-
var hasOwnProperty$7 = objectProto$9.hasOwnProperty;
|
|
2450
|
-
function hashGet$1(key) {
|
|
2451
|
-
var data = this.__data__;
|
|
2452
|
-
if (nativeCreate$2) {
|
|
2453
|
-
var result = data[key];
|
|
2454
|
-
return result === HASH_UNDEFINED$1 ? void 0 : result;
|
|
2455
|
-
}
|
|
2456
|
-
return hasOwnProperty$7.call(data, key) ? data[key] : void 0;
|
|
2457
|
-
}
|
|
2458
|
-
var _hashGet = hashGet$1;
|
|
2459
|
-
var nativeCreate$1 = _nativeCreate;
|
|
2460
|
-
var objectProto$8 = Object.prototype;
|
|
2461
|
-
var hasOwnProperty$6 = objectProto$8.hasOwnProperty;
|
|
2462
|
-
function hashHas$1(key) {
|
|
2463
|
-
var data = this.__data__;
|
|
2464
|
-
return nativeCreate$1 ? data[key] !== void 0 : hasOwnProperty$6.call(data, key);
|
|
2465
|
-
}
|
|
2466
|
-
var _hashHas = hashHas$1;
|
|
2467
|
-
var nativeCreate = _nativeCreate;
|
|
2468
|
-
var HASH_UNDEFINED = "__lodash_hash_undefined__";
|
|
2469
|
-
function hashSet$1(key, value) {
|
|
2470
|
-
var data = this.__data__;
|
|
2471
|
-
this.size += this.has(key) ? 0 : 1;
|
|
2472
|
-
data[key] = nativeCreate && value === void 0 ? HASH_UNDEFINED : value;
|
|
2473
|
-
return this;
|
|
2474
|
-
}
|
|
2475
|
-
var _hashSet = hashSet$1;
|
|
2476
|
-
var hashClear = _hashClear, hashDelete = _hashDelete, hashGet = _hashGet, hashHas = _hashHas, hashSet = _hashSet;
|
|
2477
|
-
function Hash$1(entries) {
|
|
2478
|
-
var index = -1, length = entries == null ? 0 : entries.length;
|
|
2479
|
-
this.clear();
|
|
2480
|
-
while (++index < length) {
|
|
2481
|
-
var entry = entries[index];
|
|
2482
|
-
this.set(entry[0], entry[1]);
|
|
2483
|
-
}
|
|
2484
|
-
}
|
|
2485
|
-
Hash$1.prototype.clear = hashClear;
|
|
2486
|
-
Hash$1.prototype["delete"] = hashDelete;
|
|
2487
|
-
Hash$1.prototype.get = hashGet;
|
|
2488
|
-
Hash$1.prototype.has = hashHas;
|
|
2489
|
-
Hash$1.prototype.set = hashSet;
|
|
2490
|
-
var _Hash = Hash$1;
|
|
2491
|
-
var Hash = _Hash, ListCache$2 = _ListCache, Map$3 = _Map;
|
|
2492
|
-
function mapCacheClear$1() {
|
|
2493
|
-
this.size = 0;
|
|
2494
|
-
this.__data__ = {
|
|
2495
|
-
"hash": new Hash(),
|
|
2496
|
-
"map": new (Map$3 || ListCache$2)(),
|
|
2497
|
-
"string": new Hash()
|
|
2498
|
-
};
|
|
2499
|
-
}
|
|
2500
|
-
var _mapCacheClear = mapCacheClear$1;
|
|
2501
|
-
function isKeyable$1(value) {
|
|
2502
|
-
var type = typeof value;
|
|
2503
|
-
return type == "string" || type == "number" || type == "symbol" || type == "boolean" ? value !== "__proto__" : value === null;
|
|
2504
|
-
}
|
|
2505
|
-
var _isKeyable = isKeyable$1;
|
|
2506
|
-
var isKeyable = _isKeyable;
|
|
2507
|
-
function getMapData$4(map, key) {
|
|
2508
|
-
var data = map.__data__;
|
|
2509
|
-
return isKeyable(key) ? data[typeof key == "string" ? "string" : "hash"] : data.map;
|
|
2510
|
-
}
|
|
2511
|
-
var _getMapData = getMapData$4;
|
|
2512
|
-
var getMapData$3 = _getMapData;
|
|
2513
|
-
function mapCacheDelete$1(key) {
|
|
2514
|
-
var result = getMapData$3(this, key)["delete"](key);
|
|
2515
|
-
this.size -= result ? 1 : 0;
|
|
2516
|
-
return result;
|
|
2517
|
-
}
|
|
2518
|
-
var _mapCacheDelete = mapCacheDelete$1;
|
|
2519
|
-
var getMapData$2 = _getMapData;
|
|
2520
|
-
function mapCacheGet$1(key) {
|
|
2521
|
-
return getMapData$2(this, key).get(key);
|
|
2522
|
-
}
|
|
2523
|
-
var _mapCacheGet = mapCacheGet$1;
|
|
2524
|
-
var getMapData$1 = _getMapData;
|
|
2525
|
-
function mapCacheHas$1(key) {
|
|
2526
|
-
return getMapData$1(this, key).has(key);
|
|
2527
|
-
}
|
|
2528
|
-
var _mapCacheHas = mapCacheHas$1;
|
|
2529
|
-
var getMapData = _getMapData;
|
|
2530
|
-
function mapCacheSet$1(key, value) {
|
|
2531
|
-
var data = getMapData(this, key), size = data.size;
|
|
2532
|
-
data.set(key, value);
|
|
2533
|
-
this.size += data.size == size ? 0 : 1;
|
|
2534
|
-
return this;
|
|
2535
|
-
}
|
|
2536
|
-
var _mapCacheSet = mapCacheSet$1;
|
|
2537
|
-
var mapCacheClear = _mapCacheClear, mapCacheDelete = _mapCacheDelete, mapCacheGet = _mapCacheGet, mapCacheHas = _mapCacheHas, mapCacheSet = _mapCacheSet;
|
|
2538
|
-
function MapCache$1(entries) {
|
|
2539
|
-
var index = -1, length = entries == null ? 0 : entries.length;
|
|
2540
|
-
this.clear();
|
|
2541
|
-
while (++index < length) {
|
|
2542
|
-
var entry = entries[index];
|
|
2543
|
-
this.set(entry[0], entry[1]);
|
|
2544
|
-
}
|
|
2545
|
-
}
|
|
2546
|
-
MapCache$1.prototype.clear = mapCacheClear;
|
|
2547
|
-
MapCache$1.prototype["delete"] = mapCacheDelete;
|
|
2548
|
-
MapCache$1.prototype.get = mapCacheGet;
|
|
2549
|
-
MapCache$1.prototype.has = mapCacheHas;
|
|
2550
|
-
MapCache$1.prototype.set = mapCacheSet;
|
|
2551
|
-
var _MapCache = MapCache$1;
|
|
2552
|
-
var ListCache$1 = _ListCache, Map$2 = _Map, MapCache = _MapCache;
|
|
2553
|
-
var LARGE_ARRAY_SIZE = 200;
|
|
2554
|
-
function stackSet$1(key, value) {
|
|
2555
|
-
var data = this.__data__;
|
|
2556
|
-
if (data instanceof ListCache$1) {
|
|
2557
|
-
var pairs = data.__data__;
|
|
2558
|
-
if (!Map$2 || pairs.length < LARGE_ARRAY_SIZE - 1) {
|
|
2559
|
-
pairs.push([key, value]);
|
|
2560
|
-
this.size = ++data.size;
|
|
2561
|
-
return this;
|
|
2562
|
-
}
|
|
2563
|
-
data = this.__data__ = new MapCache(pairs);
|
|
2564
|
-
}
|
|
2565
|
-
data.set(key, value);
|
|
2566
|
-
this.size = data.size;
|
|
2567
|
-
return this;
|
|
2568
|
-
}
|
|
2569
|
-
var _stackSet = stackSet$1;
|
|
2570
|
-
var ListCache = _ListCache, stackClear = _stackClear, stackDelete = _stackDelete, stackGet = _stackGet, stackHas = _stackHas, stackSet = _stackSet;
|
|
2571
|
-
function Stack$1(entries) {
|
|
2572
|
-
var data = this.__data__ = new ListCache(entries);
|
|
2573
|
-
this.size = data.size;
|
|
2574
|
-
}
|
|
2575
|
-
Stack$1.prototype.clear = stackClear;
|
|
2576
|
-
Stack$1.prototype["delete"] = stackDelete;
|
|
2577
|
-
Stack$1.prototype.get = stackGet;
|
|
2578
|
-
Stack$1.prototype.has = stackHas;
|
|
2579
|
-
Stack$1.prototype.set = stackSet;
|
|
2580
|
-
var _Stack = Stack$1;
|
|
2581
|
-
function arrayEach$1(array, iteratee) {
|
|
2582
|
-
var index = -1, length = array == null ? 0 : array.length;
|
|
2583
|
-
while (++index < length) {
|
|
2584
|
-
if (iteratee(array[index], index, array) === false) {
|
|
2585
|
-
break;
|
|
2586
|
-
}
|
|
2587
|
-
}
|
|
2588
|
-
return array;
|
|
2589
|
-
}
|
|
2590
|
-
var _arrayEach = arrayEach$1;
|
|
2591
|
-
var getNative$4 = _getNative;
|
|
2592
|
-
var defineProperty$1 = function() {
|
|
2593
|
-
try {
|
|
2594
|
-
var func = getNative$4(Object, "defineProperty");
|
|
2595
|
-
func({}, "", {});
|
|
2596
|
-
return func;
|
|
2597
|
-
} catch (e) {
|
|
2598
|
-
}
|
|
2599
|
-
}();
|
|
2600
|
-
var _defineProperty = defineProperty$1;
|
|
2601
|
-
var defineProperty = _defineProperty;
|
|
2602
|
-
function baseAssignValue$2(object, key, value) {
|
|
2603
|
-
if (key == "__proto__" && defineProperty) {
|
|
2604
|
-
defineProperty(object, key, {
|
|
2605
|
-
"configurable": true,
|
|
2606
|
-
"enumerable": true,
|
|
2607
|
-
"value": value,
|
|
2608
|
-
"writable": true
|
|
2609
|
-
});
|
|
2610
|
-
} else {
|
|
2611
|
-
object[key] = value;
|
|
2612
|
-
}
|
|
2613
|
-
}
|
|
2614
|
-
var _baseAssignValue = baseAssignValue$2;
|
|
2615
|
-
var baseAssignValue$1 = _baseAssignValue, eq = eq_1;
|
|
2616
|
-
var objectProto$7 = Object.prototype;
|
|
2617
|
-
var hasOwnProperty$5 = objectProto$7.hasOwnProperty;
|
|
2618
|
-
function assignValue$2(object, key, value) {
|
|
2619
|
-
var objValue = object[key];
|
|
2620
|
-
if (!(hasOwnProperty$5.call(object, key) && eq(objValue, value)) || value === void 0 && !(key in object)) {
|
|
2621
|
-
baseAssignValue$1(object, key, value);
|
|
2622
|
-
}
|
|
2623
|
-
}
|
|
2624
|
-
var _assignValue = assignValue$2;
|
|
2625
|
-
var assignValue$1 = _assignValue, baseAssignValue = _baseAssignValue;
|
|
2626
|
-
function copyObject$4(source, props, object, customizer) {
|
|
2627
|
-
var isNew = !object;
|
|
2628
|
-
object || (object = {});
|
|
2629
|
-
var index = -1, length = props.length;
|
|
2630
|
-
while (++index < length) {
|
|
2631
|
-
var key = props[index];
|
|
2632
|
-
var newValue = customizer ? customizer(object[key], source[key], key, object, source) : void 0;
|
|
2633
|
-
if (newValue === void 0) {
|
|
2634
|
-
newValue = source[key];
|
|
2635
|
-
}
|
|
2636
|
-
if (isNew) {
|
|
2637
|
-
baseAssignValue(object, key, newValue);
|
|
2638
|
-
} else {
|
|
2639
|
-
assignValue$1(object, key, newValue);
|
|
2640
|
-
}
|
|
2641
|
-
}
|
|
2642
|
-
return object;
|
|
2643
|
-
}
|
|
2644
|
-
var _copyObject = copyObject$4;
|
|
2645
|
-
function baseTimes$1(n, iteratee) {
|
|
2646
|
-
var index = -1, result = Array(n);
|
|
2647
|
-
while (++index < n) {
|
|
2648
|
-
result[index] = iteratee(index);
|
|
2649
|
-
}
|
|
2650
|
-
return result;
|
|
2651
|
-
}
|
|
2652
|
-
var _baseTimes = baseTimes$1;
|
|
2653
|
-
function isObjectLike$5(value) {
|
|
2654
|
-
return value != null && typeof value == "object";
|
|
2655
|
-
}
|
|
2656
|
-
var isObjectLike_1 = isObjectLike$5;
|
|
2657
|
-
var baseGetTag$2 = _baseGetTag, isObjectLike$4 = isObjectLike_1;
|
|
2658
|
-
var argsTag$2 = "[object Arguments]";
|
|
2659
|
-
function baseIsArguments$1(value) {
|
|
2660
|
-
return isObjectLike$4(value) && baseGetTag$2(value) == argsTag$2;
|
|
2661
|
-
}
|
|
2662
|
-
var _baseIsArguments = baseIsArguments$1;
|
|
2663
|
-
var baseIsArguments = _baseIsArguments, isObjectLike$3 = isObjectLike_1;
|
|
2664
|
-
var objectProto$6 = Object.prototype;
|
|
2665
|
-
var hasOwnProperty$4 = objectProto$6.hasOwnProperty;
|
|
2666
|
-
var propertyIsEnumerable$1 = objectProto$6.propertyIsEnumerable;
|
|
2667
|
-
var isArguments$1 = baseIsArguments(/* @__PURE__ */ function() {
|
|
2668
|
-
return arguments;
|
|
2669
|
-
}()) ? baseIsArguments : function(value) {
|
|
2670
|
-
return isObjectLike$3(value) && hasOwnProperty$4.call(value, "callee") && !propertyIsEnumerable$1.call(value, "callee");
|
|
2671
|
-
};
|
|
2672
|
-
var isArguments_1 = isArguments$1;
|
|
2673
|
-
var isArray$3 = Array.isArray;
|
|
2674
|
-
var isArray_1 = isArray$3;
|
|
2675
|
-
var isBuffer$2 = { exports: {} };
|
|
2676
|
-
function stubFalse() {
|
|
2677
|
-
return false;
|
|
2678
|
-
}
|
|
2679
|
-
var stubFalse_1 = stubFalse;
|
|
2680
|
-
isBuffer$2.exports;
|
|
2681
|
-
(function(module, exports$1) {
|
|
2682
|
-
var root2 = _root, stubFalse2 = stubFalse_1;
|
|
2683
|
-
var freeExports = exports$1 && !exports$1.nodeType && exports$1;
|
|
2684
|
-
var freeModule = freeExports && true && module && !module.nodeType && module;
|
|
2685
|
-
var moduleExports = freeModule && freeModule.exports === freeExports;
|
|
2686
|
-
var Buffer2 = moduleExports ? root2.Buffer : void 0;
|
|
2687
|
-
var nativeIsBuffer = Buffer2 ? Buffer2.isBuffer : void 0;
|
|
2688
|
-
var isBuffer2 = nativeIsBuffer || stubFalse2;
|
|
2689
|
-
module.exports = isBuffer2;
|
|
2690
|
-
})(isBuffer$2, isBuffer$2.exports);
|
|
2691
|
-
var isBufferExports = isBuffer$2.exports;
|
|
2692
|
-
var MAX_SAFE_INTEGER$1 = 9007199254740991;
|
|
2693
|
-
var reIsUint = /^(?:0|[1-9]\d*)$/;
|
|
2694
|
-
function isIndex$1(value, length) {
|
|
2695
|
-
var type = typeof value;
|
|
2696
|
-
length = length == null ? MAX_SAFE_INTEGER$1 : length;
|
|
2697
|
-
return !!length && (type == "number" || type != "symbol" && reIsUint.test(value)) && (value > -1 && value % 1 == 0 && value < length);
|
|
2698
|
-
}
|
|
2699
|
-
var _isIndex = isIndex$1;
|
|
2700
|
-
var MAX_SAFE_INTEGER = 9007199254740991;
|
|
2701
|
-
function isLength$2(value) {
|
|
2702
|
-
return typeof value == "number" && value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER;
|
|
2703
|
-
}
|
|
2704
|
-
var isLength_1 = isLength$2;
|
|
2705
|
-
var baseGetTag$1 = _baseGetTag, isLength$1 = isLength_1, isObjectLike$2 = isObjectLike_1;
|
|
2706
|
-
var argsTag$1 = "[object Arguments]", arrayTag$1 = "[object Array]", boolTag$2 = "[object Boolean]", dateTag$2 = "[object Date]", errorTag$1 = "[object Error]", funcTag$1 = "[object Function]", mapTag$4 = "[object Map]", numberTag$2 = "[object Number]", objectTag$2 = "[object Object]", regexpTag$2 = "[object RegExp]", setTag$4 = "[object Set]", stringTag$2 = "[object String]", weakMapTag$2 = "[object WeakMap]";
|
|
2707
|
-
var arrayBufferTag$2 = "[object ArrayBuffer]", dataViewTag$3 = "[object DataView]", float32Tag$2 = "[object Float32Array]", float64Tag$2 = "[object Float64Array]", int8Tag$2 = "[object Int8Array]", int16Tag$2 = "[object Int16Array]", int32Tag$2 = "[object Int32Array]", uint8Tag$2 = "[object Uint8Array]", uint8ClampedTag$2 = "[object Uint8ClampedArray]", uint16Tag$2 = "[object Uint16Array]", uint32Tag$2 = "[object Uint32Array]";
|
|
2708
|
-
var typedArrayTags = {};
|
|
2709
|
-
typedArrayTags[float32Tag$2] = typedArrayTags[float64Tag$2] = typedArrayTags[int8Tag$2] = typedArrayTags[int16Tag$2] = typedArrayTags[int32Tag$2] = typedArrayTags[uint8Tag$2] = typedArrayTags[uint8ClampedTag$2] = typedArrayTags[uint16Tag$2] = typedArrayTags[uint32Tag$2] = true;
|
|
2710
|
-
typedArrayTags[argsTag$1] = typedArrayTags[arrayTag$1] = typedArrayTags[arrayBufferTag$2] = typedArrayTags[boolTag$2] = typedArrayTags[dataViewTag$3] = typedArrayTags[dateTag$2] = typedArrayTags[errorTag$1] = typedArrayTags[funcTag$1] = typedArrayTags[mapTag$4] = typedArrayTags[numberTag$2] = typedArrayTags[objectTag$2] = typedArrayTags[regexpTag$2] = typedArrayTags[setTag$4] = typedArrayTags[stringTag$2] = typedArrayTags[weakMapTag$2] = false;
|
|
2711
|
-
function baseIsTypedArray$1(value) {
|
|
2712
|
-
return isObjectLike$2(value) && isLength$1(value.length) && !!typedArrayTags[baseGetTag$1(value)];
|
|
2713
|
-
}
|
|
2714
|
-
var _baseIsTypedArray = baseIsTypedArray$1;
|
|
2715
|
-
function baseUnary$3(func) {
|
|
2716
|
-
return function(value) {
|
|
2717
|
-
return func(value);
|
|
2718
|
-
};
|
|
2719
|
-
}
|
|
2720
|
-
var _baseUnary = baseUnary$3;
|
|
2721
|
-
var _nodeUtil = { exports: {} };
|
|
2722
|
-
_nodeUtil.exports;
|
|
2723
|
-
(function(module, exports$1) {
|
|
2724
|
-
var freeGlobal2 = _freeGlobal;
|
|
2725
|
-
var freeExports = exports$1 && !exports$1.nodeType && exports$1;
|
|
2726
|
-
var freeModule = freeExports && true && module && !module.nodeType && module;
|
|
2727
|
-
var moduleExports = freeModule && freeModule.exports === freeExports;
|
|
2728
|
-
var freeProcess = moduleExports && freeGlobal2.process;
|
|
2729
|
-
var nodeUtil2 = function() {
|
|
2730
|
-
try {
|
|
2731
|
-
var types = freeModule && freeModule.require && freeModule.require("util").types;
|
|
2732
|
-
if (types) {
|
|
2733
|
-
return types;
|
|
2734
|
-
}
|
|
2735
|
-
return freeProcess && freeProcess.binding && freeProcess.binding("util");
|
|
2736
|
-
} catch (e) {
|
|
2737
|
-
}
|
|
2738
|
-
}();
|
|
2739
|
-
module.exports = nodeUtil2;
|
|
2740
|
-
})(_nodeUtil, _nodeUtil.exports);
|
|
2741
|
-
var _nodeUtilExports = _nodeUtil.exports;
|
|
2742
|
-
var baseIsTypedArray = _baseIsTypedArray, baseUnary$2 = _baseUnary, nodeUtil$2 = _nodeUtilExports;
|
|
2743
|
-
var nodeIsTypedArray = nodeUtil$2 && nodeUtil$2.isTypedArray;
|
|
2744
|
-
var isTypedArray$1 = nodeIsTypedArray ? baseUnary$2(nodeIsTypedArray) : baseIsTypedArray;
|
|
2745
|
-
var isTypedArray_1 = isTypedArray$1;
|
|
2746
|
-
var baseTimes = _baseTimes, isArguments = isArguments_1, isArray$2 = isArray_1, isBuffer$1 = isBufferExports, isIndex = _isIndex, isTypedArray = isTypedArray_1;
|
|
2747
|
-
var objectProto$5 = Object.prototype;
|
|
2748
|
-
var hasOwnProperty$3 = objectProto$5.hasOwnProperty;
|
|
2749
|
-
function arrayLikeKeys$2(value, inherited) {
|
|
2750
|
-
var isArr = isArray$2(value), isArg = !isArr && isArguments(value), isBuff = !isArr && !isArg && isBuffer$1(value), isType = !isArr && !isArg && !isBuff && isTypedArray(value), skipIndexes = isArr || isArg || isBuff || isType, result = skipIndexes ? baseTimes(value.length, String) : [], length = result.length;
|
|
2751
|
-
for (var key in value) {
|
|
2752
|
-
if ((inherited || hasOwnProperty$3.call(value, key)) && !(skipIndexes && // Safari 9 has enumerable `arguments.length` in strict mode.
|
|
2753
|
-
(key == "length" || // Node.js 0.10 has enumerable non-index properties on buffers.
|
|
2754
|
-
isBuff && (key == "offset" || key == "parent") || // PhantomJS 2 has enumerable non-index properties on typed arrays.
|
|
2755
|
-
isType && (key == "buffer" || key == "byteLength" || key == "byteOffset") || // Skip index properties.
|
|
2756
|
-
isIndex(key, length)))) {
|
|
2757
|
-
result.push(key);
|
|
2758
|
-
}
|
|
2759
|
-
}
|
|
2760
|
-
return result;
|
|
2761
|
-
}
|
|
2762
|
-
var _arrayLikeKeys = arrayLikeKeys$2;
|
|
2763
|
-
var objectProto$4 = Object.prototype;
|
|
2764
|
-
function isPrototype$3(value) {
|
|
2765
|
-
var Ctor = value && value.constructor, proto = typeof Ctor == "function" && Ctor.prototype || objectProto$4;
|
|
2766
|
-
return value === proto;
|
|
2767
|
-
}
|
|
2768
|
-
var _isPrototype = isPrototype$3;
|
|
2769
|
-
function overArg$2(func, transform) {
|
|
2770
|
-
return function(arg) {
|
|
2771
|
-
return func(transform(arg));
|
|
2772
|
-
};
|
|
2773
|
-
}
|
|
2774
|
-
var _overArg = overArg$2;
|
|
2775
|
-
var overArg$1 = _overArg;
|
|
2776
|
-
var nativeKeys$1 = overArg$1(Object.keys, Object);
|
|
2777
|
-
var _nativeKeys = nativeKeys$1;
|
|
2778
|
-
var isPrototype$2 = _isPrototype, nativeKeys = _nativeKeys;
|
|
2779
|
-
var objectProto$3 = Object.prototype;
|
|
2780
|
-
var hasOwnProperty$2 = objectProto$3.hasOwnProperty;
|
|
2781
|
-
function baseKeys$1(object) {
|
|
2782
|
-
if (!isPrototype$2(object)) {
|
|
2783
|
-
return nativeKeys(object);
|
|
2784
|
-
}
|
|
2785
|
-
var result = [];
|
|
2786
|
-
for (var key in Object(object)) {
|
|
2787
|
-
if (hasOwnProperty$2.call(object, key) && key != "constructor") {
|
|
2788
|
-
result.push(key);
|
|
2789
|
-
}
|
|
2790
|
-
}
|
|
2791
|
-
return result;
|
|
2792
|
-
}
|
|
2793
|
-
var _baseKeys = baseKeys$1;
|
|
2794
|
-
var isFunction = isFunction_1, isLength = isLength_1;
|
|
2795
|
-
function isArrayLike$2(value) {
|
|
2796
|
-
return value != null && isLength(value.length) && !isFunction(value);
|
|
2797
|
-
}
|
|
2798
|
-
var isArrayLike_1 = isArrayLike$2;
|
|
2799
|
-
var arrayLikeKeys$1 = _arrayLikeKeys, baseKeys = _baseKeys, isArrayLike$1 = isArrayLike_1;
|
|
2800
|
-
function keys$3(object) {
|
|
2801
|
-
return isArrayLike$1(object) ? arrayLikeKeys$1(object) : baseKeys(object);
|
|
2802
|
-
}
|
|
2803
|
-
var keys_1 = keys$3;
|
|
2804
|
-
var copyObject$3 = _copyObject, keys$2 = keys_1;
|
|
2805
|
-
function baseAssign$1(object, source) {
|
|
2806
|
-
return object && copyObject$3(source, keys$2(source), object);
|
|
2807
|
-
}
|
|
2808
|
-
var _baseAssign = baseAssign$1;
|
|
2809
|
-
function nativeKeysIn$1(object) {
|
|
2810
|
-
var result = [];
|
|
2811
|
-
if (object != null) {
|
|
2812
|
-
for (var key in Object(object)) {
|
|
2813
|
-
result.push(key);
|
|
2814
|
-
}
|
|
2815
|
-
}
|
|
2816
|
-
return result;
|
|
2817
|
-
}
|
|
2818
|
-
var _nativeKeysIn = nativeKeysIn$1;
|
|
2819
|
-
var isObject$2 = isObject_1, isPrototype$1 = _isPrototype, nativeKeysIn = _nativeKeysIn;
|
|
2820
|
-
var objectProto$2 = Object.prototype;
|
|
2821
|
-
var hasOwnProperty$1 = objectProto$2.hasOwnProperty;
|
|
2822
|
-
function baseKeysIn$1(object) {
|
|
2823
|
-
if (!isObject$2(object)) {
|
|
2824
|
-
return nativeKeysIn(object);
|
|
2825
|
-
}
|
|
2826
|
-
var isProto = isPrototype$1(object), result = [];
|
|
2827
|
-
for (var key in object) {
|
|
2828
|
-
if (!(key == "constructor" && (isProto || !hasOwnProperty$1.call(object, key)))) {
|
|
2829
|
-
result.push(key);
|
|
2830
|
-
}
|
|
2831
|
-
}
|
|
2832
|
-
return result;
|
|
2833
|
-
}
|
|
2834
|
-
var _baseKeysIn = baseKeysIn$1;
|
|
2835
|
-
var arrayLikeKeys = _arrayLikeKeys, baseKeysIn = _baseKeysIn, isArrayLike = isArrayLike_1;
|
|
2836
|
-
function keysIn$3(object) {
|
|
2837
|
-
return isArrayLike(object) ? arrayLikeKeys(object, true) : baseKeysIn(object);
|
|
2838
|
-
}
|
|
2839
|
-
var keysIn_1 = keysIn$3;
|
|
2840
|
-
var copyObject$2 = _copyObject, keysIn$2 = keysIn_1;
|
|
2841
|
-
function baseAssignIn$1(object, source) {
|
|
2842
|
-
return object && copyObject$2(source, keysIn$2(source), object);
|
|
2843
|
-
}
|
|
2844
|
-
var _baseAssignIn = baseAssignIn$1;
|
|
2845
|
-
var _cloneBuffer = { exports: {} };
|
|
2846
|
-
_cloneBuffer.exports;
|
|
2847
|
-
(function(module, exports$1) {
|
|
2848
|
-
var root2 = _root;
|
|
2849
|
-
var freeExports = exports$1 && !exports$1.nodeType && exports$1;
|
|
2850
|
-
var freeModule = freeExports && true && module && !module.nodeType && module;
|
|
2851
|
-
var moduleExports = freeModule && freeModule.exports === freeExports;
|
|
2852
|
-
var Buffer2 = moduleExports ? root2.Buffer : void 0, allocUnsafe = Buffer2 ? Buffer2.allocUnsafe : void 0;
|
|
2853
|
-
function cloneBuffer2(buffer, isDeep) {
|
|
2854
|
-
if (isDeep) {
|
|
2855
|
-
return buffer.slice();
|
|
2856
|
-
}
|
|
2857
|
-
var length = buffer.length, result = allocUnsafe ? allocUnsafe(length) : new buffer.constructor(length);
|
|
2858
|
-
buffer.copy(result);
|
|
2859
|
-
return result;
|
|
2860
|
-
}
|
|
2861
|
-
module.exports = cloneBuffer2;
|
|
2862
|
-
})(_cloneBuffer, _cloneBuffer.exports);
|
|
2863
|
-
var _cloneBufferExports = _cloneBuffer.exports;
|
|
2864
|
-
function copyArray$1(source, array) {
|
|
2865
|
-
var index = -1, length = source.length;
|
|
2866
|
-
array || (array = Array(length));
|
|
2867
|
-
while (++index < length) {
|
|
2868
|
-
array[index] = source[index];
|
|
2869
|
-
}
|
|
2870
|
-
return array;
|
|
2871
|
-
}
|
|
2872
|
-
var _copyArray = copyArray$1;
|
|
2873
|
-
function arrayFilter$1(array, predicate) {
|
|
2874
|
-
var index = -1, length = array == null ? 0 : array.length, resIndex = 0, result = [];
|
|
2875
|
-
while (++index < length) {
|
|
2876
|
-
var value = array[index];
|
|
2877
|
-
if (predicate(value, index, array)) {
|
|
2878
|
-
result[resIndex++] = value;
|
|
2879
|
-
}
|
|
2880
|
-
}
|
|
2881
|
-
return result;
|
|
2882
|
-
}
|
|
2883
|
-
var _arrayFilter = arrayFilter$1;
|
|
2884
|
-
function stubArray$2() {
|
|
2885
|
-
return [];
|
|
2886
|
-
}
|
|
2887
|
-
var stubArray_1 = stubArray$2;
|
|
2888
|
-
var arrayFilter = _arrayFilter, stubArray$1 = stubArray_1;
|
|
2889
|
-
var objectProto$1 = Object.prototype;
|
|
2890
|
-
var propertyIsEnumerable = objectProto$1.propertyIsEnumerable;
|
|
2891
|
-
var nativeGetSymbols$1 = Object.getOwnPropertySymbols;
|
|
2892
|
-
var getSymbols$3 = !nativeGetSymbols$1 ? stubArray$1 : function(object) {
|
|
2893
|
-
if (object == null) {
|
|
2894
|
-
return [];
|
|
2895
|
-
}
|
|
2896
|
-
object = Object(object);
|
|
2897
|
-
return arrayFilter(nativeGetSymbols$1(object), function(symbol) {
|
|
2898
|
-
return propertyIsEnumerable.call(object, symbol);
|
|
2899
|
-
});
|
|
2900
|
-
};
|
|
2901
|
-
var _getSymbols = getSymbols$3;
|
|
2902
|
-
var copyObject$1 = _copyObject, getSymbols$2 = _getSymbols;
|
|
2903
|
-
function copySymbols$1(source, object) {
|
|
2904
|
-
return copyObject$1(source, getSymbols$2(source), object);
|
|
2905
|
-
}
|
|
2906
|
-
var _copySymbols = copySymbols$1;
|
|
2907
|
-
function arrayPush$2(array, values) {
|
|
2908
|
-
var index = -1, length = values.length, offset = array.length;
|
|
2909
|
-
while (++index < length) {
|
|
2910
|
-
array[offset + index] = values[index];
|
|
2911
|
-
}
|
|
2912
|
-
return array;
|
|
2913
|
-
}
|
|
2914
|
-
var _arrayPush = arrayPush$2;
|
|
2915
|
-
var overArg = _overArg;
|
|
2916
|
-
var getPrototype$2 = overArg(Object.getPrototypeOf, Object);
|
|
2917
|
-
var _getPrototype = getPrototype$2;
|
|
2918
|
-
var arrayPush$1 = _arrayPush, getPrototype$1 = _getPrototype, getSymbols$1 = _getSymbols, stubArray = stubArray_1;
|
|
2919
|
-
var nativeGetSymbols = Object.getOwnPropertySymbols;
|
|
2920
|
-
var getSymbolsIn$2 = !nativeGetSymbols ? stubArray : function(object) {
|
|
2921
|
-
var result = [];
|
|
2922
|
-
while (object) {
|
|
2923
|
-
arrayPush$1(result, getSymbols$1(object));
|
|
2924
|
-
object = getPrototype$1(object);
|
|
2925
|
-
}
|
|
2926
|
-
return result;
|
|
2927
|
-
};
|
|
2928
|
-
var _getSymbolsIn = getSymbolsIn$2;
|
|
2929
|
-
var copyObject = _copyObject, getSymbolsIn$1 = _getSymbolsIn;
|
|
2930
|
-
function copySymbolsIn$1(source, object) {
|
|
2931
|
-
return copyObject(source, getSymbolsIn$1(source), object);
|
|
2932
|
-
}
|
|
2933
|
-
var _copySymbolsIn = copySymbolsIn$1;
|
|
2934
|
-
var arrayPush = _arrayPush, isArray$1 = isArray_1;
|
|
2935
|
-
function baseGetAllKeys$2(object, keysFunc, symbolsFunc) {
|
|
2936
|
-
var result = keysFunc(object);
|
|
2937
|
-
return isArray$1(object) ? result : arrayPush(result, symbolsFunc(object));
|
|
2938
|
-
}
|
|
2939
|
-
var _baseGetAllKeys = baseGetAllKeys$2;
|
|
2940
|
-
var baseGetAllKeys$1 = _baseGetAllKeys, getSymbols = _getSymbols, keys$1 = keys_1;
|
|
2941
|
-
function getAllKeys$1(object) {
|
|
2942
|
-
return baseGetAllKeys$1(object, keys$1, getSymbols);
|
|
2943
|
-
}
|
|
2944
|
-
var _getAllKeys = getAllKeys$1;
|
|
2945
|
-
var baseGetAllKeys = _baseGetAllKeys, getSymbolsIn = _getSymbolsIn, keysIn$1 = keysIn_1;
|
|
2946
|
-
function getAllKeysIn$1(object) {
|
|
2947
|
-
return baseGetAllKeys(object, keysIn$1, getSymbolsIn);
|
|
2948
|
-
}
|
|
2949
|
-
var _getAllKeysIn = getAllKeysIn$1;
|
|
2950
|
-
var getNative$3 = _getNative, root$4 = _root;
|
|
2951
|
-
var DataView$1 = getNative$3(root$4, "DataView");
|
|
2952
|
-
var _DataView = DataView$1;
|
|
2953
|
-
var getNative$2 = _getNative, root$3 = _root;
|
|
2954
|
-
var Promise$2 = getNative$2(root$3, "Promise");
|
|
2955
|
-
var _Promise = Promise$2;
|
|
2956
|
-
var getNative$1 = _getNative, root$2 = _root;
|
|
2957
|
-
var Set$2 = getNative$1(root$2, "Set");
|
|
2958
|
-
var _Set = Set$2;
|
|
2959
|
-
var getNative = _getNative, root$1 = _root;
|
|
2960
|
-
var WeakMap$2 = getNative(root$1, "WeakMap");
|
|
2961
|
-
var _WeakMap = WeakMap$2;
|
|
2962
|
-
var DataView = _DataView, Map$1 = _Map, Promise$1 = _Promise, Set$1 = _Set, WeakMap$1 = _WeakMap, baseGetTag = _baseGetTag, toSource = _toSource;
|
|
2963
|
-
var mapTag$3 = "[object Map]", objectTag$1 = "[object Object]", promiseTag = "[object Promise]", setTag$3 = "[object Set]", weakMapTag$1 = "[object WeakMap]";
|
|
2964
|
-
var dataViewTag$2 = "[object DataView]";
|
|
2965
|
-
var dataViewCtorString = toSource(DataView), mapCtorString = toSource(Map$1), promiseCtorString = toSource(Promise$1), setCtorString = toSource(Set$1), weakMapCtorString = toSource(WeakMap$1);
|
|
2966
|
-
var getTag$3 = baseGetTag;
|
|
2967
|
-
if (DataView && getTag$3(new DataView(new ArrayBuffer(1))) != dataViewTag$2 || Map$1 && getTag$3(new Map$1()) != mapTag$3 || Promise$1 && getTag$3(Promise$1.resolve()) != promiseTag || Set$1 && getTag$3(new Set$1()) != setTag$3 || WeakMap$1 && getTag$3(new WeakMap$1()) != weakMapTag$1) {
|
|
2968
|
-
getTag$3 = function(value) {
|
|
2969
|
-
var result = baseGetTag(value), Ctor = result == objectTag$1 ? value.constructor : void 0, ctorString = Ctor ? toSource(Ctor) : "";
|
|
2970
|
-
if (ctorString) {
|
|
2971
|
-
switch (ctorString) {
|
|
2972
|
-
case dataViewCtorString:
|
|
2973
|
-
return dataViewTag$2;
|
|
2974
|
-
case mapCtorString:
|
|
2975
|
-
return mapTag$3;
|
|
2976
|
-
case promiseCtorString:
|
|
2977
|
-
return promiseTag;
|
|
2978
|
-
case setCtorString:
|
|
2979
|
-
return setTag$3;
|
|
2980
|
-
case weakMapCtorString:
|
|
2981
|
-
return weakMapTag$1;
|
|
2982
|
-
}
|
|
2983
|
-
}
|
|
2984
|
-
return result;
|
|
2985
|
-
};
|
|
2986
|
-
}
|
|
2987
|
-
var _getTag = getTag$3;
|
|
2988
|
-
var objectProto = Object.prototype;
|
|
2989
|
-
var hasOwnProperty = objectProto.hasOwnProperty;
|
|
2990
|
-
function initCloneArray$1(array) {
|
|
2991
|
-
var length = array.length, result = new array.constructor(length);
|
|
2992
|
-
if (length && typeof array[0] == "string" && hasOwnProperty.call(array, "index")) {
|
|
2993
|
-
result.index = array.index;
|
|
2994
|
-
result.input = array.input;
|
|
2995
|
-
}
|
|
2996
|
-
return result;
|
|
2997
|
-
}
|
|
2998
|
-
var _initCloneArray = initCloneArray$1;
|
|
2999
|
-
var root = _root;
|
|
3000
|
-
var Uint8Array$2 = root.Uint8Array;
|
|
3001
|
-
var _Uint8Array = Uint8Array$2;
|
|
3002
|
-
var Uint8Array$1 = _Uint8Array;
|
|
3003
|
-
function cloneArrayBuffer$3(arrayBuffer) {
|
|
3004
|
-
var result = new arrayBuffer.constructor(arrayBuffer.byteLength);
|
|
3005
|
-
new Uint8Array$1(result).set(new Uint8Array$1(arrayBuffer));
|
|
3006
|
-
return result;
|
|
3007
|
-
}
|
|
3008
|
-
var _cloneArrayBuffer = cloneArrayBuffer$3;
|
|
3009
|
-
var cloneArrayBuffer$2 = _cloneArrayBuffer;
|
|
3010
|
-
function cloneDataView$1(dataView, isDeep) {
|
|
3011
|
-
var buffer = isDeep ? cloneArrayBuffer$2(dataView.buffer) : dataView.buffer;
|
|
3012
|
-
return new dataView.constructor(buffer, dataView.byteOffset, dataView.byteLength);
|
|
3013
|
-
}
|
|
3014
|
-
var _cloneDataView = cloneDataView$1;
|
|
3015
|
-
var reFlags = /\w*$/;
|
|
3016
|
-
function cloneRegExp$1(regexp) {
|
|
3017
|
-
var result = new regexp.constructor(regexp.source, reFlags.exec(regexp));
|
|
3018
|
-
result.lastIndex = regexp.lastIndex;
|
|
3019
|
-
return result;
|
|
3020
|
-
}
|
|
3021
|
-
var _cloneRegExp = cloneRegExp$1;
|
|
3022
|
-
var Symbol$1 = _Symbol;
|
|
3023
|
-
var symbolProto = Symbol$1 ? Symbol$1.prototype : void 0, symbolValueOf = symbolProto ? symbolProto.valueOf : void 0;
|
|
3024
|
-
function cloneSymbol$1(symbol) {
|
|
3025
|
-
return symbolValueOf ? Object(symbolValueOf.call(symbol)) : {};
|
|
3026
|
-
}
|
|
3027
|
-
var _cloneSymbol = cloneSymbol$1;
|
|
3028
|
-
var cloneArrayBuffer$1 = _cloneArrayBuffer;
|
|
3029
|
-
function cloneTypedArray$1(typedArray, isDeep) {
|
|
3030
|
-
var buffer = isDeep ? cloneArrayBuffer$1(typedArray.buffer) : typedArray.buffer;
|
|
3031
|
-
return new typedArray.constructor(buffer, typedArray.byteOffset, typedArray.length);
|
|
3032
|
-
}
|
|
3033
|
-
var _cloneTypedArray = cloneTypedArray$1;
|
|
3034
|
-
var cloneArrayBuffer = _cloneArrayBuffer, cloneDataView = _cloneDataView, cloneRegExp = _cloneRegExp, cloneSymbol = _cloneSymbol, cloneTypedArray = _cloneTypedArray;
|
|
3035
|
-
var boolTag$1 = "[object Boolean]", dateTag$1 = "[object Date]", mapTag$2 = "[object Map]", numberTag$1 = "[object Number]", regexpTag$1 = "[object RegExp]", setTag$2 = "[object Set]", stringTag$1 = "[object String]", symbolTag$1 = "[object Symbol]";
|
|
3036
|
-
var arrayBufferTag$1 = "[object ArrayBuffer]", dataViewTag$1 = "[object DataView]", float32Tag$1 = "[object Float32Array]", float64Tag$1 = "[object Float64Array]", int8Tag$1 = "[object Int8Array]", int16Tag$1 = "[object Int16Array]", int32Tag$1 = "[object Int32Array]", uint8Tag$1 = "[object Uint8Array]", uint8ClampedTag$1 = "[object Uint8ClampedArray]", uint16Tag$1 = "[object Uint16Array]", uint32Tag$1 = "[object Uint32Array]";
|
|
3037
|
-
function initCloneByTag$1(object, tag, isDeep) {
|
|
3038
|
-
var Ctor = object.constructor;
|
|
3039
|
-
switch (tag) {
|
|
3040
|
-
case arrayBufferTag$1:
|
|
3041
|
-
return cloneArrayBuffer(object);
|
|
3042
|
-
case boolTag$1:
|
|
3043
|
-
case dateTag$1:
|
|
3044
|
-
return new Ctor(+object);
|
|
3045
|
-
case dataViewTag$1:
|
|
3046
|
-
return cloneDataView(object, isDeep);
|
|
3047
|
-
case float32Tag$1:
|
|
3048
|
-
case float64Tag$1:
|
|
3049
|
-
case int8Tag$1:
|
|
3050
|
-
case int16Tag$1:
|
|
3051
|
-
case int32Tag$1:
|
|
3052
|
-
case uint8Tag$1:
|
|
3053
|
-
case uint8ClampedTag$1:
|
|
3054
|
-
case uint16Tag$1:
|
|
3055
|
-
case uint32Tag$1:
|
|
3056
|
-
return cloneTypedArray(object, isDeep);
|
|
3057
|
-
case mapTag$2:
|
|
3058
|
-
return new Ctor();
|
|
3059
|
-
case numberTag$1:
|
|
3060
|
-
case stringTag$1:
|
|
3061
|
-
return new Ctor(object);
|
|
3062
|
-
case regexpTag$1:
|
|
3063
|
-
return cloneRegExp(object);
|
|
3064
|
-
case setTag$2:
|
|
3065
|
-
return new Ctor();
|
|
3066
|
-
case symbolTag$1:
|
|
3067
|
-
return cloneSymbol(object);
|
|
3068
|
-
}
|
|
3069
|
-
}
|
|
3070
|
-
var _initCloneByTag = initCloneByTag$1;
|
|
3071
|
-
var isObject$1 = isObject_1;
|
|
3072
|
-
var objectCreate = Object.create;
|
|
3073
|
-
var baseCreate$1 = /* @__PURE__ */ function() {
|
|
3074
|
-
function object() {
|
|
3075
|
-
}
|
|
3076
|
-
return function(proto) {
|
|
3077
|
-
if (!isObject$1(proto)) {
|
|
3078
|
-
return {};
|
|
3079
|
-
}
|
|
3080
|
-
if (objectCreate) {
|
|
3081
|
-
return objectCreate(proto);
|
|
3082
|
-
}
|
|
3083
|
-
object.prototype = proto;
|
|
3084
|
-
var result = new object();
|
|
3085
|
-
object.prototype = void 0;
|
|
3086
|
-
return result;
|
|
3087
|
-
};
|
|
3088
|
-
}();
|
|
3089
|
-
var _baseCreate = baseCreate$1;
|
|
3090
|
-
var baseCreate = _baseCreate, getPrototype = _getPrototype, isPrototype = _isPrototype;
|
|
3091
|
-
function initCloneObject$1(object) {
|
|
3092
|
-
return typeof object.constructor == "function" && !isPrototype(object) ? baseCreate(getPrototype(object)) : {};
|
|
3093
|
-
}
|
|
3094
|
-
var _initCloneObject = initCloneObject$1;
|
|
3095
|
-
var getTag$2 = _getTag, isObjectLike$1 = isObjectLike_1;
|
|
3096
|
-
var mapTag$1 = "[object Map]";
|
|
3097
|
-
function baseIsMap$1(value) {
|
|
3098
|
-
return isObjectLike$1(value) && getTag$2(value) == mapTag$1;
|
|
3099
|
-
}
|
|
3100
|
-
var _baseIsMap = baseIsMap$1;
|
|
3101
|
-
var baseIsMap = _baseIsMap, baseUnary$1 = _baseUnary, nodeUtil$1 = _nodeUtilExports;
|
|
3102
|
-
var nodeIsMap = nodeUtil$1 && nodeUtil$1.isMap;
|
|
3103
|
-
var isMap$1 = nodeIsMap ? baseUnary$1(nodeIsMap) : baseIsMap;
|
|
3104
|
-
var isMap_1 = isMap$1;
|
|
3105
|
-
var getTag$1 = _getTag, isObjectLike = isObjectLike_1;
|
|
3106
|
-
var setTag$1 = "[object Set]";
|
|
3107
|
-
function baseIsSet$1(value) {
|
|
3108
|
-
return isObjectLike(value) && getTag$1(value) == setTag$1;
|
|
3109
|
-
}
|
|
3110
|
-
var _baseIsSet = baseIsSet$1;
|
|
3111
|
-
var baseIsSet = _baseIsSet, baseUnary = _baseUnary, nodeUtil = _nodeUtilExports;
|
|
3112
|
-
var nodeIsSet = nodeUtil && nodeUtil.isSet;
|
|
3113
|
-
var isSet$1 = nodeIsSet ? baseUnary(nodeIsSet) : baseIsSet;
|
|
3114
|
-
var isSet_1 = isSet$1;
|
|
3115
|
-
var Stack = _Stack, arrayEach = _arrayEach, assignValue = _assignValue, baseAssign = _baseAssign, baseAssignIn = _baseAssignIn, cloneBuffer = _cloneBufferExports, copyArray = _copyArray, copySymbols = _copySymbols, copySymbolsIn = _copySymbolsIn, getAllKeys = _getAllKeys, getAllKeysIn = _getAllKeysIn, getTag = _getTag, initCloneArray = _initCloneArray, initCloneByTag = _initCloneByTag, initCloneObject = _initCloneObject, isArray = isArray_1, isBuffer = isBufferExports, isMap = isMap_1, isObject = isObject_1, isSet = isSet_1, keys = keys_1, keysIn = keysIn_1;
|
|
3116
|
-
var CLONE_DEEP_FLAG$1 = 1, CLONE_FLAT_FLAG = 2, CLONE_SYMBOLS_FLAG$1 = 4;
|
|
3117
|
-
var argsTag = "[object Arguments]", arrayTag = "[object Array]", boolTag = "[object Boolean]", dateTag = "[object Date]", errorTag = "[object Error]", funcTag = "[object Function]", genTag = "[object GeneratorFunction]", mapTag = "[object Map]", numberTag = "[object Number]", objectTag = "[object Object]", regexpTag = "[object RegExp]", setTag = "[object Set]", stringTag = "[object String]", symbolTag = "[object Symbol]", weakMapTag = "[object WeakMap]";
|
|
3118
|
-
var arrayBufferTag = "[object ArrayBuffer]", dataViewTag = "[object DataView]", float32Tag = "[object Float32Array]", float64Tag = "[object Float64Array]", int8Tag = "[object Int8Array]", int16Tag = "[object Int16Array]", int32Tag = "[object Int32Array]", uint8Tag = "[object Uint8Array]", uint8ClampedTag = "[object Uint8ClampedArray]", uint16Tag = "[object Uint16Array]", uint32Tag = "[object Uint32Array]";
|
|
3119
|
-
var cloneableTags = {};
|
|
3120
|
-
cloneableTags[argsTag] = cloneableTags[arrayTag] = cloneableTags[arrayBufferTag] = cloneableTags[dataViewTag] = cloneableTags[boolTag] = cloneableTags[dateTag] = cloneableTags[float32Tag] = cloneableTags[float64Tag] = cloneableTags[int8Tag] = cloneableTags[int16Tag] = cloneableTags[int32Tag] = cloneableTags[mapTag] = cloneableTags[numberTag] = cloneableTags[objectTag] = cloneableTags[regexpTag] = cloneableTags[setTag] = cloneableTags[stringTag] = cloneableTags[symbolTag] = cloneableTags[uint8Tag] = cloneableTags[uint8ClampedTag] = cloneableTags[uint16Tag] = cloneableTags[uint32Tag] = true;
|
|
3121
|
-
cloneableTags[errorTag] = cloneableTags[funcTag] = cloneableTags[weakMapTag] = false;
|
|
3122
|
-
function baseClone$1(value, bitmask, customizer, key, object, stack) {
|
|
3123
|
-
var result, isDeep = bitmask & CLONE_DEEP_FLAG$1, isFlat = bitmask & CLONE_FLAT_FLAG, isFull = bitmask & CLONE_SYMBOLS_FLAG$1;
|
|
3124
|
-
if (customizer) {
|
|
3125
|
-
result = object ? customizer(value, key, object, stack) : customizer(value);
|
|
3126
|
-
}
|
|
3127
|
-
if (result !== void 0) {
|
|
3128
|
-
return result;
|
|
3129
|
-
}
|
|
3130
|
-
if (!isObject(value)) {
|
|
3131
|
-
return value;
|
|
3132
|
-
}
|
|
3133
|
-
var isArr = isArray(value);
|
|
3134
|
-
if (isArr) {
|
|
3135
|
-
result = initCloneArray(value);
|
|
3136
|
-
if (!isDeep) {
|
|
3137
|
-
return copyArray(value, result);
|
|
3138
|
-
}
|
|
3139
|
-
} else {
|
|
3140
|
-
var tag = getTag(value), isFunc = tag == funcTag || tag == genTag;
|
|
3141
|
-
if (isBuffer(value)) {
|
|
3142
|
-
return cloneBuffer(value, isDeep);
|
|
3143
|
-
}
|
|
3144
|
-
if (tag == objectTag || tag == argsTag || isFunc && !object) {
|
|
3145
|
-
result = isFlat || isFunc ? {} : initCloneObject(value);
|
|
3146
|
-
if (!isDeep) {
|
|
3147
|
-
return isFlat ? copySymbolsIn(value, baseAssignIn(result, value)) : copySymbols(value, baseAssign(result, value));
|
|
3148
|
-
}
|
|
3149
|
-
} else {
|
|
3150
|
-
if (!cloneableTags[tag]) {
|
|
3151
|
-
return object ? value : {};
|
|
3152
|
-
}
|
|
3153
|
-
result = initCloneByTag(value, tag, isDeep);
|
|
3154
|
-
}
|
|
3155
|
-
}
|
|
3156
|
-
stack || (stack = new Stack());
|
|
3157
|
-
var stacked = stack.get(value);
|
|
3158
|
-
if (stacked) {
|
|
3159
|
-
return stacked;
|
|
3160
|
-
}
|
|
3161
|
-
stack.set(value, result);
|
|
3162
|
-
if (isSet(value)) {
|
|
3163
|
-
value.forEach(function(subValue) {
|
|
3164
|
-
result.add(baseClone$1(subValue, bitmask, customizer, subValue, value, stack));
|
|
3165
|
-
});
|
|
3166
|
-
} else if (isMap(value)) {
|
|
3167
|
-
value.forEach(function(subValue, key2) {
|
|
3168
|
-
result.set(key2, baseClone$1(subValue, bitmask, customizer, key2, value, stack));
|
|
3169
|
-
});
|
|
3170
|
-
}
|
|
3171
|
-
var keysFunc = isFull ? isFlat ? getAllKeysIn : getAllKeys : isFlat ? keysIn : keys;
|
|
3172
|
-
var props = isArr ? void 0 : keysFunc(value);
|
|
3173
|
-
arrayEach(props || value, function(subValue, key2) {
|
|
3174
|
-
if (props) {
|
|
3175
|
-
key2 = subValue;
|
|
3176
|
-
subValue = value[key2];
|
|
3177
|
-
}
|
|
3178
|
-
assignValue(result, key2, baseClone$1(subValue, bitmask, customizer, key2, value, stack));
|
|
3179
|
-
});
|
|
3180
|
-
return result;
|
|
3181
|
-
}
|
|
3182
|
-
var _baseClone = baseClone$1;
|
|
3183
|
-
var baseClone = _baseClone;
|
|
3184
|
-
var CLONE_DEEP_FLAG = 1, CLONE_SYMBOLS_FLAG = 4;
|
|
3185
|
-
function cloneDeep(value) {
|
|
3186
|
-
return baseClone(value, CLONE_DEEP_FLAG | CLONE_SYMBOLS_FLAG);
|
|
3187
|
-
}
|
|
3188
|
-
var cloneDeep_1 = cloneDeep;
|
|
3189
|
-
const cloneDeep$1 = /* @__PURE__ */ getDefaultExportFromCjs(cloneDeep_1);
|
|
3190
2295
|
class CollectionRegistry {
|
|
3191
2296
|
// Normalized runtime layer (used by Data Grid / UI)
|
|
3192
2297
|
collectionsByTableName = /* @__PURE__ */ new Map();
|
|
@@ -3226,15 +2331,21 @@ class CollectionRegistry {
|
|
|
3226
2331
|
*/
|
|
3227
2332
|
registerMultiple(collections) {
|
|
3228
2333
|
const rawSnapshot = collections.map((c) => removeFunctions(c));
|
|
3229
|
-
if (this.lastRawInputSnapshot && deepEqual(this.lastRawInputSnapshot, rawSnapshot)) {
|
|
2334
|
+
if (this.lastRawInputSnapshot && deepEqual$1(this.lastRawInputSnapshot, rawSnapshot)) {
|
|
3230
2335
|
return false;
|
|
3231
2336
|
}
|
|
3232
2337
|
this.reset();
|
|
2338
|
+
collections.forEach((c) => {
|
|
2339
|
+
if (c.slug) {
|
|
2340
|
+
this.collectionsBySlug.set(c.slug, c);
|
|
2341
|
+
}
|
|
2342
|
+
this.collectionsByTableName.set(getTableName(c), c);
|
|
2343
|
+
});
|
|
3233
2344
|
const normalizedCollections = collections.map((c) => this.normalizeCollection({
|
|
3234
2345
|
...c
|
|
3235
2346
|
}));
|
|
3236
2347
|
normalizedCollections.forEach((c, index) => {
|
|
3237
|
-
const raw =
|
|
2348
|
+
const raw = deepClone(collections[index]);
|
|
3238
2349
|
this.rootCollections.push(c);
|
|
3239
2350
|
this.rawRootCollections.push(raw);
|
|
3240
2351
|
const normalized = this.normalizeCollection(c);
|
|
@@ -3254,7 +2365,7 @@ class CollectionRegistry {
|
|
|
3254
2365
|
if (!subCollection) return;
|
|
3255
2366
|
this._registerRecursively(this.normalizeCollection({
|
|
3256
2367
|
...subCollection
|
|
3257
|
-
}),
|
|
2368
|
+
}), deepClone(subCollection));
|
|
3258
2369
|
});
|
|
3259
2370
|
}
|
|
3260
2371
|
});
|
|
@@ -3262,7 +2373,7 @@ class CollectionRegistry {
|
|
|
3262
2373
|
return true;
|
|
3263
2374
|
}
|
|
3264
2375
|
register(collection, rawCollection) {
|
|
3265
|
-
const raw = rawCollection ?
|
|
2376
|
+
const raw = rawCollection ? deepClone(rawCollection) : deepClone(collection);
|
|
3266
2377
|
this.rootCollections.push(collection);
|
|
3267
2378
|
this.rawRootCollections.push(raw);
|
|
3268
2379
|
this._registerRecursively(collection, raw);
|
|
@@ -3286,7 +2397,7 @@ class CollectionRegistry {
|
|
|
3286
2397
|
if (!subCollection) return;
|
|
3287
2398
|
this._registerRecursively(this.normalizeCollection({
|
|
3288
2399
|
...subCollection
|
|
3289
|
-
}),
|
|
2400
|
+
}), deepClone(subCollection));
|
|
3290
2401
|
});
|
|
3291
2402
|
}
|
|
3292
2403
|
}
|
|
@@ -3308,7 +2419,7 @@ class CollectionRegistry {
|
|
|
3308
2419
|
if (getDataSourceCapabilities(result.driver).supportsRelations) {
|
|
3309
2420
|
mergedRelations = mergedRelationsRaw.map((r) => {
|
|
3310
2421
|
try {
|
|
3311
|
-
return sanitizeRelation(r, result);
|
|
2422
|
+
return sanitizeRelation(r, result, (slug) => this.get(slug));
|
|
3312
2423
|
} catch {
|
|
3313
2424
|
return r;
|
|
3314
2425
|
}
|
|
@@ -3747,8 +2858,14 @@ class DrizzleConditionBuilder {
|
|
|
3747
2858
|
static buildSingleFilterCondition(column, op, value) {
|
|
3748
2859
|
switch (op) {
|
|
3749
2860
|
case "==":
|
|
3750
|
-
|
|
2861
|
+
if (value === null || value === void 0) {
|
|
2862
|
+
return sql`${column} IS NULL`;
|
|
2863
|
+
}
|
|
2864
|
+
return eq(column, value);
|
|
3751
2865
|
case "!=":
|
|
2866
|
+
if (value === null || value === void 0) {
|
|
2867
|
+
return sql`${column} IS NOT NULL`;
|
|
2868
|
+
}
|
|
3752
2869
|
return sql`${column} != ${value}`;
|
|
3753
2870
|
case ">":
|
|
3754
2871
|
return sql`${column} > ${value}`;
|
|
@@ -3877,7 +2994,7 @@ class DrizzleConditionBuilder {
|
|
|
3877
2994
|
throw new Error(`Join path did not result in connecting to parent table. Current: ${currentTableName}, Parent: ${parentTableName}`);
|
|
3878
2995
|
}
|
|
3879
2996
|
}
|
|
3880
|
-
const finalCondition = Array.isArray(parentEntityId) ? inArray(parentIdColumn, parentEntityId) : eq
|
|
2997
|
+
const finalCondition = Array.isArray(parentEntityId) ? inArray(parentIdColumn, parentEntityId) : eq(parentIdColumn, parentEntityId);
|
|
3881
2998
|
return {
|
|
3882
2999
|
joins,
|
|
3883
3000
|
finalCondition
|
|
@@ -3903,7 +3020,7 @@ class DrizzleConditionBuilder {
|
|
|
3903
3020
|
throw new Error(`Join columns not found: ${fromTableName}.${fromColName} = ${toTableName}.${toColName}`);
|
|
3904
3021
|
}
|
|
3905
3022
|
joinTable = fromTable;
|
|
3906
|
-
condition = eq
|
|
3023
|
+
condition = eq(left, right);
|
|
3907
3024
|
} else if (currentTable === fromTable) {
|
|
3908
3025
|
const left = toTable[toColName];
|
|
3909
3026
|
const right = currentTable[fromColName];
|
|
@@ -3917,7 +3034,7 @@ class DrizzleConditionBuilder {
|
|
|
3917
3034
|
throw new Error(`Join columns not found: ${toTableName}.${toColName} = ${fromTableName}.${fromColName}`);
|
|
3918
3035
|
}
|
|
3919
3036
|
joinTable = toTable;
|
|
3920
|
-
condition = eq
|
|
3037
|
+
condition = eq(left, right);
|
|
3921
3038
|
} else {
|
|
3922
3039
|
throw new Error(`Join step does not match current table. Current table does not match from: ${fromTableName} or to: ${toTableName}`);
|
|
3923
3040
|
}
|
|
@@ -3948,19 +3065,19 @@ class DrizzleConditionBuilder {
|
|
|
3948
3065
|
if (currentTable === targetTable) {
|
|
3949
3066
|
return {
|
|
3950
3067
|
joinTable: targetTable,
|
|
3951
|
-
condition: eq
|
|
3068
|
+
condition: eq(targetTableIdCol, junctionTargetCol),
|
|
3952
3069
|
additionalJoins: [{
|
|
3953
3070
|
table: junctionTable,
|
|
3954
|
-
condition: eq
|
|
3071
|
+
condition: eq(currentTableIdCol, junctionSourceCol)
|
|
3955
3072
|
}]
|
|
3956
3073
|
};
|
|
3957
3074
|
} else {
|
|
3958
3075
|
return {
|
|
3959
3076
|
joinTable: junctionTable,
|
|
3960
|
-
condition: eq
|
|
3077
|
+
condition: eq(currentTableIdCol, junctionSourceCol),
|
|
3961
3078
|
additionalJoins: [{
|
|
3962
3079
|
table: targetTable,
|
|
3963
|
-
condition: eq
|
|
3080
|
+
condition: eq(targetTableIdCol, junctionTargetCol)
|
|
3964
3081
|
}]
|
|
3965
3082
|
};
|
|
3966
3083
|
}
|
|
@@ -3985,11 +3102,11 @@ class DrizzleConditionBuilder {
|
|
|
3985
3102
|
if (!junctionTargetCol) {
|
|
3986
3103
|
throw new Error(`Target column '${through.targetColumn}' not found in junction table '${through.table}'`);
|
|
3987
3104
|
}
|
|
3988
|
-
const condition = Array.isArray(parentEntityId) ? inArray(junctionSourceCol, parentEntityId) : eq
|
|
3105
|
+
const condition = Array.isArray(parentEntityId) ? inArray(junctionSourceCol, parentEntityId) : eq(junctionSourceCol, parentEntityId);
|
|
3989
3106
|
return {
|
|
3990
3107
|
join: {
|
|
3991
3108
|
table: junctionTable,
|
|
3992
|
-
condition: eq
|
|
3109
|
+
condition: eq(targetIdColumn, junctionTargetCol)
|
|
3993
3110
|
},
|
|
3994
3111
|
condition
|
|
3995
3112
|
};
|
|
@@ -4010,11 +3127,11 @@ class DrizzleConditionBuilder {
|
|
|
4010
3127
|
if (!junctionTargetCol) {
|
|
4011
3128
|
throw new Error(`Target column '${through.targetColumn}' not found in junction table '${through.table}'`);
|
|
4012
3129
|
}
|
|
4013
|
-
const condition = Array.isArray(parentEntityId) ? inArray(junctionSourceCol, parentEntityId) : eq
|
|
3130
|
+
const condition = Array.isArray(parentEntityId) ? inArray(junctionSourceCol, parentEntityId) : eq(junctionSourceCol, parentEntityId);
|
|
4014
3131
|
return {
|
|
4015
3132
|
join: {
|
|
4016
3133
|
table: junctionTable,
|
|
4017
|
-
condition: eq
|
|
3134
|
+
condition: eq(targetIdColumn, junctionTargetCol)
|
|
4018
3135
|
},
|
|
4019
3136
|
condition
|
|
4020
3137
|
};
|
|
@@ -4030,15 +3147,15 @@ class DrizzleConditionBuilder {
|
|
|
4030
3147
|
if (!idCol) {
|
|
4031
3148
|
throw new Error('No primary key or "id" column found in target table');
|
|
4032
3149
|
}
|
|
4033
|
-
return Array.isArray(parentEntityId) ? inArray(idCol, parentEntityId) : eq
|
|
3150
|
+
return Array.isArray(parentEntityId) ? inArray(idCol, parentEntityId) : eq(idCol, parentEntityId);
|
|
4034
3151
|
}
|
|
4035
|
-
return Array.isArray(parentEntityId) ? inArray(targetIdCol, parentEntityId) : eq
|
|
3152
|
+
return Array.isArray(parentEntityId) ? inArray(targetIdCol, parentEntityId) : eq(targetIdCol, parentEntityId);
|
|
4036
3153
|
} else if (relation.direction === "inverse" && relation.foreignKeyOnTarget) {
|
|
4037
3154
|
const foreignKeyCol = targetTable[relation.foreignKeyOnTarget];
|
|
4038
3155
|
if (!foreignKeyCol) {
|
|
4039
3156
|
throw new Error(`Foreign key column '${relation.foreignKeyOnTarget}' not found in target table. This might be a many-to-many relationship that requires a junction table. Consider using 'through' property or ensure the corresponding owning relation exists with junction table configuration.`);
|
|
4040
3157
|
}
|
|
4041
|
-
return Array.isArray(parentEntityId) ? inArray(foreignKeyCol, parentEntityId) : eq
|
|
3158
|
+
return Array.isArray(parentEntityId) ? inArray(foreignKeyCol, parentEntityId) : eq(foreignKeyCol, parentEntityId);
|
|
4042
3159
|
} else if (relation.direction === "inverse" && relation.cardinality === "many" && relation.inverseRelationName) {
|
|
4043
3160
|
throw new Error(`Inverse many-to-many relation '${relation.relationName}' requires a junction table. Either specify 'through' property or ensure the corresponding owning relation exists with junction table configuration.`);
|
|
4044
3161
|
} else if (relation.direction === "inverse" && relation.cardinality === "one" && relation.inverseRelationName) {
|
|
@@ -4048,7 +3165,7 @@ class DrizzleConditionBuilder {
|
|
|
4048
3165
|
throw new Error(`Auto-inferred foreign key column '${inferredForeignKeyName}' not found in target table for inverse relation '${relation.relationName}'. Please specify 'foreignKeyOnTarget' explicitly.`);
|
|
4049
3166
|
}
|
|
4050
3167
|
console.debug(`🔍 [DrizzleConditionBuilder] Auto-inferred foreign key '${inferredForeignKeyName}' for inverse relation '${relation.relationName}'`);
|
|
4051
|
-
return Array.isArray(parentEntityId) ? inArray(foreignKeyCol, parentEntityId) : eq
|
|
3168
|
+
return Array.isArray(parentEntityId) ? inArray(foreignKeyCol, parentEntityId) : eq(foreignKeyCol, parentEntityId);
|
|
4052
3169
|
} else {
|
|
4053
3170
|
throw new Error(`Relation '${relation.relationName}' lacks proper configuration. For many-to-many relations, use 'through' property. For simple relations, use 'localKey' or 'foreignKeyOnTarget'.`);
|
|
4054
3171
|
}
|
|
@@ -4079,7 +3196,10 @@ class DrizzleConditionBuilder {
|
|
|
4079
3196
|
if (p.type === "string" && !p.enum && p.isId !== "uuid") {
|
|
4080
3197
|
const fieldColumn = table[key];
|
|
4081
3198
|
if (fieldColumn) {
|
|
4082
|
-
|
|
3199
|
+
const supportsILike = fieldColumn instanceof PgVarchar || fieldColumn instanceof PgText || fieldColumn instanceof PgChar || fieldColumn && typeof fieldColumn === "object" && !("columnType" in fieldColumn);
|
|
3200
|
+
if (supportsILike) {
|
|
3201
|
+
searchConditions.push(ilike(fieldColumn, `%${searchString}%`));
|
|
3202
|
+
}
|
|
4083
3203
|
}
|
|
4084
3204
|
}
|
|
4085
3205
|
}
|
|
@@ -4089,7 +3209,7 @@ class DrizzleConditionBuilder {
|
|
|
4089
3209
|
* Build a unique field check condition
|
|
4090
3210
|
*/
|
|
4091
3211
|
static buildUniqueFieldCondition(fieldColumn, value, idColumn, excludeId) {
|
|
4092
|
-
const conditions = [eq
|
|
3212
|
+
const conditions = [eq(fieldColumn, value)];
|
|
4093
3213
|
if (excludeId && idColumn) {
|
|
4094
3214
|
conditions.push(sql`${idColumn} != ${excludeId}`);
|
|
4095
3215
|
}
|
|
@@ -4164,7 +3284,7 @@ class DrizzleConditionBuilder {
|
|
|
4164
3284
|
if (currentTable !== parentTable) {
|
|
4165
3285
|
throw new Error("Join path did not result in connecting to parent table");
|
|
4166
3286
|
}
|
|
4167
|
-
const allConditions = [eq
|
|
3287
|
+
const allConditions = [eq(parentIdColumn, parentEntityId)];
|
|
4168
3288
|
if (additionalFilters) {
|
|
4169
3289
|
allConditions.push(...additionalFilters);
|
|
4170
3290
|
}
|
|
@@ -4186,11 +3306,11 @@ class DrizzleConditionBuilder {
|
|
|
4186
3306
|
if (!junctionTargetCol) {
|
|
4187
3307
|
throw new Error(`Target column '${through.targetColumn}' not found in junction table '${through.table}'`);
|
|
4188
3308
|
}
|
|
4189
|
-
const baseConditions = [eq
|
|
3309
|
+
const baseConditions = [eq(junctionSourceCol, parentEntityId)];
|
|
4190
3310
|
if (additionalFilters && additionalFilters.length > 0) {
|
|
4191
3311
|
baseConditions.push(...additionalFilters);
|
|
4192
3312
|
}
|
|
4193
|
-
return baseCountQuery.innerJoin(junctionTable, eq
|
|
3313
|
+
return baseCountQuery.innerJoin(junctionTable, eq(targetIdColumn, junctionTargetCol)).where(and(...baseConditions));
|
|
4194
3314
|
}
|
|
4195
3315
|
/**
|
|
4196
3316
|
* Build inverse junction table conditions for count queries
|
|
@@ -4208,11 +3328,11 @@ class DrizzleConditionBuilder {
|
|
|
4208
3328
|
if (!junctionTargetCol) {
|
|
4209
3329
|
throw new Error(`Target column '${through.targetColumn}' not found in junction table '${through.table}'`);
|
|
4210
3330
|
}
|
|
4211
|
-
const baseConditions = [eq
|
|
3331
|
+
const baseConditions = [eq(junctionSourceCol, parentEntityId)];
|
|
4212
3332
|
if (additionalFilters && additionalFilters.length > 0) {
|
|
4213
3333
|
baseConditions.push(...additionalFilters);
|
|
4214
3334
|
}
|
|
4215
|
-
return baseCountQuery.innerJoin(junctionTable, eq
|
|
3335
|
+
return baseCountQuery.innerJoin(junctionTable, eq(targetIdColumn, junctionTargetCol)).where(and(...baseConditions));
|
|
4216
3336
|
}
|
|
4217
3337
|
/**
|
|
4218
3338
|
* Helper method to extract table names from columns
|
|
@@ -4552,6 +3672,31 @@ function serializePropertyToServer(value, property) {
|
|
|
4552
3672
|
return result;
|
|
4553
3673
|
}
|
|
4554
3674
|
return value;
|
|
3675
|
+
case "vector": {
|
|
3676
|
+
if (value instanceof Vector) {
|
|
3677
|
+
return value.value;
|
|
3678
|
+
}
|
|
3679
|
+
if (value && typeof value === "object" && "value" in value && Array.isArray(value.value)) {
|
|
3680
|
+
return value.value.map(Number);
|
|
3681
|
+
}
|
|
3682
|
+
if (Array.isArray(value)) {
|
|
3683
|
+
return value.map(Number);
|
|
3684
|
+
}
|
|
3685
|
+
return value;
|
|
3686
|
+
}
|
|
3687
|
+
case "binary":
|
|
3688
|
+
if (typeof value === "string") {
|
|
3689
|
+
if (value.startsWith("data:application/octet-stream;base64,")) {
|
|
3690
|
+
const base64Data = value.split(",")[1];
|
|
3691
|
+
if (base64Data) {
|
|
3692
|
+
return Buffer.from(base64Data, "base64");
|
|
3693
|
+
}
|
|
3694
|
+
}
|
|
3695
|
+
}
|
|
3696
|
+
if (Buffer.isBuffer(value)) {
|
|
3697
|
+
return value;
|
|
3698
|
+
}
|
|
3699
|
+
return value;
|
|
4555
3700
|
case "string":
|
|
4556
3701
|
if (typeof value === "string") {
|
|
4557
3702
|
if (value.startsWith("data:application/octet-stream;base64,")) {
|
|
@@ -4604,7 +3749,7 @@ async function parseDataFromServer(data, collection, db, registry) {
|
|
|
4604
3749
|
if (targetTable && currentEntityId) {
|
|
4605
3750
|
const foreignKeyColumn = targetTable[relation.foreignKeyOnTarget];
|
|
4606
3751
|
if (foreignKeyColumn) {
|
|
4607
|
-
const relatedEntities = await db.select().from(targetTable).where(eq
|
|
3752
|
+
const relatedEntities = await db.select().from(targetTable).where(eq(foreignKeyColumn, currentEntityId)).limit(relation.cardinality === "one" ? 1 : 100);
|
|
4608
3753
|
if (relatedEntities.length > 0) {
|
|
4609
3754
|
if (relation.cardinality === "one") {
|
|
4610
3755
|
const targetPks = getPrimaryKeys(targetCollection, registry);
|
|
@@ -4651,12 +3796,12 @@ async function parseDataFromServer(data, collection, db, registry) {
|
|
|
4651
3796
|
console.warn(`Join columns not found: ${fromColumn} -> ${toColumn}`);
|
|
4652
3797
|
break;
|
|
4653
3798
|
}
|
|
4654
|
-
query = query.innerJoin(joinTable, eq
|
|
3799
|
+
query = query.innerJoin(joinTable, eq(fromCol, toCol));
|
|
4655
3800
|
currentTable = joinTable;
|
|
4656
3801
|
}
|
|
4657
3802
|
if (pks.length === 1) {
|
|
4658
3803
|
const sourceIdField = sourceTable[pks[0].fieldName];
|
|
4659
|
-
query = query.where(eq
|
|
3804
|
+
query = query.where(eq(sourceIdField, currentEntityId));
|
|
4660
3805
|
} else {
|
|
4661
3806
|
console.warn(`Join path resolution for composite primary keys is not yet fully supported: ${collection.slug}`);
|
|
4662
3807
|
}
|
|
@@ -4664,7 +3809,7 @@ async function parseDataFromServer(data, collection, db, registry) {
|
|
|
4664
3809
|
let combinedWhere;
|
|
4665
3810
|
if (pks.length === 1) {
|
|
4666
3811
|
const sourceIdField = sourceTable[pks[0].fieldName];
|
|
4667
|
-
combinedWhere = DrizzleConditionBuilder.combineConditionsWithAnd([eq
|
|
3812
|
+
combinedWhere = DrizzleConditionBuilder.combineConditionsWithAnd([eq(sourceIdField, currentEntityId), ...additionalFilters].filter(Boolean));
|
|
4668
3813
|
}
|
|
4669
3814
|
const joinResults = await query.where(combinedWhere).limit(relation.cardinality === "one" ? 1 : 100);
|
|
4670
3815
|
if (joinResults.length > 0) {
|
|
@@ -4696,18 +3841,36 @@ function parsePropertyFromServer(value, property, collection, propertyKey) {
|
|
|
4696
3841
|
return value;
|
|
4697
3842
|
}
|
|
4698
3843
|
switch (property.type) {
|
|
3844
|
+
case "binary": {
|
|
3845
|
+
let buf = null;
|
|
3846
|
+
if (Buffer.isBuffer(value)) {
|
|
3847
|
+
buf = value;
|
|
3848
|
+
} else if (typeof value === "object" && value !== null) {
|
|
3849
|
+
const rawVal = value;
|
|
3850
|
+
if (rawVal.type === "Buffer" && Array.isArray(rawVal.data)) {
|
|
3851
|
+
buf = Buffer.from(rawVal.data);
|
|
3852
|
+
}
|
|
3853
|
+
}
|
|
3854
|
+
if (buf) {
|
|
3855
|
+
return `data:application/octet-stream;base64,${buf.toString("base64")}`;
|
|
3856
|
+
}
|
|
3857
|
+
return value;
|
|
3858
|
+
}
|
|
4699
3859
|
case "string": {
|
|
4700
3860
|
if (typeof value === "string") return value;
|
|
4701
|
-
let
|
|
3861
|
+
let isBuffer = false;
|
|
4702
3862
|
let buf = null;
|
|
4703
3863
|
if (Buffer.isBuffer(value)) {
|
|
4704
|
-
|
|
3864
|
+
isBuffer = true;
|
|
4705
3865
|
buf = value;
|
|
4706
|
-
} else if (typeof value === "object" && value !== null
|
|
4707
|
-
|
|
4708
|
-
|
|
3866
|
+
} else if (typeof value === "object" && value !== null) {
|
|
3867
|
+
const rawVal = value;
|
|
3868
|
+
if (rawVal.type === "Buffer" && Array.isArray(rawVal.data)) {
|
|
3869
|
+
isBuffer = true;
|
|
3870
|
+
buf = Buffer.from(rawVal.data);
|
|
3871
|
+
}
|
|
4709
3872
|
}
|
|
4710
|
-
if (
|
|
3873
|
+
if (isBuffer && buf) {
|
|
4711
3874
|
let isPrintable = true;
|
|
4712
3875
|
for (let i = 0; i < buf.length; i++) {
|
|
4713
3876
|
const b = buf[i];
|
|
@@ -4792,8 +3955,27 @@ function parsePropertyFromServer(value, property, collection, propertyKey) {
|
|
|
4792
3955
|
return isNaN(parsed) ? null : parsed;
|
|
4793
3956
|
}
|
|
4794
3957
|
return value;
|
|
4795
|
-
case "
|
|
4796
|
-
let
|
|
3958
|
+
case "vector": {
|
|
3959
|
+
let nums = [];
|
|
3960
|
+
if (typeof value === "string") {
|
|
3961
|
+
nums = value.slice(1, -1).split(",").map(Number);
|
|
3962
|
+
} else if (Array.isArray(value)) {
|
|
3963
|
+
nums = value.map(Number);
|
|
3964
|
+
} else if (value instanceof Vector) {
|
|
3965
|
+
nums = value.value;
|
|
3966
|
+
} else if (typeof value === "object" && value !== null && "value" in value) {
|
|
3967
|
+
const valObj = value;
|
|
3968
|
+
if (Array.isArray(valObj.value)) {
|
|
3969
|
+
nums = valObj.value.map(Number);
|
|
3970
|
+
}
|
|
3971
|
+
}
|
|
3972
|
+
return {
|
|
3973
|
+
__type: "Vector",
|
|
3974
|
+
value: nums
|
|
3975
|
+
};
|
|
3976
|
+
}
|
|
3977
|
+
case "date": {
|
|
3978
|
+
let date;
|
|
4797
3979
|
if (value instanceof Date) {
|
|
4798
3980
|
date = value;
|
|
4799
3981
|
} else if (typeof value === "string" || typeof value === "number") {
|
|
@@ -4811,16 +3993,19 @@ function parsePropertyFromServer(value, property, collection, propertyKey) {
|
|
|
4811
3993
|
return null;
|
|
4812
3994
|
}
|
|
4813
3995
|
default: {
|
|
4814
|
-
let
|
|
3996
|
+
let isBuffer = false;
|
|
4815
3997
|
let buf = null;
|
|
4816
3998
|
if (Buffer.isBuffer(value)) {
|
|
4817
|
-
|
|
3999
|
+
isBuffer = true;
|
|
4818
4000
|
buf = value;
|
|
4819
|
-
} else if (typeof value === "object" && value !== null
|
|
4820
|
-
|
|
4821
|
-
|
|
4001
|
+
} else if (typeof value === "object" && value !== null) {
|
|
4002
|
+
const rawVal = value;
|
|
4003
|
+
if (rawVal.type === "Buffer" && Array.isArray(rawVal.data)) {
|
|
4004
|
+
isBuffer = true;
|
|
4005
|
+
buf = Buffer.from(rawVal.data);
|
|
4006
|
+
}
|
|
4822
4007
|
}
|
|
4823
|
-
if (
|
|
4008
|
+
if (isBuffer && buf) {
|
|
4824
4009
|
let isPrintable = true;
|
|
4825
4010
|
for (let i = 0; i < buf.length; i++) {
|
|
4826
4011
|
const b = buf[i];
|
|
@@ -4915,11 +4100,11 @@ class RelationService {
|
|
|
4915
4100
|
if (!fromCol || !toCol) {
|
|
4916
4101
|
throw new Error(`Join columns not found: ${fromColumn} -> ${toColumn}`);
|
|
4917
4102
|
}
|
|
4918
|
-
query2 = query2.innerJoin(joinTable, eq
|
|
4103
|
+
query2 = query2.innerJoin(joinTable, eq(fromCol, toCol));
|
|
4919
4104
|
currentTable = joinTable;
|
|
4920
4105
|
}
|
|
4921
4106
|
const parentIdField = parentTable[getPrimaryKeys(parentCollection, this.registry)[0].fieldName];
|
|
4922
|
-
query2 = query2.where(eq
|
|
4107
|
+
query2 = query2.where(eq(parentIdField, parsedParentId));
|
|
4923
4108
|
if (options.limit) {
|
|
4924
4109
|
query2 = query2.limit(options.limit);
|
|
4925
4110
|
}
|
|
@@ -5038,7 +4223,7 @@ class RelationService {
|
|
|
5038
4223
|
if (!fromCol || !toCol) {
|
|
5039
4224
|
throw new Error(`Join columns not found: ${fromColumn} -> ${toColumn}`);
|
|
5040
4225
|
}
|
|
5041
|
-
query2 = query2.innerJoin(joinTable, eq
|
|
4226
|
+
query2 = query2.innerJoin(joinTable, eq(fromCol, toCol));
|
|
5042
4227
|
currentTable = joinTable;
|
|
5043
4228
|
}
|
|
5044
4229
|
const parentIdField = parentTable[getPrimaryKeys(parentCollection, this.registry)[0].fieldName];
|
|
@@ -5169,7 +4354,7 @@ class RelationService {
|
|
|
5169
4354
|
const fromCol = currentTable[fromColName];
|
|
5170
4355
|
const toCol = joinTable[toColName];
|
|
5171
4356
|
if (!fromCol || !toCol) throw new Error(`Join columns not found: ${fromColumn} -> ${toColumn}`);
|
|
5172
|
-
query2 = query2.innerJoin(joinTable, eq
|
|
4357
|
+
query2 = query2.innerJoin(joinTable, eq(fromCol, toCol));
|
|
5173
4358
|
currentTable = joinTable;
|
|
5174
4359
|
}
|
|
5175
4360
|
const parentIdField = parentTable[getPrimaryKeys(parentCollection, this.registry)[0].fieldName];
|
|
@@ -5204,7 +4389,7 @@ class RelationService {
|
|
|
5204
4389
|
console.warn(`[batchFetchRelatedEntitiesMany] Junction columns not found in '${relation.through.table}'`);
|
|
5205
4390
|
return /* @__PURE__ */ new Map();
|
|
5206
4391
|
}
|
|
5207
|
-
const query2 = this.db.select().from(junctionTable).innerJoin(targetTable, eq
|
|
4392
|
+
const query2 = this.db.select().from(junctionTable).innerJoin(targetTable, eq(targetJunctionCol, targetIdField)).where(inArray(sourceJunctionCol, parsedParentIds));
|
|
5208
4393
|
const results2 = await query2;
|
|
5209
4394
|
const resultMap2 = /* @__PURE__ */ new Map();
|
|
5210
4395
|
const targetTableName = getTableName(targetCollection);
|
|
@@ -5302,7 +4487,7 @@ class RelationService {
|
|
|
5302
4487
|
const parentIdInfo = parentPks[0];
|
|
5303
4488
|
const parsedParentIdObj = parseIdValues(entityId, parentPks);
|
|
5304
4489
|
const parsedParentId = parsedParentIdObj[parentIdInfo.fieldName];
|
|
5305
|
-
await tx.delete(junctionTable).where(eq
|
|
4490
|
+
await tx.delete(junctionTable).where(eq(sourceJunctionColumn, parsedParentId));
|
|
5306
4491
|
if (targetEntityIds.length > 0) {
|
|
5307
4492
|
const targetPks = getPrimaryKeys(targetCollection, this.registry);
|
|
5308
4493
|
const targetIdInfo = targetPks[0];
|
|
@@ -5331,7 +4516,7 @@ class RelationService {
|
|
|
5331
4516
|
const parentIdInfo = parentPks[0];
|
|
5332
4517
|
const parsedParentIdObj = parseIdValues(entityId, parentPks);
|
|
5333
4518
|
const parsedParentId = parsedParentIdObj[parentIdInfo.fieldName];
|
|
5334
|
-
await tx.delete(junctionTable).where(eq
|
|
4519
|
+
await tx.delete(junctionTable).where(eq(sourceJunctionColumn, parsedParentId));
|
|
5335
4520
|
if (targetEntityIds.length > 0) {
|
|
5336
4521
|
const targetPks = getPrimaryKeys(targetCollection, this.registry);
|
|
5337
4522
|
const targetIdInfo = targetPks[0];
|
|
@@ -5364,14 +4549,14 @@ class RelationService {
|
|
|
5364
4549
|
const parsedTargetIds = targetEntityIds.map((id) => parseIdValues(id, targetPks)[targetIdInfo.fieldName]);
|
|
5365
4550
|
await tx.update(targetTable).set({
|
|
5366
4551
|
[relation.foreignKeyOnTarget]: null
|
|
5367
|
-
}).where(and(eq
|
|
4552
|
+
}).where(and(eq(fkCol, parsedParentId), sql`${targetIdCol} NOT IN (${sql.join(parsedTargetIds)})`));
|
|
5368
4553
|
await tx.update(targetTable).set({
|
|
5369
4554
|
[relation.foreignKeyOnTarget]: parsedParentId
|
|
5370
4555
|
}).where(inArray(targetIdCol, parsedTargetIds));
|
|
5371
4556
|
} else {
|
|
5372
4557
|
await tx.update(targetTable).set({
|
|
5373
4558
|
[relation.foreignKeyOnTarget]: null
|
|
5374
|
-
}).where(eq
|
|
4559
|
+
}).where(eq(fkCol, parsedParentId));
|
|
5375
4560
|
}
|
|
5376
4561
|
} else {
|
|
5377
4562
|
console.warn(`Many relation '${key}' in collection '${collection.slug}' lacks write configuration and will be skipped during save.`);
|
|
@@ -5430,17 +4615,17 @@ class RelationService {
|
|
|
5430
4615
|
if (newValue === null || newValue === void 0) {
|
|
5431
4616
|
await tx.update(targetTable).set({
|
|
5432
4617
|
[relation.foreignKeyOnTarget]: null
|
|
5433
|
-
}).where(eq
|
|
4618
|
+
}).where(eq(foreignKeyColumn, parsedSourceId));
|
|
5434
4619
|
} else {
|
|
5435
4620
|
const parsedNewTargetIdObj = parseIdValues(newValue, targetPks);
|
|
5436
4621
|
const parsedNewTargetId = parsedNewTargetIdObj[targetIdInfo.fieldName];
|
|
5437
4622
|
const targetIdField = targetTable[targetIdInfo.fieldName];
|
|
5438
4623
|
await tx.update(targetTable).set({
|
|
5439
4624
|
[relation.foreignKeyOnTarget]: null
|
|
5440
|
-
}).where(eq
|
|
4625
|
+
}).where(eq(foreignKeyColumn, parsedSourceId));
|
|
5441
4626
|
await tx.update(targetTable).set({
|
|
5442
4627
|
[relation.foreignKeyOnTarget]: parsedSourceId
|
|
5443
|
-
}).where(eq
|
|
4628
|
+
}).where(eq(targetIdField, parsedNewTargetId));
|
|
5444
4629
|
}
|
|
5445
4630
|
} catch (e) {
|
|
5446
4631
|
console.warn(`Failed to update inverse relation '${relation.relationName}':`, e);
|
|
@@ -5495,7 +4680,7 @@ class RelationService {
|
|
|
5495
4680
|
const sourceIdInfo = sourcePks[0];
|
|
5496
4681
|
const parsedSourceIdObj = parseIdValues(sourceEntityId, sourcePks);
|
|
5497
4682
|
const parsedSourceId = parsedSourceIdObj[sourceIdInfo.fieldName];
|
|
5498
|
-
await tx.delete(junctionTable).where(eq
|
|
4683
|
+
await tx.delete(junctionTable).where(eq(sourceJunctionColumn, parsedSourceId));
|
|
5499
4684
|
if (newValue && Array.isArray(newValue) && newValue.length > 0) {
|
|
5500
4685
|
const targetPks = getPrimaryKeys(targetCollection, this.registry);
|
|
5501
4686
|
const targetIdInfo = targetPks[0];
|
|
@@ -5546,7 +4731,7 @@ class RelationService {
|
|
|
5546
4731
|
const sourceIdInfo = sourcePks[0];
|
|
5547
4732
|
const parsedSourceIdObj = parseIdValues(sourceEntityId, sourcePks);
|
|
5548
4733
|
const parsedSourceId = parsedSourceIdObj[sourceIdInfo.fieldName];
|
|
5549
|
-
await tx.delete(junctionTable).where(eq
|
|
4734
|
+
await tx.delete(junctionTable).where(eq(sourceJunctionColumn, parsedSourceId));
|
|
5550
4735
|
if (newValue && Array.isArray(newValue) && newValue.length > 0) {
|
|
5551
4736
|
const targetPks = getPrimaryKeys(targetCollection, this.registry);
|
|
5552
4737
|
const targetIdInfo = targetPks[0];
|
|
@@ -5601,14 +4786,14 @@ class RelationService {
|
|
|
5601
4786
|
}
|
|
5602
4787
|
const parentRows = await tx.select({
|
|
5603
4788
|
val: parentSourceCol
|
|
5604
|
-
}).from(parentTable).where(eq
|
|
4789
|
+
}).from(parentTable).where(eq(parentIdCol, parsedParentId)).limit(1);
|
|
5605
4790
|
if (parentRows.length === 0) continue;
|
|
5606
4791
|
const parentFKValue = parentRows[0].val;
|
|
5607
4792
|
if (newTargetId === null || newTargetId === void 0) {
|
|
5608
4793
|
if (parentFKValue !== null && parentFKValue !== void 0) {
|
|
5609
4794
|
await tx.update(targetTable).set({
|
|
5610
4795
|
[targetFKColName]: null
|
|
5611
|
-
}).where(eq
|
|
4796
|
+
}).where(eq(targetFKCol, String(parentFKValue)));
|
|
5612
4797
|
}
|
|
5613
4798
|
continue;
|
|
5614
4799
|
}
|
|
@@ -5617,14 +4802,14 @@ class RelationService {
|
|
|
5617
4802
|
if (parentFKValue !== null && parentFKValue !== void 0) {
|
|
5618
4803
|
await tx.update(targetTable).set({
|
|
5619
4804
|
[targetFKColName]: null
|
|
5620
|
-
}).where(eq
|
|
4805
|
+
}).where(eq(targetFKCol, String(parentFKValue)));
|
|
5621
4806
|
} else {
|
|
5622
4807
|
console.warn(`Cannot set joinPath relation '${relation.relationName}' because parent FK value is null/undefined`);
|
|
5623
4808
|
continue;
|
|
5624
4809
|
}
|
|
5625
4810
|
await tx.update(targetTable).set({
|
|
5626
4811
|
[targetFKColName]: parentFKValue
|
|
5627
|
-
}).where(eq
|
|
4812
|
+
}).where(eq(targetIdCol, parsedTargetId));
|
|
5628
4813
|
}
|
|
5629
4814
|
}
|
|
5630
4815
|
/**
|
|
@@ -6009,7 +5194,7 @@ class EntityFetchService {
|
|
|
6009
5194
|
const collection = getCollectionByPath(collectionPath, this.registry);
|
|
6010
5195
|
const searchConditions = DrizzleConditionBuilder.buildSearchConditions(options.searchString, collection.properties, table);
|
|
6011
5196
|
if (searchConditions.length === 0) {
|
|
6012
|
-
queryOpts.where = and(eq
|
|
5197
|
+
queryOpts.where = and(eq(idField, -99999999));
|
|
6013
5198
|
return queryOpts;
|
|
6014
5199
|
}
|
|
6015
5200
|
allConditions.push(DrizzleConditionBuilder.combineConditionsWithOr(searchConditions));
|
|
@@ -6056,9 +5241,9 @@ class EntityFetchService {
|
|
|
6056
5241
|
const startAfterId = cursor.id ?? cursor[idInfo.fieldName];
|
|
6057
5242
|
if (startAfterOrderValue !== void 0 && startAfterId !== void 0) {
|
|
6058
5243
|
if (options.order === "asc") {
|
|
6059
|
-
return [or(gt(orderByField, startAfterOrderValue), and(eq
|
|
5244
|
+
return [or(gt(orderByField, startAfterOrderValue), and(eq(orderByField, startAfterOrderValue), gt(idField, startAfterId)))];
|
|
6060
5245
|
} else {
|
|
6061
|
-
return [or(lt(orderByField, startAfterOrderValue), and(eq
|
|
5246
|
+
return [or(lt(orderByField, startAfterOrderValue), and(eq(orderByField, startAfterOrderValue), lt(idField, startAfterId)))];
|
|
6062
5247
|
}
|
|
6063
5248
|
}
|
|
6064
5249
|
}
|
|
@@ -6092,7 +5277,7 @@ class EntityFetchService {
|
|
|
6092
5277
|
try {
|
|
6093
5278
|
const withConfig = this.buildWithConfig(collection);
|
|
6094
5279
|
const row = await qb.findFirst({
|
|
6095
|
-
where: eq
|
|
5280
|
+
where: eq(idField, parsedId),
|
|
6096
5281
|
with: withConfig
|
|
6097
5282
|
});
|
|
6098
5283
|
if (!row) return void 0;
|
|
@@ -6107,7 +5292,7 @@ class EntityFetchService {
|
|
|
6107
5292
|
console.warn(`[EntityFetchService] db.query.findFirst failed for ${collectionPath}, falling back to db.select:`, e);
|
|
6108
5293
|
}
|
|
6109
5294
|
}
|
|
6110
|
-
const result = await this.db.select().from(table).where(eq
|
|
5295
|
+
const result = await this.db.select().from(table).where(eq(idField, parsedId)).limit(1);
|
|
6111
5296
|
if (result.length === 0) return void 0;
|
|
6112
5297
|
const raw = result[0];
|
|
6113
5298
|
const values = await parseDataFromServer(raw, collection, this.db, this.registry);
|
|
@@ -6511,7 +5696,7 @@ class EntityFetchService {
|
|
|
6511
5696
|
try {
|
|
6512
5697
|
const withConfig = include && include.length > 0 ? this.buildWithConfig(collection, include) : void 0;
|
|
6513
5698
|
const row = await qb.findFirst({
|
|
6514
|
-
where: eq
|
|
5699
|
+
where: eq(idField, parsedId),
|
|
6515
5700
|
...withConfig ? {
|
|
6516
5701
|
with: withConfig
|
|
6517
5702
|
} : {}
|
|
@@ -6528,7 +5713,7 @@ class EntityFetchService {
|
|
|
6528
5713
|
console.warn(`[fetchEntityForRest] db.query.findFirst failed for ${collectionPath}, falling back:`, e);
|
|
6529
5714
|
}
|
|
6530
5715
|
}
|
|
6531
|
-
const result = await this.db.select().from(table).where(eq
|
|
5716
|
+
const result = await this.db.select().from(table).where(eq(idField, parsedId)).limit(1);
|
|
6532
5717
|
if (result.length === 0) return null;
|
|
6533
5718
|
const raw = result[0];
|
|
6534
5719
|
const flatEntity = {
|
|
@@ -6737,7 +5922,7 @@ class EntityPersistService {
|
|
|
6737
5922
|
}
|
|
6738
5923
|
const parsedIdObj = parseIdValues(entityId, idInfoArray);
|
|
6739
5924
|
const parsedId = parsedIdObj[idInfo.fieldName];
|
|
6740
|
-
await this.db.delete(table).where(eq
|
|
5925
|
+
await this.db.delete(table).where(eq(idField, parsedId));
|
|
6741
5926
|
}
|
|
6742
5927
|
/**
|
|
6743
5928
|
* Save an entity (create or update)
|
|
@@ -6861,7 +6046,7 @@ class EntityPersistService {
|
|
|
6861
6046
|
const conditions = [];
|
|
6862
6047
|
for (const info of idInfoArray) {
|
|
6863
6048
|
const field = table[info.fieldName];
|
|
6864
|
-
conditions.push(eq
|
|
6049
|
+
conditions.push(eq(field, idValues[info.fieldName]));
|
|
6865
6050
|
}
|
|
6866
6051
|
await updateQuery.where(and(...conditions));
|
|
6867
6052
|
}
|
|
@@ -7694,23 +6879,33 @@ class PostgresBackendDriver {
|
|
|
7694
6879
|
client: this.client
|
|
7695
6880
|
};
|
|
7696
6881
|
if (callbacks?.beforeDelete || propertyCallbacks?.beforeDelete) {
|
|
6882
|
+
let preventDefault = false;
|
|
7697
6883
|
if (callbacks?.beforeDelete) {
|
|
7698
|
-
await callbacks.beforeDelete({
|
|
6884
|
+
const result = await callbacks.beforeDelete({
|
|
7699
6885
|
collection: resolvedCollection,
|
|
7700
6886
|
path: entity.path,
|
|
7701
6887
|
entityId: entity.id,
|
|
7702
6888
|
entity,
|
|
7703
6889
|
context: contextForCallback
|
|
7704
6890
|
});
|
|
6891
|
+
if (result === false) {
|
|
6892
|
+
preventDefault = true;
|
|
6893
|
+
}
|
|
7705
6894
|
}
|
|
7706
6895
|
if (propertyCallbacks?.beforeDelete) {
|
|
7707
|
-
await propertyCallbacks.beforeDelete({
|
|
6896
|
+
const result = await propertyCallbacks.beforeDelete({
|
|
7708
6897
|
collection: resolvedCollection,
|
|
7709
6898
|
path: entity.path,
|
|
7710
6899
|
entityId: entity.id,
|
|
7711
6900
|
entity,
|
|
7712
6901
|
context: contextForCallback
|
|
7713
6902
|
});
|
|
6903
|
+
if (result === false) {
|
|
6904
|
+
preventDefault = true;
|
|
6905
|
+
}
|
|
6906
|
+
}
|
|
6907
|
+
if (preventDefault) {
|
|
6908
|
+
return;
|
|
7714
6909
|
}
|
|
7715
6910
|
}
|
|
7716
6911
|
await this.entityService.deleteEntity(entity.path, entity.id, entity.databaseId || resolvedCollection?.databaseId);
|
|
@@ -7783,7 +6978,17 @@ class PostgresBackendDriver {
|
|
|
7783
6978
|
}
|
|
7784
6979
|
const targetDb = this.getTargetDb(options?.database);
|
|
7785
6980
|
try {
|
|
7786
|
-
|
|
6981
|
+
let needsRoleSwitch = false;
|
|
6982
|
+
if (options?.role && process.env.DISABLE_DB_ROLE_SWITCHING !== "true") {
|
|
6983
|
+
try {
|
|
6984
|
+
const currentRoleResult = await targetDb.execute(sql.raw("SELECT current_user AS role"));
|
|
6985
|
+
const currentRole = currentRoleResult.rows?.[0]?.role;
|
|
6986
|
+
needsRoleSwitch = !!currentRole && currentRole !== options.role;
|
|
6987
|
+
} catch {
|
|
6988
|
+
needsRoleSwitch = true;
|
|
6989
|
+
}
|
|
6990
|
+
}
|
|
6991
|
+
if (needsRoleSwitch && options?.role) {
|
|
7787
6992
|
const safeRole = options.role.replace(/"/g, '""');
|
|
7788
6993
|
return await targetDb.transaction(async (tx) => {
|
|
7789
6994
|
await tx.execute(sql.raw(`SET LOCAL ROLE "${safeRole}"`));
|
|
@@ -7821,7 +7026,7 @@ class PostgresBackendDriver {
|
|
|
7821
7026
|
return databases;
|
|
7822
7027
|
}
|
|
7823
7028
|
async fetchAvailableRoles() {
|
|
7824
|
-
const result = await this.executeSql("SELECT rolname FROM pg_roles;");
|
|
7029
|
+
const result = await this.executeSql("SELECT rolname FROM pg_roles WHERE pg_has_role(current_user, rolname, 'member') ORDER BY rolname;");
|
|
7825
7030
|
return result.map((r) => r.rolname);
|
|
7826
7031
|
}
|
|
7827
7032
|
async fetchCurrentDatabase() {
|
|
@@ -7990,6 +7195,21 @@ class AuthenticatedPostgresBackendDriver {
|
|
|
7990
7195
|
* Typed admin capabilities — delegates to the base driver.
|
|
7991
7196
|
*/
|
|
7992
7197
|
admin;
|
|
7198
|
+
get restFetchService() {
|
|
7199
|
+
if (!this.delegate.restFetchService) return void 0;
|
|
7200
|
+
return {
|
|
7201
|
+
fetchCollectionForRest: async (collectionPath, options, include) => {
|
|
7202
|
+
return this.withTransaction(async (delegate) => {
|
|
7203
|
+
return delegate.restFetchService.fetchCollectionForRest(collectionPath, options, include);
|
|
7204
|
+
});
|
|
7205
|
+
},
|
|
7206
|
+
fetchEntityForRest: async (collectionPath, entityId, include, databaseId) => {
|
|
7207
|
+
return this.withTransaction(async (delegate) => {
|
|
7208
|
+
return delegate.restFetchService.fetchEntityForRest(collectionPath, entityId, include, databaseId);
|
|
7209
|
+
});
|
|
7210
|
+
}
|
|
7211
|
+
};
|
|
7212
|
+
}
|
|
7993
7213
|
async withTransaction(operation) {
|
|
7994
7214
|
const pendingNotifications = [];
|
|
7995
7215
|
const result = await this.delegate.db.transaction(async (tx) => {
|
|
@@ -8144,113 +7364,140 @@ class DatabasePoolManager {
|
|
|
8144
7364
|
this.pools.clear();
|
|
8145
7365
|
}
|
|
8146
7366
|
}
|
|
8147
|
-
|
|
8148
|
-
const
|
|
8149
|
-
|
|
8150
|
-
|
|
8151
|
-
|
|
8152
|
-
|
|
8153
|
-
|
|
8154
|
-
|
|
8155
|
-
|
|
8156
|
-
|
|
8157
|
-
|
|
8158
|
-
|
|
8159
|
-
|
|
8160
|
-
|
|
8161
|
-
|
|
8162
|
-
|
|
8163
|
-
|
|
8164
|
-
|
|
8165
|
-
|
|
8166
|
-
|
|
8167
|
-
|
|
8168
|
-
|
|
8169
|
-
|
|
8170
|
-
})
|
|
8171
|
-
|
|
8172
|
-
|
|
8173
|
-
|
|
8174
|
-
|
|
8175
|
-
|
|
8176
|
-
|
|
8177
|
-
|
|
8178
|
-
|
|
8179
|
-
|
|
8180
|
-
|
|
8181
|
-
|
|
8182
|
-
|
|
8183
|
-
})
|
|
8184
|
-
|
|
8185
|
-
|
|
8186
|
-
|
|
8187
|
-
|
|
8188
|
-
|
|
8189
|
-
|
|
8190
|
-
|
|
8191
|
-
|
|
8192
|
-
|
|
8193
|
-
|
|
8194
|
-
|
|
8195
|
-
|
|
8196
|
-
|
|
8197
|
-
})
|
|
8198
|
-
|
|
8199
|
-
|
|
8200
|
-
|
|
8201
|
-
|
|
8202
|
-
})
|
|
8203
|
-
|
|
8204
|
-
|
|
8205
|
-
|
|
8206
|
-
|
|
8207
|
-
|
|
8208
|
-
|
|
8209
|
-
|
|
8210
|
-
|
|
8211
|
-
|
|
8212
|
-
|
|
8213
|
-
|
|
8214
|
-
},
|
|
8215
|
-
|
|
8216
|
-
|
|
8217
|
-
|
|
8218
|
-
|
|
8219
|
-
|
|
8220
|
-
|
|
8221
|
-
})
|
|
8222
|
-
|
|
8223
|
-
|
|
8224
|
-
|
|
8225
|
-
|
|
8226
|
-
|
|
8227
|
-
|
|
8228
|
-
|
|
8229
|
-
|
|
8230
|
-
|
|
8231
|
-
|
|
8232
|
-
|
|
8233
|
-
|
|
8234
|
-
|
|
8235
|
-
|
|
8236
|
-
|
|
8237
|
-
|
|
8238
|
-
|
|
8239
|
-
|
|
8240
|
-
})
|
|
8241
|
-
|
|
8242
|
-
|
|
8243
|
-
|
|
8244
|
-
|
|
8245
|
-
|
|
8246
|
-
|
|
8247
|
-
|
|
8248
|
-
|
|
8249
|
-
|
|
8250
|
-
|
|
8251
|
-
|
|
8252
|
-
|
|
8253
|
-
|
|
7367
|
+
function createAuthSchema(rolesSchemaName = "rebase", usersSchemaName = "rebase") {
|
|
7368
|
+
const rolesSchema = rolesSchemaName === "public" ? null : pgSchema(rolesSchemaName);
|
|
7369
|
+
const usersSchema2 = usersSchemaName === "public" ? null : pgSchema(usersSchemaName);
|
|
7370
|
+
const rolesTableCreator = rolesSchema ? rolesSchema.table.bind(rolesSchema) : pgTable;
|
|
7371
|
+
const usersTableCreator = usersSchema2 ? usersSchema2.table.bind(usersSchema2) : pgTable;
|
|
7372
|
+
const users2 = usersTableCreator("users", {
|
|
7373
|
+
id: uuid("id").defaultRandom().primaryKey(),
|
|
7374
|
+
email: varchar("email", {
|
|
7375
|
+
length: 255
|
|
7376
|
+
}).notNull().unique(),
|
|
7377
|
+
passwordHash: varchar("password_hash", {
|
|
7378
|
+
length: 255
|
|
7379
|
+
}),
|
|
7380
|
+
// NULL for OAuth-only users
|
|
7381
|
+
displayName: varchar("display_name", {
|
|
7382
|
+
length: 255
|
|
7383
|
+
}),
|
|
7384
|
+
photoUrl: varchar("photo_url", {
|
|
7385
|
+
length: 500
|
|
7386
|
+
}),
|
|
7387
|
+
emailVerified: boolean("email_verified").default(false).notNull(),
|
|
7388
|
+
emailVerificationToken: varchar("email_verification_token", {
|
|
7389
|
+
length: 255
|
|
7390
|
+
}),
|
|
7391
|
+
emailVerificationSentAt: timestamp("email_verification_sent_at"),
|
|
7392
|
+
metadata: jsonb("metadata").$type().default({}).notNull(),
|
|
7393
|
+
createdAt: timestamp("created_at").defaultNow().notNull(),
|
|
7394
|
+
updatedAt: timestamp("updated_at").defaultNow().notNull()
|
|
7395
|
+
});
|
|
7396
|
+
const roles2 = rolesTableCreator("roles", {
|
|
7397
|
+
id: varchar("id", {
|
|
7398
|
+
length: 50
|
|
7399
|
+
}).primaryKey(),
|
|
7400
|
+
// 'admin', 'editor', 'viewer'
|
|
7401
|
+
name: varchar("name", {
|
|
7402
|
+
length: 100
|
|
7403
|
+
}).notNull(),
|
|
7404
|
+
isAdmin: boolean("is_admin").default(false).notNull(),
|
|
7405
|
+
defaultPermissions: jsonb("default_permissions").$type(),
|
|
7406
|
+
collectionPermissions: jsonb("collection_permissions").$type(),
|
|
7407
|
+
config: jsonb("config").$type()
|
|
7408
|
+
});
|
|
7409
|
+
const userRoles2 = rolesTableCreator("user_roles", {
|
|
7410
|
+
userId: uuid("user_id").notNull().references(() => users2.id, {
|
|
7411
|
+
onDelete: "cascade"
|
|
7412
|
+
}),
|
|
7413
|
+
roleId: varchar("role_id", {
|
|
7414
|
+
length: 50
|
|
7415
|
+
}).notNull().references(() => roles2.id, {
|
|
7416
|
+
onDelete: "cascade"
|
|
7417
|
+
})
|
|
7418
|
+
}, (table) => ({
|
|
7419
|
+
pk: primaryKey({
|
|
7420
|
+
columns: [table.userId, table.roleId]
|
|
7421
|
+
})
|
|
7422
|
+
}));
|
|
7423
|
+
const refreshTokens2 = rolesTableCreator("refresh_tokens", {
|
|
7424
|
+
id: uuid("id").defaultRandom().primaryKey(),
|
|
7425
|
+
userId: uuid("user_id").notNull().references(() => users2.id, {
|
|
7426
|
+
onDelete: "cascade"
|
|
7427
|
+
}),
|
|
7428
|
+
tokenHash: varchar("token_hash", {
|
|
7429
|
+
length: 255
|
|
7430
|
+
}).notNull().unique(),
|
|
7431
|
+
expiresAt: timestamp("expires_at").notNull(),
|
|
7432
|
+
userAgent: varchar("user_agent", {
|
|
7433
|
+
length: 500
|
|
7434
|
+
}),
|
|
7435
|
+
ipAddress: varchar("ip_address", {
|
|
7436
|
+
length: 45
|
|
7437
|
+
}),
|
|
7438
|
+
createdAt: timestamp("created_at").defaultNow().notNull()
|
|
7439
|
+
}, (table) => ({
|
|
7440
|
+
uniqueDeviceSession: unique("unique_device_session").on(table.userId, table.userAgent, table.ipAddress)
|
|
7441
|
+
}));
|
|
7442
|
+
const passwordResetTokens2 = rolesTableCreator("password_reset_tokens", {
|
|
7443
|
+
id: uuid("id").defaultRandom().primaryKey(),
|
|
7444
|
+
userId: uuid("user_id").notNull().references(() => users2.id, {
|
|
7445
|
+
onDelete: "cascade"
|
|
7446
|
+
}),
|
|
7447
|
+
tokenHash: varchar("token_hash", {
|
|
7448
|
+
length: 255
|
|
7449
|
+
}).notNull().unique(),
|
|
7450
|
+
expiresAt: timestamp("expires_at").notNull(),
|
|
7451
|
+
usedAt: timestamp("used_at"),
|
|
7452
|
+
createdAt: timestamp("created_at").defaultNow().notNull()
|
|
7453
|
+
});
|
|
7454
|
+
const appConfig2 = rolesTableCreator("app_config", {
|
|
7455
|
+
key: varchar("key", {
|
|
7456
|
+
length: 100
|
|
7457
|
+
}).primaryKey(),
|
|
7458
|
+
value: jsonb("value").notNull(),
|
|
7459
|
+
updatedAt: timestamp("updated_at").defaultNow().notNull()
|
|
7460
|
+
});
|
|
7461
|
+
const userIdentities2 = rolesTableCreator("user_identities", {
|
|
7462
|
+
id: uuid("id").defaultRandom().primaryKey(),
|
|
7463
|
+
userId: uuid("user_id").notNull().references(() => users2.id, {
|
|
7464
|
+
onDelete: "cascade"
|
|
7465
|
+
}),
|
|
7466
|
+
provider: varchar("provider", {
|
|
7467
|
+
length: 50
|
|
7468
|
+
}).notNull(),
|
|
7469
|
+
// e.g. 'google', 'linkedin'
|
|
7470
|
+
providerId: varchar("provider_id", {
|
|
7471
|
+
length: 255
|
|
7472
|
+
}).notNull(),
|
|
7473
|
+
profileData: jsonb("profile_data"),
|
|
7474
|
+
createdAt: timestamp("created_at").defaultNow().notNull(),
|
|
7475
|
+
updatedAt: timestamp("updated_at").defaultNow().notNull()
|
|
7476
|
+
}, (table) => ({
|
|
7477
|
+
uniqueProviderId: unique("unique_provider_id").on(table.provider, table.providerId)
|
|
7478
|
+
}));
|
|
7479
|
+
return {
|
|
7480
|
+
rolesSchema,
|
|
7481
|
+
usersSchema: usersSchema2,
|
|
7482
|
+
users: users2,
|
|
7483
|
+
roles: roles2,
|
|
7484
|
+
userRoles: userRoles2,
|
|
7485
|
+
refreshTokens: refreshTokens2,
|
|
7486
|
+
passwordResetTokens: passwordResetTokens2,
|
|
7487
|
+
appConfig: appConfig2,
|
|
7488
|
+
userIdentities: userIdentities2
|
|
7489
|
+
};
|
|
7490
|
+
}
|
|
7491
|
+
const defaultAuthSchema = createAuthSchema("rebase", "rebase");
|
|
7492
|
+
const rebaseSchema = defaultAuthSchema.rolesSchema;
|
|
7493
|
+
const usersSchema = defaultAuthSchema.usersSchema;
|
|
7494
|
+
const users = defaultAuthSchema.users;
|
|
7495
|
+
const roles = defaultAuthSchema.roles;
|
|
7496
|
+
const userRoles = defaultAuthSchema.userRoles;
|
|
7497
|
+
const refreshTokens = defaultAuthSchema.refreshTokens;
|
|
7498
|
+
const passwordResetTokens = defaultAuthSchema.passwordResetTokens;
|
|
7499
|
+
const appConfig = defaultAuthSchema.appConfig;
|
|
7500
|
+
const userIdentities = defaultAuthSchema.userIdentities;
|
|
8254
7501
|
const usersRelations = relations(users, ({
|
|
8255
7502
|
many
|
|
8256
7503
|
}) => ({
|
|
@@ -8433,6 +7680,15 @@ const getDrizzleColumn = (propName, prop, collection, collections) => {
|
|
|
8433
7680
|
}
|
|
8434
7681
|
break;
|
|
8435
7682
|
}
|
|
7683
|
+
case "vector": {
|
|
7684
|
+
const vp = prop;
|
|
7685
|
+
columnDefinition = `vector("${colName}", { dimensions: ${vp.dimensions} })`;
|
|
7686
|
+
break;
|
|
7687
|
+
}
|
|
7688
|
+
case "binary": {
|
|
7689
|
+
columnDefinition = `customType({ dataType() { return 'bytea'; } })("${colName}")`;
|
|
7690
|
+
break;
|
|
7691
|
+
}
|
|
8436
7692
|
case "relation": {
|
|
8437
7693
|
const refProp = prop;
|
|
8438
7694
|
const resolvedRelations = resolveCollectionRelations(collection);
|
|
@@ -8499,7 +7755,7 @@ const getDrizzleColumn = (propName, prop, collection, collections) => {
|
|
|
8499
7755
|
return ` ${propName}: ${columnDefinition}`;
|
|
8500
7756
|
};
|
|
8501
7757
|
const resolveRawSql = (expression) => {
|
|
8502
|
-
const resolved = expression.replace(/\{(\w+)\}/g, (_, col) =>
|
|
7758
|
+
const resolved = expression.replace(/\{(\w+)\}/g, (_, col) => col);
|
|
8503
7759
|
return `sql\`${resolved}\``;
|
|
8504
7760
|
};
|
|
8505
7761
|
const wrapWithRoleCheck = (clause, roles2) => {
|
|
@@ -8511,7 +7767,7 @@ const unwrapSql = (sqlExpr) => {
|
|
|
8511
7767
|
const match = sqlExpr.match(/^sql`(.*)`$/s);
|
|
8512
7768
|
return match ? match[1] : sqlExpr;
|
|
8513
7769
|
};
|
|
8514
|
-
const buildUsingClause = (rule) => {
|
|
7770
|
+
const buildUsingClause = (rule, collection) => {
|
|
8515
7771
|
if (rule.using) {
|
|
8516
7772
|
return resolveRawSql(rule.using);
|
|
8517
7773
|
}
|
|
@@ -8519,15 +7775,17 @@ const buildUsingClause = (rule) => {
|
|
|
8519
7775
|
return "sql`true`";
|
|
8520
7776
|
}
|
|
8521
7777
|
if (rule.ownerField) {
|
|
8522
|
-
|
|
7778
|
+
const prop = collection.properties?.[rule.ownerField];
|
|
7779
|
+
const colName = resolveColumnName(rule.ownerField, prop);
|
|
7780
|
+
return `sql\`${colName} = auth.uid()\``;
|
|
8523
7781
|
}
|
|
8524
7782
|
return null;
|
|
8525
7783
|
};
|
|
8526
|
-
const buildWithCheckClause = (rule) => {
|
|
7784
|
+
const buildWithCheckClause = (rule, collection) => {
|
|
8527
7785
|
if (rule.withCheck) {
|
|
8528
7786
|
return resolveRawSql(rule.withCheck);
|
|
8529
7787
|
}
|
|
8530
|
-
return buildUsingClause(rule);
|
|
7788
|
+
return buildUsingClause(rule, collection);
|
|
8531
7789
|
};
|
|
8532
7790
|
const getPolicyNameHash = (rule) => {
|
|
8533
7791
|
const data = JSON.stringify({
|
|
@@ -8543,21 +7801,22 @@ const getPolicyNameHash = (rule) => {
|
|
|
8543
7801
|
});
|
|
8544
7802
|
return createHash("sha1").update(data).digest("hex").substring(0, 7);
|
|
8545
7803
|
};
|
|
8546
|
-
const generatePolicyCode = (
|
|
7804
|
+
const generatePolicyCode = (collection, rule, index) => {
|
|
7805
|
+
const tableName = getTableName(collection);
|
|
8547
7806
|
const ops = rule.operations && rule.operations.length > 0 ? rule.operations : [rule.operation ?? "all"];
|
|
8548
7807
|
const ruleHash = getPolicyNameHash(rule);
|
|
8549
7808
|
return ops.map((op, opIdx) => {
|
|
8550
7809
|
const policyName = rule.name ? ops.length > 1 ? `${rule.name}_${op}` : rule.name : `${tableName}_${op}_${ruleHash}${ops.length > 1 ? `_${opIdx}` : ""}`;
|
|
8551
|
-
return generateSinglePolicyCode(
|
|
7810
|
+
return generateSinglePolicyCode(collection, rule, op, policyName);
|
|
8552
7811
|
}).join("");
|
|
8553
7812
|
};
|
|
8554
|
-
const generateSinglePolicyCode = (
|
|
7813
|
+
const generateSinglePolicyCode = (collection, rule, operation, policyName) => {
|
|
8555
7814
|
const mode = rule.mode ?? "permissive";
|
|
8556
7815
|
const roles2 = rule.roles ? [...rule.roles].sort() : void 0;
|
|
8557
7816
|
const needsUsing = operation !== "insert";
|
|
8558
7817
|
const needsWithCheck = operation !== "select" && operation !== "delete";
|
|
8559
|
-
let usingClause = needsUsing ? buildUsingClause(rule) : null;
|
|
8560
|
-
let withCheckClause = needsWithCheck ? buildWithCheckClause(rule) : null;
|
|
7818
|
+
let usingClause = needsUsing ? buildUsingClause(rule, collection) : null;
|
|
7819
|
+
let withCheckClause = needsWithCheck ? buildWithCheckClause(rule, collection) : null;
|
|
8561
7820
|
if (roles2 && roles2.length > 0) {
|
|
8562
7821
|
if (usingClause) {
|
|
8563
7822
|
usingClause = wrapWithRoleCheck(usingClause, roles2);
|
|
@@ -8626,12 +7885,26 @@ const computeSharedRelationName = (rel, sourceCollection, _collections) => {
|
|
|
8626
7885
|
const generateSchema = async (collections, stripPolicies = false) => {
|
|
8627
7886
|
let schemaContent = "// This file is auto-generated by the Rebase Drizzle generator. Do not edit manually.\n\n";
|
|
8628
7887
|
const hasUuid = collections.some((c) => c.properties && Object.values(c.properties).some((p) => p.type === "string" && (p.autoValue === "uuid" || p.isId === "uuid")));
|
|
8629
|
-
collections.some((c) => c.properties && Object.values(c.properties).some((p) =>
|
|
7888
|
+
const hasVector = collections.some((c) => c.properties && Object.values(c.properties).some((p) => p.type === "vector"));
|
|
7889
|
+
const hasBinary = collections.some((c) => c.properties && Object.values(c.properties).some((p) => p.type === "binary"));
|
|
8630
7890
|
const pgCoreImports = ["primaryKey", "pgTable", "integer", "varchar", "text", "char", "boolean", "timestamp", "date", "time", "jsonb", "json", "pgEnum", "numeric", "real", "doublePrecision", "bigint", "serial", "bigserial", "pgPolicy"];
|
|
8631
7891
|
if (hasUuid) pgCoreImports.push("uuid");
|
|
7892
|
+
if (hasVector) pgCoreImports.push("vector");
|
|
7893
|
+
if (hasBinary) pgCoreImports.push("customType");
|
|
7894
|
+
const uniqueSchemas = Array.from(new Set(collections.map((c) => isPostgresCollection(c) ? c.schema : void 0).filter(Boolean)));
|
|
7895
|
+
if (uniqueSchemas.length > 0) {
|
|
7896
|
+
pgCoreImports.push("pgSchema");
|
|
7897
|
+
}
|
|
8632
7898
|
schemaContent += `import { ${pgCoreImports.join(", ")} } from 'drizzle-orm/pg-core';
|
|
8633
7899
|
`;
|
|
8634
7900
|
schemaContent += "import { relations as drizzleRelations, sql } from 'drizzle-orm';\n\n";
|
|
7901
|
+
uniqueSchemas.forEach((schema) => {
|
|
7902
|
+
schemaContent += `export const ${schema}Schema = pgSchema("${schema}");
|
|
7903
|
+
`;
|
|
7904
|
+
});
|
|
7905
|
+
if (uniqueSchemas.length > 0) {
|
|
7906
|
+
schemaContent += "\n";
|
|
7907
|
+
}
|
|
8635
7908
|
const exportedTableVars = [];
|
|
8636
7909
|
const exportedEnumVars = [];
|
|
8637
7910
|
const exportedRelationVars = [];
|
|
@@ -8686,6 +7959,9 @@ const generateSchema = async (collections, stripPolicies = false) => {
|
|
|
8686
7959
|
const tableVarName = getTableVarName(tableName);
|
|
8687
7960
|
if (isJunction && relation && sourceCollection && relation.through) {
|
|
8688
7961
|
const targetCollection = relation.target();
|
|
7962
|
+
const schema = (isPostgresCollection(targetCollection) ? targetCollection.schema : void 0) || (isPostgresCollection(sourceCollection) ? sourceCollection.schema : void 0);
|
|
7963
|
+
const tableCreator = schema ? `${schema}Schema.table` : "pgTable";
|
|
7964
|
+
const baseTableName = tableName.includes(".") ? tableName.split(".").pop() : tableName;
|
|
8689
7965
|
const {
|
|
8690
7966
|
sourceColumn,
|
|
8691
7967
|
targetColumn
|
|
@@ -8696,7 +7972,7 @@ const generateSchema = async (collections, stripPolicies = false) => {
|
|
|
8696
7972
|
const targetColType = isNumericId(targetCollection) ? "integer" : getPrimaryKeyProp(targetCollection).isUuid ? "uuid" : "varchar";
|
|
8697
7973
|
const sourceId = getPrimaryKeyName(sourceCollection);
|
|
8698
7974
|
const targetId = getPrimaryKeyName(targetCollection);
|
|
8699
|
-
schemaContent += `export const ${tableVarName} =
|
|
7975
|
+
schemaContent += `export const ${tableVarName} = ${tableCreator}("${baseTableName}", {
|
|
8700
7976
|
`;
|
|
8701
7977
|
schemaContent += ` ${sourceColumn}: ${sourceColType}("${sourceColumn}").notNull().references(() => ${getTableVarName(getTableName(sourceCollection))}.${sourceId}, ${refOptions}),
|
|
8702
7978
|
`;
|
|
@@ -8707,7 +7983,10 @@ const generateSchema = async (collections, stripPolicies = false) => {
|
|
|
8707
7983
|
`;
|
|
8708
7984
|
schemaContent += "}));\n\n";
|
|
8709
7985
|
} else if (!isJunction) {
|
|
8710
|
-
|
|
7986
|
+
const schema = isPostgresCollection(collection) ? collection.schema : void 0;
|
|
7987
|
+
const tableCreator = schema ? `${schema}Schema.table` : "pgTable";
|
|
7988
|
+
const baseTableName = tableName.includes(".") ? tableName.split(".").pop() : tableName;
|
|
7989
|
+
schemaContent += `export const ${tableVarName} = ${tableCreator}("${baseTableName}", {
|
|
8711
7990
|
`;
|
|
8712
7991
|
const columns = /* @__PURE__ */ new Set();
|
|
8713
7992
|
Object.entries(collection.properties ?? {}).forEach(([propName, prop]) => {
|
|
@@ -8723,7 +8002,7 @@ const generateSchema = async (collections, stripPolicies = false) => {
|
|
|
8723
8002
|
if (!stripPolicies && securityRules && securityRules.length > 0) {
|
|
8724
8003
|
schemaContent += "\n}, (table) => ([\n";
|
|
8725
8004
|
securityRules.forEach((rule, idx) => {
|
|
8726
|
-
schemaContent += generatePolicyCode(
|
|
8005
|
+
schemaContent += generatePolicyCode(collection, rule);
|
|
8727
8006
|
});
|
|
8728
8007
|
schemaContent += "])).enableRLS();\n\n";
|
|
8729
8008
|
} else {
|
|
@@ -8768,11 +8047,11 @@ const generateSchema = async (collections, stripPolicies = false) => {
|
|
|
8768
8047
|
references: [${sourceTableVar}.${sourceId}],
|
|
8769
8048
|
relationName: "${owningRelationName}"
|
|
8770
8049
|
})`);
|
|
8771
|
-
const
|
|
8050
|
+
const targetRelationName = inverseRelationName ? inverseRelationName : `${tableName}_${relation.through.targetColumn}`;
|
|
8772
8051
|
tableRelations.push(` "${relation.through.targetColumn}": one(${targetTableVar}, {
|
|
8773
8052
|
fields: [${tableVarName}.${relation.through.targetColumn}],
|
|
8774
8053
|
references: [${targetTableVar}.${targetId}],
|
|
8775
|
-
relationName: "${
|
|
8054
|
+
relationName: "${targetRelationName}"
|
|
8776
8055
|
})`);
|
|
8777
8056
|
}
|
|
8778
8057
|
} else {
|
|
@@ -8871,6 +8150,89 @@ ${tableRelations.join(",\n")}
|
|
|
8871
8150
|
schemaContent += tablesExport + enumsExport + relationsExport;
|
|
8872
8151
|
return schemaContent;
|
|
8873
8152
|
};
|
|
8153
|
+
const defaultUsersCollection = {
|
|
8154
|
+
name: "Users",
|
|
8155
|
+
singularName: "User",
|
|
8156
|
+
slug: "users",
|
|
8157
|
+
table: "users",
|
|
8158
|
+
icon: "Users",
|
|
8159
|
+
group: "Settings",
|
|
8160
|
+
properties: {
|
|
8161
|
+
id: {
|
|
8162
|
+
name: "ID",
|
|
8163
|
+
type: "string",
|
|
8164
|
+
isId: "uuid"
|
|
8165
|
+
},
|
|
8166
|
+
email: {
|
|
8167
|
+
name: "Email",
|
|
8168
|
+
type: "string",
|
|
8169
|
+
validation: {
|
|
8170
|
+
required: true,
|
|
8171
|
+
unique: true
|
|
8172
|
+
}
|
|
8173
|
+
},
|
|
8174
|
+
password_hash: {
|
|
8175
|
+
name: "Password Hash",
|
|
8176
|
+
type: "string",
|
|
8177
|
+
ui: {
|
|
8178
|
+
hideFromCollection: true
|
|
8179
|
+
}
|
|
8180
|
+
},
|
|
8181
|
+
display_name: {
|
|
8182
|
+
name: "Display Name",
|
|
8183
|
+
type: "string"
|
|
8184
|
+
},
|
|
8185
|
+
photo_url: {
|
|
8186
|
+
name: "Photo URL",
|
|
8187
|
+
type: "string"
|
|
8188
|
+
},
|
|
8189
|
+
email_verified: {
|
|
8190
|
+
name: "Email Verified",
|
|
8191
|
+
type: "boolean",
|
|
8192
|
+
defaultValue: false
|
|
8193
|
+
},
|
|
8194
|
+
email_verification_token: {
|
|
8195
|
+
name: "Email Verification Token",
|
|
8196
|
+
type: "string",
|
|
8197
|
+
ui: {
|
|
8198
|
+
hideFromCollection: true
|
|
8199
|
+
}
|
|
8200
|
+
},
|
|
8201
|
+
email_verification_sent_at: {
|
|
8202
|
+
name: "Email Verification Sent At",
|
|
8203
|
+
type: "date",
|
|
8204
|
+
ui: {
|
|
8205
|
+
hideFromCollection: true
|
|
8206
|
+
}
|
|
8207
|
+
},
|
|
8208
|
+
metadata: {
|
|
8209
|
+
name: "Metadata",
|
|
8210
|
+
type: "map",
|
|
8211
|
+
defaultValue: {},
|
|
8212
|
+
ui: {
|
|
8213
|
+
hideFromCollection: true
|
|
8214
|
+
}
|
|
8215
|
+
},
|
|
8216
|
+
created_at: {
|
|
8217
|
+
name: "Created At",
|
|
8218
|
+
type: "date",
|
|
8219
|
+
autoValue: "on_create",
|
|
8220
|
+
ui: {
|
|
8221
|
+
readOnly: true,
|
|
8222
|
+
hideFromCollection: true
|
|
8223
|
+
}
|
|
8224
|
+
},
|
|
8225
|
+
updated_at: {
|
|
8226
|
+
name: "Updated At",
|
|
8227
|
+
type: "date",
|
|
8228
|
+
autoValue: "on_update",
|
|
8229
|
+
ui: {
|
|
8230
|
+
readOnly: true,
|
|
8231
|
+
hideFromCollection: true
|
|
8232
|
+
}
|
|
8233
|
+
}
|
|
8234
|
+
}
|
|
8235
|
+
};
|
|
8874
8236
|
const formatTerminalText = (text, options = {}) => {
|
|
8875
8237
|
let codes = "";
|
|
8876
8238
|
if (options.bold) codes += "\x1B[1m";
|
|
@@ -8933,10 +8295,14 @@ const runGeneration = async (collectionsFilePath, outputPath) => {
|
|
|
8933
8295
|
const imported = await dynamicImport(fileUrl);
|
|
8934
8296
|
collections = imported.backendCollections || imported.collections;
|
|
8935
8297
|
}
|
|
8936
|
-
if (!collections || !Array.isArray(collections)
|
|
8937
|
-
|
|
8938
|
-
return;
|
|
8298
|
+
if (!collections || !Array.isArray(collections)) {
|
|
8299
|
+
collections = [];
|
|
8939
8300
|
}
|
|
8301
|
+
const hasUsersCollection = collections.some((c) => c.slug === "users");
|
|
8302
|
+
if (!hasUsersCollection) {
|
|
8303
|
+
collections.push(defaultUsersCollection);
|
|
8304
|
+
}
|
|
8305
|
+
collections.sort((a, b) => a.slug.localeCompare(b.slug));
|
|
8940
8306
|
const schemaContent = await generateSchema(collections);
|
|
8941
8307
|
if (outputPath) {
|
|
8942
8308
|
const outputDir = path.dirname(outputPath);
|
|
@@ -9164,29 +8530,14 @@ class RealtimeService extends EventEmitter {
|
|
|
9164
8530
|
},
|
|
9165
8531
|
authContext
|
|
9166
8532
|
});
|
|
9167
|
-
|
|
9168
|
-
|
|
9169
|
-
|
|
9170
|
-
|
|
9171
|
-
|
|
9172
|
-
|
|
9173
|
-
|
|
9174
|
-
|
|
9175
|
-
limit: request.limit,
|
|
9176
|
-
startAfter: request.startAfter,
|
|
9177
|
-
searchString: request.searchString
|
|
9178
|
-
});
|
|
9179
|
-
} else {
|
|
9180
|
-
entities = await this.entityService.fetchCollection(request.path, {
|
|
9181
|
-
filter: request.filter,
|
|
9182
|
-
orderBy: request.orderBy,
|
|
9183
|
-
order: request.order,
|
|
9184
|
-
limit: request.limit,
|
|
9185
|
-
startAfter: request.startAfter,
|
|
9186
|
-
databaseId: request.collection?.databaseId,
|
|
9187
|
-
searchString: request.searchString
|
|
9188
|
-
});
|
|
9189
|
-
}
|
|
8533
|
+
const entities = await this.fetchCollectionWithAuth(request.path, {
|
|
8534
|
+
filter: request.filter,
|
|
8535
|
+
orderBy: request.orderBy,
|
|
8536
|
+
order: request.order,
|
|
8537
|
+
limit: request.limit,
|
|
8538
|
+
startAfter: request.startAfter,
|
|
8539
|
+
searchString: request.searchString
|
|
8540
|
+
}, authContext);
|
|
9190
8541
|
this.sendCollectionUpdate(clientId, subscriptionId, entities);
|
|
9191
8542
|
} catch (error) {
|
|
9192
8543
|
this.sendError(clientId, `Failed to subscribe to collection: ${error}`, subscriptionId);
|
|
@@ -9210,16 +8561,7 @@ class RealtimeService extends EventEmitter {
|
|
|
9210
8561
|
entityId: request.entityId,
|
|
9211
8562
|
authContext
|
|
9212
8563
|
});
|
|
9213
|
-
|
|
9214
|
-
if (this.driver) {
|
|
9215
|
-
entity = await this.driver.fetchEntity({
|
|
9216
|
-
path: request.path,
|
|
9217
|
-
entityId: request.entityId,
|
|
9218
|
-
collection
|
|
9219
|
-
});
|
|
9220
|
-
} else {
|
|
9221
|
-
entity = await this.entityService.fetchEntity(request.path, request.entityId, request.collection?.databaseId);
|
|
9222
|
-
}
|
|
8564
|
+
const entity = await this.fetchEntityWithAuth(request.path, String(request.entityId), authContext);
|
|
9223
8565
|
this.sendEntityUpdate(clientId, subscriptionId, entity || null);
|
|
9224
8566
|
} catch (error) {
|
|
9225
8567
|
this.sendError(clientId, `Failed to subscribe to entity: ${request.path} ${request.entityId} ${error}`, subscriptionId);
|
|
@@ -9364,87 +8706,77 @@ class RealtimeService extends EventEmitter {
|
|
|
9364
8706
|
async fetchCollectionWithAuth(notifyPath, collectionRequest, authContext) {
|
|
9365
8707
|
if (this.driver) {
|
|
9366
8708
|
const collection = this.registry.getCollectionByPath(notifyPath);
|
|
9367
|
-
const
|
|
9368
|
-
|
|
9369
|
-
|
|
9370
|
-
|
|
9371
|
-
|
|
9372
|
-
|
|
9373
|
-
|
|
9374
|
-
|
|
9375
|
-
|
|
9376
|
-
|
|
8709
|
+
const activeAuth = authContext || {
|
|
8710
|
+
userId: "anon",
|
|
8711
|
+
roles: ["anon"]
|
|
8712
|
+
};
|
|
8713
|
+
return await this.db.transaction(async (tx) => {
|
|
8714
|
+
await tx.execute(sql`SELECT set_config('app.user_id', ${activeAuth.userId}, true)`);
|
|
8715
|
+
await tx.execute(sql`SELECT set_config('app.user_roles', ${activeAuth.roles.join(",")}, true)`);
|
|
8716
|
+
await tx.execute(sql`SELECT set_config('app.jwt', ${JSON.stringify({
|
|
8717
|
+
sub: activeAuth.userId,
|
|
8718
|
+
roles: activeAuth.roles
|
|
8719
|
+
})}, true)`);
|
|
8720
|
+
const txEntityService = new EntityService(tx, this.registry);
|
|
8721
|
+
let fetchedEntities;
|
|
8722
|
+
if (collectionRequest.searchString) {
|
|
8723
|
+
fetchedEntities = await txEntityService.searchEntities(notifyPath, collectionRequest.searchString, {
|
|
8724
|
+
filter: collectionRequest.filter,
|
|
8725
|
+
orderBy: collectionRequest.orderBy,
|
|
8726
|
+
order: collectionRequest.order,
|
|
8727
|
+
limit: collectionRequest.limit,
|
|
8728
|
+
databaseId: collectionRequest.databaseId
|
|
8729
|
+
});
|
|
8730
|
+
} else {
|
|
8731
|
+
fetchedEntities = await txEntityService.fetchCollection(notifyPath, {
|
|
8732
|
+
filter: collectionRequest.filter,
|
|
8733
|
+
orderBy: collectionRequest.orderBy,
|
|
8734
|
+
order: collectionRequest.order,
|
|
8735
|
+
limit: collectionRequest.limit,
|
|
8736
|
+
offset: collectionRequest.offset,
|
|
8737
|
+
startAfter: collectionRequest.startAfter,
|
|
8738
|
+
databaseId: collectionRequest.databaseId
|
|
8739
|
+
});
|
|
8740
|
+
}
|
|
8741
|
+
const registryCollection = this.registry.getCollectionByPath(notifyPath);
|
|
8742
|
+
const resolvedCollection = collection ? {
|
|
8743
|
+
...collection,
|
|
8744
|
+
...registryCollection
|
|
8745
|
+
} : registryCollection;
|
|
8746
|
+
const callbacks = resolvedCollection?.callbacks;
|
|
8747
|
+
const propertyCallbacks = resolvedCollection?.properties ? buildPropertyCallbacks(resolvedCollection.properties) : void 0;
|
|
8748
|
+
if (callbacks?.afterRead || propertyCallbacks?.afterRead) {
|
|
8749
|
+
const contextForCallback = {
|
|
8750
|
+
user: {
|
|
8751
|
+
uid: activeAuth.userId,
|
|
8752
|
+
roles: activeAuth.roles
|
|
8753
|
+
},
|
|
8754
|
+
driver: this.driver,
|
|
8755
|
+
data: this.driver && "data" in this.driver ? this.driver.data : void 0
|
|
8756
|
+
};
|
|
8757
|
+
return await Promise.all(fetchedEntities.map(async (entity) => {
|
|
8758
|
+
let processedEntity = entity;
|
|
8759
|
+
if (callbacks?.afterRead) {
|
|
8760
|
+
processedEntity = await callbacks.afterRead({
|
|
8761
|
+
collection: resolvedCollection,
|
|
8762
|
+
path: notifyPath,
|
|
8763
|
+
entity: processedEntity,
|
|
8764
|
+
context: contextForCallback
|
|
8765
|
+
}) ?? processedEntity;
|
|
8766
|
+
}
|
|
8767
|
+
if (propertyCallbacks?.afterRead) {
|
|
8768
|
+
processedEntity = await propertyCallbacks.afterRead({
|
|
8769
|
+
collection: resolvedCollection,
|
|
8770
|
+
path: notifyPath,
|
|
8771
|
+
entity: processedEntity,
|
|
8772
|
+
context: contextForCallback
|
|
8773
|
+
}) ?? processedEntity;
|
|
8774
|
+
}
|
|
8775
|
+
return processedEntity;
|
|
8776
|
+
}));
|
|
8777
|
+
}
|
|
8778
|
+
return fetchedEntities;
|
|
9377
8779
|
});
|
|
9378
|
-
if (authContext) {
|
|
9379
|
-
return await this.db.transaction(async (tx) => {
|
|
9380
|
-
await tx.execute(sql`SELECT set_config('app.user_id', ${authContext.userId}, true)`);
|
|
9381
|
-
await tx.execute(sql`SELECT set_config('app.user_roles', ${authContext.roles.join(",")}, true)`);
|
|
9382
|
-
await tx.execute(sql`SELECT set_config('app.jwt', ${JSON.stringify({
|
|
9383
|
-
sub: authContext.userId,
|
|
9384
|
-
roles: authContext.roles
|
|
9385
|
-
})}, true)`);
|
|
9386
|
-
const txEntityService = new EntityService(tx, this.registry);
|
|
9387
|
-
let fetchedEntities;
|
|
9388
|
-
if (collectionRequest.searchString) {
|
|
9389
|
-
fetchedEntities = await txEntityService.searchEntities(notifyPath, collectionRequest.searchString, {
|
|
9390
|
-
filter: collectionRequest.filter,
|
|
9391
|
-
orderBy: collectionRequest.orderBy,
|
|
9392
|
-
order: collectionRequest.order,
|
|
9393
|
-
limit: collectionRequest.limit,
|
|
9394
|
-
databaseId: collectionRequest.databaseId
|
|
9395
|
-
});
|
|
9396
|
-
} else {
|
|
9397
|
-
fetchedEntities = await txEntityService.fetchCollection(notifyPath, {
|
|
9398
|
-
filter: collectionRequest.filter,
|
|
9399
|
-
orderBy: collectionRequest.orderBy,
|
|
9400
|
-
order: collectionRequest.order,
|
|
9401
|
-
limit: collectionRequest.limit,
|
|
9402
|
-
offset: collectionRequest.offset,
|
|
9403
|
-
startAfter: collectionRequest.startAfter,
|
|
9404
|
-
databaseId: collectionRequest.databaseId
|
|
9405
|
-
});
|
|
9406
|
-
}
|
|
9407
|
-
const registryCollection = this.registry.getCollectionByPath(notifyPath);
|
|
9408
|
-
const resolvedCollection = collection ? {
|
|
9409
|
-
...collection,
|
|
9410
|
-
...registryCollection
|
|
9411
|
-
} : registryCollection;
|
|
9412
|
-
const callbacks = resolvedCollection?.callbacks;
|
|
9413
|
-
const propertyCallbacks = resolvedCollection?.properties ? buildPropertyCallbacks(resolvedCollection.properties) : void 0;
|
|
9414
|
-
if (callbacks?.afterRead || propertyCallbacks?.afterRead) {
|
|
9415
|
-
const contextForCallback = {
|
|
9416
|
-
user: {
|
|
9417
|
-
uid: authContext.userId,
|
|
9418
|
-
roles: authContext.roles
|
|
9419
|
-
},
|
|
9420
|
-
driver: this.driver,
|
|
9421
|
-
data: this.driver ? this.driver.data : void 0
|
|
9422
|
-
};
|
|
9423
|
-
return await Promise.all(fetchedEntities.map(async (entity) => {
|
|
9424
|
-
let processedEntity = entity;
|
|
9425
|
-
if (callbacks?.afterRead) {
|
|
9426
|
-
processedEntity = await callbacks.afterRead({
|
|
9427
|
-
collection: resolvedCollection,
|
|
9428
|
-
path: notifyPath,
|
|
9429
|
-
entity: processedEntity,
|
|
9430
|
-
context: contextForCallback
|
|
9431
|
-
}) ?? processedEntity;
|
|
9432
|
-
}
|
|
9433
|
-
if (propertyCallbacks?.afterRead) {
|
|
9434
|
-
processedEntity = await propertyCallbacks.afterRead({
|
|
9435
|
-
collection: resolvedCollection,
|
|
9436
|
-
path: notifyPath,
|
|
9437
|
-
entity: processedEntity,
|
|
9438
|
-
context: contextForCallback
|
|
9439
|
-
}) ?? processedEntity;
|
|
9440
|
-
}
|
|
9441
|
-
return processedEntity;
|
|
9442
|
-
}));
|
|
9443
|
-
}
|
|
9444
|
-
return fetchedEntities;
|
|
9445
|
-
});
|
|
9446
|
-
}
|
|
9447
|
-
return fetchFn();
|
|
9448
8780
|
}
|
|
9449
8781
|
if (collectionRequest.searchString) {
|
|
9450
8782
|
return await this.entityService.searchEntities(notifyPath, collectionRequest.searchString, {
|
|
@@ -9508,60 +8840,56 @@ class RealtimeService extends EventEmitter {
|
|
|
9508
8840
|
async fetchEntityWithAuth(notifyPath, entityId, authContext) {
|
|
9509
8841
|
if (this.driver) {
|
|
9510
8842
|
const collection = this.registry.getCollectionByPath(notifyPath);
|
|
9511
|
-
const
|
|
9512
|
-
|
|
9513
|
-
|
|
9514
|
-
|
|
9515
|
-
|
|
9516
|
-
|
|
9517
|
-
|
|
9518
|
-
|
|
9519
|
-
|
|
9520
|
-
|
|
9521
|
-
|
|
9522
|
-
|
|
9523
|
-
|
|
9524
|
-
|
|
9525
|
-
|
|
9526
|
-
|
|
9527
|
-
|
|
9528
|
-
|
|
9529
|
-
|
|
9530
|
-
|
|
9531
|
-
|
|
9532
|
-
|
|
9533
|
-
const
|
|
9534
|
-
|
|
9535
|
-
|
|
9536
|
-
|
|
9537
|
-
|
|
9538
|
-
|
|
9539
|
-
|
|
9540
|
-
|
|
9541
|
-
|
|
9542
|
-
|
|
9543
|
-
|
|
9544
|
-
|
|
9545
|
-
|
|
9546
|
-
|
|
9547
|
-
|
|
9548
|
-
|
|
9549
|
-
|
|
9550
|
-
|
|
9551
|
-
|
|
9552
|
-
|
|
9553
|
-
|
|
9554
|
-
|
|
9555
|
-
|
|
9556
|
-
context: contextForCallback
|
|
9557
|
-
}) ?? processedEntity;
|
|
9558
|
-
}
|
|
8843
|
+
const activeAuth = authContext || {
|
|
8844
|
+
userId: "anon",
|
|
8845
|
+
roles: ["anon"]
|
|
8846
|
+
};
|
|
8847
|
+
return await this.db.transaction(async (tx) => {
|
|
8848
|
+
await tx.execute(sql`SELECT set_config('app.user_id', ${activeAuth.userId}, true)`);
|
|
8849
|
+
await tx.execute(sql`SELECT set_config('app.user_roles', ${activeAuth.roles.join(",")}, true)`);
|
|
8850
|
+
await tx.execute(sql`SELECT set_config('app.jwt', ${JSON.stringify({
|
|
8851
|
+
sub: activeAuth.userId,
|
|
8852
|
+
roles: activeAuth.roles
|
|
8853
|
+
})}, true)`);
|
|
8854
|
+
const txEntityService = new EntityService(tx, this.registry);
|
|
8855
|
+
let processedEntity = await txEntityService.fetchEntity(notifyPath, entityId, collection?.databaseId);
|
|
8856
|
+
if (processedEntity) {
|
|
8857
|
+
const registryCollection = this.registry.getCollectionByPath(notifyPath);
|
|
8858
|
+
const resolvedCollection = collection ? {
|
|
8859
|
+
...collection,
|
|
8860
|
+
...registryCollection
|
|
8861
|
+
} : registryCollection;
|
|
8862
|
+
const callbacks = resolvedCollection?.callbacks;
|
|
8863
|
+
const propertyCallbacks = resolvedCollection?.properties ? buildPropertyCallbacks(resolvedCollection.properties) : void 0;
|
|
8864
|
+
if (callbacks?.afterRead || propertyCallbacks?.afterRead) {
|
|
8865
|
+
const contextForCallback = {
|
|
8866
|
+
user: {
|
|
8867
|
+
uid: activeAuth.userId,
|
|
8868
|
+
roles: activeAuth.roles
|
|
8869
|
+
},
|
|
8870
|
+
driver: this.driver,
|
|
8871
|
+
data: this.driver && "data" in this.driver ? this.driver.data : void 0
|
|
8872
|
+
};
|
|
8873
|
+
if (callbacks?.afterRead) {
|
|
8874
|
+
processedEntity = await callbacks.afterRead({
|
|
8875
|
+
collection: resolvedCollection,
|
|
8876
|
+
path: notifyPath,
|
|
8877
|
+
entity: processedEntity,
|
|
8878
|
+
context: contextForCallback
|
|
8879
|
+
}) ?? processedEntity;
|
|
8880
|
+
}
|
|
8881
|
+
if (propertyCallbacks?.afterRead) {
|
|
8882
|
+
processedEntity = await propertyCallbacks.afterRead({
|
|
8883
|
+
collection: resolvedCollection,
|
|
8884
|
+
path: notifyPath,
|
|
8885
|
+
entity: processedEntity,
|
|
8886
|
+
context: contextForCallback
|
|
8887
|
+
}) ?? processedEntity;
|
|
9559
8888
|
}
|
|
9560
8889
|
}
|
|
9561
|
-
|
|
9562
|
-
|
|
9563
|
-
}
|
|
9564
|
-
return fetchFn();
|
|
8890
|
+
}
|
|
8891
|
+
return processedEntity;
|
|
8892
|
+
});
|
|
9565
8893
|
}
|
|
9566
8894
|
return await this.entityService.fetchEntity(notifyPath, entityId);
|
|
9567
8895
|
}
|
|
@@ -9629,6 +8957,31 @@ class RealtimeService extends EventEmitter {
|
|
|
9629
8957
|
return parentPaths;
|
|
9630
8958
|
}
|
|
9631
8959
|
// =============================================================================
|
|
8960
|
+
// Lifecycle / Cleanup
|
|
8961
|
+
// =============================================================================
|
|
8962
|
+
/**
|
|
8963
|
+
* Gracefully tear down all realtime resources.
|
|
8964
|
+
*
|
|
8965
|
+
* This MUST be called during process shutdown, **before** `pool.end()`.
|
|
8966
|
+
* It ensures:
|
|
8967
|
+
* 1. All debounced refetch timers are cancelled (prevents queries after pool closes).
|
|
8968
|
+
* 2. All subscription state and callbacks are cleared.
|
|
8969
|
+
* 3. The dedicated LISTEN client (outside the pool) is disconnected.
|
|
8970
|
+
* 4. All WebSocket clients are removed (but not forcefully closed — the
|
|
8971
|
+
* HTTP server close will handle that).
|
|
8972
|
+
*/
|
|
8973
|
+
async destroy() {
|
|
8974
|
+
for (const [key, timer] of this.refetchTimers) {
|
|
8975
|
+
clearTimeout(timer);
|
|
8976
|
+
this.refetchTimers.delete(key);
|
|
8977
|
+
}
|
|
8978
|
+
this._subscriptions.clear();
|
|
8979
|
+
this.subscriptionCallbacks.clear();
|
|
8980
|
+
await this.stopListening();
|
|
8981
|
+
this.clients.clear();
|
|
8982
|
+
this.debugLog("🧹 [RealtimeService] destroy() complete — all resources released.");
|
|
8983
|
+
}
|
|
8984
|
+
// =============================================================================
|
|
9632
8985
|
// Cross-Instance LISTEN/NOTIFY
|
|
9633
8986
|
// =============================================================================
|
|
9634
8987
|
/**
|
|
@@ -9769,8 +9122,23 @@ const clientSessions = /* @__PURE__ */ new Map();
|
|
|
9769
9122
|
const WS_RATE_LIMIT = 2e3;
|
|
9770
9123
|
const WS_RATE_WINDOW_MS = 6e4;
|
|
9771
9124
|
const ADMIN_ONLY_TYPES = /* @__PURE__ */ new Set(["EXECUTE_SQL", "FETCH_DATABASES", "FETCH_ROLES", "FETCH_UNMAPPED_TABLES", "FETCH_TABLE_METADATA", "FETCH_CURRENT_DATABASE", "CREATE_BRANCH", "DELETE_BRANCH", "LIST_BRANCHES"]);
|
|
9125
|
+
function extractErrorMessage(error) {
|
|
9126
|
+
if (!error) return "Unknown error";
|
|
9127
|
+
if (typeof error === "object") {
|
|
9128
|
+
const err = error;
|
|
9129
|
+
if (err.cause) {
|
|
9130
|
+
return extractErrorMessage(err.cause);
|
|
9131
|
+
}
|
|
9132
|
+
if (typeof err.message === "string") {
|
|
9133
|
+
return err.message;
|
|
9134
|
+
}
|
|
9135
|
+
}
|
|
9136
|
+
return String(error);
|
|
9137
|
+
}
|
|
9772
9138
|
function isAdminSession(session) {
|
|
9773
|
-
if (!session?.user
|
|
9139
|
+
if (!session?.user) return false;
|
|
9140
|
+
if (session.user.isAdmin) return true;
|
|
9141
|
+
if (!session.user.roles) return false;
|
|
9774
9142
|
return session.user.roles.some((r) => {
|
|
9775
9143
|
if (typeof r === "string") return r === "admin";
|
|
9776
9144
|
if (r && typeof r === "object" && "isAdmin" in r) return r.isAdmin;
|
|
@@ -9778,7 +9146,7 @@ function isAdminSession(session) {
|
|
|
9778
9146
|
return false;
|
|
9779
9147
|
});
|
|
9780
9148
|
}
|
|
9781
|
-
function createPostgresWebSocket(server, realtimeService, driver, authConfig) {
|
|
9149
|
+
function createPostgresWebSocket(server, realtimeService, driver, authConfig, authAdapter) {
|
|
9782
9150
|
const isProduction = process.env.NODE_ENV === "production";
|
|
9783
9151
|
const wsDebug = (...args) => {
|
|
9784
9152
|
if (!isProduction) console.debug(...args);
|
|
@@ -9792,7 +9160,7 @@ function createPostgresWebSocket(server, realtimeService, driver, authConfig) {
|
|
|
9792
9160
|
}
|
|
9793
9161
|
console.error("❌ [WebSocket Server] Error:", err);
|
|
9794
9162
|
});
|
|
9795
|
-
const requireAuth = authConfig?.requireAuth !== false && authConfig?.jwtSecret;
|
|
9163
|
+
const requireAuth = authAdapter ? true : authConfig?.requireAuth !== false && !!authConfig?.jwtSecret;
|
|
9796
9164
|
wss.on("connection", (ws) => {
|
|
9797
9165
|
const clientId = `client_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`;
|
|
9798
9166
|
wsDebug(`WebSocket client connected: ${clientId}`);
|
|
@@ -9837,11 +9205,37 @@ function createPostgresWebSocket(server, realtimeService, driver, authConfig) {
|
|
|
9837
9205
|
sendError("AUTH_ERROR", "INVALID_INPUT", "Token is required");
|
|
9838
9206
|
return;
|
|
9839
9207
|
}
|
|
9840
|
-
|
|
9841
|
-
if (
|
|
9208
|
+
let verifiedUser = null;
|
|
9209
|
+
if (authAdapter) {
|
|
9210
|
+
try {
|
|
9211
|
+
const adapterUser = authAdapter.verifyToken ? await authAdapter.verifyToken(token) : await authAdapter.verifyRequest(new Request("http://localhost/_ws_auth", {
|
|
9212
|
+
headers: {
|
|
9213
|
+
Authorization: `Bearer ${token}`
|
|
9214
|
+
}
|
|
9215
|
+
}));
|
|
9216
|
+
if (adapterUser) {
|
|
9217
|
+
verifiedUser = {
|
|
9218
|
+
userId: adapterUser.uid,
|
|
9219
|
+
roles: adapterUser.roles,
|
|
9220
|
+
isAdmin: adapterUser.isAdmin
|
|
9221
|
+
};
|
|
9222
|
+
}
|
|
9223
|
+
} catch {
|
|
9224
|
+
}
|
|
9225
|
+
} else {
|
|
9226
|
+
const jwtPayload = extractUserFromToken(token);
|
|
9227
|
+
if (jwtPayload) {
|
|
9228
|
+
verifiedUser = {
|
|
9229
|
+
userId: jwtPayload.userId,
|
|
9230
|
+
roles: jwtPayload.roles ?? [],
|
|
9231
|
+
isAdmin: (jwtPayload.roles ?? []).some((r) => r === "admin")
|
|
9232
|
+
};
|
|
9233
|
+
}
|
|
9234
|
+
}
|
|
9235
|
+
if (verifiedUser) {
|
|
9842
9236
|
const session = clientSessions.get(clientId);
|
|
9843
9237
|
if (session) {
|
|
9844
|
-
session.user =
|
|
9238
|
+
session.user = verifiedUser;
|
|
9845
9239
|
session.authenticated = true;
|
|
9846
9240
|
}
|
|
9847
9241
|
wsDebug(`[WS] replying AUTH_SUCCESS for requestId ${requestId}`);
|
|
@@ -9849,11 +9243,11 @@ function createPostgresWebSocket(server, realtimeService, driver, authConfig) {
|
|
|
9849
9243
|
type: "AUTH_SUCCESS",
|
|
9850
9244
|
requestId,
|
|
9851
9245
|
payload: {
|
|
9852
|
-
userId:
|
|
9853
|
-
roles:
|
|
9246
|
+
userId: verifiedUser.userId,
|
|
9247
|
+
roles: verifiedUser.roles
|
|
9854
9248
|
}
|
|
9855
9249
|
}));
|
|
9856
|
-
wsDebug(`🔐 [WebSocket Server] Client ${clientId} authenticated as ${
|
|
9250
|
+
wsDebug(`🔐 [WebSocket Server] Client ${clientId} authenticated as ${verifiedUser.userId}`);
|
|
9857
9251
|
} else {
|
|
9858
9252
|
wsDebug(`[WS] replying AUTH_ERROR for requestId ${requestId} (invalid token)`);
|
|
9859
9253
|
sendError("AUTH_ERROR", "INVALID_TOKEN", "Invalid or expired token");
|
|
@@ -9891,16 +9285,19 @@ function createPostgresWebSocket(server, realtimeService, driver, authConfig) {
|
|
|
9891
9285
|
}
|
|
9892
9286
|
const getScopedDelegate = async () => {
|
|
9893
9287
|
const session = clientSessions.get(clientId);
|
|
9894
|
-
if (
|
|
9288
|
+
if ("withAuth" in driver && typeof driver.withAuth === "function") {
|
|
9895
9289
|
try {
|
|
9896
|
-
const userForAuth = {
|
|
9290
|
+
const userForAuth = session?.user ? {
|
|
9897
9291
|
uid: session.user.userId,
|
|
9898
9292
|
roles: session.user.roles ?? []
|
|
9293
|
+
} : {
|
|
9294
|
+
uid: "anon",
|
|
9295
|
+
roles: ["anon"]
|
|
9899
9296
|
};
|
|
9900
9297
|
return await driver.withAuth(userForAuth);
|
|
9901
9298
|
} catch (e) {
|
|
9902
|
-
console.error("Failed to create
|
|
9903
|
-
|
|
9299
|
+
console.error("Failed to create RLS scoped delegate for WS request", e);
|
|
9300
|
+
throw new Error("Internal authentication error");
|
|
9904
9301
|
}
|
|
9905
9302
|
}
|
|
9906
9303
|
return driver;
|
|
@@ -10031,24 +9428,29 @@ function createPostgresWebSocket(server, realtimeService, driver, authConfig) {
|
|
|
10031
9428
|
sql: sql2,
|
|
10032
9429
|
options
|
|
10033
9430
|
} = payload;
|
|
10034
|
-
|
|
10035
|
-
|
|
10036
|
-
|
|
10037
|
-
|
|
10038
|
-
|
|
10039
|
-
|
|
10040
|
-
|
|
10041
|
-
|
|
10042
|
-
|
|
9431
|
+
try {
|
|
9432
|
+
const delegate = await getScopedDelegate();
|
|
9433
|
+
const admin = delegate.admin;
|
|
9434
|
+
if (!isSQLAdmin(admin)) {
|
|
9435
|
+
sendError("ERROR", "NOT_SUPPORTED", "SQL execution is not available for this driver.");
|
|
9436
|
+
break;
|
|
9437
|
+
}
|
|
9438
|
+
const result = await admin.executeSql(sql2, options);
|
|
9439
|
+
if (process.env.NODE_ENV !== "production") {
|
|
9440
|
+
wsDebug(`⚡ [WebSocket Server] SQL executed. Returned ${Array.isArray(result) ? result.length : "non-array"} rows.`);
|
|
9441
|
+
}
|
|
9442
|
+
const response = {
|
|
9443
|
+
type: "EXECUTE_SQL_SUCCESS",
|
|
9444
|
+
payload: {
|
|
9445
|
+
result
|
|
9446
|
+
},
|
|
9447
|
+
requestId
|
|
9448
|
+
};
|
|
9449
|
+
ws.send(JSON.stringify(response));
|
|
9450
|
+
} catch (sqlError) {
|
|
9451
|
+
const errMsg = extractErrorMessage(sqlError);
|
|
9452
|
+
sendError("ERROR", "SQL_ERROR", errMsg);
|
|
10043
9453
|
}
|
|
10044
|
-
const response = {
|
|
10045
|
-
type: "EXECUTE_SQL_SUCCESS",
|
|
10046
|
-
payload: {
|
|
10047
|
-
result
|
|
10048
|
-
},
|
|
10049
|
-
requestId
|
|
10050
|
-
};
|
|
10051
|
-
ws.send(JSON.stringify(response));
|
|
10052
9454
|
}
|
|
10053
9455
|
break;
|
|
10054
9456
|
case "FETCH_DATABASES":
|
|
@@ -10227,7 +9629,10 @@ function createPostgresWebSocket(server, realtimeService, driver, authConfig) {
|
|
|
10227
9629
|
const authContext = session?.user ? {
|
|
10228
9630
|
userId: session.user.userId,
|
|
10229
9631
|
roles: session.user.roles ?? []
|
|
10230
|
-
} :
|
|
9632
|
+
} : {
|
|
9633
|
+
userId: "anon",
|
|
9634
|
+
roles: ["anon"]
|
|
9635
|
+
};
|
|
10231
9636
|
await realtimeService.handleClientMessage(clientId, {
|
|
10232
9637
|
type,
|
|
10233
9638
|
payload,
|
|
@@ -10371,29 +9776,58 @@ const DEFAULT_ROLES = [{
|
|
|
10371
9776
|
},
|
|
10372
9777
|
config: null
|
|
10373
9778
|
}];
|
|
10374
|
-
async function ensureAuthTablesExist(db) {
|
|
9779
|
+
async function ensureAuthTablesExist(db, registry) {
|
|
10375
9780
|
console.log("🔍 Checking auth tables...");
|
|
10376
9781
|
try {
|
|
9782
|
+
let usersTableName = '"users"';
|
|
9783
|
+
let userIdType = "TEXT";
|
|
9784
|
+
let usersSchema2 = "public";
|
|
9785
|
+
if (registry) {
|
|
9786
|
+
const usersTable = registry.getTable("users");
|
|
9787
|
+
if (usersTable) {
|
|
9788
|
+
const {
|
|
9789
|
+
getTableName: getTableName2
|
|
9790
|
+
} = await import("drizzle-orm");
|
|
9791
|
+
usersSchema2 = getTableConfig(usersTable).schema || "public";
|
|
9792
|
+
usersTableName = usersSchema2 === "public" ? `"${getTableName2(usersTable)}"` : `"${usersSchema2}"."${getTableName2(usersTable)}"`;
|
|
9793
|
+
if (usersTable.id) {
|
|
9794
|
+
const col = usersTable.id;
|
|
9795
|
+
const meta = getColumnMeta(col);
|
|
9796
|
+
const columnType = meta.columnType;
|
|
9797
|
+
if (columnType === "PgUUID") {
|
|
9798
|
+
userIdType = "UUID";
|
|
9799
|
+
} else if (columnType === "PgSerial" || columnType === "PgInteger") {
|
|
9800
|
+
userIdType = "INTEGER";
|
|
9801
|
+
} else if (columnType === "PgBigInt" || columnType === "PgBigSerial") {
|
|
9802
|
+
userIdType = "BIGINT";
|
|
9803
|
+
}
|
|
9804
|
+
}
|
|
9805
|
+
}
|
|
9806
|
+
}
|
|
9807
|
+
let rolesSchema = "rebase";
|
|
9808
|
+
if (registry) {
|
|
9809
|
+
const rolesTable = registry.getTable("roles");
|
|
9810
|
+
if (rolesTable) {
|
|
9811
|
+
rolesSchema = getTableConfig(rolesTable).schema || "public";
|
|
9812
|
+
}
|
|
9813
|
+
}
|
|
9814
|
+
if (usersSchema2 !== "public") {
|
|
9815
|
+
await db.execute(sql`CREATE SCHEMA IF NOT EXISTS ${sql.raw(usersSchema2)}`);
|
|
9816
|
+
}
|
|
9817
|
+
if (rolesSchema !== "public" && rolesSchema !== usersSchema2) {
|
|
9818
|
+
await db.execute(sql`CREATE SCHEMA IF NOT EXISTS ${sql.raw(rolesSchema)}`);
|
|
9819
|
+
}
|
|
10377
9820
|
await db.execute(sql`CREATE SCHEMA IF NOT EXISTS rebase`);
|
|
9821
|
+
const userIdentitiesTable = `"${rolesSchema}"."user_identities"`;
|
|
9822
|
+
const rolesTableName = `"${rolesSchema}"."roles"`;
|
|
9823
|
+
const userRolesTableName = `"${rolesSchema}"."user_roles"`;
|
|
9824
|
+
const refreshTokensTableName = `"${rolesSchema}"."refresh_tokens"`;
|
|
9825
|
+
const passwordResetTokensTableName = `"${rolesSchema}"."password_reset_tokens"`;
|
|
9826
|
+
const appConfigTableName = `"${rolesSchema}"."app_config"`;
|
|
10378
9827
|
await db.execute(sql`
|
|
10379
|
-
CREATE TABLE IF NOT EXISTS
|
|
9828
|
+
CREATE TABLE IF NOT EXISTS ${sql.raw(userIdentitiesTable)} (
|
|
10380
9829
|
id TEXT PRIMARY KEY DEFAULT gen_random_uuid()::text,
|
|
10381
|
-
|
|
10382
|
-
password_hash TEXT,
|
|
10383
|
-
display_name TEXT,
|
|
10384
|
-
photo_url TEXT,
|
|
10385
|
-
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
|
10386
|
-
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
|
|
10387
|
-
)
|
|
10388
|
-
`);
|
|
10389
|
-
await db.execute(sql`
|
|
10390
|
-
CREATE INDEX IF NOT EXISTS idx_users_email
|
|
10391
|
-
ON rebase.users(email)
|
|
10392
|
-
`);
|
|
10393
|
-
await db.execute(sql`
|
|
10394
|
-
CREATE TABLE IF NOT EXISTS rebase.user_identities (
|
|
10395
|
-
id TEXT PRIMARY KEY DEFAULT gen_random_uuid()::text,
|
|
10396
|
-
user_id TEXT NOT NULL REFERENCES rebase.users(id) ON DELETE CASCADE,
|
|
9830
|
+
user_id ${sql.raw(userIdType)} NOT NULL REFERENCES ${sql.raw(usersTableName)}(id) ON DELETE CASCADE,
|
|
10397
9831
|
provider TEXT NOT NULL,
|
|
10398
9832
|
provider_id TEXT NOT NULL,
|
|
10399
9833
|
profile_data JSONB,
|
|
@@ -10404,10 +9838,10 @@ async function ensureAuthTablesExist(db) {
|
|
|
10404
9838
|
`);
|
|
10405
9839
|
await db.execute(sql`
|
|
10406
9840
|
CREATE INDEX IF NOT EXISTS idx_user_identities_user
|
|
10407
|
-
ON
|
|
9841
|
+
ON ${sql.raw(userIdentitiesTable)}(user_id)
|
|
10408
9842
|
`);
|
|
10409
9843
|
await db.execute(sql`
|
|
10410
|
-
CREATE TABLE IF NOT EXISTS
|
|
9844
|
+
CREATE TABLE IF NOT EXISTS ${sql.raw(rolesTableName)} (
|
|
10411
9845
|
id TEXT PRIMARY KEY,
|
|
10412
9846
|
name TEXT NOT NULL,
|
|
10413
9847
|
is_admin BOOLEAN DEFAULT FALSE,
|
|
@@ -10418,20 +9852,20 @@ async function ensureAuthTablesExist(db) {
|
|
|
10418
9852
|
)
|
|
10419
9853
|
`);
|
|
10420
9854
|
await db.execute(sql`
|
|
10421
|
-
CREATE TABLE IF NOT EXISTS
|
|
10422
|
-
user_id
|
|
10423
|
-
role_id TEXT NOT NULL REFERENCES
|
|
9855
|
+
CREATE TABLE IF NOT EXISTS ${sql.raw(userRolesTableName)} (
|
|
9856
|
+
user_id ${sql.raw(userIdType)} NOT NULL REFERENCES ${sql.raw(usersTableName)}(id) ON DELETE CASCADE,
|
|
9857
|
+
role_id TEXT NOT NULL REFERENCES ${sql.raw(rolesTableName)}(id) ON DELETE CASCADE,
|
|
10424
9858
|
PRIMARY KEY (user_id, role_id)
|
|
10425
9859
|
)
|
|
10426
9860
|
`);
|
|
10427
9861
|
await db.execute(sql`
|
|
10428
9862
|
CREATE INDEX IF NOT EXISTS idx_user_roles_user
|
|
10429
|
-
ON
|
|
9863
|
+
ON ${sql.raw(userRolesTableName)}(user_id)
|
|
10430
9864
|
`);
|
|
10431
9865
|
await db.execute(sql`
|
|
10432
|
-
CREATE TABLE IF NOT EXISTS
|
|
9866
|
+
CREATE TABLE IF NOT EXISTS ${sql.raw(refreshTokensTableName)} (
|
|
10433
9867
|
id TEXT PRIMARY KEY DEFAULT gen_random_uuid()::text,
|
|
10434
|
-
user_id
|
|
9868
|
+
user_id ${sql.raw(userIdType)} NOT NULL REFERENCES ${sql.raw(usersTableName)}(id) ON DELETE CASCADE,
|
|
10435
9869
|
token_hash TEXT NOT NULL UNIQUE,
|
|
10436
9870
|
expires_at TIMESTAMP WITH TIME ZONE NOT NULL,
|
|
10437
9871
|
user_agent TEXT,
|
|
@@ -10442,16 +9876,16 @@ async function ensureAuthTablesExist(db) {
|
|
|
10442
9876
|
`);
|
|
10443
9877
|
await db.execute(sql`
|
|
10444
9878
|
CREATE INDEX IF NOT EXISTS idx_refresh_tokens_hash
|
|
10445
|
-
ON
|
|
9879
|
+
ON ${sql.raw(refreshTokensTableName)}(token_hash)
|
|
10446
9880
|
`);
|
|
10447
9881
|
await db.execute(sql`
|
|
10448
9882
|
CREATE INDEX IF NOT EXISTS idx_refresh_tokens_user
|
|
10449
|
-
ON
|
|
9883
|
+
ON ${sql.raw(refreshTokensTableName)}(user_id)
|
|
10450
9884
|
`);
|
|
10451
9885
|
await db.execute(sql`
|
|
10452
|
-
CREATE TABLE IF NOT EXISTS
|
|
9886
|
+
CREATE TABLE IF NOT EXISTS ${sql.raw(passwordResetTokensTableName)} (
|
|
10453
9887
|
id TEXT PRIMARY KEY DEFAULT gen_random_uuid()::text,
|
|
10454
|
-
user_id
|
|
9888
|
+
user_id ${sql.raw(userIdType)} NOT NULL REFERENCES ${sql.raw(usersTableName)}(id) ON DELETE CASCADE,
|
|
10455
9889
|
token_hash TEXT NOT NULL UNIQUE,
|
|
10456
9890
|
expires_at TIMESTAMP WITH TIME ZONE NOT NULL,
|
|
10457
9891
|
used_at TIMESTAMP WITH TIME ZONE,
|
|
@@ -10460,20 +9894,19 @@ async function ensureAuthTablesExist(db) {
|
|
|
10460
9894
|
`);
|
|
10461
9895
|
await db.execute(sql`
|
|
10462
9896
|
CREATE INDEX IF NOT EXISTS idx_password_reset_tokens_hash
|
|
10463
|
-
ON
|
|
9897
|
+
ON ${sql.raw(passwordResetTokensTableName)}(token_hash)
|
|
10464
9898
|
`);
|
|
10465
9899
|
await db.execute(sql`
|
|
10466
9900
|
CREATE INDEX IF NOT EXISTS idx_password_reset_tokens_user
|
|
10467
|
-
ON
|
|
9901
|
+
ON ${sql.raw(passwordResetTokensTableName)}(user_id)
|
|
10468
9902
|
`);
|
|
10469
9903
|
await db.execute(sql`
|
|
10470
|
-
CREATE TABLE IF NOT EXISTS
|
|
9904
|
+
CREATE TABLE IF NOT EXISTS ${sql.raw(appConfigTableName)} (
|
|
10471
9905
|
key TEXT PRIMARY KEY,
|
|
10472
9906
|
value JSONB NOT NULL,
|
|
10473
9907
|
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
|
|
10474
9908
|
)
|
|
10475
9909
|
`);
|
|
10476
|
-
await applyInternalMigrations(db);
|
|
10477
9910
|
await db.execute(sql`CREATE SCHEMA IF NOT EXISTS auth`);
|
|
10478
9911
|
await db.transaction(async (tx) => {
|
|
10479
9912
|
await tx.execute(sql`SELECT pg_advisory_xact_lock(hashtext('rebase_auth_functions_init'))`);
|
|
@@ -10496,15 +9929,15 @@ async function ensureAuthTablesExist(db) {
|
|
|
10496
9929
|
$$ LANGUAGE sql STABLE
|
|
10497
9930
|
`);
|
|
10498
9931
|
});
|
|
10499
|
-
await seedDefaultRoles(db);
|
|
9932
|
+
await seedDefaultRoles(db, rolesTableName);
|
|
10500
9933
|
console.log("✅ Auth tables ready");
|
|
10501
9934
|
} catch (error) {
|
|
10502
9935
|
console.error("❌ Failed to create auth tables:", error);
|
|
10503
9936
|
console.warn("⚠️ Continuing without creating auth tables.");
|
|
10504
9937
|
}
|
|
10505
9938
|
}
|
|
10506
|
-
async function seedDefaultRoles(db) {
|
|
10507
|
-
const result = await db.execute(sql`SELECT COUNT(*) as count FROM
|
|
9939
|
+
async function seedDefaultRoles(db, rolesTableName) {
|
|
9940
|
+
const result = await db.execute(sql`SELECT COUNT(*) as count FROM ${sql.raw(rolesTableName)}`);
|
|
10508
9941
|
const count2 = parseInt(result.rows[0]?.count || "0", 10);
|
|
10509
9942
|
if (count2 > 0) {
|
|
10510
9943
|
console.log(`📋 Found ${count2} existing roles`);
|
|
@@ -10513,7 +9946,7 @@ async function seedDefaultRoles(db) {
|
|
|
10513
9946
|
console.log("🌱 Seeding default roles...");
|
|
10514
9947
|
for (const role of DEFAULT_ROLES) {
|
|
10515
9948
|
await db.execute(sql`
|
|
10516
|
-
INSERT INTO
|
|
9949
|
+
INSERT INTO ${sql.raw(rolesTableName)} (id, name, is_admin, default_permissions, config)
|
|
10517
9950
|
VALUES (
|
|
10518
9951
|
${role.id},
|
|
10519
9952
|
${role.name},
|
|
@@ -10526,142 +9959,156 @@ async function seedDefaultRoles(db) {
|
|
|
10526
9959
|
}
|
|
10527
9960
|
console.log("✅ Default roles created: admin, editor, viewer");
|
|
10528
9961
|
}
|
|
10529
|
-
|
|
10530
|
-
|
|
10531
|
-
|
|
10532
|
-
|
|
10533
|
-
|
|
10534
|
-
|
|
10535
|
-
|
|
10536
|
-
|
|
10537
|
-
const columnsCheck = await db.execute(sql`
|
|
10538
|
-
SELECT column_name
|
|
10539
|
-
FROM information_schema.columns
|
|
10540
|
-
WHERE table_schema='rebase' AND table_name='users' AND column_name IN ('google_id', 'linkedin_id', 'provider')
|
|
10541
|
-
`);
|
|
10542
|
-
const existingColumns = columnsCheck.rows.map((r) => r.column_name);
|
|
10543
|
-
if (existingColumns.includes("google_id")) {
|
|
10544
|
-
await db.execute(sql`
|
|
10545
|
-
INSERT INTO rebase.user_identities (user_id, provider, provider_id)
|
|
10546
|
-
SELECT id, 'google', google_id
|
|
10547
|
-
FROM rebase.users
|
|
10548
|
-
WHERE google_id IS NOT NULL
|
|
10549
|
-
ON CONFLICT (provider, provider_id) DO NOTHING
|
|
10550
|
-
`);
|
|
10551
|
-
}
|
|
10552
|
-
if (existingColumns.includes("linkedin_id")) {
|
|
10553
|
-
await db.execute(sql`
|
|
10554
|
-
INSERT INTO rebase.user_identities (user_id, provider, provider_id)
|
|
10555
|
-
SELECT id, 'linkedin', linkedin_id
|
|
10556
|
-
FROM rebase.users
|
|
10557
|
-
WHERE linkedin_id IS NOT NULL
|
|
10558
|
-
ON CONFLICT (provider, provider_id) DO NOTHING
|
|
10559
|
-
`);
|
|
10560
|
-
}
|
|
10561
|
-
if (existingColumns.length > 0) {
|
|
10562
|
-
await db.execute(sql`
|
|
10563
|
-
ALTER TABLE rebase.users
|
|
10564
|
-
DROP COLUMN IF EXISTS provider,
|
|
10565
|
-
DROP COLUMN IF EXISTS google_id,
|
|
10566
|
-
DROP COLUMN IF EXISTS linkedin_id
|
|
10567
|
-
`);
|
|
10568
|
-
await db.execute(sql`DROP INDEX IF EXISTS rebase.idx_users_google_id`);
|
|
10569
|
-
await db.execute(sql`DROP INDEX IF EXISTS rebase.idx_users_linkedin_id`);
|
|
10570
|
-
console.log("✅ Migrated to user_identities and dropped legacy columns.");
|
|
10571
|
-
}
|
|
10572
|
-
await db.execute(sql`
|
|
10573
|
-
ALTER TABLE rebase.roles
|
|
10574
|
-
ADD COLUMN IF NOT EXISTS collection_permissions JSONB
|
|
10575
|
-
`);
|
|
10576
|
-
await db.execute(sql`
|
|
10577
|
-
ALTER TABLE rebase.refresh_tokens
|
|
10578
|
-
ADD COLUMN IF NOT EXISTS user_agent TEXT,
|
|
10579
|
-
ADD COLUMN IF NOT EXISTS ip_address TEXT
|
|
10580
|
-
`);
|
|
10581
|
-
const constraintCheck = await db.execute(sql`
|
|
10582
|
-
SELECT 1 FROM information_schema.table_constraints
|
|
10583
|
-
WHERE constraint_name = 'unique_device_session'
|
|
10584
|
-
AND table_schema = 'rebase'
|
|
10585
|
-
AND table_name = 'refresh_tokens'
|
|
10586
|
-
`);
|
|
10587
|
-
if (constraintCheck.rows.length === 0) {
|
|
10588
|
-
try {
|
|
10589
|
-
await db.execute(sql`
|
|
10590
|
-
ALTER TABLE rebase.refresh_tokens
|
|
10591
|
-
ADD CONSTRAINT unique_device_session UNIQUE (user_id, user_agent, ip_address)
|
|
10592
|
-
`);
|
|
10593
|
-
console.log("✅ Added unique_device_session constraint");
|
|
10594
|
-
} catch (e) {
|
|
10595
|
-
const errorMessage = e instanceof Error ? e.message : String(e);
|
|
10596
|
-
if (errorMessage.includes("could not create unique index")) {
|
|
10597
|
-
console.warn("⚠️ Duplicate sessions found, cleaning up before adding constraint...");
|
|
10598
|
-
await db.execute(sql`
|
|
10599
|
-
DELETE FROM rebase.refresh_tokens a
|
|
10600
|
-
USING rebase.refresh_tokens b
|
|
10601
|
-
WHERE a.user_id = b.user_id
|
|
10602
|
-
AND COALESCE(a.user_agent, '') = COALESCE(b.user_agent, '')
|
|
10603
|
-
AND COALESCE(a.ip_address, '') = COALESCE(b.ip_address, '')
|
|
10604
|
-
AND a.created_at < b.created_at
|
|
10605
|
-
`);
|
|
10606
|
-
await db.execute(sql`
|
|
10607
|
-
ALTER TABLE rebase.refresh_tokens
|
|
10608
|
-
ADD CONSTRAINT unique_device_session UNIQUE (user_id, user_agent, ip_address)
|
|
10609
|
-
`).catch((retryErr) => {
|
|
10610
|
-
const retryMessage = retryErr instanceof Error ? retryErr.message : String(retryErr);
|
|
10611
|
-
console.error("Failed to add unique_device_session constraint after cleanup:", retryMessage);
|
|
10612
|
-
});
|
|
10613
|
-
} else {
|
|
10614
|
-
console.error("Constraint migration issue:", errorMessage);
|
|
10615
|
-
}
|
|
10616
|
-
}
|
|
10617
|
-
}
|
|
10618
|
-
} catch (error) {
|
|
10619
|
-
console.error("❌ Failed to run internal migrations:", error);
|
|
9962
|
+
function getColumnKey(table, ...keys2) {
|
|
9963
|
+
if (!table) return void 0;
|
|
9964
|
+
for (const key of keys2) {
|
|
9965
|
+
if (key in table) return key;
|
|
9966
|
+
const snake = toSnakeCase(key);
|
|
9967
|
+
if (snake in table) return snake;
|
|
9968
|
+
const camel = camelCase(key);
|
|
9969
|
+
if (camel in table) return camel;
|
|
10620
9970
|
}
|
|
9971
|
+
return void 0;
|
|
9972
|
+
}
|
|
9973
|
+
function getColumn(table, ...keys2) {
|
|
9974
|
+
if (!table) return void 0;
|
|
9975
|
+
const key = getColumnKey(table, ...keys2);
|
|
9976
|
+
return key ? table[key] : void 0;
|
|
10621
9977
|
}
|
|
10622
9978
|
class UserService {
|
|
10623
|
-
constructor(db) {
|
|
9979
|
+
constructor(db, tableOrTables) {
|
|
10624
9980
|
this.db = db;
|
|
9981
|
+
if (tableOrTables && (tableOrTables.users || tableOrTables.roles)) {
|
|
9982
|
+
const tables = tableOrTables;
|
|
9983
|
+
this.usersTable = tables.users || users;
|
|
9984
|
+
this.userIdentitiesTable = tables.userIdentities || userIdentities;
|
|
9985
|
+
this.userRolesTable = tables.userRoles || userRoles;
|
|
9986
|
+
this.rolesTable = tables.roles || roles;
|
|
9987
|
+
} else {
|
|
9988
|
+
const table = tableOrTables;
|
|
9989
|
+
this.usersTable = table || users;
|
|
9990
|
+
this.userIdentitiesTable = userIdentities;
|
|
9991
|
+
this.userRolesTable = userRoles;
|
|
9992
|
+
this.rolesTable = roles;
|
|
9993
|
+
}
|
|
9994
|
+
}
|
|
9995
|
+
usersTable;
|
|
9996
|
+
userIdentitiesTable;
|
|
9997
|
+
userRolesTable;
|
|
9998
|
+
rolesTable;
|
|
9999
|
+
getQualifiedUsersTableName() {
|
|
10000
|
+
const name = getTableName$1(this.usersTable);
|
|
10001
|
+
const schema = getTableConfig(this.usersTable).schema || "public";
|
|
10002
|
+
return `"${schema}"."${name}"`;
|
|
10003
|
+
}
|
|
10004
|
+
mapRowToUser(row) {
|
|
10005
|
+
if (!row) return row;
|
|
10006
|
+
const id = row.id ?? row.uid;
|
|
10007
|
+
const email = row.email;
|
|
10008
|
+
const passwordHash = row.password_hash ?? row.passwordHash ?? null;
|
|
10009
|
+
const displayName = row.display_name ?? row.displayName ?? null;
|
|
10010
|
+
const photoUrl = row.photo_url ?? row.photoUrl ?? row.photoURL ?? null;
|
|
10011
|
+
const emailVerified = row.email_verified ?? row.emailVerified ?? false;
|
|
10012
|
+
const emailVerificationToken = row.email_verification_token ?? row.emailVerificationToken ?? null;
|
|
10013
|
+
const emailVerificationSentAt = row.email_verification_sent_at ?? row.emailVerificationSentAt ?? null;
|
|
10014
|
+
const createdAt = row.created_at ?? row.createdAt;
|
|
10015
|
+
const updatedAt = row.updated_at ?? row.updatedAt;
|
|
10016
|
+
const metadata = {
|
|
10017
|
+
...row.metadata || {}
|
|
10018
|
+
};
|
|
10019
|
+
const knownKeys = /* @__PURE__ */ new Set(["id", "uid", "email", "password_hash", "passwordHash", "display_name", "displayName", "photo_url", "photoUrl", "photoURL", "email_verified", "emailVerified", "email_verification_token", "emailVerificationToken", "email_verification_sent_at", "emailVerificationSentAt", "created_at", "createdAt", "updated_at", "updatedAt", "metadata"]);
|
|
10020
|
+
for (const [key, val] of Object.entries(row)) {
|
|
10021
|
+
if (!knownKeys.has(key)) {
|
|
10022
|
+
const camelKey = camelCase(key);
|
|
10023
|
+
metadata[camelKey] = val;
|
|
10024
|
+
}
|
|
10025
|
+
}
|
|
10026
|
+
return {
|
|
10027
|
+
id,
|
|
10028
|
+
email,
|
|
10029
|
+
passwordHash,
|
|
10030
|
+
displayName,
|
|
10031
|
+
photoUrl,
|
|
10032
|
+
emailVerified,
|
|
10033
|
+
emailVerificationToken,
|
|
10034
|
+
emailVerificationSentAt: emailVerificationSentAt ? new Date(emailVerificationSentAt) : null,
|
|
10035
|
+
createdAt: createdAt ? new Date(createdAt) : /* @__PURE__ */ new Date(),
|
|
10036
|
+
updatedAt: updatedAt ? new Date(updatedAt) : /* @__PURE__ */ new Date(),
|
|
10037
|
+
metadata
|
|
10038
|
+
};
|
|
10039
|
+
}
|
|
10040
|
+
mapPayload(data) {
|
|
10041
|
+
if (!data) return {};
|
|
10042
|
+
const payload = {};
|
|
10043
|
+
const idKey = getColumnKey(this.usersTable, "id") || "id";
|
|
10044
|
+
const emailKey = getColumnKey(this.usersTable, "email") || "email";
|
|
10045
|
+
const passwordHashKey = getColumnKey(this.usersTable, "passwordHash", "password_hash") || "passwordHash";
|
|
10046
|
+
const displayNameKey = getColumnKey(this.usersTable, "displayName", "display_name") || "displayName";
|
|
10047
|
+
const photoUrlKey = getColumnKey(this.usersTable, "photoUrl", "photo_url") || "photoUrl";
|
|
10048
|
+
const emailVerifiedKey = getColumnKey(this.usersTable, "emailVerified", "email_verified") || "emailVerified";
|
|
10049
|
+
const emailVerificationTokenKey = getColumnKey(this.usersTable, "emailVerificationToken", "email_verification_token") || "emailVerificationToken";
|
|
10050
|
+
const emailVerificationSentAtKey = getColumnKey(this.usersTable, "emailVerificationSentAt", "email_verification_sent_at") || "emailVerificationSentAt";
|
|
10051
|
+
const createdAtKey = getColumnKey(this.usersTable, "createdAt", "created_at") || "createdAt";
|
|
10052
|
+
const updatedAtKey = getColumnKey(this.usersTable, "updatedAt", "updated_at") || "updatedAt";
|
|
10053
|
+
const metadataKey = getColumnKey(this.usersTable, "metadata") || "metadata";
|
|
10054
|
+
if ("id" in data) payload[idKey] = data.id;
|
|
10055
|
+
if ("email" in data) payload[emailKey] = data.email;
|
|
10056
|
+
if ("passwordHash" in data) payload[passwordHashKey] = data.passwordHash;
|
|
10057
|
+
if ("displayName" in data) payload[displayNameKey] = data.displayName;
|
|
10058
|
+
if ("photoUrl" in data) payload[photoUrlKey] = data.photoUrl;
|
|
10059
|
+
if ("emailVerified" in data) payload[emailVerifiedKey] = data.emailVerified;
|
|
10060
|
+
if ("emailVerificationToken" in data) payload[emailVerificationTokenKey] = data.emailVerificationToken;
|
|
10061
|
+
if ("emailVerificationSentAt" in data) payload[emailVerificationSentAtKey] = data.emailVerificationSentAt;
|
|
10062
|
+
if ("createdAt" in data) payload[createdAtKey] = data.createdAt;
|
|
10063
|
+
if ("updatedAt" in data) payload[updatedAtKey] = data.updatedAt;
|
|
10064
|
+
const metadata = {
|
|
10065
|
+
...data.metadata || {}
|
|
10066
|
+
};
|
|
10067
|
+
const remainingMetadata = {};
|
|
10068
|
+
for (const [key, val] of Object.entries(metadata)) {
|
|
10069
|
+
const tableColKey = getColumnKey(this.usersTable, key);
|
|
10070
|
+
if (tableColKey && tableColKey !== idKey && tableColKey !== emailKey && tableColKey !== passwordHashKey && tableColKey !== displayNameKey && tableColKey !== photoUrlKey && tableColKey !== emailVerifiedKey && tableColKey !== emailVerificationTokenKey && tableColKey !== emailVerificationSentAtKey && tableColKey !== createdAtKey && tableColKey !== updatedAtKey && tableColKey !== metadataKey) {
|
|
10071
|
+
payload[tableColKey] = val;
|
|
10072
|
+
} else {
|
|
10073
|
+
remainingMetadata[key] = val;
|
|
10074
|
+
}
|
|
10075
|
+
}
|
|
10076
|
+
if (metadataKey in this.usersTable) {
|
|
10077
|
+
payload[metadataKey] = remainingMetadata;
|
|
10078
|
+
}
|
|
10079
|
+
return payload;
|
|
10625
10080
|
}
|
|
10626
10081
|
async createUser(data) {
|
|
10627
|
-
const
|
|
10628
|
-
|
|
10082
|
+
const payload = this.mapPayload(data);
|
|
10083
|
+
const [row] = await this.db.insert(this.usersTable).values(payload).returning();
|
|
10084
|
+
return this.mapRowToUser(row);
|
|
10629
10085
|
}
|
|
10630
10086
|
async getUserById(id) {
|
|
10631
|
-
const
|
|
10632
|
-
|
|
10087
|
+
const idCol = getColumn(this.usersTable, "id");
|
|
10088
|
+
if (!idCol) return null;
|
|
10089
|
+
const [row] = await this.db.select().from(this.usersTable).where(eq(idCol, id));
|
|
10090
|
+
return row ? this.mapRowToUser(row) : null;
|
|
10633
10091
|
}
|
|
10634
10092
|
async getUserByEmail(email) {
|
|
10635
|
-
const
|
|
10636
|
-
|
|
10093
|
+
const emailCol = getColumn(this.usersTable, "email");
|
|
10094
|
+
if (!emailCol) return null;
|
|
10095
|
+
const [row] = await this.db.select().from(this.usersTable).where(eq(emailCol, email.toLowerCase()));
|
|
10096
|
+
return row ? this.mapRowToUser(row) : null;
|
|
10637
10097
|
}
|
|
10638
10098
|
async getUserByIdentity(provider, providerId) {
|
|
10639
|
-
const
|
|
10640
|
-
|
|
10641
|
-
|
|
10642
|
-
|
|
10643
|
-
|
|
10644
|
-
|
|
10645
|
-
|
|
10646
|
-
if (result.rows.length === 0) return null;
|
|
10647
|
-
const row = result.rows[0];
|
|
10648
|
-
return {
|
|
10649
|
-
id: row.id,
|
|
10650
|
-
email: row.email,
|
|
10651
|
-
passwordHash: row.password_hash ?? null,
|
|
10652
|
-
displayName: row.display_name ?? null,
|
|
10653
|
-
photoUrl: row.photo_url ?? null,
|
|
10654
|
-
emailVerified: row.email_verified ?? false,
|
|
10655
|
-
emailVerificationToken: row.email_verification_token ?? null,
|
|
10656
|
-
emailVerificationSentAt: row.email_verification_sent_at ?? null,
|
|
10657
|
-
createdAt: row.created_at,
|
|
10658
|
-
updatedAt: row.updated_at
|
|
10659
|
-
};
|
|
10099
|
+
const userIdCol = getColumn(this.usersTable, "id");
|
|
10100
|
+
if (!userIdCol) return null;
|
|
10101
|
+
const result = await this.db.select({
|
|
10102
|
+
user: this.usersTable
|
|
10103
|
+
}).from(this.usersTable).innerJoin(this.userIdentitiesTable, eq(userIdCol, this.userIdentitiesTable.userId)).where(sql`${this.userIdentitiesTable.provider} = ${provider} AND ${this.userIdentitiesTable.providerId} = ${providerId}`).limit(1);
|
|
10104
|
+
if (result.length === 0) return null;
|
|
10105
|
+
return this.mapRowToUser(result[0].user);
|
|
10660
10106
|
}
|
|
10661
10107
|
async getUserIdentities(userId) {
|
|
10108
|
+
const schema = getTableConfig(this.userIdentitiesTable).schema || "public";
|
|
10662
10109
|
const result = await this.db.execute(sql`
|
|
10663
10110
|
SELECT id, user_id, provider, provider_id, profile_data, created_at, updated_at
|
|
10664
|
-
FROM
|
|
10111
|
+
FROM ${sql.raw(`"${schema}"."user_identities"`)}
|
|
10665
10112
|
WHERE user_id = ${userId}
|
|
10666
10113
|
`);
|
|
10667
10114
|
return result.rows.map((row) => ({
|
|
@@ -10675,27 +10122,32 @@ class UserService {
|
|
|
10675
10122
|
}));
|
|
10676
10123
|
}
|
|
10677
10124
|
async linkUserIdentity(userId, provider, providerId, profileData) {
|
|
10678
|
-
await this.db.insert(
|
|
10125
|
+
await this.db.insert(this.userIdentitiesTable).values({
|
|
10679
10126
|
userId,
|
|
10680
10127
|
provider,
|
|
10681
10128
|
providerId,
|
|
10682
10129
|
profileData: profileData || null
|
|
10683
10130
|
}).onConflictDoNothing({
|
|
10684
|
-
target: [
|
|
10131
|
+
target: [this.userIdentitiesTable.provider, this.userIdentitiesTable.providerId]
|
|
10685
10132
|
});
|
|
10686
10133
|
}
|
|
10687
10134
|
async updateUser(id, data) {
|
|
10688
|
-
const
|
|
10689
|
-
|
|
10690
|
-
|
|
10691
|
-
|
|
10692
|
-
|
|
10135
|
+
const idCol = getColumn(this.usersTable, "id");
|
|
10136
|
+
if (!idCol) return null;
|
|
10137
|
+
const payload = this.mapPayload(data);
|
|
10138
|
+
const updatedAtKey = getColumnKey(this.usersTable, "updatedAt", "updated_at") || "updatedAt";
|
|
10139
|
+
payload[updatedAtKey] = /* @__PURE__ */ new Date();
|
|
10140
|
+
const [row] = await this.db.update(this.usersTable).set(payload).where(eq(idCol, id)).returning();
|
|
10141
|
+
return row ? this.mapRowToUser(row) : null;
|
|
10693
10142
|
}
|
|
10694
10143
|
async deleteUser(id) {
|
|
10695
|
-
|
|
10144
|
+
const idCol = getColumn(this.usersTable, "id");
|
|
10145
|
+
if (!idCol) return;
|
|
10146
|
+
await this.db.delete(this.usersTable).where(eq(idCol, id));
|
|
10696
10147
|
}
|
|
10697
10148
|
async listUsers() {
|
|
10698
|
-
|
|
10149
|
+
const rows = await this.db.select().from(this.usersTable);
|
|
10150
|
+
return rows.map((row) => this.mapRowToUser(row));
|
|
10699
10151
|
}
|
|
10700
10152
|
async listUsersPaginated(options) {
|
|
10701
10153
|
const limit = options?.limit ?? 25;
|
|
@@ -10704,49 +10156,40 @@ class UserService {
|
|
|
10704
10156
|
const orderBy = options?.orderBy || "createdAt";
|
|
10705
10157
|
const orderDir = options?.orderDir || "desc";
|
|
10706
10158
|
const roleId = options?.roleId;
|
|
10707
|
-
const
|
|
10708
|
-
|
|
10709
|
-
displayName: "display_name",
|
|
10710
|
-
createdAt: "created_at",
|
|
10711
|
-
updatedAt: "updated_at",
|
|
10712
|
-
provider: "provider"
|
|
10713
|
-
};
|
|
10714
|
-
const orderColumn = columnMap[orderBy] || "created_at";
|
|
10159
|
+
const orderCol = getColumn(this.usersTable, orderBy);
|
|
10160
|
+
const orderColumn = orderCol ? orderCol.name : "created_at";
|
|
10715
10161
|
const direction = orderDir === "asc" ? sql`ASC` : sql`DESC`;
|
|
10162
|
+
const emailCol = getColumn(this.usersTable, "email");
|
|
10163
|
+
const emailColumn = emailCol ? emailCol.name : "email";
|
|
10164
|
+
const displayNameCol = getColumn(this.usersTable, "displayName", "display_name");
|
|
10165
|
+
const displayNameColumn = displayNameCol ? displayNameCol.name : "display_name";
|
|
10166
|
+
const idCol = getColumn(this.usersTable, "id");
|
|
10167
|
+
const idColumn = idCol ? idCol.name : "id";
|
|
10168
|
+
const usersTableName = this.getQualifiedUsersTableName();
|
|
10169
|
+
const rolesSchema = getTableConfig(this.userRolesTable).schema || "public";
|
|
10716
10170
|
const conditions = [];
|
|
10717
10171
|
if (roleId) {
|
|
10718
|
-
conditions.push(sql`EXISTS (SELECT 1 FROM
|
|
10172
|
+
conditions.push(sql`EXISTS (SELECT 1 FROM ${sql.raw(`"${rolesSchema}"."user_roles"`)} ur WHERE ur.user_id = ${sql.raw(usersTableName)}.${sql.raw(idColumn)} AND ur.role_id = ${roleId})`);
|
|
10719
10173
|
}
|
|
10720
10174
|
if (search) {
|
|
10721
10175
|
const pattern = `%${search}%`;
|
|
10722
|
-
conditions.push(sql`(
|
|
10176
|
+
conditions.push(sql`(${sql.raw(usersTableName)}.${sql.raw(emailColumn)} ILIKE ${pattern} OR ${sql.raw(usersTableName)}.${sql.raw(displayNameColumn)} ILIKE ${pattern})`);
|
|
10723
10177
|
}
|
|
10724
10178
|
const whereClause = conditions.length > 0 ? sql`WHERE ${sql.join(conditions, sql` AND `)}` : sql``;
|
|
10725
|
-
const orderByClause = roleId ? sql`ORDER BY ${sql.raw(orderColumn)} ${direction}` : sql`ORDER BY (SELECT count(*) FROM
|
|
10179
|
+
const orderByClause = roleId ? sql`ORDER BY ${sql.raw(usersTableName)}.${sql.raw(orderColumn)} ${direction}` : sql`ORDER BY (SELECT count(*) FROM ${sql.raw(`"${rolesSchema}"."user_roles"`)} ur WHERE ur.user_id = ${sql.raw(usersTableName)}.${sql.raw(idColumn)}) DESC, ${sql.raw(usersTableName)}.${sql.raw(orderColumn)} ${direction}`;
|
|
10726
10180
|
const countResult = await this.db.execute(sql`
|
|
10727
|
-
SELECT count(*)::int as total FROM
|
|
10181
|
+
SELECT count(*)::int as total FROM ${sql.raw(usersTableName)}
|
|
10728
10182
|
${whereClause}
|
|
10729
10183
|
`);
|
|
10730
10184
|
const total = countResult.rows[0].total;
|
|
10731
10185
|
const dataResult = await this.db.execute(sql`
|
|
10732
|
-
SELECT * FROM
|
|
10186
|
+
SELECT * FROM ${sql.raw(usersTableName)}
|
|
10733
10187
|
${whereClause}
|
|
10734
10188
|
${orderByClause}
|
|
10735
10189
|
LIMIT ${limit} OFFSET ${offset}
|
|
10736
10190
|
`);
|
|
10737
10191
|
const rows = dataResult.rows;
|
|
10738
|
-
const mappedUsers = rows.map((row) => (
|
|
10739
|
-
id: row.id,
|
|
10740
|
-
email: row.email,
|
|
10741
|
-
passwordHash: row.password_hash ?? row.passwordHash ?? null,
|
|
10742
|
-
displayName: row.display_name ?? row.displayName ?? null,
|
|
10743
|
-
photoUrl: row.photo_url ?? row.photoUrl ?? null,
|
|
10744
|
-
emailVerified: row.email_verified ?? row.emailVerified ?? false,
|
|
10745
|
-
emailVerificationToken: row.email_verification_token ?? row.emailVerificationToken ?? null,
|
|
10746
|
-
emailVerificationSentAt: row.email_verification_sent_at ?? row.emailVerificationSentAt ?? null,
|
|
10747
|
-
createdAt: row.created_at ?? row.createdAt,
|
|
10748
|
-
updatedAt: row.updated_at ?? row.updatedAt
|
|
10749
|
-
}));
|
|
10192
|
+
const mappedUsers = rows.map((row) => this.mapRowToUser(row));
|
|
10750
10193
|
return {
|
|
10751
10194
|
users: mappedUsers,
|
|
10752
10195
|
total,
|
|
@@ -10758,46 +10201,63 @@ class UserService {
|
|
|
10758
10201
|
* Update user's password hash
|
|
10759
10202
|
*/
|
|
10760
10203
|
async updatePassword(id, passwordHash) {
|
|
10761
|
-
|
|
10762
|
-
|
|
10763
|
-
|
|
10764
|
-
|
|
10204
|
+
const idCol = getColumn(this.usersTable, "id");
|
|
10205
|
+
if (!idCol) return;
|
|
10206
|
+
const passwordHashColKey = getColumnKey(this.usersTable, "passwordHash", "password_hash") || "passwordHash";
|
|
10207
|
+
const updatedAtColKey = getColumnKey(this.usersTable, "updatedAt", "updated_at") || "updatedAt";
|
|
10208
|
+
await this.db.update(this.usersTable).set({
|
|
10209
|
+
[passwordHashColKey]: passwordHash,
|
|
10210
|
+
[updatedAtColKey]: /* @__PURE__ */ new Date()
|
|
10211
|
+
}).where(eq(idCol, id));
|
|
10765
10212
|
}
|
|
10766
10213
|
/**
|
|
10767
10214
|
* Set email verification status
|
|
10768
10215
|
*/
|
|
10769
10216
|
async setEmailVerified(id, verified) {
|
|
10770
|
-
|
|
10771
|
-
|
|
10772
|
-
|
|
10773
|
-
|
|
10774
|
-
|
|
10217
|
+
const idCol = getColumn(this.usersTable, "id");
|
|
10218
|
+
if (!idCol) return;
|
|
10219
|
+
const emailVerifiedColKey = getColumnKey(this.usersTable, "emailVerified", "email_verified") || "emailVerified";
|
|
10220
|
+
const emailVerificationTokenColKey = getColumnKey(this.usersTable, "emailVerificationToken", "email_verification_token") || "emailVerificationToken";
|
|
10221
|
+
const updatedAtColKey = getColumnKey(this.usersTable, "updatedAt", "updated_at") || "updatedAt";
|
|
10222
|
+
await this.db.update(this.usersTable).set({
|
|
10223
|
+
[emailVerifiedColKey]: verified,
|
|
10224
|
+
[emailVerificationTokenColKey]: null,
|
|
10225
|
+
[updatedAtColKey]: /* @__PURE__ */ new Date()
|
|
10226
|
+
}).where(eq(idCol, id));
|
|
10775
10227
|
}
|
|
10776
10228
|
/**
|
|
10777
10229
|
* Set email verification token
|
|
10778
10230
|
*/
|
|
10779
10231
|
async setVerificationToken(id, token) {
|
|
10780
|
-
|
|
10781
|
-
|
|
10782
|
-
|
|
10783
|
-
|
|
10784
|
-
|
|
10232
|
+
const idCol = getColumn(this.usersTable, "id");
|
|
10233
|
+
if (!idCol) return;
|
|
10234
|
+
const emailVerificationTokenColKey = getColumnKey(this.usersTable, "emailVerificationToken", "email_verification_token") || "emailVerificationToken";
|
|
10235
|
+
const emailVerificationSentAtColKey = getColumnKey(this.usersTable, "emailVerificationSentAt", "email_verification_sent_at") || "emailVerificationSentAt";
|
|
10236
|
+
const updatedAtColKey = getColumnKey(this.usersTable, "updatedAt", "updated_at") || "updatedAt";
|
|
10237
|
+
await this.db.update(this.usersTable).set({
|
|
10238
|
+
[emailVerificationTokenColKey]: token,
|
|
10239
|
+
[emailVerificationSentAtColKey]: token ? /* @__PURE__ */ new Date() : null,
|
|
10240
|
+
[updatedAtColKey]: /* @__PURE__ */ new Date()
|
|
10241
|
+
}).where(eq(idCol, id));
|
|
10785
10242
|
}
|
|
10786
10243
|
/**
|
|
10787
10244
|
* Find user by email verification token
|
|
10788
10245
|
*/
|
|
10789
10246
|
async getUserByVerificationToken(token) {
|
|
10790
|
-
const
|
|
10791
|
-
|
|
10247
|
+
const tokenCol = getColumn(this.usersTable, "emailVerificationToken", "email_verification_token");
|
|
10248
|
+
if (!tokenCol) return null;
|
|
10249
|
+
const [row] = await this.db.select().from(this.usersTable).where(eq(tokenCol, token));
|
|
10250
|
+
return row ? this.mapRowToUser(row) : null;
|
|
10792
10251
|
}
|
|
10793
10252
|
/**
|
|
10794
10253
|
* Get roles for a user from database
|
|
10795
10254
|
*/
|
|
10796
10255
|
async getUserRoles(userId) {
|
|
10256
|
+
const rolesSchema = getTableConfig(this.rolesTable).schema || "public";
|
|
10797
10257
|
const result = await this.db.execute(sql`
|
|
10798
10258
|
SELECT r.id, r.name, r.is_admin, r.default_permissions, r.collection_permissions, r.config
|
|
10799
|
-
FROM
|
|
10800
|
-
INNER JOIN
|
|
10259
|
+
FROM ${sql.raw(`"${rolesSchema}"."roles"`)} r
|
|
10260
|
+
INNER JOIN ${sql.raw(`"${rolesSchema}"."user_roles"`)} ur ON r.id = ur.role_id
|
|
10801
10261
|
WHERE ur.user_id = ${userId}
|
|
10802
10262
|
`);
|
|
10803
10263
|
return result.rows.map((row) => ({
|
|
@@ -10820,10 +10280,11 @@ class UserService {
|
|
|
10820
10280
|
* Set roles for a user
|
|
10821
10281
|
*/
|
|
10822
10282
|
async setUserRoles(userId, roleIds) {
|
|
10823
|
-
|
|
10283
|
+
const rolesSchema = getTableConfig(this.userRolesTable).schema || "public";
|
|
10284
|
+
await this.db.execute(sql`DELETE FROM ${sql.raw(`"${rolesSchema}"."user_roles"`)} WHERE user_id = ${userId}`);
|
|
10824
10285
|
for (const roleId of roleIds) {
|
|
10825
10286
|
await this.db.execute(sql`
|
|
10826
|
-
INSERT INTO
|
|
10287
|
+
INSERT INTO ${sql.raw(`"${rolesSchema}"."user_roles"`)} (user_id, role_id)
|
|
10827
10288
|
VALUES (${userId}, ${roleId})
|
|
10828
10289
|
ON CONFLICT DO NOTHING
|
|
10829
10290
|
`);
|
|
@@ -10833,8 +10294,9 @@ class UserService {
|
|
|
10833
10294
|
* Assign a specific role to new user
|
|
10834
10295
|
*/
|
|
10835
10296
|
async assignDefaultRole(userId, roleId) {
|
|
10297
|
+
const rolesSchema = getTableConfig(this.userRolesTable).schema || "public";
|
|
10836
10298
|
await this.db.execute(sql`
|
|
10837
|
-
INSERT INTO
|
|
10299
|
+
INSERT INTO ${sql.raw(`"${rolesSchema}"."user_roles"`)} (user_id, role_id)
|
|
10838
10300
|
VALUES (${userId}, ${roleId})
|
|
10839
10301
|
ON CONFLICT DO NOTHING
|
|
10840
10302
|
`);
|
|
@@ -10853,13 +10315,25 @@ class UserService {
|
|
|
10853
10315
|
}
|
|
10854
10316
|
}
|
|
10855
10317
|
class RoleService {
|
|
10856
|
-
constructor(db) {
|
|
10318
|
+
constructor(db, tableOrTables) {
|
|
10857
10319
|
this.db = db;
|
|
10320
|
+
if (tableOrTables && (tableOrTables.roles || tableOrTables.users)) {
|
|
10321
|
+
this.rolesTable = tableOrTables.roles || roles;
|
|
10322
|
+
} else {
|
|
10323
|
+
this.rolesTable = tableOrTables || roles;
|
|
10324
|
+
}
|
|
10325
|
+
}
|
|
10326
|
+
rolesTable;
|
|
10327
|
+
getQualifiedRolesTableName() {
|
|
10328
|
+
const name = getTableName$1(this.rolesTable);
|
|
10329
|
+
const schema = getTableConfig(this.rolesTable).schema || "public";
|
|
10330
|
+
return `"${schema}"."${name}"`;
|
|
10858
10331
|
}
|
|
10859
10332
|
async getRoleById(id) {
|
|
10333
|
+
const tableName = this.getQualifiedRolesTableName();
|
|
10860
10334
|
const result = await this.db.execute(sql`
|
|
10861
10335
|
SELECT id, name, is_admin, default_permissions, collection_permissions, config
|
|
10862
|
-
FROM
|
|
10336
|
+
FROM ${sql.raw(tableName)}
|
|
10863
10337
|
WHERE id = ${id}
|
|
10864
10338
|
`);
|
|
10865
10339
|
if (result.rows.length === 0) return null;
|
|
@@ -10874,9 +10348,10 @@ class RoleService {
|
|
|
10874
10348
|
};
|
|
10875
10349
|
}
|
|
10876
10350
|
async listRoles() {
|
|
10351
|
+
const tableName = this.getQualifiedRolesTableName();
|
|
10877
10352
|
const result = await this.db.execute(sql`
|
|
10878
10353
|
SELECT id, name, is_admin, default_permissions, collection_permissions, config
|
|
10879
|
-
FROM
|
|
10354
|
+
FROM ${sql.raw(tableName)}
|
|
10880
10355
|
ORDER BY name
|
|
10881
10356
|
`);
|
|
10882
10357
|
return result.rows.map((row) => ({
|
|
@@ -10889,8 +10364,9 @@ class RoleService {
|
|
|
10889
10364
|
}));
|
|
10890
10365
|
}
|
|
10891
10366
|
async createRole(data) {
|
|
10367
|
+
const tableName = this.getQualifiedRolesTableName();
|
|
10892
10368
|
const result = await this.db.execute(sql`
|
|
10893
|
-
INSERT INTO
|
|
10369
|
+
INSERT INTO ${sql.raw(tableName)} (id, name, is_admin, default_permissions, collection_permissions, config)
|
|
10894
10370
|
VALUES (
|
|
10895
10371
|
${data.id},
|
|
10896
10372
|
${data.name},
|
|
@@ -10914,8 +10390,9 @@ class RoleService {
|
|
|
10914
10390
|
async updateRole(id, data) {
|
|
10915
10391
|
const existing = await this.getRoleById(id);
|
|
10916
10392
|
if (!existing) return null;
|
|
10393
|
+
const tableName = this.getQualifiedRolesTableName();
|
|
10917
10394
|
await this.db.execute(sql`
|
|
10918
|
-
UPDATE
|
|
10395
|
+
UPDATE ${sql.raw(tableName)}
|
|
10919
10396
|
SET
|
|
10920
10397
|
name = ${data.name ?? existing.name},
|
|
10921
10398
|
is_admin = ${data.isAdmin ?? existing.isAdmin},
|
|
@@ -10927,23 +10404,36 @@ class RoleService {
|
|
|
10927
10404
|
return this.getRoleById(id);
|
|
10928
10405
|
}
|
|
10929
10406
|
async deleteRole(id) {
|
|
10930
|
-
|
|
10407
|
+
const tableName = this.getQualifiedRolesTableName();
|
|
10408
|
+
await this.db.execute(sql`DELETE FROM ${sql.raw(tableName)} WHERE id = ${id}`);
|
|
10931
10409
|
}
|
|
10932
10410
|
}
|
|
10933
10411
|
class RefreshTokenService {
|
|
10934
|
-
constructor(db) {
|
|
10412
|
+
constructor(db, tableOrTables) {
|
|
10935
10413
|
this.db = db;
|
|
10414
|
+
if (tableOrTables && (tableOrTables.refreshTokens || tableOrTables.users)) {
|
|
10415
|
+
this.refreshTokensTable = tableOrTables.refreshTokens || refreshTokens;
|
|
10416
|
+
} else {
|
|
10417
|
+
this.refreshTokensTable = tableOrTables || refreshTokens;
|
|
10418
|
+
}
|
|
10419
|
+
}
|
|
10420
|
+
refreshTokensTable;
|
|
10421
|
+
getQualifiedRefreshTokensTableName() {
|
|
10422
|
+
const name = getTableName$1(this.refreshTokensTable);
|
|
10423
|
+
const schema = getTableConfig(this.refreshTokensTable).schema || "public";
|
|
10424
|
+
return `"${schema}"."${name}"`;
|
|
10936
10425
|
}
|
|
10937
10426
|
async createToken(userId, tokenHash, expiresAt, userAgent, ipAddress) {
|
|
10938
10427
|
const safeUserAgent = userAgent || "";
|
|
10939
10428
|
const safeIpAddress = ipAddress || "";
|
|
10429
|
+
const tableName = this.getQualifiedRefreshTokensTableName();
|
|
10940
10430
|
await this.db.execute(sql`
|
|
10941
|
-
DELETE FROM
|
|
10431
|
+
DELETE FROM ${sql.raw(tableName)}
|
|
10942
10432
|
WHERE user_id = ${userId}
|
|
10943
10433
|
AND user_agent = ${safeUserAgent}
|
|
10944
10434
|
AND ip_address = ${safeIpAddress}
|
|
10945
10435
|
`);
|
|
10946
|
-
await this.db.insert(
|
|
10436
|
+
await this.db.insert(this.refreshTokensTable).values({
|
|
10947
10437
|
userId,
|
|
10948
10438
|
tokenHash,
|
|
10949
10439
|
expiresAt,
|
|
@@ -10953,51 +10443,63 @@ class RefreshTokenService {
|
|
|
10953
10443
|
}
|
|
10954
10444
|
async findByHash(tokenHash) {
|
|
10955
10445
|
const [token] = await this.db.select({
|
|
10956
|
-
id:
|
|
10957
|
-
userId:
|
|
10958
|
-
tokenHash:
|
|
10959
|
-
expiresAt:
|
|
10960
|
-
createdAt:
|
|
10961
|
-
userAgent:
|
|
10962
|
-
ipAddress:
|
|
10963
|
-
}).from(
|
|
10446
|
+
id: this.refreshTokensTable.id,
|
|
10447
|
+
userId: this.refreshTokensTable.userId,
|
|
10448
|
+
tokenHash: this.refreshTokensTable.tokenHash,
|
|
10449
|
+
expiresAt: this.refreshTokensTable.expiresAt,
|
|
10450
|
+
createdAt: this.refreshTokensTable.createdAt,
|
|
10451
|
+
userAgent: this.refreshTokensTable.userAgent,
|
|
10452
|
+
ipAddress: this.refreshTokensTable.ipAddress
|
|
10453
|
+
}).from(this.refreshTokensTable).where(eq(this.refreshTokensTable.tokenHash, tokenHash));
|
|
10964
10454
|
return token || null;
|
|
10965
10455
|
}
|
|
10966
10456
|
async deleteByHash(tokenHash) {
|
|
10967
|
-
await this.db.delete(
|
|
10457
|
+
await this.db.delete(this.refreshTokensTable).where(eq(this.refreshTokensTable.tokenHash, tokenHash));
|
|
10968
10458
|
}
|
|
10969
10459
|
async deleteAllForUser(userId) {
|
|
10970
|
-
await this.db.delete(
|
|
10460
|
+
await this.db.delete(this.refreshTokensTable).where(eq(this.refreshTokensTable.userId, userId));
|
|
10971
10461
|
}
|
|
10972
10462
|
async listForUser(userId) {
|
|
10973
10463
|
const tokens = await this.db.select({
|
|
10974
|
-
id:
|
|
10975
|
-
userId:
|
|
10976
|
-
tokenHash:
|
|
10977
|
-
expiresAt:
|
|
10978
|
-
createdAt:
|
|
10979
|
-
userAgent:
|
|
10980
|
-
ipAddress:
|
|
10981
|
-
}).from(
|
|
10464
|
+
id: this.refreshTokensTable.id,
|
|
10465
|
+
userId: this.refreshTokensTable.userId,
|
|
10466
|
+
tokenHash: this.refreshTokensTable.tokenHash,
|
|
10467
|
+
expiresAt: this.refreshTokensTable.expiresAt,
|
|
10468
|
+
createdAt: this.refreshTokensTable.createdAt,
|
|
10469
|
+
userAgent: this.refreshTokensTable.userAgent,
|
|
10470
|
+
ipAddress: this.refreshTokensTable.ipAddress
|
|
10471
|
+
}).from(this.refreshTokensTable).where(eq(this.refreshTokensTable.userId, userId)).orderBy(this.refreshTokensTable.createdAt);
|
|
10982
10472
|
return tokens;
|
|
10983
10473
|
}
|
|
10984
10474
|
async deleteById(id, userId) {
|
|
10985
|
-
await this.db.delete(
|
|
10475
|
+
await this.db.delete(this.refreshTokensTable).where(sql`${this.refreshTokensTable.id} = ${id} AND ${this.refreshTokensTable.userId} = ${userId}`);
|
|
10986
10476
|
}
|
|
10987
10477
|
}
|
|
10988
10478
|
class PasswordResetTokenService {
|
|
10989
|
-
constructor(db) {
|
|
10479
|
+
constructor(db, tableOrTables) {
|
|
10990
10480
|
this.db = db;
|
|
10481
|
+
if (tableOrTables && (tableOrTables.passwordResetTokens || tableOrTables.users)) {
|
|
10482
|
+
this.passwordResetTokensTable = tableOrTables.passwordResetTokens || passwordResetTokens;
|
|
10483
|
+
} else {
|
|
10484
|
+
this.passwordResetTokensTable = tableOrTables || passwordResetTokens;
|
|
10485
|
+
}
|
|
10486
|
+
}
|
|
10487
|
+
passwordResetTokensTable;
|
|
10488
|
+
getQualifiedPasswordResetTokensTableName() {
|
|
10489
|
+
const name = getTableName$1(this.passwordResetTokensTable);
|
|
10490
|
+
const schema = getTableConfig(this.passwordResetTokensTable).schema || "public";
|
|
10491
|
+
return `"${schema}"."${name}"`;
|
|
10991
10492
|
}
|
|
10992
10493
|
/**
|
|
10993
10494
|
* Create a password reset token
|
|
10994
10495
|
*/
|
|
10995
10496
|
async createToken(userId, tokenHash, expiresAt) {
|
|
10497
|
+
const tableName = this.getQualifiedPasswordResetTokensTableName();
|
|
10996
10498
|
await this.db.execute(sql`
|
|
10997
|
-
DELETE FROM
|
|
10499
|
+
DELETE FROM ${sql.raw(tableName)}
|
|
10998
10500
|
WHERE user_id = ${userId} AND used_at IS NULL
|
|
10999
10501
|
`);
|
|
11000
|
-
await this.db.insert(
|
|
10502
|
+
await this.db.insert(this.passwordResetTokensTable).values({
|
|
11001
10503
|
userId,
|
|
11002
10504
|
tokenHash,
|
|
11003
10505
|
expiresAt
|
|
@@ -11008,13 +10510,14 @@ class PasswordResetTokenService {
|
|
|
11008
10510
|
*/
|
|
11009
10511
|
async findValidByHash(tokenHash) {
|
|
11010
10512
|
const [token] = await this.db.select({
|
|
11011
|
-
userId:
|
|
11012
|
-
expiresAt:
|
|
11013
|
-
}).from(
|
|
10513
|
+
userId: this.passwordResetTokensTable.userId,
|
|
10514
|
+
expiresAt: this.passwordResetTokensTable.expiresAt
|
|
10515
|
+
}).from(this.passwordResetTokensTable).where(eq(this.passwordResetTokensTable.tokenHash, tokenHash));
|
|
11014
10516
|
if (!token) return null;
|
|
10517
|
+
const tableName = this.getQualifiedPasswordResetTokensTableName();
|
|
11015
10518
|
const result = await this.db.execute(sql`
|
|
11016
10519
|
SELECT user_id, expires_at
|
|
11017
|
-
FROM
|
|
10520
|
+
FROM ${sql.raw(tableName)}
|
|
11018
10521
|
WHERE token_hash = ${tokenHash}
|
|
11019
10522
|
AND used_at IS NULL
|
|
11020
10523
|
AND expires_at > NOW()
|
|
@@ -11030,31 +10533,32 @@ class PasswordResetTokenService {
|
|
|
11030
10533
|
* Mark token as used
|
|
11031
10534
|
*/
|
|
11032
10535
|
async markAsUsed(tokenHash) {
|
|
11033
|
-
await this.db.update(
|
|
10536
|
+
await this.db.update(this.passwordResetTokensTable).set({
|
|
11034
10537
|
usedAt: /* @__PURE__ */ new Date()
|
|
11035
|
-
}).where(eq
|
|
10538
|
+
}).where(eq(this.passwordResetTokensTable.tokenHash, tokenHash));
|
|
11036
10539
|
}
|
|
11037
10540
|
/**
|
|
11038
10541
|
* Delete all tokens for a user
|
|
11039
10542
|
*/
|
|
11040
10543
|
async deleteAllForUser(userId) {
|
|
11041
|
-
await this.db.delete(
|
|
10544
|
+
await this.db.delete(this.passwordResetTokensTable).where(eq(this.passwordResetTokensTable.userId, userId));
|
|
11042
10545
|
}
|
|
11043
10546
|
/**
|
|
11044
10547
|
* Clean up expired tokens
|
|
11045
10548
|
*/
|
|
11046
10549
|
async deleteExpired() {
|
|
10550
|
+
const tableName = this.getQualifiedPasswordResetTokensTableName();
|
|
11047
10551
|
await this.db.execute(sql`
|
|
11048
|
-
DELETE FROM
|
|
10552
|
+
DELETE FROM ${sql.raw(tableName)}
|
|
11049
10553
|
WHERE expires_at < NOW()
|
|
11050
10554
|
`);
|
|
11051
10555
|
}
|
|
11052
10556
|
}
|
|
11053
10557
|
class PostgresTokenRepository {
|
|
11054
|
-
constructor(db) {
|
|
10558
|
+
constructor(db, tableOrTables) {
|
|
11055
10559
|
this.db = db;
|
|
11056
|
-
this.refreshTokenService = new RefreshTokenService(db);
|
|
11057
|
-
this.passwordResetTokenService = new PasswordResetTokenService(db);
|
|
10560
|
+
this.refreshTokenService = new RefreshTokenService(db, tableOrTables);
|
|
10561
|
+
this.passwordResetTokenService = new PasswordResetTokenService(db, tableOrTables);
|
|
11058
10562
|
}
|
|
11059
10563
|
refreshTokenService;
|
|
11060
10564
|
passwordResetTokenService;
|
|
@@ -11095,11 +10599,11 @@ class PostgresTokenRepository {
|
|
|
11095
10599
|
}
|
|
11096
10600
|
}
|
|
11097
10601
|
class PostgresAuthRepository {
|
|
11098
|
-
constructor(db) {
|
|
10602
|
+
constructor(db, tableOrTables) {
|
|
11099
10603
|
this.db = db;
|
|
11100
|
-
this.userService = new UserService(db);
|
|
11101
|
-
this.roleService = new RoleService(db);
|
|
11102
|
-
this.tokenRepository = new PostgresTokenRepository(db);
|
|
10604
|
+
this.userService = new UserService(db, tableOrTables);
|
|
10605
|
+
this.roleService = new RoleService(db, tableOrTables);
|
|
10606
|
+
this.tokenRepository = new PostgresTokenRepository(db, tableOrTables);
|
|
11103
10607
|
}
|
|
11104
10608
|
userService;
|
|
11105
10609
|
roleService;
|
|
@@ -11160,8 +10664,7 @@ class PostgresAuthRepository {
|
|
|
11160
10664
|
await this.userService.assignDefaultRole(userId, roleId);
|
|
11161
10665
|
}
|
|
11162
10666
|
async getUserWithRoles(userId) {
|
|
11163
|
-
|
|
11164
|
-
return result;
|
|
10667
|
+
return this.userService.getUserWithRoles(userId);
|
|
11165
10668
|
}
|
|
11166
10669
|
// Role operations (delegate to RoleService)
|
|
11167
10670
|
async getRoleById(id) {
|
|
@@ -11349,6 +10852,24 @@ class HistoryService {
|
|
|
11349
10852
|
return result.rowCount ?? 0;
|
|
11350
10853
|
}
|
|
11351
10854
|
}
|
|
10855
|
+
function deepEqual(a, b) {
|
|
10856
|
+
if (a === b) return true;
|
|
10857
|
+
if (a == null || b == null) return false;
|
|
10858
|
+
if (a instanceof Date && b instanceof Date) return a.getTime() === b.getTime();
|
|
10859
|
+
if (Array.isArray(a) && Array.isArray(b)) {
|
|
10860
|
+
if (a.length !== b.length) return false;
|
|
10861
|
+
return a.every((v, i) => deepEqual(v, b[i]));
|
|
10862
|
+
}
|
|
10863
|
+
if (typeof a === "object" && typeof b === "object") {
|
|
10864
|
+
const aObj = a;
|
|
10865
|
+
const bObj = b;
|
|
10866
|
+
const aKeys = Object.keys(aObj);
|
|
10867
|
+
const bKeys = Object.keys(bObj);
|
|
10868
|
+
if (aKeys.length !== bKeys.length) return false;
|
|
10869
|
+
return aKeys.every((k) => deepEqual(aObj[k], bObj[k]));
|
|
10870
|
+
}
|
|
10871
|
+
return false;
|
|
10872
|
+
}
|
|
11352
10873
|
function findChangedFields(oldValues, newValues) {
|
|
11353
10874
|
const changed = [];
|
|
11354
10875
|
const allKeys = /* @__PURE__ */ new Set([...Object.keys(oldValues), ...Object.keys(newValues)]);
|
|
@@ -11358,7 +10879,7 @@ function findChangedFields(oldValues, newValues) {
|
|
|
11358
10879
|
if (key.startsWith("__")) continue;
|
|
11359
10880
|
if (oldVal !== newVal) {
|
|
11360
10881
|
if (typeof oldVal === "object" && oldVal !== null && typeof newVal === "object" && newVal !== null) {
|
|
11361
|
-
if (
|
|
10882
|
+
if (!deepEqual(oldVal, newVal)) {
|
|
11362
10883
|
changed.push(key);
|
|
11363
10884
|
}
|
|
11364
10885
|
} else {
|
|
@@ -11476,14 +10997,32 @@ function createPostgresBootstrapper(pgConfig) {
|
|
|
11476
10997
|
if (!authConfig) return void 0;
|
|
11477
10998
|
const internals = driverResult.internals;
|
|
11478
10999
|
const db = internals.db;
|
|
11479
|
-
|
|
11000
|
+
const registry = internals.registry;
|
|
11001
|
+
await ensureAuthTablesExist(db, registry);
|
|
11480
11002
|
let emailService;
|
|
11481
11003
|
if (authConfig.email) {
|
|
11482
11004
|
emailService = createEmailService(authConfig.email);
|
|
11483
11005
|
}
|
|
11484
|
-
const
|
|
11485
|
-
const
|
|
11486
|
-
|
|
11006
|
+
const customUsersTable = registry?.getTable("users");
|
|
11007
|
+
const customRolesTable = registry?.getTable("roles");
|
|
11008
|
+
let usersSchemaName = "rebase";
|
|
11009
|
+
let rolesSchemaName = "rebase";
|
|
11010
|
+
if (customUsersTable) {
|
|
11011
|
+
usersSchemaName = getTableConfig(customUsersTable).schema || "public";
|
|
11012
|
+
}
|
|
11013
|
+
if (customRolesTable) {
|
|
11014
|
+
rolesSchemaName = getTableConfig(customRolesTable).schema || "public";
|
|
11015
|
+
}
|
|
11016
|
+
const authTables = createAuthSchema(rolesSchemaName, usersSchemaName);
|
|
11017
|
+
if (customUsersTable) {
|
|
11018
|
+
authTables.users = customUsersTable;
|
|
11019
|
+
}
|
|
11020
|
+
if (customRolesTable) {
|
|
11021
|
+
authTables.roles = customRolesTable;
|
|
11022
|
+
}
|
|
11023
|
+
const userService = new UserService(db, authTables);
|
|
11024
|
+
const roleService = new RoleService(db, authTables);
|
|
11025
|
+
const authRepository = new PostgresAuthRepository(db, authTables);
|
|
11487
11026
|
return {
|
|
11488
11027
|
userService,
|
|
11489
11028
|
roleService,
|
|
@@ -11515,11 +11054,54 @@ function createPostgresBootstrapper(pgConfig) {
|
|
|
11515
11054
|
},
|
|
11516
11055
|
mountRoutes(app, basePath, driverResult) {
|
|
11517
11056
|
},
|
|
11518
|
-
async initializeWebsockets(server, realtimeService, driver, config) {
|
|
11057
|
+
async initializeWebsockets(server, realtimeService, driver, config, adapter) {
|
|
11519
11058
|
const {
|
|
11520
11059
|
createPostgresWebSocket: createPostgresWebSocket2
|
|
11521
11060
|
} = await Promise.resolve().then(() => websocket);
|
|
11522
|
-
createPostgresWebSocket2(server, realtimeService, driver, config);
|
|
11061
|
+
createPostgresWebSocket2(server, realtimeService, driver, config, adapter);
|
|
11062
|
+
}
|
|
11063
|
+
};
|
|
11064
|
+
}
|
|
11065
|
+
function createPostgresAdapter(pgConfig) {
|
|
11066
|
+
const bootstrapper = createPostgresBootstrapper(pgConfig);
|
|
11067
|
+
return {
|
|
11068
|
+
type: bootstrapper.type,
|
|
11069
|
+
async initializeDriver(config) {
|
|
11070
|
+
return bootstrapper.initializeDriver(config);
|
|
11071
|
+
},
|
|
11072
|
+
async initializeRealtime(driverResult) {
|
|
11073
|
+
if (bootstrapper.initializeRealtime) {
|
|
11074
|
+
return bootstrapper.initializeRealtime({}, driverResult);
|
|
11075
|
+
}
|
|
11076
|
+
return void 0;
|
|
11077
|
+
},
|
|
11078
|
+
async initializeAuth(config, driverResult) {
|
|
11079
|
+
if (bootstrapper.initializeAuth) {
|
|
11080
|
+
return bootstrapper.initializeAuth(config, driverResult);
|
|
11081
|
+
}
|
|
11082
|
+
return void 0;
|
|
11083
|
+
},
|
|
11084
|
+
async initializeHistory(config, driverResult) {
|
|
11085
|
+
if (bootstrapper.initializeHistory) {
|
|
11086
|
+
return bootstrapper.initializeHistory(config, driverResult);
|
|
11087
|
+
}
|
|
11088
|
+
return void 0;
|
|
11089
|
+
},
|
|
11090
|
+
initializeWebsockets(server, realtimeService, driver, config) {
|
|
11091
|
+
if (bootstrapper.initializeWebsockets) {
|
|
11092
|
+
return bootstrapper.initializeWebsockets(server, realtimeService, driver, config);
|
|
11093
|
+
}
|
|
11094
|
+
},
|
|
11095
|
+
getAdmin(driverResult) {
|
|
11096
|
+
if (bootstrapper.getAdmin) {
|
|
11097
|
+
return bootstrapper.getAdmin(driverResult);
|
|
11098
|
+
}
|
|
11099
|
+
return void 0;
|
|
11100
|
+
},
|
|
11101
|
+
mountRoutes(app, basePath, driverResult) {
|
|
11102
|
+
if (bootstrapper.mountRoutes) {
|
|
11103
|
+
bootstrapper.mountRoutes(app, basePath, driverResult);
|
|
11104
|
+
}
|
|
11523
11105
|
}
|
|
11524
11106
|
};
|
|
11525
11107
|
}
|
|
@@ -11534,6 +11116,8 @@ export {
|
|
|
11534
11116
|
PostgresRealtimeProvider,
|
|
11535
11117
|
RealtimeService,
|
|
11536
11118
|
appConfig,
|
|
11119
|
+
createAuthSchema,
|
|
11120
|
+
createPostgresAdapter,
|
|
11537
11121
|
createPostgresBootstrapper,
|
|
11538
11122
|
createPostgresDatabaseConnection,
|
|
11539
11123
|
createPostgresWebSocket,
|
|
@@ -11550,6 +11134,7 @@ export {
|
|
|
11550
11134
|
userRoles,
|
|
11551
11135
|
userRolesRelations,
|
|
11552
11136
|
users,
|
|
11553
|
-
usersRelations
|
|
11137
|
+
usersRelations,
|
|
11138
|
+
usersSchema
|
|
11554
11139
|
};
|
|
11555
11140
|
//# sourceMappingURL=index.es.js.map
|