Tuesday, July 5, 2022

How to enable CORS options in Apollo-Server-Micro?

 According the Apollo Server documentation, the CORS option is not available in server configuration.  

"Note that apollo-server-micro does not have a built-in way of setting CORS headers."

when  we create a apollo server, we can't set the cors options in the configuration object.

import {ApolloServer} from 'apollo-server-micro';
import 'reflect-metadata';
import { buildSchema } from 'type-graphql';
import { PetsResolver } from '../../src/schema/pet.resolver';

const schema = await buildSchema({
  resolvers: [PetsResolver],
});


const server = new ApolloServer({
    schema,
    csrfPrevention: true,  // see below for more about this
    cache: "bounded",
});

As a result, we should encounter the following CORS policy issue 

Access to fetch at 'http://localhost:3000/api/graphql' from origin 'https://studio.apollographql.com' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.

Since we can't add the cors option with the configruation object, we have to manually add those cors options in the handler function

export default async function handler(req:any, res:any){
    res.setHeader("Access-Control-Allow-Credentials", "true");
    res.setHeader(
        "Access-Control-Allow-Origin",
        "https://studio.apollographql.com"
    );
    res.setHeader(
        "Access-Control-Allow-Headers",
        "Origin, X-Requested-With, Content-Type, Accept,
        Access-Control-Allow-Methods, Access-Control-Allow-Origin,
        Access-Control-Allow-Credentials, Access-Control-Allow-Headers"
    );
    res.setHeader(
        "Access-Control-Allow-Methods",
        "POST, GET, PUT, PATCH, DELETE, OPTIONS, HEAD"
    );
    if (req.method === "OPTIONS") {
        res.end();
        return false;
    }

    await startServer;
    await server.createHandler({path:"/api/graphql"})(req, res);
}


Now the cross site access violation should be resolved and we can manipulate the query and mutation in the apollo-studio.


Monday, July 4, 2022

How to fix " ReferenceError: document is not defined" in Jest?

When I setup a test again the AppShell in Micro-Frontend Application Development, then I added the test command to the scripts section in the package.json 

   "test": "jest"

now the scripts section should be shown as below.

 "scripts": {
    "dev": "tsc --watch --outDir dist",
    "build": "tsc --outDir dist",
    "lint": "eslint *.ts*",
    "storybook": "start-storybook",
    "test": "jest"
  },


However when i run the test with pnpm test, I encoutered the error in the following image.







"AppShell › renders

    The error below may be caused by using the wrong test environment, see https://jestjs.io/docs/configuration#testenvironment-string.

    Consider using the "jsdom" test environment."


based on the suggestion, i added the environment tag jsdom to the test command, then the test run is succeed.

"scripts": {
    "dev": "tsc --watch --outDir dist",
    "build": "tsc --outDir dist",
    "lint": "eslint *.ts*",
    "storybook": "start-storybook",
    "test": "jest --env=jsdom"
  },

The successful test run is shown below.





How to access environment variable from Fastify server?

 We can easy access the environment variable from the express server with help from dotenv library. we can just need to add this following line the Server.ts or Index.ts file, then we can access the environment variable.

require('dotenv').config();
 app.use(
    cors({
      origin: __prod__
        ? process.env.CORS_ORIGIN_PROD
        : process.env.CORS_ORIGIN_DEV,
      credentials: true
    })
  )

In the server, we can't not simply assign the JWT_SECRET that stored in the environment setting as we usually did in the express server. In the fastify server, we should create a Constant.ts file to store the code above, the we import the Constant.ts into Server.ts file.

require('dotenv').config();

export const DB_CONNECTION_STRING =
  process.env.DB_CONNECTION_STRING ||
  "mongodb://localhost:27017/password-manager";

export const CORS_ORIGIN = process.env.CORS_ORIGIN || "http://localhost:3000";

export const COOKIE_DOMAIN = process.env.COOKIE_DOMAIN || "localhost";

export const JWT_SECRET= process.env.JWT_SECRET || "jwt-secret-key";

Server.ts 

import { JWT_SECRET } from "../constant";
 app.register(fastifyJwt, {
    secret: JWT_SECRET,
    cookie: {
        cookieName: "token",
        signed: false,
    },
    });