aboutsummaryrefslogtreecommitdiff
path: root/README.md
blob: 76412a1bafe9c0d2924d0eb02b99f54c10a6e8d7 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
# @eol/gq

A batteries-included GraphQL toolkit for Deno, wrapping `graphql-js` and `@graphql-tools/schema` with the bits most APIs end up reaching for anyway: a Fetch-compatible HTTP handler, a cached `gql` tag, a `.graphql` file loader, and a cleaned-up GraphQL Playground.

## Install

Published on JSR as [`@eol/gq`](https://jsr.io/@eol/gq).

```sh
deno add jsr:@eol/gq
```

Or import directly:

```ts
import { executeSchema, gql, GraphQLHTTP } from "jsr:@eol/gq";
```

## Quick start

```ts
import { executeSchema, gql, GraphQLHTTP } from "@eol/gq";

const schema = executeSchema({
  resolvers: {
    Query: {
      hello: (_, { name }) => `hello, ${name ?? "world"}`
    }
  },
  typeDefs: gql`
    type Query {
      hello(name: String): String
    }
  `
});

Deno.serve(
  { port: 8000 },
  GraphQLHTTP({ graphiql: true, schema })
);
```

Visit `http://localhost:8000` in a browser for the Playground, or `POST` a query to the same URL.

## Loading schemas from `.graphql` files

Use `importQL` to read an entry file and resolve its imports into a single SDL string.

### Explicit imports

```graphql
# schema/schema.graphql
# import "./post.graphql"
# import "./user.graphql"

type Query {
  me: User
  posts: [Post!]!
}
```

```ts
import { executeSchema, gql, importQL } from "@eol/gq";

const typeDefs = gql(await importQL("schema/schema.graphql"));
const schema = executeSchema({ resolvers, typeDefs });
```

### Dynamic imports

Drop `# DYNAMIC_IMPORTS` in your entry file and every `.graphql` file found one level below `<cwd>/schema/` gets inlined at that marker:

```
schema/
  schema.graphql   # contains: # DYNAMIC_IMPORTS
  post/
    post.graphql
  user/
    user.graphql
```

## API

All symbols are re-exported from the package root (`@eol/gq`).

### `GraphQLHTTP(options)`

Returns a `(request) => Promise<Response>` handler. Pluggable into `Deno.serve`, [oak](https://jsr.io/@oak/oak), [hono](https://jsr.io/@hono/hono), or anything else Fetch-shaped.

Options:

| Option              | Type                                  | Description                                          |
| ------------------- | ------------------------------------- | ---------------------------------------------------- |
| `schema`            | `GraphQLSchema`                       | Required. Executable schema.                         |
| `context`           | `(req) => Ctx \| Promise<Ctx>`        | Builds the resolver context per request.             |
| `graphiql`          | `boolean`                             | Serve the Playground on `GET` + `Accept: text/html`. |
| `headers`           | `HeadersInit`                         | Extra headers merged into every response.            |
| `playgroundOptions` | `Omit<RenderPageOptions, "endpoint">` | Passthrough options for the Playground renderer.     |

### `executeSchema(config)`

Re-export of `@graphql-tools/schema`’s `makeExecutableSchema`, renamed for brevity.

### `gql` *(tagged template)*

Parses a GraphQL string into a `DocumentNode`. Results are cached by normalized source, and embedded `DocumentNode` interpolations are inlined from their original source.

Companion knobs:

- `disableExperimentalFragmentVariables()`
- `disableFragmentWarnings()`
- `enableExperimentalFragmentVariables()`
- `resetCaches()`

### `importQL(path)`

Reads a `.graphql` file and resolves its imports. See [Loading schemas from `.graphql` files](#loading-schemas-from-graphql-files).

### `runHttpQuery(params, options, request)`

Low-level executor that `GraphQLHTTP` delegates to. Use it if you’re rolling your own transport but still want the context wiring.

### Types

`GQLOptions`, `GQLRequest`, `GraphQLParams`, `GraphQLHandler`, plus the Playground types (`RenderPageOptions`, `MiddlewareOptions`, `ISettings`, `EditorColours`, `Tab`, `Theme`, `CursorShape`, `IntrospectionResult`).

## Features

- Import `*.graphql` files — explicit and dynamic — via `importQL`.
- GraphiQL/Playground code cleaned up; SVGs redrawn so they actually make sense.
- Ships typed; passes `deno check entry.ts` with no fuss.
- Zero build step — it’s Deno, you just import it.

## TODO

- Add a runnable example.
- Replace React Playground with Svelte/SvelteKit.
- Take over the world (real world, metaverse, or [yggdrasil](https://yggdrasil-network.github.io), whichever comes first).

## License

MIT