Skip to content

Commit

Permalink
Single workspace design
Browse files Browse the repository at this point in the history
  • Loading branch information
koistya committed Apr 16, 2021
1 parent 0712808 commit 2ddc03e
Show file tree
Hide file tree
Showing 62 changed files with 3,547 additions and 1,026 deletions.
16 changes: 16 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# For more information about the properties used in
# this file, please see the EditorConfig documentation:
# https://editorconfig.org/

root = true

[*]
charset = utf-8
end_of_line = lf
indent_size = 2
indent_style = space
insert_final_newline = true
trim_trailing_whitespace = true

[*.md]
trim_trailing_whitespace = false
14 changes: 10 additions & 4 deletions .eslintrc.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
/* SPDX-FileCopyrightText: 2016-present Kriasoft <[email protected]> */
/* SPDX-License-Identifier: MIT */

/**
* ESLint configuration.
*
* @see https://eslint.org/docs/user-guide/configuring
* @type {import("eslint").Linter.Config}
*
* @copyright 2016-present Kriasoft (https://git.io/JYNud)
*/

module.exports = {
root: true,

Expand All @@ -23,7 +23,7 @@ module.exports = {

overrides: [
{
files: ["*.ts"],
files: ["*.ts", ".tsx"],
parser: "@typescript-eslint/parser",
extends: ["plugin:@typescript-eslint/recommended"],
plugins: ["@typescript-eslint"],
Expand All @@ -44,6 +44,12 @@ module.exports = {
sourceType: "module",
},
},
{
files: ["db/types.ts"],
rules: {
"@typescript-eslint/no-explicit-any": "off",
},
},
],

ignorePatterns: [
Expand Down
3 changes: 2 additions & 1 deletion .github/workflows/pull_request.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,10 @@ jobs:
# Analyze code for potential problems
- run: yarn prettier --check .
- run: yarn lint --no-cache
- run: yarn tsc

# Test
# - run: yarn test
- run: yarn test

# Compile
- run: yarn build
Expand Down
7 changes: 4 additions & 3 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
# Include your project-specific ignores in this file
# Read about how to use .gitignore: https://help.github.com/articles/ignoring-files

# Compiled output
.backup
.build

# Secrets
/env/*.override
/env/.env.override
/env/.env.*.override

# Yarn package manager
# https://yarnpkg.com/getting-started/qa/#which-files-should-be-gitignored
Expand All @@ -32,4 +33,4 @@ yarn-error.log*
!.vscode/settings.json

# macOS
.DS_Store
.DS_Store
1 change: 1 addition & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
.build
.cache
.yarn
.pnp.js
tsconfig.json
22 changes: 22 additions & 0 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"type": "pwa-node",
"request": "launch",
"name": "api",
"skipFiles": ["<node_internals>/**"],
"runtimeExecutable": "yarn",
"runtimeArgs": [
"node",
"-r",
"./env/config",
"-e",
"require('./.build/index').api.listen(8080)"
]
}
]
}
3 changes: 3 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
"eslintcache",
"esmodules",
"esnext",
"idps",
"gamecenter",
"globby",
"gsutil",
Expand All @@ -58,8 +59,10 @@
"psql",
"sendgrid",
"sourcemap",
"spdx",
"tslib",
"typechecking",
"upsert",
"webflow",
"yarnpkg",
"yarnrc"
Expand Down
12 changes: 5 additions & 7 deletions LICENSE.txt → LICENSE
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
The MIT License

Copyright (c) 2016-present Kriasoft. All rights reserved.
Copyright 2016-present Konstantin Tarkus, Kriasoft

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand All @@ -9,13 +7,13 @@ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
75 changes: 60 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,21 @@
<a href="https://github.com/kriasoft/node-starter-kit/stargazers"><img src="https://img.shields.io/github/stars/kriasoft/node-starter-kit.svg?style=social&label=Star&maxAge=3600" height="20"></a>
<a href="https://twitter.com/koistya"><img src="https://img.shields.io/twitter/follow/koistya.svg?style=social&label=Follow&maxAge=3600" height="20"></a>

Node.js Starter Kit is a project template for building Node.js
applications optimized for serverless infrastructure such as
[Google Cloud Functions](https://cloud.google.com/functions),
Node.js Starter Kit is a project template for building Node.js applications
optimized for serverless infrastructure such as [Google Cloud Functions](https://cloud.google.com/functions),
[AWS Lambda](https://aws.amazon.com/lambda/), [Azure Functions](https://azure.microsoft.com/services/functions/), etc.

## Features

- Pre-configured for `local`, `dev`, `test`, and `prod` environments
- Authentication and authorization using OAuth 2.0 providers (Google, Facebook, etc.)
- Stateless sessions implemented with JWT tokens and a session cookie
- Strongly typed data model using [TypeORM](https://typeorm.io/) and DB schema migrations
- Database first design; auto-generated strongly typed data models (TypeScript)
- Authentication and authorization using OAuth 2.0 providers (Google, Facebook, GitHub, etc.)
- Stateless sessions implemented with JWT tokens and a session cookie (compatible with SSR)
- Database schema migration, seeds, and REPL shell tooling
- Pre-configured unit testing tooling powered by [Jest](https://jestjs.io/) and [Supertest](https://github.com/visionmedia/supertest)
- Multiple cloud functions within the same project (`auth`, `api`, `img`, etc.)
- Application bundling with Rollup as an optimization technique for serverless deployments
- Rebuilds and restarts the app on changes when running locally
- Pre-configured for `local`, `dev`, `test`, and `prod` environments

---

Expand All @@ -28,18 +30,24 @@ Be sure to join our [Discord channel](https://discord.com/invite/bSsv7XM) for as
## Tech Stack

- [Node.js](https://nodejs.org/) v14, [Yarn](https://yarnpkg.com/) package manager, [TypeScript](https://www.typescriptlang.org/), [Babel](https://babeljs.io/), [Rollup](https://rollupjs.org/)
- [PostgreSQL](https://www.postgresql.org/), [TypeORM](https://typeorm.io/), [Express](https://expressjs.com/)
- [PostgreSQL](https://www.postgresql.org/), [Knex](https://knesjs.org/),
[Express](https://expressjs.com/), [Handlebars](https://handlebarsjs.com/),
[Simple OAuth2](https://github.com/lelylan/simple-oauth2).

## Directory Structure

`├──`[`.build`](.build) — Compiled and bundled output (per cloud function)<br>
`├──`[`.build`](.build) — Compiled and bundled output (per Cloud Function)<br>
`├──`[`.vscode`](.vscode) — VSCode settings including code snippets, recommended extensions etc.<br>
`├──`[`api`](./api) — cloud function for handling API requests<br>
`├──`[`auth`](./auth) — cloud function for handling authentication<br>
`├──`[`env`](./env) — environment variables for `local`, `dev`, `test`, and `prod`<br>
`├──`[`api`](./api) — Cloud Function for handling API requests<br>
`├──`[`auth`](./auth) — Cloud Function for handling authentication<br>
`├──`[`db`](./db) — Database client for PostgreSQL using [Knex](https://knexjs.org/)<br>
`├──`[`emails`](./emails) — Email templates (Handlebars)<br>
`├──`[`env`](./env) — Environment variables for `local`, `dev`, `test`, and `prod`<br>
`├──`[`migrations`](./migrations) — database schema migrations ([Cloud SQL](https://cloud.google.com/sql), [TypeORM](https://typeorm.io/))<br>
`├──`[`models`](./models)[TypeORM](https://typeorm.io/) data models<br>
`├──`[`scripts`](./scripts) — Deployment scripts, etc.<br>
`├──`[`scripts`](./scripts) — Deployment scripts, REPL shell, etc.<br>
`├──`[`test`](./test) — Unit tests and benchmarks<br>
`├──`[`views`](./views) — HTML templates (Handlebars)<br>
`└── ...` — add more cloud functions such as `worker`, `notifications`, etc.

## Requirements
Expand All @@ -50,13 +58,50 @@ Be sure to join our [Discord channel](https://discord.com/invite/bSsv7XM) for as

## Getting Started

- Clone the repo — `git clone https://github.com/kriasoft/node-starter-kit.git <dir>`.
- Clone the repo — `git clone -o seed https://github.com/kriasoft/node-starter-kit.git`.
- Update environment variables for `local`, `dev`, `test`, and `prod` environments ([`./env`](./env)).
- Install project dependencies — `yarn install`
- Finally, launch the app — `yarn start` which will become available at [http://localhost:8080](http://localhost:8080/).
- Bootstrap PostgreSQL database — `yarn db:create`
- Finally, launch the app — `yarn start`, it will become available at [http://localhost:8080](http://localhost:8080/).

Use `APP_ENV` environment variable to execute scripts for different environments, for example:

```
$ APP_ENV=test yarn db:migrate
$ APP_ENV=test yarn start
```

![](https://files.tarkus.me/node-starter-kit-start.svg)

**IMPORTANT**: Ensure that VSCode is using the workspace versions of TypeScript and ESLint.

![](https://files.tarkus.me/typescript-workspace.png)

## Scripts

- `yarn start` — Launches the app in development mode on [`http://localhost:8080`](http://localhost:8080/)
- `yarn build` — Compiles and bundles the app for deployment
- `yarn lint` — Validate code using ESLint
- `yarn tsc` — Validate code using TypeScript compiler
- `yarn test` — Run unit tests with Jest, Supertest
- `yarn repl` — Connect to the database using Knex REPL shell
- `yarn psql` — Connect to the database using PostgreSQL CLI
- `yarn db:create` — Create a new database
- `yarn db:version` — Check the current version of the database
- `yarn db:migrate` — Migrate database schema to the latest version
- `yarn db:rollback` — Rollback the latest migration
- `yarn db:seed` — Seed database with sample / reference data
- `yarn db:reset` — Re-apply the latest DB schema migration file
- `yarn update-types` — Generate strongly typed data models from database schema

Optionally set `APP_ENV` to `local` (default), `dev`, `test`, or `prod` before running these scripts.

![](https://files.tarkus.me/node-starter-kit-db.svg)

## Related Projects

- [GraphQL API Starter Kit](https://github.com/kriasoft/graphql-starter) — project template, pre-configured with TypeScript, GraphQL.js, React, and Relay.
- [React Starter Kit](https://github.com/kriasoft/react-starter-kit) — project template, pre-configured with Webpack and React

## How to Contribute

Expand Down
34 changes: 34 additions & 0 deletions api/email.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/* SPDX-FileCopyrightText: 2016-present Kriasoft <[email protected]> */
/* SPDX-License-Identifier: MIT */

import Email from "email-templates";
import env from "../env";

/**
* Email renderer and sender (for transactional emails).
*
* @see https://github.com/forwardemail/email-templates
*/
export default new Email({
message: {
from: `"${env.APP_NAME}" <${env.EMAIL_FROM}>`,
},
views: {
options: {
extension: "hbs",
},
locals: {
appName: env.APP_NAME,
},
},
// https://nodemailer.com/smtp/
transport: {
host: "smtp.gmail.com",
port: 587,
secure: true,
auth: {
user: env.EMAIL_FROM,
pass: env.EMAIL_PASSWORD,
},
},
});
35 changes: 35 additions & 0 deletions api/errors.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/* SPDX-FileCopyrightText: 2016-present Kriasoft <[email protected]> */
/* SPDX-License-Identifier: MIT */

import { ErrorRequestHandler } from "express";
import { isHttpError } from "http-errors";

/**
* Renders an error page.
*/
export const handleError: ErrorRequestHandler = function (
err,
req,
res,
next // eslint-disable-line @typescript-eslint/no-unused-vars
) {
const statusCode = isHttpError(err) ? err.statusCode : 500;
res.status(statusCode);

if (/application\/json;/.test(req.get("accept") ?? "")) {
res.send(err);
} else if (statusCode === 404) {
res.render("error", {
title: "Page Not Found",
message: "Sorry, but the page you were trying to view does not exist.",
layout: false,
});
} else {
res.render("error", {
title: "Application Error",
message: "An error occurred while processing this request.",
stack: err.stack,
layout: false,
});
}
};
Loading

0 comments on commit 2ddc03e

Please sign in to comment.