@assistant-ui/store 0.0.2 → 0.0.3

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.
Files changed (155) hide show
  1. package/README.md +59 -262
  2. package/dist/AssistantIf.d.ts +4 -6
  3. package/dist/AssistantIf.d.ts.map +1 -1
  4. package/dist/AssistantIf.js +1 -4
  5. package/dist/AssistantIf.js.map +1 -1
  6. package/dist/Derived.d.ts +34 -0
  7. package/dist/Derived.d.ts.map +1 -0
  8. package/dist/Derived.js +11 -0
  9. package/dist/Derived.js.map +1 -0
  10. package/dist/attachDefaultPeers.d.ts +56 -0
  11. package/dist/attachDefaultPeers.d.ts.map +1 -0
  12. package/dist/attachDefaultPeers.js +22 -0
  13. package/dist/attachDefaultPeers.js.map +1 -0
  14. package/dist/index.d.ts +10 -9
  15. package/dist/index.d.ts.map +1 -1
  16. package/dist/index.js +17 -13
  17. package/dist/index.js.map +1 -1
  18. package/dist/tapClientList.d.ts +24 -0
  19. package/dist/tapClientList.d.ts.map +1 -0
  20. package/dist/tapClientList.js +72 -0
  21. package/dist/tapClientList.js.map +1 -0
  22. package/dist/tapClientLookup.d.ts +11 -0
  23. package/dist/tapClientLookup.d.ts.map +1 -0
  24. package/dist/tapClientLookup.js +42 -0
  25. package/dist/tapClientLookup.js.map +1 -0
  26. package/dist/tapClientResource.d.ts +24 -0
  27. package/dist/tapClientResource.d.ts.map +1 -0
  28. package/dist/tapClientResource.js +100 -0
  29. package/dist/tapClientResource.js.map +1 -0
  30. package/dist/types/client.d.ts +117 -0
  31. package/dist/types/client.d.ts.map +1 -0
  32. package/dist/types/client.js +1 -0
  33. package/dist/types/events.d.ts +33 -0
  34. package/dist/types/events.d.ts.map +1 -0
  35. package/dist/types/events.js +12 -0
  36. package/dist/types/events.js.map +1 -0
  37. package/dist/useAssistantClient.d.ts +13 -46
  38. package/dist/useAssistantClient.d.ts.map +1 -1
  39. package/dist/useAssistantClient.js +177 -137
  40. package/dist/useAssistantClient.js.map +1 -1
  41. package/dist/useAssistantEvent.d.ts +2 -2
  42. package/dist/useAssistantEvent.d.ts.map +1 -1
  43. package/dist/useAssistantEvent.js +3 -6
  44. package/dist/useAssistantEvent.js.map +1 -1
  45. package/dist/useAssistantState.d.ts +2 -2
  46. package/dist/useAssistantState.d.ts.map +1 -1
  47. package/dist/useAssistantState.js +7 -36
  48. package/dist/useAssistantState.js.map +1 -1
  49. package/dist/utils/BaseProxyHandler.d.ts +23 -0
  50. package/dist/utils/BaseProxyHandler.d.ts.map +1 -0
  51. package/dist/utils/BaseProxyHandler.js +41 -0
  52. package/dist/utils/BaseProxyHandler.js.map +1 -0
  53. package/dist/utils/NotificationManager.d.ts +11 -0
  54. package/dist/utils/NotificationManager.d.ts.map +1 -0
  55. package/dist/utils/NotificationManager.js +81 -0
  56. package/dist/utils/NotificationManager.js.map +1 -0
  57. package/dist/utils/StoreResource.d.ts +14 -0
  58. package/dist/utils/StoreResource.d.ts.map +1 -0
  59. package/dist/utils/StoreResource.js +23 -0
  60. package/dist/utils/StoreResource.js.map +1 -0
  61. package/dist/utils/proxied-assistant-state.d.ts +8 -0
  62. package/dist/utils/proxied-assistant-state.d.ts.map +1 -0
  63. package/dist/utils/proxied-assistant-state.js +41 -0
  64. package/dist/utils/proxied-assistant-state.js.map +1 -0
  65. package/dist/{AssistantContext.d.ts → utils/react-assistant-context.d.ts} +6 -6
  66. package/dist/utils/react-assistant-context.d.ts.map +1 -0
  67. package/dist/utils/react-assistant-context.js +73 -0
  68. package/dist/utils/react-assistant-context.js.map +1 -0
  69. package/dist/utils/splitClients.d.ts +28 -0
  70. package/dist/utils/splitClients.d.ts.map +1 -0
  71. package/dist/utils/splitClients.js +37 -0
  72. package/dist/utils/splitClients.js.map +1 -0
  73. package/dist/utils/tap-assistant-context.d.ts +19 -0
  74. package/dist/utils/tap-assistant-context.d.ts.map +1 -0
  75. package/dist/utils/tap-assistant-context.js +37 -0
  76. package/dist/utils/tap-assistant-context.js.map +1 -0
  77. package/dist/utils/tap-client-stack-context.d.ts +23 -0
  78. package/dist/utils/tap-client-stack-context.d.ts.map +1 -0
  79. package/dist/utils/tap-client-stack-context.js +30 -0
  80. package/dist/utils/tap-client-stack-context.js.map +1 -0
  81. package/package.json +3 -3
  82. package/src/AssistantIf.tsx +3 -11
  83. package/src/Derived.ts +46 -0
  84. package/src/attachDefaultPeers.ts +78 -0
  85. package/src/index.ts +19 -22
  86. package/src/tapClientList.ts +105 -0
  87. package/src/tapClientLookup.ts +56 -0
  88. package/src/tapClientResource.ts +152 -0
  89. package/src/types/client.ts +186 -0
  90. package/src/types/events.ts +77 -0
  91. package/src/useAssistantClient.tsx +252 -234
  92. package/src/useAssistantEvent.ts +6 -9
  93. package/src/useAssistantState.tsx +10 -48
  94. package/src/utils/BaseProxyHandler.ts +50 -0
  95. package/src/utils/NotificationManager.ts +110 -0
  96. package/src/utils/StoreResource.ts +36 -0
  97. package/src/utils/proxied-assistant-state.tsx +53 -0
  98. package/src/utils/react-assistant-context.tsx +107 -0
  99. package/src/utils/splitClients.ts +85 -0
  100. package/src/utils/tap-assistant-context.ts +59 -0
  101. package/src/utils/tap-client-stack-context.ts +51 -0
  102. package/dist/AssistantContext.d.ts.map +0 -1
  103. package/dist/AssistantContext.js +0 -45
  104. package/dist/AssistantContext.js.map +0 -1
  105. package/dist/DerivedScope.d.ts +0 -20
  106. package/dist/DerivedScope.d.ts.map +0 -1
  107. package/dist/DerivedScope.js +0 -11
  108. package/dist/DerivedScope.js.map +0 -1
  109. package/dist/EventContext.d.ts +0 -61
  110. package/dist/EventContext.d.ts.map +0 -1
  111. package/dist/EventContext.js +0 -62
  112. package/dist/EventContext.js.map +0 -1
  113. package/dist/ScopeRegistry.d.ts +0 -41
  114. package/dist/ScopeRegistry.d.ts.map +0 -1
  115. package/dist/ScopeRegistry.js +0 -17
  116. package/dist/ScopeRegistry.js.map +0 -1
  117. package/dist/StoreContext.d.ts +0 -9
  118. package/dist/StoreContext.d.ts.map +0 -1
  119. package/dist/StoreContext.js +0 -20
  120. package/dist/StoreContext.js.map +0 -1
  121. package/dist/asStore.d.ts +0 -20
  122. package/dist/asStore.d.ts.map +0 -1
  123. package/dist/asStore.js +0 -23
  124. package/dist/asStore.js.map +0 -1
  125. package/dist/tapApi.d.ts +0 -36
  126. package/dist/tapApi.d.ts.map +0 -1
  127. package/dist/tapApi.js +0 -52
  128. package/dist/tapApi.js.map +0 -1
  129. package/dist/tapLookupResources.d.ts +0 -44
  130. package/dist/tapLookupResources.d.ts.map +0 -1
  131. package/dist/tapLookupResources.js +0 -21
  132. package/dist/tapLookupResources.js.map +0 -1
  133. package/dist/tapStoreList.d.ts +0 -76
  134. package/dist/tapStoreList.d.ts.map +0 -1
  135. package/dist/tapStoreList.js +0 -46
  136. package/dist/tapStoreList.js.map +0 -1
  137. package/dist/types.d.ts +0 -84
  138. package/dist/types.d.ts.map +0 -1
  139. package/dist/types.js +0 -1
  140. package/dist/utils/splitScopes.d.ts +0 -24
  141. package/dist/utils/splitScopes.d.ts.map +0 -1
  142. package/dist/utils/splitScopes.js +0 -18
  143. package/dist/utils/splitScopes.js.map +0 -1
  144. package/src/AssistantContext.tsx +0 -64
  145. package/src/DerivedScope.ts +0 -23
  146. package/src/EventContext.ts +0 -187
  147. package/src/ScopeRegistry.ts +0 -58
  148. package/src/StoreContext.ts +0 -28
  149. package/src/asStore.ts +0 -40
  150. package/src/tapApi.ts +0 -91
  151. package/src/tapLookupResources.ts +0 -62
  152. package/src/tapStoreList.ts +0 -133
  153. package/src/types.ts +0 -119
  154. package/src/utils/splitScopes.ts +0 -38
  155. /package/dist/{types.js.map → types/client.js.map} +0 -0
