@rebasepro/server-postgresql 0.2.1 → 0.2.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.umd.js CHANGED
@@ -1166,118 +1166,6 @@
1166
1166
  });
1167
1167
  }
1168
1168
  }
1169
- function getSubcollections(collection) {
1170
- if (collection.childCollections) {
1171
- return collection.childCollections() ?? [];
1172
- }
1173
- if (getDataSourceCapabilities(collection.driver).supportsSubcollections && collection.subcollections) {
1174
- return collection.subcollections() ?? [];
1175
- }
1176
- if (getDataSourceCapabilities(collection.driver).supportsRelations && collection.relations) {
1177
- const manyRelations = collection.relations.filter((r) => r.cardinality === "many");
1178
- return manyRelations.map((r) => {
1179
- const target = r.target();
1180
- if (!target) return void 0;
1181
- const relationKey = r.relationName || target.slug;
1182
- let customName;
1183
- if (collection.properties) {
1184
- const prop = Object.entries(collection.properties).find(([_, p]) => p.type === "relation" && p.relationName === relationKey);
1185
- if (prop && prop[1].name) {
1186
- customName = prop[1].name;
1187
- }
1188
- }
1189
- const baseOverrides = {
1190
- slug: relationKey
1191
- };
1192
- if (customName) {
1193
- baseOverrides.name = customName;
1194
- baseOverrides.singularName = customName;
1195
- }
1196
- const targetWithOverrides = {
1197
- ...target,
1198
- ...baseOverrides
1199
- };
1200
- return r.overrides ? mergeDeep(targetWithOverrides, r.overrides) : targetWithOverrides;
1201
- }).filter((c) => Boolean(c));
1202
- }
1203
- return [];
1204
- }
1205
- function hasPropertyCallbacks(properties, callbackName) {
1206
- if (!properties) return false;
1207
- for (const property of Object.values(properties)) {
1208
- if (property.callbacks?.[callbackName]) return true;
1209
- if (property.type === "map" && property.properties) {
1210
- if (hasPropertyCallbacks(property.properties, callbackName)) return true;
1211
- } else if (property.type === "array" && property.of) {
1212
- const ofs = Array.isArray(property.of) ? property.of : [property.of];
1213
- for (const of of ofs) {
1214
- if (of.callbacks?.[callbackName]) return true;
1215
- if (of.type === "map" && of.properties && hasPropertyCallbacks(of.properties, callbackName)) return true;
1216
- }
1217
- }
1218
- }
1219
- return false;
1220
- }
1221
- async function processProperties(properties, values, previousValues, propsContext, callbackName) {
1222
- if (!values || typeof values !== "object") return values;
1223
- const result = {
1224
- ...values
1225
- };
1226
- for (const [key, property] of Object.entries(properties)) {
1227
- if (result[key] === void 0) continue;
1228
- let currentValue = result[key];
1229
- const previousValue = previousValues?.[key];
1230
- if (property.type === "array" && Array.isArray(currentValue)) {
1231
- if (property.of && !Array.isArray(property.of)) {
1232
- currentValue = await Promise.all(currentValue.map(async (item, index) => {
1233
- const prevItem = Array.isArray(previousValue) ? previousValue[index] : void 0;
1234
- const singlePropData = {
1235
- "_tmp": property.of
1236
- };
1237
- const res = await processProperties(singlePropData, {
1238
- "_tmp": item
1239
- }, {
1240
- "_tmp": prevItem
1241
- }, propsContext, callbackName);
1242
- return res["_tmp"];
1243
- }));
1244
- }
1245
- } else if (property.type === "map" && property.properties && typeof currentValue === "object") {
1246
- currentValue = await processProperties(property.properties, currentValue, previousValue ?? {}, propsContext, callbackName);
1247
- }
1248
- if (property.callbacks?.[callbackName]) {
1249
- const cbRes = await Promise.resolve(property.callbacks[callbackName]({
1250
- ...propsContext,
1251
- value: currentValue,
1252
- previousValue
1253
- }));
1254
- if (cbRes !== void 0) {
1255
- currentValue = cbRes;
1256
- }
1257
- }
1258
- result[key] = currentValue;
1259
- }
1260
- return result;
1261
- }
1262
- const buildPropertyCallbacks = (properties) => {
1263
- if (!properties) return void 0;
1264
- const propertyCallbacks = {};
1265
- if (hasPropertyCallbacks(properties, "afterRead")) {
1266
- propertyCallbacks.afterRead = async (props) => {
1267
- const processedValues = await processProperties(properties, props.entity.values, props.entity.values, props, "afterRead");
1268
- return {
1269
- ...props.entity,
1270
- values: processedValues
1271
- };
1272
- };
1273
- }
1274
- if (hasPropertyCallbacks(properties, "beforeSave")) {
1275
- propertyCallbacks.beforeSave = async (props) => {
1276
- return await processProperties(properties, props.values, props.previousValues ?? {}, props, "beforeSave");
1277
- };
1278
- }
1279
- return Object.keys(propertyCallbacks).length > 0 ? propertyCallbacks : void 0;
1280
- };
1281
1169
  function sanitizeRelation(relation, sourceCollection, resolveCollection) {
1282
1170
  if (!relation.target) {
1283
1171
  throw new Error("Relation is missing a `target` collection.");
@@ -1309,6 +1197,8 @@
1309
1197
  } else {
1310
1198
  targetCollection = evaluated;
1311
1199
  }
1200
+ } else if (rawTarget && typeof rawTarget === "object") {
1201
+ targetCollection = rawTarget;
1312
1202
  }
1313
1203
  if (!targetCollection) {
1314
1204
  throw new Error("Relation is missing a valid `target` collection.");
@@ -1428,11 +1318,14 @@
1428
1318
  const registeredRelationNames = /* @__PURE__ */ new Set();
1429
1319
  if (relCollection.relations) {
1430
1320
  relCollection.relations.forEach((relation) => {
1431
- const normalizedRelation = sanitizeRelation(relation, collection);
1432
- const relationKey = normalizedRelation.relationName;
1433
- if (relationKey) {
1434
- relations[relationKey] = normalizedRelation;
1435
- registeredRelationNames.add(relationKey);
1321
+ try {
1322
+ const normalizedRelation = sanitizeRelation(relation, collection);
1323
+ const relationKey = normalizedRelation.relationName;
1324
+ if (relationKey) {
1325
+ relations[relationKey] = normalizedRelation;
1326
+ registeredRelationNames.add(relationKey);
1327
+ }
1328
+ } catch (e) {
1436
1329
  }
1437
1330
  });
1438
1331
  }
@@ -1480,12 +1373,8 @@
1480
1373
  overrides: relProp.overrides
1481
1374
  };
1482
1375
  }
1483
- const relation = (sourceCollection.relations ?? []).find((rel) => rel.relationName === relProp.relationName);
1484
- if (!relation) {
1485
- console.warn(`Unrecognized relation format for property '${propertyKey}' in collection '${sourceCollection.slug}'`);
1486
- return void 0;
1487
- }
1488
- return relation;
1376
+ console.warn(`Unrecognized or missing relation target for property '${propertyKey}' in collection '${sourceCollection.slug}'`);
1377
+ return void 0;
1489
1378
  }
1490
1379
  function getTableName(collection) {
1491
1380
  if (getDataSourceCapabilities(collection.driver).supportsRelations) {
@@ -1512,6 +1401,119 @@
1512
1401
  if (snakeKey !== key && resolvedRelations[snakeKey]) return resolvedRelations[snakeKey];
1513
1402
  return void 0;
1514
1403
  }
1404
+ function getSubcollections(collection) {
1405
+ if (collection.childCollections) {
1406
+ return collection.childCollections() ?? [];
1407
+ }
1408
+ if (getDataSourceCapabilities(collection.driver).supportsSubcollections && collection.subcollections) {
1409
+ return collection.subcollections() ?? [];
1410
+ }
1411
+ if (getDataSourceCapabilities(collection.driver).supportsRelations) {
1412
+ const resolvedRelations = resolveCollectionRelations(collection);
1413
+ const manyRelations = Object.values(resolvedRelations).filter((r) => r.cardinality === "many");
1414
+ return manyRelations.map((r) => {
1415
+ const target = r.target();
1416
+ if (!target) return void 0;
1417
+ const relationKey = r.relationName || target.slug;
1418
+ let customName;
1419
+ if (collection.properties) {
1420
+ const prop = Object.entries(collection.properties).find(([_, p]) => p.type === "relation" && p.relationName === relationKey);
1421
+ if (prop && prop[1].name) {
1422
+ customName = prop[1].name;
1423
+ }
1424
+ }
1425
+ const baseOverrides = {
1426
+ slug: relationKey
1427
+ };
1428
+ if (customName) {
1429
+ baseOverrides.name = customName;
1430
+ baseOverrides.singularName = customName;
1431
+ }
1432
+ const targetWithOverrides = {
1433
+ ...target,
1434
+ ...baseOverrides
1435
+ };
1436
+ return r.overrides ? mergeDeep(targetWithOverrides, r.overrides) : targetWithOverrides;
1437
+ }).filter((c) => Boolean(c));
1438
+ }
1439
+ return [];
1440
+ }
1441
+ function hasPropertyCallbacks(properties, callbackName) {
1442
+ if (!properties) return false;
1443
+ for (const property of Object.values(properties)) {
1444
+ if (property.callbacks?.[callbackName]) return true;
1445
+ if (property.type === "map" && property.properties) {
1446
+ if (hasPropertyCallbacks(property.properties, callbackName)) return true;
1447
+ } else if (property.type === "array" && property.of) {
1448
+ const ofs = Array.isArray(property.of) ? property.of : [property.of];
1449
+ for (const of of ofs) {
1450
+ if (of.callbacks?.[callbackName]) return true;
1451
+ if (of.type === "map" && of.properties && hasPropertyCallbacks(of.properties, callbackName)) return true;
1452
+ }
1453
+ }
1454
+ }
1455
+ return false;
1456
+ }
1457
+ async function processProperties(properties, values, previousValues, propsContext, callbackName) {
1458
+ if (!values || typeof values !== "object") return values;
1459
+ const result = {
1460
+ ...values
1461
+ };
1462
+ for (const [key, property] of Object.entries(properties)) {
1463
+ if (result[key] === void 0) continue;
1464
+ let currentValue = result[key];
1465
+ const previousValue = previousValues?.[key];
1466
+ if (property.type === "array" && Array.isArray(currentValue)) {
1467
+ if (property.of && !Array.isArray(property.of)) {
1468
+ currentValue = await Promise.all(currentValue.map(async (item, index) => {
1469
+ const prevItem = Array.isArray(previousValue) ? previousValue[index] : void 0;
1470
+ const singlePropData = {
1471
+ "_tmp": property.of
1472
+ };
1473
+ const res = await processProperties(singlePropData, {
1474
+ "_tmp": item
1475
+ }, {
1476
+ "_tmp": prevItem
1477
+ }, propsContext, callbackName);
1478
+ return res["_tmp"];
1479
+ }));
1480
+ }
1481
+ } else if (property.type === "map" && property.properties && typeof currentValue === "object") {
1482
+ currentValue = await processProperties(property.properties, currentValue, previousValue ?? {}, propsContext, callbackName);
1483
+ }
1484
+ if (property.callbacks?.[callbackName]) {
1485
+ const cbRes = await Promise.resolve(property.callbacks[callbackName]({
1486
+ ...propsContext,
1487
+ value: currentValue,
1488
+ previousValue
1489
+ }));
1490
+ if (cbRes !== void 0) {
1491
+ currentValue = cbRes;
1492
+ }
1493
+ }
1494
+ result[key] = currentValue;
1495
+ }
1496
+ return result;
1497
+ }
1498
+ const buildPropertyCallbacks = (properties) => {
1499
+ if (!properties) return void 0;
1500
+ const propertyCallbacks = {};
1501
+ if (hasPropertyCallbacks(properties, "afterRead")) {
1502
+ propertyCallbacks.afterRead = async (props) => {
1503
+ const processedValues = await processProperties(properties, props.entity.values, props.entity.values, props, "afterRead");
1504
+ return {
1505
+ ...props.entity,
1506
+ values: processedValues
1507
+ };
1508
+ };
1509
+ }
1510
+ if (hasPropertyCallbacks(properties, "beforeSave")) {
1511
+ propertyCallbacks.beforeSave = async (props) => {
1512
+ return await processProperties(properties, props.values, props.previousValues ?? {}, props, "beforeSave");
1513
+ };
1514
+ }
1515
+ return Object.keys(propertyCallbacks).length > 0 ? propertyCallbacks : void 0;
1516
+ };
1515
1517
  var logic = { exports: {} };
1516
1518
  (function(module2, exports3) {
1517
1519
  (function(root, factory) {
@@ -2419,8 +2421,18 @@
2419
2421
  const mergedRelationsRaw = [...extractedRelations];
2420
2422
  for (const manual of manualRelations) {
2421
2423
  const name = manual.relationName;
2422
- if (!name || !mergedRelationsRaw.find((r) => r.relationName === name)) {
2424
+ if (!name) {
2423
2425
  mergedRelationsRaw.push(manual);
2426
+ } else {
2427
+ const existingIndex = mergedRelationsRaw.findIndex((r) => r.relationName === name);
2428
+ if (existingIndex === -1) {
2429
+ mergedRelationsRaw.push(manual);
2430
+ } else {
2431
+ mergedRelationsRaw[existingIndex] = {
2432
+ ...manual,
2433
+ ...mergedRelationsRaw[existingIndex]
2434
+ };
2435
+ }
2424
2436
  }
2425
2437
  }
2426
2438
  let mergedRelations = mergedRelationsRaw;
@@ -2640,6 +2652,118 @@
2640
2652
  };
2641
2653
  }
2642
2654
  }
2655
+ function mapOperator(op) {
2656
+ switch (op) {
2657
+ case "==":
2658
+ return "eq";
2659
+ case "!=":
2660
+ return "neq";
2661
+ case ">":
2662
+ return "gt";
2663
+ case ">=":
2664
+ return "gte";
2665
+ case "<":
2666
+ return "lt";
2667
+ case "<=":
2668
+ return "lte";
2669
+ case "array-contains":
2670
+ return "cs";
2671
+ case "array-contains-any":
2672
+ return "csa";
2673
+ case "not-in":
2674
+ return "nin";
2675
+ default:
2676
+ return op;
2677
+ }
2678
+ }
2679
+ class QueryBuilder {
2680
+ constructor(collection) {
2681
+ this.collection = collection;
2682
+ }
2683
+ params = {
2684
+ where: {}
2685
+ };
2686
+ /**
2687
+ * Add a filter condition to your query.
2688
+ * @example
2689
+ * client.collection('users').where('age', '>=', 18).find()
2690
+ */
2691
+ where(column, operator, value) {
2692
+ if (!this.params.where) {
2693
+ this.params.where = {};
2694
+ }
2695
+ const mappedOp = mapOperator(operator);
2696
+ let formattedValue = value;
2697
+ if (Array.isArray(value) && ["in", "nin", "cs", "csa"].includes(mappedOp)) {
2698
+ formattedValue = `(${value.join(",")})`;
2699
+ } else if (value === null) {
2700
+ formattedValue = "null";
2701
+ }
2702
+ this.params.where[column] = mappedOp === "eq" ? String(formattedValue) : `${mappedOp}.${formattedValue}`;
2703
+ return this;
2704
+ }
2705
+ /**
2706
+ * Order the results by a specific column.
2707
+ * @example
2708
+ * client.collection('users').orderBy('createdAt', 'desc').find()
2709
+ */
2710
+ orderBy(column, ascending = "asc") {
2711
+ this.params.orderBy = `${column}:${ascending}`;
2712
+ return this;
2713
+ }
2714
+ /**
2715
+ * Limit the number of results returned.
2716
+ */
2717
+ limit(count) {
2718
+ this.params.limit = count;
2719
+ return this;
2720
+ }
2721
+ /**
2722
+ * Skip the first N results.
2723
+ */
2724
+ offset(count) {
2725
+ this.params.offset = count;
2726
+ return this;
2727
+ }
2728
+ /**
2729
+ * Set a free-text search string if supported by the backend.
2730
+ */
2731
+ search(searchString) {
2732
+ this.params.searchString = searchString;
2733
+ return this;
2734
+ }
2735
+ /**
2736
+ * Include related entities in the response.
2737
+ * Relations will be populated with full entity data instead of just IDs.
2738
+ *
2739
+ * @param relations - Relation names to include, or "*" for all.
2740
+ * @example
2741
+ * // Include specific relations
2742
+ * client.data.posts.include("tags", "author").find()
2743
+ *
2744
+ * // Include all relations
2745
+ * client.data.posts.include("*").find()
2746
+ */
2747
+ include(...relations) {
2748
+ this.params.include = relations;
2749
+ return this;
2750
+ }
2751
+ /**
2752
+ * Execute the find query and return the results.
2753
+ */
2754
+ async find() {
2755
+ return this.collection.find(this.params);
2756
+ }
2757
+ /**
2758
+ * Listen to realtime updates matching this query.
2759
+ */
2760
+ listen(onUpdate, onError) {
2761
+ if (!this.collection.listen) {
2762
+ throw new Error("Listen is only available when RebaseClient is configured with a websocketUrl.");
2763
+ }
2764
+ return this.collection.listen(this.params, onUpdate, onError);
2765
+ }
2766
+ }
2643
2767
  function convertWhereToFilter(where) {
2644
2768
  if (!where) return void 0;
2645
2769
  const operatorMap = {
@@ -2719,7 +2843,7 @@
2719
2843
  return [field, direction];
2720
2844
  }
2721
2845
  function createDriverAccessor(driver, slug) {
2722
- return {
2846
+ const accessor = {
2723
2847
  async find(params) {
2724
2848
  const orderParsed = parseOrderBy(params?.orderBy);
2725
2849
  const entities = await driver.fetchCollection({
@@ -2813,8 +2937,28 @@
2813
2937
  onUpdate: (entity) => onUpdate(entity ?? void 0),
2814
2938
  onError
2815
2939
  });
2816
- } : void 0
2940
+ } : void 0,
2941
+ // Fluent Query Builder
2942
+ where(column, operator, value) {
2943
+ return new QueryBuilder(accessor).where(column, operator, value);
2944
+ },
2945
+ orderBy(column, ascending) {
2946
+ return new QueryBuilder(accessor).orderBy(column, ascending);
2947
+ },
2948
+ limit(count) {
2949
+ return new QueryBuilder(accessor).limit(count);
2950
+ },
2951
+ offset(count) {
2952
+ return new QueryBuilder(accessor).offset(count);
2953
+ },
2954
+ search(searchString) {
2955
+ return new QueryBuilder(accessor).search(searchString);
2956
+ },
2957
+ include(...relations) {
2958
+ return new QueryBuilder(accessor).include(...relations);
2959
+ }
2817
2960
  };
2961
+ return accessor;
2818
2962
  }
2819
2963
  function buildRebaseData(driver) {
2820
2964
  const cache = /* @__PURE__ */ new Map();
@@ -6522,7 +6666,7 @@
6522
6666
  callbacks: void 0,
6523
6667
  propertyCallbacks: void 0
6524
6668
  };
6525
- const registryCollection = this.registry.getCollectionByPath(path2);
6669
+ const registryCollection = this.registry?.getCollectionByPath(path2);
6526
6670
  const resolvedCollection = registryCollection ? {
6527
6671
  ...collection,
6528
6672
  ...registryCollection
@@ -6570,7 +6714,8 @@
6570
6714
  user: this.user,
6571
6715
  driver: this,
6572
6716
  data: this.data,
6573
- client: this.client
6717
+ client: this.client,
6718
+ storageSource: this.client?.storage
6574
6719
  };
6575
6720
  return Promise.all(entities.map(async (entity) => {
6576
6721
  let fetched = entity;
@@ -6665,7 +6810,8 @@
6665
6810
  user: this.user,
6666
6811
  driver: this,
6667
6812
  data: this.data,
6668
- client: this.client
6813
+ client: this.client,
6814
+ storageSource: this.client?.storage
6669
6815
  };
6670
6816
  if (callbacks?.afterRead) {
6671
6817
  entity = await callbacks.afterRead({
@@ -6735,7 +6881,8 @@
6735
6881
  user: this.user,
6736
6882
  driver: this,
6737
6883
  data: this.data,
6738
- client: this.client
6884
+ client: this.client,
6885
+ storageSource: this.client?.storage
6739
6886
  };
6740
6887
  let previousValuesForHistory;
6741
6888
  if (status === "existing" && entityId) {
@@ -6884,7 +7031,8 @@
6884
7031
  user: this.user,
6885
7032
  driver: this,
6886
7033
  data: this.data,
6887
- client: this.client
7034
+ client: this.client,
7035
+ storageSource: this.client?.storage
6888
7036
  };
6889
7037
  if (callbacks?.beforeDelete || propertyCallbacks?.beforeDelete) {
6890
7038
  let preventDefault = false;
@@ -8163,6 +8311,7 @@ ${tableRelations.join(",\n")}
8163
8311
  singularName: "User",
8164
8312
  slug: "users",
8165
8313
  table: "users",
8314
+ schema: "rebase",
8166
8315
  icon: "Users",
8167
8316
  group: "Settings",
8168
8317
  properties: {