@assistant-ui/store 0.0.1 → 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 +10 -0
  3. package/dist/AssistantIf.d.ts.map +1 -0
  4. package/dist/AssistantIf.js +13 -0
  5. package/dist/AssistantIf.js.map +1 -0
  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 +11 -14
  15. package/dist/index.d.ts.map +1 -1
  16. package/dist/index.js +19 -16
  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 -41
  38. package/dist/useAssistantClient.d.ts.map +1 -1
  39. package/dist/useAssistantClient.js +185 -130
  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 +5 -6
  82. package/src/AssistantIf.tsx +17 -0
  83. package/src/Derived.ts +46 -0
  84. package/src/attachDefaultPeers.ts +78 -0
  85. package/src/index.ts +31 -25
  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 +259 -217
  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 -18
  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 -65
  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 -88
  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 -21
  146. package/src/EventContext.ts +0 -184
  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 -129
  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,129 +0,0 @@
1
- import type { ResourceElement } from "@assistant-ui/tap";
2
- import type {
3
- AssistantEvent,
4
- AssistantEventCallback,
5
- AssistantEventSelector,
6
- } from "./EventContext";
7
-
8
- /**
9
- * Definition of a scope in the assistant client (internal type)
10
- * @template TValue - The API type (must include getState() and any actions)
11
- * @template TSource - The parent scope name (or "root" for top-level scopes)
12
- * @template TQuery - The query parameters needed to access this scope from its source
13
- * @internal
14
- */
15
- export type ScopeDefinition<
16
- TValue = any,
17
- TSource extends string | "root" = any,
18
- TQuery = any,
19
- > = {
20
- value: TValue;
21
- source: TSource;
22
- query: TQuery;
23
- };
24
-
25
- /**
26
- * Module augmentation interface for assistant-ui store type extensions.
27
- *
28
- * @example
29
- * ```typescript
30
- * declare module "@assistant-ui/store" {
31
- * interface AssistantScopeRegistry {
32
- * foo: {
33
- * value: { getState: () => { bar: string }; updateBar: (bar: string) => void };
34
- * source: "root";
35
- * query: Record<string, never>;
36
- * };
37
- * }
38
- * }
39
- * ```
40
- */
41
- // eslint-disable-next-line @typescript-eslint/no-empty-object-type
42
- export interface AssistantScopeRegistry {}
43
-
44
- export type AssistantScopes = keyof AssistantScopeRegistry extends never
45
- ? Record<"ERROR: No scopes were defined", ScopeDefinition>
46
- : { [K in keyof AssistantScopeRegistry]: AssistantScopeRegistry[K] };
47
-
48
- /**
49
- * Helper type to extract the value type from a scope definition
50
- */
51
- export type ScopeValue<T extends ScopeDefinition> = T["value"];
52
-
53
- /**
54
- * Helper type to extract the source type from a scope definition
55
- */
56
- export type ScopeSource<T extends ScopeDefinition> = T["source"];
57
-
58
- /**
59
- * Helper type to extract the query type from a scope definition
60
- */
61
- export type ScopeQuery<T extends ScopeDefinition> = T["query"];
62
-
63
- /**
64
- * Type for a scope field - a function that returns the current API value,
65
- * with source and query metadata attached
66
- */
67
- export type ScopeField<T extends ScopeDefinition> = (() => ScopeValue<T>) &
68
- (
69
- | {
70
- source: ScopeSource<T>;
71
- query: ScopeQuery<T>;
72
- }
73
- | {
74
- source: null;
75
- query: null;
76
- }
77
- );
78
-
79
- /**
80
- * Props passed to a derived scope resource element
81
- */
82
- export type DerivedScopeProps<T extends ScopeDefinition> = {
83
- get: (parent: AssistantClient) => ScopeValue<T>;
84
- source: ScopeSource<T>;
85
- query: ScopeQuery<T>;
86
- };
87
-
88
- /**
89
- * Input type for scope definitions - ResourceElement that returns the API value
90
- * Can optionally include source/query metadata via DerivedScope
91
- */
92
- export type ScopeInput<T extends ScopeDefinition> = ResourceElement<{
93
- api: ScopeValue<T>;
94
- }>;
95
-
96
- /**
97
- * Map of scope names to their input definitions
98
- */
99
- export type ScopesInput = {
100
- [K in keyof AssistantScopes]?: ScopeInput<AssistantScopes[K]>;
101
- };
102
-
103
- /**
104
- * Unsubscribe function type
105
- */
106
- export type Unsubscribe = () => void;
107
-
108
- /**
109
- * State type extracted from all scopes
110
- */
111
- export type AssistantState = {
112
- [K in keyof AssistantScopes]: ReturnType<
113
- AssistantScopes[K]["value"]["getState"]
114
- >;
115
- };
116
-
117
- /**
118
- * The assistant client type with all registered scopes
119
- */
120
- export type AssistantClient = {
121
- [K in keyof AssistantScopes]: ScopeField<AssistantScopes[K]>;
122
- } & {
123
- subscribe(listener: () => void): Unsubscribe;
124
- flushSync(): void;
125
- on<TEvent extends AssistantEvent>(
126
- selector: AssistantEventSelector<TEvent>,
127
- callback: AssistantEventCallback<TEvent>,
128
- ): Unsubscribe;
129
- };
@@ -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