Skip to content

Commit bb76112

Browse files
authored
Merge pull request #54 from viamrobotics/add-resource-stream-hook
add create resource stream hook
2 parents 5a61a1a + 6724887 commit bb76112

File tree

6 files changed

+119
-10
lines changed

6 files changed

+119
-10
lines changed

.changeset/cuddly-kids-love.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@viamrobotics/svelte-sdk': minor
3+
---
4+
5+
Add createResourceStream hook

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@
6363
"@testing-library/svelte": "^5.2.8",
6464
"@viamrobotics/eslint-config": "^1.1.0",
6565
"@viamrobotics/prettier-config-svelte": "^1.1.0",
66-
"@viamrobotics/sdk": "^0.45.0",
66+
"@viamrobotics/sdk": "^0.49.1",
6767
"@viamrobotics/typescript-config": "^0.1.1",
6868
"eslint": "^9.30.0",
6969
"eslint-config-prettier": "^10.1.5",

pnpm-lock.yaml

Lines changed: 5 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
import {
2+
experimental_streamedQuery as streamedQuery,
3+
createQuery,
4+
type QueryObserverResult,
5+
queryOptions as createQueryOptions,
6+
} from '@tanstack/svelte-query';
7+
import type { Resource } from '@viamrobotics/sdk';
8+
import { toStore, fromStore } from 'svelte/store';
9+
import { useQueryLogger } from '../query-logger';
10+
11+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
12+
export type ArgumentsType<T> = T extends (...args: infer U) => any ? U : never;
13+
14+
export type StreamItemType<T> = T extends (
15+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
16+
...args: any[]
17+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
18+
) => AsyncGenerator<infer R, any, any>
19+
? R
20+
: never;
21+
22+
interface QueryOptions {
23+
// enabled defaults to true if unspecified
24+
enabled?: boolean;
25+
refetchMode?: 'append' | 'reset' | 'replace';
26+
maxChunks?: number;
27+
}
28+
29+
type QueryResult<U> = QueryObserverResult<U[], Error>;
30+
31+
export const createResourceStream = <T extends Resource, K extends keyof T>(
32+
client: { current: T | undefined },
33+
method: K,
34+
...additional:
35+
| [
36+
args?: (() => ArgumentsType<T[K]>) | ArgumentsType<T[K]>,
37+
options?: (() => QueryOptions) | QueryOptions,
38+
]
39+
| [options?: (() => QueryOptions) | QueryOptions]
40+
): { current: QueryResult<StreamItemType<T[K]>> } => {
41+
const debug = useQueryLogger();
42+
43+
let [args, options] = additional;
44+
45+
if (options === undefined && args !== undefined) {
46+
options = args as QueryOptions;
47+
args = undefined;
48+
}
49+
50+
const _options = $derived(
51+
typeof options === 'function' ? options() : options
52+
);
53+
54+
const _args = $derived(typeof args === 'function' ? args() : args);
55+
const name = $derived(client.current?.name);
56+
const methodName = $derived(String(method));
57+
const queryKey = $derived([
58+
'viam-svelte-sdk',
59+
'partID',
60+
(client.current as T & { partID: string })?.partID,
61+
'resource',
62+
name,
63+
methodName,
64+
...(_args ? [_args] : []),
65+
]);
66+
67+
function processStream() {
68+
const clientFunc = client.current?.[method];
69+
70+
if (typeof clientFunc !== 'function') {
71+
throw new TypeError(
72+
`${String(method)} is not a method on the resource client.`
73+
);
74+
}
75+
76+
const logger = debug.createLogger();
77+
logger('REQ', name, methodName, _args);
78+
79+
try {
80+
const response = clientFunc?.apply(
81+
client.current,
82+
_args
83+
) as AsyncGenerator<StreamItemType<T[K]>>;
84+
console.log('response', typeof response);
85+
86+
logger('RES', name, methodName, response);
87+
return response;
88+
} catch (error) {
89+
logger('ERR', name, methodName, error);
90+
throw error;
91+
}
92+
}
93+
94+
const queryOptions = $derived(
95+
createQueryOptions({
96+
queryKey,
97+
enabled: client.current !== undefined && _options?.enabled !== false,
98+
queryFn: streamedQuery<StreamItemType<T[K]>>({
99+
queryFn: processStream,
100+
..._options,
101+
}),
102+
})
103+
);
104+
105+
return fromStore(createQuery(toStore(() => queryOptions)));
106+
};

src/lib/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ export { createRobotMutation } from './hooks/create-robot-mutation.svelte';
1616
export { createResourceClient } from './hooks/create-resource-client.svelte';
1717
export { createResourceQuery } from './hooks/create-resource-query.svelte';
1818
export { createResourceMutation } from './hooks/create-resource-mutation.svelte';
19+
export { createResourceStream } from './hooks/create-resource-stream.svelte';
1920
export { createStreamClient } from './hooks/create-stream-client.svelte';
2021

2122
export { useMachineStatus } from './hooks/machine-status.svelte';

src/routes/+layout.svelte

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -43,10 +43,7 @@ let { children }: Props = $props();
4343
{/each}
4444
</div>
4545

46-
<ViamProvider
47-
{dialConfigs}
48-
logQueries
49-
>
46+
<ViamProvider {dialConfigs}>
5047
<Parts />
5148
{@render children()}
5249
<SvelteQueryDevtools />

0 commit comments

Comments
 (0)