diff --git a/packages/api-client-core/src/AnyClient.ts b/packages/api-client-core/src/AnyClient.ts index 62e1e6a24..fea8bc457 100644 --- a/packages/api-client-core/src/AnyClient.ts +++ b/packages/api-client-core/src/AnyClient.ts @@ -15,6 +15,7 @@ export interface AnyClient { mutate(graphQL: string, variables?: Record): Promise; transaction(callback: (transaction: GadgetTransaction) => Promise): Promise; internal: InternalModelManagerNamespace; + apiClientCoreVersion?: string; [$modelRelationships]?: { [modelName: string]: { [apiIdentifier: string]: { type: string; model: string } } }; } diff --git a/packages/api-client-core/src/GadgetFunctions.ts b/packages/api-client-core/src/GadgetFunctions.ts index 1f9726aa4..284222bb8 100644 --- a/packages/api-client-core/src/GadgetFunctions.ts +++ b/packages/api-client-core/src/GadgetFunctions.ts @@ -7,9 +7,13 @@ export type AsyncRecord = PromiseOrLiveIterator = PromiseOrLiveIterator | null>; export type AsyncRecordList = PromiseOrLiveIterator>; +export interface GQLBuilderResult { + query: string; + variables: Record; +} + export interface FindOneFunction { (fieldValue: string, options?: LimitToKnownKeys): AsyncRecord; - type: "findOne"; findByVariableName: string; operationName: string; @@ -19,6 +23,7 @@ export interface FindOneFunction { selectionType: SelectionT; optionsType: OptionsT; schemaType: SchemaT | null; + plan?: (fieldValue: string, options?: LimitToKnownKeys) => GQLBuilderResult; } export interface MaybeFindOneFunction { @@ -33,6 +38,7 @@ export interface MaybeFindOneFunction selectionType: SelectionT; optionsType: OptionsT; schemaType: SchemaT | null; + plan?: (fieldValue: string, options?: LimitToKnownKeys) => GQLBuilderResult; } export interface FindManyFunction { @@ -46,6 +52,7 @@ export interface FindManyFunction { selectionType: SelectionT; optionsType: OptionsT; schemaType: SchemaT | null; + plan?: (options?: LimitToKnownKeys) => GQLBuilderResult; } export interface FindFirstFunction { @@ -59,6 +66,7 @@ export interface FindFirstFunction { selectionType: SelectionT; optionsType: OptionsT; schemaType: SchemaT | null; + plan?: (options?: LimitToKnownKeys) => GQLBuilderResult; } export interface MaybeFindFirstFunction { @@ -72,6 +80,7 @@ export interface MaybeFindFirstFunction(options?: LimitToKnownKeys) => GQLBuilderResult; } export interface ActionWithIdAndVariables { @@ -122,6 +131,7 @@ export interface ActionFunctionMetadata(options?: LimitToKnownKeys) => GQLBuilderResult; /** @deprecated */ hasCreateOrUpdateEffect?: boolean; } @@ -162,6 +172,7 @@ export interface GetFunction { selectionType: SelectionT; optionsType: OptionsT; schemaType: SchemaT | null; + plan?: (options?: LimitToKnownKeys) => GQLBuilderResult; } export interface GlobalActionFunction { diff --git a/packages/react/src/useAction.ts b/packages/react/src/useAction.ts index f84c11433..5462250c4 100644 --- a/packages/react/src/useAction.ts +++ b/packages/react/src/useAction.ts @@ -1,6 +1,5 @@ import type { ActionFunction, DefaultSelection, GadgetRecord, LimitToKnownKeys, Select } from "@gadgetinc/api-client-core"; import { - actionOperation, capitalizeIdentifier, disambiguateActionVariables, get, @@ -64,17 +63,11 @@ export const useAction = < const memoizedOptions = useStructuralMemo(options); const plan = useMemo(() => { - return actionOperation( - action.operationName, - action.defaultSelection, - action.modelApiIdentifier, - action.modelSelectionField, - action.variables, - memoizedOptions, - action.namespace, - action.isBulk, - action.hasReturnType - ); + if (action.plan) { + return action.plan(memoizedOptions); + } else { + throw new Error("Incompatible client passed to useAction hook, please use an api client with version >= 0.17.0") + } }, [action, memoizedOptions]); const [result, runMutation] = useGadgetMutation< diff --git a/packages/react/src/useBulkAction.ts b/packages/react/src/useBulkAction.ts index 0f5e96cff..437ef5656 100644 --- a/packages/react/src/useBulkAction.ts +++ b/packages/react/src/useBulkAction.ts @@ -59,17 +59,11 @@ export const useBulkAction = < > => { const memoizedOptions = useStructuralMemo(options); const plan = useMemo(() => { - return actionOperation( - action.operationName, - action.defaultSelection, - action.modelApiIdentifier, - action.modelSelectionField, - action.variables, - memoizedOptions, - action.namespace, - action.isBulk, - action.hasReturnType - ); + if (action.plan) { + return action.plan(memoizedOptions); + } else { + throw new Error("Incompatible client passed to useBulkAction hook, please use an api client with version >= 0.17.0") + } }, [action, memoizedOptions]); const [result, runMutation] = useGadgetMutation< diff --git a/packages/react/src/useFindBy.ts b/packages/react/src/useFindBy.ts index 2122ce8c4..d8257e6a4 100644 --- a/packages/react/src/useFindBy.ts +++ b/packages/react/src/useFindBy.ts @@ -50,15 +50,11 @@ export const useFindBy = < > => { const memoizedOptions = useStructuralMemo(options); const plan = useMemo(() => { - return findOneByFieldOperation( - finder.operationName, - finder.findByVariableName, - value, - finder.defaultSelection, - finder.modelApiIdentifier, - memoizedOptions, - finder.namespace - ); + if (finder.plan) { + return finder.plan(value, memoizedOptions) + } else { + throw new Error("Incompatible client passed to useFindBy hook, please use an api client with version >= 0.17.0") + } }, [finder, value, memoizedOptions]); const [rawResult, refresh] = useGadgetQuery(useQueryArgs(plan, options)); diff --git a/packages/react/src/useFindFirst.ts b/packages/react/src/useFindFirst.ts index cfae2d3f7..cdbc7b0cb 100644 --- a/packages/react/src/useFindFirst.ts +++ b/packages/react/src/useFindFirst.ts @@ -1,5 +1,5 @@ import type { DefaultSelection, FindFirstFunction, GadgetRecord, LimitToKnownKeys, Select } from "@gadgetinc/api-client-core"; -import { findManyOperation, get, hydrateConnection, namespaceDataPath } from "@gadgetinc/api-client-core"; +import { get, hydrateConnection, namespaceDataPath } from "@gadgetinc/api-client-core"; import { useMemo } from "react"; import { useGadgetQuery } from "./useGadgetQuery.js"; import { useStructuralMemo } from "./useStructuralMemo.js"; @@ -41,19 +41,16 @@ export const useFindFirst = < ): ReadHookResult< GadgetRecord, DefaultSelection>> > => { - const firstOptions = { ...options, first: 1 }; - const memoizedOptions = useStructuralMemo(firstOptions); + const memoizedOptions = useStructuralMemo(options); const plan = useMemo(() => { - return findManyOperation( - manager.findFirst.operationName, - manager.findFirst.defaultSelection, - manager.findFirst.modelApiIdentifier, - memoizedOptions, - manager.findFirst.namespace - ); + if (manager.findFirst.plan) { + return manager.findFirst.plan(memoizedOptions); + } else { + throw new Error("Incompatible client passed to useFindFirst hook, please use an api client with version >= 0.17.0") + } }, [manager, memoizedOptions]); - const [rawResult, refresh] = useGadgetQuery(useQueryArgs(plan, firstOptions)); + const [rawResult, refresh] = useGadgetQuery(useQueryArgs(plan, options)); const result = useMemo(() => { const dataPath = namespaceDataPath([manager.findFirst.operationName], manager.findFirst.namespace); @@ -70,7 +67,7 @@ export const useFindFirst = < const error = ErrorWrapper.errorIfDataAbsent(rawResult, dataPath, options?.pause); return { ...rawResult, data, error }; - }, [manager.findFirst.operationName, options?.pause, rawResult]); + }, [manager.findFirst.namespace, manager.findFirst.operationName, options?.pause, rawResult]); return [result, refresh]; }; diff --git a/packages/react/src/useFindMany.ts b/packages/react/src/useFindMany.ts index e71ebddb3..56dee4005 100644 --- a/packages/react/src/useFindMany.ts +++ b/packages/react/src/useFindMany.ts @@ -43,13 +43,11 @@ export const useFindMany = < > => { const memoizedOptions = useStructuralMemo(options); const plan = useMemo(() => { - return findManyOperation( - manager.findMany.operationName, - manager.findMany.defaultSelection, - manager.findMany.modelApiIdentifier, - memoizedOptions, - manager.findMany.namespace - ); + if (manager.findMany.plan) { + return manager.findMany.plan(memoizedOptions); + } else { + throw new Error("Incompatible client passed to useFindMany hook, please use an api client with version >= 0.17.0") + } }, [manager, memoizedOptions]); const [rawResult, refresh] = useGadgetQuery(useQueryArgs(plan, options)); diff --git a/packages/react/src/useFindOne.ts b/packages/react/src/useFindOne.ts index acd65b4d0..6b9bcd406 100644 --- a/packages/react/src/useFindOne.ts +++ b/packages/react/src/useFindOne.ts @@ -1,5 +1,5 @@ import type { DefaultSelection, FindOneFunction, GadgetRecord, LimitToKnownKeys, Select } from "@gadgetinc/api-client-core"; -import { findOneOperation, get, hydrateRecord, namespaceDataPath } from "@gadgetinc/api-client-core"; +import { get, hydrateRecord, namespaceDataPath } from "@gadgetinc/api-client-core"; import { useMemo } from "react"; import { useGadgetQuery } from "./useGadgetQuery.js"; import { useStructuralMemo } from "./useStructuralMemo.js"; @@ -44,14 +44,11 @@ export const useFindOne = < > => { const memoizedOptions = useStructuralMemo(options); const plan = useMemo(() => { - return findOneOperation( - manager.findOne.operationName, - id, - manager.findOne.defaultSelection, - manager.findOne.modelApiIdentifier, - memoizedOptions, - manager.findOne.namespace - ); + if (manager.findOne.plan) { + return manager.findOne.plan(id, memoizedOptions); + } else { + throw new Error("Incompatible client passed to useFindOne hook, please use an api client with version >= 0.17.0") + } }, [manager, id, memoizedOptions]); const [rawResult, refresh] = useGadgetQuery(useQueryArgs(plan, options)); @@ -66,7 +63,7 @@ export const useFindOne = < const error = ErrorWrapper.errorIfDataAbsent(rawResult, dataPath, options?.pause); return { ...rawResult, data, error }; - }, [manager.findOne.operationName, rawResult, options?.pause]); + }, [manager.findOne.operationName, manager.findOne.namespace, rawResult, options?.pause]); return [result, refresh]; }; diff --git a/packages/react/src/useMaybeFindFirst.ts b/packages/react/src/useMaybeFindFirst.ts index e2702519b..8332fb183 100644 --- a/packages/react/src/useMaybeFindFirst.ts +++ b/packages/react/src/useMaybeFindFirst.ts @@ -1,5 +1,5 @@ import type { DefaultSelection, FindFirstFunction, GadgetRecord, LimitToKnownKeys, Select } from "@gadgetinc/api-client-core"; -import { findManyOperation, get, hydrateConnection, namespaceDataPath } from "@gadgetinc/api-client-core"; +import { get, hydrateConnection, namespaceDataPath } from "@gadgetinc/api-client-core"; import { useMemo } from "react"; import { useGadgetQuery } from "./useGadgetQuery.js"; import { useStructuralMemo } from "./useStructuralMemo.js"; @@ -41,19 +41,16 @@ export const useMaybeFindFirst = < ): ReadHookResult, DefaultSelection> >> => { - const firstOptions = { ...options, first: 1 }; - const memoizedOptions = useStructuralMemo(firstOptions); + const memoizedOptions = useStructuralMemo(options); const plan = useMemo(() => { - return findManyOperation( - manager.findFirst.operationName, - manager.findFirst.defaultSelection, - manager.findFirst.modelApiIdentifier, - memoizedOptions, - manager.findFirst.namespace - ); + if (manager.findFirst.plan) { + return manager.findFirst.plan(memoizedOptions); + } else { + throw new Error("Incompatible client passed to useMaybeFindFirst hook, please use an api client with version >= 0.17.0") + } }, [manager, memoizedOptions]); - const [rawResult, refresh] = useGadgetQuery(useQueryArgs(plan, firstOptions)); + const [rawResult, refresh] = useGadgetQuery(useQueryArgs(plan, memoizedOptions)); const result = useMemo(() => { const dataPath = namespaceDataPath([manager.findFirst.operationName], manager.findFirst.namespace); diff --git a/packages/react/src/useMaybeFindOne.ts b/packages/react/src/useMaybeFindOne.ts index cf9477db8..9b65dcdb7 100644 --- a/packages/react/src/useMaybeFindOne.ts +++ b/packages/react/src/useMaybeFindOne.ts @@ -1,5 +1,5 @@ import type { DefaultSelection, FindOneFunction, GadgetRecord, LimitToKnownKeys, Select } from "@gadgetinc/api-client-core"; -import { findOneOperation, get, hydrateRecord, namespaceDataPath } from "@gadgetinc/api-client-core"; +import { get, hydrateRecord, namespaceDataPath } from "@gadgetinc/api-client-core"; import { useMemo } from "react"; import { useGadgetQuery } from "./useGadgetQuery.js"; import { useStructuralMemo } from "./useStructuralMemo.js"; @@ -44,14 +44,11 @@ export const useMaybeFindOne = < >> => { const memoizedOptions = useStructuralMemo(options); const plan = useMemo(() => { - return findOneOperation( - manager.findOne.operationName, - id, - manager.findOne.defaultSelection, - manager.findOne.modelApiIdentifier, - memoizedOptions, - manager.findOne.namespace - ); + if (manager.findOne.plan) { + return manager.findOne.plan(id, memoizedOptions); + } else { + throw new Error("Incompatible client passed to useMaybeFindOne hook, please use an api client with version >= 0.17.0") + } }, [manager, id, memoizedOptions]); const [rawResult, refresh] = useGadgetQuery(useQueryArgs(plan, options));