svelte-realtime 0.4.14 → 0.4.15

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/README.md CHANGED
@@ -261,7 +261,7 @@ The `merge` option on `live.stream()` controls how live pub/sub events are appli
261
261
 
262
262
  ### crud (default)
263
263
 
264
- Handles `created`, `updated`, `deleted` events. The store maintains an array, keyed by `id` (configurable with `key`).
264
+ Handles `created`, `updated`, `deleted` events. The store maintains an array, keyed by `id` (configurable with `key`). Set `max` to cap the buffer size and drop the oldest items when exceeded (useful for live feeds with `prepend: true`).
265
265
 
266
266
  ```js
267
267
  // Server
@@ -361,7 +361,7 @@ Events: `update` (add/update by key), `remove` (remove by key), `set` (replace a
361
361
  | `merge` | `'crud'` | Merge strategy: `'crud'`, `'latest'`, `'set'`, `'presence'`, `'cursor'` |
362
362
  | `key` | `'id'` | Key field for `crud` mode |
363
363
  | `prepend` | `false` | Prepend new items instead of appending (`crud` mode) |
364
- | `max` | `50` | Max items to keep (`latest` mode) |
364
+ | `max` | `50` / `0` | Max items to keep. Defaults to 50 for `latest`, 0 (unlimited) for `crud`. Oldest items are dropped when exceeded |
365
365
  | `replay` | `false` | Enable seq-based replay for gap-free reconnection |
366
366
  | `onSubscribe` | -- | Callback `(ctx, topic)` fired when a client subscribes |
367
367
  | `onUnsubscribe` | -- | Callback `(ctx, topic)` fired when a client disconnects |
package/client.d.ts CHANGED
@@ -1,6 +1,17 @@
1
1
  import type { Readable } from 'svelte/store';
2
2
  import type { WSEvent } from 'svelte-adapter-uws/client';
3
3
 
4
+ /**
5
+ * A store that always holds `undefined`. Use as a fallback for conditional
6
+ * streams so you don't need to import `readable` from `svelte/store`:
7
+ *
8
+ * ```svelte
9
+ * import { todos, empty } from '$live/todos';
10
+ * const items = $derived(user ? todos(orgId) : empty);
11
+ * ```
12
+ */
13
+ export const empty: Readable<undefined>;
14
+
4
15
  /**
5
16
  * Typed error for RPC failures.
6
17
  * Contains a `code` field for programmatic handling.
package/client.js CHANGED
@@ -1,6 +1,9 @@
1
1
  // @ts-check
2
2
  import { connect as _connect, on, status } from 'svelte-adapter-uws/client';
3
- import { writable } from 'svelte/store';
3
+ import { writable, readable } from 'svelte/store';
4
+
5
+ /** @type {import('svelte/store').Readable<undefined>} */
6
+ export const empty = readable(undefined);
4
7
 
5
8
  const _textEncoder = new TextEncoder();
6
9
 
@@ -499,7 +502,7 @@ function _createStream(path, options, dynamicArgs) {
499
502
  let merge = options?.merge || 'crud';
500
503
  let key = options?.key || 'id';
501
504
  let prepend = options?.prepend || false;
502
- let max = options?.max || 50;
505
+ let max = options?.max || (merge === 'latest' ? 50 : 0);
503
506
 
504
507
  /** @type {any} */
505
508
  let currentValue;
@@ -637,9 +640,18 @@ function _createStream(path, options, dynamicArgs) {
637
640
  currentValue.unshift(data);
638
641
  for (const [k, i] of _index) _index.set(k, i + 1);
639
642
  _index.set(data[key], 0);
643
+ if (max && currentValue.length > max) {
644
+ const removed = currentValue.splice(max);
645
+ for (const item of removed) _index.delete(item[key]);
646
+ }
640
647
  } else {
641
648
  _index.set(data[key], currentValue.length);
642
649
  currentValue.push(data);
650
+ if (max && currentValue.length > max) {
651
+ const removed = currentValue.splice(0, currentValue.length - max);
652
+ for (const item of removed) _index.delete(item[key]);
653
+ _rebuildIndex();
654
+ }
643
655
  }
644
656
  } else if (event === 'updated') {
645
657
  const idx = _index.get(data[key]);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "svelte-realtime",
3
- "version": "0.4.14",
3
+ "version": "0.4.15",
4
4
  "description": "Realtime RPC and reactive subscriptions for SvelteKit, built on svelte-adapter-uws",
5
5
  "author": "Kevin Radziszewski",
6
6
  "license": "MIT",
package/server.d.ts CHANGED
@@ -67,8 +67,10 @@ export interface StreamOptions {
67
67
  prepend?: boolean;
68
68
 
69
69
  /**
70
- * Maximum items to keep (latest mode only).
71
- * @default 50
70
+ * Maximum items to keep. When the buffer exceeds this size, the oldest
71
+ * items are dropped. Works with `crud` and `latest` merge strategies.
72
+ *
73
+ * For `latest`, defaults to 50. For `crud`, defaults to 0 (unlimited).
72
74
  */
73
75
  max?: number;
74
76
 
package/vite.js CHANGED
@@ -785,7 +785,9 @@ function _generateClientStubs(filePath, modulePath, dir) {
785
785
  ? `import { ${[...imports].join(', ')} } from 'svelte-realtime/client';\n`
786
786
  : '';
787
787
 
788
- return importLine + lines.join('\n') + '\n';
788
+ const reexport = `export { empty } from 'svelte-realtime/client';\n`;
789
+
790
+ return importLine + reexport + lines.join('\n') + '\n';
789
791
  }
790
792
 
791
793
  /**
@@ -1712,10 +1714,12 @@ function _generateTypeDeclarations(liveDir, dir) {
1712
1714
  if (needsRpcError) clientImports.push('RpcError');
1713
1715
  declarations.push(` import type { ${clientImports.join(', ')} } from 'svelte-realtime/client';`);
1714
1716
  }
1717
+ declarations.push(` import type { Readable } from 'svelte/store';`);
1715
1718
  if (needsStreamStore || needsRpcError) {
1716
1719
  declarations.push('');
1717
1720
  }
1718
1721
  declarations.push(...exports);
1722
+ declarations.push(` export const empty: Readable<undefined>;`);
1719
1723
  declarations.push('}');
1720
1724
  declarations.push('');
1721
1725
  }