@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.
Files changed (108) hide show
  1. package/.turbo/turbo-build.log +61 -0
  2. package/.turbo/turbo-types$colon$check.log +2 -0
  3. package/dist/api/api.d.ts +2 -0
  4. package/dist/api/api.js +3 -0
  5. package/dist/api-CBDGZiLC.d.ts +278 -0
  6. package/dist/api-CBDGZiLC.d.ts.map +1 -0
  7. package/dist/api-DgHfYjq2.js +54 -0
  8. package/dist/api-DgHfYjq2.js.map +1 -0
  9. package/dist/client/client.d.ts +3 -0
  10. package/dist/client/client.js +6 -0
  11. package/dist/client/client.svelte.d.ts +33 -0
  12. package/dist/client/client.svelte.d.ts.map +1 -0
  13. package/dist/client/client.svelte.js +123 -0
  14. package/dist/client/client.svelte.js.map +1 -0
  15. package/dist/client/react.d.ts +58 -0
  16. package/dist/client/react.d.ts.map +1 -0
  17. package/dist/client/react.js +80 -0
  18. package/dist/client/react.js.map +1 -0
  19. package/dist/client/vanilla.d.ts +61 -0
  20. package/dist/client/vanilla.d.ts.map +1 -0
  21. package/dist/client/vanilla.js +136 -0
  22. package/dist/client/vanilla.js.map +1 -0
  23. package/dist/client/vue.d.ts +39 -0
  24. package/dist/client/vue.d.ts.map +1 -0
  25. package/dist/client/vue.js +108 -0
  26. package/dist/client/vue.js.map +1 -0
  27. package/dist/client-DWjxKDnE.js +703 -0
  28. package/dist/client-DWjxKDnE.js.map +1 -0
  29. package/dist/client-XFdAy-IQ.d.ts +287 -0
  30. package/dist/client-XFdAy-IQ.d.ts.map +1 -0
  31. package/dist/integrations/astro.d.ts +18 -0
  32. package/dist/integrations/astro.d.ts.map +1 -0
  33. package/dist/integrations/astro.js +16 -0
  34. package/dist/integrations/astro.js.map +1 -0
  35. package/dist/integrations/next-js.d.ts +15 -0
  36. package/dist/integrations/next-js.d.ts.map +1 -0
  37. package/dist/integrations/next-js.js +17 -0
  38. package/dist/integrations/next-js.js.map +1 -0
  39. package/dist/integrations/react-ssr.d.ts +19 -0
  40. package/dist/integrations/react-ssr.d.ts.map +1 -0
  41. package/dist/integrations/react-ssr.js +38 -0
  42. package/dist/integrations/react-ssr.js.map +1 -0
  43. package/dist/integrations/svelte-kit.d.ts +21 -0
  44. package/dist/integrations/svelte-kit.d.ts.map +1 -0
  45. package/dist/integrations/svelte-kit.js +18 -0
  46. package/dist/integrations/svelte-kit.js.map +1 -0
  47. package/dist/mod.d.ts +3 -0
  48. package/dist/mod.js +177 -0
  49. package/dist/mod.js.map +1 -0
  50. package/dist/route-Bp6eByhz.js +331 -0
  51. package/dist/route-Bp6eByhz.js.map +1 -0
  52. package/dist/ssr-tJHqcNSw.js +48 -0
  53. package/dist/ssr-tJHqcNSw.js.map +1 -0
  54. package/package.json +127 -0
  55. package/src/api/api.test.ts +140 -0
  56. package/src/api/api.ts +106 -0
  57. package/src/api/error.ts +47 -0
  58. package/src/api/fragment.test.ts +509 -0
  59. package/src/api/fragment.ts +277 -0
  60. package/src/api/internal/path-runtime.test.ts +121 -0
  61. package/src/api/internal/path-type.test.ts +602 -0
  62. package/src/api/internal/path.ts +322 -0
  63. package/src/api/internal/response-stream.ts +118 -0
  64. package/src/api/internal/route.test.ts +56 -0
  65. package/src/api/internal/route.ts +9 -0
  66. package/src/api/request-input-context.test.ts +437 -0
  67. package/src/api/request-input-context.ts +201 -0
  68. package/src/api/request-middleware.test.ts +544 -0
  69. package/src/api/request-middleware.ts +126 -0
  70. package/src/api/request-output-context.test.ts +626 -0
  71. package/src/api/request-output-context.ts +175 -0
  72. package/src/api/route.test.ts +176 -0
  73. package/src/api/route.ts +152 -0
  74. package/src/client/client-builder.test.ts +264 -0
  75. package/src/client/client-error.test.ts +15 -0
  76. package/src/client/client-error.ts +141 -0
  77. package/src/client/client-types.test.ts +493 -0
  78. package/src/client/client.ssr.test.ts +173 -0
  79. package/src/client/client.svelte.test.ts +837 -0
  80. package/src/client/client.svelte.ts +278 -0
  81. package/src/client/client.test.ts +1690 -0
  82. package/src/client/client.ts +1035 -0
  83. package/src/client/component.test.svelte +21 -0
  84. package/src/client/internal/ndjson-streaming.test.ts +457 -0
  85. package/src/client/internal/ndjson-streaming.ts +248 -0
  86. package/src/client/react.test.ts +947 -0
  87. package/src/client/react.ts +241 -0
  88. package/src/client/vanilla.test.ts +867 -0
  89. package/src/client/vanilla.ts +265 -0
  90. package/src/client/vue.test.ts +754 -0
  91. package/src/client/vue.ts +242 -0
  92. package/src/http/http-status.ts +60 -0
  93. package/src/integrations/astro.ts +17 -0
  94. package/src/integrations/next-js.ts +31 -0
  95. package/src/integrations/react-ssr.ts +40 -0
  96. package/src/integrations/svelte-kit.ts +41 -0
  97. package/src/mod.ts +20 -0
  98. package/src/util/async.test.ts +85 -0
  99. package/src/util/async.ts +96 -0
  100. package/src/util/content-type.test.ts +136 -0
  101. package/src/util/content-type.ts +84 -0
  102. package/src/util/nanostores.test.ts +28 -0
  103. package/src/util/nanostores.ts +65 -0
  104. package/src/util/ssr.ts +75 -0
  105. package/src/util/types-util.ts +16 -0
  106. package/tsconfig.json +10 -0
  107. package/tsdown.config.ts +21 -0
  108. 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
+ }