@deephaven/pouch-storage 0.32.1-beta.0 → 0.32.1-beta.11

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.
@@ -0,0 +1,38 @@
1
+ /// <reference types="pouchdb-find" />
2
+ import { CommandHistoryStorageItem } from '@deephaven/console';
3
+ import PouchCommandHistoryTable from './PouchCommandHistoryTable';
4
+ import { PouchStorageItem } from './PouchStorageTable';
5
+ type CommandHistoryStorageItemFindResponse = PouchDB.Find.FindResponse<CommandHistoryStorageItem & PouchStorageItem>;
6
+ type DatabaseName = string;
7
+ /**
8
+ * Cache for tracking things shared across multiple
9
+ * `PouchCommandHistoryTable` instances.
10
+ */
11
+ declare class PouchCommandHistoryCache {
12
+ constructor();
13
+ /**
14
+ * Keep track of pruning status for a database. This helps ensure only 1
15
+ * pruning operation gets executed if multiple instances of a PouchCommandHistory
16
+ * table load data at the same time.
17
+ */
18
+ isPruning: Map<DatabaseName, boolean>;
19
+ /**
20
+ * Cache for command history query results keyed by db name. The cached data
21
+ * will be shared across all `PouchCommandHistoryTable` instances that have
22
+ * the same db name.
23
+ */
24
+ response: Map<DatabaseName, Promise<CommandHistoryStorageItemFindResponse> | null>;
25
+ /**
26
+ * Keeps track of all `PouchCommandHistoryTable` instances.
27
+ */
28
+ tableRegistry: Map<DatabaseName, Set<PouchCommandHistoryTable>>;
29
+ /**
30
+ * Pauses PouchDB change listeners for any `PouchCommandHistoryTable` with
31
+ * the given database name. This will cancel existing subscriptions and
32
+ * return a callback that can be used to re-subscribe them.
33
+ * @param dbName
34
+ */
35
+ pauseChangeListeners(dbName: DatabaseName): () => void;
36
+ }
37
+ export default PouchCommandHistoryCache;
38
+ //# sourceMappingURL=PouchCommandHistoryCache.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PouchCommandHistoryCache.d.ts","sourceRoot":"","sources":["../src/PouchCommandHistoryCache.ts"],"names":[],"mappings":";AAAA,OAAO,EAAE,yBAAyB,EAAE,MAAM,oBAAoB,CAAC;AAE/D,OAAO,wBAAwB,MAAM,4BAA4B,CAAC;AAClE,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAEvD,KAAK,qCAAqC,GAAG,OAAO,CAAC,IAAI,CAAC,YAAY,CACpE,yBAAyB,GAAG,gBAAgB,CAC7C,CAAC;AAEF,KAAK,YAAY,GAAG,MAAM,CAAC;AAI3B;;;GAGG;AACH,cAAM,wBAAwB;;IAO5B;;;;OAIG;IACH,SAAS,EAAE,GAAG,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC;IAEtC;;;;OAIG;IACH,QAAQ,EAAE,GAAG,CACX,YAAY,EACZ,OAAO,CAAC,qCAAqC,CAAC,GAAG,IAAI,CACtD,CAAC;IAEF;;OAEG;IACH,aAAa,EAAE,GAAG,CAAC,YAAY,EAAE,GAAG,CAAC,wBAAwB,CAAC,CAAC,CAAC;IAEhE;;;;;OAKG;IACH,oBAAoB,CAAC,MAAM,EAAE,YAAY,GAAG,MAAM,IAAI;CAsBvD;AAED,eAAe,wBAAwB,CAAC"}
@@ -0,0 +1,56 @@
1
+ function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
2
+ function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return typeof key === "symbol" ? key : String(key); }
3
+ function _toPrimitive(input, hint) { if (typeof input !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (typeof res !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); }
4
+ import Log from '@deephaven/log';
5
+ var log = Log.module('PouchCommandHistoryCache');
6
+
7
+ /**
8
+ * Cache for tracking things shared across multiple
9
+ * `PouchCommandHistoryTable` instances.
10
+ */
11
+ class PouchCommandHistoryCache {
12
+ constructor() {
13
+ _defineProperty(this, "isPruning", void 0);
14
+ _defineProperty(this, "response", void 0);
15
+ _defineProperty(this, "tableRegistry", void 0);
16
+ this.isPruning = new Map();
17
+ this.response = new Map();
18
+ this.tableRegistry = new Map();
19
+ }
20
+
21
+ /**
22
+ * Keep track of pruning status for a database. This helps ensure only 1
23
+ * pruning operation gets executed if multiple instances of a PouchCommandHistory
24
+ * table load data at the same time.
25
+ */
26
+
27
+ /**
28
+ * Pauses PouchDB change listeners for any `PouchCommandHistoryTable` with
29
+ * the given database name. This will cancel existing subscriptions and
30
+ * return a callback that can be used to re-subscribe them.
31
+ * @param dbName
32
+ */
33
+ pauseChangeListeners(dbName) {
34
+ var _this$tableRegistry$g;
35
+ var pausedTables = [];
36
+ (_this$tableRegistry$g = this.tableRegistry.get(dbName)) === null || _this$tableRegistry$g === void 0 ? void 0 : _this$tableRegistry$g.forEach(table => {
37
+ if (table.changes) {
38
+ log.debug("Pausing event listeners on '".concat(dbName, "' table"), table);
39
+ table.changes.cancel();
40
+ pausedTables.push(table);
41
+ }
42
+ });
43
+ return () => {
44
+ pausedTables.forEach(table => {
45
+ var _this$tableRegistry$g2, _this$tableRegistry$g3;
46
+ // Resume listening for changes if the table is still in the registry
47
+ if ((_this$tableRegistry$g2 = (_this$tableRegistry$g3 = this.tableRegistry.get(dbName)) === null || _this$tableRegistry$g3 === void 0 ? void 0 : _this$tableRegistry$g3.has(table)) !== null && _this$tableRegistry$g2 !== void 0 ? _this$tableRegistry$g2 : false) {
48
+ log.debug("Resuming event listeners on '".concat(dbName, "' table"), table);
49
+ table.listenForChanges();
50
+ }
51
+ });
52
+ };
53
+ }
54
+ }
55
+ export default PouchCommandHistoryCache;
56
+ //# sourceMappingURL=PouchCommandHistoryCache.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PouchCommandHistoryCache.js","names":["Log","log","module","PouchCommandHistoryCache","constructor","isPruning","Map","response","tableRegistry","pauseChangeListeners","dbName","pausedTables","get","forEach","table","changes","debug","cancel","push","has","listenForChanges"],"sources":["../src/PouchCommandHistoryCache.ts"],"sourcesContent":["import { CommandHistoryStorageItem } from '@deephaven/console';\nimport Log from '@deephaven/log';\nimport PouchCommandHistoryTable from './PouchCommandHistoryTable';\nimport { PouchStorageItem } from './PouchStorageTable';\n\ntype CommandHistoryStorageItemFindResponse = PouchDB.Find.FindResponse<\n CommandHistoryStorageItem & PouchStorageItem\n>;\n\ntype DatabaseName = string;\n\nconst log = Log.module('PouchCommandHistoryCache');\n\n/**\n * Cache for tracking things shared across multiple\n * `PouchCommandHistoryTable` instances.\n */\nclass PouchCommandHistoryCache {\n constructor() {\n this.isPruning = new Map();\n this.response = new Map();\n this.tableRegistry = new Map();\n }\n\n /**\n * Keep track of pruning status for a database. This helps ensure only 1\n * pruning operation gets executed if multiple instances of a PouchCommandHistory\n * table load data at the same time.\n */\n isPruning: Map<DatabaseName, boolean>;\n\n /**\n * Cache for command history query results keyed by db name. The cached data\n * will be shared across all `PouchCommandHistoryTable` instances that have\n * the same db name.\n */\n response: Map<\n DatabaseName,\n Promise<CommandHistoryStorageItemFindResponse> | null\n >;\n\n /**\n * Keeps track of all `PouchCommandHistoryTable` instances.\n */\n tableRegistry: Map<DatabaseName, Set<PouchCommandHistoryTable>>;\n\n /**\n * Pauses PouchDB change listeners for any `PouchCommandHistoryTable` with\n * the given database name. This will cancel existing subscriptions and\n * return a callback that can be used to re-subscribe them.\n * @param dbName\n */\n pauseChangeListeners(dbName: DatabaseName): () => void {\n const pausedTables: PouchCommandHistoryTable[] = [];\n\n this.tableRegistry.get(dbName)?.forEach(table => {\n if (table.changes) {\n log.debug(`Pausing event listeners on '${dbName}' table`, table);\n table.changes.cancel();\n\n pausedTables.push(table);\n }\n });\n\n return () => {\n pausedTables.forEach(table => {\n // Resume listening for changes if the table is still in the registry\n if (this.tableRegistry.get(dbName)?.has(table) ?? false) {\n log.debug(`Resuming event listeners on '${dbName}' table`, table);\n table.listenForChanges();\n }\n });\n };\n }\n}\n\nexport default PouchCommandHistoryCache;\n"],"mappings":";;;AACA,OAAOA,GAAG,MAAM,gBAAgB;AAUhC,IAAMC,GAAG,GAAGD,GAAG,CAACE,MAAM,CAAC,0BAA0B,CAAC;;AAElD;AACA;AACA;AACA;AACA,MAAMC,wBAAwB,CAAC;EAC7BC,WAAW,GAAG;IAAA;IAAA;IAAA;IACZ,IAAI,CAACC,SAAS,GAAG,IAAIC,GAAG,EAAE;IAC1B,IAAI,CAACC,QAAQ,GAAG,IAAID,GAAG,EAAE;IACzB,IAAI,CAACE,aAAa,GAAG,IAAIF,GAAG,EAAE;EAChC;;EAEA;AACF;AACA;AACA;AACA;;EAkBE;AACF;AACA;AACA;AACA;AACA;EACEG,oBAAoB,CAACC,MAAoB,EAAc;IAAA;IACrD,IAAMC,YAAwC,GAAG,EAAE;IAEnD,6BAAI,CAACH,aAAa,CAACI,GAAG,CAACF,MAAM,CAAC,0DAA9B,sBAAgCG,OAAO,CAACC,KAAK,IAAI;MAC/C,IAAIA,KAAK,CAACC,OAAO,EAAE;QACjBd,GAAG,CAACe,KAAK,uCAAgCN,MAAM,cAAWI,KAAK,CAAC;QAChEA,KAAK,CAACC,OAAO,CAACE,MAAM,EAAE;QAEtBN,YAAY,CAACO,IAAI,CAACJ,KAAK,CAAC;MAC1B;IACF,CAAC,CAAC;IAEF,OAAO,MAAM;MACXH,YAAY,CAACE,OAAO,CAACC,KAAK,IAAI;QAAA;QAC5B;QACA,wDAAI,IAAI,CAACN,aAAa,CAACI,GAAG,CAACF,MAAM,CAAC,2DAA9B,uBAAgCS,GAAG,CAACL,KAAK,CAAC,2EAAI,KAAK,EAAE;UACvDb,GAAG,CAACe,KAAK,wCAAiCN,MAAM,cAAWI,KAAK,CAAC;UACjEA,KAAK,CAACM,gBAAgB,EAAE;QAC1B;MACF,CAAC,CAAC;IACJ,CAAC;EACH;AACF;AAEA,eAAejB,wBAAwB"}
@@ -2,6 +2,7 @@ import { CommandHistoryStorage, CommandHistoryStorageData, CommandHistoryStorage
2
2
  import { StorageItemListener, StorageListenerRemover } from '@deephaven/storage';
3
3
  import PouchCommandHistoryTable from './PouchCommandHistoryTable';
4
4
  export declare class PouchCommandHistoryStorage implements CommandHistoryStorage {
5
+ private cache;
5
6
  private updateTableMap;
6
7
  private getUpdateTable;
7
8
  getTable(language: string): Promise<PouchCommandHistoryTable>;
@@ -1 +1 @@
1
- {"version":3,"file":"PouchCommandHistoryStorage.d.ts","sourceRoot":"","sources":["../src/PouchCommandHistoryStorage.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,qBAAqB,EACrB,yBAAyB,EACzB,yBAAyB,EAC1B,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EACL,mBAAmB,EACnB,sBAAsB,EACvB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,wBAAwB,MAAM,4BAA4B,CAAC;AAIlE,qBAAa,0BAA2B,YAAW,qBAAqB;IACtE,OAAO,CAAC,cAAc,CAA+C;IAErE,OAAO,CAAC,cAAc;IAQhB,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,wBAAwB,CAAC;IAI7D,OAAO,CACX,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,yBAAyB,GAC9B,OAAO,CAAC,yBAAyB,CAAC;IAQ/B,UAAU,CACd,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,yBAAyB,GAC9B,OAAO,CAAC,yBAAyB,CAAC;IAgBrC,UAAU,CACR,QAAQ,EAAE,MAAM,EAChB,EAAE,EAAE,MAAM,EACV,QAAQ,EAAE,mBAAmB,CAAC,yBAAyB,CAAC,GACvD,sBAAsB;CAK1B;AAED,eAAe,0BAA0B,CAAC"}
1
+ {"version":3,"file":"PouchCommandHistoryStorage.d.ts","sourceRoot":"","sources":["../src/PouchCommandHistoryStorage.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,qBAAqB,EACrB,yBAAyB,EACzB,yBAAyB,EAC1B,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EACL,mBAAmB,EACnB,sBAAsB,EACvB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,wBAAwB,MAAM,4BAA4B,CAAC;AAKlE,qBAAa,0BAA2B,YAAW,qBAAqB;IACtE,OAAO,CAAC,KAAK,CAAkC;IAE/C,OAAO,CAAC,cAAc,CAA+C;IAErE,OAAO,CAAC,cAAc;IAWhB,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,wBAAwB,CAAC;IAI7D,OAAO,CACX,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,yBAAyB,GAC9B,OAAO,CAAC,yBAAyB,CAAC;IAQ/B,UAAU,CACd,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,yBAAyB,GAC9B,OAAO,CAAC,yBAAyB,CAAC;IAgBrC,UAAU,CACR,QAAQ,EAAE,MAAM,EAChB,EAAE,EAAE,MAAM,EACV,QAAQ,EAAE,mBAAmB,CAAC,yBAAyB,CAAC,GACvD,sBAAsB;CAK1B;AAED,eAAe,0BAA0B,CAAC"}
@@ -8,26 +8,29 @@ function _toPrimitive(input, hint) { if (typeof input !== "object" || input ===
8
8
  /* eslint-disable class-methods-use-this */
9
9
  import Log from '@deephaven/log';
10
10
  import PouchCommandHistoryTable from "./PouchCommandHistoryTable.js";
11
+ import PouchCommandHistoryCache from "./PouchCommandHistoryCache.js";
11
12
  var log = Log.module('PouchCommandHistoryStorage');
12
13
  export class PouchCommandHistoryStorage {
13
14
  constructor() {
15
+ _defineProperty(this, "cache", new PouchCommandHistoryCache());
14
16
  _defineProperty(this, "updateTableMap", new Map());
15
17
  }
16
18
  getUpdateTable(language) {
17
19
  if (!this.updateTableMap.has(language)) {
18
- this.updateTableMap.set(language, new PouchCommandHistoryTable(language));
20
+ this.updateTableMap.set(language, new PouchCommandHistoryTable(language, this.cache));
19
21
  }
20
22
  return this.updateTableMap.get(language);
21
23
  }
22
24
  getTable(language) {
25
+ var _this = this;
23
26
  return _asyncToGenerator(function* () {
24
- return new PouchCommandHistoryTable(language);
27
+ return new PouchCommandHistoryTable(language, _this.cache);
25
28
  })();
26
29
  }
27
30
  addItem(language, scope, command, data) {
28
- var _this = this;
31
+ var _this2 = this;
29
32
  return _asyncToGenerator(function* () {
30
- return _this.updateItem(language, {
33
+ return _this2.updateItem(language, {
31
34
  id: "".concat(new Date().getTime()),
32
35
  name: command,
33
36
  data
@@ -35,9 +38,9 @@ export class PouchCommandHistoryStorage {
35
38
  })();
36
39
  }
37
40
  updateItem(language, item) {
38
- var _this2 = this;
41
+ var _this3 = this;
39
42
  return _asyncToGenerator(function* () {
40
- var updateTable = _this2.getUpdateTable(language);
43
+ var updateTable = _this3.getUpdateTable(language);
41
44
  var dbItem = yield updateTable.refreshItem(item.id);
42
45
  var updatedItem = _objectSpread(_objectSpread({}, dbItem !== null && dbItem !== void 0 ? dbItem : {}), item);
43
46
  log.debug('Updating item', updatedItem);
@@ -1 +1 @@
1
- {"version":3,"file":"PouchCommandHistoryStorage.js","names":["Log","PouchCommandHistoryTable","log","module","PouchCommandHistoryStorage","Map","getUpdateTable","language","updateTableMap","has","set","get","getTable","addItem","scope","command","data","updateItem","id","Date","getTime","name","item","updateTable","dbItem","refreshItem","updatedItem","debug","put","listenItem","listener","onItemUpdate"],"sources":["../src/PouchCommandHistoryStorage.ts"],"sourcesContent":["/* eslint-disable class-methods-use-this */\nimport Log from '@deephaven/log';\nimport {\n CommandHistoryStorage,\n CommandHistoryStorageData,\n CommandHistoryStorageItem,\n} from '@deephaven/console';\nimport {\n StorageItemListener,\n StorageListenerRemover,\n} from '@deephaven/storage';\nimport PouchCommandHistoryTable from './PouchCommandHistoryTable';\n\nconst log = Log.module('PouchCommandHistoryStorage');\n\nexport class PouchCommandHistoryStorage implements CommandHistoryStorage {\n private updateTableMap = new Map<string, PouchCommandHistoryTable>();\n\n private getUpdateTable(language: string): PouchCommandHistoryTable {\n if (!this.updateTableMap.has(language)) {\n this.updateTableMap.set(language, new PouchCommandHistoryTable(language));\n }\n\n return this.updateTableMap.get(language) as PouchCommandHistoryTable;\n }\n\n async getTable(language: string): Promise<PouchCommandHistoryTable> {\n return new PouchCommandHistoryTable(language);\n }\n\n async addItem(\n language: string,\n scope: string,\n command: string,\n data: CommandHistoryStorageData\n ): Promise<CommandHistoryStorageItem> {\n return this.updateItem(language, {\n id: `${new Date().getTime()}`,\n name: command,\n data,\n } as CommandHistoryStorageItem);\n }\n\n async updateItem(\n language: string,\n item: CommandHistoryStorageItem\n ): Promise<CommandHistoryStorageItem> {\n const updateTable = this.getUpdateTable(language);\n\n const dbItem = await updateTable.refreshItem(item.id);\n\n const updatedItem = { ...(dbItem ?? {}), ...item };\n\n log.debug('Updating item', updatedItem);\n\n await updateTable.put(updatedItem);\n\n log.debug('Update saved');\n\n return item;\n }\n\n listenItem(\n language: string,\n id: string,\n listener: StorageItemListener<CommandHistoryStorageItem>\n ): StorageListenerRemover {\n const updateTable = this.getUpdateTable(language);\n\n return updateTable.onItemUpdate(id, listener);\n }\n}\n\nexport default PouchCommandHistoryStorage;\n"],"mappings":";;;;;;;AAAA;AACA,OAAOA,GAAG,MAAM,gBAAgB;AAAC,OAU1BC,wBAAwB;AAE/B,IAAMC,GAAG,GAAGF,GAAG,CAACG,MAAM,CAAC,4BAA4B,CAAC;AAEpD,OAAO,MAAMC,0BAA0B,CAAkC;EAAA;IAAA,wCAC9C,IAAIC,GAAG,EAAoC;EAAA;EAE5DC,cAAc,CAACC,QAAgB,EAA4B;IACjE,IAAI,CAAC,IAAI,CAACC,cAAc,CAACC,GAAG,CAACF,QAAQ,CAAC,EAAE;MACtC,IAAI,CAACC,cAAc,CAACE,GAAG,CAACH,QAAQ,EAAE,IAAIN,wBAAwB,CAACM,QAAQ,CAAC,CAAC;IAC3E;IAEA,OAAO,IAAI,CAACC,cAAc,CAACG,GAAG,CAACJ,QAAQ,CAAC;EAC1C;EAEMK,QAAQ,CAACL,QAAgB,EAAqC;IAAA;MAClE,OAAO,IAAIN,wBAAwB,CAACM,QAAQ,CAAC;IAAC;EAChD;EAEMM,OAAO,CACXN,QAAgB,EAChBO,KAAa,EACbC,OAAe,EACfC,IAA+B,EACK;IAAA;IAAA;MACpC,OAAO,KAAI,CAACC,UAAU,CAACV,QAAQ,EAAE;QAC/BW,EAAE,YAAK,IAAIC,IAAI,EAAE,CAACC,OAAO,EAAE,CAAE;QAC7BC,IAAI,EAAEN,OAAO;QACbC;MACF,CAAC,CAA8B;IAAC;EAClC;EAEMC,UAAU,CACdV,QAAgB,EAChBe,IAA+B,EACK;IAAA;IAAA;MACpC,IAAMC,WAAW,GAAG,MAAI,CAACjB,cAAc,CAACC,QAAQ,CAAC;MAEjD,IAAMiB,MAAM,SAASD,WAAW,CAACE,WAAW,CAACH,IAAI,CAACJ,EAAE,CAAC;MAErD,IAAMQ,WAAW,mCAASF,MAAM,aAANA,MAAM,cAANA,MAAM,GAAI,CAAC,CAAC,GAAMF,IAAI,CAAE;MAElDpB,GAAG,CAACyB,KAAK,CAAC,eAAe,EAAED,WAAW,CAAC;MAEvC,MAAMH,WAAW,CAACK,GAAG,CAACF,WAAW,CAAC;MAElCxB,GAAG,CAACyB,KAAK,CAAC,cAAc,CAAC;MAEzB,OAAOL,IAAI;IAAC;EACd;EAEAO,UAAU,CACRtB,QAAgB,EAChBW,EAAU,EACVY,QAAwD,EAChC;IACxB,IAAMP,WAAW,GAAG,IAAI,CAACjB,cAAc,CAACC,QAAQ,CAAC;IAEjD,OAAOgB,WAAW,CAACQ,YAAY,CAACb,EAAE,EAAEY,QAAQ,CAAC;EAC/C;AACF;AAEA,eAAe1B,0BAA0B"}
1
+ {"version":3,"file":"PouchCommandHistoryStorage.js","names":["Log","PouchCommandHistoryTable","PouchCommandHistoryCache","log","module","PouchCommandHistoryStorage","Map","getUpdateTable","language","updateTableMap","has","set","cache","get","getTable","addItem","scope","command","data","updateItem","id","Date","getTime","name","item","updateTable","dbItem","refreshItem","updatedItem","debug","put","listenItem","listener","onItemUpdate"],"sources":["../src/PouchCommandHistoryStorage.ts"],"sourcesContent":["/* eslint-disable class-methods-use-this */\nimport Log from '@deephaven/log';\nimport {\n CommandHistoryStorage,\n CommandHistoryStorageData,\n CommandHistoryStorageItem,\n} from '@deephaven/console';\nimport {\n StorageItemListener,\n StorageListenerRemover,\n} from '@deephaven/storage';\nimport PouchCommandHistoryTable from './PouchCommandHistoryTable';\nimport PouchCommandHistoryCache from './PouchCommandHistoryCache';\n\nconst log = Log.module('PouchCommandHistoryStorage');\n\nexport class PouchCommandHistoryStorage implements CommandHistoryStorage {\n private cache = new PouchCommandHistoryCache();\n\n private updateTableMap = new Map<string, PouchCommandHistoryTable>();\n\n private getUpdateTable(language: string): PouchCommandHistoryTable {\n if (!this.updateTableMap.has(language)) {\n this.updateTableMap.set(\n language,\n new PouchCommandHistoryTable(language, this.cache)\n );\n }\n\n return this.updateTableMap.get(language) as PouchCommandHistoryTable;\n }\n\n async getTable(language: string): Promise<PouchCommandHistoryTable> {\n return new PouchCommandHistoryTable(language, this.cache);\n }\n\n async addItem(\n language: string,\n scope: string,\n command: string,\n data: CommandHistoryStorageData\n ): Promise<CommandHistoryStorageItem> {\n return this.updateItem(language, {\n id: `${new Date().getTime()}`,\n name: command,\n data,\n } as CommandHistoryStorageItem);\n }\n\n async updateItem(\n language: string,\n item: CommandHistoryStorageItem\n ): Promise<CommandHistoryStorageItem> {\n const updateTable = this.getUpdateTable(language);\n\n const dbItem = await updateTable.refreshItem(item.id);\n\n const updatedItem = { ...(dbItem ?? {}), ...item };\n\n log.debug('Updating item', updatedItem);\n\n await updateTable.put(updatedItem);\n\n log.debug('Update saved');\n\n return item;\n }\n\n listenItem(\n language: string,\n id: string,\n listener: StorageItemListener<CommandHistoryStorageItem>\n ): StorageListenerRemover {\n const updateTable = this.getUpdateTable(language);\n\n return updateTable.onItemUpdate(id, listener);\n }\n}\n\nexport default PouchCommandHistoryStorage;\n"],"mappings":";;;;;;;AAAA;AACA,OAAOA,GAAG,MAAM,gBAAgB;AAAC,OAU1BC,wBAAwB;AAAA,OACxBC,wBAAwB;AAE/B,IAAMC,GAAG,GAAGH,GAAG,CAACI,MAAM,CAAC,4BAA4B,CAAC;AAEpD,OAAO,MAAMC,0BAA0B,CAAkC;EAAA;IAAA,+BACvD,IAAIH,wBAAwB,EAAE;IAAA,wCAErB,IAAII,GAAG,EAAoC;EAAA;EAE5DC,cAAc,CAACC,QAAgB,EAA4B;IACjE,IAAI,CAAC,IAAI,CAACC,cAAc,CAACC,GAAG,CAACF,QAAQ,CAAC,EAAE;MACtC,IAAI,CAACC,cAAc,CAACE,GAAG,CACrBH,QAAQ,EACR,IAAIP,wBAAwB,CAACO,QAAQ,EAAE,IAAI,CAACI,KAAK,CAAC,CACnD;IACH;IAEA,OAAO,IAAI,CAACH,cAAc,CAACI,GAAG,CAACL,QAAQ,CAAC;EAC1C;EAEMM,QAAQ,CAACN,QAAgB,EAAqC;IAAA;IAAA;MAClE,OAAO,IAAIP,wBAAwB,CAACO,QAAQ,EAAE,KAAI,CAACI,KAAK,CAAC;IAAC;EAC5D;EAEMG,OAAO,CACXP,QAAgB,EAChBQ,KAAa,EACbC,OAAe,EACfC,IAA+B,EACK;IAAA;IAAA;MACpC,OAAO,MAAI,CAACC,UAAU,CAACX,QAAQ,EAAE;QAC/BY,EAAE,YAAK,IAAIC,IAAI,EAAE,CAACC,OAAO,EAAE,CAAE;QAC7BC,IAAI,EAAEN,OAAO;QACbC;MACF,CAAC,CAA8B;IAAC;EAClC;EAEMC,UAAU,CACdX,QAAgB,EAChBgB,IAA+B,EACK;IAAA;IAAA;MACpC,IAAMC,WAAW,GAAG,MAAI,CAAClB,cAAc,CAACC,QAAQ,CAAC;MAEjD,IAAMkB,MAAM,SAASD,WAAW,CAACE,WAAW,CAACH,IAAI,CAACJ,EAAE,CAAC;MAErD,IAAMQ,WAAW,mCAASF,MAAM,aAANA,MAAM,cAANA,MAAM,GAAI,CAAC,CAAC,GAAMF,IAAI,CAAE;MAElDrB,GAAG,CAAC0B,KAAK,CAAC,eAAe,EAAED,WAAW,CAAC;MAEvC,MAAMH,WAAW,CAACK,GAAG,CAACF,WAAW,CAAC;MAElCzB,GAAG,CAAC0B,KAAK,CAAC,cAAc,CAAC;MAEzB,OAAOL,IAAI;IAAC;EACd;EAEAO,UAAU,CACRvB,QAAgB,EAChBY,EAAU,EACVY,QAAwD,EAChC;IACxB,IAAMP,WAAW,GAAG,IAAI,CAAClB,cAAc,CAACC,QAAQ,CAAC;IAEjD,OAAOiB,WAAW,CAACQ,YAAY,CAACb,EAAE,EAAEY,QAAQ,CAAC;EAC/C;AACF;AAEA,eAAe3B,0BAA0B"}
@@ -1,8 +1,52 @@
1
+ /// <reference types="pouchdb-core" />
2
+ /// <reference types="pouchdb-find" />
1
3
  import { CommandHistoryStorageItem, CommandHistoryTable } from '@deephaven/console';
2
- import PouchStorageTable from './PouchStorageTable';
4
+ import { StorageTableViewport, ViewportData } from '@deephaven/storage';
5
+ import PouchCommandHistoryCache from './PouchCommandHistoryCache';
6
+ import PouchStorageTable, { PouchDBSort, PouchStorageItem } from './PouchStorageTable';
7
+ type CommandHistoryDoc = PouchDB.Core.ExistingDocument<CommandHistoryStorageItem & PouchStorageItem & PouchDB.Core.AllDocsMeta>;
3
8
  export declare class PouchCommandHistoryTable extends PouchStorageTable<CommandHistoryStorageItem> implements CommandHistoryTable {
4
- constructor(language: string);
5
- setSearch(search: string): void;
9
+ private cache;
10
+ constructor(language: string, cache: PouchCommandHistoryCache);
11
+ private searchText?;
12
+ private get cacheKey();
13
+ setSearch(searchText: string): void;
14
+ dbUpdate(event: PouchDB.Core.ChangesResponseChange<CommandHistoryStorageItem>): void;
15
+ /**
16
+ * Fetch command history data from `this.cache.response` or from
17
+ * PouchDB if data is not found in the cache. If the number of total items in
18
+ * the db exceeds COMMAND_HISTORY_ITEMS_MAX, the database will be pruned down
19
+ * to COMMAND_HISTORY_ITEMS_PRUNE total items. Note that PouchDB doesn't
20
+ * actually remove them from the underlying IndexDB, they are just marked
21
+ * as deleted and won't be present in our query results.
22
+ * @param selector
23
+ */
24
+ private fetchData;
25
+ /**
26
+ * Override `PouchStorageTable.fetchInfo` so we can make use of
27
+ * `PouchCommandHistoryCache`
28
+ * @param selector
29
+ */
30
+ fetchInfo(selector: PouchDB.Find.Selector): Promise<PouchDB.Find.FindResponse<CommandHistoryStorageItem & PouchStorageItem>>;
31
+ /**
32
+ * Override `PouchStorageTable.fetchViewportData` to fetch command history
33
+ * storage items. This override provides caching + optimizations specific to
34
+ * command history. We cache the results to avoid excessive PouchDB queries
35
+ * during scrolling. The cache should only need to be invalidated when search
36
+ * filter changes or commands are added to the storage history.
37
+ *
38
+ * @param viewport
39
+ * @param selector
40
+ * @param sort
41
+ * @returns Promise to array of command history storage items
42
+ */
43
+ fetchViewportData(viewport: StorageTableViewport, selector: PouchDB.Find.Selector, sort: PouchDBSort): Promise<ViewportData<CommandHistoryStorageItem>>;
44
+ /**
45
+ * Mark given items as `_deleted` in the database.
46
+ * @param items
47
+ */
48
+ pruneItems(items: CommandHistoryDoc[]): Promise<void>;
49
+ close(): void;
6
50
  }
7
51
  export default PouchCommandHistoryTable;
8
52
  //# sourceMappingURL=PouchCommandHistoryTable.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"PouchCommandHistoryTable.d.ts","sourceRoot":"","sources":["../src/PouchCommandHistoryTable.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,yBAAyB,EACzB,mBAAmB,EACpB,MAAM,oBAAoB,CAAC;AAG5B,OAAO,iBAAiB,MAAM,qBAAqB,CAAC;AAEpD,qBAAa,wBACX,SAAQ,iBAAiB,CAAC,yBAAyB,CACnD,YAAW,mBAAmB;gBAClB,QAAQ,EAAE,MAAM;IAI5B,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;CAWhC;AAED,eAAe,wBAAwB,CAAC"}
1
+ {"version":3,"file":"PouchCommandHistoryTable.d.ts","sourceRoot":"","sources":["../src/PouchCommandHistoryTable.ts"],"names":[],"mappings":";;AAAA,OAAO,EACL,yBAAyB,EACzB,mBAAmB,EACpB,MAAM,oBAAoB,CAAC;AAG5B,OAAO,EACL,oBAAoB,EAEpB,YAAY,EACb,MAAM,oBAAoB,CAAC;AAE5B,OAAO,wBAAwB,MAAM,4BAA4B,CAAC;AAElE,OAAO,iBAAiB,EAAE,EACxB,WAAW,EACX,gBAAgB,EACjB,MAAM,qBAAqB,CAAC;AAO7B,KAAK,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,gBAAgB,CACpD,yBAAyB,GAAG,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,WAAW,CACxE,CAAC;AAEF,qBAAa,wBACX,SAAQ,iBAAiB,CAAC,yBAAyB,CACnD,YAAW,mBAAmB;IACA,OAAO,CAAC,KAAK;gBAA/B,QAAQ,EAAE,MAAM,EAAU,KAAK,EAAE,wBAAwB;IAkBrE,OAAO,CAAC,UAAU,CAAC,CAAS;IAE5B,OAAO,KAAK,QAAQ,GAEnB;IAED,SAAS,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI;IAsBnC,QAAQ,CACN,KAAK,EAAE,OAAO,CAAC,IAAI,CAAC,qBAAqB,CAAC,yBAAyB,CAAC,GACnE,IAAI;IAQP;;;;;;;;OAQG;YACW,SAAS;IAgEvB;;;;OAIG;IAGG,SAAS,CACb,QAAQ,EAAE,OAAO,CAAC,IAAI,CAAC,QAAQ,GAC9B,OAAO,CACR,OAAO,CAAC,IAAI,CAAC,YAAY,CAAC,yBAAyB,GAAG,gBAAgB,CAAC,CACxE;IAID;;;;;;;;;;;OAWG;IAGG,iBAAiB,CACrB,QAAQ,EAAE,oBAAoB,EAC9B,QAAQ,EAAE,OAAO,CAAC,IAAI,CAAC,QAAQ,EAC/B,IAAI,EAAE,WAAW,GAChB,OAAO,CAAC,YAAY,CAAC,yBAAyB,CAAC,CAAC;IAqBnD;;;OAGG;IACG,UAAU,CAAC,KAAK,EAAE,iBAAiB,EAAE;IA2B3C,KAAK,IAAI,IAAI;CAUd;AAED,eAAe,wBAAwB,CAAC"}
@@ -1,12 +1,205 @@
1
+ function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
2
+ function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
3
+ function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } }
4
+ function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); } _next(undefined); }); }; }
5
+ function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
6
+ function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return typeof key === "symbol" ? key : String(key); }
7
+ function _toPrimitive(input, hint) { if (typeof input !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (typeof res !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); }
1
8
  import { Type as FilterType } from '@deephaven/filters';
9
+ import Log from '@deephaven/log';
2
10
  import { StorageUtils } from '@deephaven/storage';
11
+ import { PromiseUtils } from '@deephaven/utils';
12
+ import { siftPrunableItems } from "./pouchCommandHistoryUtils.js";
3
13
  import PouchStorageTable from "./PouchStorageTable.js";
14
+ var COMMAND_HISTORY_ITEMS_MAX = 2500;
15
+ var COMMAND_HISTORY_ITEMS_PRUNE = 2000;
16
+ var log = Log.module('PouchCommandHistoryTable');
4
17
  export class PouchCommandHistoryTable extends PouchStorageTable {
5
- constructor(language) {
6
- super("CommandHistoryStorage.".concat(language));
18
+ constructor(language, cache) {
19
+ var _this$cache$tableRegi;
20
+ super("CommandHistoryStorage.".concat(language), {
21
+ // Optimizations to cut down on growing table size. These should be safe
22
+ // since we don't care about revision history for command history
23
+ // documents.
24
+ auto_compaction: true,
25
+ revs_limit: 1
26
+ });
27
+
28
+ // Add this table instance to the table registry
29
+ _defineProperty(this, "searchText", void 0);
30
+ this.cache = cache;
31
+ if (!this.cache.tableRegistry.has(this.cacheKey)) {
32
+ this.cache.tableRegistry.set(this.cacheKey, new Set());
33
+ }
34
+ log.debug('Adding table to registry', this.cacheKey);
35
+ (_this$cache$tableRegi = this.cache.tableRegistry.get(this.cacheKey)) === null || _this$cache$tableRegi === void 0 ? void 0 : _this$cache$tableRegi.add(this);
7
36
  }
8
- setSearch(search) {
9
- this.setFilters(search ? [StorageUtils.makeFilterConfig([StorageUtils.makeFilterItem('name', FilterType.contains, search)])] : []);
37
+ get cacheKey() {
38
+ return this.db.name;
39
+ }
40
+ setSearch(searchText) {
41
+ log.debug('Setting search filters', searchText);
42
+ this.searchText = searchText.trim().toLowerCase();
43
+ this.setFilters(searchText ? [StorageUtils.makeFilterConfig([StorageUtils.makeFilterItem('name', FilterType.contains, searchText)])] : []);
44
+ }
45
+
46
+ // Our current version of eslint + prettier doesn't always like the `override`
47
+ // keyword. Whenever we upgrade, we should annotate this function with `override`.
48
+ dbUpdate(event) {
49
+ log.debug('Clearing cache and refreshing data', event);
50
+ this.cache.response.delete(this.cacheKey);
51
+ super.dbUpdate(event);
52
+ }
53
+
54
+ /**
55
+ * Fetch command history data from `this.cache.response` or from
56
+ * PouchDB if data is not found in the cache. If the number of total items in
57
+ * the db exceeds COMMAND_HISTORY_ITEMS_MAX, the database will be pruned down
58
+ * to COMMAND_HISTORY_ITEMS_PRUNE total items. Note that PouchDB doesn't
59
+ * actually remove them from the underlying IndexDB, they are just marked
60
+ * as deleted and won't be present in our query results.
61
+ * @param selector
62
+ */
63
+ fetchData(_selector) {
64
+ var _this = this;
65
+ return _asyncToGenerator(function* () {
66
+ // Wrapping this in a setTimeout so that it executes on next call stack.
67
+ // This is necessary to ensure `this.cache` has been initialized due to some
68
+ // nuances with property initilization with inherited classes.
69
+ return PromiseUtils.withTimeout(0, /*#__PURE__*/_asyncToGenerator(function* () {
70
+ if (_this.cache.response.has(_this.cacheKey)) {
71
+ log.debug('Fetching from cache', _this.searchText, _this.viewport);
72
+ } else {
73
+ log.debug('Fetching from PouchDB', _this.searchText, _this.viewport);
74
+ _this.cache.response.set(_this.cacheKey, _this.db.allDocs({
75
+ include_docs: true
76
+ }).then(result => {
77
+ var allItems = result.rows
78
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
79
+ .map(row => row.doc).filter(_ref2 => {
80
+ var {
81
+ name
82
+ } = _ref2;
83
+ return name;
84
+ });
85
+ log.debug("Fetched ".concat(allItems.length, " command history items"));
86
+ var {
87
+ toKeep,
88
+ toPrune
89
+ } = siftPrunableItems(allItems, COMMAND_HISTORY_ITEMS_MAX, COMMAND_HISTORY_ITEMS_PRUNE);
90
+
91
+ // If number of items in PouchDB has exceeded COMMAND_HISTORY_ITEMS_MAX
92
+ // prune them down so we have COMMAND_HISTORY_ITEMS_PRUNE left
93
+ if (toPrune.length) {
94
+ _this.pruneItems(toPrune);
95
+ }
96
+ return {
97
+ docs: toKeep
98
+ };
99
+ }));
100
+ }
101
+
102
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
103
+ var result = _this.cache.response.get(_this.cacheKey);
104
+ if (_this.searchText == null || _this.searchText === '') {
105
+ return result;
106
+ }
107
+ return _objectSpread(_objectSpread({}, result), {}, {
108
+ docs: (yield result).docs.filter(_ref3 => {
109
+ var {
110
+ name
111
+ } = _ref3;
112
+ return (
113
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
114
+ name.toLowerCase().includes(_this.searchText)
115
+ );
116
+ })
117
+ });
118
+ }));
119
+ })();
120
+ }
121
+
122
+ /**
123
+ * Override `PouchStorageTable.fetchInfo` so we can make use of
124
+ * `PouchCommandHistoryCache`
125
+ * @param selector
126
+ */
127
+ // Our current version of eslint + prettier doesn't always like the `override`
128
+ // keyword. Whenever we upgrade, we should annotate this function with `override`.
129
+ fetchInfo(selector) {
130
+ var _this2 = this;
131
+ return _asyncToGenerator(function* () {
132
+ return _this2.fetchData(selector);
133
+ })();
134
+ }
135
+
136
+ /**
137
+ * Override `PouchStorageTable.fetchViewportData` to fetch command history
138
+ * storage items. This override provides caching + optimizations specific to
139
+ * command history. We cache the results to avoid excessive PouchDB queries
140
+ * during scrolling. The cache should only need to be invalidated when search
141
+ * filter changes or commands are added to the storage history.
142
+ *
143
+ * @param viewport
144
+ * @param selector
145
+ * @param sort
146
+ * @returns Promise to array of command history storage items
147
+ */
148
+ // Our current version of eslint + prettier doesn't always like the `override`
149
+ // keyword. Whenever we upgrade, we should annotate this function with `override`.
150
+ fetchViewportData(viewport, selector, sort) {
151
+ var _this3 = this;
152
+ return _asyncToGenerator(function* () {
153
+ var data = yield _this3.fetchData(selector);
154
+ log.debug('Fetching viewport data', viewport.top, viewport.bottom + 1, sort, data);
155
+ var isReversed = typeof sort[0] === 'object' && sort[0].id === 'desc';
156
+ var docs = isReversed ? data.docs.slice(0).reverse() : data.docs;
157
+ var items = docs.slice(viewport.top, viewport.bottom + 1);
158
+ return {
159
+ items,
160
+ offset: viewport.top
161
+ };
162
+ })();
163
+ }
164
+
165
+ /**
166
+ * Mark given items as `_deleted` in the database.
167
+ * @param items
168
+ */
169
+ pruneItems(items) {
170
+ var _this4 = this;
171
+ return _asyncToGenerator(function* () {
172
+ if (_this4.cache.isPruning.get(_this4.cacheKey) === true) {
173
+ log.debug('Pruning already in progress. Skipping.');
174
+ return;
175
+ }
176
+ try {
177
+ log.debug("Pruning ".concat(items.length, " command history items"));
178
+
179
+ // Disable change notifications while we bulk delete to avoid locking up
180
+ // the app
181
+ var resumeListeners = _this4.cache.pauseChangeListeners(_this4.cacheKey);
182
+ _this4.cache.isPruning.set(_this4.cacheKey, true);
183
+ yield _this4.db.bulkDocs(items.map(item => _objectSpread(_objectSpread({}, item), {}, {
184
+ _deleted: true
185
+ })));
186
+ _this4.cache.isPruning.set(_this4.cacheKey, false);
187
+ resumeListeners();
188
+ log.debug('Finished pruning command history items');
189
+ } catch (err) {
190
+ log.error('An error occurred while pruning db', err);
191
+ }
192
+ })();
193
+ }
194
+
195
+ // Our current version of eslint + prettier doesn't always like the `override`
196
+ // keyword. Whenever we upgrade, we should annotate this function with `override`.
197
+ close() {
198
+ var _this$cache$tableRegi2, _this$cache$tableRegi3, _this$changes;
199
+ log.debug('Closing table', this, (_this$cache$tableRegi2 = this.cache.tableRegistry.get(this.cacheKey)) === null || _this$cache$tableRegi2 === void 0 ? void 0 : _this$cache$tableRegi2.size);
200
+ (_this$cache$tableRegi3 = this.cache.tableRegistry.get(this.cacheKey)) === null || _this$cache$tableRegi3 === void 0 ? void 0 : _this$cache$tableRegi3.delete(this);
201
+ (_this$changes = this.changes) === null || _this$changes === void 0 ? void 0 : _this$changes.cancel();
202
+ super.close();
10
203
  }
11
204
  }
12
205
  export default PouchCommandHistoryTable;
@@ -1 +1 @@
1
- {"version":3,"file":"PouchCommandHistoryTable.js","names":["Type","FilterType","StorageUtils","PouchStorageTable","PouchCommandHistoryTable","constructor","language","setSearch","search","setFilters","makeFilterConfig","makeFilterItem","contains"],"sources":["../src/PouchCommandHistoryTable.ts"],"sourcesContent":["import {\n CommandHistoryStorageItem,\n CommandHistoryTable,\n} from '@deephaven/console';\nimport { Type as FilterType } from '@deephaven/filters';\nimport { StorageUtils } from '@deephaven/storage';\nimport PouchStorageTable from './PouchStorageTable';\n\nexport class PouchCommandHistoryTable\n extends PouchStorageTable<CommandHistoryStorageItem>\n implements CommandHistoryTable {\n constructor(language: string) {\n super(`CommandHistoryStorage.${language}`);\n }\n\n setSearch(search: string): void {\n this.setFilters(\n search\n ? [\n StorageUtils.makeFilterConfig([\n StorageUtils.makeFilterItem('name', FilterType.contains, search),\n ]),\n ]\n : []\n );\n }\n}\n\nexport default PouchCommandHistoryTable;\n"],"mappings":"AAIA,SAASA,IAAI,IAAIC,UAAU,QAAQ,oBAAoB;AACvD,SAASC,YAAY,QAAQ,oBAAoB;AAAC,OAC3CC,iBAAiB;AAExB,OAAO,MAAMC,wBAAwB,SAC3BD,iBAAiB,CACM;EAC/BE,WAAW,CAACC,QAAgB,EAAE;IAC5B,KAAK,iCAA0BA,QAAQ,EAAG;EAC5C;EAEAC,SAAS,CAACC,MAAc,EAAQ;IAC9B,IAAI,CAACC,UAAU,CACbD,MAAM,GACF,CACEN,YAAY,CAACQ,gBAAgB,CAAC,CAC5BR,YAAY,CAACS,cAAc,CAAC,MAAM,EAAEV,UAAU,CAACW,QAAQ,EAAEJ,MAAM,CAAC,CACjE,CAAC,CACH,GACD,EAAE,CACP;EACH;AACF;AAEA,eAAeJ,wBAAwB"}
1
+ {"version":3,"file":"PouchCommandHistoryTable.js","names":["Type","FilterType","Log","StorageUtils","PromiseUtils","siftPrunableItems","PouchStorageTable","COMMAND_HISTORY_ITEMS_MAX","COMMAND_HISTORY_ITEMS_PRUNE","log","module","PouchCommandHistoryTable","constructor","language","cache","auto_compaction","revs_limit","tableRegistry","has","cacheKey","set","Set","debug","get","add","db","name","setSearch","searchText","trim","toLowerCase","setFilters","makeFilterConfig","makeFilterItem","contains","dbUpdate","event","response","delete","fetchData","_selector","withTimeout","viewport","allDocs","include_docs","then","result","allItems","rows","map","row","doc","filter","length","toKeep","toPrune","pruneItems","docs","includes","fetchInfo","selector","fetchViewportData","sort","data","top","bottom","isReversed","id","slice","reverse","items","offset","isPruning","resumeListeners","pauseChangeListeners","bulkDocs","item","_deleted","err","error","close","size","changes","cancel"],"sources":["../src/PouchCommandHistoryTable.ts"],"sourcesContent":["import {\n CommandHistoryStorageItem,\n CommandHistoryTable,\n} from '@deephaven/console';\nimport { Type as FilterType } from '@deephaven/filters';\nimport Log from '@deephaven/log';\nimport {\n StorageTableViewport,\n StorageUtils,\n ViewportData,\n} from '@deephaven/storage';\nimport { PromiseUtils } from '@deephaven/utils';\nimport PouchCommandHistoryCache from './PouchCommandHistoryCache';\nimport { siftPrunableItems } from './pouchCommandHistoryUtils';\nimport PouchStorageTable, {\n PouchDBSort,\n PouchStorageItem,\n} from './PouchStorageTable';\n\nconst COMMAND_HISTORY_ITEMS_MAX = 2500;\nconst COMMAND_HISTORY_ITEMS_PRUNE = 2000;\n\nconst log = Log.module('PouchCommandHistoryTable');\n\ntype CommandHistoryDoc = PouchDB.Core.ExistingDocument<\n CommandHistoryStorageItem & PouchStorageItem & PouchDB.Core.AllDocsMeta\n>;\n\nexport class PouchCommandHistoryTable\n extends PouchStorageTable<CommandHistoryStorageItem>\n implements CommandHistoryTable {\n constructor(language: string, private cache: PouchCommandHistoryCache) {\n super(`CommandHistoryStorage.${language}`, {\n // Optimizations to cut down on growing table size. These should be safe\n // since we don't care about revision history for command history\n // documents.\n auto_compaction: true,\n revs_limit: 1,\n });\n\n // Add this table instance to the table registry\n if (!this.cache.tableRegistry.has(this.cacheKey)) {\n this.cache.tableRegistry.set(this.cacheKey, new Set());\n }\n\n log.debug('Adding table to registry', this.cacheKey);\n this.cache.tableRegistry.get(this.cacheKey)?.add(this);\n }\n\n private searchText?: string;\n\n private get cacheKey(): string {\n return this.db.name;\n }\n\n setSearch(searchText: string): void {\n log.debug('Setting search filters', searchText);\n\n this.searchText = searchText.trim().toLowerCase();\n\n this.setFilters(\n searchText\n ? [\n StorageUtils.makeFilterConfig([\n StorageUtils.makeFilterItem(\n 'name',\n FilterType.contains,\n searchText\n ),\n ]),\n ]\n : []\n );\n }\n\n // Our current version of eslint + prettier doesn't always like the `override`\n // keyword. Whenever we upgrade, we should annotate this function with `override`.\n dbUpdate(\n event: PouchDB.Core.ChangesResponseChange<CommandHistoryStorageItem>\n ): void {\n log.debug('Clearing cache and refreshing data', event);\n\n this.cache.response.delete(this.cacheKey);\n\n super.dbUpdate(event);\n }\n\n /**\n * Fetch command history data from `this.cache.response` or from\n * PouchDB if data is not found in the cache. If the number of total items in\n * the db exceeds COMMAND_HISTORY_ITEMS_MAX, the database will be pruned down\n * to COMMAND_HISTORY_ITEMS_PRUNE total items. Note that PouchDB doesn't\n * actually remove them from the underlying IndexDB, they are just marked\n * as deleted and won't be present in our query results.\n * @param selector\n */\n private async fetchData(\n _selector: PouchDB.Find.Selector\n ): Promise<\n PouchDB.Find.FindResponse<CommandHistoryStorageItem & PouchStorageItem>\n > {\n // Wrapping this in a setTimeout so that it executes on next call stack.\n // This is necessary to ensure `this.cache` has been initialized due to some\n // nuances with property initilization with inherited classes.\n return PromiseUtils.withTimeout(0, async () => {\n if (this.cache.response.has(this.cacheKey)) {\n log.debug('Fetching from cache', this.searchText, this.viewport);\n } else {\n log.debug('Fetching from PouchDB', this.searchText, this.viewport);\n\n this.cache.response.set(\n this.cacheKey,\n this.db\n .allDocs({\n include_docs: true,\n })\n .then(result => {\n const allItems = result.rows\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n .map(row => row.doc!)\n .filter(({ name }) => name);\n\n log.debug(`Fetched ${allItems.length} command history items`);\n\n const { toKeep, toPrune } = siftPrunableItems(\n allItems,\n COMMAND_HISTORY_ITEMS_MAX,\n COMMAND_HISTORY_ITEMS_PRUNE\n );\n\n // If number of items in PouchDB has exceeded COMMAND_HISTORY_ITEMS_MAX\n // prune them down so we have COMMAND_HISTORY_ITEMS_PRUNE left\n if (toPrune.length) {\n this.pruneItems(toPrune);\n }\n\n return {\n docs: toKeep,\n };\n })\n );\n }\n\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n const result = this.cache.response.get(this.cacheKey)!;\n\n if (this.searchText == null || this.searchText === '') {\n return result;\n }\n\n return {\n ...result,\n docs: (await result).docs.filter(({ name }) =>\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n name.toLowerCase().includes(this.searchText!)\n ),\n };\n });\n }\n\n /**\n * Override `PouchStorageTable.fetchInfo` so we can make use of\n * `PouchCommandHistoryCache`\n * @param selector\n */\n // Our current version of eslint + prettier doesn't always like the `override`\n // keyword. Whenever we upgrade, we should annotate this function with `override`.\n async fetchInfo(\n selector: PouchDB.Find.Selector\n ): Promise<\n PouchDB.Find.FindResponse<CommandHistoryStorageItem & PouchStorageItem>\n > {\n return this.fetchData(selector);\n }\n\n /**\n * Override `PouchStorageTable.fetchViewportData` to fetch command history\n * storage items. This override provides caching + optimizations specific to\n * command history. We cache the results to avoid excessive PouchDB queries\n * during scrolling. The cache should only need to be invalidated when search\n * filter changes or commands are added to the storage history.\n *\n * @param viewport\n * @param selector\n * @param sort\n * @returns Promise to array of command history storage items\n */\n // Our current version of eslint + prettier doesn't always like the `override`\n // keyword. Whenever we upgrade, we should annotate this function with `override`.\n async fetchViewportData(\n viewport: StorageTableViewport,\n selector: PouchDB.Find.Selector,\n sort: PouchDBSort\n ): Promise<ViewportData<CommandHistoryStorageItem>> {\n const data = await this.fetchData(selector);\n\n log.debug(\n 'Fetching viewport data',\n viewport.top,\n viewport.bottom + 1,\n sort,\n data\n );\n\n const isReversed = typeof sort[0] === 'object' && sort[0].id === 'desc';\n const docs = isReversed ? data.docs.slice(0).reverse() : data.docs;\n const items = docs.slice(viewport.top, viewport.bottom + 1);\n\n return {\n items,\n offset: viewport.top,\n };\n }\n\n /**\n * Mark given items as `_deleted` in the database.\n * @param items\n */\n async pruneItems(items: CommandHistoryDoc[]) {\n if (this.cache.isPruning.get(this.cacheKey) === true) {\n log.debug('Pruning already in progress. Skipping.');\n return;\n }\n\n try {\n log.debug(`Pruning ${items.length} command history items`);\n\n // Disable change notifications while we bulk delete to avoid locking up\n // the app\n const resumeListeners = this.cache.pauseChangeListeners(this.cacheKey);\n\n this.cache.isPruning.set(this.cacheKey, true);\n await this.db.bulkDocs(items.map(item => ({ ...item, _deleted: true })));\n this.cache.isPruning.set(this.cacheKey, false);\n\n resumeListeners();\n\n log.debug('Finished pruning command history items');\n } catch (err) {\n log.error('An error occurred while pruning db', err);\n }\n }\n\n // Our current version of eslint + prettier doesn't always like the `override`\n // keyword. Whenever we upgrade, we should annotate this function with `override`.\n close(): void {\n log.debug(\n 'Closing table',\n this,\n this.cache.tableRegistry.get(this.cacheKey)?.size\n );\n this.cache.tableRegistry.get(this.cacheKey)?.delete(this);\n this.changes?.cancel();\n super.close();\n }\n}\n\nexport default PouchCommandHistoryTable;\n"],"mappings":"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"}
@@ -1,9 +1,17 @@
1
+ /// <reference types="pouchdb-find" />
2
+ /// <reference types="pouchdb-core" />
3
+ /// <reference types="pouchdb-mapreduce" />
4
+ /// <reference types="pouchdb-replication" />
1
5
  import { FilterConfig, SortConfig, StorageItem, StorageTable, StorageListenerRemover, StorageTableViewport, StorageItemListener, StorageSnapshot, ViewportData, ViewportUpdateCallback } from '@deephaven/storage';
6
+ export interface PouchStorageItem {
7
+ _id?: string;
8
+ }
2
9
  export type PouchDBSort = Array<string | {
3
10
  [propName: string]: 'asc' | 'desc';
4
11
  }>;
5
12
  export declare class PouchStorageTable<T extends StorageItem = StorageItem> implements StorageTable<T> {
6
- private db;
13
+ protected db: PouchDB.Database<T & PouchStorageItem>;
14
+ changes?: PouchDB.Core.Changes<T & PouchStorageItem>;
7
15
  private listeners;
8
16
  private itemListeners;
9
17
  private currentSize;
@@ -14,7 +22,12 @@ export declare class PouchStorageTable<T extends StorageItem = StorageItem> impl
14
22
  private infoUpdatePromise?;
15
23
  private viewportUpdatePromise?;
16
24
  private currentViewportData?;
17
- constructor(databaseName: string);
25
+ constructor(databaseName: string, dbOptions?: PouchDB.Configuration.DatabaseConfiguration);
26
+ /**
27
+ * Listen for db changes. This can be cancelled by calling
28
+ * `this.changes?.cancel()`
29
+ */
30
+ listenForChanges(): void;
18
31
  onUpdate(callback: ViewportUpdateCallback<T>): StorageListenerRemover;
19
32
  onItemUpdate(id: string, listener: StorageItemListener<T>): StorageListenerRemover;
20
33
  close(): void;
@@ -29,8 +42,20 @@ export declare class PouchStorageTable<T extends StorageItem = StorageItem> impl
29
42
  put(item: T): Promise<T>;
30
43
  private sendUpdate;
31
44
  private sendItemUpdate;
32
- private dbUpdate;
45
+ protected dbUpdate(event: PouchDB.Core.ChangesResponseChange<T>): void;
46
+ /**
47
+ * Fetch infor for a given selector.
48
+ * @param selector
49
+ */
50
+ protected fetchInfo(selector: PouchDB.Find.Selector): Promise<PouchDB.Find.FindResponse<T & PouchStorageItem>>;
33
51
  private refreshInfo;
52
+ /**
53
+ * Fetch data for the given viewport, selector, and sort.
54
+ * @param viewport
55
+ * @param selector
56
+ * @param sort
57
+ */
58
+ protected fetchViewportData(viewport: StorageTableViewport, selector: PouchDB.Find.Selector, sort: PouchDBSort): Promise<ViewportData<T>>;
34
59
  private refreshData;
35
60
  refreshItem(id: string): Promise<T | undefined>;
36
61
  getSnapshot(sortedRanges: [number, number][]): Promise<StorageSnapshot<T>>;
@@ -1 +1 @@
1
- {"version":3,"file":"PouchStorageTable.d.ts","sourceRoot":"","sources":["../src/PouchStorageTable.ts"],"names":[],"mappings":"AAOA,OAAO,EACL,YAAY,EAEZ,UAAU,EACV,WAAW,EACX,YAAY,EACZ,sBAAsB,EACtB,oBAAoB,EACpB,mBAAmB,EACnB,eAAe,EACf,YAAY,EACZ,sBAAsB,EACvB,MAAM,oBAAoB,CAAC;AAa5B,MAAM,MAAM,WAAW,GAAG,KAAK,CAC7B,MAAM,GAAG;IAAE,CAAC,QAAQ,EAAE,MAAM,GAAG,KAAK,GAAG,MAAM,CAAA;CAAE,CAChD,CAAC;AAgFF,qBAAa,iBAAiB,CAAC,CAAC,SAAS,WAAW,GAAG,WAAW,CAChE,YAAW,YAAY,CAAC,CAAC,CAAC;IAC1B,OAAO,CAAC,EAAE,CAAyC;IAEnD,OAAO,CAAC,SAAS,CAAmC;IAEpD,OAAO,CAAC,aAAa,CAAoD;IAEzE,OAAO,CAAC,WAAW,CAAK;IAExB,OAAO,CAAC,eAAe,CAAC,CAAuB;IAE/C,OAAO,CAAC,cAAc,CAAS;IAE/B,OAAO,CAAC,aAAa,CAA+B;IAEpD,OAAO,CAAC,WAAW,CAA6B;IAEhD,OAAO,CAAC,iBAAiB,CAAC,CAExB;IAEF,OAAO,CAAC,qBAAqB,CAAC,CAAqC;IAEnE,OAAO,CAAC,mBAAmB,CAAC,CAAkB;gBAElC,YAAY,EAAE,MAAM;IAgBhC,QAAQ,CAAC,QAAQ,EAAE,sBAAsB,CAAC,CAAC,CAAC,GAAG,sBAAsB;IAOrE,YAAY,CACV,EAAE,EAAE,MAAM,EACV,QAAQ,EAAE,mBAAmB,CAAC,CAAC,CAAC,GAC/B,sBAAsB;IAsBzB,KAAK,IAAI,IAAI;IAIb,IAAI,IAAI,IAAI,MAAM,CAEjB;IAED,IAAI,QAAQ,IAAI,oBAAoB,GAAG,SAAS,CAE/C;IAED,WAAW,CAAC,QAAQ,EAAE,OAAO,GAAG,IAAI;IAQpC,WAAW,CAAC,QAAQ,EAAE,oBAAoB,GAAG,SAAS,GAAG,IAAI;IAQ7D,QAAQ,CAAC,MAAM,EAAE,UAAU,EAAE,GAAG,IAAI,GAAG,IAAI;IAQ3C,UAAU,CAAC,MAAM,EAAE,YAAY,EAAE,GAAG,IAAI,GAAG,IAAI;IAU/C,IAAI,IAAI,IAAI,YAAY,CAAC,CAAC,CAAC,GAAG,SAAS,CAEtC;IAEK,eAAe,IAAI,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;IAS3C,GAAG,CAAC,IAAI,EAAE,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IAa9B,OAAO,CAAC,UAAU;IASlB,OAAO,CAAC,cAAc;IAStB,OAAO,CAAC,QAAQ;YAYF,WAAW;YAwBX,WAAW;IA0CnB,WAAW,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,GAAG,SAAS,CAAC;IAe/C,WAAW,CACf,YAAY,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,GAC/B,OAAO,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC;CA2B/B;AAED,eAAe,iBAAiB,CAAC"}
1
+ {"version":3,"file":"PouchStorageTable.d.ts","sourceRoot":"","sources":["../src/PouchStorageTable.ts"],"names":[],"mappings":"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"}
@@ -118,8 +118,9 @@ function sortWithConfigs(sorts) {
118
118
  }))) !== null && _sorts$map !== void 0 ? _sorts$map : [])];
119
119
  }
120
120
  export class PouchStorageTable {
121
- constructor(databaseName) {
121
+ constructor(databaseName, dbOptions) {
122
122
  _defineProperty(this, "db", void 0);
123
+ _defineProperty(this, "changes", void 0);
123
124
  _defineProperty(this, "listeners", []);
124
125
  _defineProperty(this, "itemListeners", new Map());
125
126
  _defineProperty(this, "currentSize", 0);
@@ -130,16 +131,12 @@ export class PouchStorageTable {
130
131
  _defineProperty(this, "infoUpdatePromise", void 0);
131
132
  _defineProperty(this, "viewportUpdatePromise", void 0);
132
133
  _defineProperty(this, "currentViewportData", void 0);
133
- this.db = new PouchDB("".concat(DB_PREFIX).concat(databaseName));
134
+ this.db = new PouchDB("".concat(DB_PREFIX).concat(databaseName), dbOptions);
134
135
 
135
136
  // Need to set `_remote` to false to remove deprecation warnings: https://github.com/pouchdb/pouchdb/issues/6106
136
137
  // eslint-disable-next-line @typescript-eslint/no-explicit-any, no-underscore-dangle
137
138
  this.db._remote = false;
138
- this.db.changes({
139
- live: true,
140
- since: 'now',
141
- include_docs: true
142
- }).on('change', this.dbUpdate.bind(this));
139
+ this.listenForChanges();
143
140
  this.db.createIndex({
144
141
  index: {
145
142
  fields: ['id', 'name']
@@ -147,6 +144,18 @@ export class PouchStorageTable {
147
144
  });
148
145
  this.refreshInfo();
149
146
  }
147
+
148
+ /**
149
+ * Listen for db changes. This can be cancelled by calling
150
+ * `this.changes?.cancel()`
151
+ */
152
+ listenForChanges() {
153
+ this.changes = this.db.changes({
154
+ live: true,
155
+ since: 'now',
156
+ include_docs: true
157
+ }).on('change', this.dbUpdate.bind(this));
158
+ }
150
159
  onUpdate(callback) {
151
160
  this.listeners = [...this.listeners, callback];
152
161
  return () => {
@@ -251,19 +260,30 @@ export class PouchStorageTable {
251
260
  }
252
261
  this.refreshData();
253
262
  }
254
- refreshInfo() {
263
+
264
+ /**
265
+ * Fetch infor for a given selector.
266
+ * @param selector
267
+ */
268
+ fetchInfo(selector) {
255
269
  var _this3 = this;
270
+ return _asyncToGenerator(function* () {
271
+ return _this3.db.find({
272
+ selector,
273
+ fields: []
274
+ });
275
+ })();
276
+ }
277
+ refreshInfo() {
278
+ var _this4 = this;
256
279
  return _asyncToGenerator(function* () {
257
280
  try {
258
- var _this3$infoUpdateProm, _this3$currentFilter;
259
- (_this3$infoUpdateProm = _this3.infoUpdatePromise) === null || _this3$infoUpdateProm === void 0 ? void 0 : _this3$infoUpdateProm.cancel();
260
- _this3.infoUpdatePromise = PromiseUtils.makeCancelable(_this3.db.find({
261
- selector: selectorWithFilters((_this3$currentFilter = _this3.currentFilter) !== null && _this3$currentFilter !== void 0 ? _this3$currentFilter : []),
262
- fields: []
263
- }));
264
- var findResult = yield _this3.infoUpdatePromise;
265
- _this3.currentSize = findResult.docs.length;
266
- _this3.sendUpdate();
281
+ var _this4$infoUpdateProm, _this4$currentFilter;
282
+ (_this4$infoUpdateProm = _this4.infoUpdatePromise) === null || _this4$infoUpdateProm === void 0 ? void 0 : _this4$infoUpdateProm.cancel();
283
+ _this4.infoUpdatePromise = PromiseUtils.makeCancelable(_this4.fetchInfo(selectorWithFilters((_this4$currentFilter = _this4.currentFilter) !== null && _this4$currentFilter !== void 0 ? _this4$currentFilter : [])));
284
+ var findResult = yield _this4.infoUpdatePromise;
285
+ _this4.currentSize = findResult.docs.length;
286
+ _this4.sendUpdate();
267
287
  } catch (e) {
268
288
  if (!PromiseUtils.isCanceled(e)) {
269
289
  log.error('Unable to refreshInfo', e);
@@ -272,32 +292,43 @@ export class PouchStorageTable {
272
292
  }
273
293
  })();
274
294
  }
295
+
296
+ /**
297
+ * Fetch data for the given viewport, selector, and sort.
298
+ * @param viewport
299
+ * @param selector
300
+ * @param sort
301
+ */
302
+ fetchViewportData(viewport, selector, sort) {
303
+ var _this5 = this;
304
+ return _asyncToGenerator(function* () {
305
+ return _this5.db.find({
306
+ selector,
307
+ skip: viewport.top,
308
+ limit: viewport.bottom - viewport.top + 1,
309
+ sort,
310
+ fields: ['id', 'name']
311
+ }).then(findResult => ({
312
+ items: findResult.docs,
313
+ offset: viewport.top
314
+ }));
315
+ })();
316
+ }
275
317
  refreshData() {
276
- var _this4 = this;
318
+ var _this6 = this;
277
319
  return _asyncToGenerator(function* () {
278
- if (!_this4.currentViewport) {
320
+ if (!_this6.currentViewport) {
279
321
  return;
280
322
  }
281
323
  try {
282
- var _this4$viewportUpdate, _this4$currentFilter;
283
- var {
284
- currentViewport: viewport
285
- } = _this4;
286
- var sort = sortWithConfigs(_this4.currentSort, _this4.currentReverse);
287
- (_this4$viewportUpdate = _this4.viewportUpdatePromise) === null || _this4$viewportUpdate === void 0 ? void 0 : _this4$viewportUpdate.cancel();
288
- _this4.viewportUpdatePromise = PromiseUtils.makeCancelable(_this4.db.find({
289
- selector: selectorWithFilters((_this4$currentFilter = _this4.currentFilter) !== null && _this4$currentFilter !== void 0 ? _this4$currentFilter : []),
290
- skip: viewport.top,
291
- limit: viewport.bottom - viewport.top + 1,
292
- sort,
293
- fields: ['id', 'name']
294
- }).then(findResult => ({
295
- items: findResult.docs,
296
- offset: viewport.top
297
- })));
298
- var viewportData = yield _this4.viewportUpdatePromise;
299
- _this4.currentViewportData = viewportData;
300
- _this4.sendUpdate();
324
+ var _this6$currentFilter, _this6$viewportUpdate;
325
+ var selector = selectorWithFilters((_this6$currentFilter = _this6.currentFilter) !== null && _this6$currentFilter !== void 0 ? _this6$currentFilter : []);
326
+ var sort = sortWithConfigs(_this6.currentSort, _this6.currentReverse);
327
+ (_this6$viewportUpdate = _this6.viewportUpdatePromise) === null || _this6$viewportUpdate === void 0 ? void 0 : _this6$viewportUpdate.cancel();
328
+ _this6.viewportUpdatePromise = PromiseUtils.makeCancelable(_this6.fetchViewportData(_this6.currentViewport, selector, sort));
329
+ var viewportData = yield _this6.viewportUpdatePromise;
330
+ _this6.currentViewportData = viewportData;
331
+ _this6.sendUpdate();
301
332
  return viewportData;
302
333
  } catch (e) {
303
334
  if (!PromiseUtils.isCanceled(e)) {
@@ -308,9 +339,9 @@ export class PouchStorageTable {
308
339
  })();
309
340
  }
310
341
  refreshItem(id) {
311
- var _this5 = this;
342
+ var _this7 = this;
312
343
  return _asyncToGenerator(function* () {
313
- var findResult = yield _this5.db.find({
344
+ var findResult = yield _this7.db.find({
314
345
  selector: {
315
346
  id
316
347
  },
@@ -318,25 +349,25 @@ export class PouchStorageTable {
318
349
  });
319
350
  var item = findResult.docs[0];
320
351
  if (item !== undefined) {
321
- _this5.sendItemUpdate(item);
352
+ _this7.sendItemUpdate(item);
322
353
  }
323
354
  return item;
324
355
  })();
325
356
  }
326
357
  getSnapshot(sortedRanges) {
327
- var _this6 = this;
358
+ var _this8 = this;
328
359
  return _asyncToGenerator(function* () {
329
360
  var itemMap = new Map();
330
361
  var sort = [{
331
- id: _this6.currentReverse ? 'desc' : 'asc'
362
+ id: _this8.currentReverse ? 'desc' : 'asc'
332
363
  }];
333
364
  yield Promise.all(sortedRanges.map( /*#__PURE__*/function () {
334
365
  var _ref2 = _asyncToGenerator(function* (_ref) {
335
- var _this6$currentFilter;
366
+ var _this8$currentFilter;
336
367
  var [from, to] = _ref;
337
368
  var limit = to - from + 1;
338
- return _this6.db.find({
339
- selector: selectorWithFilters((_this6$currentFilter = _this6.currentFilter) !== null && _this6$currentFilter !== void 0 ? _this6$currentFilter : []),
369
+ return _this8.db.find({
370
+ selector: selectorWithFilters((_this8$currentFilter = _this8.currentFilter) !== null && _this8$currentFilter !== void 0 ? _this8$currentFilter : []),
340
371
  skip: from,
341
372
  limit,
342
373
  sort,
@@ -1 +1 @@
1
- {"version":3,"file":"PouchStorageTable.js","names":["PouchDB","PouchDBFind","Operator","FilterOperator","Type","FilterType","Log","PromiseUtils","log","module","DB_PREFIX","plugin","makePouchFilter","type","value","in","contains","$regex","RegExp","inIgnoreCase","eq","$eq","notEq","$neq","greaterThan","$gt","greaterThanOrEqualTo","$gte","lessThan","$lt","lessThanOrEqualTo","$lte","startsWith","Error","makePouchSelectorFromConfig","config","filterItems","filterOperators","filter","i","length","filterItem","columnName","newFilter","filterOperator","and","$and","or","$or","selectorWithFilters","filters","map","name","id","sortWithConfigs","sorts","reverse","sort","column","direction","PouchStorageTable","constructor","databaseName","Map","db","_remote","changes","live","since","include_docs","on","dbUpdate","bind","createIndex","index","fields","refreshInfo","onUpdate","callback","listeners","other","onItemUpdate","listener","itemListeners","has","set","get","refreshItem","close","size","currentSize","viewport","currentViewport","setReversed","reversed","currentReverse","currentViewportData","undefined","refreshData","setViewport","setSorts","currentSort","setFilters","currentFilter","data","getViewportData","viewportUpdatePromise","Promise","resolve","items","offset","put","item","newItem","_id","sendUpdate","sendItemUpdate","event","debug","doc","infoUpdatePromise","cancel","makeCancelable","find","selector","findResult","docs","e","isCanceled","error","skip","top","limit","bottom","then","viewportData","getSnapshot","sortedRanges","itemMap","all","from","to","findSnapshotResult"],"sources":["../src/PouchStorageTable.ts"],"sourcesContent":["import PouchDB from 'pouchdb-browser';\nimport PouchDBFind from 'pouchdb-find';\nimport {\n Operator as FilterOperator,\n Type as FilterType,\n} from '@deephaven/filters';\nimport Log from '@deephaven/log';\nimport {\n FilterConfig,\n FilterValue,\n SortConfig,\n StorageItem,\n StorageTable,\n StorageListenerRemover,\n StorageTableViewport,\n StorageItemListener,\n StorageSnapshot,\n ViewportData,\n ViewportUpdateCallback,\n} from '@deephaven/storage';\nimport { CancelablePromise, PromiseUtils } from '@deephaven/utils';\n\nconst log = Log.module('PouchStorageTable');\n\nconst DB_PREFIX = 'Deephaven.';\n\nPouchDB.plugin(PouchDBFind);\n\ninterface PouchStorageItem {\n _id?: string;\n}\n\nexport type PouchDBSort = Array<\n string | { [propName: string]: 'asc' | 'desc' }\n>;\n\nfunction makePouchFilter(type: string, value: FilterValue | FilterValue[]) {\n switch (type) {\n case FilterType.in:\n case FilterType.contains:\n return { $regex: new RegExp(`${value}`) };\n case FilterType.inIgnoreCase:\n return { $regex: new RegExp(`${value}`, 'i') };\n case FilterType.eq:\n return { $eq: value };\n case FilterType.notEq:\n return { $neq: value };\n case FilterType.greaterThan:\n return { $gt: value };\n case FilterType.greaterThanOrEqualTo:\n return { $gte: value };\n case FilterType.lessThan:\n return { $lt: value };\n case FilterType.lessThanOrEqualTo:\n return { $lte: value };\n case FilterType.startsWith:\n return { $regex: new RegExp(`^(?${value}).*`) };\n default:\n throw new Error(`Unsupported type: ${type}`);\n }\n}\n\nfunction makePouchSelectorFromConfig(\n config: FilterConfig\n): PouchDB.Find.Selector {\n const { filterItems, filterOperators } = config;\n let filter = null;\n for (let i = 0; i < filterItems.length; i += 1) {\n const filterItem = filterItems[i];\n const { columnName, type, value } = filterItem;\n const newFilter = { [columnName]: makePouchFilter(type, value) };\n if (i === 0) {\n filter = newFilter;\n } else if (filter !== null && i - 1 < filterOperators.length) {\n const filterOperator = filterOperators[i - 1];\n if (filterOperator === FilterOperator.and) {\n filter = { $and: [filter, newFilter] };\n } else if (filterOperator === FilterOperator.or) {\n filter = { $or: [filter, newFilter] };\n } else {\n throw new Error(\n `Unexpected filter operator ${filterOperator}, ${newFilter}`\n );\n }\n }\n }\n if (filter == null) {\n throw new Error(`Invalid filter config ${config}`);\n }\n return filter;\n}\n\nfunction selectorWithFilters(\n filters: FilterConfig[] = []\n): PouchDB.Find.Selector {\n return {\n $and: [\n ...filters.map(filter => makePouchSelectorFromConfig(filter)),\n { name: { $gt: null } },\n { id: { $gt: null } },\n ],\n };\n}\n\nfunction sortWithConfigs(\n sorts: SortConfig[] | null,\n reverse = false\n): PouchDBSort {\n return [\n { id: reverse ? 'desc' : 'asc' },\n ...(sorts?.map(sort => ({ [sort.column]: sort.direction })) ?? []),\n ];\n}\n\nexport class PouchStorageTable<T extends StorageItem = StorageItem>\n implements StorageTable<T> {\n private db: PouchDB.Database<T & PouchStorageItem>;\n\n private listeners: ViewportUpdateCallback<T>[] = [];\n\n private itemListeners: Map<string, StorageItemListener<T>[]> = new Map();\n\n private currentSize = 0;\n\n private currentViewport?: StorageTableViewport;\n\n private currentReverse = false;\n\n private currentFilter: FilterConfig[] | null = null;\n\n private currentSort: SortConfig[] | null = null;\n\n private infoUpdatePromise?: CancelablePromise<\n PouchDB.Find.FindResponse<T & PouchStorageItem>\n >;\n\n private viewportUpdatePromise?: CancelablePromise<ViewportData<T>>;\n\n private currentViewportData?: ViewportData<T>;\n\n constructor(databaseName: string) {\n this.db = new PouchDB<T & PouchStorageItem>(`${DB_PREFIX}${databaseName}`);\n\n // Need to set `_remote` to false to remove deprecation warnings: https://github.com/pouchdb/pouchdb/issues/6106\n // eslint-disable-next-line @typescript-eslint/no-explicit-any, no-underscore-dangle\n (this.db as any)._remote = false;\n\n this.db\n .changes({ live: true, since: 'now', include_docs: true })\n .on('change', this.dbUpdate.bind(this));\n\n this.db.createIndex({ index: { fields: ['id', 'name'] } });\n\n this.refreshInfo();\n }\n\n onUpdate(callback: ViewportUpdateCallback<T>): StorageListenerRemover {\n this.listeners = [...this.listeners, callback];\n return () => {\n this.listeners = this.listeners.filter(other => other !== callback);\n };\n }\n\n onItemUpdate(\n id: string,\n listener: StorageItemListener<T>\n ): StorageListenerRemover {\n if (!this.itemListeners.has(id)) {\n this.itemListeners.set(id, []);\n }\n\n this.itemListeners.set(id, [\n ...(this.itemListeners.get(id) as StorageItemListener<T>[]),\n listener,\n ]);\n\n this.refreshItem(id);\n\n return () => {\n this.itemListeners.set(\n id,\n (this.itemListeners.get(id) as StorageItemListener<T>[]).filter(\n other => other !== listener\n )\n );\n };\n }\n\n close(): void {\n this.listeners = [];\n }\n\n get size(): number {\n return this.currentSize;\n }\n\n get viewport(): StorageTableViewport | undefined {\n return this.currentViewport;\n }\n\n setReversed(reversed: boolean): void {\n this.currentReverse = reversed;\n\n this.currentViewportData = undefined;\n\n this.refreshData();\n }\n\n setViewport(viewport: StorageTableViewport | undefined): void {\n this.currentViewport = viewport;\n\n this.refreshInfo();\n\n this.refreshData();\n }\n\n setSorts(config: SortConfig[] | null): void {\n this.currentSort = config;\n\n this.currentViewportData = undefined;\n\n this.refreshData();\n }\n\n setFilters(config: FilterConfig[] | null): void {\n this.currentFilter = config;\n\n this.currentViewportData = undefined;\n\n this.refreshInfo();\n\n this.refreshData();\n }\n\n get data(): ViewportData<T> | undefined {\n return this.currentViewportData;\n }\n\n async getViewportData(): Promise<ViewportData<T>> {\n if (!this.viewportUpdatePromise) {\n this.refreshData();\n }\n return (\n this.viewportUpdatePromise ?? Promise.resolve({ items: [], offset: 0 })\n );\n }\n\n async put(item: T): Promise<T> {\n // Put the item ID in both the _id and the id slot\n // PouchDB uses _id everywhere, StorageTable just uses `id` though\n const newItem = {\n ...item,\n _id: item.id,\n } as T;\n\n await this.db.put(newItem);\n\n return newItem;\n }\n\n private sendUpdate() {\n // Retain a reference to it in case a listener gets removed while sending an update\n const { listeners } = this;\n const data = this.currentViewportData ?? { items: [], offset: 0 };\n for (let i = 0; i < listeners.length; i += 1) {\n listeners[i](data);\n }\n }\n\n private sendItemUpdate(item: T) {\n const listeners = this.itemListeners.get(item.id);\n if (listeners !== undefined) {\n for (let i = 0; i < listeners.length; i += 1) {\n listeners[i](item);\n }\n }\n }\n\n private dbUpdate(event: PouchDB.Core.ChangesResponseChange<T>): void {\n log.debug('Update received', event);\n\n this.refreshInfo();\n\n if (event.doc !== undefined) {\n this.sendItemUpdate(event.doc);\n }\n\n this.refreshData();\n }\n\n private async refreshInfo() {\n try {\n this.infoUpdatePromise?.cancel();\n\n this.infoUpdatePromise = PromiseUtils.makeCancelable(\n this.db.find({\n selector: selectorWithFilters(this.currentFilter ?? []),\n fields: [],\n })\n );\n\n const findResult = await this.infoUpdatePromise;\n\n this.currentSize = findResult.docs.length;\n\n this.sendUpdate();\n } catch (e) {\n if (!PromiseUtils.isCanceled(e)) {\n log.error('Unable to refreshInfo', e);\n throw e;\n }\n }\n }\n\n private async refreshData(): Promise<ViewportData<T> | undefined> {\n if (!this.currentViewport) {\n return;\n }\n\n try {\n const { currentViewport: viewport } = this;\n\n const sort = sortWithConfigs(this.currentSort, this.currentReverse);\n\n this.viewportUpdatePromise?.cancel();\n\n this.viewportUpdatePromise = PromiseUtils.makeCancelable(\n this.db\n .find({\n selector: selectorWithFilters(this.currentFilter ?? []),\n skip: viewport.top,\n limit: viewport.bottom - viewport.top + 1,\n sort,\n fields: ['id', 'name'],\n })\n .then(findResult => ({\n items: findResult.docs,\n offset: viewport.top,\n }))\n );\n\n const viewportData = await this.viewportUpdatePromise;\n\n this.currentViewportData = viewportData;\n\n this.sendUpdate();\n\n return viewportData;\n } catch (e) {\n if (!PromiseUtils.isCanceled(e)) {\n log.error('Unable to refreshData', e);\n throw e;\n }\n }\n }\n\n async refreshItem(id: string): Promise<T | undefined> {\n const findResult = await this.db.find({\n selector: { id },\n limit: 1,\n });\n\n const item = findResult.docs[0];\n\n if (item !== undefined) {\n this.sendItemUpdate(item);\n }\n\n return item;\n }\n\n async getSnapshot(\n sortedRanges: [number, number][]\n ): Promise<StorageSnapshot<T>> {\n const itemMap = new Map();\n\n const sort: PouchDBSort = [{ id: this.currentReverse ? 'desc' : 'asc' }];\n\n await Promise.all(\n sortedRanges.map(async ([from, to]) => {\n const limit = to - from + 1;\n return this.db\n .find({\n selector: selectorWithFilters(this.currentFilter ?? []),\n skip: from,\n limit,\n sort,\n fields: ['id', 'name'],\n })\n .then(findSnapshotResult => {\n for (let i = 0; i < limit; i += 1) {\n const index = from + i;\n itemMap.set(index, findSnapshotResult.docs[i]);\n }\n });\n })\n );\n\n return itemMap;\n }\n}\n\nexport default PouchStorageTable;\n"],"mappings":"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"}
1
+ {"version":3,"file":"PouchStorageTable.js","names":["PouchDB","PouchDBFind","Operator","FilterOperator","Type","FilterType","Log","PromiseUtils","log","module","DB_PREFIX","plugin","makePouchFilter","type","value","in","contains","$regex","RegExp","inIgnoreCase","eq","$eq","notEq","$neq","greaterThan","$gt","greaterThanOrEqualTo","$gte","lessThan","$lt","lessThanOrEqualTo","$lte","startsWith","Error","makePouchSelectorFromConfig","config","filterItems","filterOperators","filter","i","length","filterItem","columnName","newFilter","filterOperator","and","$and","or","$or","selectorWithFilters","filters","map","name","id","sortWithConfigs","sorts","reverse","sort","column","direction","PouchStorageTable","constructor","databaseName","dbOptions","Map","db","_remote","listenForChanges","createIndex","index","fields","refreshInfo","changes","live","since","include_docs","on","dbUpdate","bind","onUpdate","callback","listeners","other","onItemUpdate","listener","itemListeners","has","set","get","refreshItem","close","size","currentSize","viewport","currentViewport","setReversed","reversed","currentReverse","currentViewportData","undefined","refreshData","setViewport","setSorts","currentSort","setFilters","currentFilter","data","getViewportData","viewportUpdatePromise","Promise","resolve","items","offset","put","item","newItem","_id","sendUpdate","sendItemUpdate","event","debug","doc","fetchInfo","selector","find","infoUpdatePromise","cancel","makeCancelable","findResult","docs","e","isCanceled","error","fetchViewportData","skip","top","limit","bottom","then","viewportData","getSnapshot","sortedRanges","itemMap","all","from","to","findSnapshotResult"],"sources":["../src/PouchStorageTable.ts"],"sourcesContent":["import PouchDB from 'pouchdb-browser';\nimport PouchDBFind from 'pouchdb-find';\nimport {\n Operator as FilterOperator,\n Type as FilterType,\n} from '@deephaven/filters';\nimport Log from '@deephaven/log';\nimport {\n FilterConfig,\n FilterValue,\n SortConfig,\n StorageItem,\n StorageTable,\n StorageListenerRemover,\n StorageTableViewport,\n StorageItemListener,\n StorageSnapshot,\n ViewportData,\n ViewportUpdateCallback,\n} from '@deephaven/storage';\nimport { CancelablePromise, PromiseUtils } from '@deephaven/utils';\n\nconst log = Log.module('PouchStorageTable');\n\nconst DB_PREFIX = 'Deephaven.';\n\nPouchDB.plugin(PouchDBFind);\n\nexport interface PouchStorageItem {\n _id?: string;\n}\n\nexport type PouchDBSort = Array<\n string | { [propName: string]: 'asc' | 'desc' }\n>;\n\nfunction makePouchFilter(type: string, value: FilterValue | FilterValue[]) {\n switch (type) {\n case FilterType.in:\n case FilterType.contains:\n return { $regex: new RegExp(`${value}`) };\n case FilterType.inIgnoreCase:\n return { $regex: new RegExp(`${value}`, 'i') };\n case FilterType.eq:\n return { $eq: value };\n case FilterType.notEq:\n return { $neq: value };\n case FilterType.greaterThan:\n return { $gt: value };\n case FilterType.greaterThanOrEqualTo:\n return { $gte: value };\n case FilterType.lessThan:\n return { $lt: value };\n case FilterType.lessThanOrEqualTo:\n return { $lte: value };\n case FilterType.startsWith:\n return { $regex: new RegExp(`^(?${value}).*`) };\n default:\n throw new Error(`Unsupported type: ${type}`);\n }\n}\n\nfunction makePouchSelectorFromConfig(\n config: FilterConfig\n): PouchDB.Find.Selector {\n const { filterItems, filterOperators } = config;\n let filter = null;\n for (let i = 0; i < filterItems.length; i += 1) {\n const filterItem = filterItems[i];\n const { columnName, type, value } = filterItem;\n const newFilter = { [columnName]: makePouchFilter(type, value) };\n if (i === 0) {\n filter = newFilter;\n } else if (filter !== null && i - 1 < filterOperators.length) {\n const filterOperator = filterOperators[i - 1];\n if (filterOperator === FilterOperator.and) {\n filter = { $and: [filter, newFilter] };\n } else if (filterOperator === FilterOperator.or) {\n filter = { $or: [filter, newFilter] };\n } else {\n throw new Error(\n `Unexpected filter operator ${filterOperator}, ${newFilter}`\n );\n }\n }\n }\n if (filter == null) {\n throw new Error(`Invalid filter config ${config}`);\n }\n return filter;\n}\n\nfunction selectorWithFilters(\n filters: FilterConfig[] = []\n): PouchDB.Find.Selector {\n return {\n $and: [\n ...filters.map(filter => makePouchSelectorFromConfig(filter)),\n { name: { $gt: null } },\n { id: { $gt: null } },\n ],\n };\n}\n\nfunction sortWithConfigs(\n sorts: SortConfig[] | null,\n reverse = false\n): PouchDBSort {\n return [\n { id: reverse ? 'desc' : 'asc' },\n ...(sorts?.map(sort => ({ [sort.column]: sort.direction })) ?? []),\n ];\n}\n\nexport class PouchStorageTable<T extends StorageItem = StorageItem>\n implements StorageTable<T> {\n protected db: PouchDB.Database<T & PouchStorageItem>;\n\n changes?: PouchDB.Core.Changes<T & PouchStorageItem>;\n\n private listeners: ViewportUpdateCallback<T>[] = [];\n\n private itemListeners: Map<string, StorageItemListener<T>[]> = new Map();\n\n private currentSize = 0;\n\n private currentViewport?: StorageTableViewport;\n\n private currentReverse = false;\n\n private currentFilter: FilterConfig[] | null = null;\n\n private currentSort: SortConfig[] | null = null;\n\n private infoUpdatePromise?: CancelablePromise<\n PouchDB.Find.FindResponse<T & PouchStorageItem>\n >;\n\n private viewportUpdatePromise?: CancelablePromise<ViewportData<T>>;\n\n private currentViewportData?: ViewportData<T>;\n\n constructor(\n databaseName: string,\n dbOptions?: PouchDB.Configuration.DatabaseConfiguration\n ) {\n this.db = new PouchDB<T & PouchStorageItem>(\n `${DB_PREFIX}${databaseName}`,\n dbOptions\n );\n\n // Need to set `_remote` to false to remove deprecation warnings: https://github.com/pouchdb/pouchdb/issues/6106\n // eslint-disable-next-line @typescript-eslint/no-explicit-any, no-underscore-dangle\n (this.db as any)._remote = false;\n\n this.listenForChanges();\n\n this.db.createIndex({ index: { fields: ['id', 'name'] } });\n\n this.refreshInfo();\n }\n\n /**\n * Listen for db changes. This can be cancelled by calling\n * `this.changes?.cancel()`\n */\n listenForChanges(): void {\n this.changes = this.db\n .changes({ live: true, since: 'now', include_docs: true })\n .on('change', this.dbUpdate.bind(this));\n }\n\n onUpdate(callback: ViewportUpdateCallback<T>): StorageListenerRemover {\n this.listeners = [...this.listeners, callback];\n return () => {\n this.listeners = this.listeners.filter(other => other !== callback);\n };\n }\n\n onItemUpdate(\n id: string,\n listener: StorageItemListener<T>\n ): StorageListenerRemover {\n if (!this.itemListeners.has(id)) {\n this.itemListeners.set(id, []);\n }\n\n this.itemListeners.set(id, [\n ...(this.itemListeners.get(id) as StorageItemListener<T>[]),\n listener,\n ]);\n\n this.refreshItem(id);\n\n return () => {\n this.itemListeners.set(\n id,\n (this.itemListeners.get(id) as StorageItemListener<T>[]).filter(\n other => other !== listener\n )\n );\n };\n }\n\n close(): void {\n this.listeners = [];\n }\n\n get size(): number {\n return this.currentSize;\n }\n\n get viewport(): StorageTableViewport | undefined {\n return this.currentViewport;\n }\n\n setReversed(reversed: boolean): void {\n this.currentReverse = reversed;\n\n this.currentViewportData = undefined;\n\n this.refreshData();\n }\n\n setViewport(viewport: StorageTableViewport | undefined): void {\n this.currentViewport = viewport;\n\n this.refreshInfo();\n\n this.refreshData();\n }\n\n setSorts(config: SortConfig[] | null): void {\n this.currentSort = config;\n\n this.currentViewportData = undefined;\n\n this.refreshData();\n }\n\n setFilters(config: FilterConfig[] | null): void {\n this.currentFilter = config;\n\n this.currentViewportData = undefined;\n\n this.refreshInfo();\n\n this.refreshData();\n }\n\n get data(): ViewportData<T> | undefined {\n return this.currentViewportData;\n }\n\n async getViewportData(): Promise<ViewportData<T>> {\n if (!this.viewportUpdatePromise) {\n this.refreshData();\n }\n return (\n this.viewportUpdatePromise ?? Promise.resolve({ items: [], offset: 0 })\n );\n }\n\n async put(item: T): Promise<T> {\n // Put the item ID in both the _id and the id slot\n // PouchDB uses _id everywhere, StorageTable just uses `id` though\n const newItem = {\n ...item,\n _id: item.id,\n } as T;\n\n await this.db.put(newItem);\n\n return newItem;\n }\n\n private sendUpdate() {\n // Retain a reference to it in case a listener gets removed while sending an update\n const { listeners } = this;\n const data = this.currentViewportData ?? { items: [], offset: 0 };\n for (let i = 0; i < listeners.length; i += 1) {\n listeners[i](data);\n }\n }\n\n private sendItemUpdate(item: T) {\n const listeners = this.itemListeners.get(item.id);\n if (listeners !== undefined) {\n for (let i = 0; i < listeners.length; i += 1) {\n listeners[i](item);\n }\n }\n }\n\n protected dbUpdate(event: PouchDB.Core.ChangesResponseChange<T>): void {\n log.debug('Update received', event);\n\n this.refreshInfo();\n\n if (event.doc !== undefined) {\n this.sendItemUpdate(event.doc);\n }\n\n this.refreshData();\n }\n\n /**\n * Fetch infor for a given selector.\n * @param selector\n */\n protected async fetchInfo(\n selector: PouchDB.Find.Selector\n ): Promise<PouchDB.Find.FindResponse<T & PouchStorageItem>> {\n return this.db.find({\n selector,\n fields: [],\n });\n }\n\n private async refreshInfo() {\n try {\n this.infoUpdatePromise?.cancel();\n\n this.infoUpdatePromise = PromiseUtils.makeCancelable(\n this.fetchInfo(selectorWithFilters(this.currentFilter ?? []))\n );\n\n const findResult = await this.infoUpdatePromise;\n\n this.currentSize = findResult.docs.length;\n\n this.sendUpdate();\n } catch (e) {\n if (!PromiseUtils.isCanceled(e)) {\n log.error('Unable to refreshInfo', e);\n throw e;\n }\n }\n }\n\n /**\n * Fetch data for the given viewport, selector, and sort.\n * @param viewport\n * @param selector\n * @param sort\n */\n protected async fetchViewportData(\n viewport: StorageTableViewport,\n selector: PouchDB.Find.Selector,\n sort: PouchDBSort\n ): Promise<ViewportData<T>> {\n return this.db\n .find({\n selector,\n skip: viewport.top,\n limit: viewport.bottom - viewport.top + 1,\n sort,\n fields: ['id', 'name'],\n })\n .then(findResult => ({\n items: findResult.docs,\n offset: viewport.top,\n }));\n }\n\n private async refreshData(): Promise<ViewportData<T> | undefined> {\n if (!this.currentViewport) {\n return;\n }\n\n try {\n const selector = selectorWithFilters(this.currentFilter ?? []);\n const sort = sortWithConfigs(this.currentSort, this.currentReverse);\n\n this.viewportUpdatePromise?.cancel();\n\n this.viewportUpdatePromise = PromiseUtils.makeCancelable(\n this.fetchViewportData(this.currentViewport, selector, sort)\n );\n\n const viewportData = await this.viewportUpdatePromise;\n\n this.currentViewportData = viewportData;\n\n this.sendUpdate();\n\n return viewportData;\n } catch (e) {\n if (!PromiseUtils.isCanceled(e)) {\n log.error('Unable to refreshData', e);\n throw e;\n }\n }\n }\n\n async refreshItem(id: string): Promise<T | undefined> {\n const findResult = await this.db.find({\n selector: { id },\n limit: 1,\n });\n\n const item = findResult.docs[0];\n\n if (item !== undefined) {\n this.sendItemUpdate(item);\n }\n\n return item;\n }\n\n async getSnapshot(\n sortedRanges: [number, number][]\n ): Promise<StorageSnapshot<T>> {\n const itemMap = new Map();\n\n const sort: PouchDBSort = [{ id: this.currentReverse ? 'desc' : 'asc' }];\n\n await Promise.all(\n sortedRanges.map(async ([from, to]) => {\n const limit = to - from + 1;\n return this.db\n .find({\n selector: selectorWithFilters(this.currentFilter ?? []),\n skip: from,\n limit,\n sort,\n fields: ['id', 'name'],\n })\n .then(findSnapshotResult => {\n for (let i = 0; i < limit; i += 1) {\n const index = from + i;\n itemMap.set(index, findSnapshotResult.docs[i]);\n }\n });\n })\n );\n\n return itemMap;\n }\n}\n\nexport default PouchStorageTable;\n"],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Takes an array of items and determines which ones to keep and which ones to
3
+ * prune based on the given thresholds.
4
+ * @param items items to keep or prune
5
+ * @param maxItems maximum number of items to allow before pruning
6
+ * @param pruneItemsCount if the maxItems count is exceeded, the number we want to keep
7
+ */
8
+ export declare function siftPrunableItems<T>(items: T[], maxItems: number, pruneItemsCount: number): {
9
+ toKeep: T[];
10
+ toPrune: T[];
11
+ };
12
+ //# sourceMappingURL=pouchCommandHistoryUtils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pouchCommandHistoryUtils.d.ts","sourceRoot":"","sources":["../src/pouchCommandHistoryUtils.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,wBAAgB,iBAAiB,CAAC,CAAC,EACjC,KAAK,EAAE,CAAC,EAAE,EACV,QAAQ,EAAE,MAAM,EAChB,eAAe,EAAE,MAAM,GACtB;IACD,MAAM,EAAE,CAAC,EAAE,CAAC;IACZ,OAAO,EAAE,CAAC,EAAE,CAAC;CACd,CAaA"}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Takes an array of items and determines which ones to keep and which ones to
3
+ * prune based on the given thresholds.
4
+ * @param items items to keep or prune
5
+ * @param maxItems maximum number of items to allow before pruning
6
+ * @param pruneItemsCount if the maxItems count is exceeded, the number we want to keep
7
+ */
8
+ // eslint-disable-next-line import/prefer-default-export
9
+ export function siftPrunableItems(items, maxItems, pruneItemsCount) {
10
+ if (items.length > maxItems) {
11
+ var pruneCount = items.length - pruneItemsCount;
12
+ return {
13
+ toKeep: items.slice(pruneCount),
14
+ toPrune: items.slice(0, pruneCount)
15
+ };
16
+ }
17
+ return {
18
+ toKeep: items,
19
+ toPrune: []
20
+ };
21
+ }
22
+ //# sourceMappingURL=pouchCommandHistoryUtils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pouchCommandHistoryUtils.js","names":["siftPrunableItems","items","maxItems","pruneItemsCount","length","pruneCount","toKeep","slice","toPrune"],"sources":["../src/pouchCommandHistoryUtils.ts"],"sourcesContent":["/**\n * Takes an array of items and determines which ones to keep and which ones to\n * prune based on the given thresholds.\n * @param items items to keep or prune\n * @param maxItems maximum number of items to allow before pruning\n * @param pruneItemsCount if the maxItems count is exceeded, the number we want to keep\n */\n// eslint-disable-next-line import/prefer-default-export\nexport function siftPrunableItems<T>(\n items: T[],\n maxItems: number,\n pruneItemsCount: number\n): {\n toKeep: T[];\n toPrune: T[];\n} {\n if (items.length > maxItems) {\n const pruneCount = items.length - pruneItemsCount;\n return {\n toKeep: items.slice(pruneCount),\n toPrune: items.slice(0, pruneCount),\n };\n }\n\n return {\n toKeep: items,\n toPrune: [],\n };\n}\n"],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASA,iBAAiB,CAC/BC,KAAU,EACVC,QAAgB,EAChBC,eAAuB,EAIvB;EACA,IAAIF,KAAK,CAACG,MAAM,GAAGF,QAAQ,EAAE;IAC3B,IAAMG,UAAU,GAAGJ,KAAK,CAACG,MAAM,GAAGD,eAAe;IACjD,OAAO;MACLG,MAAM,EAAEL,KAAK,CAACM,KAAK,CAACF,UAAU,CAAC;MAC/BG,OAAO,EAAEP,KAAK,CAACM,KAAK,CAAC,CAAC,EAAEF,UAAU;IACpC,CAAC;EACH;EAEA,OAAO;IACLC,MAAM,EAAEL,KAAK;IACbO,OAAO,EAAE;EACX,CAAC;AACH"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@deephaven/pouch-storage",
3
- "version": "0.32.1-beta.0+a60bda5",
3
+ "version": "0.32.1-beta.11+bb24f610",
4
4
  "description": "Deephaven Storage based on PouchDB",
5
5
  "author": "Deephaven Data Labs LLC",
6
6
  "license": "Apache-2.0",
@@ -21,11 +21,11 @@
21
21
  "build:babel": "babel ./src --out-dir ./dist --extensions \".ts,.tsx,.js,.jsx\" --source-maps --root-mode upward"
22
22
  },
23
23
  "dependencies": {
24
- "@deephaven/console": "^0.32.1-beta.0+a60bda5",
25
- "@deephaven/filters": "^0.32.1-beta.0+a60bda5",
26
- "@deephaven/log": "^0.32.1-beta.0+a60bda5",
27
- "@deephaven/storage": "^0.32.1-beta.0+a60bda5",
28
- "@deephaven/utils": "^0.32.1-beta.0+a60bda5",
24
+ "@deephaven/console": "^0.32.1-beta.11+bb24f610",
25
+ "@deephaven/filters": "^0.32.1-beta.11+bb24f610",
26
+ "@deephaven/log": "^0.32.1-beta.11+bb24f610",
27
+ "@deephaven/storage": "^0.32.1-beta.11+bb24f610",
28
+ "@deephaven/utils": "^0.32.1-beta.11+bb24f610",
29
29
  "lodash.throttle": "^4.1.1",
30
30
  "pouchdb-browser": "^7.3.0",
31
31
  "pouchdb-find": "^7.3.0"
@@ -34,7 +34,7 @@
34
34
  "react": "^17.0.0"
35
35
  },
36
36
  "devDependencies": {
37
- "@deephaven/tsconfig": "^0.32.1-beta.0+a60bda5"
37
+ "@deephaven/tsconfig": "^0.32.1-beta.11+bb24f610"
38
38
  },
39
39
  "files": [
40
40
  "dist"
@@ -42,5 +42,5 @@
42
42
  "publishConfig": {
43
43
  "access": "public"
44
44
  },
45
- "gitHead": "a60bda5c1eae60835987b3ced6d0d8f61ea23f19"
45
+ "gitHead": "bb24f61018c5af9325c3e3dc36abd63c3b10d51a"
46
46
  }