Contributing to hyper63 Part 2 - creating an adapter

Hello πŸ‘‹,

Welcome back to the contributing to hyper63 series. In this session, we will create an adapter for our hyper63 port.

If you have not done the part 1 of the tutorial, you can find part 1 here:

What is a hyper63 adapter? πŸ”Œ

An adapter is the implementation details of a given hyper63 port. If the port is a cache api, then an adapter would be an adapter to uses the redis service. The adapter contains the specific details of a given service where the port is more general and provides the common api on how an adapter should expose its features.

Greeting Echo Adapter

We want to teach the process of creating an adapter and not get caught up in a specific service, so our adapter will be a greeting echo adapter. The port is called echo and contains one method called echo which is a function that takes a string as an argument and returns a Promise that returns a String. Our greeting adapter will implement this echo port and return a promise with the text 'Hello ' plus whatever was passed as a string. For Example, if 'World' was passed as a string then our adapter will return 'Hello World'. 😎

Setting up our project βš™οΈ

mkdir hyper63-adapter-greeting
cd hyper63-adapter-greeting
yarn init -y
yarn add -D tape 
yarn add -D @hyper63/adapter-tester
yarn add -D @hyper63/port-echo

open package.json in your code editor πŸ’»
and add "type": "module" to enable ESM

{
  ...
  "type": "module"
}

index.js

create an index.js file and open it in your code editor πŸ’»

The index file is going to implement the adapter header that is used to properly install the adapter in hyper63.
import adapter from './adapter.js'

export default function () {
  return {
    id: 'greeting',
    port: 'echo',
    load: env => env,
    link: env => _ => adapter(env)
  }
}

The main adapter function must return an object that contains the following properties:

  • id - name of the adapter
  • port - name of the port the adapter is implementing
  • load - this function handles any configuration that may need to be passed to the adapter
  • link - this function handles the actual adapter injection to hyper63

adapter.js

create an adapter.js file and open it in your code editor πŸ’»

export default function (env) {
  return {
    echo: s => Promise.resolve(`Hello ${s}`)
  }
}

Testing your adapter

First we will create a unit test for the adapter implementation.

create an adapter_test.js file and open your code editor πŸ’»

import { default as test } from 'tape'
import adapter from './adapter.js'

test('echo hello world', t => {
  t.plan(1)
  const a = adapter()
  t.equal('Hello World', a.echo('World'))
})

lets also create an integration test

create an index_test.js file and open your code editor πŸ’»

import { default as test } from 'tape'
import greetingsAdapter from './index.js'
import port from 'hyper63-port-echo'

test('ok', async t => {
  t.plan(1)
  try {
    const greetings = greetingsAdapter()
    const env = greetings.load()
    const adapter = greetings.link(env)()
    const a = port(adapter)
    const res = await a.echo('World')
    t.equal(res, 'Hello World')
  } catch (e) {
    console.log(e)
    t.ok(false)
  }
})
   
    
  

Setup Github Action

Lets setup a Github action to run our tests on every push

create a test runner file test.js

import indexTest from './index_test.js'
import adapterTest from './adapter_test.js'

modify the package.json file

{
  ...
  "scripts": {
    "test": "node test.js"
  }
}

create a new directory .github/workflows

mkdir -p .github/workflows

create a new file in the .github/workflows directory called test.yml

name: test greetings adapter
on: push
jobs:
  build:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        node-version: [14.x]
    steps:
      - uses: actions/checkout@v2
      - name: Use NodeJS ${{ matrix.node-version }}
        uses: actions/setup-node@v1
        with:
          node-version: ${{ matrix.node-version }}
      - run: yarn
      - run: yarn test
        env:
          CI: true

README

create a README.md file

# README

hyper63 greetings adapter for the hyper63 echo port

This adapter is used in hyper63 to support for the echo port

## Example

``` js
import echoPort from 'hyper63-port-echo'
import greetings from 'hyper63-adapter-greetings'

export default {
  app: express,
  adapters: [
    { port: echoPort, plugins: [greetings()] }
  ]
}
```

Deploy to Github

git init
echo node_modules > .gitignore
git add .
git commit -m 'first commit'
gh repo create hyper63-adapter-greetings
git push origin master

Publish to NPM

change the name of the package.json to include your namespace

{
  "name": "@username/hyper63-adapter-greetings"
  ...
}

run npm publish

npm publish --access public

Summary

This tutorial walked us through creating a simple adapter for a hyper63 port, the adapter process is two phases, the implementation of the port specification and the wrapper object that provides the linking information for the hyper63 core engine.

In part 3 of this series we will cover how to attach your new port and adapter to the hyper63 core module and load up your own hyper63 service.