init
This commit is contained in:
commit
5bcd93fcfc
17 changed files with 2481 additions and 0 deletions
1
.eslintignore
Normal file
1
.eslintignore
Normal file
|
@ -0,0 +1 @@
|
||||||
|
build/
|
14
.eslintrc.json
Normal file
14
.eslintrc.json
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
{
|
||||||
|
"env": {
|
||||||
|
"es2021": true,
|
||||||
|
"node": true
|
||||||
|
},
|
||||||
|
"extends": ["eslint:recommended", "plugin:@typescript-eslint/recommended"],
|
||||||
|
"parser": "@typescript-eslint/parser",
|
||||||
|
"parserOptions": {
|
||||||
|
"ecmaVersion": "latest",
|
||||||
|
"sourceType": "module"
|
||||||
|
},
|
||||||
|
"plugins": ["@typescript-eslint"],
|
||||||
|
"rules": {}
|
||||||
|
}
|
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
node_modules/
|
||||||
|
dist/
|
||||||
|
.env
|
1
.prettierignore
Normal file
1
.prettierignore
Normal file
|
@ -0,0 +1 @@
|
||||||
|
build/
|
19
.swcrc
Normal file
19
.swcrc
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
{
|
||||||
|
"jsc": {
|
||||||
|
"parser": {
|
||||||
|
"syntax": "typescript",
|
||||||
|
"tsx": false,
|
||||||
|
"decorators": true,
|
||||||
|
"dynamicImport": true
|
||||||
|
},
|
||||||
|
"target": "es2020",
|
||||||
|
"paths": {
|
||||||
|
"~/*": ["./src/*"],
|
||||||
|
"~entities/*": ["./src/db/entities/*"]
|
||||||
|
},
|
||||||
|
"baseUrl": "."
|
||||||
|
},
|
||||||
|
"module": {
|
||||||
|
"type": "es6"
|
||||||
|
}
|
||||||
|
}
|
58
README.md
Normal file
58
README.md
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
# TypeScript Node.js template
|
||||||
|
|
||||||
|
This is a template for Node.js applications using TypeScript and TypeORM.
|
||||||
|
|
||||||
|
## Customization
|
||||||
|
|
||||||
|
- To replace PostgreSQL with SQLite: remove `pg`, install either `sqlite3` or `better-sqlite3`,
|
||||||
|
and replace `postgres` in `src/db/index.ts:8` with `sqlite` or `better-sqlite3` (depending on which you installed)
|
||||||
|
- To use the Active Record pattern, make entity classes extend `BaseEntity`.
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
Add configuration keys to `src/config.ts`.
|
||||||
|
|
||||||
|
## Development commands
|
||||||
|
|
||||||
|
- Building the project: `pnpm build`
|
||||||
|
- Migrating the database: `pnpm migrate`
|
||||||
|
- Watching for changes and reloading the project automatically: `pnpm dev`
|
||||||
|
- Formatting: `pnpm format`
|
||||||
|
- Check types: `pnpm typecheck`
|
||||||
|
- Linting (if you don't have an ESLint plugin): `pnpm lint`
|
||||||
|
|
||||||
|
## Creating migrations
|
||||||
|
|
||||||
|
Creating migrations is a little awkward because TypeORM expects `ts-node`, which uses `tsc`.
|
||||||
|
To create a migration, first run `pnpm build`,
|
||||||
|
then run `pnpm typeorm migration:generate -p -d ./dist/db/index.js ./src/db/migrations/<name>`,
|
||||||
|
replacing `<name>` with the name of the migration you're creating.
|
||||||
|
Then rename the created file to end in `.js` and remove the TypeScript-specific code from it.
|
||||||
|
(Yes, this is incredibly janky, but it works, and it only needs to be done once per migration, actually migrating works flawlessly)
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
This is free and unencumbered software released into the public domain.
|
||||||
|
|
||||||
|
Anyone is free to copy, modify, publish, use, compile, sell, or
|
||||||
|
distribute this software, either in source code form or as a compiled
|
||||||
|
binary, for any purpose, commercial or non-commercial, and by any
|
||||||
|
means.
|
||||||
|
|
||||||
|
In jurisdictions that recognize copyright laws, the author or authors
|
||||||
|
of this software dedicate any and all copyright interest in the
|
||||||
|
software to the public domain. We make this dedication for the benefit
|
||||||
|
of the public at large and to the detriment of our heirs and
|
||||||
|
successors. We intend this dedication to be an overt act of
|
||||||
|
relinquishment in perpetuity of all present and future rights to this
|
||||||
|
software under copyright law.
|
||||||
|
|
||||||
|
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 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.
|
||||||
|
|
||||||
|
For more information, please refer to <https://unlicense.org>
|
40
package.json
Normal file
40
package.json
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
{
|
||||||
|
"name": "ts-tmpl",
|
||||||
|
"version": "0.1.0",
|
||||||
|
"type": "module",
|
||||||
|
"description": "",
|
||||||
|
"keywords": [],
|
||||||
|
"author": "sam <sam@sleepycat.moe>",
|
||||||
|
"license": "",
|
||||||
|
"main": "dist/index.js",
|
||||||
|
"scripts": {
|
||||||
|
"dev": "concurrently \"pnpm watch:build\" \"pnpm watch:dev\"",
|
||||||
|
"build": "tsc -noEmit && swc src -d dist",
|
||||||
|
"watch:build": "swc src -w --out-dir dist",
|
||||||
|
"watch:dev": "nodemon --watch \"dist/**/*\" -e js ./dist/index.js",
|
||||||
|
"format": "prettier -w",
|
||||||
|
"typecheck": "tsc -noEmit",
|
||||||
|
"lint": "eslint src/",
|
||||||
|
"typeorm": "typeorm",
|
||||||
|
"migrate": "pnpm build && typeorm migration:run -d ./dist/db/index.js"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"dotenv": "^16.3.1",
|
||||||
|
"pg": "^8.11.1",
|
||||||
|
"reflect-metadata": "^0.1.13",
|
||||||
|
"tslog": "^4.8.2",
|
||||||
|
"typeorm": "^0.3.17"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@swc/cli": "^0.1.62",
|
||||||
|
"@swc/core": "^1.3.70",
|
||||||
|
"@typescript-eslint/eslint-plugin": "^6.1.0",
|
||||||
|
"@typescript-eslint/parser": "^6.1.0",
|
||||||
|
"chokidar": "^3.5.3",
|
||||||
|
"concurrently": "^8.2.0",
|
||||||
|
"eslint": "^8.45.0",
|
||||||
|
"nodemon": "^3.0.1",
|
||||||
|
"prettier": "^3.0.0",
|
||||||
|
"typescript": "5.1.6"
|
||||||
|
}
|
||||||
|
}
|
2251
pnpm-lock.yaml
Normal file
2251
pnpm-lock.yaml
Normal file
File diff suppressed because it is too large
Load diff
9
src/config.ts
Normal file
9
src/config.ts
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
import { config as dotenv } from "dotenv";
|
||||||
|
|
||||||
|
dotenv();
|
||||||
|
|
||||||
|
export const DATABASE_HOST = process.env.DATABASE_HOST || "localhost";
|
||||||
|
export const DATABASE_PORT = Number(process.env.DATABASE_PORT) || 5432;
|
||||||
|
export const DATABASE_USER = process.env.DATABASE_USER || "postgres";
|
||||||
|
export const DATABASE_PASS = process.env.DATABASE_PASS || "postgres";
|
||||||
|
export const DATABASE_NAME = process.env.DATABASE_NAME || "postgres";
|
0
src/db/entities/.keep
Normal file
0
src/db/entities/.keep
Normal file
12
src/db/entities/user.ts
Normal file
12
src/db/entities/user.ts
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
import { Entity, Column, PrimaryColumn, Index } from "typeorm";
|
||||||
|
|
||||||
|
@Entity()
|
||||||
|
@Index(["username", "host"], { unique: true })
|
||||||
|
export class User {
|
||||||
|
@PrimaryColumn("text")
|
||||||
|
id: string;
|
||||||
|
@Column("text", { nullable: false })
|
||||||
|
username: string;
|
||||||
|
@Column("text", { nullable: true })
|
||||||
|
host: string | null;
|
||||||
|
}
|
20
src/db/index.ts
Normal file
20
src/db/index.ts
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
import { DataSource } from "typeorm";
|
||||||
|
import * as config from "~/config.js";
|
||||||
|
|
||||||
|
// Entity types
|
||||||
|
import { User } from "~entities/user.js";
|
||||||
|
|
||||||
|
const TypeORMDataSource = new DataSource({
|
||||||
|
type: "postgres",
|
||||||
|
host: config.DATABASE_HOST,
|
||||||
|
port: config.DATABASE_PORT,
|
||||||
|
username: config.DATABASE_USER,
|
||||||
|
password: config.DATABASE_PASS,
|
||||||
|
database: config.DATABASE_NAME,
|
||||||
|
entities: [User], // Add entity types here
|
||||||
|
migrations: ["src/db/migrations/*.js"],
|
||||||
|
logging:
|
||||||
|
process.env.NODE_ENV === "production" ? ["error"] : ["query", "error"],
|
||||||
|
});
|
||||||
|
|
||||||
|
export default TypeORMDataSource;
|
0
src/db/migrations/.keep
Normal file
0
src/db/migrations/.keep
Normal file
3
src/index.ts
Normal file
3
src/index.ts
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
import start from "./start.js";
|
||||||
|
|
||||||
|
start();
|
5
src/log.ts
Normal file
5
src/log.ts
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
import { Logger, ILogObj } from "tslog";
|
||||||
|
|
||||||
|
const log: Logger<ILogObj> = new Logger();
|
||||||
|
|
||||||
|
export default log;
|
19
src/start.ts
Normal file
19
src/start.ts
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
import "reflect-metadata"; // Required for TypeORM
|
||||||
|
|
||||||
|
import TypeORMDataSource from "~/db/index.js";
|
||||||
|
import log from "~/log.js";
|
||||||
|
|
||||||
|
export default async function start() {
|
||||||
|
log.info("Initializing database");
|
||||||
|
await TypeORMDataSource.initialize();
|
||||||
|
|
||||||
|
const pendingMigrations = await TypeORMDataSource.showMigrations();
|
||||||
|
if (pendingMigrations) {
|
||||||
|
log.error(
|
||||||
|
"There are pending migrations, please run these with `pnpm migrate`.",
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// add your logic below this line
|
||||||
|
}
|
26
tsconfig.json
Normal file
26
tsconfig.json
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"target": "es2020",
|
||||||
|
"module": "es2020",
|
||||||
|
"moduleResolution": "node",
|
||||||
|
"rootDir": "./src",
|
||||||
|
"allowJs": true,
|
||||||
|
"checkJs": true,
|
||||||
|
"declaration": false,
|
||||||
|
"sourceMap": true,
|
||||||
|
"outDir": "./build",
|
||||||
|
"esModuleInterop": true,
|
||||||
|
"forceConsistentCasingInFileNames": true,
|
||||||
|
"experimentalDecorators": true,
|
||||||
|
"strictPropertyInitialization": false,
|
||||||
|
"strict": true,
|
||||||
|
"skipLibCheck": true,
|
||||||
|
"noImplicitAny": false,
|
||||||
|
"baseUrl": "./",
|
||||||
|
"paths": {
|
||||||
|
"~/*": ["./src/*"],
|
||||||
|
"~entities/*": ["./src/db/entities/*"]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"exclude": ["./dist/"]
|
||||||
|
}
|
Loading…
Reference in a new issue