chore: remove sqlite

pull/48/MERGE
vben 2024-06-30 22:28:35 +08:00
parent 9572d1a1c5
commit 692225cfff
18 changed files with 139 additions and 663 deletions

View File

@ -3,7 +3,7 @@
"collection": "@nestjs/schematics",
"sourceRoot": "src",
"compilerOptions": {
"assets": ["**/*.yml"],
"assets": ["**/*.yml", "**/*.json"],
"watchAssets": true,
"deleteOutDir": true
}

View File

@ -19,7 +19,6 @@
"@nestjs/jwt": "^10.2.0",
"@nestjs/passport": "^10.0.3",
"@nestjs/platform-express": "^10.3.10",
"@nestjs/typeorm": "^10.0.2",
"@types/js-yaml": "^4.0.9",
"bcryptjs": "^2.4.3",
"class-transformer": "^0.5.1",
@ -31,9 +30,7 @@
"passport-jwt": "^4.0.1",
"passport-local": "^1.0.0",
"reflect-metadata": "^0.2.2",
"rxjs": "^7.8.1",
"sqlite3": "^5.1.7",
"typeorm": "^0.3.20"
"rxjs": "^7.8.1"
},
"devDependencies": {
"@nestjs/cli": "^10.4.0",

View File

@ -1,23 +1,16 @@
import configuration from '@/config/index';
import { Module } from '@nestjs/common';
import { ConfigModule } from '@nestjs/config';
import { TypeOrmModule } from '@nestjs/typeorm';
import Joi from 'joi';
import { AuthModule } from './modules/auth/auth.module';
import { DatabaseModule } from './modules/database/database.module';
import { HealthModule } from './modules/health/health.module';
import { MenuModule } from './modules/menu/menu.module';
import { MockModule } from './modules/mock/mock.module';
import { UsersModule } from './modules/users/users.module';
@Module({
imports: [
TypeOrmModule.forRoot({
autoLoadEntities: true,
database: 'data/db.sqlite',
synchronize: true,
type: 'sqlite',
}),
ConfigModule.forRoot({
cache: true,
isGlobal: true,
@ -34,8 +27,8 @@ import { UsersModule } from './modules/users/users.module';
HealthModule,
AuthModule,
UsersModule,
DatabaseModule,
MenuModule,
MockModule,
],
})
export class AppModule {}

View File

@ -1,33 +1,20 @@
import { Column, Entity, PrimaryGeneratedColumn } from 'typeorm';
@Entity()
class UserEntity {
@PrimaryGeneratedColumn()
id: number;
/**
*
*/
@Column()
password: string;
/**
*
*/
@Column()
realName: string;
/**
*
*/
@Column('text', {
transformer: {
from: (value: string) => JSON.parse(value),
to: (value: string[]) => JSON.stringify(value),
},
})
roles: string[];
/**
*
*/
@Column({ unique: true })
username: string;
}

View File

@ -1,12 +0,0 @@
import { UserEntity } from '@/models/entity/user.entity';
import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { UsersModule } from '../users/users.module';
import { DatabaseService } from './database.service';
@Module({
imports: [UsersModule, TypeOrmModule.forFeature([UserEntity])],
providers: [DatabaseService],
})
export class DatabaseModule {}

View File

@ -1,19 +0,0 @@
import { Test, TestingModule } from '@nestjs/testing';
import { DatabaseService } from './database.service';
describe('databaseService', () => {
let service: DatabaseService;
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
providers: [DatabaseService],
}).compile();
service = module.get<DatabaseService>(DatabaseService);
});
it('should be defined', () => {
expect(service).toBeDefined();
});
});

View File

@ -1,40 +0,0 @@
import type { Repository } from 'typeorm';
import { UserEntity } from '@/models/entity/user.entity';
import { Injectable, type OnModuleInit } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { UsersService } from '../users/users.service';
@Injectable()
export class DatabaseService implements OnModuleInit {
constructor(
@InjectRepository(UserEntity)
private usersRepository: Repository<UserEntity>,
private userService: UsersService,
) {}
async onModuleInit() {
// data/db.sqlite会被git忽略方式数据库文件被提交到git
// 清空表,并初始化两条数据
await this.usersRepository.clear();
await this.userService.create({
id: 0,
password: '123456',
realName: 'Administrator',
roles: ['admin'],
username: 'vben',
});
await this.userService.create({
id: 1,
password: '123456',
realName: 'Jack',
roles: ['user'],
username: 'jack',
});
const count = await this.usersRepository.count();
console.log('Database has been initialized with seed data, count:', count);
}
}

View File

@ -0,0 +1 @@
{}

View File

@ -0,0 +1,13 @@
interface User {
id: number;
password: string;
realName: string;
roles: string[];
username: string;
}
interface MockDatabaseData {
users: User[];
}
export type { MockDatabaseData, User };

View File

@ -0,0 +1,9 @@
import { Module } from '@nestjs/common';
import { MockService } from './mock.service';
@Module({
exports: [MockService],
providers: [MockService],
})
export class MockModule {}

View File

@ -0,0 +1,71 @@
import type { MockDatabaseData } from './mock.interface';
import fs from 'node:fs';
import path from 'node:path';
import { Injectable, type OnModuleInit } from '@nestjs/common';
import bcrypt from 'bcryptjs';
@Injectable()
export class MockService implements OnModuleInit {
private data: MockDatabaseData;
private readonly filePath: string;
constructor() {
this.filePath = path.join(__dirname, '.', 'mock-db.json');
this.loadData();
}
private loadData() {
const fileData = fs.readFileSync(this.filePath, 'utf8');
this.data = JSON.parse(fileData);
}
private saveData() {
fs.writeFileSync(this.filePath, JSON.stringify(this.data, null, 2));
}
addItem(collection: string, item: any) {
this.data[collection].push(item);
this.saveData();
return item;
}
clearCollection(collection: string) {
this.data[collection] = [];
this.saveData();
return this.data[collection];
}
findAll(collection: string) {
return this.data[collection];
}
findOneById(collection: string, id: number) {
return this.data[collection].find((item) => item.id === id);
}
async onModuleInit() {
// 清空表,并初始化两条数据
await this.clearCollection('users');
// 密码哈希
const hashPassword = await bcrypt.hash('123456', 10);
await this.addItem('users', {
id: 0,
password: hashPassword,
realName: 'Vben',
roles: ['admin'],
username: 'vben',
});
await this.addItem('users', {
id: 1,
password: hashPassword,
realName: 'Jack',
roles: ['user'],
username: 'jack',
});
const count = await this.findAll('users').length;
console.log('Database has been initialized with seed data, count:', count);
}
}

View File

@ -1,12 +1,11 @@
import { UserEntity } from '@/models/entity/user.entity';
import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { MockModule } from '../mock/mock.module';
import { UsersService } from './users.service';
@Module({
exports: [UsersService],
imports: [TypeOrmModule.forFeature([UserEntity])],
imports: [MockModule],
providers: [UsersService],
})
export class UsersModule {}

View File

@ -1,28 +1,18 @@
import type { CreateUserDto } from '@/models/dto/user.dto';
import type { Repository } from 'typeorm';
import { UserEntity } from '@/models/entity/user.entity';
import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import bcrypt from 'bcryptjs';
import { MockService } from '../mock/mock.service';
@Injectable()
export class UsersService {
constructor(
@InjectRepository(UserEntity)
private usersRepository: Repository<UserEntity>,
) {}
async create(user: CreateUserDto): Promise<UserEntity> {
user.password = await bcrypt.hash(user.password, 10); // 密码哈希
return this.usersRepository.save(user);
}
constructor(private mockService: MockService) {}
/**
* Find user by username
* @param username
*/
async findOne(username: string): Promise<UserEntity | undefined> {
return await this.usersRepository.findOne({ where: { username } });
const allUsers = await this.mockService.findAll('users');
return allUsers.find((user) => user.username === username);
}
}

View File

@ -38,50 +38,3 @@ const tokenTheme = computed(() => {
</ConfigProvider>
</GlobalProvider>
</template>
<!-- <style>
:root {
--background: 0 0% 100%;
--foreground: 240 10% 3.9%;
--card: 0 0% 100%;
--card-foreground: 240 10% 3.9%;
--popover: 0 0% 100%;
--popover-foreground: 240 10% 3.9%;
--primary: 240 5.9% 10%;
--primary-foreground: 0 0% 98%;
--secondary: 240 4.8% 95.9%;
--secondary-foreground: 240 5.9% 10%;
--muted: 240 4.8% 95.9%;
--muted-foreground: 240 3.8% 46.1%;
--accent: 240 4.8% 95.9%;
--accent-foreground: 240 5.9% 10%;
--destructive: 0 84.2% 60.2%;
--destructive-foreground: 0 0% 98%;
--border: 240 5.9% 90%;
--input: 240 5.9% 90%;
--ring: 240 5.9% 10%;
--radius: 0.25rem;
}
.dark {
--background: 240 10% 3.9%;
--foreground: 0 0% 98%;
--card: 240 10% 3.9%;
--card-foreground: 0 0% 98%;
--popover: 240 10% 3.9%;
--popover-foreground: 0 0% 98%;
--primary: 0 0% 98%;
--primary-foreground: 240 5.9% 10%;
--secondary: 240 3.7% 15.9%;
--secondary-foreground: 0 0% 98%;
--muted: 240 3.7% 15.9%;
--muted-foreground: 240 5% 64.9%;
--accent: 240 3.7% 15.9%;
--accent-foreground: 0 0% 98%;
--destructive: 0 62.8% 30.6%;
--destructive-foreground: 0 0% 98%;
--border: 240 3.7% 15.9%;
--input: 240 3.7% 15.9%;
--ring: 240 4.9% 83.9%;
}
</style> -->

View File

@ -5,7 +5,6 @@
"words": [
"clsx",
"esno",
"typeorm",
"unref",
"taze",
"acmr",

View File

@ -12,6 +12,7 @@ const customConfig: Linter.FlatConfig[] = [
rules: {
'@typescript-eslint/no-extraneous-class': 'off',
'no-console': 'off',
'unicorn/prefer-module': 'off',
},
},
];

View File

@ -115,6 +115,7 @@ function useEcharts(chartRef: Ref<EchartsUIType>) {
});
return {
renderEcharts,
resize,
};
}

File diff suppressed because it is too large Load Diff