From d1999788a4d6ef15977469613285b4f8749c4854 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 11 May 2026 15:23:24 +0000 Subject: [PATCH 1/3] feat(vue): add mode: "optional" overload for queries with Option input Agent-Logs-Url: https://github.com/effect-app/libs/sessions/a27dfe5f-fbbb-4bf0-955f-bf881a106181 Co-authored-by: patroza <42661+patroza@users.noreply.github.com> --- .changeset/query-optional-mode.md | 5 ++++ packages/vue/src/query.ts | 49 +++++++++++++++++++++++++------ 2 files changed, 45 insertions(+), 9 deletions(-) create mode 100644 .changeset/query-optional-mode.md diff --git a/.changeset/query-optional-mode.md b/.changeset/query-optional-mode.md new file mode 100644 index 000000000..c28dbb23a --- /dev/null +++ b/.changeset/query-optional-mode.md @@ -0,0 +1,5 @@ +--- +"@effect-app/vue": minor +--- + +Add `mode: "optional"` overload for queries. When `mode: "optional"` is set, the `arg` must be a `WatchSource>`. The query is disabled (`enabled: false`) when the option is `None`, and enabled with the unwrapped value when `Some`. diff --git a/packages/vue/src/query.ts b/packages/vue/src/query.ts index 0ce2314d5..63696444b 100644 --- a/packages/vue/src/query.ts +++ b/packages/vue/src/query.ts @@ -149,6 +149,16 @@ export const makeQuery = (getRuntime: () => Context.Context) => { ( q: RequestHandlerWithInput ): { + ( + arg: WatchSource>, + options: Omit, "enabled"> & { mode: "optional" } + ): readonly [ + ComputedRef>, + ComputedRef, + (options?: RefetchOptions) => Effect.Effect>>, + UseQueryDefinedReturnType> + ] + ( arg: I | WatchSource | undefined, options?: CustomUndefinedInitialQueryOptions @@ -183,7 +193,7 @@ export const makeQuery = (getRuntime: () => Context.Context) => { q: RequestHandlerWithInput ) => ( - arg: I | WatchSource | undefined, + arg: I | WatchSource | undefined | WatchSource>, // todo QueryKey type would be [string, ...string[]], but with I it would be [string, ...string[], I] options?: any // TODO @@ -191,15 +201,33 @@ export const makeQuery = (getRuntime: () => Context.Context) => { // we wrap into CauseException because we want to keep the full cause of the failure. const runPromise = makeRunPromise(getRuntime()) const arr = arg - const req: { value: I } | undefined = !arg - ? undefined - : typeof arr === "function" - ? ({ + const isOptional = options?.mode === "optional" + + let req: { value: I } | undefined + let enabledOpt: ComputedRef | undefined + + if (isOptional) { + const getOption: () => Option.Option = typeof arr === "function" + ? arr as () => Option.Option + : () => (arr as any).value as Option.Option + req = { get value() { - return (arr as any)() + return Option.getOrUndefined(getOption()) as I } - }) - : ref(arg) as any + } + enabledOpt = computed(() => Option.isSome(getOption())) + } else { + req = !arg + ? undefined + : typeof arr === "function" + ? ({ + get value() { + return (arr as any)() + } + }) + : ref(arg) as any + } + const queryKey = makeQueryKey(q) const projectionHash = (q as { queryKeyProjectionHash?: string }).queryKeyProjectionHash @@ -213,9 +241,12 @@ export const makeQuery = (getRuntime: () => Context.Context) => { throwOnError: false } + const { mode: _mode, enabled: _enabled, ...optionalOpts } = isOptional ? (options ?? {}) : {} + const r = useTanstackQuery, TData>({ ...defaultOptions, - ...options, + ...(isOptional ? optionalOpts : options), + ...(enabledOpt !== undefined ? { enabled: enabledOpt } : {}), retry: (retryCount, error) => { if (error instanceof CauseException) { if (!isHttpClientError(error.cause) && !S.is(ServiceUnavailableError)(error.cause)) { From fe296195ce531cc68755b6e77855ce1619f87aa9 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 11 May 2026 15:26:06 +0000 Subject: [PATCH 2/3] refactor: clean up optional mode query implementation per review Agent-Logs-Url: https://github.com/effect-app/libs/sessions/a27dfe5f-fbbb-4bf0-955f-bf881a106181 Co-authored-by: patroza <42661+patroza@users.noreply.github.com> --- packages/vue/src/query.ts | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/packages/vue/src/query.ts b/packages/vue/src/query.ts index 63696444b..cec848f67 100644 --- a/packages/vue/src/query.ts +++ b/packages/vue/src/query.ts @@ -201,21 +201,22 @@ export const makeQuery = (getRuntime: () => Context.Context) => { // we wrap into CauseException because we want to keep the full cause of the failure. const runPromise = makeRunPromise(getRuntime()) const arr = arg - const isOptional = options?.mode === "optional" let req: { value: I } | undefined - let enabledOpt: ComputedRef | undefined + let callerOptions: any = options - if (isOptional) { + if (options?.mode === "optional") { const getOption: () => Option.Option = typeof arr === "function" ? arr as () => Option.Option - : () => (arr as any).value as Option.Option + : () => (arr as { value: Option.Option }).value req = { get value() { + // getOrUndefined returns undefined when None, but queryFn is only called when enabled (Some) return Option.getOrUndefined(getOption()) as I } } - enabledOpt = computed(() => Option.isSome(getOption())) + const { mode: _mode, enabled: _enabled, ...rest } = options ?? {} + callerOptions = { ...rest, enabled: computed(() => Option.isSome(getOption())) } } else { req = !arg ? undefined @@ -241,12 +242,9 @@ export const makeQuery = (getRuntime: () => Context.Context) => { throwOnError: false } - const { mode: _mode, enabled: _enabled, ...optionalOpts } = isOptional ? (options ?? {}) : {} - const r = useTanstackQuery, TData>({ ...defaultOptions, - ...(isOptional ? optionalOpts : options), - ...(enabledOpt !== undefined ? { enabled: enabledOpt } : {}), + ...callerOptions, retry: (retryCount, error) => { if (error instanceof CauseException) { if (!isHttpClientError(error.cause) && !S.is(ServiceUnavailableError)(error.cause)) { From ec01f6197d356440cc611c47babafef2bd60633c Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 11 May 2026 15:35:48 +0000 Subject: [PATCH 3/3] feat(vue): expose mode: optional overload on outer useQuery / client query helpers Agent-Logs-Url: https://github.com/effect-app/libs/sessions/6c63899e-f382-4d80-99bf-9cce72205cdf Co-authored-by: patroza <42661+patroza@users.noreply.github.com> --- packages/vue/src/query.ts | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/packages/vue/src/query.ts b/packages/vue/src/query.ts index cec848f67..02c59bbcf 100644 --- a/packages/vue/src/query.ts +++ b/packages/vue/src/query.ts @@ -303,6 +303,15 @@ export const makeQuery = (getRuntime: () => Context.Context) => { ( self: RequestHandlerWithInput ): { + ( + arg: WatchSource>, + options: Omit, TData>, "enabled"> & { mode: "optional" } + ): readonly [ + ComputedRef>, + ComputedRef, + (options?: RefetchOptions) => Effect.Effect>>, + UseQueryReturnType + ] ( arg: I | WatchSource, options: CustomDefinedInitialQueryOptions, TData>