svelte-realtime 0.4.7 → 0.4.9
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/package.json +1 -1
- package/server.d.ts +34 -34
- package/vite.js +30 -26
package/package.json
CHANGED
package/server.d.ts
CHANGED
|
@@ -83,26 +83,26 @@ export interface StreamOptions {
|
|
|
83
83
|
* Called when a client subscribes to this stream.
|
|
84
84
|
* Receives the context and resolved topic string.
|
|
85
85
|
*/
|
|
86
|
-
onSubscribe?(ctx: LiveContext
|
|
86
|
+
onSubscribe?(ctx: LiveContext<any>, topic: string): void | Promise<void>;
|
|
87
87
|
|
|
88
88
|
/**
|
|
89
89
|
* Called when a client disconnects from this stream.
|
|
90
90
|
* Fires for both static and dynamic topics.
|
|
91
91
|
*/
|
|
92
|
-
onUnsubscribe?(ctx: LiveContext
|
|
92
|
+
onUnsubscribe?(ctx: LiveContext<any>, topic: string): void | Promise<void>;
|
|
93
93
|
|
|
94
94
|
/**
|
|
95
95
|
* Subscribe-time access predicate. Checked once when a client subscribes.
|
|
96
96
|
* Return `false` to deny the subscription with an "Access denied" error.
|
|
97
97
|
* For per-event filtering, use `pipe.filter()`.
|
|
98
98
|
*/
|
|
99
|
-
filter?(ctx: LiveContext): boolean;
|
|
99
|
+
filter?(ctx: LiveContext<any>): boolean;
|
|
100
100
|
|
|
101
101
|
/**
|
|
102
102
|
* Subscribe-time access predicate (alias for `filter`).
|
|
103
103
|
* Use `live.access` helpers to build predicates.
|
|
104
104
|
*/
|
|
105
|
-
access?(ctx: LiveContext): boolean;
|
|
105
|
+
access?(ctx: LiveContext<any>): boolean;
|
|
106
106
|
|
|
107
107
|
/**
|
|
108
108
|
* Schema version number. Increment when the data shape changes.
|
|
@@ -143,7 +143,7 @@ export interface HandleRpcOptions {
|
|
|
143
143
|
* Called when an RPC handler throws a non-LiveError.
|
|
144
144
|
* Use for error reporting (Sentry, logging, etc.).
|
|
145
145
|
*/
|
|
146
|
-
onError?(path: string, error: unknown, ctx: LiveContext): void;
|
|
146
|
+
onError?(path: string, error: unknown, ctx: LiveContext<any>): void;
|
|
147
147
|
}
|
|
148
148
|
|
|
149
149
|
/**
|
|
@@ -171,7 +171,7 @@ export interface CreateMessageOptions {
|
|
|
171
171
|
* Called when an RPC handler throws a non-LiveError.
|
|
172
172
|
* Use for error reporting (Sentry, logging, etc.).
|
|
173
173
|
*/
|
|
174
|
-
onError?(path: string, error: unknown, ctx: LiveContext): void;
|
|
174
|
+
onError?(path: string, error: unknown, ctx: LiveContext<any>): void;
|
|
175
175
|
|
|
176
176
|
/**
|
|
177
177
|
* Called when a message is not an RPC request.
|
|
@@ -195,7 +195,7 @@ export interface CreateMessageOptions {
|
|
|
195
195
|
* });
|
|
196
196
|
* ```
|
|
197
197
|
*/
|
|
198
|
-
export function live<T extends (ctx: LiveContext
|
|
198
|
+
export function live<T extends (ctx: LiveContext<any>, ...args: any[]) => any>(fn: T): T;
|
|
199
199
|
|
|
200
200
|
export namespace live {
|
|
201
201
|
/**
|
|
@@ -212,7 +212,7 @@ export namespace live {
|
|
|
212
212
|
* }, { merge: 'crud', key: 'id', prepend: true });
|
|
213
213
|
* ```
|
|
214
214
|
*/
|
|
215
|
-
function stream<T extends (ctx: LiveContext
|
|
215
|
+
function stream<T extends (ctx: LiveContext<any>, ...args: any[]) => any>(
|
|
216
216
|
topic: string,
|
|
217
217
|
initFn: T,
|
|
218
218
|
options?: StreamOptions
|
|
@@ -237,8 +237,8 @@ export namespace live {
|
|
|
237
237
|
* );
|
|
238
238
|
* ```
|
|
239
239
|
*/
|
|
240
|
-
function stream<T extends (ctx: LiveContext
|
|
241
|
-
topicFn: (ctx: LiveContext
|
|
240
|
+
function stream<T extends (ctx: LiveContext<any>, ...args: any[]) => any>(
|
|
241
|
+
topicFn: (ctx: LiveContext<any>, ...args: any[]) => string,
|
|
242
242
|
initFn: T,
|
|
243
243
|
options?: StreamOptions
|
|
244
244
|
): T;
|
|
@@ -275,7 +275,7 @@ export namespace live {
|
|
|
275
275
|
* ```
|
|
276
276
|
*/
|
|
277
277
|
function channel(
|
|
278
|
-
topicFn: (ctx: LiveContext
|
|
278
|
+
topicFn: (ctx: LiveContext<any>, ...args: any[]) => string,
|
|
279
279
|
options?: { merge?: 'crud' | 'latest' | 'set' | 'presence' | 'cursor'; key?: string; max?: number }
|
|
280
280
|
): Function;
|
|
281
281
|
|
|
@@ -293,7 +293,7 @@ export namespace live {
|
|
|
293
293
|
* });
|
|
294
294
|
* ```
|
|
295
295
|
*/
|
|
296
|
-
function binary<T extends (ctx: LiveContext
|
|
296
|
+
function binary<T extends (ctx: LiveContext<any>, buffer: ArrayBuffer, ...args: any[]) => any>(
|
|
297
297
|
fn: T
|
|
298
298
|
): T;
|
|
299
299
|
|
|
@@ -314,7 +314,7 @@ export namespace live {
|
|
|
314
314
|
* });
|
|
315
315
|
* ```
|
|
316
316
|
*/
|
|
317
|
-
function middleware(fn: (ctx: LiveContext
|
|
317
|
+
function middleware(fn: (ctx: LiveContext<any>, next: () => Promise<any>) => Promise<any>): void;
|
|
318
318
|
|
|
319
319
|
/**
|
|
320
320
|
* Wrap a stream with a server-side gate predicate.
|
|
@@ -333,7 +333,7 @@ export namespace live {
|
|
|
333
333
|
* ```
|
|
334
334
|
*/
|
|
335
335
|
function gate<T extends Function>(
|
|
336
|
-
predicate: (ctx: LiveContext
|
|
336
|
+
predicate: (ctx: LiveContext<any>, ...args: any[]) => boolean,
|
|
337
337
|
fn: T
|
|
338
338
|
): T;
|
|
339
339
|
|
|
@@ -353,14 +353,14 @@ export namespace live {
|
|
|
353
353
|
* });
|
|
354
354
|
* ```
|
|
355
355
|
*/
|
|
356
|
-
function rateLimit<T extends (ctx: LiveContext
|
|
356
|
+
function rateLimit<T extends (ctx: LiveContext<any>, ...args: any[]) => any>(
|
|
357
357
|
config: {
|
|
358
358
|
/** Maximum number of calls allowed within the window. */
|
|
359
359
|
points: number;
|
|
360
360
|
/** Time window in milliseconds. */
|
|
361
361
|
window: number;
|
|
362
362
|
/** Custom key function. Defaults to `ctx.user.id`. */
|
|
363
|
-
key?(ctx: LiveContext): string;
|
|
363
|
+
key?(ctx: LiveContext<any>): string;
|
|
364
364
|
},
|
|
365
365
|
fn: T
|
|
366
366
|
): T;
|
|
@@ -381,7 +381,7 @@ export namespace live {
|
|
|
381
381
|
* });
|
|
382
382
|
* ```
|
|
383
383
|
*/
|
|
384
|
-
function validated<S, T extends (ctx: LiveContext
|
|
384
|
+
function validated<S, T extends (ctx: LiveContext<any>, input: any, ...args: any[]) => any>(
|
|
385
385
|
schema: S,
|
|
386
386
|
fn: T
|
|
387
387
|
): T;
|
|
@@ -572,15 +572,15 @@ export namespace live {
|
|
|
572
572
|
*/
|
|
573
573
|
const access: {
|
|
574
574
|
/** Only allow subscription if `ctx.user[field]` is present. Default field: `'id'`. */
|
|
575
|
-
owner(field?: string): (ctx: LiveContext) => boolean;
|
|
575
|
+
owner(field?: string): (ctx: LiveContext<any>) => boolean;
|
|
576
576
|
/** Role-based access: map role names to boolean or predicate. */
|
|
577
|
-
role(map: Record<string, true | ((ctx: LiveContext) => boolean)>): (ctx: LiveContext) => boolean;
|
|
577
|
+
role(map: Record<string, true | ((ctx: LiveContext<any>) => boolean)>): (ctx: LiveContext<any>) => boolean;
|
|
578
578
|
/** Only allow subscription if `ctx.user.teamId` is present. */
|
|
579
|
-
team(): (ctx: LiveContext) => boolean;
|
|
579
|
+
team(): (ctx: LiveContext<any>) => boolean;
|
|
580
580
|
/** OR logic: any predicate returning true allows the subscription. */
|
|
581
|
-
any(...predicates: Array<(ctx: LiveContext) => boolean>): (ctx: LiveContext) => boolean;
|
|
581
|
+
any(...predicates: Array<(ctx: LiveContext<any>) => boolean>): (ctx: LiveContext<any>) => boolean;
|
|
582
582
|
/** AND logic: all predicates must return true. */
|
|
583
|
-
all(...predicates: Array<(ctx: LiveContext) => boolean>): (ctx: LiveContext) => boolean;
|
|
583
|
+
all(...predicates: Array<(ctx: LiveContext<any>) => boolean>): (ctx: LiveContext<any>) => boolean;
|
|
584
584
|
};
|
|
585
585
|
}
|
|
586
586
|
|
|
@@ -589,21 +589,21 @@ export namespace live {
|
|
|
589
589
|
*/
|
|
590
590
|
export interface RoomConfig {
|
|
591
591
|
/** Function that computes the room topic from context and args. */
|
|
592
|
-
topic: (ctx: LiveContext
|
|
592
|
+
topic: (ctx: LiveContext<any>, ...args: any[]) => string;
|
|
593
593
|
/** Function that returns initial data for the room. */
|
|
594
|
-
init: (ctx: LiveContext
|
|
594
|
+
init: (ctx: LiveContext<any>, ...args: any[]) => Promise<any>;
|
|
595
595
|
/** Function that returns presence data for the connecting user. */
|
|
596
|
-
presence?: (ctx: LiveContext) => any;
|
|
596
|
+
presence?: (ctx: LiveContext<any>) => any;
|
|
597
597
|
/** Enable cursor tracking. Pass `true` or `{ throttle: ms }`. */
|
|
598
598
|
cursors?: boolean | { throttle?: number };
|
|
599
599
|
/** Room-scoped RPC actions. */
|
|
600
|
-
actions?: Record<string, (ctx: LiveContext
|
|
600
|
+
actions?: Record<string, (ctx: LiveContext<any>, ...args: any[]) => any>;
|
|
601
601
|
/** Guard function run before data access and actions. */
|
|
602
|
-
guard?: (ctx: LiveContext
|
|
602
|
+
guard?: (ctx: LiveContext<any>, ...args: any[]) => void | Promise<void>;
|
|
603
603
|
/** Called when a user joins the room. */
|
|
604
|
-
onJoin?: (ctx: LiveContext
|
|
604
|
+
onJoin?: (ctx: LiveContext<any>, ...args: any[]) => void | Promise<void>;
|
|
605
605
|
/** Called when a user leaves the room. */
|
|
606
|
-
onLeave?: (ctx: LiveContext
|
|
606
|
+
onLeave?: (ctx: LiveContext<any>, topic: string) => void | Promise<void>;
|
|
607
607
|
/** Merge strategy for the data stream. @default 'crud' */
|
|
608
608
|
merge?: string;
|
|
609
609
|
/** Key field for the data stream. @default 'id' */
|
|
@@ -649,8 +649,8 @@ export interface WebhookHandler {
|
|
|
649
649
|
* A stream transform step created by `pipe.filter`, `pipe.sort`, etc.
|
|
650
650
|
*/
|
|
651
651
|
export interface PipeTransform {
|
|
652
|
-
transformInit?(data: any[], ctx: LiveContext): any[] | Promise<any[]>;
|
|
653
|
-
transformEvent?(ctx: LiveContext
|
|
652
|
+
transformInit?(data: any[], ctx: LiveContext<any>): any[] | Promise<any[]>;
|
|
653
|
+
transformEvent?(ctx: LiveContext<any>, event: string, data: any): boolean;
|
|
654
654
|
}
|
|
655
655
|
|
|
656
656
|
/**
|
|
@@ -672,7 +672,7 @@ export interface PipeTransform {
|
|
|
672
672
|
export function pipe<T extends Function>(stream: T, ...transforms: PipeTransform[]): T;
|
|
673
673
|
export namespace pipe {
|
|
674
674
|
/** Filter items from initial data and drop non-matching live events. */
|
|
675
|
-
function filter(predicate: (ctx: LiveContext
|
|
675
|
+
function filter(predicate: (ctx: LiveContext<any>, item: any) => boolean): PipeTransform;
|
|
676
676
|
/** Sort initial data by a field. */
|
|
677
677
|
function sort(field: string, direction?: 'asc' | 'desc'): PipeTransform;
|
|
678
678
|
/** Cap initial data to N items. */
|
|
@@ -692,8 +692,8 @@ export namespace pipe {
|
|
|
692
692
|
* ```
|
|
693
693
|
*/
|
|
694
694
|
export function guard(
|
|
695
|
-
...fns: Array<(ctx: LiveContext) => void | Promise<void>>
|
|
696
|
-
): (ctx: LiveContext) => void | Promise<void>;
|
|
695
|
+
...fns: Array<(ctx: LiveContext<any>) => void | Promise<void>>
|
|
696
|
+
): (ctx: LiveContext<any>) => void | Promise<void>;
|
|
697
697
|
|
|
698
698
|
/**
|
|
699
699
|
* Typed error that propagates `code` and `message` to the client.
|
package/vite.js
CHANGED
|
@@ -552,13 +552,14 @@ function _generateSsrStubs(filePath, modulePath) {
|
|
|
552
552
|
|
|
553
553
|
for (const name of storeNames) {
|
|
554
554
|
if (dynamicNames.has(name)) {
|
|
555
|
-
// Dynamic stream:
|
|
556
|
-
lines.push(`const _${name} = (...args) => readable(undefined);`);
|
|
555
|
+
// Dynamic stream: factory returns a readable with .hydrate() for SSR rendering
|
|
556
|
+
lines.push(`const _${name} = (...args) => { const s = readable(undefined); s.hydrate = (d) => readable(d); return s; };`);
|
|
557
557
|
lines.push(`_${name}.load = (platform, options) => __directCall(${safeModulePath(name)}, options?.args || [], platform, options);`);
|
|
558
558
|
lines.push(`export { _${name} as ${name} };`);
|
|
559
559
|
} else {
|
|
560
|
-
// Static stream:
|
|
560
|
+
// Static stream: readable with .hydrate() for SSR rendering
|
|
561
561
|
lines.push(`const _${name} = readable(undefined);`);
|
|
562
|
+
lines.push(`_${name}.hydrate = (d) => readable(d);`);
|
|
562
563
|
lines.push(`_${name}.load = (platform, options) => __directCall(${safeModulePath(name)}, options?.args || [], platform, options);`);
|
|
563
564
|
lines.push(`export { _${name} as ${name} };`);
|
|
564
565
|
}
|
|
@@ -1551,7 +1552,7 @@ function _generateTypeDeclarations(liveDir, dir) {
|
|
|
1551
1552
|
const exports = [];
|
|
1552
1553
|
/** @type {Set<string>} */
|
|
1553
1554
|
const handledNames = new Set();
|
|
1554
|
-
let
|
|
1555
|
+
let needsStreamStore = false;
|
|
1555
1556
|
let needsRpcError = false;
|
|
1556
1557
|
|
|
1557
1558
|
// Detect live() exports
|
|
@@ -1597,23 +1598,25 @@ function _generateTypeDeclarations(liveDir, dir) {
|
|
|
1597
1598
|
while ((match = STREAM_EXPORT_RE.exec(source)) !== null) {
|
|
1598
1599
|
const name = match[1];
|
|
1599
1600
|
handledNames.add(name);
|
|
1600
|
-
|
|
1601
|
+
needsStreamStore = true;
|
|
1601
1602
|
needsRpcError = true;
|
|
1602
1603
|
const isDynamic = _isDynamicExport(source, name, 'live\\.stream');
|
|
1603
1604
|
if (isTS) {
|
|
1604
1605
|
const returnType = _extractStreamReturnType(source, name);
|
|
1605
|
-
const storeType = `
|
|
1606
|
+
const storeType = `StreamStore<${returnType} | undefined | { error: RpcError }>`;
|
|
1607
|
+
const loadSig = `{ load(platform: any, options?: { args?: any[] }): Promise<${returnType}> }`;
|
|
1606
1608
|
if (isDynamic) {
|
|
1607
1609
|
const factoryParams = _extractDynamicFactoryParams(source, name, 'live\\.stream');
|
|
1608
|
-
exports.push(` export const ${name}: ${factoryParams} => ${storeType};`);
|
|
1610
|
+
exports.push(` export const ${name}: (${factoryParams} => ${storeType}) & ${loadSig};`);
|
|
1609
1611
|
} else {
|
|
1610
|
-
exports.push(` export const ${name}: ${storeType};`);
|
|
1612
|
+
exports.push(` export const ${name}: ${storeType} & ${loadSig};`);
|
|
1611
1613
|
}
|
|
1612
1614
|
} else {
|
|
1615
|
+
const loadSig = `{ load(platform: any, options?: { args?: any[] }): Promise<any> }`;
|
|
1613
1616
|
if (isDynamic) {
|
|
1614
|
-
exports.push(` export const ${name}: (...args: any[]) =>
|
|
1617
|
+
exports.push(` export const ${name}: ((...args: any[]) => StreamStore<any>) & ${loadSig};`);
|
|
1615
1618
|
} else {
|
|
1616
|
-
exports.push(` export const ${name}:
|
|
1619
|
+
exports.push(` export const ${name}: StreamStore<any> & ${loadSig};`);
|
|
1617
1620
|
}
|
|
1618
1621
|
}
|
|
1619
1622
|
}
|
|
@@ -1624,17 +1627,18 @@ function _generateTypeDeclarations(liveDir, dir) {
|
|
|
1624
1627
|
const name = match[1];
|
|
1625
1628
|
handledNames.add(name);
|
|
1626
1629
|
if (!exports.some(e => e.includes(`export const ${name}:`))) {
|
|
1627
|
-
|
|
1630
|
+
needsStreamStore = true;
|
|
1628
1631
|
const isDynamic = _isDynamicExport(source, name, 'live\\.channel');
|
|
1632
|
+
const loadSig = `{ load(platform: any, options?: { args?: any[] }): Promise<any> }`;
|
|
1629
1633
|
if (isDynamic) {
|
|
1630
1634
|
if (isTS) {
|
|
1631
1635
|
const factoryParams = _extractDynamicFactoryParams(source, name, 'live\\.channel');
|
|
1632
|
-
exports.push(` export const ${name}: ${factoryParams} =>
|
|
1636
|
+
exports.push(` export const ${name}: (${factoryParams} => StreamStore<any>) & ${loadSig};`);
|
|
1633
1637
|
} else {
|
|
1634
|
-
exports.push(` export const ${name}: (...args: any[]) =>
|
|
1638
|
+
exports.push(` export const ${name}: ((...args: any[]) => StreamStore<any>) & ${loadSig};`);
|
|
1635
1639
|
}
|
|
1636
1640
|
} else {
|
|
1637
|
-
exports.push(` export const ${name}:
|
|
1641
|
+
exports.push(` export const ${name}: StreamStore<any> & ${loadSig};`);
|
|
1638
1642
|
}
|
|
1639
1643
|
}
|
|
1640
1644
|
}
|
|
@@ -1645,8 +1649,8 @@ function _generateTypeDeclarations(liveDir, dir) {
|
|
|
1645
1649
|
const name = match[1];
|
|
1646
1650
|
handledNames.add(name);
|
|
1647
1651
|
if (!exports.some(e => e.includes(`export const ${name}:`))) {
|
|
1648
|
-
|
|
1649
|
-
exports.push(` export const ${name}:
|
|
1652
|
+
needsStreamStore = true;
|
|
1653
|
+
exports.push(` export const ${name}: StreamStore<any> & { load(platform: any, options?: { args?: any[] }): Promise<any> };`);
|
|
1650
1654
|
}
|
|
1651
1655
|
}
|
|
1652
1656
|
|
|
@@ -1656,8 +1660,8 @@ function _generateTypeDeclarations(liveDir, dir) {
|
|
|
1656
1660
|
const name = match[1];
|
|
1657
1661
|
handledNames.add(name);
|
|
1658
1662
|
if (!exports.some(e => e.includes(`export const ${name}:`))) {
|
|
1659
|
-
|
|
1660
|
-
exports.push(` export const ${name}:
|
|
1663
|
+
needsStreamStore = true;
|
|
1664
|
+
exports.push(` export const ${name}: StreamStore<any> & { load(platform: any, options?: { args?: any[] }): Promise<any> };`);
|
|
1661
1665
|
}
|
|
1662
1666
|
}
|
|
1663
1667
|
|
|
@@ -1692,8 +1696,8 @@ function _generateTypeDeclarations(liveDir, dir) {
|
|
|
1692
1696
|
const name = match[1];
|
|
1693
1697
|
handledNames.add(name);
|
|
1694
1698
|
if (!exports.some(e => e.includes(`export const ${name}:`))) {
|
|
1695
|
-
|
|
1696
|
-
exports.push(` export const ${name}: { data: (...args: any[]) =>
|
|
1699
|
+
needsStreamStore = true;
|
|
1700
|
+
exports.push(` export const ${name}: { data: (...args: any[]) => StreamStore<any>, presence?: (...args: any[]) => StreamStore<any>, cursors?: (...args: any[]) => StreamStore<any>, [action: string]: (...args: any[]) => Promise<any> | ((...args: any[]) => StreamStore<any>) };`);
|
|
1697
1701
|
}
|
|
1698
1702
|
}
|
|
1699
1703
|
|
|
@@ -1702,13 +1706,13 @@ function _generateTypeDeclarations(liveDir, dir) {
|
|
|
1702
1706
|
|
|
1703
1707
|
if (exports.length > 0) {
|
|
1704
1708
|
declarations.push(`declare module '$live/${rel}' {`);
|
|
1705
|
-
if (
|
|
1706
|
-
|
|
1709
|
+
if (needsStreamStore || needsRpcError) {
|
|
1710
|
+
const clientImports = [];
|
|
1711
|
+
if (needsStreamStore) clientImports.push('StreamStore');
|
|
1712
|
+
if (needsRpcError) clientImports.push('RpcError');
|
|
1713
|
+
declarations.push(` import type { ${clientImports.join(', ')} } from 'svelte-realtime/client';`);
|
|
1707
1714
|
}
|
|
1708
|
-
if (needsRpcError) {
|
|
1709
|
-
declarations.push(" import type { RpcError } from 'svelte-realtime/client';");
|
|
1710
|
-
}
|
|
1711
|
-
if (needsReadable || needsRpcError) {
|
|
1715
|
+
if (needsStreamStore || needsRpcError) {
|
|
1712
1716
|
declarations.push('');
|
|
1713
1717
|
}
|
|
1714
1718
|
declarations.push(...exports);
|