# @agreed/core

> agreed is a mock server and test client, agreed will be helper for Consumer Driven Contract

Latest version **6.0.0** (published 2024-03-14) · MIT license · 0 weekly downloads

## Install

```sh
npm install @agreed/core
pnpm add @agreed/core
yarn add @agreed/core
bun add @agreed/core
```

## Health

**Score 30/100 (F)** — status: abandoned.

Positive: no vulnerabilities; high maintenance score.

Warnings: low downloads; no types; no esm support.

Negative: abandoned.

## Facts

| | |
|---|---|
| Version | 6.0.0 |
| Published | 2024-03-14 |
| First published | 2019-10-12 |
| Weekly downloads | 0 |
| License | MIT |
| TypeScript types | none |
| Module format | CommonJS |
| Dependencies | 7 |
| Unpacked size | 138.7 KB |
| Known vulnerabilities | 0 |
| Install scripts | no |
| GitHub stars | 215 |
| Author | yosuke-furukawa |
| Maintainers | yosuke-furukawa, maxmellon |
| Keywords | agreed, consumer, driven, contract, mock, test, server |

## Links

- npm: https://www.npmjs.com/package/@agreed/core
- Repository: https://github.com/recruit-tech/agreed
- Homepage: https://github.com/recruit-tech/agreed-core
- Issues: https://github.com/recruit-tech/agreed-core/issues
- npm.io page: https://npm.io/package/@agreed/core

## Dependencies (7)

