@fragno-dev/core 0.1.11 → 0.2.2
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/.turbo/turbo-build.log +87 -69
- package/CHANGELOG.md +79 -0
- package/dist/api/api.d.ts +21 -2
- package/dist/api/api.d.ts.map +1 -1
- package/dist/api/api.js +2 -1
- package/dist/api/api.js.map +1 -1
- package/dist/api/bind-services.d.ts +0 -1
- package/dist/api/bind-services.d.ts.map +1 -1
- package/dist/api/bind-services.js.map +1 -1
- package/dist/api/error.d.ts.map +1 -1
- package/dist/api/error.js.map +1 -1
- package/dist/api/fragment-definition-builder.d.ts +32 -40
- package/dist/api/fragment-definition-builder.d.ts.map +1 -1
- package/dist/api/fragment-definition-builder.js +15 -21
- package/dist/api/fragment-definition-builder.js.map +1 -1
- package/dist/api/fragment-instantiator.d.ts +51 -30
- package/dist/api/fragment-instantiator.d.ts.map +1 -1
- package/dist/api/fragment-instantiator.js +201 -52
- package/dist/api/fragment-instantiator.js.map +1 -1
- package/dist/api/request-context-storage.d.ts +4 -0
- package/dist/api/request-context-storage.d.ts.map +1 -1
- package/dist/api/request-context-storage.js +6 -0
- package/dist/api/request-context-storage.js.map +1 -1
- package/dist/api/request-input-context.d.ts +57 -1
- package/dist/api/request-input-context.d.ts.map +1 -1
- package/dist/api/request-input-context.js +67 -0
- package/dist/api/request-input-context.js.map +1 -1
- package/dist/api/request-middleware.d.ts +2 -2
- package/dist/api/request-middleware.d.ts.map +1 -1
- package/dist/api/request-middleware.js.map +1 -1
- package/dist/api/request-output-context.d.ts +1 -1
- package/dist/api/request-output-context.d.ts.map +1 -1
- package/dist/api/request-output-context.js.map +1 -1
- package/dist/api/route-caller.d.ts +30 -0
- package/dist/api/route-caller.d.ts.map +1 -0
- package/dist/api/route-caller.js +63 -0
- package/dist/api/route-caller.js.map +1 -0
- package/dist/api/route-handler-input-options.d.ts.map +1 -1
- package/dist/api/route.d.ts +8 -8
- package/dist/api/route.d.ts.map +1 -1
- package/dist/api/route.js.map +1 -1
- package/dist/api/shared-types.d.ts.map +1 -1
- package/dist/client/client-error.d.ts.map +1 -1
- package/dist/client/client-error.js.map +1 -1
- package/dist/client/client.d.ts +90 -50
- package/dist/client/client.d.ts.map +1 -1
- package/dist/client/client.js +128 -16
- package/dist/client/client.js.map +1 -1
- package/dist/client/client.svelte.d.ts +6 -5
- package/dist/client/client.svelte.d.ts.map +1 -1
- package/dist/client/client.svelte.js +10 -2
- package/dist/client/client.svelte.js.map +1 -1
- package/dist/client/internal/ndjson-streaming.js.map +1 -1
- package/dist/client/react.d.ts +5 -4
- package/dist/client/react.d.ts.map +1 -1
- package/dist/client/react.js +104 -12
- package/dist/client/react.js.map +1 -1
- package/dist/client/solid.d.ts +7 -5
- package/dist/client/solid.d.ts.map +1 -1
- package/dist/client/solid.js +23 -9
- package/dist/client/solid.js.map +1 -1
- package/dist/client/vanilla.d.ts +16 -4
- package/dist/client/vanilla.d.ts.map +1 -1
- package/dist/client/vanilla.js +21 -1
- package/dist/client/vanilla.js.map +1 -1
- package/dist/client/vue.d.ts +10 -4
- package/dist/client/vue.d.ts.map +1 -1
- package/dist/client/vue.js +24 -1
- package/dist/client/vue.js.map +1 -1
- package/dist/id.d.ts +2 -0
- package/dist/id.js +3 -0
- package/dist/internal/cuid.d.ts +16 -0
- package/dist/internal/cuid.d.ts.map +1 -0
- package/dist/internal/cuid.js +82 -0
- package/dist/internal/cuid.js.map +1 -0
- package/dist/internal/trace-context.d.ts +23 -0
- package/dist/internal/trace-context.d.ts.map +1 -0
- package/dist/internal/trace-context.js +14 -0
- package/dist/internal/trace-context.js.map +1 -0
- package/dist/mod-client.d.ts +7 -20
- package/dist/mod-client.d.ts.map +1 -1
- package/dist/mod-client.js +25 -13
- package/dist/mod-client.js.map +1 -1
- package/dist/mod.d.ts +8 -6
- package/dist/mod.js +3 -1
- package/dist/runtime.d.ts +15 -0
- package/dist/runtime.d.ts.map +1 -0
- package/dist/runtime.js +33 -0
- package/dist/runtime.js.map +1 -0
- package/dist/test/test.d.ts +6 -6
- package/dist/test/test.d.ts.map +1 -1
- package/dist/test/test.js.map +1 -1
- package/dist/util/ssr.js.map +1 -1
- package/package.json +42 -52
- package/src/api/api.test.ts +3 -1
- package/src/api/api.ts +28 -0
- package/src/api/bind-services.ts +0 -5
- package/src/api/error.ts +1 -0
- package/src/api/fragment-definition-builder.extend.test.ts +2 -1
- package/src/api/fragment-definition-builder.test.ts +2 -1
- package/src/api/fragment-definition-builder.ts +56 -112
- package/src/api/fragment-instantiator.test.ts +311 -166
- package/src/api/fragment-instantiator.ts +470 -131
- package/src/api/fragment-services.test.ts +1 -0
- package/src/api/internal/path-runtime.test.ts +8 -0
- package/src/api/internal/path-type.test.ts +3 -1
- package/src/api/internal/route.test.ts +1 -0
- package/src/api/request-context-storage.ts +7 -0
- package/src/api/request-input-context.test.ts +156 -2
- package/src/api/request-input-context.ts +87 -1
- package/src/api/request-middleware.test.ts +43 -2
- package/src/api/request-middleware.ts +4 -3
- package/src/api/request-output-context.test.ts +3 -1
- package/src/api/request-output-context.ts +2 -1
- package/src/api/route-caller.test.ts +195 -0
- package/src/api/route-caller.ts +167 -0
- package/src/api/route-handler-input-options.ts +2 -1
- package/src/api/route.test.ts +4 -2
- package/src/api/route.ts +9 -3
- package/src/api/shared-types.ts +2 -1
- package/src/client/client-builder.test.ts +4 -2
- package/src/client/client-error.test.ts +2 -1
- package/src/client/client-error.ts +1 -1
- package/src/client/client-types.test.ts +19 -5
- package/src/client/client.ssr.test.ts +6 -4
- package/src/client/client.svelte.test.ts +18 -9
- package/src/client/client.svelte.ts +38 -13
- package/src/client/client.test.ts +244 -10
- package/src/client/client.ts +473 -148
- package/src/client/internal/ndjson-streaming.test.ts +6 -3
- package/src/client/internal/ndjson-streaming.ts +1 -0
- package/src/client/react.test.ts +176 -6
- package/src/client/react.ts +226 -31
- package/src/client/solid.test.ts +29 -5
- package/src/client/solid.ts +60 -22
- package/src/client/vanilla.test.ts +148 -6
- package/src/client/vanilla.ts +63 -9
- package/src/client/vue.test.ts +397 -8
- package/src/client/vue.ts +74 -4
- package/src/id.ts +1 -0
- package/src/internal/cuid.test.ts +164 -0
- package/src/internal/cuid.ts +133 -0
- package/src/internal/trace-context.ts +35 -0
- package/src/mod-client.ts +55 -9
- package/src/mod.ts +9 -3
- package/src/runtime.ts +48 -0
- package/src/test/test.test.ts +4 -2
- package/src/test/test.ts +14 -7
- package/src/util/async.test.ts +1 -0
- package/src/util/content-type.test.ts +1 -0
- package/src/util/nanostores.test.ts +3 -1
- package/src/util/ssr.ts +1 -0
- package/tsconfig.json +1 -1
- package/tsdown.config.ts +2 -0
- package/vitest.config.ts +2 -1
package/dist/client/react.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { hydrateFromWindow } from "../util/ssr.js";
|
|
2
1
|
import { isReadableAtom } from "../util/nanostores.js";
|
|
2
|
+
import { hydrateFromWindow } from "../util/ssr.js";
|
|
3
3
|
import { isGetHook, isMutatorHook, isStore } from "./client.js";
|
|
4
4
|
import { listenKeys } from "nanostores";
|
|
5
|
-
import { useCallback, useMemo, useRef, useSyncExternalStore } from "react";
|
|
5
|
+
import { useCallback, useEffect, useMemo, useRef, useSyncExternalStore } from "react";
|
|
6
6
|
|
|
7
7
|
//#region src/client/react.ts
|
|
8
8
|
function createReactHook(hook) {
|
|
@@ -22,18 +22,110 @@ function createReactMutator(hook) {
|
|
|
22
22
|
return useStore(useMemo(() => hook.mutatorStore, [hook]));
|
|
23
23
|
};
|
|
24
24
|
}
|
|
25
|
-
|
|
26
|
-
if (
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
25
|
+
const isPlainObject = (value) => {
|
|
26
|
+
if (!value || typeof value !== "object") return false;
|
|
27
|
+
const prototype = Object.getPrototypeOf(value);
|
|
28
|
+
return prototype === Object.prototype || prototype === null;
|
|
29
|
+
};
|
|
30
|
+
const areStoreFactoryValuesEqual = (left, right) => {
|
|
31
|
+
if (Object.is(left, right)) return true;
|
|
32
|
+
if (Array.isArray(left) && Array.isArray(right)) return left.length === right.length && left.every((value, index) => areStoreFactoryValuesEqual(value, right[index]));
|
|
33
|
+
if (left instanceof Date && right instanceof Date) return left.getTime() === right.getTime();
|
|
34
|
+
if (isReadableAtom(left) || isReadableAtom(right)) return left === right;
|
|
35
|
+
if (typeof left === "function" || typeof right === "function") return left === right;
|
|
36
|
+
if (isPlainObject(left) && isPlainObject(right)) {
|
|
37
|
+
const leftKeys = Object.keys(left).sort();
|
|
38
|
+
const rightKeys = Object.keys(right).sort();
|
|
39
|
+
return leftKeys.length === rightKeys.length && leftKeys.every((key, index) => key === rightKeys[index] && areStoreFactoryValuesEqual(left[key], right[key]));
|
|
40
|
+
}
|
|
41
|
+
return false;
|
|
42
|
+
};
|
|
43
|
+
const areStoreFactoryArgsEqual = (left, right) => left.length === right.length && left.every((value, index) => areStoreFactoryValuesEqual(value, right[index]));
|
|
44
|
+
const getStoreDisposer = (value) => {
|
|
45
|
+
const disposer = value[Symbol.dispose];
|
|
46
|
+
return typeof disposer === "function" ? disposer.bind(value) : void 0;
|
|
47
|
+
};
|
|
48
|
+
const createReactStoreObjectView = (value, getAtomValue) => {
|
|
49
|
+
const atomValues = /* @__PURE__ */ new Map();
|
|
50
|
+
const boundMethods = /* @__PURE__ */ new Map();
|
|
51
|
+
return new Proxy(value, { get(target, property, _receiver) {
|
|
52
|
+
const propertyValue = Reflect.get(target, property, target);
|
|
53
|
+
if (isReadableAtom(propertyValue)) {
|
|
54
|
+
if (atomValues.has(propertyValue)) return atomValues.get(propertyValue);
|
|
55
|
+
const atomValue = getAtomValue(propertyValue);
|
|
56
|
+
atomValues.set(propertyValue, atomValue);
|
|
57
|
+
return atomValue;
|
|
58
|
+
}
|
|
59
|
+
if (typeof propertyValue === "function") {
|
|
60
|
+
if (boundMethods.has(property)) return boundMethods.get(property);
|
|
61
|
+
const boundMethod = propertyValue.bind(target);
|
|
62
|
+
boundMethods.set(property, boundMethod);
|
|
63
|
+
return boundMethod;
|
|
34
64
|
}
|
|
35
|
-
return
|
|
65
|
+
return propertyValue;
|
|
66
|
+
} });
|
|
67
|
+
};
|
|
68
|
+
function unwrapReactStoreValueOnServer(value) {
|
|
69
|
+
if (isReadableAtom(value)) return value.get();
|
|
70
|
+
return createReactStoreObjectView(value, (store) => store.get());
|
|
71
|
+
}
|
|
72
|
+
function unwrapReactStoreValue(value) {
|
|
73
|
+
if (isReadableAtom(value)) return useStore(value);
|
|
74
|
+
const atomEntries = Object.keys(value).flatMap((key) => {
|
|
75
|
+
const fieldValue = value[key];
|
|
76
|
+
return isReadableAtom(fieldValue) ? [[key, fieldValue]] : [];
|
|
77
|
+
});
|
|
78
|
+
const snapshotRef = useRef(atomEntries.map(([, store]) => store.get()));
|
|
79
|
+
const getSnapshot = () => {
|
|
80
|
+
const nextSnapshot = atomEntries.map(([, store]) => store.get());
|
|
81
|
+
const previousSnapshot = snapshotRef.current;
|
|
82
|
+
if (previousSnapshot.length === nextSnapshot.length && previousSnapshot.every((entry, index) => Object.is(entry, nextSnapshot[index]))) return previousSnapshot;
|
|
83
|
+
snapshotRef.current = nextSnapshot;
|
|
84
|
+
return nextSnapshot;
|
|
36
85
|
};
|
|
86
|
+
const atomValues = useSyncExternalStore((onStoreChange) => {
|
|
87
|
+
const unsubscribes = atomEntries.map(([, store]) => store.listen(onStoreChange));
|
|
88
|
+
return () => {
|
|
89
|
+
for (const unsubscribe of unsubscribes) unsubscribe();
|
|
90
|
+
};
|
|
91
|
+
}, getSnapshot, getSnapshot);
|
|
92
|
+
return useMemo(() => createReactStoreObjectView(value, (store) => {
|
|
93
|
+
const atomIndex = atomEntries.findIndex(([, entryStore]) => entryStore === store);
|
|
94
|
+
return atomIndex === -1 ? store.get() : atomValues[atomIndex];
|
|
95
|
+
}), [
|
|
96
|
+
value,
|
|
97
|
+
atomEntries,
|
|
98
|
+
atomValues
|
|
99
|
+
]);
|
|
100
|
+
}
|
|
101
|
+
function createReactStore(hook) {
|
|
102
|
+
return ((...args) => {
|
|
103
|
+
const stableArgsRef = useRef(args);
|
|
104
|
+
const pendingDisposalsRef = useRef(/* @__PURE__ */ new Map());
|
|
105
|
+
if (!areStoreFactoryArgsEqual(stableArgsRef.current, args)) stableArgsRef.current = args;
|
|
106
|
+
const value = useMemo(() => {
|
|
107
|
+
if ("factory" in hook) return hook.factory(...stableArgsRef.current);
|
|
108
|
+
return hook.obj;
|
|
109
|
+
}, [hook, stableArgsRef.current]);
|
|
110
|
+
useEffect(() => {
|
|
111
|
+
const disposer = getStoreDisposer(value);
|
|
112
|
+
const pendingTimeout = pendingDisposalsRef.current.get(value);
|
|
113
|
+
if (pendingTimeout !== void 0) {
|
|
114
|
+
clearTimeout(pendingTimeout);
|
|
115
|
+
pendingDisposalsRef.current.delete(value);
|
|
116
|
+
}
|
|
117
|
+
return () => {
|
|
118
|
+
if (!disposer) return;
|
|
119
|
+
const timeoutId = setTimeout(() => {
|
|
120
|
+
pendingDisposalsRef.current.delete(value);
|
|
121
|
+
disposer();
|
|
122
|
+
}, 0);
|
|
123
|
+
pendingDisposalsRef.current.set(value, timeoutId);
|
|
124
|
+
};
|
|
125
|
+
}, [value]);
|
|
126
|
+
if (typeof window === "undefined") return unwrapReactStoreValueOnServer(value);
|
|
127
|
+
return unwrapReactStoreValue(value);
|
|
128
|
+
});
|
|
37
129
|
}
|
|
38
130
|
function useFragno(clientObj) {
|
|
39
131
|
const result = {};
|
package/dist/client/react.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"react.js","names":["result: any"],"sources":["../../src/client/react.ts"],"sourcesContent":["import type { FetcherValue } from \"@nanostores/query\";\nimport type { StandardSchemaV1 } from \"@standard-schema/spec\";\nimport { listenKeys, type ReadableAtom, type Store, type StoreValue } from \"nanostores\";\nimport { useCallback, useMemo, useRef, useSyncExternalStore, type DependencyList } from \"react\";\nimport type { NonGetHTTPMethod } from \"../api/api\";\nimport type { FragnoClientMutatorData, FragnoClientHookData } from \"./client\";\nimport { isGetHook, isMutatorHook, isStore, type FragnoStoreData } from \"./client\";\nimport type { FragnoClientError } from \"./client-error\";\nimport { hydrateFromWindow } from \"../util/ssr\";\nimport type { InferOr } from \"../util/types-util\";\nimport type {\n ExtractPathParamsOrWiden,\n HasPathParams,\n MaybeExtractPathParamsOrWiden,\n QueryParamsHint,\n} from \"../api/internal/path\";\nimport { isReadableAtom } from \"../util/nanostores\";\n\nexport type FragnoReactHook<\n _TMethod extends \"GET\",\n TPath extends string,\n TOutputSchema extends StandardSchemaV1,\n TErrorCode extends string,\n TQueryParameters extends string,\n> = (args?: {\n path?: MaybeExtractPathParamsOrWiden<TPath, string | ReadableAtom<string>>;\n query?: QueryParamsHint<TQueryParameters, string | ReadableAtom<string>>;\n}) => FetcherValue<\n StandardSchemaV1.InferOutput<TOutputSchema>,\n FragnoClientError<NonNullable<TErrorCode>>\n>;\n\nexport type FragnoReactMutator<\n _TMethod extends NonGetHTTPMethod,\n TPath extends string,\n TInputSchema extends StandardSchemaV1 | undefined,\n TOutputSchema extends StandardSchemaV1 | undefined,\n TErrorCode extends string,\n TQueryParameters extends string,\n> = () => {\n mutate: ({\n body,\n path,\n query,\n }: {\n body?: InferOr<TInputSchema, undefined>;\n path?: HasPathParams<TPath> extends true\n ? ExtractPathParamsOrWiden<TPath, string | ReadableAtom<string>>\n : undefined;\n query?: QueryParamsHint<TQueryParameters, string | ReadableAtom<string>>;\n }) => Promise<InferOr<TOutputSchema, undefined>>;\n loading?: boolean | undefined;\n error?: FragnoClientError<NonNullable<TErrorCode>[number]> | undefined;\n data?: InferOr<TOutputSchema, undefined> | undefined;\n};\n\n// Helper function to create a React hook from a GET hook\nfunction createReactHook<\n TMethod extends \"GET\",\n TPath extends string,\n TOutputSchema extends StandardSchemaV1,\n TErrorCode extends string,\n TQueryParameters extends string,\n>(\n hook: FragnoClientHookData<TMethod, TPath, TOutputSchema, TErrorCode, TQueryParameters>,\n): FragnoReactHook<TMethod, TPath, TOutputSchema, TErrorCode, TQueryParameters> {\n return ({ path, query } = {}) => {\n const pathParamValues = path ? Object.values(path) : [];\n const queryParamValues = query ? Object.values(query) : [];\n\n const deps = [...pathParamValues, ...queryParamValues];\n\n const store = useMemo(() => hook.store({ path, query }), [hook, ...deps]);\n\n if (typeof window === \"undefined\") {\n // TODO(Wilco): Handle server-side rendering. In React we have to implement onShellReady\n // and onAllReady in renderToPipable stream.\n const serverSideData = store.get();\n return serverSideData;\n }\n\n return useStore(store);\n };\n}\n\n// Helper function to create a React mutator from a mutator hook\nfunction createReactMutator<\n TMethod extends NonGetHTTPMethod,\n TPath extends string,\n TInput extends StandardSchemaV1 | undefined,\n TOutput extends StandardSchemaV1 | undefined,\n TError extends string,\n TQueryParameters extends string,\n>(\n hook: FragnoClientMutatorData<TMethod, TPath, TInput, TOutput, TError, TQueryParameters>,\n): FragnoReactMutator<TMethod, TPath, TInput, TOutput, TError, TQueryParameters> {\n return () => {\n const store = useMemo(() => hook.mutatorStore, [hook]);\n return useStore(store);\n };\n}\n\n/**\n * Type helper that unwraps any Store fields of the object into StoreValues\n */\nexport type FragnoReactStore<T extends object> = () => T extends Store<infer TStore>\n ? StoreValue<TStore>\n : {\n [K in keyof T]: T[K] extends Store ? StoreValue<T[K]> : T[K];\n };\n\nfunction createReactStore<const T extends object>(hook: FragnoStoreData<T>): FragnoReactStore<T> {\n if (isReadableAtom(hook.obj)) {\n return () => useStore(hook.obj as Store);\n }\n\n return () => {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const result: any = {};\n\n for (const key in hook.obj) {\n if (!Object.prototype.hasOwnProperty.call(hook.obj, key)) {\n continue;\n }\n\n const value = hook.obj[key];\n if (isReadableAtom(value)) {\n result[key] = useStore(value);\n } else {\n result[key] = value;\n }\n }\n\n return result;\n };\n}\n\nexport function useFragno<T extends Record<string, unknown>>(\n clientObj: T,\n): {\n [K in keyof T]: T[K] extends FragnoClientHookData<\n \"GET\",\n infer TPath,\n infer TOutputSchema,\n infer TErrorCode,\n infer TQueryParameters\n >\n ? FragnoReactHook<\"GET\", TPath, TOutputSchema, TErrorCode, TQueryParameters>\n : T[K] extends FragnoClientMutatorData<\n infer TMethod,\n infer TPath,\n infer TInput,\n infer TOutput,\n infer TError,\n infer TQueryParameters\n >\n ? FragnoReactMutator<TMethod, TPath, TInput, TOutput, TError, TQueryParameters>\n : T[K] extends FragnoStoreData<infer TStoreObj>\n ? FragnoReactStore<TStoreObj>\n : T[K];\n} {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const result = {} as any; // We need one any cast here due to TypeScript's limitations with mapped types\n\n for (const key in clientObj) {\n if (!Object.prototype.hasOwnProperty.call(clientObj, key)) {\n continue;\n }\n\n const hook = clientObj[key];\n if (isGetHook(hook)) {\n result[key] = createReactHook(hook);\n } else if (isMutatorHook(hook)) {\n result[key] = createReactMutator(hook);\n } else if (isStore(hook)) {\n result[key] = createReactStore(hook);\n } else {\n // Pass through non-hook values unchanged\n result[key] = hook;\n }\n }\n\n return result;\n}\n\ntype StoreKeys<T> = T extends { setKey: (k: infer K, v: unknown) => unknown } ? K : never;\n\nexport interface UseStoreOptions<SomeStore> {\n /**\n * @default\n * ```ts\n * [store, options.keys]\n * ```\n */\n deps?: DependencyList;\n\n /**\n * Will re-render components only on specific key changes.\n */\n keys?: StoreKeys<SomeStore>[];\n}\n\nexport function useStore<SomeStore extends Store>(\n store: SomeStore,\n options: UseStoreOptions<SomeStore> = {},\n): StoreValue<SomeStore> {\n const snapshotRef = useRef<StoreValue<SomeStore>>(store.get());\n\n const { keys, deps = [store, keys] } = options;\n\n const subscribe = useCallback((onChange: () => void) => {\n const emitChange = (value: StoreValue<SomeStore>) => {\n if (snapshotRef.current === value) {\n return;\n }\n snapshotRef.current = value;\n onChange();\n };\n\n emitChange(store.value);\n if (keys?.length) {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return listenKeys(store as any, keys, emitChange);\n }\n return store.listen(emitChange);\n }, deps);\n\n const get = () => snapshotRef.current as StoreValue<SomeStore>;\n\n return useSyncExternalStore(subscribe, get, () => {\n // Server-side rendering\n return get();\n });\n}\n\nexport function FragnoHydrator({ children }: { children: React.ReactNode }) {\n // Ensure initial data is transferred from window before any hooks run\n // Running in useMemo makes this happen during render, ahead of effects\n useMemo(() => {\n hydrateFromWindow();\n }, []);\n return children;\n}\n"],"mappings":";;;;;;;AAyDA,SAAS,gBAOP,MAC8E;AAC9E,SAAQ,EAAE,MAAM,UAAU,EAAE,KAAK;EAC/B,MAAM,kBAAkB,OAAO,OAAO,OAAO,KAAK,GAAG,EAAE;EACvD,MAAM,mBAAmB,QAAQ,OAAO,OAAO,MAAM,GAAG,EAAE;EAI1D,MAAM,QAAQ,cAAc,KAAK,MAAM;GAAE;GAAM;GAAO,CAAC,EAAE,CAAC,MAAM,GAFnD,CAAC,GAAG,iBAAiB,GAAG,iBAAiB,CAEkB,CAAC;AAEzE,MAAI,OAAO,WAAW,YAIpB,QADuB,MAAM,KAAK;AAIpC,SAAO,SAAS,MAAM;;;AAK1B,SAAS,mBAQP,MAC+E;AAC/E,cAAa;AAEX,SAAO,SADO,cAAc,KAAK,cAAc,CAAC,KAAK,CAAC,CAChC;;;AAa1B,SAAS,iBAAyC,MAA+C;AAC/F,KAAI,eAAe,KAAK,IAAI,CAC1B,cAAa,SAAS,KAAK,IAAa;AAG1C,cAAa;EAEX,MAAMA,SAAc,EAAE;AAEtB,OAAK,MAAM,OAAO,KAAK,KAAK;AAC1B,OAAI,CAAC,OAAO,UAAU,eAAe,KAAK,KAAK,KAAK,IAAI,CACtD;GAGF,MAAM,QAAQ,KAAK,IAAI;AACvB,OAAI,eAAe,MAAM,CACvB,QAAO,OAAO,SAAS,MAAM;OAE7B,QAAO,OAAO;;AAIlB,SAAO;;;AAIX,SAAgB,UACd,WAsBA;CAEA,MAAM,SAAS,EAAE;AAEjB,MAAK,MAAM,OAAO,WAAW;AAC3B,MAAI,CAAC,OAAO,UAAU,eAAe,KAAK,WAAW,IAAI,CACvD;EAGF,MAAM,OAAO,UAAU;AACvB,MAAI,UAAU,KAAK,CACjB,QAAO,OAAO,gBAAgB,KAAK;WAC1B,cAAc,KAAK,CAC5B,QAAO,OAAO,mBAAmB,KAAK;WAC7B,QAAQ,KAAK,CACtB,QAAO,OAAO,iBAAiB,KAAK;MAGpC,QAAO,OAAO;;AAIlB,QAAO;;AAoBT,SAAgB,SACd,OACA,UAAsC,EAAE,EACjB;CACvB,MAAM,cAAc,OAA8B,MAAM,KAAK,CAAC;CAE9D,MAAM,EAAE,MAAM,OAAO,CAAC,OAAO,KAAK,KAAK;CAEvC,MAAM,YAAY,aAAa,aAAyB;EACtD,MAAM,cAAc,UAAiC;AACnD,OAAI,YAAY,YAAY,MAC1B;AAEF,eAAY,UAAU;AACtB,aAAU;;AAGZ,aAAW,MAAM,MAAM;AACvB,MAAI,MAAM,OAER,QAAO,WAAW,OAAc,MAAM,WAAW;AAEnD,SAAO,MAAM,OAAO,WAAW;IAC9B,KAAK;CAER,MAAM,YAAY,YAAY;AAE9B,QAAO,qBAAqB,WAAW,WAAW;AAEhD,SAAO,KAAK;GACZ;;AAGJ,SAAgB,eAAe,EAAE,YAA2C;AAG1E,eAAc;AACZ,qBAAmB;IAClB,EAAE,CAAC;AACN,QAAO"}
|
|
1
|
+
{"version":3,"file":"react.js","names":[],"sources":["../../src/client/react.ts"],"sourcesContent":["import { listenKeys, type ReadableAtom, type Store, type StoreValue } from \"nanostores\";\nimport {\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useSyncExternalStore,\n type DependencyList,\n} from \"react\";\n\nimport type { FetcherValue } from \"@nanostores/query\";\nimport type { StandardSchemaV1 } from \"@standard-schema/spec\";\n\nimport type { NonGetHTTPMethod } from \"../api/api\";\nimport type {\n ExtractPathParamsOrWiden,\n HasPathParams,\n MaybeExtractPathParamsOrWiden,\n QueryParamsHint,\n} from \"../api/internal/path\";\nimport { isReadableAtom } from \"../util/nanostores\";\nimport { hydrateFromWindow } from \"../util/ssr\";\nimport type { InferOr } from \"../util/types-util\";\nimport type { FragnoClientMutatorData, FragnoClientHookData } from \"./client\";\nimport {\n isGetHook,\n isMutatorHook,\n isStore,\n type FragnoStoreData,\n type FragnoStoreFactoryData,\n type FragnoStoreObjectData,\n} from \"./client\";\nimport type { FragnoClientError } from \"./client-error\";\n\nexport type FragnoReactHook<\n _TMethod extends \"GET\",\n TPath extends string,\n TOutputSchema extends StandardSchemaV1,\n TErrorCode extends string,\n TQueryParameters extends string,\n> = (args?: {\n path?: MaybeExtractPathParamsOrWiden<TPath, string | ReadableAtom<string>>;\n query?: QueryParamsHint<TQueryParameters, string | ReadableAtom<string>>;\n}) => FetcherValue<\n StandardSchemaV1.InferOutput<TOutputSchema>,\n FragnoClientError<NonNullable<TErrorCode>>\n>;\n\nexport type FragnoReactMutator<\n _TMethod extends NonGetHTTPMethod,\n TPath extends string,\n TInputSchema extends StandardSchemaV1 | undefined,\n TOutputSchema extends StandardSchemaV1 | undefined,\n TErrorCode extends string,\n TQueryParameters extends string,\n> = () => {\n mutate: ({\n body,\n path,\n query,\n }: {\n body?: InferOr<TInputSchema, undefined>;\n path?: HasPathParams<TPath> extends true\n ? ExtractPathParamsOrWiden<TPath, string | ReadableAtom<string>>\n : undefined;\n query?: QueryParamsHint<TQueryParameters, string | ReadableAtom<string>>;\n }) => Promise<InferOr<TOutputSchema, undefined>>;\n loading?: boolean | undefined;\n error?: FragnoClientError<NonNullable<TErrorCode>[number]> | undefined;\n data?: InferOr<TOutputSchema, undefined> | undefined;\n};\n\n// Helper function to create a React hook from a GET hook\nfunction createReactHook<\n TMethod extends \"GET\",\n TPath extends string,\n TOutputSchema extends StandardSchemaV1,\n TErrorCode extends string,\n TQueryParameters extends string,\n>(\n hook: FragnoClientHookData<TMethod, TPath, TOutputSchema, TErrorCode, TQueryParameters>,\n): FragnoReactHook<TMethod, TPath, TOutputSchema, TErrorCode, TQueryParameters> {\n return ({ path, query } = {}) => {\n const pathParamValues = path ? Object.values(path) : [];\n const queryParamValues = query ? Object.values(query) : [];\n\n const deps = [...pathParamValues, ...queryParamValues];\n\n const store = useMemo(() => hook.store({ path, query }), [hook, ...deps]);\n\n if (typeof window === \"undefined\") {\n // TODO(Wilco): Handle server-side rendering. In React we have to implement onShellReady\n // and onAllReady in renderToPipable stream.\n const serverSideData = store.get();\n return serverSideData;\n }\n\n return useStore(store);\n };\n}\n\n// Helper function to create a React mutator from a mutator hook\nfunction createReactMutator<\n TMethod extends NonGetHTTPMethod,\n TPath extends string,\n TInput extends StandardSchemaV1 | undefined,\n TOutput extends StandardSchemaV1 | undefined,\n TError extends string,\n TQueryParameters extends string,\n>(\n hook: FragnoClientMutatorData<TMethod, TPath, TInput, TOutput, TError, TQueryParameters>,\n): FragnoReactMutator<TMethod, TPath, TInput, TOutput, TError, TQueryParameters> {\n return () => {\n const store = useMemo(() => hook.mutatorStore, [hook]);\n return useStore(store);\n };\n}\n\n/**\n * Type helper that unwraps any Store fields of the object into StoreValues\n */\ntype FragnoReactStoreValue<T extends object> =\n T extends Store<infer TStore>\n ? StoreValue<TStore>\n : {\n [K in keyof T]: T[K] extends Store ? StoreValue<T[K]> : T[K];\n };\n\nexport type FragnoReactStore<T extends object, TArgs extends unknown[] = []> = (\n ...args: TArgs\n) => FragnoReactStoreValue<T>;\n\nconst isPlainObject = (value: unknown): value is Record<string, unknown> => {\n if (!value || typeof value !== \"object\") {\n return false;\n }\n\n const prototype = Object.getPrototypeOf(value);\n return prototype === Object.prototype || prototype === null;\n};\n\nconst areStoreFactoryValuesEqual = (left: unknown, right: unknown): boolean => {\n if (Object.is(left, right)) {\n return true;\n }\n\n if (Array.isArray(left) && Array.isArray(right)) {\n return (\n left.length === right.length &&\n left.every((value, index) => areStoreFactoryValuesEqual(value, right[index]))\n );\n }\n\n if (left instanceof Date && right instanceof Date) {\n return left.getTime() === right.getTime();\n }\n\n if (isReadableAtom(left) || isReadableAtom(right)) {\n return left === right;\n }\n\n if (typeof left === \"function\" || typeof right === \"function\") {\n return left === right;\n }\n\n if (isPlainObject(left) && isPlainObject(right)) {\n const leftKeys = Object.keys(left).sort();\n const rightKeys = Object.keys(right).sort();\n return (\n leftKeys.length === rightKeys.length &&\n leftKeys.every(\n (key, index) =>\n key === rightKeys[index] && areStoreFactoryValuesEqual(left[key], right[key]),\n )\n );\n }\n\n return false;\n};\n\nconst areStoreFactoryArgsEqual = (left: unknown[], right: unknown[]) =>\n left.length === right.length &&\n left.every((value, index) => areStoreFactoryValuesEqual(value, right[index]));\n\nconst getStoreDisposer = (value: object): (() => void) | undefined => {\n const disposer = (value as { [Symbol.dispose]?: (() => void) | undefined })[Symbol.dispose];\n return typeof disposer === \"function\" ? disposer.bind(value) : undefined;\n};\n\nconst createReactStoreObjectView = <T extends object>(\n value: T,\n getAtomValue: (store: Store<unknown>) => unknown,\n): FragnoReactStoreValue<T> => {\n const atomValues = new Map<Store<unknown>, unknown>();\n const boundMethods = new Map<PropertyKey, unknown>();\n\n return new Proxy(value, {\n get(target, property, _receiver) {\n const propertyValue = Reflect.get(target, property, target);\n\n if (isReadableAtom(propertyValue)) {\n if (atomValues.has(propertyValue)) {\n return atomValues.get(propertyValue);\n }\n\n const atomValue = getAtomValue(propertyValue);\n atomValues.set(propertyValue, atomValue);\n return atomValue;\n }\n\n if (typeof propertyValue === \"function\") {\n if (boundMethods.has(property)) {\n return boundMethods.get(property);\n }\n\n const boundMethod = propertyValue.bind(target);\n boundMethods.set(property, boundMethod);\n return boundMethod;\n }\n\n return propertyValue;\n },\n }) as FragnoReactStoreValue<T>;\n};\n\nfunction unwrapReactStoreValueOnServer<T extends object>(value: T): FragnoReactStoreValue<T> {\n if (isReadableAtom(value)) {\n return value.get() as FragnoReactStoreValue<T>;\n }\n\n return createReactStoreObjectView(value, (store) => store.get());\n}\n\nfunction unwrapReactStoreValue<T extends object>(value: T): FragnoReactStoreValue<T> {\n if (isReadableAtom(value)) {\n return useStore(value as Store) as FragnoReactStoreValue<T>;\n }\n\n const keys = Object.keys(value);\n const atomEntries = keys.flatMap((key) => {\n const fieldValue = value[key as keyof T];\n return isReadableAtom(fieldValue)\n ? ([[key, fieldValue]] as Array<[string, Store<unknown>]>)\n : [];\n });\n const snapshotRef = useRef<unknown[]>(atomEntries.map(([, store]) => store.get()));\n\n const getSnapshot = () => {\n const nextSnapshot = atomEntries.map(([, store]) => store.get());\n const previousSnapshot = snapshotRef.current;\n if (\n previousSnapshot.length === nextSnapshot.length &&\n previousSnapshot.every((entry, index) => Object.is(entry, nextSnapshot[index]))\n ) {\n return previousSnapshot;\n }\n snapshotRef.current = nextSnapshot;\n return nextSnapshot;\n };\n\n const atomValues = useSyncExternalStore(\n (onStoreChange) => {\n const unsubscribes = atomEntries.map(([, store]) => store.listen(onStoreChange));\n return () => {\n for (const unsubscribe of unsubscribes) {\n unsubscribe();\n }\n };\n },\n getSnapshot,\n getSnapshot,\n );\n\n return useMemo(\n () =>\n createReactStoreObjectView(value, (store) => {\n const atomIndex = atomEntries.findIndex(([, entryStore]) => entryStore === store);\n return atomIndex === -1 ? store.get() : atomValues[atomIndex];\n }),\n [value, atomEntries, atomValues],\n );\n}\n\nfunction createReactStore<const T extends object, const TArgs extends unknown[]>(\n hook: FragnoStoreData<T, TArgs>,\n): FragnoReactStore<T, TArgs> {\n return ((...args: TArgs) => {\n const stableArgsRef = useRef<TArgs>(args);\n const pendingDisposalsRef = useRef<Map<object, ReturnType<typeof setTimeout>>>(new Map());\n if (!areStoreFactoryArgsEqual(stableArgsRef.current, args)) {\n stableArgsRef.current = args;\n }\n\n const value = useMemo(() => {\n if (\"factory\" in hook) {\n return hook.factory(...stableArgsRef.current);\n }\n\n return hook.obj;\n }, [hook, stableArgsRef.current]);\n\n useEffect(() => {\n const disposer = getStoreDisposer(value);\n const pendingTimeout = pendingDisposalsRef.current.get(value);\n if (pendingTimeout !== undefined) {\n clearTimeout(pendingTimeout);\n pendingDisposalsRef.current.delete(value);\n }\n\n return () => {\n if (!disposer) {\n return;\n }\n\n const timeoutId = setTimeout(() => {\n pendingDisposalsRef.current.delete(value);\n disposer();\n }, 0);\n pendingDisposalsRef.current.set(value, timeoutId);\n };\n }, [value]);\n\n if (typeof window === \"undefined\") {\n return unwrapReactStoreValueOnServer(value);\n }\n\n return unwrapReactStoreValue(value);\n }) as FragnoReactStore<T, TArgs>;\n}\n\nexport function useFragno<T extends Record<string, unknown>>(\n clientObj: T,\n): {\n [K in keyof T]: T[K] extends FragnoClientHookData<\n \"GET\",\n infer TPath,\n infer TOutputSchema,\n infer TErrorCode,\n infer TQueryParameters\n >\n ? FragnoReactHook<\"GET\", TPath, TOutputSchema, TErrorCode, TQueryParameters>\n : T[K] extends FragnoClientMutatorData<\n infer TMethod,\n infer TPath,\n infer TInput,\n infer TOutput,\n infer TError,\n infer TQueryParameters\n >\n ? FragnoReactMutator<TMethod, TPath, TInput, TOutput, TError, TQueryParameters>\n : T[K] extends FragnoStoreObjectData<infer TStoreObj>\n ? FragnoReactStore<TStoreObj, []>\n : T[K] extends FragnoStoreFactoryData<infer TStoreObj, infer TStoreArgs>\n ? FragnoReactStore<TStoreObj, TStoreArgs>\n : T[K];\n} {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const result = {} as any; // We need one any cast here due to TypeScript's limitations with mapped types\n\n for (const key in clientObj) {\n if (!Object.prototype.hasOwnProperty.call(clientObj, key)) {\n continue;\n }\n\n const hook = clientObj[key];\n if (isGetHook(hook)) {\n result[key] = createReactHook(hook);\n } else if (isMutatorHook(hook)) {\n result[key] = createReactMutator(hook);\n } else if (isStore(hook)) {\n result[key] = createReactStore(hook);\n } else {\n // Pass through non-hook values unchanged\n result[key] = hook;\n }\n }\n\n return result;\n}\n\ntype StoreKeys<T> = T extends { setKey: (k: infer K, v: unknown) => unknown } ? K : never;\n\nexport interface UseStoreOptions<SomeStore> {\n /**\n * @default\n * ```ts\n * [store, options.keys]\n * ```\n */\n deps?: DependencyList;\n\n /**\n * Will re-render components only on specific key changes.\n */\n keys?: StoreKeys<SomeStore>[];\n}\n\nexport function useStore<SomeStore extends Store>(\n store: SomeStore,\n options: UseStoreOptions<SomeStore> = {},\n): StoreValue<SomeStore> {\n const snapshotRef = useRef<StoreValue<SomeStore>>(store.get());\n\n const { keys, deps = [store, keys] } = options;\n\n const subscribe = useCallback((onChange: () => void) => {\n const emitChange = (value: StoreValue<SomeStore>) => {\n if (snapshotRef.current === value) {\n return;\n }\n snapshotRef.current = value;\n onChange();\n };\n\n emitChange(store.value);\n if (keys?.length) {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return listenKeys(store as any, keys, emitChange);\n }\n return store.listen(emitChange);\n }, deps);\n\n const get = () => snapshotRef.current as StoreValue<SomeStore>;\n\n return useSyncExternalStore(subscribe, get, () => {\n // Server-side rendering\n return get();\n });\n}\n\nexport function FragnoHydrator({ children }: { children: React.ReactNode }) {\n // Ensure initial data is transferred from window before any hooks run\n // Running in useMemo makes this happen during render, ahead of effects\n useMemo(() => {\n hydrateFromWindow();\n }, []);\n return children;\n}\n"],"mappings":"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"}
|
package/dist/client/solid.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { MaybeExtractPathParamsOrWiden, QueryParamsHint } from "../api/internal/path.js";
|
|
2
2
|
import { InferOr } from "../util/types-util.js";
|
|
3
|
-
import { NonGetHTTPMethod } from "../api/api.js";
|
|
4
3
|
import { FragnoClientError } from "./client-error.js";
|
|
5
|
-
import { FragnoClientHookData, FragnoClientMutatorData, FragnoStoreData } from "./client.js";
|
|
4
|
+
import { FragnoClientHookData, FragnoClientMutatorData, FragnoStoreData, FragnoStoreFactoryData, FragnoStoreObjectData } from "./client.js";
|
|
5
|
+
import { NonGetHTTPMethod } from "../api/api.js";
|
|
6
6
|
import { ReadableAtom, Store, StoreValue } from "nanostores";
|
|
7
7
|
import { Accessor } from "solid-js";
|
|
8
8
|
import { StandardSchemaV1 } from "@standard-schema/spec";
|
|
@@ -39,9 +39,11 @@ declare function isAccessor(value: unknown): value is Accessor<string>;
|
|
|
39
39
|
*
|
|
40
40
|
* @private
|
|
41
41
|
*/
|
|
42
|
-
declare function accessorToAtom<T>(accessor: Accessor<T>): ReadableAtom<T>;
|
|
43
|
-
type
|
|
44
|
-
|
|
42
|
+
declare function accessorToAtom<T$1>(accessor: Accessor<T$1>): ReadableAtom<T$1>;
|
|
43
|
+
type FragnoSolidStoreValue<T$1 extends object> = T$1 extends Store ? Accessor<StoreValue<T$1>> : { [K in keyof T$1]: T$1[K] extends Store ? Accessor<StoreValue<T$1[K]>> : T$1[K] };
|
|
44
|
+
type FragnoSolidStaticStore<T$1 extends object> = T$1 extends Store ? Accessor<StoreValue<T$1>> : () => { [K in keyof T$1]: T$1[K] extends Store ? Accessor<StoreValue<T$1[K]>> : T$1[K] };
|
|
45
|
+
type FragnoSolidStore<TStore extends FragnoStoreData<object, unknown[]>> = TStore extends FragnoStoreFactoryData<infer T, infer TArgs> ? (...args: TArgs) => FragnoSolidStoreValue<T> : TStore extends FragnoStoreObjectData<infer T> ? FragnoSolidStaticStore<T> : never;
|
|
46
|
+
declare function useFragno<T$1 extends Record<string, unknown>>(clientObj: T$1): { [K in keyof T$1]: T$1[K] extends FragnoClientHookData<"GET", infer TPath, infer TOutputSchema, infer TErrorCode, infer TQueryParameters> ? FragnoSolidHook<"GET", TPath, TOutputSchema, TErrorCode, TQueryParameters> : T$1[K] extends FragnoClientMutatorData<infer TMethod, infer TPath, infer TInput, infer TOutput, infer TError, infer TQueryParameters> ? FragnoSolidMutator<TMethod, TPath, TInput, TOutput, TError, TQueryParameters> : T$1[K] extends FragnoStoreData<object, unknown[]> ? FragnoSolidStore<T$1[K]> : T$1[K] };
|
|
45
47
|
//#endregion
|
|
46
48
|
export { FragnoSolidHook, FragnoSolidMutator, FragnoSolidStore, accessorToAtom, isAccessor, useFragno };
|
|
47
49
|
//# sourceMappingURL=solid.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"solid.d.ts","names":[],"sources":["../../src/client/solid.ts"],"sourcesContent":[],"mappings":";;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"solid.d.ts","names":[],"sources":["../../src/client/solid.ts"],"sourcesContent":[],"mappings":";;;;;;;;;;KAuBY,wFAGY,yFAAA;SAIf,8BAA8B,kBAAgB,mBAAmB;EAP9D,KAAA,CAAA,EAQF,eARiB,CAQD,kBARC,EAAA,MAAA,GAQ0B,QAR1B,CAAA,MAAA,CAAA,GAQ6C,YAR7C,CAAA,MAAA,CAAA,CAAA;CAGH,EAAA,GAAA;EAIe,IAAA,EAG/B,QAH+B,CAGtB,OAHsB,CAGd,eAHc,EAAA,SAAA,CAAA,CAAA;EAAgB,OAAA,EAI5C,QAJ4C,CAAA,OAAA,CAAA;EAAmB,KAAA,EAKjE,QALiE,CAKxD,iBALwD,CAKtC,YALsC,CAAA,MAAA,CAAA,CAAA,GAAA,SAAA,CAAA;CAAjE;AACiB,KAOd,kBAPc,CAAA,iBAQP,gBARO,EAAA,gBAAA,MAAA,EAAA,qBAUH,gBAVG,GAAA,SAAA,EAAA,wBAWF,gBAXE,GAAA,SAAA,EAAA,qBAAA,MAAA,EAAA,2BAAA,MAAA,CAAA,GAAA,GAAA,GAAA;EAA2B,MAAA,EAAA,CAAA,IAAA,EAAA;IAAmB,IAAA,CAAA,EAgB7D,OAhB6D,CAgBrD,YAhBqD,EAAA,SAAA,CAAA;IAA9D,IAAA,CAAA,EAiBC,6BAjBD,CAiB+B,OAjB/B,EAAA,MAAA,GAiB+C,QAjB/C,CAAA,MAAA,CAAA,GAiBkE,YAjBlE,CAAA,MAAA,CAAA,CAAA;IAEe,KAAA,CAAA,EAgBb,eAhBa,CAgBG,kBAhBH,EAAA,MAAA,GAgB8B,QAhB9B,CAAA,MAAA,CAAA,GAgBiD,YAhBjD,CAAA,MAAA,CAAA,CAAA;EAAR,CAAA,EAAA,GAiBT,OAjBS,CAiBD,OAjBC,CAiBO,eAjBP,EAAA,SAAA,CAAA,CAAA;EAAT,OAAA,EAkBG,QAlBH,CAAA,OAAA,GAAA,SAAA,CAAA;EACG,KAAA,EAkBF,QAlBE,CAkBO,iBAlBP,CAkByB,YAlBzB,CAAA,MAAA,CAAA,CAAA,GAAA,SAAA,CAAA;EACyB,IAAA,EAkB5B,QAlB4B,CAkBnB,OAlBmB,CAkBX,eAlBW,EAAA,SAAA,CAAA,CAAA;CAAlB;;;AAGlB;;;AAIwB,iBAmBR,UAAA,CAnBQ,KAAA,EAAA,OAAA,CAAA,EAAA,KAAA,IAmB6B,QAnB7B,CAAA,MAAA,CAAA;;;;;;;;AAO+B,iBAuBvC,cAvBuC,CAAA,GAAA,CAAA,CAAA,QAAA,EAuBX,QAvBW,CAuBF,GAvBE,CAAA,CAAA,EAuBG,YAvBH,CAuBgB,GAvBhB,CAAA;KAuIlD,qBAvIqE,CAAA,YAAA,MAAA,CAAA,GAuI3B,GAvI2B,SAuIjB,KAvIiB,GAwItE,QAxIsE,CAwI7D,UAxI6D,CAwIlD,GAxIkD,CAAA,CAAA,GAAA,QAA9D,MA0IM,GA1IN,GA0IU,GA1IV,CA0IY,CA1IZ,CAAA,SA0IuB,KA1IvB,GA0I+B,QA1I/B,CA0IwC,UA1IxC,CA0ImD,GA1InD,CA0IqD,CA1IrD,CAAA,CAAA,CAAA,GA0I4D,GA1I5D,CA0I8D,CA1I9D,CAAA,EACY;KA4InB,sBA5IW,CAAA,YAAA,MAAA,CAAA,GA4IgC,GA5IhC,SA4I0C,KA5I1C,GA6IZ,QA7IY,CA6IH,UA7IG,CA6IQ,GA7IR,CAAA,CAAA,GAAA,GAAA,GAAA,QAAR,MA+IU,GA/IV,GA+Ic,GA/Id,CA+IgB,CA/IhB,CAAA,SA+I2B,KA/I3B,GA+ImC,QA/InC,CA+I4C,UA/I5C,CA+IuD,GA/IvD,CA+IyD,CA/IzD,CAAA,CAAA,CAAA,GA+IgE,GA/IhE,CA+IkE,CA/IlE,CAAA,EACG;AACyB,KAgJxB,gBAhJwB,CAAA,eAgJQ,eAhJR,CAAA,MAAA,EAAA,OAAA,EAAA,CAAA,CAAA,GAiJlC,MAjJkC,SAiJnB,sBAjJmB,CAAA,KAAA,EAAA,EAAA,KAAA,MAAA,CAAA,GAAA,CAAA,GAAA,IAAA,EAkJpB,KAlJoB,EAAA,GAkJV,qBAlJU,CAkJY,CAlJZ,CAAA,GAmJ9B,MAnJ8B,SAmJf,qBAnJe,CAAA,KAAA,EAAA,CAAA,GAoJ5B,sBApJ4B,CAoJL,CApJK,CAAA,GAAA,KAAA;AAAlB,iBAwMF,SAxME,CAAA,YAwMkB,MAxMlB,CAAA,MAAA,EAAA,OAAA,CAAA,CAAA,CAAA,SAAA,EAyML,GAzMK,CAAA,EAAA,QAAT,MA2MK,GA3ML,GA2MS,GA3MT,CA2MW,CA3MX,CAAA,SA2MsB,oBA3MtB,CAAA,KAAA,EAAA,KAAA,MAAA,EAAA,KAAA,cAAA,EAAA,KAAA,WAAA,EAAA,KAAA,iBAAA,CAAA,GAkNH,eAlNG,CAAA,KAAA,EAkNoB,KAlNpB,EAkN2B,aAlN3B,EAkN0C,UAlN1C,EAkNsD,gBAlNtD,CAAA,GAmNH,GAnNG,CAmND,CAnNC,CAAA,SAmNU,uBAnNV,CAAA,KAAA,QAAA,EAAA,KAAA,MAAA,EAAA,KAAA,OAAA,EAAA,KAAA,QAAA,EAAA,KAAA,OAAA,EAAA,KAAA,iBAAA,CAAA,GA2ND,kBA3NC,CA2NkB,OA3NlB,EA2N2B,KA3N3B,EA2NkC,MA3NlC,EA2N0C,OA3N1C,EA2NmD,MA3NnD,EA2N2D,gBA3N3D,CAAA,GA4ND,GA5NC,CA4NC,CA5ND,CAAA,SA4NY,eA5NZ,CAAA,MAAA,EAAA,OAAA,EAAA,CAAA,GA6NC,gBA7ND,CA6NkB,GA7NlB,CA6NoB,CA7NpB,CAAA,CAAA,GA8NC,GA9ND,CA8NG,CA9NH,CAAA,EACgB"}
|
package/dist/client/solid.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { isReadableAtom } from "../util/nanostores.js";
|
|
2
2
|
import { isGetHook, isMutatorHook, isStore } from "./client.js";
|
|
3
3
|
import { atom } from "nanostores";
|
|
4
|
+
import { createEffect, onCleanup } from "solid-js";
|
|
4
5
|
import { useStore } from "@nanostores/solid";
|
|
5
|
-
import { createEffect } from "solid-js";
|
|
6
6
|
|
|
7
7
|
//#region src/client/solid.ts
|
|
8
8
|
/**
|
|
@@ -79,16 +79,30 @@ function createSolidMutator(hook) {
|
|
|
79
79
|
};
|
|
80
80
|
};
|
|
81
81
|
}
|
|
82
|
-
function
|
|
83
|
-
if (isReadableAtom(
|
|
82
|
+
function unwrapSolidStoreValue(value) {
|
|
83
|
+
if (isReadableAtom(value)) return useStore(value);
|
|
84
84
|
const result = {};
|
|
85
|
-
for (const key in
|
|
86
|
-
if (!Object.prototype.hasOwnProperty.call(
|
|
87
|
-
const
|
|
88
|
-
if (isReadableAtom(
|
|
89
|
-
else result[key] =
|
|
85
|
+
for (const key in value) {
|
|
86
|
+
if (!Object.prototype.hasOwnProperty.call(value, key)) continue;
|
|
87
|
+
const fieldValue = value[key];
|
|
88
|
+
if (isReadableAtom(fieldValue)) result[key] = useStore(fieldValue);
|
|
89
|
+
else result[key] = fieldValue;
|
|
90
|
+
}
|
|
91
|
+
return result;
|
|
92
|
+
}
|
|
93
|
+
function createSolidStore(hook) {
|
|
94
|
+
if ("obj" in hook) {
|
|
95
|
+
if (isReadableAtom(hook.obj)) return useStore(hook.obj);
|
|
96
|
+
return (() => unwrapSolidStoreValue(hook.obj));
|
|
90
97
|
}
|
|
91
|
-
return () =>
|
|
98
|
+
return ((...args) => {
|
|
99
|
+
const value = hook.factory(...args);
|
|
100
|
+
const disposer = value[Symbol.dispose];
|
|
101
|
+
if (typeof disposer === "function") onCleanup(() => {
|
|
102
|
+
disposer.call(value);
|
|
103
|
+
});
|
|
104
|
+
return unwrapSolidStoreValue(value);
|
|
105
|
+
});
|
|
92
106
|
}
|
|
93
107
|
function useFragno(clientObj) {
|
|
94
108
|
const result = {};
|
package/dist/client/solid.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"solid.js","names":["pathParams: Record<string, string | ReadableAtom<string>>","queryParams: Record<string, string | ReadableAtom<string>>","result: any"],"sources":["../../src/client/solid.ts"],"sourcesContent":["import type { StandardSchemaV1 } from \"@standard-schema/spec\";\nimport { atom, type ReadableAtom, type Store, type StoreValue } from \"nanostores\";\nimport { useStore } from \"@nanostores/solid\";\nimport type { Accessor } from \"solid-js\";\nimport { createEffect } from \"solid-js\";\nimport type { NonGetHTTPMethod } from \"../api/api\";\nimport {\n isGetHook,\n isMutatorHook,\n isStore,\n type FragnoClientHookData,\n type FragnoClientMutatorData,\n type FragnoStoreData,\n} from \"./client\";\nimport type { FragnoClientError } from \"./client-error\";\nimport type { InferOr } from \"../util/types-util\";\nimport type { MaybeExtractPathParamsOrWiden, QueryParamsHint } from \"../api/internal/path\";\nimport { isReadableAtom } from \"../util/nanostores\";\n\nexport type FragnoSolidHook<\n _TMethod extends \"GET\",\n TPath extends string,\n TOutputSchema extends StandardSchemaV1,\n TErrorCode extends string,\n TQueryParameters extends string,\n> = (args?: {\n path?: MaybeExtractPathParamsOrWiden<TPath, string | Accessor<string> | ReadableAtom<string>>;\n query?: QueryParamsHint<TQueryParameters, string | Accessor<string> | ReadableAtom<string>>;\n}) => {\n data: Accessor<InferOr<TOutputSchema, undefined>>;\n loading: Accessor<boolean>;\n error: Accessor<FragnoClientError<TErrorCode[number]> | undefined>;\n};\n\nexport type FragnoSolidMutator<\n _TMethod extends NonGetHTTPMethod,\n TPath extends string,\n TInputSchema extends StandardSchemaV1 | undefined,\n TOutputSchema extends StandardSchemaV1 | undefined,\n TErrorCode extends string,\n TQueryParameters extends string,\n> = () => {\n mutate: (args: {\n body?: InferOr<TInputSchema, undefined>;\n path?: MaybeExtractPathParamsOrWiden<TPath, string | Accessor<string> | ReadableAtom<string>>;\n query?: QueryParamsHint<TQueryParameters, string | Accessor<string> | ReadableAtom<string>>;\n }) => Promise<InferOr<TOutputSchema, undefined>>;\n loading: Accessor<boolean | undefined>;\n error: Accessor<FragnoClientError<TErrorCode[number]> | undefined>;\n data: Accessor<InferOr<TOutputSchema, undefined>>;\n};\n\n/**\n * Type guard to check if a value is a SolidJS Accessor.\n *\n * @private\n */\nexport function isAccessor(value: unknown): value is Accessor<string> {\n return typeof value === \"function\";\n}\n\n/**\n * Converts a SolidJS Accessor to a NanoStore Atom.\n *\n * This is used to convert SolidJS accessors to atoms, so that we can use them in the store.\n *\n * @private\n */\nexport function accessorToAtom<T>(accessor: Accessor<T>): ReadableAtom<T> {\n const a = atom(accessor());\n\n createEffect(() => {\n a.set(accessor());\n });\n\n return a;\n}\n\n// Helper function to create a SolidJS signal from a GET hook\n// We want 1 store per hook, so on updates to params, we need to update the store instead of creating a new one.\n// Nanostores only works with atoms (or strings), so we need to convert SolidJS accessors to atoms.\nfunction createSolidHook<\n TMethod extends \"GET\",\n TPath extends string,\n TOutputSchema extends StandardSchemaV1,\n TErrorCode extends string,\n TQueryParameters extends string,\n>(\n hook: FragnoClientHookData<TMethod, TPath, TOutputSchema, TErrorCode, TQueryParameters>,\n): FragnoSolidHook<TMethod, TPath, TOutputSchema, TErrorCode, TQueryParameters> {\n return ({ path, query } = {}) => {\n const pathParams: Record<string, string | ReadableAtom<string>> = {};\n const queryParams: Record<string, string | ReadableAtom<string>> = {};\n\n for (const [key, value] of Object.entries(path ?? {})) {\n const v = value as string | Accessor<string> | ReadableAtom<string>;\n pathParams[key] = isAccessor(v) ? accessorToAtom(v) : v;\n }\n\n for (const [key, value] of Object.entries(query ?? {})) {\n const v = value as string | Accessor<string> | ReadableAtom<string>;\n queryParams[key] = isAccessor(v) ? accessorToAtom(v) : v;\n }\n\n const store = hook.store({\n path: pathParams as MaybeExtractPathParamsOrWiden<TPath, string | ReadableAtom<string>>,\n query: queryParams,\n });\n\n const storeValue = useStore(store);\n\n return {\n data: () => storeValue().data as InferOr<TOutputSchema, undefined>,\n loading: () => storeValue().loading,\n error: () => storeValue().error,\n };\n };\n}\n\n// Helper function to create a SolidJS mutator from a mutator hook\nfunction createSolidMutator<\n TMethod extends NonGetHTTPMethod,\n TPath extends string,\n TInputSchema extends StandardSchemaV1 | undefined,\n TOutputSchema extends StandardSchemaV1 | undefined,\n TErrorCode extends string,\n TQueryParameters extends string,\n>(\n hook: FragnoClientMutatorData<\n TMethod,\n TPath,\n TInputSchema,\n TOutputSchema,\n TErrorCode,\n TQueryParameters\n >,\n): FragnoSolidMutator<TMethod, TPath, TInputSchema, TOutputSchema, TErrorCode, TQueryParameters> {\n return () => {\n const store = useStore(hook.mutatorStore);\n\n // Create a wrapped mutate function that handles SolidJS accessors\n const mutate = async (args: {\n body?: InferOr<TInputSchema, undefined>;\n path?: MaybeExtractPathParamsOrWiden<TPath, string | Accessor<string> | ReadableAtom<string>>;\n query?: QueryParamsHint<TQueryParameters, string | Accessor<string> | ReadableAtom<string>>;\n }) => {\n const { body, path, query } = args;\n\n const pathParams: Record<string, string | ReadableAtom<string>> = {};\n const queryParams: Record<string, string | ReadableAtom<string>> = {};\n\n for (const [key, value] of Object.entries(path ?? {})) {\n const v = value as string | Accessor<string> | ReadableAtom<string>;\n // For mutations, we read the current value of the accessor\n pathParams[key] = isAccessor(v) ? v() : v;\n }\n\n for (const [key, value] of Object.entries(query ?? {})) {\n const v = value as string | Accessor<string> | ReadableAtom<string>;\n // For mutations, we read the current value of the accessor\n queryParams[key] = isAccessor(v) ? v() : v;\n }\n\n // Call the store's mutate function with normalized params\n return hook.mutatorStore.mutate({\n body,\n path: pathParams as MaybeExtractPathParamsOrWiden<TPath, string | ReadableAtom<string>>,\n query: queryParams,\n });\n };\n\n return {\n mutate,\n data: () => store().data as InferOr<TOutputSchema, undefined>,\n loading: () => store().loading,\n error: () => store().error,\n };\n };\n}\n\nexport type FragnoSolidStore<T extends object> = T extends Store\n ? Accessor<StoreValue<T>>\n : () => {\n [K in keyof T]: T[K] extends Store ? Accessor<StoreValue<T[K]>> : T[K];\n };\n\nfunction createSolidStore<const T extends object>(\n hook: FragnoStoreData<T>,\n): Accessor<StoreValue<T>> | (() => Accessor<StoreValue<T>>) {\n // If the store object itself is a single atom, wrap it with useStore\n if (isReadableAtom(hook.obj)) {\n return useStore(hook.obj);\n }\n\n // For objects containing atoms, wrap each atom property with useStore\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const result: any = {};\n\n for (const key in hook.obj) {\n if (!Object.prototype.hasOwnProperty.call(hook.obj, key)) {\n continue;\n }\n\n const value = hook.obj[key];\n if (isReadableAtom(value)) {\n result[key] = useStore(value);\n } else {\n result[key] = value;\n }\n }\n\n return () => result;\n}\n\nexport function useFragno<T extends Record<string, unknown>>(\n clientObj: T,\n): {\n [K in keyof T]: T[K] extends FragnoClientHookData<\n \"GET\",\n infer TPath,\n infer TOutputSchema,\n infer TErrorCode,\n infer TQueryParameters\n >\n ? FragnoSolidHook<\"GET\", TPath, TOutputSchema, TErrorCode, TQueryParameters>\n : T[K] extends FragnoClientMutatorData<\n infer TMethod,\n infer TPath,\n infer TInput,\n infer TOutput,\n infer TError,\n infer TQueryParameters\n >\n ? FragnoSolidMutator<TMethod, TPath, TInput, TOutput, TError, TQueryParameters>\n : T[K] extends FragnoStoreData<infer TStoreObj>\n ? FragnoSolidStore<TStoreObj>\n : T[K];\n} {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const result = {} as any;\n\n for (const key in clientObj) {\n if (!Object.prototype.hasOwnProperty.call(clientObj, key)) {\n continue;\n }\n\n const hook = clientObj[key];\n if (isGetHook(hook)) {\n result[key] = createSolidHook(hook);\n } else if (isMutatorHook(hook)) {\n result[key] = createSolidMutator(hook);\n } else if (isStore(hook)) {\n result[key] = createSolidStore(hook);\n } else {\n // Pass through non-hook values unchanged\n result[key] = hook;\n }\n }\n\n return result;\n}\n"],"mappings":";;;;;;;;;;;;AAyDA,SAAgB,WAAW,OAA2C;AACpE,QAAO,OAAO,UAAU;;;;;;;;;AAU1B,SAAgB,eAAkB,UAAwC;CACxE,MAAM,IAAI,KAAK,UAAU,CAAC;AAE1B,oBAAmB;AACjB,IAAE,IAAI,UAAU,CAAC;GACjB;AAEF,QAAO;;AAMT,SAAS,gBAOP,MAC8E;AAC9E,SAAQ,EAAE,MAAM,UAAU,EAAE,KAAK;EAC/B,MAAMA,aAA4D,EAAE;EACpE,MAAMC,cAA6D,EAAE;AAErE,OAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,QAAQ,EAAE,CAAC,EAAE;GACrD,MAAM,IAAI;AACV,cAAW,OAAO,WAAW,EAAE,GAAG,eAAe,EAAE,GAAG;;AAGxD,OAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,SAAS,EAAE,CAAC,EAAE;GACtD,MAAM,IAAI;AACV,eAAY,OAAO,WAAW,EAAE,GAAG,eAAe,EAAE,GAAG;;EAQzD,MAAM,aAAa,SALL,KAAK,MAAM;GACvB,MAAM;GACN,OAAO;GACR,CAAC,CAEgC;AAElC,SAAO;GACL,YAAY,YAAY,CAAC;GACzB,eAAe,YAAY,CAAC;GAC5B,aAAa,YAAY,CAAC;GAC3B;;;AAKL,SAAS,mBAQP,MAQ+F;AAC/F,cAAa;EACX,MAAM,QAAQ,SAAS,KAAK,aAAa;EAGzC,MAAM,SAAS,OAAO,SAIhB;GACJ,MAAM,EAAE,MAAM,MAAM,UAAU;GAE9B,MAAMD,aAA4D,EAAE;GACpE,MAAMC,cAA6D,EAAE;AAErE,QAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,QAAQ,EAAE,CAAC,EAAE;IACrD,MAAM,IAAI;AAEV,eAAW,OAAO,WAAW,EAAE,GAAG,GAAG,GAAG;;AAG1C,QAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,SAAS,EAAE,CAAC,EAAE;IACtD,MAAM,IAAI;AAEV,gBAAY,OAAO,WAAW,EAAE,GAAG,GAAG,GAAG;;AAI3C,UAAO,KAAK,aAAa,OAAO;IAC9B;IACA,MAAM;IACN,OAAO;IACR,CAAC;;AAGJ,SAAO;GACL;GACA,YAAY,OAAO,CAAC;GACpB,eAAe,OAAO,CAAC;GACvB,aAAa,OAAO,CAAC;GACtB;;;AAUL,SAAS,iBACP,MAC2D;AAE3D,KAAI,eAAe,KAAK,IAAI,CAC1B,QAAO,SAAS,KAAK,IAAI;CAK3B,MAAMC,SAAc,EAAE;AAEtB,MAAK,MAAM,OAAO,KAAK,KAAK;AAC1B,MAAI,CAAC,OAAO,UAAU,eAAe,KAAK,KAAK,KAAK,IAAI,CACtD;EAGF,MAAM,QAAQ,KAAK,IAAI;AACvB,MAAI,eAAe,MAAM,CACvB,QAAO,OAAO,SAAS,MAAM;MAE7B,QAAO,OAAO;;AAIlB,cAAa;;AAGf,SAAgB,UACd,WAsBA;CAEA,MAAM,SAAS,EAAE;AAEjB,MAAK,MAAM,OAAO,WAAW;AAC3B,MAAI,CAAC,OAAO,UAAU,eAAe,KAAK,WAAW,IAAI,CACvD;EAGF,MAAM,OAAO,UAAU;AACvB,MAAI,UAAU,KAAK,CACjB,QAAO,OAAO,gBAAgB,KAAK;WAC1B,cAAc,KAAK,CAC5B,QAAO,OAAO,mBAAmB,KAAK;WAC7B,QAAQ,KAAK,CACtB,QAAO,OAAO,iBAAiB,KAAK;MAGpC,QAAO,OAAO;;AAIlB,QAAO"}
|
|
1
|
+
{"version":3,"file":"solid.js","names":["pathParams: Record<string, string | ReadableAtom<string>>","queryParams: Record<string, string | ReadableAtom<string>>","result: any"],"sources":["../../src/client/solid.ts"],"sourcesContent":["import { atom, type ReadableAtom, type Store, type StoreValue } from \"nanostores\";\nimport type { Accessor } from \"solid-js\";\nimport { createEffect, onCleanup } from \"solid-js\";\n\nimport { useStore } from \"@nanostores/solid\";\nimport type { StandardSchemaV1 } from \"@standard-schema/spec\";\n\nimport type { NonGetHTTPMethod } from \"../api/api\";\nimport type { MaybeExtractPathParamsOrWiden, QueryParamsHint } from \"../api/internal/path\";\nimport { isReadableAtom } from \"../util/nanostores\";\nimport type { InferOr } from \"../util/types-util\";\nimport {\n isGetHook,\n isMutatorHook,\n isStore,\n type FragnoClientHookData,\n type FragnoClientMutatorData,\n type FragnoStoreData,\n type FragnoStoreFactoryData,\n type FragnoStoreObjectData,\n} from \"./client\";\nimport type { FragnoClientError } from \"./client-error\";\n\nexport type FragnoSolidHook<\n _TMethod extends \"GET\",\n TPath extends string,\n TOutputSchema extends StandardSchemaV1,\n TErrorCode extends string,\n TQueryParameters extends string,\n> = (args?: {\n path?: MaybeExtractPathParamsOrWiden<TPath, string | Accessor<string> | ReadableAtom<string>>;\n query?: QueryParamsHint<TQueryParameters, string | Accessor<string> | ReadableAtom<string>>;\n}) => {\n data: Accessor<InferOr<TOutputSchema, undefined>>;\n loading: Accessor<boolean>;\n error: Accessor<FragnoClientError<TErrorCode[number]> | undefined>;\n};\n\nexport type FragnoSolidMutator<\n _TMethod extends NonGetHTTPMethod,\n TPath extends string,\n TInputSchema extends StandardSchemaV1 | undefined,\n TOutputSchema extends StandardSchemaV1 | undefined,\n TErrorCode extends string,\n TQueryParameters extends string,\n> = () => {\n mutate: (args: {\n body?: InferOr<TInputSchema, undefined>;\n path?: MaybeExtractPathParamsOrWiden<TPath, string | Accessor<string> | ReadableAtom<string>>;\n query?: QueryParamsHint<TQueryParameters, string | Accessor<string> | ReadableAtom<string>>;\n }) => Promise<InferOr<TOutputSchema, undefined>>;\n loading: Accessor<boolean | undefined>;\n error: Accessor<FragnoClientError<TErrorCode[number]> | undefined>;\n data: Accessor<InferOr<TOutputSchema, undefined>>;\n};\n\n/**\n * Type guard to check if a value is a SolidJS Accessor.\n *\n * @private\n */\nexport function isAccessor(value: unknown): value is Accessor<string> {\n return typeof value === \"function\";\n}\n\n/**\n * Converts a SolidJS Accessor to a NanoStore Atom.\n *\n * This is used to convert SolidJS accessors to atoms, so that we can use them in the store.\n *\n * @private\n */\nexport function accessorToAtom<T>(accessor: Accessor<T>): ReadableAtom<T> {\n const a = atom(accessor());\n\n createEffect(() => {\n a.set(accessor());\n });\n\n return a;\n}\n\n// Helper function to create a SolidJS signal from a GET hook\n// We want 1 store per hook, so on updates to params, we need to update the store instead of creating a new one.\n// Nanostores only works with atoms (or strings), so we need to convert SolidJS accessors to atoms.\nfunction createSolidHook<\n TMethod extends \"GET\",\n TPath extends string,\n TOutputSchema extends StandardSchemaV1,\n TErrorCode extends string,\n TQueryParameters extends string,\n>(\n hook: FragnoClientHookData<TMethod, TPath, TOutputSchema, TErrorCode, TQueryParameters>,\n): FragnoSolidHook<TMethod, TPath, TOutputSchema, TErrorCode, TQueryParameters> {\n return ({ path, query } = {}) => {\n const pathParams: Record<string, string | ReadableAtom<string>> = {};\n const queryParams: Record<string, string | ReadableAtom<string>> = {};\n\n for (const [key, value] of Object.entries(path ?? {})) {\n const v = value as string | Accessor<string> | ReadableAtom<string>;\n pathParams[key] = isAccessor(v) ? accessorToAtom(v) : v;\n }\n\n for (const [key, value] of Object.entries(query ?? {})) {\n const v = value as string | Accessor<string> | ReadableAtom<string>;\n queryParams[key] = isAccessor(v) ? accessorToAtom(v) : v;\n }\n\n const store = hook.store({\n path: pathParams as MaybeExtractPathParamsOrWiden<TPath, string | ReadableAtom<string>>,\n query: queryParams,\n });\n\n const storeValue = useStore(store);\n\n return {\n data: () => storeValue().data as InferOr<TOutputSchema, undefined>,\n loading: () => storeValue().loading,\n error: () => storeValue().error,\n };\n };\n}\n\n// Helper function to create a SolidJS mutator from a mutator hook\nfunction createSolidMutator<\n TMethod extends NonGetHTTPMethod,\n TPath extends string,\n TInputSchema extends StandardSchemaV1 | undefined,\n TOutputSchema extends StandardSchemaV1 | undefined,\n TErrorCode extends string,\n TQueryParameters extends string,\n>(\n hook: FragnoClientMutatorData<\n TMethod,\n TPath,\n TInputSchema,\n TOutputSchema,\n TErrorCode,\n TQueryParameters\n >,\n): FragnoSolidMutator<TMethod, TPath, TInputSchema, TOutputSchema, TErrorCode, TQueryParameters> {\n return () => {\n const store = useStore(hook.mutatorStore);\n\n // Create a wrapped mutate function that handles SolidJS accessors\n const mutate = async (args: {\n body?: InferOr<TInputSchema, undefined>;\n path?: MaybeExtractPathParamsOrWiden<TPath, string | Accessor<string> | ReadableAtom<string>>;\n query?: QueryParamsHint<TQueryParameters, string | Accessor<string> | ReadableAtom<string>>;\n }) => {\n const { body, path, query } = args;\n\n const pathParams: Record<string, string | ReadableAtom<string>> = {};\n const queryParams: Record<string, string | ReadableAtom<string>> = {};\n\n for (const [key, value] of Object.entries(path ?? {})) {\n const v = value as string | Accessor<string> | ReadableAtom<string>;\n // For mutations, we read the current value of the accessor\n pathParams[key] = isAccessor(v) ? v() : v;\n }\n\n for (const [key, value] of Object.entries(query ?? {})) {\n const v = value as string | Accessor<string> | ReadableAtom<string>;\n // For mutations, we read the current value of the accessor\n queryParams[key] = isAccessor(v) ? v() : v;\n }\n\n // Call the store's mutate function with normalized params\n return hook.mutatorStore.mutate({\n body,\n path: pathParams as MaybeExtractPathParamsOrWiden<TPath, string | ReadableAtom<string>>,\n query: queryParams,\n });\n };\n\n return {\n mutate,\n data: () => store().data as InferOr<TOutputSchema, undefined>,\n loading: () => store().loading,\n error: () => store().error,\n };\n };\n}\n\ntype FragnoSolidStoreValue<T extends object> = T extends Store\n ? Accessor<StoreValue<T>>\n : {\n [K in keyof T]: T[K] extends Store ? Accessor<StoreValue<T[K]>> : T[K];\n };\n\ntype FragnoSolidStaticStore<T extends object> = T extends Store\n ? Accessor<StoreValue<T>>\n : () => {\n [K in keyof T]: T[K] extends Store ? Accessor<StoreValue<T[K]>> : T[K];\n };\n\nexport type FragnoSolidStore<TStore extends FragnoStoreData<object, unknown[]>> =\n TStore extends FragnoStoreFactoryData<infer T, infer TArgs>\n ? (...args: TArgs) => FragnoSolidStoreValue<T>\n : TStore extends FragnoStoreObjectData<infer T>\n ? FragnoSolidStaticStore<T>\n : never;\n\nfunction unwrapSolidStoreValue<T extends object>(value: T): FragnoSolidStoreValue<T> {\n if (isReadableAtom(value)) {\n return useStore(value) as FragnoSolidStoreValue<T>;\n }\n\n // For objects containing atoms, wrap each atom property with useStore\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const result: any = {};\n\n for (const key in value) {\n if (!Object.prototype.hasOwnProperty.call(value, key)) {\n continue;\n }\n\n const fieldValue = value[key];\n if (isReadableAtom(fieldValue)) {\n result[key] = useStore(fieldValue);\n } else {\n result[key] = fieldValue;\n }\n }\n\n return result as FragnoSolidStoreValue<T>;\n}\n\nfunction createSolidStore<const TStore extends FragnoStoreData<object, unknown[]>>(\n hook: TStore,\n): FragnoSolidStore<TStore> {\n if (\"obj\" in hook) {\n if (isReadableAtom(hook.obj)) {\n return useStore(hook.obj) as FragnoSolidStore<TStore>;\n }\n\n return (() => unwrapSolidStoreValue(hook.obj)) as FragnoSolidStore<TStore>;\n }\n\n return ((...args: Parameters<typeof hook.factory>) => {\n const value = hook.factory(...args);\n const disposer = (value as { [Symbol.dispose]?: (() => void) | undefined })[Symbol.dispose];\n if (typeof disposer === \"function\") {\n onCleanup(() => {\n disposer.call(value);\n });\n }\n\n return unwrapSolidStoreValue(value);\n }) as FragnoSolidStore<TStore>;\n}\n\nexport function useFragno<T extends Record<string, unknown>>(\n clientObj: T,\n): {\n [K in keyof T]: T[K] extends FragnoClientHookData<\n \"GET\",\n infer TPath,\n infer TOutputSchema,\n infer TErrorCode,\n infer TQueryParameters\n >\n ? FragnoSolidHook<\"GET\", TPath, TOutputSchema, TErrorCode, TQueryParameters>\n : T[K] extends FragnoClientMutatorData<\n infer TMethod,\n infer TPath,\n infer TInput,\n infer TOutput,\n infer TError,\n infer TQueryParameters\n >\n ? FragnoSolidMutator<TMethod, TPath, TInput, TOutput, TError, TQueryParameters>\n : T[K] extends FragnoStoreData<object, unknown[]>\n ? FragnoSolidStore<T[K]>\n : T[K];\n} {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const result = {} as any;\n\n for (const key in clientObj) {\n if (!Object.prototype.hasOwnProperty.call(clientObj, key)) {\n continue;\n }\n\n const hook = clientObj[key];\n if (isGetHook(hook)) {\n result[key] = createSolidHook(hook);\n } else if (isMutatorHook(hook)) {\n result[key] = createSolidMutator(hook);\n } else if (isStore(hook)) {\n result[key] = createSolidStore(hook);\n } else {\n // Pass through non-hook values unchanged\n result[key] = hook;\n }\n }\n\n return result;\n}\n"],"mappings":"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"}
|
package/dist/client/vanilla.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { ExtractPathParamsOrWiden, HasPathParams, MaybeExtractPathParamsOrWiden } from "../api/internal/path.js";
|
|
2
2
|
import { InferOr } from "../util/types-util.js";
|
|
3
|
-
import { NonGetHTTPMethod } from "../api/api.js";
|
|
4
3
|
import { FragnoClientError } from "./client-error.js";
|
|
5
|
-
import { FragnoClientHookData, FragnoClientMutatorData } from "./client.js";
|
|
4
|
+
import { FragnoClientHookData, FragnoClientMutatorData, FragnoStoreFactoryData, FragnoStoreObjectData } from "./client.js";
|
|
5
|
+
import { NonGetHTTPMethod } from "../api/api.js";
|
|
6
6
|
import { ReadableAtom } from "nanostores";
|
|
7
7
|
import { StandardSchemaV1 } from "@standard-schema/spec";
|
|
8
8
|
|
|
@@ -57,7 +57,19 @@ type FragnoVanillaMutator<_TMethod extends NonGetHTTPMethod, TPath$1 extends str
|
|
|
57
57
|
}) => Promise<InferOr<TOutputSchema$1, undefined>>;
|
|
58
58
|
[Symbol.asyncIterator]: () => AsyncGenerator<StoreData<TOutputSchema$1, TErrorCode$1[number]>, void, unknown>;
|
|
59
59
|
};
|
|
60
|
-
|
|
60
|
+
type FragnoVanillaStore<T extends object, TArgs$1 extends unknown[] = []> = TArgs$1 extends [] ? T : (...args: TArgs$1) => T & {
|
|
61
|
+
destroy?: () => void;
|
|
62
|
+
};
|
|
63
|
+
type FragnoVanillaStoreFromData<TStore> = TStore extends {
|
|
64
|
+
factory: (...args: infer TArgs) => infer TObject extends object;
|
|
65
|
+
} ? (...args: TArgs) => TObject & {
|
|
66
|
+
destroy?: () => void;
|
|
67
|
+
} : TStore extends {
|
|
68
|
+
obj: infer TObject extends object;
|
|
69
|
+
} ? TObject : never;
|
|
70
|
+
declare function useFragno<T extends Record<string, unknown>>(clientObj: T): { [K in keyof T]: T[K] extends FragnoClientHookData<"GET", infer TPath, infer TOutputSchema, infer TErrorCode, infer TQueryParameters> ? FragnoVanillaListeners<"GET", TPath, TOutputSchema, TErrorCode, TQueryParameters> : T[K] extends FragnoClientMutatorData<NonGetHTTPMethod, infer TPath, infer TInputSchema, infer TOutputSchema, infer TErrorCode, infer TQueryParameters> ? FragnoVanillaMutator<NonGetHTTPMethod, TPath, TInputSchema, TOutputSchema, TErrorCode, TQueryParameters> : T[K] extends FragnoStoreObjectData<infer TStoreObj> ? TStoreObj : T[K] extends FragnoStoreFactoryData<infer TStoreObj, infer TStoreArgs> ? (...args: TStoreArgs) => TStoreObj & {
|
|
71
|
+
destroy?: () => void;
|
|
72
|
+
} : T[K] };
|
|
61
73
|
//#endregion
|
|
62
|
-
export { FragnoVanillaListeners, FragnoVanillaMutator, StoreData, useFragno };
|
|
74
|
+
export { FragnoVanillaListeners, FragnoVanillaMutator, FragnoVanillaStore, FragnoVanillaStoreFromData, StoreData, useFragno };
|
|
63
75
|
//# sourceMappingURL=vanilla.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"vanilla.d.ts","names":[],"sources":["../../src/client/vanilla.ts"],"sourcesContent":[],"mappings":";;;;;;;;;
|
|
1
|
+
{"version":3,"file":"vanilla.d.ts","names":[],"sources":["../../src/client/vanilla.ts"],"sourcesContent":[],"mappings":"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"}
|
package/dist/client/vanilla.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { isGetHook, isMutatorHook } from "./client.js";
|
|
1
|
+
import { isGetHook, isMutatorHook, isStore } from "./client.js";
|
|
2
2
|
import { createAsyncIteratorFromCallback } from "../util/async.js";
|
|
3
3
|
|
|
4
4
|
//#region src/client/vanilla.ts
|
|
@@ -79,6 +79,25 @@ function createVanillaMutator(hook) {
|
|
|
79
79
|
};
|
|
80
80
|
};
|
|
81
81
|
}
|
|
82
|
+
const getStoreDisposer = (value) => {
|
|
83
|
+
const disposer = value[Symbol.dispose];
|
|
84
|
+
return typeof disposer === "function" ? disposer.bind(value) : void 0;
|
|
85
|
+
};
|
|
86
|
+
function createVanillaStore(hook) {
|
|
87
|
+
if ("obj" in hook) return hook.obj;
|
|
88
|
+
return ((...args) => {
|
|
89
|
+
const value = hook.factory(...args);
|
|
90
|
+
const disposer = getStoreDisposer(value);
|
|
91
|
+
if (!disposer) return value;
|
|
92
|
+
Object.defineProperty(value, "destroy", {
|
|
93
|
+
value: disposer,
|
|
94
|
+
enumerable: false,
|
|
95
|
+
configurable: true,
|
|
96
|
+
writable: true
|
|
97
|
+
});
|
|
98
|
+
return value;
|
|
99
|
+
});
|
|
100
|
+
}
|
|
82
101
|
function useFragno(clientObj) {
|
|
83
102
|
const result = {};
|
|
84
103
|
for (const key in clientObj) {
|
|
@@ -86,6 +105,7 @@ function useFragno(clientObj) {
|
|
|
86
105
|
const hook = clientObj[key];
|
|
87
106
|
if (isGetHook(hook)) result[key] = createVanillaListeners(hook);
|
|
88
107
|
else if (isMutatorHook(hook)) result[key] = createVanillaMutator(hook);
|
|
108
|
+
else if (isStore(hook)) result[key] = createVanillaStore(hook);
|
|
89
109
|
else result[key] = hook;
|
|
90
110
|
}
|
|
91
111
|
return result;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"vanilla.js","names":[],"sources":["../../src/client/vanilla.ts"],"sourcesContent":["import type { StandardSchemaV1 } from \"@standard-schema/spec\";\nimport type { ReadableAtom } from \"nanostores\";\nimport type { NonGetHTTPMethod } from \"../api/api\";\nimport {\n isGetHook,\n isMutatorHook,\n type FragnoClientMutatorData,\n type FragnoClientHookData,\n} from \"./client\";\nimport type { FragnoClientError } from \"./client-error\";\nimport { createAsyncIteratorFromCallback } from \"../util/async\";\nimport type { InferOr } from \"../util/types-util\";\nimport type {\n ExtractPathParamsOrWiden,\n HasPathParams,\n MaybeExtractPathParamsOrWiden,\n} from \"../api/internal/path\";\n\nexport type StoreData<\n TOutputSchema extends StandardSchemaV1 | undefined,\n TErrorCodes extends string,\n> = {\n loading: boolean;\n error?: FragnoClientError<TErrorCodes>;\n data?: InferOr<TOutputSchema, undefined>;\n};\n\nexport type FragnoVanillaListeners<\n _TMethod extends \"GET\",\n TPath extends string,\n TOutputSchema extends StandardSchemaV1,\n TErrorCode extends string,\n TQueryParameters extends string,\n> = (args?: {\n path?: MaybeExtractPathParamsOrWiden<TPath, string | ReadableAtom<string>>;\n query?: Record<TQueryParameters, string | ReadableAtom<string>>;\n}) => {\n /** Called for every change in the store. */\n listen: (callback: (value: StoreData<TOutputSchema, TErrorCode[number]>) => void) => () => void;\n /** Called once initially, then called for every change in the store. */\n subscribe: (\n callback: (value: StoreData<TOutputSchema, TErrorCode[number]>) => void,\n ) => () => void;\n get: () => StoreData<TOutputSchema, TErrorCode[number]>;\n refetch: () => void;\n /**\n * Produces an item for every change in the store.\n * Note: the iterator does NOT return.\n *\n * @example\n * ```typescript\n * const store = useFragno(clientObj).store;\n * for await (const value of store[Symbol.asyncIterator]()) {\n * console.log(value);\n * }\n * ```\n */\n [Symbol.asyncIterator]: () => AsyncGenerator<\n StoreData<TOutputSchema, TErrorCode[number]>,\n void,\n unknown\n >;\n};\n\nfunction createVanillaListeners<\n TPath extends string,\n TOutputSchema extends StandardSchemaV1,\n TErrorCode extends string,\n TQueryParameters extends string,\n>(\n hook: FragnoClientHookData<\"GET\", TPath, TOutputSchema, TErrorCode, TQueryParameters>,\n): FragnoVanillaListeners<\"GET\", TPath, TOutputSchema, TErrorCode, TQueryParameters> {\n return ({ path, query } = {}) => {\n const store = hook.store({ path, query });\n\n return {\n listen: (callback) => {\n return store.listen(({ loading, error, data }) =>\n callback({\n loading,\n error,\n data: data as InferOr<TOutputSchema, undefined>,\n }),\n );\n },\n subscribe: (callback) => {\n return store.subscribe(({ loading, error, data }) =>\n callback({\n loading,\n error,\n data: data as InferOr<TOutputSchema, undefined>,\n }),\n );\n },\n refetch: () => {\n return store.revalidate();\n },\n get: () => {\n return store.get() as StoreData<TOutputSchema, TErrorCode[number]>;\n },\n [Symbol.asyncIterator]() {\n return createAsyncIteratorFromCallback((callback) =>\n store.listen(({ loading, error, data }) =>\n callback({\n loading,\n error,\n data: data as InferOr<TOutputSchema, undefined>,\n }),\n ),\n );\n },\n };\n };\n}\n\nexport type FragnoVanillaMutator<\n _TMethod extends NonGetHTTPMethod,\n TPath extends string,\n TInputSchema extends StandardSchemaV1 | undefined,\n TOutputSchema extends StandardSchemaV1 | undefined,\n TErrorCode extends string,\n TQueryParameters extends string,\n> = (args?: {\n path?: MaybeExtractPathParamsOrWiden<TPath, string | ReadableAtom<string>>;\n query?: Record<TQueryParameters, string | ReadableAtom<string>>;\n}) => {\n subscribe: (\n callback: (value: {\n loading: boolean;\n error?: FragnoClientError<TErrorCode[number]>;\n data?: InferOr<TOutputSchema, undefined>;\n }) => void,\n ) => () => void;\n get: () => StoreData<TOutputSchema, TErrorCode[number]>;\n mutate: ({\n body,\n path,\n query,\n }: {\n body?: InferOr<TInputSchema, undefined>;\n path?: HasPathParams<TPath> extends true\n ? ExtractPathParamsOrWiden<TPath, string | ReadableAtom<string>>\n : undefined;\n query?: Record<string, string | ReadableAtom<string>>;\n }) => Promise<InferOr<TOutputSchema, undefined>>;\n [Symbol.asyncIterator]: () => AsyncGenerator<\n StoreData<TOutputSchema, TErrorCode[number]>,\n void,\n unknown\n >;\n};\n\nfunction createVanillaMutator<\n _TMethod extends NonGetHTTPMethod,\n TPath extends string,\n TInputSchema extends StandardSchemaV1 | undefined,\n TOutputSchema extends StandardSchemaV1 | undefined,\n TErrorCode extends string,\n TQueryParameters extends string,\n>(\n hook: FragnoClientMutatorData<\n _TMethod,\n TPath,\n TInputSchema,\n TOutputSchema,\n TErrorCode,\n TQueryParameters\n >,\n): FragnoVanillaMutator<\n _TMethod,\n TPath,\n TInputSchema,\n TOutputSchema,\n TErrorCode,\n TQueryParameters\n> {\n return () => {\n // TODO(Wilco): it should be possible for `loading` to be undefined, before a mutation has taken place.\n const store = hook.mutatorStore;\n return {\n subscribe: (callback) => {\n return store.subscribe((value) => {\n callback({\n loading: value.loading ?? false,\n error: value.error,\n data: value.data,\n });\n });\n },\n get: () => {\n const { loading, error, data } = store.get();\n return {\n loading: loading ?? false,\n error,\n data: data,\n };\n },\n mutate: ({ body, path, query }) => {\n return store.mutate({ body, path, query });\n },\n [Symbol.asyncIterator]() {\n return createAsyncIteratorFromCallback((callback) =>\n store.listen((value) => {\n callback({\n loading: value.loading ?? false,\n error: value.error,\n data: value.data,\n });\n }),\n );\n },\n };\n };\n}\n\nexport function useFragno<T extends Record<string, unknown>>(\n clientObj: T,\n): {\n [K in keyof T]: T[K] extends FragnoClientHookData<\n \"GET\",\n infer TPath,\n infer TOutputSchema,\n infer TErrorCode,\n infer TQueryParameters\n >\n ? FragnoVanillaListeners<\"GET\", TPath, TOutputSchema, TErrorCode, TQueryParameters>\n : T[K] extends FragnoClientMutatorData<\n NonGetHTTPMethod,\n infer TPath,\n infer TInputSchema,\n infer TOutputSchema,\n infer TErrorCode,\n infer TQueryParameters\n >\n ? FragnoVanillaMutator<\n NonGetHTTPMethod,\n TPath,\n TInputSchema,\n TOutputSchema,\n TErrorCode,\n TQueryParameters\n >\n : T[K];\n} {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const result = {} as any; // We need one any cast here due to TypeScript's limitations with mapped types\n\n for (const key in clientObj) {\n if (!Object.prototype.hasOwnProperty.call(clientObj, key)) {\n continue;\n }\n\n const hook = clientObj[key];\n if (isGetHook(hook)) {\n result[key] = createVanillaListeners(hook);\n } else if (isMutatorHook(hook)) {\n result[key] = createVanillaMutator(hook);\n } else {\n // Pass through non-hook values unchanged\n result[key] = hook;\n }\n }\n\n return result;\n}\n"],"mappings":";;;;AAgEA,SAAS,uBAMP,MACmF;AACnF,SAAQ,EAAE,MAAM,UAAU,EAAE,KAAK;EAC/B,MAAM,QAAQ,KAAK,MAAM;GAAE;GAAM;GAAO,CAAC;AAEzC,SAAO;GACL,SAAS,aAAa;AACpB,WAAO,MAAM,QAAQ,EAAE,SAAS,OAAO,WACrC,SAAS;KACP;KACA;KACM;KACP,CAAC,CACH;;GAEH,YAAY,aAAa;AACvB,WAAO,MAAM,WAAW,EAAE,SAAS,OAAO,WACxC,SAAS;KACP;KACA;KACM;KACP,CAAC,CACH;;GAEH,eAAe;AACb,WAAO,MAAM,YAAY;;GAE3B,WAAW;AACT,WAAO,MAAM,KAAK;;GAEpB,CAAC,OAAO,iBAAiB;AACvB,WAAO,iCAAiC,aACtC,MAAM,QAAQ,EAAE,SAAS,OAAO,WAC9B,SAAS;KACP;KACA;KACM;KACP,CAAC,CACH,CACF;;GAEJ;;;AAyCL,SAAS,qBAQP,MAeA;AACA,cAAa;EAEX,MAAM,QAAQ,KAAK;AACnB,SAAO;GACL,YAAY,aAAa;AACvB,WAAO,MAAM,WAAW,UAAU;AAChC,cAAS;MACP,SAAS,MAAM,WAAW;MAC1B,OAAO,MAAM;MACb,MAAM,MAAM;MACb,CAAC;MACF;;GAEJ,WAAW;IACT,MAAM,EAAE,SAAS,OAAO,SAAS,MAAM,KAAK;AAC5C,WAAO;KACL,SAAS,WAAW;KACpB;KACM;KACP;;GAEH,SAAS,EAAE,MAAM,MAAM,YAAY;AACjC,WAAO,MAAM,OAAO;KAAE;KAAM;KAAM;KAAO,CAAC;;GAE5C,CAAC,OAAO,iBAAiB;AACvB,WAAO,iCAAiC,aACtC,MAAM,QAAQ,UAAU;AACtB,cAAS;MACP,SAAS,MAAM,WAAW;MAC1B,OAAO,MAAM;MACb,MAAM,MAAM;MACb,CAAC;MACF,CACH;;GAEJ;;;AAIL,SAAgB,UACd,WA2BA;CAEA,MAAM,SAAS,EAAE;AAEjB,MAAK,MAAM,OAAO,WAAW;AAC3B,MAAI,CAAC,OAAO,UAAU,eAAe,KAAK,WAAW,IAAI,CACvD;EAGF,MAAM,OAAO,UAAU;AACvB,MAAI,UAAU,KAAK,CACjB,QAAO,OAAO,uBAAuB,KAAK;WACjC,cAAc,KAAK,CAC5B,QAAO,OAAO,qBAAqB,KAAK;MAGxC,QAAO,OAAO;;AAIlB,QAAO"}
|
|
1
|
+
{"version":3,"file":"vanilla.js","names":[],"sources":["../../src/client/vanilla.ts"],"sourcesContent":["import type { ReadableAtom } from \"nanostores\";\n\nimport type { StandardSchemaV1 } from \"@standard-schema/spec\";\n\nimport type { NonGetHTTPMethod } from \"../api/api\";\nimport type {\n ExtractPathParamsOrWiden,\n HasPathParams,\n MaybeExtractPathParamsOrWiden,\n} from \"../api/internal/path\";\nimport { createAsyncIteratorFromCallback } from \"../util/async\";\nimport type { InferOr } from \"../util/types-util\";\nimport {\n isGetHook,\n isMutatorHook,\n isStore,\n type FragnoClientMutatorData,\n type FragnoClientHookData,\n type FragnoStoreData,\n type FragnoStoreFactoryData,\n type FragnoStoreObjectData,\n} from \"./client\";\nimport type { FragnoClientError } from \"./client-error\";\n\nexport type StoreData<\n TOutputSchema extends StandardSchemaV1 | undefined,\n TErrorCodes extends string,\n> = {\n loading: boolean;\n error?: FragnoClientError<TErrorCodes>;\n data?: InferOr<TOutputSchema, undefined>;\n};\n\nexport type FragnoVanillaListeners<\n _TMethod extends \"GET\",\n TPath extends string,\n TOutputSchema extends StandardSchemaV1,\n TErrorCode extends string,\n TQueryParameters extends string,\n> = (args?: {\n path?: MaybeExtractPathParamsOrWiden<TPath, string | ReadableAtom<string>>;\n query?: Record<TQueryParameters, string | ReadableAtom<string>>;\n}) => {\n /** Called for every change in the store. */\n listen: (callback: (value: StoreData<TOutputSchema, TErrorCode[number]>) => void) => () => void;\n /** Called once initially, then called for every change in the store. */\n subscribe: (\n callback: (value: StoreData<TOutputSchema, TErrorCode[number]>) => void,\n ) => () => void;\n get: () => StoreData<TOutputSchema, TErrorCode[number]>;\n refetch: () => void;\n /**\n * Produces an item for every change in the store.\n * Note: the iterator does NOT return.\n *\n * @example\n * ```typescript\n * const store = useFragno(clientObj).store;\n * for await (const value of store[Symbol.asyncIterator]()) {\n * console.log(value);\n * }\n * ```\n */\n [Symbol.asyncIterator]: () => AsyncGenerator<\n StoreData<TOutputSchema, TErrorCode[number]>,\n void,\n unknown\n >;\n};\n\nfunction createVanillaListeners<\n TPath extends string,\n TOutputSchema extends StandardSchemaV1,\n TErrorCode extends string,\n TQueryParameters extends string,\n>(\n hook: FragnoClientHookData<\"GET\", TPath, TOutputSchema, TErrorCode, TQueryParameters>,\n): FragnoVanillaListeners<\"GET\", TPath, TOutputSchema, TErrorCode, TQueryParameters> {\n return ({ path, query } = {}) => {\n const store = hook.store({ path, query });\n\n return {\n listen: (callback) => {\n return store.listen(({ loading, error, data }) =>\n callback({\n loading,\n error,\n data: data as InferOr<TOutputSchema, undefined>,\n }),\n );\n },\n subscribe: (callback) => {\n return store.subscribe(({ loading, error, data }) =>\n callback({\n loading,\n error,\n data: data as InferOr<TOutputSchema, undefined>,\n }),\n );\n },\n refetch: () => {\n return store.revalidate();\n },\n get: () => {\n return store.get() as StoreData<TOutputSchema, TErrorCode[number]>;\n },\n [Symbol.asyncIterator]() {\n return createAsyncIteratorFromCallback((callback) =>\n store.listen(({ loading, error, data }) =>\n callback({\n loading,\n error,\n data: data as InferOr<TOutputSchema, undefined>,\n }),\n ),\n );\n },\n };\n };\n}\n\nexport type FragnoVanillaMutator<\n _TMethod extends NonGetHTTPMethod,\n TPath extends string,\n TInputSchema extends StandardSchemaV1 | undefined,\n TOutputSchema extends StandardSchemaV1 | undefined,\n TErrorCode extends string,\n TQueryParameters extends string,\n> = (args?: {\n path?: MaybeExtractPathParamsOrWiden<TPath, string | ReadableAtom<string>>;\n query?: Record<TQueryParameters, string | ReadableAtom<string>>;\n}) => {\n subscribe: (\n callback: (value: {\n loading: boolean;\n error?: FragnoClientError<TErrorCode[number]>;\n data?: InferOr<TOutputSchema, undefined>;\n }) => void,\n ) => () => void;\n get: () => StoreData<TOutputSchema, TErrorCode[number]>;\n mutate: ({\n body,\n path,\n query,\n }: {\n body?: InferOr<TInputSchema, undefined>;\n path?: HasPathParams<TPath> extends true\n ? ExtractPathParamsOrWiden<TPath, string | ReadableAtom<string>>\n : undefined;\n query?: Record<string, string | ReadableAtom<string>>;\n }) => Promise<InferOr<TOutputSchema, undefined>>;\n [Symbol.asyncIterator]: () => AsyncGenerator<\n StoreData<TOutputSchema, TErrorCode[number]>,\n void,\n unknown\n >;\n};\n\nfunction createVanillaMutator<\n _TMethod extends NonGetHTTPMethod,\n TPath extends string,\n TInputSchema extends StandardSchemaV1 | undefined,\n TOutputSchema extends StandardSchemaV1 | undefined,\n TErrorCode extends string,\n TQueryParameters extends string,\n>(\n hook: FragnoClientMutatorData<\n _TMethod,\n TPath,\n TInputSchema,\n TOutputSchema,\n TErrorCode,\n TQueryParameters\n >,\n): FragnoVanillaMutator<\n _TMethod,\n TPath,\n TInputSchema,\n TOutputSchema,\n TErrorCode,\n TQueryParameters\n> {\n return () => {\n // TODO(Wilco): it should be possible for `loading` to be undefined, before a mutation has taken place.\n const store = hook.mutatorStore;\n return {\n subscribe: (callback) => {\n return store.subscribe((value) => {\n callback({\n loading: value.loading ?? false,\n error: value.error,\n data: value.data,\n });\n });\n },\n get: () => {\n const { loading, error, data } = store.get();\n return {\n loading: loading ?? false,\n error,\n data: data,\n };\n },\n mutate: ({ body, path, query }) => {\n return store.mutate({ body, path, query });\n },\n [Symbol.asyncIterator]() {\n return createAsyncIteratorFromCallback((callback) =>\n store.listen((value) => {\n callback({\n loading: value.loading ?? false,\n error: value.error,\n data: value.data,\n });\n }),\n );\n },\n };\n };\n}\n\nexport type FragnoVanillaStore<T extends object, TArgs extends unknown[] = []> = TArgs extends []\n ? T\n : (...args: TArgs) => T & { destroy?: () => void };\n\nexport type FragnoVanillaStoreFromData<TStore> = TStore extends {\n factory: (...args: infer TArgs) => infer TObject extends object;\n}\n ? (...args: TArgs) => TObject & { destroy?: () => void }\n : TStore extends { obj: infer TObject extends object }\n ? TObject\n : never;\n\nconst getStoreDisposer = (value: object): (() => void) | undefined => {\n const disposer = (value as { [Symbol.dispose]?: (() => void) | undefined })[Symbol.dispose];\n return typeof disposer === \"function\" ? disposer.bind(value) : undefined;\n};\n\nfunction createVanillaStore<const TStore extends FragnoStoreData<object, unknown[]>>(\n hook: TStore,\n): FragnoVanillaStoreFromData<TStore> {\n if (\"obj\" in hook) {\n return hook.obj as FragnoVanillaStoreFromData<TStore>;\n }\n\n return ((...args: Parameters<typeof hook.factory>) => {\n const value = hook.factory(...args);\n const disposer = getStoreDisposer(value);\n if (!disposer) {\n return value as ReturnType<typeof hook.factory> & { destroy?: () => void };\n }\n\n Object.defineProperty(value, \"destroy\", {\n value: disposer,\n enumerable: false,\n configurable: true,\n writable: true,\n });\n\n return value as ReturnType<typeof hook.factory> & { destroy?: () => void };\n }) as FragnoVanillaStoreFromData<TStore>;\n}\n\nexport function useFragno<T extends Record<string, unknown>>(\n clientObj: T,\n): {\n [K in keyof T]: T[K] extends FragnoClientHookData<\n \"GET\",\n infer TPath,\n infer TOutputSchema,\n infer TErrorCode,\n infer TQueryParameters\n >\n ? FragnoVanillaListeners<\"GET\", TPath, TOutputSchema, TErrorCode, TQueryParameters>\n : T[K] extends FragnoClientMutatorData<\n NonGetHTTPMethod,\n infer TPath,\n infer TInputSchema,\n infer TOutputSchema,\n infer TErrorCode,\n infer TQueryParameters\n >\n ? FragnoVanillaMutator<\n NonGetHTTPMethod,\n TPath,\n TInputSchema,\n TOutputSchema,\n TErrorCode,\n TQueryParameters\n >\n : T[K] extends FragnoStoreObjectData<infer TStoreObj>\n ? TStoreObj\n : T[K] extends FragnoStoreFactoryData<infer TStoreObj, infer TStoreArgs>\n ? (...args: TStoreArgs) => TStoreObj & { destroy?: () => void }\n : T[K];\n} {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const result = {} as any; // We need one any cast here due to TypeScript's limitations with mapped types\n\n for (const key in clientObj) {\n if (!Object.prototype.hasOwnProperty.call(clientObj, key)) {\n continue;\n }\n\n const hook = clientObj[key];\n if (isGetHook(hook)) {\n result[key] = createVanillaListeners(hook);\n } else if (isMutatorHook(hook)) {\n result[key] = createVanillaMutator(hook);\n } else if (isStore(hook)) {\n result[key] = createVanillaStore(hook);\n } else {\n // Pass through non-hook values unchanged\n result[key] = hook;\n }\n }\n\n return result;\n}\n"],"mappings":";;;;AAsEA,SAAS,uBAMP,MACmF;AACnF,SAAQ,EAAE,MAAM,UAAU,EAAE,KAAK;EAC/B,MAAM,QAAQ,KAAK,MAAM;GAAE;GAAM;GAAO,CAAC;AAEzC,SAAO;GACL,SAAS,aAAa;AACpB,WAAO,MAAM,QAAQ,EAAE,SAAS,OAAO,WACrC,SAAS;KACP;KACA;KACM;KACP,CAAC,CACH;;GAEH,YAAY,aAAa;AACvB,WAAO,MAAM,WAAW,EAAE,SAAS,OAAO,WACxC,SAAS;KACP;KACA;KACM;KACP,CAAC,CACH;;GAEH,eAAe;AACb,WAAO,MAAM,YAAY;;GAE3B,WAAW;AACT,WAAO,MAAM,KAAK;;GAEpB,CAAC,OAAO,iBAAiB;AACvB,WAAO,iCAAiC,aACtC,MAAM,QAAQ,EAAE,SAAS,OAAO,WAC9B,SAAS;KACP;KACA;KACM;KACP,CAAC,CACH,CACF;;GAEJ;;;AAyCL,SAAS,qBAQP,MAeA;AACA,cAAa;EAEX,MAAM,QAAQ,KAAK;AACnB,SAAO;GACL,YAAY,aAAa;AACvB,WAAO,MAAM,WAAW,UAAU;AAChC,cAAS;MACP,SAAS,MAAM,WAAW;MAC1B,OAAO,MAAM;MACb,MAAM,MAAM;MACb,CAAC;MACF;;GAEJ,WAAW;IACT,MAAM,EAAE,SAAS,OAAO,SAAS,MAAM,KAAK;AAC5C,WAAO;KACL,SAAS,WAAW;KACpB;KACM;KACP;;GAEH,SAAS,EAAE,MAAM,MAAM,YAAY;AACjC,WAAO,MAAM,OAAO;KAAE;KAAM;KAAM;KAAO,CAAC;;GAE5C,CAAC,OAAO,iBAAiB;AACvB,WAAO,iCAAiC,aACtC,MAAM,QAAQ,UAAU;AACtB,cAAS;MACP,SAAS,MAAM,WAAW;MAC1B,OAAO,MAAM;MACb,MAAM,MAAM;MACb,CAAC;MACF,CACH;;GAEJ;;;AAgBL,MAAM,oBAAoB,UAA4C;CACpE,MAAM,WAAY,MAA0D,OAAO;AACnF,QAAO,OAAO,aAAa,aAAa,SAAS,KAAK,MAAM,GAAG;;AAGjE,SAAS,mBACP,MACoC;AACpC,KAAI,SAAS,KACX,QAAO,KAAK;AAGd,UAAS,GAAG,SAA0C;EACpD,MAAM,QAAQ,KAAK,QAAQ,GAAG,KAAK;EACnC,MAAM,WAAW,iBAAiB,MAAM;AACxC,MAAI,CAAC,SACH,QAAO;AAGT,SAAO,eAAe,OAAO,WAAW;GACtC,OAAO;GACP,YAAY;GACZ,cAAc;GACd,UAAU;GACX,CAAC;AAEF,SAAO;;;AAIX,SAAgB,UACd,WA+BA;CAEA,MAAM,SAAS,EAAE;AAEjB,MAAK,MAAM,OAAO,WAAW;AAC3B,MAAI,CAAC,OAAO,UAAU,eAAe,KAAK,WAAW,IAAI,CACvD;EAGF,MAAM,OAAO,UAAU;AACvB,MAAI,UAAU,KAAK,CACjB,QAAO,OAAO,uBAAuB,KAAK;WACjC,cAAc,KAAK,CAC5B,QAAO,OAAO,qBAAqB,KAAK;WAC/B,QAAQ,KAAK,CACtB,QAAO,OAAO,mBAAmB,KAAK;MAGtC,QAAO,OAAO;;AAIlB,QAAO"}
|
package/dist/client/vue.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { MaybeExtractPathParamsOrWiden, QueryParamsHint } from "../api/internal/path.js";
|
|
2
2
|
import { InferOr } from "../util/types-util.js";
|
|
3
|
-
import { NonGetHTTPMethod } from "../api/api.js";
|
|
4
3
|
import { FragnoClientError } from "./client-error.js";
|
|
5
|
-
import { FragnoClientHookData, FragnoClientMutatorData } from "./client.js";
|
|
4
|
+
import { FragnoClientHookData, FragnoClientMutatorData, FragnoStoreFactoryData, FragnoStoreObjectData } from "./client.js";
|
|
5
|
+
import { NonGetHTTPMethod } from "../api/api.js";
|
|
6
6
|
import { ReadableAtom, Store, StoreValue } from "nanostores";
|
|
7
7
|
import { DeepReadonly, Ref, ShallowRef, UnwrapNestedRefs } from "vue";
|
|
8
8
|
import { StandardSchemaV1 } from "@standard-schema/spec";
|
|
@@ -26,6 +26,12 @@ type FragnoVueMutator<_TMethod extends NonGetHTTPMethod, TPath$1 extends string,
|
|
|
26
26
|
error: Ref<FragnoClientError<TErrorCode$1[number]> | undefined>;
|
|
27
27
|
data: Ref<InferOr<TOutputSchema$1, undefined>>;
|
|
28
28
|
};
|
|
29
|
+
/**
|
|
30
|
+
* Type helper that wraps any Store fields of the object into reactive Vue refs.
|
|
31
|
+
*/
|
|
32
|
+
type FragnoVueStoreRef<T extends Store> = DeepReadonly<UnwrapNestedRefs<ShallowRef<StoreValue<T>>>>;
|
|
33
|
+
type FragnoVueStoreValue<T extends object> = T extends Store ? FragnoVueStoreRef<T> : { [K in keyof T]: T[K] extends Store ? FragnoVueStoreRef<T[K]> : T[K] };
|
|
34
|
+
type FragnoVueStore<T extends object, TArgs extends unknown[] = []> = (...args: TArgs) => FragnoVueStoreValue<T>;
|
|
29
35
|
/**
|
|
30
36
|
* Converts a Vue Ref to a NanoStore Atom.
|
|
31
37
|
*
|
|
@@ -34,8 +40,8 @@ type FragnoVueMutator<_TMethod extends NonGetHTTPMethod, TPath$1 extends string,
|
|
|
34
40
|
* @private
|
|
35
41
|
*/
|
|
36
42
|
declare function refToAtom<T>(ref: Ref<T>): ReadableAtom<T>;
|
|
37
|
-
declare function useFragno<T extends Record<string, unknown>>(clientObj: T): { [K in keyof T]: T[K] extends FragnoClientHookData<"GET", infer TPath, infer TOutputSchema, infer TErrorCode, infer TQueryParameters> ? FragnoVueHook<"GET", TPath, TOutputSchema, TErrorCode, TQueryParameters> : T[K] extends FragnoClientMutatorData<infer M, infer TPath, infer TInputSchema, infer TOutputSchema, infer TErrorCode, infer TQueryParameters> ? FragnoVueMutator<M, TPath, TInputSchema, TOutputSchema, TErrorCode, TQueryParameters> : T[K] };
|
|
43
|
+
declare function useFragno<T extends Record<string, unknown>>(clientObj: T): { [K in keyof T]: T[K] extends FragnoClientHookData<"GET", infer TPath, infer TOutputSchema, infer TErrorCode, infer TQueryParameters> ? FragnoVueHook<"GET", TPath, TOutputSchema, TErrorCode, TQueryParameters> : T[K] extends FragnoClientMutatorData<infer M, infer TPath, infer TInputSchema, infer TOutputSchema, infer TErrorCode, infer TQueryParameters> ? FragnoVueMutator<M, TPath, TInputSchema, TOutputSchema, TErrorCode, TQueryParameters> : T[K] extends FragnoStoreObjectData<infer TStoreObj> ? FragnoVueStore<TStoreObj, []> : T[K] extends FragnoStoreFactoryData<infer TStoreObj, infer TStoreArgs> ? FragnoVueStore<TStoreObj, TStoreArgs> : T[K] };
|
|
38
44
|
declare function useStore<SomeStore extends Store, Value extends StoreValue<SomeStore>>(store: SomeStore): DeepReadonly<UnwrapNestedRefs<ShallowRef<Value>>>;
|
|
39
45
|
//#endregion
|
|
40
|
-
export { FragnoVueHook, FragnoVueMutator, refToAtom, useFragno, useStore };
|
|
46
|
+
export { FragnoVueHook, FragnoVueMutator, FragnoVueStore, refToAtom, useFragno, useStore };
|
|
41
47
|
//# sourceMappingURL=vue.d.ts.map
|
package/dist/client/vue.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"vue.d.ts","names":[],"sources":["../../src/client/vue.ts"],"sourcesContent":[],"mappings":";;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"vue.d.ts","names":[],"sources":["../../src/client/vue.ts"],"sourcesContent":[],"mappings":"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"}
|
package/dist/client/vue.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { isReadableAtom } from "../util/nanostores.js";
|
|
2
|
+
import { isGetHook, isMutatorHook, isStore } from "./client.js";
|
|
2
3
|
import { atom } from "nanostores";
|
|
3
4
|
import { computed as computed$1, getCurrentScope, isRef, onScopeDispose, ref, shallowRef, watch } from "vue";
|
|
4
5
|
|
|
@@ -80,6 +81,27 @@ function createVueMutator(hook) {
|
|
|
80
81
|
};
|
|
81
82
|
};
|
|
82
83
|
}
|
|
84
|
+
function unwrapVueStoreValue(value) {
|
|
85
|
+
if (isReadableAtom(value)) return useStore(value);
|
|
86
|
+
const result = {};
|
|
87
|
+
for (const key in value) {
|
|
88
|
+
if (!Object.prototype.hasOwnProperty.call(value, key)) continue;
|
|
89
|
+
const fieldValue = value[key];
|
|
90
|
+
if (isReadableAtom(fieldValue)) result[key] = useStore(fieldValue);
|
|
91
|
+
else result[key] = fieldValue;
|
|
92
|
+
}
|
|
93
|
+
return result;
|
|
94
|
+
}
|
|
95
|
+
function createVueStore(hook) {
|
|
96
|
+
return ((...args) => {
|
|
97
|
+
const value = "factory" in hook ? hook.factory(...args) : hook.obj;
|
|
98
|
+
const disposer = value[Symbol.dispose];
|
|
99
|
+
if (typeof disposer === "function" && getCurrentScope()) onScopeDispose(() => {
|
|
100
|
+
disposer.call(value);
|
|
101
|
+
});
|
|
102
|
+
return unwrapVueStoreValue(value);
|
|
103
|
+
});
|
|
104
|
+
}
|
|
83
105
|
function useFragno(clientObj) {
|
|
84
106
|
const result = {};
|
|
85
107
|
for (const key in clientObj) {
|
|
@@ -87,6 +109,7 @@ function useFragno(clientObj) {
|
|
|
87
109
|
const hook = clientObj[key];
|
|
88
110
|
if (isGetHook(hook)) result[key] = createVueHook(hook);
|
|
89
111
|
else if (isMutatorHook(hook)) result[key] = createVueMutator(hook);
|
|
112
|
+
else if (isStore(hook)) result[key] = createVueStore(hook);
|
|
90
113
|
else result[key] = hook;
|
|
91
114
|
}
|
|
92
115
|
return result;
|