0.0.7 • Published 2 years ago

zod-api-validator v0.0.7

Weekly downloads
-
License
ISC
Repository
-
Last release
2 years ago

🤖 Zod API Validator (ZAV)

Zod API Validator enables you to rapidly test API's to ensure the desired output matches a defined schema. To use the package you define a config file that lists all of the endpoint urls that you want to test, along with the zod schema that outlines the desired response schema. The validator can be run from the CLI for local development, or it can be hosted as an independent application which enables support for CI/CD pipelines.

🚧 Roadmap

  • Add support for request body/payload (Currently only supports GET requests)
  • Full TypeScript support
  • Add support for cjs (commonjs)

⚙️ Getting Started

Prerequisites

You must have Zod installed into your app. This is so you can defined Zod schemas in your repo.

$ npm install zod

Setup

  1. Install the package into your app
$ npm install zod-api-validator
  1. Create a new file in your repo called zav.config.js with the following contents:

zav.config.js

import { z } from 'zod';

/**
 * An array of endpoint objects. Each endpoint object should have the following properties:
 * method - The method to use on the request as a string (GET/POST/PUT/PATCH/DELTE). e.g "GET"
 * url - The http/https endpoint to call as a string. e.g "http://localhost:5000/api/test"
 * schema - A Zod schema object. e.g z.object({ name: z.string(), age: z.number() })  
 */
const endpoints = [
    // { method: 'GET', url: 'http://127.0.0.1:5000/api/test', schema: userSchema },
];

const config = {
	configName: 'my-first-config',
    endpoints,
}

export default config;
  1. Create a Zod schema for the endpoint you want to test

UserSchema.zav.js

export const userSchema = z.object({
    name: z.string(),
    email: z.string().min(20, 'Must be more than 20 chars').email('Invalid email'),
    age: z.number().min(18, 'You must be over 18'),
})
  1. Add your endpoint and schema to the config file

zav.config.js

import { z } from 'zod';

import { userSchema } from './UserSchema';

/**
 * An array of endpoint objects. Each endpoint object should have the following properties:
 * method - The method to use on the request as a string (GET/POST/PUT/PATCH/DELTE). e.g "GET"
 * url - The http/https endpoint to call as a string. e.g "http://localhost:5000/api/test"
 * schema - A Zod schema object. e.g z.object({ name: z.string(), age: z.number() })
 */
const endpoints = [
    { method: 'GET', url: 'http://127.0.0.1:5000/api/test', schema: userSchema },
];

const config = {
	configName: 'my-first-config',
    endpoints,
}

export default config;
  1. That's it! You are now setup to run the validator.

Running the Validator

The validator has a few different methods of running. Which method you choose may come down to your use case.

CLI

The first method is via the CLI. This is better suited to those who are developing locally or designing the schemas that they wish to use for the tests. The CLI commands come bundled with the package and do not require any extra setup.

To run from the CLI, run the following command in the root of your project.

$ zav

In your terminal you will see an output in this format

Valid response from API:

***** my-first-config (zav.config.js) *****
GET http://localhost:5000/api/user - VALID

Invalid response from API:

***** my-first-config (zav.config.js) *****
GET http://localhost:5000/api/user - INVALID
name: Expected string, received boolean,    
email: Must be more than 20 chars,
email: Invalid email

Server Application

The validator can also be hosted as an independent application. This is beneficial when you wish to test deployed API's or integrate the validator into a CI/CD pipeline.

You can run the server application with the following command:

$ zav-server

By default the server will be run on port 4000.

The application uses dotenv, so the port can be changed using PORT env var.

Once the server is running you can navigate to http://127.0.0,1:4000. Here you can find a simple GUI that outputs the results of the validator. Each time you refresh the page the validator will run and send a request to all of the endpoints in the configs.

Targeting specific config files

Sometimes you may only want to test a specific config or a couple of specific configs. You can do this via query params. There are 2 supported query params:

ParameterValueExample url
configThe configName value defined in the zav config file you wish to testhttp://127.0.0.1:4000?config=my-first-config
configsA comma separated list of configName valueshttp://127.0.0.1:4000?configs=my-first-config,another-config,my-app

When using these query params, only the endpoints listed in the config files will be tested.

CI/CD Pipeline Integration

The validator can be integrated into your workflow or pipeline to help ensure API endpoints are working as expected.

When the server is running it also exposes the following endpoint: http://127.0.0.1:4000/pipeline

