Skip to main content
For this example we are using fastify and tsx to run the local server on port 4000. Before running any check, we need to configure the check extension to point to our local server and set the secret key. For this example, we are using the following values:
  • Endpoint: http://localhost:4000/check-schema
  • Secret key: ...

Setting up the project

First, we need to create a new directory for our project and navigate to the directory.
mkdir <project-name>
cd <project-name>
After we are in the project directory, we need to initialize our project using your preferred package manager and install the required dependencies.
npm init -y
npm install --save-dev fastify tsx
And finally, we need to create a new script in the package.json file to run our project.
{
  ...
  "scripts": {
    "dev": "tsx watch server.ts"
  }
  ...
}

Handler implementation

Below you will find the implementation of the handler along with a helper to validate the request signature and type definitions for the payload and reply.
import Fastify, { type FastifyInstance } from 'fastify';

import { SubgraphCheckExtensionPayload, SubgraphCheckExtensionReply } from './types';
import { verifySignature } from './utils';

const YOUR_SECRET = '...';
const server: FastifyInstance = Fastify({ logger: true });

server.post<{
  Body: SubgraphCheckExtensionPayload,
  Reply: SubgraphCheckExtensionReply,
}>(
  '/check-schema',
  {
    config: { rawBody: true }
  },
  async (req, res) => {
    if (!req.body) {
      res.code(400);
      return { errorMessage: 'Bad request' };
    }

    const { body } = req;
    const cosmoSignature = req.headers['x-cosmo-signature-256'];
    if (!verifySignature(body, cosmoSignature, YOUR_SECRET)) {
      res.code(400);
      return { errorMessage: 'Bad request' };
    }

    // We can run checks conditionally
    if (body.namespace.name !== 'default' || body.subgraph?.name !== 'family') {
      // We only want to overwrite the lint issues for the subgraph `family` on the namespace `default`
      res.code(204);
      return;
    }

    return {
      lintIssues: [
        {
          lintRuleType: 'TYPE_SUFFIX',
          severity: 1,
          message: 'Type names should use the prefix `Type`',
          issueLocation: {
            line: 9,
            column: 6,
            endLine: 9,
            endColumn: 11,
          },
        },
      ],
    };
  },
);

const start = async () => {
  try {
    await server.listen({ port: 4000 })

    const address = server.server.address()
    const port = typeof address === 'string' ? address : address?.port
  } catch (err) {
    server.log.error(err)
    process.exit(1)
  }
};

start()