1

I am practicing Graphql and AWS. I used simple serverless framework also create simple Graphql schema. I deployed the schema(seems like this graphql.schema file does not deploy), resolvers to AWS. It successfully create a DynamoDB table and lambda. I can able make POST/GET request via Graphql Playground by using serverless-offline. But the issue is the the api end-point does not work. It's show me internal server error. I was investigating the issue. From cloud watch I found the local schema which I created the Lambda function did find the graphql.schema. This is the error I am getting "ENOENT: no such file or directory, open './src/graphql/schema.graphql'". This is the lambda error Image

This is my lambda function

import { ApolloServer } from 'apollo-server-lambda';
import { ApolloServerPluginLandingPageGraphQLPlayground } from 'apollo-server-core';
import runWarm from '../utils/run-warm';
import fs from 'fs';

const schema = fs.readFileSync('./src/graphql/schema.graphql', 'utf8'); // This is local my schema 
import resolvers from '../resolvers';

const server = new ApolloServer({
  typeDefs: schema,
  resolvers,
  introspection: true,
  plugins: [ApolloServerPluginLandingPageGraphQLPlayground()],
});

export default runWarm(
  server.createHandler({
    expressGetMiddlewareOptions: {
      cors: {
        origin: '*',
        credentials: true,
        allowedHeaders: ['Content-Type', 'Origin', 'Accept'],
        optionsSuccessStatus: 200,
      },
    },
  })
);

This is my serverless YAML file

service: serverless-aws-graphql

package:
  individually: true

provider:
  name: aws
  profile: ${env:profile}
  runtime: nodejs14.x
  stage: ${env:stage}
  region: eu-north-1
  timeout: 30
  apiName: ${self:service.name}-${self:provider.stage}
  environment:
    ITEM_TABLE: ${self:service}-items-${self:provider.stage}
  iamRoleStatements:
    - Effect: Allow
      Action:
        - dynamodb:Query
        - dynamodb:Scan
        - dynamodb:GetItem
        - dynamodb:PutItem
        - dynamodb:UpdateItem
        - dynamodb:DeleteItem
      Resource: 'arn:aws:dynamodb:${opt:region, self:provider.region}:*:table/${self:provider.environment.ITEM_TABLE}'

  apiGateway:
    shouldStartNameWithService: true

custom:
  webpack:
    webpackConfig: ./webpack.config.js
    includeModules: true
    packager: 'npm' # Packager that will be used to package your external modules
  warmup:
    enabled: true
    events:
      - schedule: rate(5 minutes)
    prewarm: true
    concurrency: 1
  prune:
    automatic: true
    number: 5

functions:
  graphql:
    handler: src/handlers/graphql.default
    events:
      - http:
          path: ${env:api_prefix}/graphql
          method: any
          cors: true

resources:
  Resources:
    ItemsTable:
      Type: 'AWS::DynamoDB::Table'
      Properties:
        AttributeDefinitions:
          - AttributeName: PK
            AttributeType: S
          - AttributeName: SK
            AttributeType: S
          - AttributeName: GSI1PK
            AttributeType: S
          - AttributeName: GSI1SK
            AttributeType: S
        KeySchema:
          - AttributeName: PK
            KeyType: HASH
          - AttributeName: SK
            KeyType: RANGE
        ProvisionedThroughput:
          ReadCapacityUnits: 1
          WriteCapacityUnits: 1
        GlobalSecondaryIndexes:
          - IndexName: GSI1
            KeySchema:
              - AttributeName: GSI1PK
                KeyType: HASH
              - AttributeName: GSI1SK
                KeyType: RANGE
            Projection:
              ProjectionType: ALL
            ProvisionedThroughput:
              ReadCapacityUnits: 1
              WriteCapacityUnits: 1
        TableName: ${self:provider.environment.ITEM_TABLE}

plugins:
  - serverless-webpack
  - serverless-offline
  - serverless-plugin-warmup
  - serverless-dotenv-plugin
  - serverless-prune-plugin

This is my webpack.config.js setup

const nodeExternals = require('webpack-node-externals');
const slsw = require('serverless-webpack');

module.exports = {
  entry: slsw.lib.entries,
  target: 'node',
  mode: slsw.lib.webpack.isLocal ? 'development' : 'production',
  externals: [nodeExternals()],
  module: {
    rules: [
      {
        test: /\.tsx?$/,
        use: 'ts-loader',
        exclude: /node_modules/,
      },
    ],
  },
  resolve: {
    extensions: ['.tsx', '.ts', '.js', '.jsx'],
  },
};

This my tsconfig setup

{
  "compilerOptions": {
    "target": "esnext",
    "allowJs": true,
    "skipLibCheck": false,
    "esModuleInterop": true,
    "allowSyntheticDefaultImports": true,
    "strict": true,
    "forceConsistentCasingInFileNames": true,
    "module": "esnext",
    "moduleResolution": "node",
    "resolveJsonModule": true,
    "noEmit": false,
    "jsx": "preserve",
    "noUnusedLocals": true,
    "noUnusedParameters": true
  },
  "include": [
    "src/**/*"
  ],
  "exclude": [
    "node_modules",
  ]
}

1 Answer 1

1

As you observed, the ./src/graphql/schema.graphql isn't being packaged to the final artifact Serverless builds and deploys.

You can add it by specifying the package property to your function:

graphql:
  handler: src/handlers/graphql.default
  events:
    - http:
        path: ${env:api_prefix}/graphql
        method: any
        cors: true
  package:
    include:
      - src/graphql/schema.graphql

Source: https://www.serverless.com/framework/docs/providers/aws/guide/packaging#patterns

Sign up to request clarification or add additional context in comments.

4 Comments

Still getting the same error :(
It seems there are some additional build steps when you use Typescript with Serverless. You can look at and try this question or this question's answers. The latest one has a very similar case to yours.
Thank you! I think I figure it out, but did not find the main reason . It some how does not load schema.graphql file but it accepts schema.ts file . , I think there is something wrong in my webpack and typescript setup. I will attach my webpack and tsconfig setup in the question.
Well, would've helped to know that you are using webpack. I'm glad you figured out the solution!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.