ras-stack 0.24.0 → 0.25.0
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
|
@@ -236,7 +236,7 @@ const subscription = useRealtimeSubscription({ client, channel, options, configu
|
|
|
236
236
|
const clients = useRealtimePresence(subscription)
|
|
237
237
|
```
|
|
238
238
|
|
|
239
|
-
The factory, subscription options, and configure callback should have stable identities and change only when their corresponding lifecycle should restart.
|
|
239
|
+
The client factory may return a client or a promise, so applications can fetch and validate an initial ticket before connecting. Pass `onError` as the third argument to handle asynchronous ticket failures. A client that resolves after unmount is disconnected without ever connecting. The factory, error handler, subscription options, and configure callback should have stable identities and change only when their corresponding lifecycle should restart.
|
|
240
240
|
|
|
241
241
|
The client helpers return the underlying Centrifuge client and subscription. React ownership, channel conventions, ticket validation, event parsing, presence models, and query invalidation remain application code. `publish()` returns `false` when the publisher is closed, disabled, or at capacity. `close()` rejects new work and waits for accepted publications and their bounded retries to finish.
|
|
242
242
|
|
package/dist/realtime/react.d.ts
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import type { Centrifuge, ClientInfo, Subscription, SubscriptionOptions } from 'centrifuge';
|
|
2
|
-
export declare function useConnectedRealtimeClient(create: () => Centrifuge
|
|
2
|
+
export declare function useConnectedRealtimeClient(create: () => Centrifuge | Promise<Centrifuge>, enabled?: boolean, options?: {
|
|
3
|
+
configure?: (client: Centrifuge) => void | (() => void);
|
|
4
|
+
onError?: (error: unknown) => void;
|
|
5
|
+
}): Centrifuge | undefined;
|
|
3
6
|
export type RealtimeSubscriptionHookOptions = {
|
|
4
7
|
client?: Centrifuge;
|
|
5
8
|
channel?: string;
|
package/dist/realtime/react.js
CHANGED
|
@@ -1,16 +1,49 @@
|
|
|
1
1
|
import { useEffect, useState } from 'react';
|
|
2
2
|
import { connectRealtimeClient, openRealtimeSubscription, watchSubscriptionPresence } from './client.js';
|
|
3
|
-
export function useConnectedRealtimeClient(create, enabled = true) {
|
|
3
|
+
export function useConnectedRealtimeClient(create, enabled = true, options = {}) {
|
|
4
4
|
const [client, setClient] = useState();
|
|
5
|
+
const configure = options.configure;
|
|
6
|
+
const onError = options.onError;
|
|
5
7
|
useEffect(() => {
|
|
6
8
|
if (!enabled) {
|
|
7
9
|
setClient(undefined);
|
|
8
10
|
return undefined;
|
|
9
11
|
}
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
12
|
+
let active = true;
|
|
13
|
+
let cleanup;
|
|
14
|
+
let disconnect;
|
|
15
|
+
const connect = (next) => {
|
|
16
|
+
if (!active) {
|
|
17
|
+
next.disconnect();
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
try {
|
|
21
|
+
cleanup = configure?.(next) ?? undefined;
|
|
22
|
+
}
|
|
23
|
+
catch (error) {
|
|
24
|
+
next.disconnect();
|
|
25
|
+
onError?.(error);
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
setClient(next);
|
|
29
|
+
disconnect = connectRealtimeClient(next);
|
|
30
|
+
};
|
|
31
|
+
try {
|
|
32
|
+
const created = create();
|
|
33
|
+
if (created instanceof Promise)
|
|
34
|
+
void created.then(connect, (error) => active && onError?.(error));
|
|
35
|
+
else
|
|
36
|
+
connect(created);
|
|
37
|
+
}
|
|
38
|
+
catch (error) {
|
|
39
|
+
onError?.(error);
|
|
40
|
+
}
|
|
41
|
+
return () => {
|
|
42
|
+
active = false;
|
|
43
|
+
cleanup?.();
|
|
44
|
+
disconnect?.();
|
|
45
|
+
};
|
|
46
|
+
}, [configure, create, enabled, onError]);
|
|
14
47
|
return client;
|
|
15
48
|
}
|
|
16
49
|
export function useRealtimeSubscription(options) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"react.js","sourceRoot":"","sources":["../../src/realtime/react.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAA;AAC3C,OAAO,EAAE,qBAAqB,EAAE,wBAAwB,EAAE,yBAAyB,EAAE,MAAM,aAAa,CAAA;AAExG,MAAM,UAAU,0BAA0B,
|
|
1
|
+
{"version":3,"file":"react.js","sourceRoot":"","sources":["../../src/realtime/react.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Centrifuge, ClientInfo, Subscription, SubscriptionOptions } from 'centrifuge'\nimport { useEffect, useState } from 'react'\nimport { connectRealtimeClient, openRealtimeSubscription, watchSubscriptionPresence } from './client.js'\n\nexport function useConnectedRealtimeClient(\n create: () => Centrifuge | Promise<Centrifuge>,\n enabled = true,\n options: { configure?: (client: Centrifuge) => void | (() => void); onError?: (error: unknown) => void } = {},\n) {\n const [client, setClient] = useState<Centrifuge>()\n const configure = options.configure\n const onError = options.onError\n useEffect(() => {\n if (!enabled) {\n setClient(undefined)\n return undefined\n }\n let active = true\n let cleanup: (() => void) | undefined\n let disconnect: (() => void) | undefined\n const connect = (next: Centrifuge) => {\n if (!active) {\n next.disconnect()\n return\n }\n try {\n cleanup = configure?.(next) ?? undefined\n } catch (error) {\n next.disconnect()\n onError?.(error)\n return\n }\n setClient(next)\n disconnect = connectRealtimeClient(next)\n }\n try {\n const created = create()\n if (created instanceof Promise) void created.then(connect, (error: unknown) => active && onError?.(error))\n else connect(created)\n } catch (error) {\n onError?.(error)\n }\n return () => {\n active = false\n cleanup?.()\n disconnect?.()\n }\n }, [configure, create, enabled, onError])\n return client\n}\n\nexport type RealtimeSubscriptionHookOptions = {\n client?: Centrifuge\n channel?: string\n enabled?: boolean\n options?: SubscriptionOptions\n configure?: (subscription: Subscription) => void | (() => void)\n}\n\nexport function useRealtimeSubscription(options: RealtimeSubscriptionHookOptions) {\n const [subscription, setSubscription] = useState<Subscription>()\n const { channel, client, configure, enabled = true, options: subscriptionOptions } = options\n useEffect(() => {\n if (!enabled || !client || !channel) {\n setSubscription(undefined)\n return undefined\n }\n const opened = openRealtimeSubscription(client, channel, subscriptionOptions, configure)\n setSubscription(opened.subscription)\n return opened.close\n }, [channel, client, configure, enabled, subscriptionOptions])\n return subscription\n}\n\nexport function useRealtimePresence(subscription: Subscription | undefined, options: { onError?: (error: unknown) => void } = {}) {\n const [clients, setClients] = useState<Record<string, ClientInfo>>({})\n const onError = options.onError\n useEffect(() => {\n if (!subscription) {\n setClients({})\n return undefined\n }\n let active = true\n const stop = watchSubscriptionPresence(\n subscription,\n (next) => {\n if (active) setClients(next)\n },\n onError ? { onError } : {},\n )\n return () => {\n active = false\n stop()\n }\n }, [onError, subscription])\n return clients\n}\n"]}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type OriginOptions } from '../auth/
|
|
1
|
+
import { type OriginOptions } from '../auth/origins.js';
|
|
2
2
|
import { type CanonicalRedirectOptions, type HealthResponseOptions, type RpcOptions } from '../server/index.js';
|
|
3
3
|
export type TanStackRpcOptions = Omit<RpcOptions, 'getRequest'> & Pick<RpcOptions, 'getRequest'>;
|
|
4
4
|
export declare function createTanStackRpc(options?: TanStackRpcOptions): {
|
package/dist/tanstack/server.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { getRequest } from '@tanstack/react-start/server';
|
|
2
2
|
import { createMiddleware } from '@tanstack/react-start';
|
|
3
|
-
import { requireSameOrigin } from '../auth/
|
|
3
|
+
import { requireSameOrigin } from '../auth/origins.js';
|
|
4
4
|
import { canonicalRedirect, createRpc, healthResponse, } from '../server/index.js';
|
|
5
5
|
export function createTanStackRpc(options = {}) {
|
|
6
6
|
return createRpc({ ...options, getRequest: options.getRequest ?? getRequest });
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/tanstack/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,8BAA8B,CAAA;AACzD,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAA;AACxD,OAAO,EAAE,iBAAiB,EAAsB,MAAM,
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/tanstack/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,8BAA8B,CAAA;AACzD,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAA;AACxD,OAAO,EAAE,iBAAiB,EAAsB,MAAM,oBAAoB,CAAA;AAC1E,OAAO,EACL,iBAAiB,EACjB,SAAS,EACT,cAAc,GAIf,MAAM,oBAAoB,CAAA;AAI3B,MAAM,UAAU,iBAAiB,CAAC,OAAO,GAAuB,EAAE;IAChE,OAAO,SAAS,CAAC,EAAE,GAAG,OAAO,EAAE,UAAU,EAAE,OAAO,CAAC,UAAU,IAAI,UAAU,EAAE,CAAC,CAAA;AAChF,CAAC;AAED,MAAM,UAAU,6BAA6B,CAAC,OAAO,GAAkB,EAAE,EAAE,OAAO,GAAG,UAAU,EAAE;IAC/F,OAAO,iBAAiB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAA;AAC5C,CAAC;AAID,MAAM,UAAU,kBAAkB,CAAC,WAA8E;IAC/G,MAAM,MAAM,GAAG,CAAC,EAAE,OAAO,EAAkB,EAAE,EAAE,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC,CAAA;IAC9E,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,CAAA;AACtC,CAAC;AAED,MAAM,UAAU,qBAAqB,CAAC,KAAiC,EAAE,OAAO,GAA0B,EAAE;IAC1G,OAAO,GAAG,EAAE,CAAC,cAAc,CAAC,KAAK,EAAE,OAAO,CAAC,CAAA;AAC7C,CAAC;AAED,MAAM,UAAU,oBAAoB,CAAI,OAAgB,EAAE,IAAa,EAAE,OAAiC;IACxG,MAAM,QAAQ,GAAG,iBAAiB,CAAC,OAAO,CAAC,GAAG,EAAE,OAAO,CAAC,CAAA;IACxD,OAAO,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAA;AAC7D,CAAC;AAED,MAAM,UAAU,uBAAuB,CAAC,cAA8C;IACpF,OAAO,gBAAgB,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,EAAE,EAAE;QACxE,OAAO,oBAAoB,CAAC,OAAO,EAAE,IAAI,EAAE,cAAc,EAAE,CAAC,CAAA;IAC9D,CAAC,CAAC,CAAA;AACJ,CAAC","sourcesContent":["import { getRequest } from '@tanstack/react-start/server'\nimport { createMiddleware } from '@tanstack/react-start'\nimport { requireSameOrigin, type OriginOptions } from '../auth/origins.js'\nimport {\n canonicalRedirect,\n createRpc,\n healthResponse,\n type CanonicalRedirectOptions,\n type HealthResponseOptions,\n type RpcOptions,\n} from '../server/index.js'\n\nexport type TanStackRpcOptions = Omit<RpcOptions, 'getRequest'> & Pick<RpcOptions, 'getRequest'>\n\nexport function createTanStackRpc(options: TanStackRpcOptions = {}) {\n return createRpc({ ...options, getRequest: options.getRequest ?? getRequest })\n}\n\nexport function requireTanStackMutationOrigin(options: OriginOptions = {}, request = getRequest()) {\n return requireSameOrigin(request, options)\n}\n\ntype RequestContext = { request: Request }\n\nexport function betterAuthHandlers(resolveAuth: () => { handler(request: Request): Response | Promise<Response> }) {\n const handle = ({ request }: RequestContext) => resolveAuth().handler(request)\n return { GET: handle, POST: handle }\n}\n\nexport function tanStackHealthHandler(check: () => void | Promise<void>, options: HealthResponseOptions = {}) {\n return () => healthResponse(check, options)\n}\n\nexport function canonicalHostRequest<T>(request: Request, next: () => T, options: CanonicalRedirectOptions): Response | T {\n const redirect = canonicalRedirect(request.url, options)\n return redirect ? Response.redirect(redirect, 301) : next()\n}\n\nexport function canonicalHostMiddleware(resolveOptions: () => CanonicalRedirectOptions) {\n return createMiddleware({ type: 'request' }).server(({ request, next }) => {\n return canonicalHostRequest(request, next, resolveOptions())\n })\n}\n"]}
|