type-graphql icon indicating copy to clipboard operation
type-graphql copied to clipboard

More examples

Open MichalLytek opened this issue 6 years ago • 16 comments

  • [x] integration with apollo-engine (apollo-cache-control)
  • [x] usage with mongoose (typegoose)
  • [x] usage on client side (Apollo client state)
  • [x] using class mixins
  • [x] GraphQL Modules
  • [ ] Join Monster
  • [ ] graphql-shield integration
  • [ ] using relations betweens types (user -> recipes -> comments)
  • [ ] testing examples (unit and e2e)
  • [ ] AWS lambda (apollo-server-lambda)
  • [ ] sample fullstack project with React and Apollo

MichalLytek avatar Mar 29 '18 15:03 MichalLytek

Please add some examples with apollo-server package. especially apollo-server-express and apollo-server-lambda

sandangel avatar May 23 '18 00:05 sandangel

Usage of apollo-server-express is the same as in its repository readme:

import express from 'express';
import bodyParser from 'body-parser';
import { graphqlExpress, graphiqlExpress } from 'apollo-server-express';
import { buildSchema } from "type-graphql";

async function bootstrap() {
  // the only different part
  const myGraphQLSchema = await buildSchema({
    resolvers: [__dirname + "/**/*.resolver.ts"],
  });
  const PORT = 3000;

  const app = express();

  // bodyParser is needed just for POST.
  app.use('/graphql', bodyParser.json(), graphqlExpress({ schema: myGraphQLSchema }));
  app.get('/graphiql', graphiqlExpress({ endpointURL: '/graphql' })); // if you want GraphiQL enabled

  app.listen(PORT);
}

bootstrap();

apollo-server-lambda usage looks the same as the only demand is to provide schema myGraphQLSchema = require('./schema'); so you might need to use buildSchemaSync function. However it's more complicated so I will try create an AWS free tier and try the lambda 😉

MichalLytek avatar May 23 '18 07:05 MichalLytek

@19majkel94 thank you it works. This is just brilliant. I actually have found a way to integrate with injection-js as well. Hope this will be released soon. Actually you don't need to create an aws account. You can try it with serverless framework and serverless-offline plugin to emulate lambda environment at your local machine.

sandangel avatar May 23 '18 13:05 sandangel

@sandangel how did you get this working with aws lambda? I'm having some issues as lined out in #96

darbio avatar Jun 05 '18 06:06 darbio

import 'reflect-metadata';

import { graphiqlExpress, graphqlExpress } from 'apollo-server-express';
import * as serverless from 'aws-serverless-express';
import bodyParser from 'body-parser';
import cors from 'cors';
import express from 'express';
import { Server } from 'http';
import { buildSchemaSync, useContainer } from 'type-graphql';
import { Container } from 'typedi';

import { AuthResolver, MobileDataResolver, MobileKitResolver } from './resolvers';
import { authChecker } from './utils/auth-checker';

/**
 * Must be called before build schema or Resolver won't inject the Service
 */
useContainer(Container);

/**
 * Lambda gonna build schema for each request lead to duplicate GraphQL Declaration
 * so we need to cache the built schema.
 * (this is currently the default cache for type-graphql too)
 * @type {GraphQLSchema}
 */
(<any>global).schema =
  (<any>global).schema ||
  buildSchemaSync({
    resolvers: [AuthResolver, MobileKitResolver, MobileDataResolver],
    authChecker
  });

export const app = express();

export const schema = (<any>global).schema;

export let cachedServer: Server;

export function bootstrapServer() {
  app.use('/graphql', cors(), bodyParser.json(), (req, res, next) => {
    const token = req.headers.authorization;
    graphqlExpress({ schema, context: { token } })(req, res, next);
  });
  app.get('/', graphiqlExpress({ endpointURL: '/graphql' }));

  return serverless.createServer(app);
}

export const graphqlHandler = (event, context) => {
  if (cachedServer == null) {
    console.log('Bootstrapping server...');
    const server = bootstrapServer();
    cachedServer = server;
    return serverless.proxy(server, event, context);
  } else {
    console.log('Using cached server...');
    return serverless.proxy(cachedServer, event, context);
  }
};

sandangel avatar Jun 05 '18 06:06 sandangel

@darbio The problem is that the metadata is attached to global scope to make multi-packages work but AWS lambda use the same node.js process for each request, so consecutive schema builds effect in duplicated types&resolvers definition.

Storing built schema in global fix that + save time that would be used to build the schema for each request.

MichalLytek avatar Jun 05 '18 07:06 MichalLytek

