@effect-app/vue 1.22.5 → 1.23.0

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/src/mutate.ts CHANGED
@@ -1,17 +1,15 @@
1
1
  /* eslint-disable @typescript-eslint/no-explicit-any */
2
2
  import { tuple } from "@effect-app/core/Function"
3
3
  import * as Result from "@effect-rx/rx/Result"
4
- import type * as HttpClient from "@effect/platform/HttpClient"
5
4
  import type { InvalidateOptions, InvalidateQueryFilters } from "@tanstack/vue-query"
6
5
  import { useQueryClient } from "@tanstack/vue-query"
7
- import { Cause, Effect, Exit, Option } from "effect-app"
8
- import type { ApiConfig } from "effect-app/client"
6
+ import { Cause, Effect, Exit, Option, Runtime } from "effect-app"
9
7
  import { dropUndefinedT } from "effect-app/utils"
10
8
  import { InterruptedException } from "effect/Cause"
11
9
  import * as Either from "effect/Either"
12
10
  import type { ComputedRef, Ref } from "vue"
13
11
  import { computed, ref, shallowRef } from "vue"
14
- import { makeQueryKey, reportRuntimeError, run } from "./internal.js"
12
+ import { makeQueryKey, reportRuntimeError } from "./internal.js"
15
13
 
16
14
  export type WatchSource<T = any> = Ref<T> | ComputedRef<T> | (() => T)
