forked from mirror/misskey
Merge branch 'develop' into sw-notification-action
This commit is contained in:
commit
2f151cc3d2
@ -240,36 +240,6 @@ SQLでは配列のインデックスは**1始まり**。
|
||||
MongoDBの時とは違い、findOneでレコードを取得する時に対象レコードが存在しない場合 **`undefined`** が返ってくるので注意。
|
||||
MongoDBは`null`で返してきてたので、その感覚で`if (x === null)`とか書くとバグる。代わりに`if (x == null)`と書いてください
|
||||
|
||||
### 簡素な`undefined`チェック
|
||||
データベースからレコードを取得するときに、プログラムの流れ的に(ほぼ)絶対`undefined`にはならない場合でも、`undefined`チェックしないとTypeScriptに怒られます。
|
||||
でもいちいち複数行を費やして、発生するはずのない`undefined`をチェックするのも面倒なので、`ensure`というユーティリティ関数を用意しています。
|
||||
例えば、
|
||||
``` ts
|
||||
const user = await Users.findOne(userId);
|
||||
// この時点で user の型は User | undefined
|
||||
if (user == null) {
|
||||
throw 'missing user';
|
||||
}
|
||||
// この時点で user の型は User
|
||||
```
|
||||
という処理を`ensure`を使うと
|
||||
``` ts
|
||||
const user = await Users.findOne(userId).then(ensure);
|
||||
// この時点で user の型は User
|
||||
```
|
||||
という風に書けます。
|
||||
もちろん`ensure`内部でエラーを握りつぶすようなことはしておらず、万が一`undefined`だった場合はPromiseがRejectされ後続の処理は実行されません。
|
||||
``` ts
|
||||
const user = await Users.findOne(userId).then(ensure);
|
||||
// 万が一 Users.findOne の結果が undefined だったら、ensure でエラーが発生するので
|
||||
// この行に到達することは無い
|
||||
// なので、.then(ensure) は
|
||||
// if (user == null) {
|
||||
// throw 'missing user';
|
||||
// }
|
||||
// の糖衣構文のような扱いです
|
||||
```
|
||||
|
||||
### Migration作成方法
|
||||
```
|
||||
npx ts-node ./node_modules/typeorm/cli.js migration:generate -n 変更の名前
|
||||
|
BIN
assets/mi-white.png
Normal file
BIN
assets/mi-white.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 18 KiB |
@ -437,6 +437,7 @@ signinWith: "{x}でログイン"
|
||||
signinFailed: "ログインできませんでした。ユーザー名とパスワードを確認してください。"
|
||||
tapSecurityKey: "セキュリティキーにタッチ"
|
||||
or: "もしくは"
|
||||
language: "言語"
|
||||
uiLanguage: "UIの表示言語"
|
||||
groupInvited: "グループに招待されました"
|
||||
aboutX: "{x}について"
|
||||
@ -701,6 +702,13 @@ inUse: "使用中"
|
||||
editCode: "コードを編集"
|
||||
apply: "適用"
|
||||
receiveAnnouncementFromInstance: "インスタンスからのお知らせを受け取る"
|
||||
emailNotification: "メール通知"
|
||||
|
||||
_email:
|
||||
_follow:
|
||||
title: "フォローされました"
|
||||
_receiveFollowRequest:
|
||||
title: "フォローリクエストを受け取りました"
|
||||
|
||||
_plugin:
|
||||
install: "プラグインのインストール"
|
||||
|
14
migration/1613155914446-emailNotificationTypes.ts
Normal file
14
migration/1613155914446-emailNotificationTypes.ts
Normal file
@ -0,0 +1,14 @@
|
||||
import {MigrationInterface, QueryRunner} from "typeorm";
|
||||
|
||||
export class emailNotificationTypes1613155914446 implements MigrationInterface {
|
||||
name = 'emailNotificationTypes1613155914446'
|
||||
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(`ALTER TABLE "user_profile" ADD "emailNotificationTypes" jsonb NOT NULL DEFAULT '["follow","receiveFollowRequest","groupInvited"]'`);
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(`ALTER TABLE "user_profile" DROP COLUMN "emailNotificationTypes"`);
|
||||
}
|
||||
|
||||
}
|
14
migration/1613181457597-user-lang.ts
Normal file
14
migration/1613181457597-user-lang.ts
Normal file
@ -0,0 +1,14 @@
|
||||
import {MigrationInterface, QueryRunner} from "typeorm";
|
||||
|
||||
export class userLang1613181457597 implements MigrationInterface {
|
||||
name = 'userLang1613181457597'
|
||||
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(`ALTER TABLE "user_profile" ADD "lang" character varying(32)`);
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(`ALTER TABLE "user_profile" DROP COLUMN "lang"`);
|
||||
}
|
||||
|
||||
}
|
@ -179,13 +179,13 @@
|
||||
"markdown-it": "12.0.4",
|
||||
"markdown-it-anchor": "7.0.2",
|
||||
"matter-js": "0.16.1",
|
||||
"mocha": "8.2.1",
|
||||
"mocha": "8.3.0",
|
||||
"moji": "0.5.1",
|
||||
"ms": "2.1.3",
|
||||
"multer": "1.4.2",
|
||||
"nested-property": "4.0.0",
|
||||
"node-fetch": "2.6.1",
|
||||
"nodemailer": "6.4.17",
|
||||
"nodemailer": "6.4.18",
|
||||
"object-assign-deep": "0.4.0",
|
||||
"os-utils": "0.0.14",
|
||||
"p-cancelable": "2.0.0",
|
||||
@ -238,7 +238,7 @@
|
||||
"tslint": "6.1.3",
|
||||
"tslint-sonarts": "1.9.0",
|
||||
"typeorm": "0.2.30",
|
||||
"typescript": "4.1.3",
|
||||
"typescript": "4.1.5",
|
||||
"ulid": "2.3.0",
|
||||
"url-loader": "4.1.1",
|
||||
"uuid": "8.3.2",
|
||||
@ -253,7 +253,7 @@
|
||||
"vue-style-loader": "4.1.2",
|
||||
"vuedraggable": "4.0.1",
|
||||
"web-push": "3.4.4",
|
||||
"webpack": "5.21.1",
|
||||
"webpack": "5.21.2",
|
||||
"webpack-cli": "4.5.0",
|
||||
"websocket": "1.0.33",
|
||||
"ws": "7.4.3",
|
||||
|
@ -1,63 +1,50 @@
|
||||
<template>
|
||||
<div class="ztzhwixg _formItem" :class="{ inline, disabled }">
|
||||
<div class="_formLabel"><slot></slot></div>
|
||||
<div class="icon" ref="icon"><slot name="icon"></slot></div>
|
||||
<div class="input _formPanel">
|
||||
<div class="prefix" ref="prefixEl"><slot name="prefix"></slot></div>
|
||||
<input v-if="debounce" ref="inputEl"
|
||||
v-debounce="500"
|
||||
:type="type"
|
||||
v-model.lazy="v"
|
||||
:disabled="disabled"
|
||||
:required="required"
|
||||
:readonly="readonly"
|
||||
:placeholder="placeholder"
|
||||
:pattern="pattern"
|
||||
:autocomplete="autocomplete"
|
||||
:spellcheck="spellcheck"
|
||||
:step="step"
|
||||
@focus="focused = true"
|
||||
@blur="focused = false"
|
||||
@keydown="onKeydown($event)"
|
||||
@input="onInput"
|
||||
:list="id"
|
||||
>
|
||||
<input v-else ref="inputEl"
|
||||
:type="type"
|
||||
v-model="v"
|
||||
:disabled="disabled"
|
||||
:required="required"
|
||||
:readonly="readonly"
|
||||
:placeholder="placeholder"
|
||||
:pattern="pattern"
|
||||
:autocomplete="autocomplete"
|
||||
:spellcheck="spellcheck"
|
||||
:step="step"
|
||||
@focus="focused = true"
|
||||
@blur="focused = false"
|
||||
@keydown="onKeydown($event)"
|
||||
@input="onInput"
|
||||
:list="id"
|
||||
>
|
||||
<datalist :id="id" v-if="datalist">
|
||||
<option v-for="data in datalist" :value="data"/>
|
||||
</datalist>
|
||||
<div class="suffix" ref="suffixEl"><slot name="suffix"></slot></div>
|
||||
<FormGroup class="_formItem">
|
||||
<template #label><slot></slot></template>
|
||||
<div class="ztzhwixg _formItem" :class="{ inline, disabled }">
|
||||
<div class="icon" ref="icon"><slot name="icon"></slot></div>
|
||||
<div class="input _formPanel">
|
||||
<div class="prefix" ref="prefixEl"><slot name="prefix"></slot></div>
|
||||
<input ref="inputEl"
|
||||
:type="type"
|
||||
v-model="v"
|
||||
:disabled="disabled"
|
||||
:required="required"
|
||||
:readonly="readonly"
|
||||
:placeholder="placeholder"
|
||||
:pattern="pattern"
|
||||
:autocomplete="autocomplete"
|
||||
:spellcheck="spellcheck"
|
||||
:step="step"
|
||||
@focus="focused = true"
|
||||
@blur="focused = false"
|
||||
@keydown="onKeydown($event)"
|
||||
@input="onInput"
|
||||
:list="id"
|
||||
>
|
||||
<datalist :id="id" v-if="datalist">
|
||||
<option v-for="data in datalist" :value="data"/>
|
||||
</datalist>
|
||||
<div class="suffix" ref="suffixEl"><slot name="suffix"></slot></div>
|
||||
</div>
|
||||
</div>
|
||||
<button class="save _textButton" v-if="save && changed" @click="() => { changed = false; save(); }">{{ $ts.save }}</button>
|
||||
<div class="_formCaption"><slot name="desc"></slot></div>
|
||||
</div>
|
||||
<template #caption><slot name="desc"></slot></template>
|
||||
|
||||
<FormButton v-if="manualSave && changed" @click="updated" primary><Fa :icon="faSave"/> {{ $ts.save }}</FormButton>
|
||||
</FormGroup>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent, onMounted, onUnmounted, nextTick, ref, watch, computed, toRefs } from 'vue';
|
||||
import debounce from 'v-debounce';
|
||||
import { faExclamationCircle } from '@fortawesome/free-solid-svg-icons';
|
||||
import { faExclamationCircle, faSave } from '@fortawesome/free-solid-svg-icons';
|
||||
import './form.scss';
|
||||
import FormButton from './button.vue';
|
||||
import FormGroup from './group.vue';
|
||||
|
||||
export default defineComponent({
|
||||
directives: {
|
||||
debounce
|
||||
components: {
|
||||
FormGroup,
|
||||
FormButton,
|
||||
},
|
||||
props: {
|
||||
value: {
|
||||
@ -101,9 +88,6 @@ export default defineComponent({
|
||||
step: {
|
||||
required: false
|
||||
},
|
||||
debounce: {
|
||||
required: false
|
||||
},
|
||||
datalist: {
|
||||
type: Array,
|
||||
required: false,
|
||||
@ -113,9 +97,10 @@ export default defineComponent({
|
||||
required: false,
|
||||
default: false
|
||||
},
|
||||
save: {
|
||||
type: Function,
|
||||
manualSave: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: false
|
||||
},
|
||||
},
|
||||
emits: ['change', 'keydown', 'enter'],
|
||||
@ -144,15 +129,22 @@ export default defineComponent({
|
||||
}
|
||||
};
|
||||
|
||||
const updated = () => {
|
||||
changed.value = false;
|
||||
if (type?.value === 'number') {
|
||||
context.emit('update:value', parseFloat(v.value));
|
||||
} else {
|
||||
context.emit('update:value', v.value);
|
||||
}
|
||||
};
|
||||
|
||||
watch(value, newValue => {
|
||||
v.value = newValue;
|
||||
});
|
||||
|
||||
watch(v, newValue => {
|
||||
if (type?.value === 'number') {
|
||||
context.emit('update:value', parseFloat(newValue));
|
||||
} else {
|
||||
context.emit('update:value', newValue);
|
||||
if (!props.manualSave) {
|
||||
updated();
|
||||
}
|
||||
|
||||
invalid.value = inputEl.value.validity.badInput;
|
||||
@ -198,7 +190,8 @@ export default defineComponent({
|
||||
focus,
|
||||
onInput,
|
||||
onKeydown,
|
||||
faExclamationCircle,
|
||||
updated,
|
||||
faExclamationCircle, faSave,
|
||||
};
|
||||
},
|
||||
});
|
||||
@ -285,11 +278,6 @@ export default defineComponent({
|
||||
}
|
||||
}
|
||||
|
||||
> .save {
|
||||
margin: 6px 0 0 0;
|
||||
font-size: 0.8em;
|
||||
}
|
||||
|
||||
&.inline {
|
||||
display: inline-block;
|
||||
margin: 0;
|
||||
|
@ -1,29 +1,39 @@
|
||||
<template>
|
||||
<div class="rivhosbp _formItem" :class="{ tall, pre }">
|
||||
<div class="_formLabel"><slot></slot></div>
|
||||
<div class="input _formPanel">
|
||||
<textarea ref="input" :class="{ code, _monospace: code }"
|
||||
:value="value"
|
||||
:required="required"
|
||||
:readonly="readonly"
|
||||
:pattern="pattern"
|
||||
:autocomplete="autocomplete"
|
||||
:spellcheck="!code"
|
||||
@input="onInput"
|
||||
@focus="focused = true"
|
||||
@blur="focused = false"
|
||||
></textarea>
|
||||
<FormGroup class="_formItem">
|
||||
<template #label><slot></slot></template>
|
||||
<div class="rivhosbp _formItem" :class="{ tall, pre }">
|
||||
<div class="input _formPanel">
|
||||
<textarea ref="input" :class="{ code, _monospace: code }"
|
||||
v-model="v"
|
||||
:required="required"
|
||||
:readonly="readonly"
|
||||
:pattern="pattern"
|
||||
:autocomplete="autocomplete"
|
||||
:spellcheck="!code"
|
||||
@input="onInput"
|
||||
@focus="focused = true"
|
||||
@blur="focused = false"
|
||||
></textarea>
|
||||
</div>
|
||||
</div>
|
||||
<button class="save _textButton" v-if="save && changed" @click="() => { changed = false; save(); }">{{ $ts.save }}</button>
|
||||
<div class="_formCaption"><slot name="desc"></slot></div>
|
||||
</div>
|
||||
<template #caption><slot name="desc"></slot></template>
|
||||
|
||||
<FormButton v-if="manualSave && changed" @click="updated" primary><Fa :icon="faSave"/> {{ $ts.save }}</FormButton>
|
||||
</FormGroup>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent } from 'vue';
|
||||
import { defineComponent, ref, toRefs, watch } from 'vue';
|
||||
import { faSave } from '@fortawesome/free-solid-svg-icons';
|
||||
import './form.scss';
|
||||
import FormButton from './button.vue';
|
||||
import FormGroup from './group.vue';
|
||||
|
||||
export default defineComponent({
|
||||
components: {
|
||||
FormGroup,
|
||||
FormButton,
|
||||
},
|
||||
props: {
|
||||
value: {
|
||||
required: false
|
||||
@ -58,24 +68,46 @@ export default defineComponent({
|
||||
required: false,
|
||||
default: false
|
||||
},
|
||||
save: {
|
||||
type: Function,
|
||||
manualSave: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: false
|
||||
},
|
||||
},
|
||||
data() {
|
||||
setup(props, context) {
|
||||
const { value } = toRefs(props);
|
||||
const v = ref(value.value);
|
||||
const changed = ref(false);
|
||||
const inputEl = ref(null);
|
||||
const focus = () => inputEl.value.focus();
|
||||
const onInput = (ev) => {
|
||||
changed.value = true;
|
||||
context.emit('change', ev);
|
||||
};
|
||||
|
||||
const updated = () => {
|
||||
changed.value = false;
|
||||
context.emit('update:value', v.value);
|
||||
};
|
||||
|
||||
watch(value, newValue => {
|
||||
v.value = newValue;
|
||||
});
|
||||
|
||||
watch(v, newValue => {
|
||||
if (!props.manualSave) {
|
||||
updated();
|
||||
}
|
||||
});
|
||||
|
||||
return {
|
||||
changed: false,
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
focus() {
|
||||
this.$refs.input.focus();
|
||||
},
|
||||
onInput(ev) {
|
||||
this.changed = true;
|
||||
this.$emit('update:value', ev.target.value);
|
||||
}
|
||||
v,
|
||||
updated,
|
||||
changed,
|
||||
focus,
|
||||
onInput,
|
||||
faSave,
|
||||
};
|
||||
}
|
||||
});
|
||||
</script>
|
||||
@ -112,11 +144,6 @@ export default defineComponent({
|
||||
}
|
||||
}
|
||||
|
||||
> .save {
|
||||
margin: 6px 0 0 0;
|
||||
font-size: 0.8em;
|
||||
}
|
||||
|
||||
&.tall {
|
||||
> .input {
|
||||
> textarea {
|
||||
|
@ -51,7 +51,7 @@ export default defineComponent({
|
||||
text: '',
|
||||
flag: true,
|
||||
radio: 'misskey',
|
||||
mfm: `Hello world! This is an @example mention. BTW you are @${this.$i.username}.\nAlso, here is ${config.url} and [example link](${config.url}). for more details, see https://example.com.\nAs you know #misskey is open-source software.`
|
||||
mfm: `Hello world! This is an @example mention. BTW you are @${this.$i ? this.$i.username : 'guest'}.\nAlso, here is ${config.url} and [example link](${config.url}). for more details, see https://example.com.\nAs you know #misskey is open-source software.`
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { markRaw } from 'vue';
|
||||
import { locale } from '@/config';
|
||||
import { I18n } from '@/scripts/i18n';
|
||||
import { I18n } from '../misc/i18n';
|
||||
|
||||
export const i18n = markRaw(new I18n(locale));
|
||||
|
||||
|
90
src/client/pages/settings/email-notification.vue
Normal file
90
src/client/pages/settings/email-notification.vue
Normal file
@ -0,0 +1,90 @@
|
||||
<template>
|
||||
<FormBase>
|
||||
<FormGroup>
|
||||
<FormSwitch v-model:value="mention">
|
||||
{{ $ts._notification._types.mention }}
|
||||
</FormSwitch>
|
||||
<FormSwitch v-model:value="reply">
|
||||
{{ $ts._notification._types.reply }}
|
||||
</FormSwitch>
|
||||
<FormSwitch v-model:value="quote">
|
||||
{{ $ts._notification._types.quote }}
|
||||
</FormSwitch>
|
||||
<FormSwitch v-model:value="follow">
|
||||
{{ $ts._notification._types.follow }}
|
||||
</FormSwitch>
|
||||
<FormSwitch v-model:value="receiveFollowRequest">
|
||||
{{ $ts._notification._types.receiveFollowRequest }}
|
||||
</FormSwitch>
|
||||
<FormSwitch v-model:value="groupInvited">
|
||||
{{ $ts._notification._types.groupInvited }}
|
||||
</FormSwitch>
|
||||
</FormGroup>
|
||||
</FormBase>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent } from 'vue';
|
||||
import { faCog } from '@fortawesome/free-solid-svg-icons';
|
||||
import { faBell, faEnvelope } from '@fortawesome/free-regular-svg-icons';
|
||||
import FormButton from '@/components/form/button.vue';
|
||||
import FormSwitch from '@/components/form/switch.vue';
|
||||
import FormBase from '@/components/form/base.vue';
|
||||
import FormGroup from '@/components/form/group.vue';
|
||||
import * as os from '@/os';
|
||||
|
||||
export default defineComponent({
|
||||
components: {
|
||||
FormBase,
|
||||
FormSwitch,
|
||||
FormButton,
|
||||
FormGroup,
|
||||
},
|
||||
|
||||
emits: ['info'],
|
||||
|
||||
data() {
|
||||
return {
|
||||
INFO: {
|
||||
title: this.$ts.emailNotification,
|
||||
icon: faEnvelope
|
||||
},
|
||||
|
||||
mention: this.$i.emailNotificationTypes.includes('mention'),
|
||||
reply: this.$i.emailNotificationTypes.includes('reply'),
|
||||
quote: this.$i.emailNotificationTypes.includes('quote'),
|
||||
follow: this.$i.emailNotificationTypes.includes('follow'),
|
||||
receiveFollowRequest: this.$i.emailNotificationTypes.includes('receiveFollowRequest'),
|
||||
groupInvited: this.$i.emailNotificationTypes.includes('groupInvited'),
|
||||
}
|
||||
},
|
||||
|
||||
created() {
|
||||
this.$watch('mention', this.save);
|
||||
this.$watch('reply', this.save);
|
||||
this.$watch('quote', this.save);
|
||||
this.$watch('follow', this.save);
|
||||
this.$watch('receiveFollowRequest', this.save);
|
||||
this.$watch('groupInvited', this.save);
|
||||
},
|
||||
|
||||
mounted() {
|
||||
this.$emit('info', this.INFO);
|
||||
},
|
||||
|
||||
methods: {
|
||||
save() {
|
||||
os.api('i/update', {
|
||||
emailNotificationTypes: [
|
||||
...[this.mention ? 'mention' : null],
|
||||
...[this.reply ? 'reply' : null],
|
||||
...[this.quote ? 'quote' : null],
|
||||
...[this.follow ? 'follow' : null],
|
||||
...[this.receiveFollowRequest ? 'receiveFollowRequest' : null],
|
||||
...[this.groupInvited ? 'groupInvited' : null],
|
||||
].filter(x => x != null)
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
@ -9,6 +9,11 @@
|
||||
</FormLink>
|
||||
</FormGroup>
|
||||
|
||||
<FormLink to="/settings/email/notification">
|
||||
<template #icon><Fa :icon="faBell"/></template>
|
||||
{{ $ts.emailNotification }}
|
||||
</FormLink>
|
||||
|
||||
<FormSwitch :value="$i.receiveAnnouncementEmail" @update:value="onChangeReceiveAnnouncementEmail">
|
||||
{{ $ts.receiveAnnouncementFromInstance }}
|
||||
</FormSwitch>
|
||||
@ -43,7 +48,7 @@ export default defineComponent({
|
||||
title: this.$ts.email,
|
||||
icon: faEnvelope
|
||||
},
|
||||
faCog, faExclamationTriangle, faCheck
|
||||
faCog, faExclamationTriangle, faCheck, faBell
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -99,6 +99,7 @@ export default defineComponent({
|
||||
case 'general': return defineAsyncComponent(() => import('./general.vue'));
|
||||
case 'email': return defineAsyncComponent(() => import('./email.vue'));
|
||||
case 'email/address': return defineAsyncComponent(() => import('./email-address.vue'));
|
||||
case 'email/notification': return defineAsyncComponent(() => import('./email-notification.vue'));
|
||||
case 'theme': return defineAsyncComponent(() => import('./theme.vue'));
|
||||
case 'theme/install': return defineAsyncComponent(() => import('./theme.install.vue'));
|
||||
case 'theme/manage': return defineAsyncComponent(() => import('./theme.manage.vue'));
|
||||
|
@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<FormBase>
|
||||
<MkInfo warn>{{ $ts.pluginInstallWarn }}</MkInfo>
|
||||
<MkInfo warn>{{ $ts._plugin.installWarn }}</MkInfo>
|
||||
|
||||
<FormGroup>
|
||||
<FormTextarea v-model:value="code" tall>
|
||||
|
@ -8,25 +8,30 @@
|
||||
<FormButton @click="changeBanner" primary>{{ $ts._profile.changeBanner }}</FormButton>
|
||||
</FormGroup>
|
||||
|
||||
<FormInput v-model:value="name" :max="30">
|
||||
<FormInput v-model:value="name" :max="30" manual-save>
|
||||
<span>{{ $ts._profile.name }}</span>
|
||||
</FormInput>
|
||||
|
||||
<FormTextarea v-model:value="description" :max="500">
|
||||
<FormTextarea v-model:value="description" :max="500" tall manual-save>
|
||||
<span>{{ $ts._profile.description }}</span>
|
||||
<template #desc>{{ $ts._profile.youCanIncludeHashtags }}</template>
|
||||
</FormTextarea>
|
||||
|
||||
<FormInput v-model:value="location">
|
||||
<FormInput v-model:value="location" manual-save>
|
||||
<span>{{ $ts.location }}</span>
|
||||
<template #prefix><Fa :icon="faMapMarkerAlt"/></template>
|
||||
</FormInput>
|
||||
|
||||
<FormInput v-model:value="birthday" type="date">
|
||||
<FormInput v-model:value="birthday" type="date" manual-save>
|
||||
<span>{{ $ts.birthday }}</span>
|
||||
<template #prefix><Fa :icon="faBirthdayCake"/></template>
|
||||
</FormInput>
|
||||
|
||||
<FormSelect v-model:value="lang">
|
||||
<template #label>{{ $ts.language }}</template>
|
||||
<option v-for="x in langs" :value="x[0]" :key="x[0]">{{ x[1] }}</option>
|
||||
</FormSelect>
|
||||
|
||||
<FormGroup>
|
||||
<FormButton @click="editMetadata" primary>{{ $ts._profile.metadataEdit }}</FormButton>
|
||||
<template #caption>{{ $ts._profile.metadataDescription }}</template>
|
||||
@ -37,8 +42,6 @@
|
||||
<FormSwitch v-model:value="isBot">{{ $ts.flagAsBot }}<template #desc>{{ $ts.flagAsBotDescription }}</template></FormSwitch>
|
||||
|
||||
<FormSwitch v-model:value="alwaysMarkNsfw">{{ $ts.alwaysMarkSensitive }}</FormSwitch>
|
||||
|
||||
<FormButton @click="save(true)" primary><Fa :icon="faSave"/> {{ $ts.save }}</FormButton>
|
||||
</FormBase>
|
||||
</template>
|
||||
|
||||
@ -50,10 +53,10 @@ import FormButton from '@/components/form/button.vue';
|
||||
import FormInput from '@/components/form/input.vue';
|
||||
import FormTextarea from '@/components/form/textarea.vue';
|
||||
import FormSwitch from '@/components/form/switch.vue';
|
||||
import FormTuple from '@/components/form/tuple.vue';
|
||||
import FormSelect from '@/components/form/select.vue';
|
||||
import FormBase from '@/components/form/base.vue';
|
||||
import FormGroup from '@/components/form/group.vue';
|
||||
import { host } from '@/config';
|
||||
import { host, langs } from '@/config';
|
||||
import { selectFile } from '@/scripts/select-file';
|
||||
import * as os from '@/os';
|
||||
|
||||
@ -63,7 +66,7 @@ export default defineComponent({
|
||||
FormInput,
|
||||
FormTextarea,
|
||||
FormSwitch,
|
||||
FormTuple,
|
||||
FormSelect,
|
||||
FormBase,
|
||||
FormGroup,
|
||||
},
|
||||
@ -77,9 +80,11 @@ export default defineComponent({
|
||||
icon: faUser
|
||||
},
|
||||
host,
|
||||
langs,
|
||||
name: null,
|
||||
description: null,
|
||||
birthday: null,
|
||||
lang: null,
|
||||
location: null,
|
||||
fieldName0: null,
|
||||
fieldValue0: null,
|
||||
@ -104,6 +109,7 @@ export default defineComponent({
|
||||
this.description = this.$i.description;
|
||||
this.location = this.$i.location;
|
||||
this.birthday = this.$i.birthday;
|
||||
this.lang = this.$i.lang;
|
||||
this.avatarId = this.$i.avatarId;
|
||||
this.bannerId = this.$i.bannerId;
|
||||
this.isBot = this.$i.isBot;
|
||||
@ -118,6 +124,15 @@ export default defineComponent({
|
||||
this.fieldValue2 = this.$i.fields[2] ? this.$i.fields[2].value : null;
|
||||
this.fieldName3 = this.$i.fields[3] ? this.$i.fields[3].name : null;
|
||||
this.fieldValue3 = this.$i.fields[3] ? this.$i.fields[3].value : null;
|
||||
|
||||
this.$watch('name', this.save);
|
||||
this.$watch('description', this.save);
|
||||
this.$watch('location', this.save);
|
||||
this.$watch('birthday', this.save);
|
||||
this.$watch('lang', this.save);
|
||||
this.$watch('isBot', this.save);
|
||||
this.$watch('isCat', this.save);
|
||||
this.$watch('alwaysMarkNsfw', this.save);
|
||||
},
|
||||
|
||||
mounted() {
|
||||
@ -214,14 +229,15 @@ export default defineComponent({
|
||||
});
|
||||
},
|
||||
|
||||
save(notify) {
|
||||
save() {
|
||||
this.saving = true;
|
||||
|
||||
os.api('i/update', {
|
||||
os.apiWithDialog('i/update', {
|
||||
name: this.name || null,
|
||||
description: this.description || null,
|
||||
location: this.location || null,
|
||||
birthday: this.birthday || null,
|
||||
lang: this.lang || null,
|
||||
isBot: !!this.isBot,
|
||||
isCat: !!this.isCat,
|
||||
alwaysMarkNsfw: !!this.alwaysMarkNsfw,
|
||||
@ -231,16 +247,8 @@ export default defineComponent({
|
||||
this.$i.avatarUrl = i.avatarUrl;
|
||||
this.$i.bannerId = i.bannerId;
|
||||
this.$i.bannerUrl = i.bannerUrl;
|
||||
|
||||
if (notify) {
|
||||
os.success();
|
||||
}
|
||||
}).catch(err => {
|
||||
this.saving = false;
|
||||
os.dialog({
|
||||
type: 'error',
|
||||
text: err.id
|
||||
});
|
||||
});
|
||||
},
|
||||
}
|
||||
|
@ -4,7 +4,6 @@ import { User } from '../models/entities/user';
|
||||
import { UserListJoinings, UserGroupJoinings } from '../models';
|
||||
import parseAcct from './acct/parse';
|
||||
import { getFullApAccount } from './convert-host';
|
||||
import { ensure } from '../prelude/ensure';
|
||||
|
||||
export async function checkHitAntenna(antenna: Antenna, note: Note, noteUser: User, followers: User['id'][]): Promise<boolean> {
|
||||
if (note.visibility === 'specified') return false;
|
||||
@ -24,7 +23,7 @@ export async function checkHitAntenna(antenna: Antenna, note: Note, noteUser: Us
|
||||
|
||||
if (!listUsers.includes(note.userId)) return false;
|
||||
} else if (antenna.src === 'group') {
|
||||
const joining = await UserGroupJoinings.findOne(antenna.userGroupJoiningId!).then(ensure);
|
||||
const joining = await UserGroupJoinings.findOneOrFail(antenna.userGroupJoiningId!);
|
||||
|
||||
const groupUsers = (await UserGroupJoinings.find({
|
||||
userGroupId: joining.userGroupId
|
||||
|
@ -1,10 +1,9 @@
|
||||
import { fetchMeta } from './fetch-meta';
|
||||
import { ILocalUser } from '../models/entities/user';
|
||||
import { Users } from '../models';
|
||||
import { ensure } from '../prelude/ensure';
|
||||
|
||||
export async function fetchProxyAccount(): Promise<ILocalUser | null> {
|
||||
const meta = await fetchMeta();
|
||||
if (meta.proxyAccountId == null) return null;
|
||||
return await Users.findOne(meta.proxyAccountId).then(ensure) as ILocalUser;
|
||||
return await Users.findOneOrFail(meta.proxyAccountId) as ILocalUser;
|
||||
}
|
||||
|
@ -1,14 +1,9 @@
|
||||
// Notice: Service Workerでも使用します
|
||||
export class I18n<T extends Record<string, any>> {
|
||||
public locale: T;
|
||||
|
||||
constructor(locale: T) {
|
||||
this.locale = locale;
|
||||
|
||||
if (_DEV_) {
|
||||
console.log('i18n', this.locale);
|
||||
}
|
||||
|
||||
//#region BIND
|
||||
this.t = this.t.bind(this);
|
||||
//#endregion
|
||||
@ -20,12 +15,6 @@ export class I18n<T extends Record<string, any>> {
|
||||
try {
|
||||
let str = key.split('.').reduce((o, i) => o[i], this.locale) as string;
|
||||
|
||||
if (_DEV_) {
|
||||
if (!str.includes('{')) {
|
||||
console.warn(`i18n: '${key}' has no any arg. so ref prop directly instead of call this method.`);
|
||||
}
|
||||
}
|
||||
|
||||
if (args) {
|
||||
for (const [k, v] of Object.entries(args)) {
|
||||
str = str.replace(`{${k}}`, v);
|
||||
@ -33,11 +22,7 @@ export class I18n<T extends Record<string, any>> {
|
||||
}
|
||||
return str;
|
||||
} catch (e) {
|
||||
if (_DEV_) {
|
||||
console.warn(`missing localization '${key}'`);
|
||||
return `⚠'${key}'⚠`;
|
||||
}
|
||||
|
||||
console.warn(`missing localization '${key}'`);
|
||||
return key;
|
||||
}
|
||||
}
|
@ -4,6 +4,8 @@ import { User } from './user';
|
||||
import { Page } from './page';
|
||||
import { notificationTypes } from '../../types';
|
||||
|
||||
// TODO: このテーブルで管理している情報すべてレジストリで管理するようにしても良いかも
|
||||
// ただ、「emailVerified が true なユーザーを find する」のようなクエリは書けなくなるからウーン
|
||||
@Entity()
|
||||
export class UserProfile {
|
||||
@PrimaryColumn(id())
|
||||
@ -41,6 +43,11 @@ export class UserProfile {
|
||||
value: string;
|
||||
}[];
|
||||
|
||||
@Column('varchar', {
|
||||
length: 32, nullable: true,
|
||||
})
|
||||
public lang: string | null;
|
||||
|
||||
@Column('varchar', {
|
||||
length: 512, nullable: true,
|
||||
comment: 'Remote URL of the user.'
|
||||
@ -63,6 +70,11 @@ export class UserProfile {
|
||||
})
|
||||
public emailVerified: boolean;
|
||||
|
||||
@Column('jsonb', {
|
||||
default: ['follow', 'receiveFollowRequest', 'groupInvited']
|
||||
})
|
||||
public emailNotificationTypes: string[];
|
||||
|
||||
@Column('varchar', {
|
||||
length: 128, nullable: true,
|
||||
})
|
||||
|
@ -1,7 +1,6 @@
|
||||
import { EntityRepository, Repository } from 'typeorm';
|
||||
import { Users } from '..';
|
||||
import { AbuseUserReport } from '../entities/abuse-user-report';
|
||||
import { ensure } from '../../prelude/ensure';
|
||||
import { awaitAll } from '../../prelude/await-all';
|
||||
|
||||
@EntityRepository(AbuseUserReport)
|
||||
@ -9,7 +8,7 @@ export class AbuseUserReportRepository extends Repository<AbuseUserReport> {
|
||||
public async pack(
|
||||
src: AbuseUserReport['id'] | AbuseUserReport,
|
||||
) {
|
||||
const report = typeof src === 'object' ? src : await this.findOne(src).then(ensure);
|
||||
const report = typeof src === 'object' ? src : await this.findOneOrFail(src);
|
||||
|
||||
return await awaitAll({
|
||||
id: report.id,
|
||||
|
@ -1,6 +1,5 @@
|
||||
import { EntityRepository, Repository } from 'typeorm';
|
||||
import { Antenna } from '../entities/antenna';
|
||||
import { ensure } from '../../prelude/ensure';
|
||||
import { SchemaType } from '../../misc/schema';
|
||||
import { AntennaNotes, UserGroupJoinings } from '..';
|
||||
|
||||
@ -11,7 +10,7 @@ export class AntennaRepository extends Repository<Antenna> {
|
||||
public async pack(
|
||||
src: Antenna['id'] | Antenna,
|
||||
): Promise<PackedAntenna> {
|
||||
const antenna = typeof src === 'object' ? src : await this.findOne(src).then(ensure);
|
||||
const antenna = typeof src === 'object' ? src : await this.findOneOrFail(src);
|
||||
|
||||
const hasUnreadNote = (await AntennaNotes.findOne({ antennaId: antenna.id, read: false })) != null;
|
||||
const userGroupJoining = antenna.userGroupJoiningId ? await UserGroupJoinings.findOne(antenna.userGroupJoiningId) : null;
|
||||
|
@ -1,7 +1,6 @@
|
||||
import { EntityRepository, Repository } from 'typeorm';
|
||||
import { App } from '../entities/app';
|
||||
import { AccessTokens } from '..';
|
||||
import { ensure } from '../../prelude/ensure';
|
||||
import { SchemaType } from '../../misc/schema';
|
||||
|
||||
export type PackedApp = SchemaType<typeof packedAppSchema>;
|
||||
@ -23,7 +22,7 @@ export class AppRepository extends Repository<App> {
|
||||
includeProfileImageIds: false
|
||||
}, options);
|
||||
|
||||
const app = typeof src === 'object' ? src : await this.findOne(src).then(ensure);
|
||||
const app = typeof src === 'object' ? src : await this.findOneOrFail(src);
|
||||
|
||||
return {
|
||||
id: app.id,
|
||||
|
@ -1,7 +1,6 @@
|
||||
import { EntityRepository, Repository } from 'typeorm';
|
||||
import { Apps } from '..';
|
||||
import { AuthSession } from '../entities/auth-session';
|
||||
import { ensure } from '../../prelude/ensure';
|
||||
import { awaitAll } from '../../prelude/await-all';
|
||||
|
||||
@EntityRepository(AuthSession)
|
||||
@ -10,7 +9,7 @@ export class AuthSessionRepository extends Repository<AuthSession> {
|
||||
src: AuthSession['id'] | AuthSession,
|
||||
me?: any
|
||||
) {
|
||||
const session = typeof src === 'object' ? src : await this.findOne(src).then(ensure);
|
||||
const session = typeof src === 'object' ? src : await this.findOneOrFail(src);
|
||||
|
||||
return await awaitAll({
|
||||
id: session.id,
|
||||
|
@ -1,7 +1,6 @@
|
||||
import { EntityRepository, Repository } from 'typeorm';
|
||||
import { Users } from '..';
|
||||
import { Blocking } from '../entities/blocking';
|
||||
import { ensure } from '../../prelude/ensure';
|
||||
import { awaitAll } from '../../prelude/await-all';
|
||||
import { SchemaType } from '../../misc/schema';
|
||||
|
||||
@ -13,7 +12,7 @@ export class BlockingRepository extends Repository<Blocking> {
|
||||
src: Blocking['id'] | Blocking,
|
||||
me?: any
|
||||
): Promise<PackedBlocking> {
|
||||
const blocking = typeof src === 'object' ? src : await this.findOne(src).then(ensure);
|
||||
const blocking = typeof src === 'object' ? src : await this.findOneOrFail(src);
|
||||
|
||||
return await awaitAll({
|
||||
id: blocking.id,
|
||||
|
@ -1,6 +1,5 @@
|
||||
import { EntityRepository, Repository } from 'typeorm';
|
||||
import { Channel } from '../entities/channel';
|
||||
import { ensure } from '../../prelude/ensure';
|
||||
import { SchemaType } from '../../misc/schema';
|
||||
import { DriveFiles, ChannelFollowings, NoteUnreads } from '..';
|
||||
import { User } from '../entities/user';
|
||||
@ -13,7 +12,7 @@ export class ChannelRepository extends Repository<Channel> {
|
||||
src: Channel['id'] | Channel,
|
||||
me?: User['id'] | User | null | undefined,
|
||||
): Promise<PackedChannel> {
|
||||
const channel = typeof src === 'object' ? src : await this.findOne(src).then(ensure);
|
||||
const channel = typeof src === 'object' ? src : await this.findOneOrFail(src);
|
||||
const meId = me ? typeof me === 'string' ? me : me.id : null;
|
||||
|
||||
const banner = channel.bannerId ? await DriveFiles.findOne(channel.bannerId) : null;
|
||||
|
@ -1,6 +1,5 @@
|
||||
import { EntityRepository, Repository } from 'typeorm';
|
||||
import { Clip } from '../entities/clip';
|
||||
import { ensure } from '../../prelude/ensure';
|
||||
import { SchemaType } from '../../misc/schema';
|
||||
import { Users } from '..';
|
||||
import { awaitAll } from '../../prelude/await-all';
|
||||
@ -12,7 +11,7 @@ export class ClipRepository extends Repository<Clip> {
|
||||
public async pack(
|
||||
src: Clip['id'] | Clip,
|
||||
): Promise<PackedClip> {
|
||||
const clip = typeof src === 'object' ? src : await this.findOne(src).then(ensure);
|
||||
const clip = typeof src === 'object' ? src : await this.findOneOrFail(src);
|
||||
|
||||
return await awaitAll({
|
||||
id: clip.id,
|
||||
|
@ -3,7 +3,6 @@ import { DriveFile } from '../entities/drive-file';
|
||||
import { Users, DriveFolders } from '..';
|
||||
import { User } from '../entities/user';
|
||||
import { toPuny } from '../../misc/convert-host';
|
||||
import { ensure } from '../../prelude/ensure';
|
||||
import { awaitAll } from '../../prelude/await-all';
|
||||
import { SchemaType } from '../../misc/schema';
|
||||
import config from '../../config';
|
||||
@ -103,7 +102,7 @@ export class DriveFileRepository extends Repository<DriveFile> {
|
||||
self: false
|
||||
}, options);
|
||||
|
||||
const file = typeof src === 'object' ? src : await this.findOne(src).then(ensure);
|
||||
const file = typeof src === 'object' ? src : await this.findOneOrFail(src);
|
||||
|
||||
const meta = await fetchMeta();
|
||||
|
||||
|
@ -1,7 +1,6 @@
|
||||
import { EntityRepository, Repository } from 'typeorm';
|
||||
import { DriveFolders, DriveFiles } from '..';
|
||||
import { DriveFolder } from '../entities/drive-folder';
|
||||
import { ensure } from '../../prelude/ensure';
|
||||
import { awaitAll } from '../../prelude/await-all';
|
||||
import { SchemaType } from '../../misc/schema';
|
||||
|
||||
@ -26,7 +25,7 @@ export class DriveFolderRepository extends Repository<DriveFolder> {
|
||||
detail: false
|
||||
}, options);
|
||||
|
||||
const folder = typeof src === 'object' ? src : await this.findOne(src).then(ensure);
|
||||
const folder = typeof src === 'object' ? src : await this.findOneOrFail(src);
|
||||
|
||||
return await awaitAll({
|
||||
id: folder.id,
|
||||
|
@ -1,13 +1,12 @@
|
||||
import { EntityRepository, Repository } from 'typeorm';
|
||||
import { Emoji } from '../entities/emoji';
|
||||
import { ensure } from '../../prelude/ensure';
|
||||
|
||||
@EntityRepository(Emoji)
|
||||
export class EmojiRepository extends Repository<Emoji> {
|
||||
public async pack(
|
||||
src: Emoji['id'] | Emoji,
|
||||
) {
|
||||
const emoji = typeof src === 'object' ? src : await this.findOne(src).then(ensure);
|
||||
const emoji = typeof src === 'object' ? src : await this.findOneOrFail(src);
|
||||
|
||||
return {
|
||||
id: emoji.id,
|
||||
|
@ -1,7 +1,6 @@
|
||||
import { EntityRepository, Repository } from 'typeorm';
|
||||
import { FollowRequest } from '../entities/follow-request';
|
||||
import { Users } from '..';
|
||||
import { ensure } from '../../prelude/ensure';
|
||||
|
||||
@EntityRepository(FollowRequest)
|
||||
export class FollowRequestRepository extends Repository<FollowRequest> {
|
||||
@ -9,7 +8,7 @@ export class FollowRequestRepository extends Repository<FollowRequest> {
|
||||
src: FollowRequest['id'] | FollowRequest,
|
||||
me?: any
|
||||
) {
|
||||
const request = typeof src === 'object' ? src : await this.findOne(src).then(ensure);
|
||||
const request = typeof src === 'object' ? src : await this.findOneOrFail(src);
|
||||
|
||||
return {
|
||||
id: request.id,
|
||||
|
@ -1,7 +1,6 @@
|
||||
import { EntityRepository, Repository } from 'typeorm';
|
||||
import { Users } from '..';
|
||||
import { Following } from '../entities/following';
|
||||
import { ensure } from '../../prelude/ensure';
|
||||
import { awaitAll } from '../../prelude/await-all';
|
||||
import { SchemaType } from '../../misc/schema';
|
||||
|
||||
@ -57,7 +56,7 @@ export class FollowingRepository extends Repository<Following> {
|
||||
populateFollower?: boolean;
|
||||
}
|
||||
): Promise<PackedFollowing> {
|
||||
const following = typeof src === 'object' ? src : await this.findOne(src).then(ensure);
|
||||
const following = typeof src === 'object' ? src : await this.findOneOrFail(src);
|
||||
|
||||
if (opts == null) opts = {};
|
||||
|
||||
|
@ -1,7 +1,6 @@
|
||||
import { EntityRepository, Repository } from 'typeorm';
|
||||
import { Users } from '../../..';
|
||||
import { ReversiGame } from '../../../entities/games/reversi/game';
|
||||
import { ensure } from '../../../../prelude/ensure';
|
||||
|
||||
@EntityRepository(ReversiGame)
|
||||
export class ReversiGameRepository extends Repository<ReversiGame> {
|
||||
@ -16,7 +15,7 @@ export class ReversiGameRepository extends Repository<ReversiGame> {
|
||||
detail: true
|
||||
}, options);
|
||||
|
||||
const game = typeof src === 'object' ? src : await this.findOne(src).then(ensure);
|
||||
const game = typeof src === 'object' ? src : await this.findOneOrFail(src);
|
||||
const meId = me ? typeof me === 'string' ? me : me.id : null;
|
||||
|
||||
return {
|
||||
|
@ -1,7 +1,6 @@
|
||||
import { EntityRepository, Repository } from 'typeorm';
|
||||
import { ReversiMatching } from '../../../entities/games/reversi/matching';
|
||||
import { Users } from '../../..';
|
||||
import { ensure } from '../../../../prelude/ensure';
|
||||
import { awaitAll } from '../../../../prelude/await-all';
|
||||
|
||||
@EntityRepository(ReversiMatching)
|
||||
@ -10,7 +9,7 @@ export class ReversiMatchingRepository extends Repository<ReversiMatching> {
|
||||
src: ReversiMatching['id'] | ReversiMatching,
|
||||
me: any
|
||||
) {
|
||||
const matching = typeof src === 'object' ? src : await this.findOne(src).then(ensure);
|
||||
const matching = typeof src === 'object' ? src : await this.findOneOrFail(src);
|
||||
|
||||
return await awaitAll({
|
||||
id: matching.id,
|
||||
|
@ -1,7 +1,6 @@
|
||||
import { EntityRepository, Repository } from 'typeorm';
|
||||
import { MessagingMessage } from '../entities/messaging-message';
|
||||
import { Users, DriveFiles, UserGroups } from '..';
|
||||
import { ensure } from '../../prelude/ensure';
|
||||
import { SchemaType } from '../../misc/schema';
|
||||
|
||||
export type PackedMessagingMessage = SchemaType<typeof packedMessagingMessageSchema>;
|
||||
@ -25,7 +24,7 @@ export class MessagingMessageRepository extends Repository<MessagingMessage> {
|
||||
populateGroup: true,
|
||||
};
|
||||
|
||||
const message = typeof src === 'object' ? src : await this.findOne(src).then(ensure);
|
||||
const message = typeof src === 'object' ? src : await this.findOneOrFail(src);
|
||||
|
||||
return {
|
||||
id: message.id,
|
||||
|
@ -1,7 +1,6 @@
|
||||
import { EntityRepository, Repository } from 'typeorm';
|
||||
import { Users } from '..';
|
||||
import { ModerationLog } from '../entities/moderation-log';
|
||||
import { ensure } from '../../prelude/ensure';
|
||||
import { awaitAll } from '../../prelude/await-all';
|
||||
|
||||
@EntityRepository(ModerationLog)
|
||||
@ -9,7 +8,7 @@ export class ModerationLogRepository extends Repository<ModerationLog> {
|
||||
public async pack(
|
||||
src: ModerationLog['id'] | ModerationLog,
|
||||
) {
|
||||
const log = typeof src === 'object' ? src : await this.findOne(src).then(ensure);
|
||||
const log = typeof src === 'object' ? src : await this.findOneOrFail(src);
|
||||
|
||||
return await awaitAll({
|
||||
id: log.id,
|
||||
|
@ -1,7 +1,6 @@
|
||||
import { EntityRepository, Repository } from 'typeorm';
|
||||
import { Users } from '..';
|
||||
import { Muting } from '../entities/muting';
|
||||
import { ensure } from '../../prelude/ensure';
|
||||
import { awaitAll } from '../../prelude/await-all';
|
||||
import { SchemaType } from '../../misc/schema';
|
||||
|
||||
@ -13,7 +12,7 @@ export class MutingRepository extends Repository<Muting> {
|
||||
src: Muting['id'] | Muting,
|
||||
me?: any
|
||||
): Promise<PackedMuting> {
|
||||
const muting = typeof src === 'object' ? src : await this.findOne(src).then(ensure);
|
||||
const muting = typeof src === 'object' ? src : await this.findOneOrFail(src);
|
||||
|
||||
return await awaitAll({
|
||||
id: muting.id,
|
||||
|
@ -1,7 +1,6 @@
|
||||
import { EntityRepository, Repository } from 'typeorm';
|
||||
import { NoteFavorite } from '../entities/note-favorite';
|
||||
import { Notes } from '..';
|
||||
import { ensure } from '../../prelude/ensure';
|
||||
|
||||
@EntityRepository(NoteFavorite)
|
||||
export class NoteFavoriteRepository extends Repository<NoteFavorite> {
|
||||
@ -9,7 +8,7 @@ export class NoteFavoriteRepository extends Repository<NoteFavorite> {
|
||||
src: NoteFavorite['id'] | NoteFavorite,
|
||||
me?: any
|
||||
) {
|
||||
const favorite = typeof src === 'object' ? src : await this.findOne(src).then(ensure);
|
||||
const favorite = typeof src === 'object' ? src : await this.findOneOrFail(src);
|
||||
|
||||
return {
|
||||
id: favorite.id,
|
||||
|
@ -1,7 +1,6 @@
|
||||
import { EntityRepository, Repository } from 'typeorm';
|
||||
import { NoteReaction } from '../entities/note-reaction';
|
||||
import { Users } from '..';
|
||||
import { ensure } from '../../prelude/ensure';
|
||||
import { SchemaType } from '../../misc/schema';
|
||||
import { convertLegacyReaction } from '../../misc/reaction-lib';
|
||||
|
||||
@ -13,7 +12,7 @@ export class NoteReactionRepository extends Repository<NoteReaction> {
|
||||
src: NoteReaction['id'] | NoteReaction,
|
||||
me?: any
|
||||
): Promise<PackedNoteReaction> {
|
||||
const reaction = typeof src === 'object' ? src : await this.findOne(src).then(ensure);
|
||||
const reaction = typeof src === 'object' ? src : await this.findOneOrFail(src);
|
||||
|
||||
return {
|
||||
id: reaction.id,
|
||||
|
@ -2,7 +2,6 @@ import { EntityRepository, Repository, In } from 'typeorm';
|
||||
import { Note } from '../entities/note';
|
||||
import { User } from '../entities/user';
|
||||
import { Emojis, Users, PollVotes, DriveFiles, NoteReactions, Followings, Polls, Channels } from '..';
|
||||
import { ensure } from '../../prelude/ensure';
|
||||
import { SchemaType } from '../../misc/schema';
|
||||
import { awaitAll } from '../../prelude/await-all';
|
||||
import { convertLegacyReaction, convertLegacyReactions, decodeReaction } from '../../misc/reaction-lib';
|
||||
@ -92,11 +91,11 @@ export class NoteRepository extends Repository<Note> {
|
||||
}, options);
|
||||
|
||||
const meId = me ? typeof me === 'string' ? me : me.id : null;
|
||||
const note = typeof src === 'object' ? src : await this.findOne(src).then(ensure);
|
||||
const note = typeof src === 'object' ? src : await this.findOneOrFail(src);
|
||||
const host = note.userHost;
|
||||
|
||||
async function populatePoll() {
|
||||
const poll = await Polls.findOne(note.id).then(ensure);
|
||||
const poll = await Polls.findOneOrFail(note.id);
|
||||
const choices = poll.choices.map(c => ({
|
||||
text: c,
|
||||
votes: poll.votes[poll.choices.indexOf(c)],
|
||||
@ -413,5 +412,63 @@ export const packedNoteSchema = {
|
||||
optional: true as const, nullable: true as const,
|
||||
ref: 'Channel'
|
||||
},
|
||||
localOnly: {
|
||||
type: 'boolean' as const,
|
||||
optional: false as const, nullable: true as const,
|
||||
},
|
||||
emojis: {
|
||||
type: 'array' as const,
|
||||
optional: false as const, nullable: false as const,
|
||||
items: {
|
||||
type: 'object' as const,
|
||||
optional: false as const, nullable: false as const,
|
||||
properties: {
|
||||
name: {
|
||||
type: 'string' as const,
|
||||
optional: false as const, nullable: false as const,
|
||||
},
|
||||
url: {
|
||||
type: 'string' as const,
|
||||
optional: false as const, nullable: false as const,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
reactions: {
|
||||
type: 'object' as const,
|
||||
optional: false as const, nullable: false as const,
|
||||
description: 'Key is either Unicode emoji or custom emoji, value is count of that emoji reaction.',
|
||||
},
|
||||
renoteCount: {
|
||||
type: 'number' as const,
|
||||
optional: false as const, nullable: false as const,
|
||||
},
|
||||
repliesCount: {
|
||||
type: 'number' as const,
|
||||
optional: false as const, nullable: false as const,
|
||||
},
|
||||
uri: {
|
||||
type: 'string' as const,
|
||||
optional: false as const, nullable: true as const,
|
||||
description: 'The URI of a note. it will be null when the note is local.',
|
||||
},
|
||||
url: {
|
||||
type: 'string' as const,
|
||||
optional: false as const, nullable: true as const,
|
||||
description: 'The human readable url of a note. it will be null when the note is local.',
|
||||
},
|
||||
_featuredId_: {
|
||||
type: 'string' as const,
|
||||
optional: false as const, nullable: true as const,
|
||||
},
|
||||
_prId_: {
|
||||
type: 'string' as const,
|
||||
optional: false as const, nullable: true as const,
|
||||
},
|
||||
myReaction: {
|
||||
type: 'object' as const,
|
||||
optional: true as const, nullable: true as const,
|
||||
description: 'Key is either Unicode emoji or custom emoji, value is count of that emoji reaction.',
|
||||
},
|
||||
},
|
||||
};
|
||||
|
@ -1,7 +1,6 @@
|
||||
import { EntityRepository, Repository } from 'typeorm';
|
||||
import { Users, Notes, UserGroupInvitations, AccessTokens } from '..';
|
||||
import { Notification } from '../entities/notification';
|
||||
import { ensure } from '../../prelude/ensure';
|
||||
import { awaitAll } from '../../prelude/await-all';
|
||||
import { SchemaType } from '../../misc/schema';
|
||||
|
||||
@ -12,8 +11,8 @@ export class NotificationRepository extends Repository<Notification> {
|
||||
public async pack(
|
||||
src: Notification['id'] | Notification,
|
||||
): Promise<PackedNotification> {
|
||||
const notification = typeof src === 'object' ? src : await this.findOne(src).then(ensure);
|
||||
const token = notification.appAccessTokenId ? await AccessTokens.findOne(notification.appAccessTokenId).then(ensure) : null;
|
||||
const notification = typeof src === 'object' ? src : await this.findOneOrFail(src);
|
||||
const token = notification.appAccessTokenId ? await AccessTokens.findOneOrFail(notification.appAccessTokenId) : null;
|
||||
|
||||
return await awaitAll({
|
||||
id: notification.id,
|
||||
|
@ -1,7 +1,6 @@
|
||||
import { EntityRepository, Repository } from 'typeorm';
|
||||
import { PageLike } from '../entities/page-like';
|
||||
import { Pages } from '..';
|
||||
import { ensure } from '../../prelude/ensure';
|
||||
|
||||
@EntityRepository(PageLike)
|
||||
export class PageLikeRepository extends Repository<PageLike> {
|
||||
@ -9,7 +8,7 @@ export class PageLikeRepository extends Repository<PageLike> {
|
||||
src: PageLike['id'] | PageLike,
|
||||
me?: any
|
||||
) {
|
||||
const like = typeof src === 'object' ? src : await this.findOne(src).then(ensure);
|
||||
const like = typeof src === 'object' ? src : await this.findOneOrFail(src);
|
||||
|
||||
return {
|
||||
id: like.id,
|
||||
|
@ -5,7 +5,6 @@ import { Users, DriveFiles, PageLikes } from '..';
|
||||
import { awaitAll } from '../../prelude/await-all';
|
||||
import { DriveFile } from '../entities/drive-file';
|
||||
import { User } from '../entities/user';
|
||||
import { ensure } from '../../prelude/ensure';
|
||||
|
||||
export type PackedPage = SchemaType<typeof packedPageSchema>;
|
||||
|
||||
@ -16,7 +15,7 @@ export class PageRepository extends Repository<Page> {
|
||||
me?: User['id'] | User | null | undefined,
|
||||
): Promise<PackedPage> {
|
||||
const meId = me ? typeof me === 'string' ? me : me.id : null;
|
||||
const page = typeof src === 'object' ? src : await this.findOne(src).then(ensure);
|
||||
const page = typeof src === 'object' ? src : await this.findOneOrFail(src);
|
||||
|
||||
const attachedFiles: Promise<DriveFile | undefined>[] = [];
|
||||
const collectFile = (xs: any[]) => {
|
||||
|
@ -1,14 +1,13 @@
|
||||
import { EntityRepository, Repository } from 'typeorm';
|
||||
import { UserGroupInvitation } from '../entities/user-group-invitation';
|
||||
import { UserGroups } from '..';
|
||||
import { ensure } from '../../prelude/ensure';
|
||||
|
||||
@EntityRepository(UserGroupInvitation)
|
||||
export class UserGroupInvitationRepository extends Repository<UserGroupInvitation> {
|
||||
public async pack(
|
||||
src: UserGroupInvitation['id'] | UserGroupInvitation,
|
||||
) {
|
||||
const invitation = typeof src === 'object' ? src : await this.findOne(src).then(ensure);
|
||||
const invitation = typeof src === 'object' ? src : await this.findOneOrFail(src);
|
||||
|
||||
return {
|
||||
id: invitation.id,
|
||||
|
@ -1,6 +1,5 @@
|
||||
import { EntityRepository, Repository } from 'typeorm';
|
||||
import { UserGroup } from '../entities/user-group';
|
||||
import { ensure } from '../../prelude/ensure';
|
||||
import { UserGroupJoinings } from '..';
|
||||
import { SchemaType } from '../../misc/schema';
|
||||
|
||||
@ -11,7 +10,7 @@ export class UserGroupRepository extends Repository<UserGroup> {
|
||||
public async pack(
|
||||
src: UserGroup['id'] | UserGroup,
|
||||
): Promise<PackedUserGroup> {
|
||||
const userGroup = typeof src === 'object' ? src : await this.findOne(src).then(ensure);
|
||||
const userGroup = typeof src === 'object' ? src : await this.findOneOrFail(src);
|
||||
|
||||
const users = await UserGroupJoinings.find({
|
||||
userGroupId: userGroup.id
|
||||
|
@ -1,6 +1,5 @@
|
||||
import { EntityRepository, Repository } from 'typeorm';
|
||||
import { UserList } from '../entities/user-list';
|
||||
import { ensure } from '../../prelude/ensure';
|
||||
import { UserListJoinings } from '..';
|
||||
import { SchemaType } from '../../misc/schema';
|
||||
|
||||
@ -11,7 +10,7 @@ export class UserListRepository extends Repository<UserList> {
|
||||
public async pack(
|
||||
src: UserList['id'] | UserList,
|
||||
): Promise<PackedUserList> {
|
||||
const userList = typeof src === 'object' ? src : await this.findOne(src).then(ensure);
|
||||
const userList = typeof src === 'object' ? src : await this.findOneOrFail(src);
|
||||
|
||||
const users = await UserListJoinings.find({
|
||||
userListId: userList.id
|
||||
|
@ -2,7 +2,6 @@ import $ from 'cafy';
|
||||
import { EntityRepository, Repository, In, Not } from 'typeorm';
|
||||
import { User, ILocalUser, IRemoteUser } from '../entities/user';
|
||||
import { Emojis, Notes, NoteUnreads, FollowRequests, Notifications, MessagingMessages, UserNotePinings, Followings, Blockings, Mutings, UserProfiles, UserSecurityKeys, UserGroupJoinings, Pages, Announcements, AnnouncementReads, Antennas, AntennaNotes, ChannelFollowings, Instances } from '..';
|
||||
import { ensure } from '../../prelude/ensure';
|
||||
import config from '../../config';
|
||||
import { SchemaType } from '../../misc/schema';
|
||||
import { awaitAll } from '../../prelude/await-all';
|
||||
@ -157,7 +156,7 @@ export class UserRepository extends Repository<User> {
|
||||
includeSecrets: false
|
||||
}, options);
|
||||
|
||||
const user = typeof src === 'object' ? src : await this.findOne(src).then(ensure);
|
||||
const user = typeof src === 'object' ? src : await this.findOneOrFail(src);
|
||||
const meId = me ? typeof me === 'string' ? me : me.id : null;
|
||||
|
||||
const relation = meId && (meId !== user.id) && opts.detail ? await this.getRelation(meId, user.id) : null;
|
||||
@ -165,7 +164,7 @@ export class UserRepository extends Repository<User> {
|
||||
where: { userId: user.id },
|
||||
order: { id: 'DESC' }
|
||||
}) : [];
|
||||
const profile = opts.detail ? await UserProfiles.findOne(user.id).then(ensure) : null;
|
||||
const profile = opts.detail ? await UserProfiles.findOneOrFail(user.id) : null;
|
||||
|
||||
const falsy = opts.detail ? false : undefined;
|
||||
|
||||
@ -213,6 +212,7 @@ export class UserRepository extends Repository<User> {
|
||||
description: profile!.description,
|
||||
location: profile!.location,
|
||||
birthday: profile!.birthday,
|
||||
lang: profile!.lang,
|
||||
fields: profile!.fields,
|
||||
followersCount: user.followersCount,
|
||||
followingCount: user.followingCount,
|
||||
@ -258,7 +258,8 @@ export class UserRepository extends Repository<User> {
|
||||
hasPendingReceivedFollowRequest: this.getHasPendingReceivedFollowRequest(user.id),
|
||||
integrations: profile!.integrations,
|
||||
mutedWords: profile!.mutedWords,
|
||||
mutingNotificationTypes: profile?.mutingNotificationTypes,
|
||||
mutingNotificationTypes: profile!.mutingNotificationTypes,
|
||||
emailNotificationTypes: profile!.emailNotificationTypes,
|
||||
} : {}),
|
||||
|
||||
...(opts.includeSecrets ? {
|
||||
|
@ -1,10 +0,0 @@
|
||||
/**
|
||||
* 値が null または undefined の場合はエラーを発生させ、そうでない場合は値をそのまま返します
|
||||
*/
|
||||
export function ensure<T>(x: T): NonNullable<T> {
|
||||
if (x == null) {
|
||||
throw new Error('ぬるぽ');
|
||||
} else {
|
||||
return x!;
|
||||
}
|
||||
}
|
@ -9,7 +9,6 @@ import { Users, Notes, Polls } from '../../../models';
|
||||
import { MoreThan } from 'typeorm';
|
||||
import { Note } from '../../../models/entities/note';
|
||||
import { Poll } from '../../../models/entities/poll';
|
||||
import { ensure } from '../../../prelude/ensure';
|
||||
|
||||
const logger = queueLogger.createSubLogger('export-notes');
|
||||
|
||||
@ -70,7 +69,7 @@ export async function exportNotes(job: Bull.Job, done: any): Promise<void> {
|
||||
for (const note of notes) {
|
||||
let poll: Poll | undefined;
|
||||
if (note.hasPoll) {
|
||||
poll = await Polls.findOne({ noteId: note.id }).then(ensure);
|
||||
poll = await Polls.findOneOrFail({ noteId: note.id });
|
||||
}
|
||||
const content = JSON.stringify(serialize(note, poll));
|
||||
await new Promise((res, rej) => {
|
||||
|
@ -6,7 +6,6 @@ import { MessagingMessage } from '../../models/entities/messaging-message';
|
||||
import { Notes, Users, UserPublickeys, MessagingMessages } from '../../models';
|
||||
import { IObject, getApId } from './type';
|
||||
import { resolvePerson } from './models/person';
|
||||
import { ensure } from '../../prelude/ensure';
|
||||
import escapeRegexp = require('escape-regexp');
|
||||
|
||||
export default class DbResolver {
|
||||
@ -99,7 +98,7 @@ export default class DbResolver {
|
||||
|
||||
if (user == null) return null;
|
||||
|
||||
const key = await UserPublickeys.findOne(user.id).then(ensure);
|
||||
const key = await UserPublickeys.findOneOrFail(user.id);
|
||||
|
||||
return {
|
||||
user,
|
||||
|
@ -5,7 +5,6 @@ import { fetchMeta } from '../../../misc/fetch-meta';
|
||||
import { apLogger } from '../logger';
|
||||
import { DriveFile } from '../../../models/entities/drive-file';
|
||||
import { DriveFiles } from '../../../models';
|
||||
import { ensure } from '../../../prelude/ensure';
|
||||
|
||||
const logger = apLogger;
|
||||
|
||||
@ -40,7 +39,7 @@ export async function createImage(actor: IRemoteUser, value: any): Promise<Drive
|
||||
uri: image.url
|
||||
});
|
||||
|
||||
file = await DriveFiles.findOne(file.id).then(ensure);
|
||||
file = await DriveFiles.findOneOrFail(file.id);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -21,7 +21,6 @@ import { IObject, getOneApId, getApId, getOneApHrefNullable, validPost, IPost, i
|
||||
import { Emoji } from '../../../models/entities/emoji';
|
||||
import { genId } from '../../../misc/gen-id';
|
||||
import { fetchMeta } from '../../../misc/fetch-meta';
|
||||
import { ensure } from '../../../prelude/ensure';
|
||||
import { getApLock } from '../../../misc/app-lock';
|
||||
import { createMessage } from '../../../services/messages/create';
|
||||
import { parseAudience } from '../audience';
|
||||
@ -201,7 +200,7 @@ export async function createNote(value: string | IObject, resolver?: Resolver, s
|
||||
|
||||
// vote
|
||||
if (reply && reply.hasPoll) {
|
||||
const poll = await Polls.findOne(reply.id).then(ensure);
|
||||
const poll = await Polls.findOneOrFail(reply.id);
|
||||
|
||||
const tryCreateVote = async (name: string, index: number): Promise<null> => {
|
||||
if (poll.expiresAt && Date.now() > new Date(poll.expiresAt).getTime()) {
|
||||
|
@ -24,7 +24,6 @@ import { toPuny } from '../../../misc/convert-host';
|
||||
import { UserProfile } from '../../../models/entities/user-profile';
|
||||
import { validActor } from '../../../remote/activitypub/type';
|
||||
import { getConnection } from 'typeorm';
|
||||
import { ensure } from '../../../prelude/ensure';
|
||||
import { toArray } from '../../../prelude/array';
|
||||
import { fetchInstanceMetadata } from '../../../services/fetch-instance-metadata';
|
||||
import { normalizeForSearch } from '../../../misc/normalize-for-search';
|
||||
@ -457,7 +456,7 @@ export function analyzeAttachments(attachments: IObject | IObject[] | undefined)
|
||||
}
|
||||
|
||||
export async function updateFeatured(userId: User['id']) {
|
||||
const user = await Users.findOne(userId).then(ensure);
|
||||
const user = await Users.findOneOrFail(userId);
|
||||
if (!Users.isRemoteUser(user)) return;
|
||||
if (!user.featured) return;
|
||||
|
||||
|
@ -1,13 +1,12 @@
|
||||
import config from '../../../config';
|
||||
import { Users } from '../../../models';
|
||||
import { User } from '../../../models/entities/user';
|
||||
import { ensure } from '../../../prelude/ensure';
|
||||
|
||||
/**
|
||||
* Convert (local|remote)(Follower|Followee)ID to URL
|
||||
* @param id Follower|Followee ID
|
||||
*/
|
||||
export default async function renderFollowUser(id: User['id']): Promise<any> {
|
||||
const user = await Users.findOne(id).then(ensure);
|
||||
const user = await Users.findOneOrFail(id);
|
||||
return Users.isLocalUser(user) ? `${config.url}/users/${user.id}` : user.uri;
|
||||
}
|
||||
|
@ -4,7 +4,6 @@ import { IActivity } from '../type';
|
||||
import { LdSignature } from '../misc/ld-signature';
|
||||
import { ILocalUser } from '../../../models/entities/user';
|
||||
import { UserKeypairs } from '../../../models';
|
||||
import { ensure } from '../../../prelude/ensure';
|
||||
|
||||
export const renderActivity = (x: any): IActivity | null => {
|
||||
if (x == null) return null;
|
||||
@ -24,9 +23,9 @@ export const renderActivity = (x: any): IActivity | null => {
|
||||
export const attachLdSignature = async (activity: any, user: ILocalUser): Promise<IActivity | null> => {
|
||||
if (activity == null) return null;
|
||||
|
||||
const keypair = await UserKeypairs.findOne({
|
||||
const keypair = await UserKeypairs.findOneOrFail({
|
||||
userId: user.id
|
||||
}).then(ensure);
|
||||
});
|
||||
|
||||
const obj = {
|
||||
// as non-standards
|
||||
|
@ -10,7 +10,6 @@ import { DriveFiles, Notes, Users, Emojis, Polls } from '../../../models';
|
||||
import { In } from 'typeorm';
|
||||
import { Emoji } from '../../../models/entities/emoji';
|
||||
import { Poll } from '../../../models/entities/poll';
|
||||
import { ensure } from '../../../prelude/ensure';
|
||||
|
||||
export default async function renderNote(note: Note, dive = true, isTalk = false): Promise<any> {
|
||||
const getPromisedFiles = async (ids: string[]) => {
|
||||
@ -54,7 +53,7 @@ export default async function renderNote(note: Note, dive = true, isTalk = false
|
||||
}
|
||||
}
|
||||
|
||||
const user = await Users.findOne(note.userId).then(ensure);
|
||||
const user = await Users.findOneOrFail(note.userId);
|
||||
|
||||
const attributedTo = `${config.url}/users/${user.id}`;
|
||||
|
||||
|
@ -9,7 +9,6 @@ import renderEmoji from './emoji';
|
||||
import { IIdentifier } from '../models/identifier';
|
||||
import renderHashtag from './hashtag';
|
||||
import { DriveFiles, UserProfiles, UserKeypairs } from '../../../models';
|
||||
import { ensure } from '../../../prelude/ensure';
|
||||
|
||||
export async function renderPerson(user: ILocalUser) {
|
||||
const id = `${config.url}/users/${user.id}`;
|
||||
@ -18,7 +17,7 @@ export async function renderPerson(user: ILocalUser) {
|
||||
const [avatar, banner, profile] = await Promise.all([
|
||||
user.avatarId ? DriveFiles.findOne(user.avatarId) : Promise.resolve(undefined),
|
||||
user.bannerId ? DriveFiles.findOne(user.bannerId) : Promise.resolve(undefined),
|
||||
UserProfiles.findOne(user.id).then(ensure)
|
||||
UserProfiles.findOneOrFail(user.id)
|
||||
]);
|
||||
|
||||
const attachment: {
|
||||
@ -50,7 +49,7 @@ export async function renderPerson(user: ILocalUser) {
|
||||
...hashtagTags,
|
||||
];
|
||||
|
||||
const keypair = await UserKeypairs.findOne(user.id).then(ensure);
|
||||
const keypair = await UserKeypairs.findOneOrFail(user.id);
|
||||
|
||||
const person = {
|
||||
type: isSystem ? 'Application' : user.isBot ? 'Service' : 'Person',
|
||||
|
@ -6,7 +6,6 @@ import * as crypto from 'crypto';
|
||||
import config from '../../config';
|
||||
import { ILocalUser } from '../../models/entities/user';
|
||||
import { UserKeypairs } from '../../models';
|
||||
import { ensure } from '../../prelude/ensure';
|
||||
import { getAgentByUrl } from '../../misc/fetch';
|
||||
import { URL } from 'url';
|
||||
import got from 'got';
|
||||
@ -23,9 +22,9 @@ export default async (user: ILocalUser, url: string, object: any) => {
|
||||
sha256.update(data);
|
||||
const hash = sha256.digest('base64');
|
||||
|
||||
const keypair = await UserKeypairs.findOne({
|
||||
const keypair = await UserKeypairs.findOneOrFail({
|
||||
userId: user.id
|
||||
}).then(ensure);
|
||||
});
|
||||
|
||||
await new Promise((resolve, reject) => {
|
||||
const req = https.request({
|
||||
@ -75,9 +74,9 @@ export default async (user: ILocalUser, url: string, object: any) => {
|
||||
export async function signedGet(url: string, user: ILocalUser) {
|
||||
const timeout = 10 * 1000;
|
||||
|
||||
const keypair = await UserKeypairs.findOne({
|
||||
const keypair = await UserKeypairs.findOneOrFail({
|
||||
userId: user.id
|
||||
}).then(ensure);
|
||||
});
|
||||
|
||||
const req = got.get<any>(url, {
|
||||
headers: {
|
||||
|
@ -16,7 +16,6 @@ import { isSelfHost } from '../misc/convert-host';
|
||||
import { Notes, Users, Emojis, UserKeypairs, NoteReactions } from '../models';
|
||||
import { ILocalUser, User } from '../models/entities/user';
|
||||
import { In } from 'typeorm';
|
||||
import { ensure } from '../prelude/ensure';
|
||||
import { renderLike } from '../remote/activitypub/renderer/like';
|
||||
|
||||
// Init router
|
||||
@ -136,7 +135,7 @@ router.get('/users/:user/publickey', async ctx => {
|
||||
return;
|
||||
}
|
||||
|
||||
const keypair = await UserKeypairs.findOne(user.id).then(ensure);
|
||||
const keypair = await UserKeypairs.findOneOrFail(user.id);
|
||||
|
||||
if (Users.isLocalUser(user)) {
|
||||
ctx.body = renderActivity(renderKey(user, keypair));
|
||||
|
@ -5,7 +5,6 @@ import renderOrderedCollection from '../../remote/activitypub/renderer/ordered-c
|
||||
import { setResponseType } from '../activitypub';
|
||||
import renderNote from '../../remote/activitypub/renderer/note';
|
||||
import { Users, Notes, UserNotePinings } from '../../models';
|
||||
import { ensure } from '../../prelude/ensure';
|
||||
|
||||
export default async (ctx: Router.RouterContext) => {
|
||||
const userId = ctx.params.user;
|
||||
@ -27,7 +26,7 @@ export default async (ctx: Router.RouterContext) => {
|
||||
});
|
||||
|
||||
const pinnedNotes = await Promise.all(pinings.map(pining =>
|
||||
Notes.findOne(pining.noteId).then(ensure)));
|
||||
Notes.findOneOrFail(pining.noteId)));
|
||||
|
||||
const renderedNotes = await Promise.all(pinnedNotes.map(note => renderNote(note)));
|
||||
|
||||
|
@ -15,7 +15,6 @@ import { Users, Notes } from '../../models';
|
||||
import { makePaginationQuery } from '../api/common/make-pagination-query';
|
||||
import { Brackets } from 'typeorm';
|
||||
import { Note } from '../../models/entities/note';
|
||||
import { ensure } from '../../prelude/ensure';
|
||||
|
||||
export default async (ctx: Router.RouterContext) => {
|
||||
const userId = ctx.params.user;
|
||||
@ -101,7 +100,7 @@ export default async (ctx: Router.RouterContext) => {
|
||||
*/
|
||||
export async function packActivity(note: Note): Promise<any> {
|
||||
if (note.renoteId && note.text == null && !note.hasPoll && (note.fileIds == null || note.fileIds.length === 0)) {
|
||||
const renote = await Notes.findOne(note.renoteId).then(ensure);
|
||||
const renote = await Notes.findOneOrFail(note.renoteId);
|
||||
return renderAnnounce(renote.uri ? renote.uri : `${config.url}/notes/${renote.id}`, note);
|
||||
}
|
||||
|
||||
|
@ -1,7 +1,6 @@
|
||||
import isNativeToken from './common/is-native-token';
|
||||
import { User } from '../../models/entities/user';
|
||||
import { Users, AccessTokens, Apps } from '../../models';
|
||||
import { ensure } from '../../prelude/ensure';
|
||||
import { AccessToken } from '../../models/entities/access-token';
|
||||
|
||||
export default async (token: string): Promise<[User | null | undefined, AccessToken | null | undefined]> => {
|
||||
@ -43,7 +42,7 @@ export default async (token: string): Promise<[User | null | undefined, AccessTo
|
||||
|
||||
if (accessToken.appId) {
|
||||
const app = await Apps
|
||||
.findOne(accessToken.appId).then(ensure);
|
||||
.findOneOrFail(accessToken.appId);
|
||||
|
||||
return [user, {
|
||||
id: accessToken.id,
|
||||
|
@ -3,7 +3,6 @@ import { Note } from '../../../models/entities/note';
|
||||
import { User } from '../../../models/entities/user';
|
||||
import { Notes, UserProfiles, NoteReactions } from '../../../models';
|
||||
import { generateMutedUserQuery } from './generate-muted-user-query';
|
||||
import { ensure } from '../../../prelude/ensure';
|
||||
|
||||
// TODO: リアクション、Renote、返信などをしたノートは除外する
|
||||
|
||||
@ -11,7 +10,7 @@ export async function injectFeatured(timeline: Note[], user?: User | null) {
|
||||
if (timeline.length < 5) return;
|
||||
|
||||
if (user) {
|
||||
const profile = await UserProfiles.findOne(user.id).then(ensure);
|
||||
const profile = await UserProfiles.findOneOrFail(user.id);
|
||||
if (!profile.injectFeaturedNote) return;
|
||||
}
|
||||
|
||||
|
@ -2,7 +2,6 @@ import rndstr from 'rndstr';
|
||||
import { Note } from '../../../models/entities/note';
|
||||
import { User } from '../../../models/entities/user';
|
||||
import { PromoReads, PromoNotes, Notes, Users } from '../../../models';
|
||||
import { ensure } from '../../../prelude/ensure';
|
||||
|
||||
export async function injectPromo(timeline: Note[], user?: User | null) {
|
||||
if (timeline.length < 5) return;
|
||||
@ -23,10 +22,10 @@ export async function injectPromo(timeline: Note[], user?: User | null) {
|
||||
// Pick random promo
|
||||
const promo = promos[Math.floor(Math.random() * promos.length)];
|
||||
|
||||
const note = await Notes.findOne(promo.noteId).then(ensure);
|
||||
const note = await Notes.findOneOrFail(promo.noteId);
|
||||
|
||||
// Join
|
||||
note.user = await Users.findOne(note.userId).then(ensure);
|
||||
note.user = await Users.findOneOrFail(note.userId);
|
||||
|
||||
(note as any)._prId_ = rndstr('a-z0-9', 8);
|
||||
|
||||
|
@ -2,7 +2,6 @@ import $ from 'cafy';
|
||||
import define from '../../../define';
|
||||
import deleteFollowing from '../../../../../services/following/delete';
|
||||
import { Followings, Users } from '../../../../../models';
|
||||
import { ensure } from '../../../../../prelude/ensure';
|
||||
|
||||
export const meta = {
|
||||
tags: ['admin'],
|
||||
@ -23,8 +22,8 @@ export default define(meta, async (ps, me) => {
|
||||
});
|
||||
|
||||
const pairs = await Promise.all(followings.map(f => Promise.all([
|
||||
Users.findOne(f.followerId).then(ensure),
|
||||
Users.findOne(f.followeeId).then(ensure)
|
||||
Users.findOneOrFail(f.followerId),
|
||||
Users.findOneOrFail(f.followeeId)
|
||||
])));
|
||||
|
||||
for (const pair of pairs) {
|
||||
|
@ -22,5 +22,5 @@ export const meta = {
|
||||
};
|
||||
|
||||
export default define(meta, async (ps) => {
|
||||
await sendEmail(ps.to, ps.subject, ps.text);
|
||||
await sendEmail(ps.to, ps.subject, ps.text, ps.text);
|
||||
});
|
||||
|
@ -4,7 +4,6 @@ import define from '../../define';
|
||||
import { ApiError } from '../../error';
|
||||
import { AuthSessions, AccessTokens, Apps } from '../../../../models';
|
||||
import { genId } from '../../../../misc/gen-id';
|
||||
import { ensure } from '../../../../prelude/ensure';
|
||||
import { secureRndstr } from '../../../../misc/secure-rndstr';
|
||||
|
||||
export const meta = {
|
||||
@ -49,7 +48,7 @@ export default define(meta, async (ps, user) => {
|
||||
|
||||
if (exist == null) {
|
||||
// Lookup app
|
||||
const app = await Apps.findOne(session.appId).then(ensure);
|
||||
const app = await Apps.findOneOrFail(session.appId);
|
||||
|
||||
// Generate Hash
|
||||
const sha256 = crypto.createHash('sha256');
|
||||
|
@ -2,7 +2,6 @@ import $ from 'cafy';
|
||||
import define from '../../../define';
|
||||
import { ApiError } from '../../../error';
|
||||
import { Apps, AuthSessions, AccessTokens, Users } from '../../../../../models';
|
||||
import { ensure } from '../../../../../prelude/ensure';
|
||||
|
||||
export const meta = {
|
||||
tags: ['auth'],
|
||||
@ -92,10 +91,10 @@ export default define(meta, async (ps) => {
|
||||
}
|
||||
|
||||
// Lookup access token
|
||||
const accessToken = await AccessTokens.findOne({
|
||||
const accessToken = await AccessTokens.findOneOrFail({
|
||||
appId: app.id,
|
||||
userId: session.userId
|
||||
}).then(ensure);
|
||||
});
|
||||
|
||||
// Delete session
|
||||
AuthSessions.delete(session.id);
|
||||
|
@ -1,6 +1,5 @@
|
||||
import define from '../define';
|
||||
import { RegistryItems, UserProfiles, Users } from '../../../models';
|
||||
import { ensure } from '../../../prelude/ensure';
|
||||
import { genId } from '../../../misc/gen-id';
|
||||
|
||||
export const meta = {
|
||||
@ -25,7 +24,7 @@ export default define(meta, async (ps, user, token) => {
|
||||
const isSecure = token == null;
|
||||
|
||||
// TODO: そのうち消す
|
||||
const profile = await UserProfiles.findOne(user.id).then(ensure);
|
||||
const profile = await UserProfiles.findOneOrFail(user.id);
|
||||
for (const [k, v] of Object.entries(profile.clientData)) {
|
||||
await RegistryItems.insert({
|
||||
id: genId(),
|
||||
|
@ -2,7 +2,6 @@ import $ from 'cafy';
|
||||
import * as speakeasy from 'speakeasy';
|
||||
import define from '../../../define';
|
||||
import { UserProfiles } from '../../../../../models';
|
||||
import { ensure } from '../../../../../prelude/ensure';
|
||||
|
||||
export const meta = {
|
||||
requireCredential: true as const,
|
||||
@ -19,7 +18,7 @@ export const meta = {
|
||||
export default define(meta, async (ps, user) => {
|
||||
const token = ps.token.replace(/\s/g, '');
|
||||
|
||||
const profile = await UserProfiles.findOne(user.id).then(ensure);
|
||||
const profile = await UserProfiles.findOneOrFail(user.id);
|
||||
|
||||
if (profile.twoFactorTempSecret == null) {
|
||||
throw new Error('二段階認証の設定が開始されていません');
|
||||
|
@ -9,7 +9,6 @@ import {
|
||||
AttestationChallenges,
|
||||
Users
|
||||
} from '../../../../../models';
|
||||
import { ensure } from '../../../../../prelude/ensure';
|
||||
import config from '../../../../../config';
|
||||
import { procedures, hash } from '../../../2fa';
|
||||
import { publishMainStream } from '../../../../../services/stream';
|
||||
@ -43,7 +42,7 @@ export const meta = {
|
||||
const rpIdHashReal = hash(Buffer.from(config.hostname, 'utf-8'));
|
||||
|
||||
export default define(meta, async (ps, user) => {
|
||||
const profile = await UserProfiles.findOne(user.id).then(ensure);
|
||||
const profile = await UserProfiles.findOneOrFail(user.id);
|
||||
|
||||
// Compare password
|
||||
const same = await bcrypt.compare(ps.password, profile.password!);
|
||||
|
@ -2,7 +2,6 @@ import $ from 'cafy';
|
||||
import * as bcrypt from 'bcryptjs';
|
||||
import define from '../../../define';
|
||||
import { UserProfiles, AttestationChallenges } from '../../../../../models';
|
||||
import { ensure } from '../../../../../prelude/ensure';
|
||||
import { promisify } from 'util';
|
||||
import * as crypto from 'crypto';
|
||||
import { genId } from '../../../../../misc/gen-id';
|
||||
@ -23,7 +22,7 @@ export const meta = {
|
||||
};
|
||||
|
||||
export default define(meta, async (ps, user) => {
|
||||
const profile = await UserProfiles.findOne(user.id).then(ensure);
|
||||
const profile = await UserProfiles.findOneOrFail(user.id);
|
||||
|
||||
// Compare password
|
||||
const same = await bcrypt.compare(ps.password, profile.password!);
|
||||
|
@ -5,7 +5,6 @@ import * as QRCode from 'qrcode';
|
||||
import config from '../../../../../config';
|
||||
import define from '../../../define';
|
||||
import { UserProfiles } from '../../../../../models';
|
||||
import { ensure } from '../../../../../prelude/ensure';
|
||||
|
||||
export const meta = {
|
||||
requireCredential: true as const,
|
||||
@ -20,7 +19,7 @@ export const meta = {
|
||||
};
|
||||
|
||||
export default define(meta, async (ps, user) => {
|
||||
const profile = await UserProfiles.findOne(user.id).then(ensure);
|
||||
const profile = await UserProfiles.findOneOrFail(user.id);
|
||||
|
||||
// Compare password
|
||||
const same = await bcrypt.compare(ps.password, profile.password!);
|
||||
|
@ -2,7 +2,6 @@ import $ from 'cafy';
|
||||
import * as bcrypt from 'bcryptjs';
|
||||
import define from '../../../define';
|
||||
import { UserProfiles, UserSecurityKeys, Users } from '../../../../../models';
|
||||
import { ensure } from '../../../../../prelude/ensure';
|
||||
import { publishMainStream } from '../../../../../services/stream';
|
||||
|
||||
export const meta = {
|
||||
@ -21,7 +20,7 @@ export const meta = {
|
||||
};
|
||||
|
||||
export default define(meta, async (ps, user) => {
|
||||
const profile = await UserProfiles.findOne(user.id).then(ensure);
|
||||
const profile = await UserProfiles.findOneOrFail(user.id);
|
||||
|
||||
// Compare password
|
||||
const same = await bcrypt.compare(ps.password, profile.password!);
|
||||
|
@ -2,7 +2,6 @@ import $ from 'cafy';
|
||||
import * as bcrypt from 'bcryptjs';
|
||||
import define from '../../../define';
|
||||
import { UserProfiles } from '../../../../../models';
|
||||
import { ensure } from '../../../../../prelude/ensure';
|
||||
|
||||
export const meta = {
|
||||
requireCredential: true as const,
|
||||
@ -17,7 +16,7 @@ export const meta = {
|
||||
};
|
||||
|
||||
export default define(meta, async (ps, user) => {
|
||||
const profile = await UserProfiles.findOne(user.id).then(ensure);
|
||||
const profile = await UserProfiles.findOneOrFail(user.id);
|
||||
|
||||
// Compare password
|
||||
const same = await bcrypt.compare(ps.password, profile.password!);
|
||||
|
@ -2,7 +2,6 @@ import $ from 'cafy';
|
||||
import * as bcrypt from 'bcryptjs';
|
||||
import define from '../../define';
|
||||
import { UserProfiles } from '../../../../models';
|
||||
import { ensure } from '../../../../prelude/ensure';
|
||||
|
||||
export const meta = {
|
||||
requireCredential: true as const,
|
||||
@ -21,7 +20,7 @@ export const meta = {
|
||||
};
|
||||
|
||||
export default define(meta, async (ps, user) => {
|
||||
const profile = await UserProfiles.findOne(user.id).then(ensure);
|
||||
const profile = await UserProfiles.findOneOrFail(user.id);
|
||||
|
||||
// Compare password
|
||||
const same = await bcrypt.compare(ps.currentPassword, profile.password!);
|
||||
|
@ -2,7 +2,6 @@ import $ from 'cafy';
|
||||
import * as bcrypt from 'bcryptjs';
|
||||
import define from '../../define';
|
||||
import { Users, UserProfiles } from '../../../../models';
|
||||
import { ensure } from '../../../../prelude/ensure';
|
||||
import { doPostSuspend } from '../../../../services/suspend-user';
|
||||
|
||||
export const meta = {
|
||||
@ -18,7 +17,7 @@ export const meta = {
|
||||
};
|
||||
|
||||
export default define(meta, async (ps, user) => {
|
||||
const profile = await UserProfiles.findOne(user.id).then(ensure);
|
||||
const profile = await UserProfiles.findOneOrFail(user.id);
|
||||
|
||||
// Compare password
|
||||
const same = await bcrypt.compare(ps.password, profile.password!);
|
||||
|
@ -4,7 +4,6 @@ import { publishMainStream } from '../../../../services/stream';
|
||||
import generateUserToken from '../../common/generate-native-user-token';
|
||||
import define from '../../define';
|
||||
import { Users, UserProfiles } from '../../../../models';
|
||||
import { ensure } from '../../../../prelude/ensure';
|
||||
|
||||
export const meta = {
|
||||
requireCredential: true as const,
|
||||
@ -19,7 +18,7 @@ export const meta = {
|
||||
};
|
||||
|
||||
export default define(meta, async (ps, user) => {
|
||||
const profile = await UserProfiles.findOne(user.id).then(ensure);
|
||||
const profile = await UserProfiles.findOneOrFail(user.id);
|
||||
|
||||
// Compare password
|
||||
const same = await bcrypt.compare(ps.password, profile.password!);
|
||||
|
@ -6,7 +6,6 @@ import config from '../../../../config';
|
||||
import * as ms from 'ms';
|
||||
import * as bcrypt from 'bcryptjs';
|
||||
import { Users, UserProfiles } from '../../../../models';
|
||||
import { ensure } from '../../../../prelude/ensure';
|
||||
import { sendEmail } from '../../../../services/send-email';
|
||||
import { ApiError } from '../../error';
|
||||
|
||||
@ -40,7 +39,7 @@ export const meta = {
|
||||
};
|
||||
|
||||
export default define(meta, async (ps, user) => {
|
||||
const profile = await UserProfiles.findOne(user.id).then(ensure);
|
||||
const profile = await UserProfiles.findOneOrFail(user.id);
|
||||
|
||||
// Compare password
|
||||
const same = await bcrypt.compare(ps.password, profile.password!);
|
||||
@ -72,7 +71,9 @@ export default define(meta, async (ps, user) => {
|
||||
|
||||
const link = `${config.url}/verify-email/${code}`;
|
||||
|
||||
sendEmail(ps.email, 'Email verification', `To verify email, please click this link: ${link}`);
|
||||
sendEmail(ps.email, 'Email verification',
|
||||
`To verify email, please click this link:<br><a href="${link}">${link}</a>`,
|
||||
`To verify email, please click this link: ${link}`);
|
||||
}
|
||||
|
||||
return iObj;
|
||||
|
@ -13,7 +13,6 @@ import { ApiError } from '../../error';
|
||||
import { Users, DriveFiles, UserProfiles, Pages } from '../../../../models';
|
||||
import { User } from '../../../../models/entities/user';
|
||||
import { UserProfile } from '../../../../models/entities/user-profile';
|
||||
import { ensure } from '../../../../prelude/ensure';
|
||||
import { notificationTypes } from '../../../../types';
|
||||
import { normalizeForSearch } from '../../../../misc/normalize-for-search';
|
||||
|
||||
@ -161,6 +160,10 @@ export const meta = {
|
||||
mutingNotificationTypes: {
|
||||
validator: $.optional.arr($.str.or(notificationTypes as unknown as string[]))
|
||||
},
|
||||
|
||||
emailNotificationTypes: {
|
||||
validator: $.optional.arr($.str)
|
||||
},
|
||||
},
|
||||
|
||||
errors: {
|
||||
@ -202,11 +205,11 @@ export default define(meta, async (ps, user, token) => {
|
||||
const updates = {} as Partial<User>;
|
||||
const profileUpdates = {} as Partial<UserProfile>;
|
||||
|
||||
const profile = await UserProfiles.findOne(user.id).then(ensure);
|
||||
const profile = await UserProfiles.findOneOrFail(user.id);
|
||||
|
||||
if (ps.name !== undefined) updates.name = ps.name;
|
||||
if (ps.description !== undefined) profileUpdates.description = ps.description;
|
||||
//if (ps.lang !== undefined) updates.lang = ps.lang;
|
||||
if (ps.lang !== undefined) profileUpdates.lang = ps.lang;
|
||||
if (ps.location !== undefined) profileUpdates.location = ps.location;
|
||||
if (ps.birthday !== undefined) profileUpdates.birthday = ps.birthday;
|
||||
if (ps.avatarId !== undefined) updates.avatarId = ps.avatarId;
|
||||
@ -226,6 +229,7 @@ export default define(meta, async (ps, user, token) => {
|
||||
if (typeof ps.injectFeaturedNote === 'boolean') profileUpdates.injectFeaturedNote = ps.injectFeaturedNote;
|
||||
if (typeof ps.receiveAnnouncementEmail === 'boolean') profileUpdates.receiveAnnouncementEmail = ps.receiveAnnouncementEmail;
|
||||
if (typeof ps.alwaysMarkNsfw === 'boolean') profileUpdates.alwaysMarkNsfw = ps.alwaysMarkNsfw;
|
||||
if (ps.emailNotificationTypes !== undefined) profileUpdates.emailNotificationTypes = ps.emailNotificationTypes;
|
||||
|
||||
if (ps.avatarId) {
|
||||
const avatar = await DriveFiles.findOne(ps.avatarId);
|
||||
|
@ -6,7 +6,6 @@ import * as ms from 'ms';
|
||||
import { getNote } from '../../common/getters';
|
||||
import { ApiError } from '../../error';
|
||||
import { Users } from '../../../../models';
|
||||
import { ensure } from '../../../../prelude/ensure';
|
||||
|
||||
export const meta = {
|
||||
desc: {
|
||||
@ -62,5 +61,5 @@ export default define(meta, async (ps, user) => {
|
||||
}
|
||||
|
||||
// この操作を行うのが投稿者とは限らない(例えばモデレーター)ため
|
||||
await deleteNote(await Users.findOne(note.userId).then(ensure), note);
|
||||
await deleteNote(await Users.findOneOrFail(note.userId), note);
|
||||
});
|
||||
|
@ -13,7 +13,6 @@ import { PollVotes, NoteWatchings, Users, Polls } from '../../../../../models';
|
||||
import { Not } from 'typeorm';
|
||||
import { IRemoteUser } from '../../../../../models/entities/user';
|
||||
import { genId } from '../../../../../misc/gen-id';
|
||||
import { ensure } from '../../../../../prelude/ensure';
|
||||
|
||||
export const meta = {
|
||||
desc: {
|
||||
@ -87,7 +86,7 @@ export default define(meta, async (ps, user) => {
|
||||
throw new ApiError(meta.errors.noPoll);
|
||||
}
|
||||
|
||||
const poll = await Polls.findOne({ noteId: note.id }).then(ensure);
|
||||
const poll = await Polls.findOneOrFail({ noteId: note.id });
|
||||
|
||||
if (poll.expiresAt && poll.expiresAt < createdAt) {
|
||||
throw new ApiError(meta.errors.alreadyExpired);
|
||||
@ -153,7 +152,7 @@ export default define(meta, async (ps, user) => {
|
||||
|
||||
// リモート投票の場合リプライ送信
|
||||
if (note.userHost != null) {
|
||||
const pollOwner = await Users.findOne(note.userId).then(ensure) as IRemoteUser;
|
||||
const pollOwner = await Users.findOneOrFail(note.userId) as IRemoteUser;
|
||||
|
||||
deliver(user, renderActivity(await renderVote(user, vote, note, poll, pollOwner)), pollOwner.inbox);
|
||||
}
|
||||
|
@ -3,7 +3,6 @@ import define from '../../define';
|
||||
import { ApiError } from '../../error';
|
||||
import { Users, UserProfiles } from '../../../../models';
|
||||
import { ID } from '../../../../misc/cafy-id';
|
||||
import { ensure } from '../../../../prelude/ensure';
|
||||
import { toPunyNullable } from '../../../../misc/convert-host';
|
||||
|
||||
export const meta = {
|
||||
@ -51,7 +50,7 @@ export default define(meta, async (ps, me) => {
|
||||
throw new ApiError(meta.errors.noSuchUser);
|
||||
}
|
||||
|
||||
const profile = await UserProfiles.findOne(user.id).then(ensure);
|
||||
const profile = await UserProfiles.findOneOrFail(user.id);
|
||||
|
||||
if (profile.room.furnitures == null) {
|
||||
await UserProfiles.update(user.id, {
|
||||
|
@ -6,7 +6,6 @@ import config from '../../../config';
|
||||
import { Users, Signins, UserProfiles, UserSecurityKeys, AttestationChallenges } from '../../../models';
|
||||
import { ILocalUser } from '../../../models/entities/user';
|
||||
import { genId } from '../../../misc/gen-id';
|
||||
import { ensure } from '../../../prelude/ensure';
|
||||
import { verifyLogin, hash } from '../2fa';
|
||||
import { randomBytes } from 'crypto';
|
||||
|
||||
@ -47,7 +46,7 @@ export default async (ctx: Koa.Context) => {
|
||||
return;
|
||||
}
|
||||
|
||||
const profile = await UserProfiles.findOne(user.id).then(ensure);
|
||||
const profile = await UserProfiles.findOneOrFail(user.id);
|
||||
|
||||
// Compare password
|
||||
const same = await bcrypt.compare(password, profile.password!);
|
||||
|
@ -10,7 +10,6 @@ import signin from '../common/signin';
|
||||
import { fetchMeta } from '../../../misc/fetch-meta';
|
||||
import { Users, UserProfiles } from '../../../models';
|
||||
import { ILocalUser } from '../../../models/entities/user';
|
||||
import { ensure } from '../../../prelude/ensure';
|
||||
|
||||
function getUserToken(ctx: Koa.Context) {
|
||||
return ((ctx.headers['cookie'] || '').match(/igi=(\w+)/) || [null, null])[1];
|
||||
@ -41,12 +40,12 @@ router.get('/disconnect/discord', async ctx => {
|
||||
return;
|
||||
}
|
||||
|
||||
const user = await Users.findOne({
|
||||
const user = await Users.findOneOrFail({
|
||||
host: null,
|
||||
token: userToken
|
||||
}).then(ensure);
|
||||
});
|
||||
|
||||
const profile = await UserProfiles.findOne(user.id).then(ensure);
|
||||
const profile = await UserProfiles.findOneOrFail(user.id);
|
||||
|
||||
delete profile.integrations.discord;
|
||||
|
||||
@ -253,12 +252,12 @@ router.get('/dc/cb', async ctx => {
|
||||
return;
|
||||
}
|
||||
|
||||
const user = await Users.findOne({
|
||||
const user = await Users.findOneOrFail({
|
||||
host: null,
|
||||
token: userToken
|
||||
}).then(ensure);
|
||||
});
|
||||
|
||||
const profile = await UserProfiles.findOne(user.id).then(ensure);
|
||||
const profile = await UserProfiles.findOneOrFail(user.id);
|
||||
|
||||
await UserProfiles.update(user.id, {
|
||||
integrations: {
|
||||
|
@ -10,7 +10,6 @@ import signin from '../common/signin';
|
||||
import { fetchMeta } from '../../../misc/fetch-meta';
|
||||
import { Users, UserProfiles } from '../../../models';
|
||||
import { ILocalUser } from '../../../models/entities/user';
|
||||
import { ensure } from '../../../prelude/ensure';
|
||||
|
||||
function getUserToken(ctx: Koa.Context) {
|
||||
return ((ctx.headers['cookie'] || '').match(/igi=(\w+)/) || [null, null])[1];
|
||||
@ -41,12 +40,12 @@ router.get('/disconnect/github', async ctx => {
|
||||
return;
|
||||
}
|
||||
|
||||
const user = await Users.findOne({
|
||||
const user = await Users.findOneOrFail({
|
||||
host: null,
|
||||
token: userToken
|
||||
}).then(ensure);
|
||||
});
|
||||
|
||||
const profile = await UserProfiles.findOne(user.id).then(ensure);
|
||||
const profile = await UserProfiles.findOneOrFail(user.id);
|
||||
|
||||
delete profile.integrations.github;
|
||||
|
||||
@ -227,12 +226,12 @@ router.get('/gh/cb', async ctx => {
|
||||
return;
|
||||
}
|
||||
|
||||
const user = await Users.findOne({
|
||||
const user = await Users.findOneOrFail({
|
||||
host: null,
|
||||
token: userToken
|
||||
}).then(ensure);
|
||||
});
|
||||
|
||||
const profile = await UserProfiles.findOne(user.id).then(ensure);
|
||||
const profile = await UserProfiles.findOneOrFail(user.id);
|
||||
|
||||
await UserProfiles.update(user.id, {
|
||||
integrations: {
|
||||
|
@ -9,7 +9,6 @@ import signin from '../common/signin';
|
||||
import { fetchMeta } from '../../../misc/fetch-meta';
|
||||
import { Users, UserProfiles } from '../../../models';
|
||||
import { ILocalUser } from '../../../models/entities/user';
|
||||
import { ensure } from '../../../prelude/ensure';
|
||||
|
||||
function getUserToken(ctx: Koa.Context) {
|
||||
return ((ctx.headers['cookie'] || '').match(/igi=(\w+)/) || [null, null])[1];
|
||||
@ -40,12 +39,12 @@ router.get('/disconnect/twitter', async ctx => {
|
||||
return;
|
||||
}
|
||||
|
||||
const user = await Users.findOne({
|
||||
const user = await Users.findOneOrFail({
|
||||
host: null,
|
||||
token: userToken
|
||||
}).then(ensure);
|
||||
});
|
||||
|
||||
const profile = await UserProfiles.findOne(user.id).then(ensure);
|
||||
const profile = await UserProfiles.findOneOrFail(user.id);
|
||||
|
||||
delete profile.integrations.twitter;
|
||||
|
||||
@ -163,12 +162,12 @@ router.get('/tw/cb', async ctx => {
|
||||
|
||||
const result = await twAuth!.done(JSON.parse(twCtx), verifier);
|
||||
|
||||
const user = await Users.findOne({
|
||||
const user = await Users.findOneOrFail({
|
||||
host: null,
|
||||
token: userToken
|
||||
}).then(ensure);
|
||||
});
|
||||
|
||||
const profile = await UserProfiles.findOne(user.id).then(ensure);
|
||||
const profile = await UserProfiles.findOneOrFail(user.id);
|
||||
|
||||
await UserProfiles.update(user.id, {
|
||||
integrations: {
|
||||
|
@ -3,7 +3,6 @@ import config from '../../config';
|
||||
import { User } from '../../models/entities/user';
|
||||
import { Notes, DriveFiles, UserProfiles } from '../../models';
|
||||
import { In } from 'typeorm';
|
||||
import { ensure } from '../../prelude/ensure';
|
||||
|
||||
export default async function(user: User) {
|
||||
const author = {
|
||||
@ -11,7 +10,7 @@ export default async function(user: User) {
|
||||
name: user.name || user.username
|
||||
};
|
||||
|
||||
const profile = await UserProfiles.findOne(user.id).then(ensure);
|
||||
const profile = await UserProfiles.findOneOrFail(user.id);
|
||||
|
||||
const notes = await Notes.find({
|
||||
where: {
|
||||
|
@ -20,7 +20,6 @@ import config from '../../config';
|
||||
import { Users, Notes, Emojis, UserProfiles, Pages, Channels, Clips } from '../../models';
|
||||
import parseAcct from '../../misc/acct/parse';
|
||||
import { getNoteSummary } from '../../misc/get-note-summary';
|
||||
import { ensure } from '../../prelude/ensure';
|
||||
import { getConnection } from 'typeorm';
|
||||
import redis from '../../db/redis';
|
||||
import locales = require('../../../locales');
|
||||
@ -199,7 +198,7 @@ router.get(['/@:user', '/@:user/:sub'], async (ctx, next) => {
|
||||
});
|
||||
|
||||
if (user != null) {
|
||||
const profile = await UserProfiles.findOne(user.id).then(ensure);
|
||||
const profile = await UserProfiles.findOneOrFail(user.id);
|
||||
const meta = await fetchMeta();
|
||||
const me = profile.fields
|
||||
? profile.fields
|
||||
@ -242,7 +241,7 @@ router.get('/notes/:note', async ctx => {
|
||||
|
||||
if (note) {
|
||||
const _note = await Notes.pack(note);
|
||||
const profile = await UserProfiles.findOne(note.userId).then(ensure);
|
||||
const profile = await UserProfiles.findOneOrFail(note.userId);
|
||||
const meta = await fetchMeta();
|
||||
await ctx.render('note', {
|
||||
note: _note,
|
||||
@ -282,7 +281,7 @@ router.get('/@:user/pages/:page', async ctx => {
|
||||
|
||||
if (page) {
|
||||
const _page = await Pages.pack(page);
|
||||
const profile = await UserProfiles.findOne(page.userId).then(ensure);
|
||||
const profile = await UserProfiles.findOneOrFail(page.userId);
|
||||
const meta = await fetchMeta();
|
||||
await ctx.render('page', {
|
||||
page: _page,
|
||||
@ -311,7 +310,7 @@ router.get('/clips/:clip', async ctx => {
|
||||
|
||||
if (clip) {
|
||||
const _clip = await Clips.pack(clip);
|
||||
const profile = await UserProfiles.findOne(clip.userId).then(ensure);
|
||||
const profile = await UserProfiles.findOneOrFail(clip.userId);
|
||||
const meta = await fetchMeta();
|
||||
await ctx.render('clip', {
|
||||
clip: _clip,
|
||||
|
@ -3,7 +3,6 @@ import { Note } from '../models/entities/note';
|
||||
import { AntennaNotes, Mutings, Notes } from '../models';
|
||||
import { genId } from '../misc/gen-id';
|
||||
import { isMutedUserRelated } from '../misc/is-muted-user-related';
|
||||
import { ensure } from '../prelude/ensure';
|
||||
import { publishAntennaStream, publishMainStream } from './stream';
|
||||
import { User } from '../models/entities/user';
|
||||
|
||||
@ -34,10 +33,10 @@ export async function addNoteToAntenna(antenna: Antenna, note: Note, noteUser: U
|
||||
};
|
||||
|
||||
if (note.replyId != null) {
|
||||
_note.reply = await Notes.findOne(note.replyId).then(ensure);
|
||||
_note.reply = await Notes.findOneOrFail(note.replyId);
|
||||
}
|
||||
if (note.renoteId != null) {
|
||||
_note.renote = await Notes.findOne(note.renoteId).then(ensure);
|
||||
_note.renote = await Notes.findOneOrFail(note.renoteId);
|
||||
}
|
||||
|
||||
if (isMutedUserRelated(_note, new Set<string>(mutings.map(x => x.muteeId)))) {
|
||||
|
@ -4,6 +4,7 @@ import { Notifications, Mutings, UserProfiles } from '../models';
|
||||
import { genId } from '../misc/gen-id';
|
||||
import { User } from '../models/entities/user';
|
||||
import { Notification } from '../models/entities/notification';
|
||||
import { sendEmailNotification } from './send-email-notification';
|
||||
|
||||
export async function createNotification(
|
||||
notifieeId: User['id'],
|
||||
@ -38,20 +39,22 @@ export async function createNotification(
|
||||
setTimeout(async () => {
|
||||
const fresh = await Notifications.findOne(notification.id);
|
||||
if (fresh == null) return; // 既に削除されているかもしれない
|
||||
if (!fresh.isRead) {
|
||||
//#region ただしミュートしているユーザーからの通知なら無視
|
||||
const mutings = await Mutings.find({
|
||||
muterId: notifieeId
|
||||
});
|
||||
if (data.notifierId && mutings.map(m => m.muteeId).includes(data.notifierId)) {
|
||||
return;
|
||||
}
|
||||
//#endregion
|
||||
if (fresh.isRead) return;
|
||||
|
||||
publishMainStream(notifieeId, 'unreadNotification', packed);
|
||||
|
||||
pushNotification(notifieeId, 'notification', packed);
|
||||
//#region ただしミュートしているユーザーからの通知なら無視
|
||||
const mutings = await Mutings.find({
|
||||
muterId: notifieeId
|
||||
});
|
||||
if (data.notifierId && mutings.map(m => m.muteeId).includes(data.notifierId)) {
|
||||
return;
|
||||
}
|
||||
//#endregion
|
||||
|
||||
publishMainStream(notifieeId, 'unreadNotification', packed);
|
||||
pushNotification(notifieeId, 'notification', packed);
|
||||
|
||||
if (type === 'follow') sendEmailNotification.follow(notifieeId, data);
|
||||
if (type === 'receiveFollowRequest') sendEmailNotification.receiveFollowRequest(notifieeId, data);
|
||||
}, 2000);
|
||||
|
||||
return notification;
|
||||
|
@ -14,7 +14,6 @@ import { instanceChart, perUserFollowingChart } from '../chart';
|
||||
import { genId } from '../../misc/gen-id';
|
||||
import { createNotification } from '../create-notification';
|
||||
import { isDuplicateKeyValueError } from '../../misc/is-duplicate-key-value-error';
|
||||
import { ensure } from '../../prelude/ensure';
|
||||
|
||||
const logger = new Logger('following/create');
|
||||
|
||||
@ -130,7 +129,7 @@ export default async function(follower: User, followee: User, requestId?: string
|
||||
if (blocked != null) throw new IdentifiableError('3338392a-f764-498d-8855-db939dcf8c48', 'blocked');
|
||||
}
|
||||
|
||||
const followeeProfile = await UserProfiles.findOne(followee.id).then(ensure);
|
||||
const followeeProfile = await UserProfiles.findOneOrFail(followee.id);
|
||||
|
||||
// フォロー対象が鍵アカウントである or
|
||||
// フォロワーがBotであり、フォロー対象がBotからのフォローに慎重である or
|
||||
|
@ -1,7 +1,6 @@
|
||||
import accept from './accept';
|
||||
import { User } from '../../../models/entities/user';
|
||||
import { FollowRequests, Users } from '../../../models';
|
||||
import { ensure } from '../../../prelude/ensure';
|
||||
|
||||
/**
|
||||
* 指定したユーザー宛てのフォローリクエストをすべて承認
|
||||
@ -13,7 +12,7 @@ export default async function(user: User) {
|
||||
});
|
||||
|
||||
for (const request of requests) {
|
||||
const follower = await Users.findOne(request.followerId).then(ensure);
|
||||
const follower = await Users.findOneOrFail(request.followerId);
|
||||
accept(user, follower);
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,4 @@
|
||||
import config from '../../config';
|
||||
import { ensure } from '../../prelude/ensure';
|
||||
import { MessagingMessages, Users } from '../../models';
|
||||
import { MessagingMessage } from '../../models/entities/messaging-message';
|
||||
import { publishGroupMessagingStream, publishMessagingStream } from '../stream';
|
||||
@ -15,8 +14,8 @@ export async function deleteMessage(message: MessagingMessage) {
|
||||
|
||||
async function postDeleteMessage(message: MessagingMessage) {
|
||||
if (message.recipientId) {
|
||||
const user = await Users.findOne(message.userId).then(ensure);
|
||||
const recipient = await Users.findOne(message.recipientId).then(ensure);
|
||||
const user = await Users.findOneOrFail(message.userId);
|
||||
const recipient = await Users.findOneOrFail(message.recipientId);
|
||||
|
||||
if (Users.isLocalUser(user)) publishMessagingStream(message.userId, message.recipientId, 'deleted', message.id);
|
||||
if (Users.isLocalUser(recipient)) publishMessagingStream(message.recipientId, message.userId, 'deleted', message.id);
|
||||
|
@ -26,7 +26,6 @@ import { notesChart, perUserNotesChart, activeUsersChart, instanceChart } from '
|
||||
import { Poll, IPoll } from '../../models/entities/poll';
|
||||
import { createNotification } from '../create-notification';
|
||||
import { isDuplicateKeyValueError } from '../../misc/is-duplicate-key-value-error';
|
||||
import { ensure } from '../../prelude/ensure';
|
||||
import { checkHitAntenna } from '../../misc/check-hit-antenna';
|
||||
import { checkWordMute } from '../../misc/check-word-mute';
|
||||
import { addNoteToAntenna } from '../add-note-to-antenna';
|
||||
@ -200,7 +199,7 @@ export default async (user: User, data: Option, silent = false) => new Promise<N
|
||||
tags = tags.filter(tag => Array.from(tag || '').length <= 128).splice(0, 32);
|
||||
|
||||
if (data.reply && (user.id !== data.reply.userId) && !mentionedUsers.some(u => u.id === data.reply!.userId)) {
|
||||
mentionedUsers.push(await Users.findOne(data.reply.userId).then(ensure));
|
||||
mentionedUsers.push(await Users.findOneOrFail(data.reply.userId));
|
||||
}
|
||||
|
||||
if (data.visibility == 'specified') {
|
||||
@ -213,7 +212,7 @@ export default async (user: User, data: Option, silent = false) => new Promise<N
|
||||
}
|
||||
|
||||
if (data.reply && !data.visibleUsers.some(x => x.id === data.reply!.userId)) {
|
||||
data.visibleUsers.push(await Users.findOne(data.reply.userId).then(ensure));
|
||||
data.visibleUsers.push(await Users.findOneOrFail(data.reply.userId));
|
||||
}
|
||||
}
|
||||
|
||||
|
28
src/services/send-email-notification.ts
Normal file
28
src/services/send-email-notification.ts
Normal file
@ -0,0 +1,28 @@
|
||||
import { UserProfiles } from '../models';
|
||||
import { User } from '../models/entities/user';
|
||||
import { sendEmail } from './send-email';
|
||||
import * as locales from '../../locales/';
|
||||
import { I18n } from '../misc/i18n';
|
||||
|
||||
// TODO: locale ファイルをクライアント用とサーバー用で分けたい
|
||||
|
||||
async function follow(userId: User['id'], args: {}) {
|
||||
const userProfile = await UserProfiles.findOneOrFail({ userId: userId });
|
||||
if (!userProfile.email || !userProfile.emailNotificationTypes.includes('follow')) return;
|
||||
const locale = locales[userProfile.lang || 'ja-JP'];
|
||||
const i18n = new I18n(locale);
|
||||
sendEmail(userProfile.email, i18n.t('_email._follow.title'), 'test', 'test');
|
||||
}
|
||||
|
||||
async function receiveFollowRequest(userId: User['id'], args: {}) {
|
||||
const userProfile = await UserProfiles.findOneOrFail({ userId: userId });
|
||||
if (!userProfile.email || !userProfile.emailNotificationTypes.includes('receiveFollowRequest')) return;
|
||||
const locale = locales[userProfile.lang || 'ja-JP'];
|
||||
const i18n = new I18n(locale);
|
||||
sendEmail(userProfile.email, i18n.t('_email._receiveFollowRequest.title'), 'test', 'test');
|
||||
}
|
||||
|
||||
export const sendEmailNotification = {
|
||||
follow,
|
||||
receiveFollowRequest,
|
||||
};
|
@ -5,9 +5,12 @@ import config from '../config';
|
||||
|
||||
export const logger = new Logger('email');
|
||||
|
||||
export async function sendEmail(to: string, subject: string, text: string) {
|
||||
export async function sendEmail(to: string, subject: string, html: string, text: string) {
|
||||
const meta = await fetchMeta(true);
|
||||
|
||||
const iconUrl = `${config.url}/assets/mi-white.png`;
|
||||
const emailSettingUrl = `${config.url}/settings/email`;
|
||||
|
||||
const enableAuth = meta.smtpUser != null && meta.smtpUser !== '';
|
||||
|
||||
const transporter = nodemailer.createTransport({
|
||||
@ -23,11 +26,93 @@ export async function sendEmail(to: string, subject: string, text: string) {
|
||||
} as any);
|
||||
|
||||
try {
|
||||
// TODO: htmlサニタイズ
|
||||
const info = await transporter.sendMail({
|
||||
from: meta.email!,
|
||||
to: to,
|
||||
subject: subject || 'Misskey',
|
||||
text: text
|
||||
subject: subject,
|
||||
text: text,
|
||||
html: `<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>${ subject }</title>
|
||||
<style>
|
||||
html {
|
||||
background: #eee;
|
||||
}
|
||||
|
||||
body {
|
||||
padding: 16px;
|
||||
margin: 0;
|
||||
font-family: sans-serif;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
a {
|
||||
text-decoration: none;
|
||||
color: #86b300;
|
||||
}
|
||||
a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
main {
|
||||
max-width: 500px;
|
||||
margin: 0 auto;
|
||||
background: #fff;
|
||||
color: #555;
|
||||
}
|
||||
main > header {
|
||||
padding: 32px;
|
||||
background: #86b300;
|
||||
}
|
||||
main > header > img {
|
||||
max-width: 128px;
|
||||
max-height: 28px;
|
||||
vertical-align: bottom;
|
||||
}
|
||||
main > article {
|
||||
padding: 32px;
|
||||
}
|
||||
main > article > h1 {
|
||||
margin: 0 0 1em 0;
|
||||
}
|
||||
main > footer {
|
||||
padding: 32px;
|
||||
border-top: solid 1px #eee;
|
||||
}
|
||||
|
||||
nav {
|
||||
box-sizing: border-box;
|
||||
max-width: 500px;
|
||||
margin: 16px auto 0 auto;
|
||||
padding: 0 32px;
|
||||
}
|
||||
nav > a {
|
||||
color: #888;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<main>
|
||||
<header>
|
||||
<img src="${ meta.logoImageUrl || meta.iconUrl || iconUrl }"/>
|
||||
</header>
|
||||
<article>
|
||||
<h1>${ subject }</h1>
|
||||
<div>${ html }</div>
|
||||
</article>
|
||||
<footer>
|
||||
<a href="${ emailSettingUrl }">${ 'Email setting' }</a>
|
||||
</footer>
|
||||
</main>
|
||||
<nav>
|
||||
<a href="${ config.url }">${ config.host }</a>
|
||||
</nav>
|
||||
</body>
|
||||
</html>
|
||||
`
|
||||
});
|
||||
|
||||
logger.info('Message sent: %s', info.messageId);
|
||||
|
213
yarn.lock
213
yarn.lock
@ -430,12 +430,7 @@
|
||||
"@types/estree" "*"
|
||||
"@types/json-schema" "*"
|
||||
|
||||
"@types/estree@*":
|
||||
version "0.0.45"
|
||||
resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.45.tgz#e9387572998e5ecdac221950dab3e8c3b16af884"
|
||||
integrity sha512-jnqIUKDUqJbDIUxm0Uj7bnlMnRm1T/eZ9N+AVMqhPgzrba2GhGG5o/jCTwmdPK709nEZsGoMzXEDUjcXHa3W0g==
|
||||
|
||||
"@types/estree@^0.0.46":
|
||||
"@types/estree@*", "@types/estree@^0.0.46":
|
||||
version "0.0.46"
|
||||
resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.46.tgz#0fb6bfbbeabd7a30880504993369c4bf1deab1fe"
|
||||
integrity sha512-laIjwTQaD+5DukBZaygQ79K1Z0jb1bPEMRrkXSLjtCcZm+abyp5YbrqpSLzD42FwWW6gK/aS4NYpJ804nG2brg==
|
||||
@ -2370,7 +2365,7 @@ cheerio@^0.22.0:
|
||||
lodash.reject "^4.4.0"
|
||||
lodash.some "^4.4.0"
|
||||
|
||||
chokidar@3.4.3, "chokidar@>=2.0.0 <4.0.0", chokidar@^2.0.0, chokidar@^3.3.1:
|
||||
chokidar@3.5.1, "chokidar@>=2.0.0 <4.0.0", chokidar@^2.0.0, chokidar@^3.3.1:
|
||||
version "3.3.1"
|
||||
resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.3.1.tgz#c84e5b3d18d9a4d77558fef466b1bf16bbeb3450"
|
||||
integrity sha512-4QYCEWOcK3OJrxwvyyAOxFuhpvOVCYkr33LPfFNBjAD/w3sEzWsp2BUOkI4l9bHvWioAd0rc6NlHUOEaWkTeqg==
|
||||
@ -2479,15 +2474,6 @@ cliui@^5.0.0:
|
||||
strip-ansi "^5.2.0"
|
||||
wrap-ansi "^5.1.0"
|
||||
|
||||
cliui@^7.0.0:
|
||||
version "7.0.1"
|
||||
resolved "https://registry.yarnpkg.com/cliui/-/cliui-7.0.1.tgz#a4cb67aad45cd83d8d05128fc9f4d8fbb887e6b3"
|
||||
integrity sha512-rcvHOWyGyid6I1WjT/3NatKj2kDt9OdSHSXpyLXaMWFbKpGACNW8pRhhdPUq9MWUOdwn8Rz9AVETjF4105rZZQ==
|
||||
dependencies:
|
||||
string-width "^4.2.0"
|
||||
strip-ansi "^6.0.0"
|
||||
wrap-ansi "^7.0.0"
|
||||
|
||||
cliui@^7.0.2:
|
||||
version "7.0.4"
|
||||
resolved "https://registry.yarnpkg.com/cliui/-/cliui-7.0.4.tgz#a0265ee655476fc807aea9df3df8df7783808b4f"
|
||||
@ -3207,10 +3193,10 @@ debug@3.1.0, debug@~3.1.0:
|
||||
dependencies:
|
||||
ms "2.0.0"
|
||||
|
||||
debug@4, debug@4.2.0, debug@^4.0.1, debug@^4.1.0, debug@^4.1.1:
|
||||
version "4.2.0"
|
||||
resolved "https://registry.yarnpkg.com/debug/-/debug-4.2.0.tgz#7f150f93920e94c58f5574c2fd01a3110effe7f1"
|
||||
integrity sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg==
|
||||
debug@4, debug@4.3.1, debug@^4.0.1, debug@^4.1.0, debug@^4.1.1:
|
||||
version "4.3.1"
|
||||
resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.1.tgz#f0d229c505e0c6d8c49ac553d1b13dc183f6b2ee"
|
||||
integrity sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==
|
||||
dependencies:
|
||||
ms "2.1.2"
|
||||
|
||||
@ -3396,7 +3382,12 @@ dicer@0.2.5:
|
||||
readable-stream "1.1.x"
|
||||
streamsearch "0.1.2"
|
||||
|
||||
diff@4.0.2, diff@^4.0.1:
|
||||
diff@5.0.0:
|
||||
version "5.0.0"
|
||||
resolved "https://registry.yarnpkg.com/diff/-/diff-5.0.0.tgz#7ed6ad76d859d030787ec35855f5b1daf31d852b"
|
||||
integrity sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==
|
||||
|
||||
diff@^4.0.1:
|
||||
version "4.0.2"
|
||||
resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d"
|
||||
integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==
|
||||
@ -3736,7 +3727,7 @@ es6-weak-map@^2.0.1:
|
||||
es6-iterator "^2.0.3"
|
||||
es6-symbol "^3.1.1"
|
||||
|
||||
escalade@^3.0.2, escalade@^3.1.0:
|
||||
escalade@^3.1.0:
|
||||
version "3.1.0"
|
||||
resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.0.tgz#e8e2d7c7a8b76f6ee64c2181d6b8151441602d4e"
|
||||
integrity sha512-mAk+hPSO8fLDkhV7V0dXazH5pDc6MrjBTPyD3VeKzxnVFjH1MIxbCdqGZB9O8+EwWakZs3ZCbDS4IpRt79V1ig==
|
||||
@ -5578,14 +5569,6 @@ js-tokens@^4.0.0:
|
||||
resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499"
|
||||
integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==
|
||||
|
||||
js-yaml@3.14.0, js-yaml@^3.13.1, js-yaml@^3.14.0:
|
||||
version "3.14.0"
|
||||
resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.0.tgz#a7a34170f26a21bb162424d8adacb4113a69e482"
|
||||
integrity sha512-/4IbIeHcD9VMHFqDR/gQ7EdZdLimOvW2DdcxFjdyyZ9NsbS+ccrXqVWDtab/lRl5AlUqmpBx8EhPaWR+OtY17A==
|
||||
dependencies:
|
||||
argparse "^1.0.7"
|
||||
esprima "^4.0.0"
|
||||
|
||||
js-yaml@4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.0.0.tgz#f426bc0ff4b4051926cd588c71113183409a121f"
|
||||
@ -5593,6 +5576,14 @@ js-yaml@4.0.0:
|
||||
dependencies:
|
||||
argparse "^2.0.1"
|
||||
|
||||
js-yaml@^3.13.1, js-yaml@^3.14.0:
|
||||
version "3.14.0"
|
||||
resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.0.tgz#a7a34170f26a21bb162424d8adacb4113a69e482"
|
||||
integrity sha512-/4IbIeHcD9VMHFqDR/gQ7EdZdLimOvW2DdcxFjdyyZ9NsbS+ccrXqVWDtab/lRl5AlUqmpBx8EhPaWR+OtY17A==
|
||||
dependencies:
|
||||
argparse "^1.0.7"
|
||||
esprima "^4.0.0"
|
||||
|
||||
js-yaml@~3.7.0:
|
||||
version "3.7.0"
|
||||
resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.7.0.tgz#5c967ddd837a9bfdca5f2de84253abe8a1c03b80"
|
||||
@ -6560,35 +6551,35 @@ mkdirp@^1.0.3, mkdirp@^1.0.4, mkdirp@~1.0.3:
|
||||
resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e"
|
||||
integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==
|
||||
|
||||
mocha@8.2.1:
|
||||
version "8.2.1"
|
||||
resolved "https://registry.yarnpkg.com/mocha/-/mocha-8.2.1.tgz#f2fa68817ed0e53343d989df65ccd358bc3a4b39"
|
||||
integrity sha512-cuLBVfyFfFqbNR0uUKbDGXKGk+UDFe6aR4os78XIrMQpZl/nv7JYHcvP5MFIAb374b2zFXsdgEGwmzMtP0Xg8w==
|
||||
mocha@8.3.0:
|
||||
version "8.3.0"
|
||||
resolved "https://registry.yarnpkg.com/mocha/-/mocha-8.3.0.tgz#a83a7432d382ae1ca29686062d7fdc2c36f63fe5"
|
||||
integrity sha512-TQqyC89V1J/Vxx0DhJIXlq9gbbL9XFNdeLQ1+JsnZsVaSOV1z3tWfw0qZmQJGQRIfkvZcs7snQnZnOCKoldq1Q==
|
||||
dependencies:
|
||||
"@ungap/promise-all-settled" "1.1.2"
|
||||
ansi-colors "4.1.1"
|
||||
browser-stdout "1.3.1"
|
||||
chokidar "3.4.3"
|
||||
debug "4.2.0"
|
||||
diff "4.0.2"
|
||||
chokidar "3.5.1"
|
||||
debug "4.3.1"
|
||||
diff "5.0.0"
|
||||
escape-string-regexp "4.0.0"
|
||||
find-up "5.0.0"
|
||||
glob "7.1.6"
|
||||
growl "1.10.5"
|
||||
he "1.2.0"
|
||||
js-yaml "3.14.0"
|
||||
js-yaml "4.0.0"
|
||||
log-symbols "4.0.0"
|
||||
minimatch "3.0.4"
|
||||
ms "2.1.2"
|
||||
nanoid "3.1.12"
|
||||
ms "2.1.3"
|
||||
nanoid "3.1.20"
|
||||
serialize-javascript "5.0.1"
|
||||
strip-json-comments "3.1.1"
|
||||
supports-color "7.2.0"
|
||||
supports-color "8.1.1"
|
||||
which "2.0.2"
|
||||
wide-align "1.1.3"
|
||||
workerpool "6.0.2"
|
||||
yargs "13.3.2"
|
||||
yargs-parser "13.1.2"
|
||||
workerpool "6.1.0"
|
||||
yargs "16.2.0"
|
||||
yargs-parser "20.2.4"
|
||||
yargs-unparser "2.0.0"
|
||||
|
||||
moji@0.5.1:
|
||||
@ -6658,12 +6649,7 @@ nan@^2.14.0, nan@^2.14.2:
|
||||
resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.2.tgz#f5376400695168f4cc694ac9393d0c9585eeea19"
|
||||
integrity sha512-M2ufzIiINKCuDfBSAUr1vWQ+vuVcA9kqx8JJUsbQi6yf1uGRyb7HfpdfUr5qLXf3B/t8dPvcjhKMmlfnP47EzQ==
|
||||
|
||||
nanoid@3.1.12:
|
||||
version "3.1.12"
|
||||
resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.1.12.tgz#6f7736c62e8d39421601e4a0c77623a97ea69654"
|
||||
integrity sha512-1qstj9z5+x491jfiC4Nelk+f8XBad7LN20PmyWINJEMRSf3wcAjAWysw1qaA8z6NSKe2sjq1hRSDpBH5paCb6A==
|
||||
|
||||
nanoid@^3.1.20:
|
||||
nanoid@3.1.20, nanoid@^3.1.20:
|
||||
version "3.1.20"
|
||||
resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.1.20.tgz#badc263c6b1dcf14b71efaa85f6ab4c1d6cfc788"
|
||||
integrity sha512-a1cQNyczgKbLX9jwbS/+d7W8fX/RfgYR7lVWwWOGIPNgK2m0MWvrGF6/m4kk6U3QcFMnZf3RIhL0v2Jgh/0Uxw==
|
||||
@ -6794,10 +6780,10 @@ node-releases@^1.1.61:
|
||||
resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.61.tgz#707b0fca9ce4e11783612ba4a2fcba09047af16e"
|
||||
integrity sha512-DD5vebQLg8jLCOzwupn954fbIiZht05DAZs0k2u8NStSe6h9XdsuIQL8hSRKYiU8WUQRznmSDrKGbv3ObOmC7g==
|
||||
|
||||
nodemailer@6.4.17:
|
||||
version "6.4.17"
|
||||
resolved "https://registry.yarnpkg.com/nodemailer/-/nodemailer-6.4.17.tgz#8de98618028953b80680775770f937243a7d7877"
|
||||
integrity sha512-89ps+SBGpo0D4Bi5ZrxcrCiRFaMmkCt+gItMXQGzEtZVR3uAD3QAQIDoxTWnx3ky0Dwwy/dhFrQ+6NNGXpw/qQ==
|
||||
nodemailer@6.4.18:
|
||||
version "6.4.18"
|
||||
resolved "https://registry.yarnpkg.com/nodemailer/-/nodemailer-6.4.18.tgz#2788c85792844fc17befda019031609017f4b9a1"
|
||||
integrity sha512-ht9cXxQ+lTC+t00vkSIpKHIyM4aXIsQ1tcbQCn5IOnxYHi81W2XOaU66EQBFFpbtzLEBTC94gmkbD4mGZQzVpA==
|
||||
|
||||
nofilter@^1.0.4:
|
||||
version "1.0.4"
|
||||
@ -9752,10 +9738,10 @@ summaly@2.4.0:
|
||||
require-all "2.2.0"
|
||||
trace-redirect "1.0.6"
|
||||
|
||||
supports-color@7.2.0, supports-color@^7.0.0, supports-color@^7.1.0:
|
||||
version "7.2.0"
|
||||
resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da"
|
||||
integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==
|
||||
supports-color@8.1.1:
|
||||
version "8.1.1"
|
||||
resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c"
|
||||
integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==
|
||||
dependencies:
|
||||
has-flag "^4.0.0"
|
||||
|
||||
@ -9785,6 +9771,13 @@ supports-color@^6.1.0:
|
||||
dependencies:
|
||||
has-flag "^3.0.0"
|
||||
|
||||
supports-color@^7.0.0, supports-color@^7.1.0:
|
||||
version "7.2.0"
|
||||
resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da"
|
||||
integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==
|
||||
dependencies:
|
||||
has-flag "^4.0.0"
|
||||
|
||||
sver-compat@^1.5.0:
|
||||
version "1.5.0"
|
||||
resolved "https://registry.yarnpkg.com/sver-compat/-/sver-compat-1.5.0.tgz#3cf87dfeb4d07b4a3f14827bc186b3fd0c645cd8"
|
||||
@ -9917,12 +9910,7 @@ tapable@^1.0.0, tapable@^1.0.0-beta.5:
|
||||
resolved "https://registry.yarnpkg.com/tapable/-/tapable-1.1.3.tgz#a1fccc06b58db61fd7a45da2da44f5f3a3e67ba2"
|
||||
integrity sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==
|
||||
|
||||
tapable@^2.1.1:
|
||||
version "2.1.1"
|
||||
resolved "https://registry.yarnpkg.com/tapable/-/tapable-2.1.1.tgz#b01cc1902d42a7bb30514e320ce21c456f72fd3f"
|
||||
integrity sha512-Wib1S8m2wdpLbmQz0RBEVosIyvb/ykfKXf3ZIDqvWoMg/zTNm6G/tDSuUM61J1kNCDXWJrLHGSFeMhAG+gAGpQ==
|
||||
|
||||
tapable@^2.2.0:
|
||||
tapable@^2.1.1, tapable@^2.2.0:
|
||||
version "2.2.0"
|
||||
resolved "https://registry.yarnpkg.com/tapable/-/tapable-2.2.0.tgz#5c373d281d9c672848213d0e037d1c4165ab426b"
|
||||
integrity sha512-FBk4IesMV1rBxX2tfiK8RAmogtWn53puLOQlvO8XuwlgxcYbP4mVPS9Ph4aeamSyyVjOl24aYWAuc8U5kCVwMw==
|
||||
@ -10395,10 +10383,10 @@ typeorm@0.2.30:
|
||||
yargonaut "^1.1.2"
|
||||
yargs "^16.0.3"
|
||||
|
||||
typescript@4.1.3:
|
||||
version "4.1.3"
|
||||
resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.1.3.tgz#519d582bd94cba0cf8934c7d8e8467e473f53bb7"
|
||||
integrity sha512-B3ZIOf1IKeH2ixgHhj6la6xdwR9QrLC5d1VKeCSY4tvkqhF2eqd9O7txNlS0PO3GrBAFIdr3L1ndNwteUbZLYg==
|
||||
typescript@4.1.5:
|
||||
version "4.1.5"
|
||||
resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.1.5.tgz#123a3b214aaff3be32926f0d8f1f6e704eb89a72"
|
||||
integrity sha512-6OSu9PTIzmn9TCDiovULTnET6BgXtDYL4Gg4szY+cGsc3JP1dQL8qvE8kShTRx1NIw4Q9IBHlwODjkjWEtMUyA==
|
||||
|
||||
uc.micro@^1.0.1, uc.micro@^1.0.5:
|
||||
version "1.0.6"
|
||||
@ -10866,10 +10854,10 @@ webpack-sources@^2.1.1:
|
||||
source-list-map "^2.0.1"
|
||||
source-map "^0.6.1"
|
||||
|
||||
webpack@5.21.1:
|
||||
version "5.21.1"
|
||||
resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.21.1.tgz#a5a13965187deeaa674a0ecea219b61060a2c38f"
|
||||
integrity sha512-H/fjQiDETEZDKoZm/LhvDBxOIKf9rfOdqb2pKTHRvBFMIRtwAwYlPCgBd0gc5xiDG5DqkxAiFZgAF/4H41wMuQ==
|
||||
webpack@5.21.2:
|
||||
version "5.21.2"
|
||||
resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.21.2.tgz#647507e50d3637695be28af58a6a8246050394e7"
|
||||
integrity sha512-xHflCenx+AM4uWKX71SWHhxml5aMXdy2tu/vdi4lClm7PADKxlyDAFFN1rEFzNV0MAoPpHtBeJnl/+K6F4QBPg==
|
||||
dependencies:
|
||||
"@types/eslint-scope" "^3.7.0"
|
||||
"@types/estree" "^0.0.46"
|
||||
@ -10997,10 +10985,10 @@ wordwrap@0.0.2:
|
||||
resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.2.tgz#b79669bb42ecb409f83d583cad52ca17eaa1643f"
|
||||
integrity sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=
|
||||
|
||||
workerpool@6.0.2:
|
||||
version "6.0.2"
|
||||
resolved "https://registry.yarnpkg.com/workerpool/-/workerpool-6.0.2.tgz#e241b43d8d033f1beb52c7851069456039d1d438"
|
||||
integrity sha512-DSNyvOpFKrNusaaUwk+ej6cBj1bmhLcBfj80elGk+ZIo5JSkq+unB1dLKEOcNfJDZgjGICfhQ0Q5TbP0PvF4+Q==
|
||||
workerpool@6.1.0:
|
||||
version "6.1.0"
|
||||
resolved "https://registry.yarnpkg.com/workerpool/-/workerpool-6.1.0.tgz#a8e038b4c94569596852de7a8ea4228eefdeb37b"
|
||||
integrity sha512-toV7q9rWNYha963Pl/qyeZ6wG+3nnsyvolaNUS8+R5Wtw6qJPTxIlOP1ZSvcGhEJw+l3HMMmtiNo9Gl61G4GVg==
|
||||
|
||||
wrap-ansi@^2.0.0:
|
||||
version "2.1.0"
|
||||
@ -11132,11 +11120,6 @@ y18n@^4.0.0:
|
||||
resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.0.tgz#95ef94f85ecc81d007c264e190a120f0a3c8566b"
|
||||
integrity sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==
|
||||
|
||||
y18n@^5.0.1:
|
||||
version "5.0.2"
|
||||
resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.2.tgz#48218df5da2731b4403115c39a1af709c873f829"
|
||||
integrity sha512-CkwaeZw6dQgqgPGeTWKMXCRmMcBgETFlTml1+ZOO+q7kGst8NREJ+eWwFNPVUQ4QGdAaklbqCZHH6Zuep1RjiA==
|
||||
|
||||
y18n@^5.0.5:
|
||||
version "5.0.5"
|
||||
resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.5.tgz#8769ec08d03b1ea2df2500acef561743bbb9ab18"
|
||||
@ -11176,13 +11159,10 @@ yargonaut@^1.1.2:
|
||||
figlet "^1.1.1"
|
||||
parent-require "^1.0.0"
|
||||
|
||||
yargs-parser@13.1.2, yargs-parser@^13.1.2:
|
||||
version "13.1.2"
|
||||
resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-13.1.2.tgz#130f09702ebaeef2650d54ce6e3e5706f7a4fb38"
|
||||
integrity sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==
|
||||
dependencies:
|
||||
camelcase "^5.0.0"
|
||||
decamelize "^1.2.0"
|
||||
yargs-parser@20.2.4, yargs-parser@^20.2.2:
|
||||
version "20.2.4"
|
||||
resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.4.tgz#b42890f14566796f85ae8e3a25290d205f154a54"
|
||||
integrity sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==
|
||||
|
||||
yargs-parser@5.0.0-security.0, yargs-parser@^5.0.0:
|
||||
version "5.0.0-security.0"
|
||||
@ -11192,15 +11172,13 @@ yargs-parser@5.0.0-security.0, yargs-parser@^5.0.0:
|
||||
camelcase "^3.0.0"
|
||||
object.assign "^4.1.0"
|
||||
|
||||
yargs-parser@^20.0.0:
|
||||
version "20.2.1"
|
||||
resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.1.tgz#28f3773c546cdd8a69ddae68116b48a5da328e77"
|
||||
integrity sha512-yYsjuSkjbLMBp16eaOt7/siKTjNVjMm3SoJnIg3sEh/JsvqVVDyjRKmaJV4cl+lNIgq6QEco2i3gDebJl7/vLA==
|
||||
|
||||
yargs-parser@^20.2.2:
|
||||
version "20.2.4"
|
||||
resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.4.tgz#b42890f14566796f85ae8e3a25290d205f154a54"
|
||||
integrity sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==
|
||||
yargs-parser@^13.1.2:
|
||||
version "13.1.2"
|
||||
resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-13.1.2.tgz#130f09702ebaeef2650d54ce6e3e5706f7a4fb38"
|
||||
integrity sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==
|
||||
dependencies:
|
||||
camelcase "^5.0.0"
|
||||
decamelize "^1.2.0"
|
||||
|
||||
yargs-unparser@2.0.0:
|
||||
version "2.0.0"
|
||||
@ -11212,7 +11190,20 @@ yargs-unparser@2.0.0:
|
||||
flat "^5.0.2"
|
||||
is-plain-obj "^2.1.0"
|
||||
|
||||
yargs@13.3.2, yargs@^13.2.4:
|
||||
yargs@16.2.0, yargs@^16.0.0, yargs@^16.0.3:
|
||||
version "16.2.0"
|
||||
resolved "https://registry.yarnpkg.com/yargs/-/yargs-16.2.0.tgz#1c82bf0f6b6a66eafce7ef30e376f49a12477f66"
|
||||
integrity sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==
|
||||
dependencies:
|
||||
cliui "^7.0.2"
|
||||
escalade "^3.1.1"
|
||||
get-caller-file "^2.0.5"
|
||||
require-directory "^2.1.1"
|
||||
string-width "^4.2.0"
|
||||
y18n "^5.0.5"
|
||||
yargs-parser "^20.2.2"
|
||||
|
||||
yargs@^13.2.4:
|
||||
version "13.3.2"
|
||||
resolved "https://registry.yarnpkg.com/yargs/-/yargs-13.3.2.tgz#ad7ffefec1aa59565ac915f82dccb38a9c31a2dd"
|
||||
integrity sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==
|
||||
@ -11228,32 +11219,6 @@ yargs@13.3.2, yargs@^13.2.4:
|
||||
y18n "^4.0.0"
|
||||
yargs-parser "^13.1.2"
|
||||
|
||||
yargs@^16.0.0:
|
||||
version "16.2.0"
|
||||
resolved "https://registry.yarnpkg.com/yargs/-/yargs-16.2.0.tgz#1c82bf0f6b6a66eafce7ef30e376f49a12477f66"
|
||||
integrity sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==
|
||||
dependencies:
|
||||
cliui "^7.0.2"
|
||||
escalade "^3.1.1"
|
||||
get-caller-file "^2.0.5"
|
||||
require-directory "^2.1.1"
|
||||
string-width "^4.2.0"
|
||||
y18n "^5.0.5"
|
||||
yargs-parser "^20.2.2"
|
||||
|
||||
yargs@^16.0.3:
|
||||
version "16.0.3"
|
||||
resolved "https://registry.yarnpkg.com/yargs/-/yargs-16.0.3.tgz#7a919b9e43c90f80d4a142a89795e85399a7e54c"
|
||||
integrity sha512-6+nLw8xa9uK1BOEOykaiYAJVh6/CjxWXK/q9b5FpRgNslt8s22F2xMBqVIKgCRjNgGvGPBy8Vog7WN7yh4amtA==
|
||||
dependencies:
|
||||
cliui "^7.0.0"
|
||||
escalade "^3.0.2"
|
||||
get-caller-file "^2.0.5"
|
||||
require-directory "^2.1.1"
|
||||
string-width "^4.2.0"
|
||||
y18n "^5.0.1"
|
||||
yargs-parser "^20.0.0"
|
||||
|
||||
yargs@^7.1.0:
|
||||
version "7.1.0"
|
||||
resolved "https://registry.yarnpkg.com/yargs/-/yargs-7.1.0.tgz#6ba318eb16961727f5d284f8ea003e8d6154d0c8"
|
||||
|
Loading…
Reference in New Issue
Block a user