hyperstack-react 0.3.15 → 0.4.1
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.d.ts +18 -20
- package/dist/index.esm.js +381 -342
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +381 -342
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.esm.js
CHANGED
|
@@ -7383,6 +7383,198 @@ class MemoryAdapter {
|
|
|
7383
7383
|
}
|
|
7384
7384
|
}
|
|
7385
7385
|
|
|
7386
|
+
function getNestedValue$1(obj, path) {
|
|
7387
|
+
let current = obj;
|
|
7388
|
+
for (const segment of path) {
|
|
7389
|
+
if (current === null || current === undefined)
|
|
7390
|
+
return undefined;
|
|
7391
|
+
if (typeof current !== 'object')
|
|
7392
|
+
return undefined;
|
|
7393
|
+
current = current[segment];
|
|
7394
|
+
}
|
|
7395
|
+
return current;
|
|
7396
|
+
}
|
|
7397
|
+
function compareSortValues$1(a, b) {
|
|
7398
|
+
if (a === b)
|
|
7399
|
+
return 0;
|
|
7400
|
+
if (a === undefined || a === null)
|
|
7401
|
+
return -1;
|
|
7402
|
+
if (b === undefined || b === null)
|
|
7403
|
+
return 1;
|
|
7404
|
+
if (typeof a === 'number' && typeof b === 'number') {
|
|
7405
|
+
return a - b;
|
|
7406
|
+
}
|
|
7407
|
+
if (typeof a === 'string' && typeof b === 'string') {
|
|
7408
|
+
return a.localeCompare(b);
|
|
7409
|
+
}
|
|
7410
|
+
if (typeof a === 'boolean' && typeof b === 'boolean') {
|
|
7411
|
+
return (a ? 1 : 0) - (b ? 1 : 0);
|
|
7412
|
+
}
|
|
7413
|
+
return String(a).localeCompare(String(b));
|
|
7414
|
+
}
|
|
7415
|
+
class SortedStorageDecorator {
|
|
7416
|
+
constructor(inner) {
|
|
7417
|
+
this.sortConfigs = new Map();
|
|
7418
|
+
this.sortedKeysMap = new Map();
|
|
7419
|
+
this.inner = inner;
|
|
7420
|
+
}
|
|
7421
|
+
get(viewPath, key) {
|
|
7422
|
+
return this.inner.get(viewPath, key);
|
|
7423
|
+
}
|
|
7424
|
+
getAll(viewPath) {
|
|
7425
|
+
const sortedKeys = this.sortedKeysMap.get(viewPath);
|
|
7426
|
+
if (sortedKeys && sortedKeys.length > 0) {
|
|
7427
|
+
return sortedKeys
|
|
7428
|
+
.map(k => this.inner.get(viewPath, k))
|
|
7429
|
+
.filter((v) => v !== null);
|
|
7430
|
+
}
|
|
7431
|
+
return this.inner.getAll(viewPath);
|
|
7432
|
+
}
|
|
7433
|
+
getAllSync(viewPath) {
|
|
7434
|
+
const sortedKeys = this.sortedKeysMap.get(viewPath);
|
|
7435
|
+
if (sortedKeys && sortedKeys.length > 0) {
|
|
7436
|
+
return sortedKeys
|
|
7437
|
+
.map(k => this.inner.getSync(viewPath, k))
|
|
7438
|
+
.filter((v) => v !== null && v !== undefined);
|
|
7439
|
+
}
|
|
7440
|
+
return this.inner.getAllSync(viewPath);
|
|
7441
|
+
}
|
|
7442
|
+
getSync(viewPath, key) {
|
|
7443
|
+
return this.inner.getSync(viewPath, key);
|
|
7444
|
+
}
|
|
7445
|
+
has(viewPath, key) {
|
|
7446
|
+
return this.inner.has(viewPath, key);
|
|
7447
|
+
}
|
|
7448
|
+
keys(viewPath) {
|
|
7449
|
+
const sortedKeys = this.sortedKeysMap.get(viewPath);
|
|
7450
|
+
if (sortedKeys)
|
|
7451
|
+
return [...sortedKeys];
|
|
7452
|
+
return this.inner.keys(viewPath);
|
|
7453
|
+
}
|
|
7454
|
+
size(viewPath) {
|
|
7455
|
+
return this.inner.size(viewPath);
|
|
7456
|
+
}
|
|
7457
|
+
set(viewPath, key, data) {
|
|
7458
|
+
this.inner.set(viewPath, key, data);
|
|
7459
|
+
const sortConfig = this.sortConfigs.get(viewPath);
|
|
7460
|
+
if (sortConfig) {
|
|
7461
|
+
this.updateSortedPosition(viewPath, key, data, sortConfig);
|
|
7462
|
+
}
|
|
7463
|
+
}
|
|
7464
|
+
delete(viewPath, key) {
|
|
7465
|
+
const sortedKeys = this.sortedKeysMap.get(viewPath);
|
|
7466
|
+
if (sortedKeys) {
|
|
7467
|
+
const idx = sortedKeys.indexOf(key);
|
|
7468
|
+
if (idx !== -1) {
|
|
7469
|
+
sortedKeys.splice(idx, 1);
|
|
7470
|
+
}
|
|
7471
|
+
}
|
|
7472
|
+
this.inner.delete(viewPath, key);
|
|
7473
|
+
}
|
|
7474
|
+
clear(viewPath) {
|
|
7475
|
+
if (viewPath) {
|
|
7476
|
+
this.sortedKeysMap.delete(viewPath);
|
|
7477
|
+
this.sortConfigs.delete(viewPath);
|
|
7478
|
+
}
|
|
7479
|
+
else {
|
|
7480
|
+
this.sortedKeysMap.clear();
|
|
7481
|
+
this.sortConfigs.clear();
|
|
7482
|
+
}
|
|
7483
|
+
this.inner.clear(viewPath);
|
|
7484
|
+
}
|
|
7485
|
+
evictOldest(viewPath) {
|
|
7486
|
+
const sortedKeys = this.sortedKeysMap.get(viewPath);
|
|
7487
|
+
if (sortedKeys && sortedKeys.length > 0) {
|
|
7488
|
+
const oldest = sortedKeys.pop();
|
|
7489
|
+
this.inner.delete(viewPath, oldest);
|
|
7490
|
+
return oldest;
|
|
7491
|
+
}
|
|
7492
|
+
return this.inner.evictOldest?.(viewPath);
|
|
7493
|
+
}
|
|
7494
|
+
setViewConfig(viewPath, config) {
|
|
7495
|
+
if (config.sort && !this.sortConfigs.has(viewPath)) {
|
|
7496
|
+
this.sortConfigs.set(viewPath, config.sort);
|
|
7497
|
+
this.rebuildSortedKeys(viewPath, config.sort);
|
|
7498
|
+
}
|
|
7499
|
+
this.inner.setViewConfig?.(viewPath, config);
|
|
7500
|
+
}
|
|
7501
|
+
getViewConfig(viewPath) {
|
|
7502
|
+
const sortConfig = this.sortConfigs.get(viewPath);
|
|
7503
|
+
if (sortConfig)
|
|
7504
|
+
return { sort: sortConfig };
|
|
7505
|
+
return this.inner.getViewConfig?.(viewPath);
|
|
7506
|
+
}
|
|
7507
|
+
onUpdate(callback) {
|
|
7508
|
+
return this.inner.onUpdate(callback);
|
|
7509
|
+
}
|
|
7510
|
+
onRichUpdate(callback) {
|
|
7511
|
+
return this.inner.onRichUpdate(callback);
|
|
7512
|
+
}
|
|
7513
|
+
notifyUpdate(viewPath, key, update) {
|
|
7514
|
+
this.inner.notifyUpdate(viewPath, key, update);
|
|
7515
|
+
}
|
|
7516
|
+
notifyRichUpdate(viewPath, key, update) {
|
|
7517
|
+
this.inner.notifyRichUpdate(viewPath, key, update);
|
|
7518
|
+
}
|
|
7519
|
+
updateSortedPosition(viewPath, key, data, sortConfig) {
|
|
7520
|
+
let sortedKeys = this.sortedKeysMap.get(viewPath);
|
|
7521
|
+
if (!sortedKeys) {
|
|
7522
|
+
sortedKeys = [];
|
|
7523
|
+
this.sortedKeysMap.set(viewPath, sortedKeys);
|
|
7524
|
+
}
|
|
7525
|
+
const existingIdx = sortedKeys.indexOf(key);
|
|
7526
|
+
if (existingIdx !== -1) {
|
|
7527
|
+
sortedKeys.splice(existingIdx, 1);
|
|
7528
|
+
}
|
|
7529
|
+
const insertIdx = this.binarySearchInsertPosition(viewPath, sortedKeys, sortConfig, key, data);
|
|
7530
|
+
sortedKeys.splice(insertIdx, 0, key);
|
|
7531
|
+
}
|
|
7532
|
+
binarySearchInsertPosition(viewPath, sortedKeys, sortConfig, newKey, newValue) {
|
|
7533
|
+
const newSortValue = getNestedValue$1(newValue, sortConfig.field);
|
|
7534
|
+
const isDesc = sortConfig.order === 'desc';
|
|
7535
|
+
let low = 0;
|
|
7536
|
+
let high = sortedKeys.length;
|
|
7537
|
+
while (low < high) {
|
|
7538
|
+
const mid = Math.floor((low + high) / 2);
|
|
7539
|
+
const midKey = sortedKeys[mid];
|
|
7540
|
+
const midEntity = this.inner.get(viewPath, midKey);
|
|
7541
|
+
const midValue = getNestedValue$1(midEntity, sortConfig.field);
|
|
7542
|
+
let cmp = compareSortValues$1(newSortValue, midValue);
|
|
7543
|
+
if (isDesc)
|
|
7544
|
+
cmp = -cmp;
|
|
7545
|
+
if (cmp === 0) {
|
|
7546
|
+
cmp = newKey.localeCompare(midKey);
|
|
7547
|
+
}
|
|
7548
|
+
if (cmp < 0) {
|
|
7549
|
+
high = mid;
|
|
7550
|
+
}
|
|
7551
|
+
else {
|
|
7552
|
+
low = mid + 1;
|
|
7553
|
+
}
|
|
7554
|
+
}
|
|
7555
|
+
return low;
|
|
7556
|
+
}
|
|
7557
|
+
rebuildSortedKeys(viewPath, sortConfig) {
|
|
7558
|
+
const allKeys = this.inner.keys(viewPath);
|
|
7559
|
+
if (allKeys.length === 0)
|
|
7560
|
+
return;
|
|
7561
|
+
const isDesc = sortConfig.order === 'desc';
|
|
7562
|
+
const entries = allKeys.map(k => [k, this.inner.get(viewPath, k)]);
|
|
7563
|
+
entries.sort((a, b) => {
|
|
7564
|
+
const aValue = getNestedValue$1(a[1], sortConfig.field);
|
|
7565
|
+
const bValue = getNestedValue$1(b[1], sortConfig.field);
|
|
7566
|
+
let cmp = compareSortValues$1(aValue, bValue);
|
|
7567
|
+
if (isDesc)
|
|
7568
|
+
cmp = -cmp;
|
|
7569
|
+
if (cmp === 0) {
|
|
7570
|
+
cmp = a[0].localeCompare(b[0]);
|
|
7571
|
+
}
|
|
7572
|
+
return cmp;
|
|
7573
|
+
});
|
|
7574
|
+
this.sortedKeysMap.set(viewPath, entries.map(([k]) => k));
|
|
7575
|
+
}
|
|
7576
|
+
}
|
|
7577
|
+
|
|
7386
7578
|
class SubscriptionRegistry {
|
|
7387
7579
|
constructor(connection) {
|
|
7388
7580
|
this.subscriptions = new Map();
|
|
@@ -8175,9 +8367,10 @@ function createInstructionExecutor(wallet) {
|
|
|
8175
8367
|
class HyperStack {
|
|
8176
8368
|
constructor(url, options) {
|
|
8177
8369
|
this.stack = options.stack;
|
|
8178
|
-
this.storage = options.storage ?? new MemoryAdapter();
|
|
8370
|
+
this.storage = new SortedStorageDecorator(options.storage ?? new MemoryAdapter());
|
|
8179
8371
|
this.processor = new FrameProcessor(this.storage, {
|
|
8180
8372
|
maxEntriesPerView: options.maxEntriesPerView,
|
|
8373
|
+
flushIntervalMs: options.flushIntervalMs,
|
|
8181
8374
|
});
|
|
8182
8375
|
this.connection = new ConnectionManager({
|
|
8183
8376
|
websocketUrl: url,
|
|
@@ -8211,6 +8404,7 @@ class HyperStack {
|
|
|
8211
8404
|
stack,
|
|
8212
8405
|
storage: options?.storage,
|
|
8213
8406
|
maxEntriesPerView: options?.maxEntriesPerView,
|
|
8407
|
+
flushIntervalMs: options?.flushIntervalMs,
|
|
8214
8408
|
autoReconnect: options?.autoReconnect,
|
|
8215
8409
|
reconnectIntervals: options?.reconnectIntervals,
|
|
8216
8410
|
maxReconnectAttempts: options?.maxReconnectAttempts,
|
|
@@ -8266,67 +8460,212 @@ class HyperStack {
|
|
|
8266
8460
|
}
|
|
8267
8461
|
}
|
|
8268
8462
|
|
|
8269
|
-
const
|
|
8270
|
-
|
|
8271
|
-
|
|
8272
|
-
|
|
8273
|
-
|
|
8274
|
-
|
|
8275
|
-
|
|
8463
|
+
const DEFAULT_FLUSH_INTERVAL_MS = 16;
|
|
8464
|
+
|
|
8465
|
+
class ZustandAdapter {
|
|
8466
|
+
constructor(_config = {}) {
|
|
8467
|
+
this.updateCallbacks = new Set();
|
|
8468
|
+
this.richUpdateCallbacks = new Set();
|
|
8469
|
+
this.accessOrder = new Map();
|
|
8470
|
+
this.store = create((set) => ({
|
|
8471
|
+
entities: new Map(),
|
|
8472
|
+
viewConfigs: new Map(),
|
|
8473
|
+
connectionState: 'disconnected',
|
|
8474
|
+
lastError: undefined,
|
|
8475
|
+
_set: (viewPath, key, data) => {
|
|
8476
|
+
set((state) => {
|
|
8477
|
+
const newEntities = new Map(state.entities);
|
|
8478
|
+
const viewMap = new Map(newEntities.get(viewPath) ?? new Map());
|
|
8479
|
+
viewMap.set(key, data);
|
|
8480
|
+
newEntities.set(viewPath, viewMap);
|
|
8481
|
+
return { entities: newEntities };
|
|
8482
|
+
});
|
|
8483
|
+
},
|
|
8484
|
+
_delete: (viewPath, key) => {
|
|
8485
|
+
set((state) => {
|
|
8486
|
+
const newEntities = new Map(state.entities);
|
|
8487
|
+
const viewMap = newEntities.get(viewPath);
|
|
8488
|
+
if (viewMap) {
|
|
8489
|
+
const newViewMap = new Map(viewMap);
|
|
8490
|
+
newViewMap.delete(key);
|
|
8491
|
+
newEntities.set(viewPath, newViewMap);
|
|
8492
|
+
}
|
|
8493
|
+
return { entities: newEntities };
|
|
8494
|
+
});
|
|
8495
|
+
},
|
|
8496
|
+
_clear: (viewPath) => {
|
|
8497
|
+
set((state) => {
|
|
8498
|
+
if (viewPath) {
|
|
8499
|
+
const newEntities = new Map(state.entities);
|
|
8500
|
+
newEntities.delete(viewPath);
|
|
8501
|
+
return { entities: newEntities };
|
|
8502
|
+
}
|
|
8503
|
+
return { entities: new Map() };
|
|
8504
|
+
});
|
|
8505
|
+
},
|
|
8506
|
+
_setConnectionState: (connectionState, lastError) => {
|
|
8507
|
+
set({ connectionState, lastError });
|
|
8508
|
+
},
|
|
8509
|
+
_setViewConfig: (viewPath, config) => {
|
|
8510
|
+
set((state) => {
|
|
8511
|
+
const newConfigs = new Map(state.viewConfigs);
|
|
8512
|
+
newConfigs.set(viewPath, config);
|
|
8513
|
+
return { viewConfigs: newConfigs };
|
|
8514
|
+
});
|
|
8515
|
+
},
|
|
8516
|
+
}));
|
|
8276
8517
|
}
|
|
8277
|
-
|
|
8278
|
-
|
|
8518
|
+
get(viewPath, key) {
|
|
8519
|
+
const viewMap = this.store.getState().entities.get(viewPath);
|
|
8520
|
+
if (!viewMap)
|
|
8521
|
+
return null;
|
|
8522
|
+
const value = viewMap.get(key);
|
|
8523
|
+
return value !== undefined ? value : null;
|
|
8279
8524
|
}
|
|
8280
|
-
|
|
8281
|
-
|
|
8282
|
-
|
|
8283
|
-
|
|
8284
|
-
|
|
8525
|
+
getAll(viewPath) {
|
|
8526
|
+
const viewMap = this.store.getState().entities.get(viewPath);
|
|
8527
|
+
if (!viewMap)
|
|
8528
|
+
return [];
|
|
8529
|
+
return Array.from(viewMap.values());
|
|
8285
8530
|
}
|
|
8286
|
-
|
|
8287
|
-
|
|
8288
|
-
|
|
8289
|
-
|
|
8290
|
-
|
|
8531
|
+
getAllSync(viewPath) {
|
|
8532
|
+
const viewMap = this.store.getState().entities.get(viewPath);
|
|
8533
|
+
if (!viewMap)
|
|
8534
|
+
return undefined;
|
|
8535
|
+
return Array.from(viewMap.values());
|
|
8291
8536
|
}
|
|
8292
|
-
|
|
8293
|
-
|
|
8294
|
-
|
|
8295
|
-
|
|
8296
|
-
|
|
8537
|
+
getSync(viewPath, key) {
|
|
8538
|
+
const viewMap = this.store.getState().entities.get(viewPath);
|
|
8539
|
+
if (!viewMap)
|
|
8540
|
+
return undefined;
|
|
8541
|
+
const value = viewMap.get(key);
|
|
8542
|
+
return value !== undefined ? value : null;
|
|
8543
|
+
}
|
|
8544
|
+
has(viewPath, key) {
|
|
8545
|
+
return this.store.getState().entities.get(viewPath)?.has(key) ?? false;
|
|
8546
|
+
}
|
|
8547
|
+
keys(viewPath) {
|
|
8548
|
+
const viewMap = this.store.getState().entities.get(viewPath);
|
|
8549
|
+
if (!viewMap)
|
|
8550
|
+
return [];
|
|
8551
|
+
return Array.from(viewMap.keys());
|
|
8552
|
+
}
|
|
8553
|
+
size(viewPath) {
|
|
8554
|
+
return this.store.getState().entities.get(viewPath)?.size ?? 0;
|
|
8555
|
+
}
|
|
8556
|
+
set(viewPath, key, data) {
|
|
8557
|
+
let order = this.accessOrder.get(viewPath);
|
|
8558
|
+
if (!order) {
|
|
8559
|
+
order = [];
|
|
8560
|
+
this.accessOrder.set(viewPath, order);
|
|
8561
|
+
}
|
|
8562
|
+
const existingIdx = order.indexOf(key);
|
|
8563
|
+
if (existingIdx !== -1) {
|
|
8564
|
+
order.splice(existingIdx, 1);
|
|
8565
|
+
}
|
|
8566
|
+
order.push(key);
|
|
8567
|
+
this.store.getState()._set(viewPath, key, data);
|
|
8568
|
+
}
|
|
8569
|
+
delete(viewPath, key) {
|
|
8570
|
+
const order = this.accessOrder.get(viewPath);
|
|
8571
|
+
if (order) {
|
|
8572
|
+
const idx = order.indexOf(key);
|
|
8573
|
+
if (idx !== -1) {
|
|
8574
|
+
order.splice(idx, 1);
|
|
8575
|
+
}
|
|
8576
|
+
}
|
|
8577
|
+
this.store.getState()._delete(viewPath, key);
|
|
8578
|
+
}
|
|
8579
|
+
clear(viewPath) {
|
|
8580
|
+
if (viewPath) {
|
|
8581
|
+
this.accessOrder.delete(viewPath);
|
|
8582
|
+
}
|
|
8583
|
+
else {
|
|
8584
|
+
this.accessOrder.clear();
|
|
8585
|
+
}
|
|
8586
|
+
this.store.getState()._clear(viewPath);
|
|
8587
|
+
}
|
|
8588
|
+
evictOldest(viewPath) {
|
|
8589
|
+
const order = this.accessOrder.get(viewPath);
|
|
8590
|
+
if (!order || order.length === 0)
|
|
8591
|
+
return undefined;
|
|
8592
|
+
const oldest = order.shift();
|
|
8593
|
+
if (oldest !== undefined) {
|
|
8594
|
+
this.store.getState()._delete(viewPath, oldest);
|
|
8595
|
+
}
|
|
8596
|
+
return oldest;
|
|
8597
|
+
}
|
|
8598
|
+
onUpdate(callback) {
|
|
8599
|
+
this.updateCallbacks.add(callback);
|
|
8600
|
+
return () => this.updateCallbacks.delete(callback);
|
|
8601
|
+
}
|
|
8602
|
+
onRichUpdate(callback) {
|
|
8603
|
+
this.richUpdateCallbacks.add(callback);
|
|
8604
|
+
return () => this.richUpdateCallbacks.delete(callback);
|
|
8605
|
+
}
|
|
8606
|
+
notifyUpdate(viewPath, key, update) {
|
|
8607
|
+
for (const callback of this.updateCallbacks) {
|
|
8608
|
+
callback(viewPath, key, update);
|
|
8609
|
+
}
|
|
8610
|
+
}
|
|
8611
|
+
notifyRichUpdate(viewPath, key, update) {
|
|
8612
|
+
for (const callback of this.richUpdateCallbacks) {
|
|
8613
|
+
callback(viewPath, key, update);
|
|
8614
|
+
}
|
|
8615
|
+
}
|
|
8616
|
+
setConnectionState(state, error) {
|
|
8617
|
+
this.store.getState()._setConnectionState(state, error);
|
|
8618
|
+
}
|
|
8619
|
+
setViewConfig(viewPath, config) {
|
|
8620
|
+
const state = this.store.getState();
|
|
8621
|
+
const existingConfig = state.viewConfigs.get(viewPath);
|
|
8622
|
+
if (existingConfig)
|
|
8623
|
+
return;
|
|
8624
|
+
state._setViewConfig(viewPath, config);
|
|
8625
|
+
}
|
|
8626
|
+
getViewConfig(viewPath) {
|
|
8627
|
+
return this.store.getState().viewConfigs.get(viewPath);
|
|
8297
8628
|
}
|
|
8298
|
-
throw new Error('Must provide either network or websocketUrl');
|
|
8299
8629
|
}
|
|
8630
|
+
|
|
8631
|
+
const HyperstackContext = createContext(null);
|
|
8300
8632
|
function HyperstackProvider({ children, fallback = null, ...config }) {
|
|
8301
|
-
const networkConfig = resolveNetworkConfig(config.network, config.websocketUrl);
|
|
8302
8633
|
const clientsRef = useRef(new Map());
|
|
8303
8634
|
const connectingRef = useRef(new Map());
|
|
8304
|
-
const getOrCreateClient = useCallback(async (stack) => {
|
|
8305
|
-
const
|
|
8635
|
+
const getOrCreateClient = useCallback(async (stack, urlOverride) => {
|
|
8636
|
+
const cacheKey = urlOverride ? `${stack.name}:${urlOverride}` : stack.name;
|
|
8637
|
+
const existing = clientsRef.current.get(cacheKey);
|
|
8306
8638
|
if (existing) {
|
|
8307
8639
|
return existing.client;
|
|
8308
8640
|
}
|
|
8309
|
-
const connecting = connectingRef.current.get(
|
|
8641
|
+
const connecting = connectingRef.current.get(cacheKey);
|
|
8310
8642
|
if (connecting) {
|
|
8311
8643
|
return connecting;
|
|
8312
8644
|
}
|
|
8645
|
+
const adapter = new ZustandAdapter();
|
|
8313
8646
|
const connectionPromise = HyperStack.connect(stack, {
|
|
8314
|
-
url:
|
|
8647
|
+
url: urlOverride,
|
|
8648
|
+
storage: adapter,
|
|
8315
8649
|
autoReconnect: config.autoConnect,
|
|
8316
8650
|
reconnectIntervals: config.reconnectIntervals,
|
|
8317
8651
|
maxReconnectAttempts: config.maxReconnectAttempts,
|
|
8318
8652
|
maxEntriesPerView: config.maxEntriesPerView,
|
|
8653
|
+
flushIntervalMs: config.flushIntervalMs ?? DEFAULT_FLUSH_INTERVAL_MS,
|
|
8319
8654
|
}).then((client) => {
|
|
8320
|
-
|
|
8655
|
+
client.onConnectionStateChange((state, error) => {
|
|
8656
|
+
adapter.setConnectionState(state, error);
|
|
8657
|
+
});
|
|
8658
|
+
adapter.setConnectionState(client.connectionState);
|
|
8659
|
+
clientsRef.current.set(cacheKey, {
|
|
8321
8660
|
client,
|
|
8322
8661
|
disconnect: () => client.disconnect()
|
|
8323
8662
|
});
|
|
8324
|
-
connectingRef.current.delete(
|
|
8663
|
+
connectingRef.current.delete(cacheKey);
|
|
8325
8664
|
return client;
|
|
8326
8665
|
});
|
|
8327
|
-
connectingRef.current.set(
|
|
8666
|
+
connectingRef.current.set(cacheKey, connectionPromise);
|
|
8328
8667
|
return connectionPromise;
|
|
8329
|
-
}, [
|
|
8668
|
+
}, [config.autoConnect, config.reconnectIntervals, config.maxReconnectAttempts, config.maxEntriesPerView]);
|
|
8330
8669
|
const getClient = useCallback((stack) => {
|
|
8331
8670
|
if (!stack)
|
|
8332
8671
|
return null;
|
|
@@ -8345,13 +8684,7 @@ function HyperstackProvider({ children, fallback = null, ...config }) {
|
|
|
8345
8684
|
const value = {
|
|
8346
8685
|
getOrCreateClient,
|
|
8347
8686
|
getClient,
|
|
8348
|
-
config
|
|
8349
|
-
websocketUrl: networkConfig.websocketUrl,
|
|
8350
|
-
autoConnect: config.autoConnect,
|
|
8351
|
-
reconnectIntervals: config.reconnectIntervals,
|
|
8352
|
-
maxReconnectAttempts: config.maxReconnectAttempts,
|
|
8353
|
-
maxEntriesPerView: config.maxEntriesPerView,
|
|
8354
|
-
}
|
|
8687
|
+
config,
|
|
8355
8688
|
};
|
|
8356
8689
|
return (React.createElement(HyperstackContext.Provider, { value: value }, children));
|
|
8357
8690
|
}
|
|
@@ -8699,21 +9032,22 @@ function useInstructionMutation(execute) {
|
|
|
8699
9032
|
};
|
|
8700
9033
|
}
|
|
8701
9034
|
|
|
8702
|
-
function useHyperstack(stack) {
|
|
9035
|
+
function useHyperstack(stack, options) {
|
|
8703
9036
|
const { getOrCreateClient, getClient } = useHyperstackContext();
|
|
9037
|
+
const urlOverride = options?.url;
|
|
8704
9038
|
const [client, setClient] = useState(getClient(stack));
|
|
8705
9039
|
const [isLoading, setIsLoading] = useState(!client);
|
|
8706
9040
|
const [error, setError] = useState(null);
|
|
8707
9041
|
useEffect(() => {
|
|
8708
9042
|
const existingClient = getClient(stack);
|
|
8709
|
-
if (existingClient) {
|
|
9043
|
+
if (existingClient && !urlOverride) {
|
|
8710
9044
|
setClient(existingClient);
|
|
8711
9045
|
setIsLoading(false);
|
|
8712
9046
|
return;
|
|
8713
9047
|
}
|
|
8714
9048
|
setIsLoading(true);
|
|
8715
9049
|
setError(null);
|
|
8716
|
-
getOrCreateClient(stack)
|
|
9050
|
+
getOrCreateClient(stack, urlOverride)
|
|
8717
9051
|
.then((newClient) => {
|
|
8718
9052
|
setClient(newClient);
|
|
8719
9053
|
setIsLoading(false);
|
|
@@ -8722,7 +9056,7 @@ function useHyperstack(stack) {
|
|
|
8722
9056
|
setError(err instanceof Error ? err : new Error(String(err)));
|
|
8723
9057
|
setIsLoading(false);
|
|
8724
9058
|
});
|
|
8725
|
-
}, [stack, getOrCreateClient, getClient]);
|
|
9059
|
+
}, [stack, getOrCreateClient, getClient, urlOverride]);
|
|
8726
9060
|
const views = useMemo(() => {
|
|
8727
9061
|
const result = {};
|
|
8728
9062
|
for (const [viewName, viewGroup] of Object.entries(stack.views)) {
|
|
@@ -8757,307 +9091,12 @@ function useHyperstack(stack) {
|
|
|
8757
9091
|
return {
|
|
8758
9092
|
views: views,
|
|
8759
9093
|
instructions: instructions,
|
|
8760
|
-
zustandStore: client?.store,
|
|
9094
|
+
zustandStore: client?.store?.store,
|
|
8761
9095
|
client: client,
|
|
8762
9096
|
isLoading,
|
|
8763
9097
|
error
|
|
8764
9098
|
};
|
|
8765
9099
|
}
|
|
8766
9100
|
|
|
8767
|
-
function getNestedValue(obj, path) {
|
|
8768
|
-
let current = obj;
|
|
8769
|
-
for (const segment of path) {
|
|
8770
|
-
if (current === null || current === undefined)
|
|
8771
|
-
return undefined;
|
|
8772
|
-
if (typeof current !== 'object')
|
|
8773
|
-
return undefined;
|
|
8774
|
-
current = current[segment];
|
|
8775
|
-
}
|
|
8776
|
-
return current;
|
|
8777
|
-
}
|
|
8778
|
-
function compareSortValues(a, b) {
|
|
8779
|
-
if (a === b)
|
|
8780
|
-
return 0;
|
|
8781
|
-
if (a === undefined || a === null)
|
|
8782
|
-
return -1;
|
|
8783
|
-
if (b === undefined || b === null)
|
|
8784
|
-
return 1;
|
|
8785
|
-
if (typeof a === 'number' && typeof b === 'number') {
|
|
8786
|
-
return a - b;
|
|
8787
|
-
}
|
|
8788
|
-
if (typeof a === 'string' && typeof b === 'string') {
|
|
8789
|
-
return a.localeCompare(b);
|
|
8790
|
-
}
|
|
8791
|
-
if (typeof a === 'boolean' && typeof b === 'boolean') {
|
|
8792
|
-
return (a ? 1 : 0) - (b ? 1 : 0);
|
|
8793
|
-
}
|
|
8794
|
-
return String(a).localeCompare(String(b));
|
|
8795
|
-
}
|
|
8796
|
-
function binarySearchInsertPosition(sortedKeys, entities, sortConfig, newKey, newValue) {
|
|
8797
|
-
const newSortValue = getNestedValue(newValue, sortConfig.field);
|
|
8798
|
-
const isDesc = sortConfig.order === 'desc';
|
|
8799
|
-
let low = 0;
|
|
8800
|
-
let high = sortedKeys.length;
|
|
8801
|
-
while (low < high) {
|
|
8802
|
-
const mid = Math.floor((low + high) / 2);
|
|
8803
|
-
const midKey = sortedKeys[mid];
|
|
8804
|
-
const midEntity = entities.get(midKey);
|
|
8805
|
-
const midValue = getNestedValue(midEntity, sortConfig.field);
|
|
8806
|
-
let cmp = compareSortValues(newSortValue, midValue);
|
|
8807
|
-
if (isDesc)
|
|
8808
|
-
cmp = -cmp;
|
|
8809
|
-
if (cmp === 0) {
|
|
8810
|
-
cmp = newKey.localeCompare(midKey);
|
|
8811
|
-
}
|
|
8812
|
-
if (cmp < 0) {
|
|
8813
|
-
high = mid;
|
|
8814
|
-
}
|
|
8815
|
-
else {
|
|
8816
|
-
low = mid + 1;
|
|
8817
|
-
}
|
|
8818
|
-
}
|
|
8819
|
-
return low;
|
|
8820
|
-
}
|
|
8821
|
-
class ZustandAdapter {
|
|
8822
|
-
constructor(_config = {}) {
|
|
8823
|
-
this.updateCallbacks = new Set();
|
|
8824
|
-
this.richUpdateCallbacks = new Set();
|
|
8825
|
-
this.accessOrder = new Map();
|
|
8826
|
-
this.store = create((set) => ({
|
|
8827
|
-
entities: new Map(),
|
|
8828
|
-
sortedKeys: new Map(),
|
|
8829
|
-
viewConfigs: new Map(),
|
|
8830
|
-
connectionState: 'disconnected',
|
|
8831
|
-
lastError: undefined,
|
|
8832
|
-
_set: (viewPath, key, data) => {
|
|
8833
|
-
set((state) => {
|
|
8834
|
-
const newEntities = new Map(state.entities);
|
|
8835
|
-
const viewMap = new Map(newEntities.get(viewPath) ?? new Map());
|
|
8836
|
-
viewMap.set(key, data);
|
|
8837
|
-
newEntities.set(viewPath, viewMap);
|
|
8838
|
-
return { entities: newEntities };
|
|
8839
|
-
});
|
|
8840
|
-
},
|
|
8841
|
-
_delete: (viewPath, key) => {
|
|
8842
|
-
set((state) => {
|
|
8843
|
-
const newEntities = new Map(state.entities);
|
|
8844
|
-
const viewMap = newEntities.get(viewPath);
|
|
8845
|
-
if (viewMap) {
|
|
8846
|
-
const newViewMap = new Map(viewMap);
|
|
8847
|
-
newViewMap.delete(key);
|
|
8848
|
-
newEntities.set(viewPath, newViewMap);
|
|
8849
|
-
}
|
|
8850
|
-
return { entities: newEntities };
|
|
8851
|
-
});
|
|
8852
|
-
},
|
|
8853
|
-
_clear: (viewPath) => {
|
|
8854
|
-
set((state) => {
|
|
8855
|
-
if (viewPath) {
|
|
8856
|
-
const newEntities = new Map(state.entities);
|
|
8857
|
-
newEntities.delete(viewPath);
|
|
8858
|
-
const newSortedKeys = new Map(state.sortedKeys);
|
|
8859
|
-
newSortedKeys.delete(viewPath);
|
|
8860
|
-
return { entities: newEntities, sortedKeys: newSortedKeys };
|
|
8861
|
-
}
|
|
8862
|
-
return { entities: new Map(), sortedKeys: new Map() };
|
|
8863
|
-
});
|
|
8864
|
-
},
|
|
8865
|
-
_setConnectionState: (connectionState, lastError) => {
|
|
8866
|
-
set({ connectionState, lastError });
|
|
8867
|
-
},
|
|
8868
|
-
_setViewConfig: (viewPath, config) => {
|
|
8869
|
-
set((state) => {
|
|
8870
|
-
const newConfigs = new Map(state.viewConfigs);
|
|
8871
|
-
newConfigs.set(viewPath, config);
|
|
8872
|
-
return { viewConfigs: newConfigs };
|
|
8873
|
-
});
|
|
8874
|
-
},
|
|
8875
|
-
_updateSortedKeys: (viewPath, newSortedKeys) => {
|
|
8876
|
-
set((state) => {
|
|
8877
|
-
const newSortedKeysMap = new Map(state.sortedKeys);
|
|
8878
|
-
newSortedKeysMap.set(viewPath, newSortedKeys);
|
|
8879
|
-
return { sortedKeys: newSortedKeysMap };
|
|
8880
|
-
});
|
|
8881
|
-
},
|
|
8882
|
-
}));
|
|
8883
|
-
}
|
|
8884
|
-
get(viewPath, key) {
|
|
8885
|
-
const entities = this.store.getState().entities;
|
|
8886
|
-
const viewMap = entities.get(viewPath);
|
|
8887
|
-
if (!viewMap)
|
|
8888
|
-
return null;
|
|
8889
|
-
const value = viewMap.get(key);
|
|
8890
|
-
return value !== undefined ? value : null;
|
|
8891
|
-
}
|
|
8892
|
-
getAll(viewPath) {
|
|
8893
|
-
const state = this.store.getState();
|
|
8894
|
-
const viewMap = state.entities.get(viewPath);
|
|
8895
|
-
if (!viewMap)
|
|
8896
|
-
return [];
|
|
8897
|
-
const sortedKeys = state.sortedKeys.get(viewPath);
|
|
8898
|
-
if (sortedKeys && sortedKeys.length > 0) {
|
|
8899
|
-
return sortedKeys.map(k => viewMap.get(k)).filter(v => v !== undefined);
|
|
8900
|
-
}
|
|
8901
|
-
return Array.from(viewMap.values());
|
|
8902
|
-
}
|
|
8903
|
-
getAllSync(viewPath) {
|
|
8904
|
-
const state = this.store.getState();
|
|
8905
|
-
const viewMap = state.entities.get(viewPath);
|
|
8906
|
-
if (!viewMap)
|
|
8907
|
-
return undefined;
|
|
8908
|
-
const sortedKeys = state.sortedKeys.get(viewPath);
|
|
8909
|
-
if (sortedKeys && sortedKeys.length > 0) {
|
|
8910
|
-
return sortedKeys.map(k => viewMap.get(k)).filter(v => v !== undefined);
|
|
8911
|
-
}
|
|
8912
|
-
return Array.from(viewMap.values());
|
|
8913
|
-
}
|
|
8914
|
-
getSync(viewPath, key) {
|
|
8915
|
-
const entities = this.store.getState().entities;
|
|
8916
|
-
const viewMap = entities.get(viewPath);
|
|
8917
|
-
if (!viewMap)
|
|
8918
|
-
return undefined;
|
|
8919
|
-
const value = viewMap.get(key);
|
|
8920
|
-
return value !== undefined ? value : null;
|
|
8921
|
-
}
|
|
8922
|
-
has(viewPath, key) {
|
|
8923
|
-
return this.store.getState().entities.get(viewPath)?.has(key) ?? false;
|
|
8924
|
-
}
|
|
8925
|
-
keys(viewPath) {
|
|
8926
|
-
const viewMap = this.store.getState().entities.get(viewPath);
|
|
8927
|
-
if (!viewMap)
|
|
8928
|
-
return [];
|
|
8929
|
-
return Array.from(viewMap.keys());
|
|
8930
|
-
}
|
|
8931
|
-
size(viewPath) {
|
|
8932
|
-
return this.store.getState().entities.get(viewPath)?.size ?? 0;
|
|
8933
|
-
}
|
|
8934
|
-
set(viewPath, key, data) {
|
|
8935
|
-
const state = this.store.getState();
|
|
8936
|
-
const viewConfig = state.viewConfigs.get(viewPath);
|
|
8937
|
-
if (viewConfig?.sort) {
|
|
8938
|
-
const viewMap = state.entities.get(viewPath) ?? new Map();
|
|
8939
|
-
const currentSortedKeys = [...(state.sortedKeys.get(viewPath) ?? [])];
|
|
8940
|
-
const existingIdx = currentSortedKeys.indexOf(key);
|
|
8941
|
-
if (existingIdx !== -1) {
|
|
8942
|
-
currentSortedKeys.splice(existingIdx, 1);
|
|
8943
|
-
}
|
|
8944
|
-
const tempMap = new Map(viewMap);
|
|
8945
|
-
tempMap.set(key, data);
|
|
8946
|
-
const insertIdx = binarySearchInsertPosition(currentSortedKeys, tempMap, viewConfig.sort, key, data);
|
|
8947
|
-
currentSortedKeys.splice(insertIdx, 0, key);
|
|
8948
|
-
state._set(viewPath, key, data);
|
|
8949
|
-
state._updateSortedKeys(viewPath, currentSortedKeys);
|
|
8950
|
-
}
|
|
8951
|
-
else {
|
|
8952
|
-
let order = this.accessOrder.get(viewPath);
|
|
8953
|
-
if (!order) {
|
|
8954
|
-
order = [];
|
|
8955
|
-
this.accessOrder.set(viewPath, order);
|
|
8956
|
-
}
|
|
8957
|
-
const existingIdx = order.indexOf(key);
|
|
8958
|
-
if (existingIdx !== -1) {
|
|
8959
|
-
order.splice(existingIdx, 1);
|
|
8960
|
-
}
|
|
8961
|
-
order.push(key);
|
|
8962
|
-
state._set(viewPath, key, data);
|
|
8963
|
-
}
|
|
8964
|
-
}
|
|
8965
|
-
delete(viewPath, key) {
|
|
8966
|
-
const state = this.store.getState();
|
|
8967
|
-
const viewConfig = state.viewConfigs.get(viewPath);
|
|
8968
|
-
if (viewConfig?.sort) {
|
|
8969
|
-
const currentSortedKeys = state.sortedKeys.get(viewPath);
|
|
8970
|
-
if (currentSortedKeys) {
|
|
8971
|
-
const newSortedKeys = currentSortedKeys.filter(k => k !== key);
|
|
8972
|
-
state._updateSortedKeys(viewPath, newSortedKeys);
|
|
8973
|
-
}
|
|
8974
|
-
}
|
|
8975
|
-
else {
|
|
8976
|
-
const order = this.accessOrder.get(viewPath);
|
|
8977
|
-
if (order) {
|
|
8978
|
-
const idx = order.indexOf(key);
|
|
8979
|
-
if (idx !== -1) {
|
|
8980
|
-
order.splice(idx, 1);
|
|
8981
|
-
}
|
|
8982
|
-
}
|
|
8983
|
-
}
|
|
8984
|
-
state._delete(viewPath, key);
|
|
8985
|
-
}
|
|
8986
|
-
clear(viewPath) {
|
|
8987
|
-
if (viewPath) {
|
|
8988
|
-
this.accessOrder.delete(viewPath);
|
|
8989
|
-
}
|
|
8990
|
-
else {
|
|
8991
|
-
this.accessOrder.clear();
|
|
8992
|
-
}
|
|
8993
|
-
this.store.getState()._clear(viewPath);
|
|
8994
|
-
}
|
|
8995
|
-
evictOldest(viewPath) {
|
|
8996
|
-
const order = this.accessOrder.get(viewPath);
|
|
8997
|
-
if (!order || order.length === 0)
|
|
8998
|
-
return undefined;
|
|
8999
|
-
const oldest = order.shift();
|
|
9000
|
-
if (oldest !== undefined) {
|
|
9001
|
-
this.store.getState()._delete(viewPath, oldest);
|
|
9002
|
-
}
|
|
9003
|
-
return oldest;
|
|
9004
|
-
}
|
|
9005
|
-
onUpdate(callback) {
|
|
9006
|
-
this.updateCallbacks.add(callback);
|
|
9007
|
-
return () => this.updateCallbacks.delete(callback);
|
|
9008
|
-
}
|
|
9009
|
-
onRichUpdate(callback) {
|
|
9010
|
-
this.richUpdateCallbacks.add(callback);
|
|
9011
|
-
return () => this.richUpdateCallbacks.delete(callback);
|
|
9012
|
-
}
|
|
9013
|
-
notifyUpdate(viewPath, key, update) {
|
|
9014
|
-
for (const callback of this.updateCallbacks) {
|
|
9015
|
-
callback(viewPath, key, update);
|
|
9016
|
-
}
|
|
9017
|
-
}
|
|
9018
|
-
notifyRichUpdate(viewPath, key, update) {
|
|
9019
|
-
for (const callback of this.richUpdateCallbacks) {
|
|
9020
|
-
callback(viewPath, key, update);
|
|
9021
|
-
}
|
|
9022
|
-
}
|
|
9023
|
-
setConnectionState(state, error) {
|
|
9024
|
-
this.store.getState()._setConnectionState(state, error);
|
|
9025
|
-
}
|
|
9026
|
-
setViewConfig(viewPath, config) {
|
|
9027
|
-
const state = this.store.getState();
|
|
9028
|
-
const existingConfig = state.viewConfigs.get(viewPath);
|
|
9029
|
-
if (existingConfig?.sort)
|
|
9030
|
-
return;
|
|
9031
|
-
state._setViewConfig(viewPath, config);
|
|
9032
|
-
if (config.sort) {
|
|
9033
|
-
this.rebuildSortedKeys(viewPath, config.sort);
|
|
9034
|
-
}
|
|
9035
|
-
}
|
|
9036
|
-
getViewConfig(viewPath) {
|
|
9037
|
-
return this.store.getState().viewConfigs.get(viewPath);
|
|
9038
|
-
}
|
|
9039
|
-
rebuildSortedKeys(viewPath, sortConfig) {
|
|
9040
|
-
const state = this.store.getState();
|
|
9041
|
-
const viewMap = state.entities.get(viewPath);
|
|
9042
|
-
if (!viewMap || viewMap.size === 0)
|
|
9043
|
-
return;
|
|
9044
|
-
const isDesc = sortConfig.order === 'desc';
|
|
9045
|
-
const entries = Array.from(viewMap.entries());
|
|
9046
|
-
entries.sort((a, b) => {
|
|
9047
|
-
const aValue = getNestedValue(a[1], sortConfig.field);
|
|
9048
|
-
const bValue = getNestedValue(b[1], sortConfig.field);
|
|
9049
|
-
let cmp = compareSortValues(aValue, bValue);
|
|
9050
|
-
if (isDesc)
|
|
9051
|
-
cmp = -cmp;
|
|
9052
|
-
if (cmp === 0) {
|
|
9053
|
-
cmp = a[0].localeCompare(b[0]);
|
|
9054
|
-
}
|
|
9055
|
-
return cmp;
|
|
9056
|
-
});
|
|
9057
|
-
const sortedKeys = entries.map(([k]) => k);
|
|
9058
|
-
state._updateSortedKeys(viewPath, sortedKeys);
|
|
9059
|
-
}
|
|
9060
|
-
}
|
|
9061
|
-
|
|
9062
9101
|
export { ConnectionManager, DEFAULT_CONFIG, DEFAULT_MAX_ENTRIES_PER_VIEW, FrameProcessor, HyperStack, HyperStackError, HyperstackProvider, MemoryAdapter, SubscriptionRegistry, ZustandAdapter, createInstructionExecutor, createPublicKeySeed, createSeed, derivePda, executeInstruction, formatProgramError, isSnapshotFrame, isValidFrame, parseFrame, parseFrameFromBlob, parseInstructionError, resolveAccounts, serializeInstructionData, useConnectionState, useEntity, useHyperstack, useHyperstackContext, useInstructionMutation, useView, validateAccountResolution, waitForConfirmation };
|
|
9063
9102
|
//# sourceMappingURL=index.esm.js.map
|