@electric-sql/client 1.3.1 → 1.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -71,6 +71,8 @@ __export(src_exports, {
71
71
  Shape: () => Shape,
72
72
  ShapeStream: () => ShapeStream,
73
73
  camelToSnake: () => camelToSnake,
74
+ compileExpression: () => compileExpression,
75
+ compileOrderBy: () => compileOrderBy,
74
76
  createColumnMapper: () => createColumnMapper,
75
77
  isChangeMessage: () => isChangeMessage,
76
78
  isControlMessage: () => isControlMessage,
@@ -502,6 +504,8 @@ var SUBSET_PARAM_LIMIT = `subset__limit`;
502
504
  var SUBSET_PARAM_OFFSET = `subset__offset`;
503
505
  var SUBSET_PARAM_ORDER_BY = `subset__order_by`;
504
506
  var SUBSET_PARAM_WHERE_PARAMS = `subset__params`;
507
+ var SUBSET_PARAM_WHERE_EXPR = `subset__where_expr`;
508
+ var SUBSET_PARAM_ORDER_BY_EXPR = `subset__order_by_expr`;
505
509
  var ELECTRIC_PROTOCOL_QUERY_PARAMS = [
506
510
  LIVE_QUERY_PARAM,
507
511
  LIVE_SSE_QUERY_PARAM,
@@ -514,7 +518,9 @@ var ELECTRIC_PROTOCOL_QUERY_PARAMS = [
514
518
  SUBSET_PARAM_LIMIT,
515
519
  SUBSET_PARAM_OFFSET,
516
520
  SUBSET_PARAM_ORDER_BY,
517
- SUBSET_PARAM_WHERE_PARAMS
521
+ SUBSET_PARAM_WHERE_PARAMS,
522
+ SUBSET_PARAM_WHERE_EXPR,
523
+ SUBSET_PARAM_ORDER_BY_EXPR
518
524
  ];
519
525
 
520
526
  // src/fetch.ts
@@ -801,6 +807,81 @@ function chainAborter(aborter, sourceSignal) {
801
807
  function noop() {
802
808
  }
803
809
 
810
+ // src/expression-compiler.ts
811
+ function compileExpression(expr, columnMapper) {
812
+ switch (expr.type) {
813
+ case `ref`: {
814
+ const mappedColumn = columnMapper ? columnMapper(expr.column) : expr.column;
815
+ return quoteIdentifier(mappedColumn);
816
+ }
817
+ case `val`:
818
+ return `$${expr.paramIndex}`;
819
+ case `func`:
820
+ return compileFunction(expr, columnMapper);
821
+ default: {
822
+ const _exhaustive = expr;
823
+ throw new Error(`Unknown expression type: ${JSON.stringify(_exhaustive)}`);
824
+ }
825
+ }
826
+ }
827
+ function compileFunction(expr, columnMapper) {
828
+ const args = expr.args.map((arg) => compileExpression(arg, columnMapper));
829
+ switch (expr.name) {
830
+ // Binary comparison operators
831
+ case `eq`:
832
+ return `${args[0]} = ${args[1]}`;
833
+ case `gt`:
834
+ return `${args[0]} > ${args[1]}`;
835
+ case `gte`:
836
+ return `${args[0]} >= ${args[1]}`;
837
+ case `lt`:
838
+ return `${args[0]} < ${args[1]}`;
839
+ case `lte`:
840
+ return `${args[0]} <= ${args[1]}`;
841
+ // Logical operators
842
+ case `and`:
843
+ return args.map((a) => `(${a})`).join(` AND `);
844
+ case `or`:
845
+ return args.map((a) => `(${a})`).join(` OR `);
846
+ case `not`:
847
+ return `NOT (${args[0]})`;
848
+ // Special operators
849
+ case `in`:
850
+ return `${args[0]} = ANY(${args[1]})`;
851
+ case `like`:
852
+ return `${args[0]} LIKE ${args[1]}`;
853
+ case `ilike`:
854
+ return `${args[0]} ILIKE ${args[1]}`;
855
+ case `isNull`:
856
+ case `isUndefined`:
857
+ return `${args[0]} IS NULL`;
858
+ // String functions
859
+ case `upper`:
860
+ return `UPPER(${args[0]})`;
861
+ case `lower`:
862
+ return `LOWER(${args[0]})`;
863
+ case `length`:
864
+ return `LENGTH(${args[0]})`;
865
+ case `concat`:
866
+ return `CONCAT(${args.join(`, `)})`;
867
+ // Other functions
868
+ case `coalesce`:
869
+ return `COALESCE(${args.join(`, `)})`;
870
+ default:
871
+ throw new Error(`Unknown function: ${expr.name}`);
872
+ }
873
+ }
874
+ function compileOrderBy(clauses, columnMapper) {
875
+ return clauses.map((clause) => {
876
+ const mappedColumn = columnMapper ? columnMapper(clause.column) : clause.column;
877
+ let sql = quoteIdentifier(mappedColumn);
878
+ if (clause.direction === `desc`) sql += ` DESC`;
879
+ if (clause.nulls === `first`) sql += ` NULLS FIRST`;
880
+ if (clause.nulls === `last`) sql += ` NULLS LAST`;
881
+ return sql;
882
+ }).join(`, `);
883
+ }
884
+
804
885
  // src/client.ts
805
886
  var import_fetch_event_source = require("@microsoft/fetch-event-source");
806
887
 
@@ -1466,7 +1547,7 @@ requestShape_fn = async function() {
1466
1547
  return __privateMethod(this, _ShapeStream_instances, requestShape_fn).call(this);
1467
1548
  };
1468
1549
  constructUrl_fn = async function(url, resumingFromPause, subsetParams) {
1469
- var _a, _b, _c, _d;
1550
+ var _a, _b, _c, _d, _e, _f;
1470
1551
  const [requestHeaders, params] = await Promise.all([
1471
1552
  resolveHeaders(this.options.headers),
1472
1553
  this.options.params ? toInternalParams(convertWhereParamsToObj(this.options.params)) : void 0
@@ -1511,10 +1592,20 @@ constructUrl_fn = async function(url, resumingFromPause, subsetParams) {
1511
1592
  }
1512
1593
  }
1513
1594
  if (subsetParams) {
1514
- if (subsetParams.where && typeof subsetParams.where === `string`) {
1595
+ if (subsetParams.whereExpr) {
1596
+ const compiledWhere = compileExpression(
1597
+ subsetParams.whereExpr,
1598
+ (_c = this.options.columnMapper) == null ? void 0 : _c.encode
1599
+ );
1600
+ setQueryParam(fetchUrl, SUBSET_PARAM_WHERE, compiledWhere);
1601
+ fetchUrl.searchParams.set(
1602
+ SUBSET_PARAM_WHERE_EXPR,
1603
+ JSON.stringify(subsetParams.whereExpr)
1604
+ );
1605
+ } else if (subsetParams.where && typeof subsetParams.where === `string`) {
1515
1606
  const encodedWhere = encodeWhereClause(
1516
1607
  subsetParams.where,
1517
- (_c = this.options.columnMapper) == null ? void 0 : _c.encode
1608
+ (_d = this.options.columnMapper) == null ? void 0 : _d.encode
1518
1609
  );
1519
1610
  setQueryParam(fetchUrl, SUBSET_PARAM_WHERE, encodedWhere);
1520
1611
  }
@@ -1527,10 +1618,20 @@ constructUrl_fn = async function(url, resumingFromPause, subsetParams) {
1527
1618
  setQueryParam(fetchUrl, SUBSET_PARAM_LIMIT, subsetParams.limit);
1528
1619
  if (subsetParams.offset)
1529
1620
  setQueryParam(fetchUrl, SUBSET_PARAM_OFFSET, subsetParams.offset);
1530
- if (subsetParams.orderBy && typeof subsetParams.orderBy === `string`) {
1621
+ if (subsetParams.orderByExpr) {
1622
+ const compiledOrderBy = compileOrderBy(
1623
+ subsetParams.orderByExpr,
1624
+ (_e = this.options.columnMapper) == null ? void 0 : _e.encode
1625
+ );
1626
+ setQueryParam(fetchUrl, SUBSET_PARAM_ORDER_BY, compiledOrderBy);
1627
+ fetchUrl.searchParams.set(
1628
+ SUBSET_PARAM_ORDER_BY_EXPR,
1629
+ JSON.stringify(subsetParams.orderByExpr)
1630
+ );
1631
+ } else if (subsetParams.orderBy && typeof subsetParams.orderBy === `string`) {
1531
1632
  const encodedOrderBy = encodeWhereClause(
1532
1633
  subsetParams.orderBy,
1533
- (_d = this.options.columnMapper) == null ? void 0 : _d.encode
1634
+ (_f = this.options.columnMapper) == null ? void 0 : _f.encode
1534
1635
  );
1535
1636
  setQueryParam(fetchUrl, SUBSET_PARAM_ORDER_BY, encodedOrderBy);
1536
1637
  }
@@ -2112,6 +2213,8 @@ notify_fn = function() {
2112
2213
  Shape,
2113
2214
  ShapeStream,
2114
2215
  camelToSnake,
2216
+ compileExpression,
2217
+ compileOrderBy,
2115
2218
  createColumnMapper,
2116
2219
  isChangeMessage,
2117
2220
  isControlMessage,