Skip to content

Commit

Permalink
feat(theme): create an standalone module
Browse files Browse the repository at this point in the history
  • Loading branch information
wibus-wee committed Aug 12, 2022
1 parent a902ac2 commit e93b102
Show file tree
Hide file tree
Showing 8 changed files with 138 additions and 70 deletions.
2 changes: 2 additions & 0 deletions src/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import { RolesGuard } from "./common/guard/roles.guard";
import { AuthModule } from "./modules/auth/auth.module";
import { BackupModule } from "./modules/backup/backup.module";
import { MarkdownModule } from "./modules/markdown/markdown.module";
import { ThemeModule } from './modules/theme/theme.module';

@Module({
imports: [
Expand All @@ -47,6 +48,7 @@ import { MarkdownModule } from "./modules/markdown/markdown.module";
InitModule,
BackupModule,
MarkdownModule,
ThemeModule,
],
controllers: [AppController],
providers: [
Expand Down
34 changes: 18 additions & 16 deletions src/bootstrap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,22 +27,24 @@ export async function bootstrap() {
const configService = app.get(ConfigsService);
const theme = configService.model.findOne({ name: "theme" });
const themeEnabled = theme?.value?.find((item) => item.enabled);
app.useStaticAssets({
root: join(THEME_DIR, themeEnabled?.name || "default", "public"),
prefix: "/public/",
});
app.setViewEngine({
engine: {
handlebars: require("handlebars"),
"art-template": require("art-template"),
ejs: require("ejs"),
},
templates: join(THEME_DIR, themeEnabled.name || "default"),
viewExt: themeEnabled.viewExt || "art-template",
defaultContext: {
dev: process.env.NODE_ENV === "development",
},
});
if (themeEnabled) {
app.useStaticAssets({
root: join(THEME_DIR, themeEnabled?.name || "default", "public"),
prefix: "/public/",
});
app.setViewEngine({
engine: {
handlebars: require("handlebars"),
"art-template": require("art-template"),
ejs: require("ejs"),
},
templates: join(THEME_DIR, themeEnabled.name || "default"),
viewExt: themeEnabled.viewExt || "art-template",
defaultContext: {
dev: process.env.NODE_ENV === "development",
},
});
}

const hosts = Origin.map((host) => new RegExp(host, "i"));

Expand Down
54 changes: 0 additions & 54 deletions src/modules/configs/configs.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,6 @@ import { BeAnObject } from "@typegoose/typegoose/lib/types";
import * as configDto from "./configs.dto";
import { validateSync, ValidatorOptions } from "class-validator";
import { ClassConstructor, plainToInstance } from "class-transformer";
import { THEME_DIR } from "~/constants/path.constant";
import { YAML } from "zx-cjs";
import { ThemeDto } from "./configs.dto";

const allOptionKeys: Set<ConfigsInterfaceKeys> = new Set();
const map: Record<string, any> = Object.entries(configDto).reduce(
Expand Down Expand Up @@ -226,57 +223,6 @@ export class ConfigsService {
return config;
}

CORE_VERSION = require('../../../package.json').version

private async turnOnThemeLibs(name: string) {
// 查找配置文件是否存在
const themeConfigFile = await fs
.readFile(`${THEME_DIR}/${name}/theme.yaml`, "utf8")
.catch(() => {
throw new BadRequestException(`主题 ${name} 配置文件不存在`);
})

const themeConfig = YAML.parse(themeConfigFile); // 解析配置文件

if (themeConfig.name !== name) { // 严格按照主题名称来配置,考虑大小写
throw new BadRequestException(`主题 ${name} 配置文件名称不匹配`);
}

// 检查主题是否适合当前后端的版本
if (
this.CORE_VERSION > themeConfig.support_min_version &&
this.CORE_VERSION < themeConfig.support_max_version
) {
// 提醒建议使用的版本
this.CORE_VERSION !== themeConfig.recommend_version && this.logger.warn(`主题 ${name} 建议使用版本 ${themeConfig.recommend_version}`)
} else {
throw new BadRequestException(`主题 ${name} 不支持当前版本`);
}

return {
themeConfig,
}
}

/**
* turnOnTheme 启动主题
*/
async turnOnTheme(name: string) {

if (fs.existsSync(path.join(THEME_DIR, name))) { // 检查主题是否存在

const { themeConfig } = await this.turnOnThemeLibs(name); // 获取主题配置
const theme: ThemeDto = { // 创建主题对象
name,
enable: true,
configs: themeConfig.configs ? themeConfig.configs : {},
viewExt: themeConfig.viewExt || 'art-template',
}
await this.patch('theme', theme); // 更新主题配置
return `主题 ${name} 启动成功`;
}
}

get getMaster() {
return this.userService.getMaster.bind(this.userService) as () => Promise<
LeanDocument<DocumentType<UserModel, BeAnObject>>
Expand Down
4 changes: 4 additions & 0 deletions src/modules/theme/theme.controller.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import { Controller } from '@nestjs/common';

@Controller('theme')
export class ThemeController {}
9 changes: 9 additions & 0 deletions src/modules/theme/theme.module.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { Module } from '@nestjs/common';
import { ThemeController } from './theme.controller';
import { ThemeService } from './theme.service';

@Module({
controllers: [ThemeController],
providers: [ThemeService]
})
export class ThemeModule {}
67 changes: 67 additions & 0 deletions src/modules/theme/theme.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import { BadRequestException, Injectable, Logger } from '@nestjs/common';
import { YAML } from 'zx-cjs';
import { THEME_DIR } from '~/constants/path.constant';
import { ThemeDto } from '../configs/configs.dto';
import { ConfigsService } from '../configs/configs.service';

@Injectable()
export class ThemeService {
private logger: Logger;
constructor(
private readonly configsService: ConfigsService,

) {
this.logger = new Logger(ThemeService.name)
}


CORE_VERSION = require('../../../package.json').version

private async turnOnThemeLibs(name: string) {
// 查找配置文件是否存在
const themeConfigFile = await fs
.readFile(`${THEME_DIR}/${name}/theme.yaml`, "utf8")
.catch(() => {
throw new BadRequestException(`主题 ${name} 配置文件不存在`);
})

const themeConfig = YAML.parse(themeConfigFile); // 解析配置文件

if (themeConfig.name !== name) { // 严格按照主题名称来配置,考虑大小写
throw new BadRequestException(`主题 ${name} 配置文件名称不匹配`);
}

// 检查主题是否适合当前后端的版本
if (
this.CORE_VERSION > themeConfig.support_min_version &&
this.CORE_VERSION < themeConfig.support_max_version
) {
// 提醒建议使用的版本
this.CORE_VERSION !== themeConfig.recommend_version && this.logger.warn(`主题 ${name} 建议使用版本 ${themeConfig.recommend_version}`)
} else {
throw new BadRequestException(`主题 ${name} 不支持当前版本`);
}

return {
themeConfig,
}
}

/**
* turnOnTheme 启动主题
*/
async turnOnTheme(name: string) {
if (fs.existsSync(path.join(THEME_DIR, name))) { // 检查主题是否存在

const { themeConfig } = await this.turnOnThemeLibs(name); // 获取主题配置
const theme: ThemeDto = { // 创建主题对象
name,
enable: true,
configs: themeConfig.configs ? themeConfig.configs : {},
viewExt: themeConfig.viewExt || 'art-template',
}
await this.configsService.patch('theme', theme); // 更新主题配置
return `主题 ${name} 启动成功`;
}
}
}
19 changes: 19 additions & 0 deletions test/src/modules/theme/theme.controller.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { Test, TestingModule } from '@nestjs/testing';
import { beforeEach, expect, describe, it } from "vitest";
import { ThemeController } from '~/modules/theme/theme.controller';

describe('ThemeController', () => {
let controller: ThemeController;

beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
controllers: [ThemeController],
}).compile();

controller = module.get<ThemeController>(ThemeController);
});

it('should be defined', () => {
expect(controller).toBeDefined();
});
});
19 changes: 19 additions & 0 deletions test/src/modules/theme/theme.service.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { Test, TestingModule } from '@nestjs/testing';
import { beforeEach, expect, describe, it } from "vitest";
import { ThemeService } from '~/modules/theme/theme.service';

describe('ThemeService', () => {
let service: ThemeService;

beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
providers: [ThemeService],
}).compile();

service = module.get<ThemeService>(ThemeService);
});

it('should be defined', () => {
expect(service).toBeDefined();
});
});

0 comments on commit e93b102

Please sign in to comment.