svelte-realtime 0.4.5 → 0.4.7
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 +25 -8
- package/client.d.ts +21 -0
- package/client.js +3 -3
- package/package.json +1 -1
- package/server.d.ts +69 -14
- package/server.js +18 -18
- package/vite.js +14 -12
package/README.md
CHANGED
|
@@ -1,6 +1,20 @@
|
|
|
1
|
-
|
|
1
|
+
<p align="center">
|
|
2
|
+
<a href="https://svelte-realtime.dev">
|
|
3
|
+
<img src="https://svelte-realtime.dev/svelte_orange.png" alt="svelte-realtime" width="240" />
|
|
4
|
+
</a>
|
|
5
|
+
</p>
|
|
2
6
|
|
|
3
|
-
|
|
7
|
+
<h1 align="center">svelte-realtime</h1>
|
|
8
|
+
|
|
9
|
+
<p align="center">
|
|
10
|
+
Realtime RPC and reactive subscriptions for SvelteKit, built on <a href="https://github.com/lanteanio/svelte-adapter-uws">svelte-adapter-uws</a>.
|
|
11
|
+
</p>
|
|
12
|
+
|
|
13
|
+
<p align="center">
|
|
14
|
+
<a href="https://svelte-realtime.dev">Documentation</a> · <a href="https://svelte-realtime.dev/tutorial">Tutorial</a> · <a href="https://svelte-realtime-demo.lantean.io">Live Demo</a>
|
|
15
|
+
</p>
|
|
16
|
+
|
|
17
|
+
---
|
|
4
18
|
|
|
5
19
|
Write server functions. Import them in components. Call them over WebSocket. No boilerplate, no manual pub/sub wiring, no protocol design.
|
|
6
20
|
|
|
@@ -1648,18 +1662,20 @@ export const message = createMessage({
|
|
|
1648
1662
|
});
|
|
1649
1663
|
```
|
|
1650
1664
|
|
|
1651
|
-
###
|
|
1665
|
+
### Standalone onError
|
|
1652
1666
|
|
|
1653
|
-
For cron jobs, use the standalone `
|
|
1667
|
+
For errors in cron jobs, effects, and derived streams, use the standalone `onError` function:
|
|
1654
1668
|
|
|
1655
1669
|
```js
|
|
1656
|
-
import {
|
|
1670
|
+
import { onError } from 'svelte-realtime/server';
|
|
1657
1671
|
|
|
1658
|
-
|
|
1659
|
-
sentry.captureException(error, { tags: {
|
|
1672
|
+
onError((path, error) => {
|
|
1673
|
+
sentry.captureException(error, { tags: { live: path } });
|
|
1660
1674
|
});
|
|
1661
1675
|
```
|
|
1662
1676
|
|
|
1677
|
+
> `onCronError` still works but is deprecated -- use `onError` instead.
|
|
1678
|
+
|
|
1663
1679
|
---
|
|
1664
1680
|
|
|
1665
1681
|
## Custom message handling
|
|
@@ -1814,7 +1830,8 @@ Import from `svelte-realtime/server`.
|
|
|
1814
1830
|
| `close` | Ready-made close hook (fires onUnsubscribe for remaining topics) |
|
|
1815
1831
|
| `unsubscribe` | Ready-made unsubscribe hook (fires onUnsubscribe in real time) |
|
|
1816
1832
|
| `setCronPlatform(platform)` | Capture platform for cron jobs |
|
|
1817
|
-
| `
|
|
1833
|
+
| `onError(handler)` | Global error handler for cron, effects, and derived |
|
|
1834
|
+
| `onCronError(handler)` | Deprecated alias for `onError` |
|
|
1818
1835
|
| `enableSignals(ws)` | Enable point-to-point signal delivery |
|
|
1819
1836
|
| `_activateDerived(platform)` | Enable derived stream listeners |
|
|
1820
1837
|
| `live.metrics(registry)` | Opt-in Prometheus metrics |
|
package/client.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { Readable } from 'svelte/store';
|
|
2
|
+
import type { WSEvent } from 'svelte-adapter-uws/client';
|
|
2
3
|
|
|
3
4
|
/**
|
|
4
5
|
* Typed error for RPC failures.
|
|
@@ -237,3 +238,23 @@ export const __devtools: {
|
|
|
237
238
|
streams: Map<string, { path: string; topic: string | null; subCount: number }>;
|
|
238
239
|
pending: Map<string, { path: string; args: any[]; startTime: number }>;
|
|
239
240
|
} | null;
|
|
241
|
+
|
|
242
|
+
/**
|
|
243
|
+
* Reactive derived topic subscription that auto-switches when a source store changes.
|
|
244
|
+
* Re-exported from `svelte-adapter-uws/client`.
|
|
245
|
+
*
|
|
246
|
+
* @param topicFn - Function that computes the topic from the store value
|
|
247
|
+
* @param store - Readable store whose value drives the topic
|
|
248
|
+
*
|
|
249
|
+
* @example
|
|
250
|
+
* ```svelte
|
|
251
|
+
* <script>
|
|
252
|
+
* import { onDerived } from 'svelte-realtime/client';
|
|
253
|
+
* const messages = onDerived((id) => `room:${id}`, roomId);
|
|
254
|
+
* </script>
|
|
255
|
+
* ```
|
|
256
|
+
*/
|
|
257
|
+
export function onDerived<T = unknown>(
|
|
258
|
+
topicFn: (value: T) => string,
|
|
259
|
+
store: Readable<T>
|
|
260
|
+
): Readable<WSEvent | null>;
|
package/client.js
CHANGED
|
@@ -1503,7 +1503,7 @@ function _checkArgs(path, args) {
|
|
|
1503
1503
|
const t = typeof arg;
|
|
1504
1504
|
if (t === 'function' || t === 'symbol' || t === 'bigint' || t === 'undefined') {
|
|
1505
1505
|
console.warn(
|
|
1506
|
-
`[svelte-realtime] RPC '${path}' called with non-JSON-serializable argument at index ${i} (${t}) -- this will be lost during transmission`
|
|
1506
|
+
`[svelte-realtime] RPC '${path}' called with non-JSON-serializable argument at index ${i} (${t}) -- this will be lost during transmission\n See: https://svti.me/rpc`
|
|
1507
1507
|
);
|
|
1508
1508
|
}
|
|
1509
1509
|
}
|
|
@@ -1644,10 +1644,10 @@ export function combine(...args) {
|
|
|
1644
1644
|
const sources = args;
|
|
1645
1645
|
|
|
1646
1646
|
if (typeof fn !== 'function') {
|
|
1647
|
-
throw new Error('combine() requires a combining function as the last argument');
|
|
1647
|
+
throw new Error('combine() requires a combining function as the last argument\n See: https://svti.me/client');
|
|
1648
1648
|
}
|
|
1649
1649
|
if (sources.length < 2) {
|
|
1650
|
-
throw new Error('combine() requires at least 2 source stores');
|
|
1650
|
+
throw new Error('combine() requires at least 2 source stores\n See: https://svti.me/client');
|
|
1651
1651
|
}
|
|
1652
1652
|
|
|
1653
1653
|
const values = new Array(sources.length);
|
package/package.json
CHANGED
package/server.d.ts
CHANGED
|
@@ -529,6 +529,43 @@ export namespace live {
|
|
|
529
529
|
*/
|
|
530
530
|
function webhook(topic: string, config: WebhookConfig): WebhookHandler;
|
|
531
531
|
|
|
532
|
+
/**
|
|
533
|
+
* Opt-in Prometheus metrics integration.
|
|
534
|
+
* Accepts a MetricsRegistry from `svelte-adapter-uws-extensions/prometheus`
|
|
535
|
+
* and instruments RPC calls, stream subscriptions, and cron executions.
|
|
536
|
+
*
|
|
537
|
+
* Zero overhead if never called.
|
|
538
|
+
*
|
|
539
|
+
* @param registry - A MetricsRegistry instance with counter(), histogram(), gauge()
|
|
540
|
+
*
|
|
541
|
+
* @example
|
|
542
|
+
* ```js
|
|
543
|
+
* import { createRegistry } from 'svelte-adapter-uws-extensions/prometheus';
|
|
544
|
+
* live.metrics(createRegistry());
|
|
545
|
+
* ```
|
|
546
|
+
*/
|
|
547
|
+
function metrics(registry: any): void;
|
|
548
|
+
|
|
549
|
+
/**
|
|
550
|
+
* Wrap a stream initFn call with a circuit breaker.
|
|
551
|
+
* When the breaker is open, returns the fallback value or throws SERVICE_UNAVAILABLE.
|
|
552
|
+
*
|
|
553
|
+
* @param options - Circuit breaker instance and optional fallback
|
|
554
|
+
* @param fn - The stream initFn to wrap
|
|
555
|
+
*
|
|
556
|
+
* @example
|
|
557
|
+
* ```js
|
|
558
|
+
* export const messages = live.breaker(
|
|
559
|
+
* { breaker: cb, fallback: [] },
|
|
560
|
+
* live.stream('messages', async (ctx) => db.messages.latest(50))
|
|
561
|
+
* );
|
|
562
|
+
* ```
|
|
563
|
+
*/
|
|
564
|
+
function breaker<T extends Function>(
|
|
565
|
+
options: { breaker: any; fallback?: any },
|
|
566
|
+
fn: T
|
|
567
|
+
): T;
|
|
568
|
+
|
|
532
569
|
/**
|
|
533
570
|
* Declarative access control helpers for subscribe-time gating.
|
|
534
571
|
* For per-event filtering, use `pipe.filter()`.
|
|
@@ -812,29 +849,23 @@ export function _clearCron(): void;
|
|
|
812
849
|
export function _tickCron(): Promise<void>;
|
|
813
850
|
|
|
814
851
|
/**
|
|
815
|
-
* Set a global error handler for cron
|
|
816
|
-
* Without this,
|
|
852
|
+
* Set a global error handler for server-side errors (cron, effects, derived).
|
|
853
|
+
* Without this, errors are logged in dev and silently swallowed in production.
|
|
817
854
|
*
|
|
818
|
-
* @param handler - Receives the
|
|
855
|
+
* @param handler - Receives the path and the thrown error
|
|
819
856
|
*
|
|
820
857
|
* @example
|
|
821
858
|
* ```js
|
|
822
|
-
*
|
|
823
|
-
* sentry.captureException(error, { tags: {
|
|
859
|
+
* onError((path, error) => {
|
|
860
|
+
* sentry.captureException(error, { tags: { live: path } });
|
|
824
861
|
* });
|
|
825
862
|
* ```
|
|
826
863
|
*/
|
|
864
|
+
export function onError(handler: (path: string, error: unknown) => void): void;
|
|
865
|
+
|
|
866
|
+
/** @deprecated Use `onError()` instead. */
|
|
827
867
|
export function onCronError(handler: (path: string, error: unknown) => void): void;
|
|
828
868
|
|
|
829
|
-
/**
|
|
830
|
-
* Handle a WebSocket close event. Fires `onUnsubscribe` lifecycle hooks
|
|
831
|
-
* for stream functions that define them.
|
|
832
|
-
*
|
|
833
|
-
* Re-export from your `hooks.ws.js`:
|
|
834
|
-
* ```js
|
|
835
|
-
* export { close } from 'svelte-realtime/server';
|
|
836
|
-
* ```
|
|
837
|
-
*/
|
|
838
869
|
/**
|
|
839
870
|
* Subscribe a WebSocket to its user's signal topic.
|
|
840
871
|
* Call in your `open` hook to enable signal delivery.
|
|
@@ -847,6 +878,30 @@ export function onCronError(handler: (path: string, error: unknown) => void): vo
|
|
|
847
878
|
*/
|
|
848
879
|
export function enableSignals(ws: WebSocket<any>, options?: { idField?: string }): void;
|
|
849
880
|
|
|
881
|
+
/**
|
|
882
|
+
* Handle a real-time topic unsubscribe event. Fires onUnsubscribe lifecycle
|
|
883
|
+
* hooks for the stream function that owns the topic.
|
|
884
|
+
*
|
|
885
|
+
* Re-export from your `hooks.ws.js`:
|
|
886
|
+
* ```js
|
|
887
|
+
* export { unsubscribe } from 'svelte-realtime/server';
|
|
888
|
+
* ```
|
|
889
|
+
*/
|
|
890
|
+
export function unsubscribe(
|
|
891
|
+
ws: WebSocket<any>,
|
|
892
|
+
topic: string,
|
|
893
|
+
ctx: { platform: Platform }
|
|
894
|
+
): void;
|
|
895
|
+
|
|
896
|
+
/**
|
|
897
|
+
* Handle a WebSocket close event. Fires `onUnsubscribe` lifecycle hooks
|
|
898
|
+
* for stream functions that define them.
|
|
899
|
+
*
|
|
900
|
+
* Re-export from your `hooks.ws.js`:
|
|
901
|
+
* ```js
|
|
902
|
+
* export { close } from 'svelte-realtime/server';
|
|
903
|
+
* ```
|
|
904
|
+
*/
|
|
850
905
|
export function close(
|
|
851
906
|
ws: WebSocket<any>,
|
|
852
907
|
ctx: { platform: Platform }
|
package/server.js
CHANGED
|
@@ -354,11 +354,11 @@ export function live(fn) {
|
|
|
354
354
|
*/
|
|
355
355
|
live.stream = function stream(topic, initFn, options) {
|
|
356
356
|
if (typeof topic === 'string' && topic.startsWith('__')) {
|
|
357
|
-
throw new Error(`[svelte-realtime] live.stream topic '${topic}' uses reserved prefix '__'`);
|
|
357
|
+
throw new Error(`[svelte-realtime] live.stream topic '${topic}' uses reserved prefix '__'\n See: https://svti.me/streams`);
|
|
358
358
|
}
|
|
359
359
|
if (typeof topic === 'function') {
|
|
360
360
|
if (topic.constructor?.name === 'AsyncFunction') {
|
|
361
|
-
throw new Error(`[svelte-realtime] live.stream topic function must not be async -- topic resolution is synchronous`);
|
|
361
|
+
throw new Error(`[svelte-realtime] live.stream topic function must not be async -- topic resolution is synchronous\n See: https://svti.me/streams`);
|
|
362
362
|
}
|
|
363
363
|
_tagTopicFn(topic);
|
|
364
364
|
}
|
|
@@ -391,11 +391,11 @@ live.stream = function stream(topic, initFn, options) {
|
|
|
391
391
|
*/
|
|
392
392
|
live.channel = function channel(topic, options) {
|
|
393
393
|
if (typeof topic === 'string' && topic.startsWith('__')) {
|
|
394
|
-
throw new Error(`[svelte-realtime] live.channel topic '${topic}' uses reserved prefix '__'`);
|
|
394
|
+
throw new Error(`[svelte-realtime] live.channel topic '${topic}' uses reserved prefix '__'\n See: https://svti.me/streams`);
|
|
395
395
|
}
|
|
396
396
|
if (typeof topic === 'function') {
|
|
397
397
|
if (topic.constructor?.name === 'AsyncFunction') {
|
|
398
|
-
throw new Error(`[svelte-realtime] live.channel topic function must not be async -- topic resolution is synchronous`);
|
|
398
|
+
throw new Error(`[svelte-realtime] live.channel topic function must not be async -- topic resolution is synchronous\n See: https://svti.me/streams`);
|
|
399
399
|
}
|
|
400
400
|
_tagTopicFn(topic);
|
|
401
401
|
}
|
|
@@ -1082,13 +1082,13 @@ live.room = function room(config) {
|
|
|
1082
1082
|
let _roomArgCount = Math.max(0, topicFn.length - 1);
|
|
1083
1083
|
if (config.topicArgs !== undefined) {
|
|
1084
1084
|
if (!Number.isInteger(config.topicArgs) || config.topicArgs < 0) {
|
|
1085
|
-
throw new Error(`[svelte-realtime] live.room() topicArgs must be a non-negative integer, got ${config.topicArgs}`);
|
|
1085
|
+
throw new Error(`[svelte-realtime] live.room() topicArgs must be a non-negative integer, got ${config.topicArgs}\n See: https://svti.me/rooms`);
|
|
1086
1086
|
}
|
|
1087
1087
|
_roomArgCount = config.topicArgs;
|
|
1088
1088
|
} else if (actions) {
|
|
1089
1089
|
throw new Error(
|
|
1090
1090
|
`[svelte-realtime] live.room() with actions requires 'topicArgs'. ` +
|
|
1091
|
-
`Set topicArgs to the number of room-identifying args (excluding ctx)
|
|
1091
|
+
`Set topicArgs to the number of room-identifying args (excluding ctx).\n See: https://svti.me/rooms`
|
|
1092
1092
|
);
|
|
1093
1093
|
}
|
|
1094
1094
|
|
|
@@ -1216,7 +1216,7 @@ live.room = function room(config) {
|
|
|
1216
1216
|
for (const [name, fn] of Object.entries(actions)) {
|
|
1217
1217
|
if (!_validSegmentRe.test(name)) {
|
|
1218
1218
|
if (typeof process !== 'undefined' && process.env?.NODE_ENV !== 'production') {
|
|
1219
|
-
console.warn(`[svelte-realtime] Room action '${name}' contains invalid characters (only a-z, A-Z, 0-9, _ allowed) -- skipped`);
|
|
1219
|
+
console.warn(`[svelte-realtime] Room action '${name}' contains invalid characters (only a-z, A-Z, 0-9, _ allowed) -- skipped\n See: https://svti.me/rooms`);
|
|
1220
1220
|
}
|
|
1221
1221
|
continue;
|
|
1222
1222
|
}
|
|
@@ -1713,7 +1713,7 @@ export async function _tickCron() {
|
|
|
1713
1713
|
try {
|
|
1714
1714
|
if (!_cronPlatform) {
|
|
1715
1715
|
if (typeof process !== 'undefined' && process.env.NODE_ENV !== 'production') {
|
|
1716
|
-
console.warn(`[svelte-realtime] Cron '${path}' fired but no platform captured. Call setCronPlatform(platform) in your open hook
|
|
1716
|
+
console.warn(`[svelte-realtime] Cron '${path}' fired but no platform captured. Call setCronPlatform(platform) in your open hook.\n See: https://svti.me/cron`);
|
|
1717
1717
|
}
|
|
1718
1718
|
return;
|
|
1719
1719
|
}
|
|
@@ -1748,7 +1748,7 @@ export async function _tickCron() {
|
|
|
1748
1748
|
function _parseCron(expr) {
|
|
1749
1749
|
const parts = expr.trim().split(/\s+/);
|
|
1750
1750
|
if (parts.length !== 5) {
|
|
1751
|
-
throw new Error(`[svelte-realtime] Invalid cron expression '${expr}' -- expected 5 fields (minute hour day month weekday)`);
|
|
1751
|
+
throw new Error(`[svelte-realtime] Invalid cron expression '${expr}' -- expected 5 fields (minute hour day month weekday)\n See: https://svti.me/cron`);
|
|
1752
1752
|
}
|
|
1753
1753
|
return parts.map((field, idx) => _parseCronField(field, idx));
|
|
1754
1754
|
}
|
|
@@ -1772,7 +1772,7 @@ function _parseCronField(field, idx) {
|
|
|
1772
1772
|
if (field.startsWith('*/')) {
|
|
1773
1773
|
const step = parseInt(field.slice(2), 10);
|
|
1774
1774
|
if (!Number.isFinite(step) || step < 1) {
|
|
1775
|
-
throw new Error(`[svelte-realtime] Invalid cron step '${field}' -- step must be a positive integer`);
|
|
1775
|
+
throw new Error(`[svelte-realtime] Invalid cron step '${field}' -- step must be a positive integer\n See: https://svti.me/cron`);
|
|
1776
1776
|
}
|
|
1777
1777
|
return { step };
|
|
1778
1778
|
}
|
|
@@ -1782,7 +1782,7 @@ function _parseCronField(field, idx) {
|
|
|
1782
1782
|
const a = parseInt(parts[0], 10);
|
|
1783
1783
|
const b = parseInt(parts[1], 10);
|
|
1784
1784
|
if (!Number.isFinite(a) || !Number.isFinite(b) || a < min || b > max || a > b) {
|
|
1785
|
-
throw new Error(`[svelte-realtime] Invalid cron range '${field}' -- values must be ${min}-${max}`);
|
|
1785
|
+
throw new Error(`[svelte-realtime] Invalid cron range '${field}' -- values must be ${min}-${max}\n See: https://svti.me/cron`);
|
|
1786
1786
|
}
|
|
1787
1787
|
const vals = new Set();
|
|
1788
1788
|
for (let i = a; i <= b; i++) vals.add(i);
|
|
@@ -1793,7 +1793,7 @@ function _parseCronField(field, idx) {
|
|
|
1793
1793
|
const nums = field.split(',').map(s => {
|
|
1794
1794
|
const n = parseInt(s, 10);
|
|
1795
1795
|
if (!Number.isFinite(n) || n < min || n > max) {
|
|
1796
|
-
throw new Error(`[svelte-realtime] Invalid cron value '${s}' in '${field}' -- must be ${min}-${max}`);
|
|
1796
|
+
throw new Error(`[svelte-realtime] Invalid cron value '${s}' in '${field}' -- must be ${min}-${max}\n See: https://svti.me/cron`);
|
|
1797
1797
|
}
|
|
1798
1798
|
return n;
|
|
1799
1799
|
});
|
|
@@ -1802,7 +1802,7 @@ function _parseCronField(field, idx) {
|
|
|
1802
1802
|
|
|
1803
1803
|
const n = parseInt(field, 10);
|
|
1804
1804
|
if (!Number.isFinite(n) || n < min || n > max) {
|
|
1805
|
-
throw new Error(`[svelte-realtime] Invalid cron value '${field}' -- must be ${min}-${max}`);
|
|
1805
|
+
throw new Error(`[svelte-realtime] Invalid cron value '${field}' -- must be ${min}-${max}\n See: https://svti.me/cron`);
|
|
1806
1806
|
}
|
|
1807
1807
|
return new Set([n]);
|
|
1808
1808
|
}
|
|
@@ -1928,7 +1928,7 @@ export function handleRpc(ws, data, platform, options) {
|
|
|
1928
1928
|
}
|
|
1929
1929
|
} catch (err) {
|
|
1930
1930
|
if (typeof process !== 'undefined' && process.env?.NODE_ENV !== 'production') {
|
|
1931
|
-
console.warn('[svelte-realtime] Failed to parse binary RPC header:', err);
|
|
1931
|
+
console.warn('[svelte-realtime] Failed to parse binary RPC header:', err, '\n See: https://svti.me/binary');
|
|
1932
1932
|
}
|
|
1933
1933
|
}
|
|
1934
1934
|
}
|
|
@@ -2050,7 +2050,7 @@ async function _executeSingleRpc(ws, msg, platform, options) {
|
|
|
2050
2050
|
const fn = await _resolveRegistryEntry(path);
|
|
2051
2051
|
if (!fn) {
|
|
2052
2052
|
if (typeof process !== 'undefined' && process.env.NODE_ENV !== 'production') {
|
|
2053
|
-
console.warn(`[svelte-realtime] RPC call to '${path}' -- no such live function registered`);
|
|
2053
|
+
console.warn(`[svelte-realtime] RPC call to '${path}' -- no such live function registered\n See: https://svti.me/rpc`);
|
|
2054
2054
|
}
|
|
2055
2055
|
_recordRpcMetrics(path, 'NOT_FOUND', _metricsStart);
|
|
2056
2056
|
return { id, ok: false, code: 'NOT_FOUND', error: 'Not found' };
|
|
@@ -2188,7 +2188,7 @@ async function _executeSingleRpc(ws, msg, platform, options) {
|
|
|
2188
2188
|
console.warn(
|
|
2189
2189
|
`[svelte-realtime] '${path}' threw a non-LiveError:`,
|
|
2190
2190
|
err,
|
|
2191
|
-
'\nUse throw new LiveError(code, message) for client-visible errors. Raw errors are hidden from clients.'
|
|
2191
|
+
'\nUse throw new LiveError(code, message) for client-visible errors. Raw errors are hidden from clients.\n See: https://svti.me/errors'
|
|
2192
2192
|
);
|
|
2193
2193
|
console.error(`[svelte-realtime] Error in '${path}':`, err);
|
|
2194
2194
|
}
|
|
@@ -2415,7 +2415,7 @@ function _migrateItem(item, fromVersion, toVersion, migrateFns) {
|
|
|
2415
2415
|
if (fn) {
|
|
2416
2416
|
result = fn(result);
|
|
2417
2417
|
} else if (typeof process !== 'undefined' && process.env.NODE_ENV !== 'production') {
|
|
2418
|
-
console.warn(`[svelte-realtime] Missing migration function for version ${v} -> ${v + 1}`);
|
|
2418
|
+
console.warn(`[svelte-realtime] Missing migration function for version ${v} -> ${v + 1}\n See: https://svti.me/schema`);
|
|
2419
2419
|
}
|
|
2420
2420
|
}
|
|
2421
2421
|
return result;
|
|
@@ -2428,7 +2428,7 @@ function _respond(ws, platform, correlationId, payload) {
|
|
|
2428
2428
|
if ((Array.isArray(data) && data.length > 100) || (typeof data === 'string' && data.length > 12000)) {
|
|
2429
2429
|
console.warn(
|
|
2430
2430
|
`[svelte-realtime] RPC response for '${correlationId}' contains ${data.length} items -- ` +
|
|
2431
|
-
'large responses may exceed maxPayloadLength (16KB). Increase maxPayloadLength in adapter config if needed.'
|
|
2431
|
+
'large responses may exceed maxPayloadLength (16KB). Increase maxPayloadLength in adapter config if needed.\n See: https://svti.me/adapter-config'
|
|
2432
2432
|
);
|
|
2433
2433
|
}
|
|
2434
2434
|
}
|
package/vite.js
CHANGED
|
@@ -37,7 +37,7 @@ function _isValidExportName(name, filePath) {
|
|
|
37
37
|
if (!_warnedExports.has(warnKey)) {
|
|
38
38
|
_warnedExports.add(warnKey);
|
|
39
39
|
console.warn(
|
|
40
|
-
`[svelte-realtime] ${filePath}: export '${name}' contains characters not allowed in RPC paths (only a-z, A-Z, 0-9, _ are valid) -- skipped`
|
|
40
|
+
`[svelte-realtime] ${filePath}: export '${name}' contains characters not allowed in RPC paths (only a-z, A-Z, 0-9, _ are valid) -- skipped\n See: https://svti.me/rpc`
|
|
41
41
|
);
|
|
42
42
|
}
|
|
43
43
|
return false;
|
|
@@ -131,7 +131,7 @@ function _readStringLiteral(s, start) {
|
|
|
131
131
|
if (q === '`' && ch === '$' && s[j + 1] === '{') {
|
|
132
132
|
const snippet = s.slice(start, Math.min(start + 40, s.length)).replace(/\n/g, '\\n');
|
|
133
133
|
throw new Error(
|
|
134
|
-
`[svelte-realtime] Template literal with interpolation cannot be statically analyzed: ${snippet}... -- use a plain string ('...' or "...") instead`
|
|
134
|
+
`[svelte-realtime] Template literal with interpolation cannot be statically analyzed: ${snippet}... -- use a plain string ('...' or "...") instead\n See: https://svti.me/vite`
|
|
135
135
|
);
|
|
136
136
|
}
|
|
137
137
|
result += ch;
|
|
@@ -265,7 +265,7 @@ export default function svelteRealtime(options) {
|
|
|
265
265
|
_warnedExports.clear();
|
|
266
266
|
if (!existsSync(liveDir)) {
|
|
267
267
|
console.warn(
|
|
268
|
-
`[svelte-realtime] Plugin loaded but no live modules found in ${dir}
|
|
268
|
+
`[svelte-realtime] Plugin loaded but no live modules found in ${dir}/\n See: https://svti.me/start`
|
|
269
269
|
);
|
|
270
270
|
} else {
|
|
271
271
|
if (typedImports) {
|
|
@@ -756,12 +756,12 @@ function _generateClientStubs(filePath, modulePath, dir) {
|
|
|
756
756
|
if (name.startsWith('_')) {
|
|
757
757
|
// Reserved names starting with _ (except _guard)
|
|
758
758
|
console.warn(
|
|
759
|
-
`[svelte-realtime] ${dir}/${modulePath} exports '${name}' starting with _ -- reserved for internal use`
|
|
759
|
+
`[svelte-realtime] ${dir}/${modulePath} exports '${name}' starting with _ -- reserved for internal use\n See: https://svti.me/rpc`
|
|
760
760
|
);
|
|
761
761
|
continue;
|
|
762
762
|
}
|
|
763
763
|
console.warn(
|
|
764
|
-
`[svelte-realtime] ${dir}/${modulePath} exports '${name}' which is not wrapped in live() -- it won't be callable from the client. Did you forget live()
|
|
764
|
+
`[svelte-realtime] ${dir}/${modulePath} exports '${name}' which is not wrapped in live() -- it won't be callable from the client. Did you forget live()?\n See: https://svti.me/rpc`
|
|
765
765
|
);
|
|
766
766
|
}
|
|
767
767
|
|
|
@@ -905,7 +905,7 @@ function _extractTopLevelKeys(body) {
|
|
|
905
905
|
if (/^[a-zA-Z0-9_]+$/.test(keyName)) {
|
|
906
906
|
keys.push(keyName);
|
|
907
907
|
} else if (typeof process !== 'undefined' && process.env?.NODE_ENV !== 'production') {
|
|
908
|
-
console.warn(`[svelte-realtime] Action name '${keyName}' contains characters not allowed in RPC paths -- skipped`);
|
|
908
|
+
console.warn(`[svelte-realtime] Action name '${keyName}' contains characters not allowed in RPC paths -- skipped\n See: https://svti.me/rooms`);
|
|
909
909
|
}
|
|
910
910
|
i = closeIdx + 1 + afterClose[0].length;
|
|
911
911
|
// If the match ended with '(' (quoted method shorthand), track depth
|
|
@@ -929,7 +929,7 @@ function _extractTopLevelKeys(body) {
|
|
|
929
929
|
if (/^[a-zA-Z0-9_]+$/.test(m[1])) {
|
|
930
930
|
keys.push(m[1]);
|
|
931
931
|
} else if (typeof process !== 'undefined' && process.env?.NODE_ENV !== 'production') {
|
|
932
|
-
console.warn(`[svelte-realtime] Action name '${m[1]}' contains characters not allowed in RPC paths (only a-z, A-Z, 0-9, _ are valid) -- skipped`);
|
|
932
|
+
console.warn(`[svelte-realtime] Action name '${m[1]}' contains characters not allowed in RPC paths (only a-z, A-Z, 0-9, _ are valid) -- skipped\n See: https://svti.me/rooms`);
|
|
933
933
|
}
|
|
934
934
|
i += m[0].length;
|
|
935
935
|
// If the match ended with '(' (method shorthand), account for the
|
|
@@ -1321,12 +1321,12 @@ function _generateRegistry(liveDir, dir) {
|
|
|
1321
1321
|
const topic = topicMatch[1];
|
|
1322
1322
|
if (topic.startsWith('__')) {
|
|
1323
1323
|
throw new Error(
|
|
1324
|
-
`[svelte-realtime] ${dir}/${rel} uses reserved topic '${topic}' -- topics starting with __ are reserved for internal use`
|
|
1324
|
+
`[svelte-realtime] ${dir}/${rel} uses reserved topic '${topic}' -- topics starting with __ are reserved for internal use\n See: https://svti.me/streams`
|
|
1325
1325
|
);
|
|
1326
1326
|
}
|
|
1327
1327
|
if (seenTopics.has(topic)) {
|
|
1328
1328
|
throw new Error(
|
|
1329
|
-
`[svelte-realtime] Duplicate stream topic '${topic}' in ${dir}/${rel} -- each topic must be unique across all modules`
|
|
1329
|
+
`[svelte-realtime] Duplicate stream topic '${topic}' in ${dir}/${rel} -- each topic must be unique across all modules\n See: https://svti.me/streams`
|
|
1330
1330
|
);
|
|
1331
1331
|
}
|
|
1332
1332
|
seenTopics.add(topic);
|
|
@@ -1482,7 +1482,8 @@ function _checkHooksFile(root, liveDir, dir) {
|
|
|
1482
1482
|
`WebSocket RPC will not work without it.\n` +
|
|
1483
1483
|
` Create src/hooks.ws.js with at minimum:\n` +
|
|
1484
1484
|
` export { message } from 'svelte-realtime/server';\n` +
|
|
1485
|
-
` export function upgrade() { return {}; }`
|
|
1485
|
+
` export function upgrade() { return {}; }\n` +
|
|
1486
|
+
` See: https://svti.me/hooks`
|
|
1486
1487
|
);
|
|
1487
1488
|
return;
|
|
1488
1489
|
}
|
|
@@ -1498,7 +1499,8 @@ function _checkHooksFile(root, liveDir, dir) {
|
|
|
1498
1499
|
console.warn(
|
|
1499
1500
|
`[svelte-realtime] ${name} exists but does not export a \`message\` handler -- ` +
|
|
1500
1501
|
`WebSocket RPC calls from ${dir}/ will go unhandled.\n` +
|
|
1501
|
-
` Add: export { message } from 'svelte-realtime/server'
|
|
1502
|
+
` Add: export { message } from 'svelte-realtime/server';\n` +
|
|
1503
|
+
` See: https://svti.me/hooks`
|
|
1502
1504
|
);
|
|
1503
1505
|
}
|
|
1504
1506
|
}
|
|
@@ -2267,7 +2269,7 @@ async function _hmrReloadRegistry(server, liveDir, dir, rel) {
|
|
|
2267
2269
|
try {
|
|
2268
2270
|
serverMod = await server.ssrLoadModule('svelte-realtime/server');
|
|
2269
2271
|
} catch {
|
|
2270
|
-
console.error('[svelte-realtime] HMR failed: could not load svelte-realtime/server');
|
|
2272
|
+
console.error('[svelte-realtime] HMR failed: could not load svelte-realtime/server\n See: https://svti.me/vite');
|
|
2271
2273
|
return;
|
|
2272
2274
|
}
|
|
2273
2275
|
|