When navigating to this url the configuration files will be loaded and tested in the same way as if you were running from the CLI or GUI. The difference being that it will output the raw response from the console.

The pipeline endpoint also supports the query parameters for targeting specific config files.

Inside the package bundle you will find an example script called pipeline-script.sh. This is the command that can be run as part of your pipeline.

pipeline-script.sh

if [[ $ZavPipelineUrl == "" ]]; then
    echo "'ZavPipelineUrl' environment variable is not set"
    exit 1;
fi
text=$(curl -s "$ZavPipelineUrl")
string="PIPELINE FAILED"
if [[ $text == *"$string"* ]]; then
    echo "$text"
    echo "Zod API Validator finished with errors"
    exit 1;
else
    echo "$text"
    echo "Zod API Validator finished successfully"
    exit 0;
fi

The script checks for an environment variable called ZavPipelineUrl, this should be the full url of the hosted zod-api-validator application. For example, ZavPipelineUrl=https://my-zav-app.com/pipeline

Then inside your CI/CD you can add a step for calling the validator. Below is an example in GitLab.

.gitlab-ci.yml

image: docker:stable

stages:
  - test-api

run-zav:
  stage: test-api
  before_script:
    - apk add --update curl && rm -rf /var/cache/apk/*
  script:
    - |
        if [[ $ZavPipelineUrl == "" ]]; then
            echo "'ZavPipelineUrl' environment variable is not set"
        exit 1;
        fi
        text=$(curl -s "$ZavPipelineUrl")
        string="PIPELINE FAILED"
        if [[ $text == *"$string"* ]]; then
        echo "$text"
        echo "Zod API Validator finished with errors"
        exit 1;
        else
        echo "$text"
        echo "Zod API Validator finished successfully"
        exit 0;
        fi

The script will finish with an exit code 0 if it passes, or an exit code 1 if it fails.

Slack Integration

You can use Slack Webhooks to log all messages from the zod-api-validator to a specific channel. This can be especially useful when trying to keep a full log of each run, and live monitoring. The Slack Webhook will be fired each time the pipeline runs, and each time the validator is run from the GUI.

To setup Slack Webhooks, you simply need to create an environment variable with the webhook URL. The validator will automatically detect the environment variable and attempt to log to Slack when it is found.

ZAV_SLACK_WEBHOOK_URL=XXXX

Scheduled Cron Job

The validator can also be run on a schedule. This can eb especially useful once you have the Slack integration set up, as it will automate the tests and all results can be tracked and logged in Slack. You can set up a scheduled cron by setting the ZAV_CRON environment variable.

ZAV_CRON=1h

The above example will run the validator every hour. The currently supported periods are:

Variable ValuePeriod
1hEvery hour
2hEvery 2 hours
3hEvery 3 hours
4hEvery 4 hours
6hEvery 6 hours
1dEvery day at midnight

The cron will only be initialised if this variable is set. If the variable is not set when the server runs, then the cron will not be scheduled.

Example Use Case

It is common to see front-end and back-end applications in different repositories and this often leads to API schemas being defined twice. The front-end will be making calls to the API endpoints and expect an exact schema, if these become misaligned it can cause the front-end application to break.

When working in larger teams, it is much harder to keep track of all the changes happening to the back-end API schema and ensure that all of these changes have been reflected or considered on the front-end.

The validator can help ensure that there are no unexpected changes to existing endpoints, or ensure that new endpoints match the exact schema implemented on the front-end.

The validator can be implemented at various stages of a project. In either case the first step is to create a new repo with zod and zod-api-validator installed.

For an existing project, the front-end will have defined a full set of DTO's that it uses to interact with the API. In this case the first step would be to create zod schemas for each of the front-end DTO's used in the front-end application. Then inside the zav.config files we can list all of the endpoints and the schemas related to them.

The next step is host the app.

Once hosted we can navigate to the hosted url and we should be able to see all of the endpoints are responding as valid. Then we can integrate the pipeline script with the back-end repository. The pipeline script can run on each pull request commit. This now means that if any endpoints change and they have not been updated in the validator schemas, the pipeline will fail. This prevents code from being merged/deployed that has not been updated yet.

0.0.7

2 years ago

0.0.6

2 years ago

0.0.5

2 years ago

0.0.4

2 years ago

0.0.3

2 years ago

0.0.2

2 years ago

0.0.1

2 years ago