0.4.2 • Published 2 years ago

api-socket v0.4.2

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

⚠️ IMPORTANT: api-socket is still a work in progress. It is subject to constant and unnotified changes. Do not use this library until version 1.0.0.

What is api-socket

api-socket is a library for writing api servers using WebSocket instead of http. It is intended for apps that must be as responsive as possible. api-socket makes synchronizing the state of apps between the server and the clients as easy and robust as possible.

Some other great aspects:

  • Works with typescript out of the box
  • Works in Node.js and all modern browsers
  • Has built-in support for runtime type checking
  • Can be configured to use https for security

What is api-socket-client

api-socket-client is the client-side version of this library. It allows you to very easily communicate with the server created with api-socket.

Installation

To install the latest version of api-socket:

npm install api-socket

To install the latest version of api-socket-client for your client side code go to installation.

Basic Usage

Creating a simple api server

// server.ts
import { Api, request, z } from "api-socket";

// The api server is created with http protocol (still uses WebSocket)
// and we create the user controller.
const api = Api.protocol("http").controller("user", {
  login: request({
    // The input property defines the inputs and types that the login request handler takes.
    input: z.object({ email: z.string(), password: z.string() }),

    // The request handler is called whenever a client posts a login request.
    handler({ email, password }) {
      console.log(email, password);
      return "accessToken";
    },
  }),
});

// Starts the server on port 3000 and calls the callback once the server starts.
api.listen(3000, () => console.log("listening on port 3000!"));

// Export the api server type so we can use it in the client typescript code.
export type ApiServer = typeof api;

Creating a simple api client

// client.ts
import { ApiClient, createClient } from "api-socket-client";
import { ApiServer } from "./server";

// The client is created with the server's ip and an optional
// callback for when the client connects to the server.
const client = createClient<ApiServer>("http://localhost:3000", async () => {
  // We can post the login message to the server like this. This is
  // completely typesafe since we created the client with the ApiServer type.
  const response = await client.post("user", "login", {
    email: "email",
    password: "password",
  });

  console.log(response);
});

Controllers

Controllers are added to the server by

api.controller("name", {
  /* request handlers */
});

Request Handlers

All controllers have request handlers. They are the functions that are called when a client sends a request.

import { ..., request } from 'api-socket';

api.controller("name", {
  requestHandler: request({
    input: /* the request's input schema. */,
    handler() { ... } /* the method that is called when requested. */
  })
});

C.R.U.D. (Create, Read, Update, and Delete)

api-socket supports crud operations. To create a request handler for a specific crud operation simply prepend create, get, update, or delete to the name.

// server.ts
api.controller("user", {
  // This request handler would be in charge of creating users.
  create: request({ ... }),

  // This request handler would be in charge of getting the user's account.
  getAccount: request({ ... })
});

To send a crud request to the server simply do

// client.ts
const response = await client.create("user", { ... });
const response = await client.get("user", "account", { ... });

Services

Services are used for dependency injection.

An example service

import { ... , fail } from 'api-socket';

class AuthService {
  private accessToken?: string;

  constructor(accessToken?: string) {
    this.accessToken = accessToken;
  }

  assert(predicate: boolean) {
    if (!predicate) fail('Unauthorized');
  }
}

The service can be added to your api server

import { ..., scoped, Scope }

api.services([ scoped(AuthService, ({ accessToken }) => new AuthService(accessToken), Scope.request ) ]);

The service can be injected into a request handler

import { ..., request }

api.controller('user', {
  login: request({
    input: z.object({ ..., accessToken: z.string() }),

    handler({ ..., accessToken, inject }) {
      const auth = inject(AuthService, { accessToken });
      auth.assert(...);
      ...
    }
  })
});

Singleton Services

Singleton services are services that share the same instance throughout the entire server.

They can be added to your server

import { ..., singleton } from 'api-socket';

api.services([ singleton(YourService, new YourService()) ]);

Scoped Services

Scoped services are services that create a new instance for each scope.

There are two scopes a scoped service can have: Scope.controller and Scope.request. A service with Scope.controller will share the same instance within each individual controller, while a service with Scope.request is initialized per request. A scoped service has Scope.controller by default.

They can be added to your server

import { ..., scoped, Scope } from 'api-socket';

api.services([ scoped(YourService, () => new YourService(), /* optional: Scope.controller or Scope.request */) ]);

Api Service

You can inject your api into any request

handler({ ..., inject }) {
  const api = inject(Api);
}

The api service is mainly used to either broadcast messages to all clients or send a message to a room of clients.

const api = inject(Api);
api.broadcast("namespace", "message", /* optional args */ { ... });
api.send("room-id", "namespace", "message", /* optional args */ { ... });

Api is a singleton service.

Client Service

You can inject the client into any request

handler({ ..., inject }) {
  const client = inject(ApiClient);
}

The client service is mainly used to send messages to individual clients instead of rooms and to join the specific client to a room.

const client = inject(ApiClient);
client.send("namespace", "message", /* optional args */ { ... });

ApiClient is a request scoped service.

0.4.2

2 years ago

0.4.1

2 years ago

0.4.0

2 years ago

0.3.2

2 years ago

0.3.1

2 years ago

0.3.0

2 years ago

0.2.0

2 years ago

0.1.4

2 years ago

0.1.3

2 years ago

0.1.2

2 years ago

0.1.1

2 years ago

0.1.0

2 years ago

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