package/src/tapApi.ts DELETED
@@ -1,91 +0,0 @@
1
- import { tapEffect, tapMemo, tapRef } from "@assistant-ui/tap";
2
-
3
- /**
4
- * API object type
5
- */
6
- export interface ApiObject {
7
- [key: string]: ((...args: any[]) => any) | ApiObject;
8
- }
9
-
10
- /**
11
- * Readonly API handler for creating stable proxies
12
- */
13
- class ReadonlyApiHandler<TApi extends ApiObject> implements ProxyHandler<TApi> {
14
- constructor(private readonly getApi: () => TApi) {}
15
-
16
- get(_: unknown, prop: string | symbol) {
17
- return this.getApi()[prop as keyof TApi];
18
- }
19
-
20
- ownKeys(): ArrayLike<string | symbol> {
21
- return Object.keys(this.getApi() as object);
22
- }
23
-
24
- has(_: unknown, prop: string | symbol) {
25
- return prop in (this.getApi() as object);
26
- }
27
-
28
- getOwnPropertyDescriptor(_: unknown, prop: string | symbol) {
29
- return Object.getOwnPropertyDescriptor(this.getApi(), prop);
30
- }
31
-
32
- set() {
33
- return false;
34
- }
35
- defineProperty() {
36
- return false;
37
- }
38
- deleteProperty() {
39
- return false;
40
- }
41
- }
42
-
43
- /**
44
- * Wraps an API object to make it stable across renders while keeping getState reactive.
45
- * This is the recommended pattern for scope resources.
46
- *
47
- * @example
48
- * ```typescript
49
- * export const FooResource = resource(() => {
50
- * const [state, setState] = tapState({ bar: "Hello" });
51
- *
52
- * const updateBar = (newBar: string) => {
53
- * setState({ bar: newBar });
54
- * };
55
- *
56
- * return tapApi({
57
- * getState: () => state,
58
- * updateBar,
59
- * });
60
- * });
61
- * ```
62
- */
63
- export const tapApi = <TApi extends ApiObject & { getState: () => any }>(
64
- api: TApi,
65
- options?: {
66
- key?: string | undefined;
67
- },
68
- ) => {
69
- const ref = tapRef(api);
70
- tapEffect(() => {
71
- ref.current = api;
72
- });
73
-
74
- const apiProxy = tapMemo(
75
- () =>
76
- new Proxy<TApi>({} as TApi, new ReadonlyApiHandler(() => ref.current)),
77
- [],
78
- );
79
-
80
- const key = options?.key;
81
- const state = api.getState();
82
-
83
- return tapMemo(
84
- () => ({
85
- key,
86
- state,
87
- api: apiProxy,
88
- }),
89
- [state, key],
90
- );
91
- };
@@ -1,62 +0,0 @@
1
- import { ResourceElement, tapResources } from "@assistant-ui/tap";
2
- import { ApiObject } from "./tapApi";
3
-
4
- /**
5
- * Creates a lookup-based resource collection for managing lists of items.
6
- * Returns both the combined state array and an API function to lookup specific items.
7
- *
8
- * @param elements - Array of resource elements, each returning { key, state, api }
9
- * @returns Object with { state: TState[], api: (lookup) => TApi }
10
- *
11
- * The api function accepts { index: number } or { key: string } for lookups.
12
- * Consumers can wrap it to rename the key field (e.g., to "id" or "toolCallId").
13
- *
14
- * @example
15
- * ```typescript
16
- * const foos = tapLookupResources(
17
- * items.map((item) => FooItem({ id: item.id }, { key: item.id }))
18
- * );
19
- *
20
- * // Access state array
21
- * const allStates = foos.state;
22
- *
23
- * // Wrap to rename key field to "id"
24
- * const wrappedApi = (lookup: { index: number } | { id: string }) => {
25
- * if ("id" in lookup) {
26
- * return foos.api({ key: lookup.id });
27
- * } else {
28
- * return foos.api(lookup);
29
- * }
30
- * };
31
- * ```
32
- */
33
- export const tapLookupResources = <TState, TApi extends ApiObject>(
34
- elements: ResourceElement<{
35
- key: string | undefined;
36
- state: TState;
37
- api: TApi;
38
- }>[],
39
- ): {
40
- state: TState[];
41
- api: (lookup: { index: number } | { key: string }) => TApi;
42
- } => {
43
- const resources = tapResources(elements);
44
-
45
- return {
46
- state: resources.map((r) => r.state),
47
- api: (lookup: { index: number } | { key: string }) => {
48
- const value =
49
- "index" in lookup
50
- ? resources[lookup.index]?.api
51
- : resources.find((r) => r.key === lookup.key)?.api;
52
-
53
- if (!value) {
54
- throw new Error(
55
- `tapLookupResources: Resource not found for lookup: ${JSON.stringify(lookup)}`,
56
- );
57
- }
58
-
59
- return value;
60
- },
61
- };
62
- };
@@ -1,133 +0,0 @@
1
- import { tapState } from "@assistant-ui/tap";
2
- import type { ContravariantResource } from "@assistant-ui/tap";
3
- import { tapLookupResources } from "./tapLookupResources";
4
- import { ApiObject } from "./tapApi";
5
-
6
- /**
7
- * Resource props that will be passed to each item resource
8
- */
9
- export type TapStoreListResourceProps<TProps> = {
10
- initialValue: TProps;
11
- remove: () => void;
12
- };
13
-
14
- /**
15
- * Configuration for tapStoreList hook
16
- */
17
- export type TapStoreListConfig<TProps, TState, TApi extends ApiObject> = {
18
- /**
19
- * Initial values for the list items
20
- */
21
- initialValues: TProps[];
22
-
23
- // TODO we can't use Resource type here because of contravariance
24
- // I think we need a special type in tap that correctly handles the contravariance
25
- // or change the behavior of the Resource type
26
-
27
- /**
28
- * Resource function that creates an element for each item
29
- * Should return a ResourceElement with { key, state, api }
30
- *
31
- * The resource will receive { initialValue, remove } as props.
32
- */
33
- resource: ContravariantResource<
34
- {
35
- key: string | undefined;
36
- state: TState;
37
- api: TApi;
38
- },
39
- TapStoreListResourceProps<TProps>
40
- >;
41
- /**
42
- * Optional ID generator function for new items
43
- * If not provided, items must include an ID when added
44
- */
45
- idGenerator?: () => string;
46
- };
47
-
48
- /**
49
- * Creates a stateful list with add functionality, rendering each item via the provided resource.
50
- * Returns state array, api lookup function, and add method.
51
- *
52
- * @param config - Configuration object with initialValues, resource, and optional idGenerator
53
- * @returns Object with { state: TState[], api: (lookup) => TApi, add: (id?) => void }
54
- *
55
- * @example
56
- * ```typescript
57
- * const todoList = tapStoreList({
58
- * initialValues: [
59
- * { id: "1", text: "First todo" },
60
- * { id: "2", text: "Second todo" }
61
- * ],
62
- * resource: (props) => TodoItemResource(props, { key: props.id }),
63
- * idGenerator: () => `todo-${Date.now()}`
64
- * });
65
- *
66
- * // Access state array
67
- * const allTodos = todoList.state;
68
- *
69
- * // Lookup specific item
70
- * const firstTodo = todoList.api({ index: 0 });
71
- * const specificTodo = todoList.api({ key: "1" });
72
- *
73
- * // Add new item
74
- * todoList.add(); // Uses idGenerator
75
- * todoList.add("custom-id"); // Uses provided id
76
- * ```
77
- */
78
- export const tapStoreList = <
79
- TProps extends { id: string },
80
- TState,
81
- TApi extends ApiObject,
82
- >(
83
- config: TapStoreListConfig<TProps, TState, TApi>,
84
- ): {
85
- state: TState[];
86
- api: (lookup: { index: number } | { id: string }) => TApi;
87
- add: (id?: string) => void;
88
- } => {
89
- const { initialValues, resource: Resource, idGenerator } = config;
90
-
91
- const [items, setItems] = tapState<TProps[]>(initialValues);
92
-
93
- const lookup = tapLookupResources(
94
- items.map((item) =>
95
- Resource(
96
- {
97
- initialValue: item,
98
- remove: () => {
99
- setItems(items.filter((i) => i !== item));
100
- },
101
- },
102
- {
103
- key: item.id,
104
- },
105
- ),
106
- ),
107
- );
108
-
109
- const add = (id?: string) => {
110
- const newId = id ?? idGenerator?.();
111
- if (!newId) {
112
- throw new Error(
113
- "tapStoreList: Either provide an id to add() or configure an idGenerator",
114
- );
115
- }
116
-
117
- // Create a new item with the generated/provided id
118
- // This assumes TProps has an 'id' field - users will need to ensure their props type supports this
119
- const newItem = { id: newId } as TProps;
120
- setItems([...items, newItem]);
121
- };
122
-
123
- return {
124
- state: lookup.state,
125
- api: (query: { index: number } | { id: string }) => {
126
- if ("index" in query) {
127
- return lookup.api({ index: query.index });
128
- }
129
- return lookup.api({ key: query.id });
130
- },
131
- add,
132
- };
133
- };
package/src/types.ts DELETED
@@ -1,119 +0,0 @@
1
- import type { ResourceElement } from "@assistant-ui/tap";
2
- import type {
3
- AssistantEvent,
4
- AssistantEventCallback,
5
- AssistantEventSelector,
6
- } from "./EventContext";
7
-
8
- type ScopeValueType = Record<string, unknown> & {
9
- getState: () => Record<string, unknown>;
10
- };
11
- type ScopeMetaType = { source: string; query: Record<string, unknown> };
12
-
13
- /**
14
- * Definition of a scope in the assistant client (internal type)
15
- * @template TValue - The API type (must include getState() and any actions)
16
- * @template TMeta - Source/query metadata (use ScopeMeta or discriminated union)
17
- * @template TEvents - Optional events that this scope can emit
18
- * @internal
19
- */
20
- export type ScopeDefinition<
21
- TValue extends ScopeValueType = ScopeValueType,
22
- TMeta extends ScopeMetaType = ScopeMetaType,
23
- TEvents extends Record<string, unknown> = Record<string, unknown>,
24
- > = {
25
- value: TValue;
26
- meta: TMeta;
27
- events: TEvents;
28
- };
29
-
30
- /**
31
- * Module augmentation interface for assistant-ui store type extensions.
32
- *
33
- * @example
34
- * ```typescript
35
- * declare module "@assistant-ui/store" {
36
- * interface AssistantScopeRegistry {
37
- * foo: {
38
- * value: { getState: () => { bar: string }; updateBar: (bar: string) => void };
39
- * meta: { source: "root"; query: Record<string, never> };
40
- * events: {
41
- * "foo.updated": { id: string; newValue: string };
42
- * "foo.deleted": { id: string };
43
- * };
44
- * };
45
- * // Example with multiple sources (discriminated union):
46
- * bar: {
47
- * value: { getState: () => { id: string } };
48
- * meta:
49
- * | { source: "fooList"; query: { index: number } }
50
- * | { source: "barList"; query: { id: string } };
51
- * events: Record<string, never>;
52
- * };
53
- * }
54
- * }
55
- * ```
56
- */
57
- export interface AssistantScopeRegistry {}
58
-
59
- export type AssistantScopes = keyof AssistantScopeRegistry extends never
60
- ? Record<"ERROR: No scopes were defined", ScopeDefinition>
61
- : { [K in keyof AssistantScopeRegistry]: AssistantScopeRegistry[K] };
62
- /**
63
- * Type for a scope field - a function that returns the current API value,
64
- * with source/query metadata attached (derived from meta)
65
- */
66
- export type ScopeField<T extends ScopeDefinition> = (() => T["value"]) &
67
- (T["meta"] | { source: null; query: null });
68
-
69
- /**
70
- * Props passed to a derived scope resource element
71
- */
72
- export type DerivedScopeProps<T extends ScopeDefinition> = {
73
- get: (parent: AssistantClient) => T["value"];
74
- source: T["meta"]["source"];
75
- query: T["meta"]["query"];
76
- };
77
-
78
- /**
79
- * Input type for scope definitions - ResourceElement that returns the API value
80
- * Can optionally include source/query metadata via DerivedScope
81
- */
82
- export type ScopeInput<T extends ScopeDefinition> = ResourceElement<{
83
- api: T["value"];
84
- }>;
85
-
86
- /**
87
- * Map of scope names to their input definitions
88
- */
89
- export type ScopesInput = {
90
- [K in keyof AssistantScopes]?: ScopeInput<AssistantScopes[K]>;
91
- };
92
-
93
- /**
94
- * Unsubscribe function type
95
- */
96
- export type Unsubscribe = () => void;
97
-
98
- /**
99
- * State type extracted from all scopes
100
- */
101
- export type AssistantState = {
102
- [K in keyof AssistantScopes]: ReturnType<
103
- AssistantScopes[K]["value"]["getState"]
104
- >;
105
- };
106
-
107
- /**
108
- * The assistant client type with all registered scopes
109
- */
110
- export type AssistantClient = {
111
- [K in keyof AssistantScopes]: ScopeField<AssistantScopes[K]>;
112
- } & {
113
- subscribe(listener: () => void): Unsubscribe;
114
- flushSync(): void;
115
- on<TEvent extends AssistantEvent>(
116
- selector: AssistantEventSelector<TEvent>,
117
- callback: AssistantEventCallback<TEvent>,
118
- ): Unsubscribe;
119
- };
@@ -1,38 +0,0 @@
1
- import { DerivedScope } from "../DerivedScope";
2
- import type { AssistantScopes, ScopeInput, ScopesInput } from "../types";
3
-
4
- /**
5
- * Splits a scopes object into root scopes and derived scopes.
6
- *
7
- * @param scopes - The scopes input object to split
8
- * @returns An object with { rootScopes, derivedScopes }
9
- *
10
- * @example
11
- * ```typescript
12
- * const scopes = {
13
- * foo: RootScope({ ... }),
14
- * bar: DerivedScope({ ... }),
15
- * };
16
- *
17
- * const { rootScopes, derivedScopes } = splitScopes(scopes);
18
- * // rootScopes = { foo: ... }
19
- * // derivedScopes = { bar: ... }
20
- * ```
21
- */
22
- export function splitScopes(scopes: ScopesInput) {
23
- const rootScopes: ScopesInput = {};
24
- const derivedScopes: ScopesInput = {};
25
-
26
- for (const [key, scopeElement] of Object.entries(scopes) as [
27
- keyof ScopesInput,
28
- ScopeInput<AssistantScopes[keyof ScopesInput]>,
29
- ][]) {
30
- if (scopeElement.type === DerivedScope) {
31
- derivedScopes[key] = scopeElement;
32
- } else {
33
- rootScopes[key] = scopeElement;
34
- }
35
- }
36
-
37
- return { rootScopes, derivedScopes };
38
- }
File without changes