@topgunbuild/server 0.4.0 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -10,7 +10,7 @@ import { createServer as createHttpServer } from "http";
10
10
  import { createServer as createHttpsServer } from "https";
11
11
  import { readFileSync as readFileSync2 } from "fs";
12
12
  import { WebSocketServer as WebSocketServer2, WebSocket as WebSocket3 } from "ws";
13
- import { HLC as HLC2, LWWMap as LWWMap3, ORMap as ORMap2, serialize as serialize4, deserialize, MessageSchema, WriteConcern as WriteConcern2, ConsistencyLevel as ConsistencyLevel2, DEFAULT_REPLICATION_CONFIG as DEFAULT_REPLICATION_CONFIG2 } from "@topgunbuild/core";
13
+ import { HLC as HLC2, LWWMap as LWWMap3, ORMap as ORMap2, serialize as serialize4, deserialize, MessageSchema, WriteConcern as WriteConcern2, ConsistencyLevel as ConsistencyLevel2, DEFAULT_REPLICATION_CONFIG as DEFAULT_REPLICATION_CONFIG2, IndexedLWWMap as IndexedLWWMap2, IndexedORMap as IndexedORMap2 } from "@topgunbuild/core";
14
14
  import * as jwt from "jsonwebtoken";
15
15
  import * as crypto from "crypto";
16
16
 
@@ -101,7 +101,7 @@ function executeQuery(records, query) {
101
101
  }
102
102
 
103
103
  // src/query/QueryRegistry.ts
104
- import { serialize } from "@topgunbuild/core";
104
+ import { serialize, IndexedLWWMap } from "@topgunbuild/core";
105
105
 
106
106
  // src/utils/logger.ts
107
107
  import pino from "pino";
