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

@co-digital/api-sdk

v1.0.8

Published

An API SDK for Node.JS applications in CO Digital.

Downloads

13

Readme

Node API SDK

npm Static Badge

This Node.js SDK module is a development tool that simplifies and accelerates the integration of external services or APIs into Node.js applications. It aims to make the developer's life easier by providing a well-documented, customizable, and reliable interface to interact with the external service. Allows developers to extend the SDK's behaviour through configuration options and callbacks and implements security best practices that protect against common vulnerabilities and threats, especially if handling sensitive data or credentials.

Files Structure

| Directory Path | Description | | -------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | ./api-client/ | This directory is used to create api client object based on Authentication headers (OAuth or api Key). | | ./api-sdk/ | This directory is where the department related SDK modules are kept. | | ./api-sdk/github | This folder is the entry point for the GitHub API SDK calls, data types and includes TypeScript interfaces that describe the structure and shape of various objects used in the module and possible mapping. | | ./api-sdk/identity | This folder is the entry point for the Identity API SDK calls, data types and mapping. | | ./http-request/ | This folder contains the core class of this module, the HttpRequest class. It serves as the foundation for creating an Axios object with a predefined sequence of AxiosRequestConfig configurations before initiating the actual HTTP request. This object will then be provided as a parameter to the ApiSDK and passed to all SDKs for executing the corresponding HTTP calls. | | ./index.ts | This file will export all related and important function of this module, mainly createOAuthApiClient and createApiKeyClient. | | Others files | Other files related to modules dependency, CI/CD, *git, dockerization, lint, test/typescript configs … |

Api Client module

This directory is responsible for creating API client objects that interact with external services, APIs, or systems. These clients are typically configured with the necessary authentication headers, such as OAuth tokens or API keys.

const apiOptions: ApiOptions = {
  "Content-Type": "application/json",
  Accept: "application/json",
  Authorization: "",
};

const createApiSDK = (apiOptions: ApiOptions): ApiSDK => {
  return new ApiSDK(new HttpRequest(apiOptions));
};

export const createOAuthApiClient = (token: string): ApiSDK => {
  apiOptions.Authorization = `Bearer ${token}`;
  return createApiSDK(apiOptions);
};

export const createApiKeyClient = (key: string): ApiSDK => {
  apiOptions.Authorization = key;
  return createApiSDK(apiOptions);
};

Api SDKs

The project is organized for working with multiple APIs using SDKs, with a clear separation of concerns. Each directory serves a specific purpose, making the codebase more maintainable and readable. It serves as the home for SDK modules that provide a higher-level, user-friendly interface for developers to interact with APIs. SDKs abstract away the intricacies of API calls, making it easier for developers to work with the external service. Each SDK module typically includes methods for API calls, data types, and TypeScript interfaces that describe the shape of data objects used in the module.

import { HttpRequest } from "../http-request";

import { Identity } from "./identity";
import { Github } from "./github";

export default class ApiSDK {
    public readonly identity: Identity;
    public readonly gitHub: Github;

    constructor (readonly request: HttpRequest) {
        this.identity = new Identity(request);
        this.gitHub = new Github(request);
    }
}

The first API calls implemented is specifically dedicated to the GitHub API SDK and soon after is going to include the Identity API SDK calls

export const makeUserInfoRequest = () => ();
export const makeTokenRequest = () => ();
// export const make... = () => ();
export const buildAuthorizeRequest = () => ();
export const buildSecureAuthorizeRequest = () => ();
export const buildLogoutUrl = () => ();
// export const build... = () => ();
export const validateIdToken = () => ();
export const validateLogoutToken = () => ();
// export const validate... = () => ();

HTTP Request class

The http-request directory contains core functionality for handling HTTP requests in your module. The key component is the HttpRequest class, which serves as the foundation for creating Axios objects configured with specific settings.


export class HttpRequest {

    constructor(private readonly headers: ApiOptions) { /**/ }
    public async httpGet(url: string, headers?: Headers): Promise<HttpResponse> {
        return await this.request({ method: "GET", url, headers });
    }
    public async httpPost(url: string, body?: any, headers?: Headers): Promise<HttpResponse> { /*...*/ }
    public async httpPatch(url: string, body?: any, headers?: Headers): Promise<HttpResponse> { /*...*/ }
    public async httpPut(url: string, body?: any, headers?: Headers): Promise<HttpResponse> { /*...*/ }
    public async httpDelete(url: string): Promise<HttpResponse> { /*...*/ }

    private async request(additionalOptions: AdditionalOptions): Promise<HttpResponse> {
        try {
            const options: AxiosRequestConfig = {
                // `headers` are custom headers to be sent, contains "Content-Type", "Accept"
                // "Authorization" and additional headers from response object
                headers: {
                    ...this.headers,
                    ...additionalOptions.headers
                },

                // `method` is the request method to be used when making the request
                // Only applicable for request methods 'GET', 'PUT', 'POST', 'PATCH' and 'DELETE'
                method: additionalOptions.method,

                // `url` is the server URL that will be used for the request including `params`
                url: additionalOptions.url,

                // `responseType` indicates the type of data that the server will respond with
                // options are: 'arraybuffer', 'document', 'json', 'text', 'stream', browser only: 'blob'
                responseType: 'json',

                // `validateStatus` defines whether to resolve or reject the promise for a given
                // HTTP response status code (only if the status code is less than 500 in our context).
                // If `validateStatus` returns `true` (or is set to `null` or `undefined`),
                // the promise will be resolved; otherwise, the promise will be rejected.
                validateStatus: (status: number) => status < 500
            };

            if (additionalOptions.body) {
                // `data` is the data to be sent as the request body
                // Only applicable for request methods 'PUT', 'POST', and 'PATCH'
                options.data = additionalOptions.body;
            }

            const resp = await axios(options);

            return {
                status: resp.status,
                body: resp.data,
                headers: resp.headers
            };
        } catch (e: any) {
            const errorMessage = { message: "failed to execute http request" };
            return {
                status: e?.status || 500,
                error: e?.response?.data || e?.message || errorMessage
            };
        }
    }
}

The HttpRequest class is responsible for configuring Axios request with predefined AxiosRequestConfig settings, such as authentication headers and other request-related parameters. This Axios object is then used for making HTTP requests within your SDKs.

import { HttpRequest } from "../../http-request";
import { ApiResponse, ApiErrorResponse } from "../response";
import { GitHubRepos, GitHubIssueRequest } from './type';
import { reposMapping } from './mapping';

export class Github {

    constructor(private readonly request: HttpRequest) { /**/ }

    public async getGitHubInfo(url: string): Promise<ApiResponse<any[]> | ApiErrorResponse> {
        const response = await this.request.httpGet(url);
        return this.responseHandler(response);
    }

    public async postIssue (url: string, body: GitHubIssueRequest): Promise<ApiResponse<any> | ApiErrorResponse> {
        const response = await this.request.httpPost(url, body);
        return this.responseHandler(response);
    }

    public async getRepos(url: string): Promise<ApiResponse<GitHubRepos[]> | ApiErrorResponse> {
        const response = await this.request.httpGet(url);
        return this.responseHandler<GitHubRepos[]>(response, reposMapping);
    }

    // ...

    private responseHandler<T>(
        response: any,
        responseMap?: (body: any) => T
    ): ApiResponse<T> | ApiErrorResponse {
        const resource: ApiResponse<T> & ApiErrorResponse = {
            httpStatusCode: response.status
        };

        if (response.error) {
            resource.errors = [response.error];
        } else if (response.status >= 400) {
            resource.errors = [response.body];
        } else {
            resource.resource = (responseMap) ? responseMap(response.body) : response.body;
        }

        return resource;
    }
}

Integration

import { createOAuthApiClient } from "@co-digital/api-sdk";
...
const apiClient = createOAuthApiClient(token);
const teams = await apiClient.gitHub.getTeams(url);
...

Contributing

## Set Node/NPM env
nvm use

## Installing & Building
make build

## Testing & Coverage
make test
#or
make coverage