@bluecopa/core 0.1.68 → 0.1.70

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
@@ -1,12 +1,12 @@
1
1
  var __defProp = Object.defineProperty;
2
2
  var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
3
3
  var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
4
- import axios from "axios";
4
+ import axios, { isAxiosError } from "axios";
5
5
  import _ from "lodash";
6
+ import { combineLatest, Subject, map as map$1 } from "rxjs";
6
7
  import { createRxDatabase } from "rxdb";
7
8
  import { getRxStorageDexie } from "rxdb/plugins/storage-dexie";
8
9
  import { replicateRxCollection } from "rxdb/plugins/replication";
9
- import { Subject } from "rxjs";
10
10
  class ConfigSingleton {
11
11
  constructor() {
12
12
  this.config = {
@@ -707,10 +707,7 @@ const findParentIsMetricSeries = (childId, variables) => {
707
707
  return true;
708
708
  } else if (parentTableVariable == null ? void 0 : parentTableVariable.transforms[0]) {
709
709
  const transform = parentTableVariable.transforms[0];
710
- return findParentIsMetricSeries(
711
- transform.table,
712
- variables
713
- );
710
+ return findParentIsMetricSeries(transform.table, variables);
714
711
  }
715
712
  return false;
716
713
  };
@@ -739,9 +736,7 @@ const getDrilldownFiltersMap = (props) => {
739
736
  if (ftba.operator) {
740
737
  let uniqueValuesForNegationOperator, uniqueValuesForOperator;
741
738
  if (ftba.operator.includes("not")) {
742
- uniqueValuesForNegationOperator = getValuesForSpecialOperators(
743
- ftba.operator
744
- );
739
+ uniqueValuesForNegationOperator = getValuesForSpecialOperators(ftba.operator);
745
740
  uniqueValuesForOperator = [
746
741
  {
747
742
  label: col == null ? void 0 : col.label,
@@ -828,9 +823,7 @@ const getDrilldownFiltersMap = (props) => {
828
823
  const getFiltersToBeAppliedOnDrilldown = (props) => {
829
824
  const { rowGroups, groupKeys } = props;
830
825
  const filtersToBeApplied = [];
831
- groupKeys == null ? void 0 : groupKeys.forEach(
832
- (key, index2) => filtersToBeApplied.push({ field: rowGroups[index2], key })
833
- );
826
+ groupKeys == null ? void 0 : groupKeys.forEach((key, index2) => filtersToBeApplied.push({ field: rowGroups[index2], key }));
834
827
  return filtersToBeApplied;
835
828
  };
836
829
  const getMetricFilterRule = (inputs) => {
@@ -870,34 +863,28 @@ const getUpdatedDefinitionCustomModel = (props) => {
870
863
  removeSort
871
864
  } = props;
872
865
  const parentTableVariable = parentCustomModel.variable;
873
- const metricNewColumns = _.filter(
874
- metricDefinitionModel.variables ?? [],
875
- (v) => {
876
- if (!v.transforms || !v.transforms[0]) {
877
- return false;
878
- }
879
- if (removeSort) {
880
- return findParentIsMetricSeries(
881
- v.transforms[0].table,
882
- metricDefinitionModel.variables ?? []
883
- ) && v.transforms[0].type !== "Sort";
884
- }
866
+ const metricNewColumns = _.filter(metricDefinitionModel.variables ?? [], (v) => {
867
+ if (!v.transforms || !v.transforms[0]) {
868
+ return false;
869
+ }
870
+ if (removeSort) {
885
871
  return findParentIsMetricSeries(
886
872
  v.transforms[0].table,
887
873
  metricDefinitionModel.variables ?? []
888
- );
874
+ ) && v.transforms[0].type !== "Sort";
889
875
  }
890
- );
876
+ return findParentIsMetricSeries(
877
+ v.transforms[0].table,
878
+ metricDefinitionModel.variables ?? []
879
+ );
880
+ });
891
881
  const definitionVariables = metricDefinitionModel.variables ?? [];
892
882
  const analysisVariable = _.find(
893
883
  definitionVariables,
894
884
  (v) => !!_.find(v.transforms, (t) => t.type === "MetricSeries")
895
885
  );
896
886
  metricDefinitionModel.imports = _.uniqBy(
897
- [
898
- ...parentDefinitionModel.imports ?? [],
899
- ...metricDefinitionModel.imports ?? []
900
- ],
887
+ [...parentDefinitionModel.imports ?? [], ...metricDefinitionModel.imports ?? []],
901
888
  "to"
902
889
  );
903
890
  const parentDefinitionAliases = parentDefinitionModel.aliases ?? {};
@@ -910,10 +897,7 @@ const getUpdatedDefinitionCustomModel = (props) => {
910
897
  if (!parentDefinitionAliases[tableId]) {
911
898
  const metricTableAlias = metricDefinitionAliases[tableId];
912
899
  for (const [columnName, columnId] of Object.entries(metricTableAlias)) {
913
- const pColName = _.findKey(
914
- parentTableVariableAlias,
915
- (pColId) => pColId === columnId
916
- );
900
+ const pColName = _.findKey(parentTableVariableAlias, (pColId) => pColId === columnId);
917
901
  if (pColName && pColName !== columnName) {
918
902
  delete metricTableAlias[columnName];
919
903
  metricTableAlias[pColName] = parentTableVariableAlias[pColName];
@@ -928,22 +912,15 @@ const getUpdatedDefinitionCustomModel = (props) => {
928
912
  );
929
913
  const previousVariables = metricDefinitionModel.variables;
930
914
  metricDefinitionModel.variables = [...variables];
931
- const variableNames = (_a = metricDefinitionModel.variables) == null ? void 0 : _a.map(
932
- (v) => v == null ? void 0 : v.name
933
- );
915
+ const variableNames = (_a = metricDefinitionModel.variables) == null ? void 0 : _a.map((v) => v == null ? void 0 : v.name);
934
916
  metricDefinitionModel.variables.push(
935
- ..._.filter(
936
- previousVariables,
937
- (v) => variableNames == null ? void 0 : variableNames.includes(v.name)
938
- )
917
+ ..._.filter(previousVariables, (v) => variableNames == null ? void 0 : variableNames.includes(v.name))
939
918
  );
940
919
  const filterVariable = _.find(
941
920
  definitionVariables,
942
921
  (v) => {
943
922
  var _a2;
944
- return (_a2 = v.transforms) == null ? void 0 : _a2.some(
945
- (t) => t.type === "RuleFilter" && t.rule === "${rule_pivot}"
946
- );
923
+ return (_a2 = v.transforms) == null ? void 0 : _a2.some((t) => t.type === "RuleFilter" && t.rule === "${rule_pivot}");
947
924
  }
948
925
  );
949
926
  if (filterVariable && parentTableVariable) {
@@ -2055,7 +2032,7 @@ var SubscriptionState;
2055
2032
  function startsWith(value, prefix) {
2056
2033
  return value.lastIndexOf(prefix, 0) === 0;
2057
2034
  }
2058
- function isFunction(value) {
2035
+ function isFunction$1(value) {
2059
2036
  if (value === void 0 || value === null) {
2060
2037
  return false;
2061
2038
  }
@@ -2064,7 +2041,7 @@ function isFunction(value) {
2064
2041
  function log(level, args) {
2065
2042
  if (globalThis.console) {
2066
2043
  const logger = globalThis.console[level];
2067
- if (isFunction(logger)) {
2044
+ if (isFunction$1(logger)) {
2068
2045
  logger.apply(globalThis.console, args);
2069
2046
  }
2070
2047
  }
@@ -2085,7 +2062,7 @@ function errorExists(data) {
2085
2062
  function ttlMilliseconds(ttl) {
2086
2063
  return Math.min(ttl * 1e3, 2147483647);
2087
2064
  }
2088
- class Subscription extends EventEmitter$1 {
2065
+ let Subscription$1 = class Subscription extends EventEmitter$1 {
2089
2066
  /** Subscription constructor should not be used directly, create subscriptions using Client method. */
2090
2067
  constructor(centrifuge, channel, options) {
2091
2068
  super();
@@ -2700,7 +2677,7 @@ class Subscription extends EventEmitter$1 {
2700
2677
  _failUnauthorized() {
2701
2678
  this._setUnsubscribed(unsubscribedCodes.unauthorized, "unauthorized", true);
2702
2679
  }
2703
- }
2680
+ };
2704
2681
  class SockjsTransport {
2705
2682
  constructor(endpoint, options) {
2706
2683
  this.endpoint = endpoint;
@@ -3582,7 +3559,7 @@ class Centrifuge extends EventEmitter$1 {
3582
3559
  if (this.getSubscription(channel) !== null) {
3583
3560
  throw new Error("Subscription to the channel " + channel + " already exists");
3584
3561
  }
3585
- const sub = new Subscription(this, channel, options);
3562
+ const sub = new Subscription$1(this, channel, options);
3586
3563
  this._subs[channel] = sub;
3587
3564
  return sub;
3588
3565
  }
@@ -5012,7 +4989,7 @@ class Centrifuge extends EventEmitter$1 {
5012
4989
  };
5013
4990
  this._callbacks[id].timeout = setTimeout(() => {
5014
4991
  delete this._callbacks[id];
5015
- if (isFunction(errback)) {
4992
+ if (isFunction$1(errback)) {
5016
4993
  errback({ error: this._createErrorObject(errorCodes.timeout, "timeout") });
5017
4994
  }
5018
4995
  }, this._config.timeout);
@@ -5185,17 +5162,17 @@ var pusher = { exports: {} };
5185
5162
  var __webpack_modules__ = {
5186
5163
  /***/
5187
5164
  594(__unused_webpack_module, exports$12) {
5188
- var __extends = this && this.__extends || /* @__PURE__ */ function() {
5189
- var extendStatics = function(d, b) {
5190
- extendStatics = Object.setPrototypeOf || { __proto__: [] } instanceof Array && function(d2, b2) {
5165
+ var __extends2 = this && this.__extends || /* @__PURE__ */ function() {
5166
+ var extendStatics2 = function(d, b) {
5167
+ extendStatics2 = Object.setPrototypeOf || { __proto__: [] } instanceof Array && function(d2, b2) {
5191
5168
  d2.__proto__ = b2;
5192
5169
  } || function(d2, b2) {
5193
5170
  for (var p in b2) if (b2.hasOwnProperty(p)) d2[p] = b2[p];
5194
5171
  };
5195
- return extendStatics(d, b);
5172
+ return extendStatics2(d, b);
5196
5173
  };
5197
5174
  return function(d, b) {
5198
- extendStatics(d, b);
5175
+ extendStatics2(d, b);
5199
5176
  function __() {
5200
5177
  this.constructor = d;
5201
5178
  }
@@ -5347,7 +5324,7 @@ var pusher = { exports: {} };
5347
5324
  var URLSafeCoder = (
5348
5325
  /** @class */
5349
5326
  function(_super) {
5350
- __extends(URLSafeCoder2, _super);
5327
+ __extends2(URLSafeCoder2, _super);
5351
5328
  function URLSafeCoder2() {
5352
5329
  return _super !== null && _super.apply(this, arguments) || this;
5353
5330
  }
@@ -5868,7 +5845,7 @@ var pusher = { exports: {} };
5868
5845
  f.call(context || window, array[i], i, array);
5869
5846
  }
5870
5847
  }
5871
- function map(array, f) {
5848
+ function map2(array, f) {
5872
5849
  var result = [];
5873
5850
  for (var i = 0; i < array.length; i++) {
5874
5851
  result.push(f(array[i], i, array, result));
@@ -5938,7 +5915,7 @@ var pusher = { exports: {} };
5938
5915
  var params = filterObject(data, function(value) {
5939
5916
  return value !== void 0;
5940
5917
  });
5941
- var query = map(flatten(encodeParamsObject(params)), util.method("join", "=")).join("&");
5918
+ var query = map2(flatten(encodeParamsObject(params)), util.method("join", "=")).join("&");
5942
5919
  return query;
5943
5920
  }
5944
5921
  function decycleObject(object) {
@@ -7585,7 +7562,7 @@ var pusher = { exports: {} };
7585
7562
  }
7586
7563
  }
7587
7564
  function connect(strategies, minPriority, callbackBuilder) {
7588
- var runners = map(strategies, function(strategy, i, _2, rs) {
7565
+ var runners = map2(strategies, function(strategy, i, _2, rs) {
7589
7566
  return strategy.connect(minPriority, callbackBuilder(i, rs));
7590
7567
  });
7591
7568
  return {
@@ -11329,10 +11306,77 @@ async function reassignTask({
11329
11306
  throw { message, status };
11330
11307
  }
11331
11308
  }
11309
+ async function getTriggersBySheet(sheetId) {
11310
+ var _a, _b, _c, _d;
11311
+ if (!(sheetId == null ? void 0 : sheetId.trim())) {
11312
+ throw { message: "sheetId is required", status: 400 };
11313
+ }
11314
+ try {
11315
+ const response = await apiClient.get(
11316
+ `/process/trigger/sheet/${sheetId.trim()}`
11317
+ );
11318
+ const payload = ((_a = response.data) == null ? void 0 : _a.data) ?? response.data;
11319
+ return payload ?? [];
11320
+ } catch (error) {
11321
+ const message = ((_c = (_b = error.response) == null ? void 0 : _b.data) == null ? void 0 : _c.message) || error.message || "Failed to fetch process triggers";
11322
+ const status = ((_d = error.response) == null ? void 0 : _d.status) || 500;
11323
+ throw { message, status };
11324
+ }
11325
+ }
11326
+ async function registerProcessTrigger(payload) {
11327
+ var _a, _b, _c, _d, _e, _f;
11328
+ if (!((_a = payload == null ? void 0 : payload.trigger_id) == null ? void 0 : _a.trim())) {
11329
+ throw { message: "trigger_id is required", status: 400 };
11330
+ }
11331
+ if (!((_b = payload == null ? void 0 : payload.process_sheet_id) == null ? void 0 : _b.trim())) {
11332
+ throw { message: "process_sheet_id is required", status: 400 };
11333
+ }
11334
+ if (!(payload == null ? void 0 : payload.trigger_component)) {
11335
+ throw { message: "trigger_component is required", status: 400 };
11336
+ }
11337
+ if (!(payload == null ? void 0 : payload.workflowType)) {
11338
+ throw { message: "workflowType is required", status: 400 };
11339
+ }
11340
+ try {
11341
+ const response = await apiClient.post(
11342
+ "/process/trigger/register",
11343
+ payload
11344
+ );
11345
+ const data = ((_c = response.data) == null ? void 0 : _c.data) ?? response.data;
11346
+ if (!data) {
11347
+ throw { message: "Failed to register process trigger", status: 500 };
11348
+ }
11349
+ return data;
11350
+ } catch (error) {
11351
+ const message = ((_e = (_d = error.response) == null ? void 0 : _d.data) == null ? void 0 : _e.message) || error.message || "Failed to register process trigger";
11352
+ const status = ((_f = error.response) == null ? void 0 : _f.status) || 500;
11353
+ throw { message, status };
11354
+ }
11355
+ }
11356
+ async function deleteProcessTrigger(id) {
11357
+ var _a, _b, _c, _d;
11358
+ if (!(id == null ? void 0 : id.trim())) {
11359
+ throw { message: "id is required", status: 400 };
11360
+ }
11361
+ try {
11362
+ const response = await apiClient.delete(
11363
+ `/process/trigger/${id.trim()}`
11364
+ );
11365
+ const data = ((_a = response.data) == null ? void 0 : _a.data) ?? response.data ?? { deleted: true };
11366
+ return data;
11367
+ } catch (error) {
11368
+ const message = ((_c = (_b = error.response) == null ? void 0 : _b.data) == null ? void 0 : _c.message) || error.message || "Failed to delete process trigger";
11369
+ const status = ((_d = error.response) == null ? void 0 : _d.status) || 500;
11370
+ throw { message, status };
11371
+ }
11372
+ }
11332
11373
  const index$7 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
11333
11374
  __proto__: null,
11375
+ deleteProcessTrigger,
11376
+ getTriggersBySheet,
11334
11377
  markTaskDone,
11335
- reassignTask
11378
+ reassignTask,
11379
+ registerProcessTrigger
11336
11380
  }, Symbol.toStringTag, { value: "Module" }));
11337
11381
  async function getAllInboxItems({
11338
11382
  page,
@@ -12393,135 +12437,6 @@ function deferSubscription(resolve, callback, fallback) {
12393
12437
  innerUnsub == null ? void 0 : innerUnsub();
12394
12438
  };
12395
12439
  }
12396
- const OP_MAP = {
12397
- "==": "$eq",
12398
- "!=": "$ne",
12399
- "<": "$lt",
12400
- "<=": "$lte",
12401
- ">": "$gt",
12402
- ">=": "$gte",
12403
- in: "$in",
12404
- "not-in": "$nin"
12405
- };
12406
- class QueryBuilderImpl {
12407
- constructor(collection, initialWhere, initialOrder, initialLimit, initialSkip, aggregateExecutor) {
12408
- this.collection = collection;
12409
- this.aggregateExecutor = aggregateExecutor;
12410
- this.wheres = [];
12411
- this.orders = [];
12412
- if (initialWhere) this.wheres.push(initialWhere);
12413
- if (initialOrder) this.orders.push(initialOrder);
12414
- if (initialLimit !== void 0) this.limitCount = initialLimit;
12415
- if (initialSkip !== void 0) this.skipCount = initialSkip;
12416
- }
12417
- where(field, op, value) {
12418
- this.wheres.push({ field, op, value });
12419
- return this;
12420
- }
12421
- orderBy(field, direction = "asc") {
12422
- this.orders.push({ field, direction });
12423
- return this;
12424
- }
12425
- limit(count) {
12426
- this.limitCount = count;
12427
- return this;
12428
- }
12429
- skip(count) {
12430
- this.skipCount = count;
12431
- return this;
12432
- }
12433
- subscribe(callback) {
12434
- const query = this.buildQuery();
12435
- const rxSub = query.$.subscribe((docs) => {
12436
- callback(docs.map((d) => d.toJSON()));
12437
- });
12438
- return () => rxSub.unsubscribe();
12439
- }
12440
- async get() {
12441
- const query = this.buildQuery();
12442
- const docs = await query.exec();
12443
- return docs.map((d) => d.toJSON());
12444
- }
12445
- async aggregate(spec, options) {
12446
- if (!this.aggregateExecutor) {
12447
- throw new InputTableError(
12448
- "[copaInputTableDb] aggregate() is not available on this QueryBuilder instance",
12449
- 500
12450
- );
12451
- }
12452
- return this.aggregateExecutor(
12453
- this.wheres,
12454
- this.orders,
12455
- this.limitCount,
12456
- this.skipCount,
12457
- spec,
12458
- options == null ? void 0 : options.groupBy
12459
- );
12460
- }
12461
- buildQuery() {
12462
- const selector = {};
12463
- for (const { field, op, value } of this.wheres) {
12464
- const rxOp = OP_MAP[op];
12465
- if (!selector[field]) selector[field] = {};
12466
- selector[field][rxOp] = value;
12467
- }
12468
- const queryParams = { selector };
12469
- if (this.orders.length > 0) {
12470
- queryParams.sort = this.orders.map(({ field, direction }) => ({ [field]: direction }));
12471
- }
12472
- if (this.limitCount !== void 0) {
12473
- queryParams.limit = this.limitCount;
12474
- }
12475
- if (this.skipCount !== void 0) {
12476
- queryParams.skip = this.skipCount;
12477
- }
12478
- return this.collection.find(queryParams);
12479
- }
12480
- }
12481
- const CHECKPOINT_FIELD = "updated_at";
12482
- const MAX_COLLECTIONS = 14;
12483
- const REPLICATION_RETRY_TIME = 5e3;
12484
- const PULL_BATCH_SIZE = 100;
12485
- const PUSH_BATCH_SIZE = 10;
12486
- class DocRefImpl {
12487
- constructor(collection, id, solutionId, tableName, primaryKeyField, websocketProvider) {
12488
- this.collection = collection;
12489
- this.id = id;
12490
- this.solutionId = solutionId;
12491
- this.tableName = tableName;
12492
- this.primaryKeyField = primaryKeyField;
12493
- this.websocketProvider = websocketProvider;
12494
- }
12495
- async get() {
12496
- const doc = await this.collection.findOne(this.id).exec();
12497
- return doc ? doc.toJSON() : null;
12498
- }
12499
- async update(data) {
12500
- const doc = await this.collection.findOne(this.id).exec();
12501
- if (!doc) {
12502
- throw new InputTableError(`Document "${this.id}" not found`, 404);
12503
- }
12504
- const patch = { ...data };
12505
- delete patch[this.primaryKeyField];
12506
- delete patch[CHECKPOINT_FIELD];
12507
- await doc.patch(patch);
12508
- }
12509
- async delete() {
12510
- await apiClient.request({
12511
- url: `input-table-v2/${this.solutionId}/rows/${this.tableName}`,
12512
- method: "DELETE",
12513
- params: { [this.primaryKeyField]: `eq.${this.id}` }
12514
- });
12515
- const doc = await this.collection.findOne(this.id).exec();
12516
- if (doc) await doc.remove();
12517
- }
12518
- onSnapshot(callback) {
12519
- const rxSub = this.collection.findOne(this.id).$.subscribe((doc) => {
12520
- callback(doc ? doc.toJSON() : null);
12521
- });
12522
- return () => rxSub.unsubscribe();
12523
- }
12524
- }
12525
12440
  const POSTGREST_OP_MAP = {
12526
12441
  "==": "eq",
12527
12442
  "!=": "neq",
@@ -12684,144 +12599,527 @@ function parseGroupedAggregateResponse(spec, groupBy, data) {
12684
12599
  return result;
12685
12600
  });
12686
12601
  }
12687
- class CollectionRefImpl {
12688
- constructor(collection, solutionId, tableName, primaryKeyField, pkColumn, replicationState, getWebsocketProvider) {
12689
- this.collection = collection;
12690
- this.solutionId = solutionId;
12691
- this.tableName = tableName;
12692
- this.primaryKeyField = primaryKeyField;
12693
- this.pkColumn = pkColumn;
12694
- this.replicationState = replicationState;
12695
- this.getWebsocketProvider = getWebsocketProvider;
12696
- }
12697
- makeQueryBuilder(initialWhere, initialOrder, initialLimit, initialSkip) {
12698
- return new QueryBuilderImpl(
12699
- this.collection,
12700
- initialWhere,
12701
- initialOrder,
12702
- initialLimit,
12703
- initialSkip,
12704
- (wheres, orders, limit, skip, spec, groupBy) => this.executeAggregate(wheres, orders, limit, skip, spec, groupBy)
12705
- );
12706
- }
12707
- where(field, op, value) {
12708
- return this.makeQueryBuilder({ field, op, value });
12709
- }
12710
- orderBy(field, direction = "asc") {
12711
- return this.makeQueryBuilder(void 0, { field, direction });
12712
- }
12713
- limit(count) {
12714
- return this.makeQueryBuilder(void 0, void 0, count);
12715
- }
12716
- skip(count) {
12717
- return this.makeQueryBuilder(void 0, void 0, void 0, count);
12602
+ function deriveEmbedAlias(columnName, allColumnNames) {
12603
+ const names = new Set(allColumnNames);
12604
+ const primary = columnName.endsWith("_id") ? columnName.slice(0, -3) : `${columnName}_row`;
12605
+ if (!names.has(primary)) return primary;
12606
+ const fallback = `${columnName}_row`;
12607
+ if (!names.has(fallback)) return fallback;
12608
+ return `${columnName}__row`;
12609
+ }
12610
+ function resolveRelationship(columnName, schema) {
12611
+ var _a;
12612
+ const col = schema.columns.find((c) => c.name === columnName);
12613
+ if (!col) {
12614
+ throw new InputTableError(`Column '${columnName}' does not exist on table '${schema.name}'`, 400);
12718
12615
  }
12719
- doc(id) {
12720
- return new DocRefImpl(
12721
- this.collection,
12722
- id,
12723
- this.solutionId,
12724
- this.tableName,
12725
- this.primaryKeyField,
12726
- this.getWebsocketProvider
12727
- );
12616
+ const rel = (_a = schema.relationships) == null ? void 0 : _a.find((r) => r.column === columnName);
12617
+ if (!rel) {
12618
+ throw new InputTableError(`Column '${columnName}' is not a foreign key on table '${schema.name}'`, 400);
12728
12619
  }
12729
- async add(data) {
12730
- var _a, _b;
12731
- const pk = this.primaryKeyField;
12732
- const insertData = { ...data };
12733
- const needsServerPk = ((_a = this.pkColumn) == null ? void 0 : _a.auto_increment) && this.pkColumn.type !== InputTableColumnType.UUID && !insertData[pk];
12734
- if (needsServerPk) {
12735
- delete insertData[pk];
12736
- delete insertData[CHECKPOINT_FIELD];
12737
- const response = await apiClient.post(
12738
- `/input-table-v2/${this.solutionId}/rows/${this.tableName}`,
12739
- insertData,
12740
- { headers: { Prefer: "return=representation" } }
12741
- );
12742
- this.replicationState.reSync();
12743
- const serverRow = Array.isArray(response.data) ? response.data[0] : response.data;
12744
- return String((serverRow == null ? void 0 : serverRow[pk]) ?? "");
12620
+ return rel;
12621
+ }
12622
+ function buildExpandSelectParam(expansions) {
12623
+ if (expansions.length === 0) return "*";
12624
+ const embeds = expansions.map((e) => `${e.alias}:${e.referencedTable}!${e.fkColumn}(*)`).join(",");
12625
+ return `*,${embeds}`;
12626
+ }
12627
+ function buildExpandDirectives(columnNames, schema) {
12628
+ const allNames = schema.columns.map((c) => c.name);
12629
+ return columnNames.map((name) => {
12630
+ const rel = resolveRelationship(name, schema);
12631
+ return {
12632
+ alias: deriveEmbedAlias(name, allNames),
12633
+ referencedTable: rel.references_table,
12634
+ fkColumn: name
12635
+ };
12636
+ });
12637
+ }
12638
+ function isFunction(value) {
12639
+ return typeof value === "function";
12640
+ }
12641
+ function hasLift(source) {
12642
+ return isFunction(source === null || source === void 0 ? void 0 : source.lift);
12643
+ }
12644
+ function operate(init) {
12645
+ return function(source) {
12646
+ if (hasLift(source)) {
12647
+ return source.lift(function(liftedSource) {
12648
+ try {
12649
+ return init(liftedSource, this);
12650
+ } catch (err) {
12651
+ this.error(err);
12652
+ }
12653
+ });
12745
12654
  }
12746
- if (((_b = this.pkColumn) == null ? void 0 : _b.type) === InputTableColumnType.UUID && this.pkColumn.auto_increment && !insertData[pk]) {
12747
- insertData[pk] = crypto.randomUUID();
12655
+ throw new TypeError("Unable to lift unknown Observable type");
12656
+ };
12657
+ }
12658
+ var extendStatics = function(d, b) {
12659
+ extendStatics = Object.setPrototypeOf || { __proto__: [] } instanceof Array && function(d2, b2) {
12660
+ d2.__proto__ = b2;
12661
+ } || function(d2, b2) {
12662
+ for (var p in b2) if (Object.prototype.hasOwnProperty.call(b2, p)) d2[p] = b2[p];
12663
+ };
12664
+ return extendStatics(d, b);
12665
+ };
12666
+ function __extends(d, b) {
12667
+ if (typeof b !== "function" && b !== null)
12668
+ throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
12669
+ extendStatics(d, b);
12670
+ function __() {
12671
+ this.constructor = d;
12672
+ }
12673
+ d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
12674
+ }
12675
+ function __values(o) {
12676
+ var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
12677
+ if (m) return m.call(o);
12678
+ if (o && typeof o.length === "number") return {
12679
+ next: function() {
12680
+ if (o && i >= o.length) o = void 0;
12681
+ return { value: o && o[i++], done: !o };
12748
12682
  }
12749
- if (!insertData[pk]) {
12750
- insertData[pk] = generatePushID();
12683
+ };
12684
+ throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
12685
+ }
12686
+ function __read(o, n) {
12687
+ var m = typeof Symbol === "function" && o[Symbol.iterator];
12688
+ if (!m) return o;
12689
+ var i = m.call(o), r, ar = [], e;
12690
+ try {
12691
+ while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
12692
+ } catch (error) {
12693
+ e = { error };
12694
+ } finally {
12695
+ try {
12696
+ if (r && !r.done && (m = i["return"])) m.call(i);
12697
+ } finally {
12698
+ if (e) throw e.error;
12751
12699
  }
12752
- insertData[pk] = String(insertData[pk]).trim();
12753
- delete insertData[CHECKPOINT_FIELD];
12754
- await this.collection.insert(insertData);
12755
- return String(insertData[pk]);
12756
- }
12757
- subscribe(callback) {
12758
- const rxSub = this.collection.find().$.subscribe((docs) => {
12759
- callback(docs.map((d) => d.toJSON()));
12760
- });
12761
- return () => rxSub.unsubscribe();
12762
- }
12763
- async get() {
12764
- const docs = await this.collection.find().exec();
12765
- return docs.map((d) => d.toJSON());
12766
12700
  }
12767
- count(callback) {
12768
- const rxSub = this.collection.count().$.subscribe((count) => {
12769
- callback(count);
12770
- });
12771
- return () => rxSub.unsubscribe();
12701
+ return ar;
12702
+ }
12703
+ function __spreadArray(to, from, pack) {
12704
+ if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
12705
+ if (ar || !(i in from)) {
12706
+ if (!ar) ar = Array.prototype.slice.call(from, 0, i);
12707
+ ar[i] = from[i];
12708
+ }
12772
12709
  }
12773
- async aggregate(spec, options) {
12774
- return this.executeAggregate([], [], void 0, void 0, spec, options == null ? void 0 : options.groupBy);
12710
+ return to.concat(ar || Array.prototype.slice.call(from));
12711
+ }
12712
+ typeof SuppressedError === "function" ? SuppressedError : function(error, suppressed, message) {
12713
+ var e = new Error(message);
12714
+ return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
12715
+ };
12716
+ function createErrorClass(createImpl) {
12717
+ var _super = function(instance) {
12718
+ Error.call(instance);
12719
+ instance.stack = new Error().stack;
12720
+ };
12721
+ var ctorFunc = createImpl(_super);
12722
+ ctorFunc.prototype = Object.create(Error.prototype);
12723
+ ctorFunc.prototype.constructor = ctorFunc;
12724
+ return ctorFunc;
12725
+ }
12726
+ var UnsubscriptionError = createErrorClass(function(_super) {
12727
+ return function UnsubscriptionErrorImpl(errors) {
12728
+ _super(this);
12729
+ this.message = errors ? errors.length + " errors occurred during unsubscription:\n" + errors.map(function(err, i) {
12730
+ return i + 1 + ") " + err.toString();
12731
+ }).join("\n ") : "";
12732
+ this.name = "UnsubscriptionError";
12733
+ this.errors = errors;
12734
+ };
12735
+ });
12736
+ function arrRemove(arr, item) {
12737
+ if (arr) {
12738
+ var index2 = arr.indexOf(item);
12739
+ 0 <= index2 && arr.splice(index2, 1);
12740
+ }
12741
+ }
12742
+ var Subscription2 = function() {
12743
+ function Subscription3(initialTeardown) {
12744
+ this.initialTeardown = initialTeardown;
12745
+ this.closed = false;
12746
+ this._parentage = null;
12747
+ this._finalizers = null;
12748
+ }
12749
+ Subscription3.prototype.unsubscribe = function() {
12750
+ var e_1, _a, e_2, _b;
12751
+ var errors;
12752
+ if (!this.closed) {
12753
+ this.closed = true;
12754
+ var _parentage = this._parentage;
12755
+ if (_parentage) {
12756
+ this._parentage = null;
12757
+ if (Array.isArray(_parentage)) {
12758
+ try {
12759
+ for (var _parentage_1 = __values(_parentage), _parentage_1_1 = _parentage_1.next(); !_parentage_1_1.done; _parentage_1_1 = _parentage_1.next()) {
12760
+ var parent_1 = _parentage_1_1.value;
12761
+ parent_1.remove(this);
12762
+ }
12763
+ } catch (e_1_1) {
12764
+ e_1 = { error: e_1_1 };
12765
+ } finally {
12766
+ try {
12767
+ if (_parentage_1_1 && !_parentage_1_1.done && (_a = _parentage_1.return)) _a.call(_parentage_1);
12768
+ } finally {
12769
+ if (e_1) throw e_1.error;
12770
+ }
12771
+ }
12772
+ } else {
12773
+ _parentage.remove(this);
12774
+ }
12775
+ }
12776
+ var initialFinalizer = this.initialTeardown;
12777
+ if (isFunction(initialFinalizer)) {
12778
+ try {
12779
+ initialFinalizer();
12780
+ } catch (e) {
12781
+ errors = e instanceof UnsubscriptionError ? e.errors : [e];
12782
+ }
12783
+ }
12784
+ var _finalizers = this._finalizers;
12785
+ if (_finalizers) {
12786
+ this._finalizers = null;
12787
+ try {
12788
+ for (var _finalizers_1 = __values(_finalizers), _finalizers_1_1 = _finalizers_1.next(); !_finalizers_1_1.done; _finalizers_1_1 = _finalizers_1.next()) {
12789
+ var finalizer = _finalizers_1_1.value;
12790
+ try {
12791
+ execFinalizer(finalizer);
12792
+ } catch (err) {
12793
+ errors = errors !== null && errors !== void 0 ? errors : [];
12794
+ if (err instanceof UnsubscriptionError) {
12795
+ errors = __spreadArray(__spreadArray([], __read(errors)), __read(err.errors));
12796
+ } else {
12797
+ errors.push(err);
12798
+ }
12799
+ }
12800
+ }
12801
+ } catch (e_2_1) {
12802
+ e_2 = { error: e_2_1 };
12803
+ } finally {
12804
+ try {
12805
+ if (_finalizers_1_1 && !_finalizers_1_1.done && (_b = _finalizers_1.return)) _b.call(_finalizers_1);
12806
+ } finally {
12807
+ if (e_2) throw e_2.error;
12808
+ }
12809
+ }
12810
+ }
12811
+ if (errors) {
12812
+ throw new UnsubscriptionError(errors);
12813
+ }
12814
+ }
12815
+ };
12816
+ Subscription3.prototype.add = function(teardown) {
12817
+ var _a;
12818
+ if (teardown && teardown !== this) {
12819
+ if (this.closed) {
12820
+ execFinalizer(teardown);
12821
+ } else {
12822
+ if (teardown instanceof Subscription3) {
12823
+ if (teardown.closed || teardown._hasParent(this)) {
12824
+ return;
12825
+ }
12826
+ teardown._addParent(this);
12827
+ }
12828
+ (this._finalizers = (_a = this._finalizers) !== null && _a !== void 0 ? _a : []).push(teardown);
12829
+ }
12830
+ }
12831
+ };
12832
+ Subscription3.prototype._hasParent = function(parent) {
12833
+ var _parentage = this._parentage;
12834
+ return _parentage === parent || Array.isArray(_parentage) && _parentage.includes(parent);
12835
+ };
12836
+ Subscription3.prototype._addParent = function(parent) {
12837
+ var _parentage = this._parentage;
12838
+ this._parentage = Array.isArray(_parentage) ? (_parentage.push(parent), _parentage) : _parentage ? [_parentage, parent] : parent;
12839
+ };
12840
+ Subscription3.prototype._removeParent = function(parent) {
12841
+ var _parentage = this._parentage;
12842
+ if (_parentage === parent) {
12843
+ this._parentage = null;
12844
+ } else if (Array.isArray(_parentage)) {
12845
+ arrRemove(_parentage, parent);
12846
+ }
12847
+ };
12848
+ Subscription3.prototype.remove = function(teardown) {
12849
+ var _finalizers = this._finalizers;
12850
+ _finalizers && arrRemove(_finalizers, teardown);
12851
+ if (teardown instanceof Subscription3) {
12852
+ teardown._removeParent(this);
12853
+ }
12854
+ };
12855
+ Subscription3.EMPTY = function() {
12856
+ var empty = new Subscription3();
12857
+ empty.closed = true;
12858
+ return empty;
12859
+ }();
12860
+ return Subscription3;
12861
+ }();
12862
+ Subscription2.EMPTY;
12863
+ function isSubscription(value) {
12864
+ return value instanceof Subscription2 || value && "closed" in value && isFunction(value.remove) && isFunction(value.add) && isFunction(value.unsubscribe);
12865
+ }
12866
+ function execFinalizer(finalizer) {
12867
+ if (isFunction(finalizer)) {
12868
+ finalizer();
12869
+ } else {
12870
+ finalizer.unsubscribe();
12775
12871
  }
12776
- async executeAggregate(wheres, orders, limit, skip, spec, groupBy) {
12777
- var _a, _b, _c;
12778
- validateAggregateSpec(spec);
12779
- const activeGroupBy = groupBy && groupBy.length > 0 ? groupBy : void 0;
12780
- if (activeGroupBy) {
12781
- validateGroupBySpec(activeGroupBy, spec);
12872
+ }
12873
+ var timeoutProvider = {
12874
+ setTimeout: function(handler, timeout) {
12875
+ var args = [];
12876
+ for (var _i = 2; _i < arguments.length; _i++) {
12877
+ args[_i - 2] = arguments[_i];
12782
12878
  }
12783
- const selectParam = buildAggregateSelect(spec, activeGroupBy);
12784
- if (!selectParam) {
12785
- return activeGroupBy ? [] : {};
12879
+ return setTimeout.apply(void 0, __spreadArray([handler, timeout], __read(args)));
12880
+ },
12881
+ clearTimeout: function(handle) {
12882
+ return clearTimeout(handle);
12883
+ },
12884
+ delegate: void 0
12885
+ };
12886
+ function reportUnhandledError(err) {
12887
+ timeoutProvider.setTimeout(function() {
12888
+ {
12889
+ throw err;
12786
12890
  }
12787
- const filterParams = buildPostgrestFilters(wheres);
12788
- const params = {
12789
- select: selectParam,
12790
- ...filterParams
12791
- };
12792
- if (limit !== void 0) params["limit"] = limit;
12793
- if (skip !== void 0) params["offset"] = skip;
12794
- if (activeGroupBy && orders.length > 0) {
12795
- const groupBySet = new Set(activeGroupBy);
12796
- for (const { field } of orders) {
12797
- if (!groupBySet.has(field)) {
12798
- throw new InputTableError(
12799
- `orderBy field "${field}" must be one of the groupBy columns: [${activeGroupBy.join(", ")}]`,
12800
- 400
12801
- );
12802
- }
12891
+ });
12892
+ }
12893
+ function noop() {
12894
+ }
12895
+ var Subscriber = function(_super) {
12896
+ __extends(Subscriber2, _super);
12897
+ function Subscriber2(destination) {
12898
+ var _this = _super.call(this) || this;
12899
+ _this.isStopped = false;
12900
+ if (destination) {
12901
+ _this.destination = destination;
12902
+ if (isSubscription(destination)) {
12903
+ destination.add(_this);
12803
12904
  }
12804
- params["order"] = buildPostgrestOrder(orders);
12905
+ } else {
12906
+ _this.destination = EMPTY_OBSERVER;
12805
12907
  }
12806
- let response;
12908
+ return _this;
12909
+ }
12910
+ Subscriber2.create = function(next, error, complete) {
12911
+ return new SafeSubscriber(next, error, complete);
12912
+ };
12913
+ Subscriber2.prototype.next = function(value) {
12914
+ if (this.isStopped) ;
12915
+ else {
12916
+ this._next(value);
12917
+ }
12918
+ };
12919
+ Subscriber2.prototype.error = function(err) {
12920
+ if (this.isStopped) ;
12921
+ else {
12922
+ this.isStopped = true;
12923
+ this._error(err);
12924
+ }
12925
+ };
12926
+ Subscriber2.prototype.complete = function() {
12927
+ if (this.isStopped) ;
12928
+ else {
12929
+ this.isStopped = true;
12930
+ this._complete();
12931
+ }
12932
+ };
12933
+ Subscriber2.prototype.unsubscribe = function() {
12934
+ if (!this.closed) {
12935
+ this.isStopped = true;
12936
+ _super.prototype.unsubscribe.call(this);
12937
+ this.destination = null;
12938
+ }
12939
+ };
12940
+ Subscriber2.prototype._next = function(value) {
12941
+ this.destination.next(value);
12942
+ };
12943
+ Subscriber2.prototype._error = function(err) {
12807
12944
  try {
12808
- response = await apiClient.get(
12809
- `/input-table-v2/${this.solutionId}/rows/${this.tableName}`,
12810
- { params, headers: getSolutionBranchHeaders() }
12811
- );
12812
- } catch (err) {
12813
- const axiosErr = err;
12814
- throw new InputTableError(
12815
- ((_b = (_a = axiosErr.response) == null ? void 0 : _a.data) == null ? void 0 : _b.message) ?? axiosErr.message ?? "Aggregate query failed",
12816
- ((_c = axiosErr.response) == null ? void 0 : _c.status) ?? 500
12817
- );
12945
+ this.destination.error(err);
12946
+ } finally {
12947
+ this.unsubscribe();
12818
12948
  }
12819
- const data = Array.isArray(response.data) ? response.data : [response.data];
12820
- if (activeGroupBy) {
12821
- return parseGroupedAggregateResponse(spec, activeGroupBy, data);
12949
+ };
12950
+ Subscriber2.prototype._complete = function() {
12951
+ try {
12952
+ this.destination.complete();
12953
+ } finally {
12954
+ this.unsubscribe();
12822
12955
  }
12823
- return parseAggregateResponse(spec, data);
12956
+ };
12957
+ return Subscriber2;
12958
+ }(Subscription2);
12959
+ var ConsumerObserver = function() {
12960
+ function ConsumerObserver2(partialObserver) {
12961
+ this.partialObserver = partialObserver;
12962
+ }
12963
+ ConsumerObserver2.prototype.next = function(value) {
12964
+ var partialObserver = this.partialObserver;
12965
+ if (partialObserver.next) {
12966
+ try {
12967
+ partialObserver.next(value);
12968
+ } catch (error) {
12969
+ handleUnhandledError(error);
12970
+ }
12971
+ }
12972
+ };
12973
+ ConsumerObserver2.prototype.error = function(err) {
12974
+ var partialObserver = this.partialObserver;
12975
+ if (partialObserver.error) {
12976
+ try {
12977
+ partialObserver.error(err);
12978
+ } catch (error) {
12979
+ handleUnhandledError(error);
12980
+ }
12981
+ } else {
12982
+ handleUnhandledError(err);
12983
+ }
12984
+ };
12985
+ ConsumerObserver2.prototype.complete = function() {
12986
+ var partialObserver = this.partialObserver;
12987
+ if (partialObserver.complete) {
12988
+ try {
12989
+ partialObserver.complete();
12990
+ } catch (error) {
12991
+ handleUnhandledError(error);
12992
+ }
12993
+ }
12994
+ };
12995
+ return ConsumerObserver2;
12996
+ }();
12997
+ var SafeSubscriber = function(_super) {
12998
+ __extends(SafeSubscriber2, _super);
12999
+ function SafeSubscriber2(observerOrNext, error, complete) {
13000
+ var _this = _super.call(this) || this;
13001
+ var partialObserver;
13002
+ if (isFunction(observerOrNext) || !observerOrNext) {
13003
+ partialObserver = {
13004
+ next: observerOrNext !== null && observerOrNext !== void 0 ? observerOrNext : void 0,
13005
+ error: error !== null && error !== void 0 ? error : void 0,
13006
+ complete: complete !== null && complete !== void 0 ? complete : void 0
13007
+ };
13008
+ } else {
13009
+ {
13010
+ partialObserver = observerOrNext;
13011
+ }
13012
+ }
13013
+ _this.destination = new ConsumerObserver(partialObserver);
13014
+ return _this;
13015
+ }
13016
+ return SafeSubscriber2;
13017
+ }(Subscriber);
13018
+ function handleUnhandledError(error) {
13019
+ {
13020
+ reportUnhandledError(error);
13021
+ }
13022
+ }
13023
+ function defaultErrorHandler(err) {
13024
+ throw err;
13025
+ }
13026
+ var EMPTY_OBSERVER = {
13027
+ closed: true,
13028
+ next: noop,
13029
+ error: defaultErrorHandler,
13030
+ complete: noop
13031
+ };
13032
+ function createOperatorSubscriber(destination, onNext, onComplete, onError, onFinalize) {
13033
+ return new OperatorSubscriber(destination, onNext, onComplete, onError, onFinalize);
13034
+ }
13035
+ var OperatorSubscriber = function(_super) {
13036
+ __extends(OperatorSubscriber2, _super);
13037
+ function OperatorSubscriber2(destination, onNext, onComplete, onError, onFinalize, shouldUnsubscribe) {
13038
+ var _this = _super.call(this, destination) || this;
13039
+ _this.onFinalize = onFinalize;
13040
+ _this.shouldUnsubscribe = shouldUnsubscribe;
13041
+ _this._next = onNext ? function(value) {
13042
+ try {
13043
+ onNext(value);
13044
+ } catch (err) {
13045
+ destination.error(err);
13046
+ }
13047
+ } : _super.prototype._next;
13048
+ _this._error = onError ? function(err) {
13049
+ try {
13050
+ onError(err);
13051
+ } catch (err2) {
13052
+ destination.error(err2);
13053
+ } finally {
13054
+ this.unsubscribe();
13055
+ }
13056
+ } : _super.prototype._error;
13057
+ _this._complete = onComplete ? function() {
13058
+ try {
13059
+ onComplete();
13060
+ } catch (err) {
13061
+ destination.error(err);
13062
+ } finally {
13063
+ this.unsubscribe();
13064
+ }
13065
+ } : _super.prototype._complete;
13066
+ return _this;
13067
+ }
13068
+ OperatorSubscriber2.prototype.unsubscribe = function() {
13069
+ var _a;
13070
+ if (!this.shouldUnsubscribe || this.shouldUnsubscribe()) {
13071
+ var closed_1 = this.closed;
13072
+ _super.prototype.unsubscribe.call(this);
13073
+ !closed_1 && ((_a = this.onFinalize) === null || _a === void 0 ? void 0 : _a.call(this));
13074
+ }
13075
+ };
13076
+ return OperatorSubscriber2;
13077
+ }(Subscriber);
13078
+ function map(project, thisArg) {
13079
+ return operate(function(source, subscriber) {
13080
+ var index2 = 0;
13081
+ source.subscribe(createOperatorSubscriber(subscriber, function(value) {
13082
+ subscriber.next(project.call(thisArg, value, index2++));
13083
+ }));
13084
+ });
13085
+ }
13086
+ function buildLookupMap(rows, pkField) {
13087
+ const m = /* @__PURE__ */ new Map();
13088
+ for (const row of rows) {
13089
+ const pk = row[pkField];
13090
+ if (pk === void 0 || pk === null) continue;
13091
+ m.set(pk, row);
12824
13092
  }
13093
+ return m;
13094
+ }
13095
+ function joinRowsWithLookups(primaryRows, directives, lookups) {
13096
+ return primaryRows.map((row) => {
13097
+ var _a;
13098
+ const out = { ...row };
13099
+ for (const d of directives) {
13100
+ const fkValue = row[d.fkColumn];
13101
+ const found = (_a = lookups[d.referencedTable]) == null ? void 0 : _a.get(fkValue);
13102
+ if (found !== void 0) out[d.alias] = found;
13103
+ }
13104
+ return out;
13105
+ });
13106
+ }
13107
+ function createExpandedSubscription(config, cb) {
13108
+ const refKeys = Object.keys(config.referenced);
13109
+ const streams = [config.primary$, ...refKeys.map((k) => config.referenced[k].stream$)];
13110
+ const sub = combineLatest(streams).pipe(
13111
+ map(([primary, ...refs]) => {
13112
+ const lookups = {};
13113
+ refKeys.forEach((k, i) => {
13114
+ lookups[k] = buildLookupMap(refs[i], config.referenced[k].pkField);
13115
+ });
13116
+ return joinRowsWithLookups(primary, config.directives, lookups);
13117
+ })
13118
+ ).subscribe({
13119
+ next: cb,
13120
+ error: (err) => console.error("[expandedView] subscription error", err)
13121
+ });
13122
+ return () => sub.unsubscribe();
12825
13123
  }
12826
13124
  let dbPromise = null;
12827
13125
  function getInputTableDatabase() {
@@ -12853,6 +13151,11 @@ async function closeInputTableDatabase() {
12853
13151
  dbPromise = null;
12854
13152
  }
12855
13153
  }
13154
+ const CHECKPOINT_FIELD = "updated_at";
13155
+ const MAX_COLLECTIONS = 14;
13156
+ const REPLICATION_RETRY_TIME = 5e3;
13157
+ const PULL_BATCH_SIZE = 100;
13158
+ const PUSH_BATCH_SIZE = 10;
12856
13159
  const PG_TO_JSON_SCHEMA = {
12857
13160
  [InputTableColumnType.UUID]: { type: "string" },
12858
13161
  [InputTableColumnType.TEXT]: { type: "string" },
@@ -12939,6 +13242,7 @@ function createReplication(collection, solutionId, tableName, primaryKeyField) {
12939
13242
  const conflicts = [];
12940
13243
  for (const row of changeRows) {
12941
13244
  const doc = row.newDocumentState;
13245
+ if (doc._deleted) continue;
12942
13246
  try {
12943
13247
  if (row.assumedMasterState == null) {
12944
13248
  const insertData = { ...doc };
@@ -13020,14 +13324,30 @@ function createReplication(collection, solutionId, tableName, primaryKeyField) {
13020
13324
  }
13021
13325
  };
13022
13326
  }
13023
- function createRealtimeBinding(provider, replicationState, workspaceId, solutionId, tableName) {
13327
+ function createRealtimeBinding(provider, replicationState, collection, primaryKeyField, workspaceId, solutionId, tableName) {
13024
13328
  const channel = `public-input-table-v2-${workspaceId}-${solutionId}-${tableName}`;
13025
- function handleChangeNotification() {
13329
+ function handleUpsert() {
13026
13330
  replicationState.reSync();
13027
13331
  }
13028
- provider.bind(channel, "INSERT", handleChangeNotification);
13029
- provider.bind(channel, "UPDATE", handleChangeNotification);
13030
- provider.bind(channel, "DELETE", handleChangeNotification);
13332
+ async function handleDelete(payload) {
13333
+ const data = payload;
13334
+ if (!data || data.truncated || !Array.isArray(data.deleted_rows) || data.deleted_rows.length === 0) {
13335
+ replicationState.reSync();
13336
+ return;
13337
+ }
13338
+ for (const row of data.deleted_rows) {
13339
+ const pk = row == null ? void 0 : row[primaryKeyField];
13340
+ if (pk == null) continue;
13341
+ try {
13342
+ const doc = await collection.findOne(String(pk)).exec();
13343
+ if (doc) await doc.remove();
13344
+ } catch {
13345
+ }
13346
+ }
13347
+ }
13348
+ provider.bind(channel, "INSERT", handleUpsert);
13349
+ provider.bind(channel, "UPDATE", handleUpsert);
13350
+ provider.bind(channel, "DELETE", handleDelete);
13031
13351
  return {
13032
13352
  cleanup: () => {
13033
13353
  provider.unbind(channel, "INSERT");
@@ -13038,11 +13358,42 @@ function createRealtimeBinding(provider, replicationState, workspaceId, solution
13038
13358
  }
13039
13359
  const activeCollections = /* @__PURE__ */ new Map();
13040
13360
  const pendingCollections = /* @__PURE__ */ new Map();
13361
+ const closingCollections = /* @__PURE__ */ new Map();
13041
13362
  function collectionKey(workspaceId, solutionId, tableName) {
13042
13363
  return `${workspaceId}:${toCollectionName(solutionId, tableName)}`;
13043
13364
  }
13365
+ async function pinCollection(solutionId, tableDef, workspaceId, websocketProvider) {
13366
+ const managed = await getOrCreateCollection(solutionId, tableDef, workspaceId, websocketProvider);
13367
+ managed.refCount += 1;
13368
+ managed.lastAccessed = Date.now();
13369
+ return managed;
13370
+ }
13371
+ async function unpinCollection(solutionId, tableName, workspaceId) {
13372
+ const key = collectionKey(workspaceId, solutionId, tableName);
13373
+ const managed = activeCollections.get(key);
13374
+ if (!managed) return;
13375
+ managed.refCount -= 1;
13376
+ if (managed.refCount > 0) return;
13377
+ const existing = closingCollections.get(key);
13378
+ if (existing) return existing;
13379
+ const teardown = (async () => {
13380
+ var _a;
13381
+ try {
13382
+ (_a = managed.realtimeBinding) == null ? void 0 : _a.cleanup();
13383
+ await managed.replication.cancel();
13384
+ await managed.collection.close();
13385
+ } finally {
13386
+ if (activeCollections.get(key) === managed) activeCollections.delete(key);
13387
+ closingCollections.delete(key);
13388
+ }
13389
+ })();
13390
+ closingCollections.set(key, teardown);
13391
+ await teardown;
13392
+ }
13044
13393
  async function getOrCreateCollection(solutionId, tableDef, workspaceId, websocketProvider) {
13045
13394
  const key = collectionKey(workspaceId, solutionId, tableDef.name);
13395
+ const closing = closingCollections.get(key);
13396
+ if (closing) await closing;
13046
13397
  const existing = activeCollections.get(key);
13047
13398
  if (existing) {
13048
13399
  existing.lastAccessed = Date.now();
@@ -13109,6 +13460,8 @@ async function createCollectionInternal(key, solutionId, tableDef, workspaceId,
13109
13460
  realtimeBinding = createRealtimeBinding(
13110
13461
  websocketProvider,
13111
13462
  replication.state,
13463
+ collection,
13464
+ pkField,
13112
13465
  workspaceId,
13113
13466
  solutionId,
13114
13467
  tableDef.name
@@ -13158,41 +13511,527 @@ async function evictLeastRecentlyUsed() {
13158
13511
  );
13159
13512
  }
13160
13513
  }
13161
- const SOLUTION_COOKIE_NAME = "x-bluecopa-solution-id";
13162
- function getCookieValue(name) {
13163
- try {
13164
- const cookie = document.cookie.split(";").map((c) => c.trim()).find((c) => c.startsWith(`${name}=`));
13165
- return cookie ? decodeURIComponent(cookie.split("=").slice(1).join("=")) : null;
13166
- } catch {
13167
- return null;
13168
- }
13169
- }
13170
- function getSolutionId() {
13171
- const config = getConfig();
13172
- if (config.solutionId) {
13173
- return validateIdentifier(config.solutionId, "solutionId");
13174
- }
13175
- const cookieValue = getCookieValue(SOLUTION_COOKIE_NAME);
13176
- if (cookieValue) {
13177
- return validateIdentifier(cookieValue, "solutionId (cookie)");
13178
- }
13179
- throw new InputTableError(
13180
- "[copaInputTableDb] No solutionId configured. Set via copaSetConfig({ solutionId }) or cookie.",
13181
- 400
13514
+ function rxCollectionStream(collection) {
13515
+ return collection.find().$.pipe(
13516
+ map$1((docs) => docs.map((d) => d.toJSON()))
13182
13517
  );
13183
13518
  }
13184
- const _InputTableDBImpl = class _InputTableDBImpl {
13185
- constructor() {
13186
- this.schemaCache = /* @__PURE__ */ new Map();
13187
- this.schemaPending = /* @__PURE__ */ new Map();
13188
- this.wsWarned = false;
13189
- this.generation = 0;
13519
+ const OP_MAP = {
13520
+ "==": "$eq",
13521
+ "!=": "$ne",
13522
+ "<": "$lt",
13523
+ "<=": "$lte",
13524
+ ">": "$gt",
13525
+ ">=": "$gte",
13526
+ in: "$in",
13527
+ "not-in": "$nin"
13528
+ };
13529
+ class QueryBuilderImpl {
13530
+ constructor(collection, initialWhere, initialOrder, initialLimit, initialSkip, aggregateExecutor, expandContext) {
13531
+ this.collection = collection;
13532
+ this.aggregateExecutor = aggregateExecutor;
13533
+ this.expandContext = expandContext;
13534
+ this.wheres = [];
13535
+ this.orders = [];
13536
+ if (initialWhere) this.wheres.push(initialWhere);
13537
+ if (initialOrder) this.orders.push(initialOrder);
13538
+ if (initialLimit !== void 0) this.limitCount = initialLimit;
13539
+ if (initialSkip !== void 0) this.skipCount = initialSkip;
13190
13540
  }
13191
- setWebsocketProvider(provider) {
13192
- this.wsProvider = provider;
13541
+ where(field, op, value) {
13542
+ this.wheres.push({ field, op, value });
13543
+ return this;
13193
13544
  }
13194
- getProvider() {
13195
- return this.wsProvider ?? getConfig().websocketProvider;
13545
+ orderBy(field, direction = "asc") {
13546
+ this.orders.push({ field, direction });
13547
+ return this;
13548
+ }
13549
+ limit(count) {
13550
+ this.limitCount = count;
13551
+ return this;
13552
+ }
13553
+ skip(count) {
13554
+ this.skipCount = count;
13555
+ return this;
13556
+ }
13557
+ expand(columnNames) {
13558
+ if (columnNames.length === 0) {
13559
+ throw new InputTableError(".expand() requires at least one column name", 400);
13560
+ }
13561
+ const existing = this.expandContext;
13562
+ if (!existing) {
13563
+ throw new InputTableError(
13564
+ ".expand() is only available on builders derived from a CollectionRef with a loaded schema",
13565
+ 500
13566
+ );
13567
+ }
13568
+ const merged = Array.from(/* @__PURE__ */ new Set([...existing.expandColumns, ...columnNames]));
13569
+ for (const name of merged) {
13570
+ resolveRelationship(name, existing.schema);
13571
+ }
13572
+ this.expandContext = { ...existing, expandColumns: merged };
13573
+ return this;
13574
+ }
13575
+ subscribe(callback) {
13576
+ if (this.expandContext) {
13577
+ return this.subscribeWithExpand(this.expandContext, callback);
13578
+ }
13579
+ const query = this.buildQuery();
13580
+ const rxSub = query.$.subscribe((docs) => {
13581
+ callback(docs.map((d) => d.toJSON()));
13582
+ });
13583
+ return () => rxSub.unsubscribe();
13584
+ }
13585
+ buildPrimaryStream() {
13586
+ const query = this.buildQuery();
13587
+ return query.$.pipe(
13588
+ map$1((docs) => docs.map((d) => d.toJSON()))
13589
+ );
13590
+ }
13591
+ subscribeWithExpand(ctx, callback) {
13592
+ const directives = buildExpandDirectives(ctx.expandColumns, ctx.schema);
13593
+ let cancelled = false;
13594
+ let innerStop = null;
13595
+ const unpinFns = [];
13596
+ const unpinAll = async () => {
13597
+ while (unpinFns.length > 0) {
13598
+ const fn = unpinFns.pop();
13599
+ try {
13600
+ await (fn == null ? void 0 : fn());
13601
+ } catch {
13602
+ }
13603
+ }
13604
+ };
13605
+ const wsProvider = ctx.getWebsocketProvider();
13606
+ void (async () => {
13607
+ var _a;
13608
+ try {
13609
+ await pinCollection(ctx.solutionId, ctx.schema, ctx.workspaceId, wsProvider);
13610
+ unpinFns.push(
13611
+ () => unpinCollection(ctx.solutionId, ctx.tableName, ctx.workspaceId)
13612
+ );
13613
+ if (cancelled) {
13614
+ await unpinAll();
13615
+ return;
13616
+ }
13617
+ const uniqueRefs = Array.from(new Set(directives.map((d) => d.referencedTable)));
13618
+ const referenced = {};
13619
+ for (const refName of uniqueRefs) {
13620
+ if (refName === ctx.tableName) {
13621
+ const pkField = ((_a = ctx.schema.columns.find((c) => c.primary_key)) == null ? void 0 : _a.name) ?? "id";
13622
+ referenced[refName] = {
13623
+ stream$: rxCollectionStream(this.collection),
13624
+ pkField
13625
+ };
13626
+ continue;
13627
+ }
13628
+ const refSchema = ctx.getSchemaForTable(refName);
13629
+ if (!refSchema) {
13630
+ throw new InputTableError(
13631
+ `Referenced table '${refName}' not found in schema cache`,
13632
+ 404
13633
+ );
13634
+ }
13635
+ const managed = await pinCollection(
13636
+ ctx.solutionId,
13637
+ refSchema,
13638
+ ctx.workspaceId,
13639
+ wsProvider
13640
+ );
13641
+ unpinFns.push(
13642
+ () => unpinCollection(ctx.solutionId, refName, ctx.workspaceId)
13643
+ );
13644
+ referenced[refName] = {
13645
+ stream$: rxCollectionStream(managed.collection),
13646
+ pkField: managed.primaryKeyField
13647
+ };
13648
+ if (cancelled) {
13649
+ await unpinAll();
13650
+ return;
13651
+ }
13652
+ }
13653
+ if (cancelled) {
13654
+ await unpinAll();
13655
+ return;
13656
+ }
13657
+ innerStop = createExpandedSubscription(
13658
+ { primary$: this.buildPrimaryStream(), referenced, directives },
13659
+ callback
13660
+ );
13661
+ if (cancelled) {
13662
+ innerStop();
13663
+ innerStop = null;
13664
+ await unpinAll();
13665
+ }
13666
+ } catch (err) {
13667
+ console.error("[copaInputTableDb] expand.subscribe wiring failed", err);
13668
+ await unpinAll();
13669
+ }
13670
+ })();
13671
+ return () => {
13672
+ cancelled = true;
13673
+ innerStop == null ? void 0 : innerStop();
13674
+ innerStop = null;
13675
+ void unpinAll();
13676
+ };
13677
+ }
13678
+ async get() {
13679
+ if (this.expandContext) {
13680
+ return this.getWithExpand(this.expandContext);
13681
+ }
13682
+ const query = this.buildQuery();
13683
+ const docs = await query.exec();
13684
+ return docs.map((d) => d.toJSON());
13685
+ }
13686
+ async getWithExpand(ctx) {
13687
+ var _a, _b, _c;
13688
+ const directives = buildExpandDirectives(ctx.expandColumns, ctx.schema);
13689
+ const selectParam = buildExpandSelectParam(directives);
13690
+ const params = {
13691
+ select: selectParam,
13692
+ ...buildPostgrestFilters(this.wheres)
13693
+ };
13694
+ if (this.limitCount !== void 0) params["limit"] = this.limitCount;
13695
+ if (this.skipCount !== void 0) params["offset"] = this.skipCount;
13696
+ if (this.orders.length > 0) params["order"] = buildPostgrestOrder(this.orders);
13697
+ let response;
13698
+ try {
13699
+ response = await apiClient.get(
13700
+ `/input-table-v2/${ctx.solutionId}/rows/${ctx.tableName}`,
13701
+ { params, headers: ctx.getHeaders() }
13702
+ );
13703
+ } catch (err) {
13704
+ const message = isAxiosError(err) ? ((_b = (_a = err.response) == null ? void 0 : _a.data) == null ? void 0 : _b.message) ?? err.message : (err == null ? void 0 : err.message) ?? "Expand query failed";
13705
+ const status = isAxiosError(err) ? ((_c = err.response) == null ? void 0 : _c.status) ?? 500 : 500;
13706
+ throw new InputTableError(message, status);
13707
+ }
13708
+ return response.data ?? [];
13709
+ }
13710
+ async aggregate(spec, options) {
13711
+ if (this.expandContext) {
13712
+ throw new InputTableError(".expand() cannot be combined with .aggregate()", 400);
13713
+ }
13714
+ if (!this.aggregateExecutor) {
13715
+ throw new InputTableError(
13716
+ "[copaInputTableDb] aggregate() is not available on this QueryBuilder instance",
13717
+ 500
13718
+ );
13719
+ }
13720
+ return this.aggregateExecutor(
13721
+ this.wheres,
13722
+ this.orders,
13723
+ this.limitCount,
13724
+ this.skipCount,
13725
+ spec,
13726
+ options == null ? void 0 : options.groupBy
13727
+ );
13728
+ }
13729
+ buildQuery() {
13730
+ const selector = {};
13731
+ for (const { field, op, value } of this.wheres) {
13732
+ const rxOp = OP_MAP[op];
13733
+ if (!selector[field]) selector[field] = {};
13734
+ selector[field][rxOp] = value;
13735
+ }
13736
+ const queryParams = { selector };
13737
+ if (this.orders.length > 0) {
13738
+ queryParams.sort = this.orders.map(({ field, direction }) => ({ [field]: direction }));
13739
+ }
13740
+ if (this.limitCount !== void 0) {
13741
+ queryParams.limit = this.limitCount;
13742
+ }
13743
+ if (this.skipCount !== void 0) {
13744
+ queryParams.skip = this.skipCount;
13745
+ }
13746
+ return this.collection.find(queryParams);
13747
+ }
13748
+ }
13749
+ class DocRefImpl {
13750
+ constructor(collection, id, solutionId, tableName, primaryKeyField, websocketProvider) {
13751
+ this.collection = collection;
13752
+ this.id = id;
13753
+ this.solutionId = solutionId;
13754
+ this.tableName = tableName;
13755
+ this.primaryKeyField = primaryKeyField;
13756
+ this.websocketProvider = websocketProvider;
13757
+ }
13758
+ async get() {
13759
+ const doc = await this.collection.findOne(this.id).exec();
13760
+ return doc ? doc.toJSON() : null;
13761
+ }
13762
+ async update(data) {
13763
+ const doc = await this.collection.findOne(this.id).exec();
13764
+ if (!doc) {
13765
+ throw new InputTableError(`Document "${this.id}" not found`, 404);
13766
+ }
13767
+ const patch = { ...data };
13768
+ delete patch[this.primaryKeyField];
13769
+ delete patch[CHECKPOINT_FIELD];
13770
+ await doc.patch(patch);
13771
+ }
13772
+ async delete() {
13773
+ await apiClient.request({
13774
+ url: `input-table-v2/${this.solutionId}/rows/${this.tableName}`,
13775
+ method: "DELETE",
13776
+ params: { [this.primaryKeyField]: `eq.${this.id}` }
13777
+ });
13778
+ const doc = await this.collection.findOne(this.id).exec();
13779
+ if (doc) await doc.remove();
13780
+ }
13781
+ onSnapshot(callback) {
13782
+ const rxSub = this.collection.findOne(this.id).$.subscribe((doc) => {
13783
+ callback(doc ? doc.toJSON() : null);
13784
+ });
13785
+ return () => rxSub.unsubscribe();
13786
+ }
13787
+ }
13788
+ class CollectionRefImpl {
13789
+ constructor(collection, solutionId, tableName, primaryKeyField, pkColumn, replicationState, getWebsocketProvider, schema, getSchemaForTable) {
13790
+ this.collection = collection;
13791
+ this.solutionId = solutionId;
13792
+ this.tableName = tableName;
13793
+ this.primaryKeyField = primaryKeyField;
13794
+ this.pkColumn = pkColumn;
13795
+ this.replicationState = replicationState;
13796
+ this.getWebsocketProvider = getWebsocketProvider;
13797
+ this.schema = schema;
13798
+ this.getSchemaForTable = getSchemaForTable;
13799
+ }
13800
+ makeQueryBuilder(initialWhere, initialOrder, initialLimit, initialSkip, expandContext) {
13801
+ return new QueryBuilderImpl(
13802
+ this.collection,
13803
+ initialWhere,
13804
+ initialOrder,
13805
+ initialLimit,
13806
+ initialSkip,
13807
+ (wheres, orders, limit, skip, spec, groupBy) => this.executeAggregate(wheres, orders, limit, skip, spec, groupBy),
13808
+ expandContext
13809
+ );
13810
+ }
13811
+ where(field, op, value) {
13812
+ return this.makeQueryBuilder({ field, op, value });
13813
+ }
13814
+ orderBy(field, direction = "asc") {
13815
+ return this.makeQueryBuilder(void 0, { field, direction });
13816
+ }
13817
+ limit(count) {
13818
+ return this.makeQueryBuilder(void 0, void 0, count);
13819
+ }
13820
+ skip(count) {
13821
+ return this.makeQueryBuilder(void 0, void 0, void 0, count);
13822
+ }
13823
+ expand(columnNames) {
13824
+ if (columnNames.length === 0) {
13825
+ throw new InputTableError(".expand() requires at least one column name", 400);
13826
+ }
13827
+ if (!this.schema) {
13828
+ throw new InputTableError(
13829
+ ".expand() requires the collection to be initialised with its schema",
13830
+ 500
13831
+ );
13832
+ }
13833
+ for (const name of columnNames) {
13834
+ resolveRelationship(name, this.schema);
13835
+ }
13836
+ const workspaceId = getConfig().workspaceId ?? "";
13837
+ const schema = this.schema;
13838
+ const ctx = {
13839
+ schema,
13840
+ expandColumns: [...columnNames],
13841
+ solutionId: this.solutionId,
13842
+ tableName: this.tableName,
13843
+ workspaceId,
13844
+ getHeaders: () => getSolutionBranchHeaders(),
13845
+ getSchemaForTable: (name) => this.getSchemaForTable ? this.getSchemaForTable(name) : schema.name === name ? schema : null,
13846
+ getWebsocketProvider: () => this.getWebsocketProvider()
13847
+ };
13848
+ return this.makeQueryBuilder(void 0, void 0, void 0, void 0, ctx);
13849
+ }
13850
+ doc(id) {
13851
+ return new DocRefImpl(
13852
+ this.collection,
13853
+ id,
13854
+ this.solutionId,
13855
+ this.tableName,
13856
+ this.primaryKeyField,
13857
+ this.getWebsocketProvider
13858
+ );
13859
+ }
13860
+ async add(data) {
13861
+ var _a, _b;
13862
+ const pk = this.primaryKeyField;
13863
+ const insertData = { ...data };
13864
+ const needsServerPk = ((_a = this.pkColumn) == null ? void 0 : _a.auto_increment) && this.pkColumn.type !== InputTableColumnType.UUID && !insertData[pk];
13865
+ if (needsServerPk) {
13866
+ delete insertData[pk];
13867
+ delete insertData[CHECKPOINT_FIELD];
13868
+ const response = await apiClient.post(
13869
+ `/input-table-v2/${this.solutionId}/rows/${this.tableName}`,
13870
+ insertData,
13871
+ { headers: { Prefer: "return=representation" } }
13872
+ );
13873
+ this.replicationState.reSync();
13874
+ const serverRow = Array.isArray(response.data) ? response.data[0] : response.data;
13875
+ return String((serverRow == null ? void 0 : serverRow[pk]) ?? "");
13876
+ }
13877
+ if (((_b = this.pkColumn) == null ? void 0 : _b.type) === InputTableColumnType.UUID && this.pkColumn.auto_increment && !insertData[pk]) {
13878
+ insertData[pk] = crypto.randomUUID();
13879
+ }
13880
+ if (!insertData[pk]) {
13881
+ insertData[pk] = generatePushID();
13882
+ }
13883
+ insertData[pk] = String(insertData[pk]).trim();
13884
+ delete insertData[CHECKPOINT_FIELD];
13885
+ await this.collection.insert(insertData);
13886
+ return String(insertData[pk]);
13887
+ }
13888
+ /**
13889
+ * Subscribe to live changes on this collection. Auto-manages the underlying
13890
+ * RxDB collection's pin refcount so the collection stays alive for the
13891
+ * lifetime of the subscription.
13892
+ *
13893
+ * Note: `.get()`, `.count()`, and `DocRef.get()` intentionally do NOT pin
13894
+ * the collection. They are one-shot reads where the caller is expected to
13895
+ * tolerate the collection being LRU-evicted between calls. If you need a
13896
+ * long-lived reference, use `.subscribe(...)`.
13897
+ */
13898
+ subscribe(callback) {
13899
+ const rxSub = this.collection.find().$.subscribe((docs) => {
13900
+ callback(docs.map((d) => d.toJSON()));
13901
+ });
13902
+ const workspaceId = getConfig().workspaceId;
13903
+ const shouldManagePin = Boolean(this.schema) && Boolean(workspaceId);
13904
+ let cancelled = false;
13905
+ let pinResolved = false;
13906
+ let teardownRan = false;
13907
+ if (shouldManagePin) {
13908
+ pinCollection(
13909
+ this.solutionId,
13910
+ this.schema,
13911
+ workspaceId,
13912
+ this.getWebsocketProvider()
13913
+ ).then(() => {
13914
+ pinResolved = true;
13915
+ if (cancelled) {
13916
+ void unpinCollection(
13917
+ this.solutionId,
13918
+ this.tableName,
13919
+ workspaceId
13920
+ );
13921
+ }
13922
+ }).catch(() => {
13923
+ });
13924
+ }
13925
+ return () => {
13926
+ if (teardownRan) return;
13927
+ teardownRan = true;
13928
+ rxSub.unsubscribe();
13929
+ if (!shouldManagePin) return;
13930
+ if (pinResolved) {
13931
+ void unpinCollection(this.solutionId, this.tableName, workspaceId);
13932
+ } else {
13933
+ cancelled = true;
13934
+ }
13935
+ };
13936
+ }
13937
+ async get() {
13938
+ const docs = await this.collection.find().exec();
13939
+ return docs.map((d) => d.toJSON());
13940
+ }
13941
+ count(callback) {
13942
+ const rxSub = this.collection.count().$.subscribe((count) => {
13943
+ callback(count);
13944
+ });
13945
+ return () => rxSub.unsubscribe();
13946
+ }
13947
+ async aggregate(spec, options) {
13948
+ return this.executeAggregate([], [], void 0, void 0, spec, options == null ? void 0 : options.groupBy);
13949
+ }
13950
+ async executeAggregate(wheres, orders, limit, skip, spec, groupBy) {
13951
+ var _a, _b, _c;
13952
+ validateAggregateSpec(spec);
13953
+ const activeGroupBy = groupBy && groupBy.length > 0 ? groupBy : void 0;
13954
+ if (activeGroupBy) {
13955
+ validateGroupBySpec(activeGroupBy, spec);
13956
+ }
13957
+ const selectParam = buildAggregateSelect(spec, activeGroupBy);
13958
+ if (!selectParam) {
13959
+ return activeGroupBy ? [] : {};
13960
+ }
13961
+ const filterParams = buildPostgrestFilters(wheres);
13962
+ const params = {
13963
+ select: selectParam,
13964
+ ...filterParams
13965
+ };
13966
+ if (limit !== void 0) params["limit"] = limit;
13967
+ if (skip !== void 0) params["offset"] = skip;
13968
+ if (activeGroupBy && orders.length > 0) {
13969
+ const groupBySet = new Set(activeGroupBy);
13970
+ for (const { field } of orders) {
13971
+ if (!groupBySet.has(field)) {
13972
+ throw new InputTableError(
13973
+ `orderBy field "${field}" must be one of the groupBy columns: [${activeGroupBy.join(", ")}]`,
13974
+ 400
13975
+ );
13976
+ }
13977
+ }
13978
+ params["order"] = buildPostgrestOrder(orders);
13979
+ }
13980
+ let response;
13981
+ try {
13982
+ response = await apiClient.get(
13983
+ `/input-table-v2/${this.solutionId}/rows/${this.tableName}`,
13984
+ { params, headers: getSolutionBranchHeaders() }
13985
+ );
13986
+ } catch (err) {
13987
+ const axiosErr = err;
13988
+ throw new InputTableError(
13989
+ ((_b = (_a = axiosErr.response) == null ? void 0 : _a.data) == null ? void 0 : _b.message) ?? axiosErr.message ?? "Aggregate query failed",
13990
+ ((_c = axiosErr.response) == null ? void 0 : _c.status) ?? 500
13991
+ );
13992
+ }
13993
+ const data = Array.isArray(response.data) ? response.data : [response.data];
13994
+ if (activeGroupBy) {
13995
+ return parseGroupedAggregateResponse(spec, activeGroupBy, data);
13996
+ }
13997
+ return parseAggregateResponse(spec, data);
13998
+ }
13999
+ }
14000
+ const SOLUTION_COOKIE_NAME = "x-bluecopa-solution-id";
14001
+ function getCookieValue(name) {
14002
+ try {
14003
+ const cookie = document.cookie.split(";").map((c) => c.trim()).find((c) => c.startsWith(`${name}=`));
14004
+ return cookie ? decodeURIComponent(cookie.split("=").slice(1).join("=")) : null;
14005
+ } catch {
14006
+ return null;
14007
+ }
14008
+ }
14009
+ function getSolutionId() {
14010
+ const config = getConfig();
14011
+ if (config.solutionId) {
14012
+ return validateIdentifier(config.solutionId, "solutionId");
14013
+ }
14014
+ const cookieValue = getCookieValue(SOLUTION_COOKIE_NAME);
14015
+ if (cookieValue) {
14016
+ return validateIdentifier(cookieValue, "solutionId (cookie)");
14017
+ }
14018
+ throw new InputTableError(
14019
+ "[copaInputTableDb] No solutionId configured. Set via copaSetConfig({ solutionId }) or cookie.",
14020
+ 400
14021
+ );
14022
+ }
14023
+ const _InputTableDBImpl = class _InputTableDBImpl {
14024
+ constructor() {
14025
+ this.schemaCache = /* @__PURE__ */ new Map();
14026
+ this.schemaPending = /* @__PURE__ */ new Map();
14027
+ this.wsWarned = false;
14028
+ this.generation = 0;
14029
+ }
14030
+ setWebsocketProvider(provider) {
14031
+ this.wsProvider = provider;
14032
+ }
14033
+ getProvider() {
14034
+ return this.wsProvider ?? getConfig().websocketProvider;
13196
14035
  }
13197
14036
  collection(name) {
13198
14037
  const provider = this.getProvider();
@@ -13228,6 +14067,9 @@ const _InputTableDBImpl = class _InputTableDBImpl {
13228
14067
  );
13229
14068
  if (gen !== this.generation) throw new InputTableError("InputTableDB was destroyed", 410);
13230
14069
  const pkColumn = tableItem.appliedSchema.columns.find((c) => c.primary_key);
14070
+ const schemaByName = new Map(
14071
+ tables.map((t) => [t.name, t.appliedSchema ?? null])
14072
+ );
13231
14073
  return new CollectionRefImpl(
13232
14074
  managed.collection,
13233
14075
  solutionId,
@@ -13235,7 +14077,9 @@ const _InputTableDBImpl = class _InputTableDBImpl {
13235
14077
  managed.primaryKeyField,
13236
14078
  pkColumn,
13237
14079
  managed.replication.state,
13238
- () => this.getProvider()
14080
+ () => this.getProvider(),
14081
+ tableItem.appliedSchema,
14082
+ (name) => schemaByName.get(name) ?? null
13239
14083
  );
13240
14084
  }
13241
14085
  fetchTableList(solutionId) {
@@ -13297,6 +14141,11 @@ class LazyCollectionRef {
13297
14141
  skip(count) {
13298
14142
  return new LazyQueryBuilder(() => this.getRef().then((ref) => ref.skip(count)));
13299
14143
  }
14144
+ expand(columnNames) {
14145
+ return new LazyQueryBuilder(
14146
+ () => this.getRef().then((ref) => ref.expand(columnNames))
14147
+ );
14148
+ }
13300
14149
  doc(id) {
13301
14150
  return new LazyDocRef(id, () => this.getRef().then((ref) => ref.doc(id)));
13302
14151
  }
@@ -13356,6 +14205,9 @@ class LazyQueryBuilder {
13356
14205
  skip(count) {
13357
14206
  return this.chain((qb) => qb.skip(count));
13358
14207
  }
14208
+ expand(columnNames) {
14209
+ return this.chain((qb) => qb.expand(columnNames));
14210
+ }
13359
14211
  async resolveWithOps() {
13360
14212
  let qb = await this.resolveBase();
13361
14213
  for (const op of this.pendingOps) {