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",
  ]
}
Krisna
  • 2,854
  • 2
  • 24
  • 66

1 Answers1

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

Rovelcio Junior
  • 661
  • 3
  • 5
  • Still getting the same error :( – Krisna Dec 16 '21 at 18:39
  • It seems there are some additional build steps when you use Typescript with Serverless. You can look at and try [this question](https://stackoverflow.com/questions/54933879/aws-lambda-fs-readfile-issue) or [this question](https://stackoverflow.com/questions/59556930/importschema-graphql-error-enoent-no-such-file-or-directory-open-schema-gr)'s answers. The latest one has a very similar case to yours. – Rovelcio Junior Dec 17 '21 at 00:15
  • 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. – Krisna Dec 17 '21 at 07:59
  • Well, would've helped to know that you are using webpack. I'm glad you figured out the solution! – Rovelcio Junior Dec 18 '21 at 00:13