npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@launchtray/hatch-scim2-server-sdk

v0.21.0-alpha.55

Published

This project is a TypeScript server sdk project that contains autogenerated code based on an [OpenAPI Specification](https://swagger.io/specification/). In many cases, the input specification is defined by an API project in the same repository, which fee

Downloads

8

Readme

hatch-scim2-server-sdk

This project is a TypeScript server sdk project that contains autogenerated code based on an OpenAPI Specification. In many cases, the input specification is defined by an API project in the same repository, which feeds both server and client SDK generators.

Code generation process

A server SDK is typically generated from an OpenAPI specification, which is in turn generated or defined by an API project within the same repository. The OpenAPI specification often also serves as an input to the generation of a client SDK library, which can be used by clients of the service to interact with the API in a type-safe way.

API delegates

API delegates provide handlers for incoming HTTP requests. This library includes auto-generated TypeScript interfaces that define the API delegates that must be implemented to provide the HTTP-based API defined by the input OpenAPI specification.

Auto-generated code within this project calls API delegate methods with parsed, typed parameters in order to service HTTP requests. API delegates should be registered as middleware for a server using the getApiMiddleware export of this library. For example, in composeServer.ts for a server (assuming an API called ExampleApi):


export default async (): Promise<WebServerComposition> => {
  /* ... */
  return {
    ...commonComposition,
    serverMiddleware: [
      JSONBodyParser,
      RequestLogger,
      ...getApiMiddleware({
        delegateForExampleApi: ExampleApiDelegateImpl,
      }),
      RouteNotFound, // Catch-all 404 for unimplemented APIs
    ],
  };
};

Delegate methods

The interfaces required by the parameters to getApiMiddleware include handler methods for each HTTP endpoint defined in the API spec. Each of these methods has an explicitly typed request object as its first parameter, which includes all request parameters and payloads, parsed into a type-safe object. Optionally, the class implementing the API delegate can define other parameters to be injected, as long as the types of the parameters can be resolved via dependency injection for the current request context. For example, even though the API delegate interface has a handler method defined as follows:

handleCreateTester(
  request: models.CreateTesterRequest & {isLocal: boolean, isFromSsr: boolean},
  ...optionalInjections: unknown[]
): ApiDelegateResponse<models.CreateTesterResponse>;

The implementing class might implement it as such, to get a per-request logger and low-level information about the underlying HTTP request:

handleCreateTester(
  request: CreateTesterRequest,
  @inject('Logger') logger: Logger,
  basicRouteParams: BasicRouteParams,
): CreateTesterResponse {
  /* ... */
}

This uses the same mechanism as parameters to routes defined manually. For more information, see the Manual routes section below.

Alternate Actions and API Errors

In some cases, it might not make sense to return the expected response object, e.g. in the case of an error condition. In those cases, API delegate methods can either return an ApiAlternateAction object, or throw an ApiError to indicate the HTTP status code to use, headers to return, and the contents of the response body. For example, the two non-successful cases result in the same HTTP response:

import {
  ApiAlternateAction,
} from '@launchtray/hatch-util';

handleCreateTester(
  request: CreateTesterRequest,
  @inject('Logger') logger: Logger,
  basicRouteParams: BasicRouteParams,
): CreateTesterResponse {
  return new ApiAlternateAction(500, 'Test error');
}
import {
  ApiAlternateAction,
  ApiError,
} from '@launchtray/hatch-util';

handleCreateTester(
  request: CreateTesterRequest,
  @inject('Logger') logger: Logger,
  basicRouteParams: BasicRouteParams,
): CreateTesterResponse {
  throw new ApiError(new ApiAlternateAction(500, 'Test error'), 'Detailed error message');
}

This mechanism works for explicit API controller handlers as well as for manually-defined routes.

Manual routes

In most cases, the autogenerated code is all that is necessary for building APIs. However, in some cases, it is necessary to define routes manually, e.g. for wildcard routes that do common processing before other endpoints.

Routes can be defined manually using decorators within the route namespace exported by hatch-server. These decorators use the same routing syntax that is used by express, including support for route parameters. A simple example of a GET route with a person ID parameter can be seen below:

import {
  BasicRouteParams,
  route,
} from '@launchtray/hatch-server';
import {inject, containerSingleton, Logger} from '@launchtray/hatch-util';

@containerSingleton()
export default class ExampleApiDelegateImpl {
  // Note: dependencies can be injected into the constructor
  constructor(@inject('Logger') private readonly logger: Logger) {
  }

  @route.get('/api/person/:id')
  public personEndpoint(params: BasicRouteParams) {
    params.res.status(200).send('Person: ' + params.req.params.id);
  }

  ...

As shown above, route methods can take in a parameter of type BasicRouteParams, which contains the Express Request and Response objects, the next callback passed to the request handler, a Logger instance, any cookies, and the auth header.

However, when a request comes in, the server creates a new dependency injection container specifically for that request. This container is a child of the root container that is used by composeServer.ts and composeCommon.ts to register dependency classes. The only objects that get registered into the child container that are not also in the root container are the fields of BasicRouteParams. The parameters of route handler methods are actually auto-resolved using this container. This means that not only could we define the method with a single BasicRouteParams parameter, but we could also use any parameters, as long as they can be resolved by the child container described above. For example, imagine a very simple HTTPResponder class which depends on BasicRouteParams:

import {BasicRouteParams} from '@launchtray/hatch-server';
import {containerSingleton} from '@launchtray/hatch-util';

@containerSingleton()
export default class HTTPResponder {
  constructor(public readonly params: BasicRouteParams) {}

  public ok(body?: any) {
    this.params.res.status(200).send(body);
  }
}

Since this class is annotated as injectable (via @containerSingleton()), and since it only depends on things that are registered in an HTTP request's child container (in this case, just BasicRouteParams), we can use it as a parameter to a route like so:

@route.get('/api/example')
public exampleEndpoint(responder: HTTPResponder) {
  this.logger.info('Example endpoint called');
  responder.ok('Example GET');
}

WebSockets

In addition to HTTP method routes, WebSocket server routes can be defined. These routes make use of the ws library. An example WebSocket route that broadcasts messages to all other clients is shown below. Note that route parameters (in this case an ID) can also be used with WebSocket routes.

@route.websocket('/ws/:id')
public async handleWebsocket(params: WebSocketRouteParams) {
  const ws = params.webSocket; 

  // ws is simply a web socket object from the ws library

  ws.on('message', (msg: string) => {
    params.webSocketServer.clients.forEach((client: WebSocket) => {
      if (client !== ws && client.readyState === WebSocket.OPEN) {
        client.send(params.req.params.id + ': ' + msg);
      }
    });
  });
}

Health checks

Each controller can define health checks that contribute to the overall health result returned by /api/health, /api/health/liveness and /api/health/readiness. This can be done via @livenessCheck() and @readinessCheck() decorators. Each controller can have multiple checks of each type.

Liveness checks

Liveness checks can be used for signaling that the service is alive or if it needs to be restarted.

To signal that functionality is healthy, methods decorated with @livenessCheck() can return true or LivenessState.CORRECT. Liveness checks that throw an error, return false or return LivenessState.BROKEN will cause the overall health check to indicate that the service is down.

Readiness checks

Readiness checks can be used for signaling that the service is not only alive, but is ready to receive traffic.

To signal that functionality is ready, methods decorated with @readinessCheck() can return true or ReadinessCheck.ACCEPTING_TRAFFIC. Readiness checks that throw an error, return false or return ReadinessCheck.REFUSING_TRAFFIC will cause the overall health check to indicate that the service is out of service.

Application info

By default, /api/health/info will respond with basic information about the build, like commit ID, package name and version, build time, etc. Custom data can be returned by this endpoint by adding controller methods decorated with @appInfoProvider(). These methods can be asynchronous and should return an object representing key-value pairs to be included in the response for /api/health/info.