chore: restructure vue-sync-engine workspace and remove unused files

This commit is contained in:
2026-05-29 01:09:14 +07:00
parent 654bca0a00
commit ee14101fc1
66 changed files with 5158 additions and 582 deletions
@@ -0,0 +1,10 @@
import { inject, type InjectionKey } from 'vue'
import type { TabRuntime } from '../tab/runtime'
export const EngineKey: InjectionKey<TabRuntime> = Symbol('SyncEngine')
export function useEngine(): TabRuntime {
const rt = inject(EngineKey)
if (!rt) throw new Error('SyncEngine is not provided. Call app.provide(EngineKey, runtime).')
return rt
}
@@ -0,0 +1,15 @@
import { computed, type ComputedRef, type MaybeRefOrGetter, toValue } from 'vue'
import type { EntityDef, EntityId } from '../core/types'
import { useEngine } from './useEngine'
export function useEntity<T>(
def: EntityDef<T>,
id: MaybeRefOrGetter<EntityId | undefined>,
): ComputedRef<T | undefined> {
const engine = useEngine()
return computed(() => {
const v = toValue(id)
if (v === undefined || v === null) return undefined
return engine.mirror.getEntity<T>(def.name, v)
})
}
@@ -0,0 +1,54 @@
import { computed, onScopeDispose, watch, type ComputedRef, type MaybeRefOrGetter, toValue } from 'vue'
import type { InfiniteQueryDef, QueryStatus } from '../core/types'
import { Status } from '../core/flags'
import { hashKey } from '../core/queryKey'
import { useEngine } from './useEngine'
export interface UseInfiniteQueryReturn<TResult> {
pages: ComputedRef<TResult[]>
pageParams: ComputedRef<unknown[]>
status: ComputedRef<QueryStatus>
error: ComputedRef<{ message: string } | undefined>
isLoading: ComputedRef<boolean>
fetchNextPage: () => void
}
interface InfinitePayload<T> {
pages: T[]
pageParams: unknown[]
}
export function useInfiniteQuery<TArgs, TResp, TPageParam, TResult>(
def: InfiniteQueryDef<TArgs, TResp, TPageParam, TResult> & { name: string },
args: MaybeRefOrGetter<TArgs>,
): UseInfiniteQueryReturn<TResult> {
const engine = useEngine()
const initial = toValue(args)
let handle = engine.subscribeQuery(def.name, def.key(initial), initial)
let stateRef = engine.mirror.ensureQuery<InfinitePayload<TResult>>(handle.subId)
if (!def.staticHash) {
watch(
() => hashKey(def.key(toValue(args))),
() => {
const next = toValue(args)
const prev = handle
handle = engine.subscribeQuery(def.name, def.key(next), next)
stateRef = engine.mirror.ensureQuery<InfinitePayload<TResult>>(handle.subId)
prev.release()
},
)
}
onScopeDispose(() => handle.release())
return {
pages: computed(() => stateRef.value.data?.pages ?? []),
pageParams: computed(() => stateRef.value.data?.pageParams ?? []),
status: computed(() => stateRef.value.status),
error: computed(() => stateRef.value.error),
isLoading: computed(() => stateRef.value.status === Status.Pending),
fetchNextPage: () => handle.fetchNextPage(),
}
}
@@ -0,0 +1,42 @@
import { shallowRef, type ShallowRef } from 'vue'
import type { MutationDef, QueryStatus } from '../core/types'
import { Status } from '../core/flags'
import { useEngine } from './useEngine'
export interface UseMutationReturn<TInput, TResp> {
mutate: (input: TInput) => void
mutateAsync: (input: TInput) => Promise<TResp>
status: ShallowRef<QueryStatus>
error: ShallowRef<Error | undefined>
data: ShallowRef<TResp | undefined>
}
export function useMutation<TInput, TResp>(
def: MutationDef<TInput, TResp>,
): UseMutationReturn<TInput, TResp> {
const engine = useEngine()
const status = shallowRef<QueryStatus>(Status.Idle)
const error = shallowRef<Error | undefined>(undefined)
const data = shallowRef<TResp | undefined>(undefined)
async function mutateAsync(input: TInput): Promise<TResp> {
status.value = Status.Pending
error.value = undefined
try {
const resp = (await engine.mutate(def.name, input)) as TResp
data.value = resp
status.value = Status.Success
return resp
} catch (e) {
error.value = e as Error
status.value = Status.Error
throw e
}
}
function mutate(input: TInput): void {
void mutateAsync(input).catch(() => {})
}
return { mutate, mutateAsync, status, error, data }
}
@@ -0,0 +1,49 @@
import { computed, onScopeDispose, watch, type ComputedRef, type MaybeRefOrGetter, toValue } from 'vue'
import type { InfiniteQueryDef, QueryDef, QueryStatus } from '../core/types'
import { Status } from '../core/flags'
import { hashKey } from '../core/queryKey'
import { useEngine } from './useEngine'
export interface UseQueryReturn<T> {
data: ComputedRef<T | undefined>
status: ComputedRef<QueryStatus>
error: ComputedRef<{ message: string } | undefined>
isLoading: ComputedRef<boolean>
isSuccess: ComputedRef<boolean>
isError: ComputedRef<boolean>
}
export function useQuery<TArgs, TResp, TResult>(
def: (QueryDef<TArgs, TResp, TResult> | InfiniteQueryDef<TArgs, TResp, any, TResult>) & { name: string },
args: MaybeRefOrGetter<TArgs>,
): UseQueryReturn<TResult> {
const engine = useEngine()
const initial = toValue(args)
let currentHandle = engine.subscribeQuery(def.name, def.key(initial), initial)
let currentRef = engine.mirror.ensureQuery<TResult>(currentHandle.subId)
if (!def.staticHash) {
watch(
() => hashKey(def.key(toValue(args))),
() => {
const next = toValue(args)
const prev = currentHandle
currentHandle = engine.subscribeQuery(def.name, def.key(next), next)
currentRef = engine.mirror.ensureQuery<TResult>(currentHandle.subId)
prev.release()
},
)
}
onScopeDispose(() => currentHandle.release())
return {
data: computed(() => currentRef.value.data),
status: computed(() => currentRef.value.status),
error: computed(() => currentRef.value.error),
isLoading: computed(() => currentRef.value.status === Status.Pending),
isSuccess: computed(() => currentRef.value.status === Status.Success),
isError: computed(() => currentRef.value.status === Status.Error),
}
}