@assistant-ui/store 0.2.0 → 0.2.1
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/dist/AuiIf.d.ts +1 -1
- package/dist/AuiIf.d.ts.map +1 -1
- package/dist/Derived.d.ts +34 -0
- package/dist/Derived.d.ts.map +1 -0
- package/dist/Derived.js +24 -0
- package/dist/Derived.js.map +1 -0
- package/dist/attachTransformScopes.d.ts +11 -0
- package/dist/attachTransformScopes.d.ts.map +1 -0
- package/dist/attachTransformScopes.js +12 -0
- package/dist/attachTransformScopes.js.map +1 -0
- package/dist/index.d.ts +9 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +11 -4
- package/dist/index.js.map +1 -1
- package/dist/tapClientList.d.ts +28 -0
- package/dist/tapClientList.d.ts.map +1 -0
- package/dist/tapClientList.js +68 -0
- package/dist/tapClientList.js.map +1 -0
- package/dist/tapClientLookup.d.ts +15 -0
- package/dist/tapClientLookup.d.ts.map +1 -0
- package/dist/tapClientLookup.js +42 -0
- package/dist/tapClientLookup.js.map +1 -0
- package/dist/tapClientResource.d.ts +13 -0
- package/dist/tapClientResource.d.ts.map +1 -0
- package/dist/tapClientResource.js +114 -0
- package/dist/tapClientResource.js.map +1 -0
- package/dist/types/client.d.ts +115 -0
- package/dist/types/client.d.ts.map +1 -0
- package/dist/types/client.js +2 -0
- package/dist/types/client.js.map +1 -0
- package/dist/types/events.d.ts +33 -0
- package/dist/types/events.d.ts.map +1 -0
- package/dist/types/events.js +8 -0
- package/dist/types/events.js.map +1 -0
- package/dist/useAui.d.ts +5 -3
- package/dist/useAui.d.ts.map +1 -1
- package/dist/useAui.js +7 -2
- package/dist/useAui.js.map +1 -1
- package/dist/useAuiEvent.d.ts +1 -1
- package/dist/useAuiEvent.d.ts.map +1 -1
- package/dist/useAuiEvent.js +1 -1
- package/dist/useAuiEvent.js.map +1 -1
- package/dist/useAuiState.d.ts +2 -2
- package/dist/useAuiState.d.ts.map +1 -1
- package/dist/useAuiState.js +2 -2
- package/dist/useAuiState.js.map +1 -1
- package/dist/utils/BaseProxyHandler.d.ts +23 -0
- package/dist/utils/BaseProxyHandler.d.ts.map +1 -0
- package/dist/utils/BaseProxyHandler.js +46 -0
- package/dist/utils/BaseProxyHandler.js.map +1 -0
- package/dist/utils/NotificationManager.d.ts +11 -0
- package/dist/utils/NotificationManager.d.ts.map +1 -0
- package/dist/utils/NotificationManager.js +84 -0
- package/dist/utils/NotificationManager.js.map +1 -0
- package/dist/utils/proxied-assistant-state.d.ts +8 -0
- package/dist/utils/proxied-assistant-state.d.ts.map +1 -0
- package/dist/utils/proxied-assistant-state.js +34 -0
- package/dist/utils/proxied-assistant-state.js.map +1 -0
- package/dist/utils/react-assistant-context.d.ts +1 -1
- package/dist/utils/react-assistant-context.d.ts.map +1 -1
- package/dist/utils/react-assistant-context.js +2 -1
- package/dist/utils/react-assistant-context.js.map +1 -1
- package/dist/utils/splitClients.d.ts +10 -0
- package/dist/utils/splitClients.d.ts.map +1 -0
- package/dist/utils/splitClients.js +53 -0
- package/dist/utils/splitClients.js.map +1 -0
- package/dist/utils/tap-assistant-context.d.ts +19 -0
- package/dist/utils/tap-assistant-context.d.ts.map +1 -0
- package/dist/utils/tap-assistant-context.js +23 -0
- package/dist/utils/tap-assistant-context.js.map +1 -0
- package/dist/utils/tap-client-stack-context.d.ts +23 -0
- package/dist/utils/tap-client-stack-context.d.ts.map +1 -0
- package/dist/utils/tap-client-stack-context.js +28 -0
- package/dist/utils/tap-client-stack-context.js.map +1 -0
- package/dist/wrapperResource.d.ts +3 -0
- package/dist/wrapperResource.d.ts.map +1 -0
- package/dist/wrapperResource.js +11 -0
- package/dist/wrapperResource.js.map +1 -0
- package/package.json +5 -5
- package/src/AuiIf.ts +1 -1
- package/src/Derived.ts +46 -0
- package/src/__tests__/hooks.test.tsx +1 -1
- package/src/attachTransformScopes.ts +38 -0
- package/src/index.ts +37 -21
- package/src/tapClientList.ts +121 -0
- package/src/tapClientLookup.ts +79 -0
- package/src/tapClientResource.ts +187 -0
- package/src/types/client.ts +180 -0
- package/src/types/events.ts +77 -0
- package/src/useAui.ts +21 -19
- package/src/useAuiEvent.ts +2 -2
- package/src/useAuiState.ts +3 -3
- package/src/utils/BaseProxyHandler.ts +50 -0
- package/src/utils/NotificationManager.ts +114 -0
- package/src/utils/proxied-assistant-state.ts +53 -0
- package/src/utils/react-assistant-context.tsx +3 -7
- package/src/utils/splitClients.ts +80 -0
- package/src/utils/tap-assistant-context.ts +58 -0
- package/src/utils/tap-client-stack-context.ts +51 -0
- package/src/wrapperResource.ts +17 -0
- package/dist/scope-registry-forward.d.ts +0 -6
- package/dist/scope-registry-forward.d.ts.map +0 -1
- package/dist/scope-registry-forward.js +0 -2
- package/dist/scope-registry-forward.js.map +0 -1
- package/dist/scope-registry.d.ts +0 -17
- package/dist/scope-registry.d.ts.map +0 -1
- package/dist/scope-registry.js +0 -2
- package/dist/scope-registry.js.map +0 -1
- package/src/scope-registry-forward.ts +0 -6
- package/src/scope-registry.ts +0 -15
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { getClientState } from "../tapClientResource";
|
|
3
|
+
import type { AssistantClient, AssistantState } from "../types/client";
|
|
4
|
+
import { BaseProxyHandler, handleIntrospectionProp } from "./BaseProxyHandler";
|
|
5
|
+
|
|
6
|
+
export const PROXIED_ASSISTANT_STATE_SYMBOL = Symbol(
|
|
7
|
+
"assistant-ui.store.proxiedAssistantState",
|
|
8
|
+
);
|
|
9
|
+
|
|
10
|
+
const isIgnoredKey = (key: string | symbol): key is "on" | "subscribe" => {
|
|
11
|
+
return key === "on" || key === "subscribe" || typeof key === "symbol";
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Proxied state that lazily accesses scope states
|
|
16
|
+
*/
|
|
17
|
+
export const createProxiedAssistantState = (
|
|
18
|
+
client: AssistantClient,
|
|
19
|
+
): AssistantState => {
|
|
20
|
+
class ProxiedAssistantStateProxyHandler
|
|
21
|
+
extends BaseProxyHandler
|
|
22
|
+
implements ProxyHandler<AssistantState>
|
|
23
|
+
{
|
|
24
|
+
get(_: unknown, prop: string | symbol) {
|
|
25
|
+
const introspection = handleIntrospectionProp(prop, "AssistantState");
|
|
26
|
+
if (introspection !== false) return introspection;
|
|
27
|
+
const scope = prop as keyof AssistantClient;
|
|
28
|
+
if (isIgnoredKey(scope)) return undefined;
|
|
29
|
+
return getClientState(client[scope]());
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
ownKeys(): ArrayLike<string | symbol> {
|
|
33
|
+
return Object.keys(client).filter((key) => !isIgnoredKey(key));
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
has(_: unknown, prop: string | symbol): boolean {
|
|
37
|
+
return !isIgnoredKey(prop) && prop in client;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
return new Proxy<AssistantState>(
|
|
42
|
+
{} as AssistantState,
|
|
43
|
+
new ProxiedAssistantStateProxyHandler(),
|
|
44
|
+
);
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
export const getProxiedAssistantState = (
|
|
48
|
+
client: AssistantClient,
|
|
49
|
+
): AssistantState => {
|
|
50
|
+
return (
|
|
51
|
+
client as unknown as { [PROXIED_ASSISTANT_STATE_SYMBOL]: AssistantState }
|
|
52
|
+
)[PROXIED_ASSISTANT_STATE_SYMBOL];
|
|
53
|
+
};
|
|
@@ -1,14 +1,10 @@
|
|
|
1
1
|
import React, { createContext, useContext } from "react";
|
|
2
|
-
import type {
|
|
3
|
-
AssistantClient,
|
|
4
|
-
AssistantClientAccessor,
|
|
5
|
-
} from "@assistant-ui/core/store";
|
|
2
|
+
import type { AssistantClient, AssistantClientAccessor } from "../types/client";
|
|
6
3
|
import {
|
|
7
4
|
createProxiedAssistantState,
|
|
8
5
|
PROXIED_ASSISTANT_STATE_SYMBOL,
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
} from "@assistant-ui/core/store/internal";
|
|
6
|
+
} from "./proxied-assistant-state";
|
|
7
|
+
import { BaseProxyHandler, handleIntrospectionProp } from "./BaseProxyHandler";
|
|
12
8
|
|
|
13
9
|
const NO_OP_SUBSCRIBE = () => () => {};
|
|
14
10
|
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { Derived, DerivedElement } from "../Derived";
|
|
2
|
+
import type {
|
|
3
|
+
AssistantClient,
|
|
4
|
+
ClientElement,
|
|
5
|
+
ClientNames,
|
|
6
|
+
} from "../types/client";
|
|
7
|
+
import { getTransformScopes } from "../attachTransformScopes";
|
|
8
|
+
import type { useAui } from "../useAui";
|
|
9
|
+
import { tapMemo } from "@assistant-ui/tap";
|
|
10
|
+
|
|
11
|
+
export type RootClients = Partial<
|
|
12
|
+
Record<ClientNames, ClientElement<ClientNames>>
|
|
13
|
+
>;
|
|
14
|
+
export type DerivedClients = Partial<
|
|
15
|
+
Record<ClientNames, DerivedElement<ClientNames>>
|
|
16
|
+
>;
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Splits a clients object into root clients and derived clients,
|
|
20
|
+
* applying transformScopes from root client elements.
|
|
21
|
+
*/
|
|
22
|
+
function splitClients(clients: useAui.Props, baseClient: AssistantClient) {
|
|
23
|
+
// 1. Collect transforms from root elements and run them iteratively
|
|
24
|
+
let scopes = { ...clients } as Record<
|
|
25
|
+
string,
|
|
26
|
+
ClientElement<ClientNames> | DerivedElement<ClientNames>
|
|
27
|
+
>;
|
|
28
|
+
const visited = new Set<(...args: any[]) => any>();
|
|
29
|
+
|
|
30
|
+
let changed = true;
|
|
31
|
+
while (changed) {
|
|
32
|
+
changed = false;
|
|
33
|
+
for (const clientElement of Object.values(scopes)) {
|
|
34
|
+
if (clientElement.type === (Derived as unknown)) continue;
|
|
35
|
+
if (visited.has(clientElement.type)) continue;
|
|
36
|
+
visited.add(clientElement.type);
|
|
37
|
+
|
|
38
|
+
const transform = getTransformScopes(clientElement.type);
|
|
39
|
+
if (transform) {
|
|
40
|
+
scopes = transform(scopes, baseClient) as typeof scopes;
|
|
41
|
+
changed = true;
|
|
42
|
+
break; // restart iteration since scopes may have new root elements
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// 2. Split result into root/derived
|
|
48
|
+
const rootClients: RootClients = {};
|
|
49
|
+
const derivedClients: DerivedClients = {};
|
|
50
|
+
|
|
51
|
+
for (const [key, clientElement] of Object.entries(scopes) as [
|
|
52
|
+
ClientNames,
|
|
53
|
+
ClientElement<ClientNames> | DerivedElement<ClientNames>,
|
|
54
|
+
][]) {
|
|
55
|
+
if (clientElement.type === (Derived as unknown)) {
|
|
56
|
+
derivedClients[key] = clientElement as DerivedElement<ClientNames>;
|
|
57
|
+
} else {
|
|
58
|
+
rootClients[key] = clientElement as ClientElement<ClientNames>;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
return { rootClients, derivedClients };
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const tapShallowMemoObject = <T extends object>(object: T) => {
|
|
66
|
+
// biome-ignore lint/correctness/useExhaustiveDependencies: shallow memo
|
|
67
|
+
return tapMemo(() => object, [...Object.entries(object).flat()]);
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
export const tapSplitClients = (
|
|
71
|
+
clients: useAui.Props,
|
|
72
|
+
baseClient: AssistantClient,
|
|
73
|
+
) => {
|
|
74
|
+
const { rootClients, derivedClients } = splitClients(clients, baseClient);
|
|
75
|
+
|
|
76
|
+
return {
|
|
77
|
+
rootClients: tapShallowMemoObject(rootClients),
|
|
78
|
+
derivedClients: tapShallowMemoObject(derivedClients),
|
|
79
|
+
};
|
|
80
|
+
};
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import {
|
|
2
|
+
createResourceContext,
|
|
3
|
+
tap,
|
|
4
|
+
withContextProvider,
|
|
5
|
+
tapEffectEvent,
|
|
6
|
+
} from "@assistant-ui/tap";
|
|
7
|
+
import type {
|
|
8
|
+
AssistantEventName,
|
|
9
|
+
AssistantEventPayload,
|
|
10
|
+
} from "../types/events";
|
|
11
|
+
import type { AssistantClient } from "../types/client";
|
|
12
|
+
import { tapClientStack, type ClientStack } from "./tap-client-stack-context";
|
|
13
|
+
|
|
14
|
+
type EmitFn = <TEvent extends Exclude<AssistantEventName, "*">>(
|
|
15
|
+
event: TEvent,
|
|
16
|
+
payload: AssistantEventPayload[TEvent],
|
|
17
|
+
clientStack: ClientStack,
|
|
18
|
+
) => void;
|
|
19
|
+
|
|
20
|
+
export type AssistantTapContextValue = {
|
|
21
|
+
clientRef: { parent: AssistantClient; current: AssistantClient | null };
|
|
22
|
+
emit: EmitFn;
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
const AssistantTapContext =
|
|
26
|
+
createResourceContext<AssistantTapContextValue | null>(null);
|
|
27
|
+
|
|
28
|
+
export const withAssistantTapContextProvider = <TResult>(
|
|
29
|
+
value: AssistantTapContextValue,
|
|
30
|
+
fn: () => TResult,
|
|
31
|
+
) => {
|
|
32
|
+
return withContextProvider(AssistantTapContext, value, fn);
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
const tapAssistantTapContext = () => {
|
|
36
|
+
const ctx = tap(AssistantTapContext);
|
|
37
|
+
if (!ctx) throw new Error("AssistantTapContext is not available");
|
|
38
|
+
|
|
39
|
+
return ctx;
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
export const tapAssistantClientRef = () => {
|
|
43
|
+
return tapAssistantTapContext().clientRef;
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
export const tapAssistantEmit = () => {
|
|
47
|
+
const { emit } = tapAssistantTapContext();
|
|
48
|
+
const clientStack = tapClientStack();
|
|
49
|
+
|
|
50
|
+
return tapEffectEvent(
|
|
51
|
+
<TEvent extends Exclude<AssistantEventName, "*">>(
|
|
52
|
+
event: TEvent,
|
|
53
|
+
payload: AssistantEventPayload[TEvent],
|
|
54
|
+
) => {
|
|
55
|
+
emit(event, payload, clientStack);
|
|
56
|
+
},
|
|
57
|
+
);
|
|
58
|
+
};
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import {
|
|
2
|
+
createResourceContext,
|
|
3
|
+
tap,
|
|
4
|
+
withContextProvider,
|
|
5
|
+
tapMemo,
|
|
6
|
+
} from "@assistant-ui/tap";
|
|
7
|
+
import type { ClientMethods } from "../types/client";
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Symbol used to get the client index from a ClientProxy.
|
|
11
|
+
*/
|
|
12
|
+
export const SYMBOL_CLIENT_INDEX = Symbol("assistant-ui.store.clientIndex");
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Get the index of a client (its position in the client stack when created).
|
|
16
|
+
*/
|
|
17
|
+
export const getClientIndex = (client: ClientMethods): number => {
|
|
18
|
+
return (client as unknown as { [SYMBOL_CLIENT_INDEX]: number })[
|
|
19
|
+
SYMBOL_CLIENT_INDEX
|
|
20
|
+
];
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* The client stack - an array of clients representing the current hierarchy.
|
|
25
|
+
*/
|
|
26
|
+
export type ClientStack = readonly ClientMethods[];
|
|
27
|
+
|
|
28
|
+
const ClientStackContext = createResourceContext<ClientStack>([]);
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Get the current client stack inside a tap resource.
|
|
32
|
+
*/
|
|
33
|
+
export const tapClientStack = (): ClientStack => {
|
|
34
|
+
return tap(ClientStackContext);
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Execute a callback with a client pushed onto the stack.
|
|
39
|
+
* The stack is duplicated, not mutated.
|
|
40
|
+
*/
|
|
41
|
+
export const tapWithClientStack = <T>(
|
|
42
|
+
client: ClientMethods,
|
|
43
|
+
callback: () => T,
|
|
44
|
+
): T => {
|
|
45
|
+
const currentStack = tapClientStack();
|
|
46
|
+
const newStack = tapMemo(
|
|
47
|
+
() => [...currentStack, client],
|
|
48
|
+
[currentStack, client],
|
|
49
|
+
);
|
|
50
|
+
return withContextProvider(ClientStackContext, newStack, callback);
|
|
51
|
+
};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import {
|
|
2
|
+
type ResourceElement,
|
|
3
|
+
Resource,
|
|
4
|
+
resource,
|
|
5
|
+
withKey,
|
|
6
|
+
} from "@assistant-ui/tap";
|
|
7
|
+
|
|
8
|
+
export const wrapperResource = <R, P>(
|
|
9
|
+
fn: (props: ResourceElement<P>) => R,
|
|
10
|
+
): Resource<R, ResourceElement<P>> => {
|
|
11
|
+
const res = resource(fn);
|
|
12
|
+
return (props: ResourceElement<P>) => {
|
|
13
|
+
const el = res(props);
|
|
14
|
+
if (props.key === undefined) return el;
|
|
15
|
+
return withKey(props.key, el);
|
|
16
|
+
};
|
|
17
|
+
};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"scope-registry-forward.d.ts","sourceRoot":"","sources":["../src/scope-registry-forward.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,IAAI,kBAAkB,EAAE,4BAAyB;AAG5E,OAAO,QAAQ,0BAA0B,CAAC;IACxC,UAAU,aAAc,SAAQ,kBAAkB;KAAG;CACtD"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"scope-registry-forward.js","sourceRoot":"","sources":["../src/scope-registry-forward.ts"],"names":[],"mappings":""}
|
package/dist/scope-registry.d.ts
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Module augmentation interface for assistant-ui store type extensions.
|
|
3
|
-
*
|
|
4
|
-
* Users augment this interface to register custom scopes:
|
|
5
|
-
* ```typescript
|
|
6
|
-
* declare module "@assistant-ui/store" {
|
|
7
|
-
* interface ScopeRegistry {
|
|
8
|
-
* myScope: { methods: { getState: () => MyState } };
|
|
9
|
-
* }
|
|
10
|
-
* }
|
|
11
|
-
* ```
|
|
12
|
-
*
|
|
13
|
-
* Augmentations are automatically forwarded to `@assistant-ui/core/store`.
|
|
14
|
-
*/
|
|
15
|
-
export interface ScopeRegistry {
|
|
16
|
-
}
|
|
17
|
-
//# sourceMappingURL=scope-registry.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"scope-registry.d.ts","sourceRoot":"","sources":["../src/scope-registry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,MAAM,WAAW,aAAa;CAAG"}
|
package/dist/scope-registry.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"scope-registry.js","sourceRoot":"","sources":["../src/scope-registry.ts"],"names":[],"mappings":""}
|
package/src/scope-registry.ts
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Module augmentation interface for assistant-ui store type extensions.
|
|
3
|
-
*
|
|
4
|
-
* Users augment this interface to register custom scopes:
|
|
5
|
-
* ```typescript
|
|
6
|
-
* declare module "@assistant-ui/store" {
|
|
7
|
-
* interface ScopeRegistry {
|
|
8
|
-
* myScope: { methods: { getState: () => MyState } };
|
|
9
|
-
* }
|
|
10
|
-
* }
|
|
11
|
-
* ```
|
|
12
|
-
*
|
|
13
|
-
* Augmentations are automatically forwarded to `@assistant-ui/core/store`.
|
|
14
|
-
*/
|
|
15
|
-
export interface ScopeRegistry {}
|