Skip to content

Commit b05b183

Browse files
committed
feat: Merge plugin branch 'with/graphql-server-apollo'
2 parents 6e64548 + df0de06 commit b05b183

25 files changed

+3499
-3109
lines changed

.vscode/settings.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"typescript.tsdk": "node_modules/typescript/lib",
3+
"typescript.enablePromptUseWorkspaceTsdk": true
4+
}

apps/expo/tailwind.config.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
const { universalTheme } = require('@app/core/tailwind.theme')
1+
const { universalTheme } = require('@app/core/tailwind.theme.cjs')
22

33
/** @type {import('tailwindcss').Config} */
44
module.exports = {

apps/expo/tsconfig.json

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
{
22
"extends": "@app/core/tsconfig",
3-
"include": ["**/*.ts", "**/*.tsx"],
3+
"include": [
4+
"**/*.ts",
5+
"**/*.tsx",
6+
"../../features/app-core/graphql-env.d.ts"
7+
],
48
"exclude": ["node_modules"]
59
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import type { NextRequest } from 'next/server'
2+
import { createGraphQLServerHandler } from '@app/core/graphql/graphqlServer'
3+
4+
/* --- Handler --------------------------------------------------------------------------------- */
5+
6+
const handler = createGraphQLServerHandler()
7+
8+
/* --- /api/graphql ---------------------------------------------------------------------------- */
9+
10+
export const GET = (req: NextRequest) => handler(req)
11+
12+
export const POST = (req: NextRequest) => handler(req)

apps/next/tailwind.config.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
const { universalTheme } = require('@app/core/tailwind.theme')
1+
const { universalTheme } = require('@app/core/tailwind.theme.cjs')
22

33
/** @type {import('tailwindcss').Config} */
44
module.exports = {

apps/next/tsconfig.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@
33
"include": [
44
"**/*.ts",
55
"**/*.tsx",
6-
".next/types/**/*.ts"
6+
".next/types/**/*.ts",
7+
"../../features/app-core/graphql-env.d.ts"
78
],
89
"exclude": [
910
"node_modules"

features/app-core/graphql-env.d.ts

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
/* eslint-disable */
2+
/* prettier-ignore */
3+
4+
/** An IntrospectionQuery representation of your schema.
5+
*
6+
* @remarks
7+
* This is an introspection of your schema saved as a file by GraphQLSP.
8+
* It will automatically be used by `gql.tada` to infer the types of your GraphQL documents.
9+
* If you need to reuse this data or update your `scalars`, update `tadaOutputLocation` to
10+
* instead save to a .ts instead of a .d.ts file.
11+
*/
12+
export type introspection = {
13+
name: never;
14+
query: 'Query';
15+
mutation: never;
16+
subscription: never;
17+
types: {
18+
'Boolean': unknown;
19+
'Float': unknown;
20+
'HealthCheckArgs': { kind: 'INPUT_OBJECT'; name: 'HealthCheckArgs'; inputFields: [{ name: 'echo'; type: { kind: 'SCALAR'; name: 'String'; ofType: null; }; defaultValue: null }]; };
21+
'HealthCheckData': { kind: 'OBJECT'; name: 'HealthCheckData'; fields: { 'alive': { name: 'alive'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'Boolean'; ofType: null; }; } }; 'aliveSince': { name: 'aliveSince'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'String'; ofType: null; }; } }; 'aliveTime': { name: 'aliveTime'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'Float'; ofType: null; }; } }; 'apiURL': { name: 'apiURL'; type: { kind: 'SCALAR'; name: 'String'; ofType: null; } }; 'backendURL': { name: 'backendURL'; type: { kind: 'SCALAR'; name: 'String'; ofType: null; } }; 'baseURL': { name: 'baseURL'; type: { kind: 'SCALAR'; name: 'String'; ofType: null; } }; 'debugPort': { name: 'debugPort'; type: { kind: 'SCALAR'; name: 'Int'; ofType: null; } }; 'echo': { name: 'echo'; type: { kind: 'SCALAR'; name: 'String'; ofType: null; } }; 'graphURL': { name: 'graphURL'; type: { kind: 'SCALAR'; name: 'String'; ofType: null; } }; 'kicking': { name: 'kicking'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'Boolean'; ofType: null; }; } }; 'nodeVersion': { name: 'nodeVersion'; type: { kind: 'SCALAR'; name: 'String'; ofType: null; } }; 'now': { name: 'now'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'String'; ofType: null; }; } }; 'port': { name: 'port'; type: { kind: 'SCALAR'; name: 'Int'; ofType: null; } }; 'requestHost': { name: 'requestHost'; type: { kind: 'SCALAR'; name: 'String'; ofType: null; } }; 'requestProtocol': { name: 'requestProtocol'; type: { kind: 'SCALAR'; name: 'String'; ofType: null; } }; 'requestURL': { name: 'requestURL'; type: { kind: 'SCALAR'; name: 'String'; ofType: null; } }; 'serverTimezone': { name: 'serverTimezone'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'String'; ofType: null; }; } }; 'status': { name: 'status'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'SCALAR'; name: 'String'; ofType: null; }; } }; 'systemArch': { name: 'systemArch'; type: { kind: 'SCALAR'; name: 'String'; ofType: null; } }; 'systemFreeMemory': { name: 'systemFreeMemory'; type: { kind: 'SCALAR'; name: 'Float'; ofType: null; } }; 'systemLoadAverage': { name: 'systemLoadAverage'; type: { kind: 'LIST'; name: never; ofType: { kind: 'SCALAR'; name: 'Float'; ofType: null; }; } }; 'systemPlatform': { name: 'systemPlatform'; type: { kind: 'SCALAR'; name: 'String'; ofType: null; } }; 'systemRelease': { name: 'systemRelease'; type: { kind: 'SCALAR'; name: 'String'; ofType: null; } }; 'systemTotalMemory': { name: 'systemTotalMemory'; type: { kind: 'SCALAR'; name: 'Float'; ofType: null; } }; 'v8Version': { name: 'v8Version'; type: { kind: 'SCALAR'; name: 'String'; ofType: null; } }; }; };
22+
'Int': unknown;
23+
'Query': { kind: 'OBJECT'; name: 'Query'; fields: { 'healthCheck': { name: 'healthCheck'; type: { kind: 'NON_NULL'; name: never; ofType: { kind: 'OBJECT'; name: 'HealthCheckData'; ofType: null; }; } }; }; };
24+
'String': unknown;
25+
};
26+
};
27+
28+
import * as gqlTada from 'gql.tada';
29+
30+
declare module 'gql.tada' {
31+
interface setupSchema {
32+
introspection: introspection
33+
}
34+
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
#!/usr/bin/env node --experimental-specifier-resolution=node
2+
import path from 'path'
3+
import fs from 'fs'
4+
import { fileURLToPath } from 'node:url'
5+
import { loadFilesSync } from '@graphql-tools/load-files'
6+
import { mergeTypeDefs } from '@graphql-tools/merge'
7+
import { print } from 'graphql'
8+
9+
/* --- Constants ------------------------------------------------------------------------------- */
10+
11+
const currentDir = path.dirname(fileURLToPath(import.meta.url))
12+
const schemaPath = path.resolve(currentDir, 'schema.graphql')
13+
const typeDefsPath = path.resolve(currentDir, 'typeDefs.ts')
14+
15+
/** --- createSchemaDefinitions() -------------------------------------------------------------- */
16+
/** -i- Combine all custom and other (e.g. generated) graphql schema definitions */
17+
export const createSchemaDefinitions = () => {
18+
const rootDir = path.resolve(currentDir, '../../..')
19+
const schemaPathPattern = `${rootDir}/(features|packages)/**/!(schema).graphql`
20+
const customGraphQLDefinitions = loadFilesSync(schemaPathPattern)
21+
return mergeTypeDefs([
22+
...customGraphQLDefinitions,
23+
/* other typedefs? */
24+
])
25+
}
26+
27+
/* --- Script ---------------------------------------------------------------------------------- */
28+
29+
const buildSchemaDefinitions = async () => {
30+
const schemaDefinitions = createSchemaDefinitions()
31+
const typeDefsString = print(schemaDefinitions)
32+
fs.writeFileSync(schemaPath, typeDefsString)
33+
fs.writeFileSync(typeDefsPath, `export const typeDefs = \`${typeDefsString}\``)
34+
}
35+
36+
buildSchemaDefinitions()
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import { print } from 'graphql/language/printer'
2+
import type { TadaDocumentNode, ResultOf } from 'gql.tada'
3+
import type { QueryConfig } from './graphqlQuery.types'
4+
import { appConfig } from '../appConfig'
5+
6+
/** --- graphqlQuery --------------------------------------------------------------------------- */
7+
/** -i- Isomorphic graphql request, uses the graphql endpoint in browser & mobile, but the executable schema serverside */
8+
export const graphqlQuery = async <T extends TadaDocumentNode, R = ResultOf<T>>(query: T, config?: QueryConfig<T>) => {
9+
// Config
10+
const { variables, headers, graphqlEndpoint } = config || {}
11+
12+
// Vars
13+
const queryString = print(query)
14+
15+
// -- Native: Execute query with fetch --
16+
17+
try {
18+
const { graphURL } = appConfig
19+
const fetchURL = graphqlEndpoint || graphURL
20+
const res = await fetch(fetchURL, {
21+
method: 'POST',
22+
headers: {
23+
'Content-Type': 'application/json',
24+
...headers,
25+
},
26+
body: JSON.stringify({ query: queryString, variables }),
27+
})
28+
const { data, errors } = await res.json()
29+
if (errors) throw new Error(errors[0].message)
30+
return data as R
31+
} catch (error) {
32+
throw new Error(error)
33+
}
34+
}
35+
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import type { TadaDocumentNode, VariablesOf } from 'gql.tada'
2+
3+
export type QueryConfig<T extends TadaDocumentNode> = {
4+
variables?: VariablesOf<T>
5+
headers?: Record<string, string>
6+
graphqlEndpoint?: string
7+
}

0 commit comments

Comments
 (0)