- [json5](https://npm.io/package/json5.md) ^2.0.0
- [stable](https://npm.io/package/stable.md) ^0.1.8
- [yamljs](https://npm.io/package/yamljs.md) ^0.3.0
- [jsonschema](https://npm.io/package/jsonschema.md) ^1.2.4
- [typescript](https://npm.io/package/typescript.md) ^4.0.0
- [@types/node](https://npm.io/package/@types/node.md) ^18.0.0
- [path-to-regexp](https://npm.io/package/path-to-regexp.md) ^6.0.0

## Alternatives

- [duck](https://npm.io/package/duck.md) — 4.2M weekly downloads
- [ava](https://npm.io/package/ava.md) — 560.2K weekly downloads
- [storybook-addon-module-mock](https://npm.io/package/storybook-addon-module-mock.md) — 71.7K weekly downloads
- [vest](https://npm.io/package/vest.md) — 50.1K weekly downloads
- [@ethereum-waffle/mock-contract](https://npm.io/package/@ethereum-waffle/mock-contract.md) — 40.0K weekly downloads

## Recent versions

- 6.0.0 (latest) — 2024-03-14
- 5.3.2-alpha.0 — 2022-08-25
- 5.3.1 — 2022-08-16
- 5.3.0 — 2022-07-21
- 5.2.1 — 2021-07-06
- 5.2.0 — 2021-01-29
- 5.1.10 — 2020-09-01
- 5.1.9 — 2020-08-07
- 5.1.8 — 2020-08-03
- 5.1.7 — 2020-05-28
- 5.1.6 — 2020-05-27
- 5.1.5 — 2020-04-06
- 5.1.4 — 2020-04-06
- 5.1.3 — 2020-03-30
- 5.1.2 — 2020-03-30
- … 13 more at https://npm.io/package/@agreed/core/versions

## README

agreed-core
====================
[![Build Status](https://travis-ci.org/recruit-tech/agreed-core.svg?branch=master)](https://travis-ci.org/recruit-tech/agreed-core)
[![codecov](https://codecov.io/gh/recruit-tech/agreed-core/branch/master/graph/badge.svg)](https://codecov.io/gh/recruit-tech/agreed-core)

agreed is Consumer Driven Contract tool with JSON mock server.

agreed has 3 features.

1. Create contract file as json(json5/yaml/etc) file
1. mock server for frontend development.
1. test client for backend development

`agreed-core` is a library to create test client and mock server. `agreed-core` provide the following features.

1. json5/yaml require hook, you can write require('foo.json5') / require('bar.yaml') using agreed-core/register.
1. server middleware, agreed-core provides express/pure node http middleware.
1. test client, agreed-core provides response check.

# Install

```
$ npm install agreed-core --dev
```

# Usage

## Usage as Frontend Mock Server

- Create agreed file (this file is used as a contract between frontend and backend)

```javascript
module.exports = [
  {
    request: {
      path: '/user/:id',
      method: 'GET',
      query: {
        q: '{:someQueryStrings}',
        index: '{:index}',
      },
      values: {
        id: 'yosuke',
        someQueryStrings: 'bye',
        index: 2,
      },
    },
    response: {
      headers: {
        'x-csrf-token': 'csrf-token', 
      },
      body: {
        // hello yosuke bye
        message: '{:greeting} {:id} {:someQueryStrings}',
        // http://example.com/baz.jpg 
        image: '{:images[:index]}',
        themes: [
          // { name: 'green' }
          {
            name: '{:themes.0.name}'
          },
          // { name: 'blue' }, { name: 'red' }
          '{:themes.1-last}'
        ],
      },
      // you can write json schema
      // schema: {
      //   type: 'object',
      //   properties: {
      //     message: { type: 'string' },
      //     image: { type: 'string' },
      //     themes: { 
      //       type: 'array',
      //       items: { 
      //         type: 'object',
      //         properties: {
      //           name: { type: 'string' }
      //         }
      //       }
      //     }
      //   }
      // },
      values: {
        greeting: 'hello',
        images: [
          'http://example.com/foo.jpg',
          'http://example.com/bar.jpg',
          'http://example.com/baz.jpg',
        ],
        themes: [
          {
            name: 'green',
          },
          {
            name: 'blue',
          },
          {
            name: 'red',
          },
        ]
      }
    },
  },
]
```

- Create server

We support express, pure node.js and any other frameworks can use agreed.

```javascript
'use strict';
const express = require('express');
const bodyParser = require('body-parser');
const Agreed = require('agreed-core');
const agreed = new Agreed();
const app = express();

app.use(bodyParser.json());

app.use(agreed.middleware({
  path: './agreed/file/agreed.js',
}));

app.use((err, req, res, next) => {
  res.statusCode = 500;
  res.send(`Error is occurred : ${err}`);
});
app.listen(3000);
```

```
$ node server.js
```

- call server from client

```
$ curl http://localhost:3000/user/alice?q=foo
{ 
  "message": "hello alice foo",
  "images": [
    "http://example.com/foo.jpg",
    "http://example.com/bar.jpg"
  ],
  "themes": {
    "name": "green",
  },
}
```

## Usage as Backend test client

agreed can be test client.

- Reuse agreed file

```javascript
module.exports = [
  {
    request: {
      path: '/user/:id',
      method: 'GET',
      query: {
        q: '{:someQueryStrings}',
      },
      values: {
        id: 'yosuke',
        someQueryStrings: 'foo'
      },
    },
    response: {
      headers: {
        'x-csrf-token': 'csrf-token', 
      },
      body: {
        message: '{:greeting} {:id} {:someQueryStrings}',
        images: '{:images}',
        themes: '{:themes}',
      },
      values: {
        greeting: 'hello',
        images: [
          'http://example.com/foo.jpg',
          'http://example.com/bar.jpg',
        ],
        themes: {
          name: 'green',
        },
      }
    },
  },
]
```

- Create test client 

```javascript
'use strinct';
const Agreed = require('agreed-core');
const agreed = new Agreed();
const client = agreed.createClient({
  path: './agreed/file/agreed.js',
  host: 'example.com',
  port: 12345,
});

// Get Agreements as array.
const agrees = client.getAgreement();

// request to servers.
// in this case, GET example.com:12345/user/yosuke?q=foo
const responses = client.executeAgreement(agrees);

// Check response object.
client.checkResponse(responses, agrees).then((diffs) => {
  // if the response is mismatched to agreed response,
  // you can get diff.
  // but if no difference, you can get empty object {}
  diffs.forEach((diff) => {
    if (Object.keys(diff).length > 0) {
      console.error('your request does not matched: ', diff);
    }
  });
});
```


# APIs

## Agreement

### how to define API specs

Agreement file can be written in JSON5/YAML/JavaScript format. You can choose your favorite format.

- JSON5 example

```javascript
[
  {
    "request": {
      "path": '/hoge/fuga',
      "method": 'GET',
      // you can write query
      "query": {
        "q": 'foo',
      },
    },
    response: {
      headers: {
        'x-csrf-token': 'csrf-token', 
      },
      body: {
        message: 'hello world',
      },
    },
  },
  {
    "request": {
      // you can write regexp path, 
      // match /users/yosuke
      "path": '/users/:id',
      "method": 'GET',
    },
    response: {
      // embed path :id to your response body 
      // if request path /users/yosuke
      // return { "message": "hello yosuke" }
      body: {
        message: 'hello {:id}',
      },
    },
  },
  // you can write json file
  // see test/agrees/hoge/foo.json
  './hoge/foo.json',
  // you can write yaml file
  // see test/agrees/foo/bar.yaml
  './foo/bar.yaml',
  // you can separate request/response json
  {
    request: './qux/request.json',
    response: './qux/response.json',
  },
  {
    request: {
      path: '/path/:id',
      method: 'POST',
      // query embed data, any query is ok.
      query: {
        meta: "{:meta}",
      },
      body: {
        message: "{:message}"
      },
      // value for test client
      values: {
        id: 'yosuke',
        meta: true,
        message: 'foobarbaz'
      },
    },
    response: {
      headers: {
        'x-csrf-token': 'csrf-token', 
      },
      body: {
        // :id is for request value
        message: 'hello {:id}, {:meta}, {:message}',
      },
    },
  },
  {
    request: {
      path: '/images/:id',
      method: 'GET',
      query: {
        q: '{:someQueryStrings}',
      },
      values: {
        id: 'yosuke',
        someQueryStrings: 'foo'
      },
    },
    response: {
      headers: {
        'x-csrf-token': 'csrf-token', 
      },
      body: {
        message: '{:greeting} {:id} {:someQueryStrings}',
        images: '{:images}',
        themes: '{:themes}',
      },
      values: {
        greeting: 'hello',
        images: [
          'http://example.com/foo.jpg',
          'http://example.com/bar.jpg',
        ],
        themes: {
          name: 'green',
        },
      }
    },
  },
  {
    request: {
      path: '/useschema/:index',
      method: 'GET',
      values: {
        index: 1
      }
    },
    response: {
      body: {
        result : '{:list[:index]}'
      },
      // you can write json schema
      schema: {
        type: 'object',
        properties: {
          result: {
            type: 'string'
          }
        },
      },
      values: {
        list: [
          'hello',
          'hi',
          'dunke',
        ]
      }
    },
  },
]
```

---
_Source: https://npm.io/package/@agreed/core · Machine-readable twin of the npm.io package page. Health data is recomputed on every publish._
