Apollo-server: [Typescript] Export types DataSource and DataSources from ApolloServer

Created on 11 Jan 2019  路  7Comments  路  Source: apollographql/apollo-server

With the next package.json:

"dependencies": {
   "apollo-server-express": "^2.4.0",
    ...
}

Currently to import DataSource:

import { DataSource } from "apollo-datasource";
...

Desired behavior to import DataSource:

import { DataSource } from "apollo-server-express";
...

Currently to import DataSources:

import { DataSources } from "apollo-server-core/dist/graphqlOptions";

export interface ResolverProviders extends DataSources<ResolverContext> {
    mongo: ProviderMongo;
}
...

Desired behavior to import DataSources:

import { DataSources } from "apollo-server-express";

export interface ResolverProviders extends DataSources<ResolverContext> {
    mongo: ProviderMongo;
}
...
馃К data-sources 馃К typings

Most helpful comment

@lookfirst , may i ask on how did use dataSources into type-graphql resolver?

All 7 comments

@localnet, thanks for submitting an issue. Unfortunately, we're not interested in re-exporting the types from apollo-datasource from apollo-server. As it is now, we're content with the separation of concerns here.

1606 ... need exports for DataSources (note the s) for use with apolloserver via apollo-server-cloud-functions

Ok, figured it out.

The ugly bit here is having to pull graphqlOptions from apollo-server-core instead of just nicely getting it from apollo-server-cloud-functions. It adds another dependency on apollo-server-core in my package.json that I don't really need.

import {Request, Response} from "express";
import {IncomingHttpHeaders} from "http";

import * as admin from 'firebase-admin'
import * as serviceAccount from '../serviceAccountKey.json';

import {ApolloServer} from "apollo-server-cloud-functions";
import {DataSources} from "apollo-server-core/dist/graphqlOptions";
import {DataSource} from "apollo-datasource";

const firebaseApp = admin.initializeApp({
    credential: admin.credential.cert(serviceAccount as admin.ServiceAccount),
    databaseURL: "url"
});

export interface Context {
    headers: IncomingHttpHeaders,
    req: Request,
    res: Response,
    dataSources: IDataSources,
}

class FirebaseDataSource extends DataSource {
    constructor(private app: admin.app.App) {
        super();
    }

    get adminApp() {
        return this.app;
    }

    firestore() {
        return this.adminApp.firestore();
    }

    database() {
        return this.adminApp.database();
    }

    auth() {
        return this.adminApp.auth();
    }
}

interface IDataSources {
    firebase: FirebaseDataSource;
}

const dataSources: DataSources<IDataSources> = {
    firebase: new FirebaseDataSource(firebaseApp),
};

const apolloServer = new ApolloServer({
    typeDefs,
    resolvers,
    dataSources: () => dataSources,
    context: ({req, res}) => ({
        headers: req.headers,
        req,
        res,
    } as Context),
});

Then in your Query... I'm using https://graphql-code-generator.com for my code generation from the schema. The whole thing is nicely typed now...

    Query: {
        Foo: (_: ResolversParentTypes["Query"], args: QueryFooArgs, context: Context, info: GraphQLResolveInfo) => {
                         Foo foo = context.dataSources.firestore() ... 
            return {
                id: foo.id,
            } as Foo;
        },
        }

Now that I think about it, FirebaseDataSource could call admin.initializeApp inside its initialize() function in order to compartmentalize things further.

Hey @lookfirst, thanks for your solution which works great. Have you found a better one since then?

@stephane-ruhlmann Not really other than I'm using type-graphql for the resolvers.

@lookfirst , may i ask on how did use dataSources into type-graphql resolver?

Was this page helpful?
0 / 5 - 0 ratings