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