You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
94 lines
2.5 KiB
94 lines
2.5 KiB
import type {
|
|
ConnectedLdoDataset,
|
|
ConnectedPlugin,
|
|
GetResourceReturnType,
|
|
} from "@ldo/connected";
|
|
import { writable, type Readable } from "svelte/store";
|
|
|
|
export interface UseResourceOptions<Name> {
|
|
pluginName?: Name;
|
|
suppressInitialRead?: boolean;
|
|
reloadOnMount?: boolean;
|
|
subscribe?: boolean;
|
|
}
|
|
|
|
export type useResourceType<Plugins extends ConnectedPlugin[]> = {
|
|
<
|
|
Name extends Plugins[number]["name"],
|
|
Plugin extends Extract<Plugins[number], { name: Name }>,
|
|
UriType extends string,
|
|
>(
|
|
uri: UriType,
|
|
options?: UseResourceOptions<Name>,
|
|
): Readable<GetResourceReturnType<Plugin, UriType>>;
|
|
<
|
|
Name extends Plugins[number]["name"],
|
|
Plugin extends Extract<Plugins[number], { name: Name }>,
|
|
UriType extends string,
|
|
>(
|
|
uri?: UriType,
|
|
options?: UseResourceOptions<Name>,
|
|
): Readable<GetResourceReturnType<Plugin, UriType> | undefined>;
|
|
};
|
|
|
|
/**
|
|
* @internal
|
|
*
|
|
* Creates a useResource function.
|
|
*/
|
|
export function createUseResource<Plugins extends ConnectedPlugin[]>(
|
|
dataset: ConnectedLdoDataset<Plugins>,
|
|
): useResourceType<Plugins> {
|
|
/**
|
|
* Returns a resource and triggers a rerender if that resource is updated.
|
|
*/
|
|
return function useResource<
|
|
Name extends Plugins[number]["name"],
|
|
Plugin extends Extract<Plugins[number], { name: Name }>,
|
|
UriType extends string,
|
|
>(
|
|
uri?: UriType,
|
|
options?: UseResourceOptions<Name>,
|
|
): Readable<GetResourceReturnType<Plugin, UriType> | undefined> {
|
|
let resource: GetResourceReturnType<Plugin, UriType> | undefined;
|
|
// Get the resource based on incoming data
|
|
if (uri) {
|
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
resource = dataset.getResource(uri) as any;
|
|
// Run read operations if necissary
|
|
if (!options?.suppressInitialRead) {
|
|
if (options?.reloadOnMount) {
|
|
resource!.read();
|
|
} else {
|
|
resource!.readIfUnfetched();
|
|
}
|
|
}
|
|
} else {
|
|
resource = undefined;
|
|
}
|
|
|
|
// The Svelte store
|
|
const store = writable<GetResourceReturnType<Plugin, UriType> | undefined>(
|
|
resource,
|
|
(set) => {
|
|
const onResourceUpdate = () => {
|
|
set(resource);
|
|
};
|
|
|
|
if (resource) {
|
|
resource.on("update", onResourceUpdate);
|
|
|
|
// TODO: handle subscriptions
|
|
|
|
return () => {
|
|
resource.off("update", onResourceUpdate);
|
|
};
|
|
}
|
|
},
|
|
);
|
|
|
|
return {
|
|
subscribe: store.subscribe,
|
|
};
|
|
};
|
|
}
|
|
|