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

@pocketgems/app

v0.0.15

Published

Todea App Library

Downloads

15

Readme

Todea App Library

Todea App library is a backend framework designed to streamline Node.js development workflow for your side project, then seamlessly transition to enterprise scale applications supporting millions of users.

Topics

Key Features

  • High level DB library
    • For AWS DyanmoDB
    • Schemaful
    • Transactional
    • Scalable
    • Lighting fast
    • Support DAX, Index, Query, Scan and more
  • High level API library
    • Routing
    • Input, output schema
    • Exceptions
    • CORS
    • Authentication
    • Compression
    • Health check API
    • Advanced error handling
  • SDK Generation
    • Swagger UI
    • OpenAPI SDK
    • AWS SDK & CLI compatible

Getting Started

With Todea App library, you can define database schemas, create several APIs, and have a procedurally generated SDK ready for client and frontend consumption within hours.

Creating A Database Table

You can create a database table with a few lines of code:

const db = require('@pocketgems/dynamodb')
const S = require('@pocketgems/schema')

class Order extends db.Model {
  static KEY = {
    id: S.str.min(10).desc(`A unique string id for the order.
      ID must be at least 10 characters long`)
  }

  static FIELDS = {
    customerId: S.str,
    items: S.map.value(S.obj({
      itemId: S.str.desc('An item\'s ID'),
      quantity: S.int.min(1),
      dollarPrice: S.double.min(1)
    }))
  }
}

The example above defines a db table called Order to store customers orders. Each order can have one or more items in it, with each item have an ID, quantity and dollar price. The example uses 2 dependencies for defining schema and data model. You may read more about these libraries in greater detail in their perspective project later:

Creating An API

You can create an API to look up order details like this:

const { TxAPI, EXCEPTIONS: { NotFoundException } } = require('@pocketgems/app')

class GetOrderAPI extends TxAPI {
  static PATH = '/getOrder'
  static DESC = `Get an order by ID, if order doesn't exists a 404 Not found
    error is returned`

  static INPUT = Order.KEY
  static OUTPUT = {
    order: Order.Schema
  }
  static EXCEPTIONS = {
    NotFoundException
  }

  async computeResponse ({ tx, body }) {
    const order = await tx.get(Order, body.id)
    if (!order) {
      throw new NotFoundException()
    }
    return { order: order.toJSON() }
  }
}

You can read more about API interface here.

Creating An App

To create a Todea app, you have to call makeApp like this:

const { makeApp } = require('@pocketgems/app')

const components = {
  Order,
  GetOrderAPI
}
module.exports = makeApp({
  service: 'unittest',
  components,
  cookie: {
    secret: 'unit-test'
  },
  logging: {
    reportErrorDetail: true, // process.env.NODE_ENV === 'localhost',
    unittesting: true, // process.env.NODE_ENV === 'localhost',
    reportAllErrors: true // process.env.NODE_ENV !== 'prod'
  },
  awsC2j: {
    version: '2020-02-20',
    displayName: 'Unit Test',
    signatureVersion: 'v4',
    globalEndpoint: 'todea.example.com',
    globalHeaders: ['x-app', 'x-uid', 'x-admin', 'x-token']
  },
  swagger: {
    disabled: false,
    authHeaders: ['x-app', 'x-uid', 'x-admin', 'x-token'],
    servers: ['http://localhost:8080'],
    routePrefix: '/app/docs'
  }
})

Starting Server

The makeApp() helper method creates a fastify instance with a few plugins loaded already. You may customize the fastify instance further using fastify's customization features. To start the app, you have to call .listen() according to Fastify's documentation. For example, makeApp() is called in a app.js file, and the returned promise is exported, then you write the following code to create a server:

require(pathToApp)
  .then(app => app.listen({ port: 8090, host: '0.0.0.0' }))
  .catch((err) => {
    console.log(err)
    process.exit(1)
  })

Components

Todea app is composed of components. A Todea app component can be an API, DB Table (db.Model), S3 bucket etc. These components are passed to makeApp() in an object as components. For example, components may be initialized like this:

const components = {
  Order,
  GetOrderAPI
}

makeApp({
  components,
  ...
})

Internally, each of these components get registered to a corresponding system. For example, API is registered with fastify as a route, while db table is registered with AWS DynamoDB service, or as an AWS CloudFormation Resource if Infrastructure-As-Code is required.

Customizing Component Registration

The component system uses a visitor pattern to allow extending the registration workflow with custom components. For example, to add a new type of component ExampleComponent, you need to do the following:

  1. Subclass ComponentRegistrator, and add a registerExampleComponent (exampleComponent) method
    const { ComponentRegistrator } = require('@pocketgems/app')
    
    class CustomComponentRegistrator extends ComponentRegistrator {
        registerExampleComponent (exampleComponent) {
            // do what needs to be done
        }
    }
  2. You can pass the new CustomComponentRegistrator class to makeApp() like this
    makeApp({
        RegistratorCls: CustomComponentRegistrator
    })
  3. Implement static register (registrator) in the new ExampleComponent class
    class ExampleComponent {
        static register (registrator) {
            registrator.registerExampleComponent(this)
        }
    }
  4. Pass the new type of component as part of components like this makeApp({ components: { ExampleComponent } })

Unit testing

Setup

Todea apps store data in AWS DynamoDB service. You must setup the database before running tests. You can run yarn --cwd ./node_modules/@pocketgems/app setup; yarn --cwd ./node_modules/@pocketgems/app start-local-db to start a local AWS DynamoDB docker instance. And use @pocketgems/app/test/environment.js to setup Jest envrionments.

Writing Tests

This library exposes @pocketgems/unit-test through @pocketgems/app/test/base-test and adds 2 new symbols:

  • BaseAppTest is the common base class for testing APIs. Useage is similar to BaseTest, but exposes a this.app handle to invoke APIs.

    You have to implement a static async requireApp() method to import the app.

  • mockGot is a utility method to mock out-going requests from this.callAPI(). See examples of using this in this library's unit tests.

Generating SDKs

Swagger UI

This library generates an interactive Swagger UI for all APIs at /[service]/docs.

OpenAPI SDKs

You can export APIs in an OpenAPI schema from /[service]/docs/json, and use that with OpenAPI / Swagger SDK to generate SDKs in any supported languages.

CAUTION: Swagger SDKs use postional arguments in all SDKs, maintaining backward compatibility will be challenging with vanilla SDK generators. You may customize the generators to pass keyword arguments instead for languages that support it.

AWS SDKs

This library adds REST APIs to generate C2J schemas. It is what AWS uses to generate their SDKs and CLI. One set for public APIs and one set for private APIs. In the following lines group can be service, admin or user.

  • /[service]/c2j/[group]/uid: Returns the API version, e.g. example-2020-09-20.
  • /[service]/c2j/[group]/normal: Returns the normal C2J schema. This schema contains API definition and documentations.
  • /[service]/c2j/[group]/api: Returns normal C2J schema minus any documentation.
  • /[service]/c2j/[group]/docs: Returns a docs C2J schema.

If there is no API to be exported, these endpoints will return empty string as the response.