gql.tada 1.9.0 → 1.9.1
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/dist/gql-tada.d.ts +13 -16
- package/dist/gql-tada.js.map +1 -1
- package/dist/gql-tada.mjs.map +1 -1
- package/package.json +1 -1
package/dist/gql-tada.d.ts
CHANGED
|
@@ -1768,7 +1768,6 @@ interface AbstractConfig {
|
|
|
1768
1768
|
interface setupSchema extends AbstractSetupSchema {}
|
|
1769
1769
|
interface AbstractSetupCache {
|
|
1770
1770
|
readonly __cacheDisabled: unknown;
|
|
1771
|
-
[key: string]: unknown;
|
|
1772
1771
|
}
|
|
1773
1772
|
interface setupCache extends AbstractSetupCache {}
|
|
1774
1773
|
interface GraphQLTadaAPI<Schema extends SchemaLike, Config extends AbstractConfig> {
|
|
@@ -1814,24 +1813,22 @@ interface GraphQLTadaAPI<Schema extends SchemaLike, Config extends AbstractConfi
|
|
|
1814
1813
|
*
|
|
1815
1814
|
* @see {@link readFragment} for how to read from fragment masks.
|
|
1816
1815
|
*/
|
|
1816
|
+
<
|
|
1817
|
+
const In extends unknown extends setupCache['__cacheDisabled'] ? keyof setupCache : never,
|
|
1818
|
+
const Fragments extends readonly FragmentShape[],
|
|
1819
|
+
>(
|
|
1820
|
+
input: In,
|
|
1821
|
+
fragments?: Fragments
|
|
1822
|
+
): setupCache[In];
|
|
1817
1823
|
<const In extends string, const Fragments extends readonly FragmentShape[]>(
|
|
1818
1824
|
input: In,
|
|
1819
1825
|
fragments?: Fragments
|
|
1820
|
-
):
|
|
1821
|
-
|
|
1822
|
-
|
|
1823
|
-
|
|
1824
|
-
|
|
1825
|
-
|
|
1826
|
-
getFragmentsOfDocuments<Fragments>,
|
|
1827
|
-
Config['isMaskingDisabled']
|
|
1828
|
-
>
|
|
1829
|
-
: getDocumentNode<
|
|
1830
|
-
parseDocument<In>,
|
|
1831
|
-
Schema,
|
|
1832
|
-
getFragmentsOfDocuments<Fragments>,
|
|
1833
|
-
Config['isMaskingDisabled']
|
|
1834
|
-
>;
|
|
1826
|
+
): getDocumentNode<
|
|
1827
|
+
parseDocument<In>,
|
|
1828
|
+
Schema,
|
|
1829
|
+
getFragmentsOfDocuments<Fragments>,
|
|
1830
|
+
Config['isMaskingDisabled']
|
|
1831
|
+
>;
|
|
1835
1832
|
/** Function to validate the type of a given scalar or enum value.
|
|
1836
1833
|
*
|
|
1837
1834
|
* @param name - The name of a scalar or enum type.
|
package/dist/gql-tada.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gql-tada.js","sources":["../src/utils.ts","../src/api.ts"],"sourcesContent":["import type { DocumentNode, Location } from '@0no-co/graphql.web';\n\n/** Returns `T` if it matches `Constraint` without being equal to it. Failing this evaluates to `Fallback` otherwise. */\nexport type matchOr<Constraint, T, Fallback> = Constraint extends T\n ? Fallback\n : T extends Constraint\n ? T\n : Fallback;\n\n/** Flattens a given object type.\n *\n * @remarks\n * This is typically used to make a TypeScript type appear as a flat object,\n * both in terms of type checking and for type hints and the tsserver output.\n */\nexport type obj<T> = T extends { [key: string | number]: any } ? { [K in keyof T]: T[K] } : never;\n\n/** Turns a given union to an intersection type. */\nexport type overload<T> = (T extends any ? (x: T) => void : never) extends (x: infer U) => void\n ? U & T\n : never;\n\n/** Marks all properties as writable */\nexport type writable<T> = { -readonly [K in keyof T]: T[K] };\n\n/** Annotations for GraphQL’s `DocumentNode` with attached generics for its result data and variables types.\n *\n * @remarks\n * A GraphQL {@link DocumentNode} defines both the variables it accepts on request and the `data`\n * shape it delivers on a response in the GraphQL query language.\n *\n * To bridge the gap to TypeScript, tools may be used to generate TypeScript types that define the shape\n * of `data` and `variables` ahead of time. These types are then attached to GraphQL documents using this\n * `TypedDocumentNode` type.\n *\n * Using a `DocumentNode` that is typed like this will cause any `urql` API to type its input `variables`\n * and resulting `data` using the types provided.\n *\n * @privateRemarks\n * For compatibility reasons this type has been copied and internalized from:\n * https://github.com/dotansimha/graphql-typed-document-node/blob/3711b12/packages/core/src/index.ts#L3-L10\n *\n * @see {@link https://github.com/dotansimha/graphql-typed-document-node} for more information.\n */\nexport interface DocumentDecoration<Result = any, Variables = any> {\n /** Type to support `@graphql-typed-document-node/core`\n * @internal\n */\n __apiType?: (variables: Variables) => Result;\n /** Type to support `TypedQueryDocumentNode` from `graphql`\n * @internal\n */\n __ensureTypesOfVariablesAndResultMatching?: (variables: Variables) => Result;\n}\n\nlet CONCAT_LOC_DEPTH = 0;\nconst CONCAT_LOC_SEEN = new Set();\n\ninterface LocationNode {\n loc?: Location;\n}\n\n/** Concatenates all fragments' `loc.source.body`s */\nexport function concatLocSources(fragments: readonly LocationNode[]): string {\n try {\n CONCAT_LOC_DEPTH++;\n let result = '';\n for (const fragment of fragments) {\n if (!CONCAT_LOC_SEEN.has(fragment)) {\n CONCAT_LOC_SEEN.add(fragment);\n const { loc } = fragment;\n if (loc) result += loc.source.body;\n }\n }\n return result;\n } finally {\n if (--CONCAT_LOC_DEPTH === 0) {\n CONCAT_LOC_SEEN.clear();\n }\n }\n}\n","import type { DocumentNode, DefinitionNode, Location } from '@0no-co/graphql.web';\nimport { Kind, parse as _parse } from '@0no-co/graphql.web';\n\nimport type {\n IntrospectionLikeInput,\n ScalarsLike,\n SchemaLike,\n mapIntrospection,\n addIntrospectionScalars,\n} from './introspection';\n\nimport type {\n DefinitionDecoration,\n FragmentShape,\n getFragmentsOfDocuments,\n decorateFragmentDef,\n omitFragmentRefsRec,\n makeFragmentRef,\n} from './namespace';\n\nimport type { getDocumentType } from './selection';\nimport type { parseDocument, DocumentNodeLike } from './parser';\nimport type { getVariablesType, getScalarType } from './variables';\nimport type { obj, matchOr, writable, DocumentDecoration } from './utils';\nimport { concatLocSources } from './utils';\n\n/** Abstract configuration type input for your schema and scalars.\n *\n * @remarks\n * This is used either via {@link setupSchema} or {@link initGraphQLTada} to set\n * up your schema and scalars.\n *\n * The `scalars` option is optional and can be used to set up more scalars, apart\n * from the default ones (like: Int, Float, String, Boolean).\n * It must be an object map of scalar names to their desired TypeScript types.\n *\n * @param introspection - Introspection of your schema matching {@link IntrospectionQuery}.\n * @param scalars - An object type with scalar names as keys and the corresponding scalar types as values.\n */\ninterface AbstractSetupSchema {\n introspection: IntrospectionLikeInput;\n scalars?: ScalarsLike;\n disableMasking?: boolean;\n}\n\n/** Abstract type for internal configuration\n * @internal\n */\ninterface AbstractConfig {\n isMaskingDisabled: boolean;\n}\n\n/** This is used to configure gql.tada with your introspection data and scalars.\n *\n * @remarks\n * You may extend this interface via declaration merging with your {@link IntrospectionQuery}\n * data and optionally your scalars to get proper type inference.\n * This is done by declaring a declaration for it as per the following example.\n *\n * Configuring scalars is optional and by default the standard scalrs are already\n * defined.\n *\n * This will configure the {@link graphql} export to infer types from your schema.\n * Alternatively, you may call {@link initGraphQLTada} instead.\n *\n * @param introspection - Introspection of your schema matching {@link IntrospectionQuery}.\n * @param scalars - An object type with scalar names as keys and the corresponding scalar types as values.\n *\n * @example\n * ```\n * import type { myIntrospection } from './myIntrospection';\n *\n * declare module 'gql.tada' {\n * interface setupSchema {\n * introspection: typeof myIntrospection;\n * scalars: {\n * DateTime: string;\n * Json: any;\n * };\n * }\n * }\n * ```\n */\ninterface setupSchema extends AbstractSetupSchema {\n /*empty*/\n}\n\ninterface AbstractSetupCache {\n readonly __cacheDisabled: unknown;\n [key: string]: unknown;\n}\n\ninterface setupCache extends AbstractSetupCache {}\n\ninterface GraphQLTadaAPI<Schema extends SchemaLike, Config extends AbstractConfig> {\n /** In \"multi-schema\" mode this identifies the schema.\n * @internal */\n readonly __name: Schema['name'];\n\n /** Function to create and compose GraphQL documents with result and variable types.\n *\n * @param input - A string of a GraphQL document.\n * @param fragments - An optional list of other GraphQL fragments created with this function.\n * @returns A {@link DocumentNode} with result and variables types.\n *\n * @remarks\n * This function creates a {@link DocumentNode} with result and variables types.\n * It is used with your schema in {@link setupSchema} to create a result type\n * of your queries, fragments, and variables.\n *\n * You can compose fragments into this function by passing them and a fragment\n * mask will be created for them.\n * When creating queries, the returned document of queries can be passed into GraphQL clients\n * which will then automatically infer the result and variables types.\n *\n * @example\n * ```\n * import { graphql } from 'gql.tada';\n *\n * const bookFragment = graphql(`\n * fragment BookComponent on Book {\n * id\n * title\n * }\n * `);\n *\n * const bookQuery = graphql(`\n * query Book ($id: ID!) {\n * book(id: $id) {\n * id\n * ...BookComponent\n * }\n * }\n * `, [bookFragment]);\n * ```\n *\n * @see {@link readFragment} for how to read from fragment masks.\n */\n <const In extends string, const Fragments extends readonly FragmentShape[]>(\n input: In,\n fragments?: Fragments\n ): setupCache[In] extends DocumentNodeLike\n ? unknown extends setupCache['__cacheDisabled']\n ? setupCache[In]\n : getDocumentNode<\n parseDocument<In>,\n Schema,\n getFragmentsOfDocuments<Fragments>,\n Config['isMaskingDisabled']\n >\n : getDocumentNode<\n parseDocument<In>,\n Schema,\n getFragmentsOfDocuments<Fragments>,\n Config['isMaskingDisabled']\n >;\n\n /** Function to validate the type of a given scalar or enum value.\n *\n * @param name - The name of a scalar or enum type.\n * @param value - An optional scalar value of the given type.\n * @returns A {@link DocumentNode} with result and variables types.\n *\n * @remarks\n * This function validates that a value matches an enum or scalar type\n * as a type check.\n *\n * You can use it to retrieve the type of a given scalar or enum type\n * for use in a utility function or separate component that only\n * accepts a primitive scalar or enum value.\n *\n * Note that this function does not perform runtime checks of your\n * scalar value!\n *\n * @example\n * ```\n * import { graphql } from 'gql.tada';\n *\n * type myEnum = ReturnType<graphql.scalar<'myEnum'>>;\n *\n * const myEnumValue = graphql.scalar('myEnum', 'value');\n * ```\n */\n scalar<const Name extends string, Value>(\n name: Name,\n value: getScalarType<Name, Schema> extends Value\n ? Value & getScalarType<Name, Schema>\n : getScalarType<Name, Schema>\n ): Value;\n scalar<const Name extends string, Value>(\n name: Name,\n value: getScalarType<Name, Schema> extends Value\n ? never extends Value\n ? never\n : (Value & getScalarType<Name, Schema>) | null\n : getScalarType<Name, Schema> | null\n ): Value | null;\n scalar<const Name extends string, Value>(\n name: Name,\n value: getScalarType<Name, Schema> extends Value\n ? never extends Value\n ? never\n : (Value & getScalarType<Name, Schema>) | undefined\n : getScalarType<Name, Schema> | undefined\n ): Value | undefined;\n scalar<const Name extends string, Value>(\n name: Name,\n value: getScalarType<Name, Schema> extends Value\n ? never extends Value\n ? never\n : (Value & getScalarType<Name, Schema>) | null | undefined\n : getScalarType<Name, Schema> | null | undefined\n ): Value | null | undefined;\n scalar<const Name extends string>(\n name: Name,\n value: getScalarType<Name, Schema> | undefined\n ): getScalarType<Name, Schema>;\n\n /** Function to replace a GraphQL document with a persisted document.\n *\n * @typeParam Document - The document type of {@link TadaDocumentNode}.\n * @param id - A document ID that replaces the document for the API.\n * @returns A {@link TadaPersistedDocumentNode}.\n *\n * @remarks\n * This function may be used to replace a GraphQL document with a\n * stand-in, persisted document.\n *\n * The returned document’s value won’t contain any of the document’s\n * definitions, but its type will be equivalent to the `Document` that’s\n * been passed as a generic.\n *\n * As long as the query (type parameter of `Document`) is only referenced\n * as a type in your code, it will be omitted from your output build by\n * your bundler and the resulting GraphQL document’s ID will replace your\n * document entirely.\n *\n * @example\n * ```\n * import { graphql } from 'gql.tada';\n *\n * const query = graphql(`query MyQuery { __typename }`);\n * const persisted = graphql.persisted<typeof query>('MyQuery');\n * ```\n */\n persisted<Document extends DocumentNodeLike = never>(\n documentId: string,\n document?: Document\n ): Document extends DocumentDecoration<infer Result, infer Variables>\n ? TadaPersistedDocumentNode<Result, Variables>\n : never;\n}\n\ntype schemaOfSetup<Setup extends AbstractSetupSchema> = addIntrospectionScalars<\n mapIntrospection<matchOr<IntrospectionLikeInput, Setup['introspection'], never>>,\n matchOr<ScalarsLike, Setup['scalars'], {}>\n>;\n\ntype configOfSetup<Setup extends AbstractSetupSchema> = {\n isMaskingDisabled: Setup['disableMasking'] extends true ? true : false;\n};\n\n/** Utility to type-instantiate a `graphql` document function with.\n *\n * @remarks\n * The `initGraphQLTada` type may be used to manually instantiate a type\n * as returned by `initGraphQLTada<>()` with the same input type.\n *\n * @example\n * ```\n * import { initGraphQLTada } from 'gql.tada';\n * import type { myIntrospection } from './myIntrospection';\n *\n * export const graphql: initGraphQLTada<{\n * introspection: typeof myIntrospection;\n * scalars: {\n * DateTime: string;\n * Json: any;\n * };\n * }> = initGraphQLTada();\n *\n * const query = graphql(`{ __typename }`);\n * ```\n */\nexport type initGraphQLTada<Setup extends AbstractSetupSchema> = GraphQLTadaAPI<\n schemaOfSetup<Setup>,\n configOfSetup<Setup>\n>;\n\n/** Setup function to create a typed `graphql` document function with.\n *\n * @remarks\n * `initGraphQLTada` accepts an {@link AbstractSetupSchema} configuration object as a generic\n * and returns a `graphql` function that may be used to create documents typed using your\n * GraphQL schema.\n *\n * You should use and re-export the resulting function named as `graphql` or `gql` for your\n * editor and the TypeScript language server to recognize your GraphQL documents correctly.\n *\n * @example\n * ```\n * import { initGraphQLTada } from 'gql.tada';\n * import type { myIntrospection } from './myIntrospection';\n *\n * export const graphql = initGraphQLTada<{\n * introspection: typeof myIntrospection;\n * scalars: {\n * DateTime: string;\n * Json: any;\n * };\n * }>();\n *\n * const query = graphql(`{ __typename }`);\n * ```\n */\nexport function initGraphQLTada<const Setup extends AbstractSetupSchema>(): initGraphQLTada<Setup> {\n type Schema = schemaOfSetup<Setup>;\n type Config = configOfSetup<Setup>;\n\n function graphql(input: string, fragments?: readonly TadaDocumentNode[]): any {\n const definitions = _parse(input).definitions as writable<DefinitionNode>[];\n const seen = new Set<unknown>();\n for (const document of fragments || []) {\n for (const definition of document.definitions) {\n if (definition.kind === Kind.FRAGMENT_DEFINITION && !seen.has(definition)) {\n definitions.push(definition);\n seen.add(definition);\n }\n }\n }\n\n let isFragment: boolean;\n if (\n (isFragment = definitions[0].kind === Kind.FRAGMENT_DEFINITION) &&\n definitions[0].directives\n ) {\n definitions[0].directives = definitions[0].directives.filter(\n (directive) => directive.name.value !== '_unmask'\n );\n }\n\n let loc: Location | undefined;\n return {\n kind: Kind.DOCUMENT,\n definitions,\n get loc(): Location {\n // NOTE: This is only meant for graphql-tag compatibility. When fragment documents\n // are interpolated into other documents, graphql-tag blindly reads `document.loc`\n // without checking whether it's `undefined`.\n if (!loc && isFragment) {\n const body = input + concatLocSources(fragments || []);\n return {\n start: 0,\n end: body.length,\n source: {\n body: body,\n name: 'GraphQLTada',\n locationOffset: { line: 1, column: 1 },\n },\n };\n }\n return loc;\n },\n set loc(_loc: Location) {\n loc = _loc;\n },\n } satisfies DocumentNode;\n }\n\n graphql.scalar = function scalar(_schema: Schema, value: any) {\n return value;\n };\n\n graphql.persisted = function persisted(\n documentId: string,\n document?: TadaDocumentNode\n ): TadaPersistedDocumentNode {\n return {\n kind: Kind.DOCUMENT,\n definitions: document ? document.definitions : [],\n documentId,\n };\n };\n\n return graphql as GraphQLTadaAPI<Schema, Config>;\n}\n\n/** Alias to a GraphQL parse function returning an exact document type.\n *\n * @param input - A string of a GraphQL document\n * @returns A parsed {@link DocumentNode}.\n *\n * @remarks\n * This function accepts a GraphQL document string and parses it, just like\n * GraphQL’s `parse` function. However, its return type will be the exact\n * structure of the AST parsed in types.\n */\nfunction parse<const In extends string>(input: In): parseDocument<In> {\n return _parse(input) as any;\n}\n\nexport type getDocumentNode<\n Document extends DocumentNodeLike,\n Introspection extends SchemaLike,\n Fragments extends { [name: string]: any } = {},\n isMaskingDisabled = false,\n> =\n getDocumentType<Document, Introspection, Fragments> extends never\n ? never\n : TadaDocumentNode<\n getDocumentType<Document, Introspection, Fragments>,\n getVariablesType<Document, Introspection>,\n decorateFragmentDef<Document, isMaskingDisabled>\n >;\n\n/** A GraphQL `DocumentNode` with attached types for results and variables.\n *\n * @remarks\n * This is a GraphQL {@link DocumentNode} with attached types for results and variables.\n * This is used by GraphQL clients to infer the types of results and variables and provide\n * type-safety in GraphQL documents.\n *\n * You can create typed GraphQL documents using the {@link graphql} function.\n *\n * `Result` is the type of GraphQL results, as returned by GraphQL APIs for a given query.\n * `Variables` is the type of variables, as accepted by GraphQL APIs for a given query.\n *\n * @see {@link https://github.com/dotansimha/graphql-typed-document-node} for more information.\n */\ninterface TadaDocumentNode<\n Result = { [key: string]: any },\n Variables = { [key: string]: any },\n Decoration = void,\n> extends DocumentNode,\n DocumentDecoration<Result, Variables>,\n DefinitionDecoration<Decoration> {}\n\n/** A GraphQL persisted document with attached types for results and variables.\n *\n * @remarks\n * This type still matches a GraphQL {@link DocumentNode}, but doesn’t contain\n * any definitions. At runtime, this means that this document is empty.\n *\n * Instead of its definitions, it carries an `id` property that is typically\n * used to uniquely identify the document to your GraphQL API, without disclosing\n * the shape of the query or schema transparently.\n */\ninterface TadaPersistedDocumentNode<\n Result = { [key: string]: any },\n Variables = { [key: string]: any },\n> extends DocumentNode,\n DocumentDecoration<Result, Variables> {\n definitions: readonly DefinitionNode[];\n documentId: string;\n}\n\n/** A utility type returning the `Result` type of typed GraphQL documents.\n *\n * @remarks\n * This accepts a {@link TadaDocumentNode} and returns the attached `Result` type\n * of GraphQL documents.\n */\ntype ResultOf<Document> = Document extends DocumentDecoration<infer Result, any> ? Result : never;\n\n/** A utility type returning the `Variables` type of typed GraphQL documents.\n *\n * @remarks\n * This accepts a {@link TadaDocumentNode} and returns the attached `Variables` type\n * of GraphQL documents.\n */\ntype VariablesOf<Document> =\n Document extends DocumentDecoration<any, infer Variables> ? Variables : never;\n\n/** Creates a fragment mask for a given fragment document.\n *\n * @remarks\n * When {@link graphql} is used to create a fragment and is spread into another\n * fragment or query, their result types will only contain a “reference” to the\n * fragment. This encourages isolation and is known as “fragment masking.”\n *\n * While {@link readFragment} is used to unmask these fragment masks, this utility\n * creates a fragment mask, so you can accept the masked data in the part of your\n * codebase that defines a fragment.\n *\n * @example\n * ```\n * import { FragmentOf, graphql, readFragment } from 'gql.tada';\n *\n * const bookFragment = graphql(`\n * fragment BookComponent on Book {\n * id\n * title\n * }\n * `);\n *\n * // May be called with any GraphQL data that contains a spread of `bookFragment`\n * const getBook = (data: FragmentOf<typeof bookFragment>) => {\n * // Unmasks the fragment and casts to the result type of `bookFragment`\n * const book = readFragment(bookFragment, data);\n * };\n * ```\n *\n * @see {@link readFragment} for how to read from fragment masks.\n */\ntype FragmentOf<Document extends FragmentShape> = makeFragmentRef<Document>;\n\ntype resultOrFragmentOf<Document extends FragmentShape> = FragmentOf<Document> | ResultOf<Document>;\n\ntype resultOfT<Document extends FragmentShape, T = unknown> =\n Document extends DocumentDecoration<infer Result, any>\n ? '__typename' extends keyof T\n ? Result extends { __typename?: T['__typename'] }\n ? Result\n : never\n : Result\n : never;\n\ntype resultOfFragmentsRec<\n Fragments extends readonly any[],\n Result = {},\n> = Fragments extends readonly [infer Fragment, ...infer Rest]\n ? resultOfFragmentsRec<Rest, ResultOf<Fragment> & Result>\n : Result;\n\ntype fragmentRefsOfFragmentsRec<\n Fragments extends readonly any[],\n FragmentRefs = {},\n> = Fragments extends readonly [infer Fragment, ...infer Rest]\n ? fragmentRefsOfFragmentsRec<Rest, makeFragmentRef<Fragment> & FragmentRefs>\n : obj<FragmentRefs>;\n\n/** Unmasks a fragment mask for a given fragment document and data.\n *\n * @param _document - A GraphQL document of a fragment, created using {@link graphql}.\n * @param fragment - A mask of the fragment, which can be wrapped in arrays, or nullable.\n * @returns The unmasked data of the fragment.\n *\n * @remarks\n * When {@link graphql} is used to create a fragment and is spread into another\n * fragment or query, their result types will only contain a “reference” to the\n * fragment. This encourages isolation and is known as “fragment masking.”\n *\n * This means that you must use {@link readFragment} to unmask these fragment masks\n * and get to the data. This encourages isolation and only using the data you define\n * a part of your codebase to require.\n *\n * @example\n * ```\n * import { FragmentOf, graphql, readFragment } from 'gql.tada';\n *\n * const bookFragment = graphql(`\n * fragment BookComponent on Book {\n * id\n * title\n * }\n * `);\n *\n * const getBook = (data: FragmentOf<typeof bookFragment> | null) => {\n * // Unmasks the fragment and casts to the result type of `bookFragment`\n * // This is intersected with `| null` in this case, due to the input type.\n * const book = readFragment(bookFragment, data);\n * };\n *\n * const bookQuery = graphql(`\n * query Book ($id: ID!) {\n * book(id: $id) {\n * id\n * ...BookComponent\n * }\n * }\n * `, [bookFragment]);\n *\n * const getQuery = (data: ResultOf<typeof bookQuery>) => {\n * getBook(data?.book);\n * };\n * ```\n *\n * @see {@link readFragment} for how to read from fragment masks.\n */\nfunction readFragment<const Document extends FragmentShape = never>(\n _document: Document,\n fragment: never\n): resultOfT<Document>;\n\nfunction readFragment<\n const Document extends FragmentShape,\n const T extends resultOrFragmentOf<Document> | null | undefined | {},\n>(\n _document: Document,\n fragments: readonly T[]\n): readonly (T extends resultOrFragmentOf<Document> ? resultOfT<Document, T> : T)[];\nfunction readFragment<\n const Document extends FragmentShape,\n const T extends resultOrFragmentOf<Document> | null | undefined | {},\n>(\n _document: Document,\n fragment: T\n): T extends resultOrFragmentOf<Document> ? resultOfT<Document, T> : T;\n\n// Reading arrays of fragments with required generic\nfunction readFragment<const Document extends FragmentShape>(\n fragment: readonly resultOrFragmentOf<Document>[]\n): readonly ResultOf<Document>[];\nfunction readFragment<const Document extends FragmentShape>(\n fragment: readonly (resultOrFragmentOf<Document> | null)[]\n): readonly (ResultOf<Document> | null)[];\nfunction readFragment<const Document extends FragmentShape>(\n fragment: readonly (resultOrFragmentOf<Document> | undefined)[]\n): readonly (ResultOf<Document> | undefined)[];\nfunction readFragment<const Document extends FragmentShape>(\n fragment: readonly (resultOrFragmentOf<Document> | null | undefined)[]\n): readonly (ResultOf<Document> | null | undefined)[];\n// Reading arrays of fragments with required generic with optional `{}` type\nfunction readFragment<const Document extends FragmentShape>(\n fragment: readonly (resultOrFragmentOf<Document> | {})[]\n): readonly (ResultOf<Document> | {})[];\nfunction readFragment<const Document extends FragmentShape>(\n fragment: readonly (resultOrFragmentOf<Document> | null | {})[]\n): readonly (ResultOf<Document> | null | {})[];\nfunction readFragment<const Document extends FragmentShape>(\n fragment: readonly (resultOrFragmentOf<Document> | undefined | {})[]\n): readonly (ResultOf<Document> | undefined | {})[];\nfunction readFragment<const Document extends FragmentShape>(\n fragment: readonly (resultOrFragmentOf<Document> | null | undefined | {})[]\n): readonly (ResultOf<Document> | null | undefined | {})[];\n// Reading fragments with required generic\nfunction readFragment<const Document extends FragmentShape>(\n fragment: resultOrFragmentOf<Document>\n): ResultOf<Document>;\nfunction readFragment<const Document extends FragmentShape>(\n fragment: resultOrFragmentOf<Document> | null\n): ResultOf<Document> | null;\nfunction readFragment<const Document extends FragmentShape>(\n fragment: resultOrFragmentOf<Document> | undefined\n): ResultOf<Document> | undefined;\nfunction readFragment<const Document extends FragmentShape>(\n fragment: resultOrFragmentOf<Document> | null | undefined\n): ResultOf<Document> | null | undefined;\n// Reading fragments with required generic with optional `{}` type\nfunction readFragment<const Document extends FragmentShape>(\n fragment: resultOrFragmentOf<Document> | {}\n): ResultOf<Document> | {};\nfunction readFragment<const Document extends FragmentShape>(\n fragment: resultOrFragmentOf<Document> | null | {}\n): ResultOf<Document> | null | {};\nfunction readFragment<const Document extends FragmentShape>(\n fragment: resultOrFragmentOf<Document> | undefined | {}\n): ResultOf<Document> | undefined | {};\nfunction readFragment<const Document extends FragmentShape>(\n fragment: resultOrFragmentOf<Document> | null | undefined | {}\n): ResultOf<Document> | null | undefined | {};\n\nfunction readFragment(...args: [unknown] | [unknown, unknown]) {\n return args.length === 2 ? args[1] : args[0];\n}\n\n/** For testing, masks fragment data for given data and fragments.\n *\n * @param _fragments - A list of GraphQL documents of fragments, created using {@link graphql}.\n * @param data - The combined result data of the fragments, which can be wrapped in arrays.\n * @returns The masked data of the fragments.\n *\n * @remarks\n * When creating test data, you may define data for fragments that’s unmasked, making it\n * unusable in parent fragments or queries that require masked data.\n *\n * This means that you may have to use {@link maskFragments} to mask your data first\n * for TypeScript to not report an error.\n *\n * @example\n * ```\n * import { FragmentOf, ResultOf, graphql, maskFragments } from 'gql.tada';\n *\n * const bookFragment = graphql(`\n * fragment BookComponent on Book {\n * id\n * title\n * }\n * `);\n *\n * const data = maskFragments([bookFragment], { id: 'id', title: 'book' });\n * ```\n *\n * @see {@link readFragment} for how to read from fragment masks (i.e. the reverse)\n */\nfunction maskFragments<const Fragments extends readonly FragmentShape[]>(\n _fragments: Fragments,\n fragment: resultOfFragmentsRec<Fragments>\n): fragmentRefsOfFragmentsRec<Fragments>;\nfunction maskFragments<const Fragments extends readonly FragmentShape[]>(\n _fragments: Fragments,\n fragment: resultOfFragmentsRec<Fragments> | null\n): fragmentRefsOfFragmentsRec<Fragments> | null;\nfunction maskFragments<const Fragments extends readonly FragmentShape[]>(\n _fragments: Fragments,\n fragment: resultOfFragmentsRec<Fragments> | undefined\n): fragmentRefsOfFragmentsRec<Fragments> | undefined;\nfunction maskFragments<const Fragments extends readonly FragmentShape[]>(\n _fragments: Fragments,\n fragment: resultOfFragmentsRec<Fragments> | null | undefined\n): fragmentRefsOfFragmentsRec<Fragments> | null | undefined;\nfunction maskFragments<const Fragments extends readonly FragmentShape[]>(\n _fragments: Fragments,\n fragment: readonly resultOfFragmentsRec<Fragments>[]\n): readonly fragmentRefsOfFragmentsRec<Fragments>[];\nfunction maskFragments<const Fragments extends readonly FragmentShape[]>(\n _fragments: Fragments,\n fragment: readonly (resultOfFragmentsRec<Fragments> | null)[]\n): readonly (fragmentRefsOfFragmentsRec<Fragments> | null)[];\nfunction maskFragments<const Fragments extends readonly FragmentShape[]>(\n _fragments: Fragments,\n fragment: readonly (resultOfFragmentsRec<Fragments> | undefined)[]\n): readonly (fragmentRefsOfFragmentsRec<Fragments> | undefined)[];\nfunction maskFragments<const Fragments extends readonly FragmentShape[]>(\n _fragments: Fragments,\n fragment: readonly (resultOfFragmentsRec<Fragments> | null | undefined)[]\n): readonly (fragmentRefsOfFragmentsRec<Fragments> | null | undefined)[];\nfunction maskFragments(_fragments: unknown, data: unknown) {\n return data;\n}\n\n/** For testing, converts document data without fragment refs to their result type.\n *\n * @param _document - A GraphQL document, created using {@link graphql}.\n * @param data - The result data of the GraphQL document with optional fragment refs.\n * @returns The masked result data of the document.\n *\n * @remarks\n * When creating test data, you may define data for documents that’s unmasked, but\n * need to cast the data to match the result type of your document.\n *\n * This means that you may have to use {@link unsafe_readResult} to cast\n * them to the result type, instead of doing `as any as ResultOf<typeof document>`.\n *\n * This function is inherently unsafe, since it doesn't check that your document\n * actually contains the masked fragment data!\n *\n * @example\n * ```\n * import { FragmentOf, ResultOf, graphql, unsafe_readResult } from 'gql.tada';\n *\n * const bookFragment = graphql(`\n * fragment BookComponent on Book {\n * id\n * title\n * }\n * `);\n *\n * const query = graphql(`\n * query {\n * book {\n * ...BookComponent\n * }\n * }\n * `, [bookFragment]);\n *\n * const data = unsafe_readResult(query, { book: { id: 'id', title: 'book' } });\n * ```\n *\n * @see {@link readFragment} for how to read from fragment masks (i.e. the reverse)\n */\nfunction unsafe_readResult<\n const Document extends DocumentDecoration<any, any>,\n const Data extends omitFragmentRefsRec<ResultOf<Document>>,\n>(_document: Document, data: Data): ResultOf<Document> {\n return data as any;\n}\n\nconst graphql: initGraphQLTada<setupSchema> = initGraphQLTada();\n\nexport { parse, graphql, readFragment, maskFragments, unsafe_readResult };\n\nexport type {\n setupCache,\n setupSchema,\n parseDocument,\n AbstractSetupSchema,\n AbstractSetupCache,\n GraphQLTadaAPI,\n TadaDocumentNode,\n TadaPersistedDocumentNode,\n ResultOf,\n VariablesOf,\n FragmentOf,\n};\n"],"names":["CONCAT_LOC_DEPTH","CONCAT_LOC_SEEN","Set","initGraphQLTada","graphql","input","fragments","definitions","_parse","seen","document","definition","kind","Kind","FRAGMENT_DEFINITION","has","push","add","isFragment","directives","filter","directive","name","value","loc","DOCUMENT","body","concatLocSources","result","fragment","source","clear","start","end","length","locationOffset","line","column","_loc","scalar","_schema","persisted","documentId","maskFragments","_fragments","data","parse","readFragment","args","unsafe_readResult","_document"],"mappings":";;;;;;AAuDA,IAAIA,IAAmB;;AACvB,IAAMC,IAAkB,IAAIC;;ACmQrB,SAASC;EAId,SAASC,QAAQC,GAAeC;IAC9B,IAAMC,IAAcC,EAAAA,MAAOH,GAAOE;IAClC,IAAME,IAAO,IAAIP;IACjB,KAAK,IAAMQ,KAAYJ,KAAa;MAClC,KAAK,IAAMK,KAAcD,EAASH;QAChC,IAAII,EAAWC,SAASC,OAAKC,wBAAwBL,EAAKM,IAAIJ,IAAa;UACzEJ,EAAYS,KAAKL;UACjBF,EAAKQ,IAAIN;AACX;;;IAIJ,IAAIO;IACJ,KACGA,IAAaX,EAAY,GAAGK,SAASC,EAAIA,KAACC,wBAC3CP,EAAY,GAAGY;MAEfZ,EAAY,GAAGY,aAAaZ,EAAY,GAAGY,WAAWC,QACnDC,KAAuC,cAAzBA,EAAUC,KAAKC;;IAIlC,IAAIC;IACJ,OAAO;MACLZ,MAAMC,EAAIA,KAACY;MACXlB;MACA,OAAIiB;QAIF,KAAKA,KAAON,GAAY;UACtB,IAAMQ,IAAOrB,ID/RhB,SAASsB,iBAAiBrB;YAC/B;cACEN;cACA,IAAI4B,IAAS;cACb,KAAK,IAAMC,KAAYvB;gBACrB,KAAKL,EAAgBc,IAAIc,IAAW;kBAClC5B,EAAgBgB,IAAIY;kBACpB,KAAML,KAAEA,KAAQK;kBAChB,IAAIL;oBAAKI,KAAUJ,EAAIM,OAAOJ;;AAChC;;cAEF,OAAOE;AACT,cAAU;cACR,IAA2B,OAArB5B;gBACJC,EAAgB8B;;AAEpB;AACF,WC8Q+BJ,CAAiBrB,KAAa;UACnD,OAAO;YACL0B,OAAO;YACPC,KAAKP,EAAKQ;YACVJ,QAAQ;cACNJ,MAAMA;cACNJ,MAAM;cACNa,gBAAgB;gBAAEC,MAAM;gBAAGC,QAAQ;;;;AAGzC;QACA,OAAOb;AACR;MACD,OAAIA,CAAIc;QACNd,IAAMc;AACR;;AAEJ;EAEAlC,QAAQmC,SAAS,SAASA,OAAOC,GAAiBjB;IAChD,OAAOA;;EAGTnB,QAAQqC,YAAY,SAASA,UAC3BC,GACAhC;IAEA,OAAO;MACLE,MAAMC,EAAIA,KAACY;MACXlB,aAAaG,IAAWA,EAASH,cAAc;MAC/CmC;;;EAIJ,OAAOtC;AACT;;AA+XA,IAAMA,IAAwCD;;;;;;wBAnD9C,SAASwC,cAAcC,GAAqBC;EAC1C,OAAOA;AACT;;gBAlUA,SAASC,MAA+BzC;EACtC,OAAOG,EAAAA,MAAOH;AAChB;;uBA6PA,SAAS0C,gBAAgBC;EACvB,OAAuB,MAAhBA,EAAKd,SAAec,EAAK,KAAKA,EAAK;AAC5C;;4BA2GA,SAASC,kBAGPC,GAAqBL;EACrB,OAAOA;AACT"}
|
|
1
|
+
{"version":3,"file":"gql-tada.js","sources":["../src/utils.ts","../src/api.ts"],"sourcesContent":["import type { DocumentNode, Location } from '@0no-co/graphql.web';\n\n/** Returns `T` if it matches `Constraint` without being equal to it. Failing this evaluates to `Fallback` otherwise. */\nexport type matchOr<Constraint, T, Fallback> = Constraint extends T\n ? Fallback\n : T extends Constraint\n ? T\n : Fallback;\n\n/** Flattens a given object type.\n *\n * @remarks\n * This is typically used to make a TypeScript type appear as a flat object,\n * both in terms of type checking and for type hints and the tsserver output.\n */\nexport type obj<T> = T extends { [key: string | number]: any } ? { [K in keyof T]: T[K] } : never;\n\n/** Turns a given union to an intersection type. */\nexport type overload<T> = (T extends any ? (x: T) => void : never) extends (x: infer U) => void\n ? U & T\n : never;\n\n/** Marks all properties as writable */\nexport type writable<T> = { -readonly [K in keyof T]: T[K] };\n\n/** Annotations for GraphQL’s `DocumentNode` with attached generics for its result data and variables types.\n *\n * @remarks\n * A GraphQL {@link DocumentNode} defines both the variables it accepts on request and the `data`\n * shape it delivers on a response in the GraphQL query language.\n *\n * To bridge the gap to TypeScript, tools may be used to generate TypeScript types that define the shape\n * of `data` and `variables` ahead of time. These types are then attached to GraphQL documents using this\n * `TypedDocumentNode` type.\n *\n * Using a `DocumentNode` that is typed like this will cause any `urql` API to type its input `variables`\n * and resulting `data` using the types provided.\n *\n * @privateRemarks\n * For compatibility reasons this type has been copied and internalized from:\n * https://github.com/dotansimha/graphql-typed-document-node/blob/3711b12/packages/core/src/index.ts#L3-L10\n *\n * @see {@link https://github.com/dotansimha/graphql-typed-document-node} for more information.\n */\nexport interface DocumentDecoration<Result = any, Variables = any> {\n /** Type to support `@graphql-typed-document-node/core`\n * @internal\n */\n __apiType?: (variables: Variables) => Result;\n /** Type to support `TypedQueryDocumentNode` from `graphql`\n * @internal\n */\n __ensureTypesOfVariablesAndResultMatching?: (variables: Variables) => Result;\n}\n\nlet CONCAT_LOC_DEPTH = 0;\nconst CONCAT_LOC_SEEN = new Set();\n\ninterface LocationNode {\n loc?: Location;\n}\n\n/** Concatenates all fragments' `loc.source.body`s */\nexport function concatLocSources(fragments: readonly LocationNode[]): string {\n try {\n CONCAT_LOC_DEPTH++;\n let result = '';\n for (const fragment of fragments) {\n if (!CONCAT_LOC_SEEN.has(fragment)) {\n CONCAT_LOC_SEEN.add(fragment);\n const { loc } = fragment;\n if (loc) result += loc.source.body;\n }\n }\n return result;\n } finally {\n if (--CONCAT_LOC_DEPTH === 0) {\n CONCAT_LOC_SEEN.clear();\n }\n }\n}\n","import type { DocumentNode, DefinitionNode, Location } from '@0no-co/graphql.web';\nimport { Kind, parse as _parse } from '@0no-co/graphql.web';\n\nimport type {\n IntrospectionLikeInput,\n ScalarsLike,\n SchemaLike,\n mapIntrospection,\n addIntrospectionScalars,\n} from './introspection';\n\nimport type {\n DefinitionDecoration,\n FragmentShape,\n getFragmentsOfDocuments,\n decorateFragmentDef,\n omitFragmentRefsRec,\n makeFragmentRef,\n} from './namespace';\n\nimport type { getDocumentType } from './selection';\nimport type { parseDocument, DocumentNodeLike } from './parser';\nimport type { getVariablesType, getScalarType } from './variables';\nimport type { obj, matchOr, writable, DocumentDecoration } from './utils';\nimport { concatLocSources } from './utils';\n\n/** Abstract configuration type input for your schema and scalars.\n *\n * @remarks\n * This is used either via {@link setupSchema} or {@link initGraphQLTada} to set\n * up your schema and scalars.\n *\n * The `scalars` option is optional and can be used to set up more scalars, apart\n * from the default ones (like: Int, Float, String, Boolean).\n * It must be an object map of scalar names to their desired TypeScript types.\n *\n * @param introspection - Introspection of your schema matching {@link IntrospectionQuery}.\n * @param scalars - An object type with scalar names as keys and the corresponding scalar types as values.\n */\ninterface AbstractSetupSchema {\n introspection: IntrospectionLikeInput;\n scalars?: ScalarsLike;\n disableMasking?: boolean;\n}\n\n/** Abstract type for internal configuration\n * @internal\n */\ninterface AbstractConfig {\n isMaskingDisabled: boolean;\n}\n\n/** This is used to configure gql.tada with your introspection data and scalars.\n *\n * @remarks\n * You may extend this interface via declaration merging with your {@link IntrospectionQuery}\n * data and optionally your scalars to get proper type inference.\n * This is done by declaring a declaration for it as per the following example.\n *\n * Configuring scalars is optional and by default the standard scalrs are already\n * defined.\n *\n * This will configure the {@link graphql} export to infer types from your schema.\n * Alternatively, you may call {@link initGraphQLTada} instead.\n *\n * @param introspection - Introspection of your schema matching {@link IntrospectionQuery}.\n * @param scalars - An object type with scalar names as keys and the corresponding scalar types as values.\n *\n * @example\n * ```\n * import type { myIntrospection } from './myIntrospection';\n *\n * declare module 'gql.tada' {\n * interface setupSchema {\n * introspection: typeof myIntrospection;\n * scalars: {\n * DateTime: string;\n * Json: any;\n * };\n * }\n * }\n * ```\n */\ninterface setupSchema extends AbstractSetupSchema {\n /*empty*/\n}\n\ninterface AbstractSetupCache {\n readonly __cacheDisabled: unknown;\n}\n\ninterface setupCache extends AbstractSetupCache {}\n\ninterface GraphQLTadaAPI<Schema extends SchemaLike, Config extends AbstractConfig> {\n /** In \"multi-schema\" mode this identifies the schema.\n * @internal */\n readonly __name: Schema['name'];\n\n /** Function to create and compose GraphQL documents with result and variable types.\n *\n * @param input - A string of a GraphQL document.\n * @param fragments - An optional list of other GraphQL fragments created with this function.\n * @returns A {@link DocumentNode} with result and variables types.\n *\n * @remarks\n * This function creates a {@link DocumentNode} with result and variables types.\n * It is used with your schema in {@link setupSchema} to create a result type\n * of your queries, fragments, and variables.\n *\n * You can compose fragments into this function by passing them and a fragment\n * mask will be created for them.\n * When creating queries, the returned document of queries can be passed into GraphQL clients\n * which will then automatically infer the result and variables types.\n *\n * @example\n * ```\n * import { graphql } from 'gql.tada';\n *\n * const bookFragment = graphql(`\n * fragment BookComponent on Book {\n * id\n * title\n * }\n * `);\n *\n * const bookQuery = graphql(`\n * query Book ($id: ID!) {\n * book(id: $id) {\n * id\n * ...BookComponent\n * }\n * }\n * `, [bookFragment]);\n * ```\n *\n * @see {@link readFragment} for how to read from fragment masks.\n */\n <\n const In extends unknown extends setupCache['__cacheDisabled'] ? keyof setupCache : never,\n const Fragments extends readonly FragmentShape[],\n >(\n input: In,\n fragments?: Fragments\n ): setupCache[In];\n // Overload for cache miss\n <const In extends string, const Fragments extends readonly FragmentShape[]>(\n input: In,\n fragments?: Fragments\n ): getDocumentNode<\n parseDocument<In>,\n Schema,\n getFragmentsOfDocuments<Fragments>,\n Config['isMaskingDisabled']\n >;\n\n /** Function to validate the type of a given scalar or enum value.\n *\n * @param name - The name of a scalar or enum type.\n * @param value - An optional scalar value of the given type.\n * @returns A {@link DocumentNode} with result and variables types.\n *\n * @remarks\n * This function validates that a value matches an enum or scalar type\n * as a type check.\n *\n * You can use it to retrieve the type of a given scalar or enum type\n * for use in a utility function or separate component that only\n * accepts a primitive scalar or enum value.\n *\n * Note that this function does not perform runtime checks of your\n * scalar value!\n *\n * @example\n * ```\n * import { graphql } from 'gql.tada';\n *\n * type myEnum = ReturnType<graphql.scalar<'myEnum'>>;\n *\n * const myEnumValue = graphql.scalar('myEnum', 'value');\n * ```\n */\n scalar<const Name extends string, Value>(\n name: Name,\n value: getScalarType<Name, Schema> extends Value\n ? Value & getScalarType<Name, Schema>\n : getScalarType<Name, Schema>\n ): Value;\n scalar<const Name extends string, Value>(\n name: Name,\n value: getScalarType<Name, Schema> extends Value\n ? never extends Value\n ? never\n : (Value & getScalarType<Name, Schema>) | null\n : getScalarType<Name, Schema> | null\n ): Value | null;\n scalar<const Name extends string, Value>(\n name: Name,\n value: getScalarType<Name, Schema> extends Value\n ? never extends Value\n ? never\n : (Value & getScalarType<Name, Schema>) | undefined\n : getScalarType<Name, Schema> | undefined\n ): Value | undefined;\n scalar<const Name extends string, Value>(\n name: Name,\n value: getScalarType<Name, Schema> extends Value\n ? never extends Value\n ? never\n : (Value & getScalarType<Name, Schema>) | null | undefined\n : getScalarType<Name, Schema> | null | undefined\n ): Value | null | undefined;\n scalar<const Name extends string>(\n name: Name,\n value: getScalarType<Name, Schema> | undefined\n ): getScalarType<Name, Schema>;\n\n /** Function to replace a GraphQL document with a persisted document.\n *\n * @typeParam Document - The document type of {@link TadaDocumentNode}.\n * @param id - A document ID that replaces the document for the API.\n * @returns A {@link TadaPersistedDocumentNode}.\n *\n * @remarks\n * This function may be used to replace a GraphQL document with a\n * stand-in, persisted document.\n *\n * The returned document’s value won’t contain any of the document’s\n * definitions, but its type will be equivalent to the `Document` that’s\n * been passed as a generic.\n *\n * As long as the query (type parameter of `Document`) is only referenced\n * as a type in your code, it will be omitted from your output build by\n * your bundler and the resulting GraphQL document’s ID will replace your\n * document entirely.\n *\n * @example\n * ```\n * import { graphql } from 'gql.tada';\n *\n * const query = graphql(`query MyQuery { __typename }`);\n * const persisted = graphql.persisted<typeof query>('MyQuery');\n * ```\n */\n persisted<Document extends DocumentNodeLike = never>(\n documentId: string,\n document?: Document\n ): Document extends DocumentDecoration<infer Result, infer Variables>\n ? TadaPersistedDocumentNode<Result, Variables>\n : never;\n}\n\ntype schemaOfSetup<Setup extends AbstractSetupSchema> = addIntrospectionScalars<\n mapIntrospection<matchOr<IntrospectionLikeInput, Setup['introspection'], never>>,\n matchOr<ScalarsLike, Setup['scalars'], {}>\n>;\n\ntype configOfSetup<Setup extends AbstractSetupSchema> = {\n isMaskingDisabled: Setup['disableMasking'] extends true ? true : false;\n};\n\n/** Utility to type-instantiate a `graphql` document function with.\n *\n * @remarks\n * The `initGraphQLTada` type may be used to manually instantiate a type\n * as returned by `initGraphQLTada<>()` with the same input type.\n *\n * @example\n * ```\n * import { initGraphQLTada } from 'gql.tada';\n * import type { myIntrospection } from './myIntrospection';\n *\n * export const graphql: initGraphQLTada<{\n * introspection: typeof myIntrospection;\n * scalars: {\n * DateTime: string;\n * Json: any;\n * };\n * }> = initGraphQLTada();\n *\n * const query = graphql(`{ __typename }`);\n * ```\n */\nexport type initGraphQLTada<Setup extends AbstractSetupSchema> = GraphQLTadaAPI<\n schemaOfSetup<Setup>,\n configOfSetup<Setup>\n>;\n\n/** Setup function to create a typed `graphql` document function with.\n *\n * @remarks\n * `initGraphQLTada` accepts an {@link AbstractSetupSchema} configuration object as a generic\n * and returns a `graphql` function that may be used to create documents typed using your\n * GraphQL schema.\n *\n * You should use and re-export the resulting function named as `graphql` or `gql` for your\n * editor and the TypeScript language server to recognize your GraphQL documents correctly.\n *\n * @example\n * ```\n * import { initGraphQLTada } from 'gql.tada';\n * import type { myIntrospection } from './myIntrospection';\n *\n * export const graphql = initGraphQLTada<{\n * introspection: typeof myIntrospection;\n * scalars: {\n * DateTime: string;\n * Json: any;\n * };\n * }>();\n *\n * const query = graphql(`{ __typename }`);\n * ```\n */\nexport function initGraphQLTada<const Setup extends AbstractSetupSchema>(): initGraphQLTada<Setup> {\n type Schema = schemaOfSetup<Setup>;\n type Config = configOfSetup<Setup>;\n\n function graphql(input: string, fragments?: readonly TadaDocumentNode[]): any {\n const definitions = _parse(input).definitions as writable<DefinitionNode>[];\n const seen = new Set<unknown>();\n for (const document of fragments || []) {\n for (const definition of document.definitions) {\n if (definition.kind === Kind.FRAGMENT_DEFINITION && !seen.has(definition)) {\n definitions.push(definition);\n seen.add(definition);\n }\n }\n }\n\n let isFragment: boolean;\n if (\n (isFragment = definitions[0].kind === Kind.FRAGMENT_DEFINITION) &&\n definitions[0].directives\n ) {\n definitions[0].directives = definitions[0].directives.filter(\n (directive) => directive.name.value !== '_unmask'\n );\n }\n\n let loc: Location | undefined;\n return {\n kind: Kind.DOCUMENT,\n definitions,\n get loc(): Location {\n // NOTE: This is only meant for graphql-tag compatibility. When fragment documents\n // are interpolated into other documents, graphql-tag blindly reads `document.loc`\n // without checking whether it's `undefined`.\n if (!loc && isFragment) {\n const body = input + concatLocSources(fragments || []);\n return {\n start: 0,\n end: body.length,\n source: {\n body: body,\n name: 'GraphQLTada',\n locationOffset: { line: 1, column: 1 },\n },\n };\n }\n return loc;\n },\n set loc(_loc: Location) {\n loc = _loc;\n },\n } satisfies DocumentNode;\n }\n\n graphql.scalar = function scalar(_schema: Schema, value: any) {\n return value;\n };\n\n graphql.persisted = function persisted(\n documentId: string,\n document?: TadaDocumentNode\n ): TadaPersistedDocumentNode {\n return {\n kind: Kind.DOCUMENT,\n definitions: document ? document.definitions : [],\n documentId,\n };\n };\n\n return graphql as GraphQLTadaAPI<Schema, Config>;\n}\n\n/** Alias to a GraphQL parse function returning an exact document type.\n *\n * @param input - A string of a GraphQL document\n * @returns A parsed {@link DocumentNode}.\n *\n * @remarks\n * This function accepts a GraphQL document string and parses it, just like\n * GraphQL’s `parse` function. However, its return type will be the exact\n * structure of the AST parsed in types.\n */\nfunction parse<const In extends string>(input: In): parseDocument<In> {\n return _parse(input) as any;\n}\n\nexport type getDocumentNode<\n Document extends DocumentNodeLike,\n Introspection extends SchemaLike,\n Fragments extends { [name: string]: any } = {},\n isMaskingDisabled = false,\n> =\n getDocumentType<Document, Introspection, Fragments> extends never\n ? never\n : TadaDocumentNode<\n getDocumentType<Document, Introspection, Fragments>,\n getVariablesType<Document, Introspection>,\n decorateFragmentDef<Document, isMaskingDisabled>\n >;\n\n/** A GraphQL `DocumentNode` with attached types for results and variables.\n *\n * @remarks\n * This is a GraphQL {@link DocumentNode} with attached types for results and variables.\n * This is used by GraphQL clients to infer the types of results and variables and provide\n * type-safety in GraphQL documents.\n *\n * You can create typed GraphQL documents using the {@link graphql} function.\n *\n * `Result` is the type of GraphQL results, as returned by GraphQL APIs for a given query.\n * `Variables` is the type of variables, as accepted by GraphQL APIs for a given query.\n *\n * @see {@link https://github.com/dotansimha/graphql-typed-document-node} for more information.\n */\ninterface TadaDocumentNode<\n Result = { [key: string]: any },\n Variables = { [key: string]: any },\n Decoration = void,\n> extends DocumentNode,\n DocumentDecoration<Result, Variables>,\n DefinitionDecoration<Decoration> {}\n\n/** A GraphQL persisted document with attached types for results and variables.\n *\n * @remarks\n * This type still matches a GraphQL {@link DocumentNode}, but doesn’t contain\n * any definitions. At runtime, this means that this document is empty.\n *\n * Instead of its definitions, it carries an `id` property that is typically\n * used to uniquely identify the document to your GraphQL API, without disclosing\n * the shape of the query or schema transparently.\n */\ninterface TadaPersistedDocumentNode<\n Result = { [key: string]: any },\n Variables = { [key: string]: any },\n> extends DocumentNode,\n DocumentDecoration<Result, Variables> {\n definitions: readonly DefinitionNode[];\n documentId: string;\n}\n\n/** A utility type returning the `Result` type of typed GraphQL documents.\n *\n * @remarks\n * This accepts a {@link TadaDocumentNode} and returns the attached `Result` type\n * of GraphQL documents.\n */\ntype ResultOf<Document> = Document extends DocumentDecoration<infer Result, any> ? Result : never;\n\n/** A utility type returning the `Variables` type of typed GraphQL documents.\n *\n * @remarks\n * This accepts a {@link TadaDocumentNode} and returns the attached `Variables` type\n * of GraphQL documents.\n */\ntype VariablesOf<Document> =\n Document extends DocumentDecoration<any, infer Variables> ? Variables : never;\n\n/** Creates a fragment mask for a given fragment document.\n *\n * @remarks\n * When {@link graphql} is used to create a fragment and is spread into another\n * fragment or query, their result types will only contain a “reference” to the\n * fragment. This encourages isolation and is known as “fragment masking.”\n *\n * While {@link readFragment} is used to unmask these fragment masks, this utility\n * creates a fragment mask, so you can accept the masked data in the part of your\n * codebase that defines a fragment.\n *\n * @example\n * ```\n * import { FragmentOf, graphql, readFragment } from 'gql.tada';\n *\n * const bookFragment = graphql(`\n * fragment BookComponent on Book {\n * id\n * title\n * }\n * `);\n *\n * // May be called with any GraphQL data that contains a spread of `bookFragment`\n * const getBook = (data: FragmentOf<typeof bookFragment>) => {\n * // Unmasks the fragment and casts to the result type of `bookFragment`\n * const book = readFragment(bookFragment, data);\n * };\n * ```\n *\n * @see {@link readFragment} for how to read from fragment masks.\n */\ntype FragmentOf<Document extends FragmentShape> = makeFragmentRef<Document>;\n\ntype resultOrFragmentOf<Document extends FragmentShape> = FragmentOf<Document> | ResultOf<Document>;\n\ntype resultOfT<Document extends FragmentShape, T = unknown> =\n Document extends DocumentDecoration<infer Result, any>\n ? '__typename' extends keyof T\n ? Result extends { __typename?: T['__typename'] }\n ? Result\n : never\n : Result\n : never;\n\ntype resultOfFragmentsRec<\n Fragments extends readonly any[],\n Result = {},\n> = Fragments extends readonly [infer Fragment, ...infer Rest]\n ? resultOfFragmentsRec<Rest, ResultOf<Fragment> & Result>\n : Result;\n\ntype fragmentRefsOfFragmentsRec<\n Fragments extends readonly any[],\n FragmentRefs = {},\n> = Fragments extends readonly [infer Fragment, ...infer Rest]\n ? fragmentRefsOfFragmentsRec<Rest, makeFragmentRef<Fragment> & FragmentRefs>\n : obj<FragmentRefs>;\n\n/** Unmasks a fragment mask for a given fragment document and data.\n *\n * @param _document - A GraphQL document of a fragment, created using {@link graphql}.\n * @param fragment - A mask of the fragment, which can be wrapped in arrays, or nullable.\n * @returns The unmasked data of the fragment.\n *\n * @remarks\n * When {@link graphql} is used to create a fragment and is spread into another\n * fragment or query, their result types will only contain a “reference” to the\n * fragment. This encourages isolation and is known as “fragment masking.”\n *\n * This means that you must use {@link readFragment} to unmask these fragment masks\n * and get to the data. This encourages isolation and only using the data you define\n * a part of your codebase to require.\n *\n * @example\n * ```\n * import { FragmentOf, graphql, readFragment } from 'gql.tada';\n *\n * const bookFragment = graphql(`\n * fragment BookComponent on Book {\n * id\n * title\n * }\n * `);\n *\n * const getBook = (data: FragmentOf<typeof bookFragment> | null) => {\n * // Unmasks the fragment and casts to the result type of `bookFragment`\n * // This is intersected with `| null` in this case, due to the input type.\n * const book = readFragment(bookFragment, data);\n * };\n *\n * const bookQuery = graphql(`\n * query Book ($id: ID!) {\n * book(id: $id) {\n * id\n * ...BookComponent\n * }\n * }\n * `, [bookFragment]);\n *\n * const getQuery = (data: ResultOf<typeof bookQuery>) => {\n * getBook(data?.book);\n * };\n * ```\n *\n * @see {@link readFragment} for how to read from fragment masks.\n */\nfunction readFragment<const Document extends FragmentShape = never>(\n _document: Document,\n fragment: never\n): resultOfT<Document>;\n\nfunction readFragment<\n const Document extends FragmentShape,\n const T extends resultOrFragmentOf<Document> | null | undefined | {},\n>(\n _document: Document,\n fragments: readonly T[]\n): readonly (T extends resultOrFragmentOf<Document> ? resultOfT<Document, T> : T)[];\nfunction readFragment<\n const Document extends FragmentShape,\n const T extends resultOrFragmentOf<Document> | null | undefined | {},\n>(\n _document: Document,\n fragment: T\n): T extends resultOrFragmentOf<Document> ? resultOfT<Document, T> : T;\n\n// Reading arrays of fragments with required generic\nfunction readFragment<const Document extends FragmentShape>(\n fragment: readonly resultOrFragmentOf<Document>[]\n): readonly ResultOf<Document>[];\nfunction readFragment<const Document extends FragmentShape>(\n fragment: readonly (resultOrFragmentOf<Document> | null)[]\n): readonly (ResultOf<Document> | null)[];\nfunction readFragment<const Document extends FragmentShape>(\n fragment: readonly (resultOrFragmentOf<Document> | undefined)[]\n): readonly (ResultOf<Document> | undefined)[];\nfunction readFragment<const Document extends FragmentShape>(\n fragment: readonly (resultOrFragmentOf<Document> | null | undefined)[]\n): readonly (ResultOf<Document> | null | undefined)[];\n// Reading arrays of fragments with required generic with optional `{}` type\nfunction readFragment<const Document extends FragmentShape>(\n fragment: readonly (resultOrFragmentOf<Document> | {})[]\n): readonly (ResultOf<Document> | {})[];\nfunction readFragment<const Document extends FragmentShape>(\n fragment: readonly (resultOrFragmentOf<Document> | null | {})[]\n): readonly (ResultOf<Document> | null | {})[];\nfunction readFragment<const Document extends FragmentShape>(\n fragment: readonly (resultOrFragmentOf<Document> | undefined | {})[]\n): readonly (ResultOf<Document> | undefined | {})[];\nfunction readFragment<const Document extends FragmentShape>(\n fragment: readonly (resultOrFragmentOf<Document> | null | undefined | {})[]\n): readonly (ResultOf<Document> | null | undefined | {})[];\n// Reading fragments with required generic\nfunction readFragment<const Document extends FragmentShape>(\n fragment: resultOrFragmentOf<Document>\n): ResultOf<Document>;\nfunction readFragment<const Document extends FragmentShape>(\n fragment: resultOrFragmentOf<Document> | null\n): ResultOf<Document> | null;\nfunction readFragment<const Document extends FragmentShape>(\n fragment: resultOrFragmentOf<Document> | undefined\n): ResultOf<Document> | undefined;\nfunction readFragment<const Document extends FragmentShape>(\n fragment: resultOrFragmentOf<Document> | null | undefined\n): ResultOf<Document> | null | undefined;\n// Reading fragments with required generic with optional `{}` type\nfunction readFragment<const Document extends FragmentShape>(\n fragment: resultOrFragmentOf<Document> | {}\n): ResultOf<Document> | {};\nfunction readFragment<const Document extends FragmentShape>(\n fragment: resultOrFragmentOf<Document> | null | {}\n): ResultOf<Document> | null | {};\nfunction readFragment<const Document extends FragmentShape>(\n fragment: resultOrFragmentOf<Document> | undefined | {}\n): ResultOf<Document> | undefined | {};\nfunction readFragment<const Document extends FragmentShape>(\n fragment: resultOrFragmentOf<Document> | null | undefined | {}\n): ResultOf<Document> | null | undefined | {};\n\nfunction readFragment(...args: [unknown] | [unknown, unknown]) {\n return args.length === 2 ? args[1] : args[0];\n}\n\n/** For testing, masks fragment data for given data and fragments.\n *\n * @param _fragments - A list of GraphQL documents of fragments, created using {@link graphql}.\n * @param data - The combined result data of the fragments, which can be wrapped in arrays.\n * @returns The masked data of the fragments.\n *\n * @remarks\n * When creating test data, you may define data for fragments that’s unmasked, making it\n * unusable in parent fragments or queries that require masked data.\n *\n * This means that you may have to use {@link maskFragments} to mask your data first\n * for TypeScript to not report an error.\n *\n * @example\n * ```\n * import { FragmentOf, ResultOf, graphql, maskFragments } from 'gql.tada';\n *\n * const bookFragment = graphql(`\n * fragment BookComponent on Book {\n * id\n * title\n * }\n * `);\n *\n * const data = maskFragments([bookFragment], { id: 'id', title: 'book' });\n * ```\n *\n * @see {@link readFragment} for how to read from fragment masks (i.e. the reverse)\n */\nfunction maskFragments<const Fragments extends readonly FragmentShape[]>(\n _fragments: Fragments,\n fragment: resultOfFragmentsRec<Fragments>\n): fragmentRefsOfFragmentsRec<Fragments>;\nfunction maskFragments<const Fragments extends readonly FragmentShape[]>(\n _fragments: Fragments,\n fragment: resultOfFragmentsRec<Fragments> | null\n): fragmentRefsOfFragmentsRec<Fragments> | null;\nfunction maskFragments<const Fragments extends readonly FragmentShape[]>(\n _fragments: Fragments,\n fragment: resultOfFragmentsRec<Fragments> | undefined\n): fragmentRefsOfFragmentsRec<Fragments> | undefined;\nfunction maskFragments<const Fragments extends readonly FragmentShape[]>(\n _fragments: Fragments,\n fragment: resultOfFragmentsRec<Fragments> | null | undefined\n): fragmentRefsOfFragmentsRec<Fragments> | null | undefined;\nfunction maskFragments<const Fragments extends readonly FragmentShape[]>(\n _fragments: Fragments,\n fragment: readonly resultOfFragmentsRec<Fragments>[]\n): readonly fragmentRefsOfFragmentsRec<Fragments>[];\nfunction maskFragments<const Fragments extends readonly FragmentShape[]>(\n _fragments: Fragments,\n fragment: readonly (resultOfFragmentsRec<Fragments> | null)[]\n): readonly (fragmentRefsOfFragmentsRec<Fragments> | null)[];\nfunction maskFragments<const Fragments extends readonly FragmentShape[]>(\n _fragments: Fragments,\n fragment: readonly (resultOfFragmentsRec<Fragments> | undefined)[]\n): readonly (fragmentRefsOfFragmentsRec<Fragments> | undefined)[];\nfunction maskFragments<const Fragments extends readonly FragmentShape[]>(\n _fragments: Fragments,\n fragment: readonly (resultOfFragmentsRec<Fragments> | null | undefined)[]\n): readonly (fragmentRefsOfFragmentsRec<Fragments> | null | undefined)[];\nfunction maskFragments(_fragments: unknown, data: unknown) {\n return data;\n}\n\n/** For testing, converts document data without fragment refs to their result type.\n *\n * @param _document - A GraphQL document, created using {@link graphql}.\n * @param data - The result data of the GraphQL document with optional fragment refs.\n * @returns The masked result data of the document.\n *\n * @remarks\n * When creating test data, you may define data for documents that’s unmasked, but\n * need to cast the data to match the result type of your document.\n *\n * This means that you may have to use {@link unsafe_readResult} to cast\n * them to the result type, instead of doing `as any as ResultOf<typeof document>`.\n *\n * This function is inherently unsafe, since it doesn't check that your document\n * actually contains the masked fragment data!\n *\n * @example\n * ```\n * import { FragmentOf, ResultOf, graphql, unsafe_readResult } from 'gql.tada';\n *\n * const bookFragment = graphql(`\n * fragment BookComponent on Book {\n * id\n * title\n * }\n * `);\n *\n * const query = graphql(`\n * query {\n * book {\n * ...BookComponent\n * }\n * }\n * `, [bookFragment]);\n *\n * const data = unsafe_readResult(query, { book: { id: 'id', title: 'book' } });\n * ```\n *\n * @see {@link readFragment} for how to read from fragment masks (i.e. the reverse)\n */\nfunction unsafe_readResult<\n const Document extends DocumentDecoration<any, any>,\n const Data extends omitFragmentRefsRec<ResultOf<Document>>,\n>(_document: Document, data: Data): ResultOf<Document> {\n return data as any;\n}\n\nconst graphql: initGraphQLTada<setupSchema> = initGraphQLTada();\n\nexport { parse, graphql, readFragment, maskFragments, unsafe_readResult };\n\nexport type {\n setupCache,\n setupSchema,\n parseDocument,\n AbstractSetupSchema,\n AbstractSetupCache,\n GraphQLTadaAPI,\n TadaDocumentNode,\n TadaPersistedDocumentNode,\n ResultOf,\n VariablesOf,\n FragmentOf,\n};\n"],"names":["CONCAT_LOC_DEPTH","CONCAT_LOC_SEEN","Set","initGraphQLTada","graphql","input","fragments","definitions","_parse","seen","document","definition","kind","Kind","FRAGMENT_DEFINITION","has","push","add","isFragment","directives","filter","directive","name","value","loc","DOCUMENT","body","concatLocSources","result","fragment","source","clear","start","end","length","locationOffset","line","column","_loc","scalar","_schema","persisted","documentId","maskFragments","_fragments","data","parse","readFragment","args","unsafe_readResult","_document"],"mappings":";;;;;;AAuDA,IAAIA,IAAmB;;AACvB,IAAMC,IAAkB,IAAIC;;ACiQrB,SAASC;EAId,SAASC,QAAQC,GAAeC;IAC9B,IAAMC,IAAcC,EAAAA,MAAOH,GAAOE;IAClC,IAAME,IAAO,IAAIP;IACjB,KAAK,IAAMQ,KAAYJ,KAAa;MAClC,KAAK,IAAMK,KAAcD,EAASH;QAChC,IAAII,EAAWC,SAASC,OAAKC,wBAAwBL,EAAKM,IAAIJ,IAAa;UACzEJ,EAAYS,KAAKL;UACjBF,EAAKQ,IAAIN;AACX;;;IAIJ,IAAIO;IACJ,KACGA,IAAaX,EAAY,GAAGK,SAASC,EAAIA,KAACC,wBAC3CP,EAAY,GAAGY;MAEfZ,EAAY,GAAGY,aAAaZ,EAAY,GAAGY,WAAWC,QACnDC,KAAuC,cAAzBA,EAAUC,KAAKC;;IAIlC,IAAIC;IACJ,OAAO;MACLZ,MAAMC,EAAIA,KAACY;MACXlB;MACA,OAAIiB;QAIF,KAAKA,KAAON,GAAY;UACtB,IAAMQ,IAAOrB,ID7RhB,SAASsB,iBAAiBrB;YAC/B;cACEN;cACA,IAAI4B,IAAS;cACb,KAAK,IAAMC,KAAYvB;gBACrB,KAAKL,EAAgBc,IAAIc,IAAW;kBAClC5B,EAAgBgB,IAAIY;kBACpB,KAAML,KAAEA,KAAQK;kBAChB,IAAIL;oBAAKI,KAAUJ,EAAIM,OAAOJ;;AAChC;;cAEF,OAAOE;AACT,cAAU;cACR,IAA2B,OAArB5B;gBACJC,EAAgB8B;;AAEpB;AACF,WC4Q+BJ,CAAiBrB,KAAa;UACnD,OAAO;YACL0B,OAAO;YACPC,KAAKP,EAAKQ;YACVJ,QAAQ;cACNJ,MAAMA;cACNJ,MAAM;cACNa,gBAAgB;gBAAEC,MAAM;gBAAGC,QAAQ;;;;AAGzC;QACA,OAAOb;AACR;MACD,OAAIA,CAAIc;QACNd,IAAMc;AACR;;AAEJ;EAEAlC,QAAQmC,SAAS,SAASA,OAAOC,GAAiBjB;IAChD,OAAOA;;EAGTnB,QAAQqC,YAAY,SAASA,UAC3BC,GACAhC;IAEA,OAAO;MACLE,MAAMC,EAAIA,KAACY;MACXlB,aAAaG,IAAWA,EAASH,cAAc;MAC/CmC;;;EAIJ,OAAOtC;AACT;;AA+XA,IAAMA,IAAwCD;;;;;;wBAnD9C,SAASwC,cAAcC,GAAqBC;EAC1C,OAAOA;AACT;;gBAlUA,SAASC,MAA+BzC;EACtC,OAAOG,EAAAA,MAAOH;AAChB;;uBA6PA,SAAS0C,gBAAgBC;EACvB,OAAuB,MAAhBA,EAAKd,SAAec,EAAK,KAAKA,EAAK;AAC5C;;4BA2GA,SAASC,kBAGPC,GAAqBL;EACrB,OAAOA;AACT"}
|
package/dist/gql-tada.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gql-tada.mjs","sources":["../src/utils.ts","../src/api.ts"],"sourcesContent":["import type { DocumentNode, Location } from '@0no-co/graphql.web';\n\n/** Returns `T` if it matches `Constraint` without being equal to it. Failing this evaluates to `Fallback` otherwise. */\nexport type matchOr<Constraint, T, Fallback> = Constraint extends T\n ? Fallback\n : T extends Constraint\n ? T\n : Fallback;\n\n/** Flattens a given object type.\n *\n * @remarks\n * This is typically used to make a TypeScript type appear as a flat object,\n * both in terms of type checking and for type hints and the tsserver output.\n */\nexport type obj<T> = T extends { [key: string | number]: any } ? { [K in keyof T]: T[K] } : never;\n\n/** Turns a given union to an intersection type. */\nexport type overload<T> = (T extends any ? (x: T) => void : never) extends (x: infer U) => void\n ? U & T\n : never;\n\n/** Marks all properties as writable */\nexport type writable<T> = { -readonly [K in keyof T]: T[K] };\n\n/** Annotations for GraphQL’s `DocumentNode` with attached generics for its result data and variables types.\n *\n * @remarks\n * A GraphQL {@link DocumentNode} defines both the variables it accepts on request and the `data`\n * shape it delivers on a response in the GraphQL query language.\n *\n * To bridge the gap to TypeScript, tools may be used to generate TypeScript types that define the shape\n * of `data` and `variables` ahead of time. These types are then attached to GraphQL documents using this\n * `TypedDocumentNode` type.\n *\n * Using a `DocumentNode` that is typed like this will cause any `urql` API to type its input `variables`\n * and resulting `data` using the types provided.\n *\n * @privateRemarks\n * For compatibility reasons this type has been copied and internalized from:\n * https://github.com/dotansimha/graphql-typed-document-node/blob/3711b12/packages/core/src/index.ts#L3-L10\n *\n * @see {@link https://github.com/dotansimha/graphql-typed-document-node} for more information.\n */\nexport interface DocumentDecoration<Result = any, Variables = any> {\n /** Type to support `@graphql-typed-document-node/core`\n * @internal\n */\n __apiType?: (variables: Variables) => Result;\n /** Type to support `TypedQueryDocumentNode` from `graphql`\n * @internal\n */\n __ensureTypesOfVariablesAndResultMatching?: (variables: Variables) => Result;\n}\n\nlet CONCAT_LOC_DEPTH = 0;\nconst CONCAT_LOC_SEEN = new Set();\n\ninterface LocationNode {\n loc?: Location;\n}\n\n/** Concatenates all fragments' `loc.source.body`s */\nexport function concatLocSources(fragments: readonly LocationNode[]): string {\n try {\n CONCAT_LOC_DEPTH++;\n let result = '';\n for (const fragment of fragments) {\n if (!CONCAT_LOC_SEEN.has(fragment)) {\n CONCAT_LOC_SEEN.add(fragment);\n const { loc } = fragment;\n if (loc) result += loc.source.body;\n }\n }\n return result;\n } finally {\n if (--CONCAT_LOC_DEPTH === 0) {\n CONCAT_LOC_SEEN.clear();\n }\n }\n}\n","import type { DocumentNode, DefinitionNode, Location } from '@0no-co/graphql.web';\nimport { Kind, parse as _parse } from '@0no-co/graphql.web';\n\nimport type {\n IntrospectionLikeInput,\n ScalarsLike,\n SchemaLike,\n mapIntrospection,\n addIntrospectionScalars,\n} from './introspection';\n\nimport type {\n DefinitionDecoration,\n FragmentShape,\n getFragmentsOfDocuments,\n decorateFragmentDef,\n omitFragmentRefsRec,\n makeFragmentRef,\n} from './namespace';\n\nimport type { getDocumentType } from './selection';\nimport type { parseDocument, DocumentNodeLike } from './parser';\nimport type { getVariablesType, getScalarType } from './variables';\nimport type { obj, matchOr, writable, DocumentDecoration } from './utils';\nimport { concatLocSources } from './utils';\n\n/** Abstract configuration type input for your schema and scalars.\n *\n * @remarks\n * This is used either via {@link setupSchema} or {@link initGraphQLTada} to set\n * up your schema and scalars.\n *\n * The `scalars` option is optional and can be used to set up more scalars, apart\n * from the default ones (like: Int, Float, String, Boolean).\n * It must be an object map of scalar names to their desired TypeScript types.\n *\n * @param introspection - Introspection of your schema matching {@link IntrospectionQuery}.\n * @param scalars - An object type with scalar names as keys and the corresponding scalar types as values.\n */\ninterface AbstractSetupSchema {\n introspection: IntrospectionLikeInput;\n scalars?: ScalarsLike;\n disableMasking?: boolean;\n}\n\n/** Abstract type for internal configuration\n * @internal\n */\ninterface AbstractConfig {\n isMaskingDisabled: boolean;\n}\n\n/** This is used to configure gql.tada with your introspection data and scalars.\n *\n * @remarks\n * You may extend this interface via declaration merging with your {@link IntrospectionQuery}\n * data and optionally your scalars to get proper type inference.\n * This is done by declaring a declaration for it as per the following example.\n *\n * Configuring scalars is optional and by default the standard scalrs are already\n * defined.\n *\n * This will configure the {@link graphql} export to infer types from your schema.\n * Alternatively, you may call {@link initGraphQLTada} instead.\n *\n * @param introspection - Introspection of your schema matching {@link IntrospectionQuery}.\n * @param scalars - An object type with scalar names as keys and the corresponding scalar types as values.\n *\n * @example\n * ```\n * import type { myIntrospection } from './myIntrospection';\n *\n * declare module 'gql.tada' {\n * interface setupSchema {\n * introspection: typeof myIntrospection;\n * scalars: {\n * DateTime: string;\n * Json: any;\n * };\n * }\n * }\n * ```\n */\ninterface setupSchema extends AbstractSetupSchema {\n /*empty*/\n}\n\ninterface AbstractSetupCache {\n readonly __cacheDisabled: unknown;\n [key: string]: unknown;\n}\n\ninterface setupCache extends AbstractSetupCache {}\n\ninterface GraphQLTadaAPI<Schema extends SchemaLike, Config extends AbstractConfig> {\n /** In \"multi-schema\" mode this identifies the schema.\n * @internal */\n readonly __name: Schema['name'];\n\n /** Function to create and compose GraphQL documents with result and variable types.\n *\n * @param input - A string of a GraphQL document.\n * @param fragments - An optional list of other GraphQL fragments created with this function.\n * @returns A {@link DocumentNode} with result and variables types.\n *\n * @remarks\n * This function creates a {@link DocumentNode} with result and variables types.\n * It is used with your schema in {@link setupSchema} to create a result type\n * of your queries, fragments, and variables.\n *\n * You can compose fragments into this function by passing them and a fragment\n * mask will be created for them.\n * When creating queries, the returned document of queries can be passed into GraphQL clients\n * which will then automatically infer the result and variables types.\n *\n * @example\n * ```\n * import { graphql } from 'gql.tada';\n *\n * const bookFragment = graphql(`\n * fragment BookComponent on Book {\n * id\n * title\n * }\n * `);\n *\n * const bookQuery = graphql(`\n * query Book ($id: ID!) {\n * book(id: $id) {\n * id\n * ...BookComponent\n * }\n * }\n * `, [bookFragment]);\n * ```\n *\n * @see {@link readFragment} for how to read from fragment masks.\n */\n <const In extends string, const Fragments extends readonly FragmentShape[]>(\n input: In,\n fragments?: Fragments\n ): setupCache[In] extends DocumentNodeLike\n ? unknown extends setupCache['__cacheDisabled']\n ? setupCache[In]\n : getDocumentNode<\n parseDocument<In>,\n Schema,\n getFragmentsOfDocuments<Fragments>,\n Config['isMaskingDisabled']\n >\n : getDocumentNode<\n parseDocument<In>,\n Schema,\n getFragmentsOfDocuments<Fragments>,\n Config['isMaskingDisabled']\n >;\n\n /** Function to validate the type of a given scalar or enum value.\n *\n * @param name - The name of a scalar or enum type.\n * @param value - An optional scalar value of the given type.\n * @returns A {@link DocumentNode} with result and variables types.\n *\n * @remarks\n * This function validates that a value matches an enum or scalar type\n * as a type check.\n *\n * You can use it to retrieve the type of a given scalar or enum type\n * for use in a utility function or separate component that only\n * accepts a primitive scalar or enum value.\n *\n * Note that this function does not perform runtime checks of your\n * scalar value!\n *\n * @example\n * ```\n * import { graphql } from 'gql.tada';\n *\n * type myEnum = ReturnType<graphql.scalar<'myEnum'>>;\n *\n * const myEnumValue = graphql.scalar('myEnum', 'value');\n * ```\n */\n scalar<const Name extends string, Value>(\n name: Name,\n value: getScalarType<Name, Schema> extends Value\n ? Value & getScalarType<Name, Schema>\n : getScalarType<Name, Schema>\n ): Value;\n scalar<const Name extends string, Value>(\n name: Name,\n value: getScalarType<Name, Schema> extends Value\n ? never extends Value\n ? never\n : (Value & getScalarType<Name, Schema>) | null\n : getScalarType<Name, Schema> | null\n ): Value | null;\n scalar<const Name extends string, Value>(\n name: Name,\n value: getScalarType<Name, Schema> extends Value\n ? never extends Value\n ? never\n : (Value & getScalarType<Name, Schema>) | undefined\n : getScalarType<Name, Schema> | undefined\n ): Value | undefined;\n scalar<const Name extends string, Value>(\n name: Name,\n value: getScalarType<Name, Schema> extends Value\n ? never extends Value\n ? never\n : (Value & getScalarType<Name, Schema>) | null | undefined\n : getScalarType<Name, Schema> | null | undefined\n ): Value | null | undefined;\n scalar<const Name extends string>(\n name: Name,\n value: getScalarType<Name, Schema> | undefined\n ): getScalarType<Name, Schema>;\n\n /** Function to replace a GraphQL document with a persisted document.\n *\n * @typeParam Document - The document type of {@link TadaDocumentNode}.\n * @param id - A document ID that replaces the document for the API.\n * @returns A {@link TadaPersistedDocumentNode}.\n *\n * @remarks\n * This function may be used to replace a GraphQL document with a\n * stand-in, persisted document.\n *\n * The returned document’s value won’t contain any of the document’s\n * definitions, but its type will be equivalent to the `Document` that’s\n * been passed as a generic.\n *\n * As long as the query (type parameter of `Document`) is only referenced\n * as a type in your code, it will be omitted from your output build by\n * your bundler and the resulting GraphQL document’s ID will replace your\n * document entirely.\n *\n * @example\n * ```\n * import { graphql } from 'gql.tada';\n *\n * const query = graphql(`query MyQuery { __typename }`);\n * const persisted = graphql.persisted<typeof query>('MyQuery');\n * ```\n */\n persisted<Document extends DocumentNodeLike = never>(\n documentId: string,\n document?: Document\n ): Document extends DocumentDecoration<infer Result, infer Variables>\n ? TadaPersistedDocumentNode<Result, Variables>\n : never;\n}\n\ntype schemaOfSetup<Setup extends AbstractSetupSchema> = addIntrospectionScalars<\n mapIntrospection<matchOr<IntrospectionLikeInput, Setup['introspection'], never>>,\n matchOr<ScalarsLike, Setup['scalars'], {}>\n>;\n\ntype configOfSetup<Setup extends AbstractSetupSchema> = {\n isMaskingDisabled: Setup['disableMasking'] extends true ? true : false;\n};\n\n/** Utility to type-instantiate a `graphql` document function with.\n *\n * @remarks\n * The `initGraphQLTada` type may be used to manually instantiate a type\n * as returned by `initGraphQLTada<>()` with the same input type.\n *\n * @example\n * ```\n * import { initGraphQLTada } from 'gql.tada';\n * import type { myIntrospection } from './myIntrospection';\n *\n * export const graphql: initGraphQLTada<{\n * introspection: typeof myIntrospection;\n * scalars: {\n * DateTime: string;\n * Json: any;\n * };\n * }> = initGraphQLTada();\n *\n * const query = graphql(`{ __typename }`);\n * ```\n */\nexport type initGraphQLTada<Setup extends AbstractSetupSchema> = GraphQLTadaAPI<\n schemaOfSetup<Setup>,\n configOfSetup<Setup>\n>;\n\n/** Setup function to create a typed `graphql` document function with.\n *\n * @remarks\n * `initGraphQLTada` accepts an {@link AbstractSetupSchema} configuration object as a generic\n * and returns a `graphql` function that may be used to create documents typed using your\n * GraphQL schema.\n *\n * You should use and re-export the resulting function named as `graphql` or `gql` for your\n * editor and the TypeScript language server to recognize your GraphQL documents correctly.\n *\n * @example\n * ```\n * import { initGraphQLTada } from 'gql.tada';\n * import type { myIntrospection } from './myIntrospection';\n *\n * export const graphql = initGraphQLTada<{\n * introspection: typeof myIntrospection;\n * scalars: {\n * DateTime: string;\n * Json: any;\n * };\n * }>();\n *\n * const query = graphql(`{ __typename }`);\n * ```\n */\nexport function initGraphQLTada<const Setup extends AbstractSetupSchema>(): initGraphQLTada<Setup> {\n type Schema = schemaOfSetup<Setup>;\n type Config = configOfSetup<Setup>;\n\n function graphql(input: string, fragments?: readonly TadaDocumentNode[]): any {\n const definitions = _parse(input).definitions as writable<DefinitionNode>[];\n const seen = new Set<unknown>();\n for (const document of fragments || []) {\n for (const definition of document.definitions) {\n if (definition.kind === Kind.FRAGMENT_DEFINITION && !seen.has(definition)) {\n definitions.push(definition);\n seen.add(definition);\n }\n }\n }\n\n let isFragment: boolean;\n if (\n (isFragment = definitions[0].kind === Kind.FRAGMENT_DEFINITION) &&\n definitions[0].directives\n ) {\n definitions[0].directives = definitions[0].directives.filter(\n (directive) => directive.name.value !== '_unmask'\n );\n }\n\n let loc: Location | undefined;\n return {\n kind: Kind.DOCUMENT,\n definitions,\n get loc(): Location {\n // NOTE: This is only meant for graphql-tag compatibility. When fragment documents\n // are interpolated into other documents, graphql-tag blindly reads `document.loc`\n // without checking whether it's `undefined`.\n if (!loc && isFragment) {\n const body = input + concatLocSources(fragments || []);\n return {\n start: 0,\n end: body.length,\n source: {\n body: body,\n name: 'GraphQLTada',\n locationOffset: { line: 1, column: 1 },\n },\n };\n }\n return loc;\n },\n set loc(_loc: Location) {\n loc = _loc;\n },\n } satisfies DocumentNode;\n }\n\n graphql.scalar = function scalar(_schema: Schema, value: any) {\n return value;\n };\n\n graphql.persisted = function persisted(\n documentId: string,\n document?: TadaDocumentNode\n ): TadaPersistedDocumentNode {\n return {\n kind: Kind.DOCUMENT,\n definitions: document ? document.definitions : [],\n documentId,\n };\n };\n\n return graphql as GraphQLTadaAPI<Schema, Config>;\n}\n\n/** Alias to a GraphQL parse function returning an exact document type.\n *\n * @param input - A string of a GraphQL document\n * @returns A parsed {@link DocumentNode}.\n *\n * @remarks\n * This function accepts a GraphQL document string and parses it, just like\n * GraphQL’s `parse` function. However, its return type will be the exact\n * structure of the AST parsed in types.\n */\nfunction parse<const In extends string>(input: In): parseDocument<In> {\n return _parse(input) as any;\n}\n\nexport type getDocumentNode<\n Document extends DocumentNodeLike,\n Introspection extends SchemaLike,\n Fragments extends { [name: string]: any } = {},\n isMaskingDisabled = false,\n> =\n getDocumentType<Document, Introspection, Fragments> extends never\n ? never\n : TadaDocumentNode<\n getDocumentType<Document, Introspection, Fragments>,\n getVariablesType<Document, Introspection>,\n decorateFragmentDef<Document, isMaskingDisabled>\n >;\n\n/** A GraphQL `DocumentNode` with attached types for results and variables.\n *\n * @remarks\n * This is a GraphQL {@link DocumentNode} with attached types for results and variables.\n * This is used by GraphQL clients to infer the types of results and variables and provide\n * type-safety in GraphQL documents.\n *\n * You can create typed GraphQL documents using the {@link graphql} function.\n *\n * `Result` is the type of GraphQL results, as returned by GraphQL APIs for a given query.\n * `Variables` is the type of variables, as accepted by GraphQL APIs for a given query.\n *\n * @see {@link https://github.com/dotansimha/graphql-typed-document-node} for more information.\n */\ninterface TadaDocumentNode<\n Result = { [key: string]: any },\n Variables = { [key: string]: any },\n Decoration = void,\n> extends DocumentNode,\n DocumentDecoration<Result, Variables>,\n DefinitionDecoration<Decoration> {}\n\n/** A GraphQL persisted document with attached types for results and variables.\n *\n * @remarks\n * This type still matches a GraphQL {@link DocumentNode}, but doesn’t contain\n * any definitions. At runtime, this means that this document is empty.\n *\n * Instead of its definitions, it carries an `id` property that is typically\n * used to uniquely identify the document to your GraphQL API, without disclosing\n * the shape of the query or schema transparently.\n */\ninterface TadaPersistedDocumentNode<\n Result = { [key: string]: any },\n Variables = { [key: string]: any },\n> extends DocumentNode,\n DocumentDecoration<Result, Variables> {\n definitions: readonly DefinitionNode[];\n documentId: string;\n}\n\n/** A utility type returning the `Result` type of typed GraphQL documents.\n *\n * @remarks\n * This accepts a {@link TadaDocumentNode} and returns the attached `Result` type\n * of GraphQL documents.\n */\ntype ResultOf<Document> = Document extends DocumentDecoration<infer Result, any> ? Result : never;\n\n/** A utility type returning the `Variables` type of typed GraphQL documents.\n *\n * @remarks\n * This accepts a {@link TadaDocumentNode} and returns the attached `Variables` type\n * of GraphQL documents.\n */\ntype VariablesOf<Document> =\n Document extends DocumentDecoration<any, infer Variables> ? Variables : never;\n\n/** Creates a fragment mask for a given fragment document.\n *\n * @remarks\n * When {@link graphql} is used to create a fragment and is spread into another\n * fragment or query, their result types will only contain a “reference” to the\n * fragment. This encourages isolation and is known as “fragment masking.”\n *\n * While {@link readFragment} is used to unmask these fragment masks, this utility\n * creates a fragment mask, so you can accept the masked data in the part of your\n * codebase that defines a fragment.\n *\n * @example\n * ```\n * import { FragmentOf, graphql, readFragment } from 'gql.tada';\n *\n * const bookFragment = graphql(`\n * fragment BookComponent on Book {\n * id\n * title\n * }\n * `);\n *\n * // May be called with any GraphQL data that contains a spread of `bookFragment`\n * const getBook = (data: FragmentOf<typeof bookFragment>) => {\n * // Unmasks the fragment and casts to the result type of `bookFragment`\n * const book = readFragment(bookFragment, data);\n * };\n * ```\n *\n * @see {@link readFragment} for how to read from fragment masks.\n */\ntype FragmentOf<Document extends FragmentShape> = makeFragmentRef<Document>;\n\ntype resultOrFragmentOf<Document extends FragmentShape> = FragmentOf<Document> | ResultOf<Document>;\n\ntype resultOfT<Document extends FragmentShape, T = unknown> =\n Document extends DocumentDecoration<infer Result, any>\n ? '__typename' extends keyof T\n ? Result extends { __typename?: T['__typename'] }\n ? Result\n : never\n : Result\n : never;\n\ntype resultOfFragmentsRec<\n Fragments extends readonly any[],\n Result = {},\n> = Fragments extends readonly [infer Fragment, ...infer Rest]\n ? resultOfFragmentsRec<Rest, ResultOf<Fragment> & Result>\n : Result;\n\ntype fragmentRefsOfFragmentsRec<\n Fragments extends readonly any[],\n FragmentRefs = {},\n> = Fragments extends readonly [infer Fragment, ...infer Rest]\n ? fragmentRefsOfFragmentsRec<Rest, makeFragmentRef<Fragment> & FragmentRefs>\n : obj<FragmentRefs>;\n\n/** Unmasks a fragment mask for a given fragment document and data.\n *\n * @param _document - A GraphQL document of a fragment, created using {@link graphql}.\n * @param fragment - A mask of the fragment, which can be wrapped in arrays, or nullable.\n * @returns The unmasked data of the fragment.\n *\n * @remarks\n * When {@link graphql} is used to create a fragment and is spread into another\n * fragment or query, their result types will only contain a “reference” to the\n * fragment. This encourages isolation and is known as “fragment masking.”\n *\n * This means that you must use {@link readFragment} to unmask these fragment masks\n * and get to the data. This encourages isolation and only using the data you define\n * a part of your codebase to require.\n *\n * @example\n * ```\n * import { FragmentOf, graphql, readFragment } from 'gql.tada';\n *\n * const bookFragment = graphql(`\n * fragment BookComponent on Book {\n * id\n * title\n * }\n * `);\n *\n * const getBook = (data: FragmentOf<typeof bookFragment> | null) => {\n * // Unmasks the fragment and casts to the result type of `bookFragment`\n * // This is intersected with `| null` in this case, due to the input type.\n * const book = readFragment(bookFragment, data);\n * };\n *\n * const bookQuery = graphql(`\n * query Book ($id: ID!) {\n * book(id: $id) {\n * id\n * ...BookComponent\n * }\n * }\n * `, [bookFragment]);\n *\n * const getQuery = (data: ResultOf<typeof bookQuery>) => {\n * getBook(data?.book);\n * };\n * ```\n *\n * @see {@link readFragment} for how to read from fragment masks.\n */\nfunction readFragment<const Document extends FragmentShape = never>(\n _document: Document,\n fragment: never\n): resultOfT<Document>;\n\nfunction readFragment<\n const Document extends FragmentShape,\n const T extends resultOrFragmentOf<Document> | null | undefined | {},\n>(\n _document: Document,\n fragments: readonly T[]\n): readonly (T extends resultOrFragmentOf<Document> ? resultOfT<Document, T> : T)[];\nfunction readFragment<\n const Document extends FragmentShape,\n const T extends resultOrFragmentOf<Document> | null | undefined | {},\n>(\n _document: Document,\n fragment: T\n): T extends resultOrFragmentOf<Document> ? resultOfT<Document, T> : T;\n\n// Reading arrays of fragments with required generic\nfunction readFragment<const Document extends FragmentShape>(\n fragment: readonly resultOrFragmentOf<Document>[]\n): readonly ResultOf<Document>[];\nfunction readFragment<const Document extends FragmentShape>(\n fragment: readonly (resultOrFragmentOf<Document> | null)[]\n): readonly (ResultOf<Document> | null)[];\nfunction readFragment<const Document extends FragmentShape>(\n fragment: readonly (resultOrFragmentOf<Document> | undefined)[]\n): readonly (ResultOf<Document> | undefined)[];\nfunction readFragment<const Document extends FragmentShape>(\n fragment: readonly (resultOrFragmentOf<Document> | null | undefined)[]\n): readonly (ResultOf<Document> | null | undefined)[];\n// Reading arrays of fragments with required generic with optional `{}` type\nfunction readFragment<const Document extends FragmentShape>(\n fragment: readonly (resultOrFragmentOf<Document> | {})[]\n): readonly (ResultOf<Document> | {})[];\nfunction readFragment<const Document extends FragmentShape>(\n fragment: readonly (resultOrFragmentOf<Document> | null | {})[]\n): readonly (ResultOf<Document> | null | {})[];\nfunction readFragment<const Document extends FragmentShape>(\n fragment: readonly (resultOrFragmentOf<Document> | undefined | {})[]\n): readonly (ResultOf<Document> | undefined | {})[];\nfunction readFragment<const Document extends FragmentShape>(\n fragment: readonly (resultOrFragmentOf<Document> | null | undefined | {})[]\n): readonly (ResultOf<Document> | null | undefined | {})[];\n// Reading fragments with required generic\nfunction readFragment<const Document extends FragmentShape>(\n fragment: resultOrFragmentOf<Document>\n): ResultOf<Document>;\nfunction readFragment<const Document extends FragmentShape>(\n fragment: resultOrFragmentOf<Document> | null\n): ResultOf<Document> | null;\nfunction readFragment<const Document extends FragmentShape>(\n fragment: resultOrFragmentOf<Document> | undefined\n): ResultOf<Document> | undefined;\nfunction readFragment<const Document extends FragmentShape>(\n fragment: resultOrFragmentOf<Document> | null | undefined\n): ResultOf<Document> | null | undefined;\n// Reading fragments with required generic with optional `{}` type\nfunction readFragment<const Document extends FragmentShape>(\n fragment: resultOrFragmentOf<Document> | {}\n): ResultOf<Document> | {};\nfunction readFragment<const Document extends FragmentShape>(\n fragment: resultOrFragmentOf<Document> | null | {}\n): ResultOf<Document> | null | {};\nfunction readFragment<const Document extends FragmentShape>(\n fragment: resultOrFragmentOf<Document> | undefined | {}\n): ResultOf<Document> | undefined | {};\nfunction readFragment<const Document extends FragmentShape>(\n fragment: resultOrFragmentOf<Document> | null | undefined | {}\n): ResultOf<Document> | null | undefined | {};\n\nfunction readFragment(...args: [unknown] | [unknown, unknown]) {\n return args.length === 2 ? args[1] : args[0];\n}\n\n/** For testing, masks fragment data for given data and fragments.\n *\n * @param _fragments - A list of GraphQL documents of fragments, created using {@link graphql}.\n * @param data - The combined result data of the fragments, which can be wrapped in arrays.\n * @returns The masked data of the fragments.\n *\n * @remarks\n * When creating test data, you may define data for fragments that’s unmasked, making it\n * unusable in parent fragments or queries that require masked data.\n *\n * This means that you may have to use {@link maskFragments} to mask your data first\n * for TypeScript to not report an error.\n *\n * @example\n * ```\n * import { FragmentOf, ResultOf, graphql, maskFragments } from 'gql.tada';\n *\n * const bookFragment = graphql(`\n * fragment BookComponent on Book {\n * id\n * title\n * }\n * `);\n *\n * const data = maskFragments([bookFragment], { id: 'id', title: 'book' });\n * ```\n *\n * @see {@link readFragment} for how to read from fragment masks (i.e. the reverse)\n */\nfunction maskFragments<const Fragments extends readonly FragmentShape[]>(\n _fragments: Fragments,\n fragment: resultOfFragmentsRec<Fragments>\n): fragmentRefsOfFragmentsRec<Fragments>;\nfunction maskFragments<const Fragments extends readonly FragmentShape[]>(\n _fragments: Fragments,\n fragment: resultOfFragmentsRec<Fragments> | null\n): fragmentRefsOfFragmentsRec<Fragments> | null;\nfunction maskFragments<const Fragments extends readonly FragmentShape[]>(\n _fragments: Fragments,\n fragment: resultOfFragmentsRec<Fragments> | undefined\n): fragmentRefsOfFragmentsRec<Fragments> | undefined;\nfunction maskFragments<const Fragments extends readonly FragmentShape[]>(\n _fragments: Fragments,\n fragment: resultOfFragmentsRec<Fragments> | null | undefined\n): fragmentRefsOfFragmentsRec<Fragments> | null | undefined;\nfunction maskFragments<const Fragments extends readonly FragmentShape[]>(\n _fragments: Fragments,\n fragment: readonly resultOfFragmentsRec<Fragments>[]\n): readonly fragmentRefsOfFragmentsRec<Fragments>[];\nfunction maskFragments<const Fragments extends readonly FragmentShape[]>(\n _fragments: Fragments,\n fragment: readonly (resultOfFragmentsRec<Fragments> | null)[]\n): readonly (fragmentRefsOfFragmentsRec<Fragments> | null)[];\nfunction maskFragments<const Fragments extends readonly FragmentShape[]>(\n _fragments: Fragments,\n fragment: readonly (resultOfFragmentsRec<Fragments> | undefined)[]\n): readonly (fragmentRefsOfFragmentsRec<Fragments> | undefined)[];\nfunction maskFragments<const Fragments extends readonly FragmentShape[]>(\n _fragments: Fragments,\n fragment: readonly (resultOfFragmentsRec<Fragments> | null | undefined)[]\n): readonly (fragmentRefsOfFragmentsRec<Fragments> | null | undefined)[];\nfunction maskFragments(_fragments: unknown, data: unknown) {\n return data;\n}\n\n/** For testing, converts document data without fragment refs to their result type.\n *\n * @param _document - A GraphQL document, created using {@link graphql}.\n * @param data - The result data of the GraphQL document with optional fragment refs.\n * @returns The masked result data of the document.\n *\n * @remarks\n * When creating test data, you may define data for documents that’s unmasked, but\n * need to cast the data to match the result type of your document.\n *\n * This means that you may have to use {@link unsafe_readResult} to cast\n * them to the result type, instead of doing `as any as ResultOf<typeof document>`.\n *\n * This function is inherently unsafe, since it doesn't check that your document\n * actually contains the masked fragment data!\n *\n * @example\n * ```\n * import { FragmentOf, ResultOf, graphql, unsafe_readResult } from 'gql.tada';\n *\n * const bookFragment = graphql(`\n * fragment BookComponent on Book {\n * id\n * title\n * }\n * `);\n *\n * const query = graphql(`\n * query {\n * book {\n * ...BookComponent\n * }\n * }\n * `, [bookFragment]);\n *\n * const data = unsafe_readResult(query, { book: { id: 'id', title: 'book' } });\n * ```\n *\n * @see {@link readFragment} for how to read from fragment masks (i.e. the reverse)\n */\nfunction unsafe_readResult<\n const Document extends DocumentDecoration<any, any>,\n const Data extends omitFragmentRefsRec<ResultOf<Document>>,\n>(_document: Document, data: Data): ResultOf<Document> {\n return data as any;\n}\n\nconst graphql: initGraphQLTada<setupSchema> = initGraphQLTada();\n\nexport { parse, graphql, readFragment, maskFragments, unsafe_readResult };\n\nexport type {\n setupCache,\n setupSchema,\n parseDocument,\n AbstractSetupSchema,\n AbstractSetupCache,\n GraphQLTadaAPI,\n TadaDocumentNode,\n TadaPersistedDocumentNode,\n ResultOf,\n VariablesOf,\n FragmentOf,\n};\n"],"names":["CONCAT_LOC_DEPTH","CONCAT_LOC_SEEN","Set","initGraphQLTada","graphql","input","fragments","definitions","_parse","seen","document","definition","kind","Kind","FRAGMENT_DEFINITION","has","push","add","isFragment","directives","filter","directive","name","value","loc","DOCUMENT","body","concatLocSources","result","fragment","source","clear","start","end","length","locationOffset","line","column","_loc","scalar","_schema","persisted","documentId","parse","readFragment","args","maskFragments","_fragments","data","unsafe_readResult","_document"],"mappings":";;AAuDA,IAAIA,IAAmB;;AACvB,IAAMC,IAAkB,IAAIC;;ACmQrB,SAASC;EAId,SAASC,QAAQC,GAAeC;IAC9B,IAAMC,IAAcC,EAAOH,GAAOE;IAClC,IAAME,IAAO,IAAIP;IACjB,KAAK,IAAMQ,KAAYJ,KAAa;MAClC,KAAK,IAAMK,KAAcD,EAASH;QAChC,IAAII,EAAWC,SAASC,EAAKC,wBAAwBL,EAAKM,IAAIJ,IAAa;UACzEJ,EAAYS,KAAKL;UACjBF,EAAKQ,IAAIN;AACX;;;IAIJ,IAAIO;IACJ,KACGA,IAAaX,EAAY,GAAGK,SAASC,EAAKC,wBAC3CP,EAAY,GAAGY;MAEfZ,EAAY,GAAGY,aAAaZ,EAAY,GAAGY,WAAWC,QACnDC,KAAuC,cAAzBA,EAAUC,KAAKC;;IAIlC,IAAIC;IACJ,OAAO;MACLZ,MAAMC,EAAKY;MACXlB;MACA,OAAIiB;QAIF,KAAKA,KAAON,GAAY;UACtB,IAAMQ,IAAOrB,ID/RhB,SAASsB,iBAAiBrB;YAC/B;cACEN;cACA,IAAI4B,IAAS;cACb,KAAK,IAAMC,KAAYvB;gBACrB,KAAKL,EAAgBc,IAAIc,IAAW;kBAClC5B,EAAgBgB,IAAIY;kBACpB,KAAML,KAAEA,KAAQK;kBAChB,IAAIL;oBAAKI,KAAUJ,EAAIM,OAAOJ;;AAChC;;cAEF,OAAOE;AACT,cAAU;cACR,IAA2B,OAArB5B;gBACJC,EAAgB8B;;AAEpB;AACF,WC8Q+BJ,CAAiBrB,KAAa;UACnD,OAAO;YACL0B,OAAO;YACPC,KAAKP,EAAKQ;YACVJ,QAAQ;cACNJ,MAAMA;cACNJ,MAAM;cACNa,gBAAgB;gBAAEC,MAAM;gBAAGC,QAAQ;;;;AAGzC;QACA,OAAOb;AACR;MACD,OAAIA,CAAIc;QACNd,IAAMc;AACR;;AAEJ;EAEAlC,QAAQmC,SAAS,SAASA,OAAOC,GAAiBjB;IAChD,OAAOA;;EAGTnB,QAAQqC,YAAY,SAASA,UAC3BC,GACAhC;IAEA,OAAO;MACLE,MAAMC,EAAKY;MACXlB,aAAaG,IAAWA,EAASH,cAAc;MAC/CmC;;;EAIJ,OAAOtC;AACT;;AAYA,SAASuC,MAA+BtC;EACtC,OAAOG,EAAOH;AAChB;;AA6PA,SAASuC,gBAAgBC;EACvB,OAAuB,MAAhBA,EAAKX,SAAeW,EAAK,KAAKA,EAAK;AAC5C;;AA+DA,SAASC,cAAcC,GAAqBC;EAC1C,OAAOA;AACT;;AA0CA,SAASC,kBAGPC,GAAqBF;EACrB,OAAOA;AACT;;AAEA,IAAM5C,IAAwCD;;"}
|
|
1
|
+
{"version":3,"file":"gql-tada.mjs","sources":["../src/utils.ts","../src/api.ts"],"sourcesContent":["import type { DocumentNode, Location } from '@0no-co/graphql.web';\n\n/** Returns `T` if it matches `Constraint` without being equal to it. Failing this evaluates to `Fallback` otherwise. */\nexport type matchOr<Constraint, T, Fallback> = Constraint extends T\n ? Fallback\n : T extends Constraint\n ? T\n : Fallback;\n\n/** Flattens a given object type.\n *\n * @remarks\n * This is typically used to make a TypeScript type appear as a flat object,\n * both in terms of type checking and for type hints and the tsserver output.\n */\nexport type obj<T> = T extends { [key: string | number]: any } ? { [K in keyof T]: T[K] } : never;\n\n/** Turns a given union to an intersection type. */\nexport type overload<T> = (T extends any ? (x: T) => void : never) extends (x: infer U) => void\n ? U & T\n : never;\n\n/** Marks all properties as writable */\nexport type writable<T> = { -readonly [K in keyof T]: T[K] };\n\n/** Annotations for GraphQL’s `DocumentNode` with attached generics for its result data and variables types.\n *\n * @remarks\n * A GraphQL {@link DocumentNode} defines both the variables it accepts on request and the `data`\n * shape it delivers on a response in the GraphQL query language.\n *\n * To bridge the gap to TypeScript, tools may be used to generate TypeScript types that define the shape\n * of `data` and `variables` ahead of time. These types are then attached to GraphQL documents using this\n * `TypedDocumentNode` type.\n *\n * Using a `DocumentNode` that is typed like this will cause any `urql` API to type its input `variables`\n * and resulting `data` using the types provided.\n *\n * @privateRemarks\n * For compatibility reasons this type has been copied and internalized from:\n * https://github.com/dotansimha/graphql-typed-document-node/blob/3711b12/packages/core/src/index.ts#L3-L10\n *\n * @see {@link https://github.com/dotansimha/graphql-typed-document-node} for more information.\n */\nexport interface DocumentDecoration<Result = any, Variables = any> {\n /** Type to support `@graphql-typed-document-node/core`\n * @internal\n */\n __apiType?: (variables: Variables) => Result;\n /** Type to support `TypedQueryDocumentNode` from `graphql`\n * @internal\n */\n __ensureTypesOfVariablesAndResultMatching?: (variables: Variables) => Result;\n}\n\nlet CONCAT_LOC_DEPTH = 0;\nconst CONCAT_LOC_SEEN = new Set();\n\ninterface LocationNode {\n loc?: Location;\n}\n\n/** Concatenates all fragments' `loc.source.body`s */\nexport function concatLocSources(fragments: readonly LocationNode[]): string {\n try {\n CONCAT_LOC_DEPTH++;\n let result = '';\n for (const fragment of fragments) {\n if (!CONCAT_LOC_SEEN.has(fragment)) {\n CONCAT_LOC_SEEN.add(fragment);\n const { loc } = fragment;\n if (loc) result += loc.source.body;\n }\n }\n return result;\n } finally {\n if (--CONCAT_LOC_DEPTH === 0) {\n CONCAT_LOC_SEEN.clear();\n }\n }\n}\n","import type { DocumentNode, DefinitionNode, Location } from '@0no-co/graphql.web';\nimport { Kind, parse as _parse } from '@0no-co/graphql.web';\n\nimport type {\n IntrospectionLikeInput,\n ScalarsLike,\n SchemaLike,\n mapIntrospection,\n addIntrospectionScalars,\n} from './introspection';\n\nimport type {\n DefinitionDecoration,\n FragmentShape,\n getFragmentsOfDocuments,\n decorateFragmentDef,\n omitFragmentRefsRec,\n makeFragmentRef,\n} from './namespace';\n\nimport type { getDocumentType } from './selection';\nimport type { parseDocument, DocumentNodeLike } from './parser';\nimport type { getVariablesType, getScalarType } from './variables';\nimport type { obj, matchOr, writable, DocumentDecoration } from './utils';\nimport { concatLocSources } from './utils';\n\n/** Abstract configuration type input for your schema and scalars.\n *\n * @remarks\n * This is used either via {@link setupSchema} or {@link initGraphQLTada} to set\n * up your schema and scalars.\n *\n * The `scalars` option is optional and can be used to set up more scalars, apart\n * from the default ones (like: Int, Float, String, Boolean).\n * It must be an object map of scalar names to their desired TypeScript types.\n *\n * @param introspection - Introspection of your schema matching {@link IntrospectionQuery}.\n * @param scalars - An object type with scalar names as keys and the corresponding scalar types as values.\n */\ninterface AbstractSetupSchema {\n introspection: IntrospectionLikeInput;\n scalars?: ScalarsLike;\n disableMasking?: boolean;\n}\n\n/** Abstract type for internal configuration\n * @internal\n */\ninterface AbstractConfig {\n isMaskingDisabled: boolean;\n}\n\n/** This is used to configure gql.tada with your introspection data and scalars.\n *\n * @remarks\n * You may extend this interface via declaration merging with your {@link IntrospectionQuery}\n * data and optionally your scalars to get proper type inference.\n * This is done by declaring a declaration for it as per the following example.\n *\n * Configuring scalars is optional and by default the standard scalrs are already\n * defined.\n *\n * This will configure the {@link graphql} export to infer types from your schema.\n * Alternatively, you may call {@link initGraphQLTada} instead.\n *\n * @param introspection - Introspection of your schema matching {@link IntrospectionQuery}.\n * @param scalars - An object type with scalar names as keys and the corresponding scalar types as values.\n *\n * @example\n * ```\n * import type { myIntrospection } from './myIntrospection';\n *\n * declare module 'gql.tada' {\n * interface setupSchema {\n * introspection: typeof myIntrospection;\n * scalars: {\n * DateTime: string;\n * Json: any;\n * };\n * }\n * }\n * ```\n */\ninterface setupSchema extends AbstractSetupSchema {\n /*empty*/\n}\n\ninterface AbstractSetupCache {\n readonly __cacheDisabled: unknown;\n}\n\ninterface setupCache extends AbstractSetupCache {}\n\ninterface GraphQLTadaAPI<Schema extends SchemaLike, Config extends AbstractConfig> {\n /** In \"multi-schema\" mode this identifies the schema.\n * @internal */\n readonly __name: Schema['name'];\n\n /** Function to create and compose GraphQL documents with result and variable types.\n *\n * @param input - A string of a GraphQL document.\n * @param fragments - An optional list of other GraphQL fragments created with this function.\n * @returns A {@link DocumentNode} with result and variables types.\n *\n * @remarks\n * This function creates a {@link DocumentNode} with result and variables types.\n * It is used with your schema in {@link setupSchema} to create a result type\n * of your queries, fragments, and variables.\n *\n * You can compose fragments into this function by passing them and a fragment\n * mask will be created for them.\n * When creating queries, the returned document of queries can be passed into GraphQL clients\n * which will then automatically infer the result and variables types.\n *\n * @example\n * ```\n * import { graphql } from 'gql.tada';\n *\n * const bookFragment = graphql(`\n * fragment BookComponent on Book {\n * id\n * title\n * }\n * `);\n *\n * const bookQuery = graphql(`\n * query Book ($id: ID!) {\n * book(id: $id) {\n * id\n * ...BookComponent\n * }\n * }\n * `, [bookFragment]);\n * ```\n *\n * @see {@link readFragment} for how to read from fragment masks.\n */\n <\n const In extends unknown extends setupCache['__cacheDisabled'] ? keyof setupCache : never,\n const Fragments extends readonly FragmentShape[],\n >(\n input: In,\n fragments?: Fragments\n ): setupCache[In];\n // Overload for cache miss\n <const In extends string, const Fragments extends readonly FragmentShape[]>(\n input: In,\n fragments?: Fragments\n ): getDocumentNode<\n parseDocument<In>,\n Schema,\n getFragmentsOfDocuments<Fragments>,\n Config['isMaskingDisabled']\n >;\n\n /** Function to validate the type of a given scalar or enum value.\n *\n * @param name - The name of a scalar or enum type.\n * @param value - An optional scalar value of the given type.\n * @returns A {@link DocumentNode} with result and variables types.\n *\n * @remarks\n * This function validates that a value matches an enum or scalar type\n * as a type check.\n *\n * You can use it to retrieve the type of a given scalar or enum type\n * for use in a utility function or separate component that only\n * accepts a primitive scalar or enum value.\n *\n * Note that this function does not perform runtime checks of your\n * scalar value!\n *\n * @example\n * ```\n * import { graphql } from 'gql.tada';\n *\n * type myEnum = ReturnType<graphql.scalar<'myEnum'>>;\n *\n * const myEnumValue = graphql.scalar('myEnum', 'value');\n * ```\n */\n scalar<const Name extends string, Value>(\n name: Name,\n value: getScalarType<Name, Schema> extends Value\n ? Value & getScalarType<Name, Schema>\n : getScalarType<Name, Schema>\n ): Value;\n scalar<const Name extends string, Value>(\n name: Name,\n value: getScalarType<Name, Schema> extends Value\n ? never extends Value\n ? never\n : (Value & getScalarType<Name, Schema>) | null\n : getScalarType<Name, Schema> | null\n ): Value | null;\n scalar<const Name extends string, Value>(\n name: Name,\n value: getScalarType<Name, Schema> extends Value\n ? never extends Value\n ? never\n : (Value & getScalarType<Name, Schema>) | undefined\n : getScalarType<Name, Schema> | undefined\n ): Value | undefined;\n scalar<const Name extends string, Value>(\n name: Name,\n value: getScalarType<Name, Schema> extends Value\n ? never extends Value\n ? never\n : (Value & getScalarType<Name, Schema>) | null | undefined\n : getScalarType<Name, Schema> | null | undefined\n ): Value | null | undefined;\n scalar<const Name extends string>(\n name: Name,\n value: getScalarType<Name, Schema> | undefined\n ): getScalarType<Name, Schema>;\n\n /** Function to replace a GraphQL document with a persisted document.\n *\n * @typeParam Document - The document type of {@link TadaDocumentNode}.\n * @param id - A document ID that replaces the document for the API.\n * @returns A {@link TadaPersistedDocumentNode}.\n *\n * @remarks\n * This function may be used to replace a GraphQL document with a\n * stand-in, persisted document.\n *\n * The returned document’s value won’t contain any of the document’s\n * definitions, but its type will be equivalent to the `Document` that’s\n * been passed as a generic.\n *\n * As long as the query (type parameter of `Document`) is only referenced\n * as a type in your code, it will be omitted from your output build by\n * your bundler and the resulting GraphQL document’s ID will replace your\n * document entirely.\n *\n * @example\n * ```\n * import { graphql } from 'gql.tada';\n *\n * const query = graphql(`query MyQuery { __typename }`);\n * const persisted = graphql.persisted<typeof query>('MyQuery');\n * ```\n */\n persisted<Document extends DocumentNodeLike = never>(\n documentId: string,\n document?: Document\n ): Document extends DocumentDecoration<infer Result, infer Variables>\n ? TadaPersistedDocumentNode<Result, Variables>\n : never;\n}\n\ntype schemaOfSetup<Setup extends AbstractSetupSchema> = addIntrospectionScalars<\n mapIntrospection<matchOr<IntrospectionLikeInput, Setup['introspection'], never>>,\n matchOr<ScalarsLike, Setup['scalars'], {}>\n>;\n\ntype configOfSetup<Setup extends AbstractSetupSchema> = {\n isMaskingDisabled: Setup['disableMasking'] extends true ? true : false;\n};\n\n/** Utility to type-instantiate a `graphql` document function with.\n *\n * @remarks\n * The `initGraphQLTada` type may be used to manually instantiate a type\n * as returned by `initGraphQLTada<>()` with the same input type.\n *\n * @example\n * ```\n * import { initGraphQLTada } from 'gql.tada';\n * import type { myIntrospection } from './myIntrospection';\n *\n * export const graphql: initGraphQLTada<{\n * introspection: typeof myIntrospection;\n * scalars: {\n * DateTime: string;\n * Json: any;\n * };\n * }> = initGraphQLTada();\n *\n * const query = graphql(`{ __typename }`);\n * ```\n */\nexport type initGraphQLTada<Setup extends AbstractSetupSchema> = GraphQLTadaAPI<\n schemaOfSetup<Setup>,\n configOfSetup<Setup>\n>;\n\n/** Setup function to create a typed `graphql` document function with.\n *\n * @remarks\n * `initGraphQLTada` accepts an {@link AbstractSetupSchema} configuration object as a generic\n * and returns a `graphql` function that may be used to create documents typed using your\n * GraphQL schema.\n *\n * You should use and re-export the resulting function named as `graphql` or `gql` for your\n * editor and the TypeScript language server to recognize your GraphQL documents correctly.\n *\n * @example\n * ```\n * import { initGraphQLTada } from 'gql.tada';\n * import type { myIntrospection } from './myIntrospection';\n *\n * export const graphql = initGraphQLTada<{\n * introspection: typeof myIntrospection;\n * scalars: {\n * DateTime: string;\n * Json: any;\n * };\n * }>();\n *\n * const query = graphql(`{ __typename }`);\n * ```\n */\nexport function initGraphQLTada<const Setup extends AbstractSetupSchema>(): initGraphQLTada<Setup> {\n type Schema = schemaOfSetup<Setup>;\n type Config = configOfSetup<Setup>;\n\n function graphql(input: string, fragments?: readonly TadaDocumentNode[]): any {\n const definitions = _parse(input).definitions as writable<DefinitionNode>[];\n const seen = new Set<unknown>();\n for (const document of fragments || []) {\n for (const definition of document.definitions) {\n if (definition.kind === Kind.FRAGMENT_DEFINITION && !seen.has(definition)) {\n definitions.push(definition);\n seen.add(definition);\n }\n }\n }\n\n let isFragment: boolean;\n if (\n (isFragment = definitions[0].kind === Kind.FRAGMENT_DEFINITION) &&\n definitions[0].directives\n ) {\n definitions[0].directives = definitions[0].directives.filter(\n (directive) => directive.name.value !== '_unmask'\n );\n }\n\n let loc: Location | undefined;\n return {\n kind: Kind.DOCUMENT,\n definitions,\n get loc(): Location {\n // NOTE: This is only meant for graphql-tag compatibility. When fragment documents\n // are interpolated into other documents, graphql-tag blindly reads `document.loc`\n // without checking whether it's `undefined`.\n if (!loc && isFragment) {\n const body = input + concatLocSources(fragments || []);\n return {\n start: 0,\n end: body.length,\n source: {\n body: body,\n name: 'GraphQLTada',\n locationOffset: { line: 1, column: 1 },\n },\n };\n }\n return loc;\n },\n set loc(_loc: Location) {\n loc = _loc;\n },\n } satisfies DocumentNode;\n }\n\n graphql.scalar = function scalar(_schema: Schema, value: any) {\n return value;\n };\n\n graphql.persisted = function persisted(\n documentId: string,\n document?: TadaDocumentNode\n ): TadaPersistedDocumentNode {\n return {\n kind: Kind.DOCUMENT,\n definitions: document ? document.definitions : [],\n documentId,\n };\n };\n\n return graphql as GraphQLTadaAPI<Schema, Config>;\n}\n\n/** Alias to a GraphQL parse function returning an exact document type.\n *\n * @param input - A string of a GraphQL document\n * @returns A parsed {@link DocumentNode}.\n *\n * @remarks\n * This function accepts a GraphQL document string and parses it, just like\n * GraphQL’s `parse` function. However, its return type will be the exact\n * structure of the AST parsed in types.\n */\nfunction parse<const In extends string>(input: In): parseDocument<In> {\n return _parse(input) as any;\n}\n\nexport type getDocumentNode<\n Document extends DocumentNodeLike,\n Introspection extends SchemaLike,\n Fragments extends { [name: string]: any } = {},\n isMaskingDisabled = false,\n> =\n getDocumentType<Document, Introspection, Fragments> extends never\n ? never\n : TadaDocumentNode<\n getDocumentType<Document, Introspection, Fragments>,\n getVariablesType<Document, Introspection>,\n decorateFragmentDef<Document, isMaskingDisabled>\n >;\n\n/** A GraphQL `DocumentNode` with attached types for results and variables.\n *\n * @remarks\n * This is a GraphQL {@link DocumentNode} with attached types for results and variables.\n * This is used by GraphQL clients to infer the types of results and variables and provide\n * type-safety in GraphQL documents.\n *\n * You can create typed GraphQL documents using the {@link graphql} function.\n *\n * `Result` is the type of GraphQL results, as returned by GraphQL APIs for a given query.\n * `Variables` is the type of variables, as accepted by GraphQL APIs for a given query.\n *\n * @see {@link https://github.com/dotansimha/graphql-typed-document-node} for more information.\n */\ninterface TadaDocumentNode<\n Result = { [key: string]: any },\n Variables = { [key: string]: any },\n Decoration = void,\n> extends DocumentNode,\n DocumentDecoration<Result, Variables>,\n DefinitionDecoration<Decoration> {}\n\n/** A GraphQL persisted document with attached types for results and variables.\n *\n * @remarks\n * This type still matches a GraphQL {@link DocumentNode}, but doesn’t contain\n * any definitions. At runtime, this means that this document is empty.\n *\n * Instead of its definitions, it carries an `id` property that is typically\n * used to uniquely identify the document to your GraphQL API, without disclosing\n * the shape of the query or schema transparently.\n */\ninterface TadaPersistedDocumentNode<\n Result = { [key: string]: any },\n Variables = { [key: string]: any },\n> extends DocumentNode,\n DocumentDecoration<Result, Variables> {\n definitions: readonly DefinitionNode[];\n documentId: string;\n}\n\n/** A utility type returning the `Result` type of typed GraphQL documents.\n *\n * @remarks\n * This accepts a {@link TadaDocumentNode} and returns the attached `Result` type\n * of GraphQL documents.\n */\ntype ResultOf<Document> = Document extends DocumentDecoration<infer Result, any> ? Result : never;\n\n/** A utility type returning the `Variables` type of typed GraphQL documents.\n *\n * @remarks\n * This accepts a {@link TadaDocumentNode} and returns the attached `Variables` type\n * of GraphQL documents.\n */\ntype VariablesOf<Document> =\n Document extends DocumentDecoration<any, infer Variables> ? Variables : never;\n\n/** Creates a fragment mask for a given fragment document.\n *\n * @remarks\n * When {@link graphql} is used to create a fragment and is spread into another\n * fragment or query, their result types will only contain a “reference” to the\n * fragment. This encourages isolation and is known as “fragment masking.”\n *\n * While {@link readFragment} is used to unmask these fragment masks, this utility\n * creates a fragment mask, so you can accept the masked data in the part of your\n * codebase that defines a fragment.\n *\n * @example\n * ```\n * import { FragmentOf, graphql, readFragment } from 'gql.tada';\n *\n * const bookFragment = graphql(`\n * fragment BookComponent on Book {\n * id\n * title\n * }\n * `);\n *\n * // May be called with any GraphQL data that contains a spread of `bookFragment`\n * const getBook = (data: FragmentOf<typeof bookFragment>) => {\n * // Unmasks the fragment and casts to the result type of `bookFragment`\n * const book = readFragment(bookFragment, data);\n * };\n * ```\n *\n * @see {@link readFragment} for how to read from fragment masks.\n */\ntype FragmentOf<Document extends FragmentShape> = makeFragmentRef<Document>;\n\ntype resultOrFragmentOf<Document extends FragmentShape> = FragmentOf<Document> | ResultOf<Document>;\n\ntype resultOfT<Document extends FragmentShape, T = unknown> =\n Document extends DocumentDecoration<infer Result, any>\n ? '__typename' extends keyof T\n ? Result extends { __typename?: T['__typename'] }\n ? Result\n : never\n : Result\n : never;\n\ntype resultOfFragmentsRec<\n Fragments extends readonly any[],\n Result = {},\n> = Fragments extends readonly [infer Fragment, ...infer Rest]\n ? resultOfFragmentsRec<Rest, ResultOf<Fragment> & Result>\n : Result;\n\ntype fragmentRefsOfFragmentsRec<\n Fragments extends readonly any[],\n FragmentRefs = {},\n> = Fragments extends readonly [infer Fragment, ...infer Rest]\n ? fragmentRefsOfFragmentsRec<Rest, makeFragmentRef<Fragment> & FragmentRefs>\n : obj<FragmentRefs>;\n\n/** Unmasks a fragment mask for a given fragment document and data.\n *\n * @param _document - A GraphQL document of a fragment, created using {@link graphql}.\n * @param fragment - A mask of the fragment, which can be wrapped in arrays, or nullable.\n * @returns The unmasked data of the fragment.\n *\n * @remarks\n * When {@link graphql} is used to create a fragment and is spread into another\n * fragment or query, their result types will only contain a “reference” to the\n * fragment. This encourages isolation and is known as “fragment masking.”\n *\n * This means that you must use {@link readFragment} to unmask these fragment masks\n * and get to the data. This encourages isolation and only using the data you define\n * a part of your codebase to require.\n *\n * @example\n * ```\n * import { FragmentOf, graphql, readFragment } from 'gql.tada';\n *\n * const bookFragment = graphql(`\n * fragment BookComponent on Book {\n * id\n * title\n * }\n * `);\n *\n * const getBook = (data: FragmentOf<typeof bookFragment> | null) => {\n * // Unmasks the fragment and casts to the result type of `bookFragment`\n * // This is intersected with `| null` in this case, due to the input type.\n * const book = readFragment(bookFragment, data);\n * };\n *\n * const bookQuery = graphql(`\n * query Book ($id: ID!) {\n * book(id: $id) {\n * id\n * ...BookComponent\n * }\n * }\n * `, [bookFragment]);\n *\n * const getQuery = (data: ResultOf<typeof bookQuery>) => {\n * getBook(data?.book);\n * };\n * ```\n *\n * @see {@link readFragment} for how to read from fragment masks.\n */\nfunction readFragment<const Document extends FragmentShape = never>(\n _document: Document,\n fragment: never\n): resultOfT<Document>;\n\nfunction readFragment<\n const Document extends FragmentShape,\n const T extends resultOrFragmentOf<Document> | null | undefined | {},\n>(\n _document: Document,\n fragments: readonly T[]\n): readonly (T extends resultOrFragmentOf<Document> ? resultOfT<Document, T> : T)[];\nfunction readFragment<\n const Document extends FragmentShape,\n const T extends resultOrFragmentOf<Document> | null | undefined | {},\n>(\n _document: Document,\n fragment: T\n): T extends resultOrFragmentOf<Document> ? resultOfT<Document, T> : T;\n\n// Reading arrays of fragments with required generic\nfunction readFragment<const Document extends FragmentShape>(\n fragment: readonly resultOrFragmentOf<Document>[]\n): readonly ResultOf<Document>[];\nfunction readFragment<const Document extends FragmentShape>(\n fragment: readonly (resultOrFragmentOf<Document> | null)[]\n): readonly (ResultOf<Document> | null)[];\nfunction readFragment<const Document extends FragmentShape>(\n fragment: readonly (resultOrFragmentOf<Document> | undefined)[]\n): readonly (ResultOf<Document> | undefined)[];\nfunction readFragment<const Document extends FragmentShape>(\n fragment: readonly (resultOrFragmentOf<Document> | null | undefined)[]\n): readonly (ResultOf<Document> | null | undefined)[];\n// Reading arrays of fragments with required generic with optional `{}` type\nfunction readFragment<const Document extends FragmentShape>(\n fragment: readonly (resultOrFragmentOf<Document> | {})[]\n): readonly (ResultOf<Document> | {})[];\nfunction readFragment<const Document extends FragmentShape>(\n fragment: readonly (resultOrFragmentOf<Document> | null | {})[]\n): readonly (ResultOf<Document> | null | {})[];\nfunction readFragment<const Document extends FragmentShape>(\n fragment: readonly (resultOrFragmentOf<Document> | undefined | {})[]\n): readonly (ResultOf<Document> | undefined | {})[];\nfunction readFragment<const Document extends FragmentShape>(\n fragment: readonly (resultOrFragmentOf<Document> | null | undefined | {})[]\n): readonly (ResultOf<Document> | null | undefined | {})[];\n// Reading fragments with required generic\nfunction readFragment<const Document extends FragmentShape>(\n fragment: resultOrFragmentOf<Document>\n): ResultOf<Document>;\nfunction readFragment<const Document extends FragmentShape>(\n fragment: resultOrFragmentOf<Document> | null\n): ResultOf<Document> | null;\nfunction readFragment<const Document extends FragmentShape>(\n fragment: resultOrFragmentOf<Document> | undefined\n): ResultOf<Document> | undefined;\nfunction readFragment<const Document extends FragmentShape>(\n fragment: resultOrFragmentOf<Document> | null | undefined\n): ResultOf<Document> | null | undefined;\n// Reading fragments with required generic with optional `{}` type\nfunction readFragment<const Document extends FragmentShape>(\n fragment: resultOrFragmentOf<Document> | {}\n): ResultOf<Document> | {};\nfunction readFragment<const Document extends FragmentShape>(\n fragment: resultOrFragmentOf<Document> | null | {}\n): ResultOf<Document> | null | {};\nfunction readFragment<const Document extends FragmentShape>(\n fragment: resultOrFragmentOf<Document> | undefined | {}\n): ResultOf<Document> | undefined | {};\nfunction readFragment<const Document extends FragmentShape>(\n fragment: resultOrFragmentOf<Document> | null | undefined | {}\n): ResultOf<Document> | null | undefined | {};\n\nfunction readFragment(...args: [unknown] | [unknown, unknown]) {\n return args.length === 2 ? args[1] : args[0];\n}\n\n/** For testing, masks fragment data for given data and fragments.\n *\n * @param _fragments - A list of GraphQL documents of fragments, created using {@link graphql}.\n * @param data - The combined result data of the fragments, which can be wrapped in arrays.\n * @returns The masked data of the fragments.\n *\n * @remarks\n * When creating test data, you may define data for fragments that’s unmasked, making it\n * unusable in parent fragments or queries that require masked data.\n *\n * This means that you may have to use {@link maskFragments} to mask your data first\n * for TypeScript to not report an error.\n *\n * @example\n * ```\n * import { FragmentOf, ResultOf, graphql, maskFragments } from 'gql.tada';\n *\n * const bookFragment = graphql(`\n * fragment BookComponent on Book {\n * id\n * title\n * }\n * `);\n *\n * const data = maskFragments([bookFragment], { id: 'id', title: 'book' });\n * ```\n *\n * @see {@link readFragment} for how to read from fragment masks (i.e. the reverse)\n */\nfunction maskFragments<const Fragments extends readonly FragmentShape[]>(\n _fragments: Fragments,\n fragment: resultOfFragmentsRec<Fragments>\n): fragmentRefsOfFragmentsRec<Fragments>;\nfunction maskFragments<const Fragments extends readonly FragmentShape[]>(\n _fragments: Fragments,\n fragment: resultOfFragmentsRec<Fragments> | null\n): fragmentRefsOfFragmentsRec<Fragments> | null;\nfunction maskFragments<const Fragments extends readonly FragmentShape[]>(\n _fragments: Fragments,\n fragment: resultOfFragmentsRec<Fragments> | undefined\n): fragmentRefsOfFragmentsRec<Fragments> | undefined;\nfunction maskFragments<const Fragments extends readonly FragmentShape[]>(\n _fragments: Fragments,\n fragment: resultOfFragmentsRec<Fragments> | null | undefined\n): fragmentRefsOfFragmentsRec<Fragments> | null | undefined;\nfunction maskFragments<const Fragments extends readonly FragmentShape[]>(\n _fragments: Fragments,\n fragment: readonly resultOfFragmentsRec<Fragments>[]\n): readonly fragmentRefsOfFragmentsRec<Fragments>[];\nfunction maskFragments<const Fragments extends readonly FragmentShape[]>(\n _fragments: Fragments,\n fragment: readonly (resultOfFragmentsRec<Fragments> | null)[]\n): readonly (fragmentRefsOfFragmentsRec<Fragments> | null)[];\nfunction maskFragments<const Fragments extends readonly FragmentShape[]>(\n _fragments: Fragments,\n fragment: readonly (resultOfFragmentsRec<Fragments> | undefined)[]\n): readonly (fragmentRefsOfFragmentsRec<Fragments> | undefined)[];\nfunction maskFragments<const Fragments extends readonly FragmentShape[]>(\n _fragments: Fragments,\n fragment: readonly (resultOfFragmentsRec<Fragments> | null | undefined)[]\n): readonly (fragmentRefsOfFragmentsRec<Fragments> | null | undefined)[];\nfunction maskFragments(_fragments: unknown, data: unknown) {\n return data;\n}\n\n/** For testing, converts document data without fragment refs to their result type.\n *\n * @param _document - A GraphQL document, created using {@link graphql}.\n * @param data - The result data of the GraphQL document with optional fragment refs.\n * @returns The masked result data of the document.\n *\n * @remarks\n * When creating test data, you may define data for documents that’s unmasked, but\n * need to cast the data to match the result type of your document.\n *\n * This means that you may have to use {@link unsafe_readResult} to cast\n * them to the result type, instead of doing `as any as ResultOf<typeof document>`.\n *\n * This function is inherently unsafe, since it doesn't check that your document\n * actually contains the masked fragment data!\n *\n * @example\n * ```\n * import { FragmentOf, ResultOf, graphql, unsafe_readResult } from 'gql.tada';\n *\n * const bookFragment = graphql(`\n * fragment BookComponent on Book {\n * id\n * title\n * }\n * `);\n *\n * const query = graphql(`\n * query {\n * book {\n * ...BookComponent\n * }\n * }\n * `, [bookFragment]);\n *\n * const data = unsafe_readResult(query, { book: { id: 'id', title: 'book' } });\n * ```\n *\n * @see {@link readFragment} for how to read from fragment masks (i.e. the reverse)\n */\nfunction unsafe_readResult<\n const Document extends DocumentDecoration<any, any>,\n const Data extends omitFragmentRefsRec<ResultOf<Document>>,\n>(_document: Document, data: Data): ResultOf<Document> {\n return data as any;\n}\n\nconst graphql: initGraphQLTada<setupSchema> = initGraphQLTada();\n\nexport { parse, graphql, readFragment, maskFragments, unsafe_readResult };\n\nexport type {\n setupCache,\n setupSchema,\n parseDocument,\n AbstractSetupSchema,\n AbstractSetupCache,\n GraphQLTadaAPI,\n TadaDocumentNode,\n TadaPersistedDocumentNode,\n ResultOf,\n VariablesOf,\n FragmentOf,\n};\n"],"names":["CONCAT_LOC_DEPTH","CONCAT_LOC_SEEN","Set","initGraphQLTada","graphql","input","fragments","definitions","_parse","seen","document","definition","kind","Kind","FRAGMENT_DEFINITION","has","push","add","isFragment","directives","filter","directive","name","value","loc","DOCUMENT","body","concatLocSources","result","fragment","source","clear","start","end","length","locationOffset","line","column","_loc","scalar","_schema","persisted","documentId","parse","readFragment","args","maskFragments","_fragments","data","unsafe_readResult","_document"],"mappings":";;AAuDA,IAAIA,IAAmB;;AACvB,IAAMC,IAAkB,IAAIC;;ACiQrB,SAASC;EAId,SAASC,QAAQC,GAAeC;IAC9B,IAAMC,IAAcC,EAAOH,GAAOE;IAClC,IAAME,IAAO,IAAIP;IACjB,KAAK,IAAMQ,KAAYJ,KAAa;MAClC,KAAK,IAAMK,KAAcD,EAASH;QAChC,IAAII,EAAWC,SAASC,EAAKC,wBAAwBL,EAAKM,IAAIJ,IAAa;UACzEJ,EAAYS,KAAKL;UACjBF,EAAKQ,IAAIN;AACX;;;IAIJ,IAAIO;IACJ,KACGA,IAAaX,EAAY,GAAGK,SAASC,EAAKC,wBAC3CP,EAAY,GAAGY;MAEfZ,EAAY,GAAGY,aAAaZ,EAAY,GAAGY,WAAWC,QACnDC,KAAuC,cAAzBA,EAAUC,KAAKC;;IAIlC,IAAIC;IACJ,OAAO;MACLZ,MAAMC,EAAKY;MACXlB;MACA,OAAIiB;QAIF,KAAKA,KAAON,GAAY;UACtB,IAAMQ,IAAOrB,ID7RhB,SAASsB,iBAAiBrB;YAC/B;cACEN;cACA,IAAI4B,IAAS;cACb,KAAK,IAAMC,KAAYvB;gBACrB,KAAKL,EAAgBc,IAAIc,IAAW;kBAClC5B,EAAgBgB,IAAIY;kBACpB,KAAML,KAAEA,KAAQK;kBAChB,IAAIL;oBAAKI,KAAUJ,EAAIM,OAAOJ;;AAChC;;cAEF,OAAOE;AACT,cAAU;cACR,IAA2B,OAArB5B;gBACJC,EAAgB8B;;AAEpB;AACF,WC4Q+BJ,CAAiBrB,KAAa;UACnD,OAAO;YACL0B,OAAO;YACPC,KAAKP,EAAKQ;YACVJ,QAAQ;cACNJ,MAAMA;cACNJ,MAAM;cACNa,gBAAgB;gBAAEC,MAAM;gBAAGC,QAAQ;;;;AAGzC;QACA,OAAOb;AACR;MACD,OAAIA,CAAIc;QACNd,IAAMc;AACR;;AAEJ;EAEAlC,QAAQmC,SAAS,SAASA,OAAOC,GAAiBjB;IAChD,OAAOA;;EAGTnB,QAAQqC,YAAY,SAASA,UAC3BC,GACAhC;IAEA,OAAO;MACLE,MAAMC,EAAKY;MACXlB,aAAaG,IAAWA,EAASH,cAAc;MAC/CmC;;;EAIJ,OAAOtC;AACT;;AAYA,SAASuC,MAA+BtC;EACtC,OAAOG,EAAOH;AAChB;;AA6PA,SAASuC,gBAAgBC;EACvB,OAAuB,MAAhBA,EAAKX,SAAeW,EAAK,KAAKA,EAAK;AAC5C;;AA+DA,SAASC,cAAcC,GAAqBC;EAC1C,OAAOA;AACT;;AA0CA,SAASC,kBAGPC,GAAqBF;EACrB,OAAOA;AACT;;AAEA,IAAM5C,IAAwCD;;"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "gql.tada",
|
|
3
3
|
"description": "The spec-compliant & magical GraphQL query language engine in the TypeScript type system",
|
|
4
|
-
"version": "1.9.
|
|
4
|
+
"version": "1.9.1",
|
|
5
5
|
"author": "0no.co <hi@0no.co>",
|
|
6
6
|
"source": "./src/index.ts",
|
|
7
7
|
"main": "./dist/gql-tada",
|