@@ -362,14 +362,70 @@ var QueryRegistry = class {
362
362
  /**
363
363
  * Processes a record change for all relevant subscriptions.
364
364
  * Calculates diffs and sends updates.
365
+ *
366
+ * For IndexedLWWMap: Uses StandingQueryRegistry for O(1) affected query detection.
367
+ * For regular maps: Falls back to ReverseQueryIndex.
365
368
  */
366
369
  processChange(mapName, map, changeKey, changeRecord, oldRecord) {
367
370
  const index = this.indexes.get(mapName);
368
371
  if (!index) return;
369
372
  const newVal = this.extractValue(changeRecord);
370
373
  const oldVal = this.extractValue(oldRecord);
374
+ if (map instanceof IndexedLWWMap) {
375
+ this.processChangeWithStandingQuery(mapName, map, changeKey, newVal, oldVal);
376
+ return;
377
+ }
378
+ this.processChangeWithReverseIndex(mapName, map, changeKey, newVal, oldVal, index);
379
+ }
380
+ /**
381
+ * Process change using IndexedLWWMap's StandingQueryRegistry.
382
+ * O(1) detection of affected queries.
383
+ */
384
+ processChangeWithStandingQuery(mapName, map, changeKey, newVal, oldVal) {
385
+ const subs = this.subscriptions.get(mapName);
386
+ if (!subs || subs.size === 0) return;
387
+ const subsByQueryId = /* @__PURE__ */ new Map();
388
+ for (const sub of subs) {
389
+ subsByQueryId.set(sub.id, sub);
390
+ }
391
+ const standingRegistry = map.getStandingQueryRegistry();
392
+ let changes;
393
+ if (oldVal === null || oldVal === void 0) {
394
+ if (newVal !== null && newVal !== void 0) {
395
+ changes = standingRegistry.onRecordAdded(changeKey, newVal);
396
+ } else {
397
+ return;
398
+ }
399
+ } else if (newVal === null || newVal === void 0) {
400
+ changes = standingRegistry.onRecordRemoved(changeKey, oldVal);
401
+ } else {
402
+ changes = standingRegistry.onRecordUpdated(changeKey, oldVal, newVal);
403
+ }
404
+ for (const sub of subs) {
405
+ const coreQuery = this.convertToCoreQuery(sub.query);
406
+ if (!coreQuery) {
407
+ this.processSubscriptionFallback(sub, map, changeKey, newVal);
408
+ continue;
409
+ }
410
+ const queryHash = this.hashCoreQuery(coreQuery);
411
+ const change = changes.get(queryHash);
412
+ if (change === "added") {
413
+ sub.previousResultKeys.add(changeKey);
414
+ this.sendUpdate(sub, changeKey, newVal, "UPDATE");
415
+ } else if (change === "removed") {
416
+ sub.previousResultKeys.delete(changeKey);
417
+ this.sendUpdate(sub, changeKey, null, "REMOVE");
418
+ } else if (change === "updated") {
419
+ this.sendUpdate(sub, changeKey, newVal, "UPDATE");
420
+ }
421
+ }
422
+ }
423
+ /**
424
+ * Process change using legacy ReverseQueryIndex.
425
+ */
426
+ processChangeWithReverseIndex(mapName, map, changeKey, newVal, oldVal, index) {
371
427
  const changedFields = this.getChangedFields(oldVal, newVal);
372
- if (changedFields !== "ALL" && changedFields.size === 0 && oldRecord && changeRecord) {
428
+ if (changedFields !== "ALL" && changedFields.size === 0 && oldVal && newVal) {
373
429
  return;
374
430
  }
375
431
  const candidates = index.getCandidates(changedFields, oldVal, newVal);
@@ -411,6 +467,103 @@ var QueryRegistry = class {
411
467
  sub.previousResultKeys = newResultKeys;
412
468
  }
413
469
  }
470
+ /**
471
+ * Fallback processing for subscriptions that can't use StandingQueryRegistry.
472
+ */
473
+ processSubscriptionFallback(sub, map, changeKey, newVal) {
474
+ const dummyRecord = {
475
+ value: newVal,
476
+ timestamp: { millis: 0, counter: 0, nodeId: "" }
477
+ };
478
+ const isMatch = newVal !== null && matchesQuery(dummyRecord, sub.query);
479
+ const wasInResult = sub.previousResultKeys.has(changeKey);
480
+ if (isMatch && !wasInResult) {
481
+ sub.previousResultKeys.add(changeKey);
482
+ this.sendUpdate(sub, changeKey, newVal, "UPDATE");
483
+ } else if (!isMatch && wasInResult) {
484
+ sub.previousResultKeys.delete(changeKey);
485
+ this.sendUpdate(sub, changeKey, null, "REMOVE");
486
+ } else if (isMatch && wasInResult) {
487
+ this.sendUpdate(sub, changeKey, newVal, "UPDATE");
488
+ }
489
+ }
490
+ /**
491
+ * Convert server Query format to core Query format.
492
+ */
493
+ convertToCoreQuery(query) {
494
+ if (query.predicate) {
495
+ return this.predicateToCoreQuery(query.predicate);
496
+ }
497
+ if (query.where) {
498
+ const conditions = [];
499
+ for (const [attribute, condition] of Object.entries(query.where)) {
500
+ if (typeof condition !== "object" || condition === null) {
501
+ conditions.push({ type: "eq", attribute, value: condition });
502
+ } else {
503
+ for (const [op, value] of Object.entries(condition)) {
504
+ const coreOp = this.convertOperator(op);
505
+ if (coreOp) {
506
+ conditions.push({ type: coreOp, attribute, value });
507
+ }
508
+ }
509
+ }
510
+ }
511
+ if (conditions.length === 0) return null;
512
+ if (conditions.length === 1) return conditions[0];
513
+ return { type: "and", children: conditions };
514
+ }
515
+ return null;
516
+ }
517
+ predicateToCoreQuery(predicate) {
518
+ if (!predicate || !predicate.op) return null;
519
+ switch (predicate.op) {
520
+ case "eq":
521
+ case "neq":
522
+ case "gt":
523
+ case "gte":
524
+ case "lt":
525
+ case "lte":
526
+ return {
527
+ type: predicate.op,
528
+ attribute: predicate.attribute,
529
+ value: predicate.value
530
+ };
531
+ case "and":
532
+ case "or":
533
+ if (predicate.children && Array.isArray(predicate.children)) {
534
+ const children = predicate.children.map((c) => this.predicateToCoreQuery(c)).filter((c) => c !== null);
535
+ if (children.length === 0) return null;
536
+ if (children.length === 1) return children[0];
537
+ return { type: predicate.op, children };
538
+ }
539
+ return null;
540
+ case "not":
541
+ if (predicate.children && predicate.children[0]) {
542
+ const child = this.predicateToCoreQuery(predicate.children[0]);
543
+ if (child) {
544
+ return { type: "not", child };
545
+ }
546
+ }
547
+ return null;
548
+ default:
549
+ return null;
550
+ }
551
+ }
552
+ convertOperator(op) {
553
+ const mapping = {
554
+ "$eq": "eq",
555
+ "$ne": "neq",
556
+ "$neq": "neq",
557
+ "$gt": "gt",
558
+ "$gte": "gte",
559
+ "$lt": "lt",
560
+ "$lte": "lte"
561
+ };
562
+ return mapping[op] || null;
563
+ }
564
+ hashCoreQuery(query) {
565
+ return JSON.stringify(query);
566
+ }
414
567
  extractValue(record) {
415
568
  if (!record) return null;
416
569
  if (Array.isArray(record)) {
@@ -9603,6 +9756,26 @@ var ServerCoordinator = class {
9603
9756
  }
9604
9757
  async executeLocalQuery(mapName, query) {
9605
9758
  const map = await this.getMapAsync(mapName);
9759
+ const localQuery = { ...query };
9760
+ delete localQuery.offset;
9761
+ delete localQuery.limit;
9762
+ if (map instanceof IndexedLWWMap2) {
9763
+ const coreQuery = this.convertToCoreQuery(localQuery);
9764
+ if (coreQuery) {
9765
+ const entries = map.queryEntries(coreQuery);
9766
+ return entries.map(([key, value]) => {
9767
+ const record = map.getRecord(key);
9768
+ return { key, value, timestamp: record?.timestamp };
9769
+ });
9770
+ }
9771
+ }
9772
+ if (map instanceof IndexedORMap2) {
9773
+ const coreQuery = this.convertToCoreQuery(localQuery);
9774
+ if (coreQuery) {
9775
+ const results = map.query(coreQuery);
9776
+ return results.map(({ key, value }) => ({ key, value }));
9777
+ }
9778
+ }
9606
9779
  const records = /* @__PURE__ */ new Map();
9607
9780
  if (map instanceof LWWMap3) {
9608
9781
  for (const key of map.allKeys()) {
@@ -9620,11 +9793,89 @@ var ServerCoordinator = class {
9620
9793
  }
9621
9794
  }
9622
9795
  }
9623
- const localQuery = { ...query };
9624
- delete localQuery.offset;
9625
- delete localQuery.limit;
9626
9796
  return executeQuery(records, localQuery);
9627
9797
  }
9798
+ /**
9799
+ * Convert server Query format to core Query format for indexed execution.
9800
+ * Returns null if conversion is not possible (complex queries).
9801
+ */
9802
+ convertToCoreQuery(query) {
9803
+ if (query.predicate) {
9804
+ return this.predicateToCoreQuery(query.predicate);
9805
+ }
9806
+ if (query.where) {
9807
+ const conditions = [];
9808
+ for (const [attribute, condition] of Object.entries(query.where)) {
9809
+ if (typeof condition !== "object" || condition === null) {
9810
+ conditions.push({ type: "eq", attribute, value: condition });
9811
+ } else {
9812
+ for (const [op, value] of Object.entries(condition)) {
9813
+ const coreOp = this.convertOperator(op);
9814
+ if (coreOp) {
9815
+ conditions.push({ type: coreOp, attribute, value });
9816
+ }
9817
+ }
9818
+ }
9819
+ }
9820
+ if (conditions.length === 0) return null;
9821
+ if (conditions.length === 1) return conditions[0];
9822
+ return { type: "and", children: conditions };
9823
+ }
9824
+ return null;
9825
+ }
9826
+ /**
9827
+ * Convert predicate node to core Query format.
9828
+ */
9829
+ predicateToCoreQuery(predicate) {
9830
+ if (!predicate || !predicate.op) return null;
9831
+ switch (predicate.op) {
9832
+ case "eq":
9833
+ case "neq":
9834
+ case "gt":
9835
+ case "gte":
9836
+ case "lt":
9837
+ case "lte":
9838
+ return {
9839
+ type: predicate.op,
9840
+ attribute: predicate.attribute,
9841
+ value: predicate.value
9842
+ };
9843
+ case "and":
9844
+ case "or":
9845
+ if (predicate.children && Array.isArray(predicate.children)) {
9846
+ const children = predicate.children.map((c) => this.predicateToCoreQuery(c)).filter((c) => c !== null);
9847
+ if (children.length === 0) return null;
9848
+ if (children.length === 1) return children[0];
9849
+ return { type: predicate.op, children };
9850
+ }
9851
+ return null;
9852
+ case "not":
9853
+ if (predicate.children && predicate.children[0]) {
9854
+ const child = this.predicateToCoreQuery(predicate.children[0]);
9855
+ if (child) {
9856
+ return { type: "not", child };
9857
+ }
9858
+ }
9859
+ return null;
9860
+ default:
9861
+ return null;
9862
+ }
9863
+ }
9864
+ /**
9865
+ * Convert server operator to core query type.
9866
+ */
9867
+ convertOperator(op) {
9868
+ const mapping = {
9869
+ "$eq": "eq",
9870
+ "$ne": "neq",
9871
+ "$neq": "neq",
9872
+ "$gt": "gt",
9873
+ "$gte": "gte",
9874
+ "$lt": "lt",
9875
+ "$lte": "lte"
9876
+ };
9877
+ return mapping[op] || null;
9878
+ }
9628
9879
  finalizeClusterQuery(requestId, timeout = false) {
9629
9880
  const pending = this.pendingClusterQueries.get(requestId);
9630
9881
  if (!pending) return;
@@ -11555,6 +11806,255 @@ var MapWithResolver = class {
11555
11806
  return this.map.prune(olderThan);
11556
11807
  }
11557
11808
  };
11809
+
11810
+ // src/config/IndexConfig.ts
11811
+ var DEFAULT_INDEX_CONFIG = {
11812
+ autoIndex: false,
11813
+ maxAutoIndexesPerMap: 10,
11814
+ maps: [],
11815
+ logStats: false,
11816
+ statsLogInterval: 6e4
11817
+ };
11818
+ function validateIndexConfig(config) {
11819
+ const errors = [];
11820
+ if (config.maxAutoIndexesPerMap !== void 0) {
11821
+ if (typeof config.maxAutoIndexesPerMap !== "number" || config.maxAutoIndexesPerMap < 1) {
11822
+ errors.push("maxAutoIndexesPerMap must be a positive number");
11823
+ }
11824
+ }
11825
+ if (config.statsLogInterval !== void 0) {
11826
+ if (typeof config.statsLogInterval !== "number" || config.statsLogInterval < 1e3) {
11827
+ errors.push("statsLogInterval must be at least 1000ms");
11828
+ }
11829
+ }
11830
+ if (config.maps) {
11831
+ const mapNames = /* @__PURE__ */ new Set();
11832
+ for (const mapConfig of config.maps) {
11833
+ if (!mapConfig.mapName || typeof mapConfig.mapName !== "string") {
11834
+ errors.push("Each map config must have a valid mapName");
11835
+ continue;
11836
+ }
11837
+ if (mapNames.has(mapConfig.mapName)) {
11838
+ errors.push(`Duplicate map config for: ${mapConfig.mapName}`);
11839
+ }
11840
+ mapNames.add(mapConfig.mapName);
11841
+ if (!Array.isArray(mapConfig.indexes)) {
11842
+ errors.push(`Map ${mapConfig.mapName}: indexes must be an array`);
11843
+ continue;
11844
+ }
11845
+ const attrNames = /* @__PURE__ */ new Set();
11846
+ for (const indexDef of mapConfig.indexes) {
11847
+ if (!indexDef.attribute || typeof indexDef.attribute !== "string") {
11848
+ errors.push(`Map ${mapConfig.mapName}: index must have valid attribute`);
11849
+ continue;
11850
+ }
11851
+ if (!["hash", "navigable"].includes(indexDef.type)) {
11852
+ errors.push(
11853
+ `Map ${mapConfig.mapName}: index type must be 'hash' or 'navigable'`
11854
+ );
11855
+ }
11856
+ if (indexDef.comparator && !["number", "string", "date"].includes(indexDef.comparator)) {
11857
+ errors.push(
11858
+ `Map ${mapConfig.mapName}: comparator must be 'number', 'string', or 'date'`
11859
+ );
11860
+ }
11861
+ const key = `${indexDef.attribute}:${indexDef.type}`;
11862
+ if (attrNames.has(key)) {
11863
+ errors.push(
11864
+ `Map ${mapConfig.mapName}: duplicate ${indexDef.type} index on ${indexDef.attribute}`
11865
+ );
11866
+ }
11867
+ attrNames.add(key);
11868
+ }
11869
+ }
11870
+ }
11871
+ return errors;
11872
+ }
11873
+ function mergeWithDefaults(userConfig) {
11874
+ return {
11875
+ ...DEFAULT_INDEX_CONFIG,
11876
+ ...userConfig,
11877
+ maps: userConfig.maps ?? DEFAULT_INDEX_CONFIG.maps
11878
+ };
11879
+ }
11880
+
11881
+ // src/config/MapFactory.ts
11882
+ import {
11883
+ LWWMap as LWWMap5,
11884
+ ORMap as ORMap3,
11885
+ IndexedLWWMap as IndexedLWWMap3,
11886
+ IndexedORMap as IndexedORMap3,
11887
+ simpleAttribute
11888
+ } from "@topgunbuild/core";
11889
+ var MapFactory = class {
11890
+ /**
11891
+ * Create a MapFactory.
11892
+ *
11893
+ * @param config - Server index configuration
11894
+ */
11895
+ constructor(config) {
11896
+ this.config = mergeWithDefaults(config ?? {});
11897
+ this.mapConfigs = /* @__PURE__ */ new Map();
11898
+ for (const mapConfig of this.config.maps ?? []) {
11899
+ this.mapConfigs.set(mapConfig.mapName, mapConfig);
11900
+ }
11901
+ }
11902
+ /**
11903
+ * Create an LWWMap or IndexedLWWMap based on configuration.
11904
+ *
11905
+ * @param mapName - Name of the map
11906
+ * @param hlc - Hybrid Logical Clock instance
11907
+ * @returns LWWMap or IndexedLWWMap depending on configuration
11908
+ */
11909
+ createLWWMap(mapName, hlc) {
11910
+ const mapConfig = this.mapConfigs.get(mapName);
11911
+ if (!mapConfig || mapConfig.indexes.length === 0) {
11912
+ return new LWWMap5(hlc);
11913
+ }
11914
+ const map = new IndexedLWWMap3(hlc);
11915
+ for (const indexDef of mapConfig.indexes) {
11916
+ this.addIndexToLWWMap(map, indexDef);
11917
+ }
11918
+ return map;
11919
+ }
11920
+ /**
11921
+ * Create an ORMap or IndexedORMap based on configuration.
11922
+ *
11923
+ * @param mapName - Name of the map
11924
+ * @param hlc - Hybrid Logical Clock instance
11925
+ * @returns ORMap or IndexedORMap depending on configuration
11926
+ */
11927
+ createORMap(mapName, hlc) {
11928
+ const mapConfig = this.mapConfigs.get(mapName);
11929
+ if (!mapConfig || mapConfig.indexes.length === 0) {
11930
+ return new ORMap3(hlc);
11931
+ }
11932
+ const map = new IndexedORMap3(hlc);
11933
+ for (const indexDef of mapConfig.indexes) {
11934
+ this.addIndexToORMap(map, indexDef);
11935
+ }
11936
+ return map;
11937
+ }
11938
+ /**
11939
+ * Add an index to an IndexedLWWMap based on definition.
11940
+ */
11941
+ addIndexToLWWMap(map, indexDef) {
11942
+ const attribute = this.createAttribute(indexDef.attribute);
11943
+ if (indexDef.type === "hash") {
11944
+ map.addHashIndex(attribute);
11945
+ } else if (indexDef.type === "navigable") {
11946
+ const navAttribute = attribute;
11947
+ const comparator = this.createComparator(indexDef.comparator);
11948
+ map.addNavigableIndex(navAttribute, comparator);
11949
+ }
11950
+ }
11951
+ /**
11952
+ * Add an index to an IndexedORMap based on definition.
11953
+ */
11954
+ addIndexToORMap(map, indexDef) {
11955
+ const attribute = this.createAttribute(indexDef.attribute);
11956
+ if (indexDef.type === "hash") {
11957
+ map.addHashIndex(attribute);
11958
+ } else if (indexDef.type === "navigable") {
11959
+ const navAttribute = attribute;
11960
+ const comparator = this.createComparator(indexDef.comparator);
11961
+ map.addNavigableIndex(navAttribute, comparator);
11962
+ }
11963
+ }
11964
+ /**
11965
+ * Create an Attribute for extracting values from records.
11966
+ * Supports dot notation for nested paths.
11967
+ */
11968
+ createAttribute(path) {
11969
+ return simpleAttribute(path, (record) => {
11970
+ return this.getNestedValue(record, path);
11971
+ });
11972
+ }
11973
+ /**
11974
+ * Get a nested value from an object using dot notation.
11975
+ *
11976
+ * @param obj - Object to extract value from
11977
+ * @param path - Dot-notation path (e.g., "user.email")
11978
+ * @returns Value at the path or undefined
11979
+ */
11980
+ getNestedValue(obj, path) {
11981
+ if (obj === null || obj === void 0) {
11982
+ return void 0;
11983
+ }
11984
+ const parts = path.split(".");
11985
+ let current = obj;
11986
+ for (const part of parts) {
11987
+ if (current === void 0 || current === null) {
11988
+ return void 0;
11989
+ }
11990
+ if (typeof current !== "object") {
11991
+ return void 0;
11992
+ }
11993
+ current = current[part];
11994
+ }
11995
+ return current;
11996
+ }
11997
+ /**
11998
+ * Create a comparator function for navigable indexes.
11999
+ */
12000
+ createComparator(type) {
12001
+ switch (type) {
12002
+ case "number":
12003
+ return (a, b) => {
12004
+ const numA = typeof a === "number" ? a : parseFloat(String(a));
12005
+ const numB = typeof b === "number" ? b : parseFloat(String(b));
12006
+ return numA - numB;
12007
+ };
12008
+ case "date":
12009
+ return (a, b) => {
12010
+ const dateA = new Date(a).getTime();
12011
+ const dateB = new Date(b).getTime();
12012
+ return dateA - dateB;
12013
+ };
12014
+ case "string":
12015
+ return (a, b) => {
12016
+ const strA = String(a);
12017
+ const strB = String(b);
12018
+ return strA.localeCompare(strB);
12019
+ };
12020
+ default:
12021
+ return void 0;
12022
+ }
12023
+ }
12024
+ /**
12025
+ * Check if a map should be indexed based on configuration.
12026
+ *
12027
+ * @param mapName - Name of the map
12028
+ * @returns true if map has index configuration
12029
+ */
12030
+ hasIndexConfig(mapName) {
12031
+ const config = this.mapConfigs.get(mapName);
12032
+ return config !== void 0 && config.indexes.length > 0;
12033
+ }
12034
+ /**
12035
+ * Get index configuration for a map.
12036
+ *
12037
+ * @param mapName - Name of the map
12038
+ * @returns Map index config or undefined
12039
+ */
12040
+ getMapConfig(mapName) {
12041
+ return this.mapConfigs.get(mapName);
12042
+ }
12043
+ /**
12044
+ * Get all configured map names.
12045
+ *
12046
+ * @returns Array of map names with index configuration
12047
+ */
12048
+ getConfiguredMaps() {
12049
+ return Array.from(this.mapConfigs.keys());
12050
+ }
12051
+ /**
12052
+ * Get the full server index configuration.
12053
+ */
12054
+ getConfig() {
12055
+ return this.config;
12056
+ }
12057
+ };
11558
12058
  export {
11559
12059
  BufferPool,
11560
12060
  ClusterCoordinator,
@@ -11564,6 +12064,7 @@ export {
11564
12064
  ConnectionRateLimiter,
11565
12065
  DEFAULT_CLUSTER_COORDINATOR_CONFIG,
11566
12066
  DEFAULT_CONFLICT_RESOLVER_CONFIG,
12067
+ DEFAULT_INDEX_CONFIG,
11567
12068
  DEFAULT_JOURNAL_SERVICE_CONFIG,
11568
12069
  DEFAULT_LAG_TRACKER_CONFIG,
11569
12070
  DEFAULT_SANDBOX_CONFIG,
@@ -11574,6 +12075,7 @@ export {
11574
12075
  IteratorTasklet,
11575
12076
  LagTracker,
11576
12077
  LockManager,
12078
+ MapFactory,
11577
12079
  MapTasklet,
11578
12080
  MapWithResolver,
11579
12081
  MemoryServerAdapter,
@@ -11604,10 +12106,12 @@ export {
11604
12106
  getNativeStats,
11605
12107
  logNativeStatus,
11606
12108
  logger,
12109
+ mergeWithDefaults,
11607
12110
  setGlobalBufferPool,
11608
12111
  setGlobalEventPayloadPool,
11609
12112
  setGlobalMessagePool,
11610
12113
  setGlobalRecordPool,
11611
- setGlobalTimestampPool
12114
+ setGlobalTimestampPool,
12115
+ validateIndexConfig
11612
12116
  };
11613
12117
  //# sourceMappingURL=index.mjs.map