17
15
  export function make<A, E, R>(self: Effect<A, E, R>) {
@@ -53,12 +51,6 @@ export interface MutationError<E> {
53
51
 
54
52
  export type MutationResult<A, E> = MutationInitial | MutationLoading | MutationSuccess<A> | MutationError<E>
55
53
 
56
- type HandlerWithInput<I, A, E> = {
57
- handler: (i: I) => Effect<A, E, ApiConfig | HttpClient.HttpClient>
58
- name: string
59
- }
60
- type Handler<A, E> = { handler: Effect<A, E, ApiConfig | HttpClient.HttpClient>; name: string }
61
-
62
54
  export type MaybeRef<T> = Ref<T> | ComputedRef<T> | T
63
55
  type MaybeRefDeep<T> = MaybeRef<
64
56
  // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
@@ -97,125 +89,138 @@ export const getQueryKey = (name: string) => {
97
89
  // }
98
90
  */
99
91
 
100
- /**
101
- * Pass a function that returns an Effect, e.g from a client action, or an Effect
102
- * Returns a tuple with state ref and execution function which reports errors as Toast.
103
- */
104
- export const useSafeMutation: {
105
- <I, E, A>(self: HandlerWithInput<I, A, E>, options?: MutationOptions<A, I>): readonly [
106
- Readonly<Ref<MutationResult<A, E>>>,
107
- (
108
- i: I,
109
- signal?: AbortSignal
110
- ) => Promise<Either.Either<A, E>>
111
- ]
112
- <E, A>(self: Handler<A, E>, options?: MutationOptions<A>): readonly [
113
- Readonly<Ref<MutationResult<A, E>>>,
114
- (
115
- signal?: AbortSignal
116
- ) => Promise<Either.Either<A, E>>
117
- ]
118
- } = <I, E, A>(
119
- self: {
120
- handler:
121
- | HandlerWithInput<I, A, E>["handler"]
122
- | Handler<A, E>["handler"]
92
+ export const makeMutation = <R>(runtime: Runtime.Runtime<R>) => {
93
+ type HandlerWithInput<I, A, E> = {
94
+ handler: (i: I) => Effect<A, E, R>
123
95
  name: string
124
- },
125
- options?: MutationOptions<A>
126
- ) => {
127
- const queryClient = useQueryClient()
128
- const state: Ref<MutationResult<A, E>> = ref<MutationResult<A, E>>({ _tag: "Initial" }) as any
129
- const onSuccess = options?.onSuccess
130
-
131
- const invalidateQueries = (
132
- filters?: MaybeRefDeep<InvalidateQueryFilters>,
133
- options?: MaybeRefDeep<InvalidateOptions>
134
- ) => Effect.promise(() => queryClient.invalidateQueries(filters, options))
135
-
136
- function handleExit(exit: Exit.Exit<A, E>): Effect<Either.Either<A, E>, never, never> {
137
- return Effect.sync(() => {
138
- if (Exit.isSuccess(exit)) {
139
- state.value = { _tag: "Success", data: exit.value }
140
- return Either.right(exit.value)
141
- }
96
+ }
97
+ type Handler<A, E> = { handler: Effect<A, E, R>; name: string }
98
+
99
+ const runPromise = Runtime.runPromise(runtime)
100
+ /**
101
+ * Pass a function that returns an Effect, e.g from a client action, or an Effect
102
+ * Returns a tuple with state ref and execution function which reports errors as Toast.
103
+ */
104
+ const useSafeMutation: {
105
+ <I, E, A>(self: HandlerWithInput<I, A, E>, options?: MutationOptions<A, I>): readonly [
106
+ Readonly<Ref<MutationResult<A, E>>>,
107
+ (
108
+ i: I,
109
+ signal?: AbortSignal
110
+ ) => Promise<Either.Either<A, E>>
111
+ ]
112
+ <E, A>(self: Handler<A, E>, options?: MutationOptions<A>): readonly [
113
+ Readonly<Ref<MutationResult<A, E>>>,
114
+ (
115
+ signal?: AbortSignal
116
+ ) => Promise<Either.Either<A, E>>
117
+ ]
118
+ } = <I, E, A>(
119
+ self: {
120
+ handler:
121
+ | HandlerWithInput<I, A, E>["handler"]
122
+ | Handler<A, E>["handler"]
123
+ name: string
124
+ },
125
+ options?: MutationOptions<A>
126
+ ) => {
127
+ const queryClient = useQueryClient()
128
+ const state: Ref<MutationResult<A, E>> = ref<MutationResult<A, E>>({ _tag: "Initial" }) as any
129
+ const onSuccess = options?.onSuccess
130
+
131
+ const invalidateQueries = (
132
+ filters?: MaybeRefDeep<InvalidateQueryFilters>,
133
+ options?: MaybeRefDeep<InvalidateOptions>
134
+ ) => Effect.promise(() => queryClient.invalidateQueries(filters, options))
135
+
136
+ function handleExit(exit: Exit.Exit<A, E>): Effect<Either.Either<A, E>, never, never> {
137
+ return Effect.sync(() => {
138
+ if (Exit.isSuccess(exit)) {
139
+ state.value = { _tag: "Success", data: exit.value }
140
+ return Either.right(exit.value)
141
+ }
142
+
143
+ const err = Cause.failureOption(exit.cause)
144
+ if (Option.isSome(err)) {
145
+ state.value = { _tag: "Error", error: err.value }
146
+ return Either.left(err.value)
147
+ }
148
+
149
+ const died = Cause.dieOption(exit.cause)
150
+ if (Option.isSome(died)) {
151
+ throw died.value
152
+ }
153
+ const interrupted = Cause.interruptOption(exit.cause)
154
+ if (Option.isSome(interrupted)) {
155
+ throw new InterruptedException()
156
+ }
157
+ throw new Error("Invalid state")
158
+ })
159
+ }
142
160
 
143
- const err = Cause.failureOption(exit.cause)
144
- if (Option.isSome(err)) {
145
- state.value = { _tag: "Error", error: err.value }
146
- return Either.left(err.value)
161
+ const exec = (fst?: I | AbortSignal, snd?: AbortSignal) => {
162
+ let effect: Effect<A, E, R>
163
+ let signal: AbortSignal | undefined
164
+ if (Effect.isEffect(self.handler)) {
165
+ effect = self.handler as any
166
+ signal = fst as AbortSignal | undefined
167
+ } else {
168
+ effect = self.handler(fst as I)
169
+ signal = snd
147
170
  }
148
171
 
149
- const died = Cause.dieOption(exit.cause)
150
- if (Option.isSome(died)) {
151
- throw died.value
152
- }
153
- const interrupted = Cause.interruptOption(exit.cause)
154
- if (Option.isSome(interrupted)) {
155
- throw new InterruptedException()
156
- }
157
- throw new Error("Invalid state")
158
- })
159
- }
172
+ return runPromise(
173
+ Effect
174
+ .sync(() => {
175
+ state.value = { _tag: "Loading" }
176
+ })
177
+ .pipe(
178
+ Effect.andThen(effect),
179
+ Effect.tap(() =>
180
+ Effect
181
+ .suspend(() => {
182
+ const queryKey = getQueryKey(self.name)
183
+
184
+ if (options?.queryInvalidation) {
185
+ const opts = options.queryInvalidation(queryKey, self.name)
186
+ if (!opts.length) {
187
+ return Effect.void
188
+ }
189
+ return Effect
190
+ .andThen(
191
+ Effect.annotateCurrentSpan({ queryKey, opts }),
192
+ Effect.forEach(opts, (_) => invalidateQueries(_.filters, _.options), { concurrency: "inherit" })
193
+ )
194
+ .pipe(Effect.withSpan("client.query.invalidation", { captureStackTrace: false }))
195
+ }
160
196
 
161
- const exec = (fst?: I | AbortSignal, snd?: AbortSignal) => {
162
- let effect: Effect<A, E, ApiConfig | HttpClient.HttpClient>
163
- let signal: AbortSignal | undefined
164
- if (Effect.isEffect(self.handler)) {
165
- effect = self.handler as any
166
- signal = fst as AbortSignal | undefined
167
- } else {
168
- effect = self.handler(fst as I)
169
- signal = snd
170
- }
197
+ if (!queryKey) return Effect.void
171
198
 
172
- return run.value(
173
- Effect
174
- .sync(() => {
175
- state.value = { _tag: "Loading" }
176
- })
177
- .pipe(
178
- Effect.andThen(effect),
179
- Effect.tap(() =>
180
- Effect
181
- .suspend(() => {
182
- const queryKey = getQueryKey(self.name)
183
-
184
- if (options?.queryInvalidation) {
185
- const opts = options.queryInvalidation(queryKey, self.name)
186
- if (!opts.length) {
187
- return Effect.void
188
- }
189
199
  return Effect
190
200
  .andThen(
191
- Effect.annotateCurrentSpan({ queryKey, opts }),
192
- Effect.forEach(opts, (_) => invalidateQueries(_.filters, _.options), { concurrency: "inherit" })
201
+ Effect.annotateCurrentSpan({ queryKey }),
202
+ invalidateQueries({ queryKey })
193
203
  )
194
204
  .pipe(Effect.withSpan("client.query.invalidation", { captureStackTrace: false }))
195
- }
196
-
197
- if (!queryKey) return Effect.void
198
-
199
- return Effect
200
- .andThen(
201
- Effect.annotateCurrentSpan({ queryKey }),
202
- invalidateQueries({ queryKey })
203
- )
204
- .pipe(Effect.withSpan("client.query.invalidation", { captureStackTrace: false }))
205
- })
205
+ })
206
+ ),
207
+ Effect.tapDefect(reportRuntimeError),
208
+ Effect.tap((i) => onSuccess ? Effect.promise(() => onSuccess(i)) : Effect.void),
209
+ Effect.exit,
210
+ Effect.flatMap(handleExit),
211
+ Effect.withSpan(`mutation ${self.name}`, { captureStackTrace: false })
206
212
  ),
207
- Effect.tapDefect(reportRuntimeError),
208
- Effect.tap((i) => onSuccess ? Effect.promise(() => onSuccess(i)) : Effect.void),
209
- Effect.exit,
210
- Effect.flatMap(handleExit),
211
- Effect.withSpan(`mutation ${self.name}`, { captureStackTrace: false })
212
- ),
213
- dropUndefinedT({ signal })
213
+ dropUndefinedT({ signal })
214
+ )
215
+ }
216
+
217
+ return tuple(
218
+ state,
219
+ exec
214
220
  )
215
221
  }
216
-
217
- return tuple(
218
- state,
219
- exec
220
- )
222
+ return useSafeMutation
221
223
  }
224
+
225
+ // eslint-disable-next-line @typescript-eslint/no-empty-object-type
226
+ export interface MakeMutation<R> extends ReturnType<typeof makeMutation<R>> {}
package/src/query.ts CHANGED
@@ -13,11 +13,10 @@ import type {
13
13
  } from "@tanstack/vue-query"
14
14
  import { useQuery } from "@tanstack/vue-query"
15
15
  import { Cause, Effect, Option, Runtime, S } from "effect-app"
16
- import { type ApiConfig, ServiceUnavailableError } from "effect-app/client"
17
- import type { HttpClient } from "effect-app/http"
16
+ import { ServiceUnavailableError } from "effect-app/client"
18
17
  import { computed, ref } from "vue"
19
18
  import type { ComputedRef, WatchSource } from "vue"
20
- import { makeQueryKey, reportRuntimeError, run } from "./internal.js"
19
+ import { makeQueryKey, reportRuntimeError } from "./internal.js"
21
20
 
22
21
  // eslint-disable-next-line @typescript-eslint/no-empty-object-type
23
22
  export interface QueryObserverOptionsCustom<
@@ -31,190 +30,196 @@ export interface QueryObserverOptionsCustom<
31
30
  Omit<QueryObserverOptions<TQueryFnData, TError, TData, TQueryData, TQueryKey, TPageParam>, "queryKey" | "queryFn">
32
31
  {}
33
32
 
34
- export function useSafeQuery<E, A>(
35
- self: {
36
- handler: Effect<A, E, ApiConfig | HttpClient.HttpClient>
37
- mapPath: string
38
- name: string
39
- },
40
- options?: QueryObserverOptionsCustom // TODO
41
- ): readonly [
42
- ComputedRef<Result.Result<A, E>>,
43
- ComputedRef<A | undefined>,
44
- (options?: RefetchOptions) => Promise<QueryObserverResult<any, any>>,
45
- UseQueryReturnType<any, any>
46
- ]
47
- export function useSafeQuery<Arg, E, A>(
48
- self: {
49
- handler: (arg: Arg) => Effect<A, E, ApiConfig | HttpClient.HttpClient>
50
- mapPath: (arg: Arg) => string
51
- name: string
52
- },
53
- arg: Arg | WatchSource<Arg>,
54
- options?: QueryObserverOptionsCustom // TODO
55
- ): readonly [
56
- ComputedRef<Result.Result<A, E>>,
57
- ComputedRef<A | undefined>,
58
- (options?: RefetchOptions) => Promise<QueryObserverResult<any, any>>,
59
- UseQueryReturnType<any, any>
60
- ]
61
- export function useSafeQuery(
62
- self: any,
63
- /*
64
- q:
65
- | {
66
- handler: (
67
- req: I
68
- ) => Effect<
69
- A,
70
- E,
71
- ApiConfig | HttpClient.HttpClient
72
- >
73
- mapPath: (req: I) => string
74
- name: string
75
- }
76
- | {
77
- handler: Effect<
78
- A,
79
- E,
80
- ApiConfig | HttpClient.HttpClient
81
- >
82
- mapPath: string
83
- name: string
84
- },
85
- */
86
- argOrOptions?: any,
87
- options?: any
88
- ) {
89
- return Effect.isEffect(self.handler)
90
- ? useSafeQuery_(self, undefined, argOrOptions)
91
- : useSafeQuery_(self, argOrOptions, options)
92
- }
93
-
94
33
  export interface KnownFiberFailure<E> extends Runtime.FiberFailure {
95
34
  readonly [Runtime.FiberFailureCauseId]: Cause.Cause<E>
96
35
  }
97
36
 
98
- // TODO: options
99
- // declare function useQuery<TQueryFnData = unknown, TError = DefaultError, TData = TQueryFnData, TQueryKey extends QueryKey = QueryKey>(options: UndefinedInitialQueryOptions<TQueryFnData, TError, TData, TQueryKey>, queryClient?: QueryClient): UseQueryReturnType<TData, TError>;
100
- // declare function useQuery<TQueryFnData = unknown, TError = DefaultError, TData = TQueryFnData, TQueryKey extends QueryKey = QueryKey>(options: DefinedInitialQueryOptions<TQueryFnData, TError, TData, TQueryKey>, queryClient?: QueryClient): UseQueryDefinedReturnType<TData, TError>;
101
- // declare function useQuery<TQueryFnData = unknown, TError = DefaultError, TData = TQueryFnData, TQueryKey extends QueryKey = QueryKey>(options: UseQueryOptions<TQueryFnData, TError, TData, TQueryFnData, TQueryKey>, queryClient?: QueryClient): UseQueryReturnType<TData, TError>;
102
- export const useSafeQuery_ = <I, A, E>(
37
+ export const makeQuery = <R>(runtime: Runtime.Runtime<R>) => {
38
+ const runPromise = Runtime.runPromise(runtime)
39
+ // TODO: options
40
+ // declare function useQuery<TQueryFnData = unknown, TError = DefaultError, TData = TQueryFnData, TQueryKey extends QueryKey = QueryKey>(options: UndefinedInitialQueryOptions<TQueryFnData, TError, TData, TQueryKey>, queryClient?: QueryClient): UseQueryReturnType<TData, TError>;
41
+ // declare function useQuery<TQueryFnData = unknown, TError = DefaultError, TData = TQueryFnData, TQueryKey extends QueryKey = QueryKey>(options: DefinedInitialQueryOptions<TQueryFnData, TError, TData, TQueryKey>, queryClient?: QueryClient): UseQueryDefinedReturnType<TData, TError>;
42
+ // declare function useQuery<TQueryFnData = unknown, TError = DefaultError, TData = TQueryFnData, TQueryKey extends QueryKey = QueryKey>(options: UseQueryOptions<TQueryFnData, TError, TData, TQueryFnData, TQueryKey>, queryClient?: QueryClient): UseQueryReturnType<TData, TError>;
43
+ const useSafeQuery_ = <I, A, E>(
44
+ q:
45
+ | {
46
+ readonly handler: (
47
+ req: I
48
+ ) => Effect<
49
+ A,
50
+ E,
51
+ R
52
+ >
53
+ mapPath: (req: I) => string
54
+ name: string
55
+ }
56
+ | {
57
+ readonly handler: Effect<
58
+ A,
59
+ E,
60
+ R
61
+ >
62
+ mapPath: string
63
+ name: string
64
+ },
65
+ arg?: I | WatchSource<I>,
66
+ options: QueryObserverOptionsCustom<unknown, KnownFiberFailure<E>, A> = {} // TODO
67
+ ) => {
68
+ const arr = arg
69
+ const req: { value: I } = !arg
70
+ ? undefined
71
+ : typeof arr === "function"
72
+ ? ({
73
+ get value() {
74
+ return (arr as any)()
75
+ }
76
+ } as any)
77
+ : ref(arg)
78
+ const queryKey = makeQueryKey(q.name)
79
+ const handler = q.handler
80
+ const r = useQuery<unknown, KnownFiberFailure<E>, A>(
81
+ Effect.isEffect(handler)
82
+ ? {
83
+ ...options,
84
+ retry: (retryCount, error) => {
85
+ if (Runtime.isFiberFailure(error)) {
86
+ const cause = error[Runtime.FiberFailureCauseId]
87
+ const sq = Cause.squash(cause)
88
+ if (!isHttpRequestError(sq) && !isHttpResponseError(sq) && !S.is(ServiceUnavailableError)(sq)) {
89
+ return false
90
+ }
91
+ }
92
+
93
+ return retryCount < 5
94
+ },
95
+ queryKey,
96
+ queryFn: ({ signal }) =>
97
+ runPromise(
98
+ handler
99
+ .pipe(
100
+ Effect.tapDefect(reportRuntimeError),
101
+ Effect.withSpan(`query ${q.name}`, { captureStackTrace: false })
102
+ ),
103
+ { signal }
104
+ )
105
+ }
106
+ : {
107
+ ...options,
108
+ retry: (retryCount, error) => {
109
+ if (Runtime.isFiberFailure(error)) {
110
+ const cause = error[Runtime.FiberFailureCauseId]
111
+ const sq = Cause.squash(cause)
112
+ if (!isHttpRequestError(sq) && !isHttpResponseError(sq) && !S.is(ServiceUnavailableError)(sq)) {
113
+ return false
114
+ }
115
+ }
116
+
117
+ return retryCount < 5
118
+ },
119
+ queryKey: [...queryKey, req],
120
+ queryFn: ({ signal }) =>
121
+ runPromise(
122
+ handler(req.value)
123
+ .pipe(
124
+ Effect.tapDefect(reportRuntimeError),
125
+ Effect.withSpan(`query ${q.name}`, { captureStackTrace: false })
126
+ ),
127
+ { signal }
128
+ )
129
+ }
130
+ )
131
+
132
+ const result = computed(() =>
133
+ swrToQuery({
134
+ error: r.error.value ?? undefined,
135
+ data: r.data.value,
136
+ isValidating: r.isFetching.value
137
+ })
138
+ )
139
+ const latestSuccess = computed(() => Option.getOrUndefined(Result.value(result.value)))
140
+ return [result, latestSuccess, r.refetch, r] as const
141
+ }
142
+
143
+ function swrToQuery<E, A>(r: {
144
+ error: KnownFiberFailure<E> | undefined
145
+ data: A | undefined
146
+ isValidating: boolean
147
+ }): Result.Result<A, E> {
148
+ if (r.error) {
149
+ return Result.failureWithPrevious(
150
+ r.error[Runtime.FiberFailureCauseId],
151
+ r.data === undefined ? Option.none() : Option.some(Result.success(r.data)),
152
+ r.isValidating
153
+ )
154
+ }
155
+ if (r.data !== undefined) {
156
+ return Result.success<A, E>(r.data, r.isValidating)
157
+ }
158
+
159
+ return Result.initial(r.isValidating)
160
+ }
161
+
162
+ function useSafeQuery<E, A>(
163
+ self: {
164
+ handler: Effect<A, E, R>
165
+ mapPath: string
166
+ name: string
167
+ },
168
+ options?: QueryObserverOptionsCustom // TODO
169
+ ): readonly [
170
+ ComputedRef<Result.Result<A, E>>,
171
+ ComputedRef<A | undefined>,
172
+ (options?: RefetchOptions) => Promise<QueryObserverResult<any, any>>,
173
+ UseQueryReturnType<any, any>
174
+ ]
175
+ function useSafeQuery<Arg, E, A>(
176
+ self: {
177
+ handler: (arg: Arg) => Effect<A, E, R>
178
+ mapPath: (arg: Arg) => string
179
+ name: string
180
+ },
181
+ arg: Arg | WatchSource<Arg>,
182
+ options?: QueryObserverOptionsCustom // TODO
183
+ ): readonly [
184
+ ComputedRef<Result.Result<A, E>>,
185
+ ComputedRef<A | undefined>,
186
+ (options?: RefetchOptions) => Promise<QueryObserverResult<any, any>>,
187
+ UseQueryReturnType<any, any>
188
+ ]
189
+ function useSafeQuery(
190
+ self: any,
191
+ /*
103
192
  q:
104
193
  | {
105
- readonly handler: (
194
+ handler: (
106
195
  req: I
107
196
  ) => Effect<
108
197
  A,
109
198
  E,
110
- ApiConfig | HttpClient.HttpClient
199
+ R
111
200
  >
112
201
  mapPath: (req: I) => string
113
202
  name: string
114
203
  }
115
204
  | {
116
- readonly handler: Effect<
205
+ handler: Effect<
117
206
  A,
118
207
  E,
119
- ApiConfig | HttpClient.HttpClient
208
+ R
120
209
  >
121
210
  mapPath: string
122
211
  name: string
123
212
  },
124
- arg?: I | WatchSource<I>,
125
- options: QueryObserverOptionsCustom<unknown, KnownFiberFailure<E>, A> = {} // TODO
126
- ) => {
127
- const arr = arg
128
- const req: { value: I } = !arg
129
- ? undefined
130
- : typeof arr === "function"
131
- ? ({
132
- get value() {
133
- return (arr as any)()
134
- }
135
- } as any)
136
- : ref(arg)
137
- const queryKey = makeQueryKey(q.name)
138
- const handler = q.handler
139
- const r = useQuery<unknown, KnownFiberFailure<E>, A>(
140
- Effect.isEffect(handler)
141
- ? {
142
- ...options,
143
- retry: (retryCount, error) => {
144
- if (Runtime.isFiberFailure(error)) {
145
- const cause = error[Runtime.FiberFailureCauseId]
146
- const sq = Cause.squash(cause)
147
- if (!isHttpRequestError(sq) && !isHttpResponseError(sq) && !S.is(ServiceUnavailableError)(sq)) {
148
- return false
149
- }
150
- }
151
-
152
- return retryCount < 5
153
- },
154
- queryKey,
155
- queryFn: ({ signal }) =>
156
- run.value(
157
- handler
158
- .pipe(
159
- Effect.tapDefect(reportRuntimeError),
160
- Effect.withSpan(`query ${q.name}`, { captureStackTrace: false })
161
- ),
162
- { signal }
163
- )
164
- }
165
- : {
166
- ...options,
167
- retry: (retryCount, error) => {
168
- if (Runtime.isFiberFailure(error)) {
169
- const cause = error[Runtime.FiberFailureCauseId]
170
- const sq = Cause.squash(cause)
171
- if (!isHttpRequestError(sq) && !isHttpResponseError(sq) && !S.is(ServiceUnavailableError)(sq)) {
172
- return false
173
- }
174
- }
175
-
176
- return retryCount < 5
177
- },
178
- queryKey: [...queryKey, req],
179
- queryFn: ({ signal }) =>
180
- run
181
- .value(
182
- handler(req.value)
183
- .pipe(
184
- Effect.tapDefect(reportRuntimeError),
185
- Effect.withSpan(`query ${q.name}`, { captureStackTrace: false })
186
- ),
187
- { signal }
188
- )
189
- }
190
- )
191
-
192
- const result = computed(() =>
193
- swrToQuery({
194
- error: r.error.value ?? undefined,
195
- data: r.data.value,
196
- isValidating: r.isFetching.value
197
- })
198
- )
199
- const latestSuccess = computed(() => Option.getOrUndefined(Result.value(result.value)))
200
- return [result, latestSuccess, r.refetch, r] as const
201
- }
202
-
203
- function swrToQuery<E, A>(r: {
204
- error: KnownFiberFailure<E> | undefined
205
- data: A | undefined
206
- isValidating: boolean
207
- }): Result.Result<A, E> {
208
- if (r.error) {
209
- return Result.failureWithPrevious(
210
- r.error[Runtime.FiberFailureCauseId],
211
- r.data === undefined ? Option.none() : Option.some(Result.success(r.data)),
212
- r.isValidating
213
- )
214
- }
215
- if (r.data !== undefined) {
216
- return Result.success<A, E>(r.data, r.isValidating)
213
+ */
214
+ argOrOptions?: any,
215
+ options?: any
216
+ ) {
217
+ return Effect.isEffect(self.handler)
218
+ ? useSafeQuery_(self, undefined, argOrOptions)
219
+ : useSafeQuery_(self, argOrOptions, options)
217
220
  }
218
-
219
- return Result.initial(r.isValidating)
221
+ return useSafeQuery
220
222
  }
223
+
224
+ // eslint-disable-next-line @typescript-eslint/no-empty-object-type
225
+ export interface MakeQuery<R> extends ReturnType<typeof makeQuery<R>> {}
package/src/runtime.ts CHANGED
@@ -4,9 +4,6 @@ import { Config, Exit, Runtime } from "effect"
4
4
  import { Effect, Layer, Logger } from "effect-app"
5
5
  import { ApiConfig } from "effect-app/client"
6
6
  import * as Scope from "effect/Scope"
7
- import { initRuntime } from "./internal.js"
8
-
9
- export { initRuntime } from "./internal.js"
10
7
 
11
8
  export const DefaultApiConfig = Config.all({
12
9
  apiUrl: Config.string("apiUrl").pipe(Config.withDefault("/api")),
@@ -48,7 +45,6 @@ export function makeAppRuntime<R, E, A>(layer: Layer<A, E, R>) {
48
45
 
49
46
  export function initializeSync<E, A>(layer: Layer<A | ApiConfig | HttpClient.HttpClient, E, never>) {
50
47
  const { clean, runtime } = Effect.runSync(makeAppRuntime(layer))
51
- initRuntime(runtime)
52
48
  return {
53
49
  runtime,
54
50
  clean: () => Effect.runSync(clean)
@@ -59,7 +55,6 @@ export function initializeAsync<E, A>(layer: Layer<A | ApiConfig | HttpClient.Ht
59
55
  return Effect
60
56
  .runPromise(makeAppRuntime(layer))
61
57
  .then(({ clean, runtime }) => {
62
- initRuntime(runtime)
63
58
  return {
64
59
  runtime,
65
60
  clean: () => Effect.runPromise(clean)