@effect-app/vue 4.0.0-beta.177 → 4.0.0-beta.179
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/CHANGELOG.md +36 -0
- package/dist/makeClient.d.ts +13 -3
- package/dist/makeClient.d.ts.map +1 -1
- package/dist/makeClient.js +69 -28
- package/dist/mutate.d.ts +28 -2
- package/dist/mutate.d.ts.map +1 -1
- package/dist/mutate.js +98 -7
- package/examples/streamMutation.ts +83 -0
- package/package.json +2 -2
- package/src/makeClient.ts +87 -2
- package/src/mutate.ts +151 -7
- package/test/dist/streamFinal.test.d.ts.map +1 -0
- package/test/dist/stubs.d.ts +362 -39
- package/test/dist/stubs.d.ts.map +1 -1
- package/test/dist/stubs.js +31 -2
- package/test/makeClient.test.ts +24 -0
- package/test/streamFinal.test.ts +110 -0
- package/test/stubs.ts +30 -1
- package/tsconfig.examples.json +20 -0
- package/tsconfig.json.bak +3 -0
package/dist/mutate.js
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
2
2
|
import { matchQuery } from "@tanstack/query-core";
|
|
3
3
|
import { useQueryClient } from "@tanstack/vue-query";
|
|
4
|
-
import { Effect, Option } from "effect-app";
|
|
4
|
+
import { Effect, Exit, Option } from "effect-app";
|
|
5
5
|
import { InvalidationKeysFromServer, makeInvalidationKeysService, makeQueryKey } from "effect-app/client";
|
|
6
6
|
import { tuple } from "effect-app/Function";
|
|
7
7
|
import * as Ref from "effect/Ref";
|
|
8
|
+
import * as Stream from "effect/Stream";
|
|
8
9
|
import * as AsyncResult from "effect/unstable/reactivity/AsyncResult";
|
|
9
10
|
import { computed, shallowRef } from "vue";
|
|
10
11
|
export const getQueryKey = (h) => {
|
|
@@ -63,12 +64,44 @@ export const asResult = (handler) => {
|
|
|
63
64
|
.pipe(Effect.andThen(Effect.suspend(() => handler(...args).pipe(Effect.exit, Effect.tap((exit) => Effect.sync(() => (state.value = AsyncResult.fromExit(exit))))))));
|
|
64
65
|
return tuple(computed(() => state.value), act);
|
|
65
66
|
};
|
|
66
|
-
|
|
67
|
-
|
|
67
|
+
/**
|
|
68
|
+
* Like `asResult`, but for streams. The ref is updated with each emitted value
|
|
69
|
+
* (keeping `waiting: true`) and is finalised (with `waiting: false`) once the
|
|
70
|
+
* stream terminates successfully. Errors are surfaced as `AsyncResult.failure`.
|
|
71
|
+
*/
|
|
72
|
+
export const asStreamResult = (handler) => {
|
|
73
|
+
const state = shallowRef(AsyncResult.initial());
|
|
74
|
+
const runStream = (stream) => Effect
|
|
75
|
+
.sync(() => {
|
|
76
|
+
state.value = AsyncResult.initial(true);
|
|
77
|
+
})
|
|
78
|
+
.pipe(Effect.andThen(stream.pipe(Stream.runForEach((value) => Effect.sync(() => {
|
|
79
|
+
state.value = AsyncResult.success(value, { waiting: true });
|
|
80
|
+
})), Effect.exit, Effect.flatMap((exit) => Effect.sync(() => {
|
|
81
|
+
if (exit._tag === "Success") {
|
|
82
|
+
const current = state.value;
|
|
83
|
+
if (AsyncResult.isSuccess(current)) {
|
|
84
|
+
state.value = AsyncResult.success(current.value, { waiting: false });
|
|
85
|
+
}
|
|
86
|
+
else {
|
|
87
|
+
state.value = AsyncResult.initial(false);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
else {
|
|
91
|
+
state.value = AsyncResult.failure(exit.cause);
|
|
92
|
+
}
|
|
93
|
+
})))));
|
|
94
|
+
const act = Stream.isStream(handler)
|
|
95
|
+
? runStream(handler)
|
|
96
|
+
: (...args) => runStream(handler(...args));
|
|
97
|
+
return tuple(computed(() => state.value), act);
|
|
98
|
+
};
|
|
99
|
+
const buildInvalidateCache = (queryClient, self, queryInvalidation) => {
|
|
100
|
+
const invalidateQueriesFn = (filters, options) => Effect.currentSpan.pipe(Effect.orElseSucceed(() => null), Effect.flatMap((span) => Effect.promise(() => queryClient.invalidateQueries(filters, { ...options, updateMeta: { span } }))));
|
|
68
101
|
const getClientInvalidationTargets = (input, output) => {
|
|
69
102
|
const queryKey = getQueryKey(self);
|
|
70
|
-
if (
|
|
71
|
-
return
|
|
103
|
+
if (queryInvalidation) {
|
|
104
|
+
return queryInvalidation(queryKey, self.id, input, output).map((_) => ({
|
|
72
105
|
filters: _.filters,
|
|
73
106
|
options: _.options
|
|
74
107
|
}));
|
|
@@ -99,7 +132,7 @@ export const invalidateQueries = (queryClient, self, options) => {
|
|
|
99
132
|
}
|
|
100
133
|
}
|
|
101
134
|
return Effect
|
|
102
|
-
.andThen(Effect.annotateCurrentSpan({ clientTargets, serverKeys }), Effect.forEach(groups.values(), ({ options, refetchType, targets }) =>
|
|
135
|
+
.andThen(Effect.annotateCurrentSpan({ clientTargets, serverKeys }), Effect.forEach(groups.values(), ({ options, refetchType, targets }) => invalidateQueriesFn({
|
|
103
136
|
...(refetchType !== undefined ? { refetchType } : {}),
|
|
104
137
|
predicate: (query) => targets.some((t) => t.filters ? matchQuery(t.filters, query) : true)
|
|
105
138
|
}, options), { discard: true, concurrency: "inherit" }))
|
|
@@ -108,6 +141,10 @@ export const invalidateQueries = (queryClient, self, options) => {
|
|
|
108
141
|
// TODO: should we do this in general on any mutation, regardless of invalidation?
|
|
109
142
|
Effect.sleep(0)), Effect.withSpan("client.query.invalidation", {}, { captureStackTrace: false }));
|
|
110
143
|
});
|
|
144
|
+
return invalidateCache;
|
|
145
|
+
};
|
|
146
|
+
export const invalidateQueries = (queryClient, self, options) => {
|
|
147
|
+
const invalidateCache = buildInvalidateCache(queryClient, self, options?.queryInvalidation);
|
|
111
148
|
const select = options?.select;
|
|
112
149
|
const handle = (eff, input) => Effect.gen(function* () {
|
|
113
150
|
const keysRef = yield* Ref.make([]);
|
|
@@ -148,4 +185,58 @@ export const useMakeMutation = () => {
|
|
|
148
185
|
};
|
|
149
186
|
return useMutation;
|
|
150
187
|
};
|
|
151
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibXV0YXRlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL211dGF0ZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSx1REFBdUQ7QUFDdkQsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLHNCQUFzQixDQUFBO0FBQ2pELE9BQU8sRUFBeUUsY0FBYyxFQUFFLE1BQU0scUJBQXFCLENBQUE7QUFDM0gsT0FBTyxFQUFjLE1BQU0sRUFBYSxNQUFNLEVBQUUsTUFBTSxZQUFZLENBQUE7QUFDbEUsT0FBTyxFQUF3QiwwQkFBMEIsRUFBRSwyQkFBMkIsRUFBRSxZQUFZLEVBQVksTUFBTSxtQkFBbUIsQ0FBQTtBQUV6SSxPQUFPLEVBQUUsS0FBSyxFQUFFLE1BQU0scUJBQXFCLENBQUE7QUFDM0MsT0FBTyxLQUFLLEdBQUcsTUFBTSxZQUFZLENBQUE7QUFDakMsT0FBTyxLQUFLLFdBQVcsTUFBTSx3Q0FBd0MsQ0FBQTtBQUNyRSxPQUFPLEVBQUUsUUFBUSxFQUFvQixVQUFVLEVBQUUsTUFBTSxLQUFLLENBQUE7QUFFNUQsTUFBTSxDQUFDLE1BQU0sV0FBVyxHQUFHLENBQUMsQ0FBNkMsRUFBRSxFQUFFO0lBQzNFLE1BQU0sR0FBRyxHQUFHLFlBQVksQ0FBQyxDQUFDLENBQUMsQ0FBQTtJQUMzQixNQUFNLEVBQUUsR0FBRyxHQUFHLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUMsVUFBVSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUE7SUFDL0MsNkZBQTZGO0lBQzdGLG9GQUFvRjtJQUNwRixNQUFNLENBQUMsR0FBRyxFQUFFLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsTUFBTSxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLEtBQUssQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLE1BQU0sR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMs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
|
|
188
|
+
/**
|
|
189
|
+
* Like `makeMutation`, but for stream-type request handlers.
|
|
190
|
+
* Returns a `[ref, execute]` tuple where `ref` is a reactive `AsyncResult` updated per
|
|
191
|
+
* stream element. Queries are invalidated once when the stream finishes, regardless of
|
|
192
|
+
* success or failure.
|
|
193
|
+
*
|
|
194
|
+
* When the request declares a `final` schema, `execute` resolves with the last emitted value
|
|
195
|
+
* typed as `Final`; otherwise it resolves with `void`.
|
|
196
|
+
*
|
|
197
|
+
* Must be called inside a Vue setup context (uses `useQueryClient` internally).
|
|
198
|
+
*/
|
|
199
|
+
export const makeStreamMutation = () => {
|
|
200
|
+
const queryClient = useQueryClient();
|
|
201
|
+
return (self, mergedInvalidation) => {
|
|
202
|
+
const state = shallowRef(AsyncResult.initial());
|
|
203
|
+
const runStream = (stream, input) => {
|
|
204
|
+
const invCache = buildInvalidateCache(queryClient, self, mergedInvalidation);
|
|
205
|
+
return Effect
|
|
206
|
+
.sync(() => {
|
|
207
|
+
state.value = AsyncResult.initial(true);
|
|
208
|
+
})
|
|
209
|
+
.pipe(Effect.andThen(stream.pipe(Stream.runForEach((value) => Effect.sync(() => {
|
|
210
|
+
state.value = AsyncResult.success(value, { waiting: true });
|
|
211
|
+
})), Effect.exit, Effect.tap((exit) => Effect.sync(() => {
|
|
212
|
+
if (exit._tag === "Success") {
|
|
213
|
+
const current = state.value;
|
|
214
|
+
if (AsyncResult.isSuccess(current)) {
|
|
215
|
+
state.value = AsyncResult.success(current.value, { waiting: false });
|
|
216
|
+
}
|
|
217
|
+
else {
|
|
218
|
+
state.value = AsyncResult.initial(false);
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
else {
|
|
222
|
+
state.value = AsyncResult.failure(exit.cause);
|
|
223
|
+
}
|
|
224
|
+
})), Effect.flatMap((exit) => {
|
|
225
|
+
const current = state.value;
|
|
226
|
+
const lastValue = AsyncResult.isSuccess(current) ? current.value : undefined;
|
|
227
|
+
const invExit = exit._tag === "Success" ? Exit.succeed(lastValue) : exit;
|
|
228
|
+
// Note: when the stream fails, `lastValue` is undefined. The failure is
|
|
229
|
+
// communicated via the reactive `state` ref (AsyncResult.failure). The
|
|
230
|
+
// execute effect always resolves successfully; callers should inspect the
|
|
231
|
+
// ref to distinguish success from failure.
|
|
232
|
+
return invCache(input, invExit, []).pipe(Effect.as(lastValue));
|
|
233
|
+
}))));
|
|
234
|
+
};
|
|
235
|
+
const handler = self.handler;
|
|
236
|
+
const act = Stream.isStream(handler)
|
|
237
|
+
? runStream(handler)
|
|
238
|
+
: (i) => runStream(handler(i), i);
|
|
239
|
+
return tuple(computed(() => state.value), act);
|
|
240
|
+
};
|
|
241
|
+
};
|
|
242
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibXV0YXRlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL211dGF0ZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSx1REFBdUQ7QUFDdkQsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLHNCQUFzQixDQUFBO0FBQ2pELE9BQU8sRUFBeUUsY0FBYyxFQUFFLE1BQU0scUJBQXFCLENBQUE7QUFDM0gsT0FBTyxFQUFjLE1BQU0sRUFBRSxJQUFJLEVBQUUsTUFBTSxFQUFFLE1BQU0sWUFBWSxDQUFBO0FBQzdELE9BQU8sRUFBd0IsMEJBQTBCLEVBQUUsMkJBQTJCLEVBQUUsWUFBWSxFQUFZLE1BQU0sbUJBQW1CLENBQUE7QUFFekksT0FBTyxFQUFFLEtBQUssRUFBRSxNQUFNLHFCQUFxQixDQUFBO0FBQzNDLE9BQU8sS0FBSyxHQUFHLE1BQU0sWUFBWSxDQUFBO0FBQ2pDLE9BQU8sS0FBSyxNQUFNLE1BQU0sZUFBZSxDQUFBO0FBQ3ZDLE9BQU8sS0FBSyxXQUFXLE1BQU0sd0NBQXdDLENBQUE7QUFDckUsT0FBTyxFQUFFLFFBQVEsRUFBb0IsVUFBVSxFQUFFLE1BQU0sS0FBSyxDQUFBO0FBRTVELE1BQU0sQ0FBQyxNQUFNLFdBQVcsR0FBRyxDQUFDLENBQTZDLEVBQUUsRUFBRTtJQUMzRSxNQUFNLEdBQUcsR0FBRyxZQUFZLENBQUMsQ0FBQyxDQUFDLENBQUE7SUFDM0IsTUFBTSxFQUFFLEdBQUcsR0FBRyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFBO0lBQy9DLDZGQUE2RjtJQUM3RixvRkFBb0Y7SUFDcEYsTUFBTSxDQUFDLEdBQUcsRUFBRSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLE1BQU0sR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxLQUFLLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxNQUFN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
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Example: stream-based mutation for a long-running operation.
|
|
3
|
+
*
|
|
4
|
+
* The server streams a tagged union of progress updates and a final result.
|
|
5
|
+
* The Vue ref is updated for every emitted value; `AsyncResult` stays in the
|
|
6
|
+
* `waiting` state until the stream ends.
|
|
7
|
+
*
|
|
8
|
+
* When using `makeClient` / `clientFor`, stream-type requests are exposed as
|
|
9
|
+
* `mutateStream` on the client object (and as `XxxStream` in `.helpers`).
|
|
10
|
+
* The example below shows both the low-level `asStreamResult` API and how the
|
|
11
|
+
* same functionality appears on the generated client.
|
|
12
|
+
*/
|
|
13
|
+
import { Effect, S, Stream } from "effect-app"
|
|
14
|
+
import { asStreamResult } from "../src/mutate.js"
|
|
15
|
+
|
|
16
|
+
// ---------------------------------------------------------------------------
|
|
17
|
+
// Domain model
|
|
18
|
+
// ---------------------------------------------------------------------------
|
|
19
|
+
|
|
20
|
+
/** Intermediate progress report, e.g. "5 of 400 items processed". */
|
|
21
|
+
export class OperationProgress extends S.TaggedClass<OperationProgress>()("OperationProgress", {
|
|
22
|
+
completed: S.NonNegativeInt,
|
|
23
|
+
total: S.NonNegativeInt
|
|
24
|
+
}) {}
|
|
25
|
+
|
|
26
|
+
/** The final result produced once the operation is complete. */
|
|
27
|
+
export class ExportComplete extends S.TaggedClass<ExportComplete>()("ExportComplete", {
|
|
28
|
+
fileUrl: S.NonEmptyString
|
|
29
|
+
}) {}
|
|
30
|
+
|
|
31
|
+
/** Tagged union emitted by the stream. */
|
|
32
|
+
export type ExportEvent = OperationProgress | ExportComplete
|
|
33
|
+
|
|
34
|
+
// ---------------------------------------------------------------------------
|
|
35
|
+
// Simulated stream (replace with a real RPC / SSE stream in production)
|
|
36
|
+
// ---------------------------------------------------------------------------
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Produces `total` progress updates followed by a single `ExportComplete`.
|
|
40
|
+
* Each step is separated by a 50 ms delay to simulate real async work.
|
|
41
|
+
*/
|
|
42
|
+
const makeExportStream = (total: S.NonNegativeInt): Stream.Stream<ExportEvent> =>
|
|
43
|
+
Stream.concat(
|
|
44
|
+
Stream.range(1, total).pipe(
|
|
45
|
+
Stream.map((completed) => new OperationProgress({ completed: S.NonNegativeInt(completed), total })),
|
|
46
|
+
Stream.tap(() => Effect.sleep("50 millis"))
|
|
47
|
+
),
|
|
48
|
+
Stream.make(new ExportComplete({ fileUrl: S.NonEmptyString("https://example.com/export.csv") }))
|
|
49
|
+
)
|
|
50
|
+
|
|
51
|
+
// ---------------------------------------------------------------------------
|
|
52
|
+
// Option A: low-level `asStreamResult` (call inside a `setup()` function)
|
|
53
|
+
// ---------------------------------------------------------------------------
|
|
54
|
+
|
|
55
|
+
export const useExportMutation = () => {
|
|
56
|
+
/**
|
|
57
|
+
* `result` - reactive ref, always reflects the latest stream event.
|
|
58
|
+
* `AsyncResult` tag:
|
|
59
|
+
* - Initial (waiting=true) - operation in progress
|
|
60
|
+
* - Success (waiting=true) - progress update received, still running
|
|
61
|
+
* - Success (waiting=false) - final result, operation complete
|
|
62
|
+
* - Failure - operation failed
|
|
63
|
+
*
|
|
64
|
+
* `execute` - call with the desired `total` to kick off the stream.
|
|
65
|
+
*/
|
|
66
|
+
const [result, execute] = asStreamResult((total: S.NonNegativeInt) => makeExportStream(total))
|
|
67
|
+
|
|
68
|
+
return { result, execute }
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// ---------------------------------------------------------------------------
|
|
72
|
+
// Option B: via `makeClient` / `clientFor` (stream requests -> `mutateStream`)
|
|
73
|
+
//
|
|
74
|
+
// When a request schema has `type: "stream"`, `clientFor` exposes:
|
|
75
|
+
//
|
|
76
|
+
// client.exportData.mutateStream
|
|
77
|
+
// // -> [ComputedRef<AsyncResult<ExportEvent, E>>, (input: I) => Effect<void, never, R>]
|
|
78
|
+
//
|
|
79
|
+
// which is equivalent to calling `asStreamResult(client.exportData.handler)`.
|
|
80
|
+
//
|
|
81
|
+
// The `.helpers` object also includes `exportDataStream` (the camelCase key
|
|
82
|
+
// plus "Stream" suffix) with the same [ref, execute] tuple.
|
|
83
|
+
// ---------------------------------------------------------------------------
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@effect-app/vue",
|
|
3
|
-
"version": "4.0.0-beta.
|
|
3
|
+
"version": "4.0.0-beta.179",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"homepage": "https://github.com/effect-ts-app/libs/tree/main/packages/vue",
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
"@vueuse/core": "^14.2.1",
|
|
12
12
|
"change-case": "^5.4.4",
|
|
13
13
|
"query-string": "^9.3.1",
|
|
14
|
-
"effect-app": "4.0.0-beta.
|
|
14
|
+
"effect-app": "4.0.0-beta.179"
|
|
15
15
|
},
|
|
16
16
|
"peerDependencies": {
|
|
17
17
|
"@effect/atom-vue": "^4.0.0-beta.59",
|
package/src/makeClient.ts
CHANGED
|
@@ -3,7 +3,7 @@ import { type InvalidateOptions, type InvalidateQueryFilters, isCancelledError,
|
|
|
3
3
|
import { camelCase } from "change-case"
|
|
4
4
|
import { type Context, Effect, Exit, Hash, type Layer, type ManagedRuntime, S, Struct } from "effect-app"
|
|
5
5
|
import { type ApiClientFactory, type Req } from "effect-app/client"
|
|
6
|
-
import type { ExtractModuleName, RequestHandler, RequestHandlers, RequestHandlerWithInput, RequestInputFromMake, RequestsAny } from "effect-app/client/clientFor"
|
|
6
|
+
import type { ExtractModuleName, RequestHandler, RequestHandlers, RequestHandlerWithInput, RequestInputFromMake, RequestsAny, RequestStreamHandler, RequestStreamHandlerWithInput } from "effect-app/client/clientFor"
|
|
7
7
|
import type { InvalidationCallback } from "effect-app/client/makeClient"
|
|
8
8
|
import type * as ExitResult from "effect/Exit"
|
|
9
9
|
import { type Fiber } from "effect/Fiber"
|
|
@@ -12,7 +12,7 @@ import { type ComputedRef, onBeforeUnmount, ref, type WatchSource } from "vue"
|
|
|
12
12
|
import { type Commander, CommanderStatic } from "./commander.js"
|
|
13
13
|
import { type I18n } from "./intl.js"
|
|
14
14
|
import { type CommanderResolved, makeUseCommand } from "./makeUseCommand.js"
|
|
15
|
-
import { makeMutation, type MutationOptionsBase, useMakeMutation } from "./mutate.js"
|
|
15
|
+
import { makeMutation, makeStreamMutation, type MutationOptionsBase, useMakeMutation } from "./mutate.js"
|
|
16
16
|
import { type CustomUndefinedInitialQueryOptions, makeQuery } from "./query.js"
|
|
17
17
|
import { makeRunPromise } from "./runtime.js"
|
|
18
18
|
import { type Toast } from "./toast.js"
|
|
@@ -125,6 +125,13 @@ type CommandHandler<Req> = Req extends
|
|
|
125
125
|
? Request["type"] extends "command" ? RequestHandler<A, E, R, Request, Id> : never
|
|
126
126
|
: never
|
|
127
127
|
|
|
128
|
+
type StreamHandler<Req> = Req extends
|
|
129
|
+
RequestStreamHandlerWithInput<infer I, infer A, infer E, infer R, infer Request, infer Id, infer Final>
|
|
130
|
+
? Request["type"] extends "stream" ? RequestStreamHandlerWithInput<I, A, E, R, Request, Id, Final> : never
|
|
131
|
+
: Req extends RequestStreamHandler<infer A, infer E, infer R, infer Request, infer Id, infer Final>
|
|
132
|
+
? Request["type"] extends "stream" ? RequestStreamHandler<A, E, R, Request, Id, Final> : never
|
|
133
|
+
: never
|
|
134
|
+
|
|
128
135
|
export interface MutationExtensions<RT, Id extends string, I, A, E, R> {
|
|
129
136
|
/** Defines a Command based on this mutation, taking the `id` of the mutation as the `id` of the Command.
|
|
130
137
|
* The Mutation function will be taken as the first member of the Command, the Command required input will be the Mutation input.
|
|
@@ -217,6 +224,19 @@ export type MutationWithExtensions<RT, Req> = Req extends
|
|
|
217
224
|
? MutationExt<RT, Id, A, E, R, S.Codec.Encoded<Request["success"]>>
|
|
218
225
|
: never
|
|
219
226
|
|
|
227
|
+
/**
|
|
228
|
+
* The `mutateStream` tuple for a stream-type request handler:
|
|
229
|
+
* `[resultRef, execute]` where `execute` updates the ref live with each emitted value.
|
|
230
|
+
* When the request declares a `final` schema, `execute` resolves with the last emitted value
|
|
231
|
+
* typed as `Final`; otherwise it resolves with `void`.
|
|
232
|
+
*/
|
|
233
|
+
export type StreamMutationWithExtensions<Req> = Req extends
|
|
234
|
+
RequestStreamHandlerWithInput<infer I, infer A, infer E, infer R, infer _Request, infer _Id, infer Final>
|
|
235
|
+
? readonly [ComputedRef<AsyncResult.AsyncResult<A, E>>, (input: I) => Effect.Effect<Final, never, R>]
|
|
236
|
+
: Req extends RequestStreamHandler<infer A, infer E, infer R, infer _Request, infer _Id, infer Final>
|
|
237
|
+
? readonly [ComputedRef<AsyncResult.AsyncResult<A, E>>, Effect.Effect<Final, never, R>]
|
|
238
|
+
: never
|
|
239
|
+
|
|
220
240
|
// we don't really care about the RT, as we are in charge of ensuring runtime safety anyway
|
|
221
241
|
// eslint-disable-next-line unused-imports/no-unused-vars
|
|
222
242
|
declare const useQuery_: QueryImpl<any>["useQuery"]
|
|
@@ -571,6 +591,9 @@ export const makeClient = <RT_, RTHooks>(
|
|
|
571
591
|
let m: ReturnType<typeof useMutationInt>
|
|
572
592
|
const useMutation = () => m ??= useMutationInt()
|
|
573
593
|
|
|
594
|
+
let sm: ReturnType<typeof makeStreamMutation>
|
|
595
|
+
const useStreamMutation = () => sm ??= makeStreamMutation()
|
|
596
|
+
|
|
574
597
|
const query = new QueryImpl(getBaseRt)
|
|
575
598
|
const useQuery = query.useQuery
|
|
576
599
|
const useSuspenseQuery = query.useSuspenseQuery
|
|
@@ -739,6 +762,43 @@ export const makeClient = <RT_, RTHooks>(
|
|
|
739
762
|
return mutations
|
|
740
763
|
}
|
|
741
764
|
|
|
765
|
+
const mapStreamMutation = <M extends RequestsAny>(
|
|
766
|
+
client: ClientFrom<M>,
|
|
767
|
+
queryInvalidation?: (client: ClientFrom<M>) => QueryInvalidation<M>,
|
|
768
|
+
invalidationResources?: InvalidationResourcesFor<M>
|
|
769
|
+
) => {
|
|
770
|
+
const streamMutation = useStreamMutation()
|
|
771
|
+
const invalidation = queryInvalidation?.(client)
|
|
772
|
+
const queryResources = makeQueryResources(invalidationResources)
|
|
773
|
+
const streams = Struct.keys(client).reduce(
|
|
774
|
+
(acc, key) => {
|
|
775
|
+
if (client[key].Request.type !== "stream") {
|
|
776
|
+
return acc
|
|
777
|
+
}
|
|
778
|
+
const fromRequestConfig = client[key].Request.config?.["invalidatesQueries"] as
|
|
779
|
+
| InvalidationCallback<InvalidationResourcesFor<M>>
|
|
780
|
+
| undefined
|
|
781
|
+
const fromRequest = fromRequestConfig
|
|
782
|
+
? ((defaultKey: string[], _name: string, input?: unknown, output?: unknown) =>
|
|
783
|
+
fromRequestConfig(defaultKey, queryResources as never, input as never, output as never).map((entry) => ({
|
|
784
|
+
filters: entry.filters,
|
|
785
|
+
options: entry.options
|
|
786
|
+
})))
|
|
787
|
+
: undefined
|
|
788
|
+
const mergedInvalidation = mergeInvalidation(fromRequest, invalidation?.[key])
|
|
789
|
+
;(acc as any)[camelCase(key) + "Stream"] = streamMutation(client[key] as any, mergedInvalidation)
|
|
790
|
+
return acc
|
|
791
|
+
},
|
|
792
|
+
{} as {
|
|
793
|
+
[
|
|
794
|
+
Key in keyof typeof client as StreamHandler<typeof client[Key]> extends never ? never
|
|
795
|
+
: `${ToCamel<string & Key>}Stream`
|
|
796
|
+
]: StreamMutationWithExtensions<StreamHandler<typeof client[Key]>>
|
|
797
|
+
}
|
|
798
|
+
)
|
|
799
|
+
return streams
|
|
800
|
+
}
|
|
801
|
+
|
|
742
802
|
// make available .query, .suspense and .mutate for each operation
|
|
743
803
|
// and a .helpers with all mutations and queries
|
|
744
804
|
const mapClient = <M extends RequestsAny>(
|
|
@@ -750,6 +810,7 @@ export const makeClient = <RT_, RTHooks>(
|
|
|
750
810
|
) => {
|
|
751
811
|
const Command = useCommand()
|
|
752
812
|
const mutation = useMutation()
|
|
813
|
+
const streamMutation = useStreamMutation()
|
|
753
814
|
const invalidation = queryInvalidation?.(client)
|
|
754
815
|
const queryResources = makeQueryResources(invalidationResources)
|
|
755
816
|
const extended = Struct.keys(client).reduce(
|
|
@@ -786,6 +847,27 @@ export const makeClient = <RT_, RTHooks>(
|
|
|
786
847
|
}
|
|
787
848
|
}
|
|
788
849
|
}
|
|
850
|
+
: requestType === "stream"
|
|
851
|
+
? (() => {
|
|
852
|
+
const fromRequestConfig = client[key].Request.config?.["invalidatesQueries"] as
|
|
853
|
+
| InvalidationCallback<InvalidationResourcesFor<M>>
|
|
854
|
+
| undefined
|
|
855
|
+
const fromRequest = fromRequestConfig
|
|
856
|
+
? ((defaultKey: string[], _name: string, input?: unknown, output?: unknown) =>
|
|
857
|
+
fromRequestConfig(defaultKey, queryResources as never, input as never, output as never).map((
|
|
858
|
+
entry
|
|
859
|
+
) => ({
|
|
860
|
+
filters: entry.filters,
|
|
861
|
+
options: entry.options
|
|
862
|
+
})))
|
|
863
|
+
: undefined
|
|
864
|
+
const mergedInvalidation = mergeInvalidation(fromRequest, invalidation?.[key])
|
|
865
|
+
return {
|
|
866
|
+
...client[key],
|
|
867
|
+
request: h_,
|
|
868
|
+
mutateStream: streamMutation(client[key] as any, mergedInvalidation)
|
|
869
|
+
}
|
|
870
|
+
})()
|
|
789
871
|
: {
|
|
790
872
|
mutate: ((handler: any) => {
|
|
791
873
|
const fromRequestConfig = client[key].Request.config?.["invalidatesQueries"] as
|
|
@@ -844,6 +926,8 @@ export const makeClient = <RT_, RTHooks>(
|
|
|
844
926
|
: CommandRequestWithExtensions<RT | RTHooks, CommandHandler<typeof client[Key]>>)
|
|
845
927
|
& (CommandHandler<typeof client[Key]> extends never ? {}
|
|
846
928
|
: { mutate: MutationWithExtensions<RT | RTHooks, CommandHandler<typeof client[Key]>> })
|
|
929
|
+
& (StreamHandler<typeof client[Key]> extends never ? {}
|
|
930
|
+
: { mutateStream: StreamMutationWithExtensions<StreamHandler<typeof client[Key]>> })
|
|
847
931
|
& { Input: typeof client[Key] extends RequestHandlerWithInput<infer I, any, any, any, any, any> ? I : never }
|
|
848
932
|
}
|
|
849
933
|
)
|
|
@@ -851,6 +935,7 @@ export const makeClient = <RT_, RTHooks>(
|
|
|
851
935
|
helpers: {
|
|
852
936
|
...mapRequest(client),
|
|
853
937
|
...mapMutation(client, queryInvalidation, invalidationResources),
|
|
938
|
+
...mapStreamMutation(client, queryInvalidation, invalidationResources),
|
|
854
939
|
...mapQuery(client)
|
|
855
940
|
}
|
|
856
941
|
})
|
package/src/mutate.ts
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
2
2
|
import { matchQuery } from "@tanstack/query-core"
|
|
3
3
|
import { type InvalidateOptions, type InvalidateQueryFilters, type QueryClient, useQueryClient } from "@tanstack/vue-query"
|
|
4
|
-
import { type Cause, Effect,
|
|
4
|
+
import { type Cause, Effect, Exit, Option } from "effect-app"
|
|
5
5
|
import { type InvalidationKey, InvalidationKeysFromServer, makeInvalidationKeysService, makeQueryKey, type Req } from "effect-app/client"
|
|
6
6
|
import type { ClientForOptions, RequestHandler, RequestHandlerWithInput } from "effect-app/client/clientFor"
|
|
7
7
|
import { tuple } from "effect-app/Function"
|
|
8
8
|
import * as Ref from "effect/Ref"
|
|
9
|
+
import * as Stream from "effect/Stream"
|
|
9
10
|
import * as AsyncResult from "effect/unstable/reactivity/AsyncResult"
|
|
10
11
|
import { computed, type ComputedRef, shallowRef } from "vue"
|
|
11
12
|
|
|
@@ -137,17 +138,73 @@ export const asResult: {
|
|
|
137
138
|
return tuple(computed(() => state.value), act) as any
|
|
138
139
|
}
|
|
139
140
|
|
|
140
|
-
|
|
141
|
+
/**
|
|
142
|
+
* Like `asResult`, but for streams. The ref is updated with each emitted value
|
|
143
|
+
* (keeping `waiting: true`) and is finalised (with `waiting: false`) once the
|
|
144
|
+
* stream terminates successfully. Errors are surfaced as `AsyncResult.failure`.
|
|
145
|
+
*/
|
|
146
|
+
export const asStreamResult: {
|
|
147
|
+
<A, E, R>(
|
|
148
|
+
handler: Stream.Stream<A, E, R>
|
|
149
|
+
): readonly [ComputedRef<AsyncResult.AsyncResult<A, E>>, Effect.Effect<void, never, R>]
|
|
150
|
+
<Args extends readonly any[], A, E, R>(
|
|
151
|
+
handler: (...args: Args) => Stream.Stream<A, E, R>
|
|
152
|
+
): readonly [ComputedRef<AsyncResult.AsyncResult<A, E>>, (...args: Args) => Effect.Effect<void, never, R>]
|
|
153
|
+
} = <Args extends readonly any[], A, E, R>(
|
|
154
|
+
handler: Stream.Stream<A, E, R> | ((...args: Args) => Stream.Stream<A, E, R>)
|
|
155
|
+
) => {
|
|
156
|
+
const state = shallowRef<AsyncResult.AsyncResult<A, E>>(AsyncResult.initial())
|
|
157
|
+
|
|
158
|
+
const runStream = (stream: Stream.Stream<A, E, R>): Effect.Effect<void, never, R> =>
|
|
159
|
+
Effect
|
|
160
|
+
.sync(() => {
|
|
161
|
+
state.value = AsyncResult.initial(true)
|
|
162
|
+
})
|
|
163
|
+
.pipe(
|
|
164
|
+
Effect.andThen(
|
|
165
|
+
stream.pipe(
|
|
166
|
+
Stream.runForEach((value) =>
|
|
167
|
+
Effect.sync(() => {
|
|
168
|
+
state.value = AsyncResult.success(value, { waiting: true })
|
|
169
|
+
})
|
|
170
|
+
),
|
|
171
|
+
Effect.exit,
|
|
172
|
+
Effect.flatMap((exit) =>
|
|
173
|
+
Effect.sync(() => {
|
|
174
|
+
if (exit._tag === "Success") {
|
|
175
|
+
const current = state.value
|
|
176
|
+
if (AsyncResult.isSuccess(current)) {
|
|
177
|
+
state.value = AsyncResult.success(current.value, { waiting: false })
|
|
178
|
+
} else {
|
|
179
|
+
state.value = AsyncResult.initial(false)
|
|
180
|
+
}
|
|
181
|
+
} else {
|
|
182
|
+
state.value = AsyncResult.failure(exit.cause)
|
|
183
|
+
}
|
|
184
|
+
})
|
|
185
|
+
)
|
|
186
|
+
)
|
|
187
|
+
)
|
|
188
|
+
)
|
|
189
|
+
|
|
190
|
+
const act = Stream.isStream(handler)
|
|
191
|
+
? runStream(handler)
|
|
192
|
+
: (...args: Args) => runStream(handler(...args))
|
|
193
|
+
|
|
194
|
+
return tuple(computed(() => state.value), act) as any
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
const buildInvalidateCache = (
|
|
141
198
|
queryClient: QueryClient,
|
|
142
199
|
self: { id: string; options?: ClientForOptions },
|
|
143
|
-
|
|
200
|
+
queryInvalidation?: MutationOptionsBase["queryInvalidation"]
|
|
144
201
|
) => {
|
|
145
202
|
type InvalidationTarget = {
|
|
146
203
|
readonly filters: InvalidateQueryFilters | undefined
|
|
147
204
|
readonly options: InvalidateOptions | undefined
|
|
148
205
|
}
|
|
149
206
|
|
|
150
|
-
const
|
|
207
|
+
const invalidateQueriesFn = (
|
|
151
208
|
filters?: InvalidateQueryFilters,
|
|
152
209
|
options?: InvalidateOptions
|
|
153
210
|
) =>
|
|
@@ -164,8 +221,8 @@ export const invalidateQueries = (
|
|
|
164
221
|
): ReadonlyArray<InvalidationTarget> => {
|
|
165
222
|
const queryKey = getQueryKey(self)
|
|
166
223
|
|
|
167
|
-
if (
|
|
168
|
-
return
|
|
224
|
+
if (queryInvalidation) {
|
|
225
|
+
return queryInvalidation(queryKey, self.id, input, output).map((_) => ({
|
|
169
226
|
filters: _.filters,
|
|
170
227
|
options: _.options
|
|
171
228
|
}))
|
|
@@ -219,7 +276,7 @@ export const invalidateQueries = (
|
|
|
219
276
|
Effect.forEach(
|
|
220
277
|
groups.values(),
|
|
221
278
|
({ options, refetchType, targets }) =>
|
|
222
|
-
|
|
279
|
+
invalidateQueriesFn(
|
|
223
280
|
{
|
|
224
281
|
...(refetchType !== undefined ? { refetchType } : {}),
|
|
225
282
|
predicate: (query) => targets.some((t) => t.filters ? matchQuery(t.filters, query) : true)
|
|
@@ -239,6 +296,16 @@ export const invalidateQueries = (
|
|
|
239
296
|
)
|
|
240
297
|
})
|
|
241
298
|
|
|
299
|
+
return invalidateCache
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
export const invalidateQueries = (
|
|
303
|
+
queryClient: QueryClient,
|
|
304
|
+
self: { id: string; options?: ClientForOptions },
|
|
305
|
+
options?: MutationOptionsBase
|
|
306
|
+
) => {
|
|
307
|
+
const invalidateCache = buildInvalidateCache(queryClient, self, options?.queryInvalidation)
|
|
308
|
+
|
|
242
309
|
const select = options?.select
|
|
243
310
|
|
|
244
311
|
const handle = <A, E, R>(eff: Effect.Effect<A, E, R>, input?: unknown) =>
|
|
@@ -345,3 +412,80 @@ export const useMakeMutation = () => {
|
|
|
345
412
|
}
|
|
346
413
|
return useMutation
|
|
347
414
|
}
|
|
415
|
+
|
|
416
|
+
/**
|
|
417
|
+
* Like `makeMutation`, but for stream-type request handlers.
|
|
418
|
+
* Returns a `[ref, execute]` tuple where `ref` is a reactive `AsyncResult` updated per
|
|
419
|
+
* stream element. Queries are invalidated once when the stream finishes, regardless of
|
|
420
|
+
* success or failure.
|
|
421
|
+
*
|
|
422
|
+
* When the request declares a `final` schema, `execute` resolves with the last emitted value
|
|
423
|
+
* typed as `Final`; otherwise it resolves with `void`.
|
|
424
|
+
*
|
|
425
|
+
* Must be called inside a Vue setup context (uses `useQueryClient` internally).
|
|
426
|
+
*/
|
|
427
|
+
export const makeStreamMutation = () => {
|
|
428
|
+
const queryClient = useQueryClient()
|
|
429
|
+
|
|
430
|
+
return (
|
|
431
|
+
self: {
|
|
432
|
+
id: string
|
|
433
|
+
options?: ClientForOptions
|
|
434
|
+
handler: Stream.Stream<any, any, any> | ((i: any) => Stream.Stream<any, any, any>)
|
|
435
|
+
},
|
|
436
|
+
mergedInvalidation?: MutationOptionsBase["queryInvalidation"]
|
|
437
|
+
) => {
|
|
438
|
+
const state = shallowRef<AsyncResult.AsyncResult<any, any>>(AsyncResult.initial())
|
|
439
|
+
|
|
440
|
+
const runStream = (stream: Stream.Stream<any, any, any>, input?: unknown): Effect.Effect<any, never, any> => {
|
|
441
|
+
const invCache = buildInvalidateCache(queryClient, self, mergedInvalidation)
|
|
442
|
+
return Effect
|
|
443
|
+
.sync(() => {
|
|
444
|
+
state.value = AsyncResult.initial(true)
|
|
445
|
+
})
|
|
446
|
+
.pipe(
|
|
447
|
+
Effect.andThen(
|
|
448
|
+
stream.pipe(
|
|
449
|
+
Stream.runForEach((value) =>
|
|
450
|
+
Effect.sync(() => {
|
|
451
|
+
state.value = AsyncResult.success(value, { waiting: true })
|
|
452
|
+
})
|
|
453
|
+
),
|
|
454
|
+
Effect.exit,
|
|
455
|
+
Effect.tap((exit) =>
|
|
456
|
+
Effect.sync(() => {
|
|
457
|
+
if (exit._tag === "Success") {
|
|
458
|
+
const current = state.value
|
|
459
|
+
if (AsyncResult.isSuccess(current)) {
|
|
460
|
+
state.value = AsyncResult.success(current.value, { waiting: false })
|
|
461
|
+
} else {
|
|
462
|
+
state.value = AsyncResult.initial(false)
|
|
463
|
+
}
|
|
464
|
+
} else {
|
|
465
|
+
state.value = AsyncResult.failure(exit.cause)
|
|
466
|
+
}
|
|
467
|
+
})
|
|
468
|
+
),
|
|
469
|
+
Effect.flatMap((exit) => {
|
|
470
|
+
const current = state.value
|
|
471
|
+
const lastValue = AsyncResult.isSuccess(current) ? current.value : undefined
|
|
472
|
+
const invExit = exit._tag === "Success" ? Exit.succeed(lastValue) : exit
|
|
473
|
+
// Note: when the stream fails, `lastValue` is undefined. The failure is
|
|
474
|
+
// communicated via the reactive `state` ref (AsyncResult.failure). The
|
|
475
|
+
// execute effect always resolves successfully; callers should inspect the
|
|
476
|
+
// ref to distinguish success from failure.
|
|
477
|
+
return invCache(input, invExit, []).pipe(Effect.as(lastValue))
|
|
478
|
+
})
|
|
479
|
+
)
|
|
480
|
+
)
|
|
481
|
+
)
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
const handler = self.handler
|
|
485
|
+
const act = Stream.isStream(handler)
|
|
486
|
+
? runStream(handler)
|
|
487
|
+
: (i: any) => runStream((handler as (i: any) => Stream.Stream<any, any, any>)(i), i)
|
|
488
|
+
|
|
489
|
+
return tuple(computed(() => state.value), act)
|
|
490
|
+
}
|
|
491
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"streamFinal.test.d.ts","sourceRoot":"","sources":["../streamFinal.test.ts"],"names":[],"mappings":""}
|