add tag api

This commit is contained in:
monoid 2022-06-29 21:14:39 +09:00
parent 8758e78f88
commit 253311bbd7
7 changed files with 103 additions and 25 deletions

View File

@ -1,10 +1,16 @@
import {Knex as k} from "knex";
export namespace Knex { export namespace Knex {
export const config = { export const config: {
development: k.Config,
production: k.Config
} = {
development: { development: {
client: 'sqlite3', client: 'sqlite3',
connection: { connection: {
filename: './devdb.sqlite3' filename: './devdb.sqlite3'
} },
debug: true,
}, },
production: { production: {
client: 'sqlite3', client: 'sqlite3',

View File

@ -4,10 +4,23 @@ import {Knex as KnexConfig} from './config';
import { get_setting } from './SettingConfig'; import { get_setting } from './SettingConfig';
export async function connectDB(){ export async function connectDB(){
const config = KnexConfig.config;
const env = get_setting().mode; const env = get_setting().mode;
const init_need = !existsSync(config[env].connection.filename); const config = KnexConfig.config[env];
const knex = Knex(config[env]); if(!config.connection){
throw new Error("connection options required.");
}
const connection = config.connection
if(typeof connection === "string"){
throw new Error("unknown connection options");
}
if(typeof connection === "function"){
throw new Error("connection provider not supported...");
}
if(!("filename" in connection) ){
throw new Error("sqlite3 config need");
}
const init_need = !existsSync(connection.filename);
const knex = Knex(config);
let tries = 0; let tries = 0;
for(;;){ for(;;){
try{ try{

View File

@ -3,7 +3,7 @@ import {Knex} from 'knex';
import {createKnexTagController} from './tag'; import {createKnexTagController} from './tag';
import { TagAccessor } from '../model/tag'; import { TagAccessor } from '../model/tag';
type DBTagContentRelation = { export type DBTagContentRelation = {
doc_id:number, doc_id:number,
tag_name:string tag_name:string
} }

View File

@ -1,5 +1,6 @@
import {Tag, TagAccessor} from '../model/tag'; import {Tag, TagAccessor, TagCount} from '../model/tag';
import {Knex} from 'knex'; import {Knex} from 'knex';
import {DBTagContentRelation} from './doc';
type DBTags = { type DBTags = {
name: string, name: string,
@ -11,7 +12,12 @@ class KnexTagAccessor implements TagAccessor{
constructor(knex:Knex){ constructor(knex:Knex){
this.knex = knex; this.knex = knex;
} }
async getTagAllList(onlyname?:boolean){ async getAllTagCount(): Promise<TagCount[]> {
const result = await this.knex<DBTagContentRelation>("doc_tag_relation").select("tag_name")
.count("*",{as:"occurs"}).groupBy<TagCount[]>("tag_name");
return result;
}
async getAllTagList(onlyname?:boolean){
onlyname = onlyname ?? false; onlyname = onlyname ?? false;
const t:DBTags[] = await this.knex.select(onlyname ? "*" : "name").from("tags") const t:DBTags[] = await this.knex.select(onlyname ? "*" : "name").from("tags")
return t; return t;

View File

@ -3,10 +3,16 @@ export interface Tag{
description?: string description?: string
} }
export interface TagAccessor{ export interface TagCount{
getTagAllList: (onlyname?:boolean)=> Promise<Tag[]> tagname: string;
getTagByName: (name:string)=>Promise<Tag|undefined>, occurs: number;
addTag: (tag:Tag)=>Promise<boolean>, }
delTag: (name:string) => Promise<boolean>,
updateTag: (name:string,tag:string) => Promise<boolean> export interface TagAccessor{
getAllTagList: (onlyname?:boolean)=> Promise<Tag[]>;
getAllTagCount(): Promise<TagCount[]>;
getTagByName: (name:string)=>Promise<Tag|undefined>;
addTag: (tag:Tag)=>Promise<boolean>;
delTag: (name:string) => Promise<boolean>;
updateTag: (name:string,tag:string) => Promise<boolean>;
} }

32
src/route/tags.ts Normal file
View File

@ -0,0 +1,32 @@
import {Context, Next} from "koa";
import Router,{RouterContext} from "koa-router";
import { TagAccessor } from "../model/tag";
import { sendError } from "./error_handler";
import { createPermissionCheckMiddleware as PerCheck, Permission } from "../permission/permission";
export function getTagRounter(tagController: TagAccessor){
let router = new Router();
router.get("/",PerCheck(Permission.QueryContent),
async (ctx: Context)=>{
if(ctx.query["withCount"]){
const c = await tagController.getAllTagCount();
ctx.body = c;
}
else {
const c = await tagController.getAllTagList();
ctx.body = c;
}
ctx.type = "json";
});
router.get("/:tag_name", PerCheck(Permission.QueryContent),
async (ctx: RouterContext)=>{
const tag_name = ctx.params["tag_name"];
const c = await tagController.getTagByName(tag_name);
if (!c){
sendError(404, "tags not found");
}
ctx.body = c;
ctx.type = "json";
});
return router;
}

View File

@ -7,25 +7,31 @@ import {DiffManager, createDiffRouter} from './diff/mod';
import { createReadStream, readFileSync } from 'fs'; import { createReadStream, readFileSync } from 'fs';
import getContentRouter from './route/contents'; import getContentRouter from './route/contents';
import { createKnexDocumentAccessor, createKnexUserController } from './db/mod'; import { createKnexDocumentAccessor, createKnexTagController, createKnexUserController } from './db/mod';
import bodyparser from 'koa-bodyparser'; import bodyparser from 'koa-bodyparser';
import {error_handler} from './route/error_handler'; import {error_handler} from './route/error_handler';
import {createUserMiddleWare, createLoginRouter, isAdminFirst, getAdmin} from './login'; import {createUserMiddleWare, createLoginRouter, isAdminFirst, getAdmin} from './login';
import {createInterface as createReadlineInterface} from 'readline'; import {createInterface as createReadlineInterface} from 'readline';
import { DocumentAccessor, UserAccessor } from './model/mod'; import { DocumentAccessor, UserAccessor, TagAccessor } from './model/mod';
import { createComicWatcher } from './diff/watcher/comic_watcher'; import { createComicWatcher } from './diff/watcher/comic_watcher';
import { getTagRounter } from './route/tags';
class ServerApplication{ class ServerApplication{
readonly userController: UserAccessor; readonly userController: UserAccessor;
readonly documentController: DocumentAccessor; readonly documentController: DocumentAccessor;
readonly diffManger; readonly tagController: TagAccessor;
readonly diffManger: DiffManager;
readonly app: Koa; readonly app: Koa;
private index_html:Buffer; private index_html:Buffer;
private constructor(userController: UserAccessor,documentController:DocumentAccessor){ private constructor(controller:{
this.userController = userController; userController: UserAccessor,
this.documentController = documentController; documentController:DocumentAccessor,
this.diffManger = new DiffManager(documentController); tagController: TagAccessor}){
this.userController = controller.userController;
this.documentController = controller.documentController;
this.tagController = controller.tagController;
this.diffManger = new DiffManager(this.documentController);
this.app = new Koa(); this.app = new Koa();
this.index_html = readFileSync("index.html"); this.index_html = readFileSync("index.html");
} }
@ -66,6 +72,11 @@ class ServerApplication{
const content_router = getContentRouter(this.documentController); const content_router = getContentRouter(this.documentController);
router.use('/api/doc',content_router.routes()); router.use('/api/doc',content_router.routes());
router.use('/api/doc',content_router.allowedMethods()); router.use('/api/doc',content_router.allowedMethods());
const tags_router = getTagRounter(this.tagController);
router.use("/api/tags",tags_router.routes());
router.use("/api/tags",tags_router.allowedMethods());
const login_router = createLoginRouter(this.userController); const login_router = createLoginRouter(this.userController);
router.use('/user',login_router.routes()); router.use('/user',login_router.routes());
router.use('/user',login_router.allowedMethods()); router.use('/user',login_router.allowedMethods());
@ -75,7 +86,8 @@ class ServerApplication{
let mm_count = 0; let mm_count = 0;
app.use(async (ctx,next)=>{ app.use(async (ctx,next)=>{
console.log(`==========================${mm_count++}`); console.log(`==========================${mm_count++}`);
const fromClient = ctx.state['user'].username === "" ? ctx.ip : ctx.state['user'].username; const ip = (ctx.get("X-Real-IP")) ?? ctx.ip;
const fromClient = ctx.state['user'].username === "" ? ip : ctx.state['user'].username;
console.log(`${fromClient} : ${ctx.method} ${ctx.url}`); console.log(`${fromClient} : ${ctx.method} ${ctx.url}`);
await next(); await next();
//console.log(`404`); //console.log(`404`);
@ -136,8 +148,11 @@ class ServerApplication{
const setting = get_setting(); const setting = get_setting();
let db = await connectDB(); let db = await connectDB();
const app = new ServerApplication(createKnexUserController(db) const app = new ServerApplication({
,createKnexDocumentAccessor(db)); userController:createKnexUserController(db),
documentController: createKnexDocumentAccessor(db),
tagController: createKnexTagController(db),
});
await app.setup(); await app.setup();
return app; return app;
} }