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;
}
...
@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.
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?
Most helpful comment
@lookfirst , may i ask on how did use dataSources into type-graphql resolver?