OK. I saw that in the code above, however I get the following error when I try and use the global scoped metadata. I've confirmed that I am only including type-grahql and not any other graphql packages.

Error: Cannot use GraphQLSchema "[object Object]" from another module or realm.

Ensure that there is only one instance of "graphql" in the node_modules
directory. If different versions of "graphql" are the dependencies of other
relied on modules, use "resolutions" to ensure only one version is installed.

https://yarnpkg.com/en/docs/selective-version-resolutions

Duplicate "graphql" modules cannot be used at the same time since different
versions may have different capabilities and behavior. The data from one
version used in the function from another could produce confusing and
spurious results.
    at instanceOf (/Users/jamesdarbyshire/Repositories/darb.io/cad/cad-api/.webpack/service/src/index.js:28689:13)
    at isSchema (/Users/jamesdarbyshire/Repositories/darb.io/cad/cad-api/.webpack/service/src/index.js:35013:35)
    at validateSchema (/Users/jamesdarbyshire/Repositories/darb.io/cad/cad-api/.webpack/service/src/index.js:35287:25)
    at assertValidSchema (/Users/jamesdarbyshire/Repositories/darb.io/cad/cad-api/.webpack/service/src/index.js:35312:16)
    at Object.validate (/Users/jamesdarbyshire/Repositories/darb.io/cad/cad-api/.webpack/service/src/index.js:43344:35)
    at doRunQuery (/Users/jamesdarbyshire/Repositories/darb.io/cad/cad-api/.webpack/service/src/index.js:892:38)
    at /Users/jamesdarbyshire/Repositories/darb.io/cad/cad-api/.webpack/service/src/index.js:803:56
    at <anonymous>
    at process._tickDomainCallback (internal/process/next_tick.js:228:7)

darbio avatar Jun 05 '18 07:06 darbio

Is there any code samples for e2e tests?

codingmaven avatar Aug 27 '18 03:08 codingmaven

@codingmaven A lot of in tests folder 😄

const query = `{
  myQuery {
    myField
  }
}`;

const { data } = await graphql(schema, query);

expect(data!.myQuery.myField).toEqual("myFieldValue");

MichalLytek avatar Aug 27 '18 07:08 MichalLytek

@19majkel94 do you have any testing examples with typeorm?

RodolfoSilva avatar Jan 08 '19 11:01 RodolfoSilva

@RodolfoSilva Just use the dependency injection (TypeDI) and data mapper patter (repository) as in the typeorm-typegraphql examples here on repo. Then you can easily mock the object passed to the constructor in unit test to stub the DB access.

MichalLytek avatar Jan 09 '19 20:01 MichalLytek

Hi there, would like to add +1 request to AWS Lambda example because it has been very annoying to set up this to work there. I have this repository (https://github.com/ramonpm/typescript-serverless-graphql) running and working fine with serverless offline. However, once I deploy it to AWS lambda, I get this error

Unable to import module 'handler': Error
    at Function.Module._resolveFilename (module.js:547:15)
    at Function.Module._load (module.js:474:25)
    at Module.require (module.js:596:17)
    at require (internal/module.js:11:18)
    at Object.source-map-support (/var/task/handler.js:29922:18)
    at __webpack_require__ (/var/task/handler.js:20:30)
    at Object../source-map-install.js (/var/task/handler.js:29722:1)
    at __webpack_require__ (/var/task/handler.js:20:30)
    at Object.0 (/var/task/handler.js:29733:1)
    at __webpack_require__ (/var/task/handler.js:20:30)

Which is probably due to externals: [nodeExternals()], in my webpack.config.js but if I don't use that it fails badly with Error: Cannot use GraphQLSchema "[object GraphQLSchema]" from another module or realm Thought about creating a new issue, but I noticed they have being closed pointing to this issue...

ramonpm avatar Jun 29 '19 16:06 ramonpm

@ramonpm here is a working version that I setup https://github.com/causecode/type-graphql-typegoose-serverless

And another set of examples at https://github.com/kirill578/type-graphql-serverless-example

visheshd avatar Jul 02 '19 01:07 visheshd

Thank you @visheshd It turned out that for some reason I don't really care I had to use --useSeparateProcesses to run it locally without the conflicts. Should I care :sweat_smile: though ?

ramonpm avatar Jul 05 '19 13:07 ramonpm

Apollo server lambda is an example I would really appreciate seeing today.

omar-dulaimi avatar Mar 15 '21 20:03 omar-dulaimi

Can we add Azure Functions to that list @MichalLytek? I would be able to provide a working example the following days.

itpropro avatar May 15 '22 18:05 itpropro