Hello, and thank you in advance for reading this!
I’m making a mock, rudimentary Allrecipes-like website using a REST API. My server and client both use Apollo GraphQL and TypeScript. My client uses React.
The GitHub repository for my Apollo GraphQL server is here.
My server is using Apollo GraphQL, TypeScript, and a GraphQL schema specified in a .graphql
file. My server basically only fetches data from the REST API and processes it, but this is intentional: I wanted to start with something simple before doing something more complicated with mutations and/or subscriptions.
Issue:
The Lambda Function cannot find the file that contains my GraphQL schema; Error during invocation: Error: ENOENT: no such file or directory, open '/graphql/schema.graphql'
.
My question is: why is this error happening, and how can I address this while keeping my GraphQL schema in its own .graphql
file? Is there an easier way to deploy my server while maintaining this?
This is a personal project and the local server works fine, so this is not an urgent problem – if I really need to demo my project, I can just use ngrok, but I would love to have the website hosted in all its glory on Netlify!
I also noticed that people who had similar problems were using JavaScript, so I hope the solution to my problem may prove useful to anyone who is using TypeScript and is in a similar position.
Issues that Looked Similar to Mine
I’m guessing the solutions to these issues did not work for me because I have been using netlify-lambda
to build my function in TypeScript into a JavaScript file that I then deploy. I am guessing that somewhere in this process, the path to my schema file becomes broken. Naively placing my GraphQL schema file with its folder next to the JavaScript file does not work, so it also looks like the final deployment step may just be flat out ignoring that file.
Background Information:
I am working on deploying an Apollo GraphQL server to Netlify using apollo-server-lambda
. This is my first major project using Apollo GraphQL, so I’m deploying my server and client separately because that is easier for me to handle right now.
My server is written in TypeScript so that my server is fully typed, and I have my GraphQL schema in its own file at <projectRoot>/graphql/schema.graphql
as the single source of truth for the shape of the data, as opposed to having it all in a gql
-tagged template in a single graphql.js
file or several such files.
To deploy my server to Netlify, I followed these two tutorials:
^ This one showed how I can set up the code for the Lambda Function without affecting my local server.
^ This one showed how I can use Babel to convert my TypeScript code into JavaScript, but after some further research it appears as though this step is not necessary? I can just run netlify-lambda serve lambda/delish-api
to serve my TypeScript code directly, for instance - although this does not solve my issue.
The deployment pipeline for my server:
- Copy the local server code into
lambda/delish-api/bundle
. - Copy the GraphQL schema into
lambda/delish-api/graphql
. - Run
netlify-lambda build lambda/delish-api
, usinglambda/delish-api/delish-api.ts
as the entry-point for the Lambda Function.netlify-lambda
builds the function tofunctions/delish-api.js
. - The GitHub repository is connected to Netlify, so all I need to do is force a deploy on the website or via the Netlify CLI.
My server works normally when it is running locally: that is, the server starts up, I can load localhost:4000
, and I will get the GraphiQL IDE, and I can query the GraphQL server.
However, when I deploy the Lambda Function (either locally or to Netlify) and go to localhost:9000/.netlify/functions/delish-api
, the Lambda Function reports that it is unable to find the schema file.
I tried the answer linked here from the second post, but adding that to my server.ts
for loading the schema path did not fix my issue. Currently, using that solution, I am loading my schema this way in server.ts
:
const typeDefsPath =
(process.env.LAMBDA_TASK_ROOT)
? path.resolve(process.env.LAMBDA_TASK_ROOT, config.lambda.schemaPath)
: path.resolve(__dirname, config.local.schemaPath)
const typeDefs = readFileSync(typeDefsPath).toString()
where config is, in config.ts
:
export default {
local: {
schemaPath: '../graphql/schema.graphql',
graphqlDir: '../graphql'
},
lambda: {
schemaPath: './graphql/schema.graphql',
graphqlDir: './graphql'
}
}
However, the choice of path does not make a difference - if I just the local
path in both cases, I get the same error.
Thank you for reading this If you have any idea about how I can solve this issue, please let me know. I will be happy to provide any additional information as well.