@fragno-dev/core 0.2.0 → 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 +72 -62
- package/CHANGELOG.md +28 -0
- package/dist/api/api.d.ts +3 -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 +26 -44
- package/dist/api/fragment-definition-builder.d.ts.map +1 -1
- package/dist/api/fragment-definition-builder.js +15 -22
- package/dist/api/fragment-definition-builder.js.map +1 -1
- package/dist/api/fragment-instantiator.d.ts +51 -37
- package/dist/api/fragment-instantiator.d.ts.map +1 -1
- package/dist/api/fragment-instantiator.js +74 -69
- 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.map +1 -1
- package/dist/api/request-input-context.js.map +1 -1
- package/dist/api/request-middleware.d.ts +1 -1
- 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 +1 -1
- 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 +91 -52
- package/dist/client/client.d.ts.map +1 -1
- package/dist/client/client.js +25 -9
- 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 +7 -5
- package/dist/client/vue.d.ts.map +1 -1
- package/dist/client/vue.js +18 -10
- 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/mod-client.d.ts +5 -4
- package/dist/mod-client.d.ts.map +1 -1
- package/dist/mod-client.js +7 -5
- package/dist/mod-client.js.map +1 -1
- package/dist/mod.d.ts +6 -5
- package/dist/mod.js +2 -1
- package/dist/runtime.js +1 -1
- package/dist/runtime.js.map +1 -1
- 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 +24 -40
- package/src/api/api.test.ts +3 -1
- package/src/api/api.ts +6 -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 +49 -124
- package/src/api/fragment-instantiator.test.ts +92 -233
- package/src/api/fragment-instantiator.ts +228 -196
- package/src/api/fragment-services.test.ts +1 -0
- package/src/api/internal/path-runtime.test.ts +1 -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 +4 -2
- package/src/api/request-input-context.ts +2 -1
- package/src/api/request-middleware.test.ts +9 -14
- package/src/api/request-middleware.ts +3 -2
- 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 +2 -1
- 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 +49 -10
- package/src/client/client.ts +291 -141
- 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 +223 -84
- package/src/client/vue.ts +57 -30
- package/src/id.ts +1 -0
- package/src/internal/cuid.test.ts +164 -0
- package/src/internal/cuid.ts +133 -0
- package/src/mod-client.ts +4 -2
- package/src/mod.ts +3 -2
- package/src/runtime.ts +1 -1
- package/src/test/test.test.ts +4 -2
- package/src/test/test.ts +7 -9
- 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 +1 -0
- package/vitest.config.ts +2 -1
|
@@ -7,12 +7,14 @@
|
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
9
|
import { describe, expect, test } from "vitest";
|
|
10
|
-
|
|
11
|
-
import { createClientBuilder } from "./client";
|
|
12
|
-
import { defineRoute } from "../api/route";
|
|
13
|
-
import { defineFragment } from "../api/fragment-definition-builder";
|
|
10
|
+
|
|
14
11
|
import { z } from "zod";
|
|
12
|
+
|
|
13
|
+
import { defineFragment } from "../api/fragment-definition-builder";
|
|
14
|
+
import { defineRoute } from "../api/route";
|
|
15
15
|
import { createAsyncIteratorFromCallback, waitForAsyncIterator } from "../util/async";
|
|
16
|
+
import { type FragnoPublicClientConfig } from "./client";
|
|
17
|
+
import { createClientBuilder } from "./client";
|
|
16
18
|
|
|
17
19
|
describe("server side rendering", () => {
|
|
18
20
|
const testFragmentDefinition = defineFragment("test-fragment").build();
|
|
@@ -1,16 +1,19 @@
|
|
|
1
1
|
import { test, expect, describe, vi, beforeEach, afterEach, assert } from "vitest";
|
|
2
|
-
|
|
3
|
-
import {
|
|
2
|
+
|
|
3
|
+
import { atom, computed } from "nanostores";
|
|
4
|
+
import { writable, readable, get, derived } from "svelte/store";
|
|
5
|
+
import { z } from "zod";
|
|
6
|
+
|
|
4
7
|
import { render } from "@testing-library/svelte";
|
|
5
|
-
|
|
8
|
+
|
|
6
9
|
import { defineFragment } from "../api/fragment-definition-builder";
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
+
import { RequestOutputContext } from "../api/request-output-context";
|
|
11
|
+
import { defineRoute } from "../api/route";
|
|
12
|
+
import { type FragnoPublicClientConfig } from "./client";
|
|
13
|
+
import { createClientBuilder } from "./client";
|
|
10
14
|
import { FragnoClientUnknownApiError } from "./client-error";
|
|
15
|
+
import { readableToAtom, useFragno } from "./client.svelte";
|
|
11
16
|
import TestComponent from "./component.test.svelte";
|
|
12
|
-
import { atom, computed } from "nanostores";
|
|
13
|
-
import { RequestOutputContext } from "../api/request-output-context";
|
|
14
17
|
|
|
15
18
|
function renderHook(
|
|
16
19
|
clientObj: Record<string, unknown>,
|
|
@@ -766,7 +769,13 @@ describe("useFragno", () => {
|
|
|
766
769
|
expect((get(hook.data) as TestData | undefined)?.id).toBe(456);
|
|
767
770
|
});
|
|
768
771
|
|
|
769
|
-
|
|
772
|
+
const requestedIds = vi
|
|
773
|
+
.mocked(global.fetch)
|
|
774
|
+
.mock.calls.map(([input]) => String(input).match(/\/users\/([^/]+)/)?.[1])
|
|
775
|
+
.filter((id): id is string => id !== undefined);
|
|
776
|
+
|
|
777
|
+
expect(requestedIds).toContain("123");
|
|
778
|
+
expect(requestedIds).toContain("456");
|
|
770
779
|
});
|
|
771
780
|
});
|
|
772
781
|
|
|
@@ -1,6 +1,12 @@
|
|
|
1
|
-
import type { StandardSchemaV1 } from "@standard-schema/spec";
|
|
2
1
|
import { atom, type ReadableAtom } from "nanostores";
|
|
2
|
+
import { onDestroy } from "svelte";
|
|
3
|
+
import { writable, type Readable, get } from "svelte/store";
|
|
4
|
+
|
|
5
|
+
import type { StandardSchemaV1 } from "@standard-schema/spec";
|
|
6
|
+
|
|
3
7
|
import type { NonGetHTTPMethod } from "../api/api";
|
|
8
|
+
import type { MaybeExtractPathParamsOrWiden, QueryParamsHint } from "../api/internal/path";
|
|
9
|
+
import type { InferOr } from "../util/types-util";
|
|
4
10
|
import {
|
|
5
11
|
isGetHook,
|
|
6
12
|
isMutatorHook,
|
|
@@ -8,13 +14,10 @@ import {
|
|
|
8
14
|
type FragnoClientHookData,
|
|
9
15
|
type FragnoClientMutatorData,
|
|
10
16
|
type FragnoStoreData,
|
|
17
|
+
type FragnoStoreFactoryData,
|
|
18
|
+
type FragnoStoreObjectData,
|
|
11
19
|
} from "./client";
|
|
12
20
|
import type { FragnoClientError } from "./client-error";
|
|
13
|
-
import type { InferOr } from "../util/types-util";
|
|
14
|
-
import type { MaybeExtractPathParamsOrWiden, QueryParamsHint } from "../api/internal/path";
|
|
15
|
-
|
|
16
|
-
import { writable, type Readable, get } from "svelte/store";
|
|
17
|
-
import { onDestroy } from "svelte";
|
|
18
21
|
|
|
19
22
|
export type FragnoSvelteHook<
|
|
20
23
|
_TMethod extends "GET",
|
|
@@ -223,10 +226,30 @@ function createSvelteMutator<
|
|
|
223
226
|
};
|
|
224
227
|
}
|
|
225
228
|
|
|
226
|
-
export
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
229
|
+
export type FragnoSvelteStore<T extends object, TArgs extends unknown[] = []> = TArgs extends []
|
|
230
|
+
? T
|
|
231
|
+
: (...args: TArgs) => T;
|
|
232
|
+
|
|
233
|
+
export function createSvelteStore<T extends object, TArgs extends unknown[]>(
|
|
234
|
+
hook: FragnoStoreData<T, TArgs>,
|
|
235
|
+
): FragnoSvelteStore<T, TArgs> {
|
|
236
|
+
if ("obj" in hook) {
|
|
237
|
+
// Since nanostores already implement Svelte's store contract,
|
|
238
|
+
// we can return the store object directly for use with $ syntax
|
|
239
|
+
return hook.obj as FragnoSvelteStore<T, TArgs>;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
return ((...args: TArgs) => {
|
|
243
|
+
const value = hook.factory(...args);
|
|
244
|
+
const disposer = value[Symbol.dispose as keyof typeof value];
|
|
245
|
+
if (typeof disposer === "function") {
|
|
246
|
+
onDestroy(() => {
|
|
247
|
+
disposer.call(value);
|
|
248
|
+
});
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
return value;
|
|
252
|
+
}) as FragnoSvelteStore<T, TArgs>;
|
|
230
253
|
}
|
|
231
254
|
|
|
232
255
|
export function useFragno<T extends Record<string, unknown>>(
|
|
@@ -249,9 +272,11 @@ export function useFragno<T extends Record<string, unknown>>(
|
|
|
249
272
|
infer TQueryParameters
|
|
250
273
|
>
|
|
251
274
|
? FragnoSvelteMutator<M, TPath, TInputSchema, TOutputSchema, TErrorCode, TQueryParameters>
|
|
252
|
-
: T[K] extends
|
|
253
|
-
? TStoreObj
|
|
254
|
-
: T[K]
|
|
275
|
+
: T[K] extends FragnoStoreObjectData<infer TStoreObj>
|
|
276
|
+
? FragnoSvelteStore<TStoreObj, []>
|
|
277
|
+
: T[K] extends FragnoStoreFactoryData<infer TStoreObj, infer TStoreArgs>
|
|
278
|
+
? FragnoSvelteStore<TStoreObj, TStoreArgs>
|
|
279
|
+
: T[K];
|
|
255
280
|
} {
|
|
256
281
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
257
282
|
const result = {} as any;
|
|
@@ -1,14 +1,16 @@
|
|
|
1
1
|
import { afterEach, assert, beforeEach, describe, expect, test, vi } from "vitest";
|
|
2
|
+
|
|
3
|
+
import { atom, computed, effect } from "nanostores";
|
|
2
4
|
import { z } from "zod";
|
|
5
|
+
|
|
6
|
+
import { defineFragment } from "../api/fragment-definition-builder";
|
|
7
|
+
import { RequestOutputContext } from "../api/request-output-context";
|
|
3
8
|
import { defineRoute } from "../api/route";
|
|
4
|
-
import { buildUrl, createClientBuilder, getCacheKey, isGetHook, isMutatorHook } from "./client";
|
|
5
|
-
import { useFragno } from "./vanilla";
|
|
6
9
|
import { createAsyncIteratorFromCallback, waitForAsyncIterator } from "../util/async";
|
|
10
|
+
import { buildUrl, createClientBuilder, getCacheKey, isGetHook, isMutatorHook } from "./client";
|
|
7
11
|
import type { FragnoPublicClientConfig } from "./client";
|
|
8
|
-
import { atom, computed, effect } from "nanostores";
|
|
9
|
-
import { defineFragment } from "../api/fragment-definition-builder";
|
|
10
|
-
import { RequestOutputContext } from "../api/request-output-context";
|
|
11
12
|
import { FragnoClientUnknownApiError } from "./client-error";
|
|
13
|
+
import { useFragno } from "./vanilla";
|
|
12
14
|
|
|
13
15
|
// Mock fetch globally
|
|
14
16
|
global.fetch = vi.fn();
|
|
@@ -1325,6 +1327,32 @@ describe("createMutator", () => {
|
|
|
1325
1327
|
expect(result).toBeUndefined();
|
|
1326
1328
|
});
|
|
1327
1329
|
|
|
1330
|
+
test("body is optional when inputSchema allows undefined", async () => {
|
|
1331
|
+
const testFragment = defineFragment("test-fragment").build();
|
|
1332
|
+
const testRoutes = [
|
|
1333
|
+
defineRoute({
|
|
1334
|
+
method: "POST",
|
|
1335
|
+
path: "/sign-out",
|
|
1336
|
+
inputSchema: z.object({ sessionId: z.string().optional() }).optional(),
|
|
1337
|
+
outputSchema: z.object({ success: z.boolean() }),
|
|
1338
|
+
handler: async (_ctx, { empty }) => empty(),
|
|
1339
|
+
}),
|
|
1340
|
+
] as const;
|
|
1341
|
+
|
|
1342
|
+
vi.mocked(global.fetch).mockImplementation(async () => {
|
|
1343
|
+
return new Response(null, { status: 204 });
|
|
1344
|
+
});
|
|
1345
|
+
|
|
1346
|
+
const cb = createClientBuilder(testFragment, clientConfig, testRoutes);
|
|
1347
|
+
const signOut = cb.createMutator("POST", "/sign-out");
|
|
1348
|
+
|
|
1349
|
+
const result = await signOut.mutateQuery({});
|
|
1350
|
+
expect(result).toBeUndefined();
|
|
1351
|
+
|
|
1352
|
+
const storeResult = await signOut.mutatorStore.mutate({});
|
|
1353
|
+
expect(storeResult).toBeUndefined();
|
|
1354
|
+
});
|
|
1355
|
+
|
|
1328
1356
|
test("should send octet-stream body without wrapping", async () => {
|
|
1329
1357
|
const testFragment = defineFragment("test-fragment").build();
|
|
1330
1358
|
const testRoutes = [
|
|
@@ -2208,7 +2236,7 @@ describe("Custom Fetcher Configuration", () => {
|
|
|
2208
2236
|
expect(defaultOptions).toBeUndefined();
|
|
2209
2237
|
});
|
|
2210
2238
|
|
|
2211
|
-
test("getFetcher returns default fetch and options", () => {
|
|
2239
|
+
test("getFetcher returns a bound default fetch and options", async () => {
|
|
2212
2240
|
const client = createClientBuilder(
|
|
2213
2241
|
testFragment,
|
|
2214
2242
|
{
|
|
@@ -2218,9 +2246,20 @@ describe("Custom Fetcher Configuration", () => {
|
|
|
2218
2246
|
testRoutes,
|
|
2219
2247
|
);
|
|
2220
2248
|
|
|
2221
|
-
const
|
|
2222
|
-
|
|
2223
|
-
|
|
2224
|
-
|
|
2249
|
+
const originalFetch = globalThis.fetch;
|
|
2250
|
+
const fetchSpy = vi.fn<typeof fetch>().mockResolvedValue(new Response(null, { status: 204 }));
|
|
2251
|
+
globalThis.fetch = fetchSpy;
|
|
2252
|
+
|
|
2253
|
+
try {
|
|
2254
|
+
const { fetcher, defaultOptions } = client.getFetcher();
|
|
2255
|
+
expect(fetcher).not.toBe(globalThis.fetch);
|
|
2256
|
+
expect(defaultOptions).toBeDefined();
|
|
2257
|
+
expect(defaultOptions?.credentials).toBe("include");
|
|
2258
|
+
|
|
2259
|
+
await fetcher("https://example.com");
|
|
2260
|
+
expect(fetchSpy).toHaveBeenCalledWith("https://example.com");
|
|
2261
|
+
} finally {
|
|
2262
|
+
globalThis.fetch = originalFetch;
|
|
2263
|
+
}
|
|
2225
2264
|
});
|
|
2226
2265
|
});
|