add modified_at
This commit is contained in:
parent
6dd1d4d83a
commit
e889f98530
@ -1,6 +1,11 @@
|
||||
import {Knex} from 'knex';
|
||||
|
||||
export async function up(knex:Knex) {
|
||||
await knex.schema.createTable("schema_migration",(b)=>{
|
||||
b.string("version");
|
||||
b.boolean("dirty");
|
||||
});
|
||||
|
||||
await knex.schema.createTable("users",(b)=>{
|
||||
b.string("username").primary().comment("user's login id");
|
||||
b.string("password_hash",64).notNullable();
|
||||
@ -15,6 +20,7 @@ export async function up(knex:Knex) {
|
||||
b.string("content_hash").nullable();
|
||||
b.json("additional").nullable();
|
||||
b.integer("created_at").notNullable();
|
||||
b.integer("modified_at").notNullable();
|
||||
b.integer("deleted_at");
|
||||
b.index("content_type","content_type_index");
|
||||
});
|
||||
@ -44,10 +50,5 @@ export async function up(knex:Knex) {
|
||||
};
|
||||
|
||||
export async function down(knex:Knex) {
|
||||
//throw new Error('Downward migrations are not supported. Restore from backup.');
|
||||
await knex.schema.dropTable("users");
|
||||
await knex.schema.dropTable("document");
|
||||
await knex.schema.dropTable("tags");
|
||||
await knex.schema.dropTable("document_tag_relation");
|
||||
await knex.schema.dropTable("permissions");
|
||||
throw new Error('Downward migrations are not supported. Restore from backup.');
|
||||
};
|
||||
|
8
plan.md
8
plan.md
@ -40,4 +40,10 @@
|
||||
- ~~hash~~
|
||||
- search
|
||||
- client tag add and delete
|
||||
- pagination
|
||||
- ~~pagination~~
|
||||
|
||||
add URL Render page 바꾸기
|
||||
add modified_time
|
||||
add support robots.txt
|
||||
|
||||
add vite ssr
|
3319
pnpm-lock.yaml
Normal file
3319
pnpm-lock.yaml
Normal file
File diff suppressed because it is too large
Load Diff
1068
src/client/pnpm-lock.yaml
Normal file
1068
src/client/pnpm-lock.yaml
Normal file
File diff suppressed because it is too large
Load Diff
@ -1,7 +1,7 @@
|
||||
import {Context, DefaultState, DefaultContext, Middleware, Next} from 'koa';
|
||||
import Router from 'koa-router';
|
||||
import {createHash} from 'crypto';
|
||||
import {promises} from 'fs'
|
||||
import {promises, Stats} from 'fs'
|
||||
import {extname} from 'path';
|
||||
import { DocumentBody } from '../model/mod';
|
||||
import path from 'path';
|
||||
@ -15,7 +15,7 @@ export interface ContentFile{
|
||||
readonly type: string;
|
||||
}
|
||||
export type ContentConstructOption = {
|
||||
hash: string
|
||||
hash: string,
|
||||
}
|
||||
type ContentFileConstructor = (new (path:string,option?:ContentConstructOption) => ContentFile)&{content_type:string};
|
||||
export const createDefaultClass = (type:string):ContentFileConstructor=>{
|
||||
@ -24,13 +24,16 @@ export const createDefaultClass = (type:string):ContentFileConstructor=>{
|
||||
//type = type;
|
||||
static content_type = type;
|
||||
protected hash: string| undefined;
|
||||
protected stat: Stats| undefined;
|
||||
|
||||
constructor(path:string,option?:ContentConstructOption){
|
||||
this.path = path;
|
||||
this.hash = option?.hash;
|
||||
this.stat = undefined;
|
||||
}
|
||||
async createDocumentBody(): Promise<DocumentBody> {
|
||||
const {base,dir, name} = path.parse(this.path);
|
||||
|
||||
const ret = {
|
||||
title : name,
|
||||
basepath : dir,
|
||||
@ -38,7 +41,8 @@ export const createDefaultClass = (type:string):ContentFileConstructor=>{
|
||||
content_type: cons.content_type,
|
||||
filename: base,
|
||||
tags: [],
|
||||
content_hash: this.hash ?? await this.getHash(),
|
||||
content_hash: await this.getHash(),
|
||||
modified_at: await this.getMtime(),
|
||||
} as DocumentBody;
|
||||
return ret;
|
||||
}
|
||||
@ -47,16 +51,21 @@ export const createDefaultClass = (type:string):ContentFileConstructor=>{
|
||||
}
|
||||
async getHash():Promise<string>{
|
||||
if(this.hash !== undefined) return this.hash;
|
||||
const stat = await promises.stat(this.path);
|
||||
this.stat = await promises.stat(this.path);
|
||||
const hash = createHash("sha512");
|
||||
hash.update(extname(this.path));
|
||||
hash.update(stat.mode.toString());
|
||||
hash.update(this.stat.mode.toString());
|
||||
//if(this.desc !== undefined)
|
||||
// hash.update(JSON.stringify(this.desc));
|
||||
hash.update(stat.size.toString());
|
||||
hash.update(this.stat.size.toString());
|
||||
this.hash = hash.digest("base64");
|
||||
return this.hash;
|
||||
}
|
||||
async getMtime():Promise<number>{
|
||||
if(this.stat !== undefined) return this.stat.mtimeMs;
|
||||
await this.getHash();
|
||||
return this.stat!.mtimeMs;
|
||||
}
|
||||
};
|
||||
return cons;
|
||||
}
|
||||
|
@ -7,6 +7,7 @@ export interface DocumentBody{
|
||||
content_type : string,
|
||||
basepath : string,
|
||||
filename : string,
|
||||
modified_at : number,
|
||||
content_hash : string,
|
||||
additional : JSONMap,
|
||||
tags : string[],//eager loading
|
||||
|
@ -16,6 +16,7 @@ import {createInterface as createReadlineInterface} from 'readline';
|
||||
import { DocumentAccessor, UserAccessor, TagAccessor } from './model/mod';
|
||||
import { createComicWatcher } from './diff/watcher/comic_watcher';
|
||||
import { getTagRounter } from './route/tags';
|
||||
|
||||
class ServerApplication{
|
||||
readonly userController: UserAccessor;
|
||||
readonly documentController: DocumentAccessor;
|
||||
|
Loading…
Reference in New Issue
Block a user