@lunora/angular 1.0.0-alpha.214 → 1.0.0-alpha.215

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
@@ -84,24 +84,32 @@ liveQuery(api.messages.list, () => ({ channelId: this.channelId() }), {
84
84
 
85
85
  ## Live topics
86
86
 
87
- `liveTopic` follows one topic on the connection shared by its URL, and mirrors
88
- the last payload and any refusal into two signals: `lastEvent` and `error`. It
89
- subscribes when the component is created and unsubscribes on `DestroyRef`.
87
+ `liveTopic` follows one topic a `defineLiveStream` declares, and mirrors the last
88
+ payload and any refusal into two signals: `lastEvent` and `error`. Pass the
89
+ reference `_generated/live.ts` hands out; the stream's route is resolved against
90
+ the injected `LunoraClient`, and `lastEvent` and `onEvent` are typed by the payload
91
+ the topic declares. It subscribes when the component is created and unsubscribes
92
+ on `DestroyRef`.
90
93
 
91
94
  ```ts
92
95
  import { input } from "@angular/core";
93
96
  import { liveTopic } from "@lunora/angular";
94
97
 
98
+ import { live } from "../lunora/_generated/live";
99
+
95
100
  export class PostComponent {
96
101
  readonly postId = input.required<string>();
97
102
 
98
- readonly comments = liveTopic(() => ({ url: "/live/posts/connect", topic: `comments:${this.postId()}` }));
103
+ readonly comments = liveTopic(() => live.posts.comments({ postId: this.postId() }));
99
104
  }
100
105
  ```
101
106
 
102
- A new topic resubscribes; a new `onEvent` or `onError` callback is read at call
103
- time and does not. Pass `{ destroyRef, injector }` as the second argument when
104
- calling outside an injection context, as with `liveQuery`.
107
+ A function makes the topic reactive: a new topic resubscribes, while a new
108
+ `onEvent` or `onError` callback is read at call time and does not. A plain
109
+ reference resolves once. Pass `{ client, destroyRef, injector }` as the second
110
+ argument when calling outside an injection context, as with `liveQuery`; the
111
+ options also take `shardKey` and `sessionKey` (each a string or a signal, which resubscribes on change) and the transport tuning `headers`,
112
+ `withCredentials`, `retryDelay` and `maxDelayMs`.
105
113
 
106
114
  ## Mutations
107
115
 
package/dist/index.d.mts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { DestroyRef, Signal, InjectionToken, EnvironmentProviders, Injector } from '@angular/core';
2
- import { FunctionReference, LunoraClient, SubscriptionErrorCallback, SubscriptionError, User, LunoraClientOptions, ConnectionStatus, Preloaded, ArgsOf, ReturnOf, SubscribeLiveTopicOptions, LiveStreamSubscribeError, MutationCallOptions, MutatorHandle, ActionCallOptions } from '@lunora/client';
2
+ import { FunctionReference, LunoraClient, SubscriptionErrorCallback, SubscriptionError, User, LunoraClientOptions, ConnectionStatus, Preloaded, ArgsOf, ReturnOf, LiveTopicOptions as LiveTopicOptions$1, LiveTopicRef, LiveStreamSubscribeError, MutationCallOptions, MutatorHandle, ActionCallOptions } from '@lunora/client';
3
3
  export type { ArgsOf, ConnectionStatus, FunctionReference, LunoraClient, LunoraClientOptions, MutationCallOptions, Preloaded, ReturnOf, SubscriptionError, Unsubscribe } from '@lunora/client';
4
4
  import { AuthStatus } from '@lunora/client/auth';
5
5
  import { PaginationStatus } from '@lunora/client/pagination';
@@ -844,7 +844,12 @@ declare const liveQuery: <F extends FunctionReference>(reference: F, args: ArgsO
844
844
  * `LiveTopicOptions` is part of the experimental `@lunora/angular` API and may change without a major version bump.
845
845
  * @experimental
846
846
  */
847
- interface LiveTopicOptions {
847
+ interface LiveTopicOptions<Payload = unknown> extends Omit<LiveTopicOptions$1<Payload>, "sessionKey" | "shardKey"> {
848
+ /**
849
+ * The client the stream's route is resolved against. Defaults to `LUNORA_CLIENT`, read in the
850
+ * ambient injection context, so pass it when calling outside one (with an explicit `destroyRef`).
851
+ */
852
+ client?: LunoraClient;
848
853
  /**
849
854
  * `DestroyRef` whose `onDestroy` tears the subscription down. Defaults to
850
855
  * `inject(DestroyRef)` — the calling component/service.
@@ -852,14 +857,27 @@ interface LiveTopicOptions {
852
857
  destroyRef?: DestroyRef;
853
858
  /**
854
859
  * `Injector` to create the reactive-args `effect()` from. Only needed when the
855
- * options are a function AND `liveTopic` is called outside an injection context
860
+ * topic is a function AND `liveTopic` is called outside an injection context
856
861
  * with an explicit `destroyRef`. Unused for the static form.
857
862
  */
858
863
  injector?: Injector;
864
+ /**
865
+ * Partitions the shared live connection, as `sessionKey` does on `subscribeLiveTopic`: a changed value opens a new
866
+ * connection and closes the old one. Pass a signal (or any function) to make it reactive, e.g. to move to a new
867
+ * key on sign-out.
868
+ */
869
+ sessionKey?: string | (() => string | undefined);
870
+ /**
871
+ * Follow the topic on this shard, as `shardKey` does on the other adapters. Pass a signal (or any function) when the
872
+ * shard comes from an input or other state that changes: a new value reopens the subscription on the new shard.
873
+ */
874
+ shardKey?: string | (() => string | undefined);
859
875
  }
860
876
  /**
861
- * Follow one live topic on the connection shared by its URL, and mirror its
862
- * payloads into an Angular `signal`.
877
+ * Follow one live topic on the connection shared by its stream's route, and mirror its
878
+ * payloads into an Angular `signal`. Pass the reference `_generated/live.ts` hands out
879
+ * (`live.posts.post({ postId })`); the route is resolved against the injected `LunoraClient`,
880
+ * and `lastEvent` and `onEvent` are typed by the payload the topic declares.
863
881
  *
864
882
  * `lastEvent` reads `undefined` until the first event lands; `error` carries the
865
883
  * shard's refusal of the subscription. The subscription is torn down when the
@@ -869,20 +887,19 @@ interface LiveTopicOptions {
869
887
  * export class PostComponent {
870
888
  * readonly postId = input.required<string>();
871
889
  *
872
- * readonly comments = liveTopic(() => ({ url: "/live/posts/connect", topic: `comments:${this.postId()}` }));
890
+ * readonly comments = liveTopic(() => live.posts.post({ postId: this.postId() }));
873
891
  * }
874
892
  * ```
875
893
  *
876
- * Pass a function when the options read a signal, as above: an input is not bound
877
- * while a field initializer runs, so the plain-object form would read `this.postId`
878
- * too early. An options change (a new topic, say) resubscribes, while a new
879
- * `onEvent` / `onError` identity is read at call time and does not reopen the
880
- * subscription.
894
+ * Pass a function when the topic reads a signal, as above: an input is not bound while a field
895
+ * initializer runs, so a plain reference would read `this.postId` too early. A new topic, or a new
896
+ * `sessionKey` or `shardKey` signal value, resubscribes, while a new `onEvent` / `onError` identity is read at
897
+ * call time and does not reopen the subscription.
881
898
  * @experimental
882
899
  */
883
- declare const liveTopic: (source: SubscribeLiveTopicOptions | (() => SubscribeLiveTopicOptions), options?: LiveTopicOptions) => {
900
+ declare const liveTopic: <Payload>(topic: LiveTopicRef<Payload> | (() => LiveTopicRef<Payload>), options?: LiveTopicOptions<Payload>) => {
884
901
  error: Signal<LiveStreamSubscribeError | undefined>;
885
- lastEvent: Signal<unknown>;
902
+ lastEvent: Signal<Payload | undefined>;
886
903
  };
887
904
  /**
888
905
  * `MutateOptions` is part of the experimental `@lunora/angular` API and may change without a major version bump.
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { DestroyRef, Signal, InjectionToken, EnvironmentProviders, Injector } from '@angular/core';
2
- import { FunctionReference, LunoraClient, SubscriptionErrorCallback, SubscriptionError, User, LunoraClientOptions, ConnectionStatus, Preloaded, ArgsOf, ReturnOf, SubscribeLiveTopicOptions, LiveStreamSubscribeError, MutationCallOptions, MutatorHandle, ActionCallOptions } from '@lunora/client';
2
+ import { FunctionReference, LunoraClient, SubscriptionErrorCallback, SubscriptionError, User, LunoraClientOptions, ConnectionStatus, Preloaded, ArgsOf, ReturnOf, LiveTopicOptions as LiveTopicOptions$1, LiveTopicRef, LiveStreamSubscribeError, MutationCallOptions, MutatorHandle, ActionCallOptions } from '@lunora/client';
3
3
  export type { ArgsOf, ConnectionStatus, FunctionReference, LunoraClient, LunoraClientOptions, MutationCallOptions, Preloaded, ReturnOf, SubscriptionError, Unsubscribe } from '@lunora/client';
4
4
  import { AuthStatus } from '@lunora/client/auth';
5
5
  import { PaginationStatus } from '@lunora/client/pagination';
@@ -844,7 +844,12 @@ declare const liveQuery: <F extends FunctionReference>(reference: F, args: ArgsO
844
844
  * `LiveTopicOptions` is part of the experimental `@lunora/angular` API and may change without a major version bump.
845
845
  * @experimental
846
846
  */
847
- interface LiveTopicOptions {
847
+ interface LiveTopicOptions<Payload = unknown> extends Omit<LiveTopicOptions$1<Payload>, "sessionKey" | "shardKey"> {
848
+ /**
849
+ * The client the stream's route is resolved against. Defaults to `LUNORA_CLIENT`, read in the
850
+ * ambient injection context, so pass it when calling outside one (with an explicit `destroyRef`).
851
+ */
852
+ client?: LunoraClient;
848
853
  /**
849
854
  * `DestroyRef` whose `onDestroy` tears the subscription down. Defaults to
850
855
  * `inject(DestroyRef)` — the calling component/service.
@@ -852,14 +857,27 @@ interface LiveTopicOptions {
852
857
  destroyRef?: DestroyRef;
853
858
  /**
854
859
  * `Injector` to create the reactive-args `effect()` from. Only needed when the
855
- * options are a function AND `liveTopic` is called outside an injection context
860
+ * topic is a function AND `liveTopic` is called outside an injection context
856
861
  * with an explicit `destroyRef`. Unused for the static form.
857
862
  */
858
863
  injector?: Injector;
864
+ /**
865
+ * Partitions the shared live connection, as `sessionKey` does on `subscribeLiveTopic`: a changed value opens a new
866
+ * connection and closes the old one. Pass a signal (or any function) to make it reactive, e.g. to move to a new
867
+ * key on sign-out.
868
+ */
869
+ sessionKey?: string | (() => string | undefined);
870
+ /**
871
+ * Follow the topic on this shard, as `shardKey` does on the other adapters. Pass a signal (or any function) when the
872
+ * shard comes from an input or other state that changes: a new value reopens the subscription on the new shard.
873
+ */
874
+ shardKey?: string | (() => string | undefined);
859
875
  }
860
876
  /**
861
- * Follow one live topic on the connection shared by its URL, and mirror its
862
- * payloads into an Angular `signal`.
877
+ * Follow one live topic on the connection shared by its stream's route, and mirror its
878
+ * payloads into an Angular `signal`. Pass the reference `_generated/live.ts` hands out
879
+ * (`live.posts.post({ postId })`); the route is resolved against the injected `LunoraClient`,
880
+ * and `lastEvent` and `onEvent` are typed by the payload the topic declares.
863
881
  *
864
882
  * `lastEvent` reads `undefined` until the first event lands; `error` carries the
865
883
  * shard's refusal of the subscription. The subscription is torn down when the
@@ -869,20 +887,19 @@ interface LiveTopicOptions {
869
887
  * export class PostComponent {
870
888
  * readonly postId = input.required<string>();
871
889
  *
872
- * readonly comments = liveTopic(() => ({ url: "/live/posts/connect", topic: `comments:${this.postId()}` }));
890
+ * readonly comments = liveTopic(() => live.posts.post({ postId: this.postId() }));
873
891
  * }
874
892
  * ```
875
893
  *
876
- * Pass a function when the options read a signal, as above: an input is not bound
877
- * while a field initializer runs, so the plain-object form would read `this.postId`
878
- * too early. An options change (a new topic, say) resubscribes, while a new
879
- * `onEvent` / `onError` identity is read at call time and does not reopen the
880
- * subscription.
894
+ * Pass a function when the topic reads a signal, as above: an input is not bound while a field
895
+ * initializer runs, so a plain reference would read `this.postId` too early. A new topic, or a new
896
+ * `sessionKey` or `shardKey` signal value, resubscribes, while a new `onEvent` / `onError` identity is read at
897
+ * call time and does not reopen the subscription.
881
898
  * @experimental
882
899
  */
883
- declare const liveTopic: (source: SubscribeLiveTopicOptions | (() => SubscribeLiveTopicOptions), options?: LiveTopicOptions) => {
900
+ declare const liveTopic: <Payload>(topic: LiveTopicRef<Payload> | (() => LiveTopicRef<Payload>), options?: LiveTopicOptions<Payload>) => {
884
901
  error: Signal<LiveStreamSubscribeError | undefined>;
885
- lastEvent: Signal<unknown>;
902
+ lastEvent: Signal<Payload | undefined>;
886
903
  };
887
904
  /**
888
905
  * `MutateOptions` is part of the experimental `@lunora/angular` API and may change without a major version bump.
package/dist/index.mjs CHANGED
@@ -1 +1 @@
1
- import{agent as e}from"./packem_shared/agent-DjMQf-yE.mjs";import{agentChat as p}from"./packem_shared/agentChat-DyJrje49.mjs";import{agentState as f}from"./packem_shared/agentState-Bjqf9q2f.mjs";import{agentToolEvents as x}from"./packem_shared/agentToolEvents-VuBRpS6v.mjs";import{auth as i,authGate as u}from"./packem_shared/auth-C3dB8sYS.mjs";import{LUNORA_CLIENT as g,injectLunoraClient as l,provideLunora as s}from"./packem_shared/LUNORA_CLIENT-B0toApHY.mjs";import{connectionStatus as v}from"./packem_shared/connectionStatus-UhmuwzMa.mjs";import{flag as h,flags as y}from"./packem_shared/flag-BDKBQGos.mjs";import{hydratePreloaded as C}from"./packem_shared/hydratePreloaded-QPAo50Am.mjs";import{liveQuery as S}from"./packem_shared/liveQuery-eE9zMaxo.mjs";import{liveTopic as E}from"./packem_shared/liveTopic-rphiqpWi.mjs";import{mutate as N}from"./packem_shared/mutate-BZvLQLyu.mjs";import{mutator as b}from"./packem_shared/mutator-DjG1yGk8.mjs";import{infiniteQuery as G,paginatedQuery as K}from"./packem_shared/infiniteQuery-DGYdgFHW.mjs";import{presence as R}from"./packem_shared/presence-1T4-U8ij.mjs";import{rateLimit as _}from"./packem_shared/rateLimit-B3h9qzh-.mjs";import{runAction as q}from"./packem_shared/runAction-BfiPq4Xz.mjs";import{stream as z}from"./packem_shared/stream-BuhiwhIH.mjs";import{subscription as D}from"./packem_shared/subscription-zJv48q6C.mjs";import{voiceAgent as H}from"./packem_shared/voiceAgent-CH--tRWP.mjs";import{SKIP as M}from"@lunora/client/query";export{g as LUNORA_CLIENT,M as SKIP,e as agent,p as agentChat,f as agentState,x as agentToolEvents,i as auth,u as authGate,v as connectionStatus,h as flag,y as flags,C as hydratePreloaded,G as infiniteQuery,l as injectLunoraClient,S as liveQuery,E as liveTopic,N as mutate,b as mutator,K as paginatedQuery,R as presence,s as provideLunora,_ as rateLimit,q as runAction,z as stream,D as subscription,H as voiceAgent};
1
+ import{agent as e}from"./packem_shared/agent-DjMQf-yE.mjs";import{agentChat as p}from"./packem_shared/agentChat-DyJrje49.mjs";import{agentState as f}from"./packem_shared/agentState-Bjqf9q2f.mjs";import{agentToolEvents as x}from"./packem_shared/agentToolEvents-VuBRpS6v.mjs";import{auth as i,authGate as u}from"./packem_shared/auth-C3dB8sYS.mjs";import{LUNORA_CLIENT as g,injectLunoraClient as l,provideLunora as s}from"./packem_shared/LUNORA_CLIENT-B0toApHY.mjs";import{connectionStatus as v}from"./packem_shared/connectionStatus-UhmuwzMa.mjs";import{flag as h,flags as y}from"./packem_shared/flag-BDKBQGos.mjs";import{hydratePreloaded as C}from"./packem_shared/hydratePreloaded-QPAo50Am.mjs";import{liveQuery as S}from"./packem_shared/liveQuery-eE9zMaxo.mjs";import{liveTopic as E}from"./packem_shared/liveTopic-Cz1BDkMP.mjs";import{mutate as N}from"./packem_shared/mutate-BZvLQLyu.mjs";import{mutator as b}from"./packem_shared/mutator-DjG1yGk8.mjs";import{infiniteQuery as G,paginatedQuery as K}from"./packem_shared/infiniteQuery-DGYdgFHW.mjs";import{presence as R}from"./packem_shared/presence-1T4-U8ij.mjs";import{rateLimit as _}from"./packem_shared/rateLimit-B3h9qzh-.mjs";import{runAction as q}from"./packem_shared/runAction-BfiPq4Xz.mjs";import{stream as z}from"./packem_shared/stream-BuhiwhIH.mjs";import{subscription as D}from"./packem_shared/subscription-zJv48q6C.mjs";import{voiceAgent as H}from"./packem_shared/voiceAgent-CH--tRWP.mjs";import{SKIP as M}from"@lunora/client/query";export{g as LUNORA_CLIENT,M as SKIP,e as agent,p as agentChat,f as agentState,x as agentToolEvents,i as auth,u as authGate,v as connectionStatus,h as flag,y as flags,C as hydratePreloaded,G as infiniteQuery,l as injectLunoraClient,S as liveQuery,E as liveTopic,N as mutate,b as mutator,K as paginatedQuery,R as presence,s as provideLunora,_ as rateLimit,q as runAction,z as stream,D as subscription,H as voiceAgent};
@@ -0,0 +1 @@
1
+ import{inject as D,DestroyRef as E,signal as d}from"@angular/core";import{liveTopicSubscription as K,subscribeLiveTopic as p}from"@lunora/client";import{resolveLunoraClient as j}from"./LUNORA_CLIENT-B0toApHY.mjs";import{s as x,a as C}from"./platform-DGTu4Ucl.mjs";const v=e=>({headers:e.headers,maxDelayMs:e.maxDelayMs,retryDelay:e.retryDelay,sessionKey:e.sessionKey,topic:e.topic,url:e.url,withCredentials:e.withCredentials}),L=(e,t={})=>{const u=j(t.client),m=t.destroyRef===void 0,i=t.destroyRef??D(E),n=d(void 0),s=d(void 0),h=typeof e=="function"?e:()=>e,{sessionKey:c,shardKey:y}=t,f=r=>typeof r=="function"?r():r,a=()=>K(u,h(),{...t,sessionKey:f(c),shardKey:f(y)}),l=(r,b)=>{n.set(void 0),s.set(void 0);const R=p({...r,onError:o=>{s.set(o),t.onError?.(o)},onEvent:o=>{n.set(o),s.set(void 0),t.onEvent?.(o)}});b(R)};return x(m)&&(typeof e=="function"||typeof c=="function"||typeof y=="function"?C(()=>v(a()),{destroyRef:i,injector:t.injector},l):l(v(a()),r=>i.onDestroy(r))),{error:s.asReadonly(),lastEvent:n.asReadonly()}};export{L as liveTopic};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lunora/angular",
3
- "version": "1.0.0-alpha.214",
3
+ "version": "1.0.0-alpha.215",
4
4
  "description": "Angular reactive adapter for Lunora — signal-based live queries and mutations",
5
5
  "keywords": [
6
6
  "angular",
@@ -53,8 +53,8 @@
53
53
  "access": "public"
54
54
  },
55
55
  "dependencies": {
56
- "@lunora/client": "1.0.0-alpha.228",
57
- "@lunora/ratelimit": "1.0.0-alpha.151",
56
+ "@lunora/client": "1.0.0-alpha.229",
57
+ "@lunora/ratelimit": "1.0.0-alpha.152",
58
58
  "@lunora/wire": "1.0.0-alpha.1",
59
59
  "@visulima/storage-client": "1.0.9"
60
60
  },
@@ -1 +0,0 @@
1
- import{inject as m,DestroyRef as R,signal as y}from"@angular/core";import{subscribeLiveTopic as h}from"@lunora/client";import{s as u,a as D}from"./platform-DGTu4Ucl.mjs";const d=e=>({headers:e.headers,maxDelayMs:e.maxDelayMs,retryDelay:e.retryDelay,sessionKey:e.sessionKey,topic:e.topic,url:e.url,withCredentials:e.withCredentials}),p=(e,o={})=>{const l=o.destroyRef===void 0,c=o.destroyRef??m(R),n=y(void 0),r=y(void 0),s=typeof e=="function"?e:()=>e,a=(i,f)=>{n.set(void 0),r.set(void 0);const v=h({...i,onError:t=>{r.set(t),s().onError?.(t)},onEvent:t=>{n.set(t),r.set(void 0),s().onEvent?.(t)}});f(v)};return u(l)&&(typeof e=="function"?D(()=>d(s()),{destroyRef:c,injector:o.injector},a):a(d(e),i=>c.onDestroy(i))),{error:r.asReadonly(),lastEvent:n.asReadonly()}};export{p as liveTopic};