1.新建基础架构
①创建项目文件名,
mkdir ‘名称’ ->cd ‘文件名’ -> mkdir ‘src’->npm init
mkdir 'fileName'
cd 'fileName'
mkdir 'src'
npm init
在当前项目名目录下执行npm init,按照默认执行就会创建package.json.
之后执行 npm i @jest/globals @casl/ability bcrypt env-cmd jest mssql reflect-metadata ts-jest ts-node typeorm typeorm-naming-strategies
②创建配置文件tsconfig.json
执行 npx tsc --init
这里会生成默认的配置信息
下面这里是我的配置项:
{
“compilerOptions”: {
“lib”: [
“es5”,
“es6”
],
“target”: “es2017”,
“module”: “commonjs”,
“moduleResolution”: “node”,
“outDir”: “./lib”,
“rootDir”: “./src”,
“emitDecoratorMetadata”: true,
“experimentalDecorators”: true,
“allowSyntheticDefaultImports”: true,
“skipLibCheck”: true,
“sourceMap”: true,
“declaration”: true
},
“include”: [“src”],
“exclude”:[“node_modules”,“lib”]
}
③手动生成ormconfig.js和jest.config.js
New-Item -Path . -Name "jest.config.js" -ItemType "File"
New-Item -Path . -Name "ormconfig.js" -ItemType "File"
下面是执行后生成的目录和信息
执行
修改里面文件的内容
jest.config.js
添加
/** @type {import('ts-jest/dist/types').InitialOptionsTsJest} */ module.exports = { preset: 'ts-jest', testEnvironment: 'node', };
ormconfig.js
添加
const SnakeNamingStrategy =
require("typeorm-naming-strategies").SnakeNamingStrategy;
class CustomNamingStrategy extends SnakeNamingStrategy {
primaryKeyName(tableOrName, columnNames) {
let table = tableOrName instanceof Object ? tableOrName.name : tableOrName;
let columnsSnakeCase = columnNames.join("_");
return `PK_${table}_${columnsSnakeCase}`.toUpperCase();
}
}
module.exports = {
type: process.env.DB_TYPE,
host: process.env.DB_HOST,
port: parseInt(process.env.DB_PORT),
username: process.env.DB_USERNAME,
password: process.env.DB_PASSWORD,
database: process.env.DB_SCHEMA,
synchronize: false,
entities: ["src/entity/**/*.ts"],
migrations: ["src/migration/**/*.ts"],
subscribers: ["src/subscriber/**/*.ts"],
cli: {
entitiesDir: "src/entity",
migrationsDir: "src/migration",
subscribersDir: "src/subscriber",
},
options: {
trustServerCertificate: true,
cryptoCredentialsDetails: {
minVersion: 'TLSv1'
}
},
namingStrategy: new CustomNamingStrategy(),
};
④创建.env.development配置文件
New-Item -Path . -Name ".evn.development" -ItemType "File"
添加内容:
NODE_ENV=production
#Database Settings
DB_TYPE=your-db-type
DB_HOST=your-db-address
DB_PORT=your-db-port
DB_USERNAME=your-db-name
DB_PASSWORD=your-db-password
DB_SCHEMA=your-connect-db-name
#Password Hashing
SALT_ROUNDS=8
⑤创建忽略文件.gitignore
New-Item -Path . -Name ".gitignore" -ItemType "File"
添加内容:
.idea/ .vscode/ node_modules/ build/ tmp/ temp/
2.在src下创建entity文件夹,用于作为迁移内容
我这里用两个文件来说明:user和userRole来处理
①user.entity.ts
import {
Entity,
PrimaryGeneratedColumn,
Column,
CreateDateColumn,
DeleteDateColumn,
UpdateDateColumn,
ManyToOne,
JoinColumn,
Unique,
} from "typeorm";
import { UserRole } from "./user-role.entity";
@Unique("UQ_NAME", ["name"])
@Unique("UQ_EMAIL", ["email"])
@Entity("users")
export class User {
static readonly modelName = "User";
@PrimaryGeneratedColumn()
id: number;
@Column({ type: "varchar", length: 255 })
name: string;
@ManyToOne(() => UserRole, (userRole) => userRole.users, { eager: true })
@JoinColumn()
userRole: UserRole | undefined;
@Column()
userRoleId: number;
@Column({ type: "tinyint", default: 0 })
type: number;
@Column({ type: "tinyint", default: 0 })
branch: number;
@Column({ type: "varchar", length: "255", select: false }) // Select false prevent password showing up in repository api
password: string;
@Column({ type: "varchar", length: "255" })
email: string;
@Column({ type: "varchar", length: 255 })
token: string;
@Column({ type: "tinyint", default: 0 })
status: number;
@CreateDateColumn()
createdAt: Date;
@UpdateDateColumn()
updatedAt: Date;
@DeleteDateColumn({ nullable: true })
deletedAt: Date;
@Column({ type: "tinyint", default: 0 })
userLock:number;
}
②user-role.ts
import {
Entity,
PrimaryGeneratedColumn,
Column,
CreateDateColumn,
DeleteDateColumn,
UpdateDateColumn,
OneToMany,
} from "typeorm";
import { User } from "./user.entity";
@Entity("user_roles")
export class UserRole {
static readonly modelName = "UserRole";
@PrimaryGeneratedColumn()
id: number;
@Column({
type: "nvarchar",
length: 255,
})
name: string;
@Column({ type: "tinyint", default: 0 })
status: number;
@CreateDateColumn()
createdAt: Date;
@UpdateDateColumn()
updatedAt: Date;
@DeleteDateColumn()
deletedAt: Date;
//Relations
@OneToMany(() => User, (user) => user.userRole, { cascade: true })
users: User[] | undefined;
}
③在src下创建index.ts中导出这两个内容
export { User } from "./entity/user.entity"; export { UserRole } from "./entity/user-role.entity";
**
3.执行命令查看生成内容
①执行:npm i
②执行:env-cmd -f .env.development npm run typeorm migration:generate – -p -n YourMigrationName,
这里会生成执行可以执行的sql文件,并且会在migration中
③执行:env-cmd -f .env.development npm run typeorm migration:run – -t=false
这里会将表生成到db中
这时候基本就大体可以用了.
4.生成种子
这里的种子就是给数据库添加基础的数据
①在src下创建seed文件夹
创建
user-user-role.seed.ts文件
import { Seeder, Factory } from 'typeorm-seeding';
import { Connection } from 'typeorm';
import { User } from "../entity/user.entity";
import { UserRole } from "../entity/user-role.entity";
import { Action } from "../casl/action.enum";
import { hash } from "bcrypt";
export const UserSeed = {
name: "Admin",
password: "初始化的密码",
email: "你自己提供的邮箱",
token: "token",
status: 1,
};
export const UserRoleSeed = {
name: "Administrator",
status: 1,
};
export default class UserUserRoleSeed implements Seeder {
public async run(factory: Factory, connection: Connection): Promise<void> {
try {
const userRepository = connection.getRepository<User>("users");
const userRoleRepository = connection.getRepository<UserRole>("user_roles");
//init clean user and user role tables
const userData = await connection.getRepository("users").query(`DELETE FROM [users];`);
const userRoleData = await connection.getRepository("user_roles").query(`DELETE FROM [user_roles];`);
const userRoleSeed = userRoleRepository.create(UserRoleSeed);
const userSeed = userRepository.create(UserSeed);
userSeed.password = await hash(userSeed.password, +process.env.SALT_ROUNDS);
userRoleSeed.users = [userSeed];
const userRole = await connection.getRepository("user_roles").save(userRoleSeed);
console.log('User role seeding completed successfully');
} catch (error) {
console.error('Error during seeding:', error);
}
}
}
②.在src下创建run-seed.ts文件
import 'reflect-metadata';
import { createConnection, getConnectionOptions } from 'typeorm';
import { Seeder, factory } from 'typeorm-seeding';
import UserUserRoleSeed from './seed/user-user-role.seed';
//import AnotherSeed from './seed/AnotherSeed'; // 导入其他 Seeder
async function runSeeder() {
try {
const connectionOptions = await getConnectionOptions();
const connection = await createConnection(connectionOptions);
// 创建一个 Seeder 实例并运行
//const seeders: Seeder[] = [new UserUserRoleSeed(), new AnotherSeeder()];
const seeders: Seeder[] = [new UserUserRoleSeed()];
for (const seeder of seeders) {
await seeder.run(factory, connection);
}
await connection.close();
console.log('Seeding complete.');
} catch (error) {
console.error('Error running seeder:', error);
}
}
runSeeder();
这里就是用来执行初始化代码的内容
在package.json的scripts下添加一条执行命令:
"seed:run": "env-cmd -f .env.development ts-node src/run-seed.ts"
添加好之后,点击调试在命令窗口会出现
npm run seed:run
这条命令,可以查看到数据库生成了初始的数据了.