リファクタとデザイン調整とresolve #1
This commit is contained in:
parent
41f40dd2c2
commit
219b15d9e6
17 changed files with 404 additions and 64 deletions
16
migration/1599577510614-mode.ts
Normal file
16
migration/1599577510614-mode.ts
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
import {MigrationInterface, QueryRunner} from 'typeorm';
|
||||||
|
|
||||||
|
export class mode1599577510614 implements MigrationInterface {
|
||||||
|
name = 'mode1599577510614'
|
||||||
|
|
||||||
|
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query('CREATE TYPE "user_alertmode_enum" AS ENUM(\'note\', \'notification\', \'nothing\')');
|
||||||
|
await queryRunner.query('ALTER TABLE "user" ADD "alertMode" "user_alertmode_enum" NOT NULL DEFAULT \'note\'');
|
||||||
|
}
|
||||||
|
|
||||||
|
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||||
|
await queryRunner.query('ALTER TABLE "user" DROP COLUMN "alertMode"');
|
||||||
|
await queryRunner.query('DROP TYPE "user_alertmode_enum"');
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -21,6 +21,7 @@
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@types/koa-bodyparser": "^4.3.0",
|
"@types/koa-bodyparser": "^4.3.0",
|
||||||
"@types/koa-mount": "^4.0.0",
|
"@types/koa-mount": "^4.0.0",
|
||||||
|
"@types/koa-multer": "^1.0.0",
|
||||||
"@types/koa-static": "^4.0.1",
|
"@types/koa-static": "^4.0.1",
|
||||||
"@types/node-cron": "^2.0.3",
|
"@types/node-cron": "^2.0.3",
|
||||||
"@types/uuid": "^8.0.0",
|
"@types/uuid": "^8.0.0",
|
||||||
|
@ -29,6 +30,7 @@
|
||||||
"koa": "^2.13.0",
|
"koa": "^2.13.0",
|
||||||
"koa-bodyparser": "^4.3.0",
|
"koa-bodyparser": "^4.3.0",
|
||||||
"koa-mount": "^4.0.0",
|
"koa-mount": "^4.0.0",
|
||||||
|
"koa-multer": "^1.0.2",
|
||||||
"koa-router": "^9.1.0",
|
"koa-router": "^9.1.0",
|
||||||
"koa-session": "^6.0.0",
|
"koa-session": "^6.0.0",
|
||||||
"koa-static": "^5.0.0",
|
"koa-static": "^5.0.0",
|
||||||
|
|
|
@ -2,32 +2,15 @@ import { api } from '../services/misskey';
|
||||||
import { config } from '../config';
|
import { config } from '../config';
|
||||||
import { User } from '../models/entities/user';
|
import { User } from '../models/entities/user';
|
||||||
import { updateUser } from './users';
|
import { updateUser } from './users';
|
||||||
|
import { Score } from '../types/Score';
|
||||||
|
|
||||||
export const format = async (user: User): Promise<string> => {
|
export const format = (score: Score): string => `昨日のMisskeyの活動は
|
||||||
const miUser = await api<Record<string, number>>(user.host, 'users/show', { username: user.username }, user.token);
|
|
||||||
if (miUser.error) {
|
|
||||||
throw miUser.error;
|
|
||||||
}
|
|
||||||
const notesDelta = toSignedString(miUser.notesCount - user.prevNotesCount);
|
|
||||||
const followingDelta = toSignedString(miUser.followingCount - user.prevFollowingCount);
|
|
||||||
const followersDelta = toSignedString(miUser.followersCount - user.prevFollowersCount);
|
|
||||||
|
|
||||||
await updateUser(user.username, user.host, {
|
ノート: ${score.notesCount}(${score.notesDelta})
|
||||||
prevNotesCount: miUser.notesCount,
|
フォロー : ${score.followingCount}(${score.followingDelta})
|
||||||
prevFollowingCount: miUser.followingCount,
|
フォロワー :${score.followersCount}(${score.followersDelta})
|
||||||
prevFollowersCount: miUser.followersCount,
|
|
||||||
});
|
|
||||||
|
|
||||||
return `昨日のMisskeyの活動は
|
|
||||||
|
|
||||||
ノート: ${miUser.notesCount}(${notesDelta})
|
|
||||||
フォロー : ${miUser.followingCount}(${followingDelta})
|
|
||||||
フォロワー :${miUser.followersCount}(${followersDelta})
|
|
||||||
|
|
||||||
でした。
|
でした。
|
||||||
${config.url}
|
${config.url}
|
||||||
|
|
||||||
#misshaialert`;
|
#misshaialert`;
|
||||||
};
|
|
||||||
|
|
||||||
export const toSignedString = (num: number): string => num < 0 ? num.toString() : '+' + num;
|
|
19
src/functions/get-scores.ts
Normal file
19
src/functions/get-scores.ts
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
import { User } from '../models/entities/user';
|
||||||
|
import { Score } from '../types/Score';
|
||||||
|
import { api } from '../services/misskey';
|
||||||
|
import { toSignedString } from './to-signed-string';
|
||||||
|
|
||||||
|
export const getScores = async (user: User): Promise<Score> => {
|
||||||
|
const miUser = await api<Record<string, number>>(user.host, 'users/show', { username: user.username }, user.token);
|
||||||
|
if (miUser.error) {
|
||||||
|
throw miUser.error;
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
notesCount: miUser.notesCount,
|
||||||
|
followingCount: miUser.followingCount,
|
||||||
|
followersCount: miUser.followersCount,
|
||||||
|
notesDelta: toSignedString(miUser.notesCount - user.prevNotesCount),
|
||||||
|
followingDelta: toSignedString(miUser.followingCount - user.prevFollowingCount),
|
||||||
|
followersDelta: toSignedString(miUser.followersCount - user.prevFollowersCount),
|
||||||
|
};
|
||||||
|
};
|
1
src/functions/to-signed-string.ts
Normal file
1
src/functions/to-signed-string.ts
Normal file
|
@ -0,0 +1 @@
|
||||||
|
export const toSignedString = (num: number): string => num < 0 ? num.toString() : '+' + num;
|
16
src/functions/update-score.ts
Normal file
16
src/functions/update-score.ts
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
import { User } from '../models/entities/user';
|
||||||
|
import { api } from '../services/misskey';
|
||||||
|
import { updateUser } from './users';
|
||||||
|
|
||||||
|
export const updateScore = async (user: User): Promise<void> => {
|
||||||
|
const miUser = await api<Record<string, number>>(user.host, 'users/show', { username: user.username }, user.token);
|
||||||
|
if (miUser.error) {
|
||||||
|
throw miUser.error;
|
||||||
|
}
|
||||||
|
|
||||||
|
await updateUser(user.username, user.host, {
|
||||||
|
prevNotesCount: miUser.notesCount,
|
||||||
|
prevFollowingCount: miUser.followingCount,
|
||||||
|
prevFollowersCount: miUser.followersCount,
|
||||||
|
});
|
||||||
|
};
|
|
@ -1,4 +1,5 @@
|
||||||
import { Entity, Column, PrimaryGeneratedColumn, Index } from 'typeorm';
|
import { Entity, Column, PrimaryGeneratedColumn, Index } from 'typeorm';
|
||||||
|
import { AlertMode, alertModes } from '../../types/AlertMode';
|
||||||
|
|
||||||
@Entity()
|
@Entity()
|
||||||
@Index([ 'username', 'host' ], { unique: true })
|
@Index([ 'username', 'host' ], { unique: true })
|
||||||
|
@ -44,4 +45,11 @@ export class User {
|
||||||
default: 0,
|
default: 0,
|
||||||
})
|
})
|
||||||
public prevFollowersCount: number;
|
public prevFollowersCount: number;
|
||||||
|
|
||||||
|
@Column({
|
||||||
|
type: 'enum',
|
||||||
|
enum: alertModes,
|
||||||
|
default: 'note'
|
||||||
|
})
|
||||||
|
public alertMode: AlertMode;
|
||||||
}
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
import { Context } from 'koa';
|
import { Context } from 'koa';
|
||||||
|
|
||||||
export const die = (ctx: Context, error: string, status = 400): Promise<void> => {
|
export const die = (ctx: Context, error = '問題が発生しました。お手数ですが、最初からやり直してください。', status = 400): Promise<void> => {
|
||||||
ctx.status = status;
|
ctx.status = status;
|
||||||
return ctx.render('error', { error });
|
return ctx.render('error', { error });
|
||||||
};
|
};
|
||||||
|
|
|
@ -6,8 +6,11 @@ import crypto from 'crypto';
|
||||||
import { die } from './die';
|
import { die } from './die';
|
||||||
import { v4 as uuid } from 'uuid';
|
import { v4 as uuid } from 'uuid';
|
||||||
import { config } from '../config';
|
import { config } from '../config';
|
||||||
import { upsertUser, getUser, getUserCount, updateUser, updateUsersMisshaiToken, getUserByMisshaiToken } from '../functions/users';
|
import { upsertUser, getUser, getUserCount, updateUser, updateUsersMisshaiToken, getUserByMisshaiToken, deleteUser } from '../functions/users';
|
||||||
import { api } from '../services/misskey';
|
import { api } from '../services/misskey';
|
||||||
|
import { getScores } from '../functions/get-scores';
|
||||||
|
import { AlertMode, alertModes } from '../types/AlertMode';
|
||||||
|
import { Users } from '../models';
|
||||||
|
|
||||||
export const router = new Router<DefaultState, Context>();
|
export const router = new Router<DefaultState, Context>();
|
||||||
|
|
||||||
|
@ -29,7 +32,7 @@ const login = async (ctx: Context, user: Record<string, unknown>, host: string,
|
||||||
const u = await getUser(user.username as string, host);
|
const u = await getUser(user.username as string, host);
|
||||||
|
|
||||||
if (!u) {
|
if (!u) {
|
||||||
await die(ctx, '問題が発生しました。お手数ですが、最初からやり直してください。');
|
await die(ctx);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -58,7 +61,9 @@ router.get('/', async ctx => {
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
await ctx.render('mypage', {
|
await ctx.render('mypage', {
|
||||||
user
|
user,
|
||||||
|
usersCount: await getUserCount(),
|
||||||
|
score: await getScores(user),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -76,7 +81,7 @@ router.get('/login', async ctx => {
|
||||||
host = meta.uri.replace(/^https?:\/\//, '');
|
host = meta.uri.replace(/^https?:\/\//, '');
|
||||||
const name = 'みす廃あらーと';
|
const name = 'みす廃あらーと';
|
||||||
const description = 'ついついノートしすぎていませんか?';
|
const description = 'ついついノートしすぎていませんか?';
|
||||||
const permission = [ 'write:notes' ];
|
const permission = [ 'write:notes', 'write:notifications' ];
|
||||||
|
|
||||||
if (meta.features.miauth) {
|
if (meta.features.miauth) {
|
||||||
// Use MiAuth
|
// Use MiAuth
|
||||||
|
@ -106,6 +111,42 @@ router.get('/login', async ctx => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
router.get('/logout', async ctx => {
|
||||||
|
const token = ctx.cookies.get('token');
|
||||||
|
if (!token) {
|
||||||
|
await die(ctx, 'ログインしていません');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ctx.cookies.set('token', '');
|
||||||
|
await ctx.render('welcome', {
|
||||||
|
usersCount: await getUserCount(),
|
||||||
|
welcomeMessage: 'ログアウトしました。',
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
router.get('/optout', async ctx => {
|
||||||
|
const token = ctx.cookies.get('token');
|
||||||
|
if (!token) {
|
||||||
|
await die(ctx, 'ログインしていません');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ctx.cookies.set('token', '');
|
||||||
|
|
||||||
|
const u = await getUserByMisshaiToken(token);
|
||||||
|
|
||||||
|
if (!u) {
|
||||||
|
await die(ctx);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
await deleteUser(u.username, u.host);
|
||||||
|
|
||||||
|
await ctx.render('welcome', {
|
||||||
|
usersCount: await getUserCount(),
|
||||||
|
welcomeMessage: '連携を解除しました。',
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
router.get('/terms', async ctx => {
|
router.get('/terms', async ctx => {
|
||||||
await ctx.render('term');
|
await ctx.render('term');
|
||||||
});
|
});
|
||||||
|
@ -127,7 +168,7 @@ router.get('/miauth', async ctx => {
|
||||||
const host = sessionHostCache[session];
|
const host = sessionHostCache[session];
|
||||||
delete sessionHostCache[session];
|
delete sessionHostCache[session];
|
||||||
if (!host) {
|
if (!host) {
|
||||||
await die(ctx, '問題が発生しました。お手数ですが、最初からやり直してください。');
|
await die(ctx);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -135,7 +176,7 @@ router.get('/miauth', async ctx => {
|
||||||
const { token, user } = (await axios.post(url)).data;
|
const { token, user } = (await axios.post(url)).data;
|
||||||
|
|
||||||
if (!token || !user) {
|
if (!token || !user) {
|
||||||
await die(ctx, '問題が発生しました。お手数ですが、最初からやり直してください。');
|
await die(ctx);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -152,13 +193,13 @@ router.get('/legacy-auth', async ctx => {
|
||||||
const host = sessionHostCache[token];
|
const host = sessionHostCache[token];
|
||||||
delete sessionHostCache[token];
|
delete sessionHostCache[token];
|
||||||
if (!host) {
|
if (!host) {
|
||||||
await die(ctx, '問題が発生しました。お手数ですが、最初からやり直してください。');
|
await die(ctx);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const appSecret = tokenSecretCache[token];
|
const appSecret = tokenSecretCache[token];
|
||||||
delete tokenSecretCache[token];
|
delete tokenSecretCache[token];
|
||||||
if (!appSecret) {
|
if (!appSecret) {
|
||||||
await die(ctx, '問題が発生しました。お手数ですが、最初からやり直してください。');
|
await die(ctx);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -172,6 +213,32 @@ router.get('/legacy-auth', async ctx => {
|
||||||
await login(ctx, user, host, i);
|
await login(ctx, user, host, i);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
router.post('/update-settings', async ctx => {
|
||||||
|
const mode = ctx.request.body.alertMode as AlertMode;
|
||||||
|
// 一応型チェック
|
||||||
|
if (!alertModes.includes(mode)) {
|
||||||
|
await die(ctx, `${mode} is an invalid value`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const token = ctx.cookies.get('token');
|
||||||
|
if (!token) {
|
||||||
|
await die(ctx, 'ログインしていません');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const u = await getUserByMisshaiToken(token);
|
||||||
|
|
||||||
|
if (!u) {
|
||||||
|
await die(ctx);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
await Users.update(u.id, { alertMode: mode });
|
||||||
|
|
||||||
|
ctx.redirect('/');
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
// Return 404 for other pages
|
// Return 404 for other pages
|
||||||
router.all('(.*)', async ctx => {
|
router.all('(.*)', async ctx => {
|
||||||
|
|
|
@ -5,24 +5,38 @@ import { Users } from '../models';
|
||||||
import { api } from './misskey';
|
import { api } from './misskey';
|
||||||
import { format } from '../functions/format';
|
import { format } from '../functions/format';
|
||||||
import { deleteUser } from '../functions/users';
|
import { deleteUser } from '../functions/users';
|
||||||
|
import { updateScore } from '../functions/update-score';
|
||||||
|
import { getScores } from '../functions/get-scores';
|
||||||
|
|
||||||
export default (): void => {
|
export default (): void => {
|
||||||
cron.schedule('0 0 0 * * *', async () => {
|
cron.schedule('50 45 0 * * *', async () => {
|
||||||
const users = await Users.createQueryBuilder()
|
const users = await Users.createQueryBuilder()
|
||||||
.select()
|
.select()
|
||||||
.getMany();
|
.getMany();
|
||||||
for (const user of users) {
|
for (const user of users) {
|
||||||
try {
|
try {
|
||||||
const text = await format(user);
|
await updateScore(user);
|
||||||
|
const text = format(await getScores(user));
|
||||||
|
|
||||||
const res = await api<Record<string, unknown>>(user.host, 'notes/create', {
|
if (user.alertMode === 'note') {
|
||||||
text,
|
const res = await api<Record<string, unknown>>(user.host, 'notes/create', {
|
||||||
visibility: 'home'
|
text,
|
||||||
}, user.token);
|
visibility: 'specified'
|
||||||
if (res.error) {
|
}, user.token);
|
||||||
throw res.error;
|
if (res.error) {
|
||||||
|
throw res.error;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
} else if (user.alertMode === 'notification') {
|
||||||
|
const res = await api(user.host, 'notifications/create', {
|
||||||
|
header: 'みす廃あらーと',
|
||||||
|
icon: 'https://i.imgur.com/B991yTl.png',
|
||||||
|
body: text,
|
||||||
|
}, user.token);
|
||||||
|
if (res.error) {
|
||||||
|
throw res.error;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (e.code === 'NO_SUCH_USER' || e.code === 'AUTHENTICATION_FAILED') {
|
if (e.code === 'NO_SUCH_USER' || e.code === 'AUTHENTICATION_FAILED') {
|
||||||
// ユーザーが削除されている場合、レコードからも消してとりやめ
|
// ユーザーが削除されている場合、レコードからも消してとりやめ
|
||||||
|
@ -32,7 +46,8 @@ export default (): void => {
|
||||||
console.error(e);
|
console.error(e);
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
await delay(3000);
|
if (user.alertMode === 'note')
|
||||||
|
await delay(3000);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
7
src/types/AlertMode.ts
Normal file
7
src/types/AlertMode.ts
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
export const alertModes = [
|
||||||
|
'note',
|
||||||
|
'notification',
|
||||||
|
'nothing'
|
||||||
|
] as const;
|
||||||
|
|
||||||
|
export type AlertMode = typeof alertModes[number];
|
9
src/types/Score.ts
Normal file
9
src/types/Score.ts
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
|
||||||
|
export type Score = {
|
||||||
|
notesCount: number;
|
||||||
|
followingCount: number;
|
||||||
|
followersCount: number;
|
||||||
|
notesDelta: string;
|
||||||
|
followingDelta: string;
|
||||||
|
followersDelta: string;
|
||||||
|
};
|
|
@ -1,3 +1,25 @@
|
||||||
mixin exta()
|
mixin exta()
|
||||||
a(href=attributes.href target="_blank" rel="noopener noreferrer")
|
a(href=attributes.href target="_blank" rel="noopener noreferrer")
|
||||||
block
|
block
|
||||||
|
|
||||||
|
mixin serverInfo()
|
||||||
|
.xd-card
|
||||||
|
.header
|
||||||
|
h1.title
|
||||||
|
i.fas.fa-info-circle
|
||||||
|
| サービスの情報
|
||||||
|
.body
|
||||||
|
dl
|
||||||
|
dt
|
||||||
|
i.fas.fa-users
|
||||||
|
| 登録者数
|
||||||
|
dd !{usersCount} 人
|
||||||
|
dt
|
||||||
|
| 総ノート数
|
||||||
|
dd (coming soon)
|
||||||
|
dt
|
||||||
|
| 総フォロー数
|
||||||
|
dd (coming soon)
|
||||||
|
dt
|
||||||
|
| 総フォロワー数
|
||||||
|
dd (coming soon)
|
|
@ -1,6 +1,63 @@
|
||||||
extends _base
|
extends _base
|
||||||
|
|
||||||
block content
|
block content
|
||||||
section
|
h2 マイページ
|
||||||
h2 マイページ
|
p おかえりなさい、@!{ user.username }@!{ user.host } さん。
|
||||||
p おかえりなさい、@!{ user.username }@!{ user.host } さん。
|
|
||||||
|
section#scores
|
||||||
|
.xd-cards.center
|
||||||
|
+serverInfo()
|
||||||
|
.xd-card
|
||||||
|
.header
|
||||||
|
h1.title
|
||||||
|
i.fas.fa-chart-area
|
||||||
|
| あなたの廃人度は…
|
||||||
|
.body
|
||||||
|
table
|
||||||
|
thead
|
||||||
|
tr
|
||||||
|
th 内容
|
||||||
|
th スコア
|
||||||
|
th 前日比
|
||||||
|
tbody
|
||||||
|
tr
|
||||||
|
td ノート
|
||||||
|
td !{score.notesCount}
|
||||||
|
td !{score.notesDelta}
|
||||||
|
tr
|
||||||
|
td フォロー
|
||||||
|
td !{score.followingCount}
|
||||||
|
td !{score.followingDelta}
|
||||||
|
tr
|
||||||
|
td フォロワー
|
||||||
|
td !{score.followersCount}
|
||||||
|
td !{score.followersDelta}
|
||||||
|
|
||||||
|
section.xd-card#settings
|
||||||
|
.header
|
||||||
|
h1.title
|
||||||
|
i.fas.fa-cog
|
||||||
|
| 設定
|
||||||
|
.body
|
||||||
|
form(method="post", action="/update-settings")
|
||||||
|
p: label スコア通知方法:
|
||||||
|
select(name="alertMode")
|
||||||
|
option(value="note", selected=user.alertMode === 'note') 自動的にノートを投稿 (標準)
|
||||||
|
option(value="notification", selected=user.alertMode === 'notification') Misskey に通知
|
||||||
|
option(value="nothing", selected=user.alertMode === 'nothing') 通知しない
|
||||||
|
p: label タイムゾーン:(coming soon)
|
||||||
|
button.primary(type="submit") 保存
|
||||||
|
.body
|
||||||
|
div.mb-2: a.xd-button.danger#logout(href="/logout") ログアウト
|
||||||
|
div: a.xd-button.danger#optout(href="/optout") アカウント連携を解除する
|
||||||
|
|
||||||
|
block script
|
||||||
|
script.
|
||||||
|
document.getElementById("optout").addEventListener("click", (e) => {
|
||||||
|
if (!confirm('連携を解除すると、統計情報などのデータが削除されてしまい、以後アラート機能をご利用いただけなくなります。この操作は変更できません。\n\nそれでもなお、連携を解除しますか?'))
|
||||||
|
e.preventDefault();
|
||||||
|
});
|
||||||
|
document.getElementById("logout").addEventListener("click", (e) => {
|
||||||
|
if (!confirm('ログアウトしますか?'))
|
||||||
|
e.preventDefault();
|
||||||
|
});
|
|
@ -20,17 +20,7 @@ block content
|
||||||
|
|
||||||
section
|
section
|
||||||
.xd-cards.center
|
.xd-cards.center
|
||||||
.xd-card
|
+serverInfo()
|
||||||
.header
|
|
||||||
h1.title
|
|
||||||
i.fas.fa-info-circle
|
|
||||||
| 情報
|
|
||||||
.body
|
|
||||||
dl
|
|
||||||
dt
|
|
||||||
i.fas.fa-users
|
|
||||||
| 登録者数
|
|
||||||
dd !{usersCount} 人
|
|
||||||
.xd-card
|
.xd-card
|
||||||
.header
|
.header
|
||||||
h1.title
|
h1.title
|
||||||
|
|
|
@ -18,6 +18,9 @@ $card-header: $bg-pale-1;
|
||||||
$card-footer: $bg-pale-1;
|
$card-footer: $bg-pale-1;
|
||||||
$card-fg: $fg;
|
$card-fg: $fg;
|
||||||
$divider: rgba($fg, 0.25);
|
$divider: rgba($fg, 0.25);
|
||||||
|
$table-bg-header: $md-grey-300;
|
||||||
|
$table-bg-odd: $md-grey-100;
|
||||||
|
$table-bg-even: white;
|
||||||
$barSize: 64px;
|
$barSize: 64px;
|
||||||
|
|
||||||
* {
|
* {
|
||||||
|
@ -144,6 +147,18 @@ button, .xd-button {
|
||||||
background: $primary-dark;
|
background: $primary-dark;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.danger {
|
||||||
|
background: $md-red-700;
|
||||||
|
color: $md-white;
|
||||||
|
border-color: $md-red-900;
|
||||||
|
&:hover {
|
||||||
|
background: $md-red-500;
|
||||||
|
}
|
||||||
|
&:active {
|
||||||
|
background: $md-red-800;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ul, ol {
|
// ul, ol {
|
||||||
|
@ -161,6 +176,27 @@ a, .link {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
table {
|
||||||
|
border: 1px solid $divider;
|
||||||
|
border-radius: 2px;
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
> thead {
|
||||||
|
background: $table-bg-header;
|
||||||
|
margin-bottom: 2px;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
> tbody > tr {
|
||||||
|
background: $table-bg-even;
|
||||||
|
&:nth-child(odd) {
|
||||||
|
background: $table-bg-odd;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
th, td {
|
||||||
|
padding: 4px 8px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
code {
|
code {
|
||||||
border-radius: 2px;
|
border-radius: 2px;
|
||||||
color: #0f0;
|
color: #0f0;
|
||||||
|
@ -233,6 +269,9 @@ code {
|
||||||
}
|
}
|
||||||
@media screen and (max-width: 640px) {
|
@media screen and (max-width: 640px) {
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
|
> .xd-card {
|
||||||
|
margin: 8px 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&.wrap {
|
&.wrap {
|
||||||
|
|
103
yarn.lock
103
yarn.lock
|
@ -158,6 +158,13 @@
|
||||||
dependencies:
|
dependencies:
|
||||||
"@types/koa" "*"
|
"@types/koa" "*"
|
||||||
|
|
||||||
|
"@types/koa-multer@^1.0.0":
|
||||||
|
version "1.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/koa-multer/-/koa-multer-1.0.0.tgz#f449f399ac3f80c05753452f000e8694ceec4249"
|
||||||
|
integrity sha512-1Fh/tu7nj6/QefLcTuHUUeeZ5J9zqOQbDfTLPG8sh9ni7eioDJ1jOYuP95k3/uo0ApSiUOZ5c2fEXTqiEnPZ+w==
|
||||||
|
dependencies:
|
||||||
|
"@types/koa" "*"
|
||||||
|
|
||||||
"@types/koa-router@^7.4.1":
|
"@types/koa-router@^7.4.1":
|
||||||
version "7.4.1"
|
version "7.4.1"
|
||||||
resolved "https://registry.yarnpkg.com/@types/koa-router/-/koa-router-7.4.1.tgz#3702a4cabe4558cc4eec70d5574acc04beecff7c"
|
resolved "https://registry.yarnpkg.com/@types/koa-router/-/koa-router-7.4.1.tgz#3702a4cabe4558cc4eec70d5574acc04beecff7c"
|
||||||
|
@ -416,6 +423,11 @@ app-root-path@^3.0.0:
|
||||||
resolved "https://registry.yarnpkg.com/app-root-path/-/app-root-path-3.0.0.tgz#210b6f43873227e18a4b810a032283311555d5ad"
|
resolved "https://registry.yarnpkg.com/app-root-path/-/app-root-path-3.0.0.tgz#210b6f43873227e18a4b810a032283311555d5ad"
|
||||||
integrity sha512-qMcx+Gy2UZynHjOHOIXPNvpf+9cjvk3cWrBBK7zg4gH9+clobJRb9NGzcT7mQTcV/6Gm/1WelUtqxVXnNlrwcw==
|
integrity sha512-qMcx+Gy2UZynHjOHOIXPNvpf+9cjvk3cWrBBK7zg4gH9+clobJRb9NGzcT7mQTcV/6Gm/1WelUtqxVXnNlrwcw==
|
||||||
|
|
||||||
|
append-field@^0.1.0:
|
||||||
|
version "0.1.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/append-field/-/append-field-0.1.0.tgz#6ddc58fa083c7bc545d3c5995b2830cc2366d44a"
|
||||||
|
integrity sha1-bdxY+gg8e8VF08WZWygwzCNm1Eo=
|
||||||
|
|
||||||
argparse@^1.0.7:
|
argparse@^1.0.7:
|
||||||
version "1.0.10"
|
version "1.0.10"
|
||||||
resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911"
|
resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911"
|
||||||
|
@ -506,6 +518,11 @@ braces@~3.0.2:
|
||||||
dependencies:
|
dependencies:
|
||||||
fill-range "^7.0.1"
|
fill-range "^7.0.1"
|
||||||
|
|
||||||
|
buffer-from@^1.0.0:
|
||||||
|
version "1.1.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef"
|
||||||
|
integrity sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==
|
||||||
|
|
||||||
buffer-writer@2.0.0:
|
buffer-writer@2.0.0:
|
||||||
version "2.0.0"
|
version "2.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/buffer-writer/-/buffer-writer-2.0.0.tgz#ce7eb81a38f7829db09c873f2fbb792c0c98ec04"
|
resolved "https://registry.yarnpkg.com/buffer-writer/-/buffer-writer-2.0.0.tgz#ce7eb81a38f7829db09c873f2fbb792c0c98ec04"
|
||||||
|
@ -519,6 +536,14 @@ buffer@^5.1.0:
|
||||||
base64-js "^1.0.2"
|
base64-js "^1.0.2"
|
||||||
ieee754 "^1.1.4"
|
ieee754 "^1.1.4"
|
||||||
|
|
||||||
|
busboy@^0.2.11:
|
||||||
|
version "0.2.14"
|
||||||
|
resolved "https://registry.yarnpkg.com/busboy/-/busboy-0.2.14.tgz#6c2a622efcf47c57bbbe1e2a9c37ad36c7925453"
|
||||||
|
integrity sha1-bCpiLvz0fFe7vh4qnDetNseSVFM=
|
||||||
|
dependencies:
|
||||||
|
dicer "0.2.5"
|
||||||
|
readable-stream "1.1.x"
|
||||||
|
|
||||||
bytes@3.1.0:
|
bytes@3.1.0:
|
||||||
version "3.1.0"
|
version "3.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.0.tgz#f6cf7933a360e0588fa9fde85651cdc7f805d1f6"
|
resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.0.tgz#f6cf7933a360e0588fa9fde85651cdc7f805d1f6"
|
||||||
|
@ -709,6 +734,16 @@ concat-map@0.0.1:
|
||||||
resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
|
resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
|
||||||
integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=
|
integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=
|
||||||
|
|
||||||
|
concat-stream@^1.5.0:
|
||||||
|
version "1.6.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.2.tgz#904bdf194cd3122fc675c77fc4ac3d4ff0fd1a34"
|
||||||
|
integrity sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==
|
||||||
|
dependencies:
|
||||||
|
buffer-from "^1.0.0"
|
||||||
|
inherits "^2.0.3"
|
||||||
|
readable-stream "^2.2.2"
|
||||||
|
typedarray "^0.0.6"
|
||||||
|
|
||||||
condense-newlines@^0.2.1:
|
condense-newlines@^0.2.1:
|
||||||
version "0.2.1"
|
version "0.2.1"
|
||||||
resolved "https://registry.yarnpkg.com/condense-newlines/-/condense-newlines-0.2.1.tgz#3de985553139475d32502c83b02f60684d24c55f"
|
resolved "https://registry.yarnpkg.com/condense-newlines/-/condense-newlines-0.2.1.tgz#3de985553139475d32502c83b02f60684d24c55f"
|
||||||
|
@ -919,6 +954,14 @@ destroy@^1.0.4:
|
||||||
resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80"
|
resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80"
|
||||||
integrity sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=
|
integrity sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=
|
||||||
|
|
||||||
|
dicer@0.2.5:
|
||||||
|
version "0.2.5"
|
||||||
|
resolved "https://registry.yarnpkg.com/dicer/-/dicer-0.2.5.tgz#5996c086bb33218c812c090bddc09cd12facb70f"
|
||||||
|
integrity sha1-WZbAhrszIYyBLAkL3cCc0S+stw8=
|
||||||
|
dependencies:
|
||||||
|
readable-stream "1.1.x"
|
||||||
|
streamsearch "0.1.2"
|
||||||
|
|
||||||
diff@^3.1.0:
|
diff@^3.1.0:
|
||||||
version "3.5.0"
|
version "3.5.0"
|
||||||
resolved "https://registry.yarnpkg.com/diff/-/diff-3.5.0.tgz#800c0dd1e0a8bfbc95835c202ad220fe317e5a12"
|
resolved "https://registry.yarnpkg.com/diff/-/diff-3.5.0.tgz#800c0dd1e0a8bfbc95835c202ad220fe317e5a12"
|
||||||
|
@ -1506,7 +1549,7 @@ inflight@^1.0.4:
|
||||||
once "^1.3.0"
|
once "^1.3.0"
|
||||||
wrappy "1"
|
wrappy "1"
|
||||||
|
|
||||||
inherits@2, inherits@2.0.4, inherits@^2.0.1, inherits@~2.0.1, inherits@~2.0.3:
|
inherits@2, inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.1, inherits@~2.0.3:
|
||||||
version "2.0.4"
|
version "2.0.4"
|
||||||
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c"
|
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c"
|
||||||
integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
|
integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
|
||||||
|
@ -1805,6 +1848,13 @@ koa-mount@^4.0.0:
|
||||||
debug "^4.0.1"
|
debug "^4.0.1"
|
||||||
koa-compose "^4.1.0"
|
koa-compose "^4.1.0"
|
||||||
|
|
||||||
|
koa-multer@^1.0.2:
|
||||||
|
version "1.0.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/koa-multer/-/koa-multer-1.0.2.tgz#d38f7ffd1db97b1aad33e7774732f000ebd67259"
|
||||||
|
integrity sha512-0kFzN4atVd+9oiG+4fYxQ9S2T3dPhKNvmhITIY606Qn9wLEmfhW0DhSpOzRYhddN//4rh/TCK95TMtflmFa5lA==
|
||||||
|
dependencies:
|
||||||
|
multer "1.3.0"
|
||||||
|
|
||||||
koa-router@^9.1.0:
|
koa-router@^9.1.0:
|
||||||
version "9.1.0"
|
version "9.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/koa-router/-/koa-router-9.1.0.tgz#47d1ce2109fd62b1d76eb42df90b635ff93b6831"
|
resolved "https://registry.yarnpkg.com/koa-router/-/koa-router-9.1.0.tgz#47d1ce2109fd62b1d76eb42df90b635ff93b6831"
|
||||||
|
@ -2025,6 +2075,20 @@ ms@^2.1.1:
|
||||||
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009"
|
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009"
|
||||||
integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==
|
integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==
|
||||||
|
|
||||||
|
multer@1.3.0:
|
||||||
|
version "1.3.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/multer/-/multer-1.3.0.tgz#092b2670f6846fa4914965efc8cf94c20fec6cd2"
|
||||||
|
integrity sha1-CSsmcPaEb6SRSWXvyM+Uwg/sbNI=
|
||||||
|
dependencies:
|
||||||
|
append-field "^0.1.0"
|
||||||
|
busboy "^0.2.11"
|
||||||
|
concat-stream "^1.5.0"
|
||||||
|
mkdirp "^0.5.1"
|
||||||
|
object-assign "^3.0.0"
|
||||||
|
on-finished "^2.3.0"
|
||||||
|
type-is "^1.6.4"
|
||||||
|
xtend "^4.0.0"
|
||||||
|
|
||||||
mz@^2.4.0:
|
mz@^2.4.0:
|
||||||
version "2.7.0"
|
version "2.7.0"
|
||||||
resolved "https://registry.yarnpkg.com/mz/-/mz-2.7.0.tgz#95008057a56cafadc2bc63dde7f9ff6955948e32"
|
resolved "https://registry.yarnpkg.com/mz/-/mz-2.7.0.tgz#95008057a56cafadc2bc63dde7f9ff6955948e32"
|
||||||
|
@ -2131,6 +2195,11 @@ npm-run-all@^4.1.5:
|
||||||
shell-quote "^1.6.1"
|
shell-quote "^1.6.1"
|
||||||
string.prototype.padend "^3.0.0"
|
string.prototype.padend "^3.0.0"
|
||||||
|
|
||||||
|
object-assign@^3.0.0:
|
||||||
|
version "3.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-3.0.0.tgz#9bedd5ca0897949bca47e7ff408062d549f587f2"
|
||||||
|
integrity sha1-m+3VygiXlJvKR+f/QIBi1Un1h/I=
|
||||||
|
|
||||||
object-assign@^4.0.1, object-assign@^4.1.1:
|
object-assign@^4.0.1, object-assign@^4.1.1:
|
||||||
version "4.1.1"
|
version "4.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863"
|
resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863"
|
||||||
|
@ -2659,17 +2728,17 @@ read-pkg@^3.0.0:
|
||||||
normalize-package-data "^2.3.2"
|
normalize-package-data "^2.3.2"
|
||||||
path-type "^3.0.0"
|
path-type "^3.0.0"
|
||||||
|
|
||||||
readable-stream@~1.0.31:
|
readable-stream@1.1.x:
|
||||||
version "1.0.34"
|
version "1.1.14"
|
||||||
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.0.34.tgz#125820e34bc842d2f2aaafafe4c2916ee32c157c"
|
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.1.14.tgz#7cf4c54ef648e3813084c636dd2079e166c081d9"
|
||||||
integrity sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=
|
integrity sha1-fPTFTvZI44EwhMY23SB54WbAgdk=
|
||||||
dependencies:
|
dependencies:
|
||||||
core-util-is "~1.0.0"
|
core-util-is "~1.0.0"
|
||||||
inherits "~2.0.1"
|
inherits "~2.0.1"
|
||||||
isarray "0.0.1"
|
isarray "0.0.1"
|
||||||
string_decoder "~0.10.x"
|
string_decoder "~0.10.x"
|
||||||
|
|
||||||
readable-stream@~2.3.6:
|
readable-stream@^2.2.2, readable-stream@~2.3.6:
|
||||||
version "2.3.7"
|
version "2.3.7"
|
||||||
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57"
|
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57"
|
||||||
integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==
|
integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==
|
||||||
|
@ -2682,6 +2751,16 @@ readable-stream@~2.3.6:
|
||||||
string_decoder "~1.1.1"
|
string_decoder "~1.1.1"
|
||||||
util-deprecate "~1.0.1"
|
util-deprecate "~1.0.1"
|
||||||
|
|
||||||
|
readable-stream@~1.0.31:
|
||||||
|
version "1.0.34"
|
||||||
|
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.0.34.tgz#125820e34bc842d2f2aaafafe4c2916ee32c157c"
|
||||||
|
integrity sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=
|
||||||
|
dependencies:
|
||||||
|
core-util-is "~1.0.0"
|
||||||
|
inherits "~2.0.1"
|
||||||
|
isarray "0.0.1"
|
||||||
|
string_decoder "~0.10.x"
|
||||||
|
|
||||||
readdirp@~3.4.0:
|
readdirp@~3.4.0:
|
||||||
version "3.4.0"
|
version "3.4.0"
|
||||||
resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.4.0.tgz#9fdccdf9e9155805449221ac645e8303ab5b9ada"
|
resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.4.0.tgz#9fdccdf9e9155805449221ac645e8303ab5b9ada"
|
||||||
|
@ -2962,6 +3041,11 @@ sprintf-js@~1.0.2:
|
||||||
resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c"
|
resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c"
|
||||||
integrity sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=
|
integrity sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=
|
||||||
|
|
||||||
|
streamsearch@0.1.2:
|
||||||
|
version "0.1.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/streamsearch/-/streamsearch-0.1.2.tgz#808b9d0e56fc273d809ba57338e929919a1a9f1a"
|
||||||
|
integrity sha1-gIudDlb8Jz2Am6VzOOkpkZoanxo=
|
||||||
|
|
||||||
string-width@^3.0.0, string-width@^3.1.0:
|
string-width@^3.0.0, string-width@^3.1.0:
|
||||||
version "3.1.0"
|
version "3.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/string-width/-/string-width-3.1.0.tgz#22767be21b62af1081574306f69ac51b62203961"
|
resolved "https://registry.yarnpkg.com/string-width/-/string-width-3.1.0.tgz#22767be21b62af1081574306f69ac51b62203961"
|
||||||
|
@ -3205,7 +3289,7 @@ type-fest@^0.8.1:
|
||||||
resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d"
|
resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d"
|
||||||
integrity sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==
|
integrity sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==
|
||||||
|
|
||||||
type-is@^1.6.16:
|
type-is@^1.6.16, type-is@^1.6.4:
|
||||||
version "1.6.18"
|
version "1.6.18"
|
||||||
resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131"
|
resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131"
|
||||||
integrity sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==
|
integrity sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==
|
||||||
|
@ -3220,6 +3304,11 @@ typedarray-to-buffer@^3.1.5:
|
||||||
dependencies:
|
dependencies:
|
||||||
is-typedarray "^1.0.0"
|
is-typedarray "^1.0.0"
|
||||||
|
|
||||||
|
typedarray@^0.0.6:
|
||||||
|
version "0.0.6"
|
||||||
|
resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777"
|
||||||
|
integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=
|
||||||
|
|
||||||
typeorm@0.2.25:
|
typeorm@0.2.25:
|
||||||
version "0.2.25"
|
version "0.2.25"
|
||||||
resolved "https://registry.yarnpkg.com/typeorm/-/typeorm-0.2.25.tgz#1a33513b375b78cc7740d2405202208b918d7dde"
|
resolved "https://registry.yarnpkg.com/typeorm/-/typeorm-0.2.25.tgz#1a33513b375b78cc7740d2405202208b918d7dde"
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue