@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
@@ -1,46 +0,0 @@
1
- // src/tapStoreList.ts
2
- import { tapState } from "@assistant-ui/tap";
3
- import { tapLookupResources } from "./tapLookupResources.js";
4
- var tapStoreList = (config) => {
5
- const { initialValues, resource: Resource, idGenerator } = config;
6
- const [items, setItems] = tapState(initialValues);
7
- const lookup = tapLookupResources(
8
- items.map(
9
- (item) => Resource(
10
- {
11
- initialValue: item,
12
- remove: () => {
13
- setItems(items.filter((i) => i !== item));
14
- }
15
- },
16
- {
17
- key: item.id
18
- }
19
- )
20
- )
21
- );
22
- const add = (id) => {
23
- const newId = id ?? idGenerator?.();
24
- if (!newId) {
25
- throw new Error(
26
- "tapStoreList: Either provide an id to add() or configure an idGenerator"
27
- );
28
- }
29
- const newItem = { id: newId };
30
- setItems([...items, newItem]);
31
- };
32
- return {
33
- state: lookup.state,
34
- api: (query) => {
35
- if ("index" in query) {
36
- return lookup.api({ index: query.index });
37
- }
38
- return lookup.api({ key: query.id });
39
- },
40
- add
41
- };
42
- };
43
- export {
44
- tapStoreList
45
- };
46
- //# sourceMappingURL=tapStoreList.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/tapStoreList.ts"],"sourcesContent":["import { tapState } from \"@assistant-ui/tap\";\nimport type { ContravariantResource } from \"@assistant-ui/tap\";\nimport { tapLookupResources } from \"./tapLookupResources\";\nimport { ApiObject } from \"./tapApi\";\n\n/**\n * Resource props that will be passed to each item resource\n */\nexport type TapStoreListResourceProps<TProps> = {\n initialValue: TProps;\n remove: () => void;\n};\n\n/**\n * Configuration for tapStoreList hook\n */\nexport type TapStoreListConfig<TProps, TState, TApi extends ApiObject> = {\n /**\n * Initial values for the list items\n */\n initialValues: TProps[];\n\n // TODO we can't use Resource type here because of contravariance\n // I think we need a special type in tap that correctly handles the contravariance\n // or change the behavior of the Resource type\n\n /**\n * Resource function that creates an element for each item\n * Should return a ResourceElement with { key, state, api }\n *\n * The resource will receive { initialValue, remove } as props.\n */\n resource: ContravariantResource<\n {\n key: string | undefined;\n state: TState;\n api: TApi;\n },\n TapStoreListResourceProps<TProps>\n >;\n /**\n * Optional ID generator function for new items\n * If not provided, items must include an ID when added\n */\n idGenerator?: () => string;\n};\n\n/**\n * Creates a stateful list with add functionality, rendering each item via the provided resource.\n * Returns state array, api lookup function, and add method.\n *\n * @param config - Configuration object with initialValues, resource, and optional idGenerator\n * @returns Object with { state: TState[], api: (lookup) => TApi, add: (id?) => void }\n *\n * @example\n * ```typescript\n * const todoList = tapStoreList({\n * initialValues: [\n * { id: \"1\", text: \"First todo\" },\n * { id: \"2\", text: \"Second todo\" }\n * ],\n * resource: (props) => TodoItemResource(props, { key: props.id }),\n * idGenerator: () => `todo-${Date.now()}`\n * });\n *\n * // Access state array\n * const allTodos = todoList.state;\n *\n * // Lookup specific item\n * const firstTodo = todoList.api({ index: 0 });\n * const specificTodo = todoList.api({ key: \"1\" });\n *\n * // Add new item\n * todoList.add(); // Uses idGenerator\n * todoList.add(\"custom-id\"); // Uses provided id\n * ```\n */\nexport const tapStoreList = <\n TProps extends { id: string },\n TState,\n TApi extends ApiObject,\n>(\n config: TapStoreListConfig<TProps, TState, TApi>,\n): {\n state: TState[];\n api: (lookup: { index: number } | { id: string }) => TApi;\n add: (id?: string) => void;\n} => {\n const { initialValues, resource: Resource, idGenerator } = config;\n\n const [items, setItems] = tapState<TProps[]>(initialValues);\n\n const lookup = tapLookupResources(\n items.map((item) =>\n Resource(\n {\n initialValue: item,\n remove: () => {\n setItems(items.filter((i) => i !== item));\n },\n },\n {\n key: item.id,\n },\n ),\n ),\n );\n\n const add = (id?: string) => {\n const newId = id ?? idGenerator?.();\n if (!newId) {\n throw new Error(\n \"tapStoreList: Either provide an id to add() or configure an idGenerator\",\n );\n }\n\n // Create a new item with the generated/provided id\n // This assumes TProps has an 'id' field - users will need to ensure their props type supports this\n const newItem = { id: newId } as TProps;\n setItems([...items, newItem]);\n };\n\n return {\n state: lookup.state,\n api: (query: { index: number } | { id: string }) => {\n if (\"index\" in query) {\n return lookup.api({ index: query.index });\n }\n return lookup.api({ key: query.id });\n },\n add,\n };\n};\n"],"mappings":";AAAA,SAAS,gBAAgB;AAEzB,SAAS,0BAA0B;AA2E5B,IAAM,eAAe,CAK1B,WAKG;AACH,QAAM,EAAE,eAAe,UAAU,UAAU,YAAY,IAAI;AAE3D,QAAM,CAAC,OAAO,QAAQ,IAAI,SAAmB,aAAa;AAE1D,QAAM,SAAS;AAAA,IACb,MAAM;AAAA,MAAI,CAAC,SACT;AAAA,QACE;AAAA,UACE,cAAc;AAAA,UACd,QAAQ,MAAM;AACZ,qBAAS,MAAM,OAAO,CAAC,MAAM,MAAM,IAAI,CAAC;AAAA,UAC1C;AAAA,QACF;AAAA,QACA;AAAA,UACE,KAAK,KAAK;AAAA,QACZ;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,QAAM,MAAM,CAAC,OAAgB;AAC3B,UAAM,QAAQ,MAAM,cAAc;AAClC,QAAI,CAAC,OAAO;AACV,YAAM,IAAI;AAAA,QACR;AAAA,MACF;AAAA,IACF;AAIA,UAAM,UAAU,EAAE,IAAI,MAAM;AAC5B,aAAS,CAAC,GAAG,OAAO,OAAO,CAAC;AAAA,EAC9B;AAEA,SAAO;AAAA,IACL,OAAO,OAAO;AAAA,IACd,KAAK,CAAC,UAA8C;AAClD,UAAI,WAAW,OAAO;AACpB,eAAO,OAAO,IAAI,EAAE,OAAO,MAAM,MAAM,CAAC;AAAA,MAC1C;AACA,aAAO,OAAO,IAAI,EAAE,KAAK,MAAM,GAAG,CAAC;AAAA,IACrC;AAAA,IACA;AAAA,EACF;AACF;","names":[]}
package/dist/types.d.ts DELETED
@@ -1,88 +0,0 @@
1
- import type { ResourceElement } from "@assistant-ui/tap";
2
- import type { AssistantEvent, AssistantEventCallback, AssistantEventSelector } from "./EventContext";
3
- /**
4
- * Module augmentation interface for assistant-ui store type extensions.
5
- *
6
- * @example
7
- * ```typescript
8
- * declare module "@assistant-ui/store" {
9
- * interface AssistantScopeRegistry {
10
- * foo: {
11
- * value: { getState: () => { bar: string }; updateBar: (bar: string) => void };
12
- * source: "root";
13
- * query: Record<string, never>;
14
- * };
15
- * }
16
- * }
17
- * ```
18
- */
19
- export interface AssistantScopeRegistry {
20
- }
21
- export type AssistantScopes = keyof AssistantScopeRegistry extends never ? Record<"ERROR: No scopes were defined", ScopeDefinition> : {
22
- [K in keyof AssistantScopeRegistry]: AssistantScopeRegistry[K];
23
- };
24
- /**
25
- * Helper type to extract the value type from a scope definition
26
- */
27
- export type ScopeValue<T extends ScopeDefinition> = T["value"];
28
- /**
29
- * Helper type to extract the source type from a scope definition
30
- */
31
- export type ScopeSource<T extends ScopeDefinition> = T["source"];
32
- /**
33
- * Helper type to extract the query type from a scope definition
34
- */
35
- export type ScopeQuery<T extends ScopeDefinition> = T["query"];
36
- /**
37
- * Type for a scope field - a function that returns the current API value,
38
- * with source and query metadata attached
39
- */
40
- export type ScopeField<T extends ScopeDefinition> = (() => ScopeValue<T>) & ({
41
- source: ScopeSource<T>;
42
- query: ScopeQuery<T>;
43
- } | {
44
- source: null;
45
- query: null;
46
- });
47
- /**
48
- * Props passed to a derived scope resource element
49
- */
50
- export type DerivedScopeProps<T extends ScopeDefinition> = {
51
- get: (parent: AssistantClient) => ScopeValue<T>;
52
- source: ScopeSource<T>;
53
- query: ScopeQuery<T>;
54
- };
55
- /**
56
- * Input type for scope definitions - ResourceElement that returns the API value
57
- * Can optionally include source/query metadata via DerivedScope
58
- */
59
- export type ScopeInput<T extends ScopeDefinition> = ResourceElement<{
60
- api: ScopeValue<T>;
61
- }>;
62
- /**
63
- * Map of scope names to their input definitions
64
- */
65
- export type ScopesInput = {
66
- [K in keyof AssistantScopes]?: ScopeInput<AssistantScopes[K]>;
67
- };
68
- /**
69
- * Unsubscribe function type
70
- */
71
- export type Unsubscribe = () => void;
72
- /**
73
- * State type extracted from all scopes
74
- */
75
- export type AssistantState = {
76
- [K in keyof AssistantScopes]: ReturnType<AssistantScopes[K]["value"]["getState"]>;
77
- };
78
- /**
79
- * The assistant client type with all registered scopes
80
- */
81
- export type AssistantClient = {
82
- [K in keyof AssistantScopes]: ScopeField<AssistantScopes[K]>;
83
- } & {
84
- subscribe(listener: () => void): Unsubscribe;
85
- flushSync(): void;
86
- on<TEvent extends AssistantEvent>(selector: AssistantEventSelector<TEvent>, callback: AssistantEventCallback<TEvent>): Unsubscribe;
87
- };
88
- //# sourceMappingURL=types.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACzD,OAAO,KAAK,EACV,cAAc,EACd,sBAAsB,EACtB,sBAAsB,EACvB,MAAM,gBAAgB,CAAC;AAmBxB;;;;;;;;;;;;;;;GAeG;AAEH,MAAM,WAAW,sBAAsB;CAAG;AAE1C,MAAM,MAAM,eAAe,GAAG,MAAM,sBAAsB,SAAS,KAAK,GACpE,MAAM,CAAC,+BAA+B,EAAE,eAAe,CAAC,GACxD;KAAG,CAAC,IAAI,MAAM,sBAAsB,GAAG,sBAAsB,CAAC,CAAC,CAAC;CAAE,CAAC;AAEvE;;GAEG;AACH,MAAM,MAAM,UAAU,CAAC,CAAC,SAAS,eAAe,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC;AAE/D;;GAEG;AACH,MAAM,MAAM,WAAW,CAAC,CAAC,SAAS,eAAe,IAAI,CAAC,CAAC,QAAQ,CAAC,CAAC;AAEjE;;GAEG;AACH,MAAM,MAAM,UAAU,CAAC,CAAC,SAAS,eAAe,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC;AAE/D;;;GAGG;AACH,MAAM,MAAM,UAAU,CAAC,CAAC,SAAS,eAAe,IAAI,CAAC,MAAM,UAAU,CAAC,CAAC,CAAC,CAAC,GACvE,CACI;IACE,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC,CAAC;IACvB,KAAK,EAAE,UAAU,CAAC,CAAC,CAAC,CAAC;CACtB,GACD;IACE,MAAM,EAAE,IAAI,CAAC;IACb,KAAK,EAAE,IAAI,CAAC;CACb,CACJ,CAAC;AAEJ;;GAEG;AACH,MAAM,MAAM,iBAAiB,CAAC,CAAC,SAAS,eAAe,IAAI;IACzD,GAAG,EAAE,CAAC,MAAM,EAAE,eAAe,KAAK,UAAU,CAAC,CAAC,CAAC,CAAC;IAChD,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC,CAAC;IACvB,KAAK,EAAE,UAAU,CAAC,CAAC,CAAC,CAAC;CACtB,CAAC;AAEF;;;GAGG;AACH,MAAM,MAAM,UAAU,CAAC,CAAC,SAAS,eAAe,IAAI,eAAe,CAAC;IAClE,GAAG,EAAE,UAAU,CAAC,CAAC,CAAC,CAAC;CACpB,CAAC,CAAC;AAEH;;GAEG;AACH,MAAM,MAAM,WAAW,GAAG;KACvB,CAAC,IAAI,MAAM,eAAe,CAAC,CAAC,EAAE,UAAU,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC;CAC9D,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,WAAW,GAAG,MAAM,IAAI,CAAC;AAErC;;GAEG;AACH,MAAM,MAAM,cAAc,GAAG;KAC1B,CAAC,IAAI,MAAM,eAAe,GAAG,UAAU,CACtC,eAAe,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,UAAU,CAAC,CACxC;CACF,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,eAAe,GAAG;KAC3B,CAAC,IAAI,MAAM,eAAe,GAAG,UAAU,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC;CAC7D,GAAG;IACF,SAAS,CAAC,QAAQ,EAAE,MAAM,IAAI,GAAG,WAAW,CAAC;IAC7C,SAAS,IAAI,IAAI,CAAC;IAClB,EAAE,CAAC,MAAM,SAAS,cAAc,EAC9B,QAAQ,EAAE,sBAAsB,CAAC,MAAM,CAAC,EACxC,QAAQ,EAAE,sBAAsB,CAAC,MAAM,CAAC,GACvC,WAAW,CAAC;CAChB,CAAC"}
package/dist/types.js DELETED
@@ -1 +0,0 @@
1
- //# sourceMappingURL=types.js.map
@@ -1,24 +0,0 @@
1
- import type { ScopesInput } from "../types";
2
- /**
3
- * Splits a scopes object into root scopes and derived scopes.
4
- *
5
- * @param scopes - The scopes input object to split
6
- * @returns An object with { rootScopes, derivedScopes }
7
- *
8
- * @example
9
- * ```typescript
10
- * const scopes = {
11
- * foo: RootScope({ ... }),
12
- * bar: DerivedScope({ ... }),
13
- * };
14
- *
15
- * const { rootScopes, derivedScopes } = splitScopes(scopes);
16
- * // rootScopes = { foo: ... }
17
- * // derivedScopes = { bar: ... }
18
- * ```
19
- */
20
- export declare function splitScopes(scopes: ScopesInput): {
21
- rootScopes: ScopesInput;
22
- derivedScopes: ScopesInput;
23
- };
24
- //# sourceMappingURL=splitScopes.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"splitScopes.d.ts","sourceRoot":"","sources":["../../src/utils/splitScopes.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAA+B,WAAW,EAAE,MAAM,UAAU,CAAC;AAEzE;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,WAAW,CAAC,MAAM,EAAE,WAAW;;;EAgB9C"}
@@ -1,18 +0,0 @@
1
- // src/utils/splitScopes.ts
2
- import { DerivedScope } from "../DerivedScope.js";
3
- function splitScopes(scopes) {
4
- const rootScopes = {};
5
- const derivedScopes = {};
6
- for (const [key, scopeElement] of Object.entries(scopes)) {
7
- if (scopeElement.type === DerivedScope) {
8
- derivedScopes[key] = scopeElement;
9
- } else {
10
- rootScopes[key] = scopeElement;
11
- }
12
- }
13
- return { rootScopes, derivedScopes };
14
- }
15
- export {
16
- splitScopes
17
- };
18
- //# sourceMappingURL=splitScopes.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../src/utils/splitScopes.ts"],"sourcesContent":["import { DerivedScope } from \"../DerivedScope\";\nimport type { AssistantScopes, ScopeInput, ScopesInput } from \"../types\";\n\n/**\n * Splits a scopes object into root scopes and derived scopes.\n *\n * @param scopes - The scopes input object to split\n * @returns An object with { rootScopes, derivedScopes }\n *\n * @example\n * ```typescript\n * const scopes = {\n * foo: RootScope({ ... }),\n * bar: DerivedScope({ ... }),\n * };\n *\n * const { rootScopes, derivedScopes } = splitScopes(scopes);\n * // rootScopes = { foo: ... }\n * // derivedScopes = { bar: ... }\n * ```\n */\nexport function splitScopes(scopes: ScopesInput) {\n const rootScopes: ScopesInput = {};\n const derivedScopes: ScopesInput = {};\n\n for (const [key, scopeElement] of Object.entries(scopes) as [\n keyof ScopesInput,\n ScopeInput<AssistantScopes[keyof ScopesInput]>,\n ][]) {\n if (scopeElement.type === DerivedScope) {\n derivedScopes[key] = scopeElement;\n } else {\n rootScopes[key] = scopeElement;\n }\n }\n\n return { rootScopes, derivedScopes };\n}\n"],"mappings":";AAAA,SAAS,oBAAoB;AAqBtB,SAAS,YAAY,QAAqB;AAC/C,QAAM,aAA0B,CAAC;AACjC,QAAM,gBAA6B,CAAC;AAEpC,aAAW,CAAC,KAAK,YAAY,KAAK,OAAO,QAAQ,MAAM,GAGlD;AACH,QAAI,aAAa,SAAS,cAAc;AACtC,oBAAc,GAAG,IAAI;AAAA,IACvB,OAAO;AACL,iBAAW,GAAG,IAAI;AAAA,IACpB;AAAA,EACF;AAEA,SAAO,EAAE,YAAY,cAAc;AACrC;","names":[]}
@@ -1,64 +0,0 @@
1
- import React, { createContext, useContext } from "react";
2
- import type { AssistantClient, AssistantScopes, ScopeField } from "./types";
3
- import { hasRegisteredScope } from "./ScopeRegistry";
4
-
5
- const NO_OP_SUBSCRIBE = () => () => {};
6
- const NO_OP_FLUSH_SYNC = () => {};
7
- const NO_OP_SCOPE_FIELD = (() => {
8
- const fn = (() => {
9
- throw new Error(
10
- "You need to wrap this component/hook in <AssistantProvider>",
11
- );
12
- }) as ScopeField<never>;
13
- fn.source = null;
14
- fn.query = null;
15
- return fn;
16
- })();
17
-
18
- /**
19
- * React Context for the AssistantClient
20
- */
21
- export const AssistantContext = createContext<AssistantClient>(
22
- new Proxy({} as AssistantClient, {
23
- get(_, prop: string) {
24
- // Allow access to subscribe and flushSync without error
25
- if (prop === "subscribe") return NO_OP_SUBSCRIBE;
26
- if (prop === "on") return NO_OP_SUBSCRIBE;
27
- if (prop === "flushSync") return NO_OP_FLUSH_SYNC;
28
-
29
- // If this is a registered scope, return a function that errors when called or accessed
30
- if (hasRegisteredScope(prop as keyof AssistantScopes))
31
- return NO_OP_SCOPE_FIELD;
32
-
33
- return null;
34
- },
35
- }),
36
- );
37
-
38
- export const useAssistantContextValue = (): AssistantClient => {
39
- return useContext(AssistantContext);
40
- };
41
-
42
- /**
43
- * Provider component for AssistantClient
44
- *
45
- * @example
46
- * ```typescript
47
- * <AssistantProvider client={client}>
48
- * <YourApp />
49
- * </AssistantProvider>
50
- * ```
51
- */
52
- export const AssistantProvider = ({
53
- client,
54
- children,
55
- }: {
56
- client: AssistantClient;
57
- children: React.ReactNode;
58
- }): React.ReactElement => {
59
- return (
60
- <AssistantContext.Provider value={client}>
61
- {children}
62
- </AssistantContext.Provider>
63
- );
64
- };
@@ -1,21 +0,0 @@
1
- import { resource } from "@assistant-ui/tap";
2
- import type { ScopeDefinition, ScopeValue, DerivedScopeProps } from "./types";
3
-
4
- /**
5
- * Creates a derived scope field that memoizes based on source and query.
6
- * The get callback always calls the most recent version (useEffectEvent pattern).
7
- *
8
- * @example
9
- * ```typescript
10
- * const MessageScope = DerivedScope<MessageScopeDefinition>({
11
- * source: "thread",
12
- * query: { type: "index", index: 0 },
13
- * get: () => messageApi,
14
- * });
15
- * ```
16
- */
17
- export const DerivedScope = resource(
18
- <T extends ScopeDefinition>(config: DerivedScopeProps<T>): ScopeValue<T> => {
19
- return config;
20
- },
21
- );
@@ -1,184 +0,0 @@
1
- import { resource, tapMemo } from "@assistant-ui/tap";
2
- import type { Unsubscribe } from "./types";
3
-
4
- /**
5
- * Module augmentation interface for custom events.
6
- *
7
- * @example
8
- * ```typescript
9
- * declare module "@assistant-ui/store" {
10
- * interface AssistantEventRegistry {
11
- * "thread.run-start": { threadId: string };
12
- * "custom.my-event": { data: string };
13
- * }
14
- * }
15
- * ```
16
- */
17
- // eslint-disable-next-line @typescript-eslint/no-empty-object-type
18
- export interface AssistantEventRegistry {}
19
-
20
- /**
21
- * Module augmentation interface for event scope configuration.
22
- * Maps event sources to their parent scopes.
23
- *
24
- * @example
25
- * ```typescript
26
- * declare module "@assistant-ui/store" {
27
- * interface AssistantEventScopeConfig {
28
- * composer: "thread" | "message";
29
- * thread: never;
30
- * }
31
- * }
32
- * ```
33
- */
34
- // eslint-disable-next-line @typescript-eslint/no-empty-object-type
35
- export interface AssistantEventScopeConfig {}
36
-
37
- export type AssistantEventMap = AssistantEventRegistry & {
38
- // Catch-all
39
- "*": {
40
- [K in Exclude<keyof AssistantEventRegistry, "*">]: {
41
- event: K;
42
- payload: AssistantEventRegistry[K];
43
- };
44
- }[Exclude<keyof AssistantEventRegistry, "*">];
45
- };
46
-
47
- export type AssistantEvent = keyof AssistantEventMap;
48
-
49
- export type EventSource<T extends AssistantEvent = AssistantEvent> =
50
- T extends `${infer Source}.${string}` ? Source : never;
51
-
52
- export type SourceByScope<TScope extends AssistantEventScope<AssistantEvent>> =
53
- | (TScope extends "*" ? EventSource : never)
54
- | (TScope extends keyof AssistantEventScopeConfig ? TScope : never)
55
- | {
56
- [K in keyof AssistantEventScopeConfig]: TScope extends AssistantEventScopeConfig[K]
57
- ? K
58
- : never;
59
- }[keyof AssistantEventScopeConfig];
60
-
61
- export type AssistantEventScope<TEvent extends AssistantEvent> =
62
- | "*"
63
- | EventSource<TEvent>
64
- | (EventSource<TEvent> extends keyof AssistantEventScopeConfig
65
- ? AssistantEventScopeConfig[EventSource<TEvent>]
66
- : never);
67
-
68
- export type AssistantEventSelector<TEvent extends AssistantEvent> =
69
- | TEvent
70
- | {
71
- scope: AssistantEventScope<TEvent>;
72
- event: TEvent;
73
- };
74
-
75
- export const normalizeEventSelector = <TEvent extends AssistantEvent>(
76
- selector: AssistantEventSelector<TEvent>,
77
- ) => {
78
- if (typeof selector === "string") {
79
- const source = selector.split(".")[0] as AssistantEventScope<TEvent>;
80
- return {
81
- scope: source,
82
- event: selector,
83
- };
84
- }
85
-
86
- return {
87
- scope: selector.scope,
88
- event: selector.event,
89
- };
90
- };
91
-
92
- export const checkEventScope = <
93
- TEvent extends AssistantEvent,
94
- TExpectedScope extends AssistantEventScope<AssistantEvent>,
95
- >(
96
- expectedScope: TExpectedScope,
97
- scope: AssistantEventScope<TEvent>,
98
- _event: TEvent,
99
- ): _event is Extract<TEvent, `${SourceByScope<TExpectedScope>}.${string}`> => {
100
- return scope === expectedScope;
101
- };
102
-
103
- export type AssistantEventCallback<TEvent extends AssistantEvent> = (
104
- payload: AssistantEventMap[TEvent],
105
- ) => void;
106
-
107
- export type EventManager = {
108
- on<TEvent extends AssistantEvent>(
109
- event: TEvent,
110
- callback: AssistantEventCallback<TEvent>,
111
- ): Unsubscribe;
112
- emit<TEvent extends Exclude<AssistantEvent, "*">>(
113
- event: TEvent,
114
- payload: AssistantEventMap[TEvent],
115
- ): void;
116
- };
117
-
118
- type ListenerMap = Omit<
119
- Map<AssistantEvent, Set<AssistantEventCallback<AssistantEvent>>>,
120
- "get" | "set"
121
- > & {
122
- get<TEvent extends AssistantEvent>(
123
- event: TEvent,
124
- ): Set<AssistantEventCallback<TEvent>> | undefined;
125
- set<TEvent extends AssistantEvent>(
126
- event: TEvent,
127
- value: Set<AssistantEventCallback<TEvent>>,
128
- ): void;
129
- };
130
-
131
- export const EventManager = resource(() => {
132
- const events = tapMemo(() => {
133
- const listeners: ListenerMap = new Map();
134
-
135
- return {
136
- on: (event, callback) => {
137
- if (!listeners.has(event)) {
138
- listeners.set(event, new Set());
139
- }
140
-
141
- const eventListeners = listeners.get(event)!;
142
- eventListeners.add(callback);
143
-
144
- return () => {
145
- eventListeners.delete(callback);
146
- if (eventListeners.size === 0) {
147
- listeners.delete(event);
148
- }
149
- };
150
- },
151
-
152
- emit: (event, payload) => {
153
- const eventListeners = listeners.get(event);
154
- const wildcardListeners = listeners.get("*");
155
-
156
- if (!eventListeners && !wildcardListeners) return;
157
-
158
- // make sure state updates flush
159
- queueMicrotask(() => {
160
- // Emit to specific event listeners
161
- if (eventListeners) {
162
- for (const callback of eventListeners) {
163
- callback(payload);
164
- }
165
- }
166
-
167
- // Emit to wildcard listeners
168
- if (wildcardListeners) {
169
- for (const callback of wildcardListeners) {
170
- (
171
- callback as (payload: {
172
- event: typeof event;
173
- payload: typeof payload;
174
- }) => void
175
- )({ event, payload });
176
- }
177
- }
178
- });
179
- },
180
- } satisfies EventManager;
181
- }, []);
182
-
183
- return events;
184
- });
@@ -1,58 +0,0 @@
1
- import type { AssistantScopes } from "./types";
2
- import type { ResourceElement } from "@assistant-ui/tap";
3
-
4
- type ScopeRegistryEntry<K extends keyof AssistantScopes> = {
5
- name: K;
6
- defaultInitialize:
7
- | ResourceElement<AssistantScopes[K]["value"]>
8
- | { error: string };
9
- };
10
-
11
- const scopeRegistry = new Map<
12
- keyof AssistantScopes,
13
- ResourceElement<any> | { error: string }
14
- >();
15
-
16
- /**
17
- * Register a default scope implementation.
18
- * This allows scopes to have default values when not explicitly provided.
19
- *
20
- * @example With a resource:
21
- * ```typescript
22
- * registerAssistantScope({
23
- * name: "myScope",
24
- * defaultInitialize: MyResource(),
25
- * });
26
- * ```
27
- *
28
- * @example With an error:
29
- * ```typescript
30
- * registerAssistantScope({
31
- * name: "myScope",
32
- * defaultInitialize: { error: "MyScope is not configured" },
33
- * });
34
- * ```
35
- */
36
- export function registerAssistantScope<K extends keyof AssistantScopes>(
37
- config: ScopeRegistryEntry<K>,
38
- ): void {
39
- scopeRegistry.set(config.name, config.defaultInitialize);
40
- }
41
-
42
- /**
43
- * Get the default initializer for a scope, if registered.
44
- */
45
- export function getDefaultScopeInitializer<K extends keyof AssistantScopes>(
46
- name: K,
47
- ):
48
- | (ResourceElement<AssistantScopes[K]["value"]> | { error: string })
49
- | undefined {
50
- return scopeRegistry.get(name);
51
- }
52
-
53
- /**
54
- * Get all registered scope names.
55
- */
56
- export function hasRegisteredScope(name: keyof AssistantScopes): boolean {
57
- return scopeRegistry.has(name);
58
- }
@@ -1,28 +0,0 @@
1
- import {
2
- createContext,
3
- tapContext,
4
- withContextProvider,
5
- } from "@assistant-ui/tap";
6
- import type { EventManager } from "./EventContext";
7
- import type { AssistantClient } from "./types";
8
-
9
- export type StoreContextValue = {
10
- events: EventManager;
11
- parent: AssistantClient;
12
- };
13
-
14
- const StoreContext = createContext<StoreContextValue | null>(null);
15
-
16
- export const withStoreContextProvider = <TResult>(
17
- value: StoreContextValue,
18
- fn: () => TResult,
19
- ) => {
20
- return withContextProvider(StoreContext, value, fn);
21
- };
22
-
23
- export const tapStoreContext = () => {
24
- const ctx = tapContext(StoreContext);
25
- if (!ctx) throw new Error("Store context is not available");
26
-
27
- return ctx;
28
- };
package/src/asStore.ts DELETED
@@ -1,40 +0,0 @@
1
- import {
2
- tapMemo,
3
- tapEffect,
4
- ResourceElement,
5
- resource,
6
- createResource,
7
- } from "@assistant-ui/tap";
8
- import { Unsubscribe } from "./types";
9
-
10
- export interface Store<TState> {
11
- /**
12
- * Get the current state of the store.
13
- */
14
- getState(): TState;
15
-
16
- /**
17
- * Subscribe to the store.
18
- */
19
- subscribe(listener: () => void): Unsubscribe;
20
-
21
- /**
22
- * Synchronously flush all the updates to the store.
23
- */
24
- flushSync(): void;
25
- }
26
-
27
- export const asStore = resource(
28
- <TState, TProps>(element: ResourceElement<TState, TProps>): Store<TState> => {
29
- const resource = tapMemo(
30
- () => createResource(element, true),
31
- [element.type],
32
- );
33
-
34
- tapEffect(() => {
35
- resource.updateInput(element.props);
36
- });
37
-
38
- return resource;
39
- },
40
- );