@trops/dash-core 0.1.16 → 0.1.18

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.
@@ -6045,6 +6045,125 @@ const clientCache$1 = {
6045
6045
 
6046
6046
  var clientCache_1 = clientCache$1;
6047
6047
 
6048
+ /**
6049
+ * responseCache.js
6050
+ *
6051
+ * TTL-based API response cache with in-flight deduplication.
6052
+ * Renderer-driven: widget developer includes { cache: true } or { cache: { ttl: N } }
6053
+ * in IPC messages to opt-in to caching per call.
6054
+ *
6055
+ * Usage:
6056
+ * // Wrap a handler:
6057
+ * ipcMain.handle("my-channel", responseCache.cachedHandler("my-channel", handler));
6058
+ *
6059
+ * // Widget-side (renderer):
6060
+ * window.mainApi.myService.getData({ ...pc, cache: true }); // 30s default
6061
+ * window.mainApi.myService.getData({ ...pc, cache: 60000 }); // 60s
6062
+ * window.mainApi.myService.getData({ ...pc, cache: { ttl: 120000 } }); // 120s
6063
+ * window.mainApi.myService.getData({ ...pc, cache: true, forceRefresh: true }); // bypass
6064
+ */
6065
+
6066
+ const cache = new Map(); // key → { data, timestamp, ttl }
6067
+ const inflight = new Map(); // key → Promise
6068
+
6069
+ function stableHash(obj) {
6070
+ const str = JSON.stringify(obj, Object.keys(obj).sort());
6071
+ let hash = 5381;
6072
+ for (let i = 0; i < str.length; i++) {
6073
+ hash = ((hash << 5) + hash + str.charCodeAt(i)) & 0xffffffff;
6074
+ }
6075
+ return hash.toString(36);
6076
+ }
6077
+
6078
+ const responseCache$1 = {
6079
+ async get(key, fetcher, options = {}) {
6080
+ const { ttl = 30000, forceRefresh = false } = options;
6081
+
6082
+ if (!forceRefresh && cache.has(key)) {
6083
+ const entry = cache.get(key);
6084
+ if (Date.now() - entry.timestamp < entry.ttl) {
6085
+ console.log(`[responseCache] HIT ${key}`);
6086
+ return entry.data;
6087
+ }
6088
+ cache.delete(key);
6089
+ }
6090
+
6091
+ if (!forceRefresh && inflight.has(key)) {
6092
+ console.log(`[responseCache] DEDUP ${key}`);
6093
+ return inflight.get(key);
6094
+ }
6095
+
6096
+ console.log(`[responseCache] MISS ${key}`);
6097
+ const promise = fetcher();
6098
+ inflight.set(key, promise);
6099
+ try {
6100
+ const data = await promise;
6101
+ if (data && !data.error) {
6102
+ cache.set(key, { data, timestamp: Date.now(), ttl });
6103
+ }
6104
+ return data;
6105
+ } finally {
6106
+ inflight.delete(key);
6107
+ }
6108
+ },
6109
+
6110
+ /**
6111
+ * Wrap an ipcMain.handle handler with renderer-driven caching.
6112
+ * If the incoming message has a `cache` property, the response is cached.
6113
+ * If the message has `forceRefresh: true`, the cache is bypassed.
6114
+ *
6115
+ * The `cache` and `forceRefresh` properties are stripped from the message
6116
+ * before passing to the handler, so handlers receive clean params.
6117
+ *
6118
+ * Cache parameter forms:
6119
+ * cache: true → 30s default TTL
6120
+ * cache: 60000 → 60s (number shorthand)
6121
+ * cache: { ttl: N } → explicit TTL in ms
6122
+ */
6123
+ cachedHandler(channelName, handler) {
6124
+ return async (e, msg) => {
6125
+ const { cache: cacheOpt, forceRefresh, ...params } = msg || {};
6126
+ if (cacheOpt) {
6127
+ const ttl =
6128
+ typeof cacheOpt === "number"
6129
+ ? cacheOpt
6130
+ : cacheOpt?.ttl || 30000;
6131
+ const key = `${channelName}:${stableHash(params)}`;
6132
+ return this.get(key, () => handler(e, params), {
6133
+ ttl,
6134
+ forceRefresh,
6135
+ });
6136
+ }
6137
+ return handler(e, msg);
6138
+ };
6139
+ },
6140
+
6141
+ invalidate(key) {
6142
+ cache.delete(key);
6143
+ },
6144
+
6145
+ invalidatePrefix(prefix) {
6146
+ for (const k of cache.keys()) {
6147
+ if (k.startsWith(prefix)) cache.delete(k);
6148
+ }
6149
+ },
6150
+
6151
+ clear() {
6152
+ cache.clear();
6153
+ inflight.clear();
6154
+ },
6155
+
6156
+ stats() {
6157
+ return {
6158
+ entries: cache.size,
6159
+ inflight: inflight.size,
6160
+ keys: [...cache.keys()],
6161
+ };
6162
+ },
6163
+ };
6164
+
6165
+ var responseCache_1 = responseCache$1;
6166
+
6048
6167
  /**
6049
6168
  * Controller exports.
6050
6169
  */
@@ -8727,6 +8846,7 @@ const pluginController = pluginController_1;
8727
8846
 
8728
8847
  // --- Utils ---
8729
8848
  const clientCache = clientCache_1;
8849
+ const responseCache = responseCache_1;
8730
8850
 
8731
8851
  // --- Controller functions (flat, for convenient destructuring) ---
8732
8852
  const controllers = controller;
@@ -8810,6 +8930,7 @@ var electron = {
8810
8930
 
8811
8931
  // Utils
8812
8932
  clientCache,
8933
+ responseCache,
8813
8934
  };
8814
8935
 
8815
8936
  var index = /*@__PURE__*/getDefaultExportFromCjs(electron);