@flightdev/graphql 0.1.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/LICENSE +21 -0
- package/README.md +149 -0
- package/dist/index.d.ts +93 -0
- package/dist/index.js +11 -0
- package/dist/yoga.d.ts +66 -0
- package/dist/yoga.js +39 -0
- package/package.json +49 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024-2026 Flight Contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
# @flight-framework/graphql
|
|
2
|
+
|
|
3
|
+
GraphQL adapter for Flight Framework. Optional, non-imposing - use it only if you need GraphQL.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @flight-framework/graphql graphql graphql-yoga
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Quick Start
|
|
12
|
+
|
|
13
|
+
Create a GraphQL endpoint in your Flight app:
|
|
14
|
+
|
|
15
|
+
```typescript
|
|
16
|
+
// src/routes/api/graphql.ts
|
|
17
|
+
import { createGraphQLHandler } from '@flight-framework/graphql';
|
|
18
|
+
import { yogaAdapter } from '@flight-framework/graphql/yoga';
|
|
19
|
+
import { schema } from '../../graphql/schema';
|
|
20
|
+
|
|
21
|
+
const handler = createGraphQLHandler({
|
|
22
|
+
adapter: yogaAdapter(),
|
|
23
|
+
schema,
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
export const GET = handler;
|
|
27
|
+
export const POST = handler;
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## Creating a Schema
|
|
31
|
+
|
|
32
|
+
### Code-First (Recommended)
|
|
33
|
+
|
|
34
|
+
```typescript
|
|
35
|
+
// src/graphql/schema.ts
|
|
36
|
+
import { createSchema } from 'graphql-yoga';
|
|
37
|
+
|
|
38
|
+
export const schema = createSchema({
|
|
39
|
+
typeDefs: /* GraphQL */ `
|
|
40
|
+
type Query {
|
|
41
|
+
hello(name: String): String!
|
|
42
|
+
users: [User!]!
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
type User {
|
|
46
|
+
id: ID!
|
|
47
|
+
name: String!
|
|
48
|
+
email: String!
|
|
49
|
+
}
|
|
50
|
+
`,
|
|
51
|
+
resolvers: {
|
|
52
|
+
Query: {
|
|
53
|
+
hello: (_, { name }) => `Hello ${name || 'World'}`,
|
|
54
|
+
users: () => db.users.findMany(),
|
|
55
|
+
},
|
|
56
|
+
},
|
|
57
|
+
});
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
### Schema-First
|
|
61
|
+
|
|
62
|
+
```typescript
|
|
63
|
+
import { buildSchema } from 'graphql';
|
|
64
|
+
import { createGraphQLHandler } from '@flight-framework/graphql';
|
|
65
|
+
import { yogaAdapter } from '@flight-framework/graphql/yoga';
|
|
66
|
+
|
|
67
|
+
const schema = buildSchema(/* GraphQL */ `
|
|
68
|
+
type Query {
|
|
69
|
+
hello: String
|
|
70
|
+
}
|
|
71
|
+
`);
|
|
72
|
+
|
|
73
|
+
const rootValue = {
|
|
74
|
+
hello: () => 'Hello World',
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
export const POST = createGraphQLHandler({
|
|
78
|
+
adapter: yogaAdapter({ rootValue }),
|
|
79
|
+
schema,
|
|
80
|
+
});
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
## Context
|
|
84
|
+
|
|
85
|
+
Pass request context to resolvers:
|
|
86
|
+
|
|
87
|
+
```typescript
|
|
88
|
+
const handler = createGraphQLHandler({
|
|
89
|
+
adapter: yogaAdapter(),
|
|
90
|
+
schema,
|
|
91
|
+
context: async (req) => {
|
|
92
|
+
const token = req.headers.get('Authorization');
|
|
93
|
+
const user = token ? await verifyToken(token) : null;
|
|
94
|
+
return { user, db };
|
|
95
|
+
},
|
|
96
|
+
});
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
Access in resolvers:
|
|
100
|
+
|
|
101
|
+
```typescript
|
|
102
|
+
const resolvers = {
|
|
103
|
+
Query: {
|
|
104
|
+
me: (_, __, ctx) => ctx.user,
|
|
105
|
+
posts: (_, __, ctx) => ctx.db.posts.findMany(),
|
|
106
|
+
},
|
|
107
|
+
};
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
## GraphiQL
|
|
111
|
+
|
|
112
|
+
GraphiQL is enabled by default in development. Access it at your endpoint URL.
|
|
113
|
+
|
|
114
|
+
To disable:
|
|
115
|
+
|
|
116
|
+
```typescript
|
|
117
|
+
const handler = createGraphQLHandler({
|
|
118
|
+
adapter: yogaAdapter({ graphiql: false }),
|
|
119
|
+
schema,
|
|
120
|
+
});
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
## Adapters
|
|
124
|
+
|
|
125
|
+
### GraphQL Yoga (Default)
|
|
126
|
+
|
|
127
|
+
```typescript
|
|
128
|
+
import { yogaAdapter } from '@flight-framework/graphql/yoga';
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
Yoga is the recommended adapter - modern, lightweight, full fetch API support.
|
|
132
|
+
|
|
133
|
+
### Apollo (Coming Soon)
|
|
134
|
+
|
|
135
|
+
```typescript
|
|
136
|
+
import { apolloAdapter } from '@flight-framework/graphql/apollo';
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
## TypeScript
|
|
140
|
+
|
|
141
|
+
Full TypeScript support with type inference:
|
|
142
|
+
|
|
143
|
+
```typescript
|
|
144
|
+
import type { GraphQLContext, GraphQLAdapter } from '@flight-framework/graphql';
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
## License
|
|
148
|
+
|
|
149
|
+
MIT
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import { GraphQLSchema } from 'graphql';
|
|
2
|
+
export { ExecutionResult, GraphQLSchema } from 'graphql';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* @flightdev/graphql
|
|
6
|
+
*
|
|
7
|
+
* GraphQL adapter for Flight Framework.
|
|
8
|
+
* Optional, non-imposing - use it only if you need GraphQL.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Context factory function type
|
|
13
|
+
*/
|
|
14
|
+
type ContextFactory<TContext = Record<string, unknown>> = (request: Request) => TContext | Promise<TContext>;
|
|
15
|
+
/**
|
|
16
|
+
* Configuration for GraphQL adapters
|
|
17
|
+
*/
|
|
18
|
+
interface GraphQLAdapterConfig<TContext = Record<string, unknown>> {
|
|
19
|
+
/** GraphQL schema */
|
|
20
|
+
schema: GraphQLSchema;
|
|
21
|
+
/** Context factory for resolvers */
|
|
22
|
+
context?: ContextFactory<TContext>;
|
|
23
|
+
/** Root value for schema-first approach */
|
|
24
|
+
rootValue?: unknown;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* GraphQL handler function type
|
|
28
|
+
*
|
|
29
|
+
* Uses rest parameters with `any[]` to accommodate different GraphQL server
|
|
30
|
+
* implementations with varying signatures:
|
|
31
|
+
* - GraphQL Yoga: `fetch(request, serverContext?)` with overloaded variants
|
|
32
|
+
* - Apollo: `executeHTTPGraphQLRequest(request)`
|
|
33
|
+
* - Other implementations may differ
|
|
34
|
+
*
|
|
35
|
+
* This is an intentional TypeScript escape hatch - the adapter pattern provides
|
|
36
|
+
* type safety at the public API boundaries (createGraphQLHandler), while allowing
|
|
37
|
+
* internal flexibility for wrapping third-party libraries.
|
|
38
|
+
*
|
|
39
|
+
* @see https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#any
|
|
40
|
+
*/
|
|
41
|
+
type GraphQLHandler = (request: Request, ...serverContext: any[]) => Response | Promise<Response>;
|
|
42
|
+
/**
|
|
43
|
+
* GraphQL adapter interface
|
|
44
|
+
*
|
|
45
|
+
* Implement this interface to add support for different GraphQL servers.
|
|
46
|
+
*/
|
|
47
|
+
interface GraphQLAdapter {
|
|
48
|
+
/** Adapter name for debugging */
|
|
49
|
+
readonly name: string;
|
|
50
|
+
/**
|
|
51
|
+
* Create a request handler from the adapter config
|
|
52
|
+
*/
|
|
53
|
+
createHandler<TContext = Record<string, unknown>>(config: GraphQLAdapterConfig<TContext>): GraphQLHandler;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Options for createGraphQLHandler
|
|
57
|
+
*/
|
|
58
|
+
interface CreateGraphQLHandlerOptions<TContext = Record<string, unknown>> {
|
|
59
|
+
/** The GraphQL adapter to use */
|
|
60
|
+
adapter: GraphQLAdapter;
|
|
61
|
+
/** GraphQL schema */
|
|
62
|
+
schema: GraphQLSchema;
|
|
63
|
+
/** Context factory for resolvers */
|
|
64
|
+
context?: ContextFactory<TContext>;
|
|
65
|
+
/** Root value for schema-first approach */
|
|
66
|
+
rootValue?: unknown;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Create a GraphQL request handler
|
|
70
|
+
*
|
|
71
|
+
* @example
|
|
72
|
+
* ```typescript
|
|
73
|
+
* import { createGraphQLHandler } from '@flightdev/graphql';
|
|
74
|
+
* import { yogaAdapter } from '@flightdev/graphql/yoga';
|
|
75
|
+
* import { schema } from './schema';
|
|
76
|
+
*
|
|
77
|
+
* const handler = createGraphQLHandler({
|
|
78
|
+
* adapter: yogaAdapter(),
|
|
79
|
+
* schema,
|
|
80
|
+
* context: (req) => ({ user: getUser(req) }),
|
|
81
|
+
* });
|
|
82
|
+
*
|
|
83
|
+
* export const GET = handler;
|
|
84
|
+
* export const POST = handler;
|
|
85
|
+
* ```
|
|
86
|
+
*/
|
|
87
|
+
declare function createGraphQLHandler<TContext = Record<string, unknown>>(options: CreateGraphQLHandlerOptions<TContext>): GraphQLHandler;
|
|
88
|
+
/**
|
|
89
|
+
* Type helper for GraphQL context
|
|
90
|
+
*/
|
|
91
|
+
type GraphQLContext<T = Record<string, unknown>> = T;
|
|
92
|
+
|
|
93
|
+
export { type ContextFactory, type CreateGraphQLHandlerOptions, type GraphQLAdapter, type GraphQLAdapterConfig, type GraphQLContext, type GraphQLHandler, createGraphQLHandler };
|
package/dist/index.js
ADDED
package/dist/yoga.d.ts
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { YogaServerOptions } from 'graphql-yoga';
|
|
2
|
+
export { createSchema } from 'graphql-yoga';
|
|
3
|
+
import { GraphQLAdapter } from './index.js';
|
|
4
|
+
import 'graphql';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* GraphQL Yoga Adapter for Flight Framework
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ```typescript
|
|
11
|
+
* import { createGraphQLHandler } from '@flightdev/graphql';
|
|
12
|
+
* import { yogaAdapter } from '@flightdev/graphql/yoga';
|
|
13
|
+
*
|
|
14
|
+
* const handler = createGraphQLHandler({
|
|
15
|
+
* adapter: yogaAdapter(),
|
|
16
|
+
* schema,
|
|
17
|
+
* });
|
|
18
|
+
* ```
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Options specific to the Yoga adapter
|
|
23
|
+
*/
|
|
24
|
+
interface YogaAdapterOptions {
|
|
25
|
+
/** Enable/disable GraphiQL interface (default: true in development) */
|
|
26
|
+
graphiql?: boolean | {
|
|
27
|
+
title?: string;
|
|
28
|
+
defaultQuery?: string;
|
|
29
|
+
};
|
|
30
|
+
/** CORS configuration (passed directly to Yoga) */
|
|
31
|
+
cors?: boolean | Record<string, unknown>;
|
|
32
|
+
/** Enable/disable logging */
|
|
33
|
+
logging?: boolean;
|
|
34
|
+
/** Mask errors in production */
|
|
35
|
+
maskedErrors?: boolean;
|
|
36
|
+
/** Custom plugins */
|
|
37
|
+
plugins?: YogaServerOptions<Record<string, unknown>, Record<string, unknown>>['plugins'];
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Create a GraphQL Yoga adapter
|
|
41
|
+
*
|
|
42
|
+
* Yoga is the recommended GraphQL server for Flight:
|
|
43
|
+
* - Modern, lightweight, full fetch API support
|
|
44
|
+
* - Built-in GraphiQL, CORS, file uploads
|
|
45
|
+
* - Excellent TypeScript support
|
|
46
|
+
*
|
|
47
|
+
* @example
|
|
48
|
+
* ```typescript
|
|
49
|
+
* // Basic usage
|
|
50
|
+
* yogaAdapter()
|
|
51
|
+
*
|
|
52
|
+
* // With options
|
|
53
|
+
* yogaAdapter({
|
|
54
|
+
* graphiql: { title: 'My API' },
|
|
55
|
+
* cors: { origin: 'https://myapp.com' },
|
|
56
|
+
* })
|
|
57
|
+
*
|
|
58
|
+
* // Disable GraphiQL in production
|
|
59
|
+
* yogaAdapter({
|
|
60
|
+
* graphiql: process.env.NODE_ENV !== 'production',
|
|
61
|
+
* })
|
|
62
|
+
* ```
|
|
63
|
+
*/
|
|
64
|
+
declare function yogaAdapter(options?: YogaAdapterOptions): GraphQLAdapter;
|
|
65
|
+
|
|
66
|
+
export { type YogaAdapterOptions, yogaAdapter };
|
package/dist/yoga.js
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { createYoga } from 'graphql-yoga';
|
|
2
|
+
export { createSchema } from 'graphql-yoga';
|
|
3
|
+
|
|
4
|
+
// src/yoga.ts
|
|
5
|
+
function yogaAdapter(options = {}) {
|
|
6
|
+
const {
|
|
7
|
+
graphiql = true,
|
|
8
|
+
cors,
|
|
9
|
+
logging = false,
|
|
10
|
+
maskedErrors = true,
|
|
11
|
+
plugins = []
|
|
12
|
+
} = options;
|
|
13
|
+
return {
|
|
14
|
+
name: "graphql-yoga",
|
|
15
|
+
createHandler(config) {
|
|
16
|
+
const yoga = createYoga({
|
|
17
|
+
schema: config.schema,
|
|
18
|
+
// Context factory
|
|
19
|
+
context: config.context ? async ({ request }) => {
|
|
20
|
+
const ctx = await config.context(request);
|
|
21
|
+
return ctx;
|
|
22
|
+
} : void 0,
|
|
23
|
+
// GraphiQL configuration
|
|
24
|
+
graphiql: graphiql === true ? { title: "Flight GraphQL" } : graphiql === false ? false : graphiql,
|
|
25
|
+
// CORS - use simple default
|
|
26
|
+
cors: cors ?? true,
|
|
27
|
+
// Logging
|
|
28
|
+
logging,
|
|
29
|
+
// Error masking
|
|
30
|
+
maskedErrors,
|
|
31
|
+
// Plugins
|
|
32
|
+
plugins
|
|
33
|
+
});
|
|
34
|
+
return yoga.fetch.bind(yoga);
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export { yogaAdapter };
|
package/package.json
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@flightdev/graphql",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "GraphQL adapter for Flight Framework - optional, non-imposing",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"exports": {
|
|
7
|
+
".": {
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
9
|
+
"import": "./dist/index.js"
|
|
10
|
+
},
|
|
11
|
+
"./yoga": {
|
|
12
|
+
"types": "./dist/yoga.d.ts",
|
|
13
|
+
"import": "./dist/yoga.js"
|
|
14
|
+
}
|
|
15
|
+
},
|
|
16
|
+
"files": [
|
|
17
|
+
"dist"
|
|
18
|
+
],
|
|
19
|
+
"dependencies": {},
|
|
20
|
+
"peerDependencies": {
|
|
21
|
+
"graphql": "^16.0.0",
|
|
22
|
+
"graphql-yoga": "^5.0.0"
|
|
23
|
+
},
|
|
24
|
+
"peerDependenciesMeta": {
|
|
25
|
+
"graphql-yoga": {
|
|
26
|
+
"optional": true
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
"devDependencies": {
|
|
30
|
+
"graphql": "^16.9.0",
|
|
31
|
+
"graphql-yoga": "^5.10.0",
|
|
32
|
+
"tsup": "^8.0.0",
|
|
33
|
+
"typescript": "^5.7.0",
|
|
34
|
+
"vitest": "^3.0.0"
|
|
35
|
+
},
|
|
36
|
+
"keywords": [
|
|
37
|
+
"flight",
|
|
38
|
+
"graphql",
|
|
39
|
+
"yoga",
|
|
40
|
+
"adapter"
|
|
41
|
+
],
|
|
42
|
+
"license": "MIT",
|
|
43
|
+
"scripts": {
|
|
44
|
+
"build": "tsup",
|
|
45
|
+
"dev": "tsup --watch",
|
|
46
|
+
"test": "vitest",
|
|
47
|
+
"typecheck": "tsc --noEmit"
|
|
48
|
+
}
|
|
49
|
+
}
|