@fragno-dev/core 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build.log +61 -0
- package/.turbo/turbo-types$colon$check.log +2 -0
- package/dist/api/api.d.ts +2 -0
- package/dist/api/api.js +3 -0
- package/dist/api-CBDGZiLC.d.ts +278 -0
- package/dist/api-CBDGZiLC.d.ts.map +1 -0
- package/dist/api-DgHfYjq2.js +54 -0
- package/dist/api-DgHfYjq2.js.map +1 -0
- package/dist/client/client.d.ts +3 -0
- package/dist/client/client.js +6 -0
- package/dist/client/client.svelte.d.ts +33 -0
- package/dist/client/client.svelte.d.ts.map +1 -0
- package/dist/client/client.svelte.js +123 -0
- package/dist/client/client.svelte.js.map +1 -0
- package/dist/client/react.d.ts +58 -0
- package/dist/client/react.d.ts.map +1 -0
- package/dist/client/react.js +80 -0
- package/dist/client/react.js.map +1 -0
- package/dist/client/vanilla.d.ts +61 -0
- package/dist/client/vanilla.d.ts.map +1 -0
- package/dist/client/vanilla.js +136 -0
- package/dist/client/vanilla.js.map +1 -0
- package/dist/client/vue.d.ts +39 -0
- package/dist/client/vue.d.ts.map +1 -0
- package/dist/client/vue.js +108 -0
- package/dist/client/vue.js.map +1 -0
- package/dist/client-DWjxKDnE.js +703 -0
- package/dist/client-DWjxKDnE.js.map +1 -0
- package/dist/client-XFdAy-IQ.d.ts +287 -0
- package/dist/client-XFdAy-IQ.d.ts.map +1 -0
- package/dist/integrations/astro.d.ts +18 -0
- package/dist/integrations/astro.d.ts.map +1 -0
- package/dist/integrations/astro.js +16 -0
- package/dist/integrations/astro.js.map +1 -0
- package/dist/integrations/next-js.d.ts +15 -0
- package/dist/integrations/next-js.d.ts.map +1 -0
- package/dist/integrations/next-js.js +17 -0
- package/dist/integrations/next-js.js.map +1 -0
- package/dist/integrations/react-ssr.d.ts +19 -0
- package/dist/integrations/react-ssr.d.ts.map +1 -0
- package/dist/integrations/react-ssr.js +38 -0
- package/dist/integrations/react-ssr.js.map +1 -0
- package/dist/integrations/svelte-kit.d.ts +21 -0
- package/dist/integrations/svelte-kit.d.ts.map +1 -0
- package/dist/integrations/svelte-kit.js +18 -0
- package/dist/integrations/svelte-kit.js.map +1 -0
- package/dist/mod.d.ts +3 -0
- package/dist/mod.js +177 -0
- package/dist/mod.js.map +1 -0
- package/dist/route-Bp6eByhz.js +331 -0
- package/dist/route-Bp6eByhz.js.map +1 -0
- package/dist/ssr-tJHqcNSw.js +48 -0
- package/dist/ssr-tJHqcNSw.js.map +1 -0
- package/package.json +127 -0
- package/src/api/api.test.ts +140 -0
- package/src/api/api.ts +106 -0
- package/src/api/error.ts +47 -0
- package/src/api/fragment.test.ts +509 -0
- package/src/api/fragment.ts +277 -0
- package/src/api/internal/path-runtime.test.ts +121 -0
- package/src/api/internal/path-type.test.ts +602 -0
- package/src/api/internal/path.ts +322 -0
- package/src/api/internal/response-stream.ts +118 -0
- package/src/api/internal/route.test.ts +56 -0
- package/src/api/internal/route.ts +9 -0
- package/src/api/request-input-context.test.ts +437 -0
- package/src/api/request-input-context.ts +201 -0
- package/src/api/request-middleware.test.ts +544 -0
- package/src/api/request-middleware.ts +126 -0
- package/src/api/request-output-context.test.ts +626 -0
- package/src/api/request-output-context.ts +175 -0
- package/src/api/route.test.ts +176 -0
- package/src/api/route.ts +152 -0
- package/src/client/client-builder.test.ts +264 -0
- package/src/client/client-error.test.ts +15 -0
- package/src/client/client-error.ts +141 -0
- package/src/client/client-types.test.ts +493 -0
- package/src/client/client.ssr.test.ts +173 -0
- package/src/client/client.svelte.test.ts +837 -0
- package/src/client/client.svelte.ts +278 -0
- package/src/client/client.test.ts +1690 -0
- package/src/client/client.ts +1035 -0
- package/src/client/component.test.svelte +21 -0
- package/src/client/internal/ndjson-streaming.test.ts +457 -0
- package/src/client/internal/ndjson-streaming.ts +248 -0
- package/src/client/react.test.ts +947 -0
- package/src/client/react.ts +241 -0
- package/src/client/vanilla.test.ts +867 -0
- package/src/client/vanilla.ts +265 -0
- package/src/client/vue.test.ts +754 -0
- package/src/client/vue.ts +242 -0
- package/src/http/http-status.ts +60 -0
- package/src/integrations/astro.ts +17 -0
- package/src/integrations/next-js.ts +31 -0
- package/src/integrations/react-ssr.ts +40 -0
- package/src/integrations/svelte-kit.ts +41 -0
- package/src/mod.ts +20 -0
- package/src/util/async.test.ts +85 -0
- package/src/util/async.ts +96 -0
- package/src/util/content-type.test.ts +136 -0
- package/src/util/content-type.ts +84 -0
- package/src/util/nanostores.test.ts +28 -0
- package/src/util/nanostores.ts +65 -0
- package/src/util/ssr.ts +75 -0
- package/src/util/types-util.ts +16 -0
- package/tsconfig.json +10 -0
- package/tsdown.config.ts +21 -0
- package/vitest.config.ts +10 -0
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
import type { StandardSchemaV1 } from "@standard-schema/spec";
|
|
2
|
+
import type { ReadableAtom } from "nanostores";
|
|
3
|
+
import type { NonGetHTTPMethod } from "../api/api";
|
|
4
|
+
import {
|
|
5
|
+
isGetHook,
|
|
6
|
+
isMutatorHook,
|
|
7
|
+
type FragnoClientMutatorData,
|
|
8
|
+
type FragnoClientHookData,
|
|
9
|
+
} from "./client";
|
|
10
|
+
import type { FragnoClientError } from "./client-error";
|
|
11
|
+
import { createAsyncIteratorFromCallback } from "../util/async";
|
|
12
|
+
import type { InferOr } from "../util/types-util";
|
|
13
|
+
import type {
|
|
14
|
+
ExtractPathParamsOrWiden,
|
|
15
|
+
HasPathParams,
|
|
16
|
+
MaybeExtractPathParamsOrWiden,
|
|
17
|
+
} from "../api/internal/path";
|
|
18
|
+
|
|
19
|
+
export type StoreData<
|
|
20
|
+
TOutputSchema extends StandardSchemaV1 | undefined,
|
|
21
|
+
TErrorCodes extends string,
|
|
22
|
+
> = {
|
|
23
|
+
loading: boolean;
|
|
24
|
+
error?: FragnoClientError<TErrorCodes>;
|
|
25
|
+
data?: InferOr<TOutputSchema, undefined>;
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
export type FragnoVanillaListeners<
|
|
29
|
+
_TMethod extends "GET",
|
|
30
|
+
TPath extends string,
|
|
31
|
+
TOutputSchema extends StandardSchemaV1,
|
|
32
|
+
TErrorCode extends string,
|
|
33
|
+
TQueryParameters extends string,
|
|
34
|
+
> = (args?: {
|
|
35
|
+
path?: MaybeExtractPathParamsOrWiden<TPath, string | ReadableAtom<string>>;
|
|
36
|
+
query?: Record<TQueryParameters, string | ReadableAtom<string>>;
|
|
37
|
+
}) => {
|
|
38
|
+
/** Called for every change in the store. */
|
|
39
|
+
listen: (callback: (value: StoreData<TOutputSchema, TErrorCode[number]>) => void) => () => void;
|
|
40
|
+
/** Called once initially, then called for every change in the store. */
|
|
41
|
+
subscribe: (
|
|
42
|
+
callback: (value: StoreData<TOutputSchema, TErrorCode[number]>) => void,
|
|
43
|
+
) => () => void;
|
|
44
|
+
get: () => StoreData<TOutputSchema, TErrorCode[number]>;
|
|
45
|
+
refetch: () => void;
|
|
46
|
+
/**
|
|
47
|
+
* Produces an item for every change in the store.
|
|
48
|
+
* Note: the iterator does NOT return.
|
|
49
|
+
*
|
|
50
|
+
* @example
|
|
51
|
+
* ```typescript
|
|
52
|
+
* const store = useFragno(clientObj).store;
|
|
53
|
+
* for await (const value of store[Symbol.asyncIterator]()) {
|
|
54
|
+
* console.log(value);
|
|
55
|
+
* }
|
|
56
|
+
* ```
|
|
57
|
+
*/
|
|
58
|
+
[Symbol.asyncIterator]: () => AsyncGenerator<
|
|
59
|
+
StoreData<TOutputSchema, TErrorCode[number]>,
|
|
60
|
+
void,
|
|
61
|
+
unknown
|
|
62
|
+
>;
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
function createVanillaListeners<
|
|
66
|
+
TPath extends string,
|
|
67
|
+
TOutputSchema extends StandardSchemaV1,
|
|
68
|
+
TErrorCode extends string,
|
|
69
|
+
TQueryParameters extends string,
|
|
70
|
+
>(
|
|
71
|
+
hook: FragnoClientHookData<"GET", TPath, TOutputSchema, TErrorCode, TQueryParameters>,
|
|
72
|
+
): FragnoVanillaListeners<"GET", TPath, TOutputSchema, TErrorCode, TQueryParameters> {
|
|
73
|
+
return ({ path, query } = {}) => {
|
|
74
|
+
const store = hook.store({ path, query });
|
|
75
|
+
|
|
76
|
+
return {
|
|
77
|
+
listen: (callback) => {
|
|
78
|
+
return store.listen(({ loading, error, data }) =>
|
|
79
|
+
callback({
|
|
80
|
+
loading,
|
|
81
|
+
error,
|
|
82
|
+
data: data as InferOr<TOutputSchema, undefined>,
|
|
83
|
+
}),
|
|
84
|
+
);
|
|
85
|
+
},
|
|
86
|
+
subscribe: (callback) => {
|
|
87
|
+
return store.subscribe(({ loading, error, data }) =>
|
|
88
|
+
callback({
|
|
89
|
+
loading,
|
|
90
|
+
error,
|
|
91
|
+
data: data as InferOr<TOutputSchema, undefined>,
|
|
92
|
+
}),
|
|
93
|
+
);
|
|
94
|
+
},
|
|
95
|
+
refetch: () => {
|
|
96
|
+
return store.revalidate();
|
|
97
|
+
},
|
|
98
|
+
get: () => {
|
|
99
|
+
return store.get() as StoreData<TOutputSchema, TErrorCode[number]>;
|
|
100
|
+
},
|
|
101
|
+
[Symbol.asyncIterator]() {
|
|
102
|
+
return createAsyncIteratorFromCallback((callback) =>
|
|
103
|
+
store.listen(({ loading, error, data }) =>
|
|
104
|
+
callback({
|
|
105
|
+
loading,
|
|
106
|
+
error,
|
|
107
|
+
data: data as InferOr<TOutputSchema, undefined>,
|
|
108
|
+
}),
|
|
109
|
+
),
|
|
110
|
+
);
|
|
111
|
+
},
|
|
112
|
+
};
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
export type FragnoVanillaMutator<
|
|
117
|
+
_TMethod extends NonGetHTTPMethod,
|
|
118
|
+
TPath extends string,
|
|
119
|
+
TInputSchema extends StandardSchemaV1 | undefined,
|
|
120
|
+
TOutputSchema extends StandardSchemaV1 | undefined,
|
|
121
|
+
TErrorCode extends string,
|
|
122
|
+
TQueryParameters extends string,
|
|
123
|
+
> = (args?: {
|
|
124
|
+
path?: MaybeExtractPathParamsOrWiden<TPath, string | ReadableAtom<string>>;
|
|
125
|
+
query?: Record<TQueryParameters, string | ReadableAtom<string>>;
|
|
126
|
+
}) => {
|
|
127
|
+
subscribe: (
|
|
128
|
+
callback: (value: {
|
|
129
|
+
loading: boolean;
|
|
130
|
+
error?: FragnoClientError<TErrorCode[number]>;
|
|
131
|
+
data?: InferOr<TOutputSchema, undefined>;
|
|
132
|
+
}) => void,
|
|
133
|
+
) => () => void;
|
|
134
|
+
get: () => StoreData<TOutputSchema, TErrorCode[number]>;
|
|
135
|
+
mutate: ({
|
|
136
|
+
body,
|
|
137
|
+
path,
|
|
138
|
+
query,
|
|
139
|
+
}: {
|
|
140
|
+
body?: InferOr<TInputSchema, undefined>;
|
|
141
|
+
path?: HasPathParams<TPath> extends true
|
|
142
|
+
? ExtractPathParamsOrWiden<TPath, string | ReadableAtom<string>>
|
|
143
|
+
: undefined;
|
|
144
|
+
query?: Record<string, string | ReadableAtom<string>>;
|
|
145
|
+
}) => Promise<InferOr<TOutputSchema, undefined>>;
|
|
146
|
+
[Symbol.asyncIterator]: () => AsyncGenerator<
|
|
147
|
+
StoreData<TOutputSchema, TErrorCode[number]>,
|
|
148
|
+
void,
|
|
149
|
+
unknown
|
|
150
|
+
>;
|
|
151
|
+
};
|
|
152
|
+
|
|
153
|
+
function createVanillaMutator<
|
|
154
|
+
_TMethod extends NonGetHTTPMethod,
|
|
155
|
+
TPath extends string,
|
|
156
|
+
TInputSchema extends StandardSchemaV1 | undefined,
|
|
157
|
+
TOutputSchema extends StandardSchemaV1 | undefined,
|
|
158
|
+
TErrorCode extends string,
|
|
159
|
+
TQueryParameters extends string,
|
|
160
|
+
>(
|
|
161
|
+
hook: FragnoClientMutatorData<
|
|
162
|
+
_TMethod,
|
|
163
|
+
TPath,
|
|
164
|
+
TInputSchema,
|
|
165
|
+
TOutputSchema,
|
|
166
|
+
TErrorCode,
|
|
167
|
+
TQueryParameters
|
|
168
|
+
>,
|
|
169
|
+
): FragnoVanillaMutator<
|
|
170
|
+
_TMethod,
|
|
171
|
+
TPath,
|
|
172
|
+
TInputSchema,
|
|
173
|
+
TOutputSchema,
|
|
174
|
+
TErrorCode,
|
|
175
|
+
TQueryParameters
|
|
176
|
+
> {
|
|
177
|
+
return () => {
|
|
178
|
+
// TODO(Wilco): it should be possible for `loading` to be undefined, before a mutation has taken place.
|
|
179
|
+
const store = hook.mutatorStore;
|
|
180
|
+
return {
|
|
181
|
+
subscribe: (callback) => {
|
|
182
|
+
return store.subscribe((value) => {
|
|
183
|
+
callback({
|
|
184
|
+
loading: value.loading ?? false,
|
|
185
|
+
error: value.error,
|
|
186
|
+
data: value.data,
|
|
187
|
+
});
|
|
188
|
+
});
|
|
189
|
+
},
|
|
190
|
+
get: () => {
|
|
191
|
+
const { loading, error, data } = store.get();
|
|
192
|
+
return {
|
|
193
|
+
loading: loading ?? false,
|
|
194
|
+
error,
|
|
195
|
+
data: data,
|
|
196
|
+
};
|
|
197
|
+
},
|
|
198
|
+
mutate: ({ body, path, query }) => {
|
|
199
|
+
return store.mutate({ body, path, query });
|
|
200
|
+
},
|
|
201
|
+
[Symbol.asyncIterator]() {
|
|
202
|
+
return createAsyncIteratorFromCallback((callback) =>
|
|
203
|
+
store.listen((value) => {
|
|
204
|
+
callback({
|
|
205
|
+
loading: value.loading ?? false,
|
|
206
|
+
error: value.error,
|
|
207
|
+
data: value.data,
|
|
208
|
+
});
|
|
209
|
+
}),
|
|
210
|
+
);
|
|
211
|
+
},
|
|
212
|
+
};
|
|
213
|
+
};
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
export function useFragno<T extends Record<string, unknown>>(
|
|
217
|
+
clientObj: T,
|
|
218
|
+
): {
|
|
219
|
+
[K in keyof T]: T[K] extends FragnoClientHookData<
|
|
220
|
+
"GET",
|
|
221
|
+
infer TPath,
|
|
222
|
+
infer TOutputSchema,
|
|
223
|
+
infer TErrorCode,
|
|
224
|
+
infer TQueryParameters
|
|
225
|
+
>
|
|
226
|
+
? FragnoVanillaListeners<"GET", TPath, TOutputSchema, TErrorCode, TQueryParameters>
|
|
227
|
+
: T[K] extends FragnoClientMutatorData<
|
|
228
|
+
NonGetHTTPMethod,
|
|
229
|
+
infer TPath,
|
|
230
|
+
infer TInputSchema,
|
|
231
|
+
infer TOutputSchema,
|
|
232
|
+
infer TErrorCode,
|
|
233
|
+
infer TQueryParameters
|
|
234
|
+
>
|
|
235
|
+
? FragnoVanillaMutator<
|
|
236
|
+
NonGetHTTPMethod,
|
|
237
|
+
TPath,
|
|
238
|
+
TInputSchema,
|
|
239
|
+
TOutputSchema,
|
|
240
|
+
TErrorCode,
|
|
241
|
+
TQueryParameters
|
|
242
|
+
>
|
|
243
|
+
: T[K];
|
|
244
|
+
} {
|
|
245
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
246
|
+
const result = {} as any; // We need one any cast here due to TypeScript's limitations with mapped types
|
|
247
|
+
|
|
248
|
+
for (const key in clientObj) {
|
|
249
|
+
if (!Object.prototype.hasOwnProperty.call(clientObj, key)) {
|
|
250
|
+
continue;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
const hook = clientObj[key];
|
|
254
|
+
if (isGetHook(hook)) {
|
|
255
|
+
result[key] = createVanillaListeners(hook);
|
|
256
|
+
} else if (isMutatorHook(hook)) {
|
|
257
|
+
result[key] = createVanillaMutator(hook);
|
|
258
|
+
} else {
|
|
259
|
+
// Pass through non-hook values unchanged
|
|
260
|
+
result[key] = hook;
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
return result;
|
|
265
|
+
}
|