svelte-realtime 0.4.4 → 0.4.6

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
@@ -1,6 +1,20 @@
1
- # svelte-realtime
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
- Realtime RPC and reactive subscriptions for SvelteKit, built on [svelte-adapter-uws](https://github.com/lanteanio/svelte-adapter-uws).
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
 
package/client.js CHANGED
@@ -103,7 +103,7 @@ function ensureListener() {
103
103
  pending.delete(result.id);
104
104
  if (entry.timer) clearTimeout(entry.timer);
105
105
  if (result.ok) {
106
- entry.resolve(result.data);
106
+ entry.resolve(entry.stream ? result : result.data);
107
107
  } else {
108
108
  entry.reject(new RpcError(result.code || 'UNKNOWN', result.error || 'Unknown error'));
109
109
  }
@@ -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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "svelte-realtime",
3
- "version": "0.4.4",
3
+ "version": "0.4.6",
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.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