@rebasepro/server-core 0.0.1-canary.bbcb8b4 → 0.0.1-canary.c53f5db

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.es.js CHANGED
@@ -1721,8 +1721,8 @@ var logic = { exports: {} };
1721
1721
  return jsonLogic;
1722
1722
  });
1723
1723
  })(logic);
1724
- var getOwnPropertyNames = Object.getOwnPropertyNames, getOwnPropertySymbols = Object.getOwnPropertySymbols;
1725
- var hasOwnProperty$d = Object.prototype.hasOwnProperty;
1724
+ const { getOwnPropertyNames, getOwnPropertySymbols } = Object;
1725
+ const { hasOwnProperty: hasOwnProperty$d } = Object.prototype;
1726
1726
  function combineComparators(comparatorA, comparatorB) {
1727
1727
  return function isEqual(a2, b, state) {
1728
1728
  return comparatorA(a2, b, state) && comparatorB(a2, b, state);
@@ -1733,38 +1733,45 @@ function createIsCircular(areItemsEqual) {
1733
1733
  if (!a2 || !b || typeof a2 !== "object" || typeof b !== "object") {
1734
1734
  return areItemsEqual(a2, b, state);
1735
1735
  }
1736
- var cache2 = state.cache;
1737
- var cachedA = cache2.get(a2);
1738
- var cachedB = cache2.get(b);
1736
+ const { cache: cache2 } = state;
1737
+ const cachedA = cache2.get(a2);
1738
+ const cachedB = cache2.get(b);
1739
1739
  if (cachedA && cachedB) {
1740
1740
  return cachedA === b && cachedB === a2;
1741
1741
  }
1742
1742
  cache2.set(a2, b);
1743
1743
  cache2.set(b, a2);
1744
- var result = areItemsEqual(a2, b, state);
1744
+ const result = areItemsEqual(a2, b, state);
1745
1745
  cache2.delete(a2);
1746
1746
  cache2.delete(b);
1747
1747
  return result;
1748
1748
  };
1749
1749
  }
1750
- function getShortTag(value) {
1751
- return value != null ? value[Symbol.toStringTag] : void 0;
1752
- }
1753
1750
  function getStrictProperties(object) {
1754
1751
  return getOwnPropertyNames(object).concat(getOwnPropertySymbols(object));
1755
1752
  }
1756
- var hasOwn$1 = Object.hasOwn || function(object, property) {
1757
- return hasOwnProperty$d.call(object, property);
1758
- };
1759
- function sameValueZeroEqual(a2, b) {
1760
- return a2 === b || !a2 && !b && a2 !== a2 && b !== b;
1753
+ const hasOwn$1 = (
1754
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
1755
+ Object.hasOwn || ((object, property) => hasOwnProperty$d.call(object, property))
1756
+ );
1757
+ const PREACT_VNODE = "__v";
1758
+ const PREACT_OWNER = "__o";
1759
+ const REACT_OWNER = "_owner";
1760
+ const { getOwnPropertyDescriptor, keys: keys$5 } = Object;
1761
+ const sameValueEqual = (
1762
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
1763
+ Object.is || function sameValueEqual2(a2, b) {
1764
+ return a2 === b ? a2 !== 0 || 1 / a2 === 1 / b : a2 !== a2 && b !== b;
1765
+ }
1766
+ );
1767
+ function strictEqual(a2, b) {
1768
+ return a2 === b;
1769
+ }
1770
+ function areArrayBuffersEqual(a2, b) {
1771
+ return a2.byteLength === b.byteLength && areTypedArraysEqual(new Uint8Array(a2), new Uint8Array(b));
1761
1772
  }
1762
- var PREACT_VNODE = "__v";
1763
- var PREACT_OWNER = "__o";
1764
- var REACT_OWNER = "_owner";
1765
- var getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor, keys$5 = Object.keys;
1766
1773
  function areArraysEqual(a2, b, state) {
1767
- var index = a2.length;
1774
+ let index = a2.length;
1768
1775
  if (b.length !== index) {
1769
1776
  return false;
1770
1777
  }
@@ -1775,35 +1782,35 @@ function areArraysEqual(a2, b, state) {
1775
1782
  }
1776
1783
  return true;
1777
1784
  }
1785
+ function areDataViewsEqual(a2, b) {
1786
+ return a2.byteLength === b.byteLength && areTypedArraysEqual(new Uint8Array(a2.buffer, a2.byteOffset, a2.byteLength), new Uint8Array(b.buffer, b.byteOffset, b.byteLength));
1787
+ }
1778
1788
  function areDatesEqual(a2, b) {
1779
- return sameValueZeroEqual(a2.getTime(), b.getTime());
1789
+ return sameValueEqual(a2.getTime(), b.getTime());
1780
1790
  }
1781
1791
  function areErrorsEqual(a2, b) {
1782
1792
  return a2.name === b.name && a2.message === b.message && a2.cause === b.cause && a2.stack === b.stack;
1783
1793
  }
1784
- function areFunctionsEqual(a2, b) {
1785
- return a2 === b;
1786
- }
1787
1794
  function areMapsEqual(a2, b, state) {
1788
- var size = a2.size;
1795
+ const size = a2.size;
1789
1796
  if (size !== b.size) {
1790
1797
  return false;
1791
1798
  }
1792
1799
  if (!size) {
1793
1800
  return true;
1794
1801
  }
1795
- var matchedIndices = new Array(size);
1796
- var aIterable = a2.entries();
1797
- var aResult;
1798
- var bResult;
1799
- var index = 0;
1802
+ const matchedIndices = new Array(size);
1803
+ const aIterable = a2.entries();
1804
+ let aResult;
1805
+ let bResult;
1806
+ let index = 0;
1800
1807
  while (aResult = aIterable.next()) {
1801
1808
  if (aResult.done) {
1802
1809
  break;
1803
1810
  }
1804
- var bIterable = b.entries();
1805
- var hasMatch = false;
1806
- var matchIndex = 0;
1811
+ const bIterable = b.entries();
1812
+ let hasMatch = false;
1813
+ let matchIndex = 0;
1807
1814
  while (bResult = bIterable.next()) {
1808
1815
  if (bResult.done) {
1809
1816
  break;
@@ -1812,8 +1819,8 @@ function areMapsEqual(a2, b, state) {
1812
1819
  matchIndex++;
1813
1820
  continue;
1814
1821
  }
1815
- var aEntry = aResult.value;
1816
- var bEntry = bResult.value;
1822
+ const aEntry = aResult.value;
1823
+ const bEntry = bResult.value;
1817
1824
  if (state.equals(aEntry[0], bEntry[0], index, matchIndex, a2, b, state) && state.equals(aEntry[1], bEntry[1], aEntry[0], bEntry[0], a2, b, state)) {
1818
1825
  hasMatch = matchedIndices[matchIndex] = true;
1819
1826
  break;
@@ -1827,10 +1834,9 @@ function areMapsEqual(a2, b, state) {
1827
1834
  }
1828
1835
  return true;
1829
1836
  }
1830
- var areNumbersEqual = sameValueZeroEqual;
1831
1837
  function areObjectsEqual(a2, b, state) {
1832
- var properties = keys$5(a2);
1833
- var index = properties.length;
1838
+ const properties = keys$5(a2);
1839
+ let index = properties.length;
1834
1840
  if (keys$5(b).length !== index) {
1835
1841
  return false;
1836
1842
  }
@@ -1842,14 +1848,14 @@ function areObjectsEqual(a2, b, state) {
1842
1848
  return true;
1843
1849
  }
1844
1850
  function areObjectsEqualStrict(a2, b, state) {
1845
- var properties = getStrictProperties(a2);
1846
- var index = properties.length;
1851
+ const properties = getStrictProperties(a2);
1852
+ let index = properties.length;
1847
1853
  if (getStrictProperties(b).length !== index) {
1848
1854
  return false;
1849
1855
  }
1850
- var property;
1851
- var descriptorA;
1852
- var descriptorB;
1856
+ let property;
1857
+ let descriptorA;
1858
+ let descriptorB;
1853
1859
  while (index-- > 0) {
1854
1860
  property = properties[index];
1855
1861
  if (!isPropertyEqual(a2, b, state, property)) {
@@ -1864,30 +1870,30 @@ function areObjectsEqualStrict(a2, b, state) {
1864
1870
  return true;
1865
1871
  }
1866
1872
  function arePrimitiveWrappersEqual(a2, b) {
1867
- return sameValueZeroEqual(a2.valueOf(), b.valueOf());
1873
+ return sameValueEqual(a2.valueOf(), b.valueOf());
1868
1874
  }
1869
1875
  function areRegExpsEqual(a2, b) {
1870
1876
  return a2.source === b.source && a2.flags === b.flags;
1871
1877
  }
1872
1878
  function areSetsEqual(a2, b, state) {
1873
- var size = a2.size;
1879
+ const size = a2.size;
1874
1880
  if (size !== b.size) {
1875
1881
  return false;
1876
1882
  }
1877
1883
  if (!size) {
1878
1884
  return true;
1879
1885
  }
1880
- var matchedIndices = new Array(size);
1881
- var aIterable = a2.values();
1882
- var aResult;
1883
- var bResult;
1886
+ const matchedIndices = new Array(size);
1887
+ const aIterable = a2.values();
1888
+ let aResult;
1889
+ let bResult;
1884
1890
  while (aResult = aIterable.next()) {
1885
1891
  if (aResult.done) {
1886
1892
  break;
1887
1893
  }
1888
- var bIterable = b.values();
1889
- var hasMatch = false;
1890
- var matchIndex = 0;
1894
+ const bIterable = b.values();
1895
+ let hasMatch = false;
1896
+ let matchIndex = 0;
1891
1897
  while (bResult = bIterable.next()) {
1892
1898
  if (bResult.done) {
1893
1899
  break;
@@ -1905,8 +1911,8 @@ function areSetsEqual(a2, b, state) {
1905
1911
  return true;
1906
1912
  }
1907
1913
  function areTypedArraysEqual(a2, b) {
1908
- var index = a2.length;
1909
- if (b.length !== index) {
1914
+ let index = a2.byteLength;
1915
+ if (b.byteLength !== index || a2.byteOffset !== b.byteOffset) {
1910
1916
  return false;
1911
1917
  }
1912
1918
  while (index-- > 0) {
@@ -1925,23 +1931,10 @@ function isPropertyEqual(a2, b, state, property) {
1925
1931
  }
1926
1932
  return hasOwn$1(b, property) && state.equals(a2[property], b[property], property, property, a2, b, state);
1927
1933
  }
1928
- var ARGUMENTS_TAG = "[object Arguments]";
1929
- var BOOLEAN_TAG = "[object Boolean]";
1930
- var DATE_TAG = "[object Date]";
1931
- var ERROR_TAG = "[object Error]";
1932
- var MAP_TAG = "[object Map]";
1933
- var NUMBER_TAG = "[object Number]";
1934
- var OBJECT_TAG = "[object Object]";
1935
- var REG_EXP_TAG = "[object RegExp]";
1936
- var SET_TAG = "[object Set]";
1937
- var STRING_TAG = "[object String]";
1938
- var URL_TAG = "[object URL]";
1939
- var isArray$7 = Array.isArray;
1940
- var isTypedArray$2 = typeof ArrayBuffer === "function" && ArrayBuffer.isView ? ArrayBuffer.isView : null;
1941
- var assign$1 = Object.assign;
1942
- var getTag$4 = Object.prototype.toString.call.bind(Object.prototype.toString);
1943
- function createEqualityComparator(_a2) {
1944
- var areArraysEqual2 = _a2.areArraysEqual, areDatesEqual2 = _a2.areDatesEqual, areErrorsEqual2 = _a2.areErrorsEqual, areFunctionsEqual2 = _a2.areFunctionsEqual, areMapsEqual2 = _a2.areMapsEqual, areNumbersEqual2 = _a2.areNumbersEqual, areObjectsEqual2 = _a2.areObjectsEqual, arePrimitiveWrappersEqual2 = _a2.arePrimitiveWrappersEqual, areRegExpsEqual2 = _a2.areRegExpsEqual, areSetsEqual2 = _a2.areSetsEqual, areTypedArraysEqual2 = _a2.areTypedArraysEqual, areUrlsEqual2 = _a2.areUrlsEqual, unknownTagComparators = _a2.unknownTagComparators;
1934
+ const toString$2 = Object.prototype.toString;
1935
+ function createEqualityComparator(config) {
1936
+ const supportedComparatorMap = createSupportedComparatorMap(config);
1937
+ const { areArraysEqual: areArraysEqual2, areDatesEqual: areDatesEqual2, areFunctionsEqual, areMapsEqual: areMapsEqual2, areNumbersEqual, areObjectsEqual: areObjectsEqual2, areRegExpsEqual: areRegExpsEqual2, areSetsEqual: areSetsEqual2, getUnsupportedCustomComparator } = config;
1945
1938
  return function comparator2(a2, b, state) {
1946
1939
  if (a2 === b) {
1947
1940
  return true;
@@ -1949,32 +1942,29 @@ function createEqualityComparator(_a2) {
1949
1942
  if (a2 == null || b == null) {
1950
1943
  return false;
1951
1944
  }
1952
- var type = typeof a2;
1945
+ const type = typeof a2;
1953
1946
  if (type !== typeof b) {
1954
1947
  return false;
1955
1948
  }
1956
1949
  if (type !== "object") {
1957
- if (type === "number") {
1958
- return areNumbersEqual2(a2, b, state);
1950
+ if (type === "number" || type === "bigint") {
1951
+ return areNumbersEqual(a2, b, state);
1959
1952
  }
1960
1953
  if (type === "function") {
1961
- return areFunctionsEqual2(a2, b, state);
1954
+ return areFunctionsEqual(a2, b, state);
1962
1955
  }
1963
1956
  return false;
1964
1957
  }
1965
- var constructor = a2.constructor;
1958
+ const constructor = a2.constructor;
1966
1959
  if (constructor !== b.constructor) {
1967
1960
  return false;
1968
1961
  }
1969
1962
  if (constructor === Object) {
1970
1963
  return areObjectsEqual2(a2, b, state);
1971
1964
  }
1972
- if (isArray$7(a2)) {
1965
+ if (constructor === Array) {
1973
1966
  return areArraysEqual2(a2, b, state);
1974
1967
  }
1975
- if (isTypedArray$2 != null && isTypedArray$2(a2)) {
1976
- return areTypedArraysEqual2(a2, b, state);
1977
- }
1978
1968
  if (constructor === Date) {
1979
1969
  return areDatesEqual2(a2, b, state);
1980
1970
  }
@@ -1987,79 +1977,55 @@ function createEqualityComparator(_a2) {
1987
1977
  if (constructor === Set) {
1988
1978
  return areSetsEqual2(a2, b, state);
1989
1979
  }
1990
- var tag2 = getTag$4(a2);
1991
- if (tag2 === DATE_TAG) {
1992
- return areDatesEqual2(a2, b, state);
1993
- }
1994
- if (tag2 === REG_EXP_TAG) {
1995
- return areRegExpsEqual2(a2, b, state);
1996
- }
1997
- if (tag2 === MAP_TAG) {
1998
- return areMapsEqual2(a2, b, state);
1999
- }
2000
- if (tag2 === SET_TAG) {
2001
- return areSetsEqual2(a2, b, state);
2002
- }
2003
- if (tag2 === OBJECT_TAG) {
2004
- return typeof a2.then !== "function" && typeof b.then !== "function" && areObjectsEqual2(a2, b, state);
1980
+ if (constructor === Promise) {
1981
+ return false;
2005
1982
  }
2006
- if (tag2 === URL_TAG) {
2007
- return areUrlsEqual2(a2, b, state);
1983
+ if (Array.isArray(a2)) {
1984
+ return areArraysEqual2(a2, b, state);
2008
1985
  }
2009
- if (tag2 === ERROR_TAG) {
2010
- return areErrorsEqual2(a2, b, state);
1986
+ const tag2 = toString$2.call(a2);
1987
+ const supportedComparator = supportedComparatorMap[tag2];
1988
+ if (supportedComparator) {
1989
+ return supportedComparator(a2, b, state);
2011
1990
  }
2012
- if (tag2 === ARGUMENTS_TAG) {
2013
- return areObjectsEqual2(a2, b, state);
2014
- }
2015
- if (tag2 === BOOLEAN_TAG || tag2 === NUMBER_TAG || tag2 === STRING_TAG) {
2016
- return arePrimitiveWrappersEqual2(a2, b, state);
2017
- }
2018
- if (unknownTagComparators) {
2019
- var unknownTagComparator = unknownTagComparators[tag2];
2020
- if (!unknownTagComparator) {
2021
- var shortTag = getShortTag(a2);
2022
- if (shortTag) {
2023
- unknownTagComparator = unknownTagComparators[shortTag];
2024
- }
2025
- }
2026
- if (unknownTagComparator) {
2027
- return unknownTagComparator(a2, b, state);
2028
- }
1991
+ const unsupportedCustomComparator = getUnsupportedCustomComparator && getUnsupportedCustomComparator(a2, b, state, tag2);
1992
+ if (unsupportedCustomComparator) {
1993
+ return unsupportedCustomComparator(a2, b, state);
2029
1994
  }
2030
1995
  return false;
2031
1996
  };
2032
1997
  }
2033
- function createEqualityComparatorConfig(_a2) {
2034
- var circular = _a2.circular, createCustomConfig = _a2.createCustomConfig, strict = _a2.strict;
2035
- var config = {
1998
+ function createEqualityComparatorConfig({ circular, createCustomConfig, strict }) {
1999
+ let config = {
2000
+ areArrayBuffersEqual,
2036
2001
  areArraysEqual: strict ? areObjectsEqualStrict : areArraysEqual,
2002
+ areDataViewsEqual,
2037
2003
  areDatesEqual,
2038
2004
  areErrorsEqual,
2039
- areFunctionsEqual,
2005
+ areFunctionsEqual: strictEqual,
2040
2006
  areMapsEqual: strict ? combineComparators(areMapsEqual, areObjectsEqualStrict) : areMapsEqual,
2041
- areNumbersEqual,
2007
+ areNumbersEqual: sameValueEqual,
2042
2008
  areObjectsEqual: strict ? areObjectsEqualStrict : areObjectsEqual,
2043
2009
  arePrimitiveWrappersEqual,
2044
2010
  areRegExpsEqual,
2045
2011
  areSetsEqual: strict ? combineComparators(areSetsEqual, areObjectsEqualStrict) : areSetsEqual,
2046
- areTypedArraysEqual: strict ? areObjectsEqualStrict : areTypedArraysEqual,
2012
+ areTypedArraysEqual: strict ? combineComparators(areTypedArraysEqual, areObjectsEqualStrict) : areTypedArraysEqual,
2047
2013
  areUrlsEqual,
2048
- unknownTagComparators: void 0
2014
+ getUnsupportedCustomComparator: void 0
2049
2015
  };
2050
2016
  if (createCustomConfig) {
2051
- config = assign$1({}, config, createCustomConfig(config));
2017
+ config = Object.assign({}, config, createCustomConfig(config));
2052
2018
  }
2053
2019
  if (circular) {
2054
- var areArraysEqual$1 = createIsCircular(config.areArraysEqual);
2055
- var areMapsEqual$1 = createIsCircular(config.areMapsEqual);
2056
- var areObjectsEqual$1 = createIsCircular(config.areObjectsEqual);
2057
- var areSetsEqual$1 = createIsCircular(config.areSetsEqual);
2058
- config = assign$1({}, config, {
2059
- areArraysEqual: areArraysEqual$1,
2060
- areMapsEqual: areMapsEqual$1,
2061
- areObjectsEqual: areObjectsEqual$1,
2062
- areSetsEqual: areSetsEqual$1
2020
+ const areArraysEqual2 = createIsCircular(config.areArraysEqual);
2021
+ const areMapsEqual2 = createIsCircular(config.areMapsEqual);
2022
+ const areObjectsEqual2 = createIsCircular(config.areObjectsEqual);
2023
+ const areSetsEqual2 = createIsCircular(config.areSetsEqual);
2024
+ config = Object.assign({}, config, {
2025
+ areArraysEqual: areArraysEqual2,
2026
+ areMapsEqual: areMapsEqual2,
2027
+ areObjectsEqual: areObjectsEqual2,
2028
+ areSetsEqual: areSetsEqual2
2063
2029
  });
2064
2030
  }
2065
2031
  return config;
@@ -2069,11 +2035,10 @@ function createInternalEqualityComparator(compare2) {
2069
2035
  return compare2(a2, b, state);
2070
2036
  };
2071
2037
  }
2072
- function createIsEqual(_a2) {
2073
- var circular = _a2.circular, comparator2 = _a2.comparator, createState = _a2.createState, equals = _a2.equals, strict = _a2.strict;
2038
+ function createIsEqual({ circular, comparator: comparator2, createState, equals, strict }) {
2074
2039
  if (createState) {
2075
2040
  return function isEqual(a2, b) {
2076
- var _a3 = createState(), _b2 = _a3.cache, cache2 = _b2 === void 0 ? circular ? /* @__PURE__ */ new WeakMap() : void 0 : _b2, meta = _a3.meta;
2041
+ const { cache: cache2 = circular ? /* @__PURE__ */ new WeakMap() : void 0, meta } = createState();
2077
2042
  return comparator2(a2, b, {
2078
2043
  cache: cache2,
2079
2044
  equals,
@@ -2092,7 +2057,7 @@ function createIsEqual(_a2) {
2092
2057
  });
2093
2058
  };
2094
2059
  }
2095
- var state = {
2060
+ const state = {
2096
2061
  cache: void 0,
2097
2062
  equals,
2098
2063
  meta: void 0,
@@ -2102,7 +2067,50 @@ function createIsEqual(_a2) {
2102
2067
  return comparator2(a2, b, state);
2103
2068
  };
2104
2069
  }
2105
- var deepEqual = createCustomEqual();
2070
+ function createSupportedComparatorMap({ areArrayBuffersEqual: areArrayBuffersEqual2, areArraysEqual: areArraysEqual2, areDataViewsEqual: areDataViewsEqual2, areDatesEqual: areDatesEqual2, areErrorsEqual: areErrorsEqual2, areFunctionsEqual, areMapsEqual: areMapsEqual2, areNumbersEqual, areObjectsEqual: areObjectsEqual2, arePrimitiveWrappersEqual: arePrimitiveWrappersEqual2, areRegExpsEqual: areRegExpsEqual2, areSetsEqual: areSetsEqual2, areTypedArraysEqual: areTypedArraysEqual2, areUrlsEqual: areUrlsEqual2 }) {
2071
+ return {
2072
+ "[object Arguments]": areObjectsEqual2,
2073
+ "[object Array]": areArraysEqual2,
2074
+ "[object ArrayBuffer]": areArrayBuffersEqual2,
2075
+ "[object AsyncGeneratorFunction]": areFunctionsEqual,
2076
+ "[object BigInt]": areNumbersEqual,
2077
+ "[object BigInt64Array]": areTypedArraysEqual2,
2078
+ "[object BigUint64Array]": areTypedArraysEqual2,
2079
+ "[object Boolean]": arePrimitiveWrappersEqual2,
2080
+ "[object DataView]": areDataViewsEqual2,
2081
+ "[object Date]": areDatesEqual2,
2082
+ // If an error tag, it should be tested explicitly. Like RegExp, the properties are not
2083
+ // enumerable, and therefore will give false positives if tested like a standard object.
2084
+ "[object Error]": areErrorsEqual2,
2085
+ "[object Float16Array]": areTypedArraysEqual2,
2086
+ "[object Float32Array]": areTypedArraysEqual2,
2087
+ "[object Float64Array]": areTypedArraysEqual2,
2088
+ "[object Function]": areFunctionsEqual,
2089
+ "[object GeneratorFunction]": areFunctionsEqual,
2090
+ "[object Int8Array]": areTypedArraysEqual2,
2091
+ "[object Int16Array]": areTypedArraysEqual2,
2092
+ "[object Int32Array]": areTypedArraysEqual2,
2093
+ "[object Map]": areMapsEqual2,
2094
+ "[object Number]": arePrimitiveWrappersEqual2,
2095
+ "[object Object]": (a2, b, state) => (
2096
+ // The exception for value comparison is custom `Promise`-like class instances. These should
2097
+ // be treated the same as standard `Promise` objects, which means strict equality, and if
2098
+ // it reaches this point then that strict equality comparison has already failed.
2099
+ typeof a2.then !== "function" && typeof b.then !== "function" && areObjectsEqual2(a2, b, state)
2100
+ ),
2101
+ // For RegExp, the properties are not enumerable, and therefore will give false positives if
2102
+ // tested like a standard object.
2103
+ "[object RegExp]": areRegExpsEqual2,
2104
+ "[object Set]": areSetsEqual2,
2105
+ "[object String]": arePrimitiveWrappersEqual2,
2106
+ "[object URL]": areUrlsEqual2,
2107
+ "[object Uint8Array]": areTypedArraysEqual2,
2108
+ "[object Uint8ClampedArray]": areTypedArraysEqual2,
2109
+ "[object Uint16Array]": areTypedArraysEqual2,
2110
+ "[object Uint32Array]": areTypedArraysEqual2
2111
+ };
2112
+ }
2113
+ const deepEqual = createCustomEqual();
2106
2114
  createCustomEqual({ strict: true });
2107
2115
  createCustomEqual({ circular: true });
2108
2116
  createCustomEqual({
@@ -2110,37 +2118,26 @@ createCustomEqual({
2110
2118
  strict: true
2111
2119
  });
2112
2120
  createCustomEqual({
2113
- createInternalComparator: function() {
2114
- return sameValueZeroEqual;
2115
- }
2121
+ createInternalComparator: () => sameValueEqual
2116
2122
  });
2117
2123
  createCustomEqual({
2118
2124
  strict: true,
2119
- createInternalComparator: function() {
2120
- return sameValueZeroEqual;
2121
- }
2125
+ createInternalComparator: () => sameValueEqual
2122
2126
  });
2123
2127
  createCustomEqual({
2124
2128
  circular: true,
2125
- createInternalComparator: function() {
2126
- return sameValueZeroEqual;
2127
- }
2129
+ createInternalComparator: () => sameValueEqual
2128
2130
  });
2129
2131
  createCustomEqual({
2130
2132
  circular: true,
2131
- createInternalComparator: function() {
2132
- return sameValueZeroEqual;
2133
- },
2133
+ createInternalComparator: () => sameValueEqual,
2134
2134
  strict: true
2135
2135
  });
2136
- function createCustomEqual(options2) {
2137
- if (options2 === void 0) {
2138
- options2 = {};
2139
- }
2140
- var _a2 = options2.circular, circular = _a2 === void 0 ? false : _a2, createCustomInternalComparator = options2.createInternalComparator, createState = options2.createState, _b2 = options2.strict, strict = _b2 === void 0 ? false : _b2;
2141
- var config = createEqualityComparatorConfig(options2);
2142
- var comparator2 = createEqualityComparator(config);
2143
- var equals = createCustomInternalComparator ? createCustomInternalComparator(comparator2) : createInternalEqualityComparator(comparator2);
2136
+ function createCustomEqual(options2 = {}) {
2137
+ const { circular = false, createInternalComparator: createCustomInternalComparator, createState, strict = false } = options2;
2138
+ const config = createEqualityComparatorConfig(options2);
2139
+ const comparator2 = createEqualityComparator(config);
2140
+ const equals = createCustomInternalComparator ? createCustomInternalComparator(comparator2) : createInternalEqualityComparator(comparator2);
2144
2141
  return createIsEqual({ circular, comparator: comparator2, createState, equals, strict });
2145
2142
  }
2146
2143
  function listCacheClear$1() {
@@ -3390,7 +3387,10 @@ class CollectionRegistry {
3390
3387
  if (!relation) {
3391
3388
  throw new Error(`Relation '${relationKey}' not found in collection '${currentCollection.slug}'`);
3392
3389
  }
3393
- currentCollection = relation.target();
3390
+ const target = relation.target();
3391
+ const targetRelationKey = relation.relationName || target.slug;
3392
+ const targetSlug = relation.overrides?.slug ?? targetRelationKey;
3393
+ currentCollection = this.get(targetSlug) || this.normalizeCollection(target);
3394
3394
  if (i + 1 < pathSegments.length) ;
3395
3395
  }
3396
3396
  return currentCollection;
@@ -3439,7 +3439,7 @@ class CollectionRegistry {
3439
3439
  if (!subcollection) {
3440
3440
  throw new Error(`Subcollection '${subcollectionSlug}' not found in ${currentCollection.slug}`);
3441
3441
  }
3442
- currentCollection = subcollection;
3442
+ currentCollection = this.get(subcollection.slug) || this.normalizeCollection(subcollection);
3443
3443
  collections.push(currentCollection);
3444
3444
  }
3445
3445
  }
@@ -3806,11 +3806,24 @@ class RestApiGenerator {
3806
3806
  collections;
3807
3807
  router;
3808
3808
  driver;
3809
- constructor(collections, driver) {
3809
+ dataHooks;
3810
+ constructor(collections, driver, dataHooks) {
3810
3811
  this.collections = collections;
3811
3812
  this.driver = driver;
3813
+ this.dataHooks = dataHooks;
3812
3814
  this.router = new Hono();
3813
3815
  }
3816
+ /** Build a BackendHookContext from a Hono context */
3817
+ buildHookContext(c, method) {
3818
+ const user = c.get("user");
3819
+ return {
3820
+ requestUser: user ? {
3821
+ userId: user.userId,
3822
+ roles: user.roles ?? []
3823
+ } : void 0,
3824
+ method
3825
+ };
3826
+ }
3814
3827
  /**
3815
3828
  * Generate REST routes using existing DataDriver
3816
3829
  */
@@ -3822,16 +3835,10 @@ class RestApiGenerator {
3822
3835
  return this.router;
3823
3836
  }
3824
3837
  /**
3825
- * Get the EntityFetchService from a driver if it exposes one (for include support)
3838
+ * Get the typed RestFetchService from a driver if it exposes one (for include support).
3826
3839
  */
3827
3840
  getFetchService(driver) {
3828
- if ("entityService" in driver && typeof driver.entityService === "object" && driver.entityService) {
3829
- const es = driver.entityService;
3830
- if (typeof es.getFetchService === "function") {
3831
- return es.getFetchService();
3832
- }
3833
- }
3834
- return null;
3841
+ return driver.restFetchService;
3835
3842
  }
3836
3843
  /**
3837
3844
  * Create REST routes for a collection using existing Rebase patterns
@@ -3839,15 +3846,26 @@ class RestApiGenerator {
3839
3846
  createCollectionRoutes(collection) {
3840
3847
  const basePath = `/${collection.slug}`;
3841
3848
  const resolvedCollection = collection;
3849
+ this.router.get(`${basePath}/count`, async (c) => {
3850
+ const queryDict = c.req.query();
3851
+ const queryOptions = parseQueryOptions(queryDict);
3852
+ const searchString = queryDict.searchString;
3853
+ const driver = c.get("driver") || this.driver;
3854
+ const total = await this.countRawEntities(driver, resolvedCollection, queryOptions, searchString);
3855
+ return c.json({
3856
+ count: total
3857
+ });
3858
+ });
3842
3859
  this.router.get(basePath, async (c) => {
3843
3860
  const queryDict = c.req.query();
3844
3861
  const queryOptions = parseQueryOptions(queryDict);
3845
3862
  const searchString = queryDict.searchString;
3846
3863
  const driver = c.get("driver") || this.driver;
3847
3864
  const fetchService = this.getFetchService(driver);
3865
+ const hookCtx = this.buildHookContext(c, "GET");
3848
3866
  if (fetchService) {
3849
3867
  const collectionPath = collection.slug;
3850
- const entities2 = await fetchService.fetchCollectionForRest(collectionPath, {
3868
+ let entities2 = await fetchService.fetchCollectionForRest(collectionPath, {
3851
3869
  filter: queryOptions.where,
3852
3870
  limit: queryOptions.limit,
3853
3871
  offset: queryOptions.offset,
@@ -3855,6 +3873,7 @@ class RestApiGenerator {
3855
3873
  order: queryOptions.orderBy?.[0]?.direction === "desc" ? "desc" : "asc",
3856
3874
  searchString
3857
3875
  }, queryOptions.include);
3876
+ entities2 = await this.applyAfterReadBatch(collection.slug, entities2, hookCtx);
3858
3877
  const total2 = await this.countRawEntities(driver, resolvedCollection, queryOptions, searchString);
3859
3878
  return c.json({
3860
3879
  data: entities2,
@@ -3866,7 +3885,8 @@ class RestApiGenerator {
3866
3885
  }
3867
3886
  });
3868
3887
  }
3869
- const entities = await this.fetchRawCollection(driver, resolvedCollection, queryOptions, searchString);
3888
+ let entities = await this.fetchRawCollection(driver, resolvedCollection, queryOptions, searchString);
3889
+ entities = await this.applyAfterReadBatch(collection.slug, entities, hookCtx);
3870
3890
  const total = await this.countRawEntities(driver, resolvedCollection, queryOptions, searchString);
3871
3891
  return c.json({
3872
3892
  data: entities,
@@ -3884,15 +3904,24 @@ class RestApiGenerator {
3884
3904
  const queryOptions = parseQueryOptions(queryDict);
3885
3905
  const driver = c.get("driver") || this.driver;
3886
3906
  const fetchService = this.getFetchService(driver);
3907
+ const hookCtx = this.buildHookContext(c, "GET");
3887
3908
  if (fetchService) {
3888
3909
  const collectionPath = collection.slug;
3889
- const entity2 = await fetchService.fetchEntityForRest(collectionPath, String(id), queryOptions.include);
3910
+ let entity2 = await fetchService.fetchEntityForRest(collectionPath, String(id), queryOptions.include);
3911
+ if (!entity2) {
3912
+ throw ApiError.notFound("Entity not found");
3913
+ }
3914
+ entity2 = await this.applyAfterRead(collection.slug, entity2, hookCtx);
3890
3915
  if (!entity2) {
3891
3916
  throw ApiError.notFound("Entity not found");
3892
3917
  }
3893
3918
  return c.json(entity2);
3894
3919
  }
3895
- const entity = await this.fetchRawEntity(driver, resolvedCollection, String(id));
3920
+ let entity = await this.fetchRawEntity(driver, resolvedCollection, String(id));
3921
+ if (!entity) {
3922
+ throw ApiError.notFound("Entity not found");
3923
+ }
3924
+ entity = await this.applyAfterRead(collection.slug, entity, hookCtx);
3896
3925
  if (!entity) {
3897
3926
  throw ApiError.notFound("Entity not found");
3898
3927
  }
@@ -3902,14 +3931,24 @@ class RestApiGenerator {
3902
3931
  try {
3903
3932
  const driver = c.get("driver") || this.driver;
3904
3933
  const path2 = collection.slug;
3905
- const body = await c.req.json().catch(() => ({}));
3934
+ const hookCtx = this.buildHookContext(c, "POST");
3935
+ let body = await c.req.json().catch(() => ({}));
3936
+ if (this.dataHooks?.beforeSave) {
3937
+ body = await this.dataHooks.beforeSave(path2, body, void 0, hookCtx);
3938
+ }
3906
3939
  const entity = await driver.saveEntity({
3907
3940
  path: path2,
3908
3941
  values: body,
3909
3942
  collection: resolvedCollection,
3910
3943
  status: "new"
3911
3944
  });
3912
- return c.json(this.formatResponse(entity), 201);
3945
+ const response = this.formatResponse(entity);
3946
+ if (this.dataHooks?.afterSave) {
3947
+ Promise.resolve(this.dataHooks.afterSave(path2, response, hookCtx)).catch((err) => {
3948
+ console.error("[BackendHooks] data.afterSave error:", err instanceof Error ? err.message : err);
3949
+ });
3950
+ }
3951
+ return c.json(response, 201);
3913
3952
  } catch (error2) {
3914
3953
  const err = error2;
3915
3954
  err.code = err.code || "BAD_REQUEST";
@@ -3920,6 +3959,7 @@ class RestApiGenerator {
3920
3959
  try {
3921
3960
  const id = c.req.param("id");
3922
3961
  const driver = c.get("driver") || this.driver;
3962
+ const hookCtx = this.buildHookContext(c, "PUT");
3923
3963
  const existingEntity = await driver.fetchEntity({
3924
3964
  path: collection.slug,
3925
3965
  entityId: String(id),
@@ -3928,7 +3968,10 @@ class RestApiGenerator {
3928
3968
  if (!existingEntity) {
3929
3969
  throw ApiError.notFound("Entity not found");
3930
3970
  }
3931
- const body = await c.req.json().catch(() => ({}));
3971
+ let body = await c.req.json().catch(() => ({}));
3972
+ if (this.dataHooks?.beforeSave) {
3973
+ body = await this.dataHooks.beforeSave(collection.slug, body, String(id), hookCtx);
3974
+ }
3932
3975
  const entity = await driver.saveEntity({
3933
3976
  path: collection.slug,
3934
3977
  entityId: String(id),
@@ -3936,7 +3979,13 @@ class RestApiGenerator {
3936
3979
  collection: resolvedCollection,
3937
3980
  status: "existing"
3938
3981
  });
3939
- return c.json(this.formatResponse(entity));
3982
+ const response = this.formatResponse(entity);
3983
+ if (this.dataHooks?.afterSave) {
3984
+ Promise.resolve(this.dataHooks.afterSave(collection.slug, response, hookCtx)).catch((err) => {
3985
+ console.error("[BackendHooks] data.afterSave error:", err instanceof Error ? err.message : err);
3986
+ });
3987
+ }
3988
+ return c.json(response);
3940
3989
  } catch (error2) {
3941
3990
  const err = error2;
3942
3991
  err.code = err.code || "BAD_REQUEST";
@@ -3946,6 +3995,7 @@ class RestApiGenerator {
3946
3995
  this.router.delete(`${basePath}/:id`, async (c) => {
3947
3996
  const id = c.req.param("id");
3948
3997
  const driver = c.get("driver") || this.driver;
3998
+ const hookCtx = this.buildHookContext(c, "DELETE");
3949
3999
  const existingEntity = await driver.fetchEntity({
3950
4000
  path: collection.slug,
3951
4001
  entityId: String(id),
@@ -3954,10 +4004,18 @@ class RestApiGenerator {
3954
4004
  if (!existingEntity) {
3955
4005
  throw ApiError.notFound("Entity not found");
3956
4006
  }
4007
+ if (this.dataHooks?.beforeDelete) {
4008
+ await this.dataHooks.beforeDelete(collection.slug, String(id), hookCtx);
4009
+ }
3957
4010
  await driver.deleteEntity({
3958
4011
  entity: existingEntity,
3959
4012
  collection: resolvedCollection
3960
4013
  });
4014
+ if (this.dataHooks?.afterDelete) {
4015
+ Promise.resolve(this.dataHooks.afterDelete(collection.slug, String(id), hookCtx)).catch((err) => {
4016
+ console.error("[BackendHooks] data.afterDelete error:", err instanceof Error ? err.message : err);
4017
+ });
4018
+ }
3961
4019
  return new Response(null, {
3962
4020
  status: 204
3963
4021
  });
@@ -4006,7 +4064,18 @@ class RestApiGenerator {
4006
4064
  const parsed = parseSubPath(rawPath);
4007
4065
  if (!parsed) return next();
4008
4066
  const driver = c.get("driver") || this.driver;
4009
- if (parsed.entityId) {
4067
+ if (parsed.entityId === "count") {
4068
+ const queryDict = c.req.query();
4069
+ const queryOptions = parseQueryOptions(queryDict);
4070
+ const total = driver.countEntities ? await driver.countEntities({
4071
+ path: parsed.collectionPath,
4072
+ filter: queryOptions.where,
4073
+ searchString: queryDict.searchString
4074
+ }) : 0;
4075
+ return c.json({
4076
+ count: total
4077
+ });
4078
+ } else if (parsed.entityId) {
4010
4079
  const entity = await driver.fetchEntity({
4011
4080
  path: parsed.collectionPath,
4012
4081
  entityId: parsed.entityId
@@ -4164,6 +4233,22 @@ class RestApiGenerator {
4164
4233
  });
4165
4234
  return entity ? this.flattenEntity(entity) : null;
4166
4235
  }
4236
+ /**
4237
+ * Apply data.afterRead hook to a single entity.
4238
+ * Returns the transformed entity, or null to filter it out.
4239
+ */
4240
+ async applyAfterRead(slug, entity, ctx) {
4241
+ if (!this.dataHooks?.afterRead) return entity;
4242
+ return this.dataHooks.afterRead(slug, entity, ctx);
4243
+ }
4244
+ /**
4245
+ * Apply data.afterRead hook to an array of entities, filtering out nulls.
4246
+ */
4247
+ async applyAfterReadBatch(slug, entities, ctx) {
4248
+ if (!this.dataHooks?.afterRead) return entities;
4249
+ const results = await Promise.all(entities.map((e) => this.applyAfterRead(slug, e, ctx)));
4250
+ return results.filter((e) => e !== null);
4251
+ }
4167
4252
  }
4168
4253
  var jws$5 = {};
4169
4254
  var safeBuffer = { exports: {} };
@@ -23614,7 +23699,12 @@ function createRateLimiter(options2 = {}) {
23614
23699
  };
23615
23700
  }
23616
23701
  function defaultKeyGenerator(c) {
23617
- return c.req.header("x-forwarded-for")?.split(",")[0]?.trim() || c.req.header("x-real-ip") || "unknown";
23702
+ const forwardedFor = c.req.header("x-forwarded-for");
23703
+ if (forwardedFor) {
23704
+ const ips = forwardedFor.split(",");
23705
+ return ips[ips.length - 1].trim();
23706
+ }
23707
+ return c.req.header("x-real-ip") || "unknown";
23618
23708
  }
23619
23709
  const defaultAuthLimiter = createRateLimiter({
23620
23710
  windowMs: 15 * 60 * 1e3,
@@ -24182,8 +24272,45 @@ function createAdminRoutes(config) {
24182
24272
  const authRepo = config.authRepo;
24183
24273
  const {
24184
24274
  emailService,
24185
- emailConfig
24275
+ emailConfig,
24276
+ hooks
24186
24277
  } = config;
24278
+ function buildHookContext(c, method) {
24279
+ const user = c.get("user");
24280
+ return {
24281
+ requestUser: user ? {
24282
+ userId: user.userId,
24283
+ roles: user.roles ?? []
24284
+ } : void 0,
24285
+ method
24286
+ };
24287
+ }
24288
+ async function applyUserAfterRead(user, ctx) {
24289
+ if (!hooks?.users?.afterRead) return user;
24290
+ return hooks.users.afterRead(user, ctx);
24291
+ }
24292
+ async function applyUserAfterReadBatch(users, ctx) {
24293
+ if (!hooks?.users?.afterRead) return users;
24294
+ const results = await Promise.all(users.map((u) => applyUserAfterRead(u, ctx)));
24295
+ return results.filter((u) => u !== null);
24296
+ }
24297
+ async function applyRoleAfterReadBatch(roles, ctx) {
24298
+ if (!hooks?.roles?.afterRead) return roles;
24299
+ const results = await Promise.all(roles.map((r) => hooks.roles.afterRead(r, ctx)));
24300
+ return results.filter((r) => r !== null);
24301
+ }
24302
+ function toAdminUser(u, roles) {
24303
+ return {
24304
+ uid: u.id,
24305
+ email: u.email,
24306
+ displayName: u.displayName ?? null,
24307
+ photoURL: u.photoUrl ?? null,
24308
+ provider: "custom",
24309
+ roles,
24310
+ createdAt: u.createdAt instanceof Date ? u.createdAt.toISOString() : u.createdAt ?? (/* @__PURE__ */ new Date()).toISOString(),
24311
+ updatedAt: u.updatedAt instanceof Date ? u.updatedAt.toISOString() : u.updatedAt ?? (/* @__PURE__ */ new Date()).toISOString()
24312
+ };
24313
+ }
24187
24314
  router.onError(errorHandler);
24188
24315
  router.use("/*", createRequireAuth({
24189
24316
  serviceKey: config.serviceKey
@@ -24234,6 +24361,7 @@ function createAdminRoutes(config) {
24234
24361
  const search = c.req.query("search");
24235
24362
  const orderBy = c.req.query("orderBy");
24236
24363
  const orderDir = c.req.query("orderDir");
24364
+ const hookCtx = buildHookContext(c, "GET");
24237
24365
  if (limitParam !== void 0 || search) {
24238
24366
  const limit = limitParam ? parseInt(limitParam, 10) : 25;
24239
24367
  const offset = offsetParam ? parseInt(offsetParam, 10) : 0;
@@ -24245,18 +24373,11 @@ function createAdminRoutes(config) {
24245
24373
  orderDir: orderDir || void 0,
24246
24374
  roleId: c.req.query("role") || void 0
24247
24375
  });
24248
- const usersWithRoles2 = await Promise.all(result.users.map(async (u) => {
24376
+ let usersWithRoles2 = await Promise.all(result.users.map(async (u) => {
24249
24377
  const roles = await authRepo.getUserRoleIds(u.id);
24250
- return {
24251
- uid: u.id,
24252
- email: u.email,
24253
- displayName: u.displayName,
24254
- photoURL: u.photoUrl,
24255
- roles,
24256
- createdAt: u.createdAt,
24257
- updatedAt: u.updatedAt
24258
- };
24378
+ return toAdminUser(u, roles);
24259
24379
  }));
24380
+ usersWithRoles2 = await applyUserAfterReadBatch(usersWithRoles2, hookCtx);
24260
24381
  return c.json({
24261
24382
  users: usersWithRoles2,
24262
24383
  total: result.total,
@@ -24265,18 +24386,11 @@ function createAdminRoutes(config) {
24265
24386
  });
24266
24387
  }
24267
24388
  const users = await authRepo.listUsers();
24268
- const usersWithRoles = await Promise.all(users.map(async (u) => {
24389
+ let usersWithRoles = await Promise.all(users.map(async (u) => {
24269
24390
  const roles = await authRepo.getUserRoleIds(u.id);
24270
- return {
24271
- uid: u.id,
24272
- email: u.email,
24273
- displayName: u.displayName,
24274
- photoURL: u.photoUrl,
24275
- roles,
24276
- createdAt: u.createdAt,
24277
- updatedAt: u.updatedAt
24278
- };
24391
+ return toAdminUser(u, roles);
24279
24392
  }));
24393
+ usersWithRoles = await applyUserAfterReadBatch(usersWithRoles, hookCtx);
24280
24394
  return c.json({
24281
24395
  users: usersWithRoles
24282
24396
  });
@@ -24287,21 +24401,19 @@ function createAdminRoutes(config) {
24287
24401
  if (!result) {
24288
24402
  throw ApiError.notFound("User not found");
24289
24403
  }
24404
+ const hookCtx = buildHookContext(c, "GET");
24405
+ let adminUser = toAdminUser(result.user, result.roles.map((r) => r.id));
24406
+ adminUser = await applyUserAfterRead(adminUser, hookCtx);
24407
+ if (!adminUser) {
24408
+ throw ApiError.notFound("User not found");
24409
+ }
24290
24410
  return c.json({
24291
- user: {
24292
- uid: result.user.id,
24293
- email: result.user.email,
24294
- displayName: result.user.displayName,
24295
- photoURL: result.user.photoUrl,
24296
- roles: result.roles.map((r) => r.id),
24297
- createdAt: result.user.createdAt,
24298
- updatedAt: result.user.updatedAt
24299
- }
24411
+ user: adminUser
24300
24412
  });
24301
24413
  });
24302
24414
  router.post("/users", requireAdmin, async (c) => {
24303
24415
  const body = await c.req.json();
24304
- const {
24416
+ let {
24305
24417
  email,
24306
24418
  displayName,
24307
24419
  password,
@@ -24310,6 +24422,17 @@ function createAdminRoutes(config) {
24310
24422
  if (!email) {
24311
24423
  throw ApiError.badRequest("Email is required", "INVALID_INPUT");
24312
24424
  }
24425
+ const hookCtx = buildHookContext(c, "POST");
24426
+ if (hooks?.users?.beforeSave) {
24427
+ const hooked = await hooks.users.beforeSave({
24428
+ email,
24429
+ displayName,
24430
+ roles
24431
+ }, hookCtx);
24432
+ email = hooked.email ?? email;
24433
+ displayName = hooked.displayName ?? displayName;
24434
+ roles = hooked.roles ?? roles;
24435
+ }
24313
24436
  const existing = await authRepo.getUserByEmail(email);
24314
24437
  if (existing) {
24315
24438
  throw ApiError.conflict("Email already exists", "EMAIL_EXISTS");
@@ -24365,13 +24488,14 @@ function createAdminRoutes(config) {
24365
24488
  } else if (!password) {
24366
24489
  temporaryPassword = clearPassword;
24367
24490
  }
24491
+ const createdAdminUser = toAdminUser(user, userRoles);
24492
+ if (hooks?.users?.afterSave) {
24493
+ Promise.resolve(hooks.users.afterSave(createdAdminUser, hookCtx)).catch((err) => {
24494
+ console.error("[BackendHooks] users.afterSave error:", err instanceof Error ? err.message : err);
24495
+ });
24496
+ }
24368
24497
  return c.json({
24369
- user: {
24370
- uid: user.id,
24371
- email: user.email,
24372
- displayName: user.displayName,
24373
- roles: userRoles
24374
- },
24498
+ user: createdAdminUser,
24375
24499
  invitationSent,
24376
24500
  ...temporaryPassword ? {
24377
24501
  temporaryPassword
@@ -24441,7 +24565,7 @@ function createAdminRoutes(config) {
24441
24565
  router.put("/users/:userId", requireAdmin, async (c) => {
24442
24566
  const userId = c.req.param("userId");
24443
24567
  const body = await c.req.json();
24444
- const {
24568
+ let {
24445
24569
  email,
24446
24570
  displayName,
24447
24571
  password,
@@ -24451,6 +24575,17 @@ function createAdminRoutes(config) {
24451
24575
  if (!existing) {
24452
24576
  throw ApiError.notFound("User not found");
24453
24577
  }
24578
+ const hookCtx = buildHookContext(c, "PUT");
24579
+ if (hooks?.users?.beforeSave) {
24580
+ const hooked = await hooks.users.beforeSave({
24581
+ email,
24582
+ displayName,
24583
+ roles
24584
+ }, hookCtx);
24585
+ email = hooked.email ?? email;
24586
+ displayName = hooked.displayName ?? displayName;
24587
+ roles = hooked.roles ?? roles;
24588
+ }
24454
24589
  const updates = {};
24455
24590
  if (email !== void 0) updates.email = email.toLowerCase();
24456
24591
  if (displayName !== void 0) updates.displayName = displayName;
@@ -24468,13 +24603,14 @@ function createAdminRoutes(config) {
24468
24603
  await authRepo.setUserRoles(userId, roles);
24469
24604
  }
24470
24605
  const result = await authRepo.getUserWithRoles(userId);
24606
+ const updatedAdminUser = toAdminUser(result.user, result.roles.map((r) => r.id));
24607
+ if (hooks?.users?.afterSave) {
24608
+ Promise.resolve(hooks.users.afterSave(updatedAdminUser, hookCtx)).catch((err) => {
24609
+ console.error("[BackendHooks] users.afterSave error:", err instanceof Error ? err.message : err);
24610
+ });
24611
+ }
24471
24612
  return c.json({
24472
- user: {
24473
- uid: result.user.id,
24474
- email: result.user.email,
24475
- displayName: result.user.displayName,
24476
- roles: result.roles.map((r) => r.id)
24477
- }
24613
+ user: updatedAdminUser
24478
24614
  });
24479
24615
  });
24480
24616
  router.delete("/users/:userId", requireAdmin, async (c) => {
@@ -24488,21 +24624,33 @@ function createAdminRoutes(config) {
24488
24624
  if (!existing) {
24489
24625
  throw ApiError.notFound("User not found");
24490
24626
  }
24627
+ const hookCtx = buildHookContext(c, "DELETE");
24628
+ if (hooks?.users?.beforeDelete) {
24629
+ await hooks.users.beforeDelete(userId, hookCtx);
24630
+ }
24491
24631
  await authRepo.deleteUser(userId);
24632
+ if (hooks?.users?.afterDelete) {
24633
+ Promise.resolve(hooks.users.afterDelete(userId, hookCtx)).catch((err) => {
24634
+ console.error("[BackendHooks] users.afterDelete error:", err instanceof Error ? err.message : err);
24635
+ });
24636
+ }
24492
24637
  return c.json({
24493
24638
  success: true
24494
24639
  });
24495
24640
  });
24496
24641
  router.get("/roles", requireAdmin, async (c) => {
24497
24642
  const roles = await authRepo.listRoles();
24643
+ const hookCtx = buildHookContext(c, "GET");
24644
+ let adminRoles = roles.map((r) => ({
24645
+ id: r.id,
24646
+ name: r.name,
24647
+ isAdmin: r.isAdmin,
24648
+ defaultPermissions: r.defaultPermissions,
24649
+ config: r.config
24650
+ }));
24651
+ adminRoles = await applyRoleAfterReadBatch(adminRoles, hookCtx);
24498
24652
  return c.json({
24499
- roles: roles.map((r) => ({
24500
- id: r.id,
24501
- name: r.name,
24502
- isAdmin: r.isAdmin,
24503
- defaultPermissions: r.defaultPermissions,
24504
- config: r.config
24505
- }))
24653
+ roles: adminRoles
24506
24654
  });
24507
24655
  });
24508
24656
  router.get("/roles/:roleId", requireAdmin, async (c) => {
@@ -24630,10 +24778,10 @@ class LocalStorageController {
24630
24778
  * Includes a path traversal guard to prevent escaping the base directory.
24631
24779
  */
24632
24780
  getFullPath(storagePath, bucket) {
24633
- const parts = bucket ? [this.basePath, bucket, storagePath] : [this.basePath, storagePath];
24634
- const resolved = path$3.resolve(path$3.join(...parts));
24635
- if (!resolved.startsWith(this.basePath + path$3.sep) && resolved !== this.basePath) {
24636
- throw new Error("Path traversal detected: resolved storage path is outside the base directory.");
24781
+ const bucketPath = bucket ? path$3.join(this.basePath, bucket) : this.basePath;
24782
+ const resolved = path$3.resolve(path$3.join(bucketPath, storagePath));
24783
+ if (!resolved.startsWith(bucketPath + path$3.sep) && resolved !== bucketPath) {
24784
+ throw new Error("Path traversal detected: resolved storage path is outside the bucket directory.");
24637
24785
  }
24638
24786
  return resolved;
24639
24787
  }
@@ -26343,6 +26491,18 @@ function createCollectionClient(transport, slug, ws) {
26343
26491
  method: "DELETE"
26344
26492
  });
26345
26493
  },
26494
+ async count(params) {
26495
+ const countParams = {
26496
+ ...params,
26497
+ limit: void 0,
26498
+ offset: void 0
26499
+ };
26500
+ const qs = buildQueryString(countParams);
26501
+ const raw = await transport.request(basePath + "/count" + qs, {
26502
+ method: "GET"
26503
+ });
26504
+ return raw.count ?? 0;
26505
+ },
26346
26506
  // Fluent builder instantiation
26347
26507
  where(column, operator, value) {
26348
26508
  return new QueryBuilder(client).where(column, operator, value);
@@ -37944,7 +38104,8 @@ async function _initializeRebaseBackend(config) {
37944
38104
  authRepo: authConfigResult.authRepository ?? authConfigResult.userService,
37945
38105
  emailService: authConfigResult.emailService,
37946
38106
  emailConfig: config.auth.email,
37947
- serviceKey
38107
+ serviceKey,
38108
+ hooks: config.hooks
37948
38109
  });
37949
38110
  config.app.route(`${basePath}/admin`, adminRoutes);
37950
38111
  }
@@ -38002,7 +38163,7 @@ async function _initializeRebaseBackend(config) {
38002
38163
  });
38003
38164
  dataRouter.route("/", historyRoutes);
38004
38165
  }
38005
- const restGenerator = new RestApiGenerator(activeCollections, defaultDriver);
38166
+ const restGenerator = new RestApiGenerator(activeCollections, defaultDriver, config.hooks?.data);
38006
38167
  dataRouter.route("/", restGenerator.generateRoutes());
38007
38168
  config.app.route(`${basePath}/data`, dataRouter);
38008
38169
  }
@@ -49020,9 +49181,9 @@ class RebaseApiServer {
49020
49181
  if (process.env.NODE_ENV === "production") {
49021
49182
  console.warn("[RebaseApiServer] Schema Editor is disabled in production environments for security.");
49022
49183
  } else {
49184
+ this.router.use(`${basePath}/schema-editor/*`, requireAuth, requireAdmin);
49023
49185
  const schemaEditorRoutes2 = createSchemaEditorRoutes(this.config.collectionsDir);
49024
49186
  this.router.route(`${basePath}/schema-editor`, schemaEditorRoutes2);
49025
- this.router.use(`${basePath}/schema-editor/*`, requireAuth, requireAdmin);
49026
49187
  }
49027
49188
  }
49028
49189
  this.router.get(`${basePath}/docs`, (c) => {