gql.tada 1.0.0-beta.1 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +29 -55
- package/dist/gql-tada.d.ts +8 -12
- package/dist/gql-tada.js.map +1 -1
- package/dist/gql-tada.mjs.map +1 -1
- package/package.json +3 -2
package/README.md
CHANGED
|
@@ -23,7 +23,26 @@ In short, `gql.tada`,
|
|
|
23
23
|
Since this is all done in the TypeScript type system and type checker, this all happens
|
|
24
24
|
while you edit your GraphQL front-end code and is always accurate.
|
|
25
25
|
|
|
26
|
-
|
|
26
|
+
In short, **with `gql.tada` and [GraphQLSP](https://github.com/0no-co/graphqlsp) you get on-the-fly, automatically typed GraphQL documents
|
|
27
|
+
with full editor feedback, auto-completion, and type hints!**
|
|
28
|
+
|
|
29
|
+
## 📃 [Documentation](https://gql-tada.0no.co)
|
|
30
|
+
|
|
31
|
+
Check out the [“Get Started” section’s Installation page](https://gql-tada.0no.co/get-started/installation/) in the documentation.
|
|
32
|
+
|
|
33
|
+
- Get Started
|
|
34
|
+
- **[Introduction](https://gql-tada.0no.co)** — everything you need to know
|
|
35
|
+
- **[Installation](https://gql-tada.0no.co/get-started/installation)** — an installation guide
|
|
36
|
+
- **[Writing GraphQL](https://gql-tada.0no.co/get-started/writing-graphql/)** — how to write GraphQL documents
|
|
37
|
+
- API Reference
|
|
38
|
+
- **[`gql.tada` API](https://gql-tada.0no.co/reference/gql-tada-api/)** — `gql.tada` API Reference docs
|
|
39
|
+
- **[GraphQLSP Config](https://gql-tada.0no.co/reference/graphqlsp-config/)** — GraphQLSP Configuration Reference docs
|
|
40
|
+
|
|
41
|
+
Furthermore, all APIs and packages are self-documented using TSDocs. If you’re using a language
|
|
42
|
+
server for TypeScript, the documentation for each API should pop up in your editor when hovering
|
|
43
|
+
`gql.tada`’s code and APIs.
|
|
44
|
+
|
|
45
|
+
## 🔎 Let’s take a look!
|
|
27
46
|
|
|
28
47
|
```ts
|
|
29
48
|
import { graphql } from 'gql.tada';
|
|
@@ -56,60 +75,15 @@ const query = graphql(
|
|
|
56
75
|
);
|
|
57
76
|
```
|
|
58
77
|
|
|
59
|
-
##
|
|
60
|
-
|
|
61
|
-
Install `gql.tada` using your project’s package manager,
|
|
62
|
-
|
|
63
|
-
```sh
|
|
64
|
-
npm i gql.tada
|
|
65
|
-
pnpm add graphql
|
|
66
|
-
yarn add gql.tada
|
|
67
|
-
bun add graphql
|
|
68
|
-
```
|
|
69
|
-
|
|
70
|
-
`gql.tada` infers the types of your queries. However, it can’t provide you with editor feedback,
|
|
71
|
-
like autocompletion, diagnostics & errors, and hover information inside GraphQL queries.
|
|
72
|
-
For the best experience, it’s recommended to install [GraphQLSP](https://github.com/0no-co/graphqlsp)
|
|
73
|
-
to supplement these features.
|
|
74
|
-
|
|
75
|
-
Install `@0no-co/graphqlsp` as a dev dependency,
|
|
76
|
-
|
|
77
|
-
```sh
|
|
78
|
-
npm i -D gql.tada
|
|
79
|
-
pnpm add -D graphql
|
|
80
|
-
yarn add --dev gql.tada
|
|
81
|
-
bun add --dev graphql
|
|
82
|
-
```
|
|
83
|
-
|
|
84
|
-
Then, update your `tsconfig.json` to enable the `graphqlsp` plugin in your TypeScript server,
|
|
78
|
+
## 📦 [Releases](https://github.com/0no-co/gql.tada/releases)
|
|
85
79
|
|
|
86
|
-
|
|
80
|
+
If you'd like to get involved, [check out our Contributor's guide.](https://github.com/0no-co/gql.tada/blob/main/CONTRIBUTING.md)
|
|
87
81
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
"compilerOptions": {
|
|
91
|
-
+ "plugins": [
|
|
92
|
-
+ {
|
|
93
|
-
+ "name": "@0no-co/graphqlsp",
|
|
94
|
-
+ "schema": "./schema.graphql"
|
|
95
|
-
+ }
|
|
96
|
-
+ ]
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
```
|
|
82
|
+
All new releases and updates are listed on GitHub with full changelogs.
|
|
83
|
+
The [`CHANGELOG.md` file](https://github.com/0no-co/gql.tada/blob/main/CHANGELOG.md) further documents all the historical changes for `gql.tada`.
|
|
100
84
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
> **.vscode/config.json**
|
|
107
|
-
>
|
|
108
|
-
> ```diff
|
|
109
|
-
> {
|
|
110
|
-
> + "typescript.tsdk": "node_modules/typescript/lib",
|
|
111
|
-
> + "typescript.enablePromptUseWorkspaceTsdk": true
|
|
112
|
-
> }
|
|
113
|
-
> ```
|
|
114
|
-
|
|
115
|
-
<!-- TODO -->
|
|
85
|
+
New releases are prepared using
|
|
86
|
+
[changesets](https://github.com/0no-co/gql.tada/blob/main/CONTRIBUTING.md#how-do-i-document-a-change-for-the-changelog),
|
|
87
|
+
which are changelog entries added to each PR, and we have “Version Packages” PRs that once merged
|
|
88
|
+
will release new versions of the `gql.tada` package. You can use `@canary` releases from `npm` if you’d
|
|
89
|
+
like to get a preview of the merged changes.
|
package/dist/gql-tada.d.ts
CHANGED
|
@@ -1399,9 +1399,8 @@ interface AbstractSetupSchema {
|
|
|
1399
1399
|
* @param scalars - An object type with scalar names as keys and the corresponding scalar types as values.
|
|
1400
1400
|
*
|
|
1401
1401
|
* @example
|
|
1402
|
-
*
|
|
1403
1402
|
* ```
|
|
1404
|
-
* import { myIntrospection } from './myIntrospection';
|
|
1403
|
+
* import type { myIntrospection } from './myIntrospection';
|
|
1405
1404
|
*
|
|
1406
1405
|
* declare module 'gql.tada' {
|
|
1407
1406
|
* interface setupSchema {
|
|
@@ -1433,7 +1432,6 @@ interface GraphQLTadaAPI<Schema extends IntrospectionLikeType> {
|
|
|
1433
1432
|
* which will then automatically infer the result and variables types.
|
|
1434
1433
|
*
|
|
1435
1434
|
* @example
|
|
1436
|
-
*
|
|
1437
1435
|
* ```
|
|
1438
1436
|
* import { graphql } from 'gql.tada';
|
|
1439
1437
|
*
|
|
@@ -1464,6 +1462,10 @@ interface GraphQLTadaAPI<Schema extends IntrospectionLikeType> {
|
|
|
1464
1462
|
fragments?: Fragments
|
|
1465
1463
|
): getDocumentNode<parseDocument<In>, Schema, getFragmentsOfDocumentsRec<Fragments>>;
|
|
1466
1464
|
}
|
|
1465
|
+
type schemaOfConfig<Setup extends AbstractSetupSchema> = mapIntrospection<
|
|
1466
|
+
matchOr<IntrospectionQuery, Setup['introspection'], never>,
|
|
1467
|
+
matchOr<ScalarsLike, Setup['scalars'], {}>
|
|
1468
|
+
>;
|
|
1467
1469
|
/** Setup function to create a typed `graphql` document function with.
|
|
1468
1470
|
*
|
|
1469
1471
|
* @remarks
|
|
@@ -1475,10 +1477,9 @@ interface GraphQLTadaAPI<Schema extends IntrospectionLikeType> {
|
|
|
1475
1477
|
* editor and the TypeScript language server to recognize your GraphQL documents correctly.
|
|
1476
1478
|
*
|
|
1477
1479
|
* @example
|
|
1478
|
-
*
|
|
1479
1480
|
* ```
|
|
1480
1481
|
* import { initGraphQLTada } from 'gql.tada';
|
|
1481
|
-
* import { myIntrospection } from './myIntrospection';
|
|
1482
|
+
* import type { myIntrospection } from './myIntrospection';
|
|
1482
1483
|
*
|
|
1483
1484
|
* export const graphql = initGraphQLTada<{
|
|
1484
1485
|
* introspection: typeof myIntrospection;
|
|
@@ -1492,10 +1493,7 @@ interface GraphQLTadaAPI<Schema extends IntrospectionLikeType> {
|
|
|
1492
1493
|
* ```
|
|
1493
1494
|
*/
|
|
1494
1495
|
declare function initGraphQLTada<const Setup extends AbstractSetupSchema>(): GraphQLTadaAPI<
|
|
1495
|
-
|
|
1496
|
-
matchOr<IntrospectionQuery, Setup['introspection'], never>,
|
|
1497
|
-
matchOr<ScalarsLike, Setup['scalars'], {}>
|
|
1498
|
-
>
|
|
1496
|
+
schemaOfConfig<Setup>
|
|
1499
1497
|
>;
|
|
1500
1498
|
/** Alias to a GraphQL parse function returning an exact document type.
|
|
1501
1499
|
*
|
|
@@ -1578,7 +1576,6 @@ type VariablesOf<Document> = Document extends DocumentDecoration<infer _, infer
|
|
|
1578
1576
|
* codebase that defines a fragment.
|
|
1579
1577
|
*
|
|
1580
1578
|
* @example
|
|
1581
|
-
*
|
|
1582
1579
|
* ```
|
|
1583
1580
|
* import { FragmentOf, graphql, readFragment } from 'gql.tada';
|
|
1584
1581
|
*
|
|
@@ -1634,7 +1631,6 @@ type fragmentOfTypeRec<Document extends DocumentDefDecorationLike> =
|
|
|
1634
1631
|
* a part of your codebase to require.
|
|
1635
1632
|
*
|
|
1636
1633
|
* @example
|
|
1637
|
-
*
|
|
1638
1634
|
* ```
|
|
1639
1635
|
* import { FragmentOf, graphql, readFragment } from 'gql.tada';
|
|
1640
1636
|
*
|
|
@@ -1675,7 +1671,7 @@ declare function readFragment<
|
|
|
1675
1671
|
_document: DocumentDecoration<Data, any> & Document,
|
|
1676
1672
|
fragment: Fragment
|
|
1677
1673
|
): fragmentOfTypeRec<Document> extends Fragment ? unknown : mirrorFragmentTypeRec<Fragment, Data>;
|
|
1678
|
-
declare const graphql: GraphQLTadaAPI<
|
|
1674
|
+
declare const graphql: GraphQLTadaAPI<schemaOfConfig<setupSchema>>;
|
|
1679
1675
|
|
|
1680
1676
|
export {
|
|
1681
1677
|
type AbstractSetupSchema,
|
package/dist/gql-tada.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gql-tada.js","sources":["../src/api.ts"],"sourcesContent":["import type { DocumentNode, DefinitionNode } from '@0no-co/graphql.web';\nimport { Kind, parse as _parse } from '@0no-co/graphql.web';\n\nimport type {\n IntrospectionQuery,\n ScalarsLike,\n IntrospectionLikeType,\n mapIntrospection,\n} from './introspection';\n\nimport type {\n FragmentDefDecorationLike,\n DocumentDefDecorationLike,\n getFragmentsOfDocumentsRec,\n makeFragmentDefDecoration,\n decorateFragmentDef,\n makeFragmentRef,\n $tada,\n} from './namespace';\n\nimport type { getDocumentType } from './selection';\nimport type { getVariablesType } from './variables';\nimport type { parseDocument, DocumentNodeLike } from './parser';\nimport type { stringLiteral, matchOr, DocumentDecoration } 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: IntrospectionQuery;\n scalars?: ScalarsLike;\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 * ```\n * import { 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 GraphQLTadaAPI<Schema extends IntrospectionLikeType> {\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 * ```\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 stringLiteral<In>,\n const Fragments extends readonly [...DocumentDefDecorationLike[]],\n >(\n input: In,\n fragments?: Fragments\n ): getDocumentNode<parseDocument<In>, Schema, getFragmentsOfDocumentsRec<Fragments>>;\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 * ```\n * import { initGraphQLTada } from 'gql.tada';\n * import { 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 */\nfunction initGraphQLTada<const Setup extends AbstractSetupSchema>() {\n type Schema = mapIntrospection<\n matchOr<IntrospectionQuery, Setup['introspection'], never>,\n matchOr<ScalarsLike, Setup['scalars'], {}>\n >;\n\n return function graphql(input: string, fragments?: readonly DocumentDefDecorationLike[]): any {\n const definitions = _parse(input).definitions as 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 return { kind: Kind.DOCUMENT, definitions: [...definitions] } as any;\n } as GraphQLTadaAPI<Schema>;\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 stringLiteral<In>>(input: In): parseDocument<In> {\n return _parse(input) as any;\n}\n\ntype getDocumentNode<\n Document extends DocumentNodeLike,\n Introspection extends IntrospectionLikeType,\n Fragments extends { [name: string]: any } = {},\n> = getDocumentType<Document, Introspection, Fragments> extends infer Result\n ? Result extends never\n ? never\n : TadaDocumentNode<\n Result,\n getVariablesType<Document, Introspection>,\n decorateFragmentDef<Document>\n >\n : never;\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 = never,\n> extends DocumentNode,\n DocumentDecoration<Result, Variables>,\n makeFragmentDefDecoration<Decoration> {}\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, infer _>\n ? Result\n : 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> = Document extends DocumentDecoration<infer _, infer Variables>\n ? Variables\n : 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 * ```\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 DocumentDefDecorationLike> = Exclude<\n Document[$tada.fragmentDef],\n undefined\n> extends infer FragmentDef extends FragmentDefDecorationLike\n ? makeFragmentRef<FragmentDef>\n : never;\n\nexport type mirrorFragmentTypeRec<Fragment, Data> = Fragment extends (infer Value)[]\n ? mirrorFragmentTypeRec<Value, Data>[]\n : Fragment extends readonly (infer Value)[]\n ? readonly mirrorFragmentTypeRec<Value, Data>[]\n : Fragment extends null\n ? null\n : Fragment extends undefined\n ? undefined\n : Data;\n\ntype fragmentOfTypeRec<Document extends DocumentDefDecorationLike> =\n | readonly fragmentOfTypeRec<Document>[]\n | FragmentOf<Document>\n | undefined\n | null;\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 * ```\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<\n const Document extends DocumentDefDecorationLike,\n const Fragment extends fragmentOfTypeRec<Document>,\n const Data,\n>(\n _document: DocumentDecoration<Data, any> & Document,\n fragment: Fragment\n): fragmentOfTypeRec<Document> extends Fragment ? unknown : mirrorFragmentTypeRec<Fragment, Data> {\n return fragment as any;\n}\n\nconst graphql = initGraphQLTada<setupSchema>();\n\nexport { parse, graphql, readFragment, initGraphQLTada };\n\nexport type {\n setupSchema,\n parseDocument,\n AbstractSetupSchema,\n GraphQLTadaAPI,\n TadaDocumentNode,\n ResultOf,\n VariablesOf,\n FragmentOf,\n};\n"],"names":["initGraphQLTada","graphql","input","fragments","definitions","_parse","seen","Set","document","definition","kind","Kind","FRAGMENT_DEFINITION","has","push","add","DOCUMENT","parse","readFragment","_document","fragment"],"mappings":";;;;;;AA4JA,SAASA;EAMP,OAAO,SAASC,QAAQC,GAAeC;IACrC,IAAMC,IAAcC,EAAAA,MAAOH,GAAOE;IAClC,IAAME,IAAO,IAAIC;IACjB,KAAK,IAAMC,KAAYL,KAAa;MAClC,KAAK,IAAMM,KAAcD,EAASJ;QAChC,IAAIK,EAAWC,SAASC,OAAKC,wBAAwBN,EAAKO,IAAIJ,IAAa;UACzEL,EAAYU,KAAKL;UACjBH,EAAKS,IAAIN;AACX;;;IAGJ,OAAO;MAAEC,MAAMC,EAAIA,KAACK;MAAUZ,aAAa,KAAIA;;;AAEnD;;AA2LA,IAAMH,IAAUD;;;;;;gBA/KhB,SAASiB,MAA0Cf;EACjD,OAAOG,EAAAA,MAAOH;AAChB;;uBAkKA,SAASgB,aAKPC,GACAC;EAEA,OAAOA;AACT"}
|
|
1
|
+
{"version":3,"file":"gql-tada.js","sources":["../src/api.ts"],"sourcesContent":["import type { DocumentNode, DefinitionNode } from '@0no-co/graphql.web';\nimport { Kind, parse as _parse } from '@0no-co/graphql.web';\n\nimport type {\n IntrospectionQuery,\n ScalarsLike,\n IntrospectionLikeType,\n mapIntrospection,\n} from './introspection';\n\nimport type {\n FragmentDefDecorationLike,\n DocumentDefDecorationLike,\n getFragmentsOfDocumentsRec,\n makeFragmentDefDecoration,\n decorateFragmentDef,\n makeFragmentRef,\n $tada,\n} from './namespace';\n\nimport type { getDocumentType } from './selection';\nimport type { getVariablesType } from './variables';\nimport type { parseDocument, DocumentNodeLike } from './parser';\nimport type { stringLiteral, matchOr, DocumentDecoration } 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: IntrospectionQuery;\n scalars?: ScalarsLike;\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 GraphQLTadaAPI<Schema extends IntrospectionLikeType> {\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 stringLiteral<In>,\n const Fragments extends readonly [...DocumentDefDecorationLike[]],\n >(\n input: In,\n fragments?: Fragments\n ): getDocumentNode<parseDocument<In>, Schema, getFragmentsOfDocumentsRec<Fragments>>;\n}\n\ntype schemaOfConfig<Setup extends AbstractSetupSchema> = mapIntrospection<\n matchOr<IntrospectionQuery, Setup['introspection'], never>,\n matchOr<ScalarsLike, Setup['scalars'], {}>\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 */\nfunction initGraphQLTada<const Setup extends AbstractSetupSchema>() {\n type Schema = schemaOfConfig<Setup>;\n\n return function graphql(input: string, fragments?: readonly DocumentDefDecorationLike[]): any {\n const definitions = _parse(input).definitions as 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 return { kind: Kind.DOCUMENT, definitions: [...definitions] } as any;\n } as GraphQLTadaAPI<Schema>;\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 stringLiteral<In>>(input: In): parseDocument<In> {\n return _parse(input) as any;\n}\n\ntype getDocumentNode<\n Document extends DocumentNodeLike,\n Introspection extends IntrospectionLikeType,\n Fragments extends { [name: string]: any } = {},\n> = getDocumentType<Document, Introspection, Fragments> extends infer Result\n ? Result extends never\n ? never\n : TadaDocumentNode<\n Result,\n getVariablesType<Document, Introspection>,\n decorateFragmentDef<Document>\n >\n : never;\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 = never,\n> extends DocumentNode,\n DocumentDecoration<Result, Variables>,\n makeFragmentDefDecoration<Decoration> {}\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, infer _>\n ? Result\n : 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> = Document extends DocumentDecoration<infer _, infer Variables>\n ? Variables\n : 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 DocumentDefDecorationLike> = Exclude<\n Document[$tada.fragmentDef],\n undefined\n> extends infer FragmentDef extends FragmentDefDecorationLike\n ? makeFragmentRef<FragmentDef>\n : never;\n\nexport type mirrorFragmentTypeRec<Fragment, Data> = Fragment extends (infer Value)[]\n ? mirrorFragmentTypeRec<Value, Data>[]\n : Fragment extends readonly (infer Value)[]\n ? readonly mirrorFragmentTypeRec<Value, Data>[]\n : Fragment extends null\n ? null\n : Fragment extends undefined\n ? undefined\n : Data;\n\ntype fragmentOfTypeRec<Document extends DocumentDefDecorationLike> =\n | readonly fragmentOfTypeRec<Document>[]\n | FragmentOf<Document>\n | undefined\n | null;\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<\n const Document extends DocumentDefDecorationLike,\n const Fragment extends fragmentOfTypeRec<Document>,\n const Data,\n>(\n _document: DocumentDecoration<Data, any> & Document,\n fragment: Fragment\n): fragmentOfTypeRec<Document> extends Fragment ? unknown : mirrorFragmentTypeRec<Fragment, Data> {\n return fragment as any;\n}\n\nconst graphql: GraphQLTadaAPI<schemaOfConfig<setupSchema>> = initGraphQLTada();\n\nexport { parse, graphql, readFragment, initGraphQLTada };\n\nexport type {\n setupSchema,\n parseDocument,\n AbstractSetupSchema,\n GraphQLTadaAPI,\n TadaDocumentNode,\n ResultOf,\n VariablesOf,\n FragmentOf,\n};\n"],"names":["initGraphQLTada","graphql","input","fragments","definitions","_parse","seen","Set","document","definition","kind","Kind","FRAGMENT_DEFINITION","has","push","add","DOCUMENT","parse","readFragment","_document","fragment"],"mappings":";;;;;;AA8JA,SAASA;EAGP,OAAO,SAASC,QAAQC,GAAeC;IACrC,IAAMC,IAAcC,EAAAA,MAAOH,GAAOE;IAClC,IAAME,IAAO,IAAIC;IACjB,KAAK,IAAMC,KAAYL,KAAa;MAClC,KAAK,IAAMM,KAAcD,EAASJ;QAChC,IAAIK,EAAWC,SAASC,OAAKC,wBAAwBN,EAAKO,IAAIJ,IAAa;UACzEL,EAAYU,KAAKL;UACjBH,EAAKS,IAAIN;AACX;;;IAGJ,OAAO;MAAEC,MAAMC,EAAIA,KAACK;MAAUZ,aAAa,KAAIA;;;AAEnD;;AAyLA,IAAMH,IAAuDD;;;;;;gBA7K7D,SAASiB,MAA0Cf;EACjD,OAAOG,EAAAA,MAAOH;AAChB;;uBAgKA,SAASgB,aAKPC,GACAC;EAEA,OAAOA;AACT"}
|
package/dist/gql-tada.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gql-tada.mjs","sources":["../src/api.ts"],"sourcesContent":["import type { DocumentNode, DefinitionNode } from '@0no-co/graphql.web';\nimport { Kind, parse as _parse } from '@0no-co/graphql.web';\n\nimport type {\n IntrospectionQuery,\n ScalarsLike,\n IntrospectionLikeType,\n mapIntrospection,\n} from './introspection';\n\nimport type {\n FragmentDefDecorationLike,\n DocumentDefDecorationLike,\n getFragmentsOfDocumentsRec,\n makeFragmentDefDecoration,\n decorateFragmentDef,\n makeFragmentRef,\n $tada,\n} from './namespace';\n\nimport type { getDocumentType } from './selection';\nimport type { getVariablesType } from './variables';\nimport type { parseDocument, DocumentNodeLike } from './parser';\nimport type { stringLiteral, matchOr, DocumentDecoration } 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: IntrospectionQuery;\n scalars?: ScalarsLike;\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 * ```\n * import { 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 GraphQLTadaAPI<Schema extends IntrospectionLikeType> {\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 * ```\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 stringLiteral<In>,\n const Fragments extends readonly [...DocumentDefDecorationLike[]],\n >(\n input: In,\n fragments?: Fragments\n ): getDocumentNode<parseDocument<In>, Schema, getFragmentsOfDocumentsRec<Fragments>>;\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 * ```\n * import { initGraphQLTada } from 'gql.tada';\n * import { 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 */\nfunction initGraphQLTada<const Setup extends AbstractSetupSchema>() {\n type Schema = mapIntrospection<\n matchOr<IntrospectionQuery, Setup['introspection'], never>,\n matchOr<ScalarsLike, Setup['scalars'], {}>\n >;\n\n return function graphql(input: string, fragments?: readonly DocumentDefDecorationLike[]): any {\n const definitions = _parse(input).definitions as 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 return { kind: Kind.DOCUMENT, definitions: [...definitions] } as any;\n } as GraphQLTadaAPI<Schema>;\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 stringLiteral<In>>(input: In): parseDocument<In> {\n return _parse(input) as any;\n}\n\ntype getDocumentNode<\n Document extends DocumentNodeLike,\n Introspection extends IntrospectionLikeType,\n Fragments extends { [name: string]: any } = {},\n> = getDocumentType<Document, Introspection, Fragments> extends infer Result\n ? Result extends never\n ? never\n : TadaDocumentNode<\n Result,\n getVariablesType<Document, Introspection>,\n decorateFragmentDef<Document>\n >\n : never;\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 = never,\n> extends DocumentNode,\n DocumentDecoration<Result, Variables>,\n makeFragmentDefDecoration<Decoration> {}\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, infer _>\n ? Result\n : 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> = Document extends DocumentDecoration<infer _, infer Variables>\n ? Variables\n : 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 * ```\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 DocumentDefDecorationLike> = Exclude<\n Document[$tada.fragmentDef],\n undefined\n> extends infer FragmentDef extends FragmentDefDecorationLike\n ? makeFragmentRef<FragmentDef>\n : never;\n\nexport type mirrorFragmentTypeRec<Fragment, Data> = Fragment extends (infer Value)[]\n ? mirrorFragmentTypeRec<Value, Data>[]\n : Fragment extends readonly (infer Value)[]\n ? readonly mirrorFragmentTypeRec<Value, Data>[]\n : Fragment extends null\n ? null\n : Fragment extends undefined\n ? undefined\n : Data;\n\ntype fragmentOfTypeRec<Document extends DocumentDefDecorationLike> =\n | readonly fragmentOfTypeRec<Document>[]\n | FragmentOf<Document>\n | undefined\n | null;\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 * ```\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<\n const Document extends DocumentDefDecorationLike,\n const Fragment extends fragmentOfTypeRec<Document>,\n const Data,\n>(\n _document: DocumentDecoration<Data, any> & Document,\n fragment: Fragment\n): fragmentOfTypeRec<Document> extends Fragment ? unknown : mirrorFragmentTypeRec<Fragment, Data> {\n return fragment as any;\n}\n\nconst graphql = initGraphQLTada<setupSchema>();\n\nexport { parse, graphql, readFragment, initGraphQLTada };\n\nexport type {\n setupSchema,\n parseDocument,\n AbstractSetupSchema,\n GraphQLTadaAPI,\n TadaDocumentNode,\n ResultOf,\n VariablesOf,\n FragmentOf,\n};\n"],"names":["initGraphQLTada","graphql","input","fragments","definitions","_parse","seen","Set","document","definition","kind","Kind","FRAGMENT_DEFINITION","has","push","add","DOCUMENT","parse","readFragment","_document","fragment"],"mappings":";;AA4JA,SAASA;EAMP,OAAO,SAASC,QAAQC,GAAeC;IACrC,IAAMC,IAAcC,EAAOH,GAAOE;IAClC,IAAME,IAAO,IAAIC;IACjB,KAAK,IAAMC,KAAYL,KAAa;MAClC,KAAK,IAAMM,KAAcD,EAASJ;QAChC,IAAIK,EAAWC,SAASC,EAAKC,wBAAwBN,EAAKO,IAAIJ,IAAa;UACzEL,EAAYU,KAAKL;UACjBH,EAAKS,IAAIN;AACX;;;IAGJ,OAAO;MAAEC,MAAMC,EAAKK;MAAUZ,aAAa,KAAIA;;;AAEnD;;AAYA,SAASa,MAA0Cf;EACjD,OAAOG,EAAOH;AAChB;;AAkKA,SAASgB,aAKPC,GACAC;EAEA,OAAOA;AACT;;AAEA,IAAMnB,IAAUD;;"}
|
|
1
|
+
{"version":3,"file":"gql-tada.mjs","sources":["../src/api.ts"],"sourcesContent":["import type { DocumentNode, DefinitionNode } from '@0no-co/graphql.web';\nimport { Kind, parse as _parse } from '@0no-co/graphql.web';\n\nimport type {\n IntrospectionQuery,\n ScalarsLike,\n IntrospectionLikeType,\n mapIntrospection,\n} from './introspection';\n\nimport type {\n FragmentDefDecorationLike,\n DocumentDefDecorationLike,\n getFragmentsOfDocumentsRec,\n makeFragmentDefDecoration,\n decorateFragmentDef,\n makeFragmentRef,\n $tada,\n} from './namespace';\n\nimport type { getDocumentType } from './selection';\nimport type { getVariablesType } from './variables';\nimport type { parseDocument, DocumentNodeLike } from './parser';\nimport type { stringLiteral, matchOr, DocumentDecoration } 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: IntrospectionQuery;\n scalars?: ScalarsLike;\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 GraphQLTadaAPI<Schema extends IntrospectionLikeType> {\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 stringLiteral<In>,\n const Fragments extends readonly [...DocumentDefDecorationLike[]],\n >(\n input: In,\n fragments?: Fragments\n ): getDocumentNode<parseDocument<In>, Schema, getFragmentsOfDocumentsRec<Fragments>>;\n}\n\ntype schemaOfConfig<Setup extends AbstractSetupSchema> = mapIntrospection<\n matchOr<IntrospectionQuery, Setup['introspection'], never>,\n matchOr<ScalarsLike, Setup['scalars'], {}>\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 */\nfunction initGraphQLTada<const Setup extends AbstractSetupSchema>() {\n type Schema = schemaOfConfig<Setup>;\n\n return function graphql(input: string, fragments?: readonly DocumentDefDecorationLike[]): any {\n const definitions = _parse(input).definitions as 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 return { kind: Kind.DOCUMENT, definitions: [...definitions] } as any;\n } as GraphQLTadaAPI<Schema>;\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 stringLiteral<In>>(input: In): parseDocument<In> {\n return _parse(input) as any;\n}\n\ntype getDocumentNode<\n Document extends DocumentNodeLike,\n Introspection extends IntrospectionLikeType,\n Fragments extends { [name: string]: any } = {},\n> = getDocumentType<Document, Introspection, Fragments> extends infer Result\n ? Result extends never\n ? never\n : TadaDocumentNode<\n Result,\n getVariablesType<Document, Introspection>,\n decorateFragmentDef<Document>\n >\n : never;\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 = never,\n> extends DocumentNode,\n DocumentDecoration<Result, Variables>,\n makeFragmentDefDecoration<Decoration> {}\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, infer _>\n ? Result\n : 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> = Document extends DocumentDecoration<infer _, infer Variables>\n ? Variables\n : 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 DocumentDefDecorationLike> = Exclude<\n Document[$tada.fragmentDef],\n undefined\n> extends infer FragmentDef extends FragmentDefDecorationLike\n ? makeFragmentRef<FragmentDef>\n : never;\n\nexport type mirrorFragmentTypeRec<Fragment, Data> = Fragment extends (infer Value)[]\n ? mirrorFragmentTypeRec<Value, Data>[]\n : Fragment extends readonly (infer Value)[]\n ? readonly mirrorFragmentTypeRec<Value, Data>[]\n : Fragment extends null\n ? null\n : Fragment extends undefined\n ? undefined\n : Data;\n\ntype fragmentOfTypeRec<Document extends DocumentDefDecorationLike> =\n | readonly fragmentOfTypeRec<Document>[]\n | FragmentOf<Document>\n | undefined\n | null;\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<\n const Document extends DocumentDefDecorationLike,\n const Fragment extends fragmentOfTypeRec<Document>,\n const Data,\n>(\n _document: DocumentDecoration<Data, any> & Document,\n fragment: Fragment\n): fragmentOfTypeRec<Document> extends Fragment ? unknown : mirrorFragmentTypeRec<Fragment, Data> {\n return fragment as any;\n}\n\nconst graphql: GraphQLTadaAPI<schemaOfConfig<setupSchema>> = initGraphQLTada();\n\nexport { parse, graphql, readFragment, initGraphQLTada };\n\nexport type {\n setupSchema,\n parseDocument,\n AbstractSetupSchema,\n GraphQLTadaAPI,\n TadaDocumentNode,\n ResultOf,\n VariablesOf,\n FragmentOf,\n};\n"],"names":["initGraphQLTada","graphql","input","fragments","definitions","_parse","seen","Set","document","definition","kind","Kind","FRAGMENT_DEFINITION","has","push","add","DOCUMENT","parse","readFragment","_document","fragment"],"mappings":";;AA8JA,SAASA;EAGP,OAAO,SAASC,QAAQC,GAAeC;IACrC,IAAMC,IAAcC,EAAOH,GAAOE;IAClC,IAAME,IAAO,IAAIC;IACjB,KAAK,IAAMC,KAAYL,KAAa;MAClC,KAAK,IAAMM,KAAcD,EAASJ;QAChC,IAAIK,EAAWC,SAASC,EAAKC,wBAAwBN,EAAKO,IAAIJ,IAAa;UACzEL,EAAYU,KAAKL;UACjBH,EAAKS,IAAIN;AACX;;;IAGJ,OAAO;MAAEC,MAAMC,EAAKK;MAAUZ,aAAa,KAAIA;;;AAEnD;;AAYA,SAASa,MAA0Cf;EACjD,OAAOG,EAAOH;AAChB;;AAgKA,SAASgB,aAKPC,GACAC;EAEA,OAAOA;AACT;;AAEA,IAAMnB,IAAuDD;;"}
|
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.0.0
|
|
4
|
+
"version": "1.0.0",
|
|
5
5
|
"author": "0no.co <hi@0no.co>",
|
|
6
6
|
"source": "./src/index.ts",
|
|
7
7
|
"main": "./dist/gql-tada",
|
|
@@ -88,7 +88,8 @@
|
|
|
88
88
|
"vitest": "1.1.3"
|
|
89
89
|
},
|
|
90
90
|
"publishConfig": {
|
|
91
|
-
"access": "public"
|
|
91
|
+
"access": "public",
|
|
92
|
+
"provenance": true
|
|
92
93
|
},
|
|
93
94
|
"scripts": {
|
|
94
95
|
"test": "vitest test",
|