Skip to content
forked from seek-oss/skuba

๐Ÿคฟ Toolkit for backend TypeScript development

License

Notifications You must be signed in to change notification settings

bridgetbarnes/skuba

ย 
ย 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 

Repository files navigation

๐Ÿคฟ

    โ•ญโ”€โ•ฎ     โ•ญโ”€โ•ฎ
โ•ญโ”€โ”€โ”€โ”‚ โ•ฐโ”€โ•ญโ”€โ”ฌโ”€โ•ฎ โ•ฐโ”€โ•ฎโ”€โ”€โ”€โ•ฎ
โ”‚_ โ”€โ”ค  <โ”‚ โ•ต โ”‚ โ€ข โ”‚ โ€ข โ”‚
โ•ฐโ”€โ”€โ”€โ•ฐโ”€โ”ดโ”€โ•ฐโ”€โ”€โ”€โ•ฏโ”€โ”€โ”€โ•ฏโ”€โ”€ โ•ฐ

GitHub Release GitHub Validate Node.js version npm package

Toolkit for backend application and package development on SEEK's gravel and paved roads:

  • Write in TypeScript
  • Enforce coding standards with ESLint and Prettier
  • Test with Jest
  • Deploy with Gantry / Serverless

Related reading:

Table of contents

Getting started

skuba provides you with:

  • Commands for developing your project
  • Templates to base your backend application on

To create a new project:

npx skuba init

To bootstrap an existing project:

npx skuba configure

skuba supports a global installation to speed up local development:

yarn global add skuba

# Look, no `npx`!
skuba version

CLI reference

skuba commands are typically found in the scripts section of package.json.

They replace direct calls to underlying tooling like eslint and tsc.

skuba build

Compile the project.

By convention, this points to a tsconfig.build.json that excludes tests from your production bundle.

// tsconfig.build.json
{
  "exclude": ["**/__mocks__/**/*", "**/*.test.ts", "src/testing/**/*"],
  "extends": "tsconfig.json",
  "include": ["src/**/*"]
}
// tsconfig.json
{
  "compilerOptions": {
    "outDir": "lib"
  },
  "exclude": ["lib*/**/*"]
}

Run skuba configure if you don't have this file.

skuba build-package

Compile the project for compatibility with CommonJS and ES2015 modules.

This is useful for building npm packages, and serves as a replacement for smt build.

skuba configure

Bootstrap an existing project.

This provides a step-by-step prompt for replacing your config with skuba's.

You should have a clean working tree before running this command, so it's easy to git reset in case you want to restore your original config.

skuba format

Apply automatic fixes to code quality and flag issues that require manual intervention.

This script should be run locally before pushing code to a remote branch.

Option Description
--debug Enable debug console output

skuba help

skuba
skuba help
skuba -h
skuba --help

Echoes the available skuba commands.

skuba init

Create a new project.

This initialises a new directory and Git repository.

skuba supports the following template options:

  • express-rest-api

    A REST resource API built on the Express web framework and deployed with Gantry.

  • greeter

    A minimal hello world project.

    Packs enough Buildkite, Docker and Jest configuration to put you on track for production.

  • koa-rest-api

    A REST resource API built on the Koa web framework and deployed with Gantry.

  • lambda-sqs-worker

    An asynchronous worker built on AWS Lambda and deployed with Serverless.

    Modelled after the "enricher" pattern where an event is received from a source SNS topic and a corresponding enrichment is published to a destination SNS topic. For fault tolerance, a message queue is employed between the source topic and the Lambda function, and unprocessed events are sent to a dead-letter queue for manual triage.

  • lambda-sqs-worker-cdk

    An asynchronous worker built on AWS Lambda and deployed with AWS CDK.

    SNS -> SQS (with a dead-letter queue) -> Lambda
    

    Comes with configuration validation and infrastructure snapshot testing.

  • oss-npm-package

    A public npm package published via semantic-release pipeline.

    This is intended for seek-oss projects.

  • private-npm-package

    A private npm package published via semantic-release pipeline.

    This is intended for SEEK-Jobs projects under the @seek npm org.

  • github โ†’ (experimental)

    BYO starter repo!

    skuba will shallow-clone your repo and apply some of its base configuration. You may need to run skuba configure after initialisation to fix up inconsistencies.

This script is interactive by default. For unattended execution, pipe in JSON:

skuba init << EOF
{
  "destinationDir": "tmp-greeter",
  "templateComplete": true,
  "templateData": {
    "ownerName": "my-org/my-team",
    "prodBuildkiteQueueName": "my-team-prod:cicd",
    "repoName": "tmp-greeter"
  },
  "templateName": "greeter"
}
EOF

If you are looking to bootstrap an existing project, see skuba configure.

skuba lint

Check for code quality issues.

This script should be run in CI to verify that skuba format was applied and triaged locally.

Option Description
--debug Enable debug console output

skuba node

Run a TypeScript source file, or open a REPL if none is provided:

  • skuba node src/some-cli-script.ts
  • skuba node

This automatically registers a src module alias for ease of local development. If you use this alias in your production code, your production entry point(s) will need to import a runtime module alias resolver like skuba-dive/register. For example, your src/app.ts may look like:

// This must be imported directly within the `src` directory
import 'skuba-dive/register';

// You can use the `src` module alias after registration
import { rootLogger } 'src/framework/logging';

Note: if you're using the experimental Babel toolchain, you'll be limited to the fairly primitive babel-node REPL. While it can import TypeScript modules, it does not support interactive TypeScript nor modern JavaScript syntax:

import { someExport } from 'src/someModule';
// Thrown: [...] Modules aren't supported in the REPL

const { someExport } = require('src/someModule');
// Thrown: [...] Only `var` variables are supported in the REPL

var { someExport } = require('src/someModule');
// undefined

var v: undefined;
// Thrown: [...] Unexpected token

skuba start

Start a live-reloading server for local development.

The entry point is chosen from:

  1. Command line argument: skuba start src/app.ts
  2. Manifest configuration: package.json#/skuba/entryPoint
  3. Default: src/app.ts

The --inspect and --inspect-brk Node.js options are supported for debugging sessions. For example, in Visual Studio Code:

  1. Run skuba start --inspect-brk
  2. Run the built-in Node.js: Attach launch configuration

This automatically registers a src module alias for ease of local development. If you use this alias in your production code, your production entry point(s) will need to import a runtime module alias resolver like skuba-dive/register. For example, your src/app.ts may look like:

// This must be imported directly within the `src` directory
import 'skuba-dive/register';

// You can use the `src` module alias after registration
import { rootLogger } 'src/framework/logging';

Start an executable script

Your entry point can be a simple module that runs on load:

console.log('Hello world!');

Start a Lambda function handler

Your entry point can target an exported function:

skuba start --port 12345 src/app.ts#handler
export const handler = async (event: unknown, ctx: unknown) => {
  // ...

  return;
};

This starts up a local HTTP server that you can POST arguments to:

curl --data '["event", {"awsRequestId": "123"}]' --include localhost:12345

Start an HTTP server

Your entry point should export:

interface Export {
  // one of these is required
  callback?: () => http.RequestListener;
  requestListener?: http.RequestListener;

  // optional; falls back to an available port
  port?: number;
}

Koa should work with minimal fuss:

const app = new Koa();

// you can also use `export =` syntax as required by koa-cluster
export default Object.assign(app, { port });

As does Express:

const app = express();

export default Object.assign(app, { port });

skuba test

Run tests with Jest.

Arguments are passed through to the Jest CLI.

skuba version

skuba version
skuba -v
skuba --version

Echoes the installed version of skuba.

Development API reference

skuba should be a devDependency that is excluded from your production bundle.

Its Node.js API can be used in build and test code.

Jest.mergePreset

Merge additional Jest options into the skuba preset.

This concatenates array options like testPathIgnorePatterns.

// jest.config.ts

import { Jest } from 'skuba';

export default Jest.mergePreset({
  coveragePathIgnorePatterns: ['src/testing'],
  setupFiles: ['<rootDir>/jest.setup.ts'],

  // this is concatenated to the end of the built-in patterns
  testPathIgnorePatterns: ['/test\\.ts'],
});

Net.waitFor

Wait for a resource to start listening on a socket address.

This can be used to wait for a Docker container to start listening on its port, as described in https://docs.docker.com/compose/startup-order/.

// jest.config.int.js

const rootConfig = require('./jest.config');

module.exports = {
  ...rootConfig,
  globalSetup: '<rootDir>/jest.setup.int.ts',
};
// jest.setup.int.ts

import { Net } from 'skuba';

module.exports = () =>
  Net.waitFor({
    host: 'composeService',
    port: 5432,
    resolveCompose: Boolean(process.env.LOCAL),
  });

Runtime API reference

https://github.com/seek-oss/skuba-dive#api-reference

skuba-dive is an optional runtime component for skuba.

skuba-dive should be a dependency that is included in your production bundle.

Design

Goals

Speed up prototyping and project creation

Standardise tooling

skuba tracks technology recommendations from SEEK's Technology Strategy.

Reduce maintenance overhead

skuba bundles developer tooling into one package.json#/devDependency.

This tooling is managed and upgraded for you. Upgrades are consolidated into one Renovate PR.

Non-goals

Support for vanilla JavaScript

TypeScript is proposed as the default language of SEEK.

skuba prescribes TypeScript-focused tooling.

One stencil to rule them all

skuba may advocate for certain approaches and technologies through its templates, but this shouldn't be taken as the only way you can write code.

You can continue to base codebases on your own starters and stencils.

One library to rule them all

skuba distributes a minimal runtime component through the skuba-dive package. It has no aspirations of becoming a monolithic Node.js runtime library.

SEEK's developer community maintains an assortment of targeted packages.

Here are some highlights:

Package Description
@seek/logger Write application logs in a standardised format
seek-datadog-custom-metrics Write Datadog metrics in Gantry and Lambda
seek-koala Add SEEK-standard observability to Koa servers
๐Ÿ”’ @seek/db-client Connect to databases with credential (rotation) smarts
๐Ÿ”’ @seek/graphql-utils Add observability to GraphQL servers
๐Ÿ”’ @seek/node-s2sauth-issuer Call an s2sauth-protected service
๐Ÿ”’ @seek/typegen Generate TypeScript types from a JSON schema
๐Ÿ”’ @seek/zactive-directory Authenticate and authorise SSOd users

About

๐Ÿคฟ Toolkit for backend TypeScript development

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages

  • TypeScript 94.1%
  • JavaScript 3.4%
  • Roff 1.4%
  • Other 1.1%