diff --git a/.config/example.yml b/.config/example.yml index 38d5e59ea..ef91c86f5 100644 --- a/.config/example.yml +++ b/.config/example.yml @@ -15,10 +15,7 @@ url: https://example.tld/ #───┘ Port and TLS settings └─────────────────────────────────── # -# Misskey supports two deployment options for public. -# - -# Option 1: With Reverse Proxy +# Misskey requires a reverse proxy to support HTTPS connections. # # +----- https://example.tld/ ------------+ # +------+ |+-------------+ +----------------+| @@ -26,30 +23,12 @@ url: https://example.tld/ # +------+ |+-------------+ +----------------+| # +---------------------------------------+ # -# You need to setup reverse proxy. (eg. nginx) -# You do not define 'https' section. +# You need to set up a reverse proxy. (e.g. nginx) +# An encrypted connection with HTTPS is highly recommended +# because tokens may be transferred in GET requests. -# Option 2: Standalone -# -# +- https://example.tld/ -+ -# +------+ | +---------------+ | -# | User | ---> | | Misskey (443) | | -# +------+ | +---------------+ | -# +------------------------+ -# -# You need to run Misskey as root. -# You need to set Certificate in 'https' section. - -# To use option 1, uncomment below line. -#port: 3000 # A port that your Misskey server should listen. - -# To use option 2, uncomment below lines. -#port: 443 - -#https: -# # path for certification -# key: /etc/letsencrypt/live/example.tld/privkey.pem -# cert: /etc/letsencrypt/live/example.tld/fullchain.pem +# The port that your Misskey server should listen on. +port: 3000 # ┌──────────────────────────┐ #───┘ PostgreSQL configuration └──────────────────────────────── @@ -155,6 +134,9 @@ id: 'aid' # Media Proxy #mediaProxy: https://example.com/proxy +# Proxy remote files (default: false) +#proxyRemoteFiles: true + # Sign to ActivityPub GET request (default: false) #signToActivityPubGet: true diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 1de4615f5..79ca97dfa 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -1,10 +1,7 @@ - - # What diff --git a/.node-version b/.node-version index 53a42214a..bf79505bb 100644 --- a/.node-version +++ b/.node-version @@ -1 +1 @@ -v16.13.2 +v16.14.0 diff --git a/CHANGELOG.md b/CHANGELOG.md index 89f070909..7f9d09546 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,37 @@ You should also include the user name that made the change. --> +## 12.108.0 (2022/03/09) + +### NOTE +このバージョンからNode v16.14.0以降が必要です + +### Changes +- ノートの最大文字数を設定できる機能が廃止され、デフォルトで一律3000文字になりました @syuilo +- Misskey can no longer terminate HTTPS connections. @Johann150 + - If you did not use a reverse proxy (e.g. nginx) before, you will probably need to adjust + your configuration file and set up a reverse proxy. The `https` configuration key is no + longer recognized! + +### Improvements +- インスタンスデフォルトテーマを設定できるように @syuilo +- ミュートに期限を設定できるように @syuilo +- アンケートが終了したときに通知が作成されるように @syuilo +- プロフィールの追加情報を最大16まで保存できるように @syuilo +- 連合チャートにPub&Subを追加 @syuilo +- 連合チャートにActiveを追加 @syuilo +- デフォルトで10秒以上時間がかかるデータベースへのクエリは中断されるように @syuilo + - 設定ファイルの`db.extra`に`statement_timeout`を設定することでタイムアウト時間を変更できます +- Client: スプラッシュスクリーンにインスタンスのアイコンを表示するように @syuilo + +### Bugfixes +- Client: リアクションピッカーの高さが低くなったまま戻らないことがあるのを修正 @syuilo +- Client: ユーザー名オートコンプリートが正しく動作しない問題を修正 @syuilo +- Client: タッチ操作だとウィジェットの編集がしにくいのを修正 @xianonn +- Client: register_note_view_interruptor()が動かないのを修正 @syuilo +- Client: iPhone X以降(?)でページの内容が全て表示しきれないのを修正 @tamaina +- Client: fix image caption on mobile @nullobsi + ## 12.107.0 (2022/02/12) ### Improvements diff --git a/Dockerfile b/Dockerfile index 9a651b6c2..e4959756e 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM node:16.13.2-alpine3.15 AS base +FROM node:16.14.0-alpine3.15 AS base ENV NODE_ENV=production diff --git a/README.md b/README.md index 799be299d..c7bc9ef21 100644 --- a/README.md +++ b/README.md @@ -48,7 +48,7 @@ ## Sponsors
- RSS3 + RSS3
## Backers diff --git a/locales/ar-SA.yml b/locales/ar-SA.yml index 914a16bb2..def791f9d 100644 --- a/locales/ar-SA.yml +++ b/locales/ar-SA.yml @@ -32,7 +32,7 @@ uploading: "يرفع..." save: "حفظ" users: "المستخدمون" addUser: "اضافة مستخدم" -favorite: "إضافة إلى المفضلة" +favorite: "أضفها للمفضلة" favorites: "المفضلات" unfavorite: "إزالة من المفضلة" favorited: "أُضيف إلى المفضلة." @@ -106,6 +106,7 @@ clickToShow: "اضغط للعرض" sensitive: "محتوى حساس" add: "إضافة" reaction: "التفاعلات" +reactionSetting: "التفاعلات المراد عرضها في منتقي التفاعلات." reactionSettingDescription2: "اسحب لترتيب ، انقر للحذف ، استخدم \"+\" للإضافة." rememberNoteVisibility: "تذكر إعدادت مدى رؤية الملاحظات" attachCancel: "أزل المرفق" @@ -139,6 +140,8 @@ flagAsBot: "علّمه كحساب آلي" flagAsBotDescription: "فعّل هذا الخيار إذا كان هذا الحساب يُدار عبر برمجية. إذا فُعل فسيكون بمثابة علامة للمطورين الآخرين لتجنب سلاسل لا متناهية من التفاعل بين حسابات الآلية وضبط أنظمة ميسكي للتعامل مع هذا الحساب كآلي." flagAsCat: "علّم هذا الحساب كحساب قط" flagAsCatDescription: "فعّل هذا الخيار لوضع علامة على الحساب لتوضيح أنه حساب قط." +flagShowTimelineReplies: "أظهر التعليقات في الخيط الزمني" +flagShowTimelineRepliesDescription: "يظهر الردود في الخط الزمني" autoAcceptFollowed: "اقبل طلبات المتابعة تلقائيا من الحسابات المتابَعة" addAccount: "أضف حساباً" loginFailed: "فشل الولوج" @@ -230,6 +233,8 @@ resetAreYouSure: "هل تريد إعادة التعيين؟" saved: "حُفظ" messaging: "المحادثة" upload: "ارفع" +keepOriginalUploading: "ابق الصورة الأصلية" +keepOriginalUploadingDescription: "يحفظ الصور المرفوعة على حالتها الأصلية، وان عطّل ستولد نسخة مخصصة من الصورة." fromDrive: "من المخزن" fromUrl: "عبر رابط" uploadFromUrl: "ارفع عبر رابط" @@ -276,6 +281,7 @@ emptyDrive: "قرص التخزين فارغ" emptyFolder: "هذا المجلد فارغ" unableToDelete: "لا يمكن حذفه" inputNewFileName: "ادخل الإسم الجديد للملف" +inputNewDescription: "أدخل تعليقًا توضيحيًا" inputNewFolderName: "ادخل الإسم الجديد للمجلد" circularReferenceFolder: "المجلد المستهدف ينتمي للمجلد الذي تريد حذفه" hasChildFilesOrFolders: "الان الملف غير فارغ. لا يمكن حذفه" @@ -315,8 +321,6 @@ disablingTimelinesInfo: "سيتمكن المديرون والمشرفون من registration: "إنشاء حساب" enableRegistration: "تفعيل إنشاء الحسابات الجديدة" invite: "دعوة" -proxyRemoteFiles: "جلب الملفات البعيدة عبر وكيل" -proxyRemoteFilesDescription: "إذا فُعّل هذا الإعداد ، ستُجلب الملفات البعيدة غير الموجودة في التخزين المحلي للخادم عبر وكيل وتُنشأ لها صور مصغرة. لن يأثر على تخزين الخادم." driveCapacityPerLocalAccount: "حصة التخزين لكل مستخدم محلي" driveCapacityPerRemoteAccount: "حصة التخزين لكل مستخدم بعيد" inMb: "بالميغابايت" @@ -345,6 +349,7 @@ name: "الإسم" antennaSource: "مصدر الهوائي" antennaKeywords: "الكلمات المفتاحية للإستقبال" antennaExcludeKeywords: "الكلمات المفتاحية المستثناة" +antennaKeywordsDescription: "افصل بينهم بمسافة لاستخدام معامل \"و\" أو بسطر لاستخدام معامل \"أو\"" notifyAntenna: "نبهني بصول ملاحظات جديدة" withFileAntenna: "ملاحظات تحوي ملفات فقط" antennaUsersDescription: "اكتب اسم مستخدم لكل سطر" @@ -410,7 +415,6 @@ next: "التالية" retype: "أعد الكتابة" noteOf: "ملاحظات {user}" inviteToGroup: "دعوة إلى فريق" -maxNoteTextLength: "حد عدد المحارف لكل ملاحظة" quoteAttached: "اِقتُبسَ" quoteQuestion: "أتريد تضمينها كاقتباس" noMessagesYet: "ليس هناك رسائل بعد" @@ -469,6 +473,7 @@ hideThisNote: "إخفاء هذه الملاحظة" showFeaturedNotesInTimeline: "أظهر الملاحظات الشائعة في الخيط الزمني" objectStorageBaseUrl: "الرابط الأساسي" objectStoragePrefix: "البادئة" +objectStoragePrefixDesc: "ستُحفظ الملفات في مجلدات تحوي اسماءها هذه البادئة." objectStorageEndpoint: "نقطة النهاية" objectStorageRegion: "المنطقة" objectStorageUseSSL: "استخدم SSL" @@ -630,7 +635,10 @@ experimentalFeatures: "ميّزات اختبارية" developer: "المطور" makeExplorable: "أظهر الحساب في صفحة \"استكشاف\"" makeExplorableDescription: "بتعطيل هذا الخيار لن يظهر حسابك في صفحة \"استكشاف\"" +wide: "عريض" +narrow: "رفيع" reloadToApplySetting: "سيُطبق هذا الإعداد بعد إعادة تحميل الصفحة، أتريد إعادة تحميلها الآن؟" +needReloadToApply: "سيطبق هذا بعد إعادة التحميل." showTitlebar: "اعرض شريط العنوان" clearCache: "امسح التخزين المؤقت" onlineUsersCount: "{n} مستخدم متصل" @@ -661,6 +669,7 @@ capacity: "السعة" inUse: "مستخدم" editCode: "حرر الشفرة" apply: "تطبيق" +receiveAnnouncementFromInstance: "استلم إشعارات من هذا المثيل" emailNotification: "إشعارات البريد الكتروني" inChannelSearch: "ابحث عن قناة" useReactionPickerForContextMenu: "افتح منتقي التفاعلات عند النقر بالزر الأيمن" @@ -674,6 +683,7 @@ unlikeConfirm: "أتريد إلغاء إعجابك؟" fullView: "ملء الشاشة" quitFullView: "اخرج من وضع ملء للشاشة" addDescription: "أضف وصفًا" +userPagePinTip: "لعرض ملاحظة هنا اختر \"دبسها على الصفحة الشخصية\" من قائمة تلك الملاحظة." notSpecifiedMentionWarning: "في الملاحظة ذكر لمستخدمين لن يستلموها." info: "عن" userInfo: "معلومات المستخدم" @@ -748,11 +758,30 @@ makeReactionsPublicDescription: "هذا سيجعل قائمة تفاعلاتك classic: "تقليدي" muteThread: "اكتم النقاش" unmuteThread: "ارفع الكتم عن النقاش" +ffVisibility: "مرئية المتابِعين/المتابَعين" +ffVisibilityDescription: "يسمح لك بتحديد من يمكنهم رؤية متابِعيك ومتابَعيك." deleteAccountConfirm: "سيحذف حسابك نهائيًا، أتريد المتابعة؟" incorrectPassword: "كلمة السر خاطئة." +voteConfirm: "متيقِّن من تصويتك لـ {choice}؟" hide: "إخفاء" leaveGroup: "مغادرة الفريق" +leaveGroupConfirm: "متيقن من مغادرة \"{name}\"؟" welcomeBackWithName: "مرحبًا بك مجددًا {name}" +clickToFinishEmailVerification: "انقر [{ok}] لاستيثاق بريدك الإلكتروني." +overridedDeviceKind: "نوع الجهاز" +smartphone: "هاتف ذكي" +tablet: "جهاز لوحي" +auto: "تلقائي" +themeColor: "لون السمة" +size: "الحجم" +numberOfColumn: "عدد الأعمدة" +searchByGoogle: "غوغل" +mutePeriod: "مدة الكتم" +indefinitely: "أبدًا" +tenMinutes: "10 دقائق" +oneHour: "ساعة" +oneDay: "يوم" +oneWeek: "أسبوع" _emailUnavailable: used: "هذا البريد الإلكتروني مستخدم" format: "صيغة البريد الإلكتروني غير صالحة" @@ -775,6 +804,7 @@ _accountDelete: inProgress: "عملية الحذف جارية" _ad: back: "رجوع" + reduceFrequencyOfThisAd: "قلل عرض هذا الإعلان" _forgotPassword: enterEmail: "أدخل البريد الإلكتروني المرتبط بحسابك لكي يرسل إليك رابط لإعادة تعيين كلمة المرور." ifNoEmail: "إذا لم تربط حسابك ببريد إلكتروني سيتوجب عليك التواصل مع مدير الموقع." @@ -801,7 +831,7 @@ _registry: createKey: "أنشئ مفتاحًا" _aboutMisskey: about: "ميسكي هو برمجية مفتوحة المصدر يطورها syuilo منذ 2014." - contributors: "المساهم الرئيسي" + contributors: "المساهمون الرئيسيون" allContributors: "كل المساهمين" source: "الشفرة المصدرية" translation: "ترجم ميسكي" @@ -823,8 +853,11 @@ _mfm: urlDescription: "يمكن عرض الروابط" link: "رابط" bold: "عريض" + boldDescription: "جعل الحروف أثخن لإبرازها." small: "صغير" + smallDescription: "يعرض المحتوى صغيرًا ورفيعًا." center: "وسط" + centerDescription: "يمركز المحتوى في الوَسَط." quote: "اقتبس" emoji: "إيموجي مخصص" search: "البحث" @@ -1088,9 +1121,12 @@ _postForm: quotePlaceholder: "اقتبس هذه الملاحظة…" channelPlaceholder: "انشر في قناة..." _placeholders: + a: "ما الذي تنوي فعله؟" + b: "ماذا يحدث حولك ؟" c: "ما الذي تفكر فيه؟" d: "ما الذي تريد قوله؟" e: "أكتب..." + f: "بانتظارك لتكتب..." _profile: name: "الإسم" username: "اسم المستخدم" @@ -1109,23 +1145,25 @@ _exportOrImport: muteList: "المستخدمون المكتومون" blockingList: "المستخدمون المحجوبون" userLists: "القوائم" + excludeMutingUsers: "استثن الحسابات المكتومة" + excludeInactiveUsers: "استثن المستخدمين الخاملين" _charts: federation: "الفديرالية" apRequest: "الطلبات" - usersIncDec: "اختلاف عدد المستخدمين" + usersIncDec: "تباين عدد المستخدمين" usersTotal: "مجموع عدد المستخدمين والمستخدمات" activeUsers: "المستخدمون النشطون" - notesIncDec: "اختلاف عدد الملاحظات" - localNotesIncDec: "اختلاف عدد الملاحظات المحلية" - remoteNotesIncDec: "اختلاف عدد الملاحظات البعيدة" + notesIncDec: "تباين عدد الملاحظات" + localNotesIncDec: "تباين عدد الملاحظات المحلية" + remoteNotesIncDec: "تباين عدد الملاحظات البعيدة" notesTotal: "إجمالي الملاحظات" - filesIncDec: "اختلاف عدد الملفات" + filesIncDec: "تباين عدد الملفات" filesTotal: "العدد الإجمالي للملفات" _instanceCharts: requests: "الطلبات" - users: "اختلاف عدد المستخدمين" - notes: "اختلاف عدد الملاحظات" - files: "اختلاف عدد الملفات" + users: "تباين عدد المستخدمين" + notes: "تباين عدد الملاحظات" + files: "تباين عدد الملفات" _timelines: home: "الرئيسي" local: "المحلي" @@ -1139,14 +1177,21 @@ _pages: updated: "نجح تعديل الصفحة" deleted: "نجح حذف الصفحة" pageSetting: "إعدادات الصفحة" + nameAlreadyExists: "رابط الصفحة موجود مسبقًا" + invalidNameTitle: "رابط الصفحة ليس صالحًا" + invalidNameText: "تأكد أن عنوان الصفحة ليس فارغًا" + editThisPage: "عدّل هذه الصفحة" viewSource: "اظهر المصدر" viewPage: "اعرض صفحاتك" like: "أعجبني" unlike: "أزل الإعجاب" my: "صفحاتي" + liked: "الصفحات المُعجب بها" featured: "الأكثر شعبية" contents: "المحتوى" + variables: "متغيّرات" title: "العنوان" + url: "رابط الصفحة" summary: "ملخص الصفحة" alignCenter: "توسيط العناصر" hideTitleWhenPinned: "اخف عنوان الصفحة عند تدبيسها في ملف الشخصي" @@ -1401,6 +1446,7 @@ _notification: youReceivedFollowRequest: "تلقيتَ طلب متابعة" yourFollowRequestAccepted: "قُبل طلب المتابعة" youWereInvitedToGroup: "دُعيت إلى فريقٍ" + pollEnded: "ظهرت نتائج الاستطلاع" _types: all: "الكل" follow: "متابِعون جدد" @@ -1409,6 +1455,7 @@ _notification: renote: "أعد النشر" quote: "الاقتباسات" reaction: "التفاعلات" + pollVote: "مصوِت شارك في الاستطلاع" receiveFollowRequest: "طلبات المتابعة المتلقاة" followRequestAccepted: "طلبات المتابعة المقبولة" app: "إشعارات التطبيقات المرتبطة" diff --git a/locales/bn-BD.yml b/locales/bn-BD.yml index 5cc2bb91b..870a16bc0 100644 --- a/locales/bn-BD.yml +++ b/locales/bn-BD.yml @@ -325,8 +325,6 @@ disablingTimelinesInfo: "আপনি এই টাইমলাইনগুল registration: "নিবন্ধন" enableRegistration: "নতুন ব্যাবহারকারী নিবন্ধন চালু করুন" invite: "আমন্ত্রণ" -proxyRemoteFiles: "রিমোট ফাইলসমুহ প্রক্সি করুন" -proxyRemoteFilesDescription: "যখন এই সেটিংটি চালু থাকে, তখন অসংরক্ষিত বা অতিরিক্ত ক্ষমতার কারণে দূরবর্তী ফাইলগুলিকে স্থানীয়ভাবে প্রক্সি করা হবে এবং থাম্বনেলগুলিও তৈরি করা হবে৷ সার্ভার স্টোরেজ ব্যাবহার করে না," driveCapacityPerLocalAccount: "প্রত্যেক স্থানীয় ব্যাবহারকারীর জন্য ড্রাইভের জায়গা" driveCapacityPerRemoteAccount: "প্রত্যেক রিমোট ব্যাবহারকারীর জন্য ড্রাইভের জায়গা" inMb: "মেগাবাইটে লিখুন" @@ -422,7 +420,6 @@ next: "পরবর্তী" retype: "পুনঃ প্রবেশ" noteOf: "{user} এর নোট" inviteToGroup: "গ্রুপে আমন্ত্রণ জানান" -maxNoteTextLength: "নোট এর সর্বোচ্চ দৈর্ঘ্য" quoteAttached: "উদ্ধৃত" quoteQuestion: "উদ্ধৃতি হিসাবে সংযুক্ত করবেন?" noMessagesYet: "কোন মেসেজ নেই" @@ -831,6 +828,10 @@ smartphone: "স্মার্টফোন" tablet: "ট্যাবলেট" auto: "স্বয়ংক্রিয়" themeColor: "থিমের রং" +size: "আকার" +numberOfColumn: "কলামের সংখ্যা" +searchByGoogle: "গুগল" +indefinitely: "অনির্দিষ্ট" _emailUnavailable: used: "এই ইমেইল ঠিকানাটি ইতোমধ্যে ব্যবহৃত হয়েছে" format: "এই ইমেল ঠিকানাটি সঠিকভাবে লিখা হয়নি" diff --git a/locales/ca-ES.yml b/locales/ca-ES.yml new file mode 100644 index 000000000..93c50c72e --- /dev/null +++ b/locales/ca-ES.yml @@ -0,0 +1,25 @@ +--- +_lang_: "Català" +headlineMisskey: "Una xarxa connectada per notes" +search: "Cercar" +notifications: "Notificacions" +username: "Nom d'usuari" +password: "Contrasenya" +forgotPassword: "Contrasenya oblidada" +fetchingAsApObject: "Cercant en el Fediverse..." +ok: "OK" +gotIt: "Ho he entès!" +cancel: "Cancel·lar" +smtpUser: "Nom d'usuari" +smtpPass: "Contrasenya" +_mfm: + search: "Cercar" +_sfx: + notification: "Notificacions" +_widgets: + notifications: "Notificacions" +_profile: + username: "Nom d'usuari" +_deck: + _columns: + notifications: "Notificacions" diff --git a/locales/de-DE.yml b/locales/de-DE.yml index c5bf40740..e70249da1 100644 --- a/locales/de-DE.yml +++ b/locales/de-DE.yml @@ -14,16 +14,16 @@ gotIt: "Verstanden!" cancel: "Abbrechen" enterUsername: "Benutzername eingeben" renotedBy: "Renote von {user}" -noNotes: "Keine Notizen" -noNotifications: "Keine Benachrichtigungen" +noNotes: "Keine Notizen gefunden" +noNotifications: "Keine Benachrichtigungen gefunden" instance: "Instanz" settings: "Einstellungen" basicSettings: "Allgemeine Einstellungen" otherSettings: "Weitere Einstellungen" -openInWindow: "In Fenster öffnen" +openInWindow: "In einem Fenster öffnen" profile: "Profil" timeline: "Chronik" -noAccountDescription: "Dieser Nutzer hat seine Profilbeschreibung noch nicht ausgefüllt." +noAccountDescription: "Dieser Nutzer hat seine Profilbeschreibung noch nicht ausgefüllt" login: "Anmelden" loggingIn: "Du wirst angemeldet …" logout: "Abmelden" @@ -38,8 +38,8 @@ unfavorite: "Aus Favoriten entfernen" favorited: "Zu Favoriten hinzugefügt." alreadyFavorited: "Bereits zu den Favoriten hinzugefügt." cantFavorite: "Hinzufügen zu Favoriten fehlgeschlagen." -pin: "Anheften" -unpin: "Lösen" +pin: "An dein Profil anheften" +unpin: "Von deinem Profil lösen" copyContent: "Inhalt kopieren" copyLink: "Link kopieren" delete: "Löschen" @@ -47,7 +47,7 @@ deleteAndEdit: "Löschen und Bearbeiten" deleteAndEditConfirm: "Möchtest du diese Notiz wirklich löschen und bearbeiten? Alle Reaktionen, Renotes und Antworten dieser Notiz werden verloren gehen." addToList: "Zu Liste hinzufügen" sendMessage: "Nachricht senden" -copyUsername: "Benutzername kopieren" +copyUsername: "Benutzernamen kopieren" searchUser: "Nach einem Benutzer suchen" reply: "Antworten" loadMore: "Mehr laden" @@ -63,12 +63,12 @@ import: "Import" export: "Export" files: "Dateien" download: "Herunterladen" -driveFileDeleteConfirm: "Möchtest du die Datei „{name}“ wirklich löschen? Die zugehörige Notiz wird ebenso verschwinden." +driveFileDeleteConfirm: "Möchtest du die Datei „{name}“ wirklich löschen? Notizen mit dieser Datei werden ebenso verschwinden." unfollowConfirm: "Möchtest du {name} nicht mehr folgen?" exportRequested: "Du hast einen Export angefragt. Dies kann etwas Zeit in Anspruch nehmen. Sobald der Export abgeschlossen ist, wird er deiner Drive hinzugefügt." importRequested: "Du hast einen Import angefragt. Dies kann etwas Zeit in Anspruch nehmen." lists: "Listen" -noLists: "Keine Listen" +noLists: "Keine Listen gefunden" note: "Notiz" notes: "Notizen" following: "Folgt" @@ -79,16 +79,16 @@ manageLists: "Listen verwalten" error: "Fehler" somethingHappened: "Ein Fehler ist aufgetreten" retry: "Wiederholen" -pageLoadError: "Laden der Seite fehlgeschlagen." +pageLoadError: "Die Seite konnte nicht geladen werden." pageLoadErrorDescription: "Dieser Fehler wird meist durch Netzwerkfehler oder den Browser-Cache verursacht. Bitte leere den Cache oder versuche es nach einiger Zeit erneut." serverIsDead: "Dieser Server antwortet nicht. Bitte warte einen Moment und versuche es dann erneut." youShouldUpgradeClient: "Bitte aktualisiere diese Seite, um eine neuere Version deines Clients zu verwenden." -enterListName: "Name der Liste eingeben" +enterListName: "Listennamen eingeben" privacy: "Privatsphäre" makeFollowManuallyApprove: "Follow-Anfragen benötigen Bestätigung" defaultNoteVisibility: "Standardsichtbarkeit" follow: "Folgen" -followRequest: "Follow-Anfrage" +followRequest: "Follow-Anfrage senden" followRequests: "Follow-Anfragen" unfollow: "Nicht mehr folgen" followRequestPending: "Follow-Anfrage ausstehend" @@ -107,11 +107,11 @@ sensitive: "NSFW" add: "Hinzufügen" reaction: "Reaktionen" reactionSetting: "In der Reaktionsauswahl anzuzeigende Reaktionen" -reactionSettingDescription2: "Ziehe zum Anordnen, klicke zum Löschen, drücke + zum Hinzufügen" +reactionSettingDescription2: "Ziehe um Anzuordnen, klicke um zu löschen, drücke „+“ um hinzuzufügen" rememberNoteVisibility: "Notizsichtbarkeit merken" attachCancel: "Anhang entfernen" markAsSensitive: "Als NSFW markieren" -unmarkAsSensitive: "NSFW-Markierung entfernen" +unmarkAsSensitive: "Als nicht NSFW markieren" enterFileName: "Dateinamen eingeben" mute: "Stummschalten" unmute: "Stummschaltung aufheben" @@ -129,20 +129,20 @@ selectWidget: "Widget auswählen" editWidgets: "Widgets bearbeiten" editWidgetsExit: "Fertig" customEmojis: "Benutzerdefinierte Emojis" -emoji: "Emojis" +emoji: "Emoji" emojis: "Emojis" emojiName: "Emoji-Name" emojiUrl: "Emoji-URL" addEmoji: "Emoji hinzufügen" settingGuide: "Empfohlene Einstellung" cacheRemoteFiles: "Dateien von fremden Instanzen im Cache speichern" -cacheRemoteFilesDescription: "Ist diese Einstellung deaktiviert, so werden Dateien fremder Instanzen direkt von dort geladen. Hierdurch wird Speicherplatz auf dem Server gespart, aber durch fehlende Generierung von Vorschaubildern mehr Bandbreite verwendet." +cacheRemoteFilesDescription: "Ist diese Einstellung deaktiviert, so werden Dateien fremder Instanzen direkt von dort geladen. Hierdurch wird Speicherplatz auf diesem Server gespart, aber durch fehlende Generierung von Vorschaubildern mehr Bandbreite verwendet." flagAsBot: "Als Bot markieren" flagAsBotDescription: "Aktiviere diese Option, falls dieses Benutzerkonto durch ein Programm gesteuert wird. Falls aktiviert, agiert es als Flag für andere Entwickler zur Verhinderung von endlosen Kettenreaktionen mit anderen Bots und lässt Misskeys interne Systeme dieses Benutzerkonto als Bot behandeln." flagAsCat: "Als Katze markieren" flagAsCatDescription: "Aktiviere diese Option, um dieses Benutzerkonto als Katze zu markieren." flagShowTimelineReplies: "Antworten in der Chronik anzeigen" -flagShowTimelineRepliesDescription: "Ist diese Option aktiviert, so werden Antworten von Benutzern auf die Notizen anderer Benuzter in der Chronik an angezeigt." +flagShowTimelineRepliesDescription: "Ist diese Option aktiviert, so werden Antworten von Benutzern auf die Notizen anderer Benutzer in der Chronik angezeigt." autoAcceptFollowed: "Follow-Anfragen von Benutzern, denen du folgst, automatisch akzeptieren" addAccount: "Benutzerkonto hinzufügen" loginFailed: "Anmeldung fehlgeschlagen" @@ -151,12 +151,12 @@ general: "Allgemein" wallpaper: "Hintergrund" setWallpaper: "Hintergrund festlegen" removeWallpaper: "Hintergrund entfernen" -searchWith: "Suche: {q}" +searchWith: "Suchen: {q}" youHaveNoLists: "Du hast keine Listen" followConfirm: "Möchtest du {name} wirklich folgen?" proxyAccount: "Proxy-Benutzerkonto" proxyAccountDescription: "Ein Proxy-Benutzerkonto ist ein Benutzerkonto, das sich für Nutzer unter bestimmten Konditionen wie ein Follower aus einer fremden Instanz verhält. Zum Beispiel wird die Aktivität eines Nutzers aus einer fremden Instanz nicht an diese Instanz übermittelt, falls es keinen Benutzer dieser Instanz gibt, der diesem Nutzer aus fremder Instanz folgt. In diesem Fall folgt stattdessen das Proxy-Benutzerkonto." -host: "Host" +host: "Hostname" selectUser: "Benutzer auswählen" recipient: "Empfänger" annotation: "Anmerkung" @@ -194,17 +194,17 @@ blockedInstancesDescription: "Gib die Hostnamen der Instanzen, welche blockiert muteAndBlock: "Stummschaltungen und Blockierungen" mutedUsers: "Stummgeschaltete Benutzer" blockedUsers: "Blockierte Benutzer" -noUsers: "Keine Benutzer" +noUsers: "Keine Benutzer gefunden" editProfile: "Profil bearbeiten" noteDeleteConfirm: "Möchtest du diese Notiz wirklich löschen?" -pinLimitExceeded: "Es können nicht noch mehr Notizen angeheftet werden" -intro: "Misskey Installation abgeschlossen! Lass uns nun ein Administratorkonto erstellen." +pinLimitExceeded: "Du kannst nicht noch mehr Notizen anheften." +intro: "Misskey ist installiert! Lass uns nun ein Administratorkonto einrichten." done: "Fertig" processing: "In Bearbeitung …" preview: "Vorschau" default: "Standard" -noCustomEmojis: "Keine benutzerdefinierten Emojis vorhanden" -noJobs: "Es gibt keine Jobs" +noCustomEmojis: "Keine benutzerdefinierten Emojis gefunden" +noJobs: "Keine Jobs vorhanden" federating: "Wird föderiert" blocked: "Blockiert" suspended: "Gesperrt" @@ -217,10 +217,10 @@ instanceFollowers: "Follower der Instanz" instanceUsers: "Benutzer der Instanz" changePassword: "Passwort ändern" security: "Sicherheit" -retypedNotMatch: "Beide Eingaben stimmen nicht überein." +retypedNotMatch: "Die Eingaben stimmen nicht überein." currentPassword: "Aktuelles Passwort" newPassword: "Neues Passwort" -newPasswordRetype: "Neues Passwort (wiederholen)" +newPasswordRetype: "Neues Passwort bestätigen" attachFile: "Datei anhängen" more: "Mehr!" featured: "Beliebt" @@ -234,7 +234,7 @@ removed: "Erfolgreich gelöscht" removeAreYouSure: "Möchtest du „{x}“ wirklich entfernen?" deleteAreYouSure: "Möchtest du „{x}“ wirklich löschen?" resetAreYouSure: "Wirklich zurücksetzen?" -saved: "Gespeichert" +saved: "Erfolgreich gespeichert" messaging: "Chat" upload: "Hochladen" keepOriginalUploading: "Originalbild speichern" @@ -295,7 +295,7 @@ avatar: "Profilbild" banner: "Banner" nsfw: "NSFW" whenServerDisconnected: "Bei Verbindungsverlust zum Server" -disconnectedFromServer: "Verbindung zum Server wurde getrennt" +disconnectedFromServer: "Die Verbindung zum Server wurde getrennt" reload: "Aktualisieren" doNothing: "Ignorieren" reloadConfirm: "Seite neu laden?" @@ -307,7 +307,7 @@ normal: "Normal" instanceName: "Name der Instanz" instanceDescription: "Beschreibung der Instanz" maintainerName: "Betreiber" -maintainerEmail: "Betreiber-E-Mail" +maintainerEmail: "Betreiber-Email" tosUrl: "URL der Nutzungsbedingungen" thisYear: "Jahr" thisMonth: "Monat" @@ -325,20 +325,18 @@ disablingTimelinesInfo: "Administratoren und Moderatoren haben immer Zugriff auf registration: "Registrieren" enableRegistration: "Registration neuer Benutzer erlauben" invite: "Einladen" -proxyRemoteFiles: "Dateien fremder Instanzen durch Proxy leiten" -proxyRemoteFilesDescription: "Wenn diese Einstellung aktiviert ist, dann werden Dateien von fremdem Instanzen, welche entweder nicht lokal gespeichert sind oder durch Überschreiten des Speicherlimits gelöscht wurden, durch einen Proxy geleitet. Hierbei wird auch ein Vorschaubild generiert. \n Dies hat keinen Effekt auf den Speicherplatz des Servers." -driveCapacityPerLocalAccount: "Drive-Kapazität pro lokales Benutzerkonto" +driveCapacityPerLocalAccount: "Drive-Kapazität pro lokalem Benutzerkonto" driveCapacityPerRemoteAccount: "Drive-Kapazität pro Benutzer fremder Instanzen" inMb: "In Megabytes" iconUrl: "Icon-URL (favicon etc)" bannerUrl: "Banner-URL" backgroundImageUrl: "Hintergrundbild-URL" -basicInfo: "Basisdaten" +basicInfo: "Grundlegende Informationen" pinnedUsers: "Angeheftete Benutzer" pinnedUsersDescription: "Gib durch Leerzeichen getrennte Benutzer an, die an die \"Erkunden\"-Seite angeheftet werden sollen." pinnedPages: "Angeheftete Seiten" -pinnedPagesDescription: "Gib durch Leerzeilen getrennte Pfäde zu Seiten an, die du an die Startseite dieser Instanz anheften möchtest.\n" -pinnedClipId: "ID des angehefteten Clips" +pinnedPagesDescription: "Gib durch Leerzeilen getrennte Pfäde zu Seiten an, die an die Startseite dieser Instanz angeheftet werden sollen.\n" +pinnedClipId: "ID des anzuheftenden Clips" pinnedNotes: "Angeheftete Notizen" hcaptcha: "hCaptcha" enableHcaptcha: "hCaptcha aktivieren" @@ -348,14 +346,14 @@ recaptcha: "reCAPTCHA" enableRecaptcha: "reCAPTCHA aktivieren" recaptchaSiteKey: "Site key" recaptchaSecretKey: "Secret key" -avoidMultiCaptchaConfirm: "Das Verwenden von mehreren Captcha-Systemen kann zu Störungen führen. Möchtest du die anderen Systeme deaktivieren? Du kannst mehrere Systeme aktiviert lassen, in dem du auf Abbrechen drückst." +avoidMultiCaptchaConfirm: "Das Verwenden von mehreren Captcha-Systemen kann zu Störungen führen. Sollen die anderen Systeme deaktiviert werden? Durch Abbrechen können mehrere Systeme aktiviert bleiben." antennas: "Antennen" manageAntennas: "Antennen verwalten" name: "Name" antennaSource: "Antennenquelle" antennaKeywords: "Zu beobachtende Schlüsselwörter" antennaExcludeKeywords: "Zu ignorierende Schlüsselwörter" -antennaKeywordsDescription: "Mit Leerzeichen für eine \"UND\"-Verknüpfung trennen, durch Zeilenumbrüche für eine \"ODER\"-Verknüpfung trennen" +antennaKeywordsDescription: "Zum Nutzen einer \"UND\"-Verknüpfung Einträge mit Leerzeichen trennen, zum Nutzen einer \"ODER\"-Verknüpfung Einträge mit einem Zeilenumbruch trennen" notifyAntenna: "Über neue Notizen benachrichtigen" withFileAntenna: "Nur Notizen mit Dateien" enableServiceworker: "ServiceWorker aktivieren" @@ -376,14 +374,14 @@ recentlyDiscoveredUsers: "Vor kurzem gefundene Benutzer" exploreUsersCount: "Es gibt {count} Benutzer" exploreFediverse: "Das Fediverse erkunden" popularTags: "Beliebte Schlagwörter" -userList: "Listen" +userList: "Liste" about: "Über" aboutMisskey: "Über Misskey" administrator: "Administrator" token: "Token" twoStepAuthentication: "Zwei-Faktor-Authentifizierung" moderator: "Moderator" -nUsersMentioned: "{n} Benutzer reden darüber" +nUsersMentioned: "Von {n} Benutzern erwähnt" securityKey: "Sicherheitsschlüssel" securityKeyName: "Schlüsselname" registerSecurityKey: "Sicherheitsschlüssel registrieren" @@ -391,7 +389,7 @@ lastUsed: "Zuletzt benutzt" unregister: "Deaktivieren" passwordLessLogin: "Passwortloses Anmelden einrichten" resetPassword: "Passwort zurücksetzen" -newPasswordIs: "Das neue Passwort ist \"{password}\"" +newPasswordIs: "Das neue Passwort ist „{password}“" reduceUiAnimation: "Animationen der Benutzeroberfläche reduzieren" share: "Teilen" notFound: "Nicht gefunden" @@ -407,7 +405,7 @@ close: "Schließen" group: "Gruppe" groups: "Gruppen" createGroup: "Gruppe erstellen" -ownedGroups: "Eigene Gruppen" +ownedGroups: "Meine Gruppen" joinedGroups: "Beigetretene Gruppen" invites: "Einladungen" groupName: "Gruppenname" @@ -415,30 +413,29 @@ members: "Mitglieder" transfer: "Übertragen" messagingWithUser: "Privatchat" messagingWithGroup: "Gruppenchat" -title: "Betreff" +title: "Titel" text: "Text" enable: "Aktivieren" next: "Weiter" retype: "Erneut eingeben" noteOf: "Notiz von {user}" inviteToGroup: "Zu Gruppe einladen" -maxNoteTextLength: "Maximale Länge von Notizen" -quoteAttached: "Zitiert" -quoteQuestion: "Als Zitat anfügen?" -noMessagesYet: "Noch keine Nachrichten" +quoteAttached: "Zitat" +quoteQuestion: "Als Zitat anhängen?" +noMessagesYet: "Noch keine Nachrichten vorhanden" newMessageExists: "Du hast eine neue Nachricht" onlyOneFileCanBeAttached: "Es kann pro Nachricht nur eine Datei angehängt werden" -signinRequired: "Anmeldung erforderlich" +signinRequired: "Bitte melde dich an" invitations: "Einladungen" invitationCode: "Einladungscode" -checking: "Wird überprüft..." +checking: "Wird überprüft …" available: "Verfügbar" unavailable: "Unverfügbar" -usernameInvalidFormat: "Klein- und Großbuchstaben, Zahlen sowie Unterstriche sind verwendbar." +usernameInvalidFormat: "Du kannst Klein- und Großbuchstaben, Zahlen sowie Unterstriche verwenden" tooShort: "Zu kurz" tooLong: "Zu lang" weakPassword: "Schwaches Passwort" -normalPassword: "Normales Passwort" +normalPassword: "Durchschnittliches Passwort" strongPassword: "Starkes Passwort" passwordMatched: "Stimmt überein" passwordNotMatched: "Stimmt nicht überein" @@ -454,18 +451,18 @@ useOsNativeEmojis: "Eingebaute Emojis des Betriebssystems benutzen" disableDrawer: "Keine ausfahrbaren Menüs verwenden" youHaveNoGroups: "Keine Gruppen vorhanden" joinOrCreateGroup: "Lass dich zu einer Gruppe einladen oder erstelle deine eigene." -noHistory: "Kein Verlauf" +noHistory: "Kein Verlauf gefunden" signinHistory: "Anmeldungsverlauf" disableAnimatedMfm: "MFM, die Animationen enthalten, deaktivieren" -doing: "In Bearbeitung..." +doing: "In Bearbeitung …" category: "Kategorie" tags: "Schlagwörter" -docSource: "Quelle dieses Dokuments" +docSource: "Quellcode dieses Dokuments" createAccount: "Benutzerkonto erstellen" existingAccount: "Bestehendes Benutzerkonto" regenerate: "Regenerieren" fontSize: "Schriftgröße" -noFollowRequests: "Du hast keine ausstehende Follow-Anfragen" +noFollowRequests: "Keine ausstehenden Follow-Anfragen vorhanden" openImageInNewTab: "Bilder in neuem Tab öffnen" dashboard: "Dashboard" local: "Lokal" @@ -476,25 +473,25 @@ dayOverDayChanges: "Veränderung zu Gestern" appearance: "Aussehen" clientSettings: "Client-Einstellungen" accountSettings: "Benutzerkonto-Einstellungen" -promotion: "Hervorgehoben" -promote: "Hervorheben" +promotion: "Werbung" +promote: "Werbung schalten" numberOfDays: "Anzahl der Tage" hideThisNote: "Diese Notiz verstecken" -showFeaturedNotesInTimeline: "Beliebte Notizen in Chronik anzeigen" +showFeaturedNotesInTimeline: "Beliebte Notizen in der Chronik anzeigen" objectStorage: "Objektspeicher" useObjectStorage: "Objektspeicher verwenden" objectStorageBaseUrl: "Basis-URL" -objectStorageBaseUrlDesc: "Als Referenz verwendete URL. Verwendest du einen CDN oder Proxy, gib dessen URL an. S3: 'https://.s3.amazonaws.com', GCS: 'https://storage.googleapis.com/' etc." +objectStorageBaseUrlDesc: "Die als Referenz verwendete URL. Verwendest du einen CDN oder Proxy, gib dessen URL an. Für S3 verwende 'https://.s3.amazonaws.com'. Für GCS o.ä. verwende 'https://storage.googleapis.com/'." objectStorageBucket: "Bucket" -objectStorageBucketDesc: "Bitte gib den Bucket-Namen an, der bei deinem Anbieter verwendet wird." +objectStorageBucketDesc: "Bitte gib den Namen des Buckets an, der bei deinem Anbieter verwendet wird." objectStoragePrefix: "Prefix" objectStoragePrefixDesc: "Dateien werden in Ordnern unter diesem Prefix gespeichert." objectStorageEndpoint: "Endpoint" -objectStorageEndpointDesc: "Im Falle von S3 leerlassen, für andere Anbieter den relevanten Endpoint im Format \"\" oder \":\" angeben." +objectStorageEndpointDesc: "Im Falle von S3 leerlassen, für andere Anbieter den relevanten Endpoint im Format „“ oder „:“ angeben." objectStorageRegion: "Region" -objectStorageRegionDesc: "Gib eine Region wie z.B. \"xx-east-1\" an. Falls dein Anbieter nicht zwischen Regionen unterscheidet, lass dieses Feld leer oder gib \"us-east-1\" an." +objectStorageRegionDesc: "Gib eine Region wie z.B. „xx-east-1“ an. Falls dein Anbieter nicht zwischen Regionen unterscheidet, lass dieses Feld leer oder gib „us-east-1“ an." objectStorageUseSSL: "SSL verwenden" -objectStorageUseSSLDesc: "Deaktiviere dies, falls du für die API-Verbindungen kein HTTPS verwenden wirst" +objectStorageUseSSLDesc: "Deaktiviere dies, falls du für API-Verbindungen kein HTTPS verwenden wirst" objectStorageUseProxy: "Über Proxy verbinden" objectStorageUseProxyDesc: "Deaktiviere dies, falls du keinen Proxy für den Objektspeicher verwenden wirst" objectStorageSetPublicRead: "Bei Upload auf \"public-read\" stellen" @@ -505,7 +502,7 @@ newNoteRecived: "Es gibt neue Notizen" sounds: "Töne" listen: "Anhören" none: "Nichts" -showInPage: "In Seite anzeigen" +showInPage: "In einer Seite anzeigen" popout: "Pop-Up" volume: "Lautstärke" masterVolume: "Gesamtlautstärke" @@ -524,7 +521,7 @@ sort: "Sortieren" ascendingOrder: "Aufsteigende Reihenfolge" descendingOrder: "Absteigende Reihenfolge" scratchpad: "Testumgebung" -scratchpadDescription: "Die Testumgebung bietet eine Umgebung für AiScript-Experimente. Dort kannst du AiScript schreiben, ausführen sowie dessen Auswirkungen auf Misskey überprüfen." +scratchpadDescription: "Die Testumgebung bietet einen Bereich für AiScript-Experimente. Dort kannst du AiScript schreiben, ausführen sowie dessen Auswirkungen auf Misskey überprüfen." output: "Ausgabe" script: "Skript" disablePagesScript: "AiScript auf Seiten deaktivieren" @@ -547,14 +544,14 @@ addedRelays: "Hinzugefügte Relays" serviceworkerInfo: "Muss für Push-Benachrichtigungen aktiviert sein." deletedNote: "Gelöschte Notiz" invisibleNote: "Private Notiz" -enableInfiniteScroll: "Automatisch mehr Notizen laden" +enableInfiniteScroll: "Automatisch mehr laden" visibility: "Sichtbarkeit" poll: "Umfrage" useCw: "Inhaltswarnung verwenden" enablePlayer: "Video-Player öffnen" disablePlayer: "Video-Player schließen" expandTweet: "Tweet ausklappen" -themeEditor: "Farbthemen-Editor" +themeEditor: "Farbschema-Editor" description: "Beschreibung" describeFile: "Beschreibung hinzufügen" enterFileDescription: "Beschreibung eingeben" @@ -590,13 +587,13 @@ smtpHost: "Host" smtpPort: "Port" smtpUser: "Benutzername" smtpPass: "Passwort" -emptyToDisableSmtpAuth: "Benutzername und Passwort leer lassen um SMTP-Verifizierung zu deaktivieren" +emptyToDisableSmtpAuth: "Benutzername und Passwort leer lassen, um SMTP-Verifizierung zu deaktivieren" smtpSecure: "Für SMTP-Verbindungen implizit SSL/TLS verwenden" -smtpSecureInfo: "Schalte dies aus, falls du STARTTLS verwendest" -testEmail: "Email-Versand testen" -wordMute: "Wort-Stummschaltung" -regexpError: "Regular Expression error" -regexpErrorDescription: "Error in the regular expression on line {line} in your {tab} word mutes:" +smtpSecureInfo: "Schalte dies aus, falls du STARTTLS verwendest." +testEmail: "Emailversand testen" +wordMute: "Wortstummschaltung" +regexpError: "Fehler in einem regulären Ausdruck" +regexpErrorDescription: "Im regulären Ausdruck deiner {tab}en Wortstummschaltungen ist ein Fehler aufgetreten:" instanceMute: "Instanzstummschaltungen" userSaysSomething: "{name} hat etwas gesagt" makeActive: "Aktivieren" @@ -610,11 +607,11 @@ database: "Datenbank" channel: "Kanäle" create: "Erstellen" notificationSetting: "Benachrichtigungseinstellungen" -notificationSettingDesc: "Wähle die Art der anzuzeigenden Benachrichtigung" +notificationSettingDesc: "Wähle die Art der anzuzeigenden Benachrichtigungen." useGlobalSetting: "Globale Einstellung verwenden" -useGlobalSettingDesc: "Ist dies eingeschaltet, so werden die Benachrichtigungseinstellungen deines Benutzerkontos verwendet. Wenn dies ausgeschaltet ist, können individuelle Einstellungen vorgenommen werden." -other: "Andere" -regenerateLoginToken: "Anmeldungstoken regenerieren" +useGlobalSettingDesc: "Ist diese Option aktiviert, werden die Benachrichtigungseinstellungen deines Benutzerkontos verwendet. Durch ausschalten dieser Option können individuelle Einstellungen vorgenommen werden." +other: "Anderes" +regenerateLoginToken: "Anmeldetoken regenerieren" regenerateLoginTokenDescription: "Den zur Anmeldung intern verwendeten Token regenerieren. Normalerweise wird dies nicht benötigt. Bei Regeneration werden alle Geräte ausgeloggt." setMultipleBySeparatingWithSpace: "Trenne Elemente durch ein Leerzeichen um mehrere Einstellungen zu kofigurieren." fileIdOrUrl: "Datei-ID oder URL" @@ -624,7 +621,7 @@ abuseReports: "Meldungen" reportAbuse: "Melden" reportAbuseOf: "{name} melden" fillAbuseReportDescription: "Bitte gib zusätzliche Informationen zu dieser Meldung an. Falls es sich um eine spezielle Notiz handelt, bitte gib dessen URL an." -abuseReported: "Die Meldung wurde versendet. Vielen Dank." +abuseReported: "Deine Meldung wurde versendet. Vielen Dank." reporter: "Melder" reporteeOrigin: "Herkunft des Gemeldeten" reporterOrigin: "Herkunft des Meldenden" @@ -637,18 +634,18 @@ openInSideView: "In Seitenansicht öffnen" defaultNavigationBehaviour: "Standardnavigationsverhalten" editTheseSettingsMayBreakAccount: "Bei Bearbeitung dieser Einstellungen besteht die Gefahr, dein Benutzerkonto zu beschädigen." instanceTicker: "Instanz-Informationen von Notizen" -waitingFor: "Warte auf {x}" +waitingFor: "Warte auf {x} …" random: "Zufällig" system: "System" switchUi: "UI wechseln" desktop: "Desktop" -clip: "Clip" +clip: "Clip erstellen" createNew: "Neu erstellen" optional: "Optional" createNewClip: "Neuen Clip erstellen" public: "Öffentlich" i18nInfo: "Misskey wird durch freiwillige Helfer in viele verschiedene Sprachen übersetzt. Auf {link} kannst du mithelfen." -manageAccessTokens: "Zugriffstoken verwalten" +manageAccessTokens: "Zugriffstokens verwalten" accountInfo: "Benutzerkonto-Informationen" notesCount: "Anzahl der Notizen" repliesCount: "Anzahl gesendeter Antworten" @@ -663,15 +660,15 @@ pollVotesCount: "Anzahl gesendeter Antworten auf Umfragen" pollVotedCount: "Anzahl erhaltener Antworten auf Umfragen" yes: "Ja" no: "Nein" -driveFilesCount: "Anzahl an Drive-Dateien" +driveFilesCount: "Anzahl der Dateien in Drive" driveUsage: "Drive-Auslastung" noCrawle: "Crawler-Indexierung ablehnen" -noCrawleDescription: "Suchmaschinen bitten, die eigene Profilseite, Notizen, Seiten usw. nicht zu indexieren" -lockedAccountInfo: "Auch wenn du Follow-Anfragen auf manuelle Bestätigung setzt, wird jeder deine Notizen öffentlich sehen können, sofern du die Notizsichtbarkeit nicht auf \"Nur Follower\" setzt." +noCrawleDescription: "Suchmaschinen bitten, die eigene Profilseite, Notizen, Seiten usw. nicht zu indexieren." +lockedAccountInfo: "Auch wenn du Follow-Anfragen auf manuelle Bestätigung setzt, wird jede deiner Notizen öffentlich sichtbar sein, sofern du ihre Notizsichtbarkeit nicht auf \"Nur Follower\" setzt." alwaysMarkSensitive: "Medien standardmäßig als NSFW markieren" loadRawImages: "Anstatt Vorschaubilder immer Originalbilder anzeigen" disableShowingAnimatedImages: "Animierte Bilder nicht abspielen" -verificationEmailSent: "Eine Verifizierungsnachricht wurde versendet. Besuche den dort enthaltenen Link, um die Verifizierung abzuschließen." +verificationEmailSent: "Eine Bestätigungsmail wurde an deine Email-Adresse versendet. Besuche den dort enthaltenen Link, um die Verifizierung abzuschließen." notSet: "Nicht konfiguriert" emailVerified: "Email-Adresse bestätigt" noteFavoritesCount: "Anzahl an als Favorit markierter Notizen" @@ -682,12 +679,12 @@ useSystemFont: "Standardschriftart des Systems verwenden" clips: "Clips" experimentalFeatures: "Experimentelle Funktionalitäten" developer: "Entwickler" -makeExplorable: "Benutzerkonto in \"Erkunden\" sichtbar machen" -makeExplorableDescription: "Wenn diese Option deaktiviert ist, ist dein Benutzerkonto nicht im \"Erkunden\"-Bereich sichtbar." +makeExplorable: "Benutzerkonto in „Erkunden“ sichtbar machen" +makeExplorableDescription: "Wenn diese Option deaktiviert ist, ist dein Benutzerkonto nicht im „Erkunden“-Bereich sichtbar." showGapBetweenNotesInTimeline: "Abstände zwischen Notizen auf der Chronik anzeigen" duplicate: "Duplizieren" left: "Links" -center: "Mitte" +center: "Mittig" wide: "Breit" narrow: "Schmal" reloadToApplySetting: "Diese Einstellung tritt nach einer Aktualisierung der Seite in Kraft. Jetzt aktualisieren?" @@ -698,19 +695,19 @@ onlineUsersCount: "{n} Benutzer sind online" nUsers: "{n} Benutzer" nNotes: "{n} Notizen" sendErrorReports: "Fehlerberichte senden" -sendErrorReportsDescription: "Ist diese Option aktiviert, so werden beim Auftreten von Fehlern detaillierte Fehlerinformationen an Misskey weitergegeben, was zur Verbesserung der Qualität von Misskey beiträgt.\nEnthalten in diesen Informationen sind u.a. die Version deines Betriebssystems, welchen Browser du verwendest und ein Verlauf deiner Aktivitäten." -myTheme: "Mein Farbthema" +sendErrorReportsDescription: "Ist diese Option aktiviert, so werden beim Auftreten von Fehlern detaillierte Fehlerinformationen an Misskey weitergegeben, was zur Verbesserung der Qualität von Misskey beiträgt.\nEnthalten in diesen Informationen sind u.a. die Version deines Betriebssystems, welchen Browser du verwendest und ein Verlauf deiner Aktivitäten innerhalb Misskey." +myTheme: "Mein Farbschema" backgroundColor: "Hintergrundfarbe" accentColor: "Akzentfarbe" textColor: "Textfarbe" -saveAs: "Speichern als…" +saveAs: "Speichern als …" advanced: "Fortgeschritten" value: "Wert" createdAt: "Erstellt am" updatedAt: "Zuletzt geändert am" saveConfirm: "Änderungen speichern?" deleteConfirm: "Wirklich löschen?" -invalidValue: "Ungültiger Wert." +invalidValue: "Dieser Wert ist ungültig." registry: "Registry" closeAccount: "Benutzerkonto schließen" currentVersion: "Momentane Version" @@ -723,11 +720,11 @@ inUse: "Verwendet" editCode: "Code bearbeiten" apply: "Anwenden" receiveAnnouncementFromInstance: "Benachrichtigungen von dieser Instanz empfangen" -emailNotification: "E-Mail-Benachrichtigungen" +emailNotification: "Email-Benachrichtigungen" publish: "Veröffentlichen" inChannelSearch: "In Kanal suchen" useReactionPickerForContextMenu: "Reaktionsauswahl durch Rechtsklick öffnen" -typingUsers: "{users} ist/sind am schreiben..." +typingUsers: "{users} ist/sind am schreiben …" jumpToSpecifiedDate: "Zu bestimmtem Datum springen" showingPastTimeline: "Es wird eine alte Chronik angezeigt" clear: "Zurückkehren" @@ -737,19 +734,19 @@ unlikeConfirm: "\"Gefällt mir\" wirklich entfernen?" fullView: "Vollansicht" quitFullView: "Vollansicht verlassen" addDescription: "Beschreibung hinzufügen" -userPagePinTip: "Um Notizen hier erscheinen zu lassen, drücke \"Anheften\" im Menü individueller Notizen." +userPagePinTip: "Um Notizen hier erscheinen zu lassen, drücke \"An dein Profil anheften\" im Menü individueller Notizen." notSpecifiedMentionWarning: "Diese Notiz enthält Erwähnungen von Nutzern, die nicht als Empfänger ausgewählt sind" info: "Über" userInfo: "Benutzerinformation" unknown: "Unbekannt" -onlineStatus: "Online-Status" -hideOnlineStatus: "Online-Status verbergen" -hideOnlineStatusDescription: "Das Verbergen deines Online-Statuses reduziert die Nützlichkeit von Funktionen wie der Suche." +onlineStatus: "Onlinestatus" +hideOnlineStatus: "Onlinestatus verbergen" +hideOnlineStatusDescription: "Das Verbergen deines Onlinestatuses reduziert die Nützlichkeit von Funktionen wie der Suche." online: "Online" active: "Aktiv" offline: "Offline" notRecommended: "Nicht empfohlen" -botProtection: "Bot-Schutz" +botProtection: "Schutz vor Bots" instanceBlocking: "Blockierte Instanzen" selectAccount: "Benutzerkonto auswählen" switchAccount: "Konto wechseln" @@ -761,9 +758,9 @@ administration: "Verwaltung" accounts: "Benutzerkonten" switch: "Wechseln" noMaintainerInformationWarning: "Betreiberinformationen sind nicht konfiguriert." -noBotProtectionWarning: "Bot-Schutz ist nicht konfiguriert." +noBotProtectionWarning: "Schutz vor Bots ist nicht konfiguriert." configure: "Konfigurieren" -postToGallery: "Neuen Galerie-Beitrag erstellen" +postToGallery: "Neuen Galeriebeitrag erstellen" gallery: "Galerie" recentPosts: "Neue Beiträge" popularPosts: "Beliebte Beiträge" @@ -775,7 +772,7 @@ priority: "Priorität" high: "Hoch" middle: "Mittel" low: "Niedrig" -emailNotConfiguredWarning: "Keine Email-Adresse hinterlegt" +emailNotConfiguredWarning: "Keine Email-Adresse hinterlegt." ratio: "Verhältnis" previewNoteText: "Vorschau anzeigen" customCss: "Benutzerdefiniertes CSS" @@ -793,9 +790,9 @@ misskeyUpdated: "Misskey wurde aktualisiert!" whatIsNew: "Änderungen anzeigen" translate: "Übersetzen" translatedFrom: "Aus {x} übersetzt" -accountDeletionInProgress: "Löschung des Benutzerkontos momentan in Bearbeitung" +accountDeletionInProgress: "Die Löschung deines Benutzerkontos ist momentan in Bearbeitung." usernameInfo: "Ein Name, durch den dein Benutzerkonto auf diesem Server identifiziert werden kann. Du kannst das Alphabet (a~z, A~Z), Ziffern (0~9) oder Unterstriche (_) verwenden. Benutzernamen können später nicht geändert werden." -aiChanMode: "Ai Modus" +aiChanMode: "Ai-Modus" keepCw: "Inhaltswarnungen beibehalten" pubSub: "Pub/Sub Benutzerkonten" lastCommunication: "Letzte Kommunikation" @@ -804,7 +801,7 @@ unresolved: "Ungelöst" breakFollow: "Follower entfernen" itsOn: "Eingeschaltet" itsOff: "Ausgeschaltet" -emailRequiredForSignup: "Angaben einer Email-Adresse als benötigt markieren" +emailRequiredForSignup: "Angabe einer Email-Adresse als benötigt markieren" unread: "Ungelesen" filter: "Filter" controlPanel: "Systemsteuerung" @@ -819,10 +816,10 @@ ffVisibilityDescription: "Konfiguriere wer sehen kann, wem du folgst sowie wer d continueThread: "Weiteren Threadverlauf anzeigen" deleteAccountConfirm: "Dein Benutzerkonto wird unwiderruflich gelöscht. Trotzdem fortfahren?" incorrectPassword: "Falsches Passwort." -voteConfirm: "Wirklich für \"{choice}\" abstimmen?" +voteConfirm: "Wirklich für „{choice}“ abstimmen?" hide: "Inhalt verbergen" leaveGroup: "Gruppe verlassen" -leaveGroupConfirm: "Möchtest du \"{name}\" wirklich verlassen?" +leaveGroupConfirm: "Möchtest du „{name}“ wirklich verlassen?" useDrawerReactionPickerForMobile: "Auf mobilen Geräten ausfahrbare Reaktionsauswahl anzeigen" welcomeBackWithName: "Willkommen zurück, {name}" clickToFinishEmailVerification: "Drücke bitte auf [{ok}], um die Email-Bestätigung abzuschließen." @@ -833,6 +830,16 @@ auto: "Automatisch" themeColor: "Instanzfarbe" size: "Größe" numberOfColumn: "Spaltenanzahl" +searchByGoogle: "Googlen" +instanceDefaultLightTheme: "Instanzweites Standardfarbschema (Hell)" +instanceDefaultDarkTheme: "Instanzweites Standardfarbschema (Dunkel)" +instanceDefaultThemeDescription: "Gib den Farbschemencode im Objektformat ein." +mutePeriod: "Stummschaltungsdauer" +indefinitely: "Dauerhaft" +tenMinutes: "10 Minuten" +oneHour: "Eine Stunde" +oneDay: "Einen Tag" +oneWeek: "Eine Woche" _emailUnavailable: used: "Diese Email-Adresse wird bereits verwendet" format: "Das Format dieser Email-Adresse ist ungültig" @@ -845,20 +852,20 @@ _ffVisibility: private: "Privat" _signup: almostThere: "Fast geschafft" - emailAddressInfo: "Bitte gib deine Email-Adresse ein." + emailAddressInfo: "Bitte gib deine Email-Adresse ein. Sie wird nicht öffentlich einsehbar sein." emailSent: "An deine Email-Adresse ({email}) wurde soeben eine Bestätigungsmail geschickt. Bitte klicke auf den enthaltenen Link, um die Erstellung deines Benutzerkontos abzuschließen." _accountDelete: accountDelete: "Benutzerkonto löschen" - mayTakeTime: "Da die Löschung eines Benutzerkontos ein aufwendiger Prozess ist, kann dessen Dauer davon abhängen, wie viel Inhalt in diesem erstellt wurde oder wie viele Dateien hochgeladen wurden." + mayTakeTime: "Da die Löschung eines Benutzerkontos ein aufwendiger Prozess ist, kann dessen Dauer davon abhängen, wie viel Inhalt von diesem erstellt wurde oder wie viele Dateien von diesem hochgeladen wurden." sendEmail: "Sobald die Löschung abgeschlossen ist, wird an die mit ihm verknüpfte Email-Adresse eine Benachrichtigung versendet." - requestAccountDelete: "Löschung des Benutzerkontos anfordern" - started: "Löschung wurde eingeleitet." + requestAccountDelete: "Löschung deines Benutzerkontos anfordern" + started: "Die Löschung wurde eingeleitet." inProgress: "Löschung in Bearbeitung" _ad: back: "Zurück" reduceFrequencyOfThisAd: "Diese Werbung weniger anzeigen" _forgotPassword: - enterEmail: "Gib die Email-Adresse ein, mit der du dich registriert hast. An diese wird ein Link gesendet, mit der du dein Passwort zurücksetzen kannst." + enterEmail: "Gib die Email-Adresse ein, mit der du dich registriert hast. An diese wird ein Link gesendet, mit dem du dein Passwort zurücksetzen kannst." ifNoEmail: "Solltest du bei der Registrierung keine Email-Adresse angegeben haben, wende dich bitte an den Administrator." contactAdmin: "Diese Instanz unterstützt die Verwendung von Email-Adressen nicht. Wende dich an den Administrator, um dein Passwort zurückzusetzen." _gallery: @@ -882,7 +889,7 @@ _registry: domain: "Domain" createKey: "Schlüssel erstellen" _aboutMisskey: - about: "Misskey ist Open-Source-Software die von syuilo seit 2014 entwickelt wird." + about: "Misskey ist Open-Source-Software, welche von syuilo seit 2014 entwickelt wird." contributors: "Hauptmitwirkende" allContributors: "Alle Mitwirkenden" source: "Quellcode" @@ -899,13 +906,13 @@ _mfm: intro: "MFM ist eine Misskey-exklusive Markup-Sprache, die in Misskey an vielen Stellen verwendet werden kann. Hier kannst du eine Liste von verfügbarer MFM-Syntax einsehen." dummy: "Misskey erweitert die Welt des Fediverse" mention: "Erwähnung" - mentionDescription: "Mit At-Zeichen und Nutzername kann ein individueller Nutzer angegeben werden." + mentionDescription: "Mit At-Zeichen und Benutzername kann ein individueller Nutzer angegeben werden." hashtag: "Hashtag" hashtagDescription: "Mit einer Raute und Text kann ein Hashtag angegeben werden." url: "URL" urlDescription: "Zeigt URLs an." link: "Link" - linkDescription: "Spezifische Textabschnitte als URL anzeigen." + linkDescription: "Zeigt spezifische Textabschnitte als URL an." bold: "Fett" boldDescription: "Zeichen zur Betonung dicker erscheinen lassen." small: "Klein" @@ -929,19 +936,19 @@ _mfm: flip: "Spiegelung" flipDescription: "Inhalt horizontal oder vertikal gespiegelt anzeigen." jelly: "Animation (Dehnen)" - jellyDescription: "Verleiht dem Inhalt eine sich dehnende Animation." + jellyDescription: "Verleiht Inhalt eine sich dehnende Animation." tada: "Animation (Tada)" - tadaDescription: "Verleiht eine Animation mit \"Tada!\"-Gefühl" + tadaDescription: "Verleiht Inhalt eine Animation mit \"Tada!\"-Gefühl" jump: "Animation (Sprung)" - jumpDescription: "Verleiht dem Inhalt eine springende Animation." + jumpDescription: "Verleiht Inhalt eine springende Animation." bounce: "Animation (Federn)" - bounceDescription: "Verleiht dem Inhalt eine federnde Animation." + bounceDescription: "Verleiht Inhalt eine federnde Animation." shake: "Animation (Zittern)" - shakeDescription: "Verleiht dem Inhalt eine zitternde Animation." + shakeDescription: "Verleiht Inhalt eine zitternde Animation." twitch: "Animation (Zucken)" - twitchDescription: "Verleiht dem Inhalt eine sehr stark zuckende Animation." + twitchDescription: "Verleiht Inhalt eine sehr stark zuckende Animation." spin: "Animation (Rotieren)" - spinDescription: "Verleiht dem Inhalt eine rotierende Animation." + spinDescription: "Verleiht Inhalt eine rotierende Animation." x2: "Groß" x2Description: "Inhalte größer anzeigen." x3: "Sehr groß" @@ -949,7 +956,7 @@ _mfm: x4: "Unglaublich groß" x4Description: "Lässt Inhalte noch größer als größer als groß angezeigt werden." blur: "Weichzeichnen" - blurDescription: "Inhalte durch Weihzeichnung verschwimmen lassen. Durch das Bewegen des Mauszeigers auf den Inhalt wird er klar angezeigt." + blurDescription: "Inhalte durch Weihzeichnung verschwimmen lassen. Durch das Bewegen des Mauszeigers über den Inhalt wird er klar angezeigt." font: "Schriftart" fontDescription: "Setzt die Schriftart des Inhaltes fest." rainbow: "Regenbogen" @@ -957,7 +964,7 @@ _mfm: sparkle: "Glitzer" sparkleDescription: "Verleiht Inhalt einen glitzernden Partikeleffekt." rotate: "Drehen" - rotateDescription: "Dreht den Inhalt um einen angegebenen Winkel" + rotateDescription: "Dreht den Inhalt um einen angegebenen Winkel." _instanceTicker: none: "Nie anzeigen" remote: "Für Benutzer fremder Instanzen anzeigen" @@ -983,7 +990,7 @@ _menuDisplay: hide: "Ausblenden" _wordMute: muteWords: "Stummgeschaltete Wörter" - muteWordsDescription: "Mit Leerzeichen für eine \"UND\"-Verknüpfung trennen, durch Zeilenumbrüche für eine \"ODER\"-Verknüpfung trennen." + muteWordsDescription: "Zum Nutzen einer \"UND\"-Verknüpfung Einträge mit Leerzeichen trennen, zum Nutzen einer \"ODER\"-Verknüpfung Einträge mit einem Zeilenumbruch trennen." muteWordsDescription2: "Umgib Schlüsselworter mit Schrägstrichen, um Reguläre Ausdrücke zu verwenden." softDescription: "Notizen, die die angegebenen Konditionen erfüllen, in der Chronik ausblenden." hardDescription: "Verhindern, dass Notizen, die die angegebenen Konditionen erfüllen, der Chronik hinzugefügt werden. Zudem werden diese Notizen auch nicht der Chronik hinzugefügt, falls die Konditionen geändert werden." @@ -996,17 +1003,17 @@ _instanceMute: title: "Blendet Notizen von stummgeschalteten Instanzen aus." heading: "Liste der stummzuschaltenden Instanzen" _theme: - explore: "Themen erforschen" - install: "Thema installieren" - manage: "Themaverwaltung" - code: "Themencode" + explore: "Farbschemata erforschen" + install: "Farbschmata installieren" + manage: "Farbschemaverwaltung" + code: "Farbschemencode" description: "Beschreibung" installed: "{name} wurde installiert" - installedThemes: "Installierte Themen" - builtinThemes: "Eingebaute Themen" - alreadyInstalled: "Dieses Thema ist bereits installiert" - invalid: "Der Themencode dieses Themas ist ungültig" - make: "Farbthema erstellen" + installedThemes: "Installierte Farbschemata" + builtinThemes: "Eingebaute Farbschemata" + alreadyInstalled: "Dieses Farbschema ist bereits installiert" + invalid: "Der Code dieses Farbschemas ist ungültig" + make: "Farbschema erstellen" base: "Vorlage" addConstant: "Konstante hinzufügen" constant: "Konstante" @@ -1023,7 +1030,7 @@ _theme: darken: "Verdunkeln" lighten: "Erhellen" inputConstantName: "Name der Konstanten eingeben" - importInfo: "Du kannst hier Themencode einfügen, um ihn in den Editor zu importieren" + importInfo: "Hier kannst du Farbschemencode einfügen, um ihn in den Editor zu importieren" deleteConstantConfirm: "Die Konstante {const} wirklich löschen?" keys: accent: "Akzentfarbe" @@ -1060,7 +1067,7 @@ _theme: toastFg: "Text von Benachrichtigungen" buttonBg: "Hintergrund von Schaltflächen" buttonHoverBg: "Hintergrund von Schaltflächen (Mouseover)" - inputBorder: "Rahmen des Eingabefelds" + inputBorder: "Rahmen von Eingabefeldern" listItemHoverBg: "Hintergrund von Listeneinträgen (Mouseover)" driveFolderBg: "Hintergrund von Drive-Ordnern" wallpaperOverlay: "Hintergrundbild-Overlay" @@ -1101,7 +1108,7 @@ _tutorial: step2_1: "Lass uns zuerst dein Profil vervollständigen, bevor du Notizen schreibst oder jemandem folgst." step2_2: "Informationen darüber, was für eine Person du bist, macht es anderen leichter zu wissen, ob sie deine Notizen sehen wollen und ob sie dir folgen möchten." step3_1: "Mit dem Einrichten deines Profils fertig?" - step3_2: "Dann lass uns als nächstes versuchen, eine Notiz zu schreiben. Dies kannst du tun, indem du auf das Stift-Icon oben auf dem Bildschirm drückst." + step3_2: "Dann lass uns als nächstes versuchen, eine Notiz zu schreiben. Dies kannst du tun, indem du auf den Knopf mit dem Stift-Icon auf dem Bildschirm drückst." step3_3: "Fülle das Fenster aus und drücke auf den Knopf oben rechts zum Senden." step3_4: "Fällt dir nichts ein, das du schreiben möchtest? Versuch's mit \"Hallo Misskey!\"" step4_1: "Fertig mit dem Senden deiner ersten Notiz?" @@ -1111,8 +1118,8 @@ _tutorial: step5_3: "Klicke zum Anzeigen des Profils eines Benutzers auf dessen Profilbild und dann auf den \"Folgen\"-Knopf, um diesem zu folgen." step5_4: "Je nach Benutzer kann es etwas Zeit in Anspruch nehmen, bis dieser deine Follow-Anfrage bestätigt." step6_1: "Wenn du nun auch die Notizen anderer Benutzer in deiner Chronik siehst, hast du auch diesmal alles richtig gemacht." - step6_2: "Du kannst ebenso \"Reaktionen\" verwenden, um schnell auf Notizen anderer Benutzer zu reagieren." - step6_3: "Um eine Reaktion anzufügen, klicke auf das \"+\"-Symbol in der Notiz und wähle ein Emoji aus, mit dem du reagieren möchtest." + step6_2: "Du kannst ebenso „Reaktionen“ verwenden, um schnell auf Notizen anderer Benutzer zu reagieren." + step6_3: "Um eine Reaktion anzufügen, klicke auf das „+“-Symbol in der Notiz und wähle ein Emoji aus, mit dem du reagieren möchtest." step7_1: "Glückwunsch! Du hast die Einführung in die Verwendung von Misskey abgeschlossen." step7_2: "Wenn du mehr über Misskey lernen möchtest, schau dich im {help}-Bereich um." step7_3: "Und nun, viel Spaß mit Misskey! 🚀" @@ -1159,7 +1166,7 @@ _permissions: "read:gallery-likes": "Liste deiner mit \"Gefällt mir\" markierten Galerie-Beiträge lesen" "write:gallery-likes": "Liste deiner mit \"Gefällt mir\" markierten Galerie-Beiträge bearbeiten" _auth: - shareAccess: "Möchtest du \"{name}\" authorisieren, auf dieses Benuzerkonto zugreifen zu können?" + shareAccess: "Möchtest du „{name}“ authorisieren, auf dieses Benutzerkonto zugreifen zu können?" shareAccessAsk: "Bist du dir sicher, dass du diese Anwendung authorisieren möchtest, auf dein Benutzerkonto zugreifen zu können?" permissionAsk: "Diese Anwendung fordert folgende Berechtigungen" pleaseGoBack: "Bitte kehre zur Anwendung zurück" @@ -1180,7 +1187,7 @@ _weekday: friday: "Freitag" saturday: "Samstag" _widgets: - memo: "Memo" + memo: "Merkzettel" notifications: "Benachrichtigungen" timeline: "Chronik" calendar: "Kalender" @@ -1211,8 +1218,8 @@ _poll: canMultipleVote: "Auswahl mehrerer Antworten erlauben" expiration: "Abstimmung beenden" infinite: "Nie" - at: "Beenden am..." - after: "Beenden nach..." + at: "Beenden am …" + after: "Beenden nach …" deadlineDate: "Enddatum" deadlineTime: "Zeit" duration: "Dauer" @@ -1238,24 +1245,24 @@ _visibility: localOnly: "Nur Lokal" localOnlyDescription: "Unsichtbar für Benutzer anderer Instanzen" _postForm: - replyPlaceholder: "Dieser Notiz antworten..." - quotePlaceholder: "Diese Notiz zitieren..." + replyPlaceholder: "Dieser Notiz antworten …" + quotePlaceholder: "Diese Notiz zitieren …" channelPlaceholder: "In einen Kanal senden" _placeholders: a: "Was machst du momentan?" b: "Was ist um dich herum los?" c: "Was geht dir durch den Kopf?" d: "Was möchtest du sagen?" - e: "Fang an zu schreiben..." - f: "Ich warte darauf, dass du schreibst..." + e: "Fang an zu schreiben …" + f: "Ich warte darauf, dass du schreibst …" _profile: name: "Name" username: "Benutzername" - description: "Über mich" - youCanIncludeHashtags: "Du kannst auch Hashtags in deiner Beschreibung verwenden." + description: "Profilbeschreibung" + youCanIncludeHashtags: "Du kannst auch Hashtags in deiner Profilbeschreibung verwenden." metadata: "Zusätzliche Informationen" metadataEdit: "Zusätzliche Informationen bearbeiten" - metadataDescription: "Du kannst auf deinem Profil vier zusätzliche Informationsblöcke anzeigen lassen." + metadataDescription: "Hierdurch kannst du auf deinem Profil zusätzliche Informationsblöcke anzeigen lassen." metadataLabel: "Beschriftung" metadataContent: "Inhalt" changeAvatar: "Profilbild ändern" @@ -1274,25 +1281,25 @@ _charts: usersIncDec: "Unterschied in der Anzahl von Benutzern" usersTotal: "Anzahl aller Benutzer" activeUsers: "Aktive Benutzer" - notesIncDec: "Unterschied in der Anzahl von Notizen" - localNotesIncDec: "Unterschied in der Anzahl von lokalen Notizen" - remoteNotesIncDec: "Unterschied in Anzahl der Notizen von fremden Instanzen" + notesIncDec: "Unterschied in der Anzahl an Notizen" + localNotesIncDec: "Unterschied in der Anzahl an lokalen Notizen" + remoteNotesIncDec: "Unterschied in der Anzahl an Notizen von fremden Instanzen" notesTotal: "Anzahl aller Notizen" - filesIncDec: "Unterschied an Dateien" - filesTotal: "Summe der Dateien" + filesIncDec: "Unterschied in der Anzahl an Dateien" + filesTotal: "Anzahl aller Dateien" storageUsageIncDec: "Unterschied in der Höhe der Speichernutzung" storageUsageTotal: "Gesamte Speichernutzung" _instanceCharts: requests: "Anfragen" - users: "Unterschied in der Anzahl von Benutzern" + users: "Unterschied in der Anzahl an Benutzern" usersTotal: "Gesamtanzahl an Benutzern" - notes: "Unterschied in der Anzahl von Notizen" + notes: "Unterschied in der Anzahl an Notizen" notesTotal: "Gesamtanzahl an Notizen" - ff: "Unterschied in der Anzahl von gefolgten Benutzern und Followern" + ff: "Unterschied in der Anzahl an gefolgten Benutzern und Followern" ffTotal: "Gesamtanzahl an gefolgten Benutzern und Followern" cacheSize: "Unterschied in der Größe des Caches" cacheSizeTotal: "Gesamtgröße des Caches" - files: "Unterschied in der Anzahl der Dateien" + files: "Unterschied in der Anzahl an Dateien" filesTotal: "Gesamtanzahl an Dateien" _timelines: home: "Startseite" @@ -1302,7 +1309,7 @@ _timelines: _pages: newPage: "Seite erstellen" editPage: "Seite bearbeiten" - readPage: "Quelltext-Ansicht" + readPage: "Quelltextansicht" created: "Seite erfolgreich erstellt" updated: "Seite erfolgreich aktualisiert" deleted: "Seite erfolgreich gelöscht" @@ -1326,7 +1333,7 @@ _pages: url: "Seiten-URL" summary: "Zusammenfassung" alignCenter: "Zentrieren" - hideTitleWhenPinned: "Seitentitel ausblenden, wenn angeheftet" + hideTitleWhenPinned: "Seitentitel wenn angeheftet ausblenden" font: "Schriftart" fontSerif: "Serif" fontSansSerif: "Sans Serif" @@ -1363,7 +1370,7 @@ _pages: name: "Variablenname" text: "Titel" default: "Standardwert" - numberInput: "Nummereingabe" + numberInput: "Zahleneingabe" _numberInput: name: "Variablenname" text: "Titel" @@ -1387,7 +1394,7 @@ _pages: _counter: name: "Variablenname" text: "Titel" - inc: "Erhöhen um" + inc: "Schrittgröße" _button: text: "Titel" colored: "Farbig" @@ -1433,10 +1440,10 @@ _pages: strLen: "Textlänge" _strLen: arg1: "Text" - strPick: "Zeichen extrahieren" + strPick: "Text extrahieren" _strPick: arg1: "Text" - arg2: "Zeichenposition" + arg2: "Textposition" strReplace: "Textersetzung" _strReplace: arg1: "Text" @@ -1447,7 +1454,7 @@ _pages: arg1: "Text" join: "Text zusammenfügen" _join: - arg1: "Listen" + arg1: "Liste" arg2: "Trennzeichen" add: "Addieren" _add: @@ -1576,7 +1583,7 @@ _pages: _for: arg1: "Anzahl der Schleifendurchläufe" arg2: "Aktion" - typeError: "Slot {slot} akzeptiert Werte vom Typ \"{expect}\", aber es wurde ein \"{actual}\" Wert angegeben!" + typeError: "Slot {slot} akzeptiert Werte vom Typ „{expect}“, aber es wurde ein „{actual}“ Wert angegeben!" thereIsEmptySlot: "Slot {slot} ist leer!" types: string: "Text" @@ -1587,7 +1594,7 @@ _pages: emptySlot: "Leerer Slot" enviromentVariables: "Umgebungsvariable" pageVariables: "Seitenelemente" - argVariables: "Eingabe-Slots" + argVariables: "Eingabeslots" _relayStatus: requesting: "Ausstehend" accepted: "Akzeptiert" @@ -1605,6 +1612,7 @@ _notification: youReceivedFollowRequest: "Du hast eine Follow-Anfrage erhalten" yourFollowRequestAccepted: "Deine Follow-Anfrage wurde akzeptiert" youWereInvitedToGroup: "Du wurdest in eine Gruppe eingeladen" + pollEnded: "Umfrageergebnisse sind verfügbar" _types: all: "Alle" follow: "Neue Follower" @@ -1614,6 +1622,7 @@ _notification: quote: "Zitationen" reaction: "Reaktionen" pollVote: "Antworten auf Umfragen" + pollEnded: "Ende von Umfragen" receiveFollowRequest: "Erhaltene Follow-Anfragen" followRequestAccepted: "Akzeptierte Follow-Anfragen" groupInvited: "Erhaltene Gruppeneinladungen" @@ -1624,10 +1633,10 @@ _deck: columnMargin: "Spaltenabstand" columnHeaderHeight: "Spaltenkopfhöhe" addColumn: "Spalte hinzufügen" - swapLeft: "Nach links verschieben" - swapRight: "Nach rechts verschieben" - swapUp: "Nach oben verschieben" - swapDown: "Nach unten verschieben" + swapLeft: "Mit linker Spalte tauschen" + swapRight: "Mit rechter Spalte tauschen" + swapUp: "Mit oberer Spalte tauschen" + swapDown: "Mit unterer Spalte tauschen" stackLeft: "Auf linke Spalte stapeln" popRight: "Nach rechts vom Stapel nehmen" profile: "Profil" diff --git a/locales/en-US.yml b/locales/en-US.yml index 53434d7e6..5ec97f05f 100644 --- a/locales/en-US.yml +++ b/locales/en-US.yml @@ -8,7 +8,7 @@ notifications: "Notifications" username: "Username" password: "Password" forgotPassword: "Forgot password" -fetchingAsApObject: "Fetching from Fediverse..." +fetchingAsApObject: "Fetching from the Fediverse..." ok: "OK" gotIt: "Got it!" cancel: "Cancel" @@ -32,9 +32,9 @@ uploading: "Uploading..." save: "Save" users: "Users" addUser: "Add a user" -favorite: "Favorite" +favorite: "Add to favorites" favorites: "Favorites" -unfavorite: "Unfavorite" +unfavorite: "Remove from favorites" favorited: "Added to favorites." alreadyFavorited: "Already added to favorites." cantFavorite: "Couldn't add to favorites." @@ -43,7 +43,7 @@ unpin: "Unpin from profile" copyContent: "Copy contents" copyLink: "Copy link" delete: "Delete" -deleteAndEdit: "Delete and Edit" +deleteAndEdit: "Delete and edit" deleteAndEditConfirm: "Are you sure you want to delete this note and edit it? You will lose all reactions, renotes and replies to it." addToList: "Add to list" sendMessage: "Send a message" @@ -77,21 +77,21 @@ followsYou: "Follows you" createList: "Create list" manageLists: "Manage lists" error: "Error" -somethingHappened: "An error occurred" +somethingHappened: "An error has occurred" retry: "Retry" -pageLoadError: "Failed to load page." +pageLoadError: "An error occurred loading the page." pageLoadErrorDescription: "This is normally caused by network errors or the browser's cache. Try clearing the cache and then try again after waiting a little while." serverIsDead: "This server is not responding. Please wait for a while and try again." youShouldUpgradeClient: "To view this page, please refresh to update your client." -enterListName: "Enter a list name" +enterListName: "Enter a name for the list" privacy: "Privacy" makeFollowManuallyApprove: "Follow requests require approval" defaultNoteVisibility: "Default visibility" follow: "Follow" -followRequest: "Request follow" +followRequest: "Send follow request" followRequests: "Follow requests" unfollow: "Unfollow" -followRequestPending: "Pending follow request" +followRequestPending: "Follow request pending" enterEmoji: "Enter an emoji" renote: "Renote" unrenote: "Take back renote" @@ -107,12 +107,12 @@ sensitive: "NSFW" add: "Add" reaction: "Reactions" reactionSetting: "Reactions to show in the reaction picker" -reactionSettingDescription2: "Drag to reorder, Click to delete, Press \"+\" to add" +reactionSettingDescription2: "Drag to reorder, click to delete, press \"+\" to add." rememberNoteVisibility: "Remember note visibility settings" attachCancel: "Remove attachment" markAsSensitive: "Mark as NSFW" -unmarkAsSensitive: "Undo NSFW" -enterFileName: "Enter file name" +unmarkAsSensitive: "Unmark as NSFW" +enterFileName: "Enter filename" mute: "Mute" unmute: "Unmute" block: "Block" @@ -168,8 +168,8 @@ latestRequestReceivedAt: "Last request received" latestStatus: "Latest status" storageUsage: "Storage usage" charts: "Charts" -perHour: "per Hour" -perDay: "per Day" +perHour: "Per Hour" +perDay: "Per Day" stopActivityDelivery: "Stop sending activities" blockThisInstance: "Block this instance" operations: "Operations" @@ -190,7 +190,7 @@ clearQueueConfirmText: "Any undelivered notes remaining in the queue will not be clearCachedFiles: "Clear cache" clearCachedFilesConfirm: "Are you sure that you want to delete all cached remote files?" blockedInstances: "Blocked Instances" -blockedInstancesDescription: "List the hosts of the instances to be blocked separated by line breaks. Blocked instances will no longer be able to communicate with this instance." +blockedInstancesDescription: "List the hostnames of the instances that you want to block. Listed instances will no longer be able to communicate with this instance." muteAndBlock: "Mutes and Blocks" mutedUsers: "Muted users" blockedUsers: "Blocked users" @@ -325,8 +325,6 @@ disablingTimelinesInfo: "Adminstrators and Moderators will always have access to registration: "Register" enableRegistration: "Enable new user registration" invite: "Invite" -proxyRemoteFiles: "Proxy remote files" -proxyRemoteFilesDescription: "If enabled, remote files that are either not stored locally or were deleted due to exceeding the storage limit will be proxied, including generation of thumbnails. This does not affect the server's storage." driveCapacityPerLocalAccount: "Drive capacity per local user" driveCapacityPerRemoteAccount: "Drive capacity per remote user" inMb: "In megabytes" @@ -336,9 +334,9 @@ backgroundImageUrl: "Background image URL" basicInfo: "Basic info" pinnedUsers: "Pinned users" pinnedUsersDescription: "List usernames separated by line breaks to be pinned in the \"Explore\" tab." -pinnedPages: "Pinned pages" -pinnedPagesDescription: "Enter the paths of the pages you want to pin to the top page of this instance, separated by line breaks." -pinnedClipId: "ID of the pinned clip" +pinnedPages: "Pinned Pages" +pinnedPagesDescription: "Enter the paths of the Pages you want to pin to the top page of this instance, separated by line breaks." +pinnedClipId: "ID of the clip to pin" pinnedNotes: "Pinned notes" hcaptcha: "hCaptcha" enableHcaptcha: "Enable hCaptcha" @@ -348,7 +346,7 @@ recaptcha: "reCAPTCHA" enableRecaptcha: "Enable reCAPTCHA" recaptchaSiteKey: "Site key" recaptchaSecretKey: "Secret key" -avoidMultiCaptchaConfirm: "Using multiple Captcha systems may cause interferences. Would you like to disable the other Captcha systems? You can leave multiple enabled by pressing cancel." +avoidMultiCaptchaConfirm: "Using multiple Captcha systems may cause interference between them. Would you like to disable the other Captcha systems currently active? If you would like them to stay enabled, press cancel." antennas: "Antennas" manageAntennas: "Manage Antennas" name: "Name" @@ -369,13 +367,13 @@ silence: "Silence" silenceConfirm: "Are you sure that you want to silence this user?" unsilence: "Undo silencing" unsilenceConfirm: "Are you sure that you want to undo the silencing of this user?" -popularUsers: "Trending users" -recentlyUpdatedUsers: "Users with recent activity" +popularUsers: "Popular users" +recentlyUpdatedUsers: "Recently active users" recentlyRegisteredUsers: "Newly joined users" recentlyDiscoveredUsers: "Newly discovered users" exploreUsersCount: "There are {count} users" exploreFediverse: "Explore the Fediverse" -popularTags: "Trending Tags" +popularTags: "Popular tags" userList: "Lists" about: "About" aboutMisskey: "About Misskey" @@ -383,13 +381,13 @@ administrator: "Administrator" token: "Token" twoStepAuthentication: "Two-factor authentication" moderator: "Moderator" -nUsersMentioned: "{n} users mentioned" +nUsersMentioned: "Mentioned by {n} users" securityKey: "Security key" securityKeyName: "Key name" registerSecurityKey: "Register a security key" lastUsed: "Last used" unregister: "Unregister" -passwordLessLogin: "Set up password-less login" +passwordLessLogin: "Password-less login" resetPassword: "Reset password" newPasswordIs: "The new password is \"{password}\"" reduceUiAnimation: "Reduce UI animations" @@ -422,11 +420,10 @@ next: "Next" retype: "Enter again" noteOf: "Note by {user}" inviteToGroup: "Invite to group" -maxNoteTextLength: "Character limit for notes" -quoteAttached: "Quoted" +quoteAttached: "Quote" quoteQuestion: "Append as quote?" noMessagesYet: "No messages yet" -newMessageExists: "You've got a new message" +newMessageExists: "There are new messages" onlyOneFileCanBeAttached: "You can only attach one file to a message" signinRequired: "Please sign in" invitations: "Invites" @@ -438,7 +435,7 @@ usernameInvalidFormat: "You can use upper- and lowercase letters, numbers, and u tooShort: "Too short" tooLong: "Too long" weakPassword: "Weak password" -normalPassword: "Normal password" +normalPassword: "Average password" strongPassword: "Strong password" passwordMatched: "Matches" passwordNotMatched: "Does not match" @@ -466,7 +463,7 @@ existingAccount: "Existing account" regenerate: "Regenerate" fontSize: "Font size" noFollowRequests: "You don't have any pending follow requests" -openImageInNewTab: "Open image in new tab" +openImageInNewTab: "Open images in new tab" dashboard: "Dashboard" local: "Local" remote: "Remote" @@ -474,17 +471,17 @@ total: "Total" weekOverWeekChanges: "Changes to last week" dayOverDayChanges: "Changes to yesterday" appearance: "Appearance" -clientSettings: "Client settings" +clientSettings: "Client Settings" accountSettings: "Account Settings" promotion: "Promoted" promote: "Promote" numberOfDays: "Number of days" hideThisNote: "Hide this note" -showFeaturedNotesInTimeline: "Show Featured notes in Timelines" +showFeaturedNotesInTimeline: "Show featured notes in timelines" objectStorage: "Object Storage" useObjectStorage: "Use object storage" objectStorageBaseUrl: "Base URL" -objectStorageBaseUrlDesc: "URL used as reference. Specify the URL of your CDN or Proxy if you are using either. S3: 'https://.s3.amazonaws.com', GCS: 'https://storage.googleapis.com/' etc." +objectStorageBaseUrlDesc: "The URL used as reference. Specify the URL of your CDN or Proxy if you are using either.\nFor S3 use 'https://.s3.amazonaws.com' and for GCS or equivalent services use 'https://storage.googleapis.com/', etc." objectStorageBucket: "Bucket" objectStorageBucketDesc: "Please specify the bucket name used at your provider." objectStoragePrefix: "Prefix" @@ -492,7 +489,7 @@ objectStoragePrefixDesc: "Files will be stored under directories with this prefi objectStorageEndpoint: "Endpoint" objectStorageEndpointDesc: "Leave this empty if you are using AWS S3, otherwise specify the endpoint as '' or ':', depending on the service you are using." objectStorageRegion: "Region" -objectStorageRegionDesc: "Specify a region like 'xx-east-1'. If your service does not distinct between regions, leave this blank or enter 'us-east-1'." +objectStorageRegionDesc: "Specify a region like 'xx-east-1'. If your service does not distinguish between regions, leave this blank or enter 'us-east-1'." objectStorageUseSSL: "Use SSL" objectStorageUseSSLDesc: "Turn this off if you are not going to use HTTPS for API connections" objectStorageUseProxy: "Connect over Proxy" @@ -524,17 +521,17 @@ sort: "Sort" ascendingOrder: "Ascending" descendingOrder: "Descending" scratchpad: "Scratchpad" -scratchpadDescription: "The Scratchpad provides an environment for AiScript experiments. You can write, execute, and check the results of it interacting with Misskey." +scratchpadDescription: "The Scratchpad provides an environment for AiScript experiments. You can write, execute, and check the results of it interacting with Misskey in it." output: "Output" script: "Script" disablePagesScript: "Disable AiScript on Pages" updateRemoteUser: "Update remote user information" -deleteAllFiles: "Delete All Files" +deleteAllFiles: "Delete all files" deleteAllFilesConfirm: "Are you sure that you want to delete all files?" removeAllFollowing: "Unfollow all followed users" removeAllFollowingDescription: "Executing this unfollows all accounts from {host}. Please run this if the instance e.g. no longer exists." userSuspended: "This user has been suspended." -userSilenced: "This user has been silenced." +userSilenced: "This user is being silenced." yourAccountSuspendedTitle: "This account is suspended" yourAccountSuspendedDescription: "This account has been suspended due to breaking the server's terms of services or similar. Contact the administrator if you would like to know a more detailed reason. Please do not create a new account." menu: "Menu" @@ -547,7 +544,7 @@ addedRelays: "Added Relays" serviceworkerInfo: "Must be enabled for push notifications." deletedNote: "Deleted note" invisibleNote: "Invisible note" -enableInfiniteScroll: "Enable infinite scrolling" +enableInfiniteScroll: "Automatically load more" visibility: "Visiblility" poll: "Poll" useCw: "Hide content" @@ -585,7 +582,7 @@ enableEmail: "Enable email distribution" emailConfigInfo: "Used to confirm your email during sign-up or if you forget your password" email: "Email" emailAddress: "Email address" -smtpConfig: "SMTP Server configuration" +smtpConfig: "SMTP Server Configuration" smtpHost: "Host" smtpPort: "Port" smtpUser: "Username" @@ -595,7 +592,9 @@ smtpSecure: "Use implicit SSL/TLS for SMTP connections" smtpSecureInfo: "Turn this off when using STARTTLS" testEmail: "Test email delivery" wordMute: "Word mute" -instanceMute: "Instance mutes" +regexpError: "Regular Expression error" +regexpErrorDescription: "An error occurred in the regular expression on line {line} of your {tab} word mutes:" +instanceMute: "Instance Mutes" userSaysSomething: "{name} said something" makeActive: "Activate" display: "Display" @@ -608,14 +607,14 @@ database: "Database" channel: "Channels" create: "Create" notificationSetting: "Notification settings" -notificationSettingDesc: "Select the type of notification to display" -useGlobalSetting: "Use global setting" +notificationSettingDesc: "Select the types of notification to display." +useGlobalSetting: "Use global settings" useGlobalSettingDesc: "If turned on, your account's notification settings will be used. If turned off, individual configurations can be made." other: "Other" regenerateLoginToken: "Regenerate login token" -regenerateLoginTokenDescription: "Regenerate the token used internally during login. Normally this action is not necessary. If regenerated, all devices will be logged out." +regenerateLoginTokenDescription: "Regenerates the token used internally during login. Normally this action is not necessary. If regenerated, all devices will be logged out." setMultipleBySeparatingWithSpace: "Separate multiple entries with spaces." -fileIdOrUrl: "File-ID or URL" +fileIdOrUrl: "File ID or URL" behavior: "Behavior" sample: "Sample" abuseReports: "Reports" @@ -689,14 +688,14 @@ center: "Center" wide: "Wide" narrow: "Narrow" reloadToApplySetting: "This setting will only apply after a page reload. Reload now?" -needReloadToApply: "This setting will only apply after a page reload." +needReloadToApply: "A reload is required for this to be reflected." showTitlebar: "Show title bar" clearCache: "Clear cache" onlineUsersCount: "{n} users are online" nUsers: "{n} Users" nNotes: "{n} Notes" sendErrorReports: "Send error reports" -sendErrorReportsDescription: "When turned on, detailed error information will be shared with Misskey when a problem occurs, helping to improve the quality of Misskey.\nThis will include information such the version of your OS, what browser you're using, your activity history, etc." +sendErrorReportsDescription: "When turned on, detailed error information will be shared with Misskey when a problem occurs, helping to improve the quality of Misskey.\nThis will include information such the version of your OS, what browser you're using, your activity in Misskey, etc." myTheme: "My theme" backgroundColor: "Background color" accentColor: "Accent color" @@ -794,12 +793,12 @@ translatedFrom: "Translated from {x}" accountDeletionInProgress: "Account deletion is currently in progress" usernameInfo: "A name that identifies your account from others on this server. You can use the alphabet (a~z, A~Z), digits (0~9) or underscores (_). Usernames cannot be changed later." aiChanMode: "Ai Mode" -keepCw: "Keep Content Warnings" +keepCw: "Keep content warnings" pubSub: "Pub/Sub Accounts" lastCommunication: "Last communication" resolved: "Resolved" unresolved: "Unresolved" -breakFollow: "Unfollow" +breakFollow: "Remove follower" itsOn: "Enabled" itsOff: "Disabled" emailRequiredForSignup: "Require email address for sign-up" @@ -819,7 +818,7 @@ deleteAccountConfirm: "This will irreversibly delete your account. Proceed?" incorrectPassword: "Incorrect password." voteConfirm: "Confirm your vote for \"{choice}\"?" hide: "Hide" -leaveGroup: "Leave Group" +leaveGroup: "Leave group" leaveGroupConfirm: "Are you sure you want to leave \"{name}\"?" useDrawerReactionPickerForMobile: "Display reaction picker as drawer on mobile" welcomeBackWithName: "Welcome back, {name}" @@ -831,6 +830,16 @@ auto: "Auto" themeColor: "Theme Color" size: "Size" numberOfColumn: "Number of columns" +searchByGoogle: "Google" +instanceDefaultLightTheme: "Instance-wide default light theme" +instanceDefaultDarkTheme: "Instance-wide default dark theme" +instanceDefaultThemeDescription: "Enter the theme code in object format." +mutePeriod: "Mute duration" +indefinitely: "Permanently" +tenMinutes: "10 minutes" +oneHour: "One hour" +oneDay: "One day" +oneWeek: "One week" _emailUnavailable: used: "This email address is already being used" format: "The format of this email address is invalid" @@ -843,10 +852,10 @@ _ffVisibility: private: "Private" _signup: almostThere: "Almost there" - emailAddressInfo: "Please enter your email address." + emailAddressInfo: "Please enter your email address. It will not be made public." emailSent: "A confirmation email has been sent to your email address ({email}). Please click the included link to complete account creation." _accountDelete: - accountDelete: "Delete Account" + accountDelete: "Delete account" mayTakeTime: "As account deletion is a resource-heavy process, it may take some time to complete depending on how much content you have created and how many files you have uploaded." sendEmail: "Once account deletion has been completed, an email will be sent to the email address registered to this account." requestAccountDelete: "Request account deletion" @@ -857,8 +866,8 @@ _ad: reduceFrequencyOfThisAd: "Show this ad less" _forgotPassword: enterEmail: "Enter the email address you used to register. A link with which you can reset your password will then be sent to it." - ifNoEmail: "If you did not use an email during registration, please contact the administrator instead." - contactAdmin: "This instance does not support using email addresses, please contact the administrator to reset your password instead." + ifNoEmail: "If you did not use an email during registration, please contact the instance administrator instead." + contactAdmin: "This instance does not support using email addresses, please contact the instance administrator to reset your password instead." _gallery: my: "My Gallery" liked: "Liked Posts" @@ -910,14 +919,14 @@ _mfm: smallDescription: "Displays content small and thin." center: "Center" centerDescription: "Displays content centered." - inlineCode: "Code (In-line)" + inlineCode: "Code (Inline)" inlineCodeDescription: "Displays inline syntax highlighting for (program) code." blockCode: "Code (Block)" blockCodeDescription: "Displays syntax highlighting for multi-line (program) code in a block." - inlineMath: "Math (In-line)" + inlineMath: "Math (Inline)" inlineMathDescription: "Display math formulas (KaTeX) in-line" blockMath: "Math (Block)" - blockMathDescription: "Display multi-line Math formulas (KaTeX) in a block" + blockMathDescription: "Display multi-line math formulas (KaTeX) in a block" quote: "Quote" quoteDescription: "Displays content as a quote." emoji: "Custom Emoji" @@ -947,7 +956,7 @@ _mfm: x4: "Unbelievably big" x4Description: "Displays content even bigger than bigger than big." blur: "Blur" - blurDescription: "Content can be blurred via this effect. It will be displayed clearly when hovered over." + blurDescription: "Blurs content. It will be displayed clearly when hovered over." font: "Font" fontDescription: "Sets the font to display content in." rainbow: "Rainbow" @@ -1079,10 +1088,10 @@ _ago: unknown: "Unknown" future: "Future" justNow: "Just now" - secondsAgo: "{n} seconds ago" - minutesAgo: "{n} minutes ago" - hoursAgo: "{n} hours ago" - daysAgo: "{n} days ago" + secondsAgo: "{n} second(s) ago" + minutesAgo: "{n} minute(s) ago" + hoursAgo: "{n} hour(s) ago" + daysAgo: "{n} day(s) ago" weeksAgo: "{n} week(s) ago" monthsAgo: "{n} month(s) ago" yearsAgo: "{n} year(s) ago" @@ -1099,17 +1108,17 @@ _tutorial: step2_1: "Let's finish setting up your profile before writing a note or following anyone." step2_2: "Providing some information about who you are will make it easier for others to tell if they want to see your notes or follow you." step3_1: "Finished setting up your profile?" - step3_2: "Then let's try posting a note next. You can do this by pressing the pencil icon on the top of the screen." + step3_2: "Then let's try posting a note next. You can do so by pressing the button with a pencil icon on the screen." step3_3: "Fill in the modal and press the button on the top right to post." step3_4: "Have nothing to say? Try \"just setting up my msky\"!" step4_1: "Finished posting your first note?" step4_2: "Hurray! Now your first note should be displayed on your timeline." step5_1: "Now, let's try making your timeline more lively by following other people." - step5_2: "{featured} will show you trending notes in this instance. {explore} will let you find trending users. Try finding people you'd like to follow there!" + step5_2: "{featured} will show you popular notes in this instance. {explore} will let you find popular users. Try finding people you'd like to follow there!" step5_3: "To follow other users, click on their icon and press the \"Follow\" button on their profile." step5_4: "If the other user has a lock icon next to their name, it may take some time for that user to manually approve your follow request." step6_1: "You should be able to see other users' notes on your timeline now." - step6_2: "You can also put \"reactions\" on other people's notes to quickly respond." + step6_2: "You can also put \"reactions\" on other people's notes to quickly respond to them." step6_3: "To attach a \"reaction\", press the \"+\" mark on another user's note and choose an emoji you'd like to react with." step7_1: "Congratulations! You have now finished Misskey's basic tutorial." step7_2: "If you would like to learn more about Misskey, try the {help} section." @@ -1140,7 +1149,7 @@ _permissions: "write:mutes": "Edit your list of muted users" "write:notes": "Compose or delete notes" "read:notifications": "View your notifications" - "write:notifications": "Work with your notifications" + "write:notifications": "Manage your notifications" "read:reactions": "View your reactions" "write:reactions": "Edit your reactions" "write:votes": "Vote on a poll" @@ -1150,18 +1159,18 @@ _permissions: "write:page-likes": "Edit your likes on pages" "read:user-groups": "View your user groups" "write:user-groups": "Edit or delete your user groups" - "read:channels": "Read your channels" - "write:channels": "Modify your channels" + "read:channels": "View your channels" + "write:channels": "Edit your channels" "read:gallery": "View your gallery" "write:gallery": "Edit your gallery" - "read:gallery-likes": "View list of liked gallery posts" - "write:gallery-likes": "Edit list of liked gallery posts" + "read:gallery-likes": "View your list of liked gallery posts" + "write:gallery-likes": "Edit your list of liked gallery posts" _auth: shareAccess: "Would you like to authorize \"{name}\" to access this account?" shareAccessAsk: "Are you sure you want to authorize this application to access your account?" permissionAsk: "This application requests the following permissions" pleaseGoBack: "Please go back to the application" - callback: "Returning back to the application" + callback: "Returning to the application" denied: "Access denied" _antennaSources: all: "All notes" @@ -1189,7 +1198,7 @@ _widgets: photos: "Photos" digitalClock: "Digital clock" federation: "Federation" - postForm: "Compose a note" + postForm: "Posting form" slideshow: "Slideshow" button: "Button" onlineUsers: "Online users" @@ -1220,10 +1229,10 @@ _poll: showResult: "View results" voted: "Voted" closed: "Ended" - remainingDays: "{d} days {h} hours remaining" - remainingHours: "{h} hours {m} minutes remaining" - remainingMinutes: "{m} minutes {s} seconds remaining" - remainingSeconds: "{s} seconds remaining" + remainingDays: "{d} day(s) {h} hour(s) remaining" + remainingHours: "{h} hour(s) {m} minute(s) remaining" + remainingMinutes: "{m} minute(s) {s} second(s) remaining" + remainingSeconds: "{s} second(s) remaining" _visibility: public: "Public" publicDescription: "Your note will be visible for all users" @@ -1253,7 +1262,7 @@ _profile: youCanIncludeHashtags: "You can also include hashtags in your bio." metadata: "Additional Information" metadataEdit: "Edit additional Information" - metadataDescription: "You can display up to four additional information fields in your profile." + metadataDescription: "Using these, you can display additional information fields in your profile." metadataLabel: "Label" metadataContent: "Content" changeAvatar: "Change avatar" @@ -1269,29 +1278,29 @@ _exportOrImport: _charts: federation: "Federation" apRequest: "Requests" - usersIncDec: "Difference in # of users" - usersTotal: "Total # of users" + usersIncDec: "Difference in the number of users" + usersTotal: "Total number of users" activeUsers: "Active users" - notesIncDec: "Difference in # of notes" - localNotesIncDec: "Difference in # of local notes" - remoteNotesIncDec: "Difference in # of remote notes" - notesTotal: "Total # of notes" - filesIncDec: "Difference in # of files" - filesTotal: "Total # of files" + notesIncDec: "Difference in the number of notes" + localNotesIncDec: "Difference in the number of local notes" + remoteNotesIncDec: "Difference in the number of remote notes" + notesTotal: "Total number of notes" + filesIncDec: "Difference in the number of files" + filesTotal: "Total number of files" storageUsageIncDec: "Difference in storage usage" storageUsageTotal: "Total storage usage" _instanceCharts: requests: "Requests" - users: "Difference in # of users" - usersTotal: "Cumulative total # of users" - notes: "Difference in # of notes" - notesTotal: "Cumulative total # of notes" - ff: "Difference in # of followed users / followers " - ffTotal: "Cumulative total # of followed users / followers" + users: "Difference in the number of users" + usersTotal: "Cumulative number of users" + notes: "Difference in the number of notes" + notesTotal: "Cumulative number of notes" + ff: "Difference in the number of followed users / followers " + ffTotal: "Cumulative number of followed users / followers" cacheSize: "Difference in cache size" cacheSizeTotal: "Cumulative total cache size" - files: "Difference in # of files" - filesTotal: "Cumulative total # of files" + files: "Difference in the number of files" + filesTotal: "Cumulative number of files" _timelines: home: "Home" local: "Local" @@ -1300,7 +1309,7 @@ _timelines: _pages: newPage: "Create a new Page" editPage: "Edit this Page" - readPage: "Source view activated" + readPage: "Viewing this Page's source" created: "Page successfully created" updated: "Page successfully edited" deleted: "Page successfully deleted" @@ -1315,7 +1324,7 @@ _pages: unlike: "Remove like" my: "My Pages" liked: "Liked Pages" - featured: "Featured" + featured: "Popular" inspector: "Inspector" contents: "Contents" content: "Page block" @@ -1346,10 +1355,10 @@ _pages: if: "If" _if: variable: "Variable" - post: "Compose a note" + post: "Posting form" _post: text: "Content" - attachCanvasImage: "Post with canvas image" + attachCanvasImage: "Attach canvas image" canvasId: "Canvas ID" textInput: "Text input" _textInput: @@ -1385,11 +1394,11 @@ _pages: _counter: name: "Variable name" text: "Title" - inc: "Increase by" + inc: "Step" _button: text: "Title" colored: "Colored" - action: "Operation when the button is pressed" + action: "Behavior when the button is pressed" _action: dialog: "Show a dialog" _dialog: @@ -1431,11 +1440,11 @@ _pages: strLen: "Text length" _strLen: arg1: "Text" - strPick: "Extract character" + strPick: "Extract string" _strPick: arg1: "Text" - arg2: "Character location" - strReplace: "Text replacement" + arg2: "String location" + strReplace: "Replacement string" _strReplace: arg1: "Text" arg2: "Text to be replaced" @@ -1529,7 +1538,7 @@ _pages: arg2: "Maximum value" dailyRandomPick: "Randomly choose from a list (Changes once a day for each user)" _dailyRandomPick: - arg1: "Lists" + arg1: "List" seedRandom: "Random (with seed)" _seedRandom: arg1: "Seed" @@ -1603,6 +1612,7 @@ _notification: youReceivedFollowRequest: "You've received a follow request" yourFollowRequestAccepted: "Your follow request was accepted" youWereInvitedToGroup: "You've been invited to a group" + pollEnded: "Poll results have become available" _types: all: "All" follow: "New followers" @@ -1612,6 +1622,7 @@ _notification: quote: "Quotes" reaction: "Reactions" pollVote: "Votes on polls" + pollEnded: "Polls ending" receiveFollowRequest: "Received follow requests" followRequestAccepted: "Accepted follow requests" groupInvited: "Group invitations" @@ -1622,12 +1633,12 @@ _deck: columnMargin: "Margin between columns" columnHeaderHeight: "Column header height" addColumn: "Add column" - swapLeft: "Swap left" - swapRight: "Swap right" - swapUp: "Swap with above" - swapDown: "Swap with below" - stackLeft: "Stack on left column" - popRight: "Pop to the right" + swapLeft: "Swap with the left column" + swapRight: "Swap with the right column" + swapUp: "Swap with the above column" + swapDown: "Swap with the below column" + stackLeft: "Stack with the left column" + popRight: "Pop column to the right" profile: "Profile" _columns: main: "Main" diff --git a/locales/eo-UY.yml b/locales/eo-UY.yml index 062bf85aa..934ffd2d4 100644 --- a/locales/eo-UY.yml +++ b/locales/eo-UY.yml @@ -9,7 +9,7 @@ username: "Uzantnomo" password: "Pasvorto" forgotPassword: "Ĉu vi forgesis pasvorton?" fetchingAsApObject: "Informpetado de la Fediverso…" -ok: "Bone" +ok: "Okej" gotIt: "Kompreni" cancel: "Nuligi" enterUsername: "Entajpu uzantnomon" @@ -71,7 +71,7 @@ lists: "Listoj" noLists: "Neniu listo" note: "Noti" notes: "Notoj" -following: "Sekvata" +following: "Sekvatoj" followers: "Sekvantoj" followsYou: "Sekvas vin" createList: "Krei liston" @@ -224,7 +224,7 @@ resetAreYouSure: "Ĉu vi certas restarigi?" saved: "Konservita" messaging: "Retbabili" upload: "Alŝuti" -keepOriginalUploading: "Konservi la originalan bildon" +keepOriginalUploading: "Konservi originalon" fromDrive: "De la disko" fromUrl: "De URL" uploadFromUrl: "Alŝuti de URL" @@ -278,6 +278,7 @@ rename: "Alinomi" avatar: "Bildsimbolo" banner: "Standardo" nsfw: "Enhavo ne estas deca por laborejo (NSFW)" +whenServerDisconnected: "Kiam vi malligiĝas de servilo" disconnectedFromServer: "Malkonektita de servilo" reload: "Reŝargi" doNothing: "Ignori" @@ -396,7 +397,6 @@ next: "Sekve" retype: "Retajpu" noteOf: "Noto de {user}" inviteToGroup: "Inviti al grupo" -maxNoteTextLength: "Limnombro de leteroj en noto" quoteAttached: "Kun citaĵo" quoteQuestion: "Ĉu vi volas aldoni citaĵon?" noMessagesYet: "Ankoraŭ neniu mesaĝo" @@ -420,7 +420,7 @@ signinWith: "Saluti kun {x}" signinFailed: "Fuŝiĝis ensaluti. Bonvolu kontroli uzantnomon kaj pasvorton." or: "Aŭ" language: "Lingvo" -uiLanguage: "Lingvo de fasado" +uiLanguage: "Lingvo de la fasado" groupInvited: "Invitita al grupo" aboutX: "Pri {x}" useOsNativeEmojis: "Uzi la emoĵiojn implicitan de la operaciumo" @@ -648,7 +648,7 @@ high: "Alta" middle: "Meza" low: "Malalta" emailNotConfiguredWarning: "Vi ne agordis retpoŝtadreso." -customCss: "Personecigita CSS" +customCss: "Propra CSS" global: "Malloka" squareAvatars: "Montri bildsimbolon kiel kvadrata" sent: "Sendi" @@ -683,14 +683,20 @@ hide: "Kaŝi" leaveGroup: "Eliĝi el la grupo" leaveGroupConfirm: "Ĉu vi certas ke vi volas eliĝi el la grupo {name}?" welcomeBackWithName: "Bonrevenon, {name}!" -clickToFinishEmailVerification: "Volu klaki [{ok}] por fini la konfirmon de vian retadreson" +clickToFinishEmailVerification: "Volu klaki [{ok}] por fini konfirmon de via retadreso." smartphone: "Saĝtelefono" tablet: "Platkomputilo" auto: "Aŭtomate" +searchByGoogle: "Serĉi en Google-Serĉo" +tenMinutes: "10 minutoj" +oneHour: "1 horo" +oneDay: "1 tago" +oneWeek: "1 semajno" _emailUnavailable: used: "La retpoŝto jam estas uzita." format: "Nevalida formato." disposable: "Dumtempa retpoŝto ne estas uzebla." + mx: "Ĉi retpoŝto-servilo ne estas uzebla." smtp: "Tiu retpoŝta servilo ne respondas" _ffVisibility: public: "Publika" @@ -770,9 +776,9 @@ _channel: usersCount: "{n} partoprenantoj" notesCount: "{n} notoj" _menuDisplay: - sideFull: "Flanko" - sideIcon: "Flanko (bildsimbolo)" - top: "Supro" + sideFull: "Sur la flanko" + sideIcon: "Sur la flanko (bildsimbolo)" + top: "Sur la supro" hide: "Kaŝi" _wordMute: muteWords: "Silentigitaj vortoj" @@ -920,7 +926,6 @@ _postForm: c: "Kio estas sur via penso?" d: "Kion vi volas diri?" e: "Komencu skribi tie" - f: "Atendanta de vi skribon…" _profile: name: "Nomo" username: "Uzantnomo" diff --git a/locales/es-ES.yml b/locales/es-ES.yml index 1e85e7d8c..d0fc254ef 100644 --- a/locales/es-ES.yml +++ b/locales/es-ES.yml @@ -321,8 +321,6 @@ disablingTimelinesInfo: "Aunque se desactiven estas lineas de tiempo, por conven registration: "Registro" enableRegistration: "Permitir nuevos registros" invite: "Invitar" -proxyRemoteFiles: "Hacer proxy de archivos remotos" -proxyRemoteFilesDescription: "Si activa esta configuración, los archivos remotos no almacenados o borrados por exceso de capacidad serán mostrados via proxy local y generarán una miniatura. Eso no afectará el almacenamiento del servidor." driveCapacityPerLocalAccount: "Capacidad del drive por usuario local" driveCapacityPerRemoteAccount: "Capacidad del drive por usuario remoto" inMb: "En megabytes" @@ -418,7 +416,6 @@ next: "Siguiente" retype: "Intentar de nuevo" noteOf: "Notas de {user}" inviteToGroup: "Invitar al grupo" -maxNoteTextLength: "Límite de caracteres en una nota" quoteAttached: "Cita añadida" quoteQuestion: "¿Quiere añadir una cita?" noMessagesYet: "Aún no hay chat" @@ -765,6 +762,7 @@ muteThread: "Ocultar hilo" unmuteThread: "Mostrar hilo" ffVisibility: "Visibilidad de seguidores y seguidos" hide: "Ocultar" +indefinitely: "Sin límite de tiempo" _ffVisibility: public: "Publicar" _accountDelete: diff --git a/locales/fr-FR.yml b/locales/fr-FR.yml index 1deda414c..5ccf1b2b6 100644 --- a/locales/fr-FR.yml +++ b/locales/fr-FR.yml @@ -323,8 +323,6 @@ disablingTimelinesInfo: "Même si vous désactivez ces fils, les administrateur registration: "S’inscrire" enableRegistration: "Autoriser les nouvelles inscriptions" invite: "Inviter" -proxyRemoteFiles: "Utiliser les fichiers distants comme proxy" -proxyRemoteFilesDescription: "Si vous activez ce paramètre, les fichiers distants non stockés ou supprimés en raison d'une capacité excédentaire seront affichés via un proxy local et généreront une miniature. Cela n'affectera pas le stockage du serveur." driveCapacityPerLocalAccount: "Volume du Drive par utilisateur local" driveCapacityPerRemoteAccount: "Volume du Drive par utilisateur distant" inMb: "en mégaoctets" @@ -420,7 +418,6 @@ next: "Suivant" retype: "Confirmation" noteOf: "Notes de {user}" inviteToGroup: "Inviter dans un groupe" -maxNoteTextLength: "Limite du nombre de caractères pour les notes" quoteAttached: "Avec citation" quoteQuestion: "Souhaitez-vous ajouter une citation ?" noMessagesYet: "Pas encore de discussion" @@ -592,6 +589,7 @@ smtpSecure: "Utiliser SSL/TLS implicitement dans les connexions SMTP" smtpSecureInfo: "Désactiver cette option lorsque STARTTLS est utilisé" testEmail: "Tester la distribution de courriel" wordMute: "Filtre de mots" +regexpError: "Erreur d’expression régulière" instanceMute: "Instance en sourdine" userSaysSomething: "{name} a dit quelque chose" makeActive: "Activer" @@ -620,6 +618,7 @@ reportAbuse: "Signaler" reportAbuseOf: "Signaler {name}" fillAbuseReportDescription: "Veuillez expliquer les raisons du signalement. S'il s'agit d'une note précise, veuillez en donner le lien." abuseReported: "Le rapport est envoyé. Merci." +reporter: "Signalé par" reporteeOrigin: "Origine du signalement" reporterOrigin: "Signalé par" forwardReport: "Transférer le signalement à l’instance distante" @@ -818,6 +817,22 @@ leaveGroup: "Quitter le groupe" leaveGroupConfirm: "Êtes vous sûr de vouloir quitter \"{name}\" ?" welcomeBackWithName: "Heureux de vous revoir, {name}" clickToFinishEmailVerification: "Veuillez cliquer sur [{ok}] afin de compléter la vérification par courriel." +overridedDeviceKind: "Type d’appareil" +smartphone: "Smartphone" +tablet: "Tablette" +auto: "Automatique" +themeColor: "Couleur du thème" +size: "Taille" +numberOfColumn: "Nombre de colonnes" +searchByGoogle: "Google" +instanceDefaultLightTheme: "Thème clair par défaut sur toute l’instance" +instanceDefaultDarkTheme: "Thème sombre par défaut sur toute l’instance" +mutePeriod: "Durée de mise en sourdine" +indefinitely: "Illimité" +tenMinutes: "10 minutes" +oneHour: "1 heure" +oneDay: "1 jour" +oneWeek: "1 semaine" _emailUnavailable: used: "Non disponible" format: "Le format de cette adresse de courriel est invalide" diff --git a/locales/hr-HR.yml b/locales/hr-HR.yml new file mode 100644 index 000000000..ed97d539c --- /dev/null +++ b/locales/hr-HR.yml @@ -0,0 +1 @@ +--- diff --git a/locales/id-ID.yml b/locales/id-ID.yml index be766e72c..03970c5f2 100644 --- a/locales/id-ID.yml +++ b/locales/id-ID.yml @@ -325,8 +325,6 @@ disablingTimelinesInfo: "Admin dan Moderator akan selalu memiliki akses ke semua registration: "Pendaftaran" enableRegistration: "Nyalakan pendaftaran pengguna baru" invite: "Undang" -proxyRemoteFiles: "Proksi berkas remote" -proxyRemoteFilesDescription: "Jika diaktifkan, berkas luar yang (1) tidak disimpan secara lokal atau (2) terhapus dari melewati batas penyimpanan akan diproksi secara lokal (dengan thumbnail). Ini tidak akan mempengaruhi server penyimpanan." driveCapacityPerLocalAccount: "Kapasitas drive per pengguna lokal" driveCapacityPerRemoteAccount: "Kapasitas drive per pengguna remote" inMb: "dalam Megabytes" @@ -422,7 +420,6 @@ next: "Selanjutnya" retype: "Masukkan ulang" noteOf: "Catatan milik {user}" inviteToGroup: "Undang ke grup" -maxNoteTextLength: "Batas karakter catatan" quoteAttached: "Dikutip" quoteQuestion: "Apakah kamu ingin menambahkan kutipan?" noMessagesYet: "Tidak ada pesan" @@ -828,6 +825,7 @@ overridedDeviceKind: "Tipe perangkat" smartphone: "Ponsel" tablet: "Tablet" auto: "Otomatis" +indefinitely: "Selamanya" _emailUnavailable: used: "Alamat surel ini telah digunakan" format: "Format tidak valid." diff --git a/locales/index.js b/locales/index.js index 8350b3d9c..b271b79b7 100644 --- a/locales/index.js +++ b/locales/index.js @@ -34,6 +34,7 @@ const languages = [ 'pl-PL', 'pt-PT', 'ru-RU', + 'sk-SK', 'ug-CN', 'uk-UA', 'zh-CN', diff --git a/locales/it-IT.yml b/locales/it-IT.yml index c4ec4232a..8601f9307 100644 --- a/locales/it-IT.yml +++ b/locales/it-IT.yml @@ -321,8 +321,6 @@ disablingTimelinesInfo: "Anche se disabiliti queste timeline, gli amministratori registration: "Iscriviti" enableRegistration: "Permettere nuove registrazioni" invite: "Invita" -proxyRemoteFiles: "Usare file remoti come proxy" -proxyRemoteFilesDescription: "Attivando questa opzione i file remoti non salvati o cancellati perché eccedenti il limite di archiviazione verranno inoltrati tramite proxy, inclusa la generazione di anteprime. Non ha effetto sullo spazio di archiviazione del server." driveCapacityPerLocalAccount: "Volume del Drive per utente locale" driveCapacityPerRemoteAccount: "Volume del Drive per utente remoto" inMb: "in Megabytes" @@ -418,7 +416,6 @@ next: "Avanti" retype: "Conferma" noteOf: "Note di {user}" inviteToGroup: "Invitare al gruppo" -maxNoteTextLength: "Lunghezza massima delle note" quoteAttached: "Citazione allegata" quoteQuestion: "Vuoi aggiungere una citazione?" noMessagesYet: "Ancora nessuna chat" @@ -805,6 +802,7 @@ leaveGroupConfirm: "Uscire da「{name}」?" useDrawerReactionPickerForMobile: "Mostra sul drawer da dispositivo mobile" welcomeBackWithName: "Bentornato/a, {name}" clickToFinishEmailVerification: "Fai click su [{ok}] per completare la verifica dell'indirizzo email." +indefinitely: "Non scade" _emailUnavailable: used: "Email già in uso" format: "Formato email non valido" diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml index f4c9d1998..13f9efe9b 100644 --- a/locales/ja-JP.yml +++ b/locales/ja-JP.yml @@ -325,8 +325,6 @@ disablingTimelinesInfo: "これらのタイムラインを無効化しても、 registration: "登録" enableRegistration: "誰でも新規登録できるようにする" invite: "招待" -proxyRemoteFiles: "リモートのファイルをプロキシする" -proxyRemoteFilesDescription: "この設定を有効にすると、未保存または保存容量超過で削除されたリモートファイルをローカルでプロキシし、サムネイルも生成するようになります。サーバーのストレージには影響しません、" driveCapacityPerLocalAccount: "ローカルユーザーひとりあたりのドライブ容量" driveCapacityPerRemoteAccount: "リモートユーザーひとりあたりのドライブ容量" inMb: "メガバイト単位" @@ -422,7 +420,6 @@ next: "次" retype: "再入力" noteOf: "{user}のノート" inviteToGroup: "グループに招待" -maxNoteTextLength: "ノートの文字数制限" quoteAttached: "引用付き" quoteQuestion: "引用として添付しますか?" noMessagesYet: "まだチャットはありません" @@ -833,6 +830,16 @@ auto: "自動" themeColor: "テーマカラー" size: "サイズ" numberOfColumn: "列の数" +searchByGoogle: "ググる" +instanceDefaultLightTheme: "インスタンスデフォルトのライトテーマ" +instanceDefaultDarkTheme: "インスタンスデフォルトのダークテーマ" +instanceDefaultThemeDescription: "オブジェクト形式のテーマコードを記入します。" +mutePeriod: "ミュートする期限" +indefinitely: "無期限" +tenMinutes: "10分" +oneHour: "1時間" +oneDay: "1日" +oneWeek: "1週間" _emailUnavailable: used: "既に使用されています" @@ -1291,7 +1298,7 @@ _profile: youCanIncludeHashtags: "ハッシュタグを含めることができます。" metadata: "追加情報" metadataEdit: "追加情報を編集" - metadataDescription: "プロフィールに表として4つまでの追加情報を表示することができます。" + metadataDescription: "プロフィールに表として追加情報を表示することができます。" metadataLabel: "ラベル" metadataContent: "内容" changeAvatar: "アバター画像を変更" @@ -1660,6 +1667,7 @@ _notification: youReceivedFollowRequest: "フォローリクエストが来ました" yourFollowRequestAccepted: "フォローリクエストが承認されました" youWereInvitedToGroup: "グループに招待されました" + pollEnded: "アンケートの結果が出ました" _types: all: "すべて" @@ -1670,6 +1678,7 @@ _notification: quote: "引用" reaction: "リアクション" pollVote: "アンケートに投票された" + pollEnded: "アンケートが終了" receiveFollowRequest: "フォロー申請を受け取った" followRequestAccepted: "フォローが受理された" groupInvited: "グループに招待された" diff --git a/locales/ja-KS.yml b/locales/ja-KS.yml index b5b4e7257..382d9c49c 100644 --- a/locales/ja-KS.yml +++ b/locales/ja-KS.yml @@ -323,8 +323,6 @@ disablingTimelinesInfo: "ここらへんのタイムラインを使えんよう registration: "登録" enableRegistration: "一見さんでも誰でもいらっしゃ~い" invite: "来てや" -proxyRemoteFiles: "リモートのファイルをプロキシする" -proxyRemoteFilesDescription: "この設定を有効にしたら、保存してなかったり容量が足らんくて消されたリモートファイルをローカルでプロキシして、サムネイルを作るようになるで。サーバーの容量には関係ないで。" driveCapacityPerLocalAccount: "ローカルユーザーひとりあたりのドライブ容量" driveCapacityPerRemoteAccount: "リモートユーザーひとりあたりのドライブ容量" inMb: "メガバイト単位" @@ -417,7 +415,6 @@ next: "次" retype: "もっかい入力" noteOf: "{user}のノート" inviteToGroup: "グループに招く" -maxNoteTextLength: "ノートの文字数制限" quoteAttached: "引用付いとるで" quoteQuestion: "引用として添付してもええか?" noMessagesYet: "まだチャットはあらへんで" @@ -658,6 +655,7 @@ global: "グローバル" sent: "送信" hashtags: "ハッシュタグ" hide: "隠す" +indefinitely: "無期限" _ad: back: "戻る" _gallery: diff --git a/locales/ko-KR.yml b/locales/ko-KR.yml index 116e397ff..39522e8d7 100644 --- a/locales/ko-KR.yml +++ b/locales/ko-KR.yml @@ -325,8 +325,6 @@ disablingTimelinesInfo: "특정 타임라인을 비활성화하더라도 관리 registration: "등록" enableRegistration: "신규 회원가입을 활성화" invite: "초대" -proxyRemoteFiles: "리모트 파일 프록시" -proxyRemoteFilesDescription: "이 설정을 활성화할 경우, 저장되지 않았거나 저장용량 초과로 삭제된 리모트 파일을 로컬에서 프록시하여 썸네일을 생성하게 됩니다. 서버의 스토리지에는 영향을 주지 않습니다." driveCapacityPerLocalAccount: "로컬 유저 한 명당 드라이브 용량" driveCapacityPerRemoteAccount: "리모트 유저 한 명당 드라이브 용량" inMb: "메가바이트 단위" @@ -422,7 +420,6 @@ next: "다음" retype: "다시 입력" noteOf: "{user}의 노트" inviteToGroup: "그룹에 초대하기" -maxNoteTextLength: "노트의 문자 수 제한" quoteAttached: "인용함" quoteQuestion: "인용해서 작성하시겠습니까?" noMessagesYet: "아직 대화가 없습니다" @@ -828,6 +825,7 @@ overridedDeviceKind: "장치 유형" smartphone: "스마트폰" tablet: "태블릿" auto: "자동" +indefinitely: "무기한" _emailUnavailable: used: "이 메일 주소는 사용중입니다" format: "형식이 올바르지 않습니다" diff --git a/locales/pl-PL.yml b/locales/pl-PL.yml index 0b57a3a46..9f98332a6 100644 --- a/locales/pl-PL.yml +++ b/locales/pl-PL.yml @@ -320,8 +320,6 @@ disablingTimelinesInfo: "Administratorzy i moderatorzy będą zawsze mieć dost registration: "Zarejestruj się" enableRegistration: "Włącz rejestrację nowych użytkowników" invite: "Zaproś" -proxyRemoteFiles: "Przekierowuj pliki obcych instancji przez proxy" -proxyRemoteFilesDescription: "Gdy ta opcja jest włączona, zdalne pliki które nie są przechowywane lokalnie, lub zostały usunięte z powodu przekroczenia limitu miejsca będą kierowane przez proxy, razem z generowaniem miniatur. Nie ma to żadnego wpływu na przestrzeń dyskową serwera." driveCapacityPerLocalAccount: "Powierzchnia dyskowa na lokalnego użytkownika" driveCapacityPerRemoteAccount: "Powierzchnia dyskowa na zdalnego użytkownika" inMb: "W megabajtach" @@ -417,7 +415,6 @@ next: "Dalej" retype: "Wprowadź ponownie" noteOf: "Wpisy {user}" inviteToGroup: "Zaproś do grupy" -maxNoteTextLength: "Limit znaków dla wpisów" quoteAttached: "Zacytowano" quoteQuestion: "Czy na pewno chcesz umieścić cytat?" noMessagesYet: "Nie napisano jeszcze wiadomości" @@ -761,6 +758,7 @@ received: "Otrzymane" hashtags: "Hashtag" pubSub: "Konta Pub/Sub" hide: "Ukryj" +indefinitely: "Nigdy" _ffVisibility: public: "Publikuj" _ad: diff --git a/locales/ro-RO.yml b/locales/ro-RO.yml new file mode 100644 index 000000000..8ec9deb29 --- /dev/null +++ b/locales/ro-RO.yml @@ -0,0 +1,555 @@ +--- +_lang_: "Română" +headlineMisskey: "O rețea conectată prin note" +introMisskey: "Bine ai venit! Misskey este un serviciu de microblogging open source și decentralizat.\nCreează \"note\" cu care să îți poți împărți gândurile cu oricine din jurul tău. 📡\nCu \"reacții\" îți poți expirma rapid părerea despre notele oricui. 👍\nHai să explorăm o lume nouă! 🚀" +monthAndDay: "{day}/{month}" +search: "Caută" +notifications: "Notificări" +username: "Nume de utilizator" +password: "Parolă" +forgotPassword: "Am uitat parola" +fetchingAsApObject: "Se aduce din Fediverse..." +ok: "OK" +gotIt: "Am înțeles!" +cancel: "Anulează" +enterUsername: "Introdu numele de utilizator" +renotedBy: "Re-notat de {user}" +noNotes: "Nicio notă" +noNotifications: "Nicio notificare" +instance: "Instanță" +settings: "Setări" +basicSettings: "Setări generale" +otherSettings: "Alte Setări" +openInWindow: "Deschide într-o fereastră" +profile: "Profil" +timeline: "Cronologie" +noAccountDescription: "Acest utilizator încă nu a scris un bio." +login: "Autentifică-te" +loggingIn: "Se autentifică" +logout: "Deconectează-te" +signup: "Înregistrează-te" +uploading: "Se încarcă" +save: "Salvează" +users: "Utilizatori" +addUser: "Adăugă utilizator" +favorite: "Adaugă la favorite" +favorites: "Favorite" +unfavorite: "Elimină din favorite" +favorited: "Adăugat la favorite." +alreadyFavorited: "Deja adăugat la favorite." +cantFavorite: "Nu se poate adăuga la favorite." +pin: "Fixează pe profil" +unpin: "Anulati fixare" +copyContent: "Copiază conținutul" +copyLink: "Copiază link-ul" +delete: "Şterge" +deleteAndEdit: "Șterge și editează" +deleteAndEditConfirm: "Ești sigur că vrei să ștergi această notă și să o editezi? Vei pierde reacțiile, re-notele și răspunsurile acesteia." +addToList: "Adaugă în listă" +sendMessage: "Trimite un mesaj" +copyUsername: "Copiază numele de utilizator" +searchUser: "Caută un utilizator" +reply: "Răspunde" +loadMore: "Incarcă mai mult" +showMore: "Arată mai mult" +youGotNewFollower: "te-a urmărit" +receiveFollowRequest: "Cerere de urmărire primită" +followRequestAccepted: "Cerere de urmărire acceptată" +mention: "Mențiune" +mentions: "Mențiuni" +directNotes: "Note directe" +importAndExport: "Importă / Exportă" +import: "Importă" +export: "Exportă" +files: "Fișiere" +download: "Descarcă" +driveFileDeleteConfirm: "Ești sigur ca vrei să ștergi fișierul \"{name}\"? Notele atașate fișierului vor fi șterse și ele." +unfollowConfirm: "Ești sigur ca vrei să nu mai urmărești pe {name}?" +exportRequested: "Ai cerut un export. S-ar putea să ia un pic. Va fi adăugat in Drive-ul tău odată completat." +importRequested: "Ai cerut un import. S-ar putea să ia un pic." +lists: "Liste" +noLists: "Nu ai nici o listă" +note: "Notă" +notes: "Note" +following: "Urmărești" +followers: "Urmăritori" +followsYou: "Te urmărește" +createList: "Creează listă" +manageLists: "Gestionează listele" +error: "Eroare" +somethingHappened: "A survenit o eroare" +retry: "Reîncearcă" +pageLoadError: "A apărut o eroare la încărcarea paginii." +pageLoadErrorDescription: "De obicei asta este cauzat de o eroare de rețea sau cache-ul browser-ului. Încearcă să cureți cache-ul și apoi să încerci din nou puțin mai târziu." +serverIsDead: "Serverul nu răspunde. Te rugăm să aștepți o perioadă și să încerci din nou." +youShouldUpgradeClient: "Pentru a vedea această pagină, te rugăm să îți actualizezi clientul." +enterListName: "Introdu un nume pentru listă" +privacy: "Confidenţialitate" +makeFollowManuallyApprove: "Fă cererile de urmărire să necesite aprobare" +defaultNoteVisibility: "Vizibilitate implicită" +follow: "Urmărești" +followRequest: "Trimite cerere de urmărire" +followRequests: "Cereri de urmărire" +unfollow: "Nu mai urmări" +followRequestPending: "Cerere de urmărire în așteptare" +enterEmoji: "Introdu un emoji" +renote: "Re-notează" +unrenote: "Ia înapoi re-nota" +renoted: "Re-notat." +cantRenote: "Această postare nu poate fi re-notată." +cantReRenote: "O re-notă nu poate fi re-notată." +quote: "Citează" +pinnedNote: "Notă fixată" +pinned: "Fixat pe profil" +you: "Tu" +clickToShow: "Click pentru a afișa" +sensitive: "NSFW" +add: "Adaugă" +reaction: "Reacție" +reactionSetting: "Reacții care să apară in selectorul de reacții" +reactionSettingDescription2: "Trage pentru a rearanja, apasă pe \"+\" pentru a adăuga." +rememberNoteVisibility: "Amintește setarea de vizibilitate a notelor" +attachCancel: "Înlătură atașament" +markAsSensitive: "Marchează ca NSFW" +unmarkAsSensitive: "Demarchează ca NSFW" +enterFileName: "Introduceţi numele fişierului" +mute: "Amuțește" +unmute: "Înlătură amuțirea" +block: "Blochează" +unblock: "Deblochează" +suspend: "Suspendă" +unsuspend: "Anulează suspendare" +blockConfirm: "Ești sigur că vrei să blochezi acest cont?" +unblockConfirm: "Ești sigur ca vrei să deblochezi acest cont?" +suspendConfirm: "Ești sigur ca vrei să suspendezi acest cont?" +unsuspendConfirm: "Ești sigur ca vrei să nu mai suspendezi acest cont?" +selectList: "Selectează o listă" +selectAntenna: "Selectează o antenă" +selectWidget: "Selectați un widget" +editWidgets: "Editează widget-urile" +editWidgetsExit: "Terminat" +customEmojis: "Emoji personalizat" +emoji: "Emoji" +emojis: "Emoji-uri" +emojiName: "Numele emoji-ului" +emojiUrl: "URL-ul emoji-ului" +addEmoji: "Adaugă un emoji" +settingGuide: "Setări recomandate" +cacheRemoteFiles: "Ține fișierele externe in cache" +cacheRemoteFilesDescription: "Când această setare este dezactivată, fișierele externe sunt încărcate direct din instanța externă. Dezactivarea va scădea utilizarea spațiului de stocare, dar va crește traficul, deoarece thumbnail-urile nu vor fi generate." +flagAsBot: "Marchează acest cont ca bot" +flagAsBotDescription: "Activează această opțiune dacă acest cont este controlat de un program. Daca e activată, aceasta va juca rolul unui indicator pentru dezvoltatori pentru a preveni interacțiunea în lanțuri infinite cu ceilalți boți și ajustează sistemele interne al Misskey pentru a trata acest cont drept un bot." +flagAsCat: "Marchează acest cont ca pisică" +flagAsCatDescription: "Activează această opțiune dacă acest cont este o pisică." +flagShowTimelineReplies: "Arată răspunsurile în cronologie" +flagShowTimelineRepliesDescription: "Dacă e activată vor fi arătate în cronologie răspunsurile utilizatorilor către alte notele altor utilizatori." +autoAcceptFollowed: "Aprobă automat cererile de urmărire de la utilizatorii pe care îi urmărești" +addAccount: "Adaugă un cont" +loginFailed: "Autentificare eșuată" +showOnRemote: "Vezi mai multe pe instanța externă" +general: "General" +wallpaper: "Imagine de fundal" +setWallpaper: "Setați imaginea de fundal" +removeWallpaper: "Șterge imagine de fundal" +searchWith: "Caută: {q}" +youHaveNoLists: "Nu ai nici o listă" +followConfirm: "Ești sigur ca vrei să urmărești pe {name}?" +proxyAccount: "Cont proxy" +proxyAccountDescription: "Un cont proxy este un cont care se comportă ca un urmăritor extern pentru utilizatorii puși sub anumite condiții. De exemplu, când un cineva adaugă un utilizator extern intr-o listă, activitatea utilizatorului extern nu va fi adusă în instanță daca nici un utilizator local nu urmărește acel utilizator, așa că în schimb contul proxy îl va urmări." +host: "Gazdă" +selectUser: "Selectează un utilizator" +recipient: "Destinatar" +annotation: "Adnotări" +federation: "Federație" +instances: "Instanțe" +registeredAt: "Înregistrat în" +latestRequestSentAt: "Ultima cerere trimisă" +latestRequestReceivedAt: "Ultima cerere primită" +latestStatus: "Ultimul status" +storageUsage: "Utilizare stocare" +charts: "Diagrame" +perHour: "Pe oră" +perDay: "Pe zi" +stopActivityDelivery: "Nu mai trimite activități" +blockThisInstance: "Blochează această instanță" +operations: "Operațiuni" +software: "Software" +version: "Versiune" +metadata: "Metadata" +withNFiles: "{n} fișier(e)" +monitor: "Monitor" +jobQueue: "coada de job-uri" +cpuAndMemory: "CPU și memorie" +network: "Rețea" +disk: "Disk" +instanceInfo: "Informații despre instanță" +statistics: "Statistici" +clearQueue: "Șterge coada" +clearQueueConfirmTitle: "Ești sigur că vrei să cureți coada?" +clearQueueConfirmText: "Orice notă rămasă în coadă nu va fi federată. De obicei această operație nu este necesară." +clearCachedFiles: "Golește cache-ul" +clearCachedFilesConfirm: "Ești sigur că vrei să ștergi toate fișierele externe din cache?" +blockedInstances: "Instanțe blocate" +blockedInstancesDescription: "Scrie hostname-urile instanțelor pe care dorești să le blochezi. Instanțele listate nu vor mai putea să comunice cu această instanță." +muteAndBlock: "Amuțiri și Blocări" +mutedUsers: "Utilizatori amuțiți" +blockedUsers: "Utilizatori blocați" +noUsers: "Niciun utilizator" +editProfile: "Editează profilul" +noteDeleteConfirm: "Ești sigur că vrei să ștergi această notă?" +pinLimitExceeded: "Nu poți mai fixa mai multe note" +intro: "Misskey s-a instalat! Te rog crează un utilizator admin." +done: "Gata" +processing: "Se procesează" +preview: "Previzualizare" +default: "Prestabilit" +noCustomEmojis: "Nu e niciun emoji" +noJobs: "Nu e niciun job" +federating: "Federație" +blocked: "Blocat" +suspended: "Suspendat" +all: "Tot" +subscribing: "Abonare" +publishing: "Publicare" +notResponding: "Nu răspunde" +instanceFollowing: "Urmărind în instanță" +instanceFollowers: "Urmăritori ai instanței" +instanceUsers: "Utilizatori ai acestei instanțe" +changePassword: "Schimbă parolă" +security: "Securitate" +retypedNotMatch: "Intrările nu corespund" +currentPassword: "Parola curentă" +newPassword: "Parola nouă" +newPasswordRetype: "Rescrie parola nouă" +attachFile: "Atașează fișiere" +more: "Mai mult!" +featured: "Evidențiat" +usernameOrUserId: "Nume sau ID de utilizator" +noSuchUser: "Utilizatorul nu a fost găsit" +lookup: "Privire" +announcements: "Anunțuri" +imageUrl: "URL-ul imaginii" +remove: "Şterge" +removed: "Șterș cu succes" +removeAreYouSure: "Ești sigur că vrei să înlături {x}?" +deleteAreYouSure: "Ești sigur că vrei să ștergi {x}?" +resetAreYouSure: "Sigur vrei să resetezi?" +saved: "Salvat" +messaging: "Chat" +upload: "Încarcă" +keepOriginalUploading: "Păstrează imaginea originală" +keepOriginalUploadingDescription: "Salvează imaginea originala încărcată fără modificări. Dacă e oprită, o versiune pentru afișarea pe web va fi generată la încărcare." +fromDrive: "Din Drive" +fromUrl: "Din URL" +uploadFromUrl: "Încarcă dintr-un URL" +uploadFromUrlDescription: "URL-ul fișierului pe care dorești să îl încarci" +uploadFromUrlRequested: "Încărcare solicitată" +uploadFromUrlMayTakeTime: "S-ar putea să ia puțin până se finalizează încărcarea." +explore: "Explorează" +messageRead: "Citit" +noMoreHistory: "Nu există mai mult istoric" +startMessaging: "Începe un chat nou" +nUsersRead: "citit de {n}" +agreeTo: "Sunt de acord cu {0}" +tos: "Termenii de utilizare" +start: "Să începem" +home: "Acasă" +remoteUserCaution: "Deoarece acest utilizator este dintr-o instanță externă, informația afișată poate fi incompletă." +activity: "Activitate" +images: "Imagini" +birthday: "Zi de naștere" +yearsOld: "{age} ani" +registeredDate: "Data înregistrării" +location: "Locație" +theme: "Teme" +themeForLightMode: "Temă folosită pentru Modul Luminat" +themeForDarkMode: "Temă folosită pentru Modul Întunecat" +light: "Luminos" +dark: "Întunecat" +lightThemes: "Teme luminoase" +darkThemes: "Teme întunecate" +syncDeviceDarkMode: "Sincronizează Modul Întunecat cu setările dispozitivului" +drive: "Drive" +fileName: "Nume fișier" +selectFile: "Alege un fisier" +selectFiles: "Alege fișiere" +selectFolder: "Selectează un folder" +selectFolders: "Selectează folderele" +renameFile: "Redenumește fișier" +folderName: "Nume folder" +createFolder: "Crează folder" +renameFolder: "Redenumește acest folder" +deleteFolder: "Șterge acest folder" +addFile: "Adăugați un fișier" +emptyDrive: "Drive-ul tău e gol" +emptyFolder: "Folder-ul acesta este gol" +unableToDelete: "Nu se poate șterge" +inputNewFileName: "Introdu un nou nume de fișier" +inputNewDescription: "Introdu o descriere nouă" +inputNewFolderName: "Introdu un nume de folder nou" +circularReferenceFolder: "Destinația folderului este un subfolder al folderului pe care dorești să îl muți." +hasChildFilesOrFolders: "Acest folder nu este gol, așa că nu poate fi șters." +copyUrl: "Copiază URL" +rename: "Redenumește" +avatar: "Avatar" +banner: "Banner" +nsfw: "NSFW" +whenServerDisconnected: "Când pierzi conexiunea cu serverul" +disconnectedFromServer: "Conecțiunea cu serverul a fost pierdută" +reload: "Reîncarcă" +doNothing: "Ignoră" +reloadConfirm: "Ai dori să reîmprospătezi cronologia?" +watch: "Vezi" +unwatch: "Oprește-te din văzut" +accept: "Acceptă" +reject: "Respinge" +normal: "Normal" +instanceName: "Numele instanței" +instanceDescription: "Descrierea instanței" +maintainerName: "Administrator" +maintainerEmail: "Email-ul administratorului" +tosUrl: "URL-ul Termenilor de utilizare" +thisYear: "An" +thisMonth: "Lună" +today: "Azi" +dayX: "{day}" +monthX: "{month}" +yearX: "{year}" +pages: "Pagini" +integration: "Integrare" +connectService: "Conectează" +disconnectService: "Deconectează" +enableLocalTimeline: "Activează cronologia locală" +enableGlobalTimeline: "Activeaza cronologia globală" +disablingTimelinesInfo: "Administratorii și Moderatorii vor avea mereu access la toate cronologiile, chiar dacă nu sunt activate." +registration: "Inregistrare" +enableRegistration: "Activează înregistrările pentru utilizatori noi" +invite: "Invită" +driveCapacityPerLocalAccount: "Capacitatea Drive-ului per utilizator local" +driveCapacityPerRemoteAccount: "Capacitatea Drive-ului per utilizator extern" +inMb: "În megabytes" +iconUrl: "URL-ul iconiței" +bannerUrl: "URL-ul imaginii de banner" +backgroundImageUrl: "URL-ul imaginii de fundal" +basicInfo: "Informații de bază" +pinnedUsers: "Utilizatori fixați" +pinnedUsersDescription: "Scrie utilizatorii, separați prin pauză de rând, care vor fi fixați pe pagina \"Explorează\"." +pinnedPages: "Pagini fixate" +pinnedPagesDescription: "Introdu linkurile Paginilor pe care le vrei fixate in vâruful paginii acestei instanțe, separate de pauze de rând." +pinnedClipId: "ID-ul clip-ului pe care să îl fixezi" +pinnedNotes: "Notă fixată" +hcaptcha: "hCaptcha" +enableHcaptcha: "Activează hCaptcha" +hcaptchaSiteKey: "Site key" +hcaptchaSecretKey: "Secret key" +recaptcha: "reCAPTCHA" +enableRecaptcha: "Activează reCAPTCHA" +recaptchaSiteKey: "Site key" +recaptchaSecretKey: "Secret key" +avoidMultiCaptchaConfirm: "Folosirea mai multor sisteme Captcha poate cauza interferență între acestea. Ai dori să dezactivezi alte sisteme Captcha acum active? Dacă preferi să rămână activate, apasă Anulare." +antennas: "Antene" +manageAntennas: "Gestionează Antenele" +name: "Nume" +antennaSource: "Sursa antenei" +antennaKeywords: "Cuvinte cheie ascultate" +antennaExcludeKeywords: "Cuvinte cheie excluse" +antennaKeywordsDescription: "Separă cu spații pentru o condiție ȘI sau cu o întrerupere de rând pentru o condiție SAU." +notifyAntenna: "Notifică-mă pentru note noi" +withFileAntenna: "Doar note cu fișiere" +enableServiceworker: "Activează ServiceWorker" +antennaUsersDescription: "Scrie un nume de utilizator per linie" +caseSensitive: "Sensibil la majuscule și minuscule" +withReplies: "Include răspunsuri" +connectedTo: "Următoarele conturi sunt conectate" +notesAndReplies: "Note și răspunsuri" +withFiles: "Incluzând fișiere" +silence: "Amuțește" +silenceConfirm: "Ești sigur că vrei să amuțești acest utilizator?" +unsilence: "Anulează amuțirea" +unsilenceConfirm: "Ești sigur că vrei să anulezi amuțirea acestui utilizator?" +popularUsers: "Utilizatori populari" +recentlyUpdatedUsers: "Utilizatori activi recent" +recentlyRegisteredUsers: "Utilizatori ce s-au alăturat recent" +recentlyDiscoveredUsers: "Utilizatori descoperiți recent" +exploreUsersCount: "Aici sunt {count} utilizatori" +exploreFediverse: "Explorează Fediverse-ul" +popularTags: "Taguri populare" +userList: "Liste" +about: "Despre" +aboutMisskey: "Despre Misskey" +administrator: "Administrator" +token: "Token" +twoStepAuthentication: "Autentificare în doi pași" +moderator: "Moderator" +nUsersMentioned: "Menționat de {n} utilizatori" +securityKey: "Cheie de securitate" +securityKeyName: "Numele cheii" +registerSecurityKey: "Înregistrează o cheie de securitate" +lastUsed: "Ultima utilizată" +unregister: "Dezînregistrează" +passwordLessLogin: "Autentificare fără parolă" +resetPassword: "Resetează parola" +newPasswordIs: "Noua parolă este \"{password}\"" +reduceUiAnimation: "Redu animațiile interfeței" +share: "Distribuie" +notFound: "Nu a fost găsit" +notFoundDescription: "N-a fost găsită nicio pagină cu acest URL." +uploadFolder: "Folder implicit pentru încărcări" +cacheClear: "Golește cache-ul" +markAsReadAllNotifications: "Marchează toate notificările drept citit" +markAsReadAllUnreadNotes: "Marchează toate notele drept citit" +markAsReadAllTalkMessages: "Marchează toate mesajele drept citit" +help: "Ajutor" +inputMessageHere: "Introdu un mesaj aici" +close: "Închide" +group: "Grup" +groups: "Grupuri" +createGroup: "Crează un grup" +ownedGroups: "Grupuri deținute" +joinedGroups: "Grupuri alăturate" +invites: "Invită" +groupName: "Numele grupului" +members: "Membri" +transfer: "Transferă" +messagingWithUser: "Chat privat" +messagingWithGroup: "Chat de grup" +title: "Titlu" +text: "Text" +enable: "Activează" +next: "Următorul" +retype: "Introdu din nou" +noteOf: "Notă de {user}" +inviteToGroup: "Invită în grup" +quoteAttached: "Citat" +quoteQuestion: "Vrei să adaugi ca citat?" +noMessagesYet: "Niciun mesaj încă" +newMessageExists: "Ai mesaje noi" +onlyOneFileCanBeAttached: "Poți atașa un singur fișier la un mesaj" +signinRequired: "Te rog autentifică-te" +invitations: "Invită" +invitationCode: "Cod de invitație" +checking: "Se verifică..." +available: "Disponibil" +unavailable: "Indisponibil" +usernameInvalidFormat: "Poți folosi litere mari și mici, numere și underscore-uri." +tooShort: "Prea scurt" +tooLong: "Prea lung" +weakPassword: "Parolă slabă" +normalPassword: "Parolă medie" +strongPassword: "Parolă puternică" +passwordMatched: "Se potrivește!" +passwordNotMatched: "Nu se potrivește" +signinWith: "Autentifică-te cu {x}" +signinFailed: "Nu se poate autentifica. Numele de utilizator sau parola introduse sunt incorecte." +tapSecurityKey: "Apasă pe cheia ta de securitate." +or: "Sau" +language: "Limbă" +uiLanguage: "Limba interfeței" +groupInvited: "Ai fost invitat într-un grup" +aboutX: "Despre {x}" +useOsNativeEmojis: "Folosește emojiuri native OS-ului" +disableDrawer: "Nu folosi meniuri în stil sertar" +sounds: "Sunete" +listen: "Ascultă" +none: "Nimic" +showInPage: "Arată în pagină" +popout: "Scoate în afară" +volume: "Volum" +masterVolume: "Volumul principal" +details: "Detalii" +chooseEmoji: "Alege un emoji" +unableToProcess: "Această operație nu poate fi completată" +recentUsed: "Folosit recent" +install: "Instalează" +uninstall: "Dezinstalează" +installedApps: "Aplicații autorizate" +nothing: "Nu e nimic de văzut aici" +installedDate: "Autorizat la data de" +lastUsedDate: "Folosit ultima oara la" +state: "Stare" +sort: "Sortează" +ascendingOrder: "Crescător" +descendingOrder: "Descrescător" +scratchpad: "Scratchpad" +smtpHost: "Gazdă" +smtpUser: "Nume de utilizator" +smtpPass: "Parolă" +clearCache: "Golește cache-ul" +info: "Despre" +user: "Utilizatori" +_email: + _follow: + title: "te-a urmărit" +_mfm: + mention: "Mențiune" + quote: "Citează" + emoji: "Emoji personalizat" + search: "Caută" +_theme: + keys: + mention: "Mențiune" + renote: "Re-notează" +_sfx: + note: "Note" + notification: "Notificări" + chat: "Chat" +_widgets: + notifications: "Notificări" + timeline: "Cronologie" + activity: "Activitate" + federation: "Federație" + jobQueue: "coada de job-uri" +_cw: + show: "Incarcă mai mult" +_visibility: + home: "Acasă" + followers: "Urmăritori" +_profile: + name: "Nume" + username: "Nume de utilizator" +_exportOrImport: + followingList: "Urmărești" + muteList: "Amuțește" + blockingList: "Blochează" + userLists: "Liste" +_charts: + federation: "Federație" +_timelines: + home: "Acasă" +_pages: + blocks: + image: "Imagini" + script: + categories: + list: "Liste" + blocks: + _join: + arg1: "Liste" + _randomPick: + arg1: "Liste" + _dailyRandomPick: + arg1: "Liste" + _seedRandomPick: + arg2: "Liste" + _pick: + arg1: "Liste" + _listLen: + arg1: "Liste" + types: + array: "Liste" +_notification: + youWereFollowed: "te-a urmărit" + youWereInvitedToGroup: "Ai fost invitat într-un grup" + _types: + follow: "Urmărești" + mention: "Mențiune" + renote: "Re-notează" + quote: "Citează" + reaction: "Reacție" +_deck: + _columns: + notifications: "Notificări" + tl: "Cronologie" + antenna: "Antene" + list: "Liste" + mentions: "Mențiuni" diff --git a/locales/ru-RU.yml b/locales/ru-RU.yml index b29d2173c..610fe727e 100644 --- a/locales/ru-RU.yml +++ b/locales/ru-RU.yml @@ -322,8 +322,6 @@ disablingTimelinesInfo: "У администраторов и модератор registration: "Регистрация" enableRegistration: "Разрешить регистрацию" invite: "Пригласить" -proxyRemoteFiles: "Файлы с других сайтов пускать через прокси" -proxyRemoteFilesDescription: "Когда эта настройка включена, файлы с других серверов, которые не сохранены или удалены для освобождения места, будут проксироваться локально, а так же для них будут создаваться миниатюры. Эта настройка не затрагивает хранение на сервере." driveCapacityPerLocalAccount: "Объём диска на одного локального пользователя" driveCapacityPerRemoteAccount: "Объём диска на одного пользователя с другого сайта" inMb: "В мегабайтах" @@ -419,7 +417,6 @@ next: "Дальше" retype: "Введите ещё раз" noteOf: "Что пишет {user}" inviteToGroup: "Пригласить в группу" -maxNoteTextLength: "Максимальная длина текста" quoteAttached: "Цитата" quoteQuestion: "Хотите добавить цитату?" noMessagesYet: "Пока ни одного сообщения" @@ -818,6 +815,7 @@ leaveGroupConfirm: "Покинуть группу «{name}»?" useDrawerReactionPickerForMobile: "Выдвижная палитра на мобильном устройстве" welcomeBackWithName: "С возвращением, {name}!" clickToFinishEmailVerification: "Пожалуйста, нажмите [{ok}], чтобы завершить подтверждение адреса электронной почты." +indefinitely: "вечно" _emailUnavailable: used: "Уже используется" format: "Неверный формат" diff --git a/locales/si-LK.yml b/locales/si-LK.yml new file mode 100644 index 000000000..ed97d539c --- /dev/null +++ b/locales/si-LK.yml @@ -0,0 +1 @@ +--- diff --git a/locales/sk-SK.yml b/locales/sk-SK.yml index a501591a8..db45365a5 100644 --- a/locales/sk-SK.yml +++ b/locales/sk-SK.yml @@ -325,8 +325,6 @@ disablingTimelinesInfo: "Administrátori a moderátori majú vždy prístup ku v registration: "Registrácia" enableRegistration: "Povoliť registráciu nových používateľov" invite: "Pozvať" -proxyRemoteFiles: "Proxy vzdialených súborov" -proxyRemoteFilesDescription: "Ak je zapnuté, vzdialené súbory, ktoré nie sú uložené lokálne alebo boli odstránené kvôli obmedzeniam úložiska, budú vyžiadané cez proxy, vrátane generovani miniatúr. Neovplyvní to úložisko na serveri." driveCapacityPerLocalAccount: "Kapacita disku pre používateľa" driveCapacityPerRemoteAccount: "Kapacita disku pre vzdialeného používateľa" inMb: "V megabajtoch" @@ -422,7 +420,6 @@ next: "Ďalší" retype: "Zadajte znovu" noteOf: "Poznámky používateľa {user}" inviteToGroup: "Pozvať do skupiny" -maxNoteTextLength: "Maximálny počet znakov poznámky" quoteAttached: "Citované" quoteQuestion: "Pripojiť ako citát?" noMessagesYet: "Zatiaľ žiadne správy" @@ -832,6 +829,16 @@ auto: "Automaticky" themeColor: "Farba témy" size: "Veľkosť" numberOfColumn: "Počet stĺpcov" +searchByGoogle: "Hľadať cez Google" +instanceDefaultLightTheme: "Predvolená svetlá téma" +instanceDefaultDarkTheme: "Predvolená tmavá téma" +instanceDefaultThemeDescription: "Vložte kód témy v objektovom formáte" +mutePeriod: "Trvanie stíšenia" +indefinitely: "Navždy" +tenMinutes: "10 minút" +oneHour: "1 hodina" +oneDay: "1 deň" +oneWeek: "1 týždeň" _emailUnavailable: used: "Táto emailová adresa sa už používa" format: "Formát emailovej adresy je nesprávny" @@ -1604,6 +1611,7 @@ _notification: youReceivedFollowRequest: "Dostali ste žiadosť o sledovanie" yourFollowRequestAccepted: "Vaša žiadosť o sledovanie bola prijatá" youWereInvitedToGroup: "Pozvať do skupiny" + pollEnded: "Výsledky hlasovania sú k dispozícii." _types: all: "Všetky" follow: "Sledujete" @@ -1613,6 +1621,7 @@ _notification: quote: "Citovať" reaction: "Reakcie" pollVote: "Hlasy v hlasovaniach" + pollEnded: "Hlasovanie skončilo" receiveFollowRequest: "Doručené žiadosti o sledovanie" followRequestAccepted: "Schválené žiadosti o sledovanie" groupInvited: "Pozvánky do skupín" diff --git a/locales/uk-UA.yml b/locales/uk-UA.yml index 588df8d32..4dbc29766 100644 --- a/locales/uk-UA.yml +++ b/locales/uk-UA.yml @@ -312,8 +312,6 @@ disablingTimelinesInfo: "Адміністратори та модератори registration: "Реєстрація" enableRegistration: "Дозволити реєстрацію" invite: "Запросити" -proxyRemoteFiles: "Проксувати файли з інших інстансів" -proxyRemoteFilesDescription: "При увімкненні віддалені файли, які не зберігаються локально або були видалені через недостатнії обсяг пам'яті, будуть локально проксовані включаючи обкладинки. Це налаштування не впливає на пам'ять серверу. " driveCapacityPerLocalAccount: "Об'єм диска на одного локального користувача" driveCapacityPerRemoteAccount: "Об'єм диска на одного віддаленого користувача" inMb: "В мегабайтах" @@ -407,7 +405,6 @@ next: "Далі" retype: "Введіть ще раз" noteOf: "Нотатка {user}" inviteToGroup: "Запрошення до групи" -maxNoteTextLength: "Максимальна довжина нотатки" quoteAttached: "Цитата" quoteQuestion: "Ви хочете додати цитату?" noMessagesYet: "Ще немає повідомлень" @@ -688,6 +685,7 @@ global: "Глобальна" sent: "Відправити" hashtags: "Хештеґ" hide: "Сховати" +indefinitely: "Ніколи" _ad: back: "Назад" _gallery: diff --git a/locales/vi-VN.yml b/locales/vi-VN.yml new file mode 100644 index 000000000..42f86b335 --- /dev/null +++ b/locales/vi-VN.yml @@ -0,0 +1,48 @@ +--- +_lang_: "Tiếng Việt" +headlineMisskey: "Mạng xã hội liên hợp" +monthAndDay: "{day} tháng {month}" +search: "Tìm kiếm" +notifications: "Thông báo" +username: "Tên người dùng" +password: "Mật khẩu" +forgotPassword: "Quên mật khẩu" +ok: "Đồng ý" +renotedBy: "Chia sẻ bởi {user}" +flagAsBot: "Đánh dấu đây là tài khoản bot" +searchWith: "Tìm kiếm: {q}" +followConfirm: "Bạn có chắc muốn theo dõi {name}?" +cpuAndMemory: "CPU và Dung lượng" +dayX: "{day}" +yearX: "{year}" +aboutMisskey: "Về Misskey" +smtpUser: "Tên người dùng" +smtpPass: "Mật khẩu" +reportAbuseOf: "Báo cáo {name}" +renotedCount: "Lượt chia sẻ" +translatedFrom: "Dịch từ {x}" +searchByGoogle: "Google" +_mfm: + search: "Tìm kiếm" +_theme: + installed: "{name} đã được cài đặt" +_sfx: + notification: "Thông báo" +_ago: + unknown: "Không rõ" + future: "Tương lai" + justNow: "Vừa xong" + secondsAgo: "{n}s trước" + minutesAgo: "{n} phút trước" + hoursAgo: "{n} giờ trước" + daysAgo: "{n} ngày trước" + weeksAgo: "{n} tuần trước" + monthsAgo: "{n} tháng trước" + yearsAgo: "{n} năm trước" +_widgets: + notifications: "Thông báo" +_profile: + username: "Tên người dùng" +_deck: + _columns: + notifications: "Thông báo" diff --git a/locales/zh-CN.yml b/locales/zh-CN.yml index 86d3fb5cd..483faba0d 100644 --- a/locales/zh-CN.yml +++ b/locales/zh-CN.yml @@ -325,8 +325,6 @@ disablingTimelinesInfo: "即使时间线功能被禁用,出于便利性的原 registration: "注册" enableRegistration: "允许新用户注册" invite: "邀请" -proxyRemoteFiles: "代理远程文件" -proxyRemoteFilesDescription: "启用此设置后,由于超出存储容量而导致未保存被删除的远程文件将被本地代理,并且会生成缩略图。不会影响服务器的存储。" driveCapacityPerLocalAccount: "每个用户的网盘空间" driveCapacityPerRemoteAccount: "每个远程用户的网盘容量" inMb: "以兆字节(MegaByte)为单位" @@ -422,7 +420,6 @@ next: "下一个" retype: "重新输入" noteOf: "{user}的帖子" inviteToGroup: "群组邀请" -maxNoteTextLength: "帖子的字数限制" quoteAttached: "已引用" quoteQuestion: "是否引用此链接内容?" noMessagesYet: "现在没有新的聊天" @@ -833,6 +830,16 @@ auto: "自动" themeColor: "主题颜色" size: "大小" numberOfColumn: "列数" +searchByGoogle: "Google" +instanceDefaultLightTheme: "实例默认浅色主题" +instanceDefaultDarkTheme: "实例默认深色主题" +instanceDefaultThemeDescription: "以对象格式键入主题代码" +mutePeriod: "屏蔽期限" +indefinitely: "永久" +tenMinutes: "10分钟" +oneHour: "1小时" +oneDay: "1天" +oneWeek: "1周" _emailUnavailable: used: "已经被使用过" format: "无效的格式" @@ -1210,7 +1217,7 @@ _poll: noMore: "无法再添加更多了" canMultipleVote: "允许多个投票" expiration: "截止时间" - infinite: "不限时间" + infinite: "永久" at: "指定日期" after: "指定时间" deadlineDate: "截止日期" @@ -1605,6 +1612,7 @@ _notification: youReceivedFollowRequest: "您有新的关注请求" yourFollowRequestAccepted: "您的关注请求已通过" youWereInvitedToGroup: "您有新的群组邀请" + pollEnded: "问卷调查结果已生成。" _types: all: "全部" follow: "关注中" @@ -1614,6 +1622,7 @@ _notification: quote: "引用" reaction: "回应" pollVote: "问卷调查被投票" + pollEnded: "问卷调查结束" receiveFollowRequest: "收到关注请求" followRequestAccepted: "关注请求已通过" groupInvited: "加入群组邀请" diff --git a/locales/zh-TW.yml b/locales/zh-TW.yml index b10871ec1..d169e8e61 100644 --- a/locales/zh-TW.yml +++ b/locales/zh-TW.yml @@ -318,8 +318,6 @@ disablingTimelinesInfo: "即使您關閉了時間線功能,管理員和協調 registration: "註冊" enableRegistration: "開啟新使用者註冊" invite: "邀請" -proxyRemoteFiles: "遠端代理檔案" -proxyRemoteFilesDescription: "啟用此設置後,由於超出存儲容量而未保存或刪除的遠程文件將被本地代理,並且將生成預覽圖。這不影響伺服器的存儲。" driveCapacityPerLocalAccount: "每個本地用戶的雲端空間大小" driveCapacityPerRemoteAccount: "每個非本地用戶的雲端容量" inMb: "以Mbps為單位" @@ -415,7 +413,6 @@ next: "下一步" retype: "重新輸入" noteOf: "{user}的貼文" inviteToGroup: "邀請至群組" -maxNoteTextLength: "貼文的字數限制" quoteAttached: "引用" quoteQuestion: "是否要引用?" noMessagesYet: "沒有訊息" @@ -750,6 +747,7 @@ global: "公開" sent: "發送" hashtags: "#tag" hide: "隱藏" +indefinitely: "無期限" _ffVisibility: public: "發佈" _ad: diff --git a/package.json b/package.json index 621b59003..1d22e1d12 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "misskey", - "version": "12.107.0", + "version": "12.108.0", "codename": "indigo", "repository": { "type": "git", @@ -42,12 +42,10 @@ "js-yaml": "4.1.0" }, "devDependencies": { - "@redocly/openapi-core": "1.0.0-beta.79", - "@types/fluent-ffmpeg": "2.1.20", - "@typescript-eslint/parser": "5.10.0", + "@typescript-eslint/parser": "5.14.0", "cross-env": "7.0.3", - "cypress": "9.4.1", + "cypress": "9.5.0", "start-server-and-test": "1.14.0", - "typescript": "4.5.5" + "typescript": "4.6.2" } } diff --git a/packages/backend/.mocharc.json b/packages/backend/.mocharc.json index 278a5b310..26628066e 100644 --- a/packages/backend/.mocharc.json +++ b/packages/backend/.mocharc.json @@ -1,6 +1,9 @@ { "extension": ["ts","js","cjs","mjs"], - "require": ["ts-node/register", "tsconfig-paths/register"], + "node-option": [ + "experimental-specifier-resolution=node", + "loader=./test/loader.js" + ], "slow": 1000, "timeout": 35000, "exit": true diff --git a/packages/backend/assets/splash.png b/packages/backend/assets/splash.png new file mode 100644 index 000000000..3430e6efe Binary files /dev/null and b/packages/backend/assets/splash.png differ diff --git a/packages/backend/migration/1000000000000-Init.js b/packages/backend/migration/1000000000000-Init.js index 19b216600..1140be7e8 100644 --- a/packages/backend/migration/1000000000000-Init.js +++ b/packages/backend/migration/1000000000000-Init.js @@ -1,6 +1,6 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -class Init1000000000000 { + + +export class Init1000000000000 { async up(queryRunner) { await queryRunner.query(`CREATE TYPE "log_level_enum" AS ENUM('error', 'warning', 'info', 'success', 'debug')`); await queryRunner.query(`CREATE TABLE "log" ("id" character varying(32) NOT NULL, "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL, "domain" character varying(64) array NOT NULL DEFAULT '{}'::varchar[], "level" "log_level_enum" NOT NULL, "worker" character varying(8) NOT NULL, "machine" character varying(128) NOT NULL, "message" character varying(1024) NOT NULL, "data" jsonb NOT NULL DEFAULT '{}', CONSTRAINT "PK_350604cbdf991d5930d9e618fbd" PRIMARY KEY ("id"))`); @@ -480,4 +480,3 @@ class Init1000000000000 { await queryRunner.query(`DROP TYPE "log_level_enum"`); } } -exports.Init1000000000000 = Init1000000000000; diff --git a/packages/backend/migration/1556348509290-Pages.js b/packages/backend/migration/1556348509290-Pages.js index d69d17258..50caa2ce9 100644 --- a/packages/backend/migration/1556348509290-Pages.js +++ b/packages/backend/migration/1556348509290-Pages.js @@ -1,6 +1,6 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -class Pages1556348509290 { + + +export class Pages1556348509290 { async up(queryRunner) { await queryRunner.query(`CREATE TYPE "page_visibility_enum" AS ENUM('public', 'followers', 'specified')`); await queryRunner.query(`CREATE TABLE "page" ("id" character varying(32) NOT NULL, "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL, "updatedAt" TIMESTAMP WITH TIME ZONE NOT NULL, "title" character varying(256) NOT NULL, "name" character varying(256) NOT NULL, "summary" character varying(256), "alignCenter" boolean NOT NULL, "font" character varying(32) NOT NULL, "userId" character varying(32) NOT NULL, "eyeCatchingImageId" character varying(32), "content" jsonb NOT NULL DEFAULT '[]', "variables" jsonb NOT NULL DEFAULT '[]', "visibility" "page_visibility_enum" NOT NULL, "visibleUserIds" character varying(32) array NOT NULL DEFAULT '{}'::varchar[], CONSTRAINT "PK_742f4117e065c5b6ad21b37ba1f" PRIMARY KEY ("id"))`); @@ -26,4 +26,3 @@ class Pages1556348509290 { await queryRunner.query(`DROP TYPE "page_visibility_enum"`); } } -exports.Pages1556348509290 = Pages1556348509290; diff --git a/packages/backend/migration/1556746559567-UserProfile.js b/packages/backend/migration/1556746559567-UserProfile.js index 3a082b882..50a9d1a8b 100644 --- a/packages/backend/migration/1556746559567-UserProfile.js +++ b/packages/backend/migration/1556746559567-UserProfile.js @@ -1,6 +1,6 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -class UserProfile1556746559567 { + + +export class UserProfile1556746559567 { async up(queryRunner) { await queryRunner.query(`ALTER TABLE "user_profile" ALTER COLUMN "githubId" TYPE VARCHAR(64) USING "githubId"::VARCHAR(64)`); await queryRunner.query(`ALTER TABLE "user_profile" ALTER COLUMN "discordExpiresDate" TYPE VARCHAR(64) USING "discordExpiresDate"::VARCHAR(64)`); @@ -11,4 +11,3 @@ class UserProfile1556746559567 { await queryRunner.query(`ALTER TABLE "user_profile" ALTER COLUMN "discordExpiresDate" TYPE INTEGER USING NULL`); } } -exports.UserProfile1556746559567 = UserProfile1556746559567; diff --git a/packages/backend/migration/1557476068003-PinnedUsers.js b/packages/backend/migration/1557476068003-PinnedUsers.js index c5e7fe748..d9cce2543 100644 --- a/packages/backend/migration/1557476068003-PinnedUsers.js +++ b/packages/backend/migration/1557476068003-PinnedUsers.js @@ -1,6 +1,6 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -class PinnedUsers1557476068003 { + + +export class PinnedUsers1557476068003 { async up(queryRunner) { await queryRunner.query(`ALTER TABLE "meta" ADD "pinnedUsers" character varying(256) array NOT NULL DEFAULT '{}'::varchar[]`); } @@ -8,4 +8,3 @@ class PinnedUsers1557476068003 { await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "pinnedUsers"`); } } -exports.PinnedUsers1557476068003 = PinnedUsers1557476068003; diff --git a/packages/backend/migration/1557761316509-AddSomeUrls.js b/packages/backend/migration/1557761316509-AddSomeUrls.js index f6a7b409c..ab8736f7c 100644 --- a/packages/backend/migration/1557761316509-AddSomeUrls.js +++ b/packages/backend/migration/1557761316509-AddSomeUrls.js @@ -1,6 +1,6 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -class AddSomeUrls1557761316509 { + + +export class AddSomeUrls1557761316509 { async up(queryRunner) { await queryRunner.query(`ALTER TABLE "meta" ADD "ToSUrl" character varying(512)`); await queryRunner.query(`ALTER TABLE "meta" ADD "repositoryUrl" character varying(512) NOT NULL DEFAULT 'https://github.com/misskey-dev/misskey'`); @@ -12,4 +12,3 @@ class AddSomeUrls1557761316509 { await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "ToSUrl"`); } } -exports.AddSomeUrls1557761316509 = AddSomeUrls1557761316509; diff --git a/packages/backend/migration/1557932705754-ObjectStorageSetting.js b/packages/backend/migration/1557932705754-ObjectStorageSetting.js index d798ac5ca..19a0b9d5c 100644 --- a/packages/backend/migration/1557932705754-ObjectStorageSetting.js +++ b/packages/backend/migration/1557932705754-ObjectStorageSetting.js @@ -1,6 +1,6 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -class ObjectStorageSetting1557932705754 { + + +export class ObjectStorageSetting1557932705754 { async up(queryRunner) { await queryRunner.query(`ALTER TABLE "meta" ADD "useObjectStorage" boolean NOT NULL DEFAULT false`); await queryRunner.query(`ALTER TABLE "meta" ADD "objectStorageBucket" character varying(512)`); @@ -26,4 +26,3 @@ class ObjectStorageSetting1557932705754 { await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "useObjectStorage"`); } } -exports.ObjectStorageSetting1557932705754 = ObjectStorageSetting1557932705754; diff --git a/packages/backend/migration/1558072954435-PageLike.js b/packages/backend/migration/1558072954435-PageLike.js index 703843497..31b08418a 100644 --- a/packages/backend/migration/1558072954435-PageLike.js +++ b/packages/backend/migration/1558072954435-PageLike.js @@ -1,6 +1,6 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -class PageLike1558072954435 { + + +export class PageLike1558072954435 { async up(queryRunner) { await queryRunner.query(`CREATE TABLE "page_like" ("id" character varying(32) NOT NULL, "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL, "userId" character varying(32) NOT NULL, "pageId" character varying(32) NOT NULL, CONSTRAINT "PK_813f034843af992d3ae0f43c64c" PRIMARY KEY ("id"))`); await queryRunner.query(`CREATE INDEX "IDX_0e61efab7f88dbb79c9166dbb4" ON "page_like" ("userId") `); @@ -18,4 +18,3 @@ class PageLike1558072954435 { await queryRunner.query(`DROP TABLE "page_like"`); } } -exports.PageLike1558072954435 = PageLike1558072954435; diff --git a/packages/backend/migration/1558103093633-UserGroup.js b/packages/backend/migration/1558103093633-UserGroup.js index 9c1e51128..b670b31c3 100644 --- a/packages/backend/migration/1558103093633-UserGroup.js +++ b/packages/backend/migration/1558103093633-UserGroup.js @@ -1,6 +1,6 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -class UserGroup1558103093633 { + + +export class UserGroup1558103093633 { async up(queryRunner) { await queryRunner.query(`CREATE TABLE "user_group" ("id" character varying(32) NOT NULL, "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL, "name" character varying(256) NOT NULL, "userId" character varying(32) NOT NULL, "isPrivate" boolean NOT NULL DEFAULT false, CONSTRAINT "PK_3c29fba6fe013ec8724378ce7c9" PRIMARY KEY ("id"))`); await queryRunner.query(`CREATE INDEX "IDX_20e30aa35180e317e133d75316" ON "user_group" ("createdAt") `); @@ -36,4 +36,3 @@ class UserGroup1558103093633 { await queryRunner.query(`DROP TABLE "user_group"`); } } -exports.UserGroup1558103093633 = UserGroup1558103093633; diff --git a/packages/backend/migration/1558257926829-UserGroupInvite.js b/packages/backend/migration/1558257926829-UserGroupInvite.js index e8a575e74..e48bd3a7f 100644 --- a/packages/backend/migration/1558257926829-UserGroupInvite.js +++ b/packages/backend/migration/1558257926829-UserGroupInvite.js @@ -1,6 +1,6 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -class UserGroupInvite1558257926829 { + + +export class UserGroupInvite1558257926829 { async up(queryRunner) { await queryRunner.query(`CREATE TABLE "user_group_invite" ("id" character varying(32) NOT NULL, "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL, "userId" character varying(32) NOT NULL, "userGroupId" character varying(32) NOT NULL, CONSTRAINT "PK_3893884af0d3a5f4d01e7921a97" PRIMARY KEY ("id"))`); await queryRunner.query(`CREATE INDEX "IDX_1039988afa3bf991185b277fe0" ON "user_group_invite" ("userId") `); @@ -20,4 +20,3 @@ class UserGroupInvite1558257926829 { await queryRunner.query(`DROP TABLE "user_group_invite"`); } } -exports.UserGroupInvite1558257926829 = UserGroupInvite1558257926829; diff --git a/packages/backend/migration/1558266512381-UserListJoining.js b/packages/backend/migration/1558266512381-UserListJoining.js index b31f7bd3d..3398aed13 100644 --- a/packages/backend/migration/1558266512381-UserListJoining.js +++ b/packages/backend/migration/1558266512381-UserListJoining.js @@ -1,6 +1,6 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -class UserListJoining1558266512381 { + + +export class UserListJoining1558266512381 { async up(queryRunner) { await queryRunner.query(`CREATE UNIQUE INDEX "IDX_90f7da835e4c10aca6853621e1" ON "user_list_joining" ("userId", "userListId") `); } @@ -8,4 +8,3 @@ class UserListJoining1558266512381 { await queryRunner.query(`DROP INDEX "IDX_90f7da835e4c10aca6853621e1"`); } } -exports.UserListJoining1558266512381 = UserListJoining1558266512381; diff --git a/packages/backend/migration/1561706992953-webauthn.js b/packages/backend/migration/1561706992953-webauthn.js index f05054f55..b007ffef1 100644 --- a/packages/backend/migration/1561706992953-webauthn.js +++ b/packages/backend/migration/1561706992953-webauthn.js @@ -1,6 +1,6 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -class webauthn1561706992953 { + + +export class webauthn1561706992953 { async up(queryRunner) { await queryRunner.query(`CREATE TABLE "attestation_challenge" ("id" character varying(32) NOT NULL, "userId" character varying(32) NOT NULL, "challenge" character varying(64) NOT NULL, "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL, "registrationChallenge" boolean NOT NULL DEFAULT false, CONSTRAINT "PK_d0ba6786e093f1bcb497572a6b5" PRIMARY KEY ("id", "userId"))`); await queryRunner.query(`CREATE INDEX "IDX_f1a461a618fa1755692d0e0d59" ON "attestation_challenge" ("userId") `); @@ -24,4 +24,3 @@ class webauthn1561706992953 { await queryRunner.query(`DROP TABLE "attestation_challenge"`); } } -exports.webauthn1561706992953 = webauthn1561706992953; diff --git a/packages/backend/migration/1561873850023-ChartIndexes.js b/packages/backend/migration/1561873850023-ChartIndexes.js index 559cb70cb..3ce53567f 100644 --- a/packages/backend/migration/1561873850023-ChartIndexes.js +++ b/packages/backend/migration/1561873850023-ChartIndexes.js @@ -1,6 +1,6 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -class ChartIndexes1561873850023 { + + +export class ChartIndexes1561873850023 { async up(queryRunner) { await queryRunner.query(`CREATE INDEX "IDX_0ad37b7ef50f4ddc84363d7ccc" ON "__chart__active_users" ("date") `); await queryRunner.query(`CREATE INDEX "IDX_15e91a03aeeac9dbccdf43fc06" ON "__chart__active_users" ("span") `); @@ -196,4 +196,3 @@ class ChartIndexes1561873850023 { await queryRunner.query(`DROP INDEX "IDX_8cb40cfc8f3c28261e6f887b03"`); } } -exports.ChartIndexes1561873850023 = ChartIndexes1561873850023; diff --git a/packages/backend/migration/1562422242907-PasswordLessLogin.js b/packages/backend/migration/1562422242907-PasswordLessLogin.js index bed879ade..b73c7db4d 100644 --- a/packages/backend/migration/1562422242907-PasswordLessLogin.js +++ b/packages/backend/migration/1562422242907-PasswordLessLogin.js @@ -1,6 +1,6 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -class PasswordLessLogin1562422242907 { + + +export class PasswordLessLogin1562422242907 { async up(queryRunner) { await queryRunner.query(`ALTER TABLE "user_profile" ADD COLUMN "usePasswordLessLogin" boolean DEFAULT false NOT NULL`); } @@ -8,4 +8,3 @@ class PasswordLessLogin1562422242907 { await queryRunner.query(`ALTER TABLE "user_profile" DROP COLUMN "usePasswordLessLogin"`); } } -exports.PasswordLessLogin1562422242907 = PasswordLessLogin1562422242907; diff --git a/packages/backend/migration/1562444565093-PinnedPage.js b/packages/backend/migration/1562444565093-PinnedPage.js index f0aac3a4b..9a999a915 100644 --- a/packages/backend/migration/1562444565093-PinnedPage.js +++ b/packages/backend/migration/1562444565093-PinnedPage.js @@ -1,6 +1,6 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -class PinnedPage1562444565093 { + + +export class PinnedPage1562444565093 { async up(queryRunner) { await queryRunner.query(`ALTER TABLE "user_profile" ADD "pinnedPageId" character varying(32)`); await queryRunner.query(`ALTER TABLE "user_profile" ADD CONSTRAINT "UQ_6dc44f1ceb65b1e72bacef2ca27" UNIQUE ("pinnedPageId")`); @@ -12,4 +12,3 @@ class PinnedPage1562444565093 { await queryRunner.query(`ALTER TABLE "user_profile" DROP COLUMN "pinnedPageId"`); } } -exports.PinnedPage1562444565093 = PinnedPage1562444565093; diff --git a/packages/backend/migration/1562448332510-PageTitleHideOption.js b/packages/backend/migration/1562448332510-PageTitleHideOption.js index 238b74226..8fc78d202 100644 --- a/packages/backend/migration/1562448332510-PageTitleHideOption.js +++ b/packages/backend/migration/1562448332510-PageTitleHideOption.js @@ -1,6 +1,6 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -class PageTitleHideOption1562448332510 { + + +export class PageTitleHideOption1562448332510 { async up(queryRunner) { await queryRunner.query(`ALTER TABLE "page" ADD "hideTitleWhenPinned" boolean NOT NULL DEFAULT false`); } @@ -8,4 +8,3 @@ class PageTitleHideOption1562448332510 { await queryRunner.query(`ALTER TABLE "page" DROP COLUMN "hideTitleWhenPinned"`); } } -exports.PageTitleHideOption1562448332510 = PageTitleHideOption1562448332510; diff --git a/packages/backend/migration/1562869971568-ModerationLog.js b/packages/backend/migration/1562869971568-ModerationLog.js index c8953c513..dd66d16ee 100644 --- a/packages/backend/migration/1562869971568-ModerationLog.js +++ b/packages/backend/migration/1562869971568-ModerationLog.js @@ -1,6 +1,6 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -class ModerationLog1562869971568 { + + +export class ModerationLog1562869971568 { async up(queryRunner) { await queryRunner.query(`CREATE TABLE "moderation_log" ("id" character varying(32) NOT NULL, "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL, "userId" character varying(32) NOT NULL, "type" character varying(128) NOT NULL, "info" jsonb NOT NULL, CONSTRAINT "PK_d0adca6ecfd068db83e4526cc26" PRIMARY KEY ("id"))`); await queryRunner.query(`CREATE INDEX "IDX_a08ad074601d204e0f69da9a95" ON "moderation_log" ("userId") `); @@ -12,4 +12,3 @@ class ModerationLog1562869971568 { await queryRunner.query(`DROP TABLE "moderation_log"`); } } -exports.ModerationLog1562869971568 = ModerationLog1562869971568; diff --git a/packages/backend/migration/1563757595828-UsedUsername.js b/packages/backend/migration/1563757595828-UsedUsername.js index 0e59fdd45..8972df297 100644 --- a/packages/backend/migration/1563757595828-UsedUsername.js +++ b/packages/backend/migration/1563757595828-UsedUsername.js @@ -1,6 +1,6 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -class UsedUsername1563757595828 { + + +export class UsedUsername1563757595828 { async up(queryRunner) { await queryRunner.query(`CREATE TABLE "used_username" ("username" character varying(128) NOT NULL, "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL, CONSTRAINT "PK_78fd79d2d24c6ac2f4cc9a31a5d" PRIMARY KEY ("username"))`); } @@ -8,4 +8,3 @@ class UsedUsername1563757595828 { await queryRunner.query(`DROP TABLE "used_username"`); } } -exports.UsedUsername1563757595828 = UsedUsername1563757595828; diff --git a/packages/backend/migration/1565634203341-room.js b/packages/backend/migration/1565634203341-room.js index 49ca5ea50..679940f24 100644 --- a/packages/backend/migration/1565634203341-room.js +++ b/packages/backend/migration/1565634203341-room.js @@ -1,6 +1,6 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -class room1565634203341 { + + +export class room1565634203341 { async up(queryRunner) { await queryRunner.query(`ALTER TABLE "user_profile" ADD "room" jsonb NOT NULL DEFAULT '{}'`); } @@ -8,4 +8,3 @@ class room1565634203341 { await queryRunner.query(`ALTER TABLE "user_profile" DROP COLUMN "room"`); } } -exports.room1565634203341 = room1565634203341; diff --git a/packages/backend/migration/1571220798684-CustomEmojiCategory.js b/packages/backend/migration/1571220798684-CustomEmojiCategory.js index c67c437de..37c07366e 100644 --- a/packages/backend/migration/1571220798684-CustomEmojiCategory.js +++ b/packages/backend/migration/1571220798684-CustomEmojiCategory.js @@ -1,6 +1,6 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -class CustomEmojiCategory1571220798684 { + + +export class CustomEmojiCategory1571220798684 { async up(queryRunner) { await queryRunner.query(`ALTER TABLE "emoji" ADD "category" character varying(128)`, undefined); } @@ -8,4 +8,3 @@ class CustomEmojiCategory1571220798684 { await queryRunner.query(`ALTER TABLE "emoji" DROP COLUMN "category"`, undefined); } } -exports.CustomEmojiCategory1571220798684 = CustomEmojiCategory1571220798684; diff --git a/packages/backend/migration/1572760203493-nodeinfo.js b/packages/backend/migration/1572760203493-nodeinfo.js index a3ca5d718..54d5f914a 100644 --- a/packages/backend/migration/1572760203493-nodeinfo.js +++ b/packages/backend/migration/1572760203493-nodeinfo.js @@ -1,6 +1,6 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -class nodeinfo1572760203493 { + + +export class nodeinfo1572760203493 { async up(queryRunner) { await queryRunner.query(`ALTER TABLE "instance" DROP COLUMN "system"`, undefined); await queryRunner.query(`ALTER TABLE "instance" ADD "softwareName" character varying(64) DEFAULT null`, undefined); @@ -24,4 +24,3 @@ class nodeinfo1572760203493 { await queryRunner.query(`ALTER TABLE "instance" ADD "system" character varying(64)`, undefined); } } -exports.nodeinfo1572760203493 = nodeinfo1572760203493; diff --git a/packages/backend/migration/1576269851876-TalkFederationId.js b/packages/backend/migration/1576269851876-TalkFederationId.js index 63a8f8a9a..35861d571 100644 --- a/packages/backend/migration/1576269851876-TalkFederationId.js +++ b/packages/backend/migration/1576269851876-TalkFederationId.js @@ -1,6 +1,6 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -class TalkFederationId1576269851876 { + + +export class TalkFederationId1576269851876 { constructor() { this.name = 'TalkFederationId1576269851876'; } @@ -11,4 +11,3 @@ class TalkFederationId1576269851876 { await queryRunner.query(`ALTER TABLE "messaging_message" DROP COLUMN "uri"`, undefined); } } -exports.TalkFederationId1576269851876 = TalkFederationId1576269851876; diff --git a/packages/backend/migration/1576869585998-ProxyRemoteFiles.js b/packages/backend/migration/1576869585998-ProxyRemoteFiles.js index 867ae3d6e..d6d134be4 100644 --- a/packages/backend/migration/1576869585998-ProxyRemoteFiles.js +++ b/packages/backend/migration/1576869585998-ProxyRemoteFiles.js @@ -1,6 +1,6 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -class ProxyRemoteFiles1576869585998 { + + +export class ProxyRemoteFiles1576869585998 { constructor() { this.name = 'ProxyRemoteFiles1576869585998'; } @@ -11,4 +11,3 @@ class ProxyRemoteFiles1576869585998 { await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "proxyRemoteFiles"`, undefined); } } -exports.ProxyRemoteFiles1576869585998 = ProxyRemoteFiles1576869585998; diff --git a/packages/backend/migration/1579267006611-v12.js b/packages/backend/migration/1579267006611-v12.js index ccc524773..7f6318a19 100644 --- a/packages/backend/migration/1579267006611-v12.js +++ b/packages/backend/migration/1579267006611-v12.js @@ -1,6 +1,6 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -class v121579267006611 { + + +export class v121579267006611 { constructor() { this.name = 'v121579267006611'; } @@ -31,4 +31,3 @@ class v121579267006611 { await queryRunner.query(`DROP TABLE "announcement"`, undefined); } } -exports.v121579267006611 = v121579267006611; diff --git a/packages/backend/migration/1579270193251-v12-2.js b/packages/backend/migration/1579270193251-v12-2.js index 7f67645aa..c51ce6306 100644 --- a/packages/backend/migration/1579270193251-v12-2.js +++ b/packages/backend/migration/1579270193251-v12-2.js @@ -1,6 +1,6 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -class v1221579270193251 { + + +export class v1221579270193251 { constructor() { this.name = 'v1221579270193251'; } @@ -11,4 +11,3 @@ class v1221579270193251 { await queryRunner.query(`ALTER TABLE "announcement_read" DROP COLUMN "createdAt"`, undefined); } } -exports.v1221579270193251 = v1221579270193251; diff --git a/packages/backend/migration/1579282808087-v12-3.js b/packages/backend/migration/1579282808087-v12-3.js index 80fa234a5..aeb4f5a87 100644 --- a/packages/backend/migration/1579282808087-v12-3.js +++ b/packages/backend/migration/1579282808087-v12-3.js @@ -1,6 +1,6 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -class v1231579282808087 { + + +export class v1231579282808087 { constructor() { this.name = 'v1231579282808087'; } @@ -11,4 +11,3 @@ class v1231579282808087 { await queryRunner.query(`ALTER TABLE "announcement" DROP COLUMN "updatedAt"`, undefined); } } -exports.v1231579282808087 = v1231579282808087; diff --git a/packages/backend/migration/1579544426412-v12-4.js b/packages/backend/migration/1579544426412-v12-4.js index ef2b804f5..f1e093413 100644 --- a/packages/backend/migration/1579544426412-v12-4.js +++ b/packages/backend/migration/1579544426412-v12-4.js @@ -1,6 +1,6 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -class v1241579544426412 { + + +export class v1241579544426412 { constructor() { this.name = 'v1241579544426412'; } @@ -13,4 +13,3 @@ class v1241579544426412 { await queryRunner.query(`ALTER TABLE "notification" DROP COLUMN "followRequestId"`, undefined); } } -exports.v1241579544426412 = v1241579544426412; diff --git a/packages/backend/migration/1579977526288-v12-5.js b/packages/backend/migration/1579977526288-v12-5.js index 1d2ed0966..6d2b5c584 100644 --- a/packages/backend/migration/1579977526288-v12-5.js +++ b/packages/backend/migration/1579977526288-v12-5.js @@ -1,6 +1,6 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -class v1251579977526288 { + + +export class v1251579977526288 { constructor() { this.name = 'v1251579977526288'; } @@ -51,4 +51,3 @@ class v1251579977526288 { await queryRunner.query(`DROP TABLE "clip"`, undefined); } } -exports.v1251579977526288 = v1251579977526288; diff --git a/packages/backend/migration/1579993013959-v12-6.js b/packages/backend/migration/1579993013959-v12-6.js index e6c3a40a3..3941c1391 100644 --- a/packages/backend/migration/1579993013959-v12-6.js +++ b/packages/backend/migration/1579993013959-v12-6.js @@ -1,6 +1,6 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -class v1261579993013959 { + + +export class v1261579993013959 { constructor() { this.name = 'v1261579993013959'; } @@ -15,4 +15,3 @@ class v1261579993013959 { await queryRunner.query(`ALTER TABLE "antenna" ADD "hasNewNote" boolean NOT NULL DEFAULT false`, undefined); } } -exports.v1261579993013959 = v1261579993013959; diff --git a/packages/backend/migration/1580069531114-v12-7.js b/packages/backend/migration/1580069531114-v12-7.js index 7915603b8..4b4790cb7 100644 --- a/packages/backend/migration/1580069531114-v12-7.js +++ b/packages/backend/migration/1580069531114-v12-7.js @@ -1,6 +1,6 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -class v1271580069531114 { + + +export class v1271580069531114 { constructor() { this.name = 'v1271580069531114'; } @@ -21,4 +21,3 @@ class v1271580069531114 { await queryRunner.query(`ALTER TABLE "antenna" DROP COLUMN "users"`, undefined); } } -exports.v1271580069531114 = v1271580069531114; diff --git a/packages/backend/migration/1580148575182-v12-8.js b/packages/backend/migration/1580148575182-v12-8.js index 43fbc70e4..cc30200c1 100644 --- a/packages/backend/migration/1580148575182-v12-8.js +++ b/packages/backend/migration/1580148575182-v12-8.js @@ -1,6 +1,6 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -class v1281580148575182 { + + +export class v1281580148575182 { constructor() { this.name = 'v1281580148575182'; } @@ -13,4 +13,3 @@ class v1281580148575182 { await queryRunner.query(`ALTER TABLE "note" ADD CONSTRAINT "FK_ec5c201576192ba8904c345c5cc" FOREIGN KEY ("appId") REFERENCES "app"("id") ON DELETE SET NULL ON UPDATE NO ACTION`, undefined); } } -exports.v1281580148575182 = v1281580148575182; diff --git a/packages/backend/migration/1580154400017-v12-9.js b/packages/backend/migration/1580154400017-v12-9.js index f47611868..3715798f1 100644 --- a/packages/backend/migration/1580154400017-v12-9.js +++ b/packages/backend/migration/1580154400017-v12-9.js @@ -1,6 +1,6 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -class v1291580154400017 { + + +export class v1291580154400017 { constructor() { this.name = 'v1291580154400017'; } @@ -11,4 +11,3 @@ class v1291580154400017 { await queryRunner.query(`ALTER TABLE "antenna" DROP COLUMN "withReplies"`, undefined); } } -exports.v1291580154400017 = v1291580154400017; diff --git a/packages/backend/migration/1580276619901-v12-10.js b/packages/backend/migration/1580276619901-v12-10.js index 301d0ceb9..d5decb882 100644 --- a/packages/backend/migration/1580276619901-v12-10.js +++ b/packages/backend/migration/1580276619901-v12-10.js @@ -1,6 +1,6 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -class v12101580276619901 { + + +export class v12101580276619901 { constructor() { this.name = 'v12101580276619901'; } @@ -16,4 +16,3 @@ class v12101580276619901 { await queryRunner.query(`ALTER TABLE "notification" ADD "type" character varying(32) NOT NULL`, undefined); } } -exports.v12101580276619901 = v12101580276619901; diff --git a/packages/backend/migration/1580331224276-v12-11.js b/packages/backend/migration/1580331224276-v12-11.js index fb5124baa..129720adb 100644 --- a/packages/backend/migration/1580331224276-v12-11.js +++ b/packages/backend/migration/1580331224276-v12-11.js @@ -1,6 +1,6 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -class v12111580331224276 { + + +export class v12111580331224276 { constructor() { this.name = 'v12111580331224276'; } @@ -15,4 +15,3 @@ class v12111580331224276 { await queryRunner.query(`ALTER TABLE "instance" ADD "isMarkedAsClosed" boolean NOT NULL DEFAULT false`, undefined); } } -exports.v12111580331224276 = v12111580331224276; diff --git a/packages/backend/migration/1580508795118-v12-12.js b/packages/backend/migration/1580508795118-v12-12.js index eb70ba3ce..c5cec23a3 100644 --- a/packages/backend/migration/1580508795118-v12-12.js +++ b/packages/backend/migration/1580508795118-v12-12.js @@ -1,6 +1,6 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -class v12121580508795118 { + + +export class v12121580508795118 { constructor() { this.name = 'v12121580508795118'; } @@ -43,4 +43,3 @@ class v12121580508795118 { await queryRunner.query(`ALTER TABLE "user_profile" ADD "twitter" boolean NOT NULL DEFAULT false`, undefined); } } -exports.v12121580508795118 = v12121580508795118; diff --git a/packages/backend/migration/1580543501339-v12-13.js b/packages/backend/migration/1580543501339-v12-13.js index 7dae7178b..2fa490392 100644 --- a/packages/backend/migration/1580543501339-v12-13.js +++ b/packages/backend/migration/1580543501339-v12-13.js @@ -1,6 +1,6 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -class v12131580543501339 { + + +export class v12131580543501339 { constructor() { this.name = 'v12131580543501339'; } @@ -11,4 +11,3 @@ class v12131580543501339 { await queryRunner.query(`DROP INDEX "IDX_NOTE_TAGS"`, undefined); } } -exports.v12131580543501339 = v12131580543501339; diff --git a/packages/backend/migration/1580864313253-v12-14.js b/packages/backend/migration/1580864313253-v12-14.js index b1939c51b..a3756ad02 100644 --- a/packages/backend/migration/1580864313253-v12-14.js +++ b/packages/backend/migration/1580864313253-v12-14.js @@ -1,6 +1,6 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -class v12141580864313253 { + + +export class v12141580864313253 { constructor() { this.name = 'v12141580864313253'; } @@ -17,4 +17,3 @@ class v12141580864313253 { await queryRunner.query(`ALTER TABLE "meta" RENAME COLUMN "proxyAccountId" TO "proxyAccount"`, undefined); } } -exports.v12141580864313253 = v12141580864313253; diff --git a/packages/backend/migration/1581526429287-user-group-invitation.js b/packages/backend/migration/1581526429287-user-group-invitation.js index 80946c94a..181b0aba8 100644 --- a/packages/backend/migration/1581526429287-user-group-invitation.js +++ b/packages/backend/migration/1581526429287-user-group-invitation.js @@ -1,6 +1,6 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -class userGroupInvitation1581526429287 { + + +export class userGroupInvitation1581526429287 { constructor() { this.name = 'userGroupInvitation1581526429287'; } @@ -35,4 +35,3 @@ class userGroupInvitation1581526429287 { await queryRunner.query(`DROP TABLE "user_group_invitation"`, undefined); } } -exports.userGroupInvitation1581526429287 = userGroupInvitation1581526429287; diff --git a/packages/backend/migration/1581695816408-user-group-antenna.js b/packages/backend/migration/1581695816408-user-group-antenna.js index 307b5b057..267b58cd9 100644 --- a/packages/backend/migration/1581695816408-user-group-antenna.js +++ b/packages/backend/migration/1581695816408-user-group-antenna.js @@ -1,6 +1,6 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -class userGroupAntenna1581695816408 { + + +export class userGroupAntenna1581695816408 { constructor() { this.name = 'userGroupAntenna1581695816408'; } @@ -25,4 +25,3 @@ class userGroupAntenna1581695816408 { await queryRunner.query(`ALTER TABLE "antenna" DROP COLUMN "userGroupJoiningId"`, undefined); } } -exports.userGroupAntenna1581695816408 = userGroupAntenna1581695816408; diff --git a/packages/backend/migration/1581708415836-drive-user-folder-id-index.js b/packages/backend/migration/1581708415836-drive-user-folder-id-index.js index 8029ef139..43c2ce6ce 100644 --- a/packages/backend/migration/1581708415836-drive-user-folder-id-index.js +++ b/packages/backend/migration/1581708415836-drive-user-folder-id-index.js @@ -1,6 +1,6 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -class driveUserFolderIdIndex1581708415836 { + + +export class driveUserFolderIdIndex1581708415836 { constructor() { this.name = 'driveUserFolderIdIndex1581708415836'; } @@ -11,4 +11,3 @@ class driveUserFolderIdIndex1581708415836 { await queryRunner.query(`DROP INDEX "IDX_55720b33a61a7c806a8215b825"`, undefined); } } -exports.driveUserFolderIdIndex1581708415836 = driveUserFolderIdIndex1581708415836; diff --git a/packages/backend/migration/1581979837262-promo.js b/packages/backend/migration/1581979837262-promo.js index d2c5bac17..4813a5f48 100644 --- a/packages/backend/migration/1581979837262-promo.js +++ b/packages/backend/migration/1581979837262-promo.js @@ -1,6 +1,6 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -class promo1581979837262 { + + +export class promo1581979837262 { constructor() { this.name = 'promo1581979837262'; } @@ -25,4 +25,3 @@ class promo1581979837262 { await queryRunner.query(`DROP TABLE "promo_note"`, undefined); } } -exports.promo1581979837262 = promo1581979837262; diff --git a/packages/backend/migration/1582019042083-featured-injecttion.js b/packages/backend/migration/1582019042083-featured-injecttion.js index 9779e2a08..7f8790b01 100644 --- a/packages/backend/migration/1582019042083-featured-injecttion.js +++ b/packages/backend/migration/1582019042083-featured-injecttion.js @@ -1,6 +1,6 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -class featuredInjecttion1582019042083 { + + +export class featuredInjecttion1582019042083 { constructor() { this.name = 'featuredInjecttion1582019042083'; } @@ -11,4 +11,3 @@ class featuredInjecttion1582019042083 { await queryRunner.query(`ALTER TABLE "user_profile" DROP COLUMN "injectFeaturedNote"`, undefined); } } -exports.featuredInjecttion1582019042083 = featuredInjecttion1582019042083; diff --git a/packages/backend/migration/1582210532752-antenna-exclude.js b/packages/backend/migration/1582210532752-antenna-exclude.js index cc095b4b5..ff8d7b80d 100644 --- a/packages/backend/migration/1582210532752-antenna-exclude.js +++ b/packages/backend/migration/1582210532752-antenna-exclude.js @@ -1,6 +1,6 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -class antennaExclude1582210532752 { + + +export class antennaExclude1582210532752 { constructor() { this.name = 'antennaExclude1582210532752'; } @@ -11,4 +11,3 @@ class antennaExclude1582210532752 { await queryRunner.query(`ALTER TABLE "antenna" DROP COLUMN "excludeKeywords"`, undefined); } } -exports.antennaExclude1582210532752 = antennaExclude1582210532752; diff --git a/packages/backend/migration/1582875306439-note-reaction-length.js b/packages/backend/migration/1582875306439-note-reaction-length.js index bdee1ef14..e99501f01 100644 --- a/packages/backend/migration/1582875306439-note-reaction-length.js +++ b/packages/backend/migration/1582875306439-note-reaction-length.js @@ -1,6 +1,6 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -class noteReactionLength1582875306439 { + + +export class noteReactionLength1582875306439 { constructor() { this.name = 'noteReactionLength1582875306439'; } @@ -11,4 +11,3 @@ class noteReactionLength1582875306439 { await queryRunner.query(`ALTER TABLE "note_reaction" ALTER COLUMN "reaction" TYPE character varying(128)`, undefined); } } -exports.noteReactionLength1582875306439 = noteReactionLength1582875306439; diff --git a/packages/backend/migration/1585361548360-miauth.js b/packages/backend/migration/1585361548360-miauth.js index c1a695dd2..e59aa3b6e 100644 --- a/packages/backend/migration/1585361548360-miauth.js +++ b/packages/backend/migration/1585361548360-miauth.js @@ -1,6 +1,6 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -class miauth1585361548360 { + + +export class miauth1585361548360 { constructor() { this.name = 'miauth1585361548360'; } @@ -33,4 +33,3 @@ class miauth1585361548360 { await queryRunner.query(`ALTER TABLE "access_token" DROP COLUMN "lastUsedAt"`, undefined); } } -exports.miauth1585361548360 = miauth1585361548360; diff --git a/packages/backend/migration/1585385921215-custom-notification.js b/packages/backend/migration/1585385921215-custom-notification.js index 7f94c741a..c3ddb2be1 100644 --- a/packages/backend/migration/1585385921215-custom-notification.js +++ b/packages/backend/migration/1585385921215-custom-notification.js @@ -1,6 +1,6 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -class customNotification1585385921215 { + + +export class customNotification1585385921215 { constructor() { this.name = 'customNotification1585385921215'; } @@ -45,4 +45,3 @@ class customNotification1585385921215 { await queryRunner.query(`ALTER TABLE "notification" DROP COLUMN "customBody"`, undefined); } } -exports.customNotification1585385921215 = customNotification1585385921215; diff --git a/packages/backend/migration/1585772678853-ap-url.js b/packages/backend/migration/1585772678853-ap-url.js index f7c1f87b8..5fb809ff5 100644 --- a/packages/backend/migration/1585772678853-ap-url.js +++ b/packages/backend/migration/1585772678853-ap-url.js @@ -1,6 +1,6 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -class apUrl1585772678853 { + + +export class apUrl1585772678853 { constructor() { this.name = 'apUrl1585772678853'; } @@ -11,4 +11,3 @@ class apUrl1585772678853 { await queryRunner.query(`ALTER TABLE "note" DROP COLUMN "url"`, undefined); } } -exports.apUrl1585772678853 = apUrl1585772678853; diff --git a/packages/backend/migration/1586624197029-AddObjectStorageUseProxy.js b/packages/backend/migration/1586624197029-AddObjectStorageUseProxy.js index 9fcef0c90..e13bb217e 100644 --- a/packages/backend/migration/1586624197029-AddObjectStorageUseProxy.js +++ b/packages/backend/migration/1586624197029-AddObjectStorageUseProxy.js @@ -1,6 +1,6 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -class AddObjectStorageUseProxy1586624197029 { + + +export class AddObjectStorageUseProxy1586624197029 { constructor() { this.name = 'AddObjectStorageUseProxy1586624197029'; } @@ -11,4 +11,3 @@ class AddObjectStorageUseProxy1586624197029 { await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "objectStorageUseProxy"`, undefined); } } -exports.AddObjectStorageUseProxy1586624197029 = AddObjectStorageUseProxy1586624197029; diff --git a/packages/backend/migration/1586641139527-remote-reaction.js b/packages/backend/migration/1586641139527-remote-reaction.js index a9d362474..5b23103a1 100644 --- a/packages/backend/migration/1586641139527-remote-reaction.js +++ b/packages/backend/migration/1586641139527-remote-reaction.js @@ -1,6 +1,6 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -class remoteReaction1586641139527 { + + +export class remoteReaction1586641139527 { constructor() { this.name = 'remoteReaction1586641139527'; } @@ -11,4 +11,3 @@ class remoteReaction1586641139527 { await queryRunner.query(`ALTER TABLE "note_reaction" ALTER COLUMN "reaction" TYPE character varying(130)`, undefined); } } -exports.remoteReaction1586641139527 = remoteReaction1586641139527; diff --git a/packages/backend/migration/1586708940386-pageAiScript.js b/packages/backend/migration/1586708940386-pageAiScript.js index 089ff6e27..eed616c11 100644 --- a/packages/backend/migration/1586708940386-pageAiScript.js +++ b/packages/backend/migration/1586708940386-pageAiScript.js @@ -1,6 +1,6 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -class pageAiScript1586708940386 { + + +export class pageAiScript1586708940386 { constructor() { this.name = 'pageAiScript1586708940386'; } @@ -11,4 +11,3 @@ class pageAiScript1586708940386 { await queryRunner.query(`ALTER TABLE "page" DROP COLUMN "script"`, undefined); } } -exports.pageAiScript1586708940386 = pageAiScript1586708940386; diff --git a/packages/backend/migration/1588044505511-hCaptcha.js b/packages/backend/migration/1588044505511-hCaptcha.js index 9b2524afb..a33dbd713 100644 --- a/packages/backend/migration/1588044505511-hCaptcha.js +++ b/packages/backend/migration/1588044505511-hCaptcha.js @@ -1,6 +1,6 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -class hCaptcha1588044505511 { + + +export class hCaptcha1588044505511 { constructor() { this.name = 'hCaptcha1588044505511'; } @@ -15,4 +15,3 @@ class hCaptcha1588044505511 { await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "enableHcaptcha"`, undefined); } } -exports.hCaptcha1588044505511 = hCaptcha1588044505511; diff --git a/packages/backend/migration/1589023282116-pubRelay.js b/packages/backend/migration/1589023282116-pubRelay.js index f03384a51..48a1028d3 100644 --- a/packages/backend/migration/1589023282116-pubRelay.js +++ b/packages/backend/migration/1589023282116-pubRelay.js @@ -1,6 +1,6 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -class pubRelay1589023282116 { + + +export class pubRelay1589023282116 { constructor() { this.name = 'pubRelay1589023282116'; } @@ -15,4 +15,3 @@ class pubRelay1589023282116 { await queryRunner.query(`DROP TYPE "relay_status_enum"`, undefined); } } -exports.pubRelay1589023282116 = pubRelay1589023282116; diff --git a/packages/backend/migration/1595075960584-blurhash.js b/packages/backend/migration/1595075960584-blurhash.js index 3bd9c46f1..f24d3722c 100644 --- a/packages/backend/migration/1595075960584-blurhash.js +++ b/packages/backend/migration/1595075960584-blurhash.js @@ -1,6 +1,6 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -class blurhash1595075960584 { + + +export class blurhash1595075960584 { constructor() { this.name = 'blurhash1595075960584'; } @@ -11,4 +11,3 @@ class blurhash1595075960584 { await queryRunner.query(`ALTER TABLE "drive_file" DROP COLUMN "blurhash"`); } } -exports.blurhash1595075960584 = blurhash1595075960584; diff --git a/packages/backend/migration/1595077605646-blurhash-for-avatar-banner.js b/packages/backend/migration/1595077605646-blurhash-for-avatar-banner.js index c2a9c9756..f18f6f972 100644 --- a/packages/backend/migration/1595077605646-blurhash-for-avatar-banner.js +++ b/packages/backend/migration/1595077605646-blurhash-for-avatar-banner.js @@ -1,6 +1,6 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -class blurhashForAvatarBanner1595077605646 { + + +export class blurhashForAvatarBanner1595077605646 { constructor() { this.name = 'blurhashForAvatarBanner1595077605646'; } @@ -17,4 +17,3 @@ class blurhashForAvatarBanner1595077605646 { await queryRunner.query(`ALTER TABLE "user" ADD "avatarColor" character varying(32)`); } } -exports.blurhashForAvatarBanner1595077605646 = blurhashForAvatarBanner1595077605646; diff --git a/packages/backend/migration/1595676934834-instance-icon-url.js b/packages/backend/migration/1595676934834-instance-icon-url.js index 21ae26c55..df9d8199b 100644 --- a/packages/backend/migration/1595676934834-instance-icon-url.js +++ b/packages/backend/migration/1595676934834-instance-icon-url.js @@ -1,6 +1,6 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -class instanceIconUrl1595676934834 { + + +export class instanceIconUrl1595676934834 { constructor() { this.name = 'instanceIconUrl1595676934834'; } @@ -11,4 +11,3 @@ class instanceIconUrl1595676934834 { await queryRunner.query(`ALTER TABLE "instance" DROP COLUMN "iconUrl"`); } } -exports.instanceIconUrl1595676934834 = instanceIconUrl1595676934834; diff --git a/packages/backend/migration/1595771249699-word-mute.js b/packages/backend/migration/1595771249699-word-mute.js index 0dd3a5556..e8e4ac838 100644 --- a/packages/backend/migration/1595771249699-word-mute.js +++ b/packages/backend/migration/1595771249699-word-mute.js @@ -1,6 +1,6 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -class wordMute1595771249699 { + + +export class wordMute1595771249699 { constructor() { this.name = 'wordMute1595771249699'; } @@ -27,4 +27,3 @@ class wordMute1595771249699 { await queryRunner.query(`DROP TABLE "muted_note"`); } } -exports.wordMute1595771249699 = wordMute1595771249699; diff --git a/packages/backend/migration/1595782306083-word-mute2.js b/packages/backend/migration/1595782306083-word-mute2.js index 29c707e95..ab1e40a04 100644 --- a/packages/backend/migration/1595782306083-word-mute2.js +++ b/packages/backend/migration/1595782306083-word-mute2.js @@ -1,6 +1,6 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -class wordMute21595782306083 { + + +export class wordMute21595782306083 { constructor() { this.name = 'wordMute21595782306083'; } @@ -15,4 +15,3 @@ class wordMute21595782306083 { await queryRunner.query(`DROP TYPE "muted_note_reason_enum"`); } } -exports.wordMute21595782306083 = wordMute21595782306083; diff --git a/packages/backend/migration/1596548170836-channel.js b/packages/backend/migration/1596548170836-channel.js index bce812d5e..242db7d45 100644 --- a/packages/backend/migration/1596548170836-channel.js +++ b/packages/backend/migration/1596548170836-channel.js @@ -1,6 +1,6 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -class channel1596548170836 { + + +export class channel1596548170836 { constructor() { this.name = 'channel1596548170836'; } @@ -55,4 +55,3 @@ class channel1596548170836 { await queryRunner.query(`DROP TABLE "channel"`); } } -exports.channel1596548170836 = channel1596548170836; diff --git a/packages/backend/migration/1596786425167-channel2.js b/packages/backend/migration/1596786425167-channel2.js index 160c73b06..4b17048fe 100644 --- a/packages/backend/migration/1596786425167-channel2.js +++ b/packages/backend/migration/1596786425167-channel2.js @@ -1,6 +1,6 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -class channel21596786425167 { + + +export class channel21596786425167 { constructor() { this.name = 'channel21596786425167'; } @@ -11,4 +11,3 @@ class channel21596786425167 { await queryRunner.query(`ALTER TABLE "channel_following" DROP COLUMN "readCursor"`); } } -exports.channel21596786425167 = channel21596786425167; diff --git a/packages/backend/migration/1597230137744-objectStorageSetPublicRead.js b/packages/backend/migration/1597230137744-objectStorageSetPublicRead.js index d208c425e..07283e31d 100644 --- a/packages/backend/migration/1597230137744-objectStorageSetPublicRead.js +++ b/packages/backend/migration/1597230137744-objectStorageSetPublicRead.js @@ -1,6 +1,6 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -class objectStorageSetPublicRead1597230137744 { + + +export class objectStorageSetPublicRead1597230137744 { constructor() { this.name = 'objectStorageSetPublicRead1597230137744'; } @@ -11,4 +11,3 @@ class objectStorageSetPublicRead1597230137744 { await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "objectStorageSetPublicRead"`); } } -exports.objectStorageSetPublicRead1597230137744 = objectStorageSetPublicRead1597230137744; diff --git a/packages/backend/migration/1597236229720-IncludingNotificationTypes.js b/packages/backend/migration/1597236229720-IncludingNotificationTypes.js index 0efbf2fe5..f498fa7d9 100644 --- a/packages/backend/migration/1597236229720-IncludingNotificationTypes.js +++ b/packages/backend/migration/1597236229720-IncludingNotificationTypes.js @@ -1,6 +1,6 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -class IncludingNotificationTypes1597236229720 { + + +export class IncludingNotificationTypes1597236229720 { constructor() { this.name = 'IncludingNotificationTypes1597236229720'; } @@ -13,4 +13,3 @@ class IncludingNotificationTypes1597236229720 { await queryRunner.query(`DROP TYPE "user_profile_includingnotificationtypes_enum"`); } } -exports.IncludingNotificationTypes1597236229720 = IncludingNotificationTypes1597236229720; diff --git a/packages/backend/migration/1597385880794-add-sensitive-index.js b/packages/backend/migration/1597385880794-add-sensitive-index.js index 69fd394b0..8c5c040ba 100644 --- a/packages/backend/migration/1597385880794-add-sensitive-index.js +++ b/packages/backend/migration/1597385880794-add-sensitive-index.js @@ -1,6 +1,6 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -class addSensitiveIndex1597385880794 { + + +export class addSensitiveIndex1597385880794 { constructor() { this.name = 'addSensitiveIndex1597385880794'; } @@ -11,4 +11,3 @@ class addSensitiveIndex1597385880794 { await queryRunner.query(`DROP INDEX "IDX_a7eba67f8b3fa27271e85d2e26"`); } } -exports.addSensitiveIndex1597385880794 = addSensitiveIndex1597385880794; diff --git a/packages/backend/migration/1597459042300-channel-unread.js b/packages/backend/migration/1597459042300-channel-unread.js index 629aa6009..3157ab779 100644 --- a/packages/backend/migration/1597459042300-channel-unread.js +++ b/packages/backend/migration/1597459042300-channel-unread.js @@ -1,6 +1,6 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -class channelUnread1597459042300 { + + +export class channelUnread1597459042300 { constructor() { this.name = 'channelUnread1597459042300'; } @@ -24,4 +24,3 @@ class channelUnread1597459042300 { await queryRunner.query(`ALTER TABLE "channel_following" ADD "readCursor" TIMESTAMP WITH TIME ZONE NOT NULL`); } } -exports.channelUnread1597459042300 = channelUnread1597459042300; diff --git a/packages/backend/migration/1597893996136-ChannelNoteIdDescIndex.js b/packages/backend/migration/1597893996136-ChannelNoteIdDescIndex.js index 770ac1887..2bd8aee35 100644 --- a/packages/backend/migration/1597893996136-ChannelNoteIdDescIndex.js +++ b/packages/backend/migration/1597893996136-ChannelNoteIdDescIndex.js @@ -1,6 +1,6 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -class ChannelNoteIdDescIndex1597893996136 { + + +export class ChannelNoteIdDescIndex1597893996136 { constructor() { this.name = 'ChannelNoteIdDescIndex1597893996136'; } @@ -13,4 +13,3 @@ class ChannelNoteIdDescIndex1597893996136 { await queryRunner.query(`CREATE INDEX "IDX_f22169eb10657bded6d875ac8f" ON "note" ("channelId") `); } } -exports.ChannelNoteIdDescIndex1597893996136 = ChannelNoteIdDescIndex1597893996136; diff --git a/packages/backend/migration/1600353287890-mutingNotificationTypes.js b/packages/backend/migration/1600353287890-mutingNotificationTypes.js index d39a6f2e4..ed3eb7d14 100644 --- a/packages/backend/migration/1600353287890-mutingNotificationTypes.js +++ b/packages/backend/migration/1600353287890-mutingNotificationTypes.js @@ -1,6 +1,6 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -class mutingNotificationTypes1600353287890 { + + +export class mutingNotificationTypes1600353287890 { constructor() { this.name = 'mutingNotificationTypes1600353287890'; } @@ -17,4 +17,3 @@ class mutingNotificationTypes1600353287890 { await queryRunner.query(`ALTER TABLE "user_profile" ADD "includingNotificationTypes" "user_profile_includingnotificationtypes_enum" array`); } } -exports.mutingNotificationTypes1600353287890 = mutingNotificationTypes1600353287890; diff --git a/packages/backend/migration/1603094348345-refine-abuse-user-report.js b/packages/backend/migration/1603094348345-refine-abuse-user-report.js index b01a5d80a..4918032a2 100644 --- a/packages/backend/migration/1603094348345-refine-abuse-user-report.js +++ b/packages/backend/migration/1603094348345-refine-abuse-user-report.js @@ -1,6 +1,6 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -class refineAbuseUserReport1603094348345 { + + +export class refineAbuseUserReport1603094348345 { constructor() { this.name = 'refineAbuseUserReport1603094348345'; } @@ -29,4 +29,3 @@ class refineAbuseUserReport1603094348345 { await queryRunner.query(`ALTER TABLE "abuse_user_report" ADD CONSTRAINT "FK_d049123c413e68ca52abe734203" FOREIGN KEY ("userId") REFERENCES "user"("id") ON DELETE CASCADE ON UPDATE NO ACTION`); } } -exports.refineAbuseUserReport1603094348345 = refineAbuseUserReport1603094348345; diff --git a/packages/backend/migration/1603095701770-refine-abuse-user-report2.js b/packages/backend/migration/1603095701770-refine-abuse-user-report2.js index 32b4e0bd2..64e92672f 100644 --- a/packages/backend/migration/1603095701770-refine-abuse-user-report2.js +++ b/packages/backend/migration/1603095701770-refine-abuse-user-report2.js @@ -1,6 +1,6 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -class refineAbuseUserReport21603095701770 { + + +export class refineAbuseUserReport21603095701770 { constructor() { this.name = 'refineAbuseUserReport21603095701770'; } @@ -17,4 +17,3 @@ class refineAbuseUserReport21603095701770 { await queryRunner.query(`ALTER TABLE "abuse_user_report" DROP COLUMN "targetUserHost"`); } } -exports.refineAbuseUserReport21603095701770 = refineAbuseUserReport21603095701770; diff --git a/packages/backend/migration/1603776877564-instance-theme-color.js b/packages/backend/migration/1603776877564-instance-theme-color.js index 315305f53..92440d3f6 100644 --- a/packages/backend/migration/1603776877564-instance-theme-color.js +++ b/packages/backend/migration/1603776877564-instance-theme-color.js @@ -1,6 +1,6 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -class instanceThemeColor1603776877564 { + + +export class instanceThemeColor1603776877564 { constructor() { this.name = 'instanceThemeColor1603776877564'; } @@ -11,4 +11,3 @@ class instanceThemeColor1603776877564 { await queryRunner.query(`ALTER TABLE "instance" DROP COLUMN "themeColor"`); } } -exports.instanceThemeColor1603776877564 = instanceThemeColor1603776877564; diff --git a/packages/backend/migration/1603781553011-instance-favicon.js b/packages/backend/migration/1603781553011-instance-favicon.js index 451989f91..f607c49ff 100644 --- a/packages/backend/migration/1603781553011-instance-favicon.js +++ b/packages/backend/migration/1603781553011-instance-favicon.js @@ -1,6 +1,6 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -class instanceFavicon1603781553011 { + + +export class instanceFavicon1603781553011 { constructor() { this.name = 'instanceFavicon1603781553011'; } @@ -11,4 +11,3 @@ class instanceFavicon1603781553011 { await queryRunner.query(`ALTER TABLE "instance" DROP COLUMN "faviconUrl"`); } } -exports.instanceFavicon1603781553011 = instanceFavicon1603781553011; diff --git a/packages/backend/migration/1604821689616-delete-auto-watch.js b/packages/backend/migration/1604821689616-delete-auto-watch.js index 9d972dd3f..4706e8bae 100644 --- a/packages/backend/migration/1604821689616-delete-auto-watch.js +++ b/packages/backend/migration/1604821689616-delete-auto-watch.js @@ -1,6 +1,6 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -class deleteAutoWatch1604821689616 { + + +export class deleteAutoWatch1604821689616 { constructor() { this.name = 'deleteAutoWatch1604821689616'; } @@ -11,4 +11,3 @@ class deleteAutoWatch1604821689616 { await queryRunner.query(`ALTER TABLE "user_profile" ADD "autoWatch" boolean NOT NULL DEFAULT false`); } } -exports.deleteAutoWatch1604821689616 = deleteAutoWatch1604821689616; diff --git a/packages/backend/migration/1605408848373-clip-description.js b/packages/backend/migration/1605408848373-clip-description.js index acbe2b0c8..edd5505b3 100644 --- a/packages/backend/migration/1605408848373-clip-description.js +++ b/packages/backend/migration/1605408848373-clip-description.js @@ -1,6 +1,6 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -class clipDescription1605408848373 { + + +export class clipDescription1605408848373 { constructor() { this.name = 'clipDescription1605408848373'; } @@ -11,4 +11,3 @@ class clipDescription1605408848373 { await queryRunner.query(`ALTER TABLE "clip" DROP COLUMN "description"`); } } -exports.clipDescription1605408848373 = clipDescription1605408848373; diff --git a/packages/backend/migration/1605408971051-comments.js b/packages/backend/migration/1605408971051-comments.js index 6e5dacbb6..400efd5e7 100644 --- a/packages/backend/migration/1605408971051-comments.js +++ b/packages/backend/migration/1605408971051-comments.js @@ -1,6 +1,6 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -class comments1605408971051 { + + +export class comments1605408971051 { constructor() { this.name = 'comments1605408971051'; } @@ -431,4 +431,3 @@ class comments1605408971051 { await queryRunner.query(`COMMENT ON COLUMN "log"."createdAt" IS NULL`); } } -exports.comments1605408971051 = comments1605408971051; diff --git a/packages/backend/migration/1605585339718-instance-pinned-pages.js b/packages/backend/migration/1605585339718-instance-pinned-pages.js index 8d2357276..56ccd44c8 100644 --- a/packages/backend/migration/1605585339718-instance-pinned-pages.js +++ b/packages/backend/migration/1605585339718-instance-pinned-pages.js @@ -1,6 +1,6 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -class instancePinnedPages1605585339718 { + + +export class instancePinnedPages1605585339718 { constructor() { this.name = 'instancePinnedPages1605585339718'; } @@ -11,4 +11,3 @@ class instancePinnedPages1605585339718 { await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "pinnedPages"`); } } -exports.instancePinnedPages1605585339718 = instancePinnedPages1605585339718; diff --git a/packages/backend/migration/1605965516823-instance-images.js b/packages/backend/migration/1605965516823-instance-images.js index f078428ba..710c75981 100644 --- a/packages/backend/migration/1605965516823-instance-images.js +++ b/packages/backend/migration/1605965516823-instance-images.js @@ -1,6 +1,6 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -class instanceImages1605965516823 { + + +export class instanceImages1605965516823 { constructor() { this.name = 'instanceImages1605965516823'; } @@ -13,4 +13,3 @@ class instanceImages1605965516823 { await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "backgroundImageUrl"`); } } -exports.instanceImages1605965516823 = instanceImages1605965516823; diff --git a/packages/backend/migration/1606191203881-no-crawle.js b/packages/backend/migration/1606191203881-no-crawle.js index 2c5fdaed2..b9ada4354 100644 --- a/packages/backend/migration/1606191203881-no-crawle.js +++ b/packages/backend/migration/1606191203881-no-crawle.js @@ -1,6 +1,6 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -class noCrawle1606191203881 { + + +export class noCrawle1606191203881 { constructor() { this.name = 'noCrawle1606191203881'; } @@ -13,4 +13,3 @@ class noCrawle1606191203881 { await queryRunner.query(`ALTER TABLE "user_profile" DROP COLUMN "noCrawle"`); } } -exports.noCrawle1606191203881 = noCrawle1606191203881; diff --git a/packages/backend/migration/1607151207216-instance-pinned-clip.js b/packages/backend/migration/1607151207216-instance-pinned-clip.js index 3bd479296..9a4195e74 100644 --- a/packages/backend/migration/1607151207216-instance-pinned-clip.js +++ b/packages/backend/migration/1607151207216-instance-pinned-clip.js @@ -1,6 +1,6 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -class instancePinnedClip1607151207216 { + + +export class instancePinnedClip1607151207216 { constructor() { this.name = 'instancePinnedClip1607151207216'; } @@ -11,4 +11,3 @@ class instancePinnedClip1607151207216 { await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "pinnedClipId"`); } } -exports.instancePinnedClip1607151207216 = instancePinnedClip1607151207216; diff --git a/packages/backend/migration/1607353487793-isExplorable.js b/packages/backend/migration/1607353487793-isExplorable.js index 3ddd0cb32..d9f1ff4c6 100644 --- a/packages/backend/migration/1607353487793-isExplorable.js +++ b/packages/backend/migration/1607353487793-isExplorable.js @@ -1,6 +1,6 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -class isExplorable1607353487793 { + + +export class isExplorable1607353487793 { constructor() { this.name = 'isExplorable1607353487793'; } @@ -15,4 +15,3 @@ class isExplorable1607353487793 { await queryRunner.query(`ALTER TABLE "user" DROP COLUMN "isExplorable"`); } } -exports.isExplorable1607353487793 = isExplorable1607353487793; diff --git a/packages/backend/migration/1610277136869-registry.js b/packages/backend/migration/1610277136869-registry.js index a7b5af84b..184c062dd 100644 --- a/packages/backend/migration/1610277136869-registry.js +++ b/packages/backend/migration/1610277136869-registry.js @@ -1,6 +1,6 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -class registry1610277136869 { + + +export class registry1610277136869 { constructor() { this.name = 'registry1610277136869'; } @@ -19,4 +19,3 @@ class registry1610277136869 { await queryRunner.query(`DROP TABLE "registry_item"`); } } -exports.registry1610277136869 = registry1610277136869; diff --git a/packages/backend/migration/1610277585759-registry2.js b/packages/backend/migration/1610277585759-registry2.js index aa1417e18..591bafae3 100644 --- a/packages/backend/migration/1610277585759-registry2.js +++ b/packages/backend/migration/1610277585759-registry2.js @@ -1,6 +1,6 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -class registry21610277585759 { + + +export class registry21610277585759 { constructor() { this.name = 'registry21610277585759'; } @@ -13,4 +13,3 @@ class registry21610277585759 { await queryRunner.query(`ALTER TABLE "registry_item" DROP COLUMN "value"`); } } -exports.registry21610277585759 = registry21610277585759; diff --git a/packages/backend/migration/1610283021566-registry3.js b/packages/backend/migration/1610283021566-registry3.js index 7089cee1f..e0289f17e 100644 --- a/packages/backend/migration/1610283021566-registry3.js +++ b/packages/backend/migration/1610283021566-registry3.js @@ -1,6 +1,6 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -class registry31610283021566 { + + +export class registry31610283021566 { constructor() { this.name = 'registry31610283021566'; } @@ -11,4 +11,3 @@ class registry31610283021566 { await queryRunner.query(`ALTER TABLE "registry_item" ALTER COLUMN "value" SET NOT NULL`); } } -exports.registry31610283021566 = registry31610283021566; diff --git a/packages/backend/migration/1611354329133-followersUri.js b/packages/backend/migration/1611354329133-followersUri.js index e944da73a..669ddb480 100644 --- a/packages/backend/migration/1611354329133-followersUri.js +++ b/packages/backend/migration/1611354329133-followersUri.js @@ -1,6 +1,6 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -class followersUri1611354329133 { + + +export class followersUri1611354329133 { constructor() { this.name = 'followersUri1611354329133'; } @@ -13,4 +13,3 @@ class followersUri1611354329133 { await queryRunner.query(`ALTER TABLE "user" DROP COLUMN "followersUri"`); } } -exports.followersUri1611354329133 = followersUri1611354329133; diff --git a/packages/backend/migration/1611397665007-gallery.js b/packages/backend/migration/1611397665007-gallery.js index 9cf73cbcf..f49b2df46 100644 --- a/packages/backend/migration/1611397665007-gallery.js +++ b/packages/backend/migration/1611397665007-gallery.js @@ -1,6 +1,6 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -class gallery1611397665007 { + + +export class gallery1611397665007 { constructor() { this.name = 'gallery1611397665007'; } @@ -37,4 +37,3 @@ class gallery1611397665007 { await queryRunner.query(`DROP TABLE "gallery_post"`); } } -exports.gallery1611397665007 = gallery1611397665007; diff --git a/packages/backend/migration/1611547387175-objectStorageS3ForcePathStyle.js b/packages/backend/migration/1611547387175-objectStorageS3ForcePathStyle.js index 50a618994..e4d3c0e8e 100644 --- a/packages/backend/migration/1611547387175-objectStorageS3ForcePathStyle.js +++ b/packages/backend/migration/1611547387175-objectStorageS3ForcePathStyle.js @@ -1,6 +1,6 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -class objectStorageS3ForcePathStyle1611547387175 { + + +export class objectStorageS3ForcePathStyle1611547387175 { constructor() { this.name = 'objectStorageS3ForcePathStyle1611547387175'; } @@ -11,4 +11,3 @@ class objectStorageS3ForcePathStyle1611547387175 { await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "objectStorageS3ForcePathStyle"`); } } -exports.objectStorageS3ForcePathStyle1611547387175 = objectStorageS3ForcePathStyle1611547387175; diff --git a/packages/backend/migration/1612619156584-announcement-email.js b/packages/backend/migration/1612619156584-announcement-email.js index bbd04679b..bcc718d1c 100644 --- a/packages/backend/migration/1612619156584-announcement-email.js +++ b/packages/backend/migration/1612619156584-announcement-email.js @@ -1,6 +1,6 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -class announcementEmail1612619156584 { + + +export class announcementEmail1612619156584 { constructor() { this.name = 'announcementEmail1612619156584'; } @@ -11,4 +11,3 @@ class announcementEmail1612619156584 { await queryRunner.query(`ALTER TABLE "user_profile" DROP COLUMN "receiveAnnouncementEmail"`); } } -exports.announcementEmail1612619156584 = announcementEmail1612619156584; diff --git a/packages/backend/migration/1613155914446-emailNotificationTypes.js b/packages/backend/migration/1613155914446-emailNotificationTypes.js index 30fa4924b..cd49924d2 100644 --- a/packages/backend/migration/1613155914446-emailNotificationTypes.js +++ b/packages/backend/migration/1613155914446-emailNotificationTypes.js @@ -1,6 +1,6 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -class emailNotificationTypes1613155914446 { + + +export class emailNotificationTypes1613155914446 { constructor() { this.name = 'emailNotificationTypes1613155914446'; } @@ -11,4 +11,3 @@ class emailNotificationTypes1613155914446 { await queryRunner.query(`ALTER TABLE "user_profile" DROP COLUMN "emailNotificationTypes"`); } } -exports.emailNotificationTypes1613155914446 = emailNotificationTypes1613155914446; diff --git a/packages/backend/migration/1613181457597-user-lang.js b/packages/backend/migration/1613181457597-user-lang.js index f6be7cdab..d2cd06848 100644 --- a/packages/backend/migration/1613181457597-user-lang.js +++ b/packages/backend/migration/1613181457597-user-lang.js @@ -1,6 +1,6 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -class userLang1613181457597 { + + +export class userLang1613181457597 { constructor() { this.name = 'userLang1613181457597'; } @@ -11,4 +11,3 @@ class userLang1613181457597 { await queryRunner.query(`ALTER TABLE "user_profile" DROP COLUMN "lang"`); } } -exports.userLang1613181457597 = userLang1613181457597; diff --git a/packages/backend/migration/1613503367223-use-bigint-for-driveUsage.js b/packages/backend/migration/1613503367223-use-bigint-for-driveUsage.js index 91956ad78..f2e2c5d35 100644 --- a/packages/backend/migration/1613503367223-use-bigint-for-driveUsage.js +++ b/packages/backend/migration/1613503367223-use-bigint-for-driveUsage.js @@ -1,6 +1,6 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -class useBigintForDriveUsage1613503367223 { + + +export class useBigintForDriveUsage1613503367223 { constructor() { this.name = 'useBigintForDriveUsage1613503367223'; } @@ -12,4 +12,3 @@ class useBigintForDriveUsage1613503367223 { await queryRunner.query(`ALTER TABLE "instance" ADD "driveUsage" integer NOT NULL DEFAULT 0`); } } -exports.useBigintForDriveUsage1613503367223 = useBigintForDriveUsage1613503367223; diff --git a/packages/backend/migration/1615965918224-chart-v2.js b/packages/backend/migration/1615965918224-chart-v2.js index 95f44879b..86fa5b0c0 100644 --- a/packages/backend/migration/1615965918224-chart-v2.js +++ b/packages/backend/migration/1615965918224-chart-v2.js @@ -1,6 +1,6 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -class chartV21615965918224 { + + +export class chartV21615965918224 { constructor() { this.name = 'chartV21615965918224'; } @@ -214,4 +214,3 @@ class chartV21615965918224 { await queryRunner.query(`CREATE INDEX "IDX_15e91a03aeeac9dbccdf43fc06" ON "__chart__active_users" ("span") `); } } -exports.chartV21615965918224 = chartV21615965918224; diff --git a/packages/backend/migration/1615966519402-chart-v2-2.js b/packages/backend/migration/1615966519402-chart-v2-2.js index 85a83df1a..c62f1b875 100644 --- a/packages/backend/migration/1615966519402-chart-v2-2.js +++ b/packages/backend/migration/1615966519402-chart-v2-2.js @@ -1,6 +1,6 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -class chartV221615966519402 { + + +export class chartV221615966519402 { constructor() { this.name = 'chartV221615966519402'; } @@ -19,4 +19,3 @@ class chartV221615966519402 { await queryRunner.query(`ALTER TABLE "__chart__active_users" DROP COLUMN "___local_users"`); } } -exports.chartV221615966519402 = chartV221615966519402; diff --git a/packages/backend/migration/1618637372000-user-last-active-date.js b/packages/backend/migration/1618637372000-user-last-active-date.js index 03fc011e4..6c77ace46 100644 --- a/packages/backend/migration/1618637372000-user-last-active-date.js +++ b/packages/backend/migration/1618637372000-user-last-active-date.js @@ -1,6 +1,6 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -class userLastActiveDate1618637372000 { + + +export class userLastActiveDate1618637372000 { constructor() { this.name = 'userLastActiveDate1618637372000'; } @@ -13,4 +13,3 @@ class userLastActiveDate1618637372000 { await queryRunner.query(`ALTER TABLE "user" DROP COLUMN "lastActiveDate"`); } } -exports.userLastActiveDate1618637372000 = userLastActiveDate1618637372000; diff --git a/packages/backend/migration/1618639857000-user-hide-online-status.js b/packages/backend/migration/1618639857000-user-hide-online-status.js index 0b1e34100..e63c8ae11 100644 --- a/packages/backend/migration/1618639857000-user-hide-online-status.js +++ b/packages/backend/migration/1618639857000-user-hide-online-status.js @@ -1,6 +1,6 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -class userHideOnlineStatus1618639857000 { + + +export class userHideOnlineStatus1618639857000 { constructor() { this.name = 'userHideOnlineStatus1618639857000'; } @@ -11,4 +11,3 @@ class userHideOnlineStatus1618639857000 { await queryRunner.query(`ALTER TABLE "user" DROP COLUMN "hideOnlineStatus"`); } } -exports.userHideOnlineStatus1618639857000 = userHideOnlineStatus1618639857000; diff --git a/packages/backend/migration/1619942102890-password-reset.js b/packages/backend/migration/1619942102890-password-reset.js index 9505be4b8..922d225dc 100644 --- a/packages/backend/migration/1619942102890-password-reset.js +++ b/packages/backend/migration/1619942102890-password-reset.js @@ -1,6 +1,6 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -class passwordReset1619942102890 { + + +export class passwordReset1619942102890 { constructor() { this.name = 'passwordReset1619942102890'; } @@ -17,4 +17,3 @@ class passwordReset1619942102890 { await queryRunner.query(`DROP TABLE "password_reset_request"`); } } -exports.passwordReset1619942102890 = passwordReset1619942102890; diff --git a/packages/backend/migration/1620019354680-ad.js b/packages/backend/migration/1620019354680-ad.js index 655629bc3..c96d2bfb3 100644 --- a/packages/backend/migration/1620019354680-ad.js +++ b/packages/backend/migration/1620019354680-ad.js @@ -1,6 +1,6 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -class ad1620019354680 { + + +export class ad1620019354680 { constructor() { this.name = 'ad1620019354680'; } @@ -15,4 +15,3 @@ class ad1620019354680 { await queryRunner.query(`DROP TABLE "ad"`); } } -exports.ad1620019354680 = ad1620019354680; diff --git a/packages/backend/migration/1620364649428-ad2.js b/packages/backend/migration/1620364649428-ad2.js index 7f2213f6a..db1c3e1de 100644 --- a/packages/backend/migration/1620364649428-ad2.js +++ b/packages/backend/migration/1620364649428-ad2.js @@ -1,6 +1,6 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -class ad21620364649428 { + + +export class ad21620364649428 { constructor() { this.name = 'ad21620364649428'; } @@ -11,4 +11,3 @@ class ad21620364649428 { await queryRunner.query(`ALTER TABLE "ad" DROP COLUMN "ratio"`); } } -exports.ad21620364649428 = ad21620364649428; diff --git a/packages/backend/migration/1621479946000-add-note-indexes.js b/packages/backend/migration/1621479946000-add-note-indexes.js index 1bf9827f6..dcf97fa4d 100644 --- a/packages/backend/migration/1621479946000-add-note-indexes.js +++ b/packages/backend/migration/1621479946000-add-note-indexes.js @@ -1,6 +1,6 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -class addNoteIndexes1621479946000 { + + +export class addNoteIndexes1621479946000 { constructor() { this.name = 'addNoteIndexes1621479946000'; } @@ -13,4 +13,3 @@ class addNoteIndexes1621479946000 { await queryRunner.query(`DROP INDEX "IDX_NOTE_VISIBLE_USER_IDS"`, undefined); } } -exports.addNoteIndexes1621479946000 = addNoteIndexes1621479946000; diff --git a/packages/backend/migration/1622679304522-user-profile-description-length.js b/packages/backend/migration/1622679304522-user-profile-description-length.js index 237870d6c..22f6c1c5d 100644 --- a/packages/backend/migration/1622679304522-user-profile-description-length.js +++ b/packages/backend/migration/1622679304522-user-profile-description-length.js @@ -1,6 +1,6 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -class userProfileDescriptionLength1622679304522 { + + +export class userProfileDescriptionLength1622679304522 { constructor() { this.name = 'userProfileDescriptionLength1622679304522'; } @@ -11,4 +11,3 @@ class userProfileDescriptionLength1622679304522 { await queryRunner.query(`ALTER TABLE "user_profile" ALTER COLUMN "description" TYPE character varying(1024)`, undefined); } } -exports.userProfileDescriptionLength1622679304522 = userProfileDescriptionLength1622679304522; diff --git a/packages/backend/migration/1622681548499-log-message-length.js b/packages/backend/migration/1622681548499-log-message-length.js index cb2ad288b..ac16c0e1b 100644 --- a/packages/backend/migration/1622681548499-log-message-length.js +++ b/packages/backend/migration/1622681548499-log-message-length.js @@ -1,6 +1,6 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -class logMessageLength1622681548499 { + + +export class logMessageLength1622681548499 { constructor() { this.name = 'logMessageLength1622681548499'; } @@ -11,4 +11,3 @@ class logMessageLength1622681548499 { await queryRunner.query(`ALTER TABLE "log" ALTER COLUMN "message" TYPE character varying(1024)`, undefined); } } -exports.logMessageLength1622681548499 = logMessageLength1622681548499; diff --git a/packages/backend/migration/1626509500668-fix-remote-file-proxy.js b/packages/backend/migration/1626509500668-fix-remote-file-proxy.js new file mode 100644 index 000000000..30c562007 --- /dev/null +++ b/packages/backend/migration/1626509500668-fix-remote-file-proxy.js @@ -0,0 +1,22 @@ + + +export class fixRemoteFileProxy1626509500668 { + constructor() { + this.name = 'fixRemoteFileProxy1626509500668'; + } + async up(queryRunner) { + await queryRunner.query(`ALTER TABLE "user" DROP COLUMN "avatarUrl"`); + await queryRunner.query(`ALTER TABLE "user" DROP COLUMN "bannerUrl"`); + await queryRunner.query(`ALTER TABLE "user" DROP COLUMN "avatarBlurhash"`); + await queryRunner.query(`ALTER TABLE "user" DROP COLUMN "bannerBlurhash"`); + await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "proxyRemoteFiles"`); + } + async down(queryRunner) { + await queryRunner.query(`ALTER TABLE "meta" ADD "proxyRemoteFiles" boolean NOT NULL DEFAULT false`); + await queryRunner.query(`ALTER TABLE "user" ADD "bannerBlurhash" character varying(128)`); + await queryRunner.query(`ALTER TABLE "user" ADD "avatarBlurhash" character varying(128)`); + await queryRunner.query(`ALTER TABLE "user" ADD "bannerUrl" character varying(512)`); + await queryRunner.query(`ALTER TABLE "user" ADD "avatarUrl" character varying(512)`); + } +} + diff --git a/packages/backend/migration/1629004542760-chart-reindex.js b/packages/backend/migration/1629004542760-chart-reindex.js index 927ea312e..a7d459276 100644 --- a/packages/backend/migration/1629004542760-chart-reindex.js +++ b/packages/backend/migration/1629004542760-chart-reindex.js @@ -1,6 +1,6 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -class chartReindex1629004542760 { + + +export class chartReindex1629004542760 { constructor() { this.name = 'chartReindex1629004542760'; } @@ -179,4 +179,3 @@ class chartReindex1629004542760 { await queryRunner.query(`CREATE INDEX "IDX_0ad37b7ef50f4ddc84363d7ccc" ON "__chart__active_users" ("date") `); } } -exports.chartReindex1629004542760 = chartReindex1629004542760; diff --git a/packages/backend/migration/1629024377804-deepl-integration.js b/packages/backend/migration/1629024377804-deepl-integration.js index a2bd3b188..19c49ffcd 100644 --- a/packages/backend/migration/1629024377804-deepl-integration.js +++ b/packages/backend/migration/1629024377804-deepl-integration.js @@ -1,6 +1,6 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -class deeplIntegration1629024377804 { + + +export class deeplIntegration1629024377804 { constructor() { this.name = 'deeplIntegration1629024377804'; } @@ -11,4 +11,3 @@ class deeplIntegration1629024377804 { await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "deeplAuthKey"`); } } -exports.deeplIntegration1629024377804 = deeplIntegration1629024377804; diff --git a/packages/backend/migration/1629288472000-fix-channel-userId.js b/packages/backend/migration/1629288472000-fix-channel-userId.js index d0e8baa06..02a1199b0 100644 --- a/packages/backend/migration/1629288472000-fix-channel-userId.js +++ b/packages/backend/migration/1629288472000-fix-channel-userId.js @@ -1,6 +1,6 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -class fixChannelUserId1629288472000 { + + +export class fixChannelUserId1629288472000 { constructor() { this.name = 'fixChannelUserId1629288472000'; } @@ -11,4 +11,3 @@ class fixChannelUserId1629288472000 { await queryRunner.query(`ALTER TABLE "channel" ALTER COLUMN "userId" SET NOT NULL;`); } } -exports.fixChannelUserId1629288472000 = fixChannelUserId1629288472000; diff --git a/packages/backend/migration/1629512953000-user-is-deleted.js b/packages/backend/migration/1629512953000-user-is-deleted.js index 008390719..a7848d569 100644 --- a/packages/backend/migration/1629512953000-user-is-deleted.js +++ b/packages/backend/migration/1629512953000-user-is-deleted.js @@ -1,6 +1,6 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -class isUserDeleted1629512953000 { + + +export class isUserDeleted1629512953000 { constructor() { this.name = 'isUserDeleted1629512953000'; } @@ -12,4 +12,3 @@ class isUserDeleted1629512953000 { await queryRunner.query(`ALTER TABLE "user" DROP COLUMN "isDeleted"`); } } -exports.isUserDeleted1629512953000 = isUserDeleted1629512953000; diff --git a/packages/backend/migration/1629778475000-deepl-integration2.js b/packages/backend/migration/1629778475000-deepl-integration2.js index 50365f4bb..699f06c76 100644 --- a/packages/backend/migration/1629778475000-deepl-integration2.js +++ b/packages/backend/migration/1629778475000-deepl-integration2.js @@ -1,6 +1,6 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -class deeplIntegration21629778475000 { + + +export class deeplIntegration21629778475000 { constructor() { this.name = 'deeplIntegration21629778475000'; } @@ -11,4 +11,3 @@ class deeplIntegration21629778475000 { await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "deeplIsPro"`); } } -exports.deeplIntegration21629778475000 = deeplIntegration21629778475000; diff --git a/packages/backend/migration/1629833361000-AddShowTLReplies.js b/packages/backend/migration/1629833361000-AddShowTLReplies.js index bfd4ab7ff..5d4c938a7 100644 --- a/packages/backend/migration/1629833361000-AddShowTLReplies.js +++ b/packages/backend/migration/1629833361000-AddShowTLReplies.js @@ -1,6 +1,6 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -class addShowTLReplies1629833361000 { + + +export class addShowTLReplies1629833361000 { constructor() { this.name = 'addShowTLReplies1629833361000'; } @@ -12,4 +12,3 @@ class addShowTLReplies1629833361000 { await queryRunner.query(`ALTER TABLE "user" DROP COLUMN "showTimelineReplies"`); } } -exports.addShowTLReplies1629833361000 = addShowTLReplies1629833361000; diff --git a/packages/backend/migration/1629968054000_userInstanceBlocks.js b/packages/backend/migration/1629968054000_userInstanceBlocks.js index 5703ff0b0..1f202d9f6 100644 --- a/packages/backend/migration/1629968054000_userInstanceBlocks.js +++ b/packages/backend/migration/1629968054000_userInstanceBlocks.js @@ -1,6 +1,6 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -class userInstanceBlocks1629968054000 { + + +export class userInstanceBlocks1629968054000 { constructor() { this.name = 'userInstanceBlocks1629968054000'; } @@ -12,4 +12,3 @@ class userInstanceBlocks1629968054000 { await queryRunner.query(`ALTER TABLE "user_profile" DROP COLUMN "mutedInstances"`); } } -exports.userInstanceBlocks1629968054000 = userInstanceBlocks1629968054000; diff --git a/packages/backend/migration/1633068642000-email-required-for-signup.js b/packages/backend/migration/1633068642000-email-required-for-signup.js index 9793cac00..d592f3ca2 100644 --- a/packages/backend/migration/1633068642000-email-required-for-signup.js +++ b/packages/backend/migration/1633068642000-email-required-for-signup.js @@ -1,6 +1,6 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -class emailRequiredForSignup1633068642000 { + + +export class emailRequiredForSignup1633068642000 { constructor() { this.name = 'emailRequiredForSignup1633068642000'; } @@ -11,4 +11,3 @@ class emailRequiredForSignup1633068642000 { await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "emailRequiredForSignup"`); } } -exports.emailRequiredForSignup1633068642000 = emailRequiredForSignup1633068642000; diff --git a/packages/backend/migration/1633071909016-user-pending.js b/packages/backend/migration/1633071909016-user-pending.js index 92a513994..17cf5c11b 100644 --- a/packages/backend/migration/1633071909016-user-pending.js +++ b/packages/backend/migration/1633071909016-user-pending.js @@ -1,6 +1,6 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -class userPending1633071909016 { + + +export class userPending1633071909016 { constructor() { this.name = 'userPending1633071909016'; } @@ -13,4 +13,3 @@ class userPending1633071909016 { await queryRunner.query(`DROP TABLE "user_pending"`); } } -exports.userPending1633071909016 = userPending1633071909016; diff --git a/packages/backend/migration/1634486652000-user-public-reactions.js b/packages/backend/migration/1634486652000-user-public-reactions.js index 1447abe6a..e74112249 100644 --- a/packages/backend/migration/1634486652000-user-public-reactions.js +++ b/packages/backend/migration/1634486652000-user-public-reactions.js @@ -1,6 +1,6 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -class userPublicReactions1634486652000 { + + +export class userPublicReactions1634486652000 { constructor() { this.name = 'userPublicReactions1634486652000'; } @@ -11,4 +11,3 @@ class userPublicReactions1634486652000 { await queryRunner.query(`ALTER TABLE "user_profile" DROP COLUMN "publicReactions"`); } } -exports.userPublicReactions1634486652000 = userPublicReactions1634486652000; diff --git a/packages/backend/migration/1634902659689-delete-log.js b/packages/backend/migration/1634902659689-delete-log.js index b2162519f..555a0020c 100644 --- a/packages/backend/migration/1634902659689-delete-log.js +++ b/packages/backend/migration/1634902659689-delete-log.js @@ -1,6 +1,6 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -class deleteLog1634902659689 { + + +export class deleteLog1634902659689 { constructor() { this.name = 'deleteLog1634902659689'; } @@ -10,4 +10,3 @@ class deleteLog1634902659689 { async down(queryRunner) { } } -exports.deleteLog1634902659689 = deleteLog1634902659689; diff --git a/packages/backend/migration/1635500777168-note-thread-mute.js b/packages/backend/migration/1635500777168-note-thread-mute.js index 1e0195274..a790cace3 100644 --- a/packages/backend/migration/1635500777168-note-thread-mute.js +++ b/packages/backend/migration/1635500777168-note-thread-mute.js @@ -1,6 +1,6 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -class noteThreadMute1635500777168 { + + +export class noteThreadMute1635500777168 { constructor() { this.name = 'noteThreadMute1635500777168'; } @@ -23,4 +23,3 @@ class noteThreadMute1635500777168 { await queryRunner.query(`DROP TABLE "note_thread_muting"`); } } -exports.noteThreadMute1635500777168 = noteThreadMute1635500777168; diff --git a/packages/backend/migration/1636197624383-ff-visibility.js b/packages/backend/migration/1636197624383-ff-visibility.js index 9e8d5a3dc..89028f3c2 100644 --- a/packages/backend/migration/1636197624383-ff-visibility.js +++ b/packages/backend/migration/1636197624383-ff-visibility.js @@ -1,6 +1,6 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -class ffVisibility1636197624383 { + + +export class ffVisibility1636197624383 { constructor() { this.name = 'ffVisibility1636197624383'; } @@ -13,4 +13,3 @@ class ffVisibility1636197624383 { await queryRunner.query(`DROP TYPE "public"."user_profile_ffvisibility_enum"`); } } -exports.ffVisibility1636197624383 = ffVisibility1636197624383; diff --git a/packages/backend/migration/1636697408073-remove-via-mobile.js b/packages/backend/migration/1636697408073-remove-via-mobile.js index bb5157cf1..36e96fd21 100644 --- a/packages/backend/migration/1636697408073-remove-via-mobile.js +++ b/packages/backend/migration/1636697408073-remove-via-mobile.js @@ -1,6 +1,6 @@ -const { MigrationInterface, QueryRunner } = require("typeorm"); -module.exports = class removeViaMobile1636697408073 { + +export class removeViaMobile1636697408073 { name = 'removeViaMobile1636697408073' async up(queryRunner) { diff --git a/packages/backend/migration/1637320813000-forwarded-report.js b/packages/backend/migration/1637320813000-forwarded-report.js index 4056f7b5f..1e39bd5c3 100644 --- a/packages/backend/migration/1637320813000-forwarded-report.js +++ b/packages/backend/migration/1637320813000-forwarded-report.js @@ -1,6 +1,6 @@ -const { QueryRunner } = require('typeorm'); -module.exports = class forwardedReport1637320813000 { + +export class forwardedReport1637320813000 { name = 'forwardedReport1637320813000'; async up(queryRunner) { diff --git a/packages/backend/migration/1639325650583-chart-v3.js b/packages/backend/migration/1639325650583-chart-v3.js index b9d8814c6..e2a4e920c 100644 --- a/packages/backend/migration/1639325650583-chart-v3.js +++ b/packages/backend/migration/1639325650583-chart-v3.js @@ -1,6 +1,6 @@ -const { MigrationInterface, QueryRunner } = require("typeorm"); -module.exports = class chartV31639325650583 { + +export class chartV31639325650583 { name = 'chartV31639325650583' async up(queryRunner) { diff --git a/packages/backend/migration/1642611822809-emoji-url.js b/packages/backend/migration/1642611822809-emoji-url.js index f229c403f..d38f8cc08 100644 --- a/packages/backend/migration/1642611822809-emoji-url.js +++ b/packages/backend/migration/1642611822809-emoji-url.js @@ -1,6 +1,6 @@ -const { MigrationInterface, QueryRunner } = require("typeorm"); -module.exports = class emojiUrl1642611822809 { + +export class emojiUrl1642611822809 { name = 'emojiUrl1642611822809' async up(queryRunner) { diff --git a/packages/backend/migration/1642613870898-drive-file-webpublic-type.js b/packages/backend/migration/1642613870898-drive-file-webpublic-type.js index e10c2ac2d..15434f7d0 100644 --- a/packages/backend/migration/1642613870898-drive-file-webpublic-type.js +++ b/packages/backend/migration/1642613870898-drive-file-webpublic-type.js @@ -1,6 +1,6 @@ -const { MigrationInterface, QueryRunner } = require("typeorm"); -module.exports = class driveFileWebpublicType1642613870898 { + +export class driveFileWebpublicType1642613870898 { name = 'driveFileWebpublicType1642613870898' async up(queryRunner) { diff --git a/packages/backend/migration/1643963705770-chart-v4.js b/packages/backend/migration/1643963705770-chart-v4.js index 91b0a747e..8b320c2b4 100644 --- a/packages/backend/migration/1643963705770-chart-v4.js +++ b/packages/backend/migration/1643963705770-chart-v4.js @@ -1,6 +1,6 @@ -const { MigrationInterface, QueryRunner } = require("typeorm"); -module.exports = class chartV41643963705770 { + +export class chartV41643963705770 { name = 'chartV41643963705770' async up(queryRunner) { diff --git a/packages/backend/migration/1643966656277-chart-v5.js b/packages/backend/migration/1643966656277-chart-v5.js index 9ff05be63..df84002f7 100644 --- a/packages/backend/migration/1643966656277-chart-v5.js +++ b/packages/backend/migration/1643966656277-chart-v5.js @@ -1,6 +1,6 @@ -const { MigrationInterface, QueryRunner } = require("typeorm"); -module.exports = class chartV51643966656277 { + +export class chartV51643966656277 { name = 'chartV51643966656277' async up(queryRunner) { diff --git a/packages/backend/migration/1643967331284-chart-v6.js b/packages/backend/migration/1643967331284-chart-v6.js index 86feade9d..119198f4a 100644 --- a/packages/backend/migration/1643967331284-chart-v6.js +++ b/packages/backend/migration/1643967331284-chart-v6.js @@ -1,6 +1,6 @@ -const { MigrationInterface, QueryRunner } = require("typeorm"); -module.exports = class chartV61643967331284 { + +export class chartV61643967331284 { name = 'chartV61643967331284' async up(queryRunner) { diff --git a/packages/backend/migration/1644010796173-convert-hard-mutes.js b/packages/backend/migration/1644010796173-convert-hard-mutes.js index 6169cb014..207a759b8 100644 --- a/packages/backend/migration/1644010796173-convert-hard-mutes.js +++ b/packages/backend/migration/1644010796173-convert-hard-mutes.js @@ -1,7 +1,7 @@ -const RE2 = require('re2'); -const { MigrationInterface, QueryRunner } = require("typeorm"); +import RE2 from 're2'; -module.exports = class convertHardMutes1644010796173 { + +export class convertHardMutes1644010796173 { name = 'convertHardMutes1644010796173' async up(queryRunner) { diff --git a/packages/backend/migration/1644058404077-chart-v7.js b/packages/backend/migration/1644058404077-chart-v7.js index a982b6cb6..f05ad003d 100644 --- a/packages/backend/migration/1644058404077-chart-v7.js +++ b/packages/backend/migration/1644058404077-chart-v7.js @@ -1,6 +1,6 @@ -const { MigrationInterface, QueryRunner } = require("typeorm"); -module.exports = class chartV71644058404077 { + +export class chartV71644058404077 { name = 'chartV71644058404077' async up(queryRunner) { diff --git a/packages/backend/migration/1644059847460-chart-v8.js b/packages/backend/migration/1644059847460-chart-v8.js index 7c5db0db3..a5339c0eb 100644 --- a/packages/backend/migration/1644059847460-chart-v8.js +++ b/packages/backend/migration/1644059847460-chart-v8.js @@ -1,6 +1,6 @@ -const { MigrationInterface, QueryRunner } = require("typeorm"); -module.exports = class chartV81644059847460 { + +export class chartV81644059847460 { name = 'chartV81644059847460' async up(queryRunner) { diff --git a/packages/backend/migration/1644060125705-chart-v9.js b/packages/backend/migration/1644060125705-chart-v9.js index bc607067b..da35d4231 100644 --- a/packages/backend/migration/1644060125705-chart-v9.js +++ b/packages/backend/migration/1644060125705-chart-v9.js @@ -1,6 +1,6 @@ -const { MigrationInterface, QueryRunner } = require("typeorm"); -module.exports = class chartV91644060125705 { + +export class chartV91644060125705 { name = 'chartV91644060125705' async up(queryRunner) { diff --git a/packages/backend/migration/1644073149413-chart-v10.js b/packages/backend/migration/1644073149413-chart-v10.js index 6ca568718..7260bbeca 100644 --- a/packages/backend/migration/1644073149413-chart-v10.js +++ b/packages/backend/migration/1644073149413-chart-v10.js @@ -1,6 +1,6 @@ -const { MigrationInterface, QueryRunner } = require("typeorm"); -module.exports = class chartV101644073149413 { + +export class chartV101644073149413 { name = 'chartV101644073149413' async up(queryRunner) { diff --git a/packages/backend/migration/1644095659741-chart-v11.js b/packages/backend/migration/1644095659741-chart-v11.js index 40b1c3072..309fff1d9 100644 --- a/packages/backend/migration/1644095659741-chart-v11.js +++ b/packages/backend/migration/1644095659741-chart-v11.js @@ -1,6 +1,6 @@ -const { MigrationInterface, QueryRunner } = require("typeorm"); -module.exports = class chartV111644095659741 { + +export class chartV111644095659741 { name = 'chartV111644095659741' async up(queryRunner) { diff --git a/packages/backend/migration/1644328606241-chart-v12.js b/packages/backend/migration/1644328606241-chart-v12.js index 226de6ece..c3c7e44f9 100644 --- a/packages/backend/migration/1644328606241-chart-v12.js +++ b/packages/backend/migration/1644328606241-chart-v12.js @@ -1,6 +1,6 @@ -const { MigrationInterface, QueryRunner } = require("typeorm"); -module.exports = class chartV121644328606241 { + +export class chartV121644328606241 { name = 'chartV121644328606241' async up(queryRunner) { diff --git a/packages/backend/migration/1644331238153-chart-v13.js b/packages/backend/migration/1644331238153-chart-v13.js index ed36659b3..639f7b4e2 100644 --- a/packages/backend/migration/1644331238153-chart-v13.js +++ b/packages/backend/migration/1644331238153-chart-v13.js @@ -1,6 +1,6 @@ -const { MigrationInterface, QueryRunner } = require("typeorm"); -module.exports = class chartV131644331238153 { + +export class chartV131644331238153 { name = 'chartV131644331238153' async up(queryRunner) { diff --git a/packages/backend/migration/1644344266289-chart-v14.js b/packages/backend/migration/1644344266289-chart-v14.js index 8496cc2d4..a0d9cfc38 100644 --- a/packages/backend/migration/1644344266289-chart-v14.js +++ b/packages/backend/migration/1644344266289-chart-v14.js @@ -1,6 +1,6 @@ -const { MigrationInterface, QueryRunner } = require("typeorm"); -module.exports = class chartV141644344266289 { + +export class chartV141644344266289 { name = 'chartV141644344266289' async up(queryRunner) { diff --git a/packages/backend/migration/1644395759931-instance-theme-color.js b/packages/backend/migration/1644395759931-instance-theme-color.js index 4fda26f9e..8f335ad21 100644 --- a/packages/backend/migration/1644395759931-instance-theme-color.js +++ b/packages/backend/migration/1644395759931-instance-theme-color.js @@ -1,6 +1,6 @@ -const { MigrationInterface, QueryRunner } = require("typeorm"); -module.exports = class instanceThemeColor1644395759931 { + +export class instanceThemeColor1644395759931 { name = 'instanceThemeColor1644395759931' async up(queryRunner) { diff --git a/packages/backend/migration/1644481657998-chart-v15.js b/packages/backend/migration/1644481657998-chart-v15.js index 4eee83f61..b50ca87c4 100644 --- a/packages/backend/migration/1644481657998-chart-v15.js +++ b/packages/backend/migration/1644481657998-chart-v15.js @@ -1,6 +1,6 @@ -const { MigrationInterface, QueryRunner } = require("typeorm"); -module.exports = class chartV151644481657998 { + +export class chartV151644481657998 { name = 'chartV151644481657998' async up(queryRunner) { diff --git a/packages/backend/migration/1644551208096-following-indexes.js b/packages/backend/migration/1644551208096-following-indexes.js index 6c149d806..276473ff6 100644 --- a/packages/backend/migration/1644551208096-following-indexes.js +++ b/packages/backend/migration/1644551208096-following-indexes.js @@ -1,6 +1,6 @@ -const { MigrationInterface, QueryRunner } = require("typeorm"); -module.exports = class followingIndexes1644551208096 { + +export class followingIndexes1644551208096 { name = 'followingIndexes1644551208096' async up(queryRunner) { diff --git a/packages/backend/migration/1645340161439-remove-max-note-text-length.js b/packages/backend/migration/1645340161439-remove-max-note-text-length.js new file mode 100644 index 000000000..c88cb70bf --- /dev/null +++ b/packages/backend/migration/1645340161439-remove-max-note-text-length.js @@ -0,0 +1,13 @@ + + +export class removeMaxNoteTextLength1645340161439 { + name = 'removeMaxNoteTextLength1645340161439' + + async up(queryRunner) { + await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "maxNoteTextLength"`); + } + + async down(queryRunner) { + await queryRunner.query(`ALTER TABLE "meta" ADD "maxNoteTextLength" integer NOT NULL DEFAULT '500'`); + } +} diff --git a/packages/backend/migration/1645599900873-federation-chart-pubsub.js b/packages/backend/migration/1645599900873-federation-chart-pubsub.js new file mode 100644 index 000000000..fd7cb6d5a --- /dev/null +++ b/packages/backend/migration/1645599900873-federation-chart-pubsub.js @@ -0,0 +1,15 @@ + + +export class federationChartPubsub1645599900873 { + name = 'federationChartPubsub1645599900873' + + async up(queryRunner) { + await queryRunner.query(`ALTER TABLE "__chart__federation" ADD "___pubsub" smallint NOT NULL DEFAULT '0'`); + await queryRunner.query(`ALTER TABLE "__chart_day__federation" ADD "___pubsub" smallint NOT NULL DEFAULT '0'`); + } + + async down(queryRunner) { + await queryRunner.query(`ALTER TABLE "__chart_day__federation" DROP COLUMN "___pubsub"`); + await queryRunner.query(`ALTER TABLE "__chart__federation" DROP COLUMN "___pubsub"`); + } +} diff --git a/packages/backend/migration/1646143552768-instance-default-theme.js b/packages/backend/migration/1646143552768-instance-default-theme.js new file mode 100644 index 000000000..029354fd9 --- /dev/null +++ b/packages/backend/migration/1646143552768-instance-default-theme.js @@ -0,0 +1,13 @@ +export class instanceDefaultTheme1646143552768 { + name = 'instanceDefaultTheme1646143552768' + + async up(queryRunner) { + await queryRunner.query(`ALTER TABLE "meta" ADD "defaultLightTheme" character varying(8192)`); + await queryRunner.query(`ALTER TABLE "meta" ADD "defaultDarkTheme" character varying(8192)`); + } + + async down(queryRunner) { + await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "defaultDarkTheme"`); + await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "defaultLightTheme"`); + } +} diff --git a/packages/backend/migration/1646387162108-mute-expires-at.js b/packages/backend/migration/1646387162108-mute-expires-at.js new file mode 100644 index 000000000..c8be8f3c5 --- /dev/null +++ b/packages/backend/migration/1646387162108-mute-expires-at.js @@ -0,0 +1,13 @@ +export class muteExpiresAt1646387162108 { + name = 'muteExpiresAt1646387162108' + + async up(queryRunner) { + await queryRunner.query(`ALTER TABLE "muting" ADD "expiresAt" TIMESTAMP WITH TIME ZONE`); + await queryRunner.query(`CREATE INDEX "IDX_c1fd1c3dfb0627aa36c253fd14" ON "muting" ("expiresAt") `); + } + + async down(queryRunner) { + await queryRunner.query(`DROP INDEX "public"."IDX_c1fd1c3dfb0627aa36c253fd14"`); + await queryRunner.query(`ALTER TABLE "muting" DROP COLUMN "expiresAt"`); + } +} diff --git a/packages/backend/migration/1646549089451-poll-ended-notification.js b/packages/backend/migration/1646549089451-poll-ended-notification.js new file mode 100644 index 000000000..38a38ce64 --- /dev/null +++ b/packages/backend/migration/1646549089451-poll-ended-notification.js @@ -0,0 +1,18 @@ + +export class pollEndedNotification1646549089451 { + name = 'pollEndedNotification1646549089451' + + async up(queryRunner) { + await queryRunner.query(`ALTER TYPE "public"."notification_type_enum" RENAME TO "notification_type_enum_old"`); + await queryRunner.query(`CREATE TYPE "public"."notification_type_enum" AS ENUM('follow', 'mention', 'reply', 'renote', 'quote', 'reaction', 'pollVote', 'pollEnded', 'receiveFollowRequest', 'followRequestAccepted', 'groupInvited', 'app')`); + await queryRunner.query(`ALTER TABLE "notification" ALTER COLUMN "type" TYPE "public"."notification_type_enum" USING "type"::"text"::"public"."notification_type_enum"`); + await queryRunner.query(`DROP TYPE "public"."notification_type_enum_old"`); + } + + async down(queryRunner) { + await queryRunner.query(`CREATE TYPE "public"."notification_type_enum_old" AS ENUM('follow', 'mention', 'reply', 'renote', 'quote', 'reaction', 'pollVote', 'receiveFollowRequest', 'followRequestAccepted', 'groupInvited', 'app')`); + await queryRunner.query(`ALTER TABLE "notification" ALTER COLUMN "type" TYPE "public"."notification_type_enum_old" USING "type"::"text"::"public"."notification_type_enum_old"`); + await queryRunner.query(`DROP TYPE "public"."notification_type_enum"`); + await queryRunner.query(`ALTER TYPE "public"."notification_type_enum_old" RENAME TO "notification_type_enum"`); + } +} diff --git a/packages/backend/migration/1646633030285-chart-federation-active.js b/packages/backend/migration/1646633030285-chart-federation-active.js new file mode 100644 index 000000000..952289c8f --- /dev/null +++ b/packages/backend/migration/1646633030285-chart-federation-active.js @@ -0,0 +1,13 @@ +export class chartFederationActive1646633030285 { + name = 'chartFederationActive1646633030285' + + async up(queryRunner) { + await queryRunner.query(`ALTER TABLE "__chart__federation" ADD "___active" smallint NOT NULL DEFAULT '0'`); + await queryRunner.query(`ALTER TABLE "__chart_day__federation" ADD "___active" smallint NOT NULL DEFAULT '0'`); + } + + async down(queryRunner) { + await queryRunner.query(`ALTER TABLE "__chart_day__federation" DROP COLUMN "___active"`); + await queryRunner.query(`ALTER TABLE "__chart__federation" DROP COLUMN "___active"`); + } +} diff --git a/packages/backend/migration/1646655454495-remove-instance-drive-columns.js b/packages/backend/migration/1646655454495-remove-instance-drive-columns.js new file mode 100644 index 000000000..a0ee1b2c4 --- /dev/null +++ b/packages/backend/migration/1646655454495-remove-instance-drive-columns.js @@ -0,0 +1,13 @@ +export class removeInstanceDriveColumns1646655454495 { + name = 'removeInstanceDriveColumns1646655454495' + + async up(queryRunner) { + await queryRunner.query(`ALTER TABLE "instance" DROP COLUMN "driveUsage"`); + await queryRunner.query(`ALTER TABLE "instance" DROP COLUMN "driveFiles"`); + } + + async down(queryRunner) { + await queryRunner.query(`ALTER TABLE "instance" ADD "driveFiles" integer NOT NULL DEFAULT '0'`); + await queryRunner.query(`ALTER TABLE "instance" ADD "driveUsage" bigint NOT NULL DEFAULT '0'`); + } +} diff --git a/packages/backend/migration/1646732390560-chart-federation-active-sub-pub.js b/packages/backend/migration/1646732390560-chart-federation-active-sub-pub.js new file mode 100644 index 000000000..c9a847cbc --- /dev/null +++ b/packages/backend/migration/1646732390560-chart-federation-active-sub-pub.js @@ -0,0 +1,21 @@ +export class chartFederationActiveSubPub1646732390560 { + name = 'chartFederationActiveSubPub1646732390560' + + async up(queryRunner) { + await queryRunner.query(`ALTER TABLE "__chart__federation" DROP COLUMN "___active"`); + await queryRunner.query(`ALTER TABLE "__chart_day__federation" DROP COLUMN "___active"`); + await queryRunner.query(`ALTER TABLE "__chart__federation" ADD "___subActive" smallint NOT NULL DEFAULT '0'`); + await queryRunner.query(`ALTER TABLE "__chart__federation" ADD "___pubActive" smallint NOT NULL DEFAULT '0'`); + await queryRunner.query(`ALTER TABLE "__chart_day__federation" ADD "___subActive" smallint NOT NULL DEFAULT '0'`); + await queryRunner.query(`ALTER TABLE "__chart_day__federation" ADD "___pubActive" smallint NOT NULL DEFAULT '0'`); + } + + async down(queryRunner) { + await queryRunner.query(`ALTER TABLE "__chart_day__federation" DROP COLUMN "___pubActive"`); + await queryRunner.query(`ALTER TABLE "__chart_day__federation" DROP COLUMN "___subActive"`); + await queryRunner.query(`ALTER TABLE "__chart__federation" DROP COLUMN "___pubActive"`); + await queryRunner.query(`ALTER TABLE "__chart__federation" DROP COLUMN "___subActive"`); + await queryRunner.query(`ALTER TABLE "__chart_day__federation" ADD "___active" smallint NOT NULL DEFAULT '0'`); + await queryRunner.query(`ALTER TABLE "__chart__federation" ADD "___active" smallint NOT NULL DEFAULT '0'`); + } +} diff --git a/packages/backend/ormconfig.js b/packages/backend/ormconfig.js index 524181cb8..b8150f701 100644 --- a/packages/backend/ormconfig.js +++ b/packages/backend/ormconfig.js @@ -1,7 +1,7 @@ -const config = require('./built/config').default; -const entities = require('./built/db/postgre').entities; +import config from './built/config/index.js'; +import { entities } from './built/db/postgre.js'; -module.exports = { +export default { type: 'postgres', host: config.db.host, port: config.db.port, diff --git a/packages/backend/package.json b/packages/backend/package.json index c331da732..f775a99a5 100644 --- a/packages/backend/package.json +++ b/packages/backend/package.json @@ -1,6 +1,7 @@ { "main": "./index.js", "private": true, + "type": "module", "scripts": { "init": "npm run migrate", "build": "tsc -p tsconfig.json || echo done. && tsc-alias -p tsconfig.json", @@ -18,20 +19,19 @@ "@elastic/elasticsearch": "7.11.0", "@koa/cors": "3.1.0", "@koa/multer": "3.0.0", - "@koa/router": "9.0.1", - "@sinonjs/fake-timers": "9.1.0", + "@koa/router": "10.1.1", + "@sinonjs/fake-timers": "9.1.1", "@syuilo/aiscript": "0.11.1", "@types/bcryptjs": "2.4.2", - "@types/bull": "3.15.7", + "@types/bull": "3.15.8", "@types/cbor": "6.0.0", "@types/escape-regexp": "0.0.1", - "@types/glob": "7.2.0", "@types/is-url": "1.2.30", "@types/js-yaml": "4.0.5", "@types/jsdom": "16.2.14", "@types/jsonld": "1.5.6", "@types/koa": "2.13.4", - "@types/koa-bodyparser": "4.3.5", + "@types/koa-bodyparser": "4.3.6", "@types/koa-cors": "0.0.2", "@types/koa-favicon": "2.0.21", "@types/koa-logger": "3.1.2", @@ -41,8 +41,8 @@ "@types/koa__cors": "3.1.1", "@types/koa__multer": "2.0.4", "@types/koa__router": "8.0.11", - "@types/mocha": "8.2.3", - "@types/node": "17.0.14", + "@types/mocha": "9.1.0", + "@types/node": "17.0.21", "@types/node-fetch": "3.0.3", "@types/nodemailer": "6.4.4", "@types/oauth": "0.9.1", @@ -56,7 +56,6 @@ "@types/redis": "4.0.11", "@types/rename": "1.0.4", "@types/sanitize-html": "2.6.2", - "@types/seedrandom": "3.0.1", "@types/sharp": "0.29.5", "@types/sinonjs__fake-timers": "8.1.1", "@types/speakeasy": "2.0.7", @@ -66,36 +65,36 @@ "@types/uuid": "8.3.4", "@types/web-push": "3.3.2", "@types/websocket": "1.0.5", - "@types/ws": "8.2.2", - "@typescript-eslint/eslint-plugin": "5.10.2", - "@typescript-eslint/parser": "5.10.2", + "@types/ws": "8.5.2", + "@typescript-eslint/eslint-plugin": "5.14.0", + "@typescript-eslint/parser": "5.14.0", "abort-controller": "3.0.0", + "ajv": "8.10.0", "archiver": "5.3.0", "autobind-decorator": "2.4.0", "autwh": "0.1.0", - "aws-sdk": "2.1067.0", + "aws-sdk": "2.1079.0", "bcryptjs": "2.4.3", - "blurhash": "1.1.4", - "broadcast-channel": "4.9.0", - "bull": "4.5.0", + "blurhash": "1.1.5", + "broadcast-channel": "4.10.0", + "bull": "4.7.0", "cacheable-lookup": "6.0.4", "cafy": "15.2.1", "cbor": "8.1.0", - "chalk": "4.1.2", + "chalk": "5.0.1", + "chalk-template": "0.4.0", "cli-highlight": "2.1.11", + "color-convert": "2.0.1", "content-disposition": "0.5.4", - "crc-32": "1.2.1", "date-fns": "2.28.0", "deep-email-validator": "0.1.21", "escape-regexp": "0.0.1", - "eslint": "8.8.0", + "eslint": "8.10.0", "eslint-plugin-import": "2.25.4", - "eventemitter3": "4.0.7", "feed": "4.2.2", - "file-type": "16.5.3", + "file-type": "17.1.1", "fluent-ffmpeg": "2.1.2", - "glob": "7.2.0", - "got": "11.8.2", + "got": "12.0.1", "hpagent": "0.1.2", "http-signature": "1.3.6", "ip-cidr": "3.0.4", @@ -115,19 +114,18 @@ "koa-send": "5.0.1", "koa-slow": "2.1.0", "koa-views": "7.0.2", - "langmap": "0.0.16", "mfm-js": "0.21.0", "mime-types": "2.1.34", "misskey-js": "0.0.14", - "mocha": "8.4.0", + "mocha": "9.2.1", "ms": "3.0.0-canary.1", "multer": "1.4.4", "nested-property": "4.0.0", - "node-fetch": "2.6.7", + "node-fetch": "3.2.2", "nodemailer": "6.7.2", "os-utils": "0.0.14", "parse5": "6.0.1", - "pg": "8.7.1", + "pg": "8.7.3", "portscanner": "2.2.0", "private-ip": "2.3.3", "probe-image-size": "7.2.3", @@ -138,7 +136,7 @@ "qrcode": "1.5.0", "random-seed": "0.3.0", "ratelimiter": "3.4.1", - "re2": "1.17.3", + "re2": "1.17.4", "redis": "3.1.2", "redis-lock": "0.1.4", "reflect-metadata": "0.1.13", @@ -146,38 +144,37 @@ "require-all": "3.0.0", "rndstr": "1.0.0", "s-age": "1.1.2", - "sanitize-html": "2.6.1", - "seedrandom": "3.0.5", - "sharp": "0.30.0", + "sanitize-html": "2.7.0", + "sharp": "0.30.2", "speakeasy": "2.0.0", "strict-event-emitter-types": "2.0.0", "stringz": "2.1.0", "style-loader": "3.3.1", "summaly": "2.5.0", "syslog-pro": "1.0.0", - "systeminformation": "5.11.0", + "systeminformation": "5.11.6", "throttle-debounce": "3.0.1", "tinycolor2": "1.4.2", "tmp": "0.2.1", - "ts-loader": "9.2.6", - "ts-node": "10.4.0", + "ts-loader": "9.2.7", + "ts-node": "10.7.0", "tsc-alias": "1.4.1", - "tsconfig-paths": "3.12.0", + "tsconfig-paths": "3.13.0", "twemoji-parser": "13.1.0", - "typeorm": "0.2.41", - "typescript": "4.5.5", + "typeorm": "0.2.45", + "typescript": "4.6.2", "ulid": "2.3.0", "unzipper": "0.10.11", "uuid": "8.3.2", "web-push": "3.4.5", "websocket": "1.0.34", - "ws": "8.4.2", + "ws": "8.5.0", "xev": "2.0.1" }, "devDependencies": { - "@redocly/openapi-core": "1.0.0-beta.79", + "@redocly/openapi-core": "1.0.0-beta.83", "@types/fluent-ffmpeg": "2.1.20", "cross-env": "7.0.3", - "execa": "6.0.0" + "execa": "6.1.0" } } diff --git a/packages/backend/src/@types/langmap.d.ts b/packages/backend/src/@types/langmap.d.ts deleted file mode 100644 index a0f99028a..000000000 --- a/packages/backend/src/@types/langmap.d.ts +++ /dev/null @@ -1,10 +0,0 @@ -declare module 'langmap' { - type Lang = { - nativeName: string; - englishName: string; - }; - - const langmap: { [lang: string]: Lang }; - - export = langmap; -} diff --git a/packages/backend/src/@types/probe-image-size.d.ts b/packages/backend/src/@types/probe-image-size.d.ts index 665edcf2e..11bb6c620 100644 --- a/packages/backend/src/@types/probe-image-size.d.ts +++ b/packages/backend/src/@types/probe-image-size.d.ts @@ -1,5 +1,5 @@ declare module 'probe-image-size' { - import { ReadStream } from 'fs'; + import { ReadStream } from 'node:fs'; type ProbeOptions = { retries: 1; diff --git a/packages/backend/src/boot/index.ts b/packages/backend/src/boot/index.ts index 1723c32dd..5bb20a729 100644 --- a/packages/backend/src/boot/index.ts +++ b/packages/backend/src/boot/index.ts @@ -1,18 +1,18 @@ -import * as cluster from 'cluster'; -import * as chalk from 'chalk'; -import Xev from 'xev'; +import cluster from 'node:cluster'; +import chalk from 'chalk'; +import { default as Xev } from 'xev'; -import Logger from '@/services/logger'; -import { envOption } from '../env'; +import Logger from '@/services/logger.js'; +import { envOption } from '../env.js'; // for typeorm import 'reflect-metadata'; -import { masterMain } from './master'; -import { workerMain } from './worker'; +import { masterMain } from './master.js'; +import { workerMain } from './worker.js'; const logger = new Logger('core', 'cyan'); const clusterLogger = logger.createSubLogger('cluster', 'orange', false); -const ev = new Xev(); +const ev = new Xev.default(); /** * Init process diff --git a/packages/backend/src/boot/master.ts b/packages/backend/src/boot/master.ts index eeb7017cb..1c909dff1 100644 --- a/packages/backend/src/boot/master.ts +++ b/packages/backend/src/boot/master.ts @@ -1,22 +1,22 @@ -import * as fs from 'fs'; -import { fileURLToPath } from 'url'; -import { dirname } from 'path'; -import * as os from 'os'; -import * as cluster from 'cluster'; -import * as chalk from 'chalk'; +import * as fs from 'node:fs'; +import { fileURLToPath } from 'node:url'; +import { dirname } from 'node:path'; +import * as os from 'node:os'; +import cluster from 'node:cluster'; +import chalk from 'chalk'; +import chalkTemplate from 'chalk-template'; import * as portscanner from 'portscanner'; import { getConnection } from 'typeorm'; -import Logger from '@/services/logger'; -import loadConfig from '@/config/load'; -import { Config } from '@/config/types'; -import { lessThan } from '@/prelude/array'; -import { envOption } from '../env'; -import { showMachineInfo } from '@/misc/show-machine-info'; -import { initDb } from '../db/postgre'; +import Logger from '@/services/logger.js'; +import loadConfig from '@/config/load.js'; +import { Config } from '@/config/types.js'; +import { lessThan } from '@/prelude/array.js'; +import { envOption } from '../env.js'; +import { showMachineInfo } from '@/misc/show-machine-info.js'; +import { initDb } from '../db/postgre.js'; -//const _filename = fileURLToPath(import.meta.url); -const _filename = __filename; +const _filename = fileURLToPath(import.meta.url); const _dirname = dirname(_filename); const meta = JSON.parse(fs.readFileSync(`${_dirname}/../../../../built/meta.json`, 'utf-8')); @@ -24,22 +24,24 @@ const meta = JSON.parse(fs.readFileSync(`${_dirname}/../../../../built/meta.json const logger = new Logger('core', 'cyan'); const bootLogger = logger.createSubLogger('boot', 'magenta', false); +const themeColor = chalk.hex('#86b300'); + function greet() { if (!envOption.quiet) { //#region Misskey logo const v = `v${meta.version}`; - console.log(' _____ _ _ '); - console.log(' | |_|___ ___| |_ ___ _ _ '); - console.log(' | | | | |_ -|_ -| \'_| -_| | |'); - console.log(' |_|_|_|_|___|___|_,_|___|_ |'); - console.log(' ' + chalk.gray(v) + (' |___|\n'.substr(v.length))); + console.log(themeColor(' _____ _ _ ')); + console.log(themeColor(' | |_|___ ___| |_ ___ _ _ ')); + console.log(themeColor(' | | | | |_ -|_ -| \'_| -_| | |')); + console.log(themeColor(' |_|_|_|_|___|___|_,_|___|_ |')); + console.log(' ' + chalk.gray(v) + themeColor(' |___|\n'.substr(v.length))); //#endregion console.log(' Misskey is an open-source decentralized microblogging platform.'); - console.log(chalk.keyword('orange')(' If you like Misskey, please donate to support development. https://www.patreon.com/syuilo')); + console.log(chalk.rgb(255, 136, 0)(' If you like Misskey, please donate to support development. https://www.patreon.com/syuilo')); console.log(''); - console.log(chalk`--- ${os.hostname()} {gray (PID: ${process.pid.toString()})} ---`); + console.log(chalkTemplate`--- ${os.hostname()} {gray (PID: ${process.pid.toString()})} ---`); } bootLogger.info('Welcome to Misskey!'); @@ -80,9 +82,9 @@ export async function masterMain() { bootLogger.succ(`Now listening on port ${config.port} on ${config.url}`, null, true); if (!envOption.noDaemons) { - require('../daemons/server-stats').default(); - require('../daemons/queue-stats').default(); - require('../daemons/janitor').default(); + import('../daemons/server-stats.js').then(x => x.default()); + import('../daemons/queue-stats.js').then(x => x.default()); + import('../daemons/janitor.js').then(x => x.default()); } } diff --git a/packages/backend/src/boot/worker.ts b/packages/backend/src/boot/worker.ts index 362fa3f26..8038e2563 100644 --- a/packages/backend/src/boot/worker.ts +++ b/packages/backend/src/boot/worker.ts @@ -1,5 +1,5 @@ -import * as cluster from 'cluster'; -import { initDb } from '../db/postgre'; +import cluster from 'node:cluster'; +import { initDb } from '../db/postgre.js'; /** * Init worker process @@ -8,10 +8,10 @@ export async function workerMain() { await initDb(); // start server - await require('../server').default(); + await import('../server/index.js').then(x => x.default()); // start job queue - require('../queue').default(); + import('../queue/index.js').then(x => x.default()); if (cluster.isWorker) { // Send a 'ready' message to parent process diff --git a/packages/backend/src/config/index.ts b/packages/backend/src/config/index.ts index 7bfdca461..3e53b0003 100644 --- a/packages/backend/src/config/index.ts +++ b/packages/backend/src/config/index.ts @@ -1,3 +1,3 @@ -import load from './load'; +import load from './load.js'; export default load(); diff --git a/packages/backend/src/config/load.ts b/packages/backend/src/config/load.ts index 1b5457cdb..7f765463e 100644 --- a/packages/backend/src/config/load.ts +++ b/packages/backend/src/config/load.ts @@ -2,14 +2,13 @@ * Config loader */ -import * as fs from 'fs'; -import { fileURLToPath } from 'url'; -import { dirname } from 'path'; +import * as fs from 'node:fs'; +import { fileURLToPath } from 'node:url'; +import { dirname } from 'node:path'; import * as yaml from 'js-yaml'; -import { Source, Mixin } from './types'; +import { Source, Mixin } from './types.js'; -//const _filename = fileURLToPath(import.meta.url); -const _filename = __filename; +const _filename = fileURLToPath(import.meta.url); const _dirname = dirname(_filename); /** diff --git a/packages/backend/src/config/types.ts b/packages/backend/src/config/types.ts index e3ca6c1ab..58a27803c 100644 --- a/packages/backend/src/config/types.ts +++ b/packages/backend/src/config/types.ts @@ -6,7 +6,6 @@ export type Source = { feedback_url?: string; url: string; port: number; - https?: { [x: string]: string }; disableHsts?: boolean; db: { host: string; @@ -62,6 +61,7 @@ export type Source = { }; mediaProxy?: string; + proxyRemoteFiles?: boolean; signToActivityPubGet?: boolean; }; diff --git a/packages/backend/src/const.ts b/packages/backend/src/const.ts index b00bd8165..6d3b9559e 100644 --- a/packages/backend/src/const.ts +++ b/packages/backend/src/const.ts @@ -1,3 +1,5 @@ +export const MAX_NOTE_TEXT_LENGTH = 3000; + export const USER_ONLINE_THRESHOLD = 1000 * 60 * 10; // 10min export const USER_ACTIVE_THRESHOLD = 1000 * 60 * 60 * 24 * 3; // 3days diff --git a/packages/backend/src/daemons/janitor.ts b/packages/backend/src/daemons/janitor.ts index 115c1fe38..f2a1bfcc2 100644 --- a/packages/backend/src/daemons/janitor.ts +++ b/packages/backend/src/daemons/janitor.ts @@ -1,7 +1,7 @@ // TODO: 消したい const interval = 30 * 60 * 1000; -import { AttestationChallenges } from '@/models/index'; +import { AttestationChallenges } from '@/models/index.js'; import { LessThan } from 'typeorm'; /** diff --git a/packages/backend/src/daemons/queue-stats.ts b/packages/backend/src/daemons/queue-stats.ts index 5faa16ee4..bfef11054 100644 --- a/packages/backend/src/daemons/queue-stats.ts +++ b/packages/backend/src/daemons/queue-stats.ts @@ -1,7 +1,7 @@ -import Xev from 'xev'; -import { deliverQueue, inboxQueue } from '../queue/queues'; +import { default as Xev } from 'xev'; +import { deliverQueue, inboxQueue } from '../queue/queues.js'; -const ev = new Xev(); +const ev = new Xev.default(); const interval = 10000; diff --git a/packages/backend/src/daemons/server-stats.ts b/packages/backend/src/daemons/server-stats.ts index 47c46042e..327305ccc 100644 --- a/packages/backend/src/daemons/server-stats.ts +++ b/packages/backend/src/daemons/server-stats.ts @@ -1,8 +1,8 @@ -import * as si from 'systeminformation'; -import Xev from 'xev'; +import si from 'systeminformation'; +import { default as Xev } from 'xev'; import * as osUtils from 'os-utils'; -const ev = new Xev(); +const ev = new Xev.default(); const interval = 2000; @@ -36,8 +36,8 @@ export default function() { tx: round(Math.max(0, netStats.tx_sec)), }, fs: { - r: round(Math.max(0, fsStats.rIO_sec)), - w: round(Math.max(0, fsStats.wIO_sec)), + r: round(Math.max(0, fsStats.rIO_sec ?? 0)), + w: round(Math.max(0, fsStats.wIO_sec ?? 0)), }, }; ev.emit('serverStats', stats); @@ -51,9 +51,9 @@ export default function() { } // CPU STAT -function cpuUsage() { +function cpuUsage(): Promise { return new Promise((res, rej) => { - osUtils.cpuUsage((cpuUsage: number) => { + osUtils.cpuUsage((cpuUsage) => { res(cpuUsage); }); }); diff --git a/packages/backend/src/db/elasticsearch.ts b/packages/backend/src/db/elasticsearch.ts index 60a4061d4..d98c5d180 100644 --- a/packages/backend/src/db/elasticsearch.ts +++ b/packages/backend/src/db/elasticsearch.ts @@ -1,5 +1,5 @@ import * as elasticsearch from '@elastic/elasticsearch'; -import config from '@/config/index'; +import config from '@/config/index.js'; const index = { settings: { diff --git a/packages/backend/src/db/logger.ts b/packages/backend/src/db/logger.ts index 62f90555a..22f4c6b1b 100644 --- a/packages/backend/src/db/logger.ts +++ b/packages/backend/src/db/logger.ts @@ -1,3 +1,3 @@ -import Logger from '@/services/logger'; +import Logger from '@/services/logger.js'; export const dbLogger = new Logger('db'); diff --git a/packages/backend/src/db/postgre.ts b/packages/backend/src/db/postgre.ts index 69336c2a4..066a3c673 100644 --- a/packages/backend/src/db/postgre.ts +++ b/packages/backend/src/db/postgre.ts @@ -1,78 +1,78 @@ // https://github.com/typeorm/typeorm/issues/2400 -const types = require('pg').types; -types.setTypeParser(20, Number); +import pg from 'pg'; +pg.types.setTypeParser(20, Number); import { createConnection, Logger, getConnection } from 'typeorm'; import * as highlight from 'cli-highlight'; -import config from '@/config/index'; +import config from '@/config/index.js'; -import { dbLogger } from './logger'; +import { dbLogger } from './logger.js'; -import { User } from '@/models/entities/user'; -import { DriveFile } from '@/models/entities/drive-file'; -import { DriveFolder } from '@/models/entities/drive-folder'; -import { AccessToken } from '@/models/entities/access-token'; -import { App } from '@/models/entities/app'; -import { PollVote } from '@/models/entities/poll-vote'; -import { Note } from '@/models/entities/note'; -import { NoteReaction } from '@/models/entities/note-reaction'; -import { NoteWatching } from '@/models/entities/note-watching'; -import { NoteThreadMuting } from '@/models/entities/note-thread-muting'; -import { NoteUnread } from '@/models/entities/note-unread'; -import { Notification } from '@/models/entities/notification'; -import { Meta } from '@/models/entities/meta'; -import { Following } from '@/models/entities/following'; -import { Instance } from '@/models/entities/instance'; -import { Muting } from '@/models/entities/muting'; -import { SwSubscription } from '@/models/entities/sw-subscription'; -import { Blocking } from '@/models/entities/blocking'; -import { UserList } from '@/models/entities/user-list'; -import { UserListJoining } from '@/models/entities/user-list-joining'; -import { UserGroup } from '@/models/entities/user-group'; -import { UserGroupJoining } from '@/models/entities/user-group-joining'; -import { UserGroupInvitation } from '@/models/entities/user-group-invitation'; -import { Hashtag } from '@/models/entities/hashtag'; -import { NoteFavorite } from '@/models/entities/note-favorite'; -import { AbuseUserReport } from '@/models/entities/abuse-user-report'; -import { RegistrationTicket } from '@/models/entities/registration-tickets'; -import { MessagingMessage } from '@/models/entities/messaging-message'; -import { Signin } from '@/models/entities/signin'; -import { AuthSession } from '@/models/entities/auth-session'; -import { FollowRequest } from '@/models/entities/follow-request'; -import { Emoji } from '@/models/entities/emoji'; -import { UserNotePining } from '@/models/entities/user-note-pining'; -import { Poll } from '@/models/entities/poll'; -import { UserKeypair } from '@/models/entities/user-keypair'; -import { UserPublickey } from '@/models/entities/user-publickey'; -import { UserProfile } from '@/models/entities/user-profile'; -import { UserSecurityKey } from '@/models/entities/user-security-key'; -import { AttestationChallenge } from '@/models/entities/attestation-challenge'; -import { Page } from '@/models/entities/page'; -import { PageLike } from '@/models/entities/page-like'; -import { GalleryPost } from '@/models/entities/gallery-post'; -import { GalleryLike } from '@/models/entities/gallery-like'; -import { ModerationLog } from '@/models/entities/moderation-log'; -import { UsedUsername } from '@/models/entities/used-username'; -import { Announcement } from '@/models/entities/announcement'; -import { AnnouncementRead } from '@/models/entities/announcement-read'; -import { Clip } from '@/models/entities/clip'; -import { ClipNote } from '@/models/entities/clip-note'; -import { Antenna } from '@/models/entities/antenna'; -import { AntennaNote } from '@/models/entities/antenna-note'; -import { PromoNote } from '@/models/entities/promo-note'; -import { PromoRead } from '@/models/entities/promo-read'; -import { envOption } from '../env'; -import { Relay } from '@/models/entities/relay'; -import { MutedNote } from '@/models/entities/muted-note'; -import { Channel } from '@/models/entities/channel'; -import { ChannelFollowing } from '@/models/entities/channel-following'; -import { ChannelNotePining } from '@/models/entities/channel-note-pining'; -import { RegistryItem } from '@/models/entities/registry-item'; -import { Ad } from '@/models/entities/ad'; -import { PasswordResetRequest } from '@/models/entities/password-reset-request'; -import { UserPending } from '@/models/entities/user-pending'; +import { User } from '@/models/entities/user.js'; +import { DriveFile } from '@/models/entities/drive-file.js'; +import { DriveFolder } from '@/models/entities/drive-folder.js'; +import { AccessToken } from '@/models/entities/access-token.js'; +import { App } from '@/models/entities/app.js'; +import { PollVote } from '@/models/entities/poll-vote.js'; +import { Note } from '@/models/entities/note.js'; +import { NoteReaction } from '@/models/entities/note-reaction.js'; +import { NoteWatching } from '@/models/entities/note-watching.js'; +import { NoteThreadMuting } from '@/models/entities/note-thread-muting.js'; +import { NoteUnread } from '@/models/entities/note-unread.js'; +import { Notification } from '@/models/entities/notification.js'; +import { Meta } from '@/models/entities/meta.js'; +import { Following } from '@/models/entities/following.js'; +import { Instance } from '@/models/entities/instance.js'; +import { Muting } from '@/models/entities/muting.js'; +import { SwSubscription } from '@/models/entities/sw-subscription.js'; +import { Blocking } from '@/models/entities/blocking.js'; +import { UserList } from '@/models/entities/user-list.js'; +import { UserListJoining } from '@/models/entities/user-list-joining.js'; +import { UserGroup } from '@/models/entities/user-group.js'; +import { UserGroupJoining } from '@/models/entities/user-group-joining.js'; +import { UserGroupInvitation } from '@/models/entities/user-group-invitation.js'; +import { Hashtag } from '@/models/entities/hashtag.js'; +import { NoteFavorite } from '@/models/entities/note-favorite.js'; +import { AbuseUserReport } from '@/models/entities/abuse-user-report.js'; +import { RegistrationTicket } from '@/models/entities/registration-tickets.js'; +import { MessagingMessage } from '@/models/entities/messaging-message.js'; +import { Signin } from '@/models/entities/signin.js'; +import { AuthSession } from '@/models/entities/auth-session.js'; +import { FollowRequest } from '@/models/entities/follow-request.js'; +import { Emoji } from '@/models/entities/emoji.js'; +import { UserNotePining } from '@/models/entities/user-note-pining.js'; +import { Poll } from '@/models/entities/poll.js'; +import { UserKeypair } from '@/models/entities/user-keypair.js'; +import { UserPublickey } from '@/models/entities/user-publickey.js'; +import { UserProfile } from '@/models/entities/user-profile.js'; +import { UserSecurityKey } from '@/models/entities/user-security-key.js'; +import { AttestationChallenge } from '@/models/entities/attestation-challenge.js'; +import { Page } from '@/models/entities/page.js'; +import { PageLike } from '@/models/entities/page-like.js'; +import { GalleryPost } from '@/models/entities/gallery-post.js'; +import { GalleryLike } from '@/models/entities/gallery-like.js'; +import { ModerationLog } from '@/models/entities/moderation-log.js'; +import { UsedUsername } from '@/models/entities/used-username.js'; +import { Announcement } from '@/models/entities/announcement.js'; +import { AnnouncementRead } from '@/models/entities/announcement-read.js'; +import { Clip } from '@/models/entities/clip.js'; +import { ClipNote } from '@/models/entities/clip-note.js'; +import { Antenna } from '@/models/entities/antenna.js'; +import { AntennaNote } from '@/models/entities/antenna-note.js'; +import { PromoNote } from '@/models/entities/promo-note.js'; +import { PromoRead } from '@/models/entities/promo-read.js'; +import { envOption } from '../env.js'; +import { Relay } from '@/models/entities/relay.js'; +import { MutedNote } from '@/models/entities/muted-note.js'; +import { Channel } from '@/models/entities/channel.js'; +import { ChannelFollowing } from '@/models/entities/channel-following.js'; +import { ChannelNotePining } from '@/models/entities/channel-note-pining.js'; +import { RegistryItem } from '@/models/entities/registry-item.js'; +import { Ad } from '@/models/entities/ad.js'; +import { PasswordResetRequest } from '@/models/entities/password-reset-request.js'; +import { UserPending } from '@/models/entities/user-pending.js'; -import { entities as charts } from '@/services/chart/entities'; +import { entities as charts } from '@/services/chart/entities.js'; const sqlLogger = dbLogger.createSubLogger('sql', 'white', false); @@ -184,7 +184,7 @@ export function initDb(justBorrow = false, sync = false, forceRecreate = false) } catch (e) {} } - const log = process.env.NODE_ENV != 'production'; + const log = process.env.NODE_ENV !== 'production'; return createConnection({ type: 'postgres', @@ -193,7 +193,10 @@ export function initDb(justBorrow = false, sync = false, forceRecreate = false) username: config.db.user, password: config.db.pass, database: config.db.db, - extra: config.db.extra, + extra: { + statement_timeout: 1000 * 10, + ...config.db.extra, + }, synchronize: process.env.NODE_ENV === 'test' || sync, dropSchema: process.env.NODE_ENV === 'test' && !justBorrow, cache: !config.db.disableCache ? { diff --git a/packages/backend/src/db/redis.ts b/packages/backend/src/db/redis.ts index 9fc2b6241..934604145 100644 --- a/packages/backend/src/db/redis.ts +++ b/packages/backend/src/db/redis.ts @@ -1,5 +1,5 @@ import * as redis from 'redis'; -import config from '@/config/index'; +import config from '@/config/index.js'; export function createConnection() { return redis.createClient( diff --git a/packages/backend/src/index.ts b/packages/backend/src/index.ts index 5e4e377ab..bd9c0098b 100644 --- a/packages/backend/src/index.ts +++ b/packages/backend/src/index.ts @@ -2,10 +2,12 @@ * Misskey Entry Point! */ +import { EventEmitter } from 'node:events'; +import boot from './boot/index.js'; + Error.stackTraceLimit = Infinity; +EventEmitter.defaultMaxListeners = 128; -require('events').EventEmitter.defaultMaxListeners = 128; - -import boot from './boot/index'; - -boot(); +boot().catch(err => { + console.error(err); +}); diff --git a/packages/backend/src/mfm/from-html.ts b/packages/backend/src/mfm/from-html.ts index 21e5ebb7a..623cb0e71 100644 --- a/packages/backend/src/mfm/from-html.ts +++ b/packages/backend/src/mfm/from-html.ts @@ -1,6 +1,6 @@ import * as parse5 from 'parse5'; -import treeAdapter = require('parse5/lib/tree-adapters/default'); -import { URL } from 'url'; +import treeAdapter from 'parse5/lib/tree-adapters/default.js'; +import { URL } from 'node:url'; const urlRegex = /^https?:\/\/[\w\/:%#@$&?!()\[\]~.,=+\-]+/; const urlRegexFull = /^https?:\/\/[\w\/:%#@$&?!()\[\]~.,=+\-]+$/; diff --git a/packages/backend/src/mfm/to-html.ts b/packages/backend/src/mfm/to-html.ts index b16c6b95e..5b382063e 100644 --- a/packages/backend/src/mfm/to-html.ts +++ b/packages/backend/src/mfm/to-html.ts @@ -1,8 +1,8 @@ import { JSDOM } from 'jsdom'; import * as mfm from 'mfm-js'; -import config from '@/config/index'; -import { intersperse } from '@/prelude/array'; -import { IMentionedRemoteUsers } from '@/models/entities/note'; +import config from '@/config/index.js'; +import { intersperse } from '@/prelude/array.js'; +import { IMentionedRemoteUsers } from '@/models/entities/note.js'; export function toHtml(nodes: mfm.MfmNode[] | null, mentionedRemoteUsers: IMentionedRemoteUsers = []) { if (nodes == null) { diff --git a/packages/backend/src/misc/acct.ts b/packages/backend/src/misc/acct.ts new file mode 100644 index 000000000..c32cee86c --- /dev/null +++ b/packages/backend/src/misc/acct.ts @@ -0,0 +1,14 @@ +export type Acct = { + username: string; + host: string | null; +}; + +export function parse(acct: string): Acct { + if (acct.startsWith('@')) acct = acct.substr(1); + const split = acct.split('@', 2); + return { username: split[0], host: split[1] || null }; +} + +export function toString(acct: Acct): string { + return acct.host == null ? acct.username : `${acct.username}@${acct.host}`; +} diff --git a/packages/backend/src/misc/antenna-cache.ts b/packages/backend/src/misc/antenna-cache.ts index a23eeb45e..dcf96c161 100644 --- a/packages/backend/src/misc/antenna-cache.ts +++ b/packages/backend/src/misc/antenna-cache.ts @@ -1,6 +1,6 @@ -import { Antennas } from '@/models/index'; -import { Antenna } from '@/models/entities/antenna'; -import { subsdcriber } from '../db/redis'; +import { Antennas } from '@/models/index.js'; +import { Antenna } from '@/models/entities/antenna.js'; +import { subsdcriber } from '../db/redis.js'; let antennasFetched = false; let antennas: Antenna[] = []; diff --git a/packages/backend/src/misc/app-lock.ts b/packages/backend/src/misc/app-lock.ts index a32b60061..b5089cc6a 100644 --- a/packages/backend/src/misc/app-lock.ts +++ b/packages/backend/src/misc/app-lock.ts @@ -1,6 +1,6 @@ -import { redisClient } from '../db/redis'; -import { promisify } from 'util'; -import * as redisLock from 'redis-lock'; +import { redisClient } from '../db/redis.js'; +import { promisify } from 'node:util'; +import redisLock from 'redis-lock'; /** * Retry delay (ms) for lock acquisition diff --git a/packages/backend/src/misc/captcha.ts b/packages/backend/src/misc/captcha.ts index 41a986d78..293cbdcd3 100644 --- a/packages/backend/src/misc/captcha.ts +++ b/packages/backend/src/misc/captcha.ts @@ -1,7 +1,7 @@ import fetch from 'node-fetch'; -import { URLSearchParams } from 'url'; -import { getAgentByUrl } from './fetch'; -import config from '@/config/index'; +import { URLSearchParams } from 'node:url'; +import { getAgentByUrl } from './fetch.js'; +import config from '@/config/index.js'; export async function verifyRecaptcha(secret: string, response: string) { const result = await getCaptchaResponse('https://www.recaptcha.net/recaptcha/api/siteverify', secret, response).catch(e => { diff --git a/packages/backend/src/misc/check-hit-antenna.ts b/packages/backend/src/misc/check-hit-antenna.ts index 3c39a337f..ceb74d690 100644 --- a/packages/backend/src/misc/check-hit-antenna.ts +++ b/packages/backend/src/misc/check-hit-antenna.ts @@ -1,10 +1,10 @@ -import { Antenna } from '@/models/entities/antenna'; -import { Note } from '@/models/entities/note'; -import { User } from '@/models/entities/user'; -import { UserListJoinings, UserGroupJoinings } from '@/models/index'; -import { getFullApAccount } from './convert-host'; -import * as Acct from 'misskey-js/built/acct'; -import { Packed } from './schema'; +import { Antenna } from '@/models/entities/antenna.js'; +import { Note } from '@/models/entities/note.js'; +import { User } from '@/models/entities/user.js'; +import { UserListJoinings, UserGroupJoinings } from '@/models/index.js'; +import { getFullApAccount } from './convert-host.js'; +import * as Acct from '@/misc/acct.js'; +import { Packed } from './schema.js'; /** * noteUserFollowers / antennaUserFollowing はどちらか一方が指定されていればよい diff --git a/packages/backend/src/misc/check-word-mute.ts b/packages/backend/src/misc/check-word-mute.ts index dedda3cdf..588dc79e5 100644 --- a/packages/backend/src/misc/check-word-mute.ts +++ b/packages/backend/src/misc/check-word-mute.ts @@ -1,6 +1,6 @@ -const RE2 = require('re2'); -import { Note } from '@/models/entities/note'; -import { User } from '@/models/entities/user'; +import RE2 from 're2'; +import { Note } from '@/models/entities/note.js'; +import { User } from '@/models/entities/user.js'; type NoteLike = { userId: Note['userId']; diff --git a/packages/backend/src/misc/content-disposition.ts b/packages/backend/src/misc/content-disposition.ts index 9df7ed468..b2aec471d 100644 --- a/packages/backend/src/misc/content-disposition.ts +++ b/packages/backend/src/misc/content-disposition.ts @@ -1,4 +1,4 @@ -const cd = require('content-disposition'); +import cd from 'content-disposition'; export function contentDisposition(type: 'inline' | 'attachment', filename: string): string { const fallback = filename.replace(/[^\w.-]/g, '_'); diff --git a/packages/backend/src/misc/convert-host.ts b/packages/backend/src/misc/convert-host.ts index 6e9f6ed3e..7eb940a7e 100644 --- a/packages/backend/src/misc/convert-host.ts +++ b/packages/backend/src/misc/convert-host.ts @@ -1,6 +1,6 @@ -import { URL } from 'url'; -import config from '@/config/index'; -import { toASCII } from 'punycode/'; +import { URL } from 'node:url'; +import config from '@/config/index.js'; +import { toASCII } from 'punycode'; export function getFullApAccount(username: string, host: string | null) { return host ? `${username}@${toPuny(host)}` : `${username}@${toPuny(config.host)}`; diff --git a/packages/backend/src/misc/count-same-renotes.ts b/packages/backend/src/misc/count-same-renotes.ts index 662876118..b7f8ce90c 100644 --- a/packages/backend/src/misc/count-same-renotes.ts +++ b/packages/backend/src/misc/count-same-renotes.ts @@ -1,4 +1,4 @@ -import { Notes } from '@/models/index'; +import { Notes } from '@/models/index.js'; export async function countSameRenotes(userId: string, renoteId: string, excludeNoteId: string | undefined): Promise { // 指定したユーザーの指定したノートのリノートがいくつあるか数える diff --git a/packages/backend/src/misc/detect-url-mime.ts b/packages/backend/src/misc/detect-url-mime.ts index 274c29173..cd143cf2f 100644 --- a/packages/backend/src/misc/detect-url-mime.ts +++ b/packages/backend/src/misc/detect-url-mime.ts @@ -1,6 +1,6 @@ -import { createTemp } from './create-temp'; -import { downloadUrl } from './download-url'; -import { detectType } from './get-file-info'; +import { createTemp } from './create-temp.js'; +import { downloadUrl } from './download-url.js'; +import { detectType } from './get-file-info.js'; export async function detectUrlMime(url: string) { const [path, cleanup] = await createTemp(); diff --git a/packages/backend/src/misc/download-text-file.ts b/packages/backend/src/misc/download-text-file.ts index e8e23cc12..c62c70ee3 100644 --- a/packages/backend/src/misc/download-text-file.ts +++ b/packages/backend/src/misc/download-text-file.ts @@ -1,8 +1,8 @@ -import * as fs from 'fs'; -import * as util from 'util'; -import Logger from '@/services/logger'; -import { createTemp } from './create-temp'; -import { downloadUrl } from './download-url'; +import * as fs from 'node:fs'; +import * as util from 'node:util'; +import Logger from '@/services/logger.js'; +import { createTemp } from './create-temp.js'; +import { downloadUrl } from './download-url.js'; const logger = new Logger('download-text-file'); diff --git a/packages/backend/src/misc/download-url.ts b/packages/backend/src/misc/download-url.ts index ba2fa9fae..21eee57b3 100644 --- a/packages/backend/src/misc/download-url.ts +++ b/packages/backend/src/misc/download-url.ts @@ -1,13 +1,13 @@ -import * as fs from 'fs'; -import * as stream from 'stream'; -import * as util from 'util'; +import * as fs from 'node:fs'; +import * as stream from 'node:stream'; +import * as util from 'node:util'; import got, * as Got from 'got'; -import { httpAgent, httpsAgent, StatusError } from './fetch'; -import config from '@/config/index'; -import * as chalk from 'chalk'; -import Logger from '@/services/logger'; +import { httpAgent, httpsAgent, StatusError } from './fetch.js'; +import config from '@/config/index.js'; +import chalk from 'chalk'; +import Logger from '@/services/logger.js'; import * as IPCIDR from 'ip-cidr'; -const PrivateIp = require('private-ip'); +import PrivateIp from 'private-ip'; const pipeline = util.promisify(stream.pipeline); diff --git a/packages/backend/src/misc/emoji-regex.ts b/packages/backend/src/misc/emoji-regex.ts index 8b07fbd8f..ca224971c 100644 --- a/packages/backend/src/misc/emoji-regex.ts +++ b/packages/backend/src/misc/emoji-regex.ts @@ -1,3 +1,4 @@ -const twemojiRegex = require('twemoji-parser/dist/lib/regex').default; +import twemoji from 'twemoji-parser/dist/lib/regex.js'; +const twemojiRegex = twemoji.default; export const emojiRegex = new RegExp(`(${twemojiRegex.source})`); diff --git a/packages/backend/src/misc/extract-custom-emojis-from-mfm.ts b/packages/backend/src/misc/extract-custom-emojis-from-mfm.ts index b29ce281b..a0319d8dd 100644 --- a/packages/backend/src/misc/extract-custom-emojis-from-mfm.ts +++ b/packages/backend/src/misc/extract-custom-emojis-from-mfm.ts @@ -1,5 +1,5 @@ import * as mfm from 'mfm-js'; -import { unique } from '@/prelude/array'; +import { unique } from '@/prelude/array.js'; export function extractCustomEmojisFromMfm(nodes: mfm.MfmNode[]): string[] { const emojiNodes = mfm.extract(nodes, (node) => { diff --git a/packages/backend/src/misc/extract-hashtags.ts b/packages/backend/src/misc/extract-hashtags.ts index b0a74df21..0b0418eef 100644 --- a/packages/backend/src/misc/extract-hashtags.ts +++ b/packages/backend/src/misc/extract-hashtags.ts @@ -1,5 +1,5 @@ import * as mfm from 'mfm-js'; -import { unique } from '@/prelude/array'; +import { unique } from '@/prelude/array.js'; export function extractHashtags(nodes: mfm.MfmNode[]): string[] { const hashtagNodes = mfm.extract(nodes, (node) => node.type === 'hashtag'); diff --git a/packages/backend/src/misc/fetch-meta.ts b/packages/backend/src/misc/fetch-meta.ts index b7b055d18..9f85d3d1d 100644 --- a/packages/backend/src/misc/fetch-meta.ts +++ b/packages/backend/src/misc/fetch-meta.ts @@ -1,4 +1,4 @@ -import { Meta } from '@/models/entities/meta'; +import { Meta } from '@/models/entities/meta.js'; import { getConnection } from 'typeorm'; let cache: Meta; diff --git a/packages/backend/src/misc/fetch-proxy-account.ts b/packages/backend/src/misc/fetch-proxy-account.ts index e0eedea4c..ed8a4c794 100644 --- a/packages/backend/src/misc/fetch-proxy-account.ts +++ b/packages/backend/src/misc/fetch-proxy-account.ts @@ -1,6 +1,6 @@ -import { fetchMeta } from './fetch-meta'; -import { ILocalUser } from '@/models/entities/user'; -import { Users } from '@/models/index'; +import { fetchMeta } from './fetch-meta.js'; +import { ILocalUser } from '@/models/entities/user.js'; +import { Users } from '@/models/index.js'; export async function fetchProxyAccount(): Promise { const meta = await fetchMeta(); diff --git a/packages/backend/src/misc/fetch.ts b/packages/backend/src/misc/fetch.ts index baebab192..47a5cd471 100644 --- a/packages/backend/src/misc/fetch.ts +++ b/packages/backend/src/misc/fetch.ts @@ -3,8 +3,8 @@ import * as https from 'https'; import CacheableLookup from 'cacheable-lookup'; import fetch from 'node-fetch'; import { HttpProxyAgent, HttpsProxyAgent } from 'hpagent'; -import config from '@/config/index'; -import { URL } from 'url'; +import config from '@/config/index.js'; +import { URL } from 'node:url'; export async function getJson(url: string, accept = 'application/json, */*', timeout = 10000, headers?: Record) { const res = await getResponse({ diff --git a/packages/backend/src/misc/gen-id.ts b/packages/backend/src/misc/gen-id.ts index b1b542dc4..fcf476857 100644 --- a/packages/backend/src/misc/gen-id.ts +++ b/packages/backend/src/misc/gen-id.ts @@ -1,9 +1,9 @@ import { ulid } from 'ulid'; -import { genAid } from './id/aid'; -import { genMeid } from './id/meid'; -import { genMeidg } from './id/meidg'; -import { genObjectId } from './id/object-id'; -import config from '@/config/index'; +import { genAid } from './id/aid.js'; +import { genMeid } from './id/meid.js'; +import { genMeidg } from './id/meidg.js'; +import { genObjectId } from './id/object-id.js'; +import config from '@/config/index.js'; const metohd = config.id.toLowerCase(); diff --git a/packages/backend/src/misc/gen-identicon.ts b/packages/backend/src/misc/gen-identicon.ts index fca67fcf2..9b30e5dbd 100644 --- a/packages/backend/src/misc/gen-identicon.ts +++ b/packages/backend/src/misc/gen-identicon.ts @@ -3,9 +3,9 @@ * https://en.wikipedia.org/wiki/Identicon */ +import { WriteStream } from 'node:fs'; import * as p from 'pureimage'; -import * as gen from 'random-seed'; -import { WriteStream } from 'fs'; +import gen from 'random-seed'; const size = 256; // px const n = 5; // resolution diff --git a/packages/backend/src/misc/gen-key-pair.ts b/packages/backend/src/misc/gen-key-pair.ts index 9db6b2a3e..e2ad59850 100644 --- a/packages/backend/src/misc/gen-key-pair.ts +++ b/packages/backend/src/misc/gen-key-pair.ts @@ -1,5 +1,5 @@ -import * as crypto from 'crypto'; -import * as util from 'util'; +import * as crypto from 'node:crypto'; +import * as util from 'node:util'; const generateKeyPair = util.promisify(crypto.generateKeyPair); diff --git a/packages/backend/src/misc/get-file-info.ts b/packages/backend/src/misc/get-file-info.ts index 361cdd295..d70dc3d70 100644 --- a/packages/backend/src/misc/get-file-info.ts +++ b/packages/backend/src/misc/get-file-info.ts @@ -1,11 +1,11 @@ -import * as fs from 'fs'; -import * as crypto from 'crypto'; -import * as stream from 'stream'; -import * as util from 'util'; -import * as fileType from 'file-type'; +import * as fs from 'node:fs'; +import * as crypto from 'node:crypto'; +import * as stream from 'node:stream'; +import * as util from 'node:util'; +import { fileTypeFromFile } from 'file-type'; import isSvg from 'is-svg'; -import * as probeImageSize from 'probe-image-size'; -import * as sharp from 'sharp'; +import probeImageSize from 'probe-image-size'; +import sharp from 'sharp'; import { encode } from 'blurhash'; const pipeline = util.promisify(stream.pipeline); @@ -109,7 +109,7 @@ export async function detectType(path: string): Promise<{ return TYPE_OCTET_STREAM; } - const type = await fileType.fromFile(path); + const type = await fileTypeFromFile(path); if (type) { // XMLはSVGかもしれない diff --git a/packages/backend/src/misc/get-note-summary.ts b/packages/backend/src/misc/get-note-summary.ts index d7273d1c5..93783873d 100644 --- a/packages/backend/src/misc/get-note-summary.ts +++ b/packages/backend/src/misc/get-note-summary.ts @@ -1,4 +1,4 @@ -import { Packed } from './schema'; +import { Packed } from './schema.js'; /** * 投稿を表す文字列を取得します。 diff --git a/packages/backend/src/misc/id/aid.ts b/packages/backend/src/misc/id/aid.ts index 2bcde90bf..87e688826 100644 --- a/packages/backend/src/misc/id/aid.ts +++ b/packages/backend/src/misc/id/aid.ts @@ -1,7 +1,7 @@ // AID // 長さ8の[2000年1月1日からの経過ミリ秒をbase36でエンコードしたもの] + 長さ2の[ノイズ文字列] -import * as crypto from 'crypto'; +import * as crypto from 'node:crypto'; const TIME2000 = 946684800000; let counter = crypto.randomBytes(2).readUInt16LE(0); diff --git a/packages/backend/src/misc/is-instance-muted.ts b/packages/backend/src/misc/is-instance-muted.ts index 2e1785b51..a74ba524e 100644 --- a/packages/backend/src/misc/is-instance-muted.ts +++ b/packages/backend/src/misc/is-instance-muted.ts @@ -1,4 +1,4 @@ -import { Packed } from "./schema"; +import { Packed } from './schema.js'; export function isInstanceMuted(note: Packed<'Note'>, mutedInstances: Set): boolean { if (mutedInstances.has(note?.user?.host ?? '')) return true; diff --git a/packages/backend/src/misc/is-quote.ts b/packages/backend/src/misc/is-quote.ts index 2b57f036a..779f548b0 100644 --- a/packages/backend/src/misc/is-quote.ts +++ b/packages/backend/src/misc/is-quote.ts @@ -1,4 +1,4 @@ -import { Note } from '@/models/entities/note'; +import { Note } from '@/models/entities/note.js'; export default function(note: Note): boolean { return note.renoteId != null && (note.text != null || note.hasPoll || (note.fileIds != null && note.fileIds.length > 0)); diff --git a/packages/backend/src/misc/keypair-store.ts b/packages/backend/src/misc/keypair-store.ts index c018013b7..3d505c0ab 100644 --- a/packages/backend/src/misc/keypair-store.ts +++ b/packages/backend/src/misc/keypair-store.ts @@ -1,7 +1,7 @@ -import { UserKeypairs } from '@/models/index'; -import { User } from '@/models/entities/user'; -import { UserKeypair } from '@/models/entities/user-keypair'; -import { Cache } from './cache'; +import { UserKeypairs } from '@/models/index.js'; +import { User } from '@/models/entities/user.js'; +import { UserKeypair } from '@/models/entities/user-keypair.js'; +import { Cache } from './cache.js'; const cache = new Cache(Infinity); diff --git a/packages/backend/src/misc/langmap.ts b/packages/backend/src/misc/langmap.ts new file mode 100644 index 000000000..5ee85e6c0 --- /dev/null +++ b/packages/backend/src/misc/langmap.ts @@ -0,0 +1,666 @@ +// TODO: sharedに置いてフロントエンドのと統合したい +export const langmap = { + 'ach': { + nativeName: 'Lwo', + }, + 'ady': { + nativeName: 'Адыгэбзэ', + }, + 'af': { + nativeName: 'Afrikaans', + }, + 'af-NA': { + nativeName: 'Afrikaans (Namibia)', + }, + 'af-ZA': { + nativeName: 'Afrikaans (South Africa)', + }, + 'ak': { + nativeName: 'Tɕɥi', + }, + 'ar': { + nativeName: 'العربية', + }, + 'ar-AR': { + nativeName: 'العربية', + }, + 'ar-MA': { + nativeName: 'العربية', + }, + 'ar-SA': { + nativeName: 'العربية (السعودية)', + }, + 'ay-BO': { + nativeName: 'Aymar aru', + }, + 'az': { + nativeName: 'Azərbaycan dili', + }, + 'az-AZ': { + nativeName: 'Azərbaycan dili', + }, + 'be-BY': { + nativeName: 'Беларуская', + }, + 'bg': { + nativeName: 'Български', + }, + 'bg-BG': { + nativeName: 'Български', + }, + 'bn': { + nativeName: 'বাংলা', + }, + 'bn-IN': { + nativeName: 'বাংলা (ভারত)', + }, + 'bn-BD': { + nativeName: 'বাংলা(বাংলাদেশ)', + }, + 'br': { + nativeName: 'Brezhoneg', + }, + 'bs-BA': { + nativeName: 'Bosanski', + }, + 'ca': { + nativeName: 'Català', + }, + 'ca-ES': { + nativeName: 'Català', + }, + 'cak': { + nativeName: 'Maya Kaqchikel', + }, + 'ck-US': { + nativeName: 'ᏣᎳᎩ (tsalagi)', + }, + 'cs': { + nativeName: 'Čeština', + }, + 'cs-CZ': { + nativeName: 'Čeština', + }, + 'cy': { + nativeName: 'Cymraeg', + }, + 'cy-GB': { + nativeName: 'Cymraeg', + }, + 'da': { + nativeName: 'Dansk', + }, + 'da-DK': { + nativeName: 'Dansk', + }, + 'de': { + nativeName: 'Deutsch', + }, + 'de-AT': { + nativeName: 'Deutsch (Österreich)', + }, + 'de-DE': { + nativeName: 'Deutsch (Deutschland)', + }, + 'de-CH': { + nativeName: 'Deutsch (Schweiz)', + }, + 'dsb': { + nativeName: 'Dolnoserbšćina', + }, + 'el': { + nativeName: 'Ελληνικά', + }, + 'el-GR': { + nativeName: 'Ελληνικά', + }, + 'en': { + nativeName: 'English', + }, + 'en-GB': { + nativeName: 'English (UK)', + }, + 'en-AU': { + nativeName: 'English (Australia)', + }, + 'en-CA': { + nativeName: 'English (Canada)', + }, + 'en-IE': { + nativeName: 'English (Ireland)', + }, + 'en-IN': { + nativeName: 'English (India)', + }, + 'en-PI': { + nativeName: 'English (Pirate)', + }, + 'en-SG': { + nativeName: 'English (Singapore)', + }, + 'en-UD': { + nativeName: 'English (Upside Down)', + }, + 'en-US': { + nativeName: 'English (US)', + }, + 'en-ZA': { + nativeName: 'English (South Africa)', + }, + 'en@pirate': { + nativeName: 'English (Pirate)', + }, + 'eo': { + nativeName: 'Esperanto', + }, + 'eo-EO': { + nativeName: 'Esperanto', + }, + 'es': { + nativeName: 'Español', + }, + 'es-AR': { + nativeName: 'Español (Argentine)', + }, + 'es-419': { + nativeName: 'Español (Latinoamérica)', + }, + 'es-CL': { + nativeName: 'Español (Chile)', + }, + 'es-CO': { + nativeName: 'Español (Colombia)', + }, + 'es-EC': { + nativeName: 'Español (Ecuador)', + }, + 'es-ES': { + nativeName: 'Español (España)', + }, + 'es-LA': { + nativeName: 'Español (Latinoamérica)', + }, + 'es-NI': { + nativeName: 'Español (Nicaragua)', + }, + 'es-MX': { + nativeName: 'Español (México)', + }, + 'es-US': { + nativeName: 'Español (Estados Unidos)', + }, + 'es-VE': { + nativeName: 'Español (Venezuela)', + }, + 'et': { + nativeName: 'eesti keel', + }, + 'et-EE': { + nativeName: 'Eesti (Estonia)', + }, + 'eu': { + nativeName: 'Euskara', + }, + 'eu-ES': { + nativeName: 'Euskara', + }, + 'fa': { + nativeName: 'فارسی', + }, + 'fa-IR': { + nativeName: 'فارسی', + }, + 'fb-LT': { + nativeName: 'Leet Speak', + }, + 'ff': { + nativeName: 'Fulah', + }, + 'fi': { + nativeName: 'Suomi', + }, + 'fi-FI': { + nativeName: 'Suomi', + }, + 'fo': { + nativeName: 'Føroyskt', + }, + 'fo-FO': { + nativeName: 'Føroyskt (Færeyjar)', + }, + 'fr': { + nativeName: 'Français', + }, + 'fr-CA': { + nativeName: 'Français (Canada)', + }, + 'fr-FR': { + nativeName: 'Français (France)', + }, + 'fr-BE': { + nativeName: 'Français (Belgique)', + }, + 'fr-CH': { + nativeName: 'Français (Suisse)', + }, + 'fy-NL': { + nativeName: 'Frysk', + }, + 'ga': { + nativeName: 'Gaeilge', + }, + 'ga-IE': { + nativeName: 'Gaeilge', + }, + 'gd': { + nativeName: 'Gàidhlig', + }, + 'gl': { + nativeName: 'Galego', + }, + 'gl-ES': { + nativeName: 'Galego', + }, + 'gn-PY': { + nativeName: 'Avañe\'ẽ', + }, + 'gu-IN': { + nativeName: 'ગુજરાતી', + }, + 'gv': { + nativeName: 'Gaelg', + }, + 'gx-GR': { + nativeName: 'Ἑλληνική ἀρχαία', + }, + 'he': { + nativeName: 'עברית‏', + }, + 'he-IL': { + nativeName: 'עברית‏', + }, + 'hi': { + nativeName: 'हिन्दी', + }, + 'hi-IN': { + nativeName: 'हिन्दी', + }, + 'hr': { + nativeName: 'Hrvatski', + }, + 'hr-HR': { + nativeName: 'Hrvatski', + }, + 'hsb': { + nativeName: 'Hornjoserbšćina', + }, + 'ht': { + nativeName: 'Kreyòl', + }, + 'hu': { + nativeName: 'Magyar', + }, + 'hu-HU': { + nativeName: 'Magyar', + }, + 'hy': { + nativeName: 'Հայերեն', + }, + 'hy-AM': { + nativeName: 'Հայերեն (Հայաստան)', + }, + 'id': { + nativeName: 'Bahasa Indonesia', + }, + 'id-ID': { + nativeName: 'Bahasa Indonesia', + }, + 'is': { + nativeName: 'Íslenska', + }, + 'is-IS': { + nativeName: 'Íslenska (Iceland)', + }, + 'it': { + nativeName: 'Italiano', + }, + 'it-IT': { + nativeName: 'Italiano', + }, + 'ja': { + nativeName: '日本語', + }, + 'ja-JP': { + nativeName: '日本語 (日本)', + }, + 'jv-ID': { + nativeName: 'Basa Jawa', + }, + 'ka-GE': { + nativeName: 'ქართული', + }, + 'kk-KZ': { + nativeName: 'Қазақша', + }, + 'km': { + nativeName: 'ភាសាខ្មែរ', + }, + 'kl': { + nativeName: 'kalaallisut', + }, + 'km-KH': { + nativeName: 'ភាសាខ្មែរ', + }, + 'kab': { + nativeName: 'Taqbaylit', + }, + 'kn': { + nativeName: 'ಕನ್ನಡ', + }, + 'kn-IN': { + nativeName: 'ಕನ್ನಡ (India)', + }, + 'ko': { + nativeName: '한국어', + }, + 'ko-KR': { + nativeName: '한국어 (한국)', + }, + 'ku-TR': { + nativeName: 'Kurdî', + }, + 'kw': { + nativeName: 'Kernewek', + }, + 'la': { + nativeName: 'Latin', + }, + 'la-VA': { + nativeName: 'Latin', + }, + 'lb': { + nativeName: 'Lëtzebuergesch', + }, + 'li-NL': { + nativeName: 'Lèmbörgs', + }, + 'lt': { + nativeName: 'Lietuvių', + }, + 'lt-LT': { + nativeName: 'Lietuvių', + }, + 'lv': { + nativeName: 'Latviešu', + }, + 'lv-LV': { + nativeName: 'Latviešu', + }, + 'mai': { + nativeName: 'मैथिली, মৈথিলী', + }, + 'mg-MG': { + nativeName: 'Malagasy', + }, + 'mk': { + nativeName: 'Македонски', + }, + 'mk-MK': { + nativeName: 'Македонски (Македонски)', + }, + 'ml': { + nativeName: 'മലയാളം', + }, + 'ml-IN': { + nativeName: 'മലയാളം', + }, + 'mn-MN': { + nativeName: 'Монгол', + }, + 'mr': { + nativeName: 'मराठी', + }, + 'mr-IN': { + nativeName: 'मराठी', + }, + 'ms': { + nativeName: 'Bahasa Melayu', + }, + 'ms-MY': { + nativeName: 'Bahasa Melayu', + }, + 'mt': { + nativeName: 'Malti', + }, + 'mt-MT': { + nativeName: 'Malti', + }, + 'my': { + nativeName: 'ဗမာစကာ', + }, + 'no': { + nativeName: 'Norsk', + }, + 'nb': { + nativeName: 'Norsk (bokmål)', + }, + 'nb-NO': { + nativeName: 'Norsk (bokmål)', + }, + 'ne': { + nativeName: 'नेपाली', + }, + 'ne-NP': { + nativeName: 'नेपाली', + }, + 'nl': { + nativeName: 'Nederlands', + }, + 'nl-BE': { + nativeName: 'Nederlands (België)', + }, + 'nl-NL': { + nativeName: 'Nederlands (Nederland)', + }, + 'nn-NO': { + nativeName: 'Norsk (nynorsk)', + }, + 'oc': { + nativeName: 'Occitan', + }, + 'or-IN': { + nativeName: 'ଓଡ଼ିଆ', + }, + 'pa': { + nativeName: 'ਪੰਜਾਬੀ', + }, + 'pa-IN': { + nativeName: 'ਪੰਜਾਬੀ (ਭਾਰਤ ਨੂੰ)', + }, + 'pl': { + nativeName: 'Polski', + }, + 'pl-PL': { + nativeName: 'Polski', + }, + 'ps-AF': { + nativeName: 'پښتو', + }, + 'pt': { + nativeName: 'Português', + }, + 'pt-BR': { + nativeName: 'Português (Brasil)', + }, + 'pt-PT': { + nativeName: 'Português (Portugal)', + }, + 'qu-PE': { + nativeName: 'Qhichwa', + }, + 'rm-CH': { + nativeName: 'Rumantsch', + }, + 'ro': { + nativeName: 'Română', + }, + 'ro-RO': { + nativeName: 'Română', + }, + 'ru': { + nativeName: 'Русский', + }, + 'ru-RU': { + nativeName: 'Русский', + }, + 'sa-IN': { + nativeName: 'संस्कृतम्', + }, + 'se-NO': { + nativeName: 'Davvisámegiella', + }, + 'sh': { + nativeName: 'српскохрватски', + }, + 'si-LK': { + nativeName: 'සිංහල', + }, + 'sk': { + nativeName: 'Slovenčina', + }, + 'sk-SK': { + nativeName: 'Slovenčina (Slovakia)', + }, + 'sl': { + nativeName: 'Slovenščina', + }, + 'sl-SI': { + nativeName: 'Slovenščina', + }, + 'so-SO': { + nativeName: 'Soomaaliga', + }, + 'sq': { + nativeName: 'Shqip', + }, + 'sq-AL': { + nativeName: 'Shqip', + }, + 'sr': { + nativeName: 'Српски', + }, + 'sr-RS': { + nativeName: 'Српски (Serbia)', + }, + 'su': { + nativeName: 'Basa Sunda', + }, + 'sv': { + nativeName: 'Svenska', + }, + 'sv-SE': { + nativeName: 'Svenska', + }, + 'sw': { + nativeName: 'Kiswahili', + }, + 'sw-KE': { + nativeName: 'Kiswahili', + }, + 'ta': { + nativeName: 'தமிழ்', + }, + 'ta-IN': { + nativeName: 'தமிழ்', + }, + 'te': { + nativeName: 'తెలుగు', + }, + 'te-IN': { + nativeName: 'తెలుగు', + }, + 'tg': { + nativeName: 'забо́ни тоҷикӣ́', + }, + 'tg-TJ': { + nativeName: 'тоҷикӣ', + }, + 'th': { + nativeName: 'ภาษาไทย', + }, + 'th-TH': { + nativeName: 'ภาษาไทย (ประเทศไทย)', + }, + 'fil': { + nativeName: 'Filipino', + }, + 'tlh': { + nativeName: 'tlhIngan-Hol', + }, + 'tr': { + nativeName: 'Türkçe', + }, + 'tr-TR': { + nativeName: 'Türkçe', + }, + 'tt-RU': { + nativeName: 'татарча', + }, + 'uk': { + nativeName: 'Українська', + }, + 'uk-UA': { + nativeName: 'Українська', + }, + 'ur': { + nativeName: 'اردو', + }, + 'ur-PK': { + nativeName: 'اردو', + }, + 'uz': { + nativeName: 'O\'zbek', + }, + 'uz-UZ': { + nativeName: 'O\'zbek', + }, + 'vi': { + nativeName: 'Tiếng Việt', + }, + 'vi-VN': { + nativeName: 'Tiếng Việt', + }, + 'xh-ZA': { + nativeName: 'isiXhosa', + }, + 'yi': { + nativeName: 'ייִדיש', + }, + 'yi-DE': { + nativeName: 'ייִדיש (German)', + }, + 'zh': { + nativeName: '中文', + }, + 'zh-Hans': { + nativeName: '中文简体', + }, + 'zh-Hant': { + nativeName: '中文繁體', + }, + 'zh-CN': { + nativeName: '中文(中国大陆)', + }, + 'zh-HK': { + nativeName: '中文(香港)', + }, + 'zh-SG': { + nativeName: '中文(新加坡)', + }, + 'zh-TW': { + nativeName: '中文(台灣)', + }, + 'zu-ZA': { + nativeName: 'isiZulu', + }, +}; diff --git a/packages/backend/src/misc/populate-emojis.ts b/packages/backend/src/misc/populate-emojis.ts index 26c05e5fa..4953c6890 100644 --- a/packages/backend/src/misc/populate-emojis.ts +++ b/packages/backend/src/misc/populate-emojis.ts @@ -1,12 +1,12 @@ import { In } from 'typeorm'; -import { Emojis } from '@/models/index'; -import { Emoji } from '@/models/entities/emoji'; -import { Note } from '@/models/entities/note'; -import { Cache } from './cache'; -import { isSelfHost, toPunyNullable } from './convert-host'; -import { decodeReaction } from './reaction-lib'; -import config from '@/config/index'; -import { query } from '@/prelude/url'; +import { Emojis } from '@/models/index.js'; +import { Emoji } from '@/models/entities/emoji.js'; +import { Note } from '@/models/entities/note.js'; +import { Cache } from './cache.js'; +import { isSelfHost, toPunyNullable } from './convert-host.js'; +import { decodeReaction } from './reaction-lib.js'; +import config from '@/config/index.js'; +import { query } from '@/prelude/url.js'; const cache = new Cache(1000 * 60 * 60 * 12); diff --git a/packages/backend/src/misc/reaction-lib.ts b/packages/backend/src/misc/reaction-lib.ts index 04b1e34eb..086944ccf 100644 --- a/packages/backend/src/misc/reaction-lib.ts +++ b/packages/backend/src/misc/reaction-lib.ts @@ -1,8 +1,8 @@ /* eslint-disable key-spacing */ -import { emojiRegex } from './emoji-regex'; -import { fetchMeta } from './fetch-meta'; -import { Emojis } from '@/models/index'; -import { toPunyNullable } from './convert-host'; +import { emojiRegex } from './emoji-regex.js'; +import { fetchMeta } from './fetch-meta.js'; +import { Emojis } from '@/models/index.js'; +import { toPunyNullable } from './convert-host.js'; const legacies: Record = { 'like': '👍', diff --git a/packages/backend/src/misc/schema.ts b/packages/backend/src/misc/schema.ts index 2dae954af..5b6981209 100644 --- a/packages/backend/src/misc/schema.ts +++ b/packages/backend/src/misc/schema.ts @@ -6,29 +6,29 @@ import { packedMeDetailedSchema, packedUserDetailedSchema, packedUserSchema, -} from '@/models/schema/user'; -import { packedNoteSchema } from '@/models/schema/note'; -import { packedUserListSchema } from '@/models/schema/user-list'; -import { packedAppSchema } from '@/models/schema/app'; -import { packedMessagingMessageSchema } from '@/models/schema/messaging-message'; -import { packedNotificationSchema } from '@/models/schema/notification'; -import { packedDriveFileSchema } from '@/models/schema/drive-file'; -import { packedDriveFolderSchema } from '@/models/schema/drive-folder'; -import { packedFollowingSchema } from '@/models/schema/following'; -import { packedMutingSchema } from '@/models/schema/muting'; -import { packedBlockingSchema } from '@/models/schema/blocking'; -import { packedNoteReactionSchema } from '@/models/schema/note-reaction'; -import { packedHashtagSchema } from '@/models/schema/hashtag'; -import { packedPageSchema } from '@/models/schema/page'; -import { packedUserGroupSchema } from '@/models/schema/user-group'; -import { packedNoteFavoriteSchema } from '@/models/schema/note-favorite'; -import { packedChannelSchema } from '@/models/schema/channel'; -import { packedAntennaSchema } from '@/models/schema/antenna'; -import { packedClipSchema } from '@/models/schema/clip'; -import { packedFederationInstanceSchema } from '@/models/schema/federation-instance'; -import { packedQueueCountSchema } from '@/models/schema/queue'; -import { packedGalleryPostSchema } from '@/models/schema/gallery-post'; -import { packedEmojiSchema } from '@/models/schema/emoji'; +} from '@/models/schema/user.js'; +import { packedNoteSchema } from '@/models/schema/note.js'; +import { packedUserListSchema } from '@/models/schema/user-list.js'; +import { packedAppSchema } from '@/models/schema/app.js'; +import { packedMessagingMessageSchema } from '@/models/schema/messaging-message.js'; +import { packedNotificationSchema } from '@/models/schema/notification.js'; +import { packedDriveFileSchema } from '@/models/schema/drive-file.js'; +import { packedDriveFolderSchema } from '@/models/schema/drive-folder.js'; +import { packedFollowingSchema } from '@/models/schema/following.js'; +import { packedMutingSchema } from '@/models/schema/muting.js'; +import { packedBlockingSchema } from '@/models/schema/blocking.js'; +import { packedNoteReactionSchema } from '@/models/schema/note-reaction.js'; +import { packedHashtagSchema } from '@/models/schema/hashtag.js'; +import { packedPageSchema } from '@/models/schema/page.js'; +import { packedUserGroupSchema } from '@/models/schema/user-group.js'; +import { packedNoteFavoriteSchema } from '@/models/schema/note-favorite.js'; +import { packedChannelSchema } from '@/models/schema/channel.js'; +import { packedAntennaSchema } from '@/models/schema/antenna.js'; +import { packedClipSchema } from '@/models/schema/clip.js'; +import { packedFederationInstanceSchema } from '@/models/schema/federation-instance.js'; +import { packedQueueCountSchema } from '@/models/schema/queue.js'; +import { packedGalleryPostSchema } from '@/models/schema/gallery-post.js'; +import { packedEmojiSchema } from '@/models/schema/emoji.js'; export const refs = { UserLite: packedUserLiteSchema, @@ -63,18 +63,13 @@ export const refs = { Emoji: packedEmojiSchema, }; -// Packed = SchemaTypeDef; とすると展開されてマウスホバー時に型表示が使い物にならなくなる -// ObjTypeを指定すると(なぜか)展開されずにPacked<'Hoge'>と表示される -type PackedDef; allOf?: ReadonlyArray }> = - r['allOf'] extends ReadonlyArray ? UnionToIntersection> : - r['oneOf'] extends ReadonlyArray ? UnionSchemaType : - r['properties'] extends Obj ? ObjType : - never; -export type Packed = PackedDef; +export type Packed = SchemaType; -type TypeStringef = 'boolean' | 'number' | 'string' | 'array' | 'object' | 'any'; +type TypeStringef = 'null' | 'boolean' | 'integer' | 'number' | 'string' | 'array' | 'object' | 'any'; type StringDefToType = + T extends 'null' ? null : T extends 'boolean' ? boolean : + T extends 'integer' ? number : T extends 'number' ? number : T extends 'string' ? string | Date : T extends 'array' ? ReadonlyArray : @@ -83,17 +78,18 @@ type StringDefToType = // https://swagger.io/specification/?sbsearch=optional#schema-object type OfSchema = { - readonly anyOf?: ReadonlyArray; - readonly oneOf?: ReadonlyArray; - readonly allOf?: ReadonlyArray; + readonly anyOf?: ReadonlyArray; + readonly oneOf?: ReadonlyArray; + readonly allOf?: ReadonlyArray; } -export interface MinimumSchema extends OfSchema { +export interface Schema extends OfSchema { readonly type?: TypeStringef; readonly nullable?: boolean; readonly optional?: boolean; - readonly items?: MinimumSchema; + readonly items?: Schema; readonly properties?: Obj; + readonly required?: ReadonlyArray>; readonly description?: string; readonly example?: any; readonly format?: string; @@ -104,26 +100,22 @@ export interface MinimumSchema extends OfSchema { readonly minLength?: number; } -export interface Schema extends MinimumSchema { - readonly nullable: boolean; - readonly optional: boolean; -} - -type NonUndefinedPropertyNames = { - [K in keyof T]: T[K]['optional'] extends true ? never : K -}[keyof T]; - -type UndefinedPropertyNames = { - [K in keyof T]: T[K]['optional'] extends true ? K : never -}[keyof T]; +type RequiredPropertyNames = { + [K in keyof s]: + // K is not optional + s[K]['optional'] extends false ? K : + // K has default value + s[K]['default'] extends null | string | number | boolean | Record ? K : never +}[keyof s]; export interface Obj { [key: string]: Schema; } -export type ObjType = - { -readonly [P in UndefinedPropertyNames]?: SchemaType } & - { -readonly [P in NonUndefinedPropertyNames]: SchemaType }; +export type ObjType = + { -readonly [P in keyof s]?: SchemaType } & + { -readonly [P in RequiredProps]: SchemaType } & + { -readonly [P in RequiredPropertyNames]: SchemaType }; -type NullOrUndefined

= +type NullOrUndefined

= p['nullable'] extends true ? p['optional'] extends true ? (T | null | undefined) @@ -132,15 +124,18 @@ type NullOrUndefined

= ? (T | undefined) : T; -// 共用体型を交差型にする型 https://stackoverflow.com/questions/54938141/typescript-convert-union-to-intersection +// https://stackoverflow.com/questions/54938141/typescript-convert-union-to-intersection +// Get intersection from union type UnionToIntersection = (U extends any ? (k: U) => void : never) extends ((k: infer I) => void) ? I : never; // https://github.com/misskey-dev/misskey/pull/8144#discussion_r785287552 -// 単純にSchemaTypeDefで判定するだけではダメ -type UnionSchemaType = X extends any ? SchemaType : never; +// To get union, we use `Foo extends any ? Hoge : never` +type UnionSchemaType = X extends any ? SchemaType : never; type ArrayUnion = T extends any ? Array : never; -export type SchemaTypeDef

= +export type SchemaTypeDef

= + p['type'] extends 'null' ? null : + p['type'] extends 'integer' ? number : p['type'] extends 'number' ? number : p['type'] extends 'string' ? ( p['enum'] extends readonly string[] ? @@ -151,22 +146,22 @@ export type SchemaTypeDef

= p['type'] extends 'boolean' ? boolean : p['type'] extends 'object' ? ( p['ref'] extends keyof typeof refs ? Packed : - p['properties'] extends NonNullable ? ObjType : - p['anyOf'] extends ReadonlyArray ? UnionSchemaType & Partial>> : - p['allOf'] extends ReadonlyArray ? UnionToIntersection> : + p['properties'] extends NonNullable ? ObjType[number]> : + p['anyOf'] extends ReadonlyArray ? UnionSchemaType & Partial>> : + p['allOf'] extends ReadonlyArray ? UnionToIntersection> : any ) : p['type'] extends 'array' ? ( p['items'] extends OfSchema ? ( - p['items']['anyOf'] extends ReadonlyArray ? UnionSchemaType>[] : - p['items']['oneOf'] extends ReadonlyArray ? ArrayUnion>> : - p['items']['allOf'] extends ReadonlyArray ? UnionToIntersection>>[] : + p['items']['anyOf'] extends ReadonlyArray ? UnionSchemaType>[] : + p['items']['oneOf'] extends ReadonlyArray ? ArrayUnion>> : + p['items']['allOf'] extends ReadonlyArray ? UnionToIntersection>>[] : never ) : - p['items'] extends NonNullable ? SchemaTypeDef[] : + p['items'] extends NonNullable ? SchemaTypeDef[] : any[] ) : - p['oneOf'] extends ReadonlyArray ? UnionSchemaType : + p['oneOf'] extends ReadonlyArray ? UnionSchemaType : any; -export type SchemaType

= NullOrUndefined>; +export type SchemaType

= NullOrUndefined>; diff --git a/packages/backend/src/misc/secure-rndstr.ts b/packages/backend/src/misc/secure-rndstr.ts index 76ee1225e..8d4fcb1ba 100644 --- a/packages/backend/src/misc/secure-rndstr.ts +++ b/packages/backend/src/misc/secure-rndstr.ts @@ -1,4 +1,4 @@ -import * as crypto from 'crypto'; +import * as crypto from 'node:crypto'; const L_CHARS = '0123456789abcdefghijklmnopqrstuvwxyz'; const LU_CHARS = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'; diff --git a/packages/backend/src/misc/show-machine-info.ts b/packages/backend/src/misc/show-machine-info.ts index 58747c115..bc71cfbe9 100644 --- a/packages/backend/src/misc/show-machine-info.ts +++ b/packages/backend/src/misc/show-machine-info.ts @@ -1,6 +1,6 @@ -import * as os from 'os'; -import * as sysUtils from 'systeminformation'; -import Logger from '@/services/logger'; +import * as os from 'node:os'; +import sysUtils from 'systeminformation'; +import Logger from '@/services/logger.js'; export async function showMachineInfo(parentLogger: Logger) { const logger = parentLogger.createSubLogger('machine'); diff --git a/packages/backend/src/models/entities/abuse-user-report.ts b/packages/backend/src/models/entities/abuse-user-report.ts index 27c1e47fd..6ac563552 100644 --- a/packages/backend/src/models/entities/abuse-user-report.ts +++ b/packages/backend/src/models/entities/abuse-user-report.ts @@ -1,6 +1,6 @@ import { PrimaryColumn, Entity, Index, JoinColumn, Column, ManyToOne } from 'typeorm'; -import { User } from './user'; -import { id } from '../id'; +import { User } from './user.js'; +import { id } from '../id.js'; @Entity() export class AbuseUserReport { diff --git a/packages/backend/src/models/entities/access-token.ts b/packages/backend/src/models/entities/access-token.ts index 33b60e44f..69cdc49ce 100644 --- a/packages/backend/src/models/entities/access-token.ts +++ b/packages/backend/src/models/entities/access-token.ts @@ -1,7 +1,7 @@ import { Entity, PrimaryColumn, Index, Column, ManyToOne, JoinColumn } from 'typeorm'; -import { User } from './user'; -import { App } from './app'; -import { id } from '../id'; +import { User } from './user.js'; +import { App } from './app.js'; +import { id } from '../id.js'; @Entity() export class AccessToken { diff --git a/packages/backend/src/models/entities/ad.ts b/packages/backend/src/models/entities/ad.ts index 68be4ab1c..36b758f20 100644 --- a/packages/backend/src/models/entities/ad.ts +++ b/packages/backend/src/models/entities/ad.ts @@ -1,5 +1,5 @@ import { Entity, Index, Column, PrimaryColumn } from 'typeorm'; -import { id } from '../id'; +import { id } from '../id.js'; @Entity() export class Ad { diff --git a/packages/backend/src/models/entities/announcement-read.ts b/packages/backend/src/models/entities/announcement-read.ts index 88a1966e2..e4d256a86 100644 --- a/packages/backend/src/models/entities/announcement-read.ts +++ b/packages/backend/src/models/entities/announcement-read.ts @@ -1,7 +1,7 @@ import { PrimaryColumn, Entity, Index, JoinColumn, Column, ManyToOne } from 'typeorm'; -import { User } from './user'; -import { Announcement } from './announcement'; -import { id } from '../id'; +import { User } from './user.js'; +import { Announcement } from './announcement.js'; +import { id } from '../id.js'; @Entity() @Index(['userId', 'announcementId'], { unique: true }) diff --git a/packages/backend/src/models/entities/announcement.ts b/packages/backend/src/models/entities/announcement.ts index 3448bb686..beb2f8246 100644 --- a/packages/backend/src/models/entities/announcement.ts +++ b/packages/backend/src/models/entities/announcement.ts @@ -1,5 +1,5 @@ import { Entity, Index, Column, PrimaryColumn } from 'typeorm'; -import { id } from '../id'; +import { id } from '../id.js'; @Entity() export class Announcement { diff --git a/packages/backend/src/models/entities/antenna-note.ts b/packages/backend/src/models/entities/antenna-note.ts index a72da423d..fcca493fe 100644 --- a/packages/backend/src/models/entities/antenna-note.ts +++ b/packages/backend/src/models/entities/antenna-note.ts @@ -1,7 +1,7 @@ import { Entity, Index, JoinColumn, Column, ManyToOne, PrimaryColumn } from 'typeorm'; -import { Note } from './note'; -import { Antenna } from './antenna'; -import { id } from '../id'; +import { Note } from './note.js'; +import { Antenna } from './antenna.js'; +import { id } from '../id.js'; @Entity() @Index(['noteId', 'antennaId'], { unique: true }) diff --git a/packages/backend/src/models/entities/antenna.ts b/packages/backend/src/models/entities/antenna.ts index ffe7cc7e3..6c8bb13e5 100644 --- a/packages/backend/src/models/entities/antenna.ts +++ b/packages/backend/src/models/entities/antenna.ts @@ -1,8 +1,8 @@ import { PrimaryColumn, Entity, Index, JoinColumn, Column, ManyToOne } from 'typeorm'; -import { User } from './user'; -import { id } from '../id'; -import { UserList } from './user-list'; -import { UserGroupJoining } from './user-group-joining'; +import { User } from './user.js'; +import { id } from '../id.js'; +import { UserList } from './user-list.js'; +import { UserGroupJoining } from './user-group-joining.js'; @Entity() export class Antenna { diff --git a/packages/backend/src/models/entities/app.ts b/packages/backend/src/models/entities/app.ts index c1efdc070..46c11548a 100644 --- a/packages/backend/src/models/entities/app.ts +++ b/packages/backend/src/models/entities/app.ts @@ -1,6 +1,6 @@ import { Entity, PrimaryColumn, Column, Index, ManyToOne } from 'typeorm'; -import { User } from './user'; -import { id } from '../id'; +import { User } from './user.js'; +import { id } from '../id.js'; @Entity() export class App { diff --git a/packages/backend/src/models/entities/attestation-challenge.ts b/packages/backend/src/models/entities/attestation-challenge.ts index cf3527059..c40df2329 100644 --- a/packages/backend/src/models/entities/attestation-challenge.ts +++ b/packages/backend/src/models/entities/attestation-challenge.ts @@ -1,6 +1,6 @@ import { PrimaryColumn, Entity, JoinColumn, Column, ManyToOne, Index } from 'typeorm'; -import { User } from './user'; -import { id } from '../id'; +import { User } from './user.js'; +import { id } from '../id.js'; @Entity() export class AttestationChallenge { diff --git a/packages/backend/src/models/entities/auth-session.ts b/packages/backend/src/models/entities/auth-session.ts index 199138552..b82585620 100644 --- a/packages/backend/src/models/entities/auth-session.ts +++ b/packages/backend/src/models/entities/auth-session.ts @@ -1,7 +1,7 @@ import { Entity, PrimaryColumn, Index, Column, ManyToOne, JoinColumn } from 'typeorm'; -import { User } from './user'; -import { App } from './app'; -import { id } from '../id'; +import { User } from './user.js'; +import { App } from './app.js'; +import { id } from '../id.js'; @Entity() export class AuthSession { diff --git a/packages/backend/src/models/entities/blocking.ts b/packages/backend/src/models/entities/blocking.ts index aacbfef7f..4ac73a00b 100644 --- a/packages/backend/src/models/entities/blocking.ts +++ b/packages/backend/src/models/entities/blocking.ts @@ -1,6 +1,6 @@ import { PrimaryColumn, Entity, Index, JoinColumn, Column, ManyToOne } from 'typeorm'; -import { User } from './user'; -import { id } from '../id'; +import { User } from './user.js'; +import { id } from '../id.js'; @Entity() @Index(['blockerId', 'blockeeId'], { unique: true }) diff --git a/packages/backend/src/models/entities/channel-following.ts b/packages/backend/src/models/entities/channel-following.ts index 3727283a2..029dd6cf1 100644 --- a/packages/backend/src/models/entities/channel-following.ts +++ b/packages/backend/src/models/entities/channel-following.ts @@ -1,7 +1,7 @@ import { PrimaryColumn, Entity, Index, JoinColumn, Column, ManyToOne } from 'typeorm'; -import { User } from './user'; -import { id } from '../id'; -import { Channel } from './channel'; +import { User } from './user.js'; +import { id } from '../id.js'; +import { Channel } from './channel.js'; @Entity() @Index(['followerId', 'followeeId'], { unique: true }) diff --git a/packages/backend/src/models/entities/channel-note-pining.ts b/packages/backend/src/models/entities/channel-note-pining.ts index d6b677403..23be3b69d 100644 --- a/packages/backend/src/models/entities/channel-note-pining.ts +++ b/packages/backend/src/models/entities/channel-note-pining.ts @@ -1,7 +1,7 @@ import { PrimaryColumn, Entity, Index, JoinColumn, Column, ManyToOne } from 'typeorm'; -import { Note } from './note'; -import { Channel } from './channel'; -import { id } from '../id'; +import { Note } from './note.js'; +import { Channel } from './channel.js'; +import { id } from '../id.js'; @Entity() @Index(['channelId', 'noteId'], { unique: true }) diff --git a/packages/backend/src/models/entities/channel.ts b/packages/backend/src/models/entities/channel.ts index a6767b038..abf6668bd 100644 --- a/packages/backend/src/models/entities/channel.ts +++ b/packages/backend/src/models/entities/channel.ts @@ -1,7 +1,7 @@ import { PrimaryColumn, Entity, Index, JoinColumn, Column, ManyToOne } from 'typeorm'; -import { User } from './user'; -import { id } from '../id'; -import { DriveFile } from './drive-file'; +import { User } from './user.js'; +import { id } from '../id.js'; +import { DriveFile } from './drive-file.js'; @Entity() export class Channel { diff --git a/packages/backend/src/models/entities/clip-note.ts b/packages/backend/src/models/entities/clip-note.ts index 2bc435226..6f3688550 100644 --- a/packages/backend/src/models/entities/clip-note.ts +++ b/packages/backend/src/models/entities/clip-note.ts @@ -1,7 +1,7 @@ import { Entity, Index, JoinColumn, Column, ManyToOne, PrimaryColumn } from 'typeorm'; -import { Note } from './note'; -import { Clip } from './clip'; -import { id } from '../id'; +import { Note } from './note.js'; +import { Clip } from './clip.js'; +import { id } from '../id.js'; @Entity() @Index(['noteId', 'clipId'], { unique: true }) diff --git a/packages/backend/src/models/entities/clip.ts b/packages/backend/src/models/entities/clip.ts index 84f5c4d21..da6b3c7a7 100644 --- a/packages/backend/src/models/entities/clip.ts +++ b/packages/backend/src/models/entities/clip.ts @@ -1,6 +1,6 @@ import { PrimaryColumn, Entity, Index, JoinColumn, Column, ManyToOne } from 'typeorm'; -import { User } from './user'; -import { id } from '../id'; +import { User } from './user.js'; +import { id } from '../id.js'; @Entity() export class Clip { diff --git a/packages/backend/src/models/entities/drive-file.ts b/packages/backend/src/models/entities/drive-file.ts index cec86880f..3d375f0e3 100644 --- a/packages/backend/src/models/entities/drive-file.ts +++ b/packages/backend/src/models/entities/drive-file.ts @@ -1,7 +1,7 @@ import { PrimaryColumn, Entity, Index, JoinColumn, Column, ManyToOne } from 'typeorm'; -import { User } from './user'; -import { DriveFolder } from './drive-folder'; -import { id } from '../id'; +import { User } from './user.js'; +import { DriveFolder } from './drive-folder.js'; +import { id } from '../id.js'; @Entity() @Index(['userId', 'folderId', 'id']) diff --git a/packages/backend/src/models/entities/drive-folder.ts b/packages/backend/src/models/entities/drive-folder.ts index 09f5e6448..d4022c6eb 100644 --- a/packages/backend/src/models/entities/drive-folder.ts +++ b/packages/backend/src/models/entities/drive-folder.ts @@ -1,6 +1,6 @@ import { JoinColumn, ManyToOne, Entity, PrimaryColumn, Index, Column } from 'typeorm'; -import { User } from './user'; -import { id } from '../id'; +import { User } from './user.js'; +import { id } from '../id.js'; @Entity() export class DriveFolder { diff --git a/packages/backend/src/models/entities/emoji.ts b/packages/backend/src/models/entities/emoji.ts index 2e9c11d21..b72ca7233 100644 --- a/packages/backend/src/models/entities/emoji.ts +++ b/packages/backend/src/models/entities/emoji.ts @@ -1,5 +1,5 @@ import { PrimaryColumn, Entity, Index, Column } from 'typeorm'; -import { id } from '../id'; +import { id } from '../id.js'; @Entity() @Index(['name', 'host'], { unique: true }) diff --git a/packages/backend/src/models/entities/follow-request.ts b/packages/backend/src/models/entities/follow-request.ts index 6aa202299..89946f6d3 100644 --- a/packages/backend/src/models/entities/follow-request.ts +++ b/packages/backend/src/models/entities/follow-request.ts @@ -1,6 +1,6 @@ import { PrimaryColumn, Entity, Index, JoinColumn, Column, ManyToOne } from 'typeorm'; -import { User } from './user'; -import { id } from '../id'; +import { User } from './user.js'; +import { id } from '../id.js'; @Entity() @Index(['followerId', 'followeeId'], { unique: true }) diff --git a/packages/backend/src/models/entities/following.ts b/packages/backend/src/models/entities/following.ts index ad387e518..b283ca7e8 100644 --- a/packages/backend/src/models/entities/following.ts +++ b/packages/backend/src/models/entities/following.ts @@ -1,6 +1,6 @@ import { PrimaryColumn, Entity, Index, JoinColumn, Column, ManyToOne } from 'typeorm'; -import { User } from './user'; -import { id } from '../id'; +import { User } from './user.js'; +import { id } from '../id.js'; @Entity() @Index(['followerId', 'followeeId'], { unique: true }) diff --git a/packages/backend/src/models/entities/gallery-like.ts b/packages/backend/src/models/entities/gallery-like.ts index 41615dcea..4ce166d19 100644 --- a/packages/backend/src/models/entities/gallery-like.ts +++ b/packages/backend/src/models/entities/gallery-like.ts @@ -1,7 +1,7 @@ import { PrimaryColumn, Entity, Index, JoinColumn, Column, ManyToOne } from 'typeorm'; -import { User } from './user'; -import { id } from '../id'; -import { GalleryPost } from './gallery-post'; +import { User } from './user.js'; +import { id } from '../id.js'; +import { GalleryPost } from './gallery-post.js'; @Entity() @Index(['userId', 'postId'], { unique: true }) diff --git a/packages/backend/src/models/entities/gallery-post.ts b/packages/backend/src/models/entities/gallery-post.ts index 393603e3d..774cb946e 100644 --- a/packages/backend/src/models/entities/gallery-post.ts +++ b/packages/backend/src/models/entities/gallery-post.ts @@ -1,7 +1,7 @@ import { Entity, Index, JoinColumn, Column, PrimaryColumn, ManyToOne } from 'typeorm'; -import { User } from './user'; -import { id } from '../id'; -import { DriveFile } from './drive-file'; +import { User } from './user.js'; +import { id } from '../id.js'; +import { DriveFile } from './drive-file.js'; @Entity() export class GalleryPost { diff --git a/packages/backend/src/models/entities/hashtag.ts b/packages/backend/src/models/entities/hashtag.ts index 761974590..6bd991f62 100644 --- a/packages/backend/src/models/entities/hashtag.ts +++ b/packages/backend/src/models/entities/hashtag.ts @@ -1,6 +1,6 @@ import { Entity, PrimaryColumn, Index, Column } from 'typeorm'; -import { User } from './user'; -import { id } from '../id'; +import { User } from './user.js'; +import { id } from '../id.js'; @Entity() export class Hashtag { diff --git a/packages/backend/src/models/entities/instance.ts b/packages/backend/src/models/entities/instance.ts index d1314be17..bb24d6b30 100644 --- a/packages/backend/src/models/entities/instance.ts +++ b/packages/backend/src/models/entities/instance.ts @@ -1,5 +1,5 @@ import { Entity, PrimaryColumn, Index, Column } from 'typeorm'; -import { id } from '../id'; +import { id } from '../id.js'; @Entity() export class Instance { @@ -59,22 +59,6 @@ export class Instance { }) public followersCount: number; - /** - * ドライブ使用量 - */ - @Column('bigint', { - default: 0, - }) - public driveUsage: number; - - /** - * ドライブのファイル数 - */ - @Column('integer', { - default: 0, - }) - public driveFiles: number; - /** * 直近のリクエスト送信日時 */ diff --git a/packages/backend/src/models/entities/messaging-message.ts b/packages/backend/src/models/entities/messaging-message.ts index 06ae005de..099fb7aa0 100644 --- a/packages/backend/src/models/entities/messaging-message.ts +++ b/packages/backend/src/models/entities/messaging-message.ts @@ -1,8 +1,8 @@ import { PrimaryColumn, Entity, Index, JoinColumn, Column, ManyToOne } from 'typeorm'; -import { User } from './user'; -import { DriveFile } from './drive-file'; -import { id } from '../id'; -import { UserGroup } from './user-group'; +import { User } from './user.js'; +import { DriveFile } from './drive-file.js'; +import { id } from '../id.js'; +import { UserGroup } from './user-group.js'; @Entity() export class MessagingMessage { diff --git a/packages/backend/src/models/entities/meta.ts b/packages/backend/src/models/entities/meta.ts index 1426c79c5..4d58b5f04 100644 --- a/packages/backend/src/models/entities/meta.ts +++ b/packages/backend/src/models/entities/meta.ts @@ -1,7 +1,7 @@ import { Entity, Column, PrimaryColumn, ManyToOne, JoinColumn } from 'typeorm'; -import { User } from './user'; -import { id } from '../id'; -import { Clip } from './clip'; +import { User } from './user.js'; +import { id } from '../id.js'; +import { Clip } from './clip.js'; @Entity() export class Meta { @@ -137,11 +137,6 @@ export class Meta { }) public cacheRemoteFiles: boolean; - @Column('boolean', { - default: false, - }) - public proxyRemoteFiles: boolean; - @Column({ ...id(), nullable: true, @@ -205,12 +200,6 @@ export class Meta { }) public remoteDriveCapacityMb: number; - @Column('integer', { - default: 500, - comment: 'Max allowed note text length in characters', - }) - public maxNoteTextLength: number; - @Column('varchar', { length: 128, nullable: true, @@ -355,6 +344,20 @@ export class Meta { }) public feedbackUrl: string | null; + @Column('varchar', { + length: 8192, + default: null, + nullable: true, + }) + public defaultLightTheme: string | null; + + @Column('varchar', { + length: 8192, + default: null, + nullable: true, + }) + public defaultDarkTheme: string | null; + @Column('boolean', { default: false, }) diff --git a/packages/backend/src/models/entities/moderation-log.ts b/packages/backend/src/models/entities/moderation-log.ts index fe000e14f..c99e55078 100644 --- a/packages/backend/src/models/entities/moderation-log.ts +++ b/packages/backend/src/models/entities/moderation-log.ts @@ -1,6 +1,6 @@ import { PrimaryColumn, Entity, Index, JoinColumn, Column, ManyToOne } from 'typeorm'; -import { User } from './user'; -import { id } from '../id'; +import { User } from './user.js'; +import { id } from '../id.js'; @Entity() export class ModerationLog { diff --git a/packages/backend/src/models/entities/muted-note.ts b/packages/backend/src/models/entities/muted-note.ts index b01bb0551..96a4fa8e3 100644 --- a/packages/backend/src/models/entities/muted-note.ts +++ b/packages/backend/src/models/entities/muted-note.ts @@ -1,8 +1,8 @@ import { Entity, Index, JoinColumn, Column, ManyToOne, PrimaryColumn } from 'typeorm'; -import { Note } from './note'; -import { User } from './user'; -import { id } from '../id'; -import { mutedNoteReasons } from '../../types'; +import { Note } from './note.js'; +import { User } from './user.js'; +import { id } from '../id.js'; +import { mutedNoteReasons } from '../../types.js'; @Entity() @Index(['noteId', 'userId'], { unique: true }) diff --git a/packages/backend/src/models/entities/muting.ts b/packages/backend/src/models/entities/muting.ts index b9f18a585..b3a7e7a67 100644 --- a/packages/backend/src/models/entities/muting.ts +++ b/packages/backend/src/models/entities/muting.ts @@ -1,6 +1,6 @@ import { PrimaryColumn, Entity, Index, JoinColumn, Column, ManyToOne } from 'typeorm'; -import { User } from './user'; -import { id } from '../id'; +import { User } from './user.js'; +import { id } from '../id.js'; @Entity() @Index(['muterId', 'muteeId'], { unique: true }) @@ -14,6 +14,13 @@ export class Muting { }) public createdAt: Date; + @Index() + @Column('timestamp with time zone', { + nullable: true, + default: null, + }) + public expiresAt: Date | null; + @Index() @Column({ ...id(), diff --git a/packages/backend/src/models/entities/note-favorite.ts b/packages/backend/src/models/entities/note-favorite.ts index 69d9b49d1..fe065b77a 100644 --- a/packages/backend/src/models/entities/note-favorite.ts +++ b/packages/backend/src/models/entities/note-favorite.ts @@ -1,7 +1,7 @@ import { PrimaryColumn, Entity, Index, JoinColumn, Column, ManyToOne } from 'typeorm'; -import { Note } from './note'; -import { User } from './user'; -import { id } from '../id'; +import { Note } from './note.js'; +import { User } from './user.js'; +import { id } from '../id.js'; @Entity() @Index(['userId', 'noteId'], { unique: true }) diff --git a/packages/backend/src/models/entities/note-reaction.ts b/packages/backend/src/models/entities/note-reaction.ts index 369505a6c..d7bc60989 100644 --- a/packages/backend/src/models/entities/note-reaction.ts +++ b/packages/backend/src/models/entities/note-reaction.ts @@ -1,7 +1,7 @@ import { PrimaryColumn, Entity, Index, JoinColumn, Column, ManyToOne } from 'typeorm'; -import { User } from './user'; -import { Note } from './note'; -import { id } from '../id'; +import { User } from './user.js'; +import { Note } from './note.js'; +import { id } from '../id.js'; @Entity() @Index(['userId', 'noteId'], { unique: true }) diff --git a/packages/backend/src/models/entities/note-thread-muting.ts b/packages/backend/src/models/entities/note-thread-muting.ts index f4a3a4887..8c5f7bbab 100644 --- a/packages/backend/src/models/entities/note-thread-muting.ts +++ b/packages/backend/src/models/entities/note-thread-muting.ts @@ -1,7 +1,7 @@ import { PrimaryColumn, Entity, Index, JoinColumn, Column, ManyToOne } from 'typeorm'; -import { User } from './user'; -import { Note } from './note'; -import { id } from '../id'; +import { User } from './user.js'; +import { Note } from './note.js'; +import { id } from '../id.js'; @Entity() @Index(['userId', 'threadId'], { unique: true }) diff --git a/packages/backend/src/models/entities/note-unread.ts b/packages/backend/src/models/entities/note-unread.ts index 952f71cda..a7acf254d 100644 --- a/packages/backend/src/models/entities/note-unread.ts +++ b/packages/backend/src/models/entities/note-unread.ts @@ -1,8 +1,8 @@ import { PrimaryColumn, Entity, Index, JoinColumn, Column, ManyToOne } from 'typeorm'; -import { User } from './user'; -import { Note } from './note'; -import { id } from '../id'; -import { Channel } from './channel'; +import { User } from './user.js'; +import { Note } from './note.js'; +import { id } from '../id.js'; +import { Channel } from './channel.js'; @Entity() @Index(['userId', 'noteId'], { unique: true }) diff --git a/packages/backend/src/models/entities/note-watching.ts b/packages/backend/src/models/entities/note-watching.ts index 2758efdc3..ed82e7dfe 100644 --- a/packages/backend/src/models/entities/note-watching.ts +++ b/packages/backend/src/models/entities/note-watching.ts @@ -1,7 +1,7 @@ import { PrimaryColumn, Entity, Index, JoinColumn, Column, ManyToOne } from 'typeorm'; -import { User } from './user'; -import { Note } from './note'; -import { id } from '../id'; +import { User } from './user.js'; +import { Note } from './note.js'; +import { id } from '../id.js'; @Entity() @Index(['userId', 'noteId'], { unique: true }) diff --git a/packages/backend/src/models/entities/note.ts b/packages/backend/src/models/entities/note.ts index e4a5ac871..da49d53b6 100644 --- a/packages/backend/src/models/entities/note.ts +++ b/packages/backend/src/models/entities/note.ts @@ -1,9 +1,9 @@ import { Entity, Index, JoinColumn, Column, PrimaryColumn, ManyToOne } from 'typeorm'; -import { User } from './user'; -import { DriveFile } from './drive-file'; -import { id } from '../id'; -import { noteVisibilities } from '../../types'; -import { Channel } from './channel'; +import { User } from './user.js'; +import { DriveFile } from './drive-file.js'; +import { id } from '../id.js'; +import { noteVisibilities } from '../../types.js'; +import { Channel } from './channel.js'; @Entity() @Index('IDX_NOTE_TAGS', { synchronize: false }) diff --git a/packages/backend/src/models/entities/notification.ts b/packages/backend/src/models/entities/notification.ts index 9c1d8242f..db3dba363 100644 --- a/packages/backend/src/models/entities/notification.ts +++ b/packages/backend/src/models/entities/notification.ts @@ -1,11 +1,11 @@ import { Entity, Index, JoinColumn, ManyToOne, Column, PrimaryColumn } from 'typeorm'; -import { User } from './user'; -import { id } from '../id'; -import { Note } from './note'; -import { FollowRequest } from './follow-request'; -import { UserGroupInvitation } from './user-group-invitation'; -import { AccessToken } from './access-token'; -import { notificationTypes } from '@/types'; +import { User } from './user.js'; +import { id } from '../id.js'; +import { Note } from './note.js'; +import { FollowRequest } from './follow-request.js'; +import { UserGroupInvitation } from './user-group-invitation.js'; +import { AccessToken } from './access-token.js'; +import { notificationTypes } from '@/types.js'; @Entity() export class Notification { @@ -59,7 +59,8 @@ export class Notification { * renote - (自分または自分がWatchしている)投稿がRenoteされた * quote - (自分または自分がWatchしている)投稿が引用Renoteされた * reaction - (自分または自分がWatchしている)投稿にリアクションされた - * pollVote - (自分または自分がWatchしている)投稿の投票に投票された + * pollVote - (自分または自分がWatchしている)投稿のアンケートに投票された + * pollEnded - 自分のアンケートもしくは自分が投票したアンケートが終了した * receiveFollowRequest - フォローリクエストされた * followRequestAccepted - 自分の送ったフォローリクエストが承認された * groupInvited - グループに招待された diff --git a/packages/backend/src/models/entities/page-like.ts b/packages/backend/src/models/entities/page-like.ts index 16fb8f172..17f4ebf52 100644 --- a/packages/backend/src/models/entities/page-like.ts +++ b/packages/backend/src/models/entities/page-like.ts @@ -1,7 +1,7 @@ import { PrimaryColumn, Entity, Index, JoinColumn, Column, ManyToOne } from 'typeorm'; -import { User } from './user'; -import { id } from '../id'; -import { Page } from './page'; +import { User } from './user.js'; +import { id } from '../id.js'; +import { Page } from './page.js'; @Entity() @Index(['userId', 'pageId'], { unique: true }) diff --git a/packages/backend/src/models/entities/page.ts b/packages/backend/src/models/entities/page.ts index 2b540e199..baad3a36f 100644 --- a/packages/backend/src/models/entities/page.ts +++ b/packages/backend/src/models/entities/page.ts @@ -1,7 +1,7 @@ import { Entity, Index, JoinColumn, Column, PrimaryColumn, ManyToOne } from 'typeorm'; -import { User } from './user'; -import { id } from '../id'; -import { DriveFile } from './drive-file'; +import { User } from './user.js'; +import { id } from '../id.js'; +import { DriveFile } from './drive-file.js'; @Entity() @Index(['userId', 'name'], { unique: true }) diff --git a/packages/backend/src/models/entities/password-reset-request.ts b/packages/backend/src/models/entities/password-reset-request.ts index a2db0f114..05e62cc5a 100644 --- a/packages/backend/src/models/entities/password-reset-request.ts +++ b/packages/backend/src/models/entities/password-reset-request.ts @@ -1,6 +1,6 @@ import { PrimaryColumn, Entity, Index, Column, ManyToOne, JoinColumn } from 'typeorm'; -import { id } from '../id'; -import { User } from './user'; +import { id } from '../id.js'; +import { User } from './user.js'; @Entity() export class PasswordResetRequest { diff --git a/packages/backend/src/models/entities/poll-vote.ts b/packages/backend/src/models/entities/poll-vote.ts index fb44a58e9..fca1cd009 100644 --- a/packages/backend/src/models/entities/poll-vote.ts +++ b/packages/backend/src/models/entities/poll-vote.ts @@ -1,7 +1,7 @@ import { PrimaryColumn, Entity, Index, JoinColumn, Column, ManyToOne } from 'typeorm'; -import { User } from './user'; -import { Note } from './note'; -import { id } from '../id'; +import { User } from './user.js'; +import { Note } from './note.js'; +import { id } from '../id.js'; @Entity() @Index(['userId', 'noteId', 'choice'], { unique: true }) diff --git a/packages/backend/src/models/entities/poll.ts b/packages/backend/src/models/entities/poll.ts index 9c8069349..83d0873cc 100644 --- a/packages/backend/src/models/entities/poll.ts +++ b/packages/backend/src/models/entities/poll.ts @@ -1,8 +1,8 @@ import { PrimaryColumn, Entity, Index, JoinColumn, Column, OneToOne } from 'typeorm'; -import { id } from '../id'; -import { Note } from './note'; -import { User } from './user'; -import { noteVisibilities } from '../../types'; +import { id } from '../id.js'; +import { Note } from './note.js'; +import { User } from './user.js'; +import { noteVisibilities } from '../../types.js'; @Entity() export class Poll { diff --git a/packages/backend/src/models/entities/promo-note.ts b/packages/backend/src/models/entities/promo-note.ts index e3fbab441..d110b81e9 100644 --- a/packages/backend/src/models/entities/promo-note.ts +++ b/packages/backend/src/models/entities/promo-note.ts @@ -1,7 +1,7 @@ import { PrimaryColumn, Entity, Index, JoinColumn, Column, OneToOne } from 'typeorm'; -import { Note } from './note'; -import { User } from './user'; -import { id } from '../id'; +import { Note } from './note.js'; +import { User } from './user.js'; +import { id } from '../id.js'; @Entity() export class PromoNote { diff --git a/packages/backend/src/models/entities/promo-read.ts b/packages/backend/src/models/entities/promo-read.ts index 777ed301b..a63b79cd1 100644 --- a/packages/backend/src/models/entities/promo-read.ts +++ b/packages/backend/src/models/entities/promo-read.ts @@ -1,7 +1,7 @@ import { PrimaryColumn, Entity, Index, JoinColumn, Column, ManyToOne } from 'typeorm'; -import { Note } from './note'; -import { User } from './user'; -import { id } from '../id'; +import { Note } from './note.js'; +import { User } from './user.js'; +import { id } from '../id.js'; @Entity() @Index(['userId', 'noteId'], { unique: true }) diff --git a/packages/backend/src/models/entities/registration-tickets.ts b/packages/backend/src/models/entities/registration-tickets.ts index d962f78a7..139e40f85 100644 --- a/packages/backend/src/models/entities/registration-tickets.ts +++ b/packages/backend/src/models/entities/registration-tickets.ts @@ -1,5 +1,5 @@ import { PrimaryColumn, Entity, Index, Column } from 'typeorm'; -import { id } from '../id'; +import { id } from '../id.js'; @Entity() export class RegistrationTicket { diff --git a/packages/backend/src/models/entities/registry-item.ts b/packages/backend/src/models/entities/registry-item.ts index 6d5f0185d..283796df9 100644 --- a/packages/backend/src/models/entities/registry-item.ts +++ b/packages/backend/src/models/entities/registry-item.ts @@ -1,6 +1,6 @@ import { PrimaryColumn, Entity, Index, JoinColumn, Column, ManyToOne } from 'typeorm'; -import { User } from './user'; -import { id } from '../id'; +import { User } from './user.js'; +import { id } from '../id.js'; // TODO: 同じdomain、同じscope、同じkeyのレコードは二つ以上存在しないように制約付けたい @Entity() diff --git a/packages/backend/src/models/entities/relay.ts b/packages/backend/src/models/entities/relay.ts index 4c82ccb12..94d192957 100644 --- a/packages/backend/src/models/entities/relay.ts +++ b/packages/backend/src/models/entities/relay.ts @@ -1,5 +1,5 @@ import { PrimaryColumn, Entity, Index, Column } from 'typeorm'; -import { id } from '../id'; +import { id } from '../id.js'; @Entity() export class Relay { diff --git a/packages/backend/src/models/entities/signin.ts b/packages/backend/src/models/entities/signin.ts index 7f54f2ebf..ba81f45e4 100644 --- a/packages/backend/src/models/entities/signin.ts +++ b/packages/backend/src/models/entities/signin.ts @@ -1,6 +1,6 @@ import { PrimaryColumn, Entity, Index, JoinColumn, Column, ManyToOne } from 'typeorm'; -import { User } from './user'; -import { id } from '../id'; +import { User } from './user.js'; +import { id } from '../id.js'; @Entity() export class Signin { diff --git a/packages/backend/src/models/entities/sw-subscription.ts b/packages/backend/src/models/entities/sw-subscription.ts index 2debcf744..59144d348 100644 --- a/packages/backend/src/models/entities/sw-subscription.ts +++ b/packages/backend/src/models/entities/sw-subscription.ts @@ -1,6 +1,6 @@ import { PrimaryColumn, Entity, Index, JoinColumn, Column, ManyToOne } from 'typeorm'; -import { User } from './user'; -import { id } from '../id'; +import { User } from './user.js'; +import { id } from '../id.js'; @Entity() export class SwSubscription { diff --git a/packages/backend/src/models/entities/user-group-invitation.ts b/packages/backend/src/models/entities/user-group-invitation.ts index 479442a13..10f357049 100644 --- a/packages/backend/src/models/entities/user-group-invitation.ts +++ b/packages/backend/src/models/entities/user-group-invitation.ts @@ -1,7 +1,7 @@ import { PrimaryColumn, Entity, Index, JoinColumn, Column, ManyToOne } from 'typeorm'; -import { User } from './user'; -import { UserGroup } from './user-group'; -import { id } from '../id'; +import { User } from './user.js'; +import { UserGroup } from './user-group.js'; +import { id } from '../id.js'; @Entity() @Index(['userId', 'userGroupId'], { unique: true }) diff --git a/packages/backend/src/models/entities/user-group-joining.ts b/packages/backend/src/models/entities/user-group-joining.ts index 81f335858..62a814218 100644 --- a/packages/backend/src/models/entities/user-group-joining.ts +++ b/packages/backend/src/models/entities/user-group-joining.ts @@ -1,7 +1,7 @@ import { PrimaryColumn, Entity, Index, JoinColumn, Column, ManyToOne } from 'typeorm'; -import { User } from './user'; -import { UserGroup } from './user-group'; -import { id } from '../id'; +import { User } from './user.js'; +import { UserGroup } from './user-group.js'; +import { id } from '../id.js'; @Entity() @Index(['userId', 'userGroupId'], { unique: true }) diff --git a/packages/backend/src/models/entities/user-group.ts b/packages/backend/src/models/entities/user-group.ts index 1fdb60c40..8d5de1d92 100644 --- a/packages/backend/src/models/entities/user-group.ts +++ b/packages/backend/src/models/entities/user-group.ts @@ -1,6 +1,6 @@ import { Entity, Index, JoinColumn, Column, PrimaryColumn, ManyToOne } from 'typeorm'; -import { User } from './user'; -import { id } from '../id'; +import { User } from './user.js'; +import { id } from '../id.js'; @Entity() export class UserGroup { diff --git a/packages/backend/src/models/entities/user-keypair.ts b/packages/backend/src/models/entities/user-keypair.ts index 48bff0d10..85fa06297 100644 --- a/packages/backend/src/models/entities/user-keypair.ts +++ b/packages/backend/src/models/entities/user-keypair.ts @@ -1,6 +1,6 @@ import { PrimaryColumn, Entity, JoinColumn, Column, OneToOne } from 'typeorm'; -import { User } from './user'; -import { id } from '../id'; +import { User } from './user.js'; +import { id } from '../id.js'; @Entity() export class UserKeypair { diff --git a/packages/backend/src/models/entities/user-list-joining.ts b/packages/backend/src/models/entities/user-list-joining.ts index 2efa01752..12f28c414 100644 --- a/packages/backend/src/models/entities/user-list-joining.ts +++ b/packages/backend/src/models/entities/user-list-joining.ts @@ -1,7 +1,7 @@ import { PrimaryColumn, Entity, Index, JoinColumn, Column, ManyToOne } from 'typeorm'; -import { User } from './user'; -import { UserList } from './user-list'; -import { id } from '../id'; +import { User } from './user.js'; +import { UserList } from './user-list.js'; +import { id } from '../id.js'; @Entity() @Index(['userId', 'userListId'], { unique: true }) diff --git a/packages/backend/src/models/entities/user-list.ts b/packages/backend/src/models/entities/user-list.ts index c2896a1db..ca69394e9 100644 --- a/packages/backend/src/models/entities/user-list.ts +++ b/packages/backend/src/models/entities/user-list.ts @@ -1,6 +1,6 @@ import { PrimaryColumn, Entity, Index, JoinColumn, Column, ManyToOne } from 'typeorm'; -import { User } from './user'; -import { id } from '../id'; +import { User } from './user.js'; +import { id } from '../id.js'; @Entity() export class UserList { diff --git a/packages/backend/src/models/entities/user-note-pining.ts b/packages/backend/src/models/entities/user-note-pining.ts index b91e02c5c..c91ab7fdd 100644 --- a/packages/backend/src/models/entities/user-note-pining.ts +++ b/packages/backend/src/models/entities/user-note-pining.ts @@ -1,7 +1,7 @@ import { PrimaryColumn, Entity, Index, JoinColumn, Column, ManyToOne } from 'typeorm'; -import { Note } from './note'; -import { User } from './user'; -import { id } from '../id'; +import { Note } from './note.js'; +import { User } from './user.js'; +import { id } from '../id.js'; @Entity() @Index(['userId', 'noteId'], { unique: true }) diff --git a/packages/backend/src/models/entities/user-pending.ts b/packages/backend/src/models/entities/user-pending.ts index 40482af33..763794884 100644 --- a/packages/backend/src/models/entities/user-pending.ts +++ b/packages/backend/src/models/entities/user-pending.ts @@ -1,5 +1,5 @@ import { PrimaryColumn, Entity, Index, Column } from 'typeorm'; -import { id } from '../id'; +import { id } from '../id.js'; @Entity() export class UserPending { diff --git a/packages/backend/src/models/entities/user-profile.ts b/packages/backend/src/models/entities/user-profile.ts index d8317de8d..f95cb144c 100644 --- a/packages/backend/src/models/entities/user-profile.ts +++ b/packages/backend/src/models/entities/user-profile.ts @@ -1,8 +1,8 @@ import { Entity, Column, Index, OneToOne, JoinColumn, PrimaryColumn } from 'typeorm'; -import { id } from '../id'; -import { User } from './user'; -import { Page } from './page'; -import { ffVisibility, notificationTypes } from '@/types'; +import { id } from '../id.js'; +import { User } from './user.js'; +import { Page } from './page.js'; +import { ffVisibility, notificationTypes } from '@/types.js'; // TODO: このテーブルで管理している情報すべてレジストリで管理するようにしても良いかも // ただ、「emailVerified が true なユーザーを find する」のようなクエリは書けなくなるからウーン diff --git a/packages/backend/src/models/entities/user-publickey.ts b/packages/backend/src/models/entities/user-publickey.ts index 128e13510..31ed60de8 100644 --- a/packages/backend/src/models/entities/user-publickey.ts +++ b/packages/backend/src/models/entities/user-publickey.ts @@ -1,6 +1,6 @@ import { PrimaryColumn, Entity, Index, JoinColumn, Column, OneToOne } from 'typeorm'; -import { User } from './user'; -import { id } from '../id'; +import { User } from './user.js'; +import { id } from '../id.js'; @Entity() export class UserPublickey { diff --git a/packages/backend/src/models/entities/user-security-key.ts b/packages/backend/src/models/entities/user-security-key.ts index e7b63fb82..c4f2a852e 100644 --- a/packages/backend/src/models/entities/user-security-key.ts +++ b/packages/backend/src/models/entities/user-security-key.ts @@ -1,6 +1,6 @@ import { PrimaryColumn, Entity, JoinColumn, Column, ManyToOne, Index } from 'typeorm'; -import { User } from './user'; -import { id } from '../id'; +import { User } from './user.js'; +import { id } from '../id.js'; @Entity() export class UserSecurityKey { diff --git a/packages/backend/src/models/entities/user.ts b/packages/backend/src/models/entities/user.ts index e4d9a3ced..9d5db10eb 100644 --- a/packages/backend/src/models/entities/user.ts +++ b/packages/backend/src/models/entities/user.ts @@ -1,6 +1,6 @@ import { Entity, Column, Index, OneToOne, JoinColumn, PrimaryColumn } from 'typeorm'; -import { DriveFile } from './drive-file'; -import { id } from '../id'; +import { DriveFile } from './drive-file.js'; +import { id } from '../id.js'; @Entity() @Index(['usernameLower', 'host'], { unique: true }) @@ -106,26 +106,6 @@ export class User { }) public tags: string[]; - @Column('varchar', { - length: 512, nullable: true, - }) - public avatarUrl: string | null; - - @Column('varchar', { - length: 512, nullable: true, - }) - public bannerUrl: string | null; - - @Column('varchar', { - length: 128, nullable: true, - }) - public avatarBlurhash: string | null; - - @Column('varchar', { - length: 128, nullable: true, - }) - public bannerBlurhash: string | null; - @Column('boolean', { default: false, comment: 'Whether the User is suspended.', diff --git a/packages/backend/src/models/index.ts b/packages/backend/src/models/index.ts index 67da34739..e7b685488 100644 --- a/packages/backend/src/models/index.ts +++ b/packages/backend/src/models/index.ts @@ -1,66 +1,67 @@ import { getRepository, getCustomRepository } from 'typeorm'; -import { Announcement } from './entities/announcement'; -import { AnnouncementRead } from './entities/announcement-read'; -import { Instance } from './entities/instance'; -import { Poll } from './entities/poll'; -import { PollVote } from './entities/poll-vote'; -import { Meta } from './entities/meta'; -import { SwSubscription } from './entities/sw-subscription'; -import { NoteWatching } from './entities/note-watching'; -import { NoteThreadMuting } from './entities/note-thread-muting'; -import { NoteUnread } from './entities/note-unread'; -import { RegistrationTicket } from './entities/registration-tickets'; -import { UserRepository } from './repositories/user'; -import { NoteRepository } from './repositories/note'; -import { DriveFileRepository } from './repositories/drive-file'; -import { DriveFolderRepository } from './repositories/drive-folder'; -import { AccessToken } from './entities/access-token'; -import { UserNotePining } from './entities/user-note-pining'; -import { SigninRepository } from './repositories/signin'; -import { MessagingMessageRepository } from './repositories/messaging-message'; -import { UserListRepository } from './repositories/user-list'; -import { UserListJoining } from './entities/user-list-joining'; -import { UserGroupRepository } from './repositories/user-group'; -import { UserGroupJoining } from './entities/user-group-joining'; -import { UserGroupInvitationRepository } from './repositories/user-group-invitation'; -import { FollowRequestRepository } from './repositories/follow-request'; -import { MutingRepository } from './repositories/muting'; -import { BlockingRepository } from './repositories/blocking'; -import { NoteReactionRepository } from './repositories/note-reaction'; -import { NotificationRepository } from './repositories/notification'; -import { NoteFavoriteRepository } from './repositories/note-favorite'; -import { UserPublickey } from './entities/user-publickey'; -import { UserKeypair } from './entities/user-keypair'; -import { AppRepository } from './repositories/app'; -import { FollowingRepository } from './repositories/following'; -import { AbuseUserReportRepository } from './repositories/abuse-user-report'; -import { AuthSessionRepository } from './repositories/auth-session'; -import { UserProfile } from './entities/user-profile'; -import { AttestationChallenge } from './entities/attestation-challenge'; -import { UserSecurityKey } from './entities/user-security-key'; -import { HashtagRepository } from './repositories/hashtag'; -import { PageRepository } from './repositories/page'; -import { PageLikeRepository } from './repositories/page-like'; -import { GalleryPostRepository } from './repositories/gallery-post'; -import { GalleryLikeRepository } from './repositories/gallery-like'; -import { ModerationLogRepository } from './repositories/moderation-logs'; -import { UsedUsername } from './entities/used-username'; -import { ClipRepository } from './repositories/clip'; -import { ClipNote } from './entities/clip-note'; -import { AntennaRepository } from './repositories/antenna'; -import { AntennaNote } from './entities/antenna-note'; -import { PromoNote } from './entities/promo-note'; -import { PromoRead } from './entities/promo-read'; -import { EmojiRepository } from './repositories/emoji'; -import { RelayRepository } from './repositories/relay'; -import { ChannelRepository } from './repositories/channel'; -import { MutedNote } from './entities/muted-note'; -import { ChannelFollowing } from './entities/channel-following'; -import { ChannelNotePining } from './entities/channel-note-pining'; -import { RegistryItem } from './entities/registry-item'; -import { Ad } from './entities/ad'; -import { PasswordResetRequest } from './entities/password-reset-request'; -import { UserPending } from './entities/user-pending'; +import { Announcement } from './entities/announcement.js'; +import { AnnouncementRead } from './entities/announcement-read.js'; +import { Instance } from './entities/instance.js'; +import { Poll } from './entities/poll.js'; +import { PollVote } from './entities/poll-vote.js'; +import { Meta } from './entities/meta.js'; +import { SwSubscription } from './entities/sw-subscription.js'; +import { NoteWatching } from './entities/note-watching.js'; +import { NoteThreadMuting } from './entities/note-thread-muting.js'; +import { NoteUnread } from './entities/note-unread.js'; +import { RegistrationTicket } from './entities/registration-tickets.js'; +import { UserRepository } from './repositories/user.js'; +import { NoteRepository } from './repositories/note.js'; +import { DriveFileRepository } from './repositories/drive-file.js'; +import { DriveFolderRepository } from './repositories/drive-folder.js'; +import { AccessToken } from './entities/access-token.js'; +import { UserNotePining } from './entities/user-note-pining.js'; +import { SigninRepository } from './repositories/signin.js'; +import { MessagingMessageRepository } from './repositories/messaging-message.js'; +import { UserListRepository } from './repositories/user-list.js'; +import { UserListJoining } from './entities/user-list-joining.js'; +import { UserGroupRepository } from './repositories/user-group.js'; +import { UserGroupJoining } from './entities/user-group-joining.js'; +import { UserGroupInvitationRepository } from './repositories/user-group-invitation.js'; +import { FollowRequestRepository } from './repositories/follow-request.js'; +import { MutingRepository } from './repositories/muting.js'; +import { BlockingRepository } from './repositories/blocking.js'; +import { NoteReactionRepository } from './repositories/note-reaction.js'; +import { NotificationRepository } from './repositories/notification.js'; +import { NoteFavoriteRepository } from './repositories/note-favorite.js'; +import { UserPublickey } from './entities/user-publickey.js'; +import { UserKeypair } from './entities/user-keypair.js'; +import { AppRepository } from './repositories/app.js'; +import { FollowingRepository } from './repositories/following.js'; +import { AbuseUserReportRepository } from './repositories/abuse-user-report.js'; +import { AuthSessionRepository } from './repositories/auth-session.js'; +import { UserProfile } from './entities/user-profile.js'; +import { AttestationChallenge } from './entities/attestation-challenge.js'; +import { UserSecurityKey } from './entities/user-security-key.js'; +import { HashtagRepository } from './repositories/hashtag.js'; +import { PageRepository } from './repositories/page.js'; +import { PageLikeRepository } from './repositories/page-like.js'; +import { GalleryPostRepository } from './repositories/gallery-post.js'; +import { GalleryLikeRepository } from './repositories/gallery-like.js'; +import { ModerationLogRepository } from './repositories/moderation-logs.js'; +import { UsedUsername } from './entities/used-username.js'; +import { ClipRepository } from './repositories/clip.js'; +import { ClipNote } from './entities/clip-note.js'; +import { AntennaRepository } from './repositories/antenna.js'; +import { AntennaNote } from './entities/antenna-note.js'; +import { PromoNote } from './entities/promo-note.js'; +import { PromoRead } from './entities/promo-read.js'; +import { EmojiRepository } from './repositories/emoji.js'; +import { RelayRepository } from './repositories/relay.js'; +import { ChannelRepository } from './repositories/channel.js'; +import { MutedNote } from './entities/muted-note.js'; +import { ChannelFollowing } from './entities/channel-following.js'; +import { ChannelNotePining } from './entities/channel-note-pining.js'; +import { RegistryItem } from './entities/registry-item.js'; +import { Ad } from './entities/ad.js'; +import { PasswordResetRequest } from './entities/password-reset-request.js'; +import { UserPending } from './entities/user-pending.js'; +import { InstanceRepository } from './repositories/instance.js'; export const Announcements = getRepository(Announcement); export const AnnouncementReads = getRepository(AnnouncementRead); @@ -89,7 +90,7 @@ export const UserNotePinings = getRepository(UserNotePining); export const UsedUsernames = getRepository(UsedUsername); export const Followings = getCustomRepository(FollowingRepository); export const FollowRequests = getCustomRepository(FollowRequestRepository); -export const Instances = getRepository(Instance); +export const Instances = getCustomRepository(InstanceRepository); export const Emojis = getCustomRepository(EmojiRepository); export const DriveFiles = getCustomRepository(DriveFileRepository); export const DriveFolders = getCustomRepository(DriveFolderRepository); diff --git a/packages/backend/src/models/repositories/abuse-user-report.ts b/packages/backend/src/models/repositories/abuse-user-report.ts index 144195855..348f88b3a 100644 --- a/packages/backend/src/models/repositories/abuse-user-report.ts +++ b/packages/backend/src/models/repositories/abuse-user-report.ts @@ -1,7 +1,7 @@ import { EntityRepository, Repository } from 'typeorm'; -import { Users } from '../index'; -import { AbuseUserReport } from '@/models/entities/abuse-user-report'; -import { awaitAll } from '@/prelude/await-all'; +import { Users } from '../index.js'; +import { AbuseUserReport } from '@/models/entities/abuse-user-report.js'; +import { awaitAll } from '@/prelude/await-all.js'; @EntityRepository(AbuseUserReport) export class AbuseUserReportRepository extends Repository { diff --git a/packages/backend/src/models/repositories/antenna.ts b/packages/backend/src/models/repositories/antenna.ts index 3bf0645a7..3440ca187 100644 --- a/packages/backend/src/models/repositories/antenna.ts +++ b/packages/backend/src/models/repositories/antenna.ts @@ -1,7 +1,7 @@ import { EntityRepository, Repository } from 'typeorm'; -import { Antenna } from '@/models/entities/antenna'; -import { Packed } from '@/misc/schema'; -import { AntennaNotes, UserGroupJoinings } from '../index'; +import { Antenna } from '@/models/entities/antenna.js'; +import { Packed } from '@/misc/schema.js'; +import { AntennaNotes, UserGroupJoinings } from '../index.js'; @EntityRepository(Antenna) export class AntennaRepository extends Repository { diff --git a/packages/backend/src/models/repositories/app.ts b/packages/backend/src/models/repositories/app.ts index 6bac4d959..4c3c488da 100644 --- a/packages/backend/src/models/repositories/app.ts +++ b/packages/backend/src/models/repositories/app.ts @@ -1,8 +1,8 @@ import { EntityRepository, Repository } from 'typeorm'; -import { App } from '@/models/entities/app'; -import { AccessTokens } from '../index'; -import { Packed } from '@/misc/schema'; -import { User } from '../entities/user'; +import { App } from '@/models/entities/app.js'; +import { AccessTokens } from '../index.js'; +import { Packed } from '@/misc/schema.js'; +import { User } from '../entities/user.js'; @EntityRepository(App) export class AppRepository extends Repository { @@ -32,7 +32,7 @@ export class AppRepository extends Repository { ...(me ? { isAuthorized: await AccessTokens.count({ appId: app.id, - userId: me, + userId: me.id, }).then(count => count > 0), } : {}), }; diff --git a/packages/backend/src/models/repositories/auth-session.ts b/packages/backend/src/models/repositories/auth-session.ts index 6308909c4..7a7bd3a1e 100644 --- a/packages/backend/src/models/repositories/auth-session.ts +++ b/packages/backend/src/models/repositories/auth-session.ts @@ -1,8 +1,8 @@ import { EntityRepository, Repository } from 'typeorm'; -import { Apps } from '../index'; -import { AuthSession } from '@/models/entities/auth-session'; -import { awaitAll } from '@/prelude/await-all'; -import { User } from '@/models/entities/user'; +import { Apps } from '../index.js'; +import { AuthSession } from '@/models/entities/auth-session.js'; +import { awaitAll } from '@/prelude/await-all.js'; +import { User } from '@/models/entities/user.js'; @EntityRepository(AuthSession) export class AuthSessionRepository extends Repository { diff --git a/packages/backend/src/models/repositories/blocking.ts b/packages/backend/src/models/repositories/blocking.ts index c20b02f50..b155bf944 100644 --- a/packages/backend/src/models/repositories/blocking.ts +++ b/packages/backend/src/models/repositories/blocking.ts @@ -1,9 +1,9 @@ import { EntityRepository, Repository } from 'typeorm'; -import { Users } from '../index'; -import { Blocking } from '@/models/entities/blocking'; -import { awaitAll } from '@/prelude/await-all'; -import { Packed } from '@/misc/schema'; -import { User } from '@/models/entities/user'; +import { Users } from '../index.js'; +import { Blocking } from '@/models/entities/blocking.js'; +import { awaitAll } from '@/prelude/await-all.js'; +import { Packed } from '@/misc/schema.js'; +import { User } from '@/models/entities/user.js'; @EntityRepository(Blocking) export class BlockingRepository extends Repository { diff --git a/packages/backend/src/models/repositories/channel.ts b/packages/backend/src/models/repositories/channel.ts index b3afb823a..cc13d7c1e 100644 --- a/packages/backend/src/models/repositories/channel.ts +++ b/packages/backend/src/models/repositories/channel.ts @@ -1,8 +1,8 @@ import { EntityRepository, Repository } from 'typeorm'; -import { Channel } from '@/models/entities/channel'; -import { Packed } from '@/misc/schema'; -import { DriveFiles, ChannelFollowings, NoteUnreads } from '../index'; -import { User } from '@/models/entities/user'; +import { Channel } from '@/models/entities/channel.js'; +import { Packed } from '@/misc/schema.js'; +import { DriveFiles, ChannelFollowings, NoteUnreads } from '../index.js'; +import { User } from '@/models/entities/user.js'; @EntityRepository(Channel) export class ChannelRepository extends Repository { diff --git a/packages/backend/src/models/repositories/clip.ts b/packages/backend/src/models/repositories/clip.ts index 6f9ceeb50..9e1979729 100644 --- a/packages/backend/src/models/repositories/clip.ts +++ b/packages/backend/src/models/repositories/clip.ts @@ -1,8 +1,8 @@ import { EntityRepository, Repository } from 'typeorm'; -import { Clip } from '@/models/entities/clip'; -import { Packed } from '@/misc/schema'; -import { Users } from '../index'; -import { awaitAll } from '@/prelude/await-all'; +import { Clip } from '@/models/entities/clip.js'; +import { Packed } from '@/misc/schema.js'; +import { Users } from '../index.js'; +import { awaitAll } from '@/prelude/await-all.js'; @EntityRepository(Clip) export class ClipRepository extends Repository { diff --git a/packages/backend/src/models/repositories/drive-file.ts b/packages/backend/src/models/repositories/drive-file.ts index 44db9a0a5..6452632db 100644 --- a/packages/backend/src/models/repositories/drive-file.ts +++ b/packages/backend/src/models/repositories/drive-file.ts @@ -1,14 +1,14 @@ import { EntityRepository, Repository } from 'typeorm'; -import { DriveFile } from '@/models/entities/drive-file'; -import { Users, DriveFolders } from '../index'; -import { User } from '@/models/entities/user'; -import { toPuny } from '@/misc/convert-host'; -import { awaitAll, Promiseable } from '@/prelude/await-all'; -import { Packed } from '@/misc/schema'; -import config from '@/config/index'; -import { query, appendQuery } from '@/prelude/url'; -import { Meta } from '@/models/entities/meta'; -import { fetchMeta } from '@/misc/fetch-meta'; +import { DriveFile } from '@/models/entities/drive-file.js'; +import { Users, DriveFolders } from '../index.js'; +import { User } from '@/models/entities/user.js'; +import { toPuny } from '@/misc/convert-host.js'; +import { awaitAll, Promiseable } from '@/prelude/await-all.js'; +import { Packed } from '@/misc/schema.js'; +import config from '@/config/index.js'; +import { query, appendQuery } from '@/prelude/url.js'; +import { Meta } from '@/models/entities/meta.js'; +import { fetchMeta } from '@/misc/fetch-meta.js'; type PackOptions = { detail?: boolean, @@ -41,7 +41,7 @@ export class DriveFileRepository extends Repository { return file.properties; } - public getPublicUrl(file: DriveFile, thumbnail = false, meta?: Meta): string | null { + public getPublicUrl(file: DriveFile, thumbnail = false): string | null { // リモートかつメディアプロキシ if (file.uri != null && file.userHost != null && config.mediaProxy != null) { return appendQuery(config.mediaProxy, query({ @@ -51,7 +51,7 @@ export class DriveFileRepository extends Repository { } // リモートかつ期限切れはローカルプロキシを試みる - if (file.uri != null && file.isLink && meta && meta.proxyRemoteFiles) { + if (file.uri != null && file.isLink && config.proxyRemoteFiles) { const key = thumbnail ? file.thumbnailAccessKey : file.webpublicAccessKey; if (key && !key.match('/')) { // 古いものはここにオブジェクトストレージキーが入ってるので除外 @@ -136,8 +136,8 @@ export class DriveFileRepository extends Repository { isSensitive: file.isSensitive, blurhash: file.blurhash, properties: opts.self ? file.properties : this.getPublicProperties(file), - url: opts.self ? file.url : this.getPublicUrl(file, false, meta), - thumbnailUrl: this.getPublicUrl(file, true, meta), + url: opts.self ? file.url : this.getPublicUrl(file, false), + thumbnailUrl: this.getPublicUrl(file, true), comment: file.comment, folderId: file.folderId, folder: opts.detail && file.folderId ? DriveFolders.pack(file.folderId, { diff --git a/packages/backend/src/models/repositories/drive-folder.ts b/packages/backend/src/models/repositories/drive-folder.ts index b2e6cee9b..b0e09eedf 100644 --- a/packages/backend/src/models/repositories/drive-folder.ts +++ b/packages/backend/src/models/repositories/drive-folder.ts @@ -1,18 +1,11 @@ import { EntityRepository, Repository } from 'typeorm'; -import { DriveFolders, DriveFiles } from '../index'; -import { DriveFolder } from '@/models/entities/drive-folder'; -import { awaitAll } from '@/prelude/await-all'; -import { Packed } from '@/misc/schema'; +import { DriveFolders, DriveFiles } from '../index.js'; +import { DriveFolder } from '@/models/entities/drive-folder.js'; +import { awaitAll } from '@/prelude/await-all.js'; +import { Packed } from '@/misc/schema.js'; @EntityRepository(DriveFolder) export class DriveFolderRepository extends Repository { - public validateFolderName(name: string): boolean { - return ( - (name.trim().length > 0) && - (name.length <= 200) - ); - } - public async pack( src: DriveFolder['id'] | DriveFolder, options?: { diff --git a/packages/backend/src/models/repositories/emoji.ts b/packages/backend/src/models/repositories/emoji.ts index b9dc6ed0a..3b13832a3 100644 --- a/packages/backend/src/models/repositories/emoji.ts +++ b/packages/backend/src/models/repositories/emoji.ts @@ -1,6 +1,6 @@ import { EntityRepository, Repository } from 'typeorm'; -import { Emoji } from '@/models/entities/emoji'; -import { Packed } from '@/misc/schema'; +import { Emoji } from '@/models/entities/emoji.js'; +import { Packed } from '@/misc/schema.js'; @EntityRepository(Emoji) export class EmojiRepository extends Repository { diff --git a/packages/backend/src/models/repositories/federation-instance.ts b/packages/backend/src/models/repositories/federation-instance.ts deleted file mode 100644 index 426fd5bfc..000000000 --- a/packages/backend/src/models/repositories/federation-instance.ts +++ /dev/null @@ -1,2 +0,0 @@ -import config from '@/config/index'; - diff --git a/packages/backend/src/models/repositories/follow-request.ts b/packages/backend/src/models/repositories/follow-request.ts index d6ee58e23..1da1f875e 100644 --- a/packages/backend/src/models/repositories/follow-request.ts +++ b/packages/backend/src/models/repositories/follow-request.ts @@ -1,7 +1,7 @@ import { EntityRepository, Repository } from 'typeorm'; -import { FollowRequest } from '@/models/entities/follow-request'; -import { Users } from '../index'; -import { User } from '@/models/entities/user'; +import { FollowRequest } from '@/models/entities/follow-request.js'; +import { Users } from '../index.js'; +import { User } from '@/models/entities/user.js'; @EntityRepository(FollowRequest) export class FollowRequestRepository extends Repository { diff --git a/packages/backend/src/models/repositories/following.ts b/packages/backend/src/models/repositories/following.ts index 9d20f442d..f25289d19 100644 --- a/packages/backend/src/models/repositories/following.ts +++ b/packages/backend/src/models/repositories/following.ts @@ -1,9 +1,9 @@ import { EntityRepository, Repository } from 'typeorm'; -import { Users } from '../index'; -import { Following } from '@/models/entities/following'; -import { awaitAll } from '@/prelude/await-all'; -import { Packed } from '@/misc/schema'; -import { User } from '@/models/entities/user'; +import { Users } from '../index.js'; +import { Following } from '@/models/entities/following.js'; +import { awaitAll } from '@/prelude/await-all.js'; +import { Packed } from '@/misc/schema.js'; +import { User } from '@/models/entities/user.js'; type LocalFollowerFollowing = Following & { followerHost: null; diff --git a/packages/backend/src/models/repositories/gallery-like.ts b/packages/backend/src/models/repositories/gallery-like.ts index 79123e5ee..545186fa1 100644 --- a/packages/backend/src/models/repositories/gallery-like.ts +++ b/packages/backend/src/models/repositories/gallery-like.ts @@ -1,6 +1,6 @@ import { EntityRepository, Repository } from 'typeorm'; -import { GalleryLike } from '@/models/entities/gallery-like'; -import { GalleryPosts } from '../index'; +import { GalleryLike } from '@/models/entities/gallery-like.js'; +import { GalleryPosts } from '../index.js'; @EntityRepository(GalleryLike) export class GalleryLikeRepository extends Repository { diff --git a/packages/backend/src/models/repositories/gallery-post.ts b/packages/backend/src/models/repositories/gallery-post.ts index e9233bb91..bbb036dd0 100644 --- a/packages/backend/src/models/repositories/gallery-post.ts +++ b/packages/backend/src/models/repositories/gallery-post.ts @@ -1,9 +1,9 @@ import { EntityRepository, Repository } from 'typeorm'; -import { GalleryPost } from '@/models/entities/gallery-post'; -import { Packed } from '@/misc/schema'; -import { Users, DriveFiles, GalleryLikes } from '../index'; -import { awaitAll } from '@/prelude/await-all'; -import { User } from '@/models/entities/user'; +import { GalleryPost } from '@/models/entities/gallery-post.js'; +import { Packed } from '@/misc/schema.js'; +import { Users, DriveFiles, GalleryLikes } from '../index.js'; +import { awaitAll } from '@/prelude/await-all.js'; +import { User } from '@/models/entities/user.js'; @EntityRepository(GalleryPost) export class GalleryPostRepository extends Repository { diff --git a/packages/backend/src/models/repositories/hashtag.ts b/packages/backend/src/models/repositories/hashtag.ts index c4b8d50c4..0548e19ee 100644 --- a/packages/backend/src/models/repositories/hashtag.ts +++ b/packages/backend/src/models/repositories/hashtag.ts @@ -1,6 +1,6 @@ import { EntityRepository, Repository } from 'typeorm'; -import { Hashtag } from '@/models/entities/hashtag'; -import { Packed } from '@/misc/schema'; +import { Hashtag } from '@/models/entities/hashtag.js'; +import { Packed } from '@/misc/schema.js'; @EntityRepository(Hashtag) export class HashtagRepository extends Repository { diff --git a/packages/backend/src/models/repositories/instance.ts b/packages/backend/src/models/repositories/instance.ts new file mode 100644 index 000000000..358e055aa --- /dev/null +++ b/packages/backend/src/models/repositories/instance.ts @@ -0,0 +1,39 @@ +import { EntityRepository, Repository } from 'typeorm'; +import { Instance } from '@/models/entities/instance.js'; +import { Packed } from '@/misc/schema.js'; + +@EntityRepository(Instance) +export class InstanceRepository extends Repository { + public async pack( + instance: Instance, + ): Promise> { + return { + id: instance.id, + caughtAt: instance.caughtAt.toISOString(), + host: instance.host, + usersCount: instance.usersCount, + notesCount: instance.notesCount, + followingCount: instance.followingCount, + followersCount: instance.followersCount, + latestRequestSentAt: instance.latestRequestSentAt ? instance.latestRequestSentAt.toISOString() : null, + lastCommunicatedAt: instance.lastCommunicatedAt.toISOString(), + isNotResponding: instance.isNotResponding, + isSuspended: instance.isSuspended, + softwareName: instance.softwareName, + softwareVersion: instance.softwareVersion, + openRegistrations: instance.openRegistrations, + name: instance.name, + description: instance.description, + maintainerName: instance.maintainerName, + maintainerEmail: instance.maintainerEmail, + iconUrl: instance.iconUrl, + infoUpdatedAt: instance.infoUpdatedAt ? instance.infoUpdatedAt.toISOString() : null, + }; + } + + public packMany( + instances: Instance[], + ) { + return Promise.all(instances.map(x => this.pack(x))); + } +} diff --git a/packages/backend/src/models/repositories/messaging-message.ts b/packages/backend/src/models/repositories/messaging-message.ts index 0a342430b..3f5170700 100644 --- a/packages/backend/src/models/repositories/messaging-message.ts +++ b/packages/backend/src/models/repositories/messaging-message.ts @@ -1,15 +1,11 @@ import { EntityRepository, Repository } from 'typeorm'; -import { MessagingMessage } from '@/models/entities/messaging-message'; -import { Users, DriveFiles, UserGroups } from '../index'; -import { Packed } from '@/misc/schema'; -import { User } from '@/models/entities/user'; +import { MessagingMessage } from '@/models/entities/messaging-message.js'; +import { Users, DriveFiles, UserGroups } from '../index.js'; +import { Packed } from '@/misc/schema.js'; +import { User } from '@/models/entities/user.js'; @EntityRepository(MessagingMessage) export class MessagingMessageRepository extends Repository { - public validateText(text: string): boolean { - return text.trim().length <= 1000 && text.trim() != ''; - } - public async pack( src: MessagingMessage['id'] | MessagingMessage, me?: { id: User['id'] } | null | undefined, diff --git a/packages/backend/src/models/repositories/moderation-logs.ts b/packages/backend/src/models/repositories/moderation-logs.ts index f530613bc..ea7810496 100644 --- a/packages/backend/src/models/repositories/moderation-logs.ts +++ b/packages/backend/src/models/repositories/moderation-logs.ts @@ -1,7 +1,7 @@ import { EntityRepository, Repository } from 'typeorm'; -import { Users } from '../index'; -import { ModerationLog } from '@/models/entities/moderation-log'; -import { awaitAll } from '@/prelude/await-all'; +import { Users } from '../index.js'; +import { ModerationLog } from '@/models/entities/moderation-log.js'; +import { awaitAll } from '@/prelude/await-all.js'; @EntityRepository(ModerationLog) export class ModerationLogRepository extends Repository { diff --git a/packages/backend/src/models/repositories/muting.ts b/packages/backend/src/models/repositories/muting.ts index bdbe9b47d..643e0b68e 100644 --- a/packages/backend/src/models/repositories/muting.ts +++ b/packages/backend/src/models/repositories/muting.ts @@ -1,9 +1,9 @@ import { EntityRepository, Repository } from 'typeorm'; -import { Users } from '../index'; -import { Muting } from '@/models/entities/muting'; -import { awaitAll } from '@/prelude/await-all'; -import { Packed } from '@/misc/schema'; -import { User } from '@/models/entities/user'; +import { Users } from '../index.js'; +import { Muting } from '@/models/entities/muting.js'; +import { awaitAll } from '@/prelude/await-all.js'; +import { Packed } from '@/misc/schema.js'; +import { User } from '@/models/entities/user.js'; @EntityRepository(Muting) export class MutingRepository extends Repository { @@ -16,6 +16,7 @@ export class MutingRepository extends Repository { return await awaitAll({ id: muting.id, createdAt: muting.createdAt.toISOString(), + expiresAt: muting.expiresAt ? muting.expiresAt.toISOString() : null, muteeId: muting.muteeId, mutee: Users.pack(muting.muteeId, me, { detail: true, diff --git a/packages/backend/src/models/repositories/note-favorite.ts b/packages/backend/src/models/repositories/note-favorite.ts index f4cd64e39..d7a7925eb 100644 --- a/packages/backend/src/models/repositories/note-favorite.ts +++ b/packages/backend/src/models/repositories/note-favorite.ts @@ -1,7 +1,7 @@ import { EntityRepository, Repository } from 'typeorm'; -import { NoteFavorite } from '@/models/entities/note-favorite'; -import { Notes } from '../index'; -import { User } from '@/models/entities/user'; +import { NoteFavorite } from '@/models/entities/note-favorite.js'; +import { Notes } from '../index.js'; +import { User } from '@/models/entities/user.js'; @EntityRepository(NoteFavorite) export class NoteFavoriteRepository extends Repository { diff --git a/packages/backend/src/models/repositories/note-reaction.ts b/packages/backend/src/models/repositories/note-reaction.ts index 097574eff..a212b0d3e 100644 --- a/packages/backend/src/models/repositories/note-reaction.ts +++ b/packages/backend/src/models/repositories/note-reaction.ts @@ -1,9 +1,9 @@ import { EntityRepository, Repository } from 'typeorm'; -import { NoteReaction } from '@/models/entities/note-reaction'; -import { Notes, Users } from '../index'; -import { Packed } from '@/misc/schema'; -import { convertLegacyReaction } from '@/misc/reaction-lib'; -import { User } from '@/models/entities/user'; +import { NoteReaction } from '@/models/entities/note-reaction.js'; +import { Notes, Users } from '../index.js'; +import { Packed } from '@/misc/schema.js'; +import { convertLegacyReaction } from '@/misc/reaction-lib.js'; +import { User } from '@/models/entities/user.js'; @EntityRepository(NoteReaction) export class NoteReactionRepository extends Repository { @@ -23,10 +23,10 @@ export class NoteReactionRepository extends Repository { return { id: reaction.id, createdAt: reaction.createdAt.toISOString(), - user: await Users.pack(reaction.userId, me), + user: await Users.pack(reaction.user ?? reaction.userId, me), type: convertLegacyReaction(reaction.reaction), ...(opts.withNote ? { - note: await Notes.pack(reaction.noteId, me), + note: await Notes.pack(reaction.note ?? reaction.noteId, me), } : {}), }; } diff --git a/packages/backend/src/models/repositories/note.ts b/packages/backend/src/models/repositories/note.ts index 9a7fef497..418d6e234 100644 --- a/packages/backend/src/models/repositories/note.ts +++ b/packages/backend/src/models/repositories/note.ts @@ -1,21 +1,17 @@ import { EntityRepository, Repository, In } from 'typeorm'; import * as mfm from 'mfm-js'; -import { Note } from '@/models/entities/note'; -import { User } from '@/models/entities/user'; -import { Users, PollVotes, DriveFiles, NoteReactions, Followings, Polls, Channels } from '../index'; -import { Packed } from '@/misc/schema'; -import { nyaize } from '@/misc/nyaize'; -import { awaitAll } from '@/prelude/await-all'; -import { convertLegacyReaction, convertLegacyReactions, decodeReaction } from '@/misc/reaction-lib'; -import { NoteReaction } from '@/models/entities/note-reaction'; -import { aggregateNoteEmojis, populateEmojis, prefetchEmojis } from '@/misc/populate-emojis'; +import { Note } from '@/models/entities/note.js'; +import { User } from '@/models/entities/user.js'; +import { Users, PollVotes, DriveFiles, NoteReactions, Followings, Polls, Channels } from '../index.js'; +import { Packed } from '@/misc/schema.js'; +import { nyaize } from '@/misc/nyaize.js'; +import { awaitAll } from '@/prelude/await-all.js'; +import { convertLegacyReaction, convertLegacyReactions, decodeReaction } from '@/misc/reaction-lib.js'; +import { NoteReaction } from '@/models/entities/note-reaction.js'; +import { aggregateNoteEmojis, populateEmojis, prefetchEmojis } from '@/misc/populate-emojis.js'; @EntityRepository(Note) export class NoteRepository extends Repository { - public validateCw(x: string) { - return x.trim().length <= 100; - } - public async isVisibleForMe(note: Note, meId: User['id'] | null): Promise { // visibility が specified かつ自分が指定されていなかったら非表示 if (note.visibility === 'specified') { @@ -206,8 +202,8 @@ export class NoteRepository extends Repository { let text = note.text; - if (note.name && (note.url || note.uri)) { - text = `【${note.name}】\n${(note.text || '').trim()}\n\n${note.url || note.uri}`; + if (note.name && (note.url ?? note.uri)) { + text = `【${note.name}】\n${(note.text || '').trim()}\n\n${note.url ?? note.uri}`; } const channel = note.channelId @@ -222,7 +218,7 @@ export class NoteRepository extends Repository { id: note.id, createdAt: note.createdAt.toISOString(), userId: note.userId, - user: Users.pack(note.user || note.userId, me, { + user: Users.pack(note.user ?? note.userId, me, { detail: false, }), text: text, diff --git a/packages/backend/src/models/repositories/notification.ts b/packages/backend/src/models/repositories/notification.ts index 5e4279889..8e72d8aab 100644 --- a/packages/backend/src/models/repositories/notification.ts +++ b/packages/backend/src/models/repositories/notification.ts @@ -1,13 +1,13 @@ import { EntityRepository, In, Repository } from 'typeorm'; -import { Users, Notes, UserGroupInvitations, AccessTokens, NoteReactions } from '../index'; -import { Notification } from '@/models/entities/notification'; -import { awaitAll } from '@/prelude/await-all'; -import { Packed } from '@/misc/schema'; -import { Note } from '@/models/entities/note'; -import { NoteReaction } from '@/models/entities/note-reaction'; -import { User } from '@/models/entities/user'; -import { aggregateNoteEmojis, prefetchEmojis } from '@/misc/populate-emojis'; -import { notificationTypes } from '@/types'; +import { Users, Notes, UserGroupInvitations, AccessTokens, NoteReactions } from '../index.js'; +import { Notification } from '@/models/entities/notification.js'; +import { awaitAll } from '@/prelude/await-all.js'; +import { Packed } from '@/misc/schema.js'; +import { Note } from '@/models/entities/note.js'; +import { NoteReaction } from '@/models/entities/note-reaction.js'; +import { User } from '@/models/entities/user.js'; +import { aggregateNoteEmojis, prefetchEmojis } from '@/misc/populate-emojis.js'; +import { notificationTypes } from '@/types.js'; @EntityRepository(Notification) export class NotificationRepository extends Repository { @@ -67,6 +67,12 @@ export class NotificationRepository extends Repository { }), choice: notification.choice, } : {}), + ...(notification.type === 'pollEnded' ? { + note: Notes.pack(notification.note || notification.noteId!, { id: notification.notifieeId }, { + detail: true, + _hint_: options._hintForEachNotes_, + }), + } : {}), ...(notification.type === 'groupInvited' ? { invitation: UserGroupInvitations.pack(notification.userGroupInvitationId!), } : {}), diff --git a/packages/backend/src/models/repositories/page-like.ts b/packages/backend/src/models/repositories/page-like.ts index 28f34254d..66d780584 100644 --- a/packages/backend/src/models/repositories/page-like.ts +++ b/packages/backend/src/models/repositories/page-like.ts @@ -1,7 +1,7 @@ import { EntityRepository, Repository } from 'typeorm'; -import { PageLike } from '@/models/entities/page-like'; -import { Pages } from '../index'; -import { User } from '@/models/entities/user'; +import { PageLike } from '@/models/entities/page-like.js'; +import { Pages } from '../index.js'; +import { User } from '@/models/entities/user.js'; @EntityRepository(PageLike) export class PageLikeRepository extends Repository { diff --git a/packages/backend/src/models/repositories/page.ts b/packages/backend/src/models/repositories/page.ts index ec76c2e41..037c13c43 100644 --- a/packages/backend/src/models/repositories/page.ts +++ b/packages/backend/src/models/repositories/page.ts @@ -1,10 +1,10 @@ import { EntityRepository, Repository } from 'typeorm'; -import { Page } from '@/models/entities/page'; -import { Packed } from '@/misc/schema'; -import { Users, DriveFiles, PageLikes } from '../index'; -import { awaitAll } from '@/prelude/await-all'; -import { DriveFile } from '@/models/entities/drive-file'; -import { User } from '@/models/entities/user'; +import { Page } from '@/models/entities/page.js'; +import { Packed } from '@/misc/schema.js'; +import { Users, DriveFiles, PageLikes } from '../index.js'; +import { awaitAll } from '@/prelude/await-all.js'; +import { DriveFile } from '@/models/entities/drive-file.js'; +import { User } from '@/models/entities/user.js'; @EntityRepository(Page) export class PageRepository extends Repository { diff --git a/packages/backend/src/models/repositories/relay.ts b/packages/backend/src/models/repositories/relay.ts index 72ead899f..160ca60f7 100644 --- a/packages/backend/src/models/repositories/relay.ts +++ b/packages/backend/src/models/repositories/relay.ts @@ -1,5 +1,5 @@ import { EntityRepository, Repository } from 'typeorm'; -import { Relay } from '@/models/entities/relay'; +import { Relay } from '@/models/entities/relay.js'; @EntityRepository(Relay) export class RelayRepository extends Repository { diff --git a/packages/backend/src/models/repositories/signin.ts b/packages/backend/src/models/repositories/signin.ts index f375f9b5c..a0e2ce152 100644 --- a/packages/backend/src/models/repositories/signin.ts +++ b/packages/backend/src/models/repositories/signin.ts @@ -1,5 +1,5 @@ import { EntityRepository, Repository } from 'typeorm'; -import { Signin } from '@/models/entities/signin'; +import { Signin } from '@/models/entities/signin.js'; @EntityRepository(Signin) export class SigninRepository extends Repository { diff --git a/packages/backend/src/models/repositories/user-group-invitation.ts b/packages/backend/src/models/repositories/user-group-invitation.ts index 638603d6e..e338242c6 100644 --- a/packages/backend/src/models/repositories/user-group-invitation.ts +++ b/packages/backend/src/models/repositories/user-group-invitation.ts @@ -1,6 +1,6 @@ import { EntityRepository, Repository } from 'typeorm'; -import { UserGroupInvitation } from '@/models/entities/user-group-invitation'; -import { UserGroups } from '../index'; +import { UserGroupInvitation } from '@/models/entities/user-group-invitation.js'; +import { UserGroups } from '../index.js'; @EntityRepository(UserGroupInvitation) export class UserGroupInvitationRepository extends Repository { diff --git a/packages/backend/src/models/repositories/user-group.ts b/packages/backend/src/models/repositories/user-group.ts index 3ed37ca0e..a9ffe7369 100644 --- a/packages/backend/src/models/repositories/user-group.ts +++ b/packages/backend/src/models/repositories/user-group.ts @@ -1,7 +1,7 @@ import { EntityRepository, Repository } from 'typeorm'; -import { UserGroup } from '@/models/entities/user-group'; -import { UserGroupJoinings } from '../index'; -import { Packed } from '@/misc/schema'; +import { UserGroup } from '@/models/entities/user-group.js'; +import { UserGroupJoinings } from '../index.js'; +import { Packed } from '@/misc/schema.js'; @EntityRepository(UserGroup) export class UserGroupRepository extends Repository { diff --git a/packages/backend/src/models/repositories/user-list.ts b/packages/backend/src/models/repositories/user-list.ts index a2bffe835..0ea26427f 100644 --- a/packages/backend/src/models/repositories/user-list.ts +++ b/packages/backend/src/models/repositories/user-list.ts @@ -1,7 +1,7 @@ import { EntityRepository, Repository } from 'typeorm'; -import { UserList } from '@/models/entities/user-list'; -import { UserListJoinings } from '../index'; -import { Packed } from '@/misc/schema'; +import { UserList } from '@/models/entities/user-list.js'; +import { UserListJoinings } from '../index.js'; +import { Packed } from '@/misc/schema.js'; @EntityRepository(UserList) export class UserListRepository extends Repository { diff --git a/packages/backend/src/models/repositories/user.ts b/packages/backend/src/models/repositories/user.ts index 33b2b32fe..a909ab3ba 100644 --- a/packages/backend/src/models/repositories/user.ts +++ b/packages/backend/src/models/repositories/user.ts @@ -1,13 +1,13 @@ -import $ from 'cafy'; import { EntityRepository, Repository, In, Not } from 'typeorm'; -import { User, ILocalUser, IRemoteUser } from '@/models/entities/user'; -import { Notes, NoteUnreads, FollowRequests, Notifications, MessagingMessages, UserNotePinings, Followings, Blockings, Mutings, UserProfiles, UserSecurityKeys, UserGroupJoinings, Pages, Announcements, AnnouncementReads, Antennas, AntennaNotes, ChannelFollowings, Instances } from '../index'; -import config from '@/config/index'; -import { Packed } from '@/misc/schema'; -import { awaitAll, Promiseable } from '@/prelude/await-all'; -import { populateEmojis } from '@/misc/populate-emojis'; -import { getAntennas } from '@/misc/antenna-cache'; -import { USER_ACTIVE_THRESHOLD, USER_ONLINE_THRESHOLD } from '@/const'; +import Ajv from 'ajv'; +import { User, ILocalUser, IRemoteUser } from '@/models/entities/user.js'; +import { Notes, NoteUnreads, FollowRequests, Notifications, MessagingMessages, UserNotePinings, Followings, Blockings, Mutings, UserProfiles, UserSecurityKeys, UserGroupJoinings, Pages, Announcements, AnnouncementReads, Antennas, AntennaNotes, ChannelFollowings, Instances, DriveFiles } from '../index.js'; +import config from '@/config/index.js'; +import { Packed } from '@/misc/schema.js'; +import { awaitAll, Promiseable } from '@/prelude/await-all.js'; +import { populateEmojis } from '@/misc/populate-emojis.js'; +import { getAntennas } from '@/misc/antenna-cache.js'; +import { USER_ACTIVE_THRESHOLD, USER_ONLINE_THRESHOLD } from '@/const.js'; type IsUserDetailed = Detailed extends true ? Packed<'UserDetailed'> : Packed<'UserLite'>; type IsMeAndIsUserDetailed = @@ -17,8 +17,26 @@ type IsMeAndIsUserDetailed : Packed<'UserLite'>; +const ajv = new Ajv(); + @EntityRepository(User) export class UserRepository extends Repository { + public localUsernameSchema = { type: 'string', pattern: /^\w{1,20}$/.toString().slice(1, -1) } as const; + public passwordSchema = { type: 'string', minLength: 1 } as const; + public nameSchema = { type: 'string', minLength: 1, maxLength: 50 } as const; + public descriptionSchema = { type: 'string', minLength: 1, maxLength: 500 } as const; + public locationSchema = { type: 'string', minLength: 1, maxLength: 50 } as const; + public birthdaySchema = { type: 'string', pattern: /^([0-9]{4})-([0-9]{2})-([0-9]{2})$/.toString().slice(1, -1) } as const; + + //#region Validators + public validateLocalUsername = ajv.compile(this.localUsernameSchema); + public validatePassword = ajv.compile(this.passwordSchema); + public validateName = ajv.compile(this.nameSchema); + public validateDescription = ajv.compile(this.descriptionSchema); + public validateLocation = ajv.compile(this.locationSchema); + public validateBirthday = ajv.compile(this.birthdaySchema); + //#endregion + public async getRelation(me: User['id'], target: User['id']) { const [following1, following2, followReq1, followReq2, toBlocking, fromBlocked, mute] = await Promise.all([ Followings.findOne({ @@ -164,13 +182,18 @@ export class UserRepository extends Repository { } public getAvatarUrl(user: User): string { - if (user.avatarUrl) { - return user.avatarUrl; + // TODO: avatarIdがあるがavatarがない(JOINされてない)場合のハンドリング + if (user.avatar) { + return DriveFiles.getPublicUrl(user.avatar, true) || this.getIdenticonUrl(user.id); } else { - return `${config.url}/identicon/${user.id}`; + return this.getIdenticonUrl(user.id); } } + public getIdenticonUrl(userId: User['id']): string { + return `${config.url}/identicon/${userId}`; + } + public async pack( src: User['id'] | User, me?: { id: User['id'] } | null | undefined, @@ -184,7 +207,18 @@ export class UserRepository extends Repository { includeSecrets: false, }, options); - const user = typeof src === 'object' ? src : await this.findOneOrFail(src); + let user: User; + + if (typeof src === 'object') { + user = src; + if (src.avatar === undefined && src.avatarId) src.avatar = await DriveFiles.findOne(src.avatarId) ?? null; + if (src.banner === undefined && src.bannerId) src.banner = await DriveFiles.findOne(src.bannerId) ?? null; + } else { + user = await this.findOneOrFail(src, { + relations: ['avatar', 'banner'], + }); + } + const meId = me ? me.id : null; const isMe = meId === user.id; @@ -214,7 +248,7 @@ export class UserRepository extends Repository { username: user.username, host: user.host, avatarUrl: this.getAvatarUrl(user), - avatarBlurhash: user.avatarBlurhash, + avatarBlurhash: user.avatar?.blurhash || null, avatarColor: null, // 後方互換性のため isAdmin: user.isAdmin || falsy, isModerator: user.isModerator || falsy, @@ -238,8 +272,8 @@ export class UserRepository extends Repository { createdAt: user.createdAt.toISOString(), updatedAt: user.updatedAt ? user.updatedAt.toISOString() : null, lastFetchedAt: user.lastFetchedAt ? user.lastFetchedAt.toISOString() : null, - bannerUrl: user.bannerUrl, - bannerBlurhash: user.bannerBlurhash, + bannerUrl: user.banner ? DriveFiles.getPublicUrl(user.banner, false) : null, + bannerBlurhash: user.banner?.blurhash || null, bannerColor: null, // 後方互換性のため isLocked: user.isLocked, isSilenced: user.isSilenced || falsy, @@ -351,13 +385,4 @@ export class UserRepository extends Repository { public isRemoteUser(user: User | { host: User['host'] }): boolean { return !this.isLocalUser(user); } - - //#region Validators - public validateLocalUsername = $.str.match(/^\w{1,20}$/); - public validatePassword = $.str.min(1); - public validateName = $.str.min(1).max(50); - public validateDescription = $.str.min(1).max(500); - public validateLocation = $.str.min(1).max(50); - public validateBirthday = $.str.match(/^([0-9]{4})-([0-9]{2})-([0-9]{2})$/); - //#endregion } diff --git a/packages/backend/src/models/schema/federation-instance.ts b/packages/backend/src/models/schema/federation-instance.ts index eef2f9e24..c4e7b3f18 100644 --- a/packages/backend/src/models/schema/federation-instance.ts +++ b/packages/backend/src/models/schema/federation-instance.ts @@ -1,4 +1,4 @@ -import config from "@/config"; +import config from '@/config/index.js'; export const packedFederationInstanceSchema = { type: 'object', @@ -34,14 +34,6 @@ export const packedFederationInstanceSchema = { type: 'number', optional: false, nullable: false, }, - driveUsage: { - type: 'number', - optional: false, nullable: false, - }, - driveFiles: { - type: 'number', - optional: false, nullable: false, - }, latestRequestSentAt: { type: 'string', optional: false, nullable: true, diff --git a/packages/backend/src/models/schema/muting.ts b/packages/backend/src/models/schema/muting.ts index d75a4fbfe..3ab99e17e 100644 --- a/packages/backend/src/models/schema/muting.ts +++ b/packages/backend/src/models/schema/muting.ts @@ -12,6 +12,11 @@ export const packedMutingSchema = { optional: false, nullable: false, format: 'date-time', }, + expiresAt: { + type: 'string', + optional: false, nullable: true, + format: 'date-time', + }, muteeId: { type: 'string', optional: false, nullable: false, diff --git a/packages/backend/src/models/schema/notification.ts b/packages/backend/src/models/schema/notification.ts index f3c293c48..d3f2405cd 100644 --- a/packages/backend/src/models/schema/notification.ts +++ b/packages/backend/src/models/schema/notification.ts @@ -1,4 +1,4 @@ -import { notificationTypes } from "@/types"; +import { notificationTypes } from '@/types.js'; export const packedNotificationSchema = { type: 'object', diff --git a/packages/backend/src/prelude/array.ts b/packages/backend/src/prelude/array.ts index 1e9e62b89..0b2830cb7 100644 --- a/packages/backend/src/prelude/array.ts +++ b/packages/backend/src/prelude/array.ts @@ -1,4 +1,4 @@ -import { EndoRelation, Predicate } from './relation'; +import { EndoRelation, Predicate } from './relation.js'; /** * Count the number of elements that satisfy the predicate diff --git a/packages/backend/src/queue/get-job-info.ts b/packages/backend/src/queue/get-job-info.ts index f601ae62d..d33e349c3 100644 --- a/packages/backend/src/queue/get-job-info.ts +++ b/packages/backend/src/queue/get-job-info.ts @@ -1,4 +1,4 @@ -import * as Bull from 'bull'; +import Bull from 'bull'; export function getJobInfo(job: Bull.Job, increment = false) { const age = Date.now() - job.timestamp; diff --git a/packages/backend/src/queue/index.ts b/packages/backend/src/queue/index.ts index 62f372f3a..50bcccbb7 100644 --- a/packages/backend/src/queue/index.ts +++ b/packages/backend/src/queue/index.ts @@ -1,19 +1,20 @@ -import * as httpSignature from 'http-signature'; +import httpSignature from 'http-signature'; -import config from '@/config/index'; -import { envOption } from '../env'; +import config from '@/config/index.js'; +import { envOption } from '../env.js'; -import processDeliver from './processors/deliver'; -import processInbox from './processors/inbox'; -import processDb from './processors/db/index'; -import processObjectStorage from './processors/object-storage/index'; -import processSystemQueue from './processors/system/index'; -import { queueLogger } from './logger'; -import { DriveFile } from '@/models/entities/drive-file'; -import { getJobInfo } from './get-job-info'; -import { systemQueue, dbQueue, deliverQueue, inboxQueue, objectStorageQueue } from './queues'; -import { ThinUser } from './types'; -import { IActivity } from '@/remote/activitypub/type'; +import processDeliver from './processors/deliver.js'; +import processInbox from './processors/inbox.js'; +import processDb from './processors/db/index.js'; +import processObjectStorage from './processors/object-storage/index.js'; +import processSystemQueue from './processors/system/index.js'; +import { endedPollNotification } from './processors/ended-poll-notification.js'; +import { queueLogger } from './logger.js'; +import { DriveFile } from '@/models/entities/drive-file.js'; +import { getJobInfo } from './get-job-info.js'; +import { systemQueue, dbQueue, deliverQueue, inboxQueue, objectStorageQueue, endedPollNotificationQueue } from './queues.js'; +import { ThinUser } from './types.js'; +import { IActivity } from '@/remote/activitypub/type.js'; function renderError(e: Error): any { return { @@ -255,6 +256,7 @@ export default function() { deliverQueue.process(config.deliverJobConcurrency || 128, processDeliver); inboxQueue.process(config.inboxJobConcurrency || 16, processInbox); + endedPollNotificationQueue.process(endedPollNotification); processDb(dbQueue); processObjectStorage(objectStorageQueue); @@ -273,6 +275,11 @@ export default function() { repeat: { cron: '0 0 * * *' }, }); + systemQueue.add('checkExpiredMutings', { + }, { + repeat: { cron: '*/5 * * * *' }, + }); + processSystemQueue(systemQueue); } diff --git a/packages/backend/src/queue/initialize.ts b/packages/backend/src/queue/initialize.ts index af9acb3ce..1db118ca9 100644 --- a/packages/backend/src/queue/initialize.ts +++ b/packages/backend/src/queue/initialize.ts @@ -1,5 +1,5 @@ -import * as Bull from 'bull'; -import config from '@/config/index'; +import Bull from 'bull'; +import config from '@/config/index.js'; export function initialize(name: string, limitPerSec = -1) { return new Bull(name, { diff --git a/packages/backend/src/queue/logger.ts b/packages/backend/src/queue/logger.ts index f789b9d07..2843a3c26 100644 --- a/packages/backend/src/queue/logger.ts +++ b/packages/backend/src/queue/logger.ts @@ -1,3 +1,3 @@ -import Logger from '@/services/logger'; +import Logger from '@/services/logger.js'; export const queueLogger = new Logger('queue', 'orange'); diff --git a/packages/backend/src/queue/processors/db/delete-account.ts b/packages/backend/src/queue/processors/db/delete-account.ts index 4b620842a..dbc1f16a4 100644 --- a/packages/backend/src/queue/processors/db/delete-account.ts +++ b/packages/backend/src/queue/processors/db/delete-account.ts @@ -1,12 +1,12 @@ -import * as Bull from 'bull'; -import { queueLogger } from '../../logger'; -import { DriveFiles, Notes, UserProfiles, Users } from '@/models/index'; -import { DbUserDeleteJobData } from '@/queue/types'; -import { Note } from '@/models/entities/note'; -import { DriveFile } from '@/models/entities/drive-file'; +import Bull from 'bull'; +import { queueLogger } from '../../logger.js'; +import { DriveFiles, Notes, UserProfiles, Users } from '@/models/index.js'; +import { DbUserDeleteJobData } from '@/queue/types.js'; +import { Note } from '@/models/entities/note.js'; +import { DriveFile } from '@/models/entities/drive-file.js'; import { MoreThan } from 'typeorm'; -import { deleteFileSync } from '@/services/drive/delete-file'; -import { sendEmail } from '@/services/send-email'; +import { deleteFileSync } from '@/services/drive/delete-file.js'; +import { sendEmail } from '@/services/send-email.js'; const logger = queueLogger.createSubLogger('delete-account'); @@ -31,7 +31,7 @@ export async function deleteAccount(job: Bull.Job): Promise order: { id: 1, }, - }); + }) as Note[]; if (notes.length === 0) { break; @@ -58,7 +58,7 @@ export async function deleteAccount(job: Bull.Job): Promise order: { id: 1, }, - }); + }) as DriveFile[]; if (files.length === 0) { break; diff --git a/packages/backend/src/queue/processors/db/delete-drive-files.ts b/packages/backend/src/queue/processors/db/delete-drive-files.ts index d26f5a47c..f6a869985 100644 --- a/packages/backend/src/queue/processors/db/delete-drive-files.ts +++ b/packages/backend/src/queue/processors/db/delete-drive-files.ts @@ -1,10 +1,10 @@ -import * as Bull from 'bull'; +import Bull from 'bull'; -import { queueLogger } from '../../logger'; -import { deleteFileSync } from '@/services/drive/delete-file'; -import { Users, DriveFiles } from '@/models/index'; +import { queueLogger } from '../../logger.js'; +import { deleteFileSync } from '@/services/drive/delete-file.js'; +import { Users, DriveFiles } from '@/models/index.js'; import { MoreThan } from 'typeorm'; -import { DbUserJobData } from '@/queue/types'; +import { DbUserJobData } from '@/queue/types.js'; const logger = queueLogger.createSubLogger('delete-drive-files'); diff --git a/packages/backend/src/queue/processors/db/export-blocking.ts b/packages/backend/src/queue/processors/db/export-blocking.ts index f4de9ce00..83f1ec8fd 100644 --- a/packages/backend/src/queue/processors/db/export-blocking.ts +++ b/packages/backend/src/queue/processors/db/export-blocking.ts @@ -1,14 +1,14 @@ -import * as Bull from 'bull'; +import Bull from 'bull'; import * as tmp from 'tmp'; -import * as fs from 'fs'; +import * as fs from 'node:fs'; -import { queueLogger } from '../../logger'; -import { addFile } from '@/services/drive/add-file'; +import { queueLogger } from '../../logger.js'; +import { addFile } from '@/services/drive/add-file.js'; import { format as dateFormat } from 'date-fns'; -import { getFullApAccount } from '@/misc/convert-host'; -import { Users, Blockings } from '@/models/index'; +import { getFullApAccount } from '@/misc/convert-host.js'; +import { Users, Blockings } from '@/models/index.js'; import { MoreThan } from 'typeorm'; -import { DbUserJobData } from '@/queue/types'; +import { DbUserJobData } from '@/queue/types.js'; const logger = queueLogger.createSubLogger('export-blocking'); diff --git a/packages/backend/src/queue/processors/db/export-custom-emojis.ts b/packages/backend/src/queue/processors/db/export-custom-emojis.ts index 2f7505f15..a65b46cc0 100644 --- a/packages/backend/src/queue/processors/db/export-custom-emojis.ts +++ b/packages/backend/src/queue/processors/db/export-custom-emojis.ts @@ -1,17 +1,17 @@ -import * as Bull from 'bull'; +import Bull from 'bull'; import * as tmp from 'tmp'; -import * as fs from 'fs'; +import * as fs from 'node:fs'; import { ulid } from 'ulid'; -const mime = require('mime-types'); -const archiver = require('archiver'); -import { queueLogger } from '../../logger'; -import { addFile } from '@/services/drive/add-file'; +import mime from 'mime-types'; +import archiver from 'archiver'; +import { queueLogger } from '../../logger.js'; +import { addFile } from '@/services/drive/add-file.js'; import { format as dateFormat } from 'date-fns'; -import { Users, Emojis } from '@/models/index'; -import { } from '@/queue/types'; -import { downloadUrl } from '@/misc/download-url'; -import config from '@/config/index'; +import { Users, Emojis } from '@/models/index.js'; +import { } from '@/queue/types.js'; +import { downloadUrl } from '@/misc/download-url.js'; +import config from '@/config/index.js'; const logger = queueLogger.createSubLogger('export-custom-emojis'); @@ -75,7 +75,7 @@ export async function exportCustomEmojis(job: Bull.Job, done: () => void): Promi await downloadUrl(emoji.originalUrl, emojiPath); downloaded = true; } catch (e) { // TODO: 何度か再試行 - logger.error(e); + logger.error(e instanceof Error ? e : new Error(e as string)); } if (!downloaded) { diff --git a/packages/backend/src/queue/processors/db/export-following.ts b/packages/backend/src/queue/processors/db/export-following.ts index 2ac558381..162862180 100644 --- a/packages/backend/src/queue/processors/db/export-following.ts +++ b/packages/backend/src/queue/processors/db/export-following.ts @@ -1,15 +1,15 @@ -import * as Bull from 'bull'; +import Bull from 'bull'; import * as tmp from 'tmp'; -import * as fs from 'fs'; +import * as fs from 'node:fs'; -import { queueLogger } from '../../logger'; -import { addFile } from '@/services/drive/add-file'; +import { queueLogger } from '../../logger.js'; +import { addFile } from '@/services/drive/add-file.js'; import { format as dateFormat } from 'date-fns'; -import { getFullApAccount } from '@/misc/convert-host'; -import { Users, Followings, Mutings } from '@/models/index'; +import { getFullApAccount } from '@/misc/convert-host.js'; +import { Users, Followings, Mutings } from '@/models/index.js'; import { In, MoreThan, Not } from 'typeorm'; -import { DbUserJobData } from '@/queue/types'; -import { Following } from '@/models/entities/following'; +import { DbUserJobData } from '@/queue/types.js'; +import { Following } from '@/models/entities/following.js'; const logger = queueLogger.createSubLogger('export-following'); @@ -51,7 +51,7 @@ export async function exportFollowing(job: Bull.Job, done: () => order: { id: 1, }, - }); + }) as Following[]; if (followings.length === 0) { break; diff --git a/packages/backend/src/queue/processors/db/export-mute.ts b/packages/backend/src/queue/processors/db/export-mute.ts index 9e917ccbf..9fb144abb 100644 --- a/packages/backend/src/queue/processors/db/export-mute.ts +++ b/packages/backend/src/queue/processors/db/export-mute.ts @@ -1,14 +1,14 @@ -import * as Bull from 'bull'; +import Bull from 'bull'; import * as tmp from 'tmp'; -import * as fs from 'fs'; +import * as fs from 'node:fs'; -import { queueLogger } from '../../logger'; -import { addFile } from '@/services/drive/add-file'; +import { queueLogger } from '../../logger.js'; +import { addFile } from '@/services/drive/add-file.js'; import { format as dateFormat } from 'date-fns'; -import { getFullApAccount } from '@/misc/convert-host'; -import { Users, Mutings } from '@/models/index'; -import { MoreThan } from 'typeorm'; -import { DbUserJobData } from '@/queue/types'; +import { getFullApAccount } from '@/misc/convert-host.js'; +import { Users, Mutings } from '@/models/index.js'; +import { IsNull, MoreThan } from 'typeorm'; +import { DbUserJobData } from '@/queue/types.js'; const logger = queueLogger.createSubLogger('export-mute'); @@ -40,6 +40,7 @@ export async function exportMute(job: Bull.Job, done: any): Promi const mutes = await Mutings.find({ where: { muterId: user.id, + expiresAt: IsNull(), ...(cursor ? { id: MoreThan(cursor) } : {}), }, take: 100, diff --git a/packages/backend/src/queue/processors/db/export-notes.ts b/packages/backend/src/queue/processors/db/export-notes.ts index 0e65cb884..c79679366 100644 --- a/packages/backend/src/queue/processors/db/export-notes.ts +++ b/packages/backend/src/queue/processors/db/export-notes.ts @@ -1,15 +1,15 @@ -import * as Bull from 'bull'; +import Bull from 'bull'; import * as tmp from 'tmp'; -import * as fs from 'fs'; +import * as fs from 'node:fs'; -import { queueLogger } from '../../logger'; -import { addFile } from '@/services/drive/add-file'; +import { queueLogger } from '../../logger.js'; +import { addFile } from '@/services/drive/add-file.js'; import { format as dateFormat } from 'date-fns'; -import { Users, Notes, Polls } from '@/models/index'; +import { Users, Notes, Polls } from '@/models/index.js'; import { MoreThan } from 'typeorm'; -import { Note } from '@/models/entities/note'; -import { Poll } from '@/models/entities/poll'; -import { DbUserJobData } from '@/queue/types'; +import { Note } from '@/models/entities/note.js'; +import { Poll } from '@/models/entities/poll.js'; +import { DbUserJobData } from '@/queue/types.js'; const logger = queueLogger.createSubLogger('export-notes'); @@ -62,7 +62,7 @@ export async function exportNotes(job: Bull.Job, done: any): Prom order: { id: 1, }, - }); + }) as Note[]; if (notes.length === 0) { job.progress(100); diff --git a/packages/backend/src/queue/processors/db/export-user-lists.ts b/packages/backend/src/queue/processors/db/export-user-lists.ts index fcd2ba336..1c04c3678 100644 --- a/packages/backend/src/queue/processors/db/export-user-lists.ts +++ b/packages/backend/src/queue/processors/db/export-user-lists.ts @@ -1,14 +1,14 @@ -import * as Bull from 'bull'; +import Bull from 'bull'; import * as tmp from 'tmp'; -import * as fs from 'fs'; +import * as fs from 'node:fs'; -import { queueLogger } from '../../logger'; -import { addFile } from '@/services/drive/add-file'; +import { queueLogger } from '../../logger.js'; +import { addFile } from '@/services/drive/add-file.js'; import { format as dateFormat } from 'date-fns'; -import { getFullApAccount } from '@/misc/convert-host'; -import { Users, UserLists, UserListJoinings } from '@/models/index'; +import { getFullApAccount } from '@/misc/convert-host.js'; +import { Users, UserLists, UserListJoinings } from '@/models/index.js'; import { In } from 'typeorm'; -import { DbUserJobData } from '@/queue/types'; +import { DbUserJobData } from '@/queue/types.js'; const logger = queueLogger.createSubLogger('export-user-lists'); diff --git a/packages/backend/src/queue/processors/db/import-blocking.ts b/packages/backend/src/queue/processors/db/import-blocking.ts index 42c3cd0a4..857c2629e 100644 --- a/packages/backend/src/queue/processors/db/import-blocking.ts +++ b/packages/backend/src/queue/processors/db/import-blocking.ts @@ -1,13 +1,13 @@ -import * as Bull from 'bull'; +import Bull from 'bull'; -import { queueLogger } from '../../logger'; -import * as Acct from 'misskey-js/built/acct'; -import { resolveUser } from '@/remote/resolve-user'; -import { downloadTextFile } from '@/misc/download-text-file'; -import { isSelfHost, toPuny } from '@/misc/convert-host'; -import { Users, DriveFiles, Blockings } from '@/models/index'; -import { DbUserImportJobData } from '@/queue/types'; -import block from '@/services/blocking/create'; +import { queueLogger } from '../../logger.js'; +import * as Acct from '@/misc/acct.js'; +import { resolveUser } from '@/remote/resolve-user.js'; +import { downloadTextFile } from '@/misc/download-text-file.js'; +import { isSelfHost, toPuny } from '@/misc/convert-host.js'; +import { Users, DriveFiles, Blockings } from '@/models/index.js'; +import { DbUserImportJobData } from '@/queue/types.js'; +import block from '@/services/blocking/create.js'; const logger = queueLogger.createSubLogger('import-blocking'); diff --git a/packages/backend/src/queue/processors/db/import-custom-emojis.ts b/packages/backend/src/queue/processors/db/import-custom-emojis.ts index b6c012653..f862276b4 100644 --- a/packages/backend/src/queue/processors/db/import-custom-emojis.ts +++ b/packages/backend/src/queue/processors/db/import-custom-emojis.ts @@ -1,15 +1,15 @@ -import * as Bull from 'bull'; +import Bull from 'bull'; import * as tmp from 'tmp'; -import * as fs from 'fs'; -const unzipper = require('unzipper'); +import * as fs from 'node:fs'; +import unzipper from 'unzipper'; import { getConnection } from 'typeorm'; -import { queueLogger } from '../../logger'; -import { downloadUrl } from '@/misc/download-url'; -import { DriveFiles, Emojis } from '@/models/index'; -import { DbUserImportJobData } from '@/queue/types'; -import { addFile } from '@/services/drive/add-file'; -import { genId } from '@/misc/gen-id'; +import { queueLogger } from '../../logger.js'; +import { downloadUrl } from '@/misc/download-url.js'; +import { DriveFiles, Emojis } from '@/models/index.js'; +import { DbUserImportJobData } from '@/queue/types.js'; +import { addFile } from '@/services/drive/add-file.js'; +import { genId } from '@/misc/gen-id.js'; const logger = queueLogger.createSubLogger('import-custom-emojis'); diff --git a/packages/backend/src/queue/processors/db/import-following.ts b/packages/backend/src/queue/processors/db/import-following.ts index f19296832..235fc2839 100644 --- a/packages/backend/src/queue/processors/db/import-following.ts +++ b/packages/backend/src/queue/processors/db/import-following.ts @@ -1,13 +1,13 @@ -import * as Bull from 'bull'; +import Bull from 'bull'; -import { queueLogger } from '../../logger'; -import follow from '@/services/following/create'; -import * as Acct from 'misskey-js/built/acct'; -import { resolveUser } from '@/remote/resolve-user'; -import { downloadTextFile } from '@/misc/download-text-file'; -import { isSelfHost, toPuny } from '@/misc/convert-host'; -import { Users, DriveFiles } from '@/models/index'; -import { DbUserImportJobData } from '@/queue/types'; +import { queueLogger } from '../../logger.js'; +import follow from '@/services/following/create.js'; +import * as Acct from '@/misc/acct.js'; +import { resolveUser } from '@/remote/resolve-user.js'; +import { downloadTextFile } from '@/misc/download-text-file.js'; +import { isSelfHost, toPuny } from '@/misc/convert-host.js'; +import { Users, DriveFiles } from '@/models/index.js'; +import { DbUserImportJobData } from '@/queue/types.js'; const logger = queueLogger.createSubLogger('import-following'); diff --git a/packages/backend/src/queue/processors/db/import-muting.ts b/packages/backend/src/queue/processors/db/import-muting.ts index 189740c29..32f5f6bbe 100644 --- a/packages/backend/src/queue/processors/db/import-muting.ts +++ b/packages/backend/src/queue/processors/db/import-muting.ts @@ -1,14 +1,14 @@ -import * as Bull from 'bull'; +import Bull from 'bull'; -import { queueLogger } from '../../logger'; -import * as Acct from 'misskey-js/built/acct'; -import { resolveUser } from '@/remote/resolve-user'; -import { downloadTextFile } from '@/misc/download-text-file'; -import { isSelfHost, toPuny } from '@/misc/convert-host'; -import { Users, DriveFiles, Mutings } from '@/models/index'; -import { DbUserImportJobData } from '@/queue/types'; -import { User } from '@/models/entities/user'; -import { genId } from '@/misc/gen-id'; +import { queueLogger } from '../../logger.js'; +import * as Acct from '@/misc/acct.js'; +import { resolveUser } from '@/remote/resolve-user.js'; +import { downloadTextFile } from '@/misc/download-text-file.js'; +import { isSelfHost, toPuny } from '@/misc/convert-host.js'; +import { Users, DriveFiles, Mutings } from '@/models/index.js'; +import { DbUserImportJobData } from '@/queue/types.js'; +import { User } from '@/models/entities/user.js'; +import { genId } from '@/misc/gen-id.js'; const logger = queueLogger.createSubLogger('import-muting'); diff --git a/packages/backend/src/queue/processors/db/import-user-lists.ts b/packages/backend/src/queue/processors/db/import-user-lists.ts index 9b3c0ed60..ae263e19b 100644 --- a/packages/backend/src/queue/processors/db/import-user-lists.ts +++ b/packages/backend/src/queue/processors/db/import-user-lists.ts @@ -1,14 +1,14 @@ -import * as Bull from 'bull'; +import Bull from 'bull'; -import { queueLogger } from '../../logger'; -import * as Acct from 'misskey-js/built/acct'; -import { resolveUser } from '@/remote/resolve-user'; -import { pushUserToUserList } from '@/services/user-list/push'; -import { downloadTextFile } from '@/misc/download-text-file'; -import { isSelfHost, toPuny } from '@/misc/convert-host'; -import { DriveFiles, Users, UserLists, UserListJoinings } from '@/models/index'; -import { genId } from '@/misc/gen-id'; -import { DbUserImportJobData } from '@/queue/types'; +import { queueLogger } from '../../logger.js'; +import * as Acct from '@/misc/acct.js'; +import { resolveUser } from '@/remote/resolve-user.js'; +import { pushUserToUserList } from '@/services/user-list/push.js'; +import { downloadTextFile } from '@/misc/download-text-file.js'; +import { isSelfHost, toPuny } from '@/misc/convert-host.js'; +import { DriveFiles, Users, UserLists, UserListJoinings } from '@/models/index.js'; +import { genId } from '@/misc/gen-id.js'; +import { DbUserImportJobData } from '@/queue/types.js'; const logger = queueLogger.createSubLogger('import-user-lists'); diff --git a/packages/backend/src/queue/processors/db/index.ts b/packages/backend/src/queue/processors/db/index.ts index 5fffa378f..e91d56977 100644 --- a/packages/backend/src/queue/processors/db/index.ts +++ b/packages/backend/src/queue/processors/db/index.ts @@ -1,18 +1,18 @@ -import * as Bull from 'bull'; -import { DbJobData } from '@/queue/types'; -import { deleteDriveFiles } from './delete-drive-files'; -import { exportCustomEmojis } from './export-custom-emojis'; -import { exportNotes } from './export-notes'; -import { exportFollowing } from './export-following'; -import { exportMute } from './export-mute'; -import { exportBlocking } from './export-blocking'; -import { exportUserLists } from './export-user-lists'; -import { importFollowing } from './import-following'; -import { importUserLists } from './import-user-lists'; -import { deleteAccount } from './delete-account'; -import { importMuting } from './import-muting'; -import { importBlocking } from './import-blocking'; -import { importCustomEmojis } from './import-custom-emojis'; +import Bull from 'bull'; +import { DbJobData } from '@/queue/types.js'; +import { deleteDriveFiles } from './delete-drive-files.js'; +import { exportCustomEmojis } from './export-custom-emojis.js'; +import { exportNotes } from './export-notes.js'; +import { exportFollowing } from './export-following.js'; +import { exportMute } from './export-mute.js'; +import { exportBlocking } from './export-blocking.js'; +import { exportUserLists } from './export-user-lists.js'; +import { importFollowing } from './import-following.js'; +import { importUserLists } from './import-user-lists.js'; +import { deleteAccount } from './delete-account.js'; +import { importMuting } from './import-muting.js'; +import { importBlocking } from './import-blocking.js'; +import { importCustomEmojis } from './import-custom-emojis.js'; const jobs = { deleteDriveFiles, diff --git a/packages/backend/src/queue/processors/deliver.ts b/packages/backend/src/queue/processors/deliver.ts index bd91dfc3b..291c05766 100644 --- a/packages/backend/src/queue/processors/deliver.ts +++ b/packages/backend/src/queue/processors/deliver.ts @@ -1,17 +1,17 @@ -import { URL } from 'url'; -import * as Bull from 'bull'; -import request from '@/remote/activitypub/request'; -import { registerOrFetchInstanceDoc } from '@/services/register-or-fetch-instance-doc'; -import Logger from '@/services/logger'; -import { Instances } from '@/models/index'; -import { apRequestChart, federationChart, instanceChart } from '@/services/chart/index'; -import { fetchInstanceMetadata } from '@/services/fetch-instance-metadata'; -import { fetchMeta } from '@/misc/fetch-meta'; -import { toPuny } from '@/misc/convert-host'; -import { Cache } from '@/misc/cache'; -import { Instance } from '@/models/entities/instance'; -import { DeliverJobData } from '../types'; -import { StatusError } from '@/misc/fetch'; +import { URL } from 'node:url'; +import Bull from 'bull'; +import request from '@/remote/activitypub/request.js'; +import { registerOrFetchInstanceDoc } from '@/services/register-or-fetch-instance-doc.js'; +import Logger from '@/services/logger.js'; +import { Instances } from '@/models/index.js'; +import { apRequestChart, federationChart, instanceChart } from '@/services/chart/index.js'; +import { fetchInstanceMetadata } from '@/services/fetch-instance-metadata.js'; +import { fetchMeta } from '@/misc/fetch-meta.js'; +import { toPuny } from '@/misc/convert-host.js'; +import { Cache } from '@/misc/cache.js'; +import { Instance } from '@/models/entities/instance.js'; +import { DeliverJobData } from '../types.js'; +import { StatusError } from '@/misc/fetch.js'; const logger = new Logger('deliver'); diff --git a/packages/backend/src/queue/processors/ended-poll-notification.ts b/packages/backend/src/queue/processors/ended-poll-notification.ts new file mode 100644 index 000000000..afac27921 --- /dev/null +++ b/packages/backend/src/queue/processors/ended-poll-notification.ts @@ -0,0 +1,33 @@ +import Bull from 'bull'; +import { In } from 'typeorm'; +import { Notes, Polls, PollVotes } from '@/models/index.js'; +import { queueLogger } from '../logger.js'; +import { EndedPollNotificationJobData } from '@/queue/types.js'; +import { createNotification } from '@/services/create-notification.js'; + +const logger = queueLogger.createSubLogger('ended-poll-notification'); + +export async function endedPollNotification(job: Bull.Job, done: any): Promise { + const note = await Notes.findOne(job.data.noteId); + if (note == null || !note.hasPoll) { + done(); + return; + } + + const votes = await PollVotes.createQueryBuilder('vote') + .select('vote.userId') + .where('vote.noteId = :noteId', { noteId: note.id }) + .innerJoinAndSelect('vote.user', 'user') + .andWhere('user.host IS NULL') + .getMany(); + + const userIds = [...new Set([note.userId, ...votes.map(v => v.userId)])]; + + for (const userId of userIds) { + createNotification(userId, 'pollEnded', { + noteId: note.id, + }); + } + + done(); +} diff --git a/packages/backend/src/queue/processors/inbox.ts b/packages/backend/src/queue/processors/inbox.ts index c189256c3..1b3f94b70 100644 --- a/packages/backend/src/queue/processors/inbox.ts +++ b/packages/backend/src/queue/processors/inbox.ts @@ -1,20 +1,20 @@ -import { URL } from 'url'; -import * as Bull from 'bull'; -import * as httpSignature from 'http-signature'; -import perform from '@/remote/activitypub/perform'; -import Logger from '@/services/logger'; -import { registerOrFetchInstanceDoc } from '@/services/register-or-fetch-instance-doc'; -import { Instances } from '@/models/index'; -import { apRequestChart, federationChart, instanceChart } from '@/services/chart/index'; -import { fetchMeta } from '@/misc/fetch-meta'; -import { toPuny, extractDbHost } from '@/misc/convert-host'; -import { getApId } from '@/remote/activitypub/type'; -import { fetchInstanceMetadata } from '@/services/fetch-instance-metadata'; -import { InboxJobData } from '../types'; -import DbResolver from '@/remote/activitypub/db-resolver'; -import { resolvePerson } from '@/remote/activitypub/models/person'; -import { LdSignature } from '@/remote/activitypub/misc/ld-signature'; -import { StatusError } from '@/misc/fetch'; +import { URL } from 'node:url'; +import Bull from 'bull'; +import httpSignature from 'http-signature'; +import perform from '@/remote/activitypub/perform.js'; +import Logger from '@/services/logger.js'; +import { registerOrFetchInstanceDoc } from '@/services/register-or-fetch-instance-doc.js'; +import { Instances } from '@/models/index.js'; +import { apRequestChart, federationChart, instanceChart } from '@/services/chart/index.js'; +import { fetchMeta } from '@/misc/fetch-meta.js'; +import { toPuny, extractDbHost } from '@/misc/convert-host.js'; +import { getApId } from '@/remote/activitypub/type.js'; +import { fetchInstanceMetadata } from '@/services/fetch-instance-metadata.js'; +import { InboxJobData } from '../types.js'; +import DbResolver from '@/remote/activitypub/db-resolver.js'; +import { resolvePerson } from '@/remote/activitypub/models/person.js'; +import { LdSignature } from '@/remote/activitypub/misc/ld-signature.js'; +import { StatusError } from '@/misc/fetch.js'; const logger = new Logger('inbox'); diff --git a/packages/backend/src/queue/processors/object-storage/clean-remote-files.ts b/packages/backend/src/queue/processors/object-storage/clean-remote-files.ts index 788383a0a..7d71a20ad 100644 --- a/packages/backend/src/queue/processors/object-storage/clean-remote-files.ts +++ b/packages/backend/src/queue/processors/object-storage/clean-remote-files.ts @@ -1,8 +1,8 @@ -import * as Bull from 'bull'; +import Bull from 'bull'; -import { queueLogger } from '../../logger'; -import { deleteFileSync } from '@/services/drive/delete-file'; -import { DriveFiles } from '@/models/index'; +import { queueLogger } from '../../logger.js'; +import { deleteFileSync } from '@/services/drive/delete-file.js'; +import { DriveFiles } from '@/models/index.js'; import { MoreThan, Not, IsNull } from 'typeorm'; const logger = queueLogger.createSubLogger('clean-remote-files'); diff --git a/packages/backend/src/queue/processors/object-storage/delete-file.ts b/packages/backend/src/queue/processors/object-storage/delete-file.ts index ed22968a2..c271e3ddd 100644 --- a/packages/backend/src/queue/processors/object-storage/delete-file.ts +++ b/packages/backend/src/queue/processors/object-storage/delete-file.ts @@ -1,6 +1,6 @@ -import { ObjectStorageFileJobData } from '@/queue/types'; -import * as Bull from 'bull'; -import { deleteObjectStorageFile } from '@/services/drive/delete-file'; +import { ObjectStorageFileJobData } from '@/queue/types.js'; +import Bull from 'bull'; +import { deleteObjectStorageFile } from '@/services/drive/delete-file.js'; export default async (job: Bull.Job) => { const key: string = job.data.key; diff --git a/packages/backend/src/queue/processors/object-storage/index.ts b/packages/backend/src/queue/processors/object-storage/index.ts index 0d9570e17..ae6c481fe 100644 --- a/packages/backend/src/queue/processors/object-storage/index.ts +++ b/packages/backend/src/queue/processors/object-storage/index.ts @@ -1,7 +1,7 @@ -import * as Bull from 'bull'; -import { ObjectStorageJobData } from '@/queue/types'; -import deleteFile from './delete-file'; -import cleanRemoteFiles from './clean-remote-files'; +import Bull from 'bull'; +import { ObjectStorageJobData } from '@/queue/types.js'; +import deleteFile from './delete-file.js'; +import cleanRemoteFiles from './clean-remote-files.js'; const jobs = { deleteFile, diff --git a/packages/backend/src/queue/processors/system/check-expired-mutings.ts b/packages/backend/src/queue/processors/system/check-expired-mutings.ts new file mode 100644 index 000000000..621269e7e --- /dev/null +++ b/packages/backend/src/queue/processors/system/check-expired-mutings.ts @@ -0,0 +1,30 @@ +import Bull from 'bull'; +import { In } from 'typeorm'; +import { Mutings } from '@/models/index.js'; +import { queueLogger } from '../../logger.js'; +import { publishUserEvent } from '@/services/stream.js'; + +const logger = queueLogger.createSubLogger('check-expired-mutings'); + +export async function checkExpiredMutings(job: Bull.Job>, done: any): Promise { + logger.info(`Checking expired mutings...`); + + const expired = await Mutings.createQueryBuilder('muting') + .where('muting.expiresAt IS NOT NULL') + .andWhere('muting.expiresAt < :now', { now: new Date() }) + .innerJoinAndSelect('muting.mutee', 'mutee') + .getMany(); + + if (expired.length > 0) { + await Mutings.delete({ + id: In(expired.map(m => m.id)), + }); + + for (const m of expired) { + publishUserEvent(m.muterId, 'unmute', m.mutee!); + } + } + + logger.succ(`All expired mutings checked.`); + done(); +} diff --git a/packages/backend/src/queue/processors/system/clean-charts.ts b/packages/backend/src/queue/processors/system/clean-charts.ts index 3ae0f495f..c9169d5ac 100644 --- a/packages/backend/src/queue/processors/system/clean-charts.ts +++ b/packages/backend/src/queue/processors/system/clean-charts.ts @@ -1,7 +1,7 @@ -import * as Bull from 'bull'; +import Bull from 'bull'; -import { queueLogger } from '../../logger'; -import { activeUsersChart, driveChart, federationChart, hashtagChart, instanceChart, notesChart, perUserDriveChart, perUserFollowingChart, perUserNotesChart, perUserReactionsChart, usersChart, apRequestChart } from '@/services/chart/index'; +import { queueLogger } from '../../logger.js'; +import { activeUsersChart, driveChart, federationChart, hashtagChart, instanceChart, notesChart, perUserDriveChart, perUserFollowingChart, perUserNotesChart, perUserReactionsChart, usersChart, apRequestChart } from '@/services/chart/index.js'; const logger = queueLogger.createSubLogger('clean-charts'); diff --git a/packages/backend/src/queue/processors/system/index.ts b/packages/backend/src/queue/processors/system/index.ts index 1513ea4a8..f90f6efaf 100644 --- a/packages/backend/src/queue/processors/system/index.ts +++ b/packages/backend/src/queue/processors/system/index.ts @@ -1,12 +1,14 @@ -import * as Bull from 'bull'; -import { tickCharts } from './tick-charts'; -import { resyncCharts } from './resync-charts'; -import { cleanCharts } from './clean-charts'; +import Bull from 'bull'; +import { tickCharts } from './tick-charts.js'; +import { resyncCharts } from './resync-charts.js'; +import { cleanCharts } from './clean-charts.js'; +import { checkExpiredMutings } from './check-expired-mutings.js'; const jobs = { tickCharts, resyncCharts, cleanCharts, + checkExpiredMutings, } as Record> | Bull.ProcessPromiseFunction>>; export default function(dbQueue: Bull.Queue>) { diff --git a/packages/backend/src/queue/processors/system/resync-charts.ts b/packages/backend/src/queue/processors/system/resync-charts.ts index 78a70bb98..20012513a 100644 --- a/packages/backend/src/queue/processors/system/resync-charts.ts +++ b/packages/backend/src/queue/processors/system/resync-charts.ts @@ -1,7 +1,7 @@ -import * as Bull from 'bull'; +import Bull from 'bull'; -import { queueLogger } from '../../logger'; -import { driveChart, notesChart, usersChart } from '@/services/chart/index'; +import { queueLogger } from '../../logger.js'; +import { driveChart, notesChart, usersChart } from '@/services/chart/index.js'; const logger = queueLogger.createSubLogger('resync-charts'); diff --git a/packages/backend/src/queue/processors/system/tick-charts.ts b/packages/backend/src/queue/processors/system/tick-charts.ts index d53089f89..13403f8f7 100644 --- a/packages/backend/src/queue/processors/system/tick-charts.ts +++ b/packages/backend/src/queue/processors/system/tick-charts.ts @@ -1,7 +1,7 @@ -import * as Bull from 'bull'; +import Bull from 'bull'; -import { queueLogger } from '../../logger'; -import { activeUsersChart, driveChart, federationChart, hashtagChart, instanceChart, notesChart, perUserDriveChart, perUserFollowingChart, perUserNotesChart, perUserReactionsChart, usersChart, apRequestChart } from '@/services/chart/index'; +import { queueLogger } from '../../logger.js'; +import { activeUsersChart, driveChart, federationChart, hashtagChart, instanceChart, notesChart, perUserDriveChart, perUserFollowingChart, perUserNotesChart, perUserReactionsChart, usersChart, apRequestChart } from '@/services/chart/index.js'; const logger = queueLogger.createSubLogger('tick-charts'); diff --git a/packages/backend/src/queue/queues.ts b/packages/backend/src/queue/queues.ts index b1d790fcb..02df58736 100644 --- a/packages/backend/src/queue/queues.ts +++ b/packages/backend/src/queue/queues.ts @@ -1,8 +1,9 @@ -import config from '@/config/index'; -import { initialize as initializeQueue } from './initialize'; -import { DeliverJobData, InboxJobData, DbJobData, ObjectStorageJobData } from './types'; +import config from '@/config/index.js'; +import { initialize as initializeQueue } from './initialize.js'; +import { DeliverJobData, InboxJobData, DbJobData, ObjectStorageJobData, EndedPollNotificationJobData } from './types.js'; export const systemQueue = initializeQueue>('system'); +export const endedPollNotificationQueue = initializeQueue('endedPollNotification'); export const deliverQueue = initializeQueue('deliver', config.deliverJobPerSec || 128); export const inboxQueue = initializeQueue('inbox', config.inboxJobPerSec || 16); export const dbQueue = initializeQueue('db'); diff --git a/packages/backend/src/queue/types.ts b/packages/backend/src/queue/types.ts index 91036177d..5191caea4 100644 --- a/packages/backend/src/queue/types.ts +++ b/packages/backend/src/queue/types.ts @@ -1,7 +1,8 @@ -import { DriveFile } from '@/models/entities/drive-file'; -import { User } from '@/models/entities/user'; -import { IActivity } from '@/remote/activitypub/type'; -import * as httpSignature from 'http-signature'; +import { DriveFile } from '@/models/entities/drive-file.js'; +import { Note } from '@/models/entities/note'; +import { User } from '@/models/entities/user.js'; +import { IActivity } from '@/remote/activitypub/type.js'; +import httpSignature from 'http-signature'; export type DeliverJobData = { /** Actor */ @@ -41,6 +42,10 @@ export type ObjectStorageFileJobData = { key: string; }; +export type EndedPollNotificationJobData = { + noteId: Note['id']; +}; + export type ThinUser = { id: User['id']; }; diff --git a/packages/backend/src/remote/activitypub/ap-request.ts b/packages/backend/src/remote/activitypub/ap-request.ts index c75f44f2e..96bfec3b1 100644 --- a/packages/backend/src/remote/activitypub/ap-request.ts +++ b/packages/backend/src/remote/activitypub/ap-request.ts @@ -1,5 +1,5 @@ -import * as crypto from 'crypto'; -import { URL } from 'url'; +import * as crypto from 'node:crypto'; +import { URL } from 'node:url'; type Request = { url: string; diff --git a/packages/backend/src/remote/activitypub/audience.ts b/packages/backend/src/remote/activitypub/audience.ts index e82ed94a6..ba69b11e8 100644 --- a/packages/backend/src/remote/activitypub/audience.ts +++ b/packages/backend/src/remote/activitypub/audience.ts @@ -1,9 +1,9 @@ -import { ApObject, getApIds } from './type'; -import Resolver from './resolver'; -import { resolvePerson } from './models/person'; -import { unique, concat } from '@/prelude/array'; -import * as promiseLimit from 'promise-limit'; -import { User, IRemoteUser } from '@/models/entities/user'; +import { ApObject, getApIds } from './type.js'; +import Resolver from './resolver.js'; +import { resolvePerson } from './models/person.js'; +import { unique, concat } from '@/prelude/array.js'; +import promiseLimit from 'promise-limit'; +import { User, IRemoteUser } from '@/models/entities/user.js'; type Visibility = 'public' | 'home' | 'followers' | 'specified'; diff --git a/packages/backend/src/remote/activitypub/db-resolver.ts b/packages/backend/src/remote/activitypub/db-resolver.ts index f2064cf26..9281e494d 100644 --- a/packages/backend/src/remote/activitypub/db-resolver.ts +++ b/packages/backend/src/remote/activitypub/db-resolver.ts @@ -1,12 +1,12 @@ -import config from '@/config/index'; -import { Note } from '@/models/entities/note'; -import { User, IRemoteUser } from '@/models/entities/user'; -import { UserPublickey } from '@/models/entities/user-publickey'; -import { MessagingMessage } from '@/models/entities/messaging-message'; -import { Notes, Users, UserPublickeys, MessagingMessages } from '@/models/index'; -import { IObject, getApId } from './type'; -import { resolvePerson } from './models/person'; -import escapeRegexp = require('escape-regexp'); +import config from '@/config/index.js'; +import { Note } from '@/models/entities/note.js'; +import { User, IRemoteUser } from '@/models/entities/user.js'; +import { UserPublickey } from '@/models/entities/user-publickey.js'; +import { MessagingMessage } from '@/models/entities/messaging-message.js'; +import { Notes, Users, UserPublickeys, MessagingMessages } from '@/models/index.js'; +import { IObject, getApId } from './type.js'; +import { resolvePerson } from './models/person.js'; +import escapeRegexp from 'escape-regexp'; export default class DbResolver { constructor() { diff --git a/packages/backend/src/remote/activitypub/deliver-manager.ts b/packages/backend/src/remote/activitypub/deliver-manager.ts index b16f90769..9c4e3418f 100644 --- a/packages/backend/src/remote/activitypub/deliver-manager.ts +++ b/packages/backend/src/remote/activitypub/deliver-manager.ts @@ -1,6 +1,6 @@ -import { Users, Followings } from '@/models/index'; -import { ILocalUser, IRemoteUser, User } from '@/models/entities/user'; -import { deliver } from '@/queue/index'; +import { Users, Followings } from '@/models/index.js'; +import { ILocalUser, IRemoteUser, User } from '@/models/entities/user.js'; +import { deliver } from '@/queue/index.js'; //#region types interface IRecipe { diff --git a/packages/backend/src/remote/activitypub/kernel/accept/follow.ts b/packages/backend/src/remote/activitypub/kernel/accept/follow.ts index 1afb733ab..393516add 100644 --- a/packages/backend/src/remote/activitypub/kernel/accept/follow.ts +++ b/packages/backend/src/remote/activitypub/kernel/accept/follow.ts @@ -1,8 +1,8 @@ -import { IRemoteUser } from '@/models/entities/user'; -import accept from '@/services/following/requests/accept'; -import { IFollow } from '../../type'; -import DbResolver from '../../db-resolver'; -import { relayAccepted } from '@/services/relay'; +import { IRemoteUser } from '@/models/entities/user.js'; +import accept from '@/services/following/requests/accept.js'; +import { IFollow } from '../../type.js'; +import DbResolver from '../../db-resolver.js'; +import { relayAccepted } from '@/services/relay.js'; export default async (actor: IRemoteUser, activity: IFollow): Promise => { // ※ activityはこっちから投げたフォローリクエストなので、activity.actorは存在するローカルユーザーである必要がある diff --git a/packages/backend/src/remote/activitypub/kernel/accept/index.ts b/packages/backend/src/remote/activitypub/kernel/accept/index.ts index 5c6f81b2e..354bd4f6e 100644 --- a/packages/backend/src/remote/activitypub/kernel/accept/index.ts +++ b/packages/backend/src/remote/activitypub/kernel/accept/index.ts @@ -1,8 +1,8 @@ -import Resolver from '../../resolver'; -import { IRemoteUser } from '@/models/entities/user'; -import acceptFollow from './follow'; -import { IAccept, isFollow, getApType } from '../../type'; -import { apLogger } from '../../logger'; +import Resolver from '../../resolver.js'; +import { IRemoteUser } from '@/models/entities/user.js'; +import acceptFollow from './follow.js'; +import { IAccept, isFollow, getApType } from '../../type.js'; +import { apLogger } from '../../logger.js'; const logger = apLogger; diff --git a/packages/backend/src/remote/activitypub/kernel/add/index.ts b/packages/backend/src/remote/activitypub/kernel/add/index.ts index b33be0cc8..9a2fac1e7 100644 --- a/packages/backend/src/remote/activitypub/kernel/add/index.ts +++ b/packages/backend/src/remote/activitypub/kernel/add/index.ts @@ -1,7 +1,7 @@ -import { IRemoteUser } from '@/models/entities/user'; -import { IAdd } from '../../type'; -import { resolveNote } from '../../models/note'; -import { addPinned } from '@/services/i/pin'; +import { IRemoteUser } from '@/models/entities/user.js'; +import { IAdd } from '../../type.js'; +import { resolveNote } from '../../models/note.js'; +import { addPinned } from '@/services/i/pin.js'; export default async (actor: IRemoteUser, activity: IAdd): Promise => { if ('actor' in activity && actor.uri !== activity.actor) { diff --git a/packages/backend/src/remote/activitypub/kernel/announce/index.ts b/packages/backend/src/remote/activitypub/kernel/announce/index.ts index 581357e57..7e2e73bdd 100644 --- a/packages/backend/src/remote/activitypub/kernel/announce/index.ts +++ b/packages/backend/src/remote/activitypub/kernel/announce/index.ts @@ -1,8 +1,8 @@ -import Resolver from '../../resolver'; -import { IRemoteUser } from '@/models/entities/user'; -import announceNote from './note'; -import { IAnnounce, getApId } from '../../type'; -import { apLogger } from '../../logger'; +import Resolver from '../../resolver.js'; +import { IRemoteUser } from '@/models/entities/user.js'; +import announceNote from './note.js'; +import { IAnnounce, getApId } from '../../type.js'; +import { apLogger } from '../../logger.js'; const logger = apLogger; diff --git a/packages/backend/src/remote/activitypub/kernel/announce/note.ts b/packages/backend/src/remote/activitypub/kernel/announce/note.ts index eae92d418..f6068fac7 100644 --- a/packages/backend/src/remote/activitypub/kernel/announce/note.ts +++ b/packages/backend/src/remote/activitypub/kernel/announce/note.ts @@ -1,14 +1,14 @@ -import Resolver from '../../resolver'; -import post from '@/services/note/create'; -import { IRemoteUser } from '@/models/entities/user'; -import { IAnnounce, getApId } from '../../type'; -import { fetchNote, resolveNote } from '../../models/note'; -import { apLogger } from '../../logger'; -import { extractDbHost } from '@/misc/convert-host'; -import { fetchMeta } from '@/misc/fetch-meta'; -import { getApLock } from '@/misc/app-lock'; -import { parseAudience } from '../../audience'; -import { StatusError } from '@/misc/fetch'; +import Resolver from '../../resolver.js'; +import post from '@/services/note/create.js'; +import { IRemoteUser } from '@/models/entities/user.js'; +import { IAnnounce, getApId } from '../../type.js'; +import { fetchNote, resolveNote } from '../../models/note.js'; +import { apLogger } from '../../logger.js'; +import { extractDbHost } from '@/misc/convert-host.js'; +import { fetchMeta } from '@/misc/fetch-meta.js'; +import { getApLock } from '@/misc/app-lock.js'; +import { parseAudience } from '../../audience.js'; +import { StatusError } from '@/misc/fetch.js'; const logger = apLogger; diff --git a/packages/backend/src/remote/activitypub/kernel/block/index.ts b/packages/backend/src/remote/activitypub/kernel/block/index.ts index 4fd1e07b9..9e4f1b316 100644 --- a/packages/backend/src/remote/activitypub/kernel/block/index.ts +++ b/packages/backend/src/remote/activitypub/kernel/block/index.ts @@ -1,7 +1,7 @@ -import { IBlock } from '../../type'; -import block from '@/services/blocking/create'; -import { IRemoteUser } from '@/models/entities/user'; -import DbResolver from '../../db-resolver'; +import { IBlock } from '../../type.js'; +import block from '@/services/blocking/create.js'; +import { IRemoteUser } from '@/models/entities/user.js'; +import DbResolver from '../../db-resolver.js'; export default async (actor: IRemoteUser, activity: IBlock): Promise => { // ※ activity.objectにブロック対象があり、それは存在するローカルユーザーのはず diff --git a/packages/backend/src/remote/activitypub/kernel/create/index.ts b/packages/backend/src/remote/activitypub/kernel/create/index.ts index ce039a363..1187b95ac 100644 --- a/packages/backend/src/remote/activitypub/kernel/create/index.ts +++ b/packages/backend/src/remote/activitypub/kernel/create/index.ts @@ -1,9 +1,9 @@ -import Resolver from '../../resolver'; -import { IRemoteUser } from '@/models/entities/user'; -import createNote from './note'; -import { ICreate, getApId, isPost, getApType } from '../../type'; -import { apLogger } from '../../logger'; -import { toArray, concat, unique } from '@/prelude/array'; +import Resolver from '../../resolver.js'; +import { IRemoteUser } from '@/models/entities/user.js'; +import createNote from './note.js'; +import { ICreate, getApId, isPost, getApType } from '../../type.js'; +import { apLogger } from '../../logger.js'; +import { toArray, concat, unique } from '@/prelude/array.js'; const logger = apLogger; diff --git a/packages/backend/src/remote/activitypub/kernel/create/note.ts b/packages/backend/src/remote/activitypub/kernel/create/note.ts index 14e311e4c..b5c47990a 100644 --- a/packages/backend/src/remote/activitypub/kernel/create/note.ts +++ b/packages/backend/src/remote/activitypub/kernel/create/note.ts @@ -1,10 +1,10 @@ -import Resolver from '../../resolver'; -import { IRemoteUser } from '@/models/entities/user'; -import { createNote, fetchNote } from '../../models/note'; -import { getApId, IObject, ICreate } from '../../type'; -import { getApLock } from '@/misc/app-lock'; -import { extractDbHost } from '@/misc/convert-host'; -import { StatusError } from '@/misc/fetch'; +import Resolver from '../../resolver.js'; +import { IRemoteUser } from '@/models/entities/user.js'; +import { createNote, fetchNote } from '../../models/note.js'; +import { getApId, IObject, ICreate } from '../../type.js'; +import { getApLock } from '@/misc/app-lock.js'; +import { extractDbHost } from '@/misc/convert-host.js'; +import { StatusError } from '@/misc/fetch.js'; /** * 投稿作成アクティビティを捌きます diff --git a/packages/backend/src/remote/activitypub/kernel/delete/actor.ts b/packages/backend/src/remote/activitypub/kernel/delete/actor.ts index 502f8d5ab..2f75841e5 100644 --- a/packages/backend/src/remote/activitypub/kernel/delete/actor.ts +++ b/packages/backend/src/remote/activitypub/kernel/delete/actor.ts @@ -1,7 +1,7 @@ -import { apLogger } from '../../logger'; -import { createDeleteAccountJob } from '@/queue'; -import { IRemoteUser } from '@/models/entities/user'; -import { Users } from '@/models/index'; +import { apLogger } from '../../logger.js'; +import { createDeleteAccountJob } from '@/queue/index.js'; +import { IRemoteUser } from '@/models/entities/user.js'; +import { Users } from '@/models/index.js'; const logger = apLogger; diff --git a/packages/backend/src/remote/activitypub/kernel/delete/index.ts b/packages/backend/src/remote/activitypub/kernel/delete/index.ts index 86a452de7..b6d5e96d0 100644 --- a/packages/backend/src/remote/activitypub/kernel/delete/index.ts +++ b/packages/backend/src/remote/activitypub/kernel/delete/index.ts @@ -1,8 +1,8 @@ -import deleteNote from './note'; -import { IRemoteUser } from '@/models/entities/user'; -import { IDelete, getApId, isTombstone, IObject, validPost, validActor } from '../../type'; -import { toSingle } from '@/prelude/array'; -import { deleteActor } from './actor'; +import deleteNote from './note.js'; +import { IRemoteUser } from '@/models/entities/user.js'; +import { IDelete, getApId, isTombstone, IObject, validPost, validActor } from '../../type.js'; +import { toSingle } from '@/prelude/array.js'; +import { deleteActor } from './actor.js'; /** * 削除アクティビティを捌きます diff --git a/packages/backend/src/remote/activitypub/kernel/delete/note.ts b/packages/backend/src/remote/activitypub/kernel/delete/note.ts index 3875a33d1..ad5e1a2ed 100644 --- a/packages/backend/src/remote/activitypub/kernel/delete/note.ts +++ b/packages/backend/src/remote/activitypub/kernel/delete/note.ts @@ -1,9 +1,9 @@ -import { IRemoteUser } from '@/models/entities/user'; -import deleteNode from '@/services/note/delete'; -import { apLogger } from '../../logger'; -import DbResolver from '../../db-resolver'; -import { getApLock } from '@/misc/app-lock'; -import { deleteMessage } from '@/services/messages/delete'; +import { IRemoteUser } from '@/models/entities/user.js'; +import deleteNode from '@/services/note/delete.js'; +import { apLogger } from '../../logger.js'; +import DbResolver from '../../db-resolver.js'; +import { getApLock } from '@/misc/app-lock.js'; +import { deleteMessage } from '@/services/messages/delete.js'; const logger = apLogger; diff --git a/packages/backend/src/remote/activitypub/kernel/flag/index.ts b/packages/backend/src/remote/activitypub/kernel/flag/index.ts index d910e2ebe..e80e63278 100644 --- a/packages/backend/src/remote/activitypub/kernel/flag/index.ts +++ b/packages/backend/src/remote/activitypub/kernel/flag/index.ts @@ -1,9 +1,9 @@ -import { IRemoteUser } from '@/models/entities/user'; -import config from '@/config/index'; -import { IFlag, getApIds } from '../../type'; -import { AbuseUserReports, Users } from '@/models/index'; +import { IRemoteUser } from '@/models/entities/user.js'; +import config from '@/config/index.js'; +import { IFlag, getApIds } from '../../type.js'; +import { AbuseUserReports, Users } from '@/models/index.js'; import { In } from 'typeorm'; -import { genId } from '@/misc/gen-id'; +import { genId } from '@/misc/gen-id.js'; export default async (actor: IRemoteUser, activity: IFlag): Promise => { // objectは `(User|Note) | (User|Note)[]` だけど、全パターンDBスキーマと対応させられないので diff --git a/packages/backend/src/remote/activitypub/kernel/follow.ts b/packages/backend/src/remote/activitypub/kernel/follow.ts index 3183207af..49c1a7ee0 100644 --- a/packages/backend/src/remote/activitypub/kernel/follow.ts +++ b/packages/backend/src/remote/activitypub/kernel/follow.ts @@ -1,7 +1,7 @@ -import { IRemoteUser } from '@/models/entities/user'; -import follow from '@/services/following/create'; -import { IFollow } from '../type'; -import DbResolver from '../db-resolver'; +import { IRemoteUser } from '@/models/entities/user.js'; +import follow from '@/services/following/create.js'; +import { IFollow } from '../type.js'; +import DbResolver from '../db-resolver.js'; export default async (actor: IRemoteUser, activity: IFollow): Promise => { const dbResolver = new DbResolver(); diff --git a/packages/backend/src/remote/activitypub/kernel/index.ts b/packages/backend/src/remote/activitypub/kernel/index.ts index a103e5a1b..6aea8e57c 100644 --- a/packages/backend/src/remote/activitypub/kernel/index.ts +++ b/packages/backend/src/remote/activitypub/kernel/index.ts @@ -1,22 +1,22 @@ -import { IObject, isCreate, isDelete, isUpdate, isRead, isFollow, isAccept, isReject, isAdd, isRemove, isAnnounce, isLike, isUndo, isBlock, isCollectionOrOrderedCollection, isCollection, isFlag } from '../type'; -import { IRemoteUser } from '@/models/entities/user'; -import create from './create/index'; -import performDeleteActivity from './delete/index'; -import performUpdateActivity from './update/index'; -import { performReadActivity } from './read'; -import follow from './follow'; -import undo from './undo/index'; -import like from './like'; -import announce from './announce/index'; -import accept from './accept/index'; -import reject from './reject/index'; -import add from './add/index'; -import remove from './remove/index'; -import block from './block/index'; -import flag from './flag/index'; -import { apLogger } from '../logger'; -import Resolver from '../resolver'; -import { toArray } from '@/prelude/array'; +import { IObject, isCreate, isDelete, isUpdate, isRead, isFollow, isAccept, isReject, isAdd, isRemove, isAnnounce, isLike, isUndo, isBlock, isCollectionOrOrderedCollection, isCollection, isFlag } from '../type.js'; +import { IRemoteUser } from '@/models/entities/user.js'; +import create from './create/index.js'; +import performDeleteActivity from './delete/index.js'; +import performUpdateActivity from './update/index.js'; +import { performReadActivity } from './read.js'; +import follow from './follow.js'; +import undo from './undo/index.js'; +import like from './like.js'; +import announce from './announce/index.js'; +import accept from './accept/index.js'; +import reject from './reject/index.js'; +import add from './add/index.js'; +import remove from './remove/index.js'; +import block from './block/index.js'; +import flag from './flag/index.js'; +import { apLogger } from '../logger.js'; +import Resolver from '../resolver.js'; +import { toArray } from '@/prelude/array.js'; export async function performActivity(actor: IRemoteUser, activity: IObject) { if (isCollectionOrOrderedCollection(activity)) { diff --git a/packages/backend/src/remote/activitypub/kernel/like.ts b/packages/backend/src/remote/activitypub/kernel/like.ts index 58d5aefef..715cc379b 100644 --- a/packages/backend/src/remote/activitypub/kernel/like.ts +++ b/packages/backend/src/remote/activitypub/kernel/like.ts @@ -1,7 +1,7 @@ -import { IRemoteUser } from '@/models/entities/user'; -import { ILike, getApId } from '../type'; -import create from '@/services/note/reaction/create'; -import { fetchNote, extractEmojis } from '../models/note'; +import { IRemoteUser } from '@/models/entities/user.js'; +import { ILike, getApId } from '../type.js'; +import create from '@/services/note/reaction/create.js'; +import { fetchNote, extractEmojis } from '../models/note.js'; export default async (actor: IRemoteUser, activity: ILike) => { const targetUri = getApId(activity.object); diff --git a/packages/backend/src/remote/activitypub/kernel/read.ts b/packages/backend/src/remote/activitypub/kernel/read.ts index 11a173186..93cc36ec4 100644 --- a/packages/backend/src/remote/activitypub/kernel/read.ts +++ b/packages/backend/src/remote/activitypub/kernel/read.ts @@ -1,8 +1,8 @@ -import { IRemoteUser } from '@/models/entities/user'; -import { IRead, getApId } from '../type'; -import { isSelfHost, extractDbHost } from '@/misc/convert-host'; -import { MessagingMessages } from '@/models/index'; -import { readUserMessagingMessage } from '../../../server/api/common/read-messaging-message'; +import { IRemoteUser } from '@/models/entities/user.js'; +import { IRead, getApId } from '../type.js'; +import { isSelfHost, extractDbHost } from '@/misc/convert-host.js'; +import { MessagingMessages } from '@/models/index.js'; +import { readUserMessagingMessage } from '../../../server/api/common/read-messaging-message.js'; export const performReadActivity = async (actor: IRemoteUser, activity: IRead): Promise => { const id = await getApId(activity.object); diff --git a/packages/backend/src/remote/activitypub/kernel/reject/follow.ts b/packages/backend/src/remote/activitypub/kernel/reject/follow.ts index 049437b18..72751e83c 100644 --- a/packages/backend/src/remote/activitypub/kernel/reject/follow.ts +++ b/packages/backend/src/remote/activitypub/kernel/reject/follow.ts @@ -1,9 +1,9 @@ -import { IRemoteUser } from '@/models/entities/user'; -import { remoteReject } from '@/services/following/reject'; -import { IFollow } from '../../type'; -import DbResolver from '../../db-resolver'; -import { relayRejected } from '@/services/relay'; -import { Users } from '@/models'; +import { IRemoteUser } from '@/models/entities/user.js'; +import { remoteReject } from '@/services/following/reject.js'; +import { IFollow } from '../../type.js'; +import DbResolver from '../../db-resolver.js'; +import { relayRejected } from '@/services/relay.js'; +import { Users } from '@/models/index.js'; export default async (actor: IRemoteUser, activity: IFollow): Promise => { // ※ activityはこっちから投げたフォローリクエストなので、activity.actorは存在するローカルユーザーである必要がある diff --git a/packages/backend/src/remote/activitypub/kernel/reject/index.ts b/packages/backend/src/remote/activitypub/kernel/reject/index.ts index d0de9c329..ed86a4aa2 100644 --- a/packages/backend/src/remote/activitypub/kernel/reject/index.ts +++ b/packages/backend/src/remote/activitypub/kernel/reject/index.ts @@ -1,8 +1,8 @@ -import Resolver from '../../resolver'; -import { IRemoteUser } from '@/models/entities/user'; -import rejectFollow from './follow'; -import { IReject, isFollow, getApType } from '../../type'; -import { apLogger } from '../../logger'; +import Resolver from '../../resolver.js'; +import { IRemoteUser } from '@/models/entities/user.js'; +import rejectFollow from './follow.js'; +import { IReject, isFollow, getApType } from '../../type.js'; +import { apLogger } from '../../logger.js'; const logger = apLogger; diff --git a/packages/backend/src/remote/activitypub/kernel/remove/index.ts b/packages/backend/src/remote/activitypub/kernel/remove/index.ts index d59953e65..7d7b3386c 100644 --- a/packages/backend/src/remote/activitypub/kernel/remove/index.ts +++ b/packages/backend/src/remote/activitypub/kernel/remove/index.ts @@ -1,7 +1,7 @@ -import { IRemoteUser } from '@/models/entities/user'; -import { IRemove } from '../../type'; -import { resolveNote } from '../../models/note'; -import { removePinned } from '@/services/i/pin'; +import { IRemoteUser } from '@/models/entities/user.js'; +import { IRemove } from '../../type.js'; +import { resolveNote } from '../../models/note.js'; +import { removePinned } from '@/services/i/pin.js'; export default async (actor: IRemoteUser, activity: IRemove): Promise => { if ('actor' in activity && actor.uri !== activity.actor) { diff --git a/packages/backend/src/remote/activitypub/kernel/undo/accept.ts b/packages/backend/src/remote/activitypub/kernel/undo/accept.ts index 10c8a9c9d..2383eea5b 100644 --- a/packages/backend/src/remote/activitypub/kernel/undo/accept.ts +++ b/packages/backend/src/remote/activitypub/kernel/undo/accept.ts @@ -1,9 +1,9 @@ -import unfollow from '@/services/following/delete'; -import cancelRequest from '@/services/following/requests/cancel'; -import {IAccept} from '../../type'; -import { IRemoteUser } from '@/models/entities/user'; -import { Followings } from '@/models/index'; -import DbResolver from '../../db-resolver'; +import unfollow from '@/services/following/delete.js'; +import cancelRequest from '@/services/following/requests/cancel.js'; +import {IAccept} from '../../type.js'; +import { IRemoteUser } from '@/models/entities/user.js'; +import { Followings } from '@/models/index.js'; +import DbResolver from '../../db-resolver.js'; export default async (actor: IRemoteUser, activity: IAccept): Promise => { const dbResolver = new DbResolver(); diff --git a/packages/backend/src/remote/activitypub/kernel/undo/announce.ts b/packages/backend/src/remote/activitypub/kernel/undo/announce.ts index 7f302a616..822c1e494 100644 --- a/packages/backend/src/remote/activitypub/kernel/undo/announce.ts +++ b/packages/backend/src/remote/activitypub/kernel/undo/announce.ts @@ -1,7 +1,7 @@ -import { Notes } from '@/models/index'; -import { IRemoteUser } from '@/models/entities/user'; -import { IAnnounce, getApId } from '../../type'; -import deleteNote from '@/services/note/delete'; +import { Notes } from '@/models/index.js'; +import { IRemoteUser } from '@/models/entities/user.js'; +import { IAnnounce, getApId } from '../../type.js'; +import deleteNote from '@/services/note/delete.js'; export const undoAnnounce = async (actor: IRemoteUser, activity: IAnnounce): Promise => { const uri = getApId(activity); diff --git a/packages/backend/src/remote/activitypub/kernel/undo/block.ts b/packages/backend/src/remote/activitypub/kernel/undo/block.ts index 61940486b..844b067e2 100644 --- a/packages/backend/src/remote/activitypub/kernel/undo/block.ts +++ b/packages/backend/src/remote/activitypub/kernel/undo/block.ts @@ -1,7 +1,7 @@ -import { IBlock } from '../../type'; -import unblock from '@/services/blocking/delete'; -import { IRemoteUser } from '@/models/entities/user'; -import DbResolver from '../../db-resolver'; +import { IBlock } from '../../type.js'; +import unblock from '@/services/blocking/delete.js'; +import { IRemoteUser } from '@/models/entities/user.js'; +import DbResolver from '../../db-resolver.js'; export default async (actor: IRemoteUser, activity: IBlock): Promise => { const dbResolver = new DbResolver(); diff --git a/packages/backend/src/remote/activitypub/kernel/undo/follow.ts b/packages/backend/src/remote/activitypub/kernel/undo/follow.ts index 783e5acf1..6715adcf7 100644 --- a/packages/backend/src/remote/activitypub/kernel/undo/follow.ts +++ b/packages/backend/src/remote/activitypub/kernel/undo/follow.ts @@ -1,9 +1,9 @@ -import unfollow from '@/services/following/delete'; -import cancelRequest from '@/services/following/requests/cancel'; -import { IFollow } from '../../type'; -import { IRemoteUser } from '@/models/entities/user'; -import { FollowRequests, Followings } from '@/models/index'; -import DbResolver from '../../db-resolver'; +import unfollow from '@/services/following/delete.js'; +import cancelRequest from '@/services/following/requests/cancel.js'; +import { IFollow } from '../../type.js'; +import { IRemoteUser } from '@/models/entities/user.js'; +import { FollowRequests, Followings } from '@/models/index.js'; +import DbResolver from '../../db-resolver.js'; export default async (actor: IRemoteUser, activity: IFollow): Promise => { const dbResolver = new DbResolver(); diff --git a/packages/backend/src/remote/activitypub/kernel/undo/index.ts b/packages/backend/src/remote/activitypub/kernel/undo/index.ts index 8de78420e..05937c685 100644 --- a/packages/backend/src/remote/activitypub/kernel/undo/index.ts +++ b/packages/backend/src/remote/activitypub/kernel/undo/index.ts @@ -1,12 +1,12 @@ -import { IRemoteUser } from '@/models/entities/user'; -import {IUndo, isFollow, isBlock, isLike, isAnnounce, getApType, isAccept} from '../../type'; -import unfollow from './follow'; -import unblock from './block'; -import undoLike from './like'; -import undoAccept from './accept'; -import { undoAnnounce } from './announce'; -import Resolver from '../../resolver'; -import { apLogger } from '../../logger'; +import { IRemoteUser } from '@/models/entities/user.js'; +import {IUndo, isFollow, isBlock, isLike, isAnnounce, getApType, isAccept} from '../../type.js'; +import unfollow from './follow.js'; +import unblock from './block.js'; +import undoLike from './like.js'; +import undoAccept from './accept.js'; +import { undoAnnounce } from './announce.js'; +import Resolver from '../../resolver.js'; +import { apLogger } from '../../logger.js'; const logger = apLogger; diff --git a/packages/backend/src/remote/activitypub/kernel/undo/like.ts b/packages/backend/src/remote/activitypub/kernel/undo/like.ts index 107d3053e..08ac63035 100644 --- a/packages/backend/src/remote/activitypub/kernel/undo/like.ts +++ b/packages/backend/src/remote/activitypub/kernel/undo/like.ts @@ -1,7 +1,7 @@ -import { IRemoteUser } from '@/models/entities/user'; -import { ILike, getApId } from '../../type'; -import deleteReaction from '@/services/note/reaction/delete'; -import { fetchNote } from '../../models/note'; +import { IRemoteUser } from '@/models/entities/user.js'; +import { ILike, getApId } from '../../type.js'; +import deleteReaction from '@/services/note/reaction/delete.js'; +import { fetchNote } from '../../models/note.js'; /** * Process Undo.Like activity diff --git a/packages/backend/src/remote/activitypub/kernel/update/index.ts b/packages/backend/src/remote/activitypub/kernel/update/index.ts index 52bfc5002..7888c698e 100644 --- a/packages/backend/src/remote/activitypub/kernel/update/index.ts +++ b/packages/backend/src/remote/activitypub/kernel/update/index.ts @@ -1,9 +1,9 @@ -import { IRemoteUser } from '@/models/entities/user'; -import { getApType, IUpdate, isActor } from '../../type'; -import { apLogger } from '../../logger'; -import { updateQuestion } from '../../models/question'; -import Resolver from '../../resolver'; -import { updatePerson } from '../../models/person'; +import { IRemoteUser } from '@/models/entities/user.js'; +import { getApType, IUpdate, isActor } from '../../type.js'; +import { apLogger } from '../../logger.js'; +import { updateQuestion } from '../../models/question.js'; +import Resolver from '../../resolver.js'; +import { updatePerson } from '../../models/person.js'; /** * Updateアクティビティを捌きます diff --git a/packages/backend/src/remote/activitypub/logger.ts b/packages/backend/src/remote/activitypub/logger.ts index e13add01d..cab51b3bf 100644 --- a/packages/backend/src/remote/activitypub/logger.ts +++ b/packages/backend/src/remote/activitypub/logger.ts @@ -1,3 +1,3 @@ -import { remoteLogger } from '../logger'; +import { remoteLogger } from '../logger.js'; export const apLogger = remoteLogger.createSubLogger('ap', 'magenta'); diff --git a/packages/backend/src/remote/activitypub/misc/get-note-html.ts b/packages/backend/src/remote/activitypub/misc/get-note-html.ts index 043335a5b..3800b4060 100644 --- a/packages/backend/src/remote/activitypub/misc/get-note-html.ts +++ b/packages/backend/src/remote/activitypub/misc/get-note-html.ts @@ -1,6 +1,6 @@ import * as mfm from 'mfm-js'; -import { Note } from '@/models/entities/note'; -import { toHtml } from '../../../mfm/to-html'; +import { Note } from '@/models/entities/note.js'; +import { toHtml } from '../../../mfm/to-html.js'; export default function(note: Note) { let html = note.text ? toHtml(mfm.parse(note.text), JSON.parse(note.mentionedRemoteUsers)) : null; diff --git a/packages/backend/src/remote/activitypub/misc/html-to-mfm.ts b/packages/backend/src/remote/activitypub/misc/html-to-mfm.ts index 5cca04df2..bb1ba7925 100644 --- a/packages/backend/src/remote/activitypub/misc/html-to-mfm.ts +++ b/packages/backend/src/remote/activitypub/misc/html-to-mfm.ts @@ -1,6 +1,6 @@ -import { IObject } from '../type'; -import { extractApHashtagObjects } from '../models/tag'; -import { fromHtml } from '../../../mfm/from-html'; +import { IObject } from '../type.js'; +import { extractApHashtagObjects } from '../models/tag.js'; +import { fromHtml } from '../../../mfm/from-html.js'; export function htmlToMfm(html: string, tag?: IObject | IObject[]) { const hashtagNames = extractApHashtagObjects(tag).map(x => x.name).filter((x): x is string => x != null); diff --git a/packages/backend/src/remote/activitypub/misc/ld-signature.ts b/packages/backend/src/remote/activitypub/misc/ld-signature.ts index 3b799c755..34294c935 100644 --- a/packages/backend/src/remote/activitypub/misc/ld-signature.ts +++ b/packages/backend/src/remote/activitypub/misc/ld-signature.ts @@ -1,8 +1,8 @@ -import * as crypto from 'crypto'; +import * as crypto from 'node:crypto'; import * as jsonld from 'jsonld'; -import { CONTEXTS } from './contexts'; +import { CONTEXTS } from './contexts.js'; import fetch from 'node-fetch'; -import { httpAgent, httpsAgent } from '@/misc/fetch'; +import { httpAgent, httpsAgent } from '@/misc/fetch.js'; // RsaSignature2017 based from https://github.com/transmute-industries/RsaSignature2017 diff --git a/packages/backend/src/remote/activitypub/models/image.ts b/packages/backend/src/remote/activitypub/models/image.ts index 6f60b7827..b5e9181d3 100644 --- a/packages/backend/src/remote/activitypub/models/image.ts +++ b/packages/backend/src/remote/activitypub/models/image.ts @@ -1,12 +1,12 @@ -import { uploadFromUrl } from '@/services/drive/upload-from-url'; -import { IRemoteUser } from '@/models/entities/user'; -import Resolver from '../resolver'; -import { fetchMeta } from '@/misc/fetch-meta'; -import { apLogger } from '../logger'; -import { DriveFile } from '@/models/entities/drive-file'; -import { DriveFiles } from '@/models/index'; -import { truncate } from '@/misc/truncate'; -import { DB_MAX_IMAGE_COMMENT_LENGTH } from '@/misc/hard-limits'; +import { uploadFromUrl } from '@/services/drive/upload-from-url.js'; +import { IRemoteUser } from '@/models/entities/user.js'; +import Resolver from '../resolver.js'; +import { fetchMeta } from '@/misc/fetch-meta.js'; +import { apLogger } from '../logger.js'; +import { DriveFile } from '@/models/entities/drive-file.js'; +import { DriveFiles } from '@/models/index.js'; +import { truncate } from '@/misc/truncate.js'; +import { DB_MAX_IMAGE_COMMENT_LENGTH } from '@/misc/hard-limits.js'; const logger = apLogger; diff --git a/packages/backend/src/remote/activitypub/models/mention.ts b/packages/backend/src/remote/activitypub/models/mention.ts index ade9c9080..c5b0ea53c 100644 --- a/packages/backend/src/remote/activitypub/models/mention.ts +++ b/packages/backend/src/remote/activitypub/models/mention.ts @@ -1,9 +1,9 @@ -import { toArray, unique } from '@/prelude/array'; -import { IObject, isMention, IApMention } from '../type'; -import { resolvePerson } from './person'; -import * as promiseLimit from 'promise-limit'; -import Resolver from '../resolver'; -import { User } from '@/models/entities/user'; +import { toArray, unique } from '@/prelude/array.js'; +import { IObject, isMention, IApMention } from '../type.js'; +import { resolvePerson } from './person.js'; +import promiseLimit from 'promise-limit'; +import Resolver from '../resolver.js'; +import { User } from '@/models/entities/user.js'; export async function extractApMentions(tags: IObject | IObject[] | null | undefined) { const hrefs = unique(extractApMentionObjects(tags).map(x => x.href as string)); diff --git a/packages/backend/src/remote/activitypub/models/note.ts b/packages/backend/src/remote/activitypub/models/note.ts index 6847925a5..dca64d0a6 100644 --- a/packages/backend/src/remote/activitypub/models/note.ts +++ b/packages/backend/src/remote/activitypub/models/note.ts @@ -1,32 +1,32 @@ -import * as promiseLimit from 'promise-limit'; +import promiseLimit from 'promise-limit'; -import config from '@/config/index'; -import Resolver from '../resolver'; -import post from '@/services/note/create'; -import { resolvePerson, updatePerson } from './person'; -import { resolveImage } from './image'; -import { IRemoteUser } from '@/models/entities/user'; -import { htmlToMfm } from '../misc/html-to-mfm'; -import { extractApHashtags } from './tag'; -import { unique, toArray, toSingle } from '@/prelude/array'; -import { extractPollFromQuestion } from './question'; -import vote from '@/services/note/polls/vote'; -import { apLogger } from '../logger'; -import { DriveFile } from '@/models/entities/drive-file'; -import { deliverQuestionUpdate } from '@/services/note/polls/update'; -import { extractDbHost, toPuny } from '@/misc/convert-host'; -import { Emojis, Polls, MessagingMessages } from '@/models/index'; -import { Note } from '@/models/entities/note'; -import { IObject, getOneApId, getApId, getOneApHrefNullable, validPost, IPost, isEmoji, getApType } from '../type'; -import { Emoji } from '@/models/entities/emoji'; -import { genId } from '@/misc/gen-id'; -import { fetchMeta } from '@/misc/fetch-meta'; -import { getApLock } from '@/misc/app-lock'; -import { createMessage } from '@/services/messages/create'; -import { parseAudience } from '../audience'; -import { extractApMentions } from './mention'; -import DbResolver from '../db-resolver'; -import { StatusError } from '@/misc/fetch'; +import config from '@/config/index.js'; +import Resolver from '../resolver.js'; +import post from '@/services/note/create.js'; +import { resolvePerson, updatePerson } from './person.js'; +import { resolveImage } from './image.js'; +import { IRemoteUser } from '@/models/entities/user.js'; +import { htmlToMfm } from '../misc/html-to-mfm.js'; +import { extractApHashtags } from './tag.js'; +import { unique, toArray, toSingle } from '@/prelude/array.js'; +import { extractPollFromQuestion } from './question.js'; +import vote from '@/services/note/polls/vote.js'; +import { apLogger } from '../logger.js'; +import { DriveFile } from '@/models/entities/drive-file.js'; +import { deliverQuestionUpdate } from '@/services/note/polls/update.js'; +import { extractDbHost, toPuny } from '@/misc/convert-host.js'; +import { Emojis, Polls, MessagingMessages } from '@/models/index.js'; +import { Note } from '@/models/entities/note.js'; +import { IObject, getOneApId, getApId, getOneApHrefNullable, validPost, IPost, isEmoji, getApType } from '../type.js'; +import { Emoji } from '@/models/entities/emoji.js'; +import { genId } from '@/misc/gen-id.js'; +import { fetchMeta } from '@/misc/fetch-meta.js'; +import { getApLock } from '@/misc/app-lock.js'; +import { createMessage } from '@/services/messages/create.js'; +import { parseAudience } from '../audience.js'; +import { extractApMentions } from './mention.js'; +import DbResolver from '../db-resolver.js'; +import { StatusError } from '@/misc/fetch.js'; const logger = apLogger; diff --git a/packages/backend/src/remote/activitypub/models/person.ts b/packages/backend/src/remote/activitypub/models/person.ts index aaccf51fa..659d3ac9a 100644 --- a/packages/backend/src/remote/activitypub/models/person.ts +++ b/packages/backend/src/remote/activitypub/models/person.ts @@ -1,35 +1,35 @@ -import { URL } from 'url'; -import * as promiseLimit from 'promise-limit'; +import { URL } from 'node:url'; +import promiseLimit from 'promise-limit'; import $, { Context } from 'cafy'; -import config from '@/config/index'; -import Resolver from '../resolver'; -import { resolveImage } from './image'; -import { isCollectionOrOrderedCollection, isCollection, IActor, getApId, getOneApHrefNullable, IObject, isPropertyValue, IApPropertyValue, getApType, isActor } from '../type'; -import { fromHtml } from '../../../mfm/from-html'; -import { htmlToMfm } from '../misc/html-to-mfm'; -import { resolveNote, extractEmojis } from './note'; -import { registerOrFetchInstanceDoc } from '@/services/register-or-fetch-instance-doc'; -import { extractApHashtags } from './tag'; -import { apLogger } from '../logger'; -import { Note } from '@/models/entities/note'; -import { updateUsertags } from '@/services/update-hashtag'; -import { Users, Instances, DriveFiles, Followings, UserProfiles, UserPublickeys } from '@/models/index'; -import { User, IRemoteUser } from '@/models/entities/user'; -import { Emoji } from '@/models/entities/emoji'; -import { UserNotePining } from '@/models/entities/user-note-pining'; -import { genId } from '@/misc/gen-id'; -import { instanceChart, usersChart } from '@/services/chart/index'; -import { UserPublickey } from '@/models/entities/user-publickey'; -import { isDuplicateKeyValueError } from '@/misc/is-duplicate-key-value-error'; -import { toPuny } from '@/misc/convert-host'; -import { UserProfile } from '@/models/entities/user-profile'; +import config from '@/config/index.js'; +import Resolver from '../resolver.js'; +import { resolveImage } from './image.js'; +import { isCollectionOrOrderedCollection, isCollection, IActor, getApId, getOneApHrefNullable, IObject, isPropertyValue, IApPropertyValue, getApType, isActor } from '../type.js'; +import { fromHtml } from '../../../mfm/from-html.js'; +import { htmlToMfm } from '../misc/html-to-mfm.js'; +import { resolveNote, extractEmojis } from './note.js'; +import { registerOrFetchInstanceDoc } from '@/services/register-or-fetch-instance-doc.js'; +import { extractApHashtags } from './tag.js'; +import { apLogger } from '../logger.js'; +import { Note } from '@/models/entities/note.js'; +import { updateUsertags } from '@/services/update-hashtag.js'; +import { Users, Instances, DriveFiles, Followings, UserProfiles, UserPublickeys } from '@/models/index.js'; +import { User, IRemoteUser } from '@/models/entities/user.js'; +import { Emoji } from '@/models/entities/emoji.js'; +import { UserNotePining } from '@/models/entities/user-note-pining.js'; +import { genId } from '@/misc/gen-id.js'; +import { instanceChart, usersChart } from '@/services/chart/index.js'; +import { UserPublickey } from '@/models/entities/user-publickey.js'; +import { isDuplicateKeyValueError } from '@/misc/is-duplicate-key-value-error.js'; +import { toPuny } from '@/misc/convert-host.js'; +import { UserProfile } from '@/models/entities/user-profile.js'; import { getConnection } from 'typeorm'; -import { toArray } from '@/prelude/array'; -import { fetchInstanceMetadata } from '@/services/fetch-instance-metadata'; -import { normalizeForSearch } from '@/misc/normalize-for-search'; -import { truncate } from '@/misc/truncate'; -import { StatusError } from '@/misc/fetch'; +import { toArray } from '@/prelude/array.js'; +import { fetchInstanceMetadata } from '@/services/fetch-instance-metadata.js'; +import { normalizeForSearch } from '@/misc/normalize-for-search.js'; +import { truncate } from '@/misc/truncate.js'; +import { StatusError } from '@/misc/fetch.js'; const logger = apLogger; @@ -57,15 +57,15 @@ function validateActor(x: IObject, uri: string): IActor { if (e) throw new Error(`invalid Actor: ${name} ${e.message}`); }; - validate('id', x.id, $.str.min(1)); - validate('inbox', x.inbox, $.str.min(1)); - validate('preferredUsername', x.preferredUsername, $.str.min(1).max(128).match(/^\w([\w-.]*\w)?$/)); + validate('id', x.id, $.default.str.min(1)); + validate('inbox', x.inbox, $.default.str.min(1)); + validate('preferredUsername', x.preferredUsername, $.default.str.min(1).max(128).match(/^\w([\w-.]*\w)?$/)); // These fields are only informational, and some AP software allows these // fields to be very long. If they are too long, we cut them off. This way // we can at least see these users and their activities. - validate('name', truncate(x.name, nameLength), $.optional.nullable.str); - validate('summary', truncate(x.summary, summaryLength), $.optional.nullable.str); + validate('name', truncate(x.name, nameLength), $.default.optional.nullable.str); + validate('summary', truncate(x.summary, summaryLength), $.default.optional.nullable.str); const idHost = toPuny(new URL(x.id!).hostname); if (idHost !== expectHost) { @@ -199,7 +199,7 @@ export async function createPerson(uri: string, resolver?: Resolver): Promise { if (resolver == null) resolver = new Resolver(); diff --git a/packages/backend/src/remote/activitypub/models/tag.ts b/packages/backend/src/remote/activitypub/models/tag.ts index fbc6b9b42..964dabad0 100644 --- a/packages/backend/src/remote/activitypub/models/tag.ts +++ b/packages/backend/src/remote/activitypub/models/tag.ts @@ -1,5 +1,5 @@ -import { toArray } from '@/prelude/array'; -import { IObject, isHashtag, IApHashtag } from '../type'; +import { toArray } from '@/prelude/array.js'; +import { IObject, isHashtag, IApHashtag } from '../type.js'; export function extractApHashtags(tags: IObject | IObject[] | null | undefined) { if (tags == null) return []; diff --git a/packages/backend/src/remote/activitypub/perform.ts b/packages/backend/src/remote/activitypub/perform.ts index 01f0e3676..3e1881558 100644 --- a/packages/backend/src/remote/activitypub/perform.ts +++ b/packages/backend/src/remote/activitypub/perform.ts @@ -1,6 +1,6 @@ -import { IObject } from './type'; -import { IRemoteUser } from '@/models/entities/user'; -import { performActivity } from './kernel/index'; +import { IObject } from './type.js'; +import { IRemoteUser } from '@/models/entities/user.js'; +import { performActivity } from './kernel/index.js'; export default async (actor: IRemoteUser, activity: IObject): Promise => { await performActivity(actor, activity); diff --git a/packages/backend/src/remote/activitypub/renderer/accept.ts b/packages/backend/src/remote/activitypub/renderer/accept.ts index 3bce2165c..cb01f6a91 100644 --- a/packages/backend/src/remote/activitypub/renderer/accept.ts +++ b/packages/backend/src/remote/activitypub/renderer/accept.ts @@ -1,5 +1,5 @@ -import config from '@/config/index'; -import { User } from '@/models/entities/user'; +import config from '@/config/index.js'; +import { User } from '@/models/entities/user.js'; export default (object: any, user: { id: User['id']; host: null }) => ({ type: 'Accept', diff --git a/packages/backend/src/remote/activitypub/renderer/add.ts b/packages/backend/src/remote/activitypub/renderer/add.ts index 960daf842..ec4788429 100644 --- a/packages/backend/src/remote/activitypub/renderer/add.ts +++ b/packages/backend/src/remote/activitypub/renderer/add.ts @@ -1,5 +1,5 @@ -import config from '@/config/index'; -import { ILocalUser } from '@/models/entities/user'; +import config from '@/config/index.js'; +import { ILocalUser } from '@/models/entities/user.js'; export default (user: ILocalUser, target: any, object: any) => ({ type: 'Add', diff --git a/packages/backend/src/remote/activitypub/renderer/announce.ts b/packages/backend/src/remote/activitypub/renderer/announce.ts index ab113b48e..2709fea51 100644 --- a/packages/backend/src/remote/activitypub/renderer/announce.ts +++ b/packages/backend/src/remote/activitypub/renderer/announce.ts @@ -1,5 +1,5 @@ -import config from '@/config/index'; -import { Note } from '@/models/entities/note'; +import config from '@/config/index.js'; +import { Note } from '@/models/entities/note.js'; export default (object: any, note: Note) => { const attributedTo = `${config.url}/users/${note.userId}`; diff --git a/packages/backend/src/remote/activitypub/renderer/block.ts b/packages/backend/src/remote/activitypub/renderer/block.ts index bfb831daa..10a4fde51 100644 --- a/packages/backend/src/remote/activitypub/renderer/block.ts +++ b/packages/backend/src/remote/activitypub/renderer/block.ts @@ -1,5 +1,5 @@ -import config from '@/config/index'; -import { ILocalUser, IRemoteUser } from '@/models/entities/user'; +import config from '@/config/index.js'; +import { ILocalUser, IRemoteUser } from '@/models/entities/user.js'; export default (blocker: ILocalUser, blockee: IRemoteUser) => ({ type: 'Block', diff --git a/packages/backend/src/remote/activitypub/renderer/create.ts b/packages/backend/src/remote/activitypub/renderer/create.ts index ac9e69af2..281a3cb2a 100644 --- a/packages/backend/src/remote/activitypub/renderer/create.ts +++ b/packages/backend/src/remote/activitypub/renderer/create.ts @@ -1,5 +1,5 @@ -import config from '@/config/index'; -import { Note } from '@/models/entities/note'; +import config from '@/config/index.js'; +import { Note } from '@/models/entities/note.js'; export default (object: any, note: Note) => { const activity = { diff --git a/packages/backend/src/remote/activitypub/renderer/delete.ts b/packages/backend/src/remote/activitypub/renderer/delete.ts index 176a6f7e2..4edd3a880 100644 --- a/packages/backend/src/remote/activitypub/renderer/delete.ts +++ b/packages/backend/src/remote/activitypub/renderer/delete.ts @@ -1,5 +1,5 @@ -import config from '@/config/index'; -import { User } from '@/models/entities/user'; +import config from '@/config/index.js'; +import { User } from '@/models/entities/user.js'; export default (object: any, user: { id: User['id']; host: null }) => ({ type: 'Delete', diff --git a/packages/backend/src/remote/activitypub/renderer/document.ts b/packages/backend/src/remote/activitypub/renderer/document.ts index a9d86dea1..c973de4c4 100644 --- a/packages/backend/src/remote/activitypub/renderer/document.ts +++ b/packages/backend/src/remote/activitypub/renderer/document.ts @@ -1,5 +1,5 @@ -import { DriveFile } from '@/models/entities/drive-file'; -import { DriveFiles } from '@/models/index'; +import { DriveFile } from '@/models/entities/drive-file.js'; +import { DriveFiles } from '@/models/index.js'; export default (file: DriveFile) => ({ type: 'Document', diff --git a/packages/backend/src/remote/activitypub/renderer/emoji.ts b/packages/backend/src/remote/activitypub/renderer/emoji.ts index e7ae7d959..0bf15eefd 100644 --- a/packages/backend/src/remote/activitypub/renderer/emoji.ts +++ b/packages/backend/src/remote/activitypub/renderer/emoji.ts @@ -1,5 +1,5 @@ -import config from '@/config/index'; -import { Emoji } from '@/models/entities/emoji'; +import config from '@/config/index.js'; +import { Emoji } from '@/models/entities/emoji.js'; export default (emoji: Emoji) => ({ id: `${config.url}/emojis/${emoji.name}`, diff --git a/packages/backend/src/remote/activitypub/renderer/flag.ts b/packages/backend/src/remote/activitypub/renderer/flag.ts index 60ac49650..6fbc11580 100644 --- a/packages/backend/src/remote/activitypub/renderer/flag.ts +++ b/packages/backend/src/remote/activitypub/renderer/flag.ts @@ -1,7 +1,7 @@ -import config from '@/config/index'; -import { IObject, IActivity } from '@/remote/activitypub/type'; -import { ILocalUser, IRemoteUser } from '@/models/entities/user'; -import { getInstanceActor } from '@/services/instance-actor'; +import config from '@/config/index.js'; +import { IObject, IActivity } from '@/remote/activitypub/type.js'; +import { ILocalUser, IRemoteUser } from '@/models/entities/user.js'; +import { getInstanceActor } from '@/services/instance-actor.js'; // to anonymise reporters, the reporting actor must be a system user // object has to be a uri or array of uris diff --git a/packages/backend/src/remote/activitypub/renderer/follow-relay.ts b/packages/backend/src/remote/activitypub/renderer/follow-relay.ts index 38800267b..2c9678090 100644 --- a/packages/backend/src/remote/activitypub/renderer/follow-relay.ts +++ b/packages/backend/src/remote/activitypub/renderer/follow-relay.ts @@ -1,6 +1,6 @@ -import config from '@/config/index'; -import { Relay } from '@/models/entities/relay'; -import { ILocalUser } from '@/models/entities/user'; +import config from '@/config/index.js'; +import { Relay } from '@/models/entities/relay.js'; +import { ILocalUser } from '@/models/entities/user.js'; export function renderFollowRelay(relay: Relay, relayActor: ILocalUser) { const follow = { diff --git a/packages/backend/src/remote/activitypub/renderer/follow-user.ts b/packages/backend/src/remote/activitypub/renderer/follow-user.ts index e3dde7f7f..ad1d63b93 100644 --- a/packages/backend/src/remote/activitypub/renderer/follow-user.ts +++ b/packages/backend/src/remote/activitypub/renderer/follow-user.ts @@ -1,6 +1,6 @@ -import config from '@/config/index'; -import { Users } from '@/models/index'; -import { User } from '@/models/entities/user'; +import config from '@/config/index.js'; +import { Users } from '@/models/index.js'; +import { User } from '@/models/entities/user.js'; /** * Convert (local|remote)(Follower|Followee)ID to URL diff --git a/packages/backend/src/remote/activitypub/renderer/follow.ts b/packages/backend/src/remote/activitypub/renderer/follow.ts index 5258df7e9..9e9692b77 100644 --- a/packages/backend/src/remote/activitypub/renderer/follow.ts +++ b/packages/backend/src/remote/activitypub/renderer/follow.ts @@ -1,6 +1,6 @@ -import config from '@/config/index'; -import { User } from '@/models/entities/user'; -import { Users } from '@/models/index'; +import config from '@/config/index.js'; +import { User } from '@/models/entities/user.js'; +import { Users } from '@/models/index.js'; export default (follower: { id: User['id']; host: User['host']; uri: User['host'] }, followee: { id: User['id']; host: User['host']; uri: User['host'] }, requestId?: string) => { const follow = { diff --git a/packages/backend/src/remote/activitypub/renderer/hashtag.ts b/packages/backend/src/remote/activitypub/renderer/hashtag.ts index d83a8e68b..a7b441e00 100644 --- a/packages/backend/src/remote/activitypub/renderer/hashtag.ts +++ b/packages/backend/src/remote/activitypub/renderer/hashtag.ts @@ -1,4 +1,4 @@ -import config from '@/config/index'; +import config from '@/config/index.js'; export default (tag: string) => ({ type: 'Hashtag', diff --git a/packages/backend/src/remote/activitypub/renderer/image.ts b/packages/backend/src/remote/activitypub/renderer/image.ts index ee3860be8..c7d5a31a2 100644 --- a/packages/backend/src/remote/activitypub/renderer/image.ts +++ b/packages/backend/src/remote/activitypub/renderer/image.ts @@ -1,5 +1,5 @@ -import { DriveFile } from '@/models/entities/drive-file'; -import { DriveFiles } from '@/models/index'; +import { DriveFile } from '@/models/entities/drive-file.js'; +import { DriveFiles } from '@/models/index.js'; export default (file: DriveFile) => ({ type: 'Image', diff --git a/packages/backend/src/remote/activitypub/renderer/index.ts b/packages/backend/src/remote/activitypub/renderer/index.ts index cffc9bfe0..5f6933226 100644 --- a/packages/backend/src/remote/activitypub/renderer/index.ts +++ b/packages/backend/src/remote/activitypub/renderer/index.ts @@ -1,9 +1,9 @@ -import config from '@/config/index'; +import config from '@/config/index.js'; import { v4 as uuid } from 'uuid'; -import { IActivity } from '../type'; -import { LdSignature } from '../misc/ld-signature'; -import { getUserKeypair } from '@/misc/keypair-store'; -import { User } from '@/models/entities/user'; +import { IActivity } from '../type.js'; +import { LdSignature } from '../misc/ld-signature.js'; +import { getUserKeypair } from '@/misc/keypair-store.js'; +import { User } from '@/models/entities/user.js'; export const renderActivity = (x: any): IActivity | null => { if (x == null) return null; diff --git a/packages/backend/src/remote/activitypub/renderer/key.ts b/packages/backend/src/remote/activitypub/renderer/key.ts index 51bc888dd..c4f3d464f 100644 --- a/packages/backend/src/remote/activitypub/renderer/key.ts +++ b/packages/backend/src/remote/activitypub/renderer/key.ts @@ -1,7 +1,7 @@ -import config from '@/config/index'; -import { ILocalUser } from '@/models/entities/user'; -import { UserKeypair } from '@/models/entities/user-keypair'; -import { createPublicKey } from 'crypto'; +import config from '@/config/index.js'; +import { ILocalUser } from '@/models/entities/user.js'; +import { UserKeypair } from '@/models/entities/user-keypair.js'; +import { createPublicKey } from 'node:crypto'; export default (user: ILocalUser, key: UserKeypair, postfix?: string) => ({ id: `${config.url}/users/${user.id}${postfix || '/publickey'}`, diff --git a/packages/backend/src/remote/activitypub/renderer/like.ts b/packages/backend/src/remote/activitypub/renderer/like.ts index 2e4da9d26..1bf36d470 100644 --- a/packages/backend/src/remote/activitypub/renderer/like.ts +++ b/packages/backend/src/remote/activitypub/renderer/like.ts @@ -1,8 +1,8 @@ -import config from '@/config/index'; -import { NoteReaction } from '@/models/entities/note-reaction'; -import { Note } from '@/models/entities/note'; -import { Emojis } from '@/models/index'; -import renderEmoji from './emoji'; +import config from '@/config/index.js'; +import { NoteReaction } from '@/models/entities/note-reaction.js'; +import { Note } from '@/models/entities/note.js'; +import { Emojis } from '@/models/index.js'; +import renderEmoji from './emoji.js'; export const renderLike = async (noteReaction: NoteReaction, note: Note) => { const reaction = noteReaction.reaction; diff --git a/packages/backend/src/remote/activitypub/renderer/mention.ts b/packages/backend/src/remote/activitypub/renderer/mention.ts index 06d2d33e5..c7e62e884 100644 --- a/packages/backend/src/remote/activitypub/renderer/mention.ts +++ b/packages/backend/src/remote/activitypub/renderer/mention.ts @@ -1,6 +1,6 @@ -import config from '@/config/index'; -import { User, ILocalUser } from '@/models/entities/user'; -import { Users } from '@/models/index'; +import config from '@/config/index.js'; +import { User, ILocalUser } from '@/models/entities/user.js'; +import { Users } from '@/models/index.js'; export default (mention: User) => ({ type: 'Mention', diff --git a/packages/backend/src/remote/activitypub/renderer/note.ts b/packages/backend/src/remote/activitypub/renderer/note.ts index 654ab6812..c3d9e120d 100644 --- a/packages/backend/src/remote/activitypub/renderer/note.ts +++ b/packages/backend/src/remote/activitypub/renderer/note.ts @@ -1,15 +1,15 @@ -import renderDocument from './document'; -import renderHashtag from './hashtag'; -import renderMention from './mention'; -import renderEmoji from './emoji'; -import config from '@/config/index'; -import toHtml from '../misc/get-note-html'; -import { Note, IMentionedRemoteUsers } from '@/models/entities/note'; -import { DriveFile } from '@/models/entities/drive-file'; -import { DriveFiles, Notes, Users, Emojis, Polls } from '@/models/index'; +import renderDocument from './document.js'; +import renderHashtag from './hashtag.js'; +import renderMention from './mention.js'; +import renderEmoji from './emoji.js'; +import config from '@/config/index.js'; +import toHtml from '../misc/get-note-html.js'; +import { Note, IMentionedRemoteUsers } from '@/models/entities/note.js'; +import { DriveFile } from '@/models/entities/drive-file.js'; +import { DriveFiles, Notes, Users, Emojis, Polls } from '@/models/index.js'; import { In } from 'typeorm'; -import { Emoji } from '@/models/entities/emoji'; -import { Poll } from '@/models/entities/poll'; +import { Emoji } from '@/models/entities/emoji.js'; +import { Poll } from '@/models/entities/poll.js'; export default async function renderNote(note: Note, dive = true, isTalk = false): Promise> { const getPromisedFiles = async (ids: string[]) => { diff --git a/packages/backend/src/remote/activitypub/renderer/person.ts b/packages/backend/src/remote/activitypub/renderer/person.ts index d1c4c0040..3d86e37cc 100644 --- a/packages/backend/src/remote/activitypub/renderer/person.ts +++ b/packages/backend/src/remote/activitypub/renderer/person.ts @@ -1,16 +1,16 @@ -import { URL } from 'url'; +import { URL } from 'node:url'; import * as mfm from 'mfm-js'; -import renderImage from './image'; -import renderKey from './key'; -import config from '@/config/index'; -import { ILocalUser } from '@/models/entities/user'; -import { toHtml } from '../../../mfm/to-html'; -import { getEmojis } from './note'; -import renderEmoji from './emoji'; -import { IIdentifier } from '../models/identifier'; -import renderHashtag from './hashtag'; -import { DriveFiles, UserProfiles } from '@/models/index'; -import { getUserKeypair } from '@/misc/keypair-store'; +import renderImage from './image.js'; +import renderKey from './key.js'; +import config from '@/config/index.js'; +import { ILocalUser } from '@/models/entities/user.js'; +import { toHtml } from '../../../mfm/to-html.js'; +import { getEmojis } from './note.js'; +import renderEmoji from './emoji.js'; +import { IIdentifier } from '../models/identifier.js'; +import renderHashtag from './hashtag.js'; +import { DriveFiles, UserProfiles } from '@/models/index.js'; +import { getUserKeypair } from '@/misc/keypair-store.js'; export async function renderPerson(user: ILocalUser) { const id = `${config.url}/users/${user.id}`; diff --git a/packages/backend/src/remote/activitypub/renderer/question.ts b/packages/backend/src/remote/activitypub/renderer/question.ts index 3cbff33ab..d4d1b590a 100644 --- a/packages/backend/src/remote/activitypub/renderer/question.ts +++ b/packages/backend/src/remote/activitypub/renderer/question.ts @@ -1,7 +1,7 @@ -import config from '@/config/index'; -import { User } from '@/models/entities/user'; -import { Note } from '@/models/entities/note'; -import { Poll } from '@/models/entities/poll'; +import config from '@/config/index.js'; +import { User } from '@/models/entities/user.js'; +import { Note } from '@/models/entities/note.js'; +import { Poll } from '@/models/entities/poll.js'; export default async function renderQuestion(user: { id: User['id'] }, note: Note, poll: Poll) { const question = { diff --git a/packages/backend/src/remote/activitypub/renderer/read.ts b/packages/backend/src/remote/activitypub/renderer/read.ts index 2fe3b8e5e..a30e649f6 100644 --- a/packages/backend/src/remote/activitypub/renderer/read.ts +++ b/packages/backend/src/remote/activitypub/renderer/read.ts @@ -1,6 +1,6 @@ -import config from '@/config/index'; -import { User } from '@/models/entities/user'; -import { MessagingMessage } from '@/models/entities/messaging-message'; +import config from '@/config/index.js'; +import { User } from '@/models/entities/user.js'; +import { MessagingMessage } from '@/models/entities/messaging-message.js'; export const renderReadActivity = (user: { id: User['id'] }, message: MessagingMessage) => ({ type: 'Read', diff --git a/packages/backend/src/remote/activitypub/renderer/reject.ts b/packages/backend/src/remote/activitypub/renderer/reject.ts index 575ef52ab..ab4cc1646 100644 --- a/packages/backend/src/remote/activitypub/renderer/reject.ts +++ b/packages/backend/src/remote/activitypub/renderer/reject.ts @@ -1,5 +1,5 @@ -import config from '@/config/index'; -import { User } from '@/models/entities/user'; +import config from '@/config/index.js'; +import { User } from '@/models/entities/user.js'; export default (object: any, user: { id: User['id'] }) => ({ type: 'Reject', diff --git a/packages/backend/src/remote/activitypub/renderer/remove.ts b/packages/backend/src/remote/activitypub/renderer/remove.ts index 8afaf199c..1be3edc5d 100644 --- a/packages/backend/src/remote/activitypub/renderer/remove.ts +++ b/packages/backend/src/remote/activitypub/renderer/remove.ts @@ -1,5 +1,5 @@ -import config from '@/config/index'; -import { User } from '@/models/entities/user'; +import config from '@/config/index.js'; +import { User } from '@/models/entities/user.js'; export default (user: { id: User['id'] }, target: any, object: any) => ({ type: 'Remove', diff --git a/packages/backend/src/remote/activitypub/renderer/undo.ts b/packages/backend/src/remote/activitypub/renderer/undo.ts index 14115b788..d28778e22 100644 --- a/packages/backend/src/remote/activitypub/renderer/undo.ts +++ b/packages/backend/src/remote/activitypub/renderer/undo.ts @@ -1,5 +1,5 @@ -import config from '@/config/index'; -import { ILocalUser, User } from '@/models/entities/user'; +import config from '@/config/index.js'; +import { ILocalUser, User } from '@/models/entities/user.js'; export default (object: any, user: { id: User['id'] }) => { if (object == null) return null; diff --git a/packages/backend/src/remote/activitypub/renderer/update.ts b/packages/backend/src/remote/activitypub/renderer/update.ts index 8bb415d11..cf880f03f 100644 --- a/packages/backend/src/remote/activitypub/renderer/update.ts +++ b/packages/backend/src/remote/activitypub/renderer/update.ts @@ -1,5 +1,5 @@ -import config from '@/config/index'; -import { User } from '@/models/entities/user'; +import config from '@/config/index.js'; +import { User } from '@/models/entities/user.js'; export default (object: any, user: { id: User['id'] }) => { const activity = { diff --git a/packages/backend/src/remote/activitypub/renderer/vote.ts b/packages/backend/src/remote/activitypub/renderer/vote.ts index fd7bc9dbe..b6eb8e095 100644 --- a/packages/backend/src/remote/activitypub/renderer/vote.ts +++ b/packages/backend/src/remote/activitypub/renderer/vote.ts @@ -1,8 +1,8 @@ -import config from '@/config/index'; -import { Note } from '@/models/entities/note'; -import { IRemoteUser, User } from '@/models/entities/user'; -import { PollVote } from '@/models/entities/poll-vote'; -import { Poll } from '@/models/entities/poll'; +import config from '@/config/index.js'; +import { Note } from '@/models/entities/note.js'; +import { IRemoteUser, User } from '@/models/entities/user.js'; +import { PollVote } from '@/models/entities/poll-vote.js'; +import { Poll } from '@/models/entities/poll.js'; export default async function renderVote(user: { id: User['id'] }, vote: PollVote, note: Note, poll: Poll, pollOwner: IRemoteUser): Promise { return { diff --git a/packages/backend/src/remote/activitypub/request.ts b/packages/backend/src/remote/activitypub/request.ts index 715937e2a..5cbfd8c25 100644 --- a/packages/backend/src/remote/activitypub/request.ts +++ b/packages/backend/src/remote/activitypub/request.ts @@ -1,8 +1,8 @@ -import config from '@/config/index'; -import { getUserKeypair } from '@/misc/keypair-store'; -import { User } from '@/models/entities/user'; -import { getResponse } from '../../misc/fetch'; -import { createSignedPost, createSignedGet } from './ap-request'; +import config from '@/config/index.js'; +import { getUserKeypair } from '@/misc/keypair-store.js'; +import { User } from '@/models/entities/user.js'; +import { getResponse } from '../../misc/fetch.js'; +import { createSignedPost, createSignedGet } from './ap-request.js'; export default async (user: { id: User['id'] }, url: string, object: any) => { const body = JSON.stringify(object); diff --git a/packages/backend/src/remote/activitypub/resolver.ts b/packages/backend/src/remote/activitypub/resolver.ts index f392a65e3..c1269c75c 100644 --- a/packages/backend/src/remote/activitypub/resolver.ts +++ b/packages/backend/src/remote/activitypub/resolver.ts @@ -1,11 +1,11 @@ -import config from '@/config/index'; -import { getJson } from '@/misc/fetch'; -import { ILocalUser } from '@/models/entities/user'; -import { getInstanceActor } from '@/services/instance-actor'; -import { signedGet } from './request'; -import { IObject, isCollectionOrOrderedCollection, ICollection, IOrderedCollection } from './type'; -import { fetchMeta } from '@/misc/fetch-meta'; -import { extractDbHost } from '@/misc/convert-host'; +import config from '@/config/index.js'; +import { getJson } from '@/misc/fetch.js'; +import { ILocalUser } from '@/models/entities/user.js'; +import { getInstanceActor } from '@/services/instance-actor.js'; +import { signedGet } from './request.js'; +import { IObject, isCollectionOrOrderedCollection, ICollection, IOrderedCollection } from './type.js'; +import { fetchMeta } from '@/misc/fetch-meta.js'; +import { extractDbHost } from '@/misc/convert-host.js'; export default class Resolver { private history: Set; diff --git a/packages/backend/src/remote/logger.ts b/packages/backend/src/remote/logger.ts index 9ffad4d71..4921f53bd 100644 --- a/packages/backend/src/remote/logger.ts +++ b/packages/backend/src/remote/logger.ts @@ -1,3 +1,3 @@ -import Logger from '@/services/logger'; +import Logger from '@/services/logger.js'; export const remoteLogger = new Logger('remote', 'cyan'); diff --git a/packages/backend/src/remote/resolve-user.ts b/packages/backend/src/remote/resolve-user.ts index 747735eca..aa37013c4 100644 --- a/packages/backend/src/remote/resolve-user.ts +++ b/packages/backend/src/remote/resolve-user.ts @@ -1,12 +1,12 @@ -import { URL } from 'url'; -import webFinger from './webfinger'; -import config from '@/config/index'; -import { createPerson, updatePerson } from './activitypub/models/person'; -import { remoteLogger } from './logger'; -import * as chalk from 'chalk'; -import { User, IRemoteUser } from '@/models/entities/user'; -import { Users } from '@/models/index'; -import { toPuny } from '@/misc/convert-host'; +import { URL } from 'node:url'; +import webFinger from './webfinger.js'; +import config from '@/config/index.js'; +import { createPerson, updatePerson } from './activitypub/models/person.js'; +import { remoteLogger } from './logger.js'; +import chalk from 'chalk'; +import { User, IRemoteUser } from '@/models/entities/user.js'; +import { Users } from '@/models/index.js'; +import { toPuny } from '@/misc/convert-host.js'; const logger = remoteLogger.createSubLogger('resolve-user'); @@ -26,7 +26,7 @@ export async function resolveUser(username: string, host: string | null, option? host = toPuny(host); - if (config.host == host) { + if (config.host === host) { logger.info(`return local user: ${usernameLower}`); return await Users.findOne({ usernameLower, host: null }).then(u => { if (u == null) { diff --git a/packages/backend/src/remote/webfinger.ts b/packages/backend/src/remote/webfinger.ts index f63fd0362..9d3bfab24 100644 --- a/packages/backend/src/remote/webfinger.ts +++ b/packages/backend/src/remote/webfinger.ts @@ -1,6 +1,6 @@ -import { URL } from 'url'; -import { getJson } from '@/misc/fetch'; -import { query as urlQuery } from '@/prelude/url'; +import { URL } from 'node:url'; +import { getJson } from '@/misc/fetch.js'; +import { query as urlQuery } from '@/prelude/url.js'; type ILink = { href: string; diff --git a/packages/backend/src/server/activitypub.ts b/packages/backend/src/server/activitypub.ts index bbbc231b8..21be0a251 100644 --- a/packages/backend/src/server/activitypub.ts +++ b/packages/backend/src/server/activitypub.ts @@ -1,23 +1,23 @@ -import * as Router from '@koa/router'; -import * as json from 'koa-json-body'; -import * as httpSignature from 'http-signature'; +import Router from '@koa/router'; +import json from 'koa-json-body'; +import httpSignature from 'http-signature'; -import { renderActivity } from '@/remote/activitypub/renderer/index'; -import renderNote from '@/remote/activitypub/renderer/note'; -import renderKey from '@/remote/activitypub/renderer/key'; -import { renderPerson } from '@/remote/activitypub/renderer/person'; -import renderEmoji from '@/remote/activitypub/renderer/emoji'; -import Outbox, { packActivity } from './activitypub/outbox'; -import Followers from './activitypub/followers'; -import Following from './activitypub/following'; -import Featured from './activitypub/featured'; -import { inbox as processInbox } from '@/queue/index'; -import { isSelfHost } from '@/misc/convert-host'; -import { Notes, Users, Emojis, NoteReactions } from '@/models/index'; -import { ILocalUser, User } from '@/models/entities/user'; +import { renderActivity } from '@/remote/activitypub/renderer/index.js'; +import renderNote from '@/remote/activitypub/renderer/note.js'; +import renderKey from '@/remote/activitypub/renderer/key.js'; +import { renderPerson } from '@/remote/activitypub/renderer/person.js'; +import renderEmoji from '@/remote/activitypub/renderer/emoji.js'; +import Outbox, { packActivity } from './activitypub/outbox.js'; +import Followers from './activitypub/followers.js'; +import Following from './activitypub/following.js'; +import Featured from './activitypub/featured.js'; +import { inbox as processInbox } from '@/queue/index.js'; +import { isSelfHost } from '@/misc/convert-host.js'; +import { Notes, Users, Emojis, NoteReactions } from '@/models/index.js'; +import { ILocalUser, User } from '@/models/entities/user.js'; import { In } from 'typeorm'; -import { renderLike } from '@/remote/activitypub/renderer/like'; -import { getUserKeypair } from '@/misc/keypair-store'; +import { renderLike } from '@/remote/activitypub/renderer/like.js'; +import { getUserKeypair } from '@/misc/keypair-store.js'; // Init router const router = new Router(); diff --git a/packages/backend/src/server/activitypub/featured.ts b/packages/backend/src/server/activitypub/featured.ts index ed5bfc426..129881a71 100644 --- a/packages/backend/src/server/activitypub/featured.ts +++ b/packages/backend/src/server/activitypub/featured.ts @@ -1,10 +1,10 @@ -import * as Router from '@koa/router'; -import config from '@/config/index'; -import { renderActivity } from '@/remote/activitypub/renderer/index'; -import renderOrderedCollection from '@/remote/activitypub/renderer/ordered-collection'; -import { setResponseType } from '../activitypub'; -import renderNote from '@/remote/activitypub/renderer/note'; -import { Users, Notes, UserNotePinings } from '@/models/index'; +import Router from '@koa/router'; +import config from '@/config/index.js'; +import { renderActivity } from '@/remote/activitypub/renderer/index.js'; +import renderOrderedCollection from '@/remote/activitypub/renderer/ordered-collection.js'; +import { setResponseType } from '../activitypub.js'; +import renderNote from '@/remote/activitypub/renderer/note.js'; +import { Users, Notes, UserNotePinings } from '@/models/index.js'; export default async (ctx: Router.RouterContext) => { const userId = ctx.params.user; diff --git a/packages/backend/src/server/activitypub/followers.ts b/packages/backend/src/server/activitypub/followers.ts index 927fb5d18..5d1d7c59e 100644 --- a/packages/backend/src/server/activitypub/followers.ts +++ b/packages/backend/src/server/activitypub/followers.ts @@ -1,24 +1,24 @@ -import * as Router from '@koa/router'; -import config from '@/config/index'; +import Router from '@koa/router'; +import config from '@/config/index.js'; import $ from 'cafy'; -import { ID } from '@/misc/cafy-id'; -import * as url from '@/prelude/url'; -import { renderActivity } from '@/remote/activitypub/renderer/index'; -import renderOrderedCollection from '@/remote/activitypub/renderer/ordered-collection'; -import renderOrderedCollectionPage from '@/remote/activitypub/renderer/ordered-collection-page'; -import renderFollowUser from '@/remote/activitypub/renderer/follow-user'; -import { setResponseType } from '../activitypub'; -import { Users, Followings, UserProfiles } from '@/models/index'; +import { ID } from '@/misc/cafy-id.js'; +import * as url from '@/prelude/url.js'; +import { renderActivity } from '@/remote/activitypub/renderer/index.js'; +import renderOrderedCollection from '@/remote/activitypub/renderer/ordered-collection.js'; +import renderOrderedCollectionPage from '@/remote/activitypub/renderer/ordered-collection-page.js'; +import renderFollowUser from '@/remote/activitypub/renderer/follow-user.js'; +import { setResponseType } from '../activitypub.js'; +import { Users, Followings, UserProfiles } from '@/models/index.js'; import { LessThan } from 'typeorm'; export default async (ctx: Router.RouterContext) => { const userId = ctx.params.user; // Get 'cursor' parameter - const [cursor, cursorErr] = $.optional.type(ID).get(ctx.request.query.cursor); + const [cursor, cursorErr] = $.default.optional.type(ID).get(ctx.request.query.cursor); // Get 'page' parameter - const pageErr = !$.optional.str.or(['true', 'false']).ok(ctx.request.query.page); + const pageErr = !$.default.optional.str.or(['true', 'false']).ok(ctx.request.query.page); const page: boolean = ctx.request.query.page === 'true'; // Validate parameters diff --git a/packages/backend/src/server/activitypub/following.ts b/packages/backend/src/server/activitypub/following.ts index a3237582a..23110ce87 100644 --- a/packages/backend/src/server/activitypub/following.ts +++ b/packages/backend/src/server/activitypub/following.ts @@ -1,25 +1,25 @@ -import * as Router from '@koa/router'; -import config from '@/config/index'; +import Router from '@koa/router'; +import config from '@/config/index.js'; import $ from 'cafy'; -import { ID } from '@/misc/cafy-id'; -import * as url from '@/prelude/url'; -import { renderActivity } from '@/remote/activitypub/renderer/index'; -import renderOrderedCollection from '@/remote/activitypub/renderer/ordered-collection'; -import renderOrderedCollectionPage from '@/remote/activitypub/renderer/ordered-collection-page'; -import renderFollowUser from '@/remote/activitypub/renderer/follow-user'; -import { setResponseType } from '../activitypub'; -import { Users, Followings, UserProfiles } from '@/models/index'; +import { ID } from '@/misc/cafy-id.js'; +import * as url from '@/prelude/url.js'; +import { renderActivity } from '@/remote/activitypub/renderer/index.js'; +import renderOrderedCollection from '@/remote/activitypub/renderer/ordered-collection.js'; +import renderOrderedCollectionPage from '@/remote/activitypub/renderer/ordered-collection-page.js'; +import renderFollowUser from '@/remote/activitypub/renderer/follow-user.js'; +import { setResponseType } from '../activitypub.js'; +import { Users, Followings, UserProfiles } from '@/models/index.js'; import { LessThan, FindConditions } from 'typeorm'; -import { Following } from '@/models/entities/following'; +import { Following } from '@/models/entities/following.js'; export default async (ctx: Router.RouterContext) => { const userId = ctx.params.user; // Get 'cursor' parameter - const [cursor, cursorErr] = $.optional.type(ID).get(ctx.request.query.cursor); + const [cursor, cursorErr] = $.default.optional.type(ID).get(ctx.request.query.cursor); // Get 'page' parameter - const pageErr = !$.optional.str.or(['true', 'false']).ok(ctx.request.query.page); + const pageErr = !$.default.optional.str.or(['true', 'false']).ok(ctx.request.query.page); const page: boolean = ctx.request.query.page === 'true'; // Validate parameters diff --git a/packages/backend/src/server/activitypub/outbox.ts b/packages/backend/src/server/activitypub/outbox.ts index ba6b46a0c..57c126752 100644 --- a/packages/backend/src/server/activitypub/outbox.ts +++ b/packages/backend/src/server/activitypub/outbox.ts @@ -1,32 +1,32 @@ -import * as Router from '@koa/router'; -import config from '@/config/index'; +import Router from '@koa/router'; +import config from '@/config/index.js'; import $ from 'cafy'; -import { ID } from '@/misc/cafy-id'; -import { renderActivity } from '@/remote/activitypub/renderer/index'; -import renderOrderedCollection from '@/remote/activitypub/renderer/ordered-collection'; -import renderOrderedCollectionPage from '@/remote/activitypub/renderer/ordered-collection-page'; -import { setResponseType } from '../activitypub'; -import renderNote from '@/remote/activitypub/renderer/note'; -import renderCreate from '@/remote/activitypub/renderer/create'; -import renderAnnounce from '@/remote/activitypub/renderer/announce'; -import { countIf } from '@/prelude/array'; -import * as url from '@/prelude/url'; -import { Users, Notes } from '@/models/index'; -import { makePaginationQuery } from '../api/common/make-pagination-query'; +import { ID } from '@/misc/cafy-id.js'; +import { renderActivity } from '@/remote/activitypub/renderer/index.js'; +import renderOrderedCollection from '@/remote/activitypub/renderer/ordered-collection.js'; +import renderOrderedCollectionPage from '@/remote/activitypub/renderer/ordered-collection-page.js'; +import { setResponseType } from '../activitypub.js'; +import renderNote from '@/remote/activitypub/renderer/note.js'; +import renderCreate from '@/remote/activitypub/renderer/create.js'; +import renderAnnounce from '@/remote/activitypub/renderer/announce.js'; +import { countIf } from '@/prelude/array.js'; +import * as url from '@/prelude/url.js'; +import { Users, Notes } from '@/models/index.js'; +import { makePaginationQuery } from '../api/common/make-pagination-query.js'; import { Brackets } from 'typeorm'; -import { Note } from '@/models/entities/note'; +import { Note } from '@/models/entities/note.js'; export default async (ctx: Router.RouterContext) => { const userId = ctx.params.user; // Get 'sinceId' parameter - const [sinceId, sinceIdErr] = $.optional.type(ID).get(ctx.request.query.since_id); + const [sinceId, sinceIdErr] = $.default.optional.type(ID).get(ctx.request.query.since_id); // Get 'untilId' parameter - const [untilId, untilIdErr] = $.optional.type(ID).get(ctx.request.query.until_id); + const [untilId, untilIdErr] = $.default.optional.type(ID).get(ctx.request.query.until_id); // Get 'page' parameter - const pageErr = !$.optional.str.or(['true', 'false']).ok(ctx.request.query.page); + const pageErr = !$.default.optional.str.or(['true', 'false']).ok(ctx.request.query.page); const page: boolean = ctx.request.query.page === 'true'; // Validate parameters diff --git a/packages/backend/src/server/api/2fa.ts b/packages/backend/src/server/api/2fa.ts index 2a69e49c8..e1c226979 100644 --- a/packages/backend/src/server/api/2fa.ts +++ b/packages/backend/src/server/api/2fa.ts @@ -1,5 +1,5 @@ -import * as crypto from 'crypto'; -import config from '@/config/index'; +import * as crypto from 'node:crypto'; +import config from '@/config/index.js'; import * as jsrsasign from 'jsrsasign'; const ECC_PRELUDE = Buffer.from([0x04]); diff --git a/packages/backend/src/server/api/api-handler.ts b/packages/backend/src/server/api/api-handler.ts index 362bbb0f5..f97c3dd39 100644 --- a/packages/backend/src/server/api/api-handler.ts +++ b/packages/backend/src/server/api/api-handler.ts @@ -1,11 +1,11 @@ -import * as Koa from 'koa'; +import Koa from 'koa'; -import { IEndpoint } from './endpoints'; -import authenticate, { AuthenticationError } from './authenticate'; -import call from './call'; -import { ApiError } from './error'; +import { IEndpoint } from './endpoints.js'; +import authenticate, { AuthenticationError } from './authenticate.js'; +import call from './call.js'; +import { ApiError } from './error.js'; -export default (endpoint: IEndpoint, ctx: Koa.Context) => new Promise((res) => { +export default (endpoint: IEndpoint, ctx: Koa.Context) => new Promise((res) => { const body = ctx.request.body; const reply = (x?: any, y?: ApiError) => { diff --git a/packages/backend/src/server/api/authenticate.ts b/packages/backend/src/server/api/authenticate.ts index 9e2f3eb74..7fdf14666 100644 --- a/packages/backend/src/server/api/authenticate.ts +++ b/packages/backend/src/server/api/authenticate.ts @@ -1,7 +1,7 @@ -import isNativeToken from './common/is-native-token'; -import { User } from '@/models/entities/user'; -import { Users, AccessTokens, Apps } from '@/models/index'; -import { AccessToken } from '@/models/entities/access-token'; +import isNativeToken from './common/is-native-token.js'; +import { User } from '@/models/entities/user.js'; +import { Users, AccessTokens, Apps } from '@/models/index.js'; +import { AccessToken } from '@/models/entities/access-token.js'; export class AuthenticationError extends Error { constructor(message: string) { diff --git a/packages/backend/src/server/api/call.ts b/packages/backend/src/server/api/call.ts index 18143340a..5c5ef6601 100644 --- a/packages/backend/src/server/api/call.ts +++ b/packages/backend/src/server/api/call.ts @@ -1,11 +1,11 @@ -import * as Koa from 'koa'; +import Koa from 'koa'; import { performance } from 'perf_hooks'; -import { limiter } from './limiter'; -import { User } from '@/models/entities/user'; -import endpoints from './endpoints'; -import { ApiError } from './error'; -import { apiLogger } from './logger'; -import { AccessToken } from '@/models/entities/access-token'; +import { limiter } from './limiter.js'; +import { User } from '@/models/entities/user.js'; +import endpoints, { IEndpoint } from './endpoints.js'; +import { ApiError } from './error.js'; +import { apiLogger } from './logger.js'; +import { AccessToken } from '@/models/entities/access-token.js'; const accessDenied = { message: 'Access denied.', @@ -67,7 +67,7 @@ export default async (endpoint: string, user: User | null | undefined, token: Ac if (ep.meta.requireCredential && ep.meta.limit && !user!.isAdmin && !user!.isModerator) { // Rate limit - await limiter(ep, user!).catch(e => { + await limiter(ep as IEndpoint & { meta: { limit: NonNullable } }, user!).catch(e => { throw new ApiError({ message: 'Rate limit exceeded. Please try again later.', code: 'RATE_LIMIT_EXCEEDED', @@ -78,10 +78,10 @@ export default async (endpoint: string, user: User | null | undefined, token: Ac } // Cast non JSON input - if (ep.meta.requireFile && ep.meta.params) { - for (const k of Object.keys(ep.meta.params)) { - const param = ep.meta.params[k]; - if (['Boolean', 'Number'].includes(param.validator.name) && typeof data[k] === 'string') { + if (ep.meta.requireFile && ep.params.properties) { + for (const k of Object.keys(ep.params.properties)) { + const param = ep.params.properties![k]; + if (['boolean', 'number', 'integer'].includes(param.type ?? '') && typeof data[k] === 'string') { try { data[k] = JSON.parse(data[k]); } catch (e) { @@ -91,8 +91,8 @@ export default async (endpoint: string, user: User | null | undefined, token: Ac id: '0b5f1631-7c1a-41a6-b399-cce335f34d85', }, { param: k, - reason: `cannot cast to ${param.validator.name}`, - }) + reason: `cannot cast to ${param.type}`, + }); } } } diff --git a/packages/backend/src/server/api/common/generate-block-query.ts b/packages/backend/src/server/api/common/generate-block-query.ts index 4fd618473..60db1e731 100644 --- a/packages/backend/src/server/api/common/generate-block-query.ts +++ b/packages/backend/src/server/api/common/generate-block-query.ts @@ -1,5 +1,5 @@ -import { User } from '@/models/entities/user'; -import { Blockings } from '@/models/index'; +import { User } from '@/models/entities/user.js'; +import { Blockings } from '@/models/index.js'; import { Brackets, SelectQueryBuilder } from 'typeorm'; // ここでいうBlockedは被Blockedの意 diff --git a/packages/backend/src/server/api/common/generate-channel-query.ts b/packages/backend/src/server/api/common/generate-channel-query.ts index 80a0acf7f..333bb73b8 100644 --- a/packages/backend/src/server/api/common/generate-channel-query.ts +++ b/packages/backend/src/server/api/common/generate-channel-query.ts @@ -1,5 +1,5 @@ -import { User } from '@/models/entities/user'; -import { ChannelFollowings } from '@/models/index'; +import { User } from '@/models/entities/user.js'; +import { ChannelFollowings } from '@/models/index.js'; import { Brackets, SelectQueryBuilder } from 'typeorm'; export function generateChannelQuery(q: SelectQueryBuilder, me?: { id: User['id'] } | null) { diff --git a/packages/backend/src/server/api/common/generate-muted-instance-query.ts b/packages/backend/src/server/api/common/generate-muted-instance-query.ts index dbc9fc98f..72a6fec68 100644 --- a/packages/backend/src/server/api/common/generate-muted-instance-query.ts +++ b/packages/backend/src/server/api/common/generate-muted-instance-query.ts @@ -1,6 +1,6 @@ -import { User } from '@/models/entities/user'; -import { id } from '@/models/id'; -import { UserProfiles } from '@/models/index'; +import { User } from '@/models/entities/user.js'; +import { id } from '@/models/id.js'; +import { UserProfiles } from '@/models/index.js'; import { SelectQueryBuilder, Brackets } from 'typeorm'; function createMutesQuery(id: string) { diff --git a/packages/backend/src/server/api/common/generate-muted-note-query.ts b/packages/backend/src/server/api/common/generate-muted-note-query.ts index 073784261..f544e334d 100644 --- a/packages/backend/src/server/api/common/generate-muted-note-query.ts +++ b/packages/backend/src/server/api/common/generate-muted-note-query.ts @@ -1,5 +1,5 @@ -import { User } from '@/models/entities/user'; -import { MutedNotes } from '@/models/index'; +import { User } from '@/models/entities/user.js'; +import { MutedNotes } from '@/models/index.js'; import { SelectQueryBuilder } from 'typeorm'; export function generateMutedNoteQuery(q: SelectQueryBuilder, me: { id: User['id'] }) { diff --git a/packages/backend/src/server/api/common/generate-muted-note-thread-query.ts b/packages/backend/src/server/api/common/generate-muted-note-thread-query.ts index 7e2cbd498..7263ea2e6 100644 --- a/packages/backend/src/server/api/common/generate-muted-note-thread-query.ts +++ b/packages/backend/src/server/api/common/generate-muted-note-thread-query.ts @@ -1,5 +1,5 @@ -import { User } from '@/models/entities/user'; -import { NoteThreadMutings } from '@/models/index'; +import { User } from '@/models/entities/user.js'; +import { NoteThreadMutings } from '@/models/index.js'; import { Brackets, SelectQueryBuilder } from 'typeorm'; export function generateMutedNoteThreadQuery(q: SelectQueryBuilder, me: { id: User['id'] }) { diff --git a/packages/backend/src/server/api/common/generate-muted-user-query.ts b/packages/backend/src/server/api/common/generate-muted-user-query.ts index 7e200b87e..79cb3ff89 100644 --- a/packages/backend/src/server/api/common/generate-muted-user-query.ts +++ b/packages/backend/src/server/api/common/generate-muted-user-query.ts @@ -1,5 +1,5 @@ -import { User } from '@/models/entities/user'; -import { Mutings } from '@/models/index'; +import { User } from '@/models/entities/user.js'; +import { Mutings } from '@/models/index.js'; import { SelectQueryBuilder, Brackets } from 'typeorm'; export function generateMutedUserQuery(q: SelectQueryBuilder, me: { id: User['id'] }, exclude?: User) { diff --git a/packages/backend/src/server/api/common/generate-native-user-token.ts b/packages/backend/src/server/api/common/generate-native-user-token.ts index 1f791c57c..5d8a4c537 100644 --- a/packages/backend/src/server/api/common/generate-native-user-token.ts +++ b/packages/backend/src/server/api/common/generate-native-user-token.ts @@ -1,3 +1,3 @@ -import { secureRndstr } from '@/misc/secure-rndstr'; +import { secureRndstr } from '@/misc/secure-rndstr.js'; export default () => secureRndstr(16, true); diff --git a/packages/backend/src/server/api/common/generate-replies-query.ts b/packages/backend/src/server/api/common/generate-replies-query.ts index 249064d58..301782eab 100644 --- a/packages/backend/src/server/api/common/generate-replies-query.ts +++ b/packages/backend/src/server/api/common/generate-replies-query.ts @@ -1,4 +1,4 @@ -import { User } from '@/models/entities/user'; +import { User } from '@/models/entities/user.js'; import { Brackets, SelectQueryBuilder } from 'typeorm'; export function generateRepliesQuery(q: SelectQueryBuilder, me?: Pick | null) { @@ -10,7 +10,7 @@ export function generateRepliesQuery(q: SelectQueryBuilder, me?: Pick { qb .where(`note.replyId IS NULL`) // 返信ではない .orWhere('note.replyUserId = :meId', { meId: me.id }) // 返信だけど自分のノートへの返信 diff --git a/packages/backend/src/server/api/common/generate-visibility-query.ts b/packages/backend/src/server/api/common/generate-visibility-query.ts index 813e8b6c0..715982934 100644 --- a/packages/backend/src/server/api/common/generate-visibility-query.ts +++ b/packages/backend/src/server/api/common/generate-visibility-query.ts @@ -1,5 +1,5 @@ -import { User } from '@/models/entities/user'; -import { Followings } from '@/models/index'; +import { User } from '@/models/entities/user.js'; +import { Followings } from '@/models/index.js'; import { Brackets, SelectQueryBuilder } from 'typeorm'; export function generateVisibilityQuery(q: SelectQueryBuilder, me?: { id: User['id'] } | null) { diff --git a/packages/backend/src/server/api/common/getters.ts b/packages/backend/src/server/api/common/getters.ts index 4b2ee8f1d..c5a47876d 100644 --- a/packages/backend/src/server/api/common/getters.ts +++ b/packages/backend/src/server/api/common/getters.ts @@ -1,7 +1,7 @@ -import { IdentifiableError } from '@/misc/identifiable-error'; -import { User } from '@/models/entities/user'; -import { Note } from '@/models/entities/note'; -import { Notes, Users } from '@/models/index'; +import { IdentifiableError } from '@/misc/identifiable-error.js'; +import { User } from '@/models/entities/user.js'; +import { Note } from '@/models/entities/note.js'; +import { Notes, Users } from '@/models/index.js'; /** * Get note for API processing diff --git a/packages/backend/src/server/api/common/inject-featured.ts b/packages/backend/src/server/api/common/inject-featured.ts index 1dc13c83e..b7dd8028b 100644 --- a/packages/backend/src/server/api/common/inject-featured.ts +++ b/packages/backend/src/server/api/common/inject-featured.ts @@ -1,9 +1,9 @@ import rndstr from 'rndstr'; -import { Note } from '@/models/entities/note'; -import { User } from '@/models/entities/user'; -import { Notes, UserProfiles, NoteReactions } from '@/models/index'; -import { generateMutedUserQuery } from './generate-muted-user-query'; -import { generateBlockedUserQuery } from './generate-block-query'; +import { Note } from '@/models/entities/note.js'; +import { User } from '@/models/entities/user.js'; +import { Notes, UserProfiles, NoteReactions } from '@/models/index.js'; +import { generateMutedUserQuery } from './generate-muted-user-query.js'; +import { generateBlockedUserQuery } from './generate-block-query.js'; // TODO: リアクション、Renote、返信などをしたノートは除外する diff --git a/packages/backend/src/server/api/common/inject-promo.ts b/packages/backend/src/server/api/common/inject-promo.ts index 06a384199..b467b7b70 100644 --- a/packages/backend/src/server/api/common/inject-promo.ts +++ b/packages/backend/src/server/api/common/inject-promo.ts @@ -1,7 +1,7 @@ import rndstr from 'rndstr'; -import { Note } from '@/models/entities/note'; -import { User } from '@/models/entities/user'; -import { PromoReads, PromoNotes, Notes, Users } from '@/models/index'; +import { Note } from '@/models/entities/note.js'; +import { User } from '@/models/entities/user.js'; +import { PromoReads, PromoNotes, Notes, Users } from '@/models/index.js'; export async function injectPromo(timeline: Note[], user?: User | null) { if (timeline.length < 5) return; diff --git a/packages/backend/src/server/api/common/read-messaging-message.ts b/packages/backend/src/server/api/common/read-messaging-message.ts index 928333e59..b0ce54d37 100644 --- a/packages/backend/src/server/api/common/read-messaging-message.ts +++ b/packages/backend/src/server/api/common/read-messaging-message.ts @@ -1,17 +1,17 @@ -import { publishMainStream, publishGroupMessagingStream } from '@/services/stream'; -import { publishMessagingStream } from '@/services/stream'; -import { publishMessagingIndexStream } from '@/services/stream'; -import { User, IRemoteUser } from '@/models/entities/user'; -import { MessagingMessage } from '@/models/entities/messaging-message'; -import { MessagingMessages, UserGroupJoinings, Users } from '@/models/index'; +import { publishMainStream, publishGroupMessagingStream } from '@/services/stream.js'; +import { publishMessagingStream } from '@/services/stream.js'; +import { publishMessagingIndexStream } from '@/services/stream.js'; +import { User, IRemoteUser } from '@/models/entities/user.js'; +import { MessagingMessage } from '@/models/entities/messaging-message.js'; +import { MessagingMessages, UserGroupJoinings, Users } from '@/models/index.js'; import { In } from 'typeorm'; -import { IdentifiableError } from '@/misc/identifiable-error'; -import { UserGroup } from '@/models/entities/user-group'; -import { toArray } from '@/prelude/array'; -import { renderReadActivity } from '@/remote/activitypub/renderer/read'; -import { renderActivity } from '@/remote/activitypub/renderer/index'; -import { deliver } from '@/queue/index'; -import orderedCollection from '@/remote/activitypub/renderer/ordered-collection'; +import { IdentifiableError } from '@/misc/identifiable-error.js'; +import { UserGroup } from '@/models/entities/user-group.js'; +import { toArray } from '@/prelude/array.js'; +import { renderReadActivity } from '@/remote/activitypub/renderer/read.js'; +import { renderActivity } from '@/remote/activitypub/renderer/index.js'; +import { deliver } from '@/queue/index.js'; +import orderedCollection from '@/remote/activitypub/renderer/ordered-collection.js'; /** * Mark messages as read diff --git a/packages/backend/src/server/api/common/read-notification.ts b/packages/backend/src/server/api/common/read-notification.ts index 049a7feed..1f575042a 100644 --- a/packages/backend/src/server/api/common/read-notification.ts +++ b/packages/backend/src/server/api/common/read-notification.ts @@ -1,7 +1,7 @@ -import { publishMainStream } from '@/services/stream'; -import { User } from '@/models/entities/user'; -import { Notification } from '@/models/entities/notification'; -import { Notifications, Users } from '@/models/index'; +import { publishMainStream } from '@/services/stream.js'; +import { User } from '@/models/entities/user.js'; +import { Notification } from '@/models/entities/notification.js'; +import { Notifications, Users } from '@/models/index.js'; import { In } from 'typeorm'; export async function readNotification( diff --git a/packages/backend/src/server/api/common/signin.ts b/packages/backend/src/server/api/common/signin.ts index df986fc45..163f132a4 100644 --- a/packages/backend/src/server/api/common/signin.ts +++ b/packages/backend/src/server/api/common/signin.ts @@ -1,10 +1,10 @@ -import * as Koa from 'koa'; +import Koa from 'koa'; -import config from '@/config/index'; -import { ILocalUser } from '@/models/entities/user'; -import { Signins } from '@/models/index'; -import { genId } from '@/misc/gen-id'; -import { publishMainStream } from '@/services/stream'; +import config from '@/config/index.js'; +import { ILocalUser } from '@/models/entities/user.js'; +import { Signins } from '@/models/index.js'; +import { genId } from '@/misc/gen-id.js'; +import { publishMainStream } from '@/services/stream.js'; export default function(ctx: Koa.Context, user: ILocalUser, redirect = false) { if (redirect) { diff --git a/packages/backend/src/server/api/common/signup.ts b/packages/backend/src/server/api/common/signup.ts index f8db7e374..7689e8233 100644 --- a/packages/backend/src/server/api/common/signup.ts +++ b/packages/backend/src/server/api/common/signup.ts @@ -1,15 +1,15 @@ -import * as bcrypt from 'bcryptjs'; -import { generateKeyPair } from 'crypto'; -import generateUserToken from './generate-native-user-token'; -import { User } from '@/models/entities/user'; -import { Users, UsedUsernames } from '@/models/index'; -import { UserProfile } from '@/models/entities/user-profile'; +import bcrypt from 'bcryptjs'; +import { generateKeyPair } from 'node:crypto'; +import generateUserToken from './generate-native-user-token.js'; +import { User } from '@/models/entities/user.js'; +import { Users, UsedUsernames } from '@/models/index.js'; +import { UserProfile } from '@/models/entities/user-profile.js'; import { getConnection } from 'typeorm'; -import { genId } from '@/misc/gen-id'; -import { toPunyNullable } from '@/misc/convert-host'; -import { UserKeypair } from '@/models/entities/user-keypair'; -import { usersChart } from '@/services/chart/index'; -import { UsedUsername } from '@/models/entities/used-username'; +import { genId } from '@/misc/gen-id.js'; +import { toPunyNullable } from '@/misc/convert-host.js'; +import { UserKeypair } from '@/models/entities/user-keypair.js'; +import { usersChart } from '@/services/chart/index.js'; +import { UsedUsername } from '@/models/entities/used-username.js'; export async function signup(opts: { username: User['username']; @@ -21,13 +21,13 @@ export async function signup(opts: { let hash = passwordHash; // Validate username - if (!Users.validateLocalUsername.ok(username)) { + if (!Users.validateLocalUsername(username)) { throw new Error('INVALID_USERNAME'); } if (password != null && passwordHash == null) { // Validate password - if (!Users.validatePassword.ok(password)) { + if (!Users.validatePassword(password)) { throw new Error('INVALID_PASSWORD'); } diff --git a/packages/backend/src/server/api/define.ts b/packages/backend/src/server/api/define.ts index e0720e2ad..9094fcffc 100644 --- a/packages/backend/src/server/api/define.ts +++ b/packages/backend/src/server/api/define.ts @@ -1,11 +1,10 @@ -import * as fs from 'fs'; -import { ILocalUser } from '@/models/entities/user'; -import { IEndpointMeta } from './endpoints'; -import { ApiError } from './error'; -import { SchemaType } from '@/misc/schema'; -import { AccessToken } from '@/models/entities/access-token'; - -type NonOptional = T extends undefined ? never : T; +import * as fs from 'node:fs'; +import Ajv from 'ajv'; +import { ILocalUser } from '@/models/entities/user.js'; +import { IEndpointMeta } from './endpoints.js'; +import { ApiError } from './error.js'; +import { Schema, SchemaType } from '@/misc/schema.js'; +import { AccessToken } from '@/models/entities/access-token.js'; type SimpleUserInfo = { id: ILocalUser['id']; @@ -18,24 +17,27 @@ type SimpleUserInfo = { isAdmin: ILocalUser['isAdmin']; isModerator: ILocalUser['isModerator']; isSilenced: ILocalUser['isSilenced']; -}; - -type Params = { - [P in keyof T['params']]: NonNullable[P]['transform'] extends () => any - ? ReturnType[P]['transform']> - : NonNullable[P]['default'] extends null | number | string - ? NonOptional[P]['validator']['get']>[0]> - : ReturnType[P]['validator']['get']>[0]; + showTimelineReplies: ILocalUser['showTimelineReplies']; }; export type Response = Record | void; -type executor = - (params: Params, user: T['requireCredential'] extends true ? SimpleUserInfo : SimpleUserInfo | null, token: AccessToken | null, file?: any, cleanup?: () => any) => +// TODO: paramsの型をT['params']のスキーマ定義から推論する +type executor = + (params: SchemaType, user: T['requireCredential'] extends true ? SimpleUserInfo : SimpleUserInfo | null, token: AccessToken | null, file?: any, cleanup?: () => any) => Promise>>; -export default function (meta: T, cb: executor) +const ajv = new Ajv({ + useDefaults: true, +}); + +ajv.addFormat('misskey:id', /^[a-z0-9]+$/); + +export default function (meta: T, paramDef: Ps, cb: executor) : (params: any, user: T['requireCredential'] extends true ? SimpleUserInfo : SimpleUserInfo | null, token: AccessToken | null, file?: any) => Promise { + + const validate = ajv.compile(paramDef); + return (params: any, user: T['requireCredential'] extends true ? SimpleUserInfo : SimpleUserInfo | null, token: AccessToken | null, file?: any) => { function cleanup() { fs.unlink(file.path, () => {}); @@ -47,42 +49,22 @@ export default function (meta: T, cb: executor) id: '4267801e-70d1-416a-b011-4ee502885d8b', })); - const [ps, pserr] = getParams(meta, params); - if (pserr) { + const valid = validate(params); + if (!valid) { if (file) cleanup(); - return Promise.reject(pserr); - } - return cb(ps, user, token, file, cleanup); - }; -} - -function getParams(defs: T, params: any): [Params, ApiError | null] { - if (defs.params == null) return [params, null]; - - const x: any = {}; - let err: ApiError | null = null; - Object.entries(defs.params).some(([k, def]) => { - const [v, e] = def.validator.get(params[k]); - if (e) { - err = new ApiError({ + const errors = validate.errors!; + const err = new ApiError({ message: 'Invalid param.', code: 'INVALID_PARAM', id: '3d81ceae-475f-4600-b2a8-2bc116157532', }, { - param: k, - reason: e.message, + param: errors[0].schemaPath, + reason: errors[0].message, }); - return true; - } else { - if (v === undefined && Object.prototype.hasOwnProperty.call(def, 'default')) { - x[k] = def.default; - } else { - x[k] = v; - } - if (def.transform) x[k] = def.transform(x[k]); - return false; + return Promise.reject(err); } - }); - return [x, err]; + + return cb(params as SchemaType, user, token, file, cleanup); + }; } diff --git a/packages/backend/src/server/api/endpoints.ts b/packages/backend/src/server/api/endpoints.ts index bb4e972b8..6b4eff078 100644 --- a/packages/backend/src/server/api/endpoints.ts +++ b/packages/backend/src/server/api/endpoints.ts @@ -1,31 +1,618 @@ -import { fileURLToPath } from 'url'; -import { dirname } from 'path'; -import { Context } from 'cafy'; -import * as path from 'path'; -import * as glob from 'glob'; -import { Schema } from '@/misc/schema'; +import { Schema } from '@/misc/schema.js'; -//const _filename = fileURLToPath(import.meta.url); -const _filename = __filename; -const _dirname = dirname(_filename); +import * as ep___admin_abuseUserReports from './endpoints/admin/abuse-user-reports.js'; +import * as ep___admin_accounts_create from './endpoints/admin/accounts/create.js'; +import * as ep___admin_accounts_delete from './endpoints/admin/accounts/delete.js'; +import * as ep___admin_ad_create from './endpoints/admin/ad/create.js'; +import * as ep___admin_ad_delete from './endpoints/admin/ad/delete.js'; +import * as ep___admin_ad_list from './endpoints/admin/ad/list.js'; +import * as ep___admin_ad_update from './endpoints/admin/ad/update.js'; +import * as ep___admin_announcements_create from './endpoints/admin/announcements/create.js'; +import * as ep___admin_announcements_delete from './endpoints/admin/announcements/delete.js'; +import * as ep___admin_announcements_list from './endpoints/admin/announcements/list.js'; +import * as ep___admin_announcements_update from './endpoints/admin/announcements/update.js'; +import * as ep___admin_deleteAllFilesOfAUser from './endpoints/admin/delete-all-files-of-a-user.js'; +import * as ep___admin_drive_cleanRemoteFiles from './endpoints/admin/drive/clean-remote-files.js'; +import * as ep___admin_drive_cleanup from './endpoints/admin/drive/cleanup.js'; +import * as ep___admin_drive_files from './endpoints/admin/drive/files.js'; +import * as ep___admin_drive_showFile from './endpoints/admin/drive/show-file.js'; +import * as ep___admin_emoji_addAliasesBulk from './endpoints/admin/emoji/add-aliases-bulk.js'; +import * as ep___admin_emoji_add from './endpoints/admin/emoji/add.js'; +import * as ep___admin_emoji_copy from './endpoints/admin/emoji/copy.js'; +import * as ep___admin_emoji_deleteBulk from './endpoints/admin/emoji/delete-bulk.js'; +import * as ep___admin_emoji_delete from './endpoints/admin/emoji/delete.js'; +import * as ep___admin_emoji_importZip from './endpoints/admin/emoji/import-zip.js'; +import * as ep___admin_emoji_listRemote from './endpoints/admin/emoji/list-remote.js'; +import * as ep___admin_emoji_list from './endpoints/admin/emoji/list.js'; +import * as ep___admin_emoji_removeAliasesBulk from './endpoints/admin/emoji/remove-aliases-bulk.js'; +import * as ep___admin_emoji_setAliasesBulk from './endpoints/admin/emoji/set-aliases-bulk.js'; +import * as ep___admin_emoji_setCategoryBulk from './endpoints/admin/emoji/set-category-bulk.js'; +import * as ep___admin_emoji_update from './endpoints/admin/emoji/update.js'; +import * as ep___admin_federation_deleteAllFiles from './endpoints/admin/federation/delete-all-files.js'; +import * as ep___admin_federation_refreshRemoteInstanceMetadata from './endpoints/admin/federation/refresh-remote-instance-metadata.js'; +import * as ep___admin_federation_removeAllFollowing from './endpoints/admin/federation/remove-all-following.js'; +import * as ep___admin_federation_updateInstance from './endpoints/admin/federation/update-instance.js'; +import * as ep___admin_getIndexStats from './endpoints/admin/get-index-stats.js'; +import * as ep___admin_getTableStats from './endpoints/admin/get-table-stats.js'; +import * as ep___admin_invite from './endpoints/admin/invite.js'; +import * as ep___admin_moderators_add from './endpoints/admin/moderators/add.js'; +import * as ep___admin_moderators_remove from './endpoints/admin/moderators/remove.js'; +import * as ep___admin_promo_create from './endpoints/admin/promo/create.js'; +import * as ep___admin_queue_clear from './endpoints/admin/queue/clear.js'; +import * as ep___admin_queue_deliverDelayed from './endpoints/admin/queue/deliver-delayed.js'; +import * as ep___admin_queue_inboxDelayed from './endpoints/admin/queue/inbox-delayed.js'; +import * as ep___admin_queue_stats from './endpoints/admin/queue/stats.js'; +import * as ep___admin_relays_add from './endpoints/admin/relays/add.js'; +import * as ep___admin_relays_list from './endpoints/admin/relays/list.js'; +import * as ep___admin_relays_remove from './endpoints/admin/relays/remove.js'; +import * as ep___admin_resetPassword from './endpoints/admin/reset-password.js'; +import * as ep___admin_resolveAbuseUserReport from './endpoints/admin/resolve-abuse-user-report.js'; +import * as ep___admin_sendEmail from './endpoints/admin/send-email.js'; +import * as ep___admin_serverInfo from './endpoints/admin/server-info.js'; +import * as ep___admin_showModerationLogs from './endpoints/admin/show-moderation-logs.js'; +import * as ep___admin_showUser from './endpoints/admin/show-user.js'; +import * as ep___admin_showUsers from './endpoints/admin/show-users.js'; +import * as ep___admin_silenceUser from './endpoints/admin/silence-user.js'; +import * as ep___admin_suspendUser from './endpoints/admin/suspend-user.js'; +import * as ep___admin_unsilenceUser from './endpoints/admin/unsilence-user.js'; +import * as ep___admin_unsuspendUser from './endpoints/admin/unsuspend-user.js'; +import * as ep___admin_updateMeta from './endpoints/admin/update-meta.js'; +import * as ep___admin_vacuum from './endpoints/admin/vacuum.js'; +import * as ep___announcements from './endpoints/announcements.js'; +import * as ep___antennas_create from './endpoints/antennas/create.js'; +import * as ep___antennas_delete from './endpoints/antennas/delete.js'; +import * as ep___antennas_list from './endpoints/antennas/list.js'; +import * as ep___antennas_notes from './endpoints/antennas/notes.js'; +import * as ep___antennas_show from './endpoints/antennas/show.js'; +import * as ep___antennas_update from './endpoints/antennas/update.js'; +import * as ep___ap_get from './endpoints/ap/get.js'; +import * as ep___ap_show from './endpoints/ap/show.js'; +import * as ep___app_create from './endpoints/app/create.js'; +import * as ep___app_show from './endpoints/app/show.js'; +import * as ep___auth_accept from './endpoints/auth/accept.js'; +import * as ep___auth_session_generate from './endpoints/auth/session/generate.js'; +import * as ep___auth_session_show from './endpoints/auth/session/show.js'; +import * as ep___auth_session_userkey from './endpoints/auth/session/userkey.js'; +import * as ep___blocking_create from './endpoints/blocking/create.js'; +import * as ep___blocking_delete from './endpoints/blocking/delete.js'; +import * as ep___blocking_list from './endpoints/blocking/list.js'; +import * as ep___channels_create from './endpoints/channels/create.js'; +import * as ep___channels_featured from './endpoints/channels/featured.js'; +import * as ep___channels_follow from './endpoints/channels/follow.js'; +import * as ep___channels_followed from './endpoints/channels/followed.js'; +import * as ep___channels_owned from './endpoints/channels/owned.js'; +import * as ep___channels_show from './endpoints/channels/show.js'; +import * as ep___channels_timeline from './endpoints/channels/timeline.js'; +import * as ep___channels_unfollow from './endpoints/channels/unfollow.js'; +import * as ep___channels_update from './endpoints/channels/update.js'; +import * as ep___charts_activeUsers from './endpoints/charts/active-users.js'; +import * as ep___charts_apRequest from './endpoints/charts/ap-request.js'; +import * as ep___charts_drive from './endpoints/charts/drive.js'; +import * as ep___charts_federation from './endpoints/charts/federation.js'; +import * as ep___charts_hashtag from './endpoints/charts/hashtag.js'; +import * as ep___charts_instance from './endpoints/charts/instance.js'; +import * as ep___charts_notes from './endpoints/charts/notes.js'; +import * as ep___charts_user_drive from './endpoints/charts/user/drive.js'; +import * as ep___charts_user_following from './endpoints/charts/user/following.js'; +import * as ep___charts_user_notes from './endpoints/charts/user/notes.js'; +import * as ep___charts_user_reactions from './endpoints/charts/user/reactions.js'; +import * as ep___charts_users from './endpoints/charts/users.js'; +import * as ep___clips_addNote from './endpoints/clips/add-note.js'; +import * as ep___clips_create from './endpoints/clips/create.js'; +import * as ep___clips_delete from './endpoints/clips/delete.js'; +import * as ep___clips_list from './endpoints/clips/list.js'; +import * as ep___clips_notes from './endpoints/clips/notes.js'; +import * as ep___clips_show from './endpoints/clips/show.js'; +import * as ep___clips_update from './endpoints/clips/update.js'; +import * as ep___drive from './endpoints/drive.js'; +import * as ep___drive_files from './endpoints/drive/files.js'; +import * as ep___drive_files_attachedNotes from './endpoints/drive/files/attached-notes.js'; +import * as ep___drive_files_checkExistence from './endpoints/drive/files/check-existence.js'; +import * as ep___drive_files_create from './endpoints/drive/files/create.js'; +import * as ep___drive_files_delete from './endpoints/drive/files/delete.js'; +import * as ep___drive_files_findByHash from './endpoints/drive/files/find-by-hash.js'; +import * as ep___drive_files_find from './endpoints/drive/files/find.js'; +import * as ep___drive_files_show from './endpoints/drive/files/show.js'; +import * as ep___drive_files_update from './endpoints/drive/files/update.js'; +import * as ep___drive_files_uploadFromUrl from './endpoints/drive/files/upload-from-url.js'; +import * as ep___drive_folders from './endpoints/drive/folders.js'; +import * as ep___drive_folders_create from './endpoints/drive/folders/create.js'; +import * as ep___drive_folders_delete from './endpoints/drive/folders/delete.js'; +import * as ep___drive_folders_find from './endpoints/drive/folders/find.js'; +import * as ep___drive_folders_show from './endpoints/drive/folders/show.js'; +import * as ep___drive_folders_update from './endpoints/drive/folders/update.js'; +import * as ep___drive_stream from './endpoints/drive/stream.js'; +import * as ep___emailAddress_available from './endpoints/email-address/available.js'; +import * as ep___endpoint from './endpoints/endpoint.js'; +import * as ep___endpoints from './endpoints/endpoints.js'; +import * as ep___exportCustomEmojis from './endpoints/export-custom-emojis.js'; +import * as ep___federation_followers from './endpoints/federation/followers.js'; +import * as ep___federation_following from './endpoints/federation/following.js'; +import * as ep___federation_instances from './endpoints/federation/instances.js'; +import * as ep___federation_showInstance from './endpoints/federation/show-instance.js'; +import * as ep___federation_updateRemoteUser from './endpoints/federation/update-remote-user.js'; +import * as ep___federation_users from './endpoints/federation/users.js'; +import * as ep___following_create from './endpoints/following/create.js'; +import * as ep___following_delete from './endpoints/following/delete.js'; +import * as ep___following_invalidate from './endpoints/following/invalidate.js'; +import * as ep___following_requests_accept from './endpoints/following/requests/accept.js'; +import * as ep___following_requests_cancel from './endpoints/following/requests/cancel.js'; +import * as ep___following_requests_list from './endpoints/following/requests/list.js'; +import * as ep___following_requests_reject from './endpoints/following/requests/reject.js'; +import * as ep___gallery_featured from './endpoints/gallery/featured.js'; +import * as ep___gallery_popular from './endpoints/gallery/popular.js'; +import * as ep___gallery_posts from './endpoints/gallery/posts.js'; +import * as ep___gallery_posts_create from './endpoints/gallery/posts/create.js'; +import * as ep___gallery_posts_delete from './endpoints/gallery/posts/delete.js'; +import * as ep___gallery_posts_like from './endpoints/gallery/posts/like.js'; +import * as ep___gallery_posts_show from './endpoints/gallery/posts/show.js'; +import * as ep___gallery_posts_unlike from './endpoints/gallery/posts/unlike.js'; +import * as ep___gallery_posts_update from './endpoints/gallery/posts/update.js'; +import * as ep___getOnlineUsersCount from './endpoints/get-online-users-count.js'; +import * as ep___hashtags_list from './endpoints/hashtags/list.js'; +import * as ep___hashtags_search from './endpoints/hashtags/search.js'; +import * as ep___hashtags_show from './endpoints/hashtags/show.js'; +import * as ep___hashtags_trend from './endpoints/hashtags/trend.js'; +import * as ep___hashtags_users from './endpoints/hashtags/users.js'; +import * as ep___i from './endpoints/i.js'; +import * as ep___i_2fa_done from './endpoints/i/2fa/done.js'; +import * as ep___i_2fa_keyDone from './endpoints/i/2fa/key-done.js'; +import * as ep___i_2fa_passwordLess from './endpoints/i/2fa/password-less.js'; +import * as ep___i_2fa_registerKey from './endpoints/i/2fa/register-key.js'; +import * as ep___i_2fa_register from './endpoints/i/2fa/register.js'; +import * as ep___i_2fa_removeKey from './endpoints/i/2fa/remove-key.js'; +import * as ep___i_2fa_unregister from './endpoints/i/2fa/unregister.js'; +import * as ep___i_apps from './endpoints/i/apps.js'; +import * as ep___i_authorizedApps from './endpoints/i/authorized-apps.js'; +import * as ep___i_changePassword from './endpoints/i/change-password.js'; +import * as ep___i_deleteAccount from './endpoints/i/delete-account.js'; +import * as ep___i_exportBlocking from './endpoints/i/export-blocking.js'; +import * as ep___i_exportFollowing from './endpoints/i/export-following.js'; +import * as ep___i_exportMute from './endpoints/i/export-mute.js'; +import * as ep___i_exportNotes from './endpoints/i/export-notes.js'; +import * as ep___i_exportUserLists from './endpoints/i/export-user-lists.js'; +import * as ep___i_favorites from './endpoints/i/favorites.js'; +import * as ep___i_gallery_likes from './endpoints/i/gallery/likes.js'; +import * as ep___i_gallery_posts from './endpoints/i/gallery/posts.js'; +import * as ep___i_getWordMutedNotesCount from './endpoints/i/get-word-muted-notes-count.js'; +import * as ep___i_importBlocking from './endpoints/i/import-blocking.js'; +import * as ep___i_importFollowing from './endpoints/i/import-following.js'; +import * as ep___i_importMuting from './endpoints/i/import-muting.js'; +import * as ep___i_importUserLists from './endpoints/i/import-user-lists.js'; +import * as ep___i_notifications from './endpoints/i/notifications.js'; +import * as ep___i_pageLikes from './endpoints/i/page-likes.js'; +import * as ep___i_pages from './endpoints/i/pages.js'; +import * as ep___i_pin from './endpoints/i/pin.js'; +import * as ep___i_readAllMessagingMessages from './endpoints/i/read-all-messaging-messages.js'; +import * as ep___i_readAllUnreadNotes from './endpoints/i/read-all-unread-notes.js'; +import * as ep___i_readAnnouncement from './endpoints/i/read-announcement.js'; +import * as ep___i_regenerateToken from './endpoints/i/regenerate-token.js'; +import * as ep___i_registry_getAll from './endpoints/i/registry/get-all.js'; +import * as ep___i_registry_getDetail from './endpoints/i/registry/get-detail.js'; +import * as ep___i_registry_get from './endpoints/i/registry/get.js'; +import * as ep___i_registry_keysWithType from './endpoints/i/registry/keys-with-type.js'; +import * as ep___i_registry_keys from './endpoints/i/registry/keys.js'; +import * as ep___i_registry_remove from './endpoints/i/registry/remove.js'; +import * as ep___i_registry_scopes from './endpoints/i/registry/scopes.js'; +import * as ep___i_registry_set from './endpoints/i/registry/set.js'; +import * as ep___i_revokeToken from './endpoints/i/revoke-token.js'; +import * as ep___i_signinHistory from './endpoints/i/signin-history.js'; +import * as ep___i_unpin from './endpoints/i/unpin.js'; +import * as ep___i_updateEmail from './endpoints/i/update-email.js'; +import * as ep___i_update from './endpoints/i/update.js'; +import * as ep___i_userGroupInvites from './endpoints/i/user-group-invites.js'; +import * as ep___messaging_history from './endpoints/messaging/history.js'; +import * as ep___messaging_messages from './endpoints/messaging/messages.js'; +import * as ep___messaging_messages_create from './endpoints/messaging/messages/create.js'; +import * as ep___messaging_messages_delete from './endpoints/messaging/messages/delete.js'; +import * as ep___messaging_messages_read from './endpoints/messaging/messages/read.js'; +import * as ep___meta from './endpoints/meta.js'; +import * as ep___miauth_genToken from './endpoints/miauth/gen-token.js'; +import * as ep___mute_create from './endpoints/mute/create.js'; +import * as ep___mute_delete from './endpoints/mute/delete.js'; +import * as ep___mute_list from './endpoints/mute/list.js'; +import * as ep___my_apps from './endpoints/my/apps.js'; +import * as ep___notes from './endpoints/notes.js'; +import * as ep___notes_children from './endpoints/notes/children.js'; +import * as ep___notes_clips from './endpoints/notes/clips.js'; +import * as ep___notes_conversation from './endpoints/notes/conversation.js'; +import * as ep___notes_create from './endpoints/notes/create.js'; +import * as ep___notes_delete from './endpoints/notes/delete.js'; +import * as ep___notes_favorites_create from './endpoints/notes/favorites/create.js'; +import * as ep___notes_favorites_delete from './endpoints/notes/favorites/delete.js'; +import * as ep___notes_featured from './endpoints/notes/featured.js'; +import * as ep___notes_globalTimeline from './endpoints/notes/global-timeline.js'; +import * as ep___notes_hybridTimeline from './endpoints/notes/hybrid-timeline.js'; +import * as ep___notes_localTimeline from './endpoints/notes/local-timeline.js'; +import * as ep___notes_mentions from './endpoints/notes/mentions.js'; +import * as ep___notes_polls_recommendation from './endpoints/notes/polls/recommendation.js'; +import * as ep___notes_polls_vote from './endpoints/notes/polls/vote.js'; +import * as ep___notes_reactions from './endpoints/notes/reactions.js'; +import * as ep___notes_reactions_create from './endpoints/notes/reactions/create.js'; +import * as ep___notes_reactions_delete from './endpoints/notes/reactions/delete.js'; +import * as ep___notes_renotes from './endpoints/notes/renotes.js'; +import * as ep___notes_replies from './endpoints/notes/replies.js'; +import * as ep___notes_searchByTag from './endpoints/notes/search-by-tag.js'; +import * as ep___notes_search from './endpoints/notes/search.js'; +import * as ep___notes_show from './endpoints/notes/show.js'; +import * as ep___notes_state from './endpoints/notes/state.js'; +import * as ep___notes_threadMuting_create from './endpoints/notes/thread-muting/create.js'; +import * as ep___notes_threadMuting_delete from './endpoints/notes/thread-muting/delete.js'; +import * as ep___notes_timeline from './endpoints/notes/timeline.js'; +import * as ep___notes_translate from './endpoints/notes/translate.js'; +import * as ep___notes_unrenote from './endpoints/notes/unrenote.js'; +import * as ep___notes_userListTimeline from './endpoints/notes/user-list-timeline.js'; +import * as ep___notes_watching_create from './endpoints/notes/watching/create.js'; +import * as ep___notes_watching_delete from './endpoints/notes/watching/delete.js'; +import * as ep___notifications_create from './endpoints/notifications/create.js'; +import * as ep___notifications_markAllAsRead from './endpoints/notifications/mark-all-as-read.js'; +import * as ep___notifications_read from './endpoints/notifications/read.js'; +import * as ep___pagePush from './endpoints/page-push.js'; +import * as ep___pages_create from './endpoints/pages/create.js'; +import * as ep___pages_delete from './endpoints/pages/delete.js'; +import * as ep___pages_featured from './endpoints/pages/featured.js'; +import * as ep___pages_like from './endpoints/pages/like.js'; +import * as ep___pages_show from './endpoints/pages/show.js'; +import * as ep___pages_unlike from './endpoints/pages/unlike.js'; +import * as ep___pages_update from './endpoints/pages/update.js'; +import * as ep___ping from './endpoints/ping.js'; +import * as ep___pinnedUsers from './endpoints/pinned-users.js'; +import * as ep___promo_read from './endpoints/promo/read.js'; +import * as ep___requestResetPassword from './endpoints/request-reset-password.js'; +import * as ep___resetDb from './endpoints/reset-db.js'; +import * as ep___resetPassword from './endpoints/reset-password.js'; +import * as ep___serverInfo from './endpoints/server-info.js'; +import * as ep___stats from './endpoints/stats.js'; +import * as ep___sw_register from './endpoints/sw/register.js'; +import * as ep___sw_unregister from './endpoints/sw/unregister.js'; +import * as ep___test from './endpoints/test.js'; +import * as ep___username_available from './endpoints/username/available.js'; +import * as ep___users from './endpoints/users.js'; +import * as ep___users_clips from './endpoints/users/clips.js'; +import * as ep___users_followers from './endpoints/users/followers.js'; +import * as ep___users_following from './endpoints/users/following.js'; +import * as ep___users_gallery_posts from './endpoints/users/gallery/posts.js'; +import * as ep___users_getFrequentlyRepliedUsers from './endpoints/users/get-frequently-replied-users.js'; +import * as ep___users_groups_create from './endpoints/users/groups/create.js'; +import * as ep___users_groups_delete from './endpoints/users/groups/delete.js'; +import * as ep___users_groups_invitations_accept from './endpoints/users/groups/invitations/accept.js'; +import * as ep___users_groups_invitations_reject from './endpoints/users/groups/invitations/reject.js'; +import * as ep___users_groups_invite from './endpoints/users/groups/invite.js'; +import * as ep___users_groups_joined from './endpoints/users/groups/joined.js'; +import * as ep___users_groups_leave from './endpoints/users/groups/leave.js'; +import * as ep___users_groups_owned from './endpoints/users/groups/owned.js'; +import * as ep___users_groups_pull from './endpoints/users/groups/pull.js'; +import * as ep___users_groups_show from './endpoints/users/groups/show.js'; +import * as ep___users_groups_transfer from './endpoints/users/groups/transfer.js'; +import * as ep___users_groups_update from './endpoints/users/groups/update.js'; +import * as ep___users_lists_create from './endpoints/users/lists/create.js'; +import * as ep___users_lists_delete from './endpoints/users/lists/delete.js'; +import * as ep___users_lists_list from './endpoints/users/lists/list.js'; +import * as ep___users_lists_pull from './endpoints/users/lists/pull.js'; +import * as ep___users_lists_push from './endpoints/users/lists/push.js'; +import * as ep___users_lists_show from './endpoints/users/lists/show.js'; +import * as ep___users_lists_update from './endpoints/users/lists/update.js'; +import * as ep___users_notes from './endpoints/users/notes.js'; +import * as ep___users_pages from './endpoints/users/pages.js'; +import * as ep___users_reactions from './endpoints/users/reactions.js'; +import * as ep___users_recommendation from './endpoints/users/recommendation.js'; +import * as ep___users_relation from './endpoints/users/relation.js'; +import * as ep___users_reportAbuse from './endpoints/users/report-abuse.js'; +import * as ep___users_searchByUsernameAndHost from './endpoints/users/search-by-username-and-host.js'; +import * as ep___users_search from './endpoints/users/search.js'; +import * as ep___users_show from './endpoints/users/show.js'; +import * as ep___users_stats from './endpoints/users/stats.js'; -export type Param = { - validator: Context; - transform?: any; - default?: any; - deprecated?: boolean; - ref?: string; -}; +const eps = [ + ['admin/abuse-user-reports', ep___admin_abuseUserReports], + ['admin/accounts/create', ep___admin_accounts_create], + ['admin/accounts/delete', ep___admin_accounts_delete], + ['admin/ad/create', ep___admin_ad_create], + ['admin/ad/delete', ep___admin_ad_delete], + ['admin/ad/list', ep___admin_ad_list], + ['admin/ad/update', ep___admin_ad_update], + ['admin/announcements/create', ep___admin_announcements_create], + ['admin/announcements/delete', ep___admin_announcements_delete], + ['admin/announcements/list', ep___admin_announcements_list], + ['admin/announcements/update', ep___admin_announcements_update], + ['admin/delete-all-files-of-a-user', ep___admin_deleteAllFilesOfAUser], + ['admin/drive/clean-remote-files', ep___admin_drive_cleanRemoteFiles], + ['admin/drive/cleanup', ep___admin_drive_cleanup], + ['admin/drive/files', ep___admin_drive_files], + ['admin/drive/show-file', ep___admin_drive_showFile], + ['admin/emoji/add-aliases-bulk', ep___admin_emoji_addAliasesBulk], + ['admin/emoji/add', ep___admin_emoji_add], + ['admin/emoji/copy', ep___admin_emoji_copy], + ['admin/emoji/delete-bulk', ep___admin_emoji_deleteBulk], + ['admin/emoji/delete', ep___admin_emoji_delete], + ['admin/emoji/import-zip', ep___admin_emoji_importZip], + ['admin/emoji/list-remote', ep___admin_emoji_listRemote], + ['admin/emoji/list', ep___admin_emoji_list], + ['admin/emoji/remove-aliases-bulk', ep___admin_emoji_removeAliasesBulk], + ['admin/emoji/set-aliases-bulk', ep___admin_emoji_setAliasesBulk], + ['admin/emoji/set-category-bulk', ep___admin_emoji_setCategoryBulk], + ['admin/emoji/update', ep___admin_emoji_update], + ['admin/federation/delete-all-files', ep___admin_federation_deleteAllFiles], + ['admin/federation/refresh-remote-instance-metadata', ep___admin_federation_refreshRemoteInstanceMetadata], + ['admin/federation/remove-all-following', ep___admin_federation_removeAllFollowing], + ['admin/federation/update-instance', ep___admin_federation_updateInstance], + ['admin/get-index-stats', ep___admin_getIndexStats], + ['admin/get-table-stats', ep___admin_getTableStats], + ['admin/invite', ep___admin_invite], + ['admin/moderators/add', ep___admin_moderators_add], + ['admin/moderators/remove', ep___admin_moderators_remove], + ['admin/promo/create', ep___admin_promo_create], + ['admin/queue/clear', ep___admin_queue_clear], + ['admin/queue/deliver-delayed', ep___admin_queue_deliverDelayed], + ['admin/queue/inbox-delayed', ep___admin_queue_inboxDelayed], + ['admin/queue/stats', ep___admin_queue_stats], + ['admin/relays/add', ep___admin_relays_add], + ['admin/relays/list', ep___admin_relays_list], + ['admin/relays/remove', ep___admin_relays_remove], + ['admin/reset-password', ep___admin_resetPassword], + ['admin/resolve-abuse-user-report', ep___admin_resolveAbuseUserReport], + ['admin/send-email', ep___admin_sendEmail], + ['admin/server-info', ep___admin_serverInfo], + ['admin/show-moderation-logs', ep___admin_showModerationLogs], + ['admin/show-user', ep___admin_showUser], + ['admin/show-users', ep___admin_showUsers], + ['admin/silence-user', ep___admin_silenceUser], + ['admin/suspend-user', ep___admin_suspendUser], + ['admin/unsilence-user', ep___admin_unsilenceUser], + ['admin/unsuspend-user', ep___admin_unsuspendUser], + ['admin/update-meta', ep___admin_updateMeta], + ['admin/vacuum', ep___admin_vacuum], + ['announcements', ep___announcements], + ['antennas/create', ep___antennas_create], + ['antennas/delete', ep___antennas_delete], + ['antennas/list', ep___antennas_list], + ['antennas/notes', ep___antennas_notes], + ['antennas/show', ep___antennas_show], + ['antennas/update', ep___antennas_update], + ['ap/get', ep___ap_get], + ['ap/show', ep___ap_show], + ['app/create', ep___app_create], + ['app/show', ep___app_show], + ['auth/accept', ep___auth_accept], + ['auth/session/generate', ep___auth_session_generate], + ['auth/session/show', ep___auth_session_show], + ['auth/session/userkey', ep___auth_session_userkey], + ['blocking/create', ep___blocking_create], + ['blocking/delete', ep___blocking_delete], + ['blocking/list', ep___blocking_list], + ['channels/create', ep___channels_create], + ['channels/featured', ep___channels_featured], + ['channels/follow', ep___channels_follow], + ['channels/followed', ep___channels_followed], + ['channels/owned', ep___channels_owned], + ['channels/show', ep___channels_show], + ['channels/timeline', ep___channels_timeline], + ['channels/unfollow', ep___channels_unfollow], + ['channels/update', ep___channels_update], + ['charts/active-users', ep___charts_activeUsers], + ['charts/ap-request', ep___charts_apRequest], + ['charts/drive', ep___charts_drive], + ['charts/federation', ep___charts_federation], + ['charts/hashtag', ep___charts_hashtag], + ['charts/instance', ep___charts_instance], + ['charts/notes', ep___charts_notes], + ['charts/user/drive', ep___charts_user_drive], + ['charts/user/following', ep___charts_user_following], + ['charts/user/notes', ep___charts_user_notes], + ['charts/user/reactions', ep___charts_user_reactions], + ['charts/users', ep___charts_users], + ['clips/add-note', ep___clips_addNote], + ['clips/create', ep___clips_create], + ['clips/delete', ep___clips_delete], + ['clips/list', ep___clips_list], + ['clips/notes', ep___clips_notes], + ['clips/show', ep___clips_show], + ['clips/update', ep___clips_update], + ['drive', ep___drive], + ['drive/files', ep___drive_files], + ['drive/files/attached-notes', ep___drive_files_attachedNotes], + ['drive/files/check-existence', ep___drive_files_checkExistence], + ['drive/files/create', ep___drive_files_create], + ['drive/files/delete', ep___drive_files_delete], + ['drive/files/find-by-hash', ep___drive_files_findByHash], + ['drive/files/find', ep___drive_files_find], + ['drive/files/show', ep___drive_files_show], + ['drive/files/update', ep___drive_files_update], + ['drive/files/upload-from-url', ep___drive_files_uploadFromUrl], + ['drive/folders', ep___drive_folders], + ['drive/folders/create', ep___drive_folders_create], + ['drive/folders/delete', ep___drive_folders_delete], + ['drive/folders/find', ep___drive_folders_find], + ['drive/folders/show', ep___drive_folders_show], + ['drive/folders/update', ep___drive_folders_update], + ['drive/stream', ep___drive_stream], + ['email-address/available', ep___emailAddress_available], + ['endpoint', ep___endpoint], + ['endpoints', ep___endpoints], + ['export-custom-emojis', ep___exportCustomEmojis], + ['federation/followers', ep___federation_followers], + ['federation/following', ep___federation_following], + ['federation/instances', ep___federation_instances], + ['federation/show-instance', ep___federation_showInstance], + ['federation/update-remote-user', ep___federation_updateRemoteUser], + ['federation/users', ep___federation_users], + ['following/create', ep___following_create], + ['following/delete', ep___following_delete], + ['following/invalidate', ep___following_invalidate], + ['following/requests/accept', ep___following_requests_accept], + ['following/requests/cancel', ep___following_requests_cancel], + ['following/requests/list', ep___following_requests_list], + ['following/requests/reject', ep___following_requests_reject], + ['gallery/featured', ep___gallery_featured], + ['gallery/popular', ep___gallery_popular], + ['gallery/posts', ep___gallery_posts], + ['gallery/posts/create', ep___gallery_posts_create], + ['gallery/posts/delete', ep___gallery_posts_delete], + ['gallery/posts/like', ep___gallery_posts_like], + ['gallery/posts/show', ep___gallery_posts_show], + ['gallery/posts/unlike', ep___gallery_posts_unlike], + ['gallery/posts/update', ep___gallery_posts_update], + ['get-online-users-count', ep___getOnlineUsersCount], + ['hashtags/list', ep___hashtags_list], + ['hashtags/search', ep___hashtags_search], + ['hashtags/show', ep___hashtags_show], + ['hashtags/trend', ep___hashtags_trend], + ['hashtags/users', ep___hashtags_users], + ['i', ep___i], + ['i/2fa/done', ep___i_2fa_done], + ['i/2fa/key-done', ep___i_2fa_keyDone], + ['i/2fa/password-less', ep___i_2fa_passwordLess], + ['i/2fa/register-key', ep___i_2fa_registerKey], + ['i/2fa/register', ep___i_2fa_register], + ['i/2fa/remove-key', ep___i_2fa_removeKey], + ['i/2fa/unregister', ep___i_2fa_unregister], + ['i/apps', ep___i_apps], + ['i/authorized-apps', ep___i_authorizedApps], + ['i/change-password', ep___i_changePassword], + ['i/delete-account', ep___i_deleteAccount], + ['i/export-blocking', ep___i_exportBlocking], + ['i/export-following', ep___i_exportFollowing], + ['i/export-mute', ep___i_exportMute], + ['i/export-notes', ep___i_exportNotes], + ['i/export-user-lists', ep___i_exportUserLists], + ['i/favorites', ep___i_favorites], + ['i/gallery/likes', ep___i_gallery_likes], + ['i/gallery/posts', ep___i_gallery_posts], + ['i/get-word-muted-notes-count', ep___i_getWordMutedNotesCount], + ['i/import-blocking', ep___i_importBlocking], + ['i/import-following', ep___i_importFollowing], + ['i/import-muting', ep___i_importMuting], + ['i/import-user-lists', ep___i_importUserLists], + ['i/notifications', ep___i_notifications], + ['i/page-likes', ep___i_pageLikes], + ['i/pages', ep___i_pages], + ['i/pin', ep___i_pin], + ['i/read-all-messaging-messages', ep___i_readAllMessagingMessages], + ['i/read-all-unread-notes', ep___i_readAllUnreadNotes], + ['i/read-announcement', ep___i_readAnnouncement], + ['i/regenerate-token', ep___i_regenerateToken], + ['i/registry/get-all', ep___i_registry_getAll], + ['i/registry/get-detail', ep___i_registry_getDetail], + ['i/registry/get', ep___i_registry_get], + ['i/registry/keys-with-type', ep___i_registry_keysWithType], + ['i/registry/keys', ep___i_registry_keys], + ['i/registry/remove', ep___i_registry_remove], + ['i/registry/scopes', ep___i_registry_scopes], + ['i/registry/set', ep___i_registry_set], + ['i/revoke-token', ep___i_revokeToken], + ['i/signin-history', ep___i_signinHistory], + ['i/unpin', ep___i_unpin], + ['i/update-email', ep___i_updateEmail], + ['i/update', ep___i_update], + ['i/user-group-invites', ep___i_userGroupInvites], + ['messaging/history', ep___messaging_history], + ['messaging/messages', ep___messaging_messages], + ['messaging/messages/create', ep___messaging_messages_create], + ['messaging/messages/delete', ep___messaging_messages_delete], + ['messaging/messages/read', ep___messaging_messages_read], + ['meta', ep___meta], + ['miauth/gen-token', ep___miauth_genToken], + ['mute/create', ep___mute_create], + ['mute/delete', ep___mute_delete], + ['mute/list', ep___mute_list], + ['my/apps', ep___my_apps], + ['notes', ep___notes], + ['notes/children', ep___notes_children], + ['notes/clips', ep___notes_clips], + ['notes/conversation', ep___notes_conversation], + ['notes/create', ep___notes_create], + ['notes/delete', ep___notes_delete], + ['notes/favorites/create', ep___notes_favorites_create], + ['notes/favorites/delete', ep___notes_favorites_delete], + ['notes/featured', ep___notes_featured], + ['notes/global-timeline', ep___notes_globalTimeline], + ['notes/hybrid-timeline', ep___notes_hybridTimeline], + ['notes/local-timeline', ep___notes_localTimeline], + ['notes/mentions', ep___notes_mentions], + ['notes/polls/recommendation', ep___notes_polls_recommendation], + ['notes/polls/vote', ep___notes_polls_vote], + ['notes/reactions', ep___notes_reactions], + ['notes/reactions/create', ep___notes_reactions_create], + ['notes/reactions/delete', ep___notes_reactions_delete], + ['notes/renotes', ep___notes_renotes], + ['notes/replies', ep___notes_replies], + ['notes/search-by-tag', ep___notes_searchByTag], + ['notes/search', ep___notes_search], + ['notes/show', ep___notes_show], + ['notes/state', ep___notes_state], + ['notes/thread-muting/create', ep___notes_threadMuting_create], + ['notes/thread-muting/delete', ep___notes_threadMuting_delete], + ['notes/timeline', ep___notes_timeline], + ['notes/translate', ep___notes_translate], + ['notes/unrenote', ep___notes_unrenote], + ['notes/user-list-timeline', ep___notes_userListTimeline], + ['notes/watching/create', ep___notes_watching_create], + ['notes/watching/delete', ep___notes_watching_delete], + ['notifications/create', ep___notifications_create], + ['notifications/mark-all-as-read', ep___notifications_markAllAsRead], + ['notifications/read', ep___notifications_read], + ['page-push', ep___pagePush], + ['pages/create', ep___pages_create], + ['pages/delete', ep___pages_delete], + ['pages/featured', ep___pages_featured], + ['pages/like', ep___pages_like], + ['pages/show', ep___pages_show], + ['pages/unlike', ep___pages_unlike], + ['pages/update', ep___pages_update], + ['ping', ep___ping], + ['pinned-users', ep___pinnedUsers], + ['promo/read', ep___promo_read], + ['request-reset-password', ep___requestResetPassword], + ['reset-db', ep___resetDb], + ['reset-password', ep___resetPassword], + ['server-info', ep___serverInfo], + ['stats', ep___stats], + ['sw/register', ep___sw_register], + ['sw/unregister', ep___sw_unregister], + ['test', ep___test], + ['username/available', ep___username_available], + ['users', ep___users], + ['users/clips', ep___users_clips], + ['users/followers', ep___users_followers], + ['users/following', ep___users_following], + ['users/gallery/posts', ep___users_gallery_posts], + ['users/get-frequently-replied-users', ep___users_getFrequentlyRepliedUsers], + ['users/groups/create', ep___users_groups_create], + ['users/groups/delete', ep___users_groups_delete], + ['users/groups/invitations/accept', ep___users_groups_invitations_accept], + ['users/groups/invitations/reject', ep___users_groups_invitations_reject], + ['users/groups/invite', ep___users_groups_invite], + ['users/groups/joined', ep___users_groups_joined], + ['users/groups/leave', ep___users_groups_leave], + ['users/groups/owned', ep___users_groups_owned], + ['users/groups/pull', ep___users_groups_pull], + ['users/groups/show', ep___users_groups_show], + ['users/groups/transfer', ep___users_groups_transfer], + ['users/groups/update', ep___users_groups_update], + ['users/lists/create', ep___users_lists_create], + ['users/lists/delete', ep___users_lists_delete], + ['users/lists/list', ep___users_lists_list], + ['users/lists/pull', ep___users_lists_pull], + ['users/lists/push', ep___users_lists_push], + ['users/lists/show', ep___users_lists_show], + ['users/lists/update', ep___users_lists_update], + ['users/notes', ep___users_notes], + ['users/pages', ep___users_pages], + ['users/reactions', ep___users_reactions], + ['users/recommendation', ep___users_recommendation], + ['users/relation', ep___users_relation], + ['users/report-abuse', ep___users_reportAbuse], + ['users/search-by-username-and-host', ep___users_searchByUsernameAndHost], + ['users/search', ep___users_search], + ['users/show', ep___users_show], + ['users/stats', ep___users_stats], +]; export interface IEndpointMeta { readonly stability?: 'deprecated' | 'experimental' | 'stable'; readonly tags?: ReadonlyArray; - readonly params?: { - readonly [key: string]: Param; - }; - readonly errors?: { readonly [key: string]: { readonly message: string; @@ -99,25 +686,23 @@ export interface IEndpointMeta { * パーミッションの実現に利用されます。 */ readonly kind?: string; + + readonly description?: string; } export interface IEndpoint { name: string; exec: any; meta: IEndpointMeta; + params: Schema; } -const files = glob.sync('**/*.js', { - cwd: path.resolve(_dirname + '/endpoints/'), -}); - -const endpoints: IEndpoint[] = files.map(f => { - const ep = require(`./endpoints/${f}`); - +const endpoints: IEndpoint[] = eps.map(([name, ep]) => { return { - name: f.replace('.js', ''), + name: name, exec: ep.default, meta: ep.meta || {}, + params: ep.paramDef, }; }); diff --git a/packages/backend/src/server/api/endpoints/admin/abuse-user-reports.ts b/packages/backend/src/server/api/endpoints/admin/abuse-user-reports.ts index ed7b146d0..333746f42 100644 --- a/packages/backend/src/server/api/endpoints/admin/abuse-user-reports.ts +++ b/packages/backend/src/server/api/endpoints/admin/abuse-user-reports.ts @@ -1,8 +1,6 @@ -import $ from 'cafy'; -import { ID } from '@/misc/cafy-id'; -import define from '../../define'; -import { AbuseUserReports } from '@/models/index'; -import { makePaginationQuery } from '../../common/make-pagination-query'; +import define from '../../define.js'; +import { AbuseUserReports } from '@/models/index.js'; +import { makePaginationQuery } from '../../common/make-pagination-query.js'; export const meta = { tags: ['admin'], @@ -10,49 +8,6 @@ export const meta = { requireCredential: true, requireModerator: true, - params: { - limit: { - validator: $.optional.num.range(1, 100), - default: 10, - }, - - sinceId: { - validator: $.optional.type(ID), - }, - - untilId: { - validator: $.optional.type(ID), - }, - - state: { - validator: $.optional.nullable.str, - default: null, - }, - - reporterOrigin: { - validator: $.optional.str.or([ - 'combined', - 'local', - 'remote', - ]), - default: 'combined', - }, - - targetUserOrigin: { - validator: $.optional.str.or([ - 'combined', - 'local', - 'remote', - ]), - default: 'combined', - }, - - forwarded: { - validator: $.optional.bool, - default: false, - }, - }, - res: { type: 'array', optional: false, nullable: false, @@ -115,8 +70,22 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + limit: { type: 'integer', minimum: 1, maximum: 100, default: 10 }, + sinceId: { type: 'string', format: 'misskey:id' }, + untilId: { type: 'string', format: 'misskey:id' }, + state: { type: 'string', nullable: true, default: null }, + reporterOrigin: { type: 'string', enum: ['combined', 'local', 'remote'], default: "combined" }, + targetUserOrigin: { type: 'string', enum: ['combined', 'local', 'remote'], default: "combined" }, + forwarded: { type: 'boolean', default: false }, + }, + required: [], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps) => { +export default define(meta, paramDef, async (ps) => { const query = makePaginationQuery(AbuseUserReports.createQueryBuilder('report'), ps.sinceId, ps.untilId); switch (ps.state) { @@ -134,7 +103,7 @@ export default define(meta, async (ps) => { case 'remote': query.andWhere('report.targetUserHost IS NOT NULL'); break; } - const reports = await query.take(ps.limit!).getMany(); + const reports = await query.take(ps.limit).getMany(); return await AbuseUserReports.packMany(reports); }); diff --git a/packages/backend/src/server/api/endpoints/admin/accounts/create.ts b/packages/backend/src/server/api/endpoints/admin/accounts/create.ts index 20f123295..2820c7993 100644 --- a/packages/backend/src/server/api/endpoints/admin/accounts/create.ts +++ b/packages/backend/src/server/api/endpoints/admin/accounts/create.ts @@ -1,20 +1,10 @@ -import define from '../../../define'; -import { Users } from '@/models/index'; -import { signup } from '../../../common/signup'; +import define from '../../../define.js'; +import { Users } from '@/models/index.js'; +import { signup } from '../../../common/signup.js'; export const meta = { tags: ['admin'], - params: { - username: { - validator: Users.validateLocalUsername, - }, - - password: { - validator: Users.validatePassword, - }, - }, - res: { type: 'object', optional: false, nullable: false, @@ -28,8 +18,17 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + username: Users.localUsernameSchema, + password: Users.passwordSchema, + }, + required: ['username', 'password'], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, _me) => { +export default define(meta, paramDef, async (ps, _me) => { const me = _me ? await Users.findOneOrFail(_me.id) : null; const noUsers = (await Users.count({ host: null, diff --git a/packages/backend/src/server/api/endpoints/admin/accounts/delete.ts b/packages/backend/src/server/api/endpoints/admin/accounts/delete.ts index 1701c1e3a..01754ec8f 100644 --- a/packages/backend/src/server/api/endpoints/admin/accounts/delete.ts +++ b/packages/backend/src/server/api/endpoints/admin/accounts/delete.ts @@ -1,26 +1,26 @@ -import $ from 'cafy'; -import define from '../../../define'; -import { Users } from '@/models/index'; -import { doPostSuspend } from '@/services/suspend-user'; -import { publishUserEvent } from '@/services/stream'; -import { createDeleteAccountJob } from '@/queue'; -import { ID } from '@/misc/cafy-id'; +import define from '../../../define.js'; +import { Users } from '@/models/index.js'; +import { doPostSuspend } from '@/services/suspend-user.js'; +import { publishUserEvent } from '@/services/stream.js'; +import { createDeleteAccountJob } from '@/queue/index.js'; export const meta = { tags: ['admin'], requireCredential: true, requireModerator: true, +} as const; - params: { - userId: { - validator: $.type(ID), - }, +export const paramDef = { + type: 'object', + properties: { + userId: { type: 'string', format: 'misskey:id' }, }, + required: ['userId'], } as const; // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, me) => { +export default define(meta, paramDef, async (ps, me) => { const user = await Users.findOne(ps.userId); if (user == null) { diff --git a/packages/backend/src/server/api/endpoints/admin/ad/create.ts b/packages/backend/src/server/api/endpoints/admin/ad/create.ts index 00ad2012f..ab2c50b50 100644 --- a/packages/backend/src/server/api/endpoints/admin/ad/create.ts +++ b/packages/backend/src/server/api/endpoints/admin/ad/create.ts @@ -1,41 +1,30 @@ -import $ from 'cafy'; -import define from '../../../define'; -import { Ads } from '@/models/index'; -import { genId } from '@/misc/gen-id'; +import define from '../../../define.js'; +import { Ads } from '@/models/index.js'; +import { genId } from '@/misc/gen-id.js'; export const meta = { tags: ['admin'], requireCredential: true, requireModerator: true, +} as const; - params: { - url: { - validator: $.str.min(1), - }, - memo: { - validator: $.str, - }, - place: { - validator: $.str, - }, - priority: { - validator: $.str, - }, - ratio: { - validator: $.num.int().min(0), - }, - expiresAt: { - validator: $.num.int(), - }, - imageUrl: { - validator: $.str.min(1), - }, +export const paramDef = { + type: 'object', + properties: { + url: { type: 'string', minLength: 1 }, + memo: { type: 'string' }, + place: { type: 'string' }, + priority: { type: 'string' }, + ratio: { type: 'integer' }, + expiresAt: { type: 'integer' }, + imageUrl: { type: 'string', minLength: 1 }, }, + required: ['url', 'memo', 'place', 'priority', 'ratio', 'expiresAt', 'imageUrl'], } as const; // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps) => { +export default define(meta, paramDef, async (ps) => { await Ads.insert({ id: genId(), createdAt: new Date(), diff --git a/packages/backend/src/server/api/endpoints/admin/ad/delete.ts b/packages/backend/src/server/api/endpoints/admin/ad/delete.ts index c0124e248..3663d974c 100644 --- a/packages/backend/src/server/api/endpoints/admin/ad/delete.ts +++ b/packages/backend/src/server/api/endpoints/admin/ad/delete.ts @@ -1,8 +1,6 @@ -import $ from 'cafy'; -import define from '../../../define'; -import { ID } from '@/misc/cafy-id'; -import { Ads } from '@/models/index'; -import { ApiError } from '../../../error'; +import define from '../../../define.js'; +import { Ads } from '@/models/index.js'; +import { ApiError } from '../../../error.js'; export const meta = { tags: ['admin'], @@ -10,12 +8,6 @@ export const meta = { requireCredential: true, requireModerator: true, - params: { - id: { - validator: $.type(ID), - }, - }, - errors: { noSuchAd: { message: 'No such ad.', @@ -25,8 +17,16 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + id: { type: 'string', format: 'misskey:id' }, + }, + required: ['id'], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, me) => { +export default define(meta, paramDef, async (ps, me) => { const ad = await Ads.findOne(ps.id); if (ad == null) throw new ApiError(meta.errors.noSuchAd); diff --git a/packages/backend/src/server/api/endpoints/admin/ad/list.ts b/packages/backend/src/server/api/endpoints/admin/ad/list.ts index 7a83637f3..74f154f27 100644 --- a/packages/backend/src/server/api/endpoints/admin/ad/list.ts +++ b/packages/backend/src/server/api/endpoints/admin/ad/list.ts @@ -1,37 +1,30 @@ -import $ from 'cafy'; -import { ID } from '@/misc/cafy-id'; -import define from '../../../define'; -import { Ads } from '@/models/index'; -import { makePaginationQuery } from '../../../common/make-pagination-query'; +import define from '../../../define.js'; +import { Ads } from '@/models/index.js'; +import { makePaginationQuery } from '../../../common/make-pagination-query.js'; export const meta = { tags: ['admin'], requireCredential: true, requireModerator: true, +} as const; - params: { - limit: { - validator: $.optional.num.range(1, 100), - default: 10, - }, - - sinceId: { - validator: $.optional.type(ID), - }, - - untilId: { - validator: $.optional.type(ID), - }, +export const paramDef = { + type: 'object', + properties: { + limit: { type: 'integer', minimum: 1, maximum: 100, default: 10 }, + sinceId: { type: 'string', format: 'misskey:id' }, + untilId: { type: 'string', format: 'misskey:id' }, }, + required: [], } as const; // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps) => { +export default define(meta, paramDef, async (ps) => { const query = makePaginationQuery(Ads.createQueryBuilder('ad'), ps.sinceId, ps.untilId) .andWhere('ad.expiresAt > :now', { now: new Date() }); - const ads = await query.take(ps.limit!).getMany(); + const ads = await query.take(ps.limit).getMany(); return ads; }); diff --git a/packages/backend/src/server/api/endpoints/admin/ad/update.ts b/packages/backend/src/server/api/endpoints/admin/ad/update.ts index c2b09ab9c..89c421db6 100644 --- a/packages/backend/src/server/api/endpoints/admin/ad/update.ts +++ b/packages/backend/src/server/api/endpoints/admin/ad/update.ts @@ -1,8 +1,6 @@ -import $ from 'cafy'; -import define from '../../../define'; -import { ID } from '@/misc/cafy-id'; -import { Ads } from '@/models/index'; -import { ApiError } from '../../../error'; +import define from '../../../define.js'; +import { Ads } from '@/models/index.js'; +import { ApiError } from '../../../error.js'; export const meta = { tags: ['admin'], @@ -10,33 +8,6 @@ export const meta = { requireCredential: true, requireModerator: true, - params: { - id: { - validator: $.type(ID), - }, - memo: { - validator: $.str, - }, - url: { - validator: $.str.min(1), - }, - imageUrl: { - validator: $.str.min(1), - }, - place: { - validator: $.str, - }, - priority: { - validator: $.str, - }, - ratio: { - validator: $.num.int().min(0), - }, - expiresAt: { - validator: $.num.int(), - }, - }, - errors: { noSuchAd: { message: 'No such ad.', @@ -46,8 +17,23 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + id: { type: 'string', format: 'misskey:id' }, + memo: { type: 'string' }, + url: { type: 'string', minLength: 1 }, + imageUrl: { type: 'string', minLength: 1 }, + place: { type: 'string' }, + priority: { type: 'string' }, + ratio: { type: 'integer' }, + expiresAt: { type: 'integer' }, + }, + required: ['id', 'memo', 'url', 'imageUrl', 'place', 'priority', 'ratio', 'expiresAt'], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, me) => { +export default define(meta, paramDef, async (ps, me) => { const ad = await Ads.findOne(ps.id); if (ad == null) throw new ApiError(meta.errors.noSuchAd); diff --git a/packages/backend/src/server/api/endpoints/admin/announcements/create.ts b/packages/backend/src/server/api/endpoints/admin/announcements/create.ts index 24c4caa37..41570078d 100644 --- a/packages/backend/src/server/api/endpoints/admin/announcements/create.ts +++ b/packages/backend/src/server/api/endpoints/admin/announcements/create.ts @@ -1,7 +1,6 @@ -import $ from 'cafy'; -import define from '../../../define'; -import { Announcements } from '@/models/index'; -import { genId } from '@/misc/gen-id'; +import define from '../../../define.js'; +import { Announcements } from '@/models/index.js'; +import { genId } from '@/misc/gen-id.js'; export const meta = { tags: ['admin'], @@ -9,18 +8,6 @@ export const meta = { requireCredential: true, requireModerator: true, - params: { - title: { - validator: $.str.min(1), - }, - text: { - validator: $.str.min(1), - }, - imageUrl: { - validator: $.nullable.str.min(1), - }, - }, - res: { type: 'object', optional: false, nullable: false, @@ -57,8 +44,18 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + title: { type: 'string', minLength: 1 }, + text: { type: 'string', minLength: 1 }, + imageUrl: { type: 'string', nullable: true, minLength: 1 }, + }, + required: ['title', 'text', 'imageUrl'], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps) => { +export default define(meta, paramDef, async (ps) => { const announcement = await Announcements.insert({ id: genId(), createdAt: new Date(), @@ -68,5 +65,5 @@ export default define(meta, async (ps) => { imageUrl: ps.imageUrl, }).then(x => Announcements.findOneOrFail(x.identifiers[0])); - return announcement; + return Object.assign({}, announcement, { createdAt: announcement.createdAt.toISOString(), updatedAt: null }); }); diff --git a/packages/backend/src/server/api/endpoints/admin/announcements/delete.ts b/packages/backend/src/server/api/endpoints/admin/announcements/delete.ts index 5548f9900..4871dc4e1 100644 --- a/packages/backend/src/server/api/endpoints/admin/announcements/delete.ts +++ b/packages/backend/src/server/api/endpoints/admin/announcements/delete.ts @@ -1,8 +1,6 @@ -import $ from 'cafy'; -import define from '../../../define'; -import { ID } from '@/misc/cafy-id'; -import { Announcements } from '@/models/index'; -import { ApiError } from '../../../error'; +import define from '../../../define.js'; +import { Announcements } from '@/models/index.js'; +import { ApiError } from '../../../error.js'; export const meta = { tags: ['admin'], @@ -10,12 +8,6 @@ export const meta = { requireCredential: true, requireModerator: true, - params: { - id: { - validator: $.type(ID), - }, - }, - errors: { noSuchAnnouncement: { message: 'No such announcement.', @@ -25,8 +17,16 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + id: { type: 'string', format: 'misskey:id' }, + }, + required: ['id'], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, me) => { +export default define(meta, paramDef, async (ps, me) => { const announcement = await Announcements.findOne(ps.id); if (announcement == null) throw new ApiError(meta.errors.noSuchAnnouncement); diff --git a/packages/backend/src/server/api/endpoints/admin/announcements/list.ts b/packages/backend/src/server/api/endpoints/admin/announcements/list.ts index e5cc53ccd..0ba0a8ee0 100644 --- a/packages/backend/src/server/api/endpoints/admin/announcements/list.ts +++ b/packages/backend/src/server/api/endpoints/admin/announcements/list.ts @@ -1,8 +1,6 @@ -import $ from 'cafy'; -import { ID } from '@/misc/cafy-id'; -import define from '../../../define'; -import { Announcements, AnnouncementReads } from '@/models/index'; -import { makePaginationQuery } from '../../../common/make-pagination-query'; +import define from '../../../define.js'; +import { Announcements, AnnouncementReads } from '@/models/index.js'; +import { makePaginationQuery } from '../../../common/make-pagination-query.js'; export const meta = { tags: ['admin'], @@ -10,21 +8,6 @@ export const meta = { requireCredential: true, requireModerator: true, - params: { - limit: { - validator: $.optional.num.range(1, 100), - default: 10, - }, - - sinceId: { - validator: $.optional.type(ID), - }, - - untilId: { - validator: $.optional.type(ID), - }, - }, - res: { type: 'array', optional: false, nullable: false, @@ -69,11 +52,21 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + limit: { type: 'integer', minimum: 1, maximum: 100, default: 10 }, + sinceId: { type: 'string', format: 'misskey:id' }, + untilId: { type: 'string', format: 'misskey:id' }, + }, + required: [], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps) => { +export default define(meta, paramDef, async (ps) => { const query = makePaginationQuery(Announcements.createQueryBuilder('announcement'), ps.sinceId, ps.untilId); - const announcements = await query.take(ps.limit!).getMany(); + const announcements = await query.take(ps.limit).getMany(); for (const announcement of announcements) { (announcement as any).reads = await AnnouncementReads.count({ diff --git a/packages/backend/src/server/api/endpoints/admin/announcements/update.ts b/packages/backend/src/server/api/endpoints/admin/announcements/update.ts index f66293bb1..138337ef5 100644 --- a/packages/backend/src/server/api/endpoints/admin/announcements/update.ts +++ b/packages/backend/src/server/api/endpoints/admin/announcements/update.ts @@ -1,8 +1,6 @@ -import $ from 'cafy'; -import define from '../../../define'; -import { ID } from '@/misc/cafy-id'; -import { Announcements } from '@/models/index'; -import { ApiError } from '../../../error'; +import define from '../../../define.js'; +import { Announcements } from '@/models/index.js'; +import { ApiError } from '../../../error.js'; export const meta = { tags: ['admin'], @@ -10,21 +8,6 @@ export const meta = { requireCredential: true, requireModerator: true, - params: { - id: { - validator: $.type(ID), - }, - title: { - validator: $.str.min(1), - }, - text: { - validator: $.str.min(1), - }, - imageUrl: { - validator: $.nullable.str.min(1), - }, - }, - errors: { noSuchAnnouncement: { message: 'No such announcement.', @@ -34,8 +17,19 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + id: { type: 'string', format: 'misskey:id' }, + title: { type: 'string', minLength: 1 }, + text: { type: 'string', minLength: 1 }, + imageUrl: { type: 'string', nullable: true, minLength: 1 }, + }, + required: ['id', 'title', 'text', 'imageUrl'], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, me) => { +export default define(meta, paramDef, async (ps, me) => { const announcement = await Announcements.findOne(ps.id); if (announcement == null) throw new ApiError(meta.errors.noSuchAnnouncement); diff --git a/packages/backend/src/server/api/endpoints/admin/delete-all-files-of-a-user.ts b/packages/backend/src/server/api/endpoints/admin/delete-all-files-of-a-user.ts index 249e63a0f..90e65ec4c 100644 --- a/packages/backend/src/server/api/endpoints/admin/delete-all-files-of-a-user.ts +++ b/packages/backend/src/server/api/endpoints/admin/delete-all-files-of-a-user.ts @@ -1,24 +1,24 @@ -import $ from 'cafy'; -import define from '../../define'; -import { deleteFile } from '@/services/drive/delete-file'; -import { DriveFiles } from '@/models/index'; -import { ID } from '@/misc/cafy-id'; +import define from '../../define.js'; +import { deleteFile } from '@/services/drive/delete-file.js'; +import { DriveFiles } from '@/models/index.js'; export const meta = { tags: ['admin'], requireCredential: true, requireModerator: true, +} as const; - params: { - userId: { - validator: $.type(ID), - }, +export const paramDef = { + type: 'object', + properties: { + userId: { type: 'string', format: 'misskey:id' }, }, + required: ['userId'], } as const; // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, me) => { +export default define(meta, paramDef, async (ps, me) => { const files = await DriveFiles.find({ userId: ps.userId, }); diff --git a/packages/backend/src/server/api/endpoints/admin/drive/clean-remote-files.ts b/packages/backend/src/server/api/endpoints/admin/drive/clean-remote-files.ts index acabbfef5..bab149532 100644 --- a/packages/backend/src/server/api/endpoints/admin/drive/clean-remote-files.ts +++ b/packages/backend/src/server/api/endpoints/admin/drive/clean-remote-files.ts @@ -1,5 +1,5 @@ -import define from '../../../define'; -import { createCleanRemoteFilesJob } from '@/queue/index'; +import define from '../../../define.js'; +import { createCleanRemoteFilesJob } from '@/queue/index.js'; export const meta = { tags: ['admin'], @@ -8,7 +8,13 @@ export const meta = { requireModerator: true, } as const; +export const paramDef = { + type: 'object', + properties: {}, + required: [], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, me) => { +export default define(meta, paramDef, async (ps, me) => { createCleanRemoteFilesJob(); }); diff --git a/packages/backend/src/server/api/endpoints/admin/drive/cleanup.ts b/packages/backend/src/server/api/endpoints/admin/drive/cleanup.ts index 452e7069a..3e7d43fb0 100644 --- a/packages/backend/src/server/api/endpoints/admin/drive/cleanup.ts +++ b/packages/backend/src/server/api/endpoints/admin/drive/cleanup.ts @@ -1,7 +1,7 @@ import { IsNull } from 'typeorm'; -import define from '../../../define'; -import { deleteFile } from '@/services/drive/delete-file'; -import { DriveFiles } from '@/models/index'; +import define from '../../../define.js'; +import { deleteFile } from '@/services/drive/delete-file.js'; +import { DriveFiles } from '@/models/index.js'; export const meta = { tags: ['admin'], @@ -10,8 +10,14 @@ export const meta = { requireModerator: true, } as const; +export const paramDef = { + type: 'object', + properties: {}, + required: [], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, me) => { +export default define(meta, paramDef, async (ps, me) => { const files = await DriveFiles.find({ userId: IsNull(), }); diff --git a/packages/backend/src/server/api/endpoints/admin/drive/files.ts b/packages/backend/src/server/api/endpoints/admin/drive/files.ts index 264f54986..646d85a1e 100644 --- a/packages/backend/src/server/api/endpoints/admin/drive/files.ts +++ b/packages/backend/src/server/api/endpoints/admin/drive/files.ts @@ -1,8 +1,6 @@ -import $ from 'cafy'; -import define from '../../../define'; -import { DriveFiles } from '@/models/index'; -import { makePaginationQuery } from '../../../common/make-pagination-query'; -import { ID } from '@/misc/cafy-id'; +import define from '../../../define.js'; +import { DriveFiles } from '@/models/index.js'; +import { makePaginationQuery } from '../../../common/make-pagination-query.js'; export const meta = { tags: ['admin'], @@ -10,39 +8,6 @@ export const meta = { requireCredential: false, requireModerator: true, - params: { - limit: { - validator: $.optional.num.range(1, 100), - default: 10, - }, - - sinceId: { - validator: $.optional.type(ID), - }, - - untilId: { - validator: $.optional.type(ID), - }, - - type: { - validator: $.optional.nullable.str.match(/^[a-zA-Z0-9\/\-*]+$/), - }, - - origin: { - validator: $.optional.str.or([ - 'combined', - 'local', - 'remote', - ]), - default: 'local', - }, - - hostname: { - validator: $.optional.nullable.str, - default: null, - }, - }, - res: { type: 'array', optional: false, nullable: false, @@ -54,8 +19,21 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + limit: { type: 'integer', minimum: 1, maximum: 100, default: 10 }, + sinceId: { type: 'string', format: 'misskey:id' }, + untilId: { type: 'string', format: 'misskey:id' }, + type: { type: 'string', nullable: true, pattern: /^[a-zA-Z0-9\/\-*]+$/.toString().slice(1, -1) }, + origin: { type: 'string', enum: ['combined', 'local', 'remote'], default: "local" }, + hostname: { type: 'string', nullable: true, default: null }, + }, + required: [], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, me) => { +export default define(meta, paramDef, async (ps, me) => { const query = makePaginationQuery(DriveFiles.createQueryBuilder('file'), ps.sinceId, ps.untilId); if (ps.origin === 'local') { @@ -76,7 +54,7 @@ export default define(meta, async (ps, me) => { } } - const files = await query.take(ps.limit!).getMany(); + const files = await query.take(ps.limit).getMany(); return await DriveFiles.packMany(files, { detail: true, withUser: true, self: true }); }); diff --git a/packages/backend/src/server/api/endpoints/admin/drive/show-file.ts b/packages/backend/src/server/api/endpoints/admin/drive/show-file.ts index 5d9a1f270..e82116009 100644 --- a/packages/backend/src/server/api/endpoints/admin/drive/show-file.ts +++ b/packages/backend/src/server/api/endpoints/admin/drive/show-file.ts @@ -1,8 +1,6 @@ -import $ from 'cafy'; -import { ID } from '@/misc/cafy-id'; -import define from '../../../define'; -import { ApiError } from '../../../error'; -import { DriveFiles } from '@/models/index'; +import define from '../../../define.js'; +import { ApiError } from '../../../error.js'; +import { DriveFiles } from '@/models/index.js'; export const meta = { tags: ['admin'], @@ -10,16 +8,6 @@ export const meta = { requireCredential: true, requireModerator: true, - params: { - fileId: { - validator: $.optional.type(ID), - }, - - url: { - validator: $.optional.str, - }, - }, - errors: { noSuchFile: { message: 'No such file.', @@ -161,8 +149,17 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + fileId: { type: 'string', format: 'misskey:id' }, + url: { type: 'string' }, + }, + required: [], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, me) => { +export default define(meta, paramDef, async (ps, me) => { const file = ps.fileId ? await DriveFiles.findOne(ps.fileId) : await DriveFiles.findOne({ where: [{ url: ps.url, diff --git a/packages/backend/src/server/api/endpoints/admin/emoji/add-aliases-bulk.ts b/packages/backend/src/server/api/endpoints/admin/emoji/add-aliases-bulk.ts index f0fd73c27..77a4adea6 100644 --- a/packages/backend/src/server/api/endpoints/admin/emoji/add-aliases-bulk.ts +++ b/packages/backend/src/server/api/endpoints/admin/emoji/add-aliases-bulk.ts @@ -1,29 +1,30 @@ -import $ from 'cafy'; -import define from '../../../define'; -import { ID } from '@/misc/cafy-id'; -import { Emojis } from '@/models/index'; +import define from '../../../define.js'; +import { Emojis } from '@/models/index.js'; import { getConnection, In } from 'typeorm'; -import { ApiError } from '../../../error'; +import { ApiError } from '../../../error.js'; export const meta = { tags: ['admin'], requireCredential: true, requireModerator: true, +} as const; - params: { - ids: { - validator: $.arr($.type(ID)), - }, - - aliases: { - validator: $.arr($.str), - }, +export const paramDef = { + type: 'object', + properties: { + ids: { type: 'array', items: { + type: 'string', format: 'misskey:id', + } }, + aliases: { type: 'array', items: { + type: 'string', + } }, }, + required: ['ids', 'aliases'], } as const; // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps) => { +export default define(meta, paramDef, async (ps) => { const emojis = await Emojis.find({ id: In(ps.ids), }); diff --git a/packages/backend/src/server/api/endpoints/admin/emoji/add.ts b/packages/backend/src/server/api/endpoints/admin/emoji/add.ts index 1dfeae262..c5787d59d 100644 --- a/packages/backend/src/server/api/endpoints/admin/emoji/add.ts +++ b/packages/backend/src/server/api/endpoints/admin/emoji/add.ts @@ -1,13 +1,11 @@ -import $ from 'cafy'; -import define from '../../../define'; -import { Emojis, DriveFiles } from '@/models/index'; -import { genId } from '@/misc/gen-id'; +import define from '../../../define.js'; +import { Emojis, DriveFiles } from '@/models/index.js'; +import { genId } from '@/misc/gen-id.js'; import { getConnection } from 'typeorm'; -import { insertModerationLog } from '@/services/insert-moderation-log'; -import { ApiError } from '../../../error'; -import { ID } from '@/misc/cafy-id'; +import { insertModerationLog } from '@/services/insert-moderation-log.js'; +import { ApiError } from '../../../error.js'; import rndstr from 'rndstr'; -import { publishBroadcastStream } from '@/services/stream'; +import { publishBroadcastStream } from '@/services/stream.js'; export const meta = { tags: ['admin'], @@ -15,12 +13,6 @@ export const meta = { requireCredential: true, requireModerator: true, - params: { - fileId: { - validator: $.type(ID), - }, - }, - errors: { noSuchFile: { message: 'No such file.', @@ -30,8 +22,16 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + fileId: { type: 'string', format: 'misskey:id' }, + }, + required: ['fileId'], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, me) => { +export default define(meta, paramDef, async (ps, me) => { const file = await DriveFiles.findOne(ps.fileId); if (file == null) throw new ApiError(meta.errors.noSuchFile); diff --git a/packages/backend/src/server/api/endpoints/admin/emoji/copy.ts b/packages/backend/src/server/api/endpoints/admin/emoji/copy.ts index 17cbf208a..a0eaa6125 100644 --- a/packages/backend/src/server/api/endpoints/admin/emoji/copy.ts +++ b/packages/backend/src/server/api/endpoints/admin/emoji/copy.ts @@ -1,13 +1,11 @@ -import $ from 'cafy'; -import define from '../../../define'; -import { Emojis } from '@/models/index'; -import { genId } from '@/misc/gen-id'; +import define from '../../../define.js'; +import { Emojis } from '@/models/index.js'; +import { genId } from '@/misc/gen-id.js'; import { getConnection } from 'typeorm'; -import { ApiError } from '../../../error'; -import { DriveFile } from '@/models/entities/drive-file'; -import { ID } from '@/misc/cafy-id'; -import { uploadFromUrl } from '@/services/drive/upload-from-url'; -import { publishBroadcastStream } from '@/services/stream'; +import { ApiError } from '../../../error.js'; +import { DriveFile } from '@/models/entities/drive-file.js'; +import { uploadFromUrl } from '@/services/drive/upload-from-url.js'; +import { publishBroadcastStream } from '@/services/stream.js'; export const meta = { tags: ['admin'], @@ -15,12 +13,6 @@ export const meta = { requireCredential: true, requireModerator: true, - params: { - emojiId: { - validator: $.type(ID), - }, - }, - errors: { noSuchEmoji: { message: 'No such emoji.', @@ -42,8 +34,16 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + emojiId: { type: 'string', format: 'misskey:id' }, + }, + required: ['emojiId'], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, me) => { +export default define(meta, paramDef, async (ps, me) => { const emoji = await Emojis.findOne(ps.emojiId); if (emoji == null) { diff --git a/packages/backend/src/server/api/endpoints/admin/emoji/delete-bulk.ts b/packages/backend/src/server/api/endpoints/admin/emoji/delete-bulk.ts index 797a5de67..38a2d65cf 100644 --- a/packages/backend/src/server/api/endpoints/admin/emoji/delete-bulk.ts +++ b/packages/backend/src/server/api/endpoints/admin/emoji/delete-bulk.ts @@ -1,26 +1,28 @@ -import $ from 'cafy'; -import define from '../../../define'; -import { ID } from '@/misc/cafy-id'; -import { Emojis } from '@/models/index'; +import define from '../../../define.js'; +import { Emojis } from '@/models/index.js'; import { getConnection, In } from 'typeorm'; -import { insertModerationLog } from '@/services/insert-moderation-log'; -import { ApiError } from '../../../error'; +import { insertModerationLog } from '@/services/insert-moderation-log.js'; +import { ApiError } from '../../../error.js'; export const meta = { tags: ['admin'], requireCredential: true, requireModerator: true, +} as const; - params: { - ids: { - validator: $.arr($.type(ID)), - }, +export const paramDef = { + type: 'object', + properties: { + ids: { type: 'array', items: { + type: 'string', format: 'misskey:id', + } }, }, + required: ['ids'], } as const; // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, me) => { +export default define(meta, paramDef, async (ps, me) => { const emojis = await Emojis.find({ id: In(ps.ids), }); diff --git a/packages/backend/src/server/api/endpoints/admin/emoji/delete.ts b/packages/backend/src/server/api/endpoints/admin/emoji/delete.ts index 158043902..a0cffb47f 100644 --- a/packages/backend/src/server/api/endpoints/admin/emoji/delete.ts +++ b/packages/backend/src/server/api/endpoints/admin/emoji/delete.ts @@ -1,10 +1,8 @@ -import $ from 'cafy'; -import define from '../../../define'; -import { ID } from '@/misc/cafy-id'; -import { Emojis } from '@/models/index'; +import define from '../../../define.js'; +import { Emojis } from '@/models/index.js'; import { getConnection } from 'typeorm'; -import { insertModerationLog } from '@/services/insert-moderation-log'; -import { ApiError } from '../../../error'; +import { insertModerationLog } from '@/services/insert-moderation-log.js'; +import { ApiError } from '../../../error.js'; export const meta = { tags: ['admin'], @@ -12,12 +10,6 @@ export const meta = { requireCredential: true, requireModerator: true, - params: { - id: { - validator: $.type(ID), - }, - }, - errors: { noSuchEmoji: { message: 'No such emoji.', @@ -27,8 +19,16 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + id: { type: 'string', format: 'misskey:id' }, + }, + required: ['id'], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, me) => { +export default define(meta, paramDef, async (ps, me) => { const emoji = await Emojis.findOne(ps.id); if (emoji == null) throw new ApiError(meta.errors.noSuchEmoji); diff --git a/packages/backend/src/server/api/endpoints/admin/emoji/import-zip.ts b/packages/backend/src/server/api/endpoints/admin/emoji/import-zip.ts index 8856a38f2..3f03dc2da 100644 --- a/packages/backend/src/server/api/endpoints/admin/emoji/import-zip.ts +++ b/packages/backend/src/server/api/endpoints/admin/emoji/import-zip.ts @@ -1,21 +1,22 @@ -import $ from 'cafy'; -import define from '../../../define'; -import { createImportCustomEmojisJob } from '@/queue/index'; +import define from '../../../define.js'; +import { createImportCustomEmojisJob } from '@/queue/index.js'; import ms from 'ms'; -import { ID } from '@/misc/cafy-id'; export const meta = { secure: true, requireCredential: true, requireModerator: true, - params: { - fileId: { - validator: $.type(ID), - }, +} as const; + +export const paramDef = { + type: 'object', + properties: { + fileId: { type: 'string', format: 'misskey:id' }, }, + required: ['fileId'], } as const; // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, user) => { +export default define(meta, paramDef, async (ps, user) => { createImportCustomEmojisJob(user, ps.fileId); }); diff --git a/packages/backend/src/server/api/endpoints/admin/emoji/list-remote.ts b/packages/backend/src/server/api/endpoints/admin/emoji/list-remote.ts index 6e502547f..f19c3ddbd 100644 --- a/packages/backend/src/server/api/endpoints/admin/emoji/list-remote.ts +++ b/packages/backend/src/server/api/endpoints/admin/emoji/list-remote.ts @@ -1,9 +1,7 @@ -import $ from 'cafy'; -import define from '../../../define'; -import { Emojis } from '@/models/index'; -import { toPuny } from '@/misc/convert-host'; -import { makePaginationQuery } from '../../../common/make-pagination-query'; -import { ID } from '@/misc/cafy-id'; +import define from '../../../define.js'; +import { Emojis } from '@/models/index.js'; +import { toPuny } from '@/misc/convert-host.js'; +import { makePaginationQuery } from '../../../common/make-pagination-query.js'; export const meta = { tags: ['admin'], @@ -11,31 +9,6 @@ export const meta = { requireCredential: true, requireModerator: true, - params: { - query: { - validator: $.optional.nullable.str, - default: null, - }, - - host: { - validator: $.optional.nullable.str, - default: null, - }, - - limit: { - validator: $.optional.num.range(1, 100), - default: 10, - }, - - sinceId: { - validator: $.optional.type(ID), - }, - - untilId: { - validator: $.optional.type(ID), - }, - }, - res: { type: 'array', optional: false, nullable: false, @@ -77,8 +50,20 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + query: { type: 'string', nullable: true, default: null }, + host: { type: 'string', nullable: true, default: null }, + limit: { type: 'integer', minimum: 1, maximum: 100, default: 10 }, + sinceId: { type: 'string', format: 'misskey:id' }, + untilId: { type: 'string', format: 'misskey:id' }, + }, + required: [], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps) => { +export default define(meta, paramDef, async (ps) => { const q = makePaginationQuery(Emojis.createQueryBuilder('emoji'), ps.sinceId, ps.untilId); if (ps.host == null) { @@ -93,7 +78,7 @@ export default define(meta, async (ps) => { const emojis = await q .orderBy('emoji.id', 'DESC') - .take(ps.limit!) + .take(ps.limit) .getMany(); return Emojis.packMany(emojis); diff --git a/packages/backend/src/server/api/endpoints/admin/emoji/list.ts b/packages/backend/src/server/api/endpoints/admin/emoji/list.ts index 76ef190f9..f488a71a0 100644 --- a/packages/backend/src/server/api/endpoints/admin/emoji/list.ts +++ b/packages/backend/src/server/api/endpoints/admin/emoji/list.ts @@ -1,9 +1,7 @@ -import $ from 'cafy'; -import define from '../../../define'; -import { Emojis } from '@/models/index'; -import { makePaginationQuery } from '../../../common/make-pagination-query'; -import { ID } from '@/misc/cafy-id'; -import { Emoji } from '@/models/entities/emoji'; +import define from '../../../define.js'; +import { Emojis } from '@/models/index.js'; +import { makePaginationQuery } from '../../../common/make-pagination-query.js'; +import { Emoji } from '@/models/entities/emoji.js'; export const meta = { tags: ['admin'], @@ -11,26 +9,6 @@ export const meta = { requireCredential: true, requireModerator: true, - params: { - query: { - validator: $.optional.nullable.str, - default: null, - }, - - limit: { - validator: $.optional.num.range(1, 100), - default: 10, - }, - - sinceId: { - validator: $.optional.type(ID), - }, - - untilId: { - validator: $.optional.type(ID), - }, - }, - res: { type: 'array', optional: false, nullable: false, @@ -72,8 +50,19 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + query: { type: 'string', nullable: true, default: null }, + limit: { type: 'integer', minimum: 1, maximum: 100, default: 10 }, + sinceId: { type: 'string', format: 'misskey:id' }, + untilId: { type: 'string', format: 'misskey:id' }, + }, + required: [], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps) => { +export default define(meta, paramDef, async (ps) => { const q = makePaginationQuery(Emojis.createQueryBuilder('emoji'), ps.sinceId, ps.untilId) .andWhere(`emoji.host IS NULL`); @@ -81,7 +70,7 @@ export default define(meta, async (ps) => { if (ps.query) { //q.andWhere('emoji.name ILIKE :q', { q: `%${ps.query}%` }); - //const emojis = await q.take(ps.limit!).getMany(); + //const emojis = await q.take(ps.limit).getMany(); emojis = await q.getMany(); @@ -90,9 +79,9 @@ export default define(meta, async (ps) => { emoji.aliases.some(a => a.includes(ps.query!)) || emoji.category?.includes(ps.query!)); - emojis.splice(ps.limit! + 1); + emojis.splice(ps.limit + 1); } else { - emojis = await q.take(ps.limit!).getMany(); + emojis = await q.take(ps.limit).getMany(); } return Emojis.packMany(emojis); diff --git a/packages/backend/src/server/api/endpoints/admin/emoji/remove-aliases-bulk.ts b/packages/backend/src/server/api/endpoints/admin/emoji/remove-aliases-bulk.ts index c49f84b7f..dbad93d33 100644 --- a/packages/backend/src/server/api/endpoints/admin/emoji/remove-aliases-bulk.ts +++ b/packages/backend/src/server/api/endpoints/admin/emoji/remove-aliases-bulk.ts @@ -1,29 +1,30 @@ -import $ from 'cafy'; -import define from '../../../define'; -import { ID } from '@/misc/cafy-id'; -import { Emojis } from '@/models/index'; +import define from '../../../define.js'; +import { Emojis } from '@/models/index.js'; import { getConnection, In } from 'typeorm'; -import { ApiError } from '../../../error'; +import { ApiError } from '../../../error.js'; export const meta = { tags: ['admin'], requireCredential: true, requireModerator: true, +} as const; - params: { - ids: { - validator: $.arr($.type(ID)), - }, - - aliases: { - validator: $.arr($.str), - }, +export const paramDef = { + type: 'object', + properties: { + ids: { type: 'array', items: { + type: 'string', format: 'misskey:id', + } }, + aliases: { type: 'array', items: { + type: 'string', + } }, }, + required: ['ids', 'aliases'], } as const; // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps) => { +export default define(meta, paramDef, async (ps) => { const emojis = await Emojis.find({ id: In(ps.ids), }); diff --git a/packages/backend/src/server/api/endpoints/admin/emoji/set-aliases-bulk.ts b/packages/backend/src/server/api/endpoints/admin/emoji/set-aliases-bulk.ts index 06197820f..470b9bef0 100644 --- a/packages/backend/src/server/api/endpoints/admin/emoji/set-aliases-bulk.ts +++ b/packages/backend/src/server/api/endpoints/admin/emoji/set-aliases-bulk.ts @@ -1,29 +1,30 @@ -import $ from 'cafy'; -import define from '../../../define'; -import { ID } from '@/misc/cafy-id'; -import { Emojis } from '@/models/index'; +import define from '../../../define.js'; +import { Emojis } from '@/models/index.js'; import { getConnection, In } from 'typeorm'; -import { ApiError } from '../../../error'; +import { ApiError } from '../../../error.js'; export const meta = { tags: ['admin'], requireCredential: true, requireModerator: true, +} as const; - params: { - ids: { - validator: $.arr($.type(ID)), - }, - - aliases: { - validator: $.arr($.str), - }, +export const paramDef = { + type: 'object', + properties: { + ids: { type: 'array', items: { + type: 'string', format: 'misskey:id', + } }, + aliases: { type: 'array', items: { + type: 'string', + } }, }, + required: ['ids', 'aliases'], } as const; // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps) => { +export default define(meta, paramDef, async (ps) => { await Emojis.update({ id: In(ps.ids), }, { diff --git a/packages/backend/src/server/api/endpoints/admin/emoji/set-category-bulk.ts b/packages/backend/src/server/api/endpoints/admin/emoji/set-category-bulk.ts index f0645f111..40e4c0199 100644 --- a/packages/backend/src/server/api/endpoints/admin/emoji/set-category-bulk.ts +++ b/packages/backend/src/server/api/endpoints/admin/emoji/set-category-bulk.ts @@ -1,29 +1,28 @@ -import $ from 'cafy'; -import define from '../../../define'; -import { ID } from '@/misc/cafy-id'; -import { Emojis } from '@/models/index'; +import define from '../../../define.js'; +import { Emojis } from '@/models/index.js'; import { getConnection, In } from 'typeorm'; -import { ApiError } from '../../../error'; +import { ApiError } from '../../../error.js'; export const meta = { tags: ['admin'], requireCredential: true, requireModerator: true, +} as const; - params: { - ids: { - validator: $.arr($.type(ID)), - }, - - category: { - validator: $.optional.nullable.str, - }, +export const paramDef = { + type: 'object', + properties: { + ids: { type: 'array', items: { + type: 'string', format: 'misskey:id', + } }, + category: { type: 'string', nullable: true }, }, + required: ['ids'], } as const; // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps) => { +export default define(meta, paramDef, async (ps) => { await Emojis.update({ id: In(ps.ids), }, { diff --git a/packages/backend/src/server/api/endpoints/admin/emoji/update.ts b/packages/backend/src/server/api/endpoints/admin/emoji/update.ts index 54a2cf951..c6d07e16f 100644 --- a/packages/backend/src/server/api/endpoints/admin/emoji/update.ts +++ b/packages/backend/src/server/api/endpoints/admin/emoji/update.ts @@ -1,9 +1,7 @@ -import $ from 'cafy'; -import define from '../../../define'; -import { ID } from '@/misc/cafy-id'; -import { Emojis } from '@/models/index'; +import define from '../../../define.js'; +import { Emojis } from '@/models/index.js'; import { getConnection } from 'typeorm'; -import { ApiError } from '../../../error'; +import { ApiError } from '../../../error.js'; export const meta = { tags: ['admin'], @@ -11,24 +9,6 @@ export const meta = { requireCredential: true, requireModerator: true, - params: { - id: { - validator: $.type(ID), - }, - - name: { - validator: $.str, - }, - - category: { - validator: $.optional.nullable.str, - }, - - aliases: { - validator: $.arr($.str), - }, - }, - errors: { noSuchEmoji: { message: 'No such emoji.', @@ -38,8 +18,21 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + id: { type: 'string', format: 'misskey:id' }, + name: { type: 'string' }, + category: { type: 'string', nullable: true }, + aliases: { type: 'array', items: { + type: 'string', + } }, + }, + required: ['id', 'name', 'aliases'], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps) => { +export default define(meta, paramDef, async (ps) => { const emoji = await Emojis.findOne(ps.id); if (emoji == null) throw new ApiError(meta.errors.noSuchEmoji); diff --git a/packages/backend/src/server/api/endpoints/admin/federation/delete-all-files.ts b/packages/backend/src/server/api/endpoints/admin/federation/delete-all-files.ts index db023c6f0..d4251f2fe 100644 --- a/packages/backend/src/server/api/endpoints/admin/federation/delete-all-files.ts +++ b/packages/backend/src/server/api/endpoints/admin/federation/delete-all-files.ts @@ -1,23 +1,24 @@ -import $ from 'cafy'; -import define from '../../../define'; -import { deleteFile } from '@/services/drive/delete-file'; -import { DriveFiles } from '@/models/index'; +import define from '../../../define.js'; +import { deleteFile } from '@/services/drive/delete-file.js'; +import { DriveFiles } from '@/models/index.js'; export const meta = { tags: ['admin'], requireCredential: true, requireModerator: true, +} as const; - params: { - host: { - validator: $.str, - }, +export const paramDef = { + type: 'object', + properties: { + host: { type: 'string' }, }, + required: ['host'], } as const; // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, me) => { +export default define(meta, paramDef, async (ps, me) => { const files = await DriveFiles.find({ userHost: ps.host, }); diff --git a/packages/backend/src/server/api/endpoints/admin/federation/refresh-remote-instance-metadata.ts b/packages/backend/src/server/api/endpoints/admin/federation/refresh-remote-instance-metadata.ts index b68252ef2..86978cc30 100644 --- a/packages/backend/src/server/api/endpoints/admin/federation/refresh-remote-instance-metadata.ts +++ b/packages/backend/src/server/api/endpoints/admin/federation/refresh-remote-instance-metadata.ts @@ -1,24 +1,25 @@ -import $ from 'cafy'; -import define from '../../../define'; -import { Instances } from '@/models/index'; -import { toPuny } from '@/misc/convert-host'; -import { fetchInstanceMetadata } from '@/services/fetch-instance-metadata'; +import define from '../../../define.js'; +import { Instances } from '@/models/index.js'; +import { toPuny } from '@/misc/convert-host.js'; +import { fetchInstanceMetadata } from '@/services/fetch-instance-metadata.js'; export const meta = { tags: ['admin'], requireCredential: true, requireModerator: true, +} as const; - params: { - host: { - validator: $.str, - }, +export const paramDef = { + type: 'object', + properties: { + host: { type: 'string' }, }, + required: ['host'], } as const; // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, me) => { +export default define(meta, paramDef, async (ps, me) => { const instance = await Instances.findOne({ host: toPuny(ps.host) }); if (instance == null) { diff --git a/packages/backend/src/server/api/endpoints/admin/federation/remove-all-following.ts b/packages/backend/src/server/api/endpoints/admin/federation/remove-all-following.ts index 4de8ad133..ccd07489c 100644 --- a/packages/backend/src/server/api/endpoints/admin/federation/remove-all-following.ts +++ b/packages/backend/src/server/api/endpoints/admin/federation/remove-all-following.ts @@ -1,23 +1,24 @@ -import $ from 'cafy'; -import define from '../../../define'; -import deleteFollowing from '@/services/following/delete'; -import { Followings, Users } from '@/models/index'; +import define from '../../../define.js'; +import deleteFollowing from '@/services/following/delete.js'; +import { Followings, Users } from '@/models/index.js'; export const meta = { tags: ['admin'], requireCredential: true, requireModerator: true, +} as const; - params: { - host: { - validator: $.str, - }, +export const paramDef = { + type: 'object', + properties: { + host: { type: 'string' }, }, + required: ['host'], } as const; // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, me) => { +export default define(meta, paramDef, async (ps, me) => { const followings = await Followings.find({ followerHost: ps.host, }); diff --git a/packages/backend/src/server/api/endpoints/admin/federation/update-instance.ts b/packages/backend/src/server/api/endpoints/admin/federation/update-instance.ts index 6ac2f1f46..198108242 100644 --- a/packages/backend/src/server/api/endpoints/admin/federation/update-instance.ts +++ b/packages/backend/src/server/api/endpoints/admin/federation/update-instance.ts @@ -1,27 +1,25 @@ -import $ from 'cafy'; -import define from '../../../define'; -import { Instances } from '@/models/index'; -import { toPuny } from '@/misc/convert-host'; +import define from '../../../define.js'; +import { Instances } from '@/models/index.js'; +import { toPuny } from '@/misc/convert-host.js'; export const meta = { tags: ['admin'], requireCredential: true, requireModerator: true, +} as const; - params: { - host: { - validator: $.str, - }, - - isSuspended: { - validator: $.bool, - }, +export const paramDef = { + type: 'object', + properties: { + host: { type: 'string' }, + isSuspended: { type: 'boolean' }, }, + required: ['host', 'isSuspended'], } as const; // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, me) => { +export default define(meta, paramDef, async (ps, me) => { const instance = await Instances.findOne({ host: toPuny(ps.host) }); if (instance == null) { diff --git a/packages/backend/src/server/api/endpoints/admin/get-index-stats.ts b/packages/backend/src/server/api/endpoints/admin/get-index-stats.ts index 9a2bccec7..37878c414 100644 --- a/packages/backend/src/server/api/endpoints/admin/get-index-stats.ts +++ b/packages/backend/src/server/api/endpoints/admin/get-index-stats.ts @@ -1,4 +1,4 @@ -import define from '../../define'; +import define from '../../define.js'; import { getConnection } from 'typeorm'; export const meta = { @@ -6,13 +6,16 @@ export const meta = { requireModerator: true, tags: ['admin'], +} as const; - params: { - }, +export const paramDef = { + type: 'object', + properties: {}, + required: [], } as const; // eslint-disable-next-line import/no-default-export -export default define(meta, async () => { +export default define(meta, paramDef, async () => { const stats = await getConnection().query(`SELECT * FROM pg_indexes;`) .then(recs => { diff --git a/packages/backend/src/server/api/endpoints/admin/get-table-stats.ts b/packages/backend/src/server/api/endpoints/admin/get-table-stats.ts index 1c5f25067..7cf2d5ffd 100644 --- a/packages/backend/src/server/api/endpoints/admin/get-table-stats.ts +++ b/packages/backend/src/server/api/endpoints/admin/get-table-stats.ts @@ -1,4 +1,4 @@ -import define from '../../define'; +import define from '../../define.js'; import { getConnection } from 'typeorm'; export const meta = { @@ -7,9 +7,6 @@ export const meta = { tags: ['admin'], - params: { - }, - res: { type: 'object', optional: false, nullable: false, @@ -22,8 +19,14 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: {}, + required: [], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async () => { +export default define(meta, paramDef, async () => { const sizes = await getConnection().query(` SELECT relname AS "table", reltuples as "count", pg_total_relation_size(C.oid) AS "size" diff --git a/packages/backend/src/server/api/endpoints/admin/invite.ts b/packages/backend/src/server/api/endpoints/admin/invite.ts index 3428709c0..7e950cf87 100644 --- a/packages/backend/src/server/api/endpoints/admin/invite.ts +++ b/packages/backend/src/server/api/endpoints/admin/invite.ts @@ -1,7 +1,7 @@ import rndstr from 'rndstr'; -import define from '../../define'; -import { RegistrationTickets } from '@/models/index'; -import { genId } from '@/misc/gen-id'; +import define from '../../define.js'; +import { RegistrationTickets } from '@/models/index.js'; +import { genId } from '@/misc/gen-id.js'; export const meta = { tags: ['admin'], @@ -9,8 +9,6 @@ export const meta = { requireCredential: true, requireModerator: true, - params: {}, - res: { type: 'object', optional: false, nullable: false, @@ -26,8 +24,14 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: {}, + required: [], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async () => { +export default define(meta, paramDef, async () => { const code = rndstr({ length: 8, chars: '2-9A-HJ-NP-Z', // [0-9A-Z] w/o [01IO] (32 patterns) diff --git a/packages/backend/src/server/api/endpoints/admin/moderators/add.ts b/packages/backend/src/server/api/endpoints/admin/moderators/add.ts index 0308cf276..4206e3a3c 100644 --- a/packages/backend/src/server/api/endpoints/admin/moderators/add.ts +++ b/packages/backend/src/server/api/endpoints/admin/moderators/add.ts @@ -1,23 +1,23 @@ -import $ from 'cafy'; -import { ID } from '@/misc/cafy-id'; -import define from '../../../define'; -import { Users } from '@/models/index'; +import define from '../../../define.js'; +import { Users } from '@/models/index.js'; export const meta = { tags: ['admin'], requireCredential: true, requireAdmin: true, +} as const; - params: { - userId: { - validator: $.type(ID), - }, +export const paramDef = { + type: 'object', + properties: { + userId: { type: 'string', format: 'misskey:id' }, }, + required: ['userId'], } as const; // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps) => { +export default define(meta, paramDef, async (ps) => { const user = await Users.findOne(ps.userId as string); if (user == null) { diff --git a/packages/backend/src/server/api/endpoints/admin/moderators/remove.ts b/packages/backend/src/server/api/endpoints/admin/moderators/remove.ts index bdb976e9e..143119bfe 100644 --- a/packages/backend/src/server/api/endpoints/admin/moderators/remove.ts +++ b/packages/backend/src/server/api/endpoints/admin/moderators/remove.ts @@ -1,23 +1,23 @@ -import $ from 'cafy'; -import { ID } from '@/misc/cafy-id'; -import define from '../../../define'; -import { Users } from '@/models/index'; +import define from '../../../define.js'; +import { Users } from '@/models/index.js'; export const meta = { tags: ['admin'], requireCredential: true, requireAdmin: true, +} as const; - params: { - userId: { - validator: $.type(ID), - }, +export const paramDef = { + type: 'object', + properties: { + userId: { type: 'string', format: 'misskey:id' }, }, + required: ['userId'], } as const; // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps) => { +export default define(meta, paramDef, async (ps) => { const user = await Users.findOne(ps.userId as string); if (user == null) { diff --git a/packages/backend/src/server/api/endpoints/admin/promo/create.ts b/packages/backend/src/server/api/endpoints/admin/promo/create.ts index f2735ac9f..2eec5bf0d 100644 --- a/packages/backend/src/server/api/endpoints/admin/promo/create.ts +++ b/packages/backend/src/server/api/endpoints/admin/promo/create.ts @@ -1,9 +1,7 @@ -import $ from 'cafy'; -import { ID } from '@/misc/cafy-id'; -import define from '../../../define'; -import { ApiError } from '../../../error'; -import { getNote } from '../../../common/getters'; -import { PromoNotes } from '@/models/index'; +import define from '../../../define.js'; +import { ApiError } from '../../../error.js'; +import { getNote } from '../../../common/getters.js'; +import { PromoNotes } from '@/models/index.js'; export const meta = { tags: ['admin'], @@ -11,16 +9,6 @@ export const meta = { requireCredential: true, requireModerator: true, - params: { - noteId: { - validator: $.type(ID), - }, - - expiresAt: { - validator: $.num.int(), - }, - }, - errors: { noSuchNote: { message: 'No such note.', @@ -36,8 +24,17 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + noteId: { type: 'string', format: 'misskey:id' }, + expiresAt: { type: 'integer' }, + }, + required: ['noteId', 'expiresAt'], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, user) => { +export default define(meta, paramDef, async (ps, user) => { const note = await getNote(ps.noteId).catch(e => { if (e.id === '9725d0ce-ba28-4dde-95a7-2cbb2c15de24') throw new ApiError(meta.errors.noSuchNote); throw e; @@ -51,7 +48,6 @@ export default define(meta, async (ps, user) => { await PromoNotes.insert({ noteId: note.id, - createdAt: new Date(), expiresAt: new Date(ps.expiresAt), userId: note.userId, }); diff --git a/packages/backend/src/server/api/endpoints/admin/queue/clear.ts b/packages/backend/src/server/api/endpoints/admin/queue/clear.ts index 3c8e7a27a..8f015c280 100644 --- a/packages/backend/src/server/api/endpoints/admin/queue/clear.ts +++ b/packages/backend/src/server/api/endpoints/admin/queue/clear.ts @@ -1,18 +1,22 @@ -import define from '../../../define'; -import { destroy } from '@/queue/index'; -import { insertModerationLog } from '@/services/insert-moderation-log'; +import define from '../../../define.js'; +import { destroy } from '@/queue/index.js'; +import { insertModerationLog } from '@/services/insert-moderation-log.js'; export const meta = { tags: ['admin'], requireCredential: true, requireModerator: true, +} as const; - params: {}, +export const paramDef = { + type: 'object', + properties: {}, + required: [], } as const; // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, me) => { +export default define(meta, paramDef, async (ps, me) => { destroy(); insertModerationLog(me, 'clearQueue'); diff --git a/packages/backend/src/server/api/endpoints/admin/queue/deliver-delayed.ts b/packages/backend/src/server/api/endpoints/admin/queue/deliver-delayed.ts index 4760e2c31..70f7d77de 100644 --- a/packages/backend/src/server/api/endpoints/admin/queue/deliver-delayed.ts +++ b/packages/backend/src/server/api/endpoints/admin/queue/deliver-delayed.ts @@ -1,6 +1,6 @@ -import { deliverQueue } from '@/queue/queues'; -import { URL } from 'url'; -import define from '../../../define'; +import { deliverQueue } from '@/queue/queues.js'; +import { URL } from 'node:url'; +import define from '../../../define.js'; export const meta = { tags: ['admin'], @@ -8,9 +8,6 @@ export const meta = { requireCredential: true, requireModerator: true, - params: { - }, - res: { type: 'array', optional: false, nullable: false, @@ -35,8 +32,14 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: {}, + required: [], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps) => { +export default define(meta, paramDef, async (ps) => { const jobs = await deliverQueue.getJobs(['delayed']); const res = [] as [string, number][]; diff --git a/packages/backend/src/server/api/endpoints/admin/queue/inbox-delayed.ts b/packages/backend/src/server/api/endpoints/admin/queue/inbox-delayed.ts index a95aabc50..2235ce8f9 100644 --- a/packages/backend/src/server/api/endpoints/admin/queue/inbox-delayed.ts +++ b/packages/backend/src/server/api/endpoints/admin/queue/inbox-delayed.ts @@ -1,6 +1,6 @@ -import { URL } from 'url'; -import define from '../../../define'; -import { inboxQueue } from '@/queue/queues'; +import { URL } from 'node:url'; +import define from '../../../define.js'; +import { inboxQueue } from '@/queue/queues.js'; export const meta = { tags: ['admin'], @@ -8,9 +8,6 @@ export const meta = { requireCredential: true, requireModerator: true, - params: { - }, - res: { type: 'array', optional: false, nullable: false, @@ -35,8 +32,14 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: {}, + required: [], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps) => { +export default define(meta, paramDef, async (ps) => { const jobs = await inboxQueue.getJobs(['delayed']); const res = [] as [string, number][]; diff --git a/packages/backend/src/server/api/endpoints/admin/queue/jobs.ts b/packages/backend/src/server/api/endpoints/admin/queue/jobs.ts deleted file mode 100644 index df0b4a8f1..000000000 --- a/packages/backend/src/server/api/endpoints/admin/queue/jobs.ts +++ /dev/null @@ -1,82 +0,0 @@ -import { deliverQueue, inboxQueue, dbQueue, objectStorageQueue } from '@/queue/queues'; -import $ from 'cafy'; -import define from '../../../define'; - -export const meta = { - tags: ['admin'], - - requireCredential: true, - requireModerator: true, - - params: { - domain: { - validator: $.str.or(['deliver', 'inbox', 'db', 'objectStorage']), - }, - - state: { - validator: $.str.or(['active', 'waiting', 'delayed']), - }, - - limit: { - validator: $.optional.num, - default: 50, - }, - }, - - res: { - type: 'array', - optional: false, nullable: false, - items: { - type: 'object', - optional: false, nullable: false, - properties: { - id: { - type: 'string', - optional: false, nullable: false, - format: 'id', - }, - data: { - type: 'object', - optional: false, nullable: false, - }, - attempts: { - type: 'number', - optional: false, nullable: false, - }, - maxAttempts: { - type: 'number', - optional: false, nullable: false, - }, - timestamp: { - type: 'number', - optional: false, nullable: false, - }, - }, - }, - }, -} as const; - -// eslint-disable-next-line import/no-default-export -export default define(meta, async (ps) => { - const queue = - ps.domain === 'deliver' ? deliverQueue : - ps.domain === 'inbox' ? inboxQueue : - ps.domain === 'db' ? dbQueue : - ps.domain === 'objectStorage' ? objectStorageQueue : - null as never; - - const jobs = await queue.getJobs([ps.state], 0, ps.limit!); - - return jobs.map(job => { - const data = job.data; - delete data.content; - delete data.user; - return { - id: job.id, - data, - attempts: job.attemptsMade, - maxAttempts: job.opts ? job.opts.attempts : 0, - timestamp: job.timestamp, - }; - }); -}); diff --git a/packages/backend/src/server/api/endpoints/admin/queue/stats.ts b/packages/backend/src/server/api/endpoints/admin/queue/stats.ts index dab0be5db..988b5a5e3 100644 --- a/packages/backend/src/server/api/endpoints/admin/queue/stats.ts +++ b/packages/backend/src/server/api/endpoints/admin/queue/stats.ts @@ -1,5 +1,5 @@ -import { deliverQueue, inboxQueue, dbQueue, objectStorageQueue } from '@/queue/queues'; -import define from '../../../define'; +import { deliverQueue, inboxQueue, dbQueue, objectStorageQueue } from '@/queue/queues.js'; +import define from '../../../define.js'; export const meta = { tags: ['admin'], @@ -7,8 +7,6 @@ export const meta = { requireCredential: true, requireModerator: true, - params: {}, - res: { type: 'object', optional: false, nullable: false, @@ -33,8 +31,14 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: {}, + required: [], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps) => { +export default define(meta, paramDef, async (ps) => { const deliverJobCounts = await deliverQueue.getJobCounts(); const inboxJobCounts = await inboxQueue.getJobCounts(); const dbJobCounts = await dbQueue.getJobCounts(); diff --git a/packages/backend/src/server/api/endpoints/admin/relays/add.ts b/packages/backend/src/server/api/endpoints/admin/relays/add.ts index 65890a00f..348e9baca 100644 --- a/packages/backend/src/server/api/endpoints/admin/relays/add.ts +++ b/packages/backend/src/server/api/endpoints/admin/relays/add.ts @@ -1,8 +1,7 @@ -import { URL } from 'url'; -import $ from 'cafy'; -import define from '../../../define'; -import { addRelay } from '@/services/relay'; -import { ApiError } from '../../../error'; +import { URL } from 'node:url'; +import define from '../../../define.js'; +import { addRelay } from '@/services/relay.js'; +import { ApiError } from '../../../error.js'; export const meta = { tags: ['admin'], @@ -10,12 +9,6 @@ export const meta = { requireCredential: true, requireModerator: true, - params: { - inbox: { - validator: $.str, - }, - }, - errors: { invalidUrl: { message: 'Invalid URL', @@ -52,8 +45,16 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + inbox: { type: 'string' }, + }, + required: ['inbox'], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, user) => { +export default define(meta, paramDef, async (ps, user) => { try { if (new URL(ps.inbox).protocol !== 'https:') throw 'https only'; } catch { diff --git a/packages/backend/src/server/api/endpoints/admin/relays/list.ts b/packages/backend/src/server/api/endpoints/admin/relays/list.ts index bdddf1337..89ec651e6 100644 --- a/packages/backend/src/server/api/endpoints/admin/relays/list.ts +++ b/packages/backend/src/server/api/endpoints/admin/relays/list.ts @@ -1,5 +1,5 @@ -import define from '../../../define'; -import { listRelay } from '@/services/relay'; +import define from '../../../define.js'; +import { listRelay } from '@/services/relay.js'; export const meta = { tags: ['admin'], @@ -7,9 +7,6 @@ export const meta = { requireCredential: true, requireModerator: true, - params: { - }, - res: { type: 'array', optional: false, nullable: false, @@ -42,7 +39,13 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: {}, + required: [], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, user) => { +export default define(meta, paramDef, async (ps, user) => { return await listRelay(); }); diff --git a/packages/backend/src/server/api/endpoints/admin/relays/remove.ts b/packages/backend/src/server/api/endpoints/admin/relays/remove.ts index 4b04e620c..b59cf72c5 100644 --- a/packages/backend/src/server/api/endpoints/admin/relays/remove.ts +++ b/packages/backend/src/server/api/endpoints/admin/relays/remove.ts @@ -1,21 +1,22 @@ -import $ from 'cafy'; -import define from '../../../define'; -import { removeRelay } from '@/services/relay'; +import define from '../../../define.js'; +import { removeRelay } from '@/services/relay.js'; export const meta = { tags: ['admin'], requireCredential: true, requireModerator: true, +} as const; - params: { - inbox: { - validator: $.str, - }, +export const paramDef = { + type: 'object', + properties: { + inbox: { type: 'string' }, }, + required: ['inbox'], } as const; // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, user) => { +export default define(meta, paramDef, async (ps, user) => { return await removeRelay(ps.inbox); }); diff --git a/packages/backend/src/server/api/endpoints/admin/reset-password.ts b/packages/backend/src/server/api/endpoints/admin/reset-password.ts index b6cf1ee2d..1fd5c8d5a 100644 --- a/packages/backend/src/server/api/endpoints/admin/reset-password.ts +++ b/packages/backend/src/server/api/endpoints/admin/reset-password.ts @@ -1,9 +1,7 @@ -import $ from 'cafy'; -import { ID } from '@/misc/cafy-id'; -import define from '../../define'; -import * as bcrypt from 'bcryptjs'; +import define from '../../define.js'; +import bcrypt from 'bcryptjs'; import rndstr from 'rndstr'; -import { Users, UserProfiles } from '@/models/index'; +import { Users, UserProfiles } from '@/models/index.js'; export const meta = { tags: ['admin'], @@ -11,12 +9,6 @@ export const meta = { requireCredential: true, requireModerator: true, - params: { - userId: { - validator: $.type(ID), - }, - }, - res: { type: 'object', optional: false, nullable: false, @@ -31,8 +23,16 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + userId: { type: 'string', format: 'misskey:id' }, + }, + required: ['userId'], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps) => { +export default define(meta, paramDef, async (ps) => { const user = await Users.findOne(ps.userId as string); if (user == null) { diff --git a/packages/backend/src/server/api/endpoints/admin/resolve-abuse-user-report.ts b/packages/backend/src/server/api/endpoints/admin/resolve-abuse-user-report.ts index a47b69ec1..a9e565841 100644 --- a/packages/backend/src/server/api/endpoints/admin/resolve-abuse-user-report.ts +++ b/packages/backend/src/server/api/endpoints/admin/resolve-abuse-user-report.ts @@ -1,33 +1,28 @@ -import $ from 'cafy'; -import { ID } from '@/misc/cafy-id'; -import define from '../../define'; -import { AbuseUserReports, Users } from '@/models/index'; -import { getInstanceActor } from '@/services/instance-actor'; -import { deliver } from '@/queue/index'; -import { renderActivity } from '@/remote/activitypub/renderer/index'; -import { renderFlag } from '@/remote/activitypub/renderer/flag'; +import define from '../../define.js'; +import { AbuseUserReports, Users } from '@/models/index.js'; +import { getInstanceActor } from '@/services/instance-actor.js'; +import { deliver } from '@/queue/index.js'; +import { renderActivity } from '@/remote/activitypub/renderer/index.js'; +import { renderFlag } from '@/remote/activitypub/renderer/flag.js'; export const meta = { tags: ['admin'], requireCredential: true, requireModerator: true, +} as const; - params: { - reportId: { - validator: $.type(ID), - }, - - forward: { - validator: $.optional.boolean, - required: false, - default: false, - }, +export const paramDef = { + type: 'object', + properties: { + reportId: { type: 'string', format: 'misskey:id' }, + forward: { type: 'boolean', default: false }, }, + required: ['reportId'], } as const; // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, me) => { +export default define(meta, paramDef, async (ps, me) => { const report = await AbuseUserReports.findOne(ps.reportId); if (report == null) { diff --git a/packages/backend/src/server/api/endpoints/admin/send-email.ts b/packages/backend/src/server/api/endpoints/admin/send-email.ts index c2972c35f..bbdd66e4c 100644 --- a/packages/backend/src/server/api/endpoints/admin/send-email.ts +++ b/packages/backend/src/server/api/endpoints/admin/send-email.ts @@ -1,27 +1,24 @@ -import $ from 'cafy'; -import define from '../../define'; -import { sendEmail } from '@/services/send-email'; +import define from '../../define.js'; +import { sendEmail } from '@/services/send-email.js'; export const meta = { tags: ['admin'], requireCredential: true, requireModerator: true, +} as const; - params: { - to: { - validator: $.str, - }, - subject: { - validator: $.str, - }, - text: { - validator: $.str, - }, +export const paramDef = { + type: 'object', + properties: { + to: { type: 'string' }, + subject: { type: 'string' }, + text: { type: 'string' }, }, + required: ['to', 'subject', 'text'], } as const; // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps) => { +export default define(meta, paramDef, async (ps) => { await sendEmail(ps.to, ps.subject, ps.text, ps.text); }); diff --git a/packages/backend/src/server/api/endpoints/admin/server-info.ts b/packages/backend/src/server/api/endpoints/admin/server-info.ts index cd282e364..8bf1c4341 100644 --- a/packages/backend/src/server/api/endpoints/admin/server-info.ts +++ b/packages/backend/src/server/api/endpoints/admin/server-info.ts @@ -1,8 +1,8 @@ -import * as os from 'os'; -import * as si from 'systeminformation'; +import * as os from 'node:os'; +import si from 'systeminformation'; import { getConnection } from 'typeorm'; -import define from '../../define'; -import { redisClient } from '../../../../db/redis'; +import define from '../../define.js'; +import { redisClient } from '../../../../db/redis.js'; export const meta = { requireCredential: true, @@ -10,9 +10,6 @@ export const meta = { tags: ['admin', 'meta'], - params: { - }, - res: { type: 'object', optional: false, nullable: false, @@ -90,8 +87,14 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: {}, + required: [], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async () => { +export default define(meta, paramDef, async () => { const memStats = await si.mem(); const fsStats = await si.fsSize(); const netInterface = await si.networkInterfaceDefault(); diff --git a/packages/backend/src/server/api/endpoints/admin/show-moderation-logs.ts b/packages/backend/src/server/api/endpoints/admin/show-moderation-logs.ts index 84e2b84bb..3545536aa 100644 --- a/packages/backend/src/server/api/endpoints/admin/show-moderation-logs.ts +++ b/packages/backend/src/server/api/endpoints/admin/show-moderation-logs.ts @@ -1,8 +1,6 @@ -import $ from 'cafy'; -import { ID } from '@/misc/cafy-id'; -import define from '../../define'; -import { ModerationLogs } from '@/models/index'; -import { makePaginationQuery } from '../../common/make-pagination-query'; +import define from '../../define.js'; +import { ModerationLogs } from '@/models/index.js'; +import { makePaginationQuery } from '../../common/make-pagination-query.js'; export const meta = { tags: ['admin'], @@ -10,21 +8,6 @@ export const meta = { requireCredential: true, requireModerator: true, - params: { - limit: { - validator: $.optional.num.range(1, 100), - default: 10, - }, - - sinceId: { - validator: $.optional.type(ID), - }, - - untilId: { - validator: $.optional.type(ID), - }, - }, - res: { type: 'array', optional: false, nullable: false, @@ -65,11 +48,21 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + limit: { type: 'integer', minimum: 1, maximum: 100, default: 10 }, + sinceId: { type: 'string', format: 'misskey:id' }, + untilId: { type: 'string', format: 'misskey:id' }, + }, + required: [], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps) => { +export default define(meta, paramDef, async (ps) => { const query = makePaginationQuery(ModerationLogs.createQueryBuilder('report'), ps.sinceId, ps.untilId); - const reports = await query.take(ps.limit!).getMany(); + const reports = await query.take(ps.limit).getMany(); return await ModerationLogs.packMany(reports); }); diff --git a/packages/backend/src/server/api/endpoints/admin/show-user.ts b/packages/backend/src/server/api/endpoints/admin/show-user.ts index 0d0cc9087..a435dcc28 100644 --- a/packages/backend/src/server/api/endpoints/admin/show-user.ts +++ b/packages/backend/src/server/api/endpoints/admin/show-user.ts @@ -1,7 +1,5 @@ -import $ from 'cafy'; -import { ID } from '@/misc/cafy-id'; -import define from '../../define'; -import { Users } from '@/models/index'; +import define from '../../define.js'; +import { Users } from '@/models/index.js'; export const meta = { tags: ['admin'], @@ -9,20 +7,22 @@ export const meta = { requireCredential: true, requireModerator: true, - params: { - userId: { - validator: $.type(ID), - }, - }, - res: { type: 'object', nullable: false, optional: false, }, } as const; +export const paramDef = { + type: 'object', + properties: { + userId: { type: 'string', format: 'misskey:id' }, + }, + required: ['userId'], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, me) => { +export default define(meta, paramDef, async (ps, me) => { const user = await Users.findOne(ps.userId as string); if (user == null) { diff --git a/packages/backend/src/server/api/endpoints/admin/show-users.ts b/packages/backend/src/server/api/endpoints/admin/show-users.ts index d3dde99b7..1ec86fef2 100644 --- a/packages/backend/src/server/api/endpoints/admin/show-users.ts +++ b/packages/backend/src/server/api/endpoints/admin/show-users.ts @@ -1,6 +1,5 @@ -import $ from 'cafy'; -import define from '../../define'; -import { Users } from '@/models/index'; +import define from '../../define.js'; +import { Users } from '@/models/index.js'; export const meta = { tags: ['admin'], @@ -8,61 +7,6 @@ export const meta = { requireCredential: true, requireModerator: true, - params: { - limit: { - validator: $.optional.num.range(1, 100), - default: 10, - }, - - offset: { - validator: $.optional.num.min(0), - default: 0, - }, - - sort: { - validator: $.optional.str.or([ - '+follower', - '-follower', - '+createdAt', - '-createdAt', - '+updatedAt', - '-updatedAt', - ]), - }, - - state: { - validator: $.optional.str.or([ - 'all', - 'available', - 'admin', - 'moderator', - 'adminOrModerator', - 'silenced', - 'suspended', - ]), - default: 'all', - }, - - origin: { - validator: $.optional.str.or([ - 'combined', - 'local', - 'remote', - ]), - default: 'local', - }, - - username: { - validator: $.optional.str, - default: null, - }, - - hostname: { - validator: $.optional.str, - default: null, - }, - }, - res: { type: 'array', nullable: false, optional: false, @@ -74,8 +18,22 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + limit: { type: 'integer', minimum: 1, maximum: 100, default: 10 }, + offset: { type: 'integer', default: 0 }, + sort: { type: 'string', enum: ['+follower', '-follower', '+createdAt', '-createdAt', '+updatedAt', '-updatedAt'] }, + state: { type: 'string', enum: ['all', 'available', 'admin', 'moderator', 'adminOrModerator', 'silenced', 'suspended'], default: "all" }, + origin: { type: 'string', enum: ['combined', 'local', 'remote'], default: "local" }, + username: { type: 'string', default: null }, + hostname: { type: 'string', default: null }, + }, + required: [], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, me) => { +export default define(meta, paramDef, async (ps, me) => { const query = Users.createQueryBuilder('user'); switch (ps.state) { @@ -111,7 +69,7 @@ export default define(meta, async (ps, me) => { default: query.orderBy('user.id', 'ASC'); break; } - query.take(ps.limit!); + query.take(ps.limit); query.skip(ps.offset); const users = await query.getMany(); diff --git a/packages/backend/src/server/api/endpoints/admin/silence-user.ts b/packages/backend/src/server/api/endpoints/admin/silence-user.ts index 872bd2a6a..4a74c3fb0 100644 --- a/packages/backend/src/server/api/endpoints/admin/silence-user.ts +++ b/packages/backend/src/server/api/endpoints/admin/silence-user.ts @@ -1,24 +1,24 @@ -import $ from 'cafy'; -import { ID } from '@/misc/cafy-id'; -import define from '../../define'; -import { Users } from '@/models/index'; -import { insertModerationLog } from '@/services/insert-moderation-log'; +import define from '../../define.js'; +import { Users } from '@/models/index.js'; +import { insertModerationLog } from '@/services/insert-moderation-log.js'; export const meta = { tags: ['admin'], requireCredential: true, requireModerator: true, +} as const; - params: { - userId: { - validator: $.type(ID), - }, +export const paramDef = { + type: 'object', + properties: { + userId: { type: 'string', format: 'misskey:id' }, }, + required: ['userId'], } as const; // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, me) => { +export default define(meta, paramDef, async (ps, me) => { const user = await Users.findOne(ps.userId as string); if (user == null) { diff --git a/packages/backend/src/server/api/endpoints/admin/suspend-user.ts b/packages/backend/src/server/api/endpoints/admin/suspend-user.ts index 2bb1875fc..adaa7b86c 100644 --- a/packages/backend/src/server/api/endpoints/admin/suspend-user.ts +++ b/packages/backend/src/server/api/endpoints/admin/suspend-user.ts @@ -1,28 +1,28 @@ -import $ from 'cafy'; -import { ID } from '@/misc/cafy-id'; -import define from '../../define'; -import deleteFollowing from '@/services/following/delete'; -import { Users, Followings, Notifications } from '@/models/index'; -import { User } from '@/models/entities/user'; -import { insertModerationLog } from '@/services/insert-moderation-log'; -import { doPostSuspend } from '@/services/suspend-user'; -import { publishUserEvent } from '@/services/stream'; +import define from '../../define.js'; +import deleteFollowing from '@/services/following/delete.js'; +import { Users, Followings, Notifications } from '@/models/index.js'; +import { User } from '@/models/entities/user.js'; +import { insertModerationLog } from '@/services/insert-moderation-log.js'; +import { doPostSuspend } from '@/services/suspend-user.js'; +import { publishUserEvent } from '@/services/stream.js'; export const meta = { tags: ['admin'], requireCredential: true, requireModerator: true, +} as const; - params: { - userId: { - validator: $.type(ID), - }, +export const paramDef = { + type: 'object', + properties: { + userId: { type: 'string', format: 'misskey:id' }, }, + required: ['userId'], } as const; // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, me) => { +export default define(meta, paramDef, async (ps, me) => { const user = await Users.findOne(ps.userId as string); if (user == null) { diff --git a/packages/backend/src/server/api/endpoints/admin/unsilence-user.ts b/packages/backend/src/server/api/endpoints/admin/unsilence-user.ts index a4c6ff2ad..4e6366aa1 100644 --- a/packages/backend/src/server/api/endpoints/admin/unsilence-user.ts +++ b/packages/backend/src/server/api/endpoints/admin/unsilence-user.ts @@ -1,24 +1,24 @@ -import $ from 'cafy'; -import { ID } from '@/misc/cafy-id'; -import define from '../../define'; -import { Users } from '@/models/index'; -import { insertModerationLog } from '@/services/insert-moderation-log'; +import define from '../../define.js'; +import { Users } from '@/models/index.js'; +import { insertModerationLog } from '@/services/insert-moderation-log.js'; export const meta = { tags: ['admin'], requireCredential: true, requireModerator: true, +} as const; - params: { - userId: { - validator: $.type(ID), - }, +export const paramDef = { + type: 'object', + properties: { + userId: { type: 'string', format: 'misskey:id' }, }, + required: ['userId'], } as const; // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, me) => { +export default define(meta, paramDef, async (ps, me) => { const user = await Users.findOne(ps.userId as string); if (user == null) { diff --git a/packages/backend/src/server/api/endpoints/admin/unsuspend-user.ts b/packages/backend/src/server/api/endpoints/admin/unsuspend-user.ts index 5ab56d51c..3b9e0a94e 100644 --- a/packages/backend/src/server/api/endpoints/admin/unsuspend-user.ts +++ b/packages/backend/src/server/api/endpoints/admin/unsuspend-user.ts @@ -1,25 +1,25 @@ -import $ from 'cafy'; -import { ID } from '@/misc/cafy-id'; -import define from '../../define'; -import { Users } from '@/models/index'; -import { insertModerationLog } from '@/services/insert-moderation-log'; -import { doPostUnsuspend } from '@/services/unsuspend-user'; +import define from '../../define.js'; +import { Users } from '@/models/index.js'; +import { insertModerationLog } from '@/services/insert-moderation-log.js'; +import { doPostUnsuspend } from '@/services/unsuspend-user.js'; export const meta = { tags: ['admin'], requireCredential: true, requireModerator: true, +} as const; - params: { - userId: { - validator: $.type(ID), - }, +export const paramDef = { + type: 'object', + properties: { + userId: { type: 'string', format: 'misskey:id' }, }, + required: ['userId'], } as const; // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, me) => { +export default define(meta, paramDef, async (ps, me) => { const user = await Users.findOne(ps.userId as string); if (user == null) { diff --git a/packages/backend/src/server/api/endpoints/admin/update-meta.ts b/packages/backend/src/server/api/endpoints/admin/update-meta.ts index 1764d230a..66b634c87 100644 --- a/packages/backend/src/server/api/endpoints/admin/update-meta.ts +++ b/packages/backend/src/server/api/endpoints/admin/update-meta.ts @@ -1,310 +1,107 @@ -import $ from 'cafy'; -import define from '../../define'; +import define from '../../define.js'; import { getConnection } from 'typeorm'; -import { Meta } from '@/models/entities/meta'; -import { insertModerationLog } from '@/services/insert-moderation-log'; -import { DB_MAX_NOTE_TEXT_LENGTH } from '@/misc/hard-limits'; -import { ID } from '@/misc/cafy-id'; +import { Meta } from '@/models/entities/meta.js'; +import { insertModerationLog } from '@/services/insert-moderation-log.js'; +import { DB_MAX_NOTE_TEXT_LENGTH } from '@/misc/hard-limits.js'; export const meta = { tags: ['admin'], requireCredential: true, requireAdmin: true, - - params: { - disableRegistration: { - validator: $.optional.nullable.bool, - }, - - disableLocalTimeline: { - validator: $.optional.nullable.bool, - }, - - disableGlobalTimeline: { - validator: $.optional.nullable.bool, - }, - - useStarForReactionFallback: { - validator: $.optional.nullable.bool, - }, - - pinnedUsers: { - validator: $.optional.nullable.arr($.str), - }, - - hiddenTags: { - validator: $.optional.nullable.arr($.str), - }, - - blockedHosts: { - validator: $.optional.nullable.arr($.str), - }, - - themeColor: { - validator: $.optional.nullable.str, - }, - - mascotImageUrl: { - validator: $.optional.nullable.str, - }, - - bannerUrl: { - validator: $.optional.nullable.str, - }, - - errorImageUrl: { - validator: $.optional.nullable.str, - }, - - iconUrl: { - validator: $.optional.nullable.str, - }, - - backgroundImageUrl: { - validator: $.optional.nullable.str, - }, - - logoImageUrl: { - validator: $.optional.nullable.str, - }, - - name: { - validator: $.optional.nullable.str, - }, - - description: { - validator: $.optional.nullable.str, - }, - - maxNoteTextLength: { - validator: $.optional.num.min(0).max(DB_MAX_NOTE_TEXT_LENGTH), - }, - - localDriveCapacityMb: { - validator: $.optional.num.min(0), - }, - - remoteDriveCapacityMb: { - validator: $.optional.num.min(0), - }, - - cacheRemoteFiles: { - validator: $.optional.bool, - }, - - proxyRemoteFiles: { - validator: $.optional.bool, - }, - - emailRequiredForSignup: { - validator: $.optional.bool, - }, - - enableHcaptcha: { - validator: $.optional.bool, - }, - - hcaptchaSiteKey: { - validator: $.optional.nullable.str, - }, - - hcaptchaSecretKey: { - validator: $.optional.nullable.str, - }, - - enableRecaptcha: { - validator: $.optional.bool, - }, - - recaptchaSiteKey: { - validator: $.optional.nullable.str, - }, - - recaptchaSecretKey: { - validator: $.optional.nullable.str, - }, - - proxyAccountId: { - validator: $.optional.nullable.type(ID), - }, - - maintainerName: { - validator: $.optional.nullable.str, - }, - - maintainerEmail: { - validator: $.optional.nullable.str, - }, - - pinnedPages: { - validator: $.optional.arr($.str), - }, - - pinnedClipId: { - validator: $.optional.nullable.type(ID), - }, - - langs: { - validator: $.optional.arr($.str), - }, - - summalyProxy: { - validator: $.optional.nullable.str, - }, - - deeplAuthKey: { - validator: $.optional.nullable.str, - }, - - deeplIsPro: { - validator: $.optional.bool, - }, - - enableTwitterIntegration: { - validator: $.optional.bool, - }, - - twitterConsumerKey: { - validator: $.optional.nullable.str, - }, - - twitterConsumerSecret: { - validator: $.optional.nullable.str, - }, - - enableGithubIntegration: { - validator: $.optional.bool, - }, - - githubClientId: { - validator: $.optional.nullable.str, - }, - - githubClientSecret: { - validator: $.optional.nullable.str, - }, - - enableDiscordIntegration: { - validator: $.optional.bool, - }, - - discordClientId: { - validator: $.optional.nullable.str, - }, - - discordClientSecret: { - validator: $.optional.nullable.str, - }, - - enableEmail: { - validator: $.optional.bool, - }, - - email: { - validator: $.optional.nullable.str, - }, - - smtpSecure: { - validator: $.optional.bool, - }, - - smtpHost: { - validator: $.optional.nullable.str, - }, - - smtpPort: { - validator: $.optional.nullable.num, - }, - - smtpUser: { - validator: $.optional.nullable.str, - }, - - smtpPass: { - validator: $.optional.nullable.str, - }, - - enableServiceWorker: { - validator: $.optional.bool, - }, - - swPublicKey: { - validator: $.optional.nullable.str, - }, - - swPrivateKey: { - validator: $.optional.nullable.str, - }, - - tosUrl: { - validator: $.optional.nullable.str, - }, - - repositoryUrl: { - validator: $.optional.str, - }, - - feedbackUrl: { - validator: $.optional.str, - }, - - useObjectStorage: { - validator: $.optional.bool, - }, - - objectStorageBaseUrl: { - validator: $.optional.nullable.str, - }, - - objectStorageBucket: { - validator: $.optional.nullable.str, - }, - - objectStoragePrefix: { - validator: $.optional.nullable.str, - }, - - objectStorageEndpoint: { - validator: $.optional.nullable.str, - }, - - objectStorageRegion: { - validator: $.optional.nullable.str, - }, - - objectStoragePort: { - validator: $.optional.nullable.num, - }, - - objectStorageAccessKey: { - validator: $.optional.nullable.str, - }, - - objectStorageSecretKey: { - validator: $.optional.nullable.str, - }, - - objectStorageUseSSL: { - validator: $.optional.bool, - }, - - objectStorageUseProxy: { - validator: $.optional.bool, - }, - - objectStorageSetPublicRead: { - validator: $.optional.bool, - }, - - objectStorageS3ForcePathStyle: { - validator: $.optional.bool, - }, +} as const; + +export const paramDef = { + type: 'object', + properties: { + disableRegistration: { type: 'boolean', nullable: true }, + disableLocalTimeline: { type: 'boolean', nullable: true }, + disableGlobalTimeline: { type: 'boolean', nullable: true }, + useStarForReactionFallback: { type: 'boolean', nullable: true }, + pinnedUsers: { type: 'array', nullable: true, items: { + type: 'string', + } }, + hiddenTags: { type: 'array', nullable: true, items: { + type: 'string', + } }, + blockedHosts: { type: 'array', nullable: true, items: { + type: 'string', + } }, + themeColor: { type: 'string', nullable: true }, + mascotImageUrl: { type: 'string', nullable: true }, + bannerUrl: { type: 'string', nullable: true }, + errorImageUrl: { type: 'string', nullable: true }, + iconUrl: { type: 'string', nullable: true }, + backgroundImageUrl: { type: 'string', nullable: true }, + logoImageUrl: { type: 'string', nullable: true }, + name: { type: 'string', nullable: true }, + description: { type: 'string', nullable: true }, + defaultLightTheme: { type: 'string', nullable: true }, + defaultDarkTheme: { type: 'string', nullable: true }, + localDriveCapacityMb: { type: 'integer' }, + remoteDriveCapacityMb: { type: 'integer' }, + cacheRemoteFiles: { type: 'boolean' }, + emailRequiredForSignup: { type: 'boolean' }, + enableHcaptcha: { type: 'boolean' }, + hcaptchaSiteKey: { type: 'string', nullable: true }, + hcaptchaSecretKey: { type: 'string', nullable: true }, + enableRecaptcha: { type: 'boolean' }, + recaptchaSiteKey: { type: 'string', nullable: true }, + recaptchaSecretKey: { type: 'string', nullable: true }, + proxyAccountId: { type: 'string', format: 'misskey:id', nullable: true }, + maintainerName: { type: 'string', nullable: true }, + maintainerEmail: { type: 'string', nullable: true }, + pinnedPages: { type: 'array', items: { + type: 'string', + } }, + pinnedClipId: { type: 'string', format: 'misskey:id', nullable: true }, + langs: { type: 'array', items: { + type: 'string', + } }, + summalyProxy: { type: 'string', nullable: true }, + deeplAuthKey: { type: 'string', nullable: true }, + deeplIsPro: { type: 'boolean' }, + enableTwitterIntegration: { type: 'boolean' }, + twitterConsumerKey: { type: 'string', nullable: true }, + twitterConsumerSecret: { type: 'string', nullable: true }, + enableGithubIntegration: { type: 'boolean' }, + githubClientId: { type: 'string', nullable: true }, + githubClientSecret: { type: 'string', nullable: true }, + enableDiscordIntegration: { type: 'boolean' }, + discordClientId: { type: 'string', nullable: true }, + discordClientSecret: { type: 'string', nullable: true }, + enableEmail: { type: 'boolean' }, + email: { type: 'string', nullable: true }, + smtpSecure: { type: 'boolean' }, + smtpHost: { type: 'string', nullable: true }, + smtpPort: { type: 'integer', nullable: true }, + smtpUser: { type: 'string', nullable: true }, + smtpPass: { type: 'string', nullable: true }, + enableServiceWorker: { type: 'boolean' }, + swPublicKey: { type: 'string', nullable: true }, + swPrivateKey: { type: 'string', nullable: true }, + tosUrl: { type: 'string', nullable: true }, + repositoryUrl: { type: 'string' }, + feedbackUrl: { type: 'string' }, + useObjectStorage: { type: 'boolean' }, + objectStorageBaseUrl: { type: 'string', nullable: true }, + objectStorageBucket: { type: 'string', nullable: true }, + objectStoragePrefix: { type: 'string', nullable: true }, + objectStorageEndpoint: { type: 'string', nullable: true }, + objectStorageRegion: { type: 'string', nullable: true }, + objectStoragePort: { type: 'integer', nullable: true }, + objectStorageAccessKey: { type: 'string', nullable: true }, + objectStorageSecretKey: { type: 'string', nullable: true }, + objectStorageUseSSL: { type: 'boolean' }, + objectStorageUseProxy: { type: 'boolean' }, + objectStorageSetPublicRead: { type: 'boolean' }, + objectStorageS3ForcePathStyle: { type: 'boolean' }, }, + required: [], } as const; // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, me) => { +export default define(meta, paramDef, async (ps, me) => { const set = {} as Partial; if (typeof ps.disableRegistration === 'boolean') { @@ -367,8 +164,12 @@ export default define(meta, async (ps, me) => { set.description = ps.description; } - if (ps.maxNoteTextLength) { - set.maxNoteTextLength = ps.maxNoteTextLength; + if (ps.defaultLightTheme !== undefined) { + set.defaultLightTheme = ps.defaultLightTheme; + } + + if (ps.defaultDarkTheme !== undefined) { + set.defaultDarkTheme = ps.defaultDarkTheme; } if (ps.localDriveCapacityMb !== undefined) { @@ -383,10 +184,6 @@ export default define(meta, async (ps, me) => { set.cacheRemoteFiles = ps.cacheRemoteFiles; } - if (ps.proxyRemoteFiles !== undefined) { - set.proxyRemoteFiles = ps.proxyRemoteFiles; - } - if (ps.emailRequiredForSignup !== undefined) { set.emailRequiredForSignup = ps.emailRequiredForSignup; } diff --git a/packages/backend/src/server/api/endpoints/admin/vacuum.ts b/packages/backend/src/server/api/endpoints/admin/vacuum.ts index 4229ef0d2..4c04e019d 100644 --- a/packages/backend/src/server/api/endpoints/admin/vacuum.ts +++ b/packages/backend/src/server/api/endpoints/admin/vacuum.ts @@ -1,26 +1,25 @@ -import $ from 'cafy'; -import define from '../../define'; +import define from '../../define.js'; import { getConnection } from 'typeorm'; -import { insertModerationLog } from '@/services/insert-moderation-log'; +import { insertModerationLog } from '@/services/insert-moderation-log.js'; export const meta = { tags: ['admin'], requireCredential: true, requireModerator: true, +} as const; - params: { - full: { - validator: $.bool, - }, - analyze: { - validator: $.bool, - }, +export const paramDef = { + type: 'object', + properties: { + full: { type: 'boolean' }, + analyze: { type: 'boolean' }, }, + required: ['full', 'analyze'], } as const; // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, me) => { +export default define(meta, paramDef, async (ps, me) => { const params: string[] = []; if (ps.full) { diff --git a/packages/backend/src/server/api/endpoints/announcements.ts b/packages/backend/src/server/api/endpoints/announcements.ts index 22c13743a..bba66e98c 100644 --- a/packages/backend/src/server/api/endpoints/announcements.ts +++ b/packages/backend/src/server/api/endpoints/announcements.ts @@ -1,34 +1,12 @@ -import $ from 'cafy'; -import { ID } from '@/misc/cafy-id'; -import define from '../define'; -import { Announcements, AnnouncementReads } from '@/models/index'; -import { makePaginationQuery } from '../common/make-pagination-query'; +import define from '../define.js'; +import { Announcements, AnnouncementReads } from '@/models/index.js'; +import { makePaginationQuery } from '../common/make-pagination-query.js'; export const meta = { tags: ['meta'], requireCredential: false, - params: { - limit: { - validator: $.optional.num.range(1, 100), - default: 10, - }, - - withUnreads: { - validator: $.optional.boolean, - default: false, - }, - - sinceId: { - validator: $.optional.type(ID), - }, - - untilId: { - validator: $.optional.type(ID), - }, - }, - res: { type: 'array', optional: false, nullable: false, @@ -73,11 +51,22 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + limit: { type: 'integer', minimum: 1, maximum: 100, default: 10 }, + withUnreads: { type: 'boolean', default: false }, + sinceId: { type: 'string', format: 'misskey:id' }, + untilId: { type: 'string', format: 'misskey:id' }, + }, + required: [], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, user) => { +export default define(meta, paramDef, async (ps, user) => { const query = makePaginationQuery(Announcements.createQueryBuilder('announcement'), ps.sinceId, ps.untilId); - const announcements = await query.take(ps.limit!).getMany(); + const announcements = await query.take(ps.limit).getMany(); if (user) { const reads = (await AnnouncementReads.find({ diff --git a/packages/backend/src/server/api/endpoints/antennas/create.ts b/packages/backend/src/server/api/endpoints/antennas/create.ts index 2092d177b..92cbba817 100644 --- a/packages/backend/src/server/api/endpoints/antennas/create.ts +++ b/packages/backend/src/server/api/endpoints/antennas/create.ts @@ -1,10 +1,8 @@ -import $ from 'cafy'; -import define from '../../define'; -import { genId } from '@/misc/gen-id'; -import { Antennas, UserLists, UserGroupJoinings } from '@/models/index'; -import { ID } from '@/misc/cafy-id'; -import { ApiError } from '../../error'; -import { publishInternalEvent } from '@/services/stream'; +import define from '../../define.js'; +import { genId } from '@/misc/gen-id.js'; +import { Antennas, UserLists, UserGroupJoinings } from '@/models/index.js'; +import { ApiError } from '../../error.js'; +import { publishInternalEvent } from '@/services/stream.js'; export const meta = { tags: ['antennas'], @@ -13,52 +11,6 @@ export const meta = { kind: 'write:account', - params: { - name: { - validator: $.str.range(1, 100), - }, - - src: { - validator: $.str.or(['home', 'all', 'users', 'list', 'group']), - }, - - userListId: { - validator: $.nullable.optional.type(ID), - }, - - userGroupId: { - validator: $.nullable.optional.type(ID), - }, - - keywords: { - validator: $.arr($.arr($.str)), - }, - - excludeKeywords: { - validator: $.arr($.arr($.str)), - }, - - users: { - validator: $.arr($.str), - }, - - caseSensitive: { - validator: $.bool, - }, - - withReplies: { - validator: $.bool, - }, - - withFile: { - validator: $.bool, - }, - - notify: { - validator: $.bool, - }, - }, - errors: { noSuchUserList: { message: 'No such user list.', @@ -80,8 +32,36 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + name: { type: 'string', minLength: 1, maxLength: 100 }, + src: { type: 'string', enum: ['home', 'all', 'users', 'list', 'group'] }, + userListId: { type: 'string', format: 'misskey:id', nullable: true }, + userGroupId: { type: 'string', format: 'misskey:id', nullable: true }, + keywords: { type: 'array', items: { + type: 'array', items: { + type: 'string', + }, + } }, + excludeKeywords: { type: 'array', items: { + type: 'array', items: { + type: 'string', + }, + } }, + users: { type: 'array', items: { + type: 'string', + } }, + caseSensitive: { type: 'boolean' }, + withReplies: { type: 'boolean' }, + withFile: { type: 'boolean' }, + notify: { type: 'boolean' }, + }, + required: ['name', 'src', 'keywords', 'excludeKeywords', 'users', 'caseSensitive', 'withReplies', 'withFile', 'notify'], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, user) => { +export default define(meta, paramDef, async (ps, user) => { let userList; let userGroupJoining; diff --git a/packages/backend/src/server/api/endpoints/antennas/delete.ts b/packages/backend/src/server/api/endpoints/antennas/delete.ts index b2793fc70..4e6b8b3d2 100644 --- a/packages/backend/src/server/api/endpoints/antennas/delete.ts +++ b/packages/backend/src/server/api/endpoints/antennas/delete.ts @@ -1,9 +1,7 @@ -import $ from 'cafy'; -import { ID } from '@/misc/cafy-id'; -import define from '../../define'; -import { ApiError } from '../../error'; -import { Antennas } from '@/models/index'; -import { publishInternalEvent } from '@/services/stream'; +import define from '../../define.js'; +import { ApiError } from '../../error.js'; +import { Antennas } from '@/models/index.js'; +import { publishInternalEvent } from '@/services/stream.js'; export const meta = { tags: ['antennas'], @@ -12,12 +10,6 @@ export const meta = { kind: 'write:account', - params: { - antennaId: { - validator: $.type(ID), - }, - }, - errors: { noSuchAntenna: { message: 'No such antenna.', @@ -27,8 +19,16 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + antennaId: { type: 'string', format: 'misskey:id' }, + }, + required: ['antennaId'], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, user) => { +export default define(meta, paramDef, async (ps, user) => { const antenna = await Antennas.findOne({ id: ps.antennaId, userId: user.id, diff --git a/packages/backend/src/server/api/endpoints/antennas/list.ts b/packages/backend/src/server/api/endpoints/antennas/list.ts index bb5891261..accca5de7 100644 --- a/packages/backend/src/server/api/endpoints/antennas/list.ts +++ b/packages/backend/src/server/api/endpoints/antennas/list.ts @@ -1,5 +1,5 @@ -import define from '../../define'; -import { Antennas } from '@/models/index'; +import define from '../../define.js'; +import { Antennas } from '@/models/index.js'; export const meta = { tags: ['antennas', 'account'], @@ -19,8 +19,14 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: {}, + required: [], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, me) => { +export default define(meta, paramDef, async (ps, me) => { const antennas = await Antennas.find({ userId: me.id, }); diff --git a/packages/backend/src/server/api/endpoints/antennas/notes.ts b/packages/backend/src/server/api/endpoints/antennas/notes.ts index eb7de901c..f0cb2ba3c 100644 --- a/packages/backend/src/server/api/endpoints/antennas/notes.ts +++ b/packages/backend/src/server/api/endpoints/antennas/notes.ts @@ -1,13 +1,11 @@ -import $ from 'cafy'; -import { ID } from '@/misc/cafy-id'; -import define from '../../define'; -import readNote from '@/services/note/read'; -import { Antennas, Notes, AntennaNotes } from '@/models/index'; -import { makePaginationQuery } from '../../common/make-pagination-query'; -import { generateVisibilityQuery } from '../../common/generate-visibility-query'; -import { generateMutedUserQuery } from '../../common/generate-muted-user-query'; -import { ApiError } from '../../error'; -import { generateBlockedUserQuery } from '../../common/generate-block-query'; +import define from '../../define.js'; +import readNote from '@/services/note/read.js'; +import { Antennas, Notes, AntennaNotes } from '@/models/index.js'; +import { makePaginationQuery } from '../../common/make-pagination-query.js'; +import { generateVisibilityQuery } from '../../common/generate-visibility-query.js'; +import { generateMutedUserQuery } from '../../common/generate-muted-user-query.js'; +import { ApiError } from '../../error.js'; +import { generateBlockedUserQuery } from '../../common/generate-block-query.js'; export const meta = { tags: ['antennas', 'account', 'notes'], @@ -16,33 +14,6 @@ export const meta = { kind: 'read:account', - params: { - antennaId: { - validator: $.type(ID), - }, - - limit: { - validator: $.optional.num.range(1, 100), - default: 10, - }, - - sinceId: { - validator: $.optional.type(ID), - }, - - untilId: { - validator: $.optional.type(ID), - }, - - sinceDate: { - validator: $.optional.num, - }, - - untilDate: { - validator: $.optional.num, - }, - }, - errors: { noSuchAntenna: { message: 'No such antenna.', @@ -62,8 +33,21 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + antennaId: { type: 'string', format: 'misskey:id' }, + limit: { type: 'integer', minimum: 1, maximum: 100, default: 10 }, + sinceId: { type: 'string', format: 'misskey:id' }, + untilId: { type: 'string', format: 'misskey:id' }, + sinceDate: { type: 'integer' }, + untilDate: { type: 'integer' }, + }, + required: ['antennaId'], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, user) => { +export default define(meta, paramDef, async (ps, user) => { const antenna = await Antennas.findOne({ id: ps.antennaId, userId: user.id, @@ -81,10 +65,16 @@ export default define(meta, async (ps, user) => { ps.sinceId, ps.untilId, ps.sinceDate, ps.untilDate) .andWhere(`note.id IN (${ antennaQuery.getQuery() })`) .innerJoinAndSelect('note.user', 'user') + .leftJoinAndSelect('user.avatar', 'avatar') + .leftJoinAndSelect('user.banner', 'banner') .leftJoinAndSelect('note.reply', 'reply') .leftJoinAndSelect('note.renote', 'renote') .leftJoinAndSelect('reply.user', 'replyUser') + .leftJoinAndSelect('replyUser.avatar', 'replyUserAvatar') + .leftJoinAndSelect('replyUser.banner', 'replyUserBanner') .leftJoinAndSelect('renote.user', 'renoteUser') + .leftJoinAndSelect('renoteUser.avatar', 'renoteUserAvatar') + .leftJoinAndSelect('renoteUser.banner', 'renoteUserBanner') .setParameters(antennaQuery.getParameters()); generateVisibilityQuery(query, user); @@ -92,7 +82,7 @@ export default define(meta, async (ps, user) => { generateBlockedUserQuery(query, user); const notes = await query - .take(ps.limit!) + .take(ps.limit) .getMany(); if (notes.length > 0) { diff --git a/packages/backend/src/server/api/endpoints/antennas/show.ts b/packages/backend/src/server/api/endpoints/antennas/show.ts index a37d37d31..36c4da81b 100644 --- a/packages/backend/src/server/api/endpoints/antennas/show.ts +++ b/packages/backend/src/server/api/endpoints/antennas/show.ts @@ -1,8 +1,6 @@ -import $ from 'cafy'; -import { ID } from '@/misc/cafy-id'; -import define from '../../define'; -import { ApiError } from '../../error'; -import { Antennas } from '@/models/index'; +import define from '../../define.js'; +import { ApiError } from '../../error.js'; +import { Antennas } from '@/models/index.js'; export const meta = { tags: ['antennas', 'account'], @@ -11,12 +9,6 @@ export const meta = { kind: 'read:account', - params: { - antennaId: { - validator: $.type(ID), - }, - }, - errors: { noSuchAntenna: { message: 'No such antenna.', @@ -32,8 +24,16 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + antennaId: { type: 'string', format: 'misskey:id' }, + }, + required: ['antennaId'], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, me) => { +export default define(meta, paramDef, async (ps, me) => { // Fetch the antenna const antenna = await Antennas.findOne({ id: ps.antennaId, diff --git a/packages/backend/src/server/api/endpoints/antennas/update.ts b/packages/backend/src/server/api/endpoints/antennas/update.ts index 900f72550..a99964555 100644 --- a/packages/backend/src/server/api/endpoints/antennas/update.ts +++ b/packages/backend/src/server/api/endpoints/antennas/update.ts @@ -1,9 +1,7 @@ -import $ from 'cafy'; -import { ID } from '@/misc/cafy-id'; -import define from '../../define'; -import { ApiError } from '../../error'; -import { Antennas, UserLists, UserGroupJoinings } from '@/models/index'; -import { publishInternalEvent } from '@/services/stream'; +import define from '../../define.js'; +import { ApiError } from '../../error.js'; +import { Antennas, UserLists, UserGroupJoinings } from '@/models/index.js'; +import { publishInternalEvent } from '@/services/stream.js'; export const meta = { tags: ['antennas'], @@ -12,56 +10,6 @@ export const meta = { kind: 'write:account', - params: { - antennaId: { - validator: $.type(ID), - }, - - name: { - validator: $.str.range(1, 100), - }, - - src: { - validator: $.str.or(['home', 'all', 'users', 'list', 'group']), - }, - - userListId: { - validator: $.nullable.optional.type(ID), - }, - - userGroupId: { - validator: $.nullable.optional.type(ID), - }, - - keywords: { - validator: $.arr($.arr($.str)), - }, - - excludeKeywords: { - validator: $.arr($.arr($.str)), - }, - - users: { - validator: $.arr($.str), - }, - - caseSensitive: { - validator: $.bool, - }, - - withReplies: { - validator: $.bool, - }, - - withFile: { - validator: $.bool, - }, - - notify: { - validator: $.bool, - }, - }, - errors: { noSuchAntenna: { message: 'No such antenna.', @@ -89,8 +37,37 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + antennaId: { type: 'string', format: 'misskey:id' }, + name: { type: 'string', minLength: 1, maxLength: 100 }, + src: { type: 'string', enum: ['home', 'all', 'users', 'list', 'group'] }, + userListId: { type: 'string', format: 'misskey:id', nullable: true }, + userGroupId: { type: 'string', format: 'misskey:id', nullable: true }, + keywords: { type: 'array', items: { + type: 'array', items: { + type: 'string', + }, + } }, + excludeKeywords: { type: 'array', items: { + type: 'array', items: { + type: 'string', + }, + } }, + users: { type: 'array', items: { + type: 'string', + } }, + caseSensitive: { type: 'boolean' }, + withReplies: { type: 'boolean' }, + withFile: { type: 'boolean' }, + notify: { type: 'boolean' }, + }, + required: ['antennaId', 'name', 'src', 'keywords', 'excludeKeywords', 'users', 'caseSensitive', 'withReplies', 'withFile', 'notify'], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, user) => { +export default define(meta, paramDef, async (ps, user) => { // Fetch the antenna const antenna = await Antennas.findOne({ id: ps.antennaId, diff --git a/packages/backend/src/server/api/endpoints/ap/get.ts b/packages/backend/src/server/api/endpoints/ap/get.ts index ff8c677b9..0cbe7ebc6 100644 --- a/packages/backend/src/server/api/endpoints/ap/get.ts +++ b/packages/backend/src/server/api/endpoints/ap/get.ts @@ -1,7 +1,6 @@ -import $ from 'cafy'; -import define from '../../define'; -import Resolver from '@/remote/activitypub/resolver'; -import { ApiError } from '../../error'; +import define from '../../define.js'; +import Resolver from '@/remote/activitypub/resolver.js'; +import { ApiError } from '../../error.js'; import ms from 'ms'; export const meta = { @@ -14,12 +13,6 @@ export const meta = { max: 30, }, - params: { - uri: { - validator: $.str, - }, - }, - errors: { }, @@ -29,8 +22,16 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + uri: { type: 'string' }, + }, + required: ['uri'], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps) => { +export default define(meta, paramDef, async (ps) => { const resolver = new Resolver(); const object = await resolver.resolve(ps.uri); return object; diff --git a/packages/backend/src/server/api/endpoints/ap/show.ts b/packages/backend/src/server/api/endpoints/ap/show.ts index 7d17d8edc..7595c38e8 100644 --- a/packages/backend/src/server/api/endpoints/ap/show.ts +++ b/packages/backend/src/server/api/endpoints/ap/show.ts @@ -1,18 +1,17 @@ -import $ from 'cafy'; -import define from '../../define'; -import config from '@/config/index'; -import { createPerson } from '@/remote/activitypub/models/person'; -import { createNote } from '@/remote/activitypub/models/note'; -import Resolver from '@/remote/activitypub/resolver'; -import { ApiError } from '../../error'; -import { extractDbHost } from '@/misc/convert-host'; -import { Users, Notes } from '@/models/index'; -import { Note } from '@/models/entities/note'; -import { User } from '@/models/entities/user'; -import { fetchMeta } from '@/misc/fetch-meta'; -import { isActor, isPost, getApId } from '@/remote/activitypub/type'; +import define from '../../define.js'; +import config from '@/config/index.js'; +import { createPerson } from '@/remote/activitypub/models/person.js'; +import { createNote } from '@/remote/activitypub/models/note.js'; +import Resolver from '@/remote/activitypub/resolver.js'; +import { ApiError } from '../../error.js'; +import { extractDbHost } from '@/misc/convert-host.js'; +import { Users, Notes } from '@/models/index.js'; +import { Note } from '@/models/entities/note.js'; +import { User } from '@/models/entities/user.js'; +import { fetchMeta } from '@/misc/fetch-meta.js'; +import { isActor, isPost, getApId } from '@/remote/activitypub/type.js'; import ms from 'ms'; -import { SchemaType } from '@/misc/schema'; +import { SchemaType } from '@/misc/schema.js'; export const meta = { tags: ['federation'], @@ -24,12 +23,6 @@ export const meta = { max: 30, }, - params: { - uri: { - validator: $.str, - }, - }, - errors: { noSuchObject: { message: 'No such object.', @@ -75,8 +68,16 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + uri: { type: 'string' }, + }, + required: ['uri'], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps) => { +export default define(meta, paramDef, async (ps) => { const object = await fetchAny(ps.uri); if (object) { return object; diff --git a/packages/backend/src/server/api/endpoints/app/create.ts b/packages/backend/src/server/api/endpoints/app/create.ts index fbe6690f1..e0cf8632f 100644 --- a/packages/backend/src/server/api/endpoints/app/create.ts +++ b/packages/backend/src/server/api/endpoints/app/create.ts @@ -1,35 +1,14 @@ -import $ from 'cafy'; -import define from '../../define'; -import { Apps } from '@/models/index'; -import { genId } from '@/misc/gen-id'; -import { unique } from '@/prelude/array'; -import { secureRndstr } from '@/misc/secure-rndstr'; +import define from '../../define.js'; +import { Apps } from '@/models/index.js'; +import { genId } from '@/misc/gen-id.js'; +import { unique } from '@/prelude/array.js'; +import { secureRndstr } from '@/misc/secure-rndstr.js'; export const meta = { tags: ['app'], requireCredential: false, - params: { - name: { - validator: $.str, - }, - - description: { - validator: $.str, - }, - - permission: { - validator: $.arr($.str).unique(), - }, - - // TODO: Check it is valid url - callbackUrl: { - validator: $.optional.nullable.str, - default: null, - }, - }, - res: { type: 'object', optional: false, nullable: false, @@ -37,8 +16,21 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + name: { type: 'string' }, + description: { type: 'string' }, + permission: { type: 'array', uniqueItems: true, items: { + type: 'string', + } }, + callbackUrl: { type: 'string', nullable: true }, + }, + required: ['name', 'description', 'permission'], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, user) => { +export default define(meta, paramDef, async (ps, user) => { // Generate secret const secret = secureRndstr(32, true); diff --git a/packages/backend/src/server/api/endpoints/app/show.ts b/packages/backend/src/server/api/endpoints/app/show.ts index 9f4777b38..54e714e19 100644 --- a/packages/backend/src/server/api/endpoints/app/show.ts +++ b/packages/backend/src/server/api/endpoints/app/show.ts @@ -1,18 +1,10 @@ -import $ from 'cafy'; -import { ID } from '@/misc/cafy-id'; -import define from '../../define'; -import { ApiError } from '../../error'; -import { Apps } from '@/models/index'; +import define from '../../define.js'; +import { ApiError } from '../../error.js'; +import { Apps } from '@/models/index.js'; export const meta = { tags: ['app'], - params: { - appId: { - validator: $.type(ID), - }, - }, - errors: { noSuchApp: { message: 'No such app.', @@ -28,8 +20,16 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + appId: { type: 'string', format: 'misskey:id' }, + }, + required: ['appId'], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, user, token) => { +export default define(meta, paramDef, async (ps, user, token) => { const isSecure = user != null && token == null; // Lookup app diff --git a/packages/backend/src/server/api/endpoints/auth/accept.ts b/packages/backend/src/server/api/endpoints/auth/accept.ts index f028135ca..0760eef52 100644 --- a/packages/backend/src/server/api/endpoints/auth/accept.ts +++ b/packages/backend/src/server/api/endpoints/auth/accept.ts @@ -1,10 +1,9 @@ -import * as crypto from 'crypto'; -import $ from 'cafy'; -import define from '../../define'; -import { ApiError } from '../../error'; -import { AuthSessions, AccessTokens, Apps } from '@/models/index'; -import { genId } from '@/misc/gen-id'; -import { secureRndstr } from '@/misc/secure-rndstr'; +import * as crypto from 'node:crypto'; +import define from '../../define.js'; +import { ApiError } from '../../error.js'; +import { AuthSessions, AccessTokens, Apps } from '@/models/index.js'; +import { genId } from '@/misc/gen-id.js'; +import { secureRndstr } from '@/misc/secure-rndstr.js'; export const meta = { tags: ['auth'], @@ -13,12 +12,6 @@ export const meta = { secure: true, - params: { - token: { - validator: $.str, - }, - }, - errors: { noSuchSession: { message: 'No such session.', @@ -28,8 +21,16 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + token: { type: 'string' }, + }, + required: ['token'], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, user) => { +export default define(meta, paramDef, async (ps, user) => { // Fetch token const session = await AuthSessions .findOne({ token: ps.token }); diff --git a/packages/backend/src/server/api/endpoints/auth/session/generate.ts b/packages/backend/src/server/api/endpoints/auth/session/generate.ts index 98987eba5..bd571327d 100644 --- a/packages/backend/src/server/api/endpoints/auth/session/generate.ts +++ b/packages/backend/src/server/api/endpoints/auth/session/generate.ts @@ -1,22 +1,15 @@ import { v4 as uuid } from 'uuid'; -import $ from 'cafy'; -import config from '@/config/index'; -import define from '../../../define'; -import { ApiError } from '../../../error'; -import { Apps, AuthSessions } from '@/models/index'; -import { genId } from '@/misc/gen-id'; +import config from '@/config/index.js'; +import define from '../../../define.js'; +import { ApiError } from '../../../error.js'; +import { Apps, AuthSessions } from '@/models/index.js'; +import { genId } from '@/misc/gen-id.js'; export const meta = { tags: ['auth'], requireCredential: false, - params: { - appSecret: { - validator: $.str, - }, - }, - res: { type: 'object', optional: false, nullable: false, @@ -42,8 +35,16 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + appSecret: { type: 'string' }, + }, + required: ['appSecret'], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps) => { +export default define(meta, paramDef, async (ps) => { // Lookup app const app = await Apps.findOne({ secret: ps.appSecret, diff --git a/packages/backend/src/server/api/endpoints/auth/session/show.ts b/packages/backend/src/server/api/endpoints/auth/session/show.ts index ae0d016ce..d40c9363c 100644 --- a/packages/backend/src/server/api/endpoints/auth/session/show.ts +++ b/packages/backend/src/server/api/endpoints/auth/session/show.ts @@ -1,19 +1,12 @@ -import $ from 'cafy'; -import define from '../../../define'; -import { ApiError } from '../../../error'; -import { AuthSessions } from '@/models/index'; +import define from '../../../define.js'; +import { ApiError } from '../../../error.js'; +import { AuthSessions } from '@/models/index.js'; export const meta = { tags: ['auth'], requireCredential: false, - params: { - token: { - validator: $.str, - }, - }, - errors: { noSuchSession: { message: 'No such session.', @@ -44,8 +37,16 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + token: { type: 'string' }, + }, + required: ['token'], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, user) => { +export default define(meta, paramDef, async (ps, user) => { // Lookup session const session = await AuthSessions.findOne({ token: ps.token, diff --git a/packages/backend/src/server/api/endpoints/auth/session/userkey.ts b/packages/backend/src/server/api/endpoints/auth/session/userkey.ts index fe0211ebe..b699c6fa2 100644 --- a/packages/backend/src/server/api/endpoints/auth/session/userkey.ts +++ b/packages/backend/src/server/api/endpoints/auth/session/userkey.ts @@ -1,23 +1,12 @@ -import $ from 'cafy'; -import define from '../../../define'; -import { ApiError } from '../../../error'; -import { Apps, AuthSessions, AccessTokens, Users } from '@/models/index'; +import define from '../../../define.js'; +import { ApiError } from '../../../error.js'; +import { Apps, AuthSessions, AccessTokens, Users } from '@/models/index.js'; export const meta = { tags: ['auth'], requireCredential: false, - params: { - appSecret: { - validator: $.str, - }, - - token: { - validator: $.str, - }, - }, - res: { type: 'object', optional: false, nullable: false, @@ -56,8 +45,17 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + appSecret: { type: 'string' }, + token: { type: 'string' }, + }, + required: ['appSecret', 'token'], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps) => { +export default define(meta, paramDef, async (ps) => { // Lookup app const app = await Apps.findOne({ secret: ps.appSecret, diff --git a/packages/backend/src/server/api/endpoints/blocking/create.ts b/packages/backend/src/server/api/endpoints/blocking/create.ts index 6d555ff56..c5e73c013 100644 --- a/packages/backend/src/server/api/endpoints/blocking/create.ts +++ b/packages/backend/src/server/api/endpoints/blocking/create.ts @@ -1,11 +1,9 @@ -import $ from 'cafy'; -import { ID } from '@/misc/cafy-id'; import ms from 'ms'; -import create from '@/services/blocking/create'; -import define from '../../define'; -import { ApiError } from '../../error'; -import { getUser } from '../../common/getters'; -import { Blockings, NoteWatchings, Users } from '@/models/index'; +import create from '@/services/blocking/create.js'; +import define from '../../define.js'; +import { ApiError } from '../../error.js'; +import { getUser } from '../../common/getters.js'; +import { Blockings, NoteWatchings, Users } from '@/models/index.js'; export const meta = { tags: ['account'], @@ -19,12 +17,6 @@ export const meta = { kind: 'write:blocks', - params: { - userId: { - validator: $.type(ID), - }, - }, - errors: { noSuchUser: { message: 'No such user.', @@ -52,8 +44,16 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + userId: { type: 'string', format: 'misskey:id' }, + }, + required: ['userId'], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, user) => { +export default define(meta, paramDef, async (ps, user) => { const blocker = await Users.findOneOrFail(user.id); // 自分自身 diff --git a/packages/backend/src/server/api/endpoints/blocking/delete.ts b/packages/backend/src/server/api/endpoints/blocking/delete.ts index 942cddaed..a45547290 100644 --- a/packages/backend/src/server/api/endpoints/blocking/delete.ts +++ b/packages/backend/src/server/api/endpoints/blocking/delete.ts @@ -1,11 +1,9 @@ -import $ from 'cafy'; -import { ID } from '@/misc/cafy-id'; import ms from 'ms'; -import deleteBlocking from '@/services/blocking/delete'; -import define from '../../define'; -import { ApiError } from '../../error'; -import { getUser } from '../../common/getters'; -import { Blockings, Users } from '@/models/index'; +import deleteBlocking from '@/services/blocking/delete.js'; +import define from '../../define.js'; +import { ApiError } from '../../error.js'; +import { getUser } from '../../common/getters.js'; +import { Blockings, Users } from '@/models/index.js'; export const meta = { tags: ['account'], @@ -19,12 +17,6 @@ export const meta = { kind: 'write:blocks', - params: { - userId: { - validator: $.type(ID), - }, - }, - errors: { noSuchUser: { message: 'No such user.', @@ -52,8 +44,16 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + userId: { type: 'string', format: 'misskey:id' }, + }, + required: ['userId'], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, user) => { +export default define(meta, paramDef, async (ps, user) => { const blocker = await Users.findOneOrFail(user.id); // Check if the blockee is yourself diff --git a/packages/backend/src/server/api/endpoints/blocking/list.ts b/packages/backend/src/server/api/endpoints/blocking/list.ts index 9a4f66214..29095ebe2 100644 --- a/packages/backend/src/server/api/endpoints/blocking/list.ts +++ b/packages/backend/src/server/api/endpoints/blocking/list.ts @@ -1,8 +1,6 @@ -import $ from 'cafy'; -import { ID } from '@/misc/cafy-id'; -import define from '../../define'; -import { Blockings } from '@/models/index'; -import { makePaginationQuery } from '../../common/make-pagination-query'; +import define from '../../define.js'; +import { Blockings } from '@/models/index.js'; +import { makePaginationQuery } from '../../common/make-pagination-query.js'; export const meta = { tags: ['account'], @@ -11,21 +9,6 @@ export const meta = { kind: 'read:blocks', - params: { - limit: { - validator: $.optional.num.range(1, 100), - default: 30, - }, - - sinceId: { - validator: $.optional.type(ID), - }, - - untilId: { - validator: $.optional.type(ID), - }, - }, - res: { type: 'array', optional: false, nullable: false, @@ -37,13 +20,23 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + limit: { type: 'integer', minimum: 1, maximum: 100, default: 30 }, + sinceId: { type: 'string', format: 'misskey:id' }, + untilId: { type: 'string', format: 'misskey:id' }, + }, + required: [], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, me) => { +export default define(meta, paramDef, async (ps, me) => { const query = makePaginationQuery(Blockings.createQueryBuilder('blocking'), ps.sinceId, ps.untilId) .andWhere(`blocking.blockerId = :meId`, { meId: me.id }); const blockings = await query - .take(ps.limit!) + .take(ps.limit) .getMany(); return await Blockings.packMany(blockings, me); diff --git a/packages/backend/src/server/api/endpoints/channels/create.ts b/packages/backend/src/server/api/endpoints/channels/create.ts index 68cdf1143..16456b9c0 100644 --- a/packages/backend/src/server/api/endpoints/channels/create.ts +++ b/packages/backend/src/server/api/endpoints/channels/create.ts @@ -1,10 +1,8 @@ -import $ from 'cafy'; -import define from '../../define'; -import { ApiError } from '../../error'; -import { Channels, DriveFiles } from '@/models/index'; -import { Channel } from '@/models/entities/channel'; -import { genId } from '@/misc/gen-id'; -import { ID } from '@/misc/cafy-id'; +import define from '../../define.js'; +import { ApiError } from '../../error.js'; +import { Channels, DriveFiles } from '@/models/index.js'; +import { Channel } from '@/models/entities/channel.js'; +import { genId } from '@/misc/gen-id.js'; export const meta = { tags: ['channels'], @@ -13,20 +11,6 @@ export const meta = { kind: 'write:channels', - params: { - name: { - validator: $.str.range(1, 128), - }, - - description: { - validator: $.nullable.optional.str.range(1, 2048), - }, - - bannerId: { - validator: $.nullable.optional.type(ID), - }, - }, - res: { type: 'object', optional: false, nullable: false, @@ -42,8 +26,18 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + name: { type: 'string', minLength: 1, maxLength: 128 }, + description: { type: 'string', nullable: true, minLength: 1, maxLength: 2048 }, + bannerId: { type: 'string', format: 'misskey:id', nullable: true }, + }, + required: ['name'], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, user) => { +export default define(meta, paramDef, async (ps, user) => { let banner = null; if (ps.bannerId != null) { banner = await DriveFiles.findOne({ diff --git a/packages/backend/src/server/api/endpoints/channels/featured.ts b/packages/backend/src/server/api/endpoints/channels/featured.ts index ceadde907..73980c0fa 100644 --- a/packages/backend/src/server/api/endpoints/channels/featured.ts +++ b/packages/backend/src/server/api/endpoints/channels/featured.ts @@ -1,5 +1,5 @@ -import define from '../../define'; -import { Channels } from '@/models/index'; +import define from '../../define.js'; +import { Channels } from '@/models/index.js'; export const meta = { tags: ['channels'], @@ -17,8 +17,14 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: {}, + required: [], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, me) => { +export default define(meta, paramDef, async (ps, me) => { const query = Channels.createQueryBuilder('channel') .where('channel.lastNotedAt IS NOT NULL') .orderBy('channel.lastNotedAt', 'DESC'); diff --git a/packages/backend/src/server/api/endpoints/channels/follow.ts b/packages/backend/src/server/api/endpoints/channels/follow.ts index bf580eea6..4372c283c 100644 --- a/packages/backend/src/server/api/endpoints/channels/follow.ts +++ b/packages/backend/src/server/api/endpoints/channels/follow.ts @@ -1,10 +1,8 @@ -import $ from 'cafy'; -import { ID } from '@/misc/cafy-id'; -import define from '../../define'; -import { ApiError } from '../../error'; -import { Channels, ChannelFollowings } from '@/models/index'; -import { genId } from '@/misc/gen-id'; -import { publishUserEvent } from '@/services/stream'; +import define from '../../define.js'; +import { ApiError } from '../../error.js'; +import { Channels, ChannelFollowings } from '@/models/index.js'; +import { genId } from '@/misc/gen-id.js'; +import { publishUserEvent } from '@/services/stream.js'; export const meta = { tags: ['channels'], @@ -13,12 +11,6 @@ export const meta = { kind: 'write:channels', - params: { - channelId: { - validator: $.type(ID), - }, - }, - errors: { noSuchChannel: { message: 'No such channel.', @@ -28,8 +20,16 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + channelId: { type: 'string', format: 'misskey:id' }, + }, + required: ['channelId'], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, user) => { +export default define(meta, paramDef, async (ps, user) => { const channel = await Channels.findOne({ id: ps.channelId, }); diff --git a/packages/backend/src/server/api/endpoints/channels/followed.ts b/packages/backend/src/server/api/endpoints/channels/followed.ts index 9e4c942af..e4aa4d161 100644 --- a/packages/backend/src/server/api/endpoints/channels/followed.ts +++ b/packages/backend/src/server/api/endpoints/channels/followed.ts @@ -1,8 +1,6 @@ -import $ from 'cafy'; -import { ID } from '@/misc/cafy-id'; -import define from '../../define'; -import { Channels, ChannelFollowings } from '@/models/index'; -import { makePaginationQuery } from '../../common/make-pagination-query'; +import define from '../../define.js'; +import { Channels, ChannelFollowings } from '@/models/index.js'; +import { makePaginationQuery } from '../../common/make-pagination-query.js'; export const meta = { tags: ['channels', 'account'], @@ -11,21 +9,6 @@ export const meta = { kind: 'read:channels', - params: { - sinceId: { - validator: $.optional.type(ID), - }, - - untilId: { - validator: $.optional.type(ID), - }, - - limit: { - validator: $.optional.num.range(1, 100), - default: 5, - }, - }, - res: { type: 'array', optional: false, nullable: false, @@ -37,13 +20,23 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + sinceId: { type: 'string', format: 'misskey:id' }, + untilId: { type: 'string', format: 'misskey:id' }, + limit: { type: 'integer', minimum: 1, maximum: 100, default: 5 }, + }, + required: [], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, me) => { +export default define(meta, paramDef, async (ps, me) => { const query = makePaginationQuery(ChannelFollowings.createQueryBuilder(), ps.sinceId, ps.untilId) .andWhere({ followerId: me.id }); const followings = await query - .take(ps.limit!) + .take(ps.limit) .getMany(); return await Promise.all(followings.map(x => Channels.pack(x.followeeId, me))); diff --git a/packages/backend/src/server/api/endpoints/channels/owned.ts b/packages/backend/src/server/api/endpoints/channels/owned.ts index 5473636a8..ed7e41cac 100644 --- a/packages/backend/src/server/api/endpoints/channels/owned.ts +++ b/packages/backend/src/server/api/endpoints/channels/owned.ts @@ -1,8 +1,6 @@ -import $ from 'cafy'; -import { ID } from '@/misc/cafy-id'; -import define from '../../define'; -import { Channels } from '@/models/index'; -import { makePaginationQuery } from '../../common/make-pagination-query'; +import define from '../../define.js'; +import { Channels } from '@/models/index.js'; +import { makePaginationQuery } from '../../common/make-pagination-query.js'; export const meta = { tags: ['channels', 'account'], @@ -11,21 +9,6 @@ export const meta = { kind: 'read:channels', - params: { - sinceId: { - validator: $.optional.type(ID), - }, - - untilId: { - validator: $.optional.type(ID), - }, - - limit: { - validator: $.optional.num.range(1, 100), - default: 5, - }, - }, - res: { type: 'array', optional: false, nullable: false, @@ -37,13 +20,23 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + sinceId: { type: 'string', format: 'misskey:id' }, + untilId: { type: 'string', format: 'misskey:id' }, + limit: { type: 'integer', minimum: 1, maximum: 100, default: 5 }, + }, + required: [], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, me) => { +export default define(meta, paramDef, async (ps, me) => { const query = makePaginationQuery(Channels.createQueryBuilder(), ps.sinceId, ps.untilId) .andWhere({ userId: me.id }); const channels = await query - .take(ps.limit!) + .take(ps.limit) .getMany(); return await Promise.all(channels.map(x => Channels.pack(x, me))); diff --git a/packages/backend/src/server/api/endpoints/channels/show.ts b/packages/backend/src/server/api/endpoints/channels/show.ts index 598a87ec4..ea4e01307 100644 --- a/packages/backend/src/server/api/endpoints/channels/show.ts +++ b/packages/backend/src/server/api/endpoints/channels/show.ts @@ -1,20 +1,12 @@ -import $ from 'cafy'; -import { ID } from '@/misc/cafy-id'; -import define from '../../define'; -import { ApiError } from '../../error'; -import { Channels } from '@/models/index'; +import define from '../../define.js'; +import { ApiError } from '../../error.js'; +import { Channels } from '@/models/index.js'; export const meta = { tags: ['channels'], requireCredential: false, - params: { - channelId: { - validator: $.type(ID), - }, - }, - res: { type: 'object', optional: false, nullable: false, @@ -30,8 +22,16 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + channelId: { type: 'string', format: 'misskey:id' }, + }, + required: ['channelId'], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, me) => { +export default define(meta, paramDef, async (ps, me) => { const channel = await Channels.findOne({ id: ps.channelId, }); diff --git a/packages/backend/src/server/api/endpoints/channels/timeline.ts b/packages/backend/src/server/api/endpoints/channels/timeline.ts index 2639095f8..57a9fa44b 100644 --- a/packages/backend/src/server/api/endpoints/channels/timeline.ts +++ b/packages/backend/src/server/api/endpoints/channels/timeline.ts @@ -1,43 +1,14 @@ -import $ from 'cafy'; -import { ID } from '@/misc/cafy-id'; -import define from '../../define'; -import { ApiError } from '../../error'; -import { Notes, Channels } from '@/models/index'; -import { makePaginationQuery } from '../../common/make-pagination-query'; -import { activeUsersChart } from '@/services/chart/index'; +import define from '../../define.js'; +import { ApiError } from '../../error.js'; +import { Notes, Channels } from '@/models/index.js'; +import { makePaginationQuery } from '../../common/make-pagination-query.js'; +import { activeUsersChart } from '@/services/chart/index.js'; export const meta = { tags: ['notes', 'channels'], requireCredential: false, - params: { - channelId: { - validator: $.type(ID), - }, - - limit: { - validator: $.optional.num.range(1, 100), - default: 10, - }, - - sinceId: { - validator: $.optional.type(ID), - }, - - untilId: { - validator: $.optional.type(ID), - }, - - sinceDate: { - validator: $.optional.num, - }, - - untilDate: { - validator: $.optional.num, - }, - }, - res: { type: 'array', optional: false, nullable: false, @@ -57,8 +28,21 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + channelId: { type: 'string', format: 'misskey:id' }, + limit: { type: 'integer', minimum: 1, maximum: 100, default: 10 }, + sinceId: { type: 'string', format: 'misskey:id' }, + untilId: { type: 'string', format: 'misskey:id' }, + sinceDate: { type: 'integer' }, + untilDate: { type: 'integer' }, + }, + required: ['channelId'], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, user) => { +export default define(meta, paramDef, async (ps, user) => { const channel = await Channels.findOne({ id: ps.channelId, }); @@ -71,14 +55,20 @@ export default define(meta, async (ps, user) => { const query = makePaginationQuery(Notes.createQueryBuilder('note'), ps.sinceId, ps.untilId, ps.sinceDate, ps.untilDate) .andWhere('note.channelId = :channelId', { channelId: channel.id }) .innerJoinAndSelect('note.user', 'user') + .leftJoinAndSelect('user.avatar', 'avatar') + .leftJoinAndSelect('user.banner', 'banner') .leftJoinAndSelect('note.reply', 'reply') .leftJoinAndSelect('note.renote', 'renote') .leftJoinAndSelect('reply.user', 'replyUser') + .leftJoinAndSelect('replyUser.avatar', 'replyUserAvatar') + .leftJoinAndSelect('replyUser.banner', 'replyUserBanner') .leftJoinAndSelect('renote.user', 'renoteUser') + .leftJoinAndSelect('renoteUser.avatar', 'renoteUserAvatar') + .leftJoinAndSelect('renoteUser.banner', 'renoteUserBanner') .leftJoinAndSelect('note.channel', 'channel'); //#endregion - const timeline = await query.take(ps.limit!).getMany(); + const timeline = await query.take(ps.limit).getMany(); if (user) activeUsersChart.read(user); diff --git a/packages/backend/src/server/api/endpoints/channels/unfollow.ts b/packages/backend/src/server/api/endpoints/channels/unfollow.ts index ada0cb29f..32beb24d6 100644 --- a/packages/backend/src/server/api/endpoints/channels/unfollow.ts +++ b/packages/backend/src/server/api/endpoints/channels/unfollow.ts @@ -1,9 +1,7 @@ -import $ from 'cafy'; -import { ID } from '@/misc/cafy-id'; -import define from '../../define'; -import { ApiError } from '../../error'; -import { Channels, ChannelFollowings } from '@/models/index'; -import { publishUserEvent } from '@/services/stream'; +import define from '../../define.js'; +import { ApiError } from '../../error.js'; +import { Channels, ChannelFollowings } from '@/models/index.js'; +import { publishUserEvent } from '@/services/stream.js'; export const meta = { tags: ['channels'], @@ -12,12 +10,6 @@ export const meta = { kind: 'write:channels', - params: { - channelId: { - validator: $.type(ID), - }, - }, - errors: { noSuchChannel: { message: 'No such channel.', @@ -27,8 +19,16 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + channelId: { type: 'string', format: 'misskey:id' }, + }, + required: ['channelId'], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, user) => { +export default define(meta, paramDef, async (ps, user) => { const channel = await Channels.findOne({ id: ps.channelId, }); diff --git a/packages/backend/src/server/api/endpoints/channels/update.ts b/packages/backend/src/server/api/endpoints/channels/update.ts index 1f7108a1c..2f2b4aeeb 100644 --- a/packages/backend/src/server/api/endpoints/channels/update.ts +++ b/packages/backend/src/server/api/endpoints/channels/update.ts @@ -1,8 +1,6 @@ -import $ from 'cafy'; -import { ID } from '@/misc/cafy-id'; -import define from '../../define'; -import { ApiError } from '../../error'; -import { Channels, DriveFiles } from '@/models/index'; +import define from '../../define.js'; +import { ApiError } from '../../error.js'; +import { Channels, DriveFiles } from '@/models/index.js'; export const meta = { tags: ['channels'], @@ -11,24 +9,6 @@ export const meta = { kind: 'write:channels', - params: { - channelId: { - validator: $.type(ID), - }, - - name: { - validator: $.optional.str.range(1, 128), - }, - - description: { - validator: $.nullable.optional.str.range(1, 2048), - }, - - bannerId: { - validator: $.nullable.optional.type(ID), - }, - }, - res: { type: 'object', optional: false, nullable: false, @@ -56,8 +36,19 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + channelId: { type: 'string', format: 'misskey:id' }, + name: { type: 'string', minLength: 1, maxLength: 128 }, + description: { type: 'string', nullable: true, minLength: 1, maxLength: 2048 }, + bannerId: { type: 'string', format: 'misskey:id', nullable: true }, + }, + required: ['channelId'], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, me) => { +export default define(meta, paramDef, async (ps, me) => { const channel = await Channels.findOne({ id: ps.channelId, }); diff --git a/packages/backend/src/server/api/endpoints/charts/active-users.ts b/packages/backend/src/server/api/endpoints/charts/active-users.ts index a51cd0035..97f7885db 100644 --- a/packages/backend/src/server/api/endpoints/charts/active-users.ts +++ b/packages/backend/src/server/api/endpoints/charts/active-users.ts @@ -1,31 +1,24 @@ -import $ from 'cafy'; -import define from '../../define'; -import { convertLog } from '@/services/chart/core'; -import { activeUsersChart } from '@/services/chart/index'; +import define from '../../define.js'; +import { getJsonSchema } from '@/services/chart/core.js'; +import { activeUsersChart } from '@/services/chart/index.js'; export const meta = { tags: ['charts', 'users'], - params: { - span: { - validator: $.str.or(['day', 'hour']), - }, + res: getJsonSchema(activeUsersChart.schema), +} as const; - limit: { - validator: $.optional.num.range(1, 500), - default: 30, - }, - - offset: { - validator: $.optional.nullable.num, - default: null, - }, +export const paramDef = { + type: 'object', + properties: { + span: { type: 'string', enum: ['day', 'hour'] }, + limit: { type: 'integer', minimum: 1, maximum: 500, default: 30 }, + offset: { type: 'integer', nullable: true, default: null }, }, - - // TODO: response definition + required: ['span'], } as const; // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps) => { - return await activeUsersChart.getChart(ps.span as any, ps.limit!, ps.offset ? new Date(ps.offset) : null); +export default define(meta, paramDef, async (ps) => { + return await activeUsersChart.getChart(ps.span, ps.limit, ps.offset ? new Date(ps.offset) : null); }); diff --git a/packages/backend/src/server/api/endpoints/charts/ap-request.ts b/packages/backend/src/server/api/endpoints/charts/ap-request.ts index 38bbddb27..4477bfc98 100644 --- a/packages/backend/src/server/api/endpoints/charts/ap-request.ts +++ b/packages/backend/src/server/api/endpoints/charts/ap-request.ts @@ -1,31 +1,24 @@ -import $ from 'cafy'; -import define from '../../define'; -import { convertLog } from '@/services/chart/core'; -import { apRequestChart } from '@/services/chart/index'; +import define from '../../define.js'; +import { getJsonSchema } from '@/services/chart/core.js'; +import { apRequestChart } from '@/services/chart/index.js'; export const meta = { tags: ['charts'], - params: { - span: { - validator: $.str.or(['day', 'hour']), - }, + res: getJsonSchema(apRequestChart.schema), +} as const; - limit: { - validator: $.optional.num.range(1, 500), - default: 30, - }, - - offset: { - validator: $.optional.nullable.num, - default: null, - }, +export const paramDef = { + type: 'object', + properties: { + span: { type: 'string', enum: ['day', 'hour'] }, + limit: { type: 'integer', minimum: 1, maximum: 500, default: 30 }, + offset: { type: 'integer', nullable: true, default: null }, }, - - // TODO: response definition + required: ['span'], } as const; // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps) => { - return await apRequestChart.getChart(ps.span as any, ps.limit!, ps.offset ? new Date(ps.offset) : null); +export default define(meta, paramDef, async (ps) => { + return await apRequestChart.getChart(ps.span, ps.limit, ps.offset ? new Date(ps.offset) : null); }); diff --git a/packages/backend/src/server/api/endpoints/charts/drive.ts b/packages/backend/src/server/api/endpoints/charts/drive.ts index 4bbb9861f..fd6033392 100644 --- a/packages/backend/src/server/api/endpoints/charts/drive.ts +++ b/packages/backend/src/server/api/endpoints/charts/drive.ts @@ -1,31 +1,24 @@ -import $ from 'cafy'; -import define from '../../define'; -import { convertLog } from '@/services/chart/core'; -import { driveChart } from '@/services/chart/index'; +import define from '../../define.js'; +import { getJsonSchema } from '@/services/chart/core.js'; +import { driveChart } from '@/services/chart/index.js'; export const meta = { tags: ['charts', 'drive'], - params: { - span: { - validator: $.str.or(['day', 'hour']), - }, + res: getJsonSchema(driveChart.schema), +} as const; - limit: { - validator: $.optional.num.range(1, 500), - default: 30, - }, - - offset: { - validator: $.optional.nullable.num, - default: null, - }, +export const paramDef = { + type: 'object', + properties: { + span: { type: 'string', enum: ['day', 'hour'] }, + limit: { type: 'integer', minimum: 1, maximum: 500, default: 30 }, + offset: { type: 'integer', nullable: true, default: null }, }, - - // TODO: response definition + required: ['span'], } as const; // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps) => { - return await driveChart.getChart(ps.span as any, ps.limit!, ps.offset ? new Date(ps.offset) : null); +export default define(meta, paramDef, async (ps) => { + return await driveChart.getChart(ps.span, ps.limit, ps.offset ? new Date(ps.offset) : null); }); diff --git a/packages/backend/src/server/api/endpoints/charts/federation.ts b/packages/backend/src/server/api/endpoints/charts/federation.ts index 237678ffe..f842f574e 100644 --- a/packages/backend/src/server/api/endpoints/charts/federation.ts +++ b/packages/backend/src/server/api/endpoints/charts/federation.ts @@ -1,31 +1,24 @@ -import $ from 'cafy'; -import define from '../../define'; -import { convertLog } from '@/services/chart/core'; -import { federationChart } from '@/services/chart/index'; +import define from '../../define.js'; +import { getJsonSchema } from '@/services/chart/core.js'; +import { federationChart } from '@/services/chart/index.js'; export const meta = { tags: ['charts'], - params: { - span: { - validator: $.str.or(['day', 'hour']), - }, + res: getJsonSchema(federationChart.schema), +} as const; - limit: { - validator: $.optional.num.range(1, 500), - default: 30, - }, - - offset: { - validator: $.optional.nullable.num, - default: null, - }, +export const paramDef = { + type: 'object', + properties: { + span: { type: 'string', enum: ['day', 'hour'] }, + limit: { type: 'integer', minimum: 1, maximum: 500, default: 30 }, + offset: { type: 'integer', nullable: true, default: null }, }, - - // TODO: response definition + required: ['span'], } as const; // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps) => { - return await federationChart.getChart(ps.span as any, ps.limit!, ps.offset ? new Date(ps.offset) : null); +export default define(meta, paramDef, async (ps) => { + return await federationChart.getChart(ps.span, ps.limit, ps.offset ? new Date(ps.offset) : null); }); diff --git a/packages/backend/src/server/api/endpoints/charts/hashtag.ts b/packages/backend/src/server/api/endpoints/charts/hashtag.ts index 6c12cb063..01407defd 100644 --- a/packages/backend/src/server/api/endpoints/charts/hashtag.ts +++ b/packages/backend/src/server/api/endpoints/charts/hashtag.ts @@ -1,35 +1,25 @@ -import $ from 'cafy'; -import define from '../../define'; -import { convertLog } from '@/services/chart/core'; -import { hashtagChart } from '@/services/chart/index'; +import define from '../../define.js'; +import { getJsonSchema } from '@/services/chart/core.js'; +import { hashtagChart } from '@/services/chart/index.js'; export const meta = { tags: ['charts', 'hashtags'], - params: { - span: { - validator: $.str.or(['day', 'hour']), - }, + res: getJsonSchema(hashtagChart.schema), +} as const; - limit: { - validator: $.optional.num.range(1, 500), - default: 30, - }, - - offset: { - validator: $.optional.nullable.num, - default: null, - }, - - tag: { - validator: $.str, - }, +export const paramDef = { + type: 'object', + properties: { + span: { type: 'string', enum: ['day', 'hour'] }, + limit: { type: 'integer', minimum: 1, maximum: 500, default: 30 }, + offset: { type: 'integer', nullable: true, default: null }, + tag: { type: 'string' }, }, - - // TODO: response definition + required: ['span', 'tag'], } as const; // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps) => { - return await hashtagChart.getChart(ps.span as any, ps.limit!, ps.offset ? new Date(ps.offset) : null, ps.tag); +export default define(meta, paramDef, async (ps) => { + return await hashtagChart.getChart(ps.span, ps.limit, ps.offset ? new Date(ps.offset) : null, ps.tag); }); diff --git a/packages/backend/src/server/api/endpoints/charts/instance.ts b/packages/backend/src/server/api/endpoints/charts/instance.ts index 32a10d5a2..2d12951c6 100644 --- a/packages/backend/src/server/api/endpoints/charts/instance.ts +++ b/packages/backend/src/server/api/endpoints/charts/instance.ts @@ -1,35 +1,25 @@ -import $ from 'cafy'; -import define from '../../define'; -import { convertLog } from '@/services/chart/core'; -import { instanceChart } from '@/services/chart/index'; +import define from '../../define.js'; +import { getJsonSchema } from '@/services/chart/core.js'; +import { instanceChart } from '@/services/chart/index.js'; export const meta = { tags: ['charts'], - params: { - span: { - validator: $.str.or(['day', 'hour']), - }, + res: getJsonSchema(instanceChart.schema), +} as const; - limit: { - validator: $.optional.num.range(1, 500), - default: 30, - }, - - offset: { - validator: $.optional.nullable.num, - default: null, - }, - - host: { - validator: $.str, - }, +export const paramDef = { + type: 'object', + properties: { + span: { type: 'string', enum: ['day', 'hour'] }, + limit: { type: 'integer', minimum: 1, maximum: 500, default: 30 }, + offset: { type: 'integer', nullable: true, default: null }, + host: { type: 'string' }, }, - - // TODO: response definition + required: ['span', 'host'], } as const; // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps) => { - return await instanceChart.getChart(ps.span as any, ps.limit!, ps.offset ? new Date(ps.offset) : null, ps.host); +export default define(meta, paramDef, async (ps) => { + return await instanceChart.getChart(ps.span, ps.limit, ps.offset ? new Date(ps.offset) : null, ps.host); }); diff --git a/packages/backend/src/server/api/endpoints/charts/notes.ts b/packages/backend/src/server/api/endpoints/charts/notes.ts index 09255f1d2..b6089f67e 100644 --- a/packages/backend/src/server/api/endpoints/charts/notes.ts +++ b/packages/backend/src/server/api/endpoints/charts/notes.ts @@ -1,31 +1,24 @@ -import $ from 'cafy'; -import define from '../../define'; -import { convertLog } from '@/services/chart/core'; -import { notesChart } from '@/services/chart/index'; +import define from '../../define.js'; +import { getJsonSchema } from '@/services/chart/core.js'; +import { notesChart } from '@/services/chart/index.js'; export const meta = { tags: ['charts', 'notes'], - params: { - span: { - validator: $.str.or(['day', 'hour']), - }, + res: getJsonSchema(notesChart.schema), +} as const; - limit: { - validator: $.optional.num.range(1, 500), - default: 30, - }, - - offset: { - validator: $.optional.nullable.num, - default: null, - }, +export const paramDef = { + type: 'object', + properties: { + span: { type: 'string', enum: ['day', 'hour'] }, + limit: { type: 'integer', minimum: 1, maximum: 500, default: 30 }, + offset: { type: 'integer', nullable: true, default: null }, }, - - // TODO: response definition + required: ['span'], } as const; // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps) => { - return await notesChart.getChart(ps.span as any, ps.limit!, ps.offset ? new Date(ps.offset) : null); +export default define(meta, paramDef, async (ps) => { + return await notesChart.getChart(ps.span, ps.limit, ps.offset ? new Date(ps.offset) : null); }); diff --git a/packages/backend/src/server/api/endpoints/charts/user/drive.ts b/packages/backend/src/server/api/endpoints/charts/user/drive.ts index 89379858d..e5db7131a 100644 --- a/packages/backend/src/server/api/endpoints/charts/user/drive.ts +++ b/packages/backend/src/server/api/endpoints/charts/user/drive.ts @@ -1,36 +1,25 @@ -import $ from 'cafy'; -import define from '../../../define'; -import { ID } from '@/misc/cafy-id'; -import { convertLog } from '@/services/chart/core'; -import { perUserDriveChart } from '@/services/chart/index'; +import define from '../../../define.js'; +import { getJsonSchema } from '@/services/chart/core.js'; +import { perUserDriveChart } from '@/services/chart/index.js'; export const meta = { tags: ['charts', 'drive', 'users'], - params: { - span: { - validator: $.str.or(['day', 'hour']), - }, + res: getJsonSchema(perUserDriveChart.schema), +} as const; - limit: { - validator: $.optional.num.range(1, 500), - default: 30, - }, - - offset: { - validator: $.optional.nullable.num, - default: null, - }, - - userId: { - validator: $.type(ID), - }, +export const paramDef = { + type: 'object', + properties: { + span: { type: 'string', enum: ['day', 'hour'] }, + limit: { type: 'integer', minimum: 1, maximum: 500, default: 30 }, + offset: { type: 'integer', nullable: true, default: null }, + userId: { type: 'string', format: 'misskey:id' }, }, - - // TODO: response definition + required: ['span', 'userId'], } as const; // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps) => { - return await perUserDriveChart.getChart(ps.span as any, ps.limit!, ps.offset ? new Date(ps.offset) : null, ps.userId); +export default define(meta, paramDef, async (ps) => { + return await perUserDriveChart.getChart(ps.span, ps.limit, ps.offset ? new Date(ps.offset) : null, ps.userId); }); diff --git a/packages/backend/src/server/api/endpoints/charts/user/following.ts b/packages/backend/src/server/api/endpoints/charts/user/following.ts index 26c3f5c12..9b72de745 100644 --- a/packages/backend/src/server/api/endpoints/charts/user/following.ts +++ b/packages/backend/src/server/api/endpoints/charts/user/following.ts @@ -1,36 +1,25 @@ -import $ from 'cafy'; -import define from '../../../define'; -import { ID } from '@/misc/cafy-id'; -import { convertLog } from '@/services/chart/core'; -import { perUserFollowingChart } from '@/services/chart/index'; +import define from '../../../define.js'; +import { getJsonSchema } from '@/services/chart/core.js'; +import { perUserFollowingChart } from '@/services/chart/index.js'; export const meta = { tags: ['charts', 'users', 'following'], - params: { - span: { - validator: $.str.or(['day', 'hour']), - }, + res: getJsonSchema(perUserFollowingChart.schema), +} as const; - limit: { - validator: $.optional.num.range(1, 500), - default: 30, - }, - - offset: { - validator: $.optional.nullable.num, - default: null, - }, - - userId: { - validator: $.type(ID), - }, +export const paramDef = { + type: 'object', + properties: { + span: { type: 'string', enum: ['day', 'hour'] }, + limit: { type: 'integer', minimum: 1, maximum: 500, default: 30 }, + offset: { type: 'integer', nullable: true, default: null }, + userId: { type: 'string', format: 'misskey:id' }, }, - - // TODO: response definition + required: ['span', 'userId'], } as const; // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps) => { - return await perUserFollowingChart.getChart(ps.span as any, ps.limit!, ps.offset ? new Date(ps.offset) : null, ps.userId); +export default define(meta, paramDef, async (ps) => { + return await perUserFollowingChart.getChart(ps.span, ps.limit, ps.offset ? new Date(ps.offset) : null, ps.userId); }); diff --git a/packages/backend/src/server/api/endpoints/charts/user/notes.ts b/packages/backend/src/server/api/endpoints/charts/user/notes.ts index ecf85becf..7cc6cbf31 100644 --- a/packages/backend/src/server/api/endpoints/charts/user/notes.ts +++ b/packages/backend/src/server/api/endpoints/charts/user/notes.ts @@ -1,36 +1,25 @@ -import $ from 'cafy'; -import define from '../../../define'; -import { ID } from '@/misc/cafy-id'; -import { convertLog } from '@/services/chart/core'; -import { perUserNotesChart } from '@/services/chart/index'; +import define from '../../../define.js'; +import { getJsonSchema } from '@/services/chart/core.js'; +import { perUserNotesChart } from '@/services/chart/index.js'; export const meta = { tags: ['charts', 'users', 'notes'], - params: { - span: { - validator: $.str.or(['day', 'hour']), - }, + res: getJsonSchema(perUserNotesChart.schema), +} as const; - limit: { - validator: $.optional.num.range(1, 500), - default: 30, - }, - - offset: { - validator: $.optional.nullable.num, - default: null, - }, - - userId: { - validator: $.type(ID), - }, +export const paramDef = { + type: 'object', + properties: { + span: { type: 'string', enum: ['day', 'hour'] }, + limit: { type: 'integer', minimum: 1, maximum: 500, default: 30 }, + offset: { type: 'integer', nullable: true, default: null }, + userId: { type: 'string', format: 'misskey:id' }, }, - - // TODO: response definition + required: ['span', 'userId'], } as const; // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps) => { - return await perUserNotesChart.getChart(ps.span as any, ps.limit!, ps.offset ? new Date(ps.offset) : null, ps.userId); +export default define(meta, paramDef, async (ps) => { + return await perUserNotesChart.getChart(ps.span, ps.limit, ps.offset ? new Date(ps.offset) : null, ps.userId); }); diff --git a/packages/backend/src/server/api/endpoints/charts/user/reactions.ts b/packages/backend/src/server/api/endpoints/charts/user/reactions.ts index 6e08d0751..5c58a7f15 100644 --- a/packages/backend/src/server/api/endpoints/charts/user/reactions.ts +++ b/packages/backend/src/server/api/endpoints/charts/user/reactions.ts @@ -1,36 +1,25 @@ -import $ from 'cafy'; -import define from '../../../define'; -import { ID } from '@/misc/cafy-id'; -import { convertLog } from '@/services/chart/core'; -import { perUserReactionsChart } from '@/services/chart/index'; +import define from '../../../define.js'; +import { getJsonSchema } from '@/services/chart/core.js'; +import { perUserReactionsChart } from '@/services/chart/index.js'; export const meta = { tags: ['charts', 'users', 'reactions'], - params: { - span: { - validator: $.str.or(['day', 'hour']), - }, + res: getJsonSchema(perUserReactionsChart.schema), +} as const; - limit: { - validator: $.optional.num.range(1, 500), - default: 30, - }, - - offset: { - validator: $.optional.nullable.num, - default: null, - }, - - userId: { - validator: $.type(ID), - }, +export const paramDef = { + type: 'object', + properties: { + span: { type: 'string', enum: ['day', 'hour'] }, + limit: { type: 'integer', minimum: 1, maximum: 500, default: 30 }, + offset: { type: 'integer', nullable: true, default: null }, + userId: { type: 'string', format: 'misskey:id' }, }, - - // TODO: response definition + required: ['span', 'userId'], } as const; // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps) => { - return await perUserReactionsChart.getChart(ps.span as any, ps.limit!, ps.offset ? new Date(ps.offset) : null, ps.userId); +export default define(meta, paramDef, async (ps) => { + return await perUserReactionsChart.getChart(ps.span, ps.limit, ps.offset ? new Date(ps.offset) : null, ps.userId); }); diff --git a/packages/backend/src/server/api/endpoints/charts/users.ts b/packages/backend/src/server/api/endpoints/charts/users.ts index 15a9ec038..49c762b2e 100644 --- a/packages/backend/src/server/api/endpoints/charts/users.ts +++ b/packages/backend/src/server/api/endpoints/charts/users.ts @@ -1,31 +1,24 @@ -import $ from 'cafy'; -import define from '../../define'; -import { convertLog } from '@/services/chart/core'; -import { usersChart } from '@/services/chart/index'; +import define from '../../define.js'; +import { getJsonSchema } from '@/services/chart/core.js'; +import { usersChart } from '@/services/chart/index.js'; export const meta = { tags: ['charts', 'users'], - params: { - span: { - validator: $.str.or(['day', 'hour']), - }, + res: getJsonSchema(usersChart.schema), +} as const; - limit: { - validator: $.optional.num.range(1, 500), - default: 30, - }, - - offset: { - validator: $.optional.nullable.num, - default: null, - }, +export const paramDef = { + type: 'object', + properties: { + span: { type: 'string', enum: ['day', 'hour'] }, + limit: { type: 'integer', minimum: 1, maximum: 500, default: 30 }, + offset: { type: 'integer', nullable: true, default: null }, }, - - // TODO: response definition + required: ['span'], } as const; // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps) => { - return await usersChart.getChart(ps.span as any, ps.limit!, ps.offset ? new Date(ps.offset) : null); +export default define(meta, paramDef, async (ps) => { + return await usersChart.getChart(ps.span, ps.limit, ps.offset ? new Date(ps.offset) : null); }); diff --git a/packages/backend/src/server/api/endpoints/clips/add-note.ts b/packages/backend/src/server/api/endpoints/clips/add-note.ts index 4a740b6cf..c630302b9 100644 --- a/packages/backend/src/server/api/endpoints/clips/add-note.ts +++ b/packages/backend/src/server/api/endpoints/clips/add-note.ts @@ -1,10 +1,8 @@ -import $ from 'cafy'; -import { ID } from '@/misc/cafy-id'; -import define from '../../define'; -import { ClipNotes, Clips } from '@/models/index'; -import { ApiError } from '../../error'; -import { genId } from '@/misc/gen-id'; -import { getNote } from '../../common/getters'; +import define from '../../define.js'; +import { ClipNotes, Clips } from '@/models/index.js'; +import { ApiError } from '../../error.js'; +import { genId } from '@/misc/gen-id.js'; +import { getNote } from '../../common/getters.js'; export const meta = { tags: ['account', 'notes', 'clips'], @@ -13,16 +11,6 @@ export const meta = { kind: 'write:account', - params: { - clipId: { - validator: $.type(ID), - }, - - noteId: { - validator: $.type(ID), - }, - }, - errors: { noSuchClip: { message: 'No such clip.', @@ -44,8 +32,17 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + clipId: { type: 'string', format: 'misskey:id' }, + noteId: { type: 'string', format: 'misskey:id' }, + }, + required: ['clipId', 'noteId'], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, user) => { +export default define(meta, paramDef, async (ps, user) => { const clip = await Clips.findOne({ id: ps.clipId, userId: user.id, diff --git a/packages/backend/src/server/api/endpoints/clips/create.ts b/packages/backend/src/server/api/endpoints/clips/create.ts index 852e66c9e..531847d15 100644 --- a/packages/backend/src/server/api/endpoints/clips/create.ts +++ b/packages/backend/src/server/api/endpoints/clips/create.ts @@ -1,7 +1,6 @@ -import $ from 'cafy'; -import define from '../../define'; -import { genId } from '@/misc/gen-id'; -import { Clips } from '@/models/index'; +import define from '../../define.js'; +import { genId } from '@/misc/gen-id.js'; +import { Clips } from '@/models/index.js'; export const meta = { tags: ['clips'], @@ -10,20 +9,6 @@ export const meta = { kind: 'write:account', - params: { - name: { - validator: $.str.range(1, 100), - }, - - isPublic: { - validator: $.optional.bool, - }, - - description: { - validator: $.optional.nullable.str.range(1, 2048), - }, - }, - res: { type: 'object', optional: false, nullable: false, @@ -31,8 +16,18 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + name: { type: 'string', minLength: 1, maxLength: 100 }, + isPublic: { type: 'boolean' }, + description: { type: 'string', nullable: true, minLength: 1, maxLength: 2048 }, + }, + required: ['name'], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, user) => { +export default define(meta, paramDef, async (ps, user) => { const clip = await Clips.insert({ id: genId(), createdAt: new Date(), diff --git a/packages/backend/src/server/api/endpoints/clips/delete.ts b/packages/backend/src/server/api/endpoints/clips/delete.ts index 85c64a115..675db1d57 100644 --- a/packages/backend/src/server/api/endpoints/clips/delete.ts +++ b/packages/backend/src/server/api/endpoints/clips/delete.ts @@ -1,8 +1,6 @@ -import $ from 'cafy'; -import { ID } from '@/misc/cafy-id'; -import define from '../../define'; -import { ApiError } from '../../error'; -import { Clips } from '@/models/index'; +import define from '../../define.js'; +import { ApiError } from '../../error.js'; +import { Clips } from '@/models/index.js'; export const meta = { tags: ['clips'], @@ -11,12 +9,6 @@ export const meta = { kind: 'write:account', - params: { - clipId: { - validator: $.type(ID), - }, - }, - errors: { noSuchClip: { message: 'No such clip.', @@ -26,8 +18,16 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + clipId: { type: 'string', format: 'misskey:id' }, + }, + required: ['clipId'], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, user) => { +export default define(meta, paramDef, async (ps, user) => { const clip = await Clips.findOne({ id: ps.clipId, userId: user.id, diff --git a/packages/backend/src/server/api/endpoints/clips/list.ts b/packages/backend/src/server/api/endpoints/clips/list.ts index d88897d16..1c955d64f 100644 --- a/packages/backend/src/server/api/endpoints/clips/list.ts +++ b/packages/backend/src/server/api/endpoints/clips/list.ts @@ -1,5 +1,5 @@ -import define from '../../define'; -import { Clips } from '@/models/index'; +import define from '../../define.js'; +import { Clips } from '@/models/index.js'; export const meta = { tags: ['clips', 'account'], @@ -19,8 +19,14 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: {}, + required: [], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, me) => { +export default define(meta, paramDef, async (ps, me) => { const clips = await Clips.find({ userId: me.id, }); diff --git a/packages/backend/src/server/api/endpoints/clips/notes.ts b/packages/backend/src/server/api/endpoints/clips/notes.ts index eeb20631c..2627884ee 100644 --- a/packages/backend/src/server/api/endpoints/clips/notes.ts +++ b/packages/backend/src/server/api/endpoints/clips/notes.ts @@ -1,12 +1,10 @@ -import $ from 'cafy'; -import { ID } from '@/misc/cafy-id'; -import define from '../../define'; -import { ClipNotes, Clips, Notes } from '@/models/index'; -import { makePaginationQuery } from '../../common/make-pagination-query'; -import { generateVisibilityQuery } from '../../common/generate-visibility-query'; -import { generateMutedUserQuery } from '../../common/generate-muted-user-query'; -import { ApiError } from '../../error'; -import { generateBlockedUserQuery } from '../../common/generate-block-query'; +import define from '../../define.js'; +import { ClipNotes, Clips, Notes } from '@/models/index.js'; +import { makePaginationQuery } from '../../common/make-pagination-query.js'; +import { generateVisibilityQuery } from '../../common/generate-visibility-query.js'; +import { generateMutedUserQuery } from '../../common/generate-muted-user-query.js'; +import { ApiError } from '../../error.js'; +import { generateBlockedUserQuery } from '../../common/generate-block-query.js'; export const meta = { tags: ['account', 'notes', 'clips'], @@ -15,25 +13,6 @@ export const meta = { kind: 'read:account', - params: { - clipId: { - validator: $.type(ID), - }, - - limit: { - validator: $.optional.num.range(1, 100), - default: 10, - }, - - sinceId: { - validator: $.optional.type(ID), - }, - - untilId: { - validator: $.optional.type(ID), - }, - }, - errors: { noSuchClip: { message: 'No such clip.', @@ -53,8 +32,19 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + clipId: { type: 'string', format: 'misskey:id' }, + limit: { type: 'integer', minimum: 1, maximum: 100, default: 10 }, + sinceId: { type: 'string', format: 'misskey:id' }, + untilId: { type: 'string', format: 'misskey:id' }, + }, + required: ['clipId'], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, user) => { +export default define(meta, paramDef, async (ps, user) => { const clip = await Clips.findOne({ id: ps.clipId, }); @@ -74,10 +64,16 @@ export default define(meta, async (ps, user) => { const query = makePaginationQuery(Notes.createQueryBuilder('note'), ps.sinceId, ps.untilId) .andWhere(`note.id IN (${ clipQuery.getQuery() })`) .innerJoinAndSelect('note.user', 'user') + .leftJoinAndSelect('user.avatar', 'avatar') + .leftJoinAndSelect('user.banner', 'banner') .leftJoinAndSelect('note.reply', 'reply') .leftJoinAndSelect('note.renote', 'renote') .leftJoinAndSelect('reply.user', 'replyUser') + .leftJoinAndSelect('replyUser.avatar', 'replyUserAvatar') + .leftJoinAndSelect('replyUser.banner', 'replyUserBanner') .leftJoinAndSelect('renote.user', 'renoteUser') + .leftJoinAndSelect('renoteUser.avatar', 'renoteUserAvatar') + .leftJoinAndSelect('renoteUser.banner', 'renoteUserBanner') .setParameters(clipQuery.getParameters()); if (user) { @@ -87,7 +83,7 @@ export default define(meta, async (ps, user) => { } const notes = await query - .take(ps.limit!) + .take(ps.limit) .getMany(); return await Notes.packMany(notes, user); diff --git a/packages/backend/src/server/api/endpoints/clips/show.ts b/packages/backend/src/server/api/endpoints/clips/show.ts index 0a4567201..0a3b25c94 100644 --- a/packages/backend/src/server/api/endpoints/clips/show.ts +++ b/packages/backend/src/server/api/endpoints/clips/show.ts @@ -1,8 +1,6 @@ -import $ from 'cafy'; -import { ID } from '@/misc/cafy-id'; -import define from '../../define'; -import { ApiError } from '../../error'; -import { Clips } from '@/models/index'; +import define from '../../define.js'; +import { ApiError } from '../../error.js'; +import { Clips } from '@/models/index.js'; export const meta = { tags: ['clips', 'account'], @@ -11,12 +9,6 @@ export const meta = { kind: 'read:account', - params: { - clipId: { - validator: $.type(ID), - }, - }, - errors: { noSuchClip: { message: 'No such clip.', @@ -32,8 +24,16 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + clipId: { type: 'string', format: 'misskey:id' }, + }, + required: ['clipId'], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, me) => { +export default define(meta, paramDef, async (ps, me) => { // Fetch the clip const clip = await Clips.findOne({ id: ps.clipId, diff --git a/packages/backend/src/server/api/endpoints/clips/update.ts b/packages/backend/src/server/api/endpoints/clips/update.ts index 795483d5b..0ac5ccd04 100644 --- a/packages/backend/src/server/api/endpoints/clips/update.ts +++ b/packages/backend/src/server/api/endpoints/clips/update.ts @@ -1,8 +1,6 @@ -import $ from 'cafy'; -import { ID } from '@/misc/cafy-id'; -import define from '../../define'; -import { ApiError } from '../../error'; -import { Clips } from '@/models/index'; +import define from '../../define.js'; +import { ApiError } from '../../error.js'; +import { Clips } from '@/models/index.js'; export const meta = { tags: ['clips'], @@ -11,24 +9,6 @@ export const meta = { kind: 'write:account', - params: { - clipId: { - validator: $.type(ID), - }, - - name: { - validator: $.str.range(1, 100), - }, - - isPublic: { - validator: $.optional.bool, - }, - - description: { - validator: $.optional.nullable.str.range(1, 2048), - }, - }, - errors: { noSuchClip: { message: 'No such clip.', @@ -44,8 +24,19 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + clipId: { type: 'string', format: 'misskey:id' }, + name: { type: 'string', minLength: 1, maxLength: 100 }, + isPublic: { type: 'boolean' }, + description: { type: 'string', nullable: true, minLength: 1, maxLength: 2048 }, + }, + required: ['clipId', 'name'], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, user) => { +export default define(meta, paramDef, async (ps, user) => { // Fetch the clip const clip = await Clips.findOne({ id: ps.clipId, diff --git a/packages/backend/src/server/api/endpoints/drive.ts b/packages/backend/src/server/api/endpoints/drive.ts index d9ab9883c..c599d96ca 100644 --- a/packages/backend/src/server/api/endpoints/drive.ts +++ b/packages/backend/src/server/api/endpoints/drive.ts @@ -1,6 +1,6 @@ -import define from '../define'; -import { fetchMeta } from '@/misc/fetch-meta'; -import { DriveFiles } from '@/models/index'; +import define from '../define.js'; +import { fetchMeta } from '@/misc/fetch-meta.js'; +import { DriveFiles } from '@/models/index.js'; export const meta = { tags: ['drive', 'account'], @@ -25,8 +25,14 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: {}, + required: [], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, user) => { +export default define(meta, paramDef, async (ps, user) => { const instance = await fetchMeta(true); // Calculate drive usage diff --git a/packages/backend/src/server/api/endpoints/drive/files.ts b/packages/backend/src/server/api/endpoints/drive/files.ts index a5c0a626a..40e6c16c9 100644 --- a/packages/backend/src/server/api/endpoints/drive/files.ts +++ b/packages/backend/src/server/api/endpoints/drive/files.ts @@ -1,8 +1,6 @@ -import $ from 'cafy'; -import { ID } from '@/misc/cafy-id'; -import define from '../../define'; -import { DriveFiles } from '@/models/index'; -import { makePaginationQuery } from '../../common/make-pagination-query'; +import define from '../../define.js'; +import { DriveFiles } from '@/models/index.js'; +import { makePaginationQuery } from '../../common/make-pagination-query.js'; export const meta = { tags: ['drive'], @@ -11,30 +9,6 @@ export const meta = { kind: 'read:drive', - params: { - limit: { - validator: $.optional.num.range(1, 100), - default: 10, - }, - - sinceId: { - validator: $.optional.type(ID), - }, - - untilId: { - validator: $.optional.type(ID), - }, - - folderId: { - validator: $.optional.nullable.type(ID), - default: null, - }, - - type: { - validator: $.optional.nullable.str.match(/^[a-zA-Z\/\-*]+$/), - }, - }, - res: { type: 'array', optional: false, nullable: false, @@ -46,8 +20,20 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + limit: { type: 'integer', minimum: 1, maximum: 100, default: 10 }, + sinceId: { type: 'string', format: 'misskey:id' }, + untilId: { type: 'string', format: 'misskey:id' }, + folderId: { type: 'string', format: 'misskey:id', nullable: true, default: null }, + type: { type: 'string', nullable: true, pattern: /^[a-zA-Z\/\-*]+$/.toString().slice(1, -1) }, + }, + required: [], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, user) => { +export default define(meta, paramDef, async (ps, user) => { const query = makePaginationQuery(DriveFiles.createQueryBuilder('file'), ps.sinceId, ps.untilId) .andWhere('file.userId = :userId', { userId: user.id }); @@ -65,7 +51,7 @@ export default define(meta, async (ps, user) => { } } - const files = await query.take(ps.limit!).getMany(); + const files = await query.take(ps.limit).getMany(); return await DriveFiles.packMany(files, { detail: false, self: true }); }); diff --git a/packages/backend/src/server/api/endpoints/drive/files/attached-notes.ts b/packages/backend/src/server/api/endpoints/drive/files/attached-notes.ts index 835dde805..3c68beee1 100644 --- a/packages/backend/src/server/api/endpoints/drive/files/attached-notes.ts +++ b/packages/backend/src/server/api/endpoints/drive/files/attached-notes.ts @@ -1,8 +1,6 @@ -import $ from 'cafy'; -import { ID } from '@/misc/cafy-id'; -import define from '../../../define'; -import { ApiError } from '../../../error'; -import { DriveFiles, Notes } from '@/models/index'; +import define from '../../../define.js'; +import { ApiError } from '../../../error.js'; +import { DriveFiles, Notes } from '@/models/index.js'; export const meta = { tags: ['drive', 'notes'], @@ -11,12 +9,6 @@ export const meta = { kind: 'read:drive', - params: { - fileId: { - validator: $.type(ID), - }, - }, - res: { type: 'array', optional: false, nullable: false, @@ -36,8 +28,16 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + fileId: { type: 'string', format: 'misskey:id' }, + }, + required: ['fileId'], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, user) => { +export default define(meta, paramDef, async (ps, user) => { // Fetch file const file = await DriveFiles.findOne({ id: ps.fileId, diff --git a/packages/backend/src/server/api/endpoints/drive/files/check-existence.ts b/packages/backend/src/server/api/endpoints/drive/files/check-existence.ts index a45d357ee..7e5cb2498 100644 --- a/packages/backend/src/server/api/endpoints/drive/files/check-existence.ts +++ b/packages/backend/src/server/api/endpoints/drive/files/check-existence.ts @@ -1,6 +1,5 @@ -import $ from 'cafy'; -import define from '../../../define'; -import { DriveFiles } from '@/models/index'; +import define from '../../../define.js'; +import { DriveFiles } from '@/models/index.js'; export const meta = { tags: ['drive'], @@ -9,20 +8,22 @@ export const meta = { kind: 'read:drive', - params: { - md5: { - validator: $.str, - }, - }, - res: { type: 'boolean', optional: false, nullable: false, }, } as const; +export const paramDef = { + type: 'object', + properties: { + md5: { type: 'string' }, + }, + required: ['md5'], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, user) => { +export default define(meta, paramDef, async (ps, user) => { const file = await DriveFiles.findOne({ md5: ps.md5, userId: user.id, diff --git a/packages/backend/src/server/api/endpoints/drive/files/create.ts b/packages/backend/src/server/api/endpoints/drive/files/create.ts index ac7863ec7..b6a2cf720 100644 --- a/packages/backend/src/server/api/endpoints/drive/files/create.ts +++ b/packages/backend/src/server/api/endpoints/drive/files/create.ts @@ -1,12 +1,10 @@ import ms from 'ms'; -import $ from 'cafy'; -import { ID } from '@/misc/cafy-id'; -import { addFile } from '@/services/drive/add-file'; -import define from '../../../define'; -import { apiLogger } from '../../../logger'; -import { ApiError } from '../../../error'; -import { DriveFiles } from '@/models/index'; -import { DB_MAX_IMAGE_COMMENT_LENGTH } from '@/misc/hard-limits'; +import { addFile } from '@/services/drive/add-file.js'; +import define from '../../../define.js'; +import { apiLogger } from '../../../logger.js'; +import { ApiError } from '../../../error.js'; +import { DriveFiles } from '@/models/index.js'; +import { DB_MAX_IMAGE_COMMENT_LENGTH } from '@/misc/hard-limits.js'; export const meta = { tags: ['drive'], @@ -22,33 +20,6 @@ export const meta = { kind: 'write:drive', - params: { - folderId: { - validator: $.optional.nullable.type(ID), - default: null, - }, - - name: { - validator: $.optional.nullable.str, - default: null, - }, - - comment: { - validator: $.optional.nullable.str.max(DB_MAX_IMAGE_COMMENT_LENGTH), - default: null, - }, - - isSensitive: { - validator: $.optional.bool, - default: false, - }, - - force: { - validator: $.optional.bool, - default: false, - }, - }, - res: { type: 'object', optional: false, nullable: false, @@ -64,8 +35,21 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + folderId: { type: 'string', format: 'misskey:id', nullable: true, default: null }, + name: { type: 'string', nullable: true, default: null }, + comment: { type: 'string', nullable: true, maxLength: DB_MAX_IMAGE_COMMENT_LENGTH, default: null }, + isSensitive: { type: 'boolean', default: false }, + force: { type: 'boolean', default: false }, + }, + required: [], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, user, _, file, cleanup) => { +// @ts-ignore +export default define(meta, paramDef, async (ps, user, _, file, cleanup) => { // Get 'name' parameter let name = ps.name || file.originalname; if (name !== undefined && name !== null) { diff --git a/packages/backend/src/server/api/endpoints/drive/files/delete.ts b/packages/backend/src/server/api/endpoints/drive/files/delete.ts index 308beb58a..5f565a63f 100644 --- a/packages/backend/src/server/api/endpoints/drive/files/delete.ts +++ b/packages/backend/src/server/api/endpoints/drive/files/delete.ts @@ -1,10 +1,8 @@ -import $ from 'cafy'; -import { ID } from '@/misc/cafy-id'; -import { deleteFile } from '@/services/drive/delete-file'; -import { publishDriveStream } from '@/services/stream'; -import define from '../../../define'; -import { ApiError } from '../../../error'; -import { DriveFiles } from '@/models/index'; +import { deleteFile } from '@/services/drive/delete-file.js'; +import { publishDriveStream } from '@/services/stream.js'; +import define from '../../../define.js'; +import { ApiError } from '../../../error.js'; +import { DriveFiles } from '@/models/index.js'; export const meta = { tags: ['drive'], @@ -13,12 +11,6 @@ export const meta = { kind: 'write:drive', - params: { - fileId: { - validator: $.type(ID), - }, - }, - errors: { noSuchFile: { message: 'No such file.', @@ -34,8 +26,16 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + fileId: { type: 'string', format: 'misskey:id' }, + }, + required: ['fileId'], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, user) => { +export default define(meta, paramDef, async (ps, user) => { const file = await DriveFiles.findOne(ps.fileId); if (file == null) { diff --git a/packages/backend/src/server/api/endpoints/drive/files/find-by-hash.ts b/packages/backend/src/server/api/endpoints/drive/files/find-by-hash.ts index dc74dcb7e..e45ec633d 100644 --- a/packages/backend/src/server/api/endpoints/drive/files/find-by-hash.ts +++ b/packages/backend/src/server/api/endpoints/drive/files/find-by-hash.ts @@ -1,6 +1,5 @@ -import $ from 'cafy'; -import define from '../../../define'; -import { DriveFiles } from '@/models/index'; +import define from '../../../define.js'; +import { DriveFiles } from '@/models/index.js'; export const meta = { tags: ['drive'], @@ -9,12 +8,6 @@ export const meta = { kind: 'read:drive', - params: { - md5: { - validator: $.str, - }, - }, - res: { type: 'array', optional: false, nullable: false, @@ -26,8 +19,16 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + md5: { type: 'string' }, + }, + required: ['md5'], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, user) => { +export default define(meta, paramDef, async (ps, user) => { const files = await DriveFiles.find({ md5: ps.md5, userId: user.id, diff --git a/packages/backend/src/server/api/endpoints/drive/files/find.ts b/packages/backend/src/server/api/endpoints/drive/files/find.ts index 2244df13c..974fc9fba 100644 --- a/packages/backend/src/server/api/endpoints/drive/files/find.ts +++ b/packages/backend/src/server/api/endpoints/drive/files/find.ts @@ -1,7 +1,5 @@ -import $ from 'cafy'; -import { ID } from '@/misc/cafy-id'; -import define from '../../../define'; -import { DriveFiles } from '@/models/index'; +import define from '../../../define.js'; +import { DriveFiles } from '@/models/index.js'; export const meta = { requireCredential: true, @@ -10,17 +8,6 @@ export const meta = { kind: 'read:drive', - params: { - name: { - validator: $.str, - }, - - folderId: { - validator: $.optional.nullable.type(ID), - default: null, - }, - }, - res: { type: 'array', optional: false, nullable: false, @@ -32,8 +19,17 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + name: { type: 'string' }, + folderId: { type: 'string', format: 'misskey:id', nullable: true, default: null }, + }, + required: ['name'], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, user) => { +export default define(meta, paramDef, async (ps, user) => { const files = await DriveFiles.find({ name: ps.name, userId: user.id, diff --git a/packages/backend/src/server/api/endpoints/drive/files/show.ts b/packages/backend/src/server/api/endpoints/drive/files/show.ts index 18b17c465..181365c7e 100644 --- a/packages/backend/src/server/api/endpoints/drive/files/show.ts +++ b/packages/backend/src/server/api/endpoints/drive/files/show.ts @@ -1,9 +1,7 @@ -import $ from 'cafy'; -import { ID } from '@/misc/cafy-id'; -import define from '../../../define'; -import { ApiError } from '../../../error'; -import { DriveFile } from '@/models/entities/drive-file'; -import { DriveFiles } from '@/models/index'; +import define from '../../../define.js'; +import { ApiError } from '../../../error.js'; +import { DriveFile } from '@/models/entities/drive-file.js'; +import { DriveFiles } from '@/models/index.js'; export const meta = { tags: ['drive'], @@ -12,16 +10,6 @@ export const meta = { kind: 'read:drive', - params: { - fileId: { - validator: $.optional.type(ID), - }, - - url: { - validator: $.optional.str, - }, - }, - res: { type: 'object', optional: false, nullable: false, @@ -49,8 +37,17 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + fileId: { type: 'string', format: 'misskey:id' }, + url: { type: 'string' }, + }, + required: [], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, user) => { +export default define(meta, paramDef, async (ps, user) => { let file: DriveFile | undefined; if (ps.fileId) { diff --git a/packages/backend/src/server/api/endpoints/drive/files/update.ts b/packages/backend/src/server/api/endpoints/drive/files/update.ts index b7ca80e83..ab8e4aeeb 100644 --- a/packages/backend/src/server/api/endpoints/drive/files/update.ts +++ b/packages/backend/src/server/api/endpoints/drive/files/update.ts @@ -1,10 +1,8 @@ -import $ from 'cafy'; -import { ID } from '@/misc/cafy-id'; -import { publishDriveStream } from '@/services/stream'; -import define from '../../../define'; -import { ApiError } from '../../../error'; -import { DriveFiles, DriveFolders } from '@/models/index'; -import { DB_MAX_IMAGE_COMMENT_LENGTH } from '@/misc/hard-limits'; +import { publishDriveStream } from '@/services/stream.js'; +import define from '../../../define.js'; +import { ApiError } from '../../../error.js'; +import { DriveFiles, DriveFolders } from '@/models/index.js'; +import { DB_MAX_IMAGE_COMMENT_LENGTH } from '@/misc/hard-limits.js'; export const meta = { tags: ['drive'], @@ -13,33 +11,13 @@ export const meta = { kind: 'write:drive', - params: { - fileId: { - validator: $.type(ID), - }, - - folderId: { - validator: $.optional.nullable.type(ID), - default: undefined as any, - }, - - name: { - validator: $.optional.str.pipe(DriveFiles.validateFileName), - default: undefined as any, - }, - - isSensitive: { - validator: $.optional.bool, - default: undefined as any, - }, - - comment: { - validator: $.optional.nullable.str.max(DB_MAX_IMAGE_COMMENT_LENGTH), - default: undefined as any, - }, - }, - errors: { + invalidFileName: { + message: 'Invalid file name.', + code: 'INVALID_FILE_NAME', + id: '395e7156-f9f0-475e-af89-53c3c23080c2', + }, + noSuchFile: { message: 'No such file.', code: 'NO_SUCH_FILE', @@ -66,8 +44,20 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + fileId: { type: 'string', format: 'misskey:id' }, + folderId: { type: 'string', format: 'misskey:id', nullable: true }, + name: { type: 'string' }, + isSensitive: { type: 'boolean' }, + comment: { type: 'string', nullable: true, maxLength: 512 }, + }, + required: ['fileId'], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, user) => { +export default define(meta, paramDef, async (ps, user) => { const file = await DriveFiles.findOne(ps.fileId); if (file == null) { @@ -79,6 +69,9 @@ export default define(meta, async (ps, user) => { } if (ps.name) file.name = ps.name; + if (!DriveFiles.validateFileName(file.name)) { + throw new ApiError(meta.errors.invalidFileName); + } if (ps.comment !== undefined) file.comment = ps.comment; diff --git a/packages/backend/src/server/api/endpoints/drive/files/upload-from-url.ts b/packages/backend/src/server/api/endpoints/drive/files/upload-from-url.ts index 40da1a4fb..3bfecac80 100644 --- a/packages/backend/src/server/api/endpoints/drive/files/upload-from-url.ts +++ b/packages/backend/src/server/api/endpoints/drive/files/upload-from-url.ts @@ -1,11 +1,9 @@ -import $ from 'cafy'; -import { ID } from '@/misc/cafy-id'; import ms from 'ms'; -import { uploadFromUrl } from '@/services/drive/upload-from-url'; -import define from '../../../define'; -import { DriveFiles } from '@/models/index'; -import { publishMainStream } from '@/services/stream'; -import { DB_MAX_IMAGE_COMMENT_LENGTH } from '@/misc/hard-limits'; +import { uploadFromUrl } from '@/services/drive/upload-from-url.js'; +import define from '../../../define.js'; +import { DriveFiles } from '@/models/index.js'; +import { publishMainStream } from '@/services/stream.js'; +import { DB_MAX_IMAGE_COMMENT_LENGTH } from '@/misc/hard-limits.js'; export const meta = { tags: ['drive'], @@ -18,42 +16,23 @@ export const meta = { requireCredential: true, kind: 'write:drive', +} as const; - params: { - url: { - // TODO: Validate this url - validator: $.str, - }, - - folderId: { - validator: $.optional.nullable.type(ID), - default: null, - }, - - isSensitive: { - validator: $.optional.bool, - default: false, - }, - - comment: { - validator: $.optional.nullable.str.max(DB_MAX_IMAGE_COMMENT_LENGTH), - default: null, - }, - - marker: { - validator: $.optional.nullable.str, - default: null, - }, - - force: { - validator: $.optional.bool, - default: false, - }, +export const paramDef = { + type: 'object', + properties: { + url: { type: 'string' }, + folderId: { type: 'string', format: 'misskey:id', nullable: true, default: null }, + isSensitive: { type: 'boolean', default: false }, + comment: { type: 'string', nullable: true, maxLength: 512, default: null }, + marker: { type: 'string', nullable: true, default: null }, + force: { type: 'boolean', default: false }, }, + required: ['url'], } as const; // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, user) => { +export default define(meta, paramDef, async (ps, user) => { uploadFromUrl({ url: ps.url, user, folderId: ps.folderId, sensitive: ps.isSensitive, force: ps.force, comment: ps.comment }).then(file => { DriveFiles.pack(file, { self: true }).then(packedFile => { publishMainStream(user.id, 'urlUploadFinished', { diff --git a/packages/backend/src/server/api/endpoints/drive/folders.ts b/packages/backend/src/server/api/endpoints/drive/folders.ts index 8f8d1d2c0..d4d530ba9 100644 --- a/packages/backend/src/server/api/endpoints/drive/folders.ts +++ b/packages/backend/src/server/api/endpoints/drive/folders.ts @@ -1,8 +1,6 @@ -import $ from 'cafy'; -import { ID } from '@/misc/cafy-id'; -import define from '../../define'; -import { DriveFolders } from '@/models/index'; -import { makePaginationQuery } from '../../common/make-pagination-query'; +import define from '../../define.js'; +import { DriveFolders } from '@/models/index.js'; +import { makePaginationQuery } from '../../common/make-pagination-query.js'; export const meta = { tags: ['drive'], @@ -11,26 +9,6 @@ export const meta = { kind: 'read:drive', - params: { - limit: { - validator: $.optional.num.range(1, 100), - default: 10, - }, - - sinceId: { - validator: $.optional.type(ID), - }, - - untilId: { - validator: $.optional.type(ID), - }, - - folderId: { - validator: $.optional.nullable.type(ID), - default: null, - }, - }, - res: { type: 'array', optional: false, nullable: false, @@ -42,8 +20,19 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + limit: { type: 'integer', minimum: 1, maximum: 100, default: 10 }, + sinceId: { type: 'string', format: 'misskey:id' }, + untilId: { type: 'string', format: 'misskey:id' }, + folderId: { type: 'string', format: 'misskey:id', nullable: true, default: null }, + }, + required: [], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, user) => { +export default define(meta, paramDef, async (ps, user) => { const query = makePaginationQuery(DriveFolders.createQueryBuilder('folder'), ps.sinceId, ps.untilId) .andWhere('folder.userId = :userId', { userId: user.id }); @@ -53,7 +42,7 @@ export default define(meta, async (ps, user) => { query.andWhere('folder.parentId IS NULL'); } - const folders = await query.take(ps.limit!).getMany(); + const folders = await query.take(ps.limit).getMany(); return await Promise.all(folders.map(folder => DriveFolders.pack(folder))); }); diff --git a/packages/backend/src/server/api/endpoints/drive/folders/create.ts b/packages/backend/src/server/api/endpoints/drive/folders/create.ts index 38ed17e0e..4ae10f062 100644 --- a/packages/backend/src/server/api/endpoints/drive/folders/create.ts +++ b/packages/backend/src/server/api/endpoints/drive/folders/create.ts @@ -1,10 +1,8 @@ -import $ from 'cafy'; -import { ID } from '@/misc/cafy-id'; -import { publishDriveStream } from '@/services/stream'; -import define from '../../../define'; -import { ApiError } from '../../../error'; -import { DriveFolders } from '@/models/index'; -import { genId } from '@/misc/gen-id'; +import { publishDriveStream } from '@/services/stream.js'; +import define from '../../../define.js'; +import { ApiError } from '../../../error.js'; +import { DriveFolders } from '@/models/index.js'; +import { genId } from '@/misc/gen-id.js'; export const meta = { tags: ['drive'], @@ -13,17 +11,6 @@ export const meta = { kind: 'write:drive', - params: { - name: { - validator: $.optional.str.pipe(DriveFolders.validateFolderName), - default: 'Untitled', - }, - - parentId: { - validator: $.optional.nullable.type(ID), - }, - }, - errors: { noSuchFolder: { message: 'No such folder.', @@ -39,8 +26,17 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + name: { type: 'string', default: "Untitled", maxLength: 200 }, + parentId: { type: 'string', format: 'misskey:id', nullable: true }, + }, + required: [], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, user) => { +export default define(meta, paramDef, async (ps, user) => { // If the parent folder is specified let parent = null; if (ps.parentId) { diff --git a/packages/backend/src/server/api/endpoints/drive/folders/delete.ts b/packages/backend/src/server/api/endpoints/drive/folders/delete.ts index 13716fcce..4994615cc 100644 --- a/packages/backend/src/server/api/endpoints/drive/folders/delete.ts +++ b/packages/backend/src/server/api/endpoints/drive/folders/delete.ts @@ -1,9 +1,7 @@ -import $ from 'cafy'; -import { ID } from '@/misc/cafy-id'; -import define from '../../../define'; -import { publishDriveStream } from '@/services/stream'; -import { ApiError } from '../../../error'; -import { DriveFolders, DriveFiles } from '@/models/index'; +import define from '../../../define.js'; +import { publishDriveStream } from '@/services/stream.js'; +import { ApiError } from '../../../error.js'; +import { DriveFolders, DriveFiles } from '@/models/index.js'; export const meta = { tags: ['drive'], @@ -12,12 +10,6 @@ export const meta = { kind: 'write:drive', - params: { - folderId: { - validator: $.type(ID), - }, - }, - errors: { noSuchFolder: { message: 'No such folder.', @@ -33,8 +25,16 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + folderId: { type: 'string', format: 'misskey:id' }, + }, + required: ['folderId'], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, user) => { +export default define(meta, paramDef, async (ps, user) => { // Get folder const folder = await DriveFolders.findOne({ id: ps.folderId, diff --git a/packages/backend/src/server/api/endpoints/drive/folders/find.ts b/packages/backend/src/server/api/endpoints/drive/folders/find.ts index 911f51d78..9bf0e3d61 100644 --- a/packages/backend/src/server/api/endpoints/drive/folders/find.ts +++ b/packages/backend/src/server/api/endpoints/drive/folders/find.ts @@ -1,7 +1,5 @@ -import $ from 'cafy'; -import { ID } from '@/misc/cafy-id'; -import define from '../../../define'; -import { DriveFolders } from '@/models/index'; +import define from '../../../define.js'; +import { DriveFolders } from '@/models/index.js'; export const meta = { tags: ['drive'], @@ -10,17 +8,6 @@ export const meta = { kind: 'read:drive', - params: { - name: { - validator: $.str, - }, - - parentId: { - validator: $.optional.nullable.type(ID), - default: null, - }, - }, - res: { type: 'array', optional: false, nullable: false, @@ -32,8 +19,17 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + name: { type: 'string' }, + parentId: { type: 'string', format: 'misskey:id', nullable: true, default: null }, + }, + required: ['name'], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, user) => { +export default define(meta, paramDef, async (ps, user) => { const folders = await DriveFolders.find({ name: ps.name, userId: user.id, diff --git a/packages/backend/src/server/api/endpoints/drive/folders/show.ts b/packages/backend/src/server/api/endpoints/drive/folders/show.ts index 58a6dd3c0..f09816d57 100644 --- a/packages/backend/src/server/api/endpoints/drive/folders/show.ts +++ b/packages/backend/src/server/api/endpoints/drive/folders/show.ts @@ -1,8 +1,6 @@ -import $ from 'cafy'; -import { ID } from '@/misc/cafy-id'; -import define from '../../../define'; -import { ApiError } from '../../../error'; -import { DriveFolders } from '@/models/index'; +import define from '../../../define.js'; +import { ApiError } from '../../../error.js'; +import { DriveFolders } from '@/models/index.js'; export const meta = { tags: ['drive'], @@ -11,12 +9,6 @@ export const meta = { kind: 'read:drive', - params: { - folderId: { - validator: $.type(ID), - }, - }, - res: { type: 'object', optional: false, nullable: false, @@ -32,8 +24,16 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + folderId: { type: 'string', format: 'misskey:id' }, + }, + required: ['folderId'], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, user) => { +export default define(meta, paramDef, async (ps, user) => { // Get folder const folder = await DriveFolders.findOne({ id: ps.folderId, diff --git a/packages/backend/src/server/api/endpoints/drive/folders/update.ts b/packages/backend/src/server/api/endpoints/drive/folders/update.ts index 5b0cccd1c..c020b243e 100644 --- a/packages/backend/src/server/api/endpoints/drive/folders/update.ts +++ b/packages/backend/src/server/api/endpoints/drive/folders/update.ts @@ -1,9 +1,7 @@ -import $ from 'cafy'; -import { ID } from '@/misc/cafy-id'; -import { publishDriveStream } from '@/services/stream'; -import define from '../../../define'; -import { ApiError } from '../../../error'; -import { DriveFolders } from '@/models/index'; +import { publishDriveStream } from '@/services/stream.js'; +import define from '../../../define.js'; +import { ApiError } from '../../../error.js'; +import { DriveFolders } from '@/models/index.js'; export const meta = { tags: ['drive'], @@ -12,20 +10,6 @@ export const meta = { kind: 'write:drive', - params: { - folderId: { - validator: $.type(ID), - }, - - name: { - validator: $.optional.str.pipe(DriveFolders.validateFolderName), - }, - - parentId: { - validator: $.optional.nullable.type(ID), - }, - }, - errors: { noSuchFolder: { message: 'No such folder.', @@ -53,8 +37,18 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + folderId: { type: 'string', format: 'misskey:id' }, + name: { type: 'string', maxLength: 200 }, + parentId: { type: 'string', format: 'misskey:id', nullable: true }, + }, + required: ['folderId'], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, user) => { +export default define(meta, paramDef, async (ps, user) => { // Fetch folder const folder = await DriveFolders.findOne({ id: ps.folderId, diff --git a/packages/backend/src/server/api/endpoints/drive/stream.ts b/packages/backend/src/server/api/endpoints/drive/stream.ts index 9ba780494..99e8d024f 100644 --- a/packages/backend/src/server/api/endpoints/drive/stream.ts +++ b/packages/backend/src/server/api/endpoints/drive/stream.ts @@ -1,8 +1,6 @@ -import $ from 'cafy'; -import { ID } from '@/misc/cafy-id'; -import define from '../../define'; -import { DriveFiles } from '@/models/index'; -import { makePaginationQuery } from '../../common/make-pagination-query'; +import define from '../../define.js'; +import { DriveFiles } from '@/models/index.js'; +import { makePaginationQuery } from '../../common/make-pagination-query.js'; export const meta = { tags: ['drive'], @@ -11,25 +9,6 @@ export const meta = { kind: 'read:drive', - params: { - limit: { - validator: $.optional.num.range(1, 100), - default: 10, - }, - - sinceId: { - validator: $.optional.type(ID), - }, - - untilId: { - validator: $.optional.type(ID), - }, - - type: { - validator: $.optional.str.match(/^[a-zA-Z\/\-*]+$/), - }, - }, - res: { type: 'array', optional: false, nullable: false, @@ -41,8 +20,19 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + limit: { type: 'integer', minimum: 1, maximum: 100, default: 10 }, + sinceId: { type: 'string', format: 'misskey:id' }, + untilId: { type: 'string', format: 'misskey:id' }, + type: { type: 'string', pattern: /^[a-zA-Z\/\-*]+$/.toString().slice(1, -1) }, + }, + required: [], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, user) => { +export default define(meta, paramDef, async (ps, user) => { const query = makePaginationQuery(DriveFiles.createQueryBuilder('file'), ps.sinceId, ps.untilId) .andWhere('file.userId = :userId', { userId: user.id }); @@ -54,7 +44,7 @@ export default define(meta, async (ps, user) => { } } - const files = await query.take(ps.limit!).getMany(); + const files = await query.take(ps.limit).getMany(); return await DriveFiles.packMany(files, { detail: false, self: true }); }); diff --git a/packages/backend/src/server/api/endpoints/email-address/available.ts b/packages/backend/src/server/api/endpoints/email-address/available.ts index 19f9b7ccd..07064ce9f 100644 --- a/packages/backend/src/server/api/endpoints/email-address/available.ts +++ b/packages/backend/src/server/api/endpoints/email-address/available.ts @@ -1,18 +1,11 @@ -import $ from 'cafy'; -import define from '../../define'; -import { validateEmailForAccount } from '@/services/validate-email-for-account'; +import define from '../../define.js'; +import { validateEmailForAccount } from '@/services/validate-email-for-account.js'; export const meta = { tags: ['users'], requireCredential: false, - params: { - emailAddress: { - validator: $.str, - }, - }, - res: { type: 'object', optional: false, nullable: false, @@ -29,7 +22,15 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + emailAddress: { type: 'string' }, + }, + required: ['emailAddress'], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps) => { +export default define(meta, paramDef, async (ps) => { return await validateEmailForAccount(ps.emailAddress); }); diff --git a/packages/backend/src/server/api/endpoints/endpoint.ts b/packages/backend/src/server/api/endpoints/endpoint.ts index 42fd46883..9db140183 100644 --- a/packages/backend/src/server/api/endpoints/endpoint.ts +++ b/packages/backend/src/server/api/endpoints/endpoint.ts @@ -1,21 +1,22 @@ -import $ from 'cafy'; -import define from '../define'; -import endpoints from '../endpoints'; +import define from '../define.js'; +import endpoints from '../endpoints.js'; export const meta = { requireCredential: false, tags: ['meta'], +} as const; - params: { - endpoint: { - validator: $.str, - }, +export const paramDef = { + type: 'object', + properties: { + endpoint: { type: 'string' }, }, + required: ['endpoint'], } as const; // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps) => { +export default define(meta, paramDef, async (ps) => { const ep = endpoints.find(x => x.name === ps.endpoint); if (ep == null) return null; return { diff --git a/packages/backend/src/server/api/endpoints/endpoints.ts b/packages/backend/src/server/api/endpoints/endpoints.ts index ebb78de33..b20da96eb 100644 --- a/packages/backend/src/server/api/endpoints/endpoints.ts +++ b/packages/backend/src/server/api/endpoints/endpoints.ts @@ -1,14 +1,11 @@ -import define from '../define'; -import endpoints from '../endpoints'; +import define from '../define.js'; +import endpoints from '../endpoints.js'; export const meta = { requireCredential: false, tags: ['meta'], - params: { - }, - res: { type: 'array', optional: false, nullable: false, @@ -25,7 +22,13 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: {}, + required: [], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async () => { +export default define(meta, paramDef, async () => { return endpoints.map(x => x.name); }); diff --git a/packages/backend/src/server/api/endpoints/export-custom-emojis.ts b/packages/backend/src/server/api/endpoints/export-custom-emojis.ts index 24c9f56aa..bc8d2e2ac 100644 --- a/packages/backend/src/server/api/endpoints/export-custom-emojis.ts +++ b/packages/backend/src/server/api/endpoints/export-custom-emojis.ts @@ -1,6 +1,5 @@ -import $ from 'cafy'; -import define from '../define'; -import { createExportCustomEmojisJob } from '@/queue/index'; +import define from '../define.js'; +import { createExportCustomEmojisJob } from '@/queue/index.js'; import ms from 'ms'; export const meta = { @@ -12,7 +11,13 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: {}, + required: [], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, user) => { +export default define(meta, paramDef, async (ps, user) => { createExportCustomEmojisJob(user); }); diff --git a/packages/backend/src/server/api/endpoints/federation/followers.ts b/packages/backend/src/server/api/endpoints/federation/followers.ts index c0a85f166..7b1197d1e 100644 --- a/packages/backend/src/server/api/endpoints/federation/followers.ts +++ b/packages/backend/src/server/api/endpoints/federation/followers.ts @@ -1,33 +1,12 @@ -import $ from 'cafy'; -import { ID } from '@/misc/cafy-id'; -import define from '../../define'; -import { Followings } from '@/models/index'; -import { makePaginationQuery } from '../../common/make-pagination-query'; +import define from '../../define.js'; +import { Followings } from '@/models/index.js'; +import { makePaginationQuery } from '../../common/make-pagination-query.js'; export const meta = { tags: ['federation'], requireCredential: false, - params: { - host: { - validator: $.str, - }, - - sinceId: { - validator: $.optional.type(ID), - }, - - untilId: { - validator: $.optional.type(ID), - }, - - limit: { - validator: $.optional.num.range(1, 100), - default: 10, - }, - }, - res: { type: 'array', optional: false, nullable: false, @@ -39,13 +18,24 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + host: { type: 'string' }, + sinceId: { type: 'string', format: 'misskey:id' }, + untilId: { type: 'string', format: 'misskey:id' }, + limit: { type: 'integer', minimum: 1, maximum: 100, default: 10 }, + }, + required: ['host'], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, me) => { +export default define(meta, paramDef, async (ps, me) => { const query = makePaginationQuery(Followings.createQueryBuilder('following'), ps.sinceId, ps.untilId) .andWhere(`following.followeeHost = :host`, { host: ps.host }); const followings = await query - .take(ps.limit!) + .take(ps.limit) .getMany(); return await Followings.packMany(followings, me, { populateFollowee: true }); diff --git a/packages/backend/src/server/api/endpoints/federation/following.ts b/packages/backend/src/server/api/endpoints/federation/following.ts index 147f0aedb..ed1f142d8 100644 --- a/packages/backend/src/server/api/endpoints/federation/following.ts +++ b/packages/backend/src/server/api/endpoints/federation/following.ts @@ -1,33 +1,12 @@ -import $ from 'cafy'; -import { ID } from '@/misc/cafy-id'; -import define from '../../define'; -import { Followings } from '@/models/index'; -import { makePaginationQuery } from '../../common/make-pagination-query'; +import define from '../../define.js'; +import { Followings } from '@/models/index.js'; +import { makePaginationQuery } from '../../common/make-pagination-query.js'; export const meta = { tags: ['federation'], requireCredential: false, - params: { - host: { - validator: $.str, - }, - - sinceId: { - validator: $.optional.type(ID), - }, - - untilId: { - validator: $.optional.type(ID), - }, - - limit: { - validator: $.optional.num.range(1, 100), - default: 10, - }, - }, - res: { type: 'array', optional: false, nullable: false, @@ -39,13 +18,24 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + host: { type: 'string' }, + sinceId: { type: 'string', format: 'misskey:id' }, + untilId: { type: 'string', format: 'misskey:id' }, + limit: { type: 'integer', minimum: 1, maximum: 100, default: 10 }, + }, + required: ['host'], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, me) => { +export default define(meta, paramDef, async (ps, me) => { const query = makePaginationQuery(Followings.createQueryBuilder('following'), ps.sinceId, ps.untilId) .andWhere(`following.followerHost = :host`, { host: ps.host }); const followings = await query - .take(ps.limit!) + .take(ps.limit) .getMany(); return await Followings.packMany(followings, me, { populateFollowee: true }); diff --git a/packages/backend/src/server/api/endpoints/federation/instances.ts b/packages/backend/src/server/api/endpoints/federation/instances.ts index 11df7ed6b..e27297176 100644 --- a/packages/backend/src/server/api/endpoints/federation/instances.ts +++ b/packages/backend/src/server/api/endpoints/federation/instances.ts @@ -1,58 +1,13 @@ -import $ from 'cafy'; -import config from '@/config/index'; -import define from '../../define'; -import { Instances } from '@/models/index'; -import { fetchMeta } from '@/misc/fetch-meta'; +import config from '@/config/index.js'; +import define from '../../define.js'; +import { Instances } from '@/models/index.js'; +import { fetchMeta } from '@/misc/fetch-meta.js'; export const meta = { tags: ['federation'], requireCredential: false, - params: { - host: { - validator: $.optional.nullable.str, - }, - - blocked: { - validator: $.optional.nullable.bool, - }, - - notResponding: { - validator: $.optional.nullable.bool, - }, - - suspended: { - validator: $.optional.nullable.bool, - }, - - federating: { - validator: $.optional.nullable.bool, - }, - - subscribing: { - validator: $.optional.nullable.bool, - }, - - publishing: { - validator: $.optional.nullable.bool, - }, - - limit: { - validator: $.optional.num.range(1, 100), - default: 30, - }, - - offset: { - validator: $.optional.num.min(0), - default: 0, - }, - - sort: { - validator: $.optional.str, - }, - }, - res: { type: 'array', optional: false, nullable: false, @@ -64,8 +19,25 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + host: { type: 'string', nullable: true }, + blocked: { type: 'boolean', nullable: true }, + notResponding: { type: 'boolean', nullable: true }, + suspended: { type: 'boolean', nullable: true }, + federating: { type: 'boolean', nullable: true }, + subscribing: { type: 'boolean', nullable: true }, + publishing: { type: 'boolean', nullable: true }, + limit: { type: 'integer', minimum: 1, maximum: 100, default: 30 }, + offset: { type: 'integer', default: 0 }, + sort: { type: 'string' }, + }, + required: [], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, me) => { +export default define(meta, paramDef, async (ps, me) => { const query = Instances.createQueryBuilder('instance'); switch (ps.sort) { @@ -83,10 +55,6 @@ export default define(meta, async (ps, me) => { case '-caughtAt': query.orderBy('instance.caughtAt', 'ASC'); break; case '+lastCommunicatedAt': query.orderBy('instance.lastCommunicatedAt', 'DESC'); break; case '-lastCommunicatedAt': query.orderBy('instance.lastCommunicatedAt', 'ASC'); break; - case '+driveUsage': query.orderBy('instance.driveUsage', 'DESC'); break; - case '-driveUsage': query.orderBy('instance.driveUsage', 'ASC'); break; - case '+driveFiles': query.orderBy('instance.driveFiles', 'DESC'); break; - case '-driveFiles': query.orderBy('instance.driveFiles', 'ASC'); break; default: query.orderBy('instance.id', 'DESC'); break; } @@ -144,7 +112,7 @@ export default define(meta, async (ps, me) => { query.andWhere('instance.host like :host', { host: '%' + ps.host.toLowerCase() + '%' }); } - const instances = await query.take(ps.limit!).skip(ps.offset).getMany(); + const instances = await query.take(ps.limit).skip(ps.offset).getMany(); - return instances; + return await Instances.packMany(instances); }); diff --git a/packages/backend/src/server/api/endpoints/federation/show-instance.ts b/packages/backend/src/server/api/endpoints/federation/show-instance.ts index 6f13b28ca..5bfe43fc9 100644 --- a/packages/backend/src/server/api/endpoints/federation/show-instance.ts +++ b/packages/backend/src/server/api/endpoints/federation/show-instance.ts @@ -1,30 +1,34 @@ -import $ from 'cafy'; -import define from '../../define'; -import { Instances } from '@/models/index'; -import { toPuny } from '@/misc/convert-host'; +import define from '../../define.js'; +import { Instances } from '@/models/index.js'; +import { toPuny } from '@/misc/convert-host.js'; export const meta = { tags: ['federation'], requireCredential: false, - params: { - host: { - validator: $.str, - }, - }, - res: { - type: 'object', - optional: true, nullable: false, - ref: 'FederationInstance', + oneOf: [{ + type: 'object', + ref: 'FederationInstance', + }, { + type: 'null', + }], }, } as const; +export const paramDef = { + type: 'object', + properties: { + host: { type: 'string' }, + }, + required: ['host'], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, me) => { +export default define(meta, paramDef, async (ps, me) => { const instance = await Instances .findOne({ host: toPuny(ps.host) }); - return instance; + return instance ? await Instances.pack(instance) : null; }); diff --git a/packages/backend/src/server/api/endpoints/federation/update-remote-user.ts b/packages/backend/src/server/api/endpoints/federation/update-remote-user.ts index 092f805bc..409cc7695 100644 --- a/packages/backend/src/server/api/endpoints/federation/update-remote-user.ts +++ b/packages/backend/src/server/api/endpoints/federation/update-remote-user.ts @@ -1,23 +1,23 @@ -import $ from 'cafy'; -import { ID } from '@/misc/cafy-id'; -import define from '../../define'; -import { getRemoteUser } from '../../common/getters'; -import { updatePerson } from '@/remote/activitypub/models/person'; +import define from '../../define.js'; +import { getRemoteUser } from '../../common/getters.js'; +import { updatePerson } from '@/remote/activitypub/models/person.js'; export const meta = { tags: ['federation'], requireCredential: true, +} as const; - params: { - userId: { - validator: $.type(ID), - }, +export const paramDef = { + type: 'object', + properties: { + userId: { type: 'string', format: 'misskey:id' }, }, + required: ['userId'], } as const; // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps) => { +export default define(meta, paramDef, async (ps) => { const user = await getRemoteUser(ps.userId); await updatePerson(user.uri!); }); diff --git a/packages/backend/src/server/api/endpoints/federation/users.ts b/packages/backend/src/server/api/endpoints/federation/users.ts index 9a8f74993..65ad9f88d 100644 --- a/packages/backend/src/server/api/endpoints/federation/users.ts +++ b/packages/backend/src/server/api/endpoints/federation/users.ts @@ -1,33 +1,12 @@ -import $ from 'cafy'; -import { ID } from '@/misc/cafy-id'; -import define from '../../define'; -import { Users } from '@/models/index'; -import { makePaginationQuery } from '../../common/make-pagination-query'; +import define from '../../define.js'; +import { Users } from '@/models/index.js'; +import { makePaginationQuery } from '../../common/make-pagination-query.js'; export const meta = { tags: ['federation'], requireCredential: false, - params: { - host: { - validator: $.str, - }, - - sinceId: { - validator: $.optional.type(ID), - }, - - untilId: { - validator: $.optional.type(ID), - }, - - limit: { - validator: $.optional.num.range(1, 100), - default: 10, - }, - }, - res: { type: 'array', optional: false, nullable: false, @@ -39,13 +18,24 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + host: { type: 'string' }, + sinceId: { type: 'string', format: 'misskey:id' }, + untilId: { type: 'string', format: 'misskey:id' }, + limit: { type: 'integer', minimum: 1, maximum: 100, default: 10 }, + }, + required: ['host'], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, me) => { +export default define(meta, paramDef, async (ps, me) => { const query = makePaginationQuery(Users.createQueryBuilder('user'), ps.sinceId, ps.untilId) .andWhere(`user.host = :host`, { host: ps.host }); const users = await query - .take(ps.limit!) + .take(ps.limit) .getMany(); return await Users.packMany(users, me, { detail: true }); diff --git a/packages/backend/src/server/api/endpoints/following/create.ts b/packages/backend/src/server/api/endpoints/following/create.ts index b840ab769..8758a64a3 100644 --- a/packages/backend/src/server/api/endpoints/following/create.ts +++ b/packages/backend/src/server/api/endpoints/following/create.ts @@ -1,12 +1,10 @@ -import $ from 'cafy'; -import { ID } from '@/misc/cafy-id'; import ms from 'ms'; -import create from '@/services/following/create'; -import define from '../../define'; -import { ApiError } from '../../error'; -import { getUser } from '../../common/getters'; -import { Followings, Users } from '@/models/index'; -import { IdentifiableError } from '@/misc/identifiable-error'; +import create from '@/services/following/create.js'; +import define from '../../define.js'; +import { ApiError } from '../../error.js'; +import { getUser } from '../../common/getters.js'; +import { Followings, Users } from '@/models/index.js'; +import { IdentifiableError } from '@/misc/identifiable-error.js'; export const meta = { tags: ['following', 'users'], @@ -20,12 +18,6 @@ export const meta = { kind: 'write:following', - params: { - userId: { - validator: $.type(ID), - }, - }, - errors: { noSuchUser: { message: 'No such user.', @@ -65,8 +57,16 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + userId: { type: 'string', format: 'misskey:id' }, + }, + required: ['userId'], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, user) => { +export default define(meta, paramDef, async (ps, user) => { const follower = user; // 自分自身 diff --git a/packages/backend/src/server/api/endpoints/following/delete.ts b/packages/backend/src/server/api/endpoints/following/delete.ts index 4cd0c4945..47efc59b8 100644 --- a/packages/backend/src/server/api/endpoints/following/delete.ts +++ b/packages/backend/src/server/api/endpoints/following/delete.ts @@ -1,11 +1,9 @@ -import $ from 'cafy'; -import { ID } from '@/misc/cafy-id'; import ms from 'ms'; -import deleteFollowing from '@/services/following/delete'; -import define from '../../define'; -import { ApiError } from '../../error'; -import { getUser } from '../../common/getters'; -import { Followings, Users } from '@/models/index'; +import deleteFollowing from '@/services/following/delete.js'; +import define from '../../define.js'; +import { ApiError } from '../../error.js'; +import { getUser } from '../../common/getters.js'; +import { Followings, Users } from '@/models/index.js'; export const meta = { tags: ['following', 'users'], @@ -19,12 +17,6 @@ export const meta = { kind: 'write:following', - params: { - userId: { - validator: $.type(ID), - }, - }, - errors: { noSuchUser: { message: 'No such user.', @@ -52,8 +44,16 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + userId: { type: 'string', format: 'misskey:id' }, + }, + required: ['userId'], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, user) => { +export default define(meta, paramDef, async (ps, user) => { const follower = user; // Check if the followee is yourself diff --git a/packages/backend/src/server/api/endpoints/following/invalidate.ts b/packages/backend/src/server/api/endpoints/following/invalidate.ts index 92e887e00..24d8256ca 100644 --- a/packages/backend/src/server/api/endpoints/following/invalidate.ts +++ b/packages/backend/src/server/api/endpoints/following/invalidate.ts @@ -1,11 +1,9 @@ -import $ from 'cafy'; -import { ID } from '@/misc/cafy-id'; -import * as ms from 'ms'; -import deleteFollowing from '@/services/following/delete'; -import define from '../../define'; -import { ApiError } from '../../error'; -import { getUser } from '../../common/getters'; -import { Followings, Users } from '@/models/index'; +import ms from 'ms'; +import deleteFollowing from '@/services/following/delete.js'; +import define from '../../define.js'; +import { ApiError } from '../../error.js'; +import { getUser } from '../../common/getters.js'; +import { Followings, Users } from '@/models/index.js'; export const meta = { tags: ['following', 'users'], @@ -19,12 +17,6 @@ export const meta = { kind: 'write:following', - params: { - userId: { - validator: $.type(ID), - }, - }, - errors: { noSuchUser: { message: 'No such user.', @@ -52,8 +44,16 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + userId: { type: 'string', format: 'misskey:id' }, + }, + required: ['userId'], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, user) => { +export default define(meta, paramDef, async (ps, user) => { const followee = user; // Check if the follower is yourself diff --git a/packages/backend/src/server/api/endpoints/following/requests/accept.ts b/packages/backend/src/server/api/endpoints/following/requests/accept.ts index 7e7c056f5..e5df55375 100644 --- a/packages/backend/src/server/api/endpoints/following/requests/accept.ts +++ b/packages/backend/src/server/api/endpoints/following/requests/accept.ts @@ -1,9 +1,7 @@ -import $ from 'cafy'; -import { ID } from '@/misc/cafy-id'; -import acceptFollowRequest from '@/services/following/requests/accept'; -import define from '../../../define'; -import { ApiError } from '../../../error'; -import { getUser } from '../../../common/getters'; +import acceptFollowRequest from '@/services/following/requests/accept.js'; +import define from '../../../define.js'; +import { ApiError } from '../../../error.js'; +import { getUser } from '../../../common/getters.js'; export const meta = { tags: ['following', 'account'], @@ -12,12 +10,6 @@ export const meta = { kind: 'write:following', - params: { - userId: { - validator: $.type(ID), - }, - }, - errors: { noSuchUser: { message: 'No such user.', @@ -32,8 +24,16 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + userId: { type: 'string', format: 'misskey:id' }, + }, + required: ['userId'], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, user) => { +export default define(meta, paramDef, async (ps, user) => { // Fetch follower const follower = await getUser(ps.userId).catch(e => { if (e.id === '15348ddd-432d-49c2-8a5a-8069753becff') throw new ApiError(meta.errors.noSuchUser); diff --git a/packages/backend/src/server/api/endpoints/following/requests/cancel.ts b/packages/backend/src/server/api/endpoints/following/requests/cancel.ts index c9abbf36d..80d37fb07 100644 --- a/packages/backend/src/server/api/endpoints/following/requests/cancel.ts +++ b/packages/backend/src/server/api/endpoints/following/requests/cancel.ts @@ -1,11 +1,9 @@ -import $ from 'cafy'; -import { ID } from '@/misc/cafy-id'; -import cancelFollowRequest from '@/services/following/requests/cancel'; -import define from '../../../define'; -import { ApiError } from '../../../error'; -import { getUser } from '../../../common/getters'; -import { Users } from '@/models/index'; -import { IdentifiableError } from '@/misc/identifiable-error'; +import cancelFollowRequest from '@/services/following/requests/cancel.js'; +import define from '../../../define.js'; +import { ApiError } from '../../../error.js'; +import { getUser } from '../../../common/getters.js'; +import { Users } from '@/models/index.js'; +import { IdentifiableError } from '@/misc/identifiable-error.js'; export const meta = { tags: ['following', 'account'], @@ -14,12 +12,6 @@ export const meta = { kind: 'write:following', - params: { - userId: { - validator: $.type(ID), - }, - }, - errors: { noSuchUser: { message: 'No such user.', @@ -41,8 +33,16 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + userId: { type: 'string', format: 'misskey:id' }, + }, + required: ['userId'], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, user) => { +export default define(meta, paramDef, async (ps, user) => { // Fetch followee const followee = await getUser(ps.userId).catch(e => { if (e.id === '15348ddd-432d-49c2-8a5a-8069753becff') throw new ApiError(meta.errors.noSuchUser); diff --git a/packages/backend/src/server/api/endpoints/following/requests/list.ts b/packages/backend/src/server/api/endpoints/following/requests/list.ts index ec0c76502..3b60b89b3 100644 --- a/packages/backend/src/server/api/endpoints/following/requests/list.ts +++ b/packages/backend/src/server/api/endpoints/following/requests/list.ts @@ -1,5 +1,5 @@ -import define from '../../../define'; -import { FollowRequests } from '@/models/index'; +import define from '../../../define.js'; +import { FollowRequests } from '@/models/index.js'; export const meta = { tags: ['following', 'account'], @@ -35,8 +35,14 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: {}, + required: [], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, user) => { +export default define(meta, paramDef, async (ps, user) => { const reqs = await FollowRequests.find({ followeeId: user.id, }); diff --git a/packages/backend/src/server/api/endpoints/following/requests/reject.ts b/packages/backend/src/server/api/endpoints/following/requests/reject.ts index a5ce1e7c7..cebe60428 100644 --- a/packages/backend/src/server/api/endpoints/following/requests/reject.ts +++ b/packages/backend/src/server/api/endpoints/following/requests/reject.ts @@ -1,9 +1,7 @@ -import $ from 'cafy'; -import { ID } from '@/misc/cafy-id'; -import { rejectFollowRequest } from '@/services/following/reject'; -import define from '../../../define'; -import { ApiError } from '../../../error'; -import { getUser } from '../../../common/getters'; +import { rejectFollowRequest } from '@/services/following/reject.js'; +import define from '../../../define.js'; +import { ApiError } from '../../../error.js'; +import { getUser } from '../../../common/getters.js'; export const meta = { tags: ['following', 'account'], @@ -12,12 +10,6 @@ export const meta = { kind: 'write:following', - params: { - userId: { - validator: $.type(ID), - }, - }, - errors: { noSuchUser: { message: 'No such user.', @@ -27,8 +19,16 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + userId: { type: 'string', format: 'misskey:id' }, + }, + required: ['userId'], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, user) => { +export default define(meta, paramDef, async (ps, user) => { // Fetch follower const follower = await getUser(ps.userId).catch(e => { if (e.id === '15348ddd-432d-49c2-8a5a-8069753becff') throw new ApiError(meta.errors.noSuchUser); diff --git a/packages/backend/src/server/api/endpoints/gallery/featured.ts b/packages/backend/src/server/api/endpoints/gallery/featured.ts index ff7c16889..e6acd3691 100644 --- a/packages/backend/src/server/api/endpoints/gallery/featured.ts +++ b/packages/backend/src/server/api/endpoints/gallery/featured.ts @@ -1,5 +1,5 @@ -import define from '../../define'; -import { GalleryPosts } from '@/models/index'; +import define from '../../define.js'; +import { GalleryPosts } from '@/models/index.js'; export const meta = { tags: ['gallery'], @@ -17,8 +17,14 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: {}, + required: [], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, me) => { +export default define(meta, paramDef, async (ps, me) => { const query = GalleryPosts.createQueryBuilder('post') .andWhere('post.createdAt > :date', { date: new Date(Date.now() - (1000 * 60 * 60 * 24 * 3)) }) .andWhere('post.likedCount > 0') diff --git a/packages/backend/src/server/api/endpoints/gallery/popular.ts b/packages/backend/src/server/api/endpoints/gallery/popular.ts index 2c3368a19..c4c8982fc 100644 --- a/packages/backend/src/server/api/endpoints/gallery/popular.ts +++ b/packages/backend/src/server/api/endpoints/gallery/popular.ts @@ -1,5 +1,5 @@ -import define from '../../define'; -import { GalleryPosts } from '@/models/index'; +import define from '../../define.js'; +import { GalleryPosts } from '@/models/index.js'; export const meta = { tags: ['gallery'], @@ -17,8 +17,14 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: {}, + required: [], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, me) => { +export default define(meta, paramDef, async (ps, me) => { const query = GalleryPosts.createQueryBuilder('post') .andWhere('post.likedCount > 0') .orderBy('post.likedCount', 'DESC'); diff --git a/packages/backend/src/server/api/endpoints/gallery/posts.ts b/packages/backend/src/server/api/endpoints/gallery/posts.ts index 9d2601c7e..428ba9cc7 100644 --- a/packages/backend/src/server/api/endpoints/gallery/posts.ts +++ b/packages/backend/src/server/api/endpoints/gallery/posts.ts @@ -1,27 +1,10 @@ -import $ from 'cafy'; -import { ID } from '@/misc/cafy-id'; -import define from '../../define'; -import { makePaginationQuery } from '../../common/make-pagination-query'; -import { GalleryPosts } from '@/models/index'; +import define from '../../define.js'; +import { makePaginationQuery } from '../../common/make-pagination-query.js'; +import { GalleryPosts } from '@/models/index.js'; export const meta = { tags: ['gallery'], - params: { - limit: { - validator: $.optional.num.range(1, 100), - default: 10, - }, - - sinceId: { - validator: $.optional.type(ID), - }, - - untilId: { - validator: $.optional.type(ID), - }, - }, - res: { type: 'array', optional: false, nullable: false, @@ -33,12 +16,22 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + limit: { type: 'integer', minimum: 1, maximum: 100, default: 10 }, + sinceId: { type: 'string', format: 'misskey:id' }, + untilId: { type: 'string', format: 'misskey:id' }, + }, + required: [], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, me) => { +export default define(meta, paramDef, async (ps, me) => { const query = makePaginationQuery(GalleryPosts.createQueryBuilder('post'), ps.sinceId, ps.untilId) .innerJoinAndSelect('post.user', 'user'); - const posts = await query.take(ps.limit!).getMany(); + const posts = await query.take(ps.limit).getMany(); return await GalleryPosts.packMany(posts, me); }); diff --git a/packages/backend/src/server/api/endpoints/gallery/posts/create.ts b/packages/backend/src/server/api/endpoints/gallery/posts/create.ts index e9d5df1ab..eb6c0f3eb 100644 --- a/packages/backend/src/server/api/endpoints/gallery/posts/create.ts +++ b/packages/backend/src/server/api/endpoints/gallery/posts/create.ts @@ -1,12 +1,10 @@ -import $ from 'cafy'; import ms from 'ms'; -import define from '../../../define'; -import { ID } from '../../../../../misc/cafy-id'; -import { DriveFiles, GalleryPosts } from '@/models/index'; -import { genId } from '../../../../../misc/gen-id'; -import { GalleryPost } from '@/models/entities/gallery-post'; -import { ApiError } from '../../../error'; -import { DriveFile } from '@/models/entities/drive-file'; +import define from '../../../define.js'; +import { DriveFiles, GalleryPosts } from '@/models/index.js'; +import { genId } from '../../../../../misc/gen-id.js'; +import { GalleryPost } from '@/models/entities/gallery-post.js'; +import { ApiError } from '../../../error.js'; +import { DriveFile } from '@/models/entities/drive-file.js'; export const meta = { tags: ['gallery'], @@ -20,25 +18,6 @@ export const meta = { max: 300, }, - params: { - title: { - validator: $.str.min(1), - }, - - description: { - validator: $.optional.nullable.str, - }, - - fileIds: { - validator: $.arr($.type(ID)).unique().range(1, 32), - }, - - isSensitive: { - validator: $.optional.bool, - default: false, - }, - }, - res: { type: 'object', optional: false, nullable: false, @@ -50,8 +29,21 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + title: { type: 'string', minLength: 1 }, + description: { type: 'string', nullable: true }, + fileIds: { type: 'array', uniqueItems: true, minItems: 1, maxItems: 32, items: { + type: 'string', format: 'misskey:id', + } }, + isSensitive: { type: 'boolean', default: false }, + }, + required: ['title', 'fileIds'], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, user) => { +export default define(meta, paramDef, async (ps, user) => { const files = (await Promise.all(ps.fileIds.map(fileId => DriveFiles.findOne({ id: fileId, diff --git a/packages/backend/src/server/api/endpoints/gallery/posts/delete.ts b/packages/backend/src/server/api/endpoints/gallery/posts/delete.ts index 2a13b9ed5..f8bf785ee 100644 --- a/packages/backend/src/server/api/endpoints/gallery/posts/delete.ts +++ b/packages/backend/src/server/api/endpoints/gallery/posts/delete.ts @@ -1,8 +1,6 @@ -import $ from 'cafy'; -import define from '../../../define'; -import { ApiError } from '../../../error'; -import { GalleryPosts } from '@/models/index'; -import { ID } from '@/misc/cafy-id'; +import define from '../../../define.js'; +import { ApiError } from '../../../error.js'; +import { GalleryPosts } from '@/models/index.js'; export const meta = { tags: ['gallery'], @@ -11,12 +9,6 @@ export const meta = { kind: 'write:gallery', - params: { - postId: { - validator: $.type(ID), - }, - }, - errors: { noSuchPost: { message: 'No such post.', @@ -26,8 +18,16 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + postId: { type: 'string', format: 'misskey:id' }, + }, + required: ['postId'], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, user) => { +export default define(meta, paramDef, async (ps, user) => { const post = await GalleryPosts.findOne({ id: ps.postId, userId: user.id, diff --git a/packages/backend/src/server/api/endpoints/gallery/posts/like.ts b/packages/backend/src/server/api/endpoints/gallery/posts/like.ts index 0fb408fa5..d154bfc3c 100644 --- a/packages/backend/src/server/api/endpoints/gallery/posts/like.ts +++ b/packages/backend/src/server/api/endpoints/gallery/posts/like.ts @@ -1,9 +1,7 @@ -import $ from 'cafy'; -import { ID } from '@/misc/cafy-id'; -import define from '../../../define'; -import { ApiError } from '../../../error'; -import { GalleryPosts, GalleryLikes } from '@/models/index'; -import { genId } from '@/misc/gen-id'; +import define from '../../../define.js'; +import { ApiError } from '../../../error.js'; +import { GalleryPosts, GalleryLikes } from '@/models/index.js'; +import { genId } from '@/misc/gen-id.js'; export const meta = { tags: ['gallery'], @@ -12,12 +10,6 @@ export const meta = { kind: 'write:gallery-likes', - params: { - postId: { - validator: $.type(ID), - }, - }, - errors: { noSuchPost: { message: 'No such post.', @@ -39,8 +31,16 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + postId: { type: 'string', format: 'misskey:id' }, + }, + required: ['postId'], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, user) => { +export default define(meta, paramDef, async (ps, user) => { const post = await GalleryPosts.findOne(ps.postId); if (post == null) { throw new ApiError(meta.errors.noSuchPost); diff --git a/packages/backend/src/server/api/endpoints/gallery/posts/show.ts b/packages/backend/src/server/api/endpoints/gallery/posts/show.ts index 4325d2ad3..5b4594070 100644 --- a/packages/backend/src/server/api/endpoints/gallery/posts/show.ts +++ b/packages/backend/src/server/api/endpoints/gallery/posts/show.ts @@ -1,20 +1,12 @@ -import $ from 'cafy'; -import { ID } from '@/misc/cafy-id'; -import define from '../../../define'; -import { ApiError } from '../../../error'; -import { GalleryPosts } from '@/models/index'; +import define from '../../../define.js'; +import { ApiError } from '../../../error.js'; +import { GalleryPosts } from '@/models/index.js'; export const meta = { tags: ['gallery'], requireCredential: false, - params: { - postId: { - validator: $.type(ID), - }, - }, - errors: { noSuchPost: { message: 'No such post.', @@ -30,8 +22,16 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + postId: { type: 'string', format: 'misskey:id' }, + }, + required: ['postId'], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, me) => { +export default define(meta, paramDef, async (ps, me) => { const post = await GalleryPosts.findOne({ id: ps.postId, }); diff --git a/packages/backend/src/server/api/endpoints/gallery/posts/unlike.ts b/packages/backend/src/server/api/endpoints/gallery/posts/unlike.ts index 9cca09bdd..b00008a86 100644 --- a/packages/backend/src/server/api/endpoints/gallery/posts/unlike.ts +++ b/packages/backend/src/server/api/endpoints/gallery/posts/unlike.ts @@ -1,8 +1,6 @@ -import $ from 'cafy'; -import { ID } from '@/misc/cafy-id'; -import define from '../../../define'; -import { ApiError } from '../../../error'; -import { GalleryPosts, GalleryLikes } from '@/models/index'; +import define from '../../../define.js'; +import { ApiError } from '../../../error.js'; +import { GalleryPosts, GalleryLikes } from '@/models/index.js'; export const meta = { tags: ['gallery'], @@ -11,12 +9,6 @@ export const meta = { kind: 'write:gallery-likes', - params: { - postId: { - validator: $.type(ID), - }, - }, - errors: { noSuchPost: { message: 'No such post.', @@ -32,8 +24,16 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + postId: { type: 'string', format: 'misskey:id' }, + }, + required: ['postId'], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, user) => { +export default define(meta, paramDef, async (ps, user) => { const post = await GalleryPosts.findOne(ps.postId); if (post == null) { throw new ApiError(meta.errors.noSuchPost); diff --git a/packages/backend/src/server/api/endpoints/gallery/posts/update.ts b/packages/backend/src/server/api/endpoints/gallery/posts/update.ts index c35e1bbf5..123794d08 100644 --- a/packages/backend/src/server/api/endpoints/gallery/posts/update.ts +++ b/packages/backend/src/server/api/endpoints/gallery/posts/update.ts @@ -1,11 +1,9 @@ -import $ from 'cafy'; import ms from 'ms'; -import define from '../../../define'; -import { ID } from '../../../../../misc/cafy-id'; -import { DriveFiles, GalleryPosts } from '@/models/index'; -import { GalleryPost } from '@/models/entities/gallery-post'; -import { ApiError } from '../../../error'; -import { DriveFile } from '@/models/entities/drive-file'; +import define from '../../../define.js'; +import { DriveFiles, GalleryPosts } from '@/models/index.js'; +import { GalleryPost } from '@/models/entities/gallery-post.js'; +import { ApiError } from '../../../error.js'; +import { DriveFile } from '@/models/entities/drive-file.js'; export const meta = { tags: ['gallery'], @@ -19,29 +17,6 @@ export const meta = { max: 300, }, - params: { - postId: { - validator: $.type(ID), - }, - - title: { - validator: $.str.min(1), - }, - - description: { - validator: $.optional.nullable.str, - }, - - fileIds: { - validator: $.arr($.type(ID)).unique().range(1, 32), - }, - - isSensitive: { - validator: $.optional.bool, - default: false, - }, - }, - res: { type: 'object', optional: false, nullable: false, @@ -53,8 +28,22 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + postId: { type: 'string', format: 'misskey:id' }, + title: { type: 'string', minLength: 1 }, + description: { type: 'string', nullable: true }, + fileIds: { type: 'array', uniqueItems: true, minItems: 1, maxItems: 32, items: { + type: 'string', format: 'misskey:id', + } }, + isSensitive: { type: 'boolean', default: false }, + }, + required: ['postId', 'title', 'fileIds'], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, user) => { +export default define(meta, paramDef, async (ps, user) => { const files = (await Promise.all(ps.fileIds.map(fileId => DriveFiles.findOne({ id: fileId, diff --git a/packages/backend/src/server/api/endpoints/get-online-users-count.ts b/packages/backend/src/server/api/endpoints/get-online-users-count.ts index 5b13d5a3b..80a2334cf 100644 --- a/packages/backend/src/server/api/endpoints/get-online-users-count.ts +++ b/packages/backend/src/server/api/endpoints/get-online-users-count.ts @@ -1,19 +1,22 @@ -import { USER_ONLINE_THRESHOLD } from '@/const'; -import { Users } from '@/models/index'; +import { USER_ONLINE_THRESHOLD } from '@/const.js'; +import { Users } from '@/models/index.js'; import { MoreThan } from 'typeorm'; -import define from '../define'; +import define from '../define.js'; export const meta = { tags: ['meta'], requireCredential: false, +} as const; - params: { - }, +export const paramDef = { + type: 'object', + properties: {}, + required: [], } as const; // eslint-disable-next-line import/no-default-export -export default define(meta, async () => { +export default define(meta, paramDef, async () => { const count = await Users.count({ lastActiveDate: MoreThan(new Date(Date.now() - USER_ONLINE_THRESHOLD)), }); diff --git a/packages/backend/src/server/api/endpoints/hashtags/list.ts b/packages/backend/src/server/api/endpoints/hashtags/list.ts index 9fa9b3edc..50e36386c 100644 --- a/packages/backend/src/server/api/endpoints/hashtags/list.ts +++ b/packages/backend/src/server/api/endpoints/hashtags/list.ts @@ -1,51 +1,11 @@ -import $ from 'cafy'; -import define from '../../define'; -import { Hashtags } from '@/models/index'; +import define from '../../define.js'; +import { Hashtags } from '@/models/index.js'; export const meta = { tags: ['hashtags'], requireCredential: false, - params: { - limit: { - validator: $.optional.num.range(1, 100), - default: 10, - }, - - attachedToUserOnly: { - validator: $.optional.bool, - default: false, - }, - - attachedToLocalUserOnly: { - validator: $.optional.bool, - default: false, - }, - - attachedToRemoteUserOnly: { - validator: $.optional.bool, - default: false, - }, - - sort: { - validator: $.str.or([ - '+mentionedUsers', - '-mentionedUsers', - '+mentionedLocalUsers', - '-mentionedLocalUsers', - '+mentionedRemoteUsers', - '-mentionedRemoteUsers', - '+attachedUsers', - '-attachedUsers', - '+attachedLocalUsers', - '-attachedLocalUsers', - '+attachedRemoteUsers', - '-attachedRemoteUsers', - ]), - }, - }, - res: { type: 'array', optional: false, nullable: false, @@ -57,8 +17,20 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + limit: { type: 'integer', minimum: 1, maximum: 100, default: 10 }, + attachedToUserOnly: { type: 'boolean', default: false }, + attachedToLocalUserOnly: { type: 'boolean', default: false }, + attachedToRemoteUserOnly: { type: 'boolean', default: false }, + sort: { type: 'string', enum: ['+mentionedUsers', '-mentionedUsers', '+mentionedLocalUsers', '-mentionedLocalUsers', '+mentionedRemoteUsers', '-mentionedRemoteUsers', '+attachedUsers', '-attachedUsers', '+attachedLocalUsers', '-attachedLocalUsers', '+attachedRemoteUsers', '-attachedRemoteUsers'] }, + }, + required: ['sort'], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, me) => { +export default define(meta, paramDef, async (ps, me) => { const query = Hashtags.createQueryBuilder('tag'); if (ps.attachedToUserOnly) query.andWhere('tag.attachedUsersCount != 0'); @@ -90,7 +62,7 @@ export default define(meta, async (ps, me) => { 'tag.attachedRemoteUsersCount', ]); - const tags = await query.take(ps.limit!).getMany(); + const tags = await query.take(ps.limit).getMany(); return Hashtags.packMany(tags); }); diff --git a/packages/backend/src/server/api/endpoints/hashtags/search.ts b/packages/backend/src/server/api/endpoints/hashtags/search.ts index 0d646c64f..c28984477 100644 --- a/packages/backend/src/server/api/endpoints/hashtags/search.ts +++ b/packages/backend/src/server/api/endpoints/hashtags/search.ts @@ -1,28 +1,11 @@ -import $ from 'cafy'; -import define from '../../define'; -import { Hashtags } from '@/models/index'; +import define from '../../define.js'; +import { Hashtags } from '@/models/index.js'; export const meta = { tags: ['hashtags'], requireCredential: false, - params: { - limit: { - validator: $.optional.num.range(1, 100), - default: 10, - }, - - query: { - validator: $.str, - }, - - offset: { - validator: $.optional.num.min(0), - default: 0, - }, - }, - res: { type: 'array', optional: false, nullable: false, @@ -33,13 +16,23 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + limit: { type: 'integer', minimum: 1, maximum: 100, default: 10 }, + query: { type: 'string' }, + offset: { type: 'integer', default: 0 }, + }, + required: ['query'], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps) => { +export default define(meta, paramDef, async (ps) => { const hashtags = await Hashtags.createQueryBuilder('tag') .where('tag.name like :q', { q: ps.query.toLowerCase() + '%' }) .orderBy('tag.count', 'DESC') .groupBy('tag.id') - .take(ps.limit!) + .take(ps.limit) .skip(ps.offset) .getMany(); diff --git a/packages/backend/src/server/api/endpoints/hashtags/show.ts b/packages/backend/src/server/api/endpoints/hashtags/show.ts index 242cef99d..6e6afa4f1 100644 --- a/packages/backend/src/server/api/endpoints/hashtags/show.ts +++ b/packages/backend/src/server/api/endpoints/hashtags/show.ts @@ -1,20 +1,13 @@ -import $ from 'cafy'; -import define from '../../define'; -import { ApiError } from '../../error'; -import { Hashtags } from '@/models/index'; -import { normalizeForSearch } from '@/misc/normalize-for-search'; +import define from '../../define.js'; +import { ApiError } from '../../error.js'; +import { Hashtags } from '@/models/index.js'; +import { normalizeForSearch } from '@/misc/normalize-for-search.js'; export const meta = { tags: ['hashtags'], requireCredential: false, - params: { - tag: { - validator: $.str, - }, - }, - res: { type: 'object', optional: false, nullable: false, @@ -30,8 +23,16 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + tag: { type: 'string' }, + }, + required: ['tag'], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, user) => { +export default define(meta, paramDef, async (ps, user) => { const hashtag = await Hashtags.findOne({ name: normalizeForSearch(ps.tag) }); if (hashtag == null) { throw new ApiError(meta.errors.noSuchHashtag); diff --git a/packages/backend/src/server/api/endpoints/hashtags/trend.ts b/packages/backend/src/server/api/endpoints/hashtags/trend.ts index be964ad63..9cdbc8941 100644 --- a/packages/backend/src/server/api/endpoints/hashtags/trend.ts +++ b/packages/backend/src/server/api/endpoints/hashtags/trend.ts @@ -1,10 +1,10 @@ import { Brackets } from 'typeorm'; -import define from '../../define'; -import { fetchMeta } from '@/misc/fetch-meta'; -import { Notes } from '@/models/index'; -import { Note } from '@/models/entities/note'; -import { safeForSql } from '@/misc/safe-for-sql'; -import { normalizeForSearch } from '@/misc/normalize-for-search'; +import define from '../../define.js'; +import { fetchMeta } from '@/misc/fetch-meta.js'; +import { Notes } from '@/models/index.js'; +import { Note } from '@/models/entities/note.js'; +import { safeForSql } from '@/misc/safe-for-sql.js'; +import { normalizeForSearch } from '@/misc/normalize-for-search.js'; /* トレンドに載るためには「『直近a分間のユニーク投稿数が今からa分前~今からb分前の間のユニーク投稿数のn倍以上』のハッシュタグの上位5位以内に入る」ことが必要 @@ -53,8 +53,14 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: {}, + required: [], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async () => { +export default define(meta, paramDef, async () => { const instance = await fetchMeta(true); const hiddenTags = instance.hiddenTags.map(t => normalizeForSearch(t)); diff --git a/packages/backend/src/server/api/endpoints/hashtags/users.ts b/packages/backend/src/server/api/endpoints/hashtags/users.ts index 2158dc434..a5df21a7e 100644 --- a/packages/backend/src/server/api/endpoints/hashtags/users.ts +++ b/packages/backend/src/server/api/endpoints/hashtags/users.ts @@ -1,52 +1,12 @@ -import $ from 'cafy'; -import define from '../../define'; -import { Users } from '@/models/index'; -import { normalizeForSearch } from '@/misc/normalize-for-search'; +import define from '../../define.js'; +import { Users } from '@/models/index.js'; +import { normalizeForSearch } from '@/misc/normalize-for-search.js'; export const meta = { requireCredential: false, tags: ['hashtags', 'users'], - params: { - tag: { - validator: $.str, - }, - - limit: { - validator: $.optional.num.range(1, 100), - default: 10, - }, - - sort: { - validator: $.str.or([ - '+follower', - '-follower', - '+createdAt', - '-createdAt', - '+updatedAt', - '-updatedAt', - ]), - }, - - state: { - validator: $.optional.str.or([ - 'all', - 'alive', - ]), - default: 'all', - }, - - origin: { - validator: $.optional.str.or([ - 'combined', - 'local', - 'remote', - ]), - default: 'local', - }, - }, - res: { type: 'array', optional: false, nullable: false, @@ -58,8 +18,20 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + tag: { type: 'string' }, + limit: { type: 'integer', minimum: 1, maximum: 100, default: 10 }, + sort: { type: 'string', enum: ['+follower', '-follower', '+createdAt', '-createdAt', '+updatedAt', '-updatedAt'] }, + state: { type: 'string', enum: ['all', 'alive'], default: "all" }, + origin: { type: 'string', enum: ['combined', 'local', 'remote'], default: "local" }, + }, + required: ['tag', 'sort'], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, me) => { +export default define(meta, paramDef, async (ps, me) => { const query = Users.createQueryBuilder('user') .where(':tag = ANY(user.tags)', { tag: normalizeForSearch(ps.tag) }); @@ -84,7 +56,7 @@ export default define(meta, async (ps, me) => { case '-updatedAt': query.orderBy('user.updatedAt', 'ASC'); break; } - const users = await query.take(ps.limit!).getMany(); + const users = await query.take(ps.limit).getMany(); return await Users.packMany(users, me, { detail: true }); }); diff --git a/packages/backend/src/server/api/endpoints/i.ts b/packages/backend/src/server/api/endpoints/i.ts index d69c118cf..5b1ad2b09 100644 --- a/packages/backend/src/server/api/endpoints/i.ts +++ b/packages/backend/src/server/api/endpoints/i.ts @@ -1,13 +1,11 @@ -import define from '../define'; -import { Users } from '@/models/index'; +import define from '../define.js'; +import { Users } from '@/models/index.js'; export const meta = { tags: ['account'], requireCredential: true, - params: {}, - res: { type: 'object', optional: false, nullable: false, @@ -15,8 +13,14 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: {}, + required: [], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, user, token) => { +export default define(meta, paramDef, async (ps, user, token) => { const isSecure = token == null; // ここで渡ってきている user はキャッシュされていて古い可能性もあるので id だけ渡す diff --git a/packages/backend/src/server/api/endpoints/i/2fa/done.ts b/packages/backend/src/server/api/endpoints/i/2fa/done.ts index 485390869..70478430d 100644 --- a/packages/backend/src/server/api/endpoints/i/2fa/done.ts +++ b/packages/backend/src/server/api/endpoints/i/2fa/done.ts @@ -1,22 +1,23 @@ -import $ from 'cafy'; import * as speakeasy from 'speakeasy'; -import define from '../../../define'; -import { UserProfiles } from '@/models/index'; +import define from '../../../define.js'; +import { UserProfiles } from '@/models/index.js'; export const meta = { requireCredential: true, secure: true, +} as const; - params: { - token: { - validator: $.str, - }, +export const paramDef = { + type: 'object', + properties: { + token: { type: 'string' }, }, + required: ['token'], } as const; // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, user) => { +export default define(meta, paramDef, async (ps, user) => { const token = ps.token.replace(/\s/g, ''); const profile = await UserProfiles.findOneOrFail(user.id); diff --git a/packages/backend/src/server/api/endpoints/i/2fa/key-done.ts b/packages/backend/src/server/api/endpoints/i/2fa/key-done.ts index 26e9a6088..f33237c8b 100644 --- a/packages/backend/src/server/api/endpoints/i/2fa/key-done.ts +++ b/packages/backend/src/server/api/endpoints/i/2fa/key-done.ts @@ -1,48 +1,40 @@ -import $ from 'cafy'; -import * as bcrypt from 'bcryptjs'; -import { promisify } from 'util'; +import bcrypt from 'bcryptjs'; +import { promisify } from 'node:util'; import * as cbor from 'cbor'; -import define from '../../../define'; +import define from '../../../define.js'; import { UserProfiles, UserSecurityKeys, AttestationChallenges, Users, -} from '@/models/index'; -import config from '@/config/index'; -import { procedures, hash } from '../../../2fa'; -import { publishMainStream } from '@/services/stream'; +} from '@/models/index.js'; +import config from '@/config/index.js'; +import { procedures, hash } from '../../../2fa.js'; +import { publishMainStream } from '@/services/stream.js'; const cborDecodeFirst = promisify(cbor.decodeFirst) as any; +const rpIdHashReal = hash(Buffer.from(config.hostname, 'utf-8')); export const meta = { requireCredential: true, secure: true, - - params: { - clientDataJSON: { - validator: $.str, - }, - attestationObject: { - validator: $.str, - }, - password: { - validator: $.str, - }, - challengeId: { - validator: $.str, - }, - name: { - validator: $.str, - }, - }, } as const; -const rpIdHashReal = hash(Buffer.from(config.hostname, 'utf-8')); +export const paramDef = { + type: 'object', + properties: { + clientDataJSON: { type: 'string' }, + attestationObject: { type: 'string' }, + password: { type: 'string' }, + challengeId: { type: 'string' }, + name: { type: 'string' }, + }, + required: ['clientDataJSON', 'attestationObject', 'password', 'challengeId', 'name'], +} as const; // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, user) => { +export default define(meta, paramDef, async (ps, user) => { const profile = await UserProfiles.findOneOrFail(user.id); // Compare password diff --git a/packages/backend/src/server/api/endpoints/i/2fa/password-less.ts b/packages/backend/src/server/api/endpoints/i/2fa/password-less.ts index 854848a43..4bfa24f97 100644 --- a/packages/backend/src/server/api/endpoints/i/2fa/password-less.ts +++ b/packages/backend/src/server/api/endpoints/i/2fa/password-less.ts @@ -1,21 +1,22 @@ -import $ from 'cafy'; -import define from '../../../define'; -import { UserProfiles } from '@/models/index'; +import define from '../../../define.js'; +import { UserProfiles } from '@/models/index.js'; export const meta = { requireCredential: true, secure: true, +} as const; - params: { - value: { - validator: $.boolean, - }, +export const paramDef = { + type: 'object', + properties: { + value: { type: 'boolean' }, }, + required: ['value'], } as const; // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, user) => { +export default define(meta, paramDef, async (ps, user) => { await UserProfiles.update(user.id, { usePasswordLessLogin: ps.value, }); diff --git a/packages/backend/src/server/api/endpoints/i/2fa/register-key.ts b/packages/backend/src/server/api/endpoints/i/2fa/register-key.ts index 057e54c69..0c4c99271 100644 --- a/packages/backend/src/server/api/endpoints/i/2fa/register-key.ts +++ b/packages/backend/src/server/api/endpoints/i/2fa/register-key.ts @@ -1,11 +1,10 @@ -import $ from 'cafy'; -import * as bcrypt from 'bcryptjs'; -import define from '../../../define'; -import { UserProfiles, AttestationChallenges } from '@/models/index'; -import { promisify } from 'util'; -import * as crypto from 'crypto'; -import { genId } from '@/misc/gen-id'; -import { hash } from '../../../2fa'; +import bcrypt from 'bcryptjs'; +import define from '../../../define.js'; +import { UserProfiles, AttestationChallenges } from '@/models/index.js'; +import { promisify } from 'node:util'; +import * as crypto from 'node:crypto'; +import { genId } from '@/misc/gen-id.js'; +import { hash } from '../../../2fa.js'; const randomBytes = promisify(crypto.randomBytes); @@ -13,16 +12,18 @@ export const meta = { requireCredential: true, secure: true, +} as const; - params: { - password: { - validator: $.str, - }, +export const paramDef = { + type: 'object', + properties: { + password: { type: 'string' }, }, + required: ['password'], } as const; // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, user) => { +export default define(meta, paramDef, async (ps, user) => { const profile = await UserProfiles.findOneOrFail(user.id); // Compare password diff --git a/packages/backend/src/server/api/endpoints/i/2fa/register.ts b/packages/backend/src/server/api/endpoints/i/2fa/register.ts index c5cfb9dfa..7951e393b 100644 --- a/packages/backend/src/server/api/endpoints/i/2fa/register.ts +++ b/packages/backend/src/server/api/endpoints/i/2fa/register.ts @@ -1,25 +1,26 @@ -import $ from 'cafy'; -import * as bcrypt from 'bcryptjs'; +import bcrypt from 'bcryptjs'; import * as speakeasy from 'speakeasy'; import * as QRCode from 'qrcode'; -import config from '@/config/index'; -import define from '../../../define'; -import { UserProfiles } from '@/models/index'; +import config from '@/config/index.js'; +import define from '../../../define.js'; +import { UserProfiles } from '@/models/index.js'; export const meta = { requireCredential: true, secure: true, +} as const; - params: { - password: { - validator: $.str, - }, +export const paramDef = { + type: 'object', + properties: { + password: { type: 'string' }, }, + required: ['password'], } as const; // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, user) => { +export default define(meta, paramDef, async (ps, user) => { const profile = await UserProfiles.findOneOrFail(user.id); // Compare password diff --git a/packages/backend/src/server/api/endpoints/i/2fa/remove-key.ts b/packages/backend/src/server/api/endpoints/i/2fa/remove-key.ts index 03e1d0434..2b69b1f8c 100644 --- a/packages/backend/src/server/api/endpoints/i/2fa/remove-key.ts +++ b/packages/backend/src/server/api/endpoints/i/2fa/remove-key.ts @@ -1,26 +1,25 @@ -import $ from 'cafy'; -import * as bcrypt from 'bcryptjs'; -import define from '../../../define'; -import { UserProfiles, UserSecurityKeys, Users } from '@/models/index'; -import { publishMainStream } from '@/services/stream'; +import bcrypt from 'bcryptjs'; +import define from '../../../define.js'; +import { UserProfiles, UserSecurityKeys, Users } from '@/models/index.js'; +import { publishMainStream } from '@/services/stream.js'; export const meta = { requireCredential: true, secure: true, +} as const; - params: { - password: { - validator: $.str, - }, - credentialId: { - validator: $.str, - }, +export const paramDef = { + type: 'object', + properties: { + password: { type: 'string' }, + credentialId: { type: 'string' }, }, + required: ['password', 'credentialId'], } as const; // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, user) => { +export default define(meta, paramDef, async (ps, user) => { const profile = await UserProfiles.findOneOrFail(user.id); // Compare password diff --git a/packages/backend/src/server/api/endpoints/i/2fa/unregister.ts b/packages/backend/src/server/api/endpoints/i/2fa/unregister.ts index a19ad6810..c5633f68b 100644 --- a/packages/backend/src/server/api/endpoints/i/2fa/unregister.ts +++ b/packages/backend/src/server/api/endpoints/i/2fa/unregister.ts @@ -1,22 +1,23 @@ -import $ from 'cafy'; -import * as bcrypt from 'bcryptjs'; -import define from '../../../define'; -import { UserProfiles } from '@/models/index'; +import bcrypt from 'bcryptjs'; +import define from '../../../define.js'; +import { UserProfiles } from '@/models/index.js'; export const meta = { requireCredential: true, secure: true, +} as const; - params: { - password: { - validator: $.str, - }, +export const paramDef = { + type: 'object', + properties: { + password: { type: 'string' }, }, + required: ['password'], } as const; // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, user) => { +export default define(meta, paramDef, async (ps, user) => { const profile = await UserProfiles.findOneOrFail(user.id); // Compare password diff --git a/packages/backend/src/server/api/endpoints/i/apps.ts b/packages/backend/src/server/api/endpoints/i/apps.ts index 63999b098..eca955884 100644 --- a/packages/backend/src/server/api/endpoints/i/apps.ts +++ b/packages/backend/src/server/api/endpoints/i/apps.ts @@ -1,26 +1,22 @@ -import $ from 'cafy'; -import define from '../../define'; -import { AccessTokens } from '@/models/index'; +import define from '../../define.js'; +import { AccessTokens } from '@/models/index.js'; export const meta = { requireCredential: true, secure: true, +} as const; - params: { - sort: { - validator: $.optional.str.or([ - '+createdAt', - '-createdAt', - '+lastUsedAt', - '-lastUsedAt', - ]), - }, +export const paramDef = { + type: 'object', + properties: { + sort: { type: 'string', enum: ['+createdAt', '-createdAt', '+lastUsedAt', '-lastUsedAt'] }, }, + required: [], } as const; // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, user) => { +export default define(meta, paramDef, async (ps, user) => { const query = AccessTokens.createQueryBuilder('token') .where('token.userId = :userId', { userId: user.id }); diff --git a/packages/backend/src/server/api/endpoints/i/authorized-apps.ts b/packages/backend/src/server/api/endpoints/i/authorized-apps.ts index 52122b851..3301808e7 100644 --- a/packages/backend/src/server/api/endpoints/i/authorized-apps.ts +++ b/packages/backend/src/server/api/endpoints/i/authorized-apps.ts @@ -1,38 +1,30 @@ -import $ from 'cafy'; -import define from '../../define'; -import { AccessTokens, Apps } from '@/models/index'; +import define from '../../define.js'; +import { AccessTokens, Apps } from '@/models/index.js'; export const meta = { requireCredential: true, secure: true, +} as const; - params: { - limit: { - validator: $.optional.num.range(1, 100), - default: 10, - }, - - offset: { - validator: $.optional.num.min(0), - default: 0, - }, - - sort: { - validator: $.optional.str.or('desc|asc'), - default: 'desc', - }, +export const paramDef = { + type: 'object', + properties: { + limit: { type: 'integer', minimum: 1, maximum: 100, default: 10 }, + offset: { type: 'integer', default: 0 }, + sort: { type: 'string', enum: ['desc', 'asc'], default: "desc" }, }, + required: [], } as const; // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, user) => { +export default define(meta, paramDef, async (ps, user) => { // Get tokens const tokens = await AccessTokens.find({ where: { userId: user.id, }, - take: ps.limit!, + take: ps.limit, skip: ps.offset, order: { id: ps.sort == 'asc' ? 1 : -1, diff --git a/packages/backend/src/server/api/endpoints/i/change-password.ts b/packages/backend/src/server/api/endpoints/i/change-password.ts index 7b6c13773..16509d2dc 100644 --- a/packages/backend/src/server/api/endpoints/i/change-password.ts +++ b/packages/backend/src/server/api/endpoints/i/change-password.ts @@ -1,26 +1,24 @@ -import $ from 'cafy'; -import * as bcrypt from 'bcryptjs'; -import define from '../../define'; -import { UserProfiles } from '@/models/index'; +import bcrypt from 'bcryptjs'; +import define from '../../define.js'; +import { UserProfiles } from '@/models/index.js'; export const meta = { requireCredential: true, secure: true, +} as const; - params: { - currentPassword: { - validator: $.str, - }, - - newPassword: { - validator: $.str, - }, +export const paramDef = { + type: 'object', + properties: { + currentPassword: { type: 'string' }, + newPassword: { type: 'string', minLength: 1 }, }, + required: ['currentPassword', 'newPassword'], } as const; // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, user) => { +export default define(meta, paramDef, async (ps, user) => { const profile = await UserProfiles.findOneOrFail(user.id); // Compare password diff --git a/packages/backend/src/server/api/endpoints/i/delete-account.ts b/packages/backend/src/server/api/endpoints/i/delete-account.ts index e1eee949f..8cb6b6a63 100644 --- a/packages/backend/src/server/api/endpoints/i/delete-account.ts +++ b/packages/backend/src/server/api/endpoints/i/delete-account.ts @@ -1,25 +1,26 @@ -import $ from 'cafy'; -import * as bcrypt from 'bcryptjs'; -import define from '../../define'; -import { UserProfiles, Users } from '@/models/index'; -import { doPostSuspend } from '@/services/suspend-user'; -import { publishUserEvent } from '@/services/stream'; -import { createDeleteAccountJob } from '@/queue'; +import bcrypt from 'bcryptjs'; +import define from '../../define.js'; +import { UserProfiles, Users } from '@/models/index.js'; +import { doPostSuspend } from '@/services/suspend-user.js'; +import { publishUserEvent } from '@/services/stream.js'; +import { createDeleteAccountJob } from '@/queue/index.js'; export const meta = { requireCredential: true, secure: true, +} as const; - params: { - password: { - validator: $.str, - }, +export const paramDef = { + type: 'object', + properties: { + password: { type: 'string' }, }, + required: ['password'], } as const; // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, user) => { +export default define(meta, paramDef, async (ps, user) => { const profile = await UserProfiles.findOneOrFail(user.id); const userDetailed = await Users.findOneOrFail(user.id); if (userDetailed.isDeleted) { diff --git a/packages/backend/src/server/api/endpoints/i/export-blocking.ts b/packages/backend/src/server/api/endpoints/i/export-blocking.ts index 44d8a1cb3..aed4c2e0a 100644 --- a/packages/backend/src/server/api/endpoints/i/export-blocking.ts +++ b/packages/backend/src/server/api/endpoints/i/export-blocking.ts @@ -1,5 +1,5 @@ -import define from '../../define'; -import { createExportBlockingJob } from '@/queue/index'; +import define from '../../define.js'; +import { createExportBlockingJob } from '@/queue/index.js'; import ms from 'ms'; export const meta = { @@ -11,7 +11,13 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: {}, + required: [], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, user) => { +export default define(meta, paramDef, async (ps, user) => { createExportBlockingJob(user); }); diff --git a/packages/backend/src/server/api/endpoints/i/export-following.ts b/packages/backend/src/server/api/endpoints/i/export-following.ts index 5d1617d57..058d77b3c 100644 --- a/packages/backend/src/server/api/endpoints/i/export-following.ts +++ b/packages/backend/src/server/api/endpoints/i/export-following.ts @@ -1,6 +1,5 @@ -import $ from 'cafy'; -import define from '../../define'; -import { createExportFollowingJob } from '@/queue/index'; +import define from '../../define.js'; +import { createExportFollowingJob } from '@/queue/index.js'; import ms from 'ms'; export const meta = { @@ -10,19 +9,18 @@ export const meta = { duration: ms('1hour'), max: 1, }, - params: { - excludeMuting: { - validator: $.optional.bool, - default: false, - }, - excludeInactive: { - validator: $.optional.bool, - default: false, - }, +} as const; + +export const paramDef = { + type: 'object', + properties: { + excludeMuting: { type: 'boolean', default: false }, + excludeInactive: { type: 'boolean', default: false }, }, + required: [], } as const; // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, user) => { +export default define(meta, paramDef, async (ps, user) => { createExportFollowingJob(user, ps.excludeMuting, ps.excludeInactive); }); diff --git a/packages/backend/src/server/api/endpoints/i/export-mute.ts b/packages/backend/src/server/api/endpoints/i/export-mute.ts index 27ce8f0b2..c0216fac0 100644 --- a/packages/backend/src/server/api/endpoints/i/export-mute.ts +++ b/packages/backend/src/server/api/endpoints/i/export-mute.ts @@ -1,5 +1,5 @@ -import define from '../../define'; -import { createExportMuteJob } from '@/queue/index'; +import define from '../../define.js'; +import { createExportMuteJob } from '@/queue/index.js'; import ms from 'ms'; export const meta = { @@ -11,7 +11,13 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: {}, + required: [], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, user) => { +export default define(meta, paramDef, async (ps, user) => { createExportMuteJob(user); }); diff --git a/packages/backend/src/server/api/endpoints/i/export-notes.ts b/packages/backend/src/server/api/endpoints/i/export-notes.ts index 25b1849e8..4b85a4555 100644 --- a/packages/backend/src/server/api/endpoints/i/export-notes.ts +++ b/packages/backend/src/server/api/endpoints/i/export-notes.ts @@ -1,5 +1,5 @@ -import define from '../../define'; -import { createExportNotesJob } from '@/queue/index'; +import define from '../../define.js'; +import { createExportNotesJob } from '@/queue/index.js'; import ms from 'ms'; export const meta = { @@ -11,7 +11,13 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: {}, + required: [], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, user) => { +export default define(meta, paramDef, async (ps, user) => { createExportNotesJob(user); }); diff --git a/packages/backend/src/server/api/endpoints/i/export-user-lists.ts b/packages/backend/src/server/api/endpoints/i/export-user-lists.ts index d28b699c5..fa5c1f5e5 100644 --- a/packages/backend/src/server/api/endpoints/i/export-user-lists.ts +++ b/packages/backend/src/server/api/endpoints/i/export-user-lists.ts @@ -1,5 +1,5 @@ -import define from '../../define'; -import { createExportUserListsJob } from '@/queue/index'; +import define from '../../define.js'; +import { createExportUserListsJob } from '@/queue/index.js'; import ms from 'ms'; export const meta = { @@ -11,7 +11,13 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: {}, + required: [], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, user) => { +export default define(meta, paramDef, async (ps, user) => { createExportUserListsJob(user); }); diff --git a/packages/backend/src/server/api/endpoints/i/favorites.ts b/packages/backend/src/server/api/endpoints/i/favorites.ts index 92c767876..3c420e4d0 100644 --- a/packages/backend/src/server/api/endpoints/i/favorites.ts +++ b/packages/backend/src/server/api/endpoints/i/favorites.ts @@ -1,8 +1,6 @@ -import $ from 'cafy'; -import { ID } from '@/misc/cafy-id'; -import define from '../../define'; -import { NoteFavorites } from '@/models/index'; -import { makePaginationQuery } from '../../common/make-pagination-query'; +import define from '../../define.js'; +import { NoteFavorites } from '@/models/index.js'; +import { makePaginationQuery } from '../../common/make-pagination-query.js'; export const meta = { tags: ['account', 'notes', 'favorites'], @@ -11,21 +9,6 @@ export const meta = { kind: 'read:favorites', - params: { - limit: { - validator: $.optional.num.range(1, 100), - default: 10, - }, - - sinceId: { - validator: $.optional.type(ID), - }, - - untilId: { - validator: $.optional.type(ID), - }, - }, - res: { type: 'array', optional: false, nullable: false, @@ -37,14 +20,24 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + limit: { type: 'integer', minimum: 1, maximum: 100, default: 10 }, + sinceId: { type: 'string', format: 'misskey:id' }, + untilId: { type: 'string', format: 'misskey:id' }, + }, + required: [], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, user) => { +export default define(meta, paramDef, async (ps, user) => { const query = makePaginationQuery(NoteFavorites.createQueryBuilder('favorite'), ps.sinceId, ps.untilId) .andWhere(`favorite.userId = :meId`, { meId: user.id }) .leftJoinAndSelect('favorite.note', 'note'); const favorites = await query - .take(ps.limit!) + .take(ps.limit) .getMany(); return await NoteFavorites.packMany(favorites, user); diff --git a/packages/backend/src/server/api/endpoints/i/gallery/likes.ts b/packages/backend/src/server/api/endpoints/i/gallery/likes.ts index f1c576359..a38383f30 100644 --- a/packages/backend/src/server/api/endpoints/i/gallery/likes.ts +++ b/packages/backend/src/server/api/endpoints/i/gallery/likes.ts @@ -1,8 +1,6 @@ -import $ from 'cafy'; -import { ID } from '@/misc/cafy-id'; -import define from '../../../define'; -import { GalleryLikes } from '@/models/index'; -import { makePaginationQuery } from '../../../common/make-pagination-query'; +import define from '../../../define.js'; +import { GalleryLikes } from '@/models/index.js'; +import { makePaginationQuery } from '../../../common/make-pagination-query.js'; export const meta = { tags: ['account', 'gallery'], @@ -11,47 +9,46 @@ export const meta = { kind: 'read:gallery-likes', - params: { - limit: { - validator: $.optional.num.range(1, 100), - default: 10, - }, - - sinceId: { - validator: $.optional.type(ID), - }, - - untilId: { - validator: $.optional.type(ID), - }, - }, - res: { - type: 'object', + type: 'array', optional: false, nullable: false, - properties: { - id: { - type: 'string', - optional: false, nullable: false, - format: 'id', + items: { + type: 'object', + optional: false, nullable: false, + properties: { + id: { + type: 'string', + optional: false, nullable: false, + format: 'id', + }, + post: { + type: 'object', + optional: false, nullable: false, + ref: 'GalleryPost', + }, }, - page: { - type: 'object', - optional: false, nullable: false, - ref: 'GalleryPost', - }, - }, + } }, } as const; +export const paramDef = { + type: 'object', + properties: { + limit: { type: 'integer', minimum: 1, maximum: 100, default: 10 }, + sinceId: { type: 'string', format: 'misskey:id' }, + untilId: { type: 'string', format: 'misskey:id' }, + }, + required: [], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, user) => { +export default define(meta, paramDef, async (ps, user) => { const query = makePaginationQuery(GalleryLikes.createQueryBuilder('like'), ps.sinceId, ps.untilId) .andWhere(`like.userId = :meId`, { meId: user.id }) .leftJoinAndSelect('like.post', 'post'); const likes = await query - .take(ps.limit!) + .take(ps.limit) .getMany(); return await GalleryLikes.packMany(likes, user); diff --git a/packages/backend/src/server/api/endpoints/i/gallery/posts.ts b/packages/backend/src/server/api/endpoints/i/gallery/posts.ts index d46d42f63..b4edb5f73 100644 --- a/packages/backend/src/server/api/endpoints/i/gallery/posts.ts +++ b/packages/backend/src/server/api/endpoints/i/gallery/posts.ts @@ -1,8 +1,6 @@ -import $ from 'cafy'; -import { ID } from '@/misc/cafy-id'; -import define from '../../../define'; -import { GalleryPosts } from '@/models/index'; -import { makePaginationQuery } from '../../../common/make-pagination-query'; +import define from '../../../define.js'; +import { GalleryPosts } from '@/models/index.js'; +import { makePaginationQuery } from '../../../common/make-pagination-query.js'; export const meta = { tags: ['account', 'gallery'], @@ -11,21 +9,6 @@ export const meta = { kind: 'read:gallery', - params: { - limit: { - validator: $.optional.num.range(1, 100), - default: 10, - }, - - sinceId: { - validator: $.optional.type(ID), - }, - - untilId: { - validator: $.optional.type(ID), - }, - }, - res: { type: 'array', optional: false, nullable: false, @@ -37,13 +20,23 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + limit: { type: 'integer', minimum: 1, maximum: 100, default: 10 }, + sinceId: { type: 'string', format: 'misskey:id' }, + untilId: { type: 'string', format: 'misskey:id' }, + }, + required: [], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, user) => { +export default define(meta, paramDef, async (ps, user) => { const query = makePaginationQuery(GalleryPosts.createQueryBuilder('post'), ps.sinceId, ps.untilId) .andWhere(`post.userId = :meId`, { meId: user.id }); const posts = await query - .take(ps.limit!) + .take(ps.limit) .getMany(); return await GalleryPosts.packMany(posts, user); diff --git a/packages/backend/src/server/api/endpoints/i/get-word-muted-notes-count.ts b/packages/backend/src/server/api/endpoints/i/get-word-muted-notes-count.ts index 4e1a4d3db..bc3e0aff4 100644 --- a/packages/backend/src/server/api/endpoints/i/get-word-muted-notes-count.ts +++ b/packages/backend/src/server/api/endpoints/i/get-word-muted-notes-count.ts @@ -1,5 +1,5 @@ -import define from '../../define'; -import { MutedNotes } from '@/models/index'; +import define from '../../define.js'; +import { MutedNotes } from '@/models/index.js'; export const meta = { tags: ['account'], @@ -8,9 +8,6 @@ export const meta = { kind: 'read:account', - params: { - }, - res: { type: 'object', optional: false, nullable: false, @@ -23,8 +20,14 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: {}, + required: [], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, user) => { +export default define(meta, paramDef, async (ps, user) => { return { count: await MutedNotes.count({ userId: user.id, diff --git a/packages/backend/src/server/api/endpoints/i/import-blocking.ts b/packages/backend/src/server/api/endpoints/i/import-blocking.ts index acc579742..c70704f9a 100644 --- a/packages/backend/src/server/api/endpoints/i/import-blocking.ts +++ b/packages/backend/src/server/api/endpoints/i/import-blocking.ts @@ -1,10 +1,8 @@ -import $ from 'cafy'; -import { ID } from '@/misc/cafy-id'; -import define from '../../define'; -import { createImportBlockingJob } from '@/queue/index'; +import define from '../../define.js'; +import { createImportBlockingJob } from '@/queue/index.js'; import ms from 'ms'; -import { ApiError } from '../../error'; -import { DriveFiles } from '@/models/index'; +import { ApiError } from '../../error.js'; +import { DriveFiles } from '@/models/index.js'; export const meta = { secure: true, @@ -15,12 +13,6 @@ export const meta = { max: 1, }, - params: { - fileId: { - validator: $.type(ID), - }, - }, - errors: { noSuchFile: { message: 'No such file.', @@ -48,8 +40,16 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + fileId: { type: 'string', format: 'misskey:id' }, + }, + required: ['fileId'], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, user) => { +export default define(meta, paramDef, async (ps, user) => { const file = await DriveFiles.findOne(ps.fileId); if (file == null) throw new ApiError(meta.errors.noSuchFile); diff --git a/packages/backend/src/server/api/endpoints/i/import-following.ts b/packages/backend/src/server/api/endpoints/i/import-following.ts index 35006746f..7e9175cbf 100644 --- a/packages/backend/src/server/api/endpoints/i/import-following.ts +++ b/packages/backend/src/server/api/endpoints/i/import-following.ts @@ -1,10 +1,8 @@ -import $ from 'cafy'; -import { ID } from '@/misc/cafy-id'; -import define from '../../define'; -import { createImportFollowingJob } from '@/queue/index'; +import define from '../../define.js'; +import { createImportFollowingJob } from '@/queue/index.js'; import ms from 'ms'; -import { ApiError } from '../../error'; -import { DriveFiles } from '@/models/index'; +import { ApiError } from '../../error.js'; +import { DriveFiles } from '@/models/index.js'; export const meta = { secure: true, @@ -14,12 +12,6 @@ export const meta = { max: 1, }, - params: { - fileId: { - validator: $.type(ID), - }, - }, - errors: { noSuchFile: { message: 'No such file.', @@ -47,8 +39,16 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + fileId: { type: 'string', format: 'misskey:id' }, + }, + required: ['fileId'], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, user) => { +export default define(meta, paramDef, async (ps, user) => { const file = await DriveFiles.findOne(ps.fileId); if (file == null) throw new ApiError(meta.errors.noSuchFile); diff --git a/packages/backend/src/server/api/endpoints/i/import-muting.ts b/packages/backend/src/server/api/endpoints/i/import-muting.ts index 7bbb2e008..abbf07212 100644 --- a/packages/backend/src/server/api/endpoints/i/import-muting.ts +++ b/packages/backend/src/server/api/endpoints/i/import-muting.ts @@ -1,10 +1,8 @@ -import $ from 'cafy'; -import { ID } from '@/misc/cafy-id'; -import define from '../../define'; -import { createImportMutingJob } from '@/queue/index'; +import define from '../../define.js'; +import { createImportMutingJob } from '@/queue/index.js'; import ms from 'ms'; -import { ApiError } from '../../error'; -import { DriveFiles } from '@/models/index'; +import { ApiError } from '../../error.js'; +import { DriveFiles } from '@/models/index.js'; export const meta = { secure: true, @@ -15,12 +13,6 @@ export const meta = { max: 1, }, - params: { - fileId: { - validator: $.type(ID), - }, - }, - errors: { noSuchFile: { message: 'No such file.', @@ -48,8 +40,16 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + fileId: { type: 'string', format: 'misskey:id' }, + }, + required: ['fileId'], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, user) => { +export default define(meta, paramDef, async (ps, user) => { const file = await DriveFiles.findOne(ps.fileId); if (file == null) throw new ApiError(meta.errors.noSuchFile); diff --git a/packages/backend/src/server/api/endpoints/i/import-user-lists.ts b/packages/backend/src/server/api/endpoints/i/import-user-lists.ts index 759d41b6c..be162817f 100644 --- a/packages/backend/src/server/api/endpoints/i/import-user-lists.ts +++ b/packages/backend/src/server/api/endpoints/i/import-user-lists.ts @@ -1,10 +1,8 @@ -import $ from 'cafy'; -import { ID } from '@/misc/cafy-id'; -import define from '../../define'; -import { createImportUserListsJob } from '@/queue/index'; +import define from '../../define.js'; +import { createImportUserListsJob } from '@/queue/index.js'; import ms from 'ms'; -import { ApiError } from '../../error'; -import { DriveFiles } from '@/models/index'; +import { ApiError } from '../../error.js'; +import { DriveFiles } from '@/models/index.js'; export const meta = { secure: true, @@ -14,12 +12,6 @@ export const meta = { max: 1, }, - params: { - fileId: { - validator: $.type(ID), - }, - }, - errors: { noSuchFile: { message: 'No such file.', @@ -47,8 +39,16 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + fileId: { type: 'string', format: 'misskey:id' }, + }, + required: ['fileId'], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, user) => { +export default define(meta, paramDef, async (ps, user) => { const file = await DriveFiles.findOne(ps.fileId); if (file == null) throw new ApiError(meta.errors.noSuchFile); diff --git a/packages/backend/src/server/api/endpoints/i/notifications.ts b/packages/backend/src/server/api/endpoints/i/notifications.ts index 59efd32bb..7d9bd44d1 100644 --- a/packages/backend/src/server/api/endpoints/i/notifications.ts +++ b/packages/backend/src/server/api/endpoints/i/notifications.ts @@ -1,12 +1,10 @@ -import $ from 'cafy'; -import { ID } from '@/misc/cafy-id'; -import { readNotification } from '../../common/read-notification'; -import define from '../../define'; -import { makePaginationQuery } from '../../common/make-pagination-query'; -import { generateMutedInstanceNotificationQuery } from '../../common/generate-muted-instance-query'; -import { Notifications, Followings, Mutings, Users } from '@/models/index'; -import { notificationTypes } from '@/types'; -import read from '@/services/note/read'; +import { readNotification } from '../../common/read-notification.js'; +import define from '../../define.js'; +import { makePaginationQuery } from '../../common/make-pagination-query.js'; +import { generateMutedInstanceNotificationQuery } from '../../common/generate-muted-instance-query.js'; +import { Notifications, Followings, Mutings, Users } from '@/models/index.js'; +import { notificationTypes } from '@/types.js'; +import read from '@/services/note/read.js'; import { Brackets } from 'typeorm'; export const meta = { @@ -16,44 +14,6 @@ export const meta = { kind: 'read:notifications', - params: { - limit: { - validator: $.optional.num.range(1, 100), - default: 10, - }, - - sinceId: { - validator: $.optional.type(ID), - }, - - untilId: { - validator: $.optional.type(ID), - }, - - following: { - validator: $.optional.bool, - default: false, - }, - - unreadOnly: { - validator: $.optional.bool, - default: false, - }, - - markAsRead: { - validator: $.optional.bool, - default: true, - }, - - includeTypes: { - validator: $.optional.arr($.str.or(notificationTypes as unknown as string[])), - }, - - excludeTypes: { - validator: $.optional.arr($.str.or(notificationTypes as unknown as string[])), - }, - }, - res: { type: 'array', optional: false, nullable: false, @@ -65,8 +25,27 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + limit: { type: 'integer', minimum: 1, maximum: 100, default: 10 }, + sinceId: { type: 'string', format: 'misskey:id' }, + untilId: { type: 'string', format: 'misskey:id' }, + following: { type: 'boolean', default: false }, + unreadOnly: { type: 'boolean', default: false }, + markAsRead: { type: 'boolean', default: true }, + includeTypes: { type: 'array', items: { + type: 'string', enum: notificationTypes, + } }, + excludeTypes: { type: 'array', items: { + type: 'string', enum: notificationTypes, + } }, + }, + required: [], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, user) => { +export default define(meta, paramDef, async (ps, user) => { // includeTypes が空の場合はクエリしない if (ps.includeTypes && ps.includeTypes.length === 0) { return []; @@ -92,10 +71,16 @@ export default define(meta, async (ps, user) => { .leftJoinAndSelect('notification.notifier', 'notifier') .leftJoinAndSelect('notification.note', 'note') .leftJoinAndSelect('note.user', 'user') + .leftJoinAndSelect('user.avatar', 'avatar') + .leftJoinAndSelect('user.banner', 'banner') .leftJoinAndSelect('note.reply', 'reply') .leftJoinAndSelect('note.renote', 'renote') .leftJoinAndSelect('reply.user', 'replyUser') - .leftJoinAndSelect('renote.user', 'renoteUser'); + .leftJoinAndSelect('replyUser.avatar', 'replyUserAvatar') + .leftJoinAndSelect('replyUser.banner', 'replyUserBanner') + .leftJoinAndSelect('renote.user', 'renoteUser') + .leftJoinAndSelect('renoteUser.avatar', 'renoteUserAvatar') + .leftJoinAndSelect('renoteUser.banner', 'renoteUserBanner'); query.andWhere(new Brackets(qb => { qb .where(`notification.notifierId NOT IN (${ mutingQuery.getQuery() })`) @@ -125,7 +110,7 @@ export default define(meta, async (ps, user) => { query.andWhere(`notification.isRead = false`); } - const notifications = await query.take(ps.limit!).getMany(); + const notifications = await query.take(ps.limit).getMany(); // Mark all as read if (notifications.length > 0 && ps.markAsRead) { diff --git a/packages/backend/src/server/api/endpoints/i/page-likes.ts b/packages/backend/src/server/api/endpoints/i/page-likes.ts index 59239c744..71e326e2f 100644 --- a/packages/backend/src/server/api/endpoints/i/page-likes.ts +++ b/packages/backend/src/server/api/endpoints/i/page-likes.ts @@ -1,8 +1,6 @@ -import $ from 'cafy'; -import { ID } from '@/misc/cafy-id'; -import define from '../../define'; -import { PageLikes } from '@/models/index'; -import { makePaginationQuery } from '../../common/make-pagination-query'; +import define from '../../define.js'; +import { PageLikes } from '@/models/index.js'; +import { makePaginationQuery } from '../../common/make-pagination-query.js'; export const meta = { tags: ['account', 'pages'], @@ -11,48 +9,46 @@ export const meta = { kind: 'read:page-likes', - params: { - limit: { - validator: $.optional.num.range(1, 100), - default: 10, - }, - - sinceId: { - validator: $.optional.type(ID), - }, - - untilId: { - validator: $.optional.type(ID), - }, - }, - res: { - type: 'object', + type: 'array', optional: false, nullable: false, - properties: { - id: { - type: 'string', - optional: false, nullable: false, - format: 'id', + items: { + type: 'object', + properties: { + id: { + type: 'string', + optional: false, nullable: false, + format: 'id', + }, + page: { + type: 'object', + optional: false, nullable: false, + ref: 'Page', + }, }, - page: { - type: 'object', - optional: false, nullable: false, - ref: 'Page', - }, - }, + } }, } as const; +export const paramDef = { + type: 'object', + properties: { + limit: { type: 'integer', minimum: 1, maximum: 100, default: 10 }, + sinceId: { type: 'string', format: 'misskey:id' }, + untilId: { type: 'string', format: 'misskey:id' }, + }, + required: [], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, user) => { +export default define(meta, paramDef, async (ps, user) => { const query = makePaginationQuery(PageLikes.createQueryBuilder('like'), ps.sinceId, ps.untilId) .andWhere(`like.userId = :meId`, { meId: user.id }) .leftJoinAndSelect('like.page', 'page'); const likes = await query - .take(ps.limit!) + .take(ps.limit) .getMany(); - return await PageLikes.packMany(likes, user); + return PageLikes.packMany(likes, user); }); diff --git a/packages/backend/src/server/api/endpoints/i/pages.ts b/packages/backend/src/server/api/endpoints/i/pages.ts index bef775d06..f28aed3fd 100644 --- a/packages/backend/src/server/api/endpoints/i/pages.ts +++ b/packages/backend/src/server/api/endpoints/i/pages.ts @@ -1,8 +1,6 @@ -import $ from 'cafy'; -import { ID } from '@/misc/cafy-id'; -import define from '../../define'; -import { Pages } from '@/models/index'; -import { makePaginationQuery } from '../../common/make-pagination-query'; +import define from '../../define.js'; +import { Pages } from '@/models/index.js'; +import { makePaginationQuery } from '../../common/make-pagination-query.js'; export const meta = { tags: ['account', 'pages'], @@ -11,21 +9,6 @@ export const meta = { kind: 'read:pages', - params: { - limit: { - validator: $.optional.num.range(1, 100), - default: 10, - }, - - sinceId: { - validator: $.optional.type(ID), - }, - - untilId: { - validator: $.optional.type(ID), - }, - }, - res: { type: 'array', optional: false, nullable: false, @@ -37,13 +20,23 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + limit: { type: 'integer', minimum: 1, maximum: 100, default: 10 }, + sinceId: { type: 'string', format: 'misskey:id' }, + untilId: { type: 'string', format: 'misskey:id' }, + }, + required: [], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, user) => { +export default define(meta, paramDef, async (ps, user) => { const query = makePaginationQuery(Pages.createQueryBuilder('page'), ps.sinceId, ps.untilId) .andWhere(`page.userId = :meId`, { meId: user.id }); const pages = await query - .take(ps.limit!) + .take(ps.limit) .getMany(); return await Pages.packMany(pages); diff --git a/packages/backend/src/server/api/endpoints/i/pin.ts b/packages/backend/src/server/api/endpoints/i/pin.ts index a940d1b99..67b7026be 100644 --- a/packages/backend/src/server/api/endpoints/i/pin.ts +++ b/packages/backend/src/server/api/endpoints/i/pin.ts @@ -1,9 +1,7 @@ -import $ from 'cafy'; -import { ID } from '@/misc/cafy-id'; -import { addPinned } from '@/services/i/pin'; -import define from '../../define'; -import { ApiError } from '../../error'; -import { Users } from '@/models/index'; +import { addPinned } from '@/services/i/pin.js'; +import define from '../../define.js'; +import { ApiError } from '../../error.js'; +import { Users } from '@/models/index.js'; export const meta = { tags: ['account', 'notes'], @@ -12,12 +10,6 @@ export const meta = { kind: 'write:account', - params: { - noteId: { - validator: $.type(ID), - }, - }, - errors: { noSuchNote: { message: 'No such note.', @@ -45,8 +37,16 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + noteId: { type: 'string', format: 'misskey:id' }, + }, + required: ['noteId'], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, user) => { +export default define(meta, paramDef, async (ps, user) => { await addPinned(user, ps.noteId).catch(e => { if (e.id === '70c4e51f-5bea-449c-a030-53bee3cce202') throw new ApiError(meta.errors.noSuchNote); if (e.id === '15a018eb-58e5-4da1-93be-330fcc5e4e1a') throw new ApiError(meta.errors.pinLimitExceeded); diff --git a/packages/backend/src/server/api/endpoints/i/read-all-messaging-messages.ts b/packages/backend/src/server/api/endpoints/i/read-all-messaging-messages.ts index 4e4fb3840..2e291a34a 100644 --- a/packages/backend/src/server/api/endpoints/i/read-all-messaging-messages.ts +++ b/packages/backend/src/server/api/endpoints/i/read-all-messaging-messages.ts @@ -1,6 +1,6 @@ -import { publishMainStream } from '@/services/stream'; -import define from '../../define'; -import { MessagingMessages, UserGroupJoinings } from '@/models/index'; +import { publishMainStream } from '@/services/stream.js'; +import define from '../../define.js'; +import { MessagingMessages, UserGroupJoinings } from '@/models/index.js'; export const meta = { tags: ['account', 'messaging'], @@ -8,13 +8,16 @@ export const meta = { requireCredential: true, kind: 'write:account', +} as const; - params: { - }, +export const paramDef = { + type: 'object', + properties: {}, + required: [], } as const; // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, user) => { +export default define(meta, paramDef, async (ps, user) => { // Update documents await MessagingMessages.update({ recipientId: user.id, diff --git a/packages/backend/src/server/api/endpoints/i/read-all-unread-notes.ts b/packages/backend/src/server/api/endpoints/i/read-all-unread-notes.ts index 99f17ddfc..49f3deb33 100644 --- a/packages/backend/src/server/api/endpoints/i/read-all-unread-notes.ts +++ b/packages/backend/src/server/api/endpoints/i/read-all-unread-notes.ts @@ -1,6 +1,6 @@ -import { publishMainStream } from '@/services/stream'; -import define from '../../define'; -import { NoteUnreads } from '@/models/index'; +import { publishMainStream } from '@/services/stream.js'; +import define from '../../define.js'; +import { NoteUnreads } from '@/models/index.js'; export const meta = { tags: ['account'], @@ -8,13 +8,16 @@ export const meta = { requireCredential: true, kind: 'write:account', +} as const; - params: { - }, +export const paramDef = { + type: 'object', + properties: {}, + required: [], } as const; // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, user) => { +export default define(meta, paramDef, async (ps, user) => { // Remove documents await NoteUnreads.delete({ userId: user.id, diff --git a/packages/backend/src/server/api/endpoints/i/read-announcement.ts b/packages/backend/src/server/api/endpoints/i/read-announcement.ts index e9bb66264..647fa77fa 100644 --- a/packages/backend/src/server/api/endpoints/i/read-announcement.ts +++ b/packages/backend/src/server/api/endpoints/i/read-announcement.ts @@ -1,10 +1,8 @@ -import $ from 'cafy'; -import { ID } from '@/misc/cafy-id'; -import define from '../../define'; -import { ApiError } from '../../error'; -import { genId } from '@/misc/gen-id'; -import { AnnouncementReads, Announcements, Users } from '@/models/index'; -import { publishMainStream } from '@/services/stream'; +import define from '../../define.js'; +import { ApiError } from '../../error.js'; +import { genId } from '@/misc/gen-id.js'; +import { AnnouncementReads, Announcements, Users } from '@/models/index.js'; +import { publishMainStream } from '@/services/stream.js'; export const meta = { tags: ['account'], @@ -13,12 +11,6 @@ export const meta = { kind: 'write:account', - params: { - announcementId: { - validator: $.type(ID), - }, - }, - errors: { noSuchAnnouncement: { message: 'No such announcement.', @@ -28,8 +20,16 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + announcementId: { type: 'string', format: 'misskey:id' }, + }, + required: ['announcementId'], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, user) => { +export default define(meta, paramDef, async (ps, user) => { // Check if announcement exists const announcement = await Announcements.findOne(ps.announcementId); diff --git a/packages/backend/src/server/api/endpoints/i/regenerate-token.ts b/packages/backend/src/server/api/endpoints/i/regenerate-token.ts index a20719363..771c98b21 100644 --- a/packages/backend/src/server/api/endpoints/i/regenerate-token.ts +++ b/packages/backend/src/server/api/endpoints/i/regenerate-token.ts @@ -1,24 +1,25 @@ -import $ from 'cafy'; -import * as bcrypt from 'bcryptjs'; -import { publishMainStream, publishUserEvent } from '@/services/stream'; -import generateUserToken from '../../common/generate-native-user-token'; -import define from '../../define'; -import { Users, UserProfiles } from '@/models/index'; +import bcrypt from 'bcryptjs'; +import { publishMainStream, publishUserEvent } from '@/services/stream.js'; +import generateUserToken from '../../common/generate-native-user-token.js'; +import define from '../../define.js'; +import { Users, UserProfiles } from '@/models/index.js'; export const meta = { requireCredential: true, secure: true, +} as const; - params: { - password: { - validator: $.str, - }, +export const paramDef = { + type: 'object', + properties: { + password: { type: 'string' }, }, + required: ['password'], } as const; // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, user) => { +export default define(meta, paramDef, async (ps, user) => { const profile = await UserProfiles.findOneOrFail(user.id); // Compare password diff --git a/packages/backend/src/server/api/endpoints/i/registry/get-all.ts b/packages/backend/src/server/api/endpoints/i/registry/get-all.ts index 2941b441e..d0b16dbc4 100644 --- a/packages/backend/src/server/api/endpoints/i/registry/get-all.ts +++ b/packages/backend/src/server/api/endpoints/i/registry/get-all.ts @@ -1,22 +1,24 @@ -import $ from 'cafy'; -import define from '../../../define'; -import { RegistryItems } from '@/models/index'; +import define from '../../../define.js'; +import { RegistryItems } from '@/models/index.js'; export const meta = { requireCredential: true, secure: true, +} as const; - params: { - scope: { - validator: $.optional.arr($.str.match(/^[a-zA-Z0-9_]+$/)), - default: [], - }, +export const paramDef = { + type: 'object', + properties: { + scope: { type: 'array', default: [], items: { + type: 'string', pattern: /^[a-zA-Z0-9_]+$/.toString().slice(1, -1), + } }, }, + required: [], } as const; // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, user) => { +export default define(meta, paramDef, async (ps, user) => { const query = RegistryItems.createQueryBuilder('item') .where('item.domain IS NULL') .andWhere('item.userId = :userId', { userId: user.id }) diff --git a/packages/backend/src/server/api/endpoints/i/registry/get-detail.ts b/packages/backend/src/server/api/endpoints/i/registry/get-detail.ts index 51371353c..cc5d5a8c6 100644 --- a/packages/backend/src/server/api/endpoints/i/registry/get-detail.ts +++ b/packages/backend/src/server/api/endpoints/i/registry/get-detail.ts @@ -1,24 +1,12 @@ -import $ from 'cafy'; -import define from '../../../define'; -import { RegistryItems } from '@/models/index'; -import { ApiError } from '../../../error'; +import define from '../../../define.js'; +import { RegistryItems } from '@/models/index.js'; +import { ApiError } from '../../../error.js'; export const meta = { requireCredential: true, secure: true, - params: { - key: { - validator: $.str, - }, - - scope: { - validator: $.optional.arr($.str.match(/^[a-zA-Z0-9_]+$/)), - default: [], - }, - }, - errors: { noSuchKey: { message: 'No such key.', @@ -28,8 +16,19 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + key: { type: 'string' }, + scope: { type: 'array', default: [], items: { + type: 'string', pattern: /^[a-zA-Z0-9_]+$/.toString().slice(1, -1), + } }, + }, + required: ['key'], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, user) => { +export default define(meta, paramDef, async (ps, user) => { const query = RegistryItems.createQueryBuilder('item') .where('item.domain IS NULL') .andWhere('item.userId = :userId', { userId: user.id }) diff --git a/packages/backend/src/server/api/endpoints/i/registry/get.ts b/packages/backend/src/server/api/endpoints/i/registry/get.ts index ac617defb..a79319744 100644 --- a/packages/backend/src/server/api/endpoints/i/registry/get.ts +++ b/packages/backend/src/server/api/endpoints/i/registry/get.ts @@ -1,24 +1,12 @@ -import $ from 'cafy'; -import define from '../../../define'; -import { RegistryItems } from '@/models/index'; -import { ApiError } from '../../../error'; +import define from '../../../define.js'; +import { RegistryItems } from '@/models/index.js'; +import { ApiError } from '../../../error.js'; export const meta = { requireCredential: true, secure: true, - params: { - key: { - validator: $.str, - }, - - scope: { - validator: $.optional.arr($.str.match(/^[a-zA-Z0-9_]+$/)), - default: [], - }, - }, - errors: { noSuchKey: { message: 'No such key.', @@ -28,8 +16,19 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + key: { type: 'string' }, + scope: { type: 'array', default: [], items: { + type: 'string', pattern: /^[a-zA-Z0-9_]+$/.toString().slice(1, -1), + } }, + }, + required: ['key'], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, user) => { +export default define(meta, paramDef, async (ps, user) => { const query = RegistryItems.createQueryBuilder('item') .where('item.domain IS NULL') .andWhere('item.userId = :userId', { userId: user.id }) diff --git a/packages/backend/src/server/api/endpoints/i/registry/keys-with-type.ts b/packages/backend/src/server/api/endpoints/i/registry/keys-with-type.ts index 044592218..ac209c06a 100644 --- a/packages/backend/src/server/api/endpoints/i/registry/keys-with-type.ts +++ b/packages/backend/src/server/api/endpoints/i/registry/keys-with-type.ts @@ -1,22 +1,24 @@ -import $ from 'cafy'; -import define from '../../../define'; -import { RegistryItems } from '@/models/index'; +import define from '../../../define.js'; +import { RegistryItems } from '@/models/index.js'; export const meta = { requireCredential: true, secure: true, +} as const; - params: { - scope: { - validator: $.optional.arr($.str.match(/^[a-zA-Z0-9_]+$/)), - default: [], - }, +export const paramDef = { + type: 'object', + properties: { + scope: { type: 'array', default: [], items: { + type: 'string', pattern: /^[a-zA-Z0-9_]+$/.toString().slice(1, -1), + } }, }, + required: [], } as const; // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, user) => { +export default define(meta, paramDef, async (ps, user) => { const query = RegistryItems.createQueryBuilder('item') .where('item.domain IS NULL') .andWhere('item.userId = :userId', { userId: user.id }) diff --git a/packages/backend/src/server/api/endpoints/i/registry/keys.ts b/packages/backend/src/server/api/endpoints/i/registry/keys.ts index a3c9d0e5e..5ea1a9d34 100644 --- a/packages/backend/src/server/api/endpoints/i/registry/keys.ts +++ b/packages/backend/src/server/api/endpoints/i/registry/keys.ts @@ -1,22 +1,24 @@ -import $ from 'cafy'; -import define from '../../../define'; -import { RegistryItems } from '@/models/index'; +import define from '../../../define.js'; +import { RegistryItems } from '@/models/index.js'; export const meta = { requireCredential: true, secure: true, +} as const; - params: { - scope: { - validator: $.optional.arr($.str.match(/^[a-zA-Z0-9_]+$/)), - default: [], - }, +export const paramDef = { + type: 'object', + properties: { + scope: { type: 'array', default: [], items: { + type: 'string', pattern: /^[a-zA-Z0-9_]+$/.toString().slice(1, -1), + } }, }, + required: [], } as const; // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, user) => { +export default define(meta, paramDef, async (ps, user) => { const query = RegistryItems.createQueryBuilder('item') .select('item.key') .where('item.domain IS NULL') diff --git a/packages/backend/src/server/api/endpoints/i/registry/remove.ts b/packages/backend/src/server/api/endpoints/i/registry/remove.ts index 08185f224..92473654c 100644 --- a/packages/backend/src/server/api/endpoints/i/registry/remove.ts +++ b/packages/backend/src/server/api/endpoints/i/registry/remove.ts @@ -1,24 +1,12 @@ -import $ from 'cafy'; -import define from '../../../define'; -import { RegistryItems } from '@/models/index'; -import { ApiError } from '../../../error'; +import define from '../../../define.js'; +import { RegistryItems } from '@/models/index.js'; +import { ApiError } from '../../../error.js'; export const meta = { requireCredential: true, secure: true, - params: { - key: { - validator: $.str, - }, - - scope: { - validator: $.optional.arr($.str.match(/^[a-zA-Z0-9_]+$/)), - default: [], - }, - }, - errors: { noSuchKey: { message: 'No such key.', @@ -28,8 +16,19 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + key: { type: 'string' }, + scope: { type: 'array', default: [], items: { + type: 'string', pattern: /^[a-zA-Z0-9_]+$/.toString().slice(1, -1), + } }, + }, + required: ['key'], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, user) => { +export default define(meta, paramDef, async (ps, user) => { const query = RegistryItems.createQueryBuilder('item') .where('item.domain IS NULL') .andWhere('item.userId = :userId', { userId: user.id }) diff --git a/packages/backend/src/server/api/endpoints/i/registry/scopes.ts b/packages/backend/src/server/api/endpoints/i/registry/scopes.ts index 9de68ac6e..de4b313e2 100644 --- a/packages/backend/src/server/api/endpoints/i/registry/scopes.ts +++ b/packages/backend/src/server/api/endpoints/i/registry/scopes.ts @@ -1,17 +1,20 @@ -import define from '../../../define'; -import { RegistryItems } from '@/models/index'; +import define from '../../../define.js'; +import { RegistryItems } from '@/models/index.js'; export const meta = { requireCredential: true, secure: true, +} as const; - params: { - }, +export const paramDef = { + type: 'object', + properties: {}, + required: [], } as const; // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, user) => { +export default define(meta, paramDef, async (ps, user) => { const query = RegistryItems.createQueryBuilder('item') .select('item.scope') .where('item.domain IS NULL') diff --git a/packages/backend/src/server/api/endpoints/i/registry/set.ts b/packages/backend/src/server/api/endpoints/i/registry/set.ts index 27884046b..d380b428a 100644 --- a/packages/backend/src/server/api/endpoints/i/registry/set.ts +++ b/packages/backend/src/server/api/endpoints/i/registry/set.ts @@ -1,32 +1,28 @@ -import $ from 'cafy'; -import { publishMainStream } from '@/services/stream'; -import define from '../../../define'; -import { RegistryItems } from '@/models/index'; -import { genId } from '@/misc/gen-id'; +import { publishMainStream } from '@/services/stream.js'; +import define from '../../../define.js'; +import { RegistryItems } from '@/models/index.js'; +import { genId } from '@/misc/gen-id.js'; export const meta = { requireCredential: true, secure: true, +} as const; - params: { - key: { - validator: $.str.min(1), - }, - - value: { - validator: $.nullable.any, - }, - - scope: { - validator: $.optional.arr($.str.match(/^[a-zA-Z0-9_]+$/)), - default: [], - }, +export const paramDef = { + type: 'object', + properties: { + key: { type: 'string', minLength: 1 }, + value: {}, + scope: { type: 'array', default: [], items: { + type: 'string', pattern: /^[a-zA-Z0-9_]+$/.toString().slice(1, -1), + } }, }, + required: ['key', 'value'], } as const; // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, user) => { +export default define(meta, paramDef, async (ps, user) => { const query = RegistryItems.createQueryBuilder('item') .where('item.domain IS NULL') .andWhere('item.userId = :userId', { userId: user.id }) diff --git a/packages/backend/src/server/api/endpoints/i/revoke-token.ts b/packages/backend/src/server/api/endpoints/i/revoke-token.ts index 51721c5b5..b957fd079 100644 --- a/packages/backend/src/server/api/endpoints/i/revoke-token.ts +++ b/packages/backend/src/server/api/endpoints/i/revoke-token.ts @@ -1,23 +1,23 @@ -import $ from 'cafy'; -import define from '../../define'; -import { AccessTokens } from '@/models/index'; -import { ID } from '@/misc/cafy-id'; -import { publishUserEvent } from '@/services/stream'; +import define from '../../define.js'; +import { AccessTokens } from '@/models/index.js'; +import { publishUserEvent } from '@/services/stream.js'; export const meta = { requireCredential: true, secure: true, +} as const; - params: { - tokenId: { - validator: $.type(ID), - }, +export const paramDef = { + type: 'object', + properties: { + tokenId: { type: 'string', format: 'misskey:id' }, }, + required: ['tokenId'], } as const; // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, user) => { +export default define(meta, paramDef, async (ps, user) => { const token = await AccessTokens.findOne(ps.tokenId); if (token) { diff --git a/packages/backend/src/server/api/endpoints/i/signin-history.ts b/packages/backend/src/server/api/endpoints/i/signin-history.ts index 796e2ec30..ca3741166 100644 --- a/packages/backend/src/server/api/endpoints/i/signin-history.ts +++ b/packages/backend/src/server/api/endpoints/i/signin-history.ts @@ -1,36 +1,29 @@ -import $ from 'cafy'; -import { ID } from '@/misc/cafy-id'; -import define from '../../define'; -import { Signins } from '@/models/index'; -import { makePaginationQuery } from '../../common/make-pagination-query'; +import define from '../../define.js'; +import { Signins } from '@/models/index.js'; +import { makePaginationQuery } from '../../common/make-pagination-query.js'; export const meta = { requireCredential: true, secure: true, +} as const; - params: { - limit: { - validator: $.optional.num.range(1, 100), - default: 10, - }, - - sinceId: { - validator: $.optional.type(ID), - }, - - untilId: { - validator: $.optional.type(ID), - }, +export const paramDef = { + type: 'object', + properties: { + limit: { type: 'integer', minimum: 1, maximum: 100, default: 10 }, + sinceId: { type: 'string', format: 'misskey:id' }, + untilId: { type: 'string', format: 'misskey:id' }, }, + required: [], } as const; // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, user) => { +export default define(meta, paramDef, async (ps, user) => { const query = makePaginationQuery(Signins.createQueryBuilder('signin'), ps.sinceId, ps.untilId) .andWhere(`signin.userId = :meId`, { meId: user.id }); - const history = await query.take(ps.limit!).getMany(); + const history = await query.take(ps.limit).getMany(); return await Promise.all(history.map(record => Signins.pack(record))); }); diff --git a/packages/backend/src/server/api/endpoints/i/unpin.ts b/packages/backend/src/server/api/endpoints/i/unpin.ts index 9c82b7496..9912689da 100644 --- a/packages/backend/src/server/api/endpoints/i/unpin.ts +++ b/packages/backend/src/server/api/endpoints/i/unpin.ts @@ -1,9 +1,7 @@ -import $ from 'cafy'; -import { ID } from '@/misc/cafy-id'; -import { removePinned } from '@/services/i/pin'; -import define from '../../define'; -import { ApiError } from '../../error'; -import { Users } from '@/models/index'; +import { removePinned } from '@/services/i/pin.js'; +import define from '../../define.js'; +import { ApiError } from '../../error.js'; +import { Users } from '@/models/index.js'; export const meta = { tags: ['account', 'notes'], @@ -12,12 +10,6 @@ export const meta = { kind: 'write:account', - params: { - noteId: { - validator: $.type(ID), - }, - }, - errors: { noSuchNote: { message: 'No such note.', @@ -33,8 +25,16 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + noteId: { type: 'string', format: 'misskey:id' }, + }, + required: ['noteId'], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, user) => { +export default define(meta, paramDef, async (ps, user) => { await removePinned(user, ps.noteId).catch(e => { if (e.id === 'b302d4cf-c050-400a-bbb3-be208681f40c') throw new ApiError(meta.errors.noSuchNote); throw e; diff --git a/packages/backend/src/server/api/endpoints/i/update-email.ts b/packages/backend/src/server/api/endpoints/i/update-email.ts index b4479aa50..389ff1b81 100644 --- a/packages/backend/src/server/api/endpoints/i/update-email.ts +++ b/packages/backend/src/server/api/endpoints/i/update-email.ts @@ -1,14 +1,13 @@ -import $ from 'cafy'; -import { publishMainStream } from '@/services/stream'; -import define from '../../define'; +import { publishMainStream } from '@/services/stream.js'; +import define from '../../define.js'; import rndstr from 'rndstr'; -import config from '@/config/index'; +import config from '@/config/index.js'; import ms from 'ms'; -import * as bcrypt from 'bcryptjs'; -import { Users, UserProfiles } from '@/models/index'; -import { sendEmail } from '@/services/send-email'; -import { ApiError } from '../../error'; -import { validateEmailForAccount } from '@/services/validate-email-for-account'; +import bcrypt from 'bcryptjs'; +import { Users, UserProfiles } from '@/models/index.js'; +import { sendEmail } from '@/services/send-email.js'; +import { ApiError } from '../../error.js'; +import { validateEmailForAccount } from '@/services/validate-email-for-account.js'; export const meta = { requireCredential: true, @@ -20,16 +19,6 @@ export const meta = { max: 3, }, - params: { - password: { - validator: $.str, - }, - - email: { - validator: $.optional.nullable.str, - }, - }, - errors: { incorrectPassword: { message: 'Incorrect password.', @@ -45,8 +34,17 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + password: { type: 'string' }, + email: { type: 'string', nullable: true }, + }, + required: ['password'], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, user) => { +export default define(meta, paramDef, async (ps, user) => { const profile = await UserProfiles.findOneOrFail(user.id); // Compare password diff --git a/packages/backend/src/server/api/endpoints/i/update.ts b/packages/backend/src/server/api/endpoints/i/update.ts index aec7bbd2e..85d0a6254 100644 --- a/packages/backend/src/server/api/endpoints/i/update.ts +++ b/packages/backend/src/server/api/endpoints/i/update.ts @@ -1,21 +1,19 @@ -const RE2 = require('re2'); -import $ from 'cafy'; +import RE2 from 're2'; import * as mfm from 'mfm-js'; -import { ID } from '@/misc/cafy-id'; -import { publishMainStream, publishUserEvent } from '@/services/stream'; -import acceptAllFollowRequests from '@/services/following/requests/accept-all'; -import { publishToFollowers } from '@/services/i/update'; -import define from '../../define'; -import { extractCustomEmojisFromMfm } from '@/misc/extract-custom-emojis-from-mfm'; -import { extractHashtags } from '@/misc/extract-hashtags'; -import * as langmap from 'langmap'; -import { updateUsertags } from '@/services/update-hashtag'; -import { ApiError } from '../../error'; -import { Users, DriveFiles, UserProfiles, Pages } from '@/models/index'; -import { User } from '@/models/entities/user'; -import { UserProfile } from '@/models/entities/user-profile'; -import { notificationTypes } from '@/types'; -import { normalizeForSearch } from '@/misc/normalize-for-search'; +import { publishMainStream, publishUserEvent } from '@/services/stream.js'; +import acceptAllFollowRequests from '@/services/following/requests/accept-all.js'; +import { publishToFollowers } from '@/services/i/update.js'; +import define from '../../define.js'; +import { extractCustomEmojisFromMfm } from '@/misc/extract-custom-emojis-from-mfm.js'; +import { extractHashtags } from '@/misc/extract-hashtags.js'; +import { updateUsertags } from '@/services/update-hashtag.js'; +import { ApiError } from '../../error.js'; +import { Users, DriveFiles, UserProfiles, Pages } from '@/models/index.js'; +import { User } from '@/models/entities/user.js'; +import { UserProfile } from '@/models/entities/user-profile.js'; +import { notificationTypes } from '@/types.js'; +import { normalizeForSearch } from '@/misc/normalize-for-search.js'; +import { langmap } from '@/misc/langmap.js'; export const meta = { tags: ['account'], @@ -24,116 +22,6 @@ export const meta = { kind: 'write:account', - params: { - name: { - validator: $.optional.nullable.use(Users.validateName), - }, - - description: { - validator: $.optional.nullable.use(Users.validateDescription), - }, - - lang: { - validator: $.optional.nullable.str.or(Object.keys(langmap)), - }, - - location: { - validator: $.optional.nullable.use(Users.validateLocation), - }, - - birthday: { - validator: $.optional.nullable.use(Users.validateBirthday), - }, - - avatarId: { - validator: $.optional.nullable.type(ID), - }, - - bannerId: { - validator: $.optional.nullable.type(ID), - }, - - fields: { - validator: $.optional.arr($.object()).range(1, 4), - }, - - isLocked: { - validator: $.optional.bool, - }, - - isExplorable: { - validator: $.optional.bool, - }, - - hideOnlineStatus: { - validator: $.optional.bool, - }, - - publicReactions: { - validator: $.optional.bool, - }, - - ffVisibility: { - validator: $.optional.str, - }, - - carefulBot: { - validator: $.optional.bool, - }, - - autoAcceptFollowed: { - validator: $.optional.bool, - }, - - noCrawle: { - validator: $.optional.bool, - }, - - isBot: { - validator: $.optional.bool, - }, - - isCat: { - validator: $.optional.bool, - }, - - showTimelineReplies: { - validator: $.optional.bool, - }, - - injectFeaturedNote: { - validator: $.optional.bool, - }, - - receiveAnnouncementEmail: { - validator: $.optional.bool, - }, - - alwaysMarkNsfw: { - validator: $.optional.bool, - }, - - pinnedPageId: { - validator: $.optional.nullable.type(ID), - }, - - mutedWords: { - validator: $.optional.arr($.either($.arr($.str.min(1)).min(1), $.str)), - }, - - mutedInstances: { - validator: $.optional.arr($.str), - }, - - mutingNotificationTypes: { - validator: $.optional.arr($.str.or(notificationTypes as unknown as string[])), - }, - - emailNotificationTypes: { - validator: $.optional.arr($.str), - }, - }, - errors: { noSuchAvatar: { message: 'No such avatar file.', @@ -179,8 +67,60 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + name: { ...Users.nameSchema, nullable: true }, + description: { ...Users.descriptionSchema, nullable: true }, + location: { ...Users.locationSchema, nullable: true }, + birthday: { ...Users.birthdaySchema, nullable: true }, + lang: { type: 'string', enum: [null, ...Object.keys(langmap)], nullable: true }, + avatarId: { type: 'string', format: 'misskey:id', nullable: true }, + bannerId: { type: 'string', format: 'misskey:id', nullable: true }, + fields: { type: 'array', + minItems: 0, + maxItems: 16, + items: { + type: 'object', + properties: { + name: { type: 'string' }, + value: { type: 'string' }, + }, + required: ['name', 'value'], + }, + }, + isLocked: { type: 'boolean' }, + isExplorable: { type: 'boolean' }, + hideOnlineStatus: { type: 'boolean' }, + publicReactions: { type: 'boolean' }, + carefulBot: { type: 'boolean' }, + autoAcceptFollowed: { type: 'boolean' }, + noCrawle: { type: 'boolean' }, + isBot: { type: 'boolean' }, + isCat: { type: 'boolean' }, + showTimelineReplies: { type: 'boolean' }, + injectFeaturedNote: { type: 'boolean' }, + receiveAnnouncementEmail: { type: 'boolean' }, + alwaysMarkNsfw: { type: 'boolean' }, + ffVisibility: { type: 'string', enum: ['public', 'followers', 'private'] }, + pinnedPageId: { type: 'array', items: { + type: 'string', format: 'misskey:id', + } }, + mutedWords: { type: 'array' }, + mutedInstances: { type: 'array', items: { + type: 'string', + } }, + mutingNotificationTypes: { type: 'array', items: { + type: 'string', enum: notificationTypes, + } }, + emailNotificationTypes: { type: 'array', items: { + type: 'string', + } }, + }, +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, _user, token) => { +export default define(meta, paramDef, async (ps, _user, token) => { const user = await Users.findOneOrFail(_user.id); const isSecure = token == null; @@ -235,12 +175,6 @@ export default define(meta, async (ps, _user, token) => { if (avatar == null || avatar.userId !== user.id) throw new ApiError(meta.errors.noSuchAvatar); if (!avatar.type.startsWith('image/')) throw new ApiError(meta.errors.avatarNotAnImage); - - updates.avatarUrl = DriveFiles.getPublicUrl(avatar, true); - - if (avatar.blurhash) { - updates.avatarBlurhash = avatar.blurhash; - } } if (ps.bannerId) { @@ -248,12 +182,6 @@ export default define(meta, async (ps, _user, token) => { if (banner == null || banner.userId !== user.id) throw new ApiError(meta.errors.noSuchBanner); if (!banner.type.startsWith('image/')) throw new ApiError(meta.errors.bannerNotAnImage); - - updates.bannerUrl = DriveFiles.getPublicUrl(banner, false); - - if (banner.blurhash) { - updates.bannerBlurhash = banner.blurhash; - } } if (ps.pinnedPageId) { diff --git a/packages/backend/src/server/api/endpoints/i/user-group-invites.ts b/packages/backend/src/server/api/endpoints/i/user-group-invites.ts index 76a3131e6..1d7e4a16b 100644 --- a/packages/backend/src/server/api/endpoints/i/user-group-invites.ts +++ b/packages/backend/src/server/api/endpoints/i/user-group-invites.ts @@ -1,8 +1,6 @@ -import $ from 'cafy'; -import { ID } from '@/misc/cafy-id'; -import define from '../../define'; -import { UserGroupInvitations } from '@/models/index'; -import { makePaginationQuery } from '../../common/make-pagination-query'; +import define from '../../define.js'; +import { UserGroupInvitations } from '@/models/index.js'; +import { makePaginationQuery } from '../../common/make-pagination-query.js'; export const meta = { tags: ['account', 'groups'], @@ -11,21 +9,6 @@ export const meta = { kind: 'read:user-groups', - params: { - limit: { - validator: $.optional.num.range(1, 100), - default: 10, - }, - - sinceId: { - validator: $.optional.type(ID), - }, - - untilId: { - validator: $.optional.type(ID), - }, - }, - res: { type: 'array', optional: false, nullable: false, @@ -48,14 +31,24 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + limit: { type: 'integer', minimum: 1, maximum: 100, default: 10 }, + sinceId: { type: 'string', format: 'misskey:id' }, + untilId: { type: 'string', format: 'misskey:id' }, + }, + required: [], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, user) => { +export default define(meta, paramDef, async (ps, user) => { const query = makePaginationQuery(UserGroupInvitations.createQueryBuilder('invitation'), ps.sinceId, ps.untilId) .andWhere(`invitation.userId = :meId`, { meId: user.id }) .leftJoinAndSelect('invitation.userGroup', 'user_group'); const invitations = await query - .take(ps.limit!) + .take(ps.limit) .getMany(); return await UserGroupInvitations.packMany(invitations); diff --git a/packages/backend/src/server/api/endpoints/messaging/history.ts b/packages/backend/src/server/api/endpoints/messaging/history.ts index 5ac49cf96..14de4e102 100644 --- a/packages/backend/src/server/api/endpoints/messaging/history.ts +++ b/packages/backend/src/server/api/endpoints/messaging/history.ts @@ -1,7 +1,6 @@ -import $ from 'cafy'; -import define from '../../define'; -import { MessagingMessage } from '@/models/entities/messaging-message'; -import { MessagingMessages, Mutings, UserGroupJoinings } from '@/models/index'; +import define from '../../define.js'; +import { MessagingMessage } from '@/models/entities/messaging-message.js'; +import { MessagingMessages, Mutings, UserGroupJoinings } from '@/models/index.js'; import { Brackets } from 'typeorm'; export const meta = { @@ -11,18 +10,6 @@ export const meta = { kind: 'read:messaging', - params: { - limit: { - validator: $.optional.num.range(1, 100), - default: 10, - }, - - group: { - validator: $.optional.bool, - default: false, - }, - }, - res: { type: 'array', optional: false, nullable: false, @@ -34,8 +21,17 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + limit: { type: 'integer', minimum: 1, maximum: 100, default: 10 }, + group: { type: 'boolean', default: false }, + }, + required: [], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, user) => { +export default define(meta, paramDef, async (ps, user) => { const mute = await Mutings.find({ muterId: user.id, }); @@ -50,7 +46,7 @@ export default define(meta, async (ps, user) => { const history: MessagingMessage[] = []; - for (let i = 0; i < ps.limit!; i++) { + for (let i = 0; i < ps.limit; i++) { const found = ps.group ? history.map(m => m.groupId!) : history.map(m => (m.userId === user.id) ? m.recipientId! : m.userId!); diff --git a/packages/backend/src/server/api/endpoints/messaging/messages.ts b/packages/backend/src/server/api/endpoints/messaging/messages.ts index 7dbddd80e..49ace2160 100644 --- a/packages/backend/src/server/api/endpoints/messaging/messages.ts +++ b/packages/backend/src/server/api/endpoints/messaging/messages.ts @@ -1,12 +1,10 @@ -import $ from 'cafy'; -import { ID } from '@/misc/cafy-id'; -import define from '../../define'; -import { ApiError } from '../../error'; -import { getUser } from '../../common/getters'; -import { MessagingMessages, UserGroups, UserGroupJoinings, Users } from '@/models/index'; -import { makePaginationQuery } from '../../common/make-pagination-query'; +import define from '../../define.js'; +import { ApiError } from '../../error.js'; +import { getUser } from '../../common/getters.js'; +import { MessagingMessages, UserGroups, UserGroupJoinings, Users } from '@/models/index.js'; +import { makePaginationQuery } from '../../common/make-pagination-query.js'; import { Brackets } from 'typeorm'; -import { readUserMessagingMessage, readGroupMessagingMessage, deliverReadActivity } from '../../common/read-messaging-message'; +import { readUserMessagingMessage, readGroupMessagingMessage, deliverReadActivity } from '../../common/read-messaging-message.js'; export const meta = { tags: ['messaging'], @@ -15,34 +13,6 @@ export const meta = { kind: 'read:messaging', - params: { - userId: { - validator: $.optional.type(ID), - }, - - groupId: { - validator: $.optional.type(ID), - }, - - limit: { - validator: $.optional.num.range(1, 100), - default: 10, - }, - - sinceId: { - validator: $.optional.type(ID), - }, - - untilId: { - validator: $.optional.type(ID), - }, - - markAsRead: { - validator: $.optional.bool, - default: true, - }, - }, - res: { type: 'array', optional: false, nullable: false, @@ -74,8 +44,21 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + userId: { type: 'string', format: 'misskey:id' }, + groupId: { type: 'string', format: 'misskey:id' }, + limit: { type: 'integer', minimum: 1, maximum: 100, default: 10 }, + sinceId: { type: 'string', format: 'misskey:id' }, + untilId: { type: 'string', format: 'misskey:id' }, + markAsRead: { type: 'boolean', default: true }, + }, + required: [], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, user) => { +export default define(meta, paramDef, async (ps, user) => { if (ps.userId != null) { // Fetch recipient (user) const recipient = await getUser(ps.userId).catch(e => { @@ -97,7 +80,7 @@ export default define(meta, async (ps, user) => { .setParameter('meId', user.id) .setParameter('recipientId', recipient.id); - const messages = await query.take(ps.limit!).getMany(); + const messages = await query.take(ps.limit).getMany(); // Mark all as read if (ps.markAsRead) { @@ -133,7 +116,7 @@ export default define(meta, async (ps, user) => { const query = makePaginationQuery(MessagingMessages.createQueryBuilder('message'), ps.sinceId, ps.untilId) .andWhere(`message.groupId = :groupId`, { groupId: recipientGroup.id }); - const messages = await query.take(ps.limit!).getMany(); + const messages = await query.take(ps.limit).getMany(); // Mark all as read if (ps.markAsRead) { diff --git a/packages/backend/src/server/api/endpoints/messaging/messages/create.ts b/packages/backend/src/server/api/endpoints/messaging/messages/create.ts index 5ec16f5e5..a9b926c4f 100644 --- a/packages/backend/src/server/api/endpoints/messaging/messages/create.ts +++ b/packages/backend/src/server/api/endpoints/messaging/messages/create.ts @@ -1,12 +1,10 @@ -import $ from 'cafy'; -import { ID } from '@/misc/cafy-id'; -import define from '../../../define'; -import { ApiError } from '../../../error'; -import { getUser } from '../../../common/getters'; -import { MessagingMessages, DriveFiles, UserGroups, UserGroupJoinings, Blockings } from '@/models/index'; -import { User } from '@/models/entities/user'; -import { UserGroup } from '@/models/entities/user-group'; -import { createMessage } from '@/services/messages/create'; +import define from '../../../define.js'; +import { ApiError } from '../../../error.js'; +import { getUser } from '../../../common/getters.js'; +import { MessagingMessages, DriveFiles, UserGroups, UserGroupJoinings, Blockings } from '@/models/index.js'; +import { User } from '@/models/entities/user.js'; +import { UserGroup } from '@/models/entities/user-group.js'; +import { createMessage } from '@/services/messages/create.js'; export const meta = { tags: ['messaging'], @@ -15,24 +13,6 @@ export const meta = { kind: 'write:messaging', - params: { - userId: { - validator: $.optional.type(ID), - }, - - groupId: { - validator: $.optional.type(ID), - }, - - text: { - validator: $.optional.str.pipe(MessagingMessages.validateText), - }, - - fileId: { - validator: $.optional.type(ID), - }, - }, - res: { type: 'object', optional: false, nullable: false, @@ -84,8 +64,19 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + userId: { type: 'string', format: 'misskey:id' }, + groupId: { type: 'string', format: 'misskey:id' }, + text: { type: 'string', nullable: true, maxLength: 3000 }, + fileId: { type: 'string', format: 'misskey:id' }, + }, + required: [], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, user) => { +export default define(meta, paramDef, async (ps, user) => { let recipientUser: User | undefined; let recipientGroup: UserGroup | undefined; diff --git a/packages/backend/src/server/api/endpoints/messaging/messages/delete.ts b/packages/backend/src/server/api/endpoints/messaging/messages/delete.ts index 2975419ce..a0945af51 100644 --- a/packages/backend/src/server/api/endpoints/messaging/messages/delete.ts +++ b/packages/backend/src/server/api/endpoints/messaging/messages/delete.ts @@ -1,10 +1,8 @@ -import $ from 'cafy'; -import { ID } from '@/misc/cafy-id'; -import define from '../../../define'; +import define from '../../../define.js'; import ms from 'ms'; -import { ApiError } from '../../../error'; -import { MessagingMessages } from '@/models/index'; -import { deleteMessage } from '@/services/messages/delete'; +import { ApiError } from '../../../error.js'; +import { MessagingMessages } from '@/models/index.js'; +import { deleteMessage } from '@/services/messages/delete.js'; export const meta = { tags: ['messaging'], @@ -19,12 +17,6 @@ export const meta = { minInterval: ms('1sec'), }, - params: { - messageId: { - validator: $.type(ID), - }, - }, - errors: { noSuchMessage: { message: 'No such message.', @@ -34,8 +26,16 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + messageId: { type: 'string', format: 'misskey:id' }, + }, + required: ['messageId'], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, user) => { +export default define(meta, paramDef, async (ps, user) => { const message = await MessagingMessages.findOne({ id: ps.messageId, userId: user.id, diff --git a/packages/backend/src/server/api/endpoints/messaging/messages/read.ts b/packages/backend/src/server/api/endpoints/messaging/messages/read.ts index 42c3f49f6..8d38e509a 100644 --- a/packages/backend/src/server/api/endpoints/messaging/messages/read.ts +++ b/packages/backend/src/server/api/endpoints/messaging/messages/read.ts @@ -1,9 +1,7 @@ -import $ from 'cafy'; -import { ID } from '@/misc/cafy-id'; -import define from '../../../define'; -import { ApiError } from '../../../error'; -import { MessagingMessages } from '@/models/index'; -import { readUserMessagingMessage, readGroupMessagingMessage } from '../../../common/read-messaging-message'; +import define from '../../../define.js'; +import { ApiError } from '../../../error.js'; +import { MessagingMessages } from '@/models/index.js'; +import { readUserMessagingMessage, readGroupMessagingMessage } from '../../../common/read-messaging-message.js'; export const meta = { tags: ['messaging'], @@ -12,12 +10,6 @@ export const meta = { kind: 'write:messaging', - params: { - messageId: { - validator: $.type(ID), - }, - }, - errors: { noSuchMessage: { message: 'No such message.', @@ -27,8 +19,16 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + messageId: { type: 'string', format: 'misskey:id' }, + }, + required: ['messageId'], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, user) => { +export default define(meta, paramDef, async (ps, user) => { const message = await MessagingMessages.findOne(ps.messageId); if (message == null) { diff --git a/packages/backend/src/server/api/endpoints/meta.ts b/packages/backend/src/server/api/endpoints/meta.ts index 16ea99af6..1aff1f63f 100644 --- a/packages/backend/src/server/api/endpoints/meta.ts +++ b/packages/backend/src/server/api/endpoints/meta.ts @@ -1,23 +1,16 @@ -import $ from 'cafy'; -import config from '@/config/index'; -import define from '../define'; -import { fetchMeta } from '@/misc/fetch-meta'; -import { Ads, Emojis, Users } from '@/models/index'; -import { DB_MAX_NOTE_TEXT_LENGTH } from '@/misc/hard-limits'; +import config from '@/config/index.js'; +import define from '../define.js'; +import { fetchMeta } from '@/misc/fetch-meta.js'; +import { Ads, Emojis, Users } from '@/models/index.js'; +import { DB_MAX_NOTE_TEXT_LENGTH } from '@/misc/hard-limits.js'; import { MoreThan } from 'typeorm'; +import { MAX_NOTE_TEXT_LENGTH } from '@/const.js'; export const meta = { tags: ['meta'], requireCredential: false, - params: { - detail: { - validator: $.optional.bool, - default: true, - }, - }, - res: { type: 'object', optional: false, nullable: false, @@ -71,10 +64,13 @@ export const meta = { optional: false, nullable: false, default: 'https://github.com/misskey-dev/misskey/issues/new', }, - secure: { - type: 'boolean', - optional: false, nullable: false, - default: false, + defaultDarkTheme: { + type: 'string', + optional: false, nullable: true, + }, + defaultLightTheme: { + type: 'string', + optional: false, nullable: true, }, disableRegistration: { type: 'boolean', @@ -100,10 +96,6 @@ export const meta = { type: 'boolean', optional: false, nullable: false, }, - proxyRemoteFiles: { - type: 'boolean', - optional: false, nullable: false, - }, emailRequiredForSignup: { type: 'boolean', optional: false, nullable: false, @@ -149,7 +141,6 @@ export const meta = { maxNoteTextLength: { type: 'number', optional: false, nullable: false, - default: 500, }, emojis: { type: 'array', @@ -448,8 +439,16 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + detail: { type: 'boolean', default: true }, + }, + required: [], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, me) => { +export default define(meta, paramDef, async (ps, me) => { const instance = await fetchMeta(true); const emojis = await Emojis.find({ @@ -485,9 +484,6 @@ export default define(meta, async (ps, me) => { tosUrl: instance.ToSUrl, repositoryUrl: instance.repositoryUrl, feedbackUrl: instance.feedbackUrl, - - secure: config.https != null, - disableRegistration: instance.disableRegistration, disableLocalTimeline: instance.disableLocalTimeline, disableGlobalTimeline: instance.disableGlobalTimeline, @@ -506,8 +502,10 @@ export default define(meta, async (ps, me) => { iconUrl: instance.iconUrl, backgroundImageUrl: instance.backgroundImageUrl, logoImageUrl: instance.logoImageUrl, - maxNoteTextLength: Math.min(instance.maxNoteTextLength, DB_MAX_NOTE_TEXT_LENGTH), + maxNoteTextLength: MAX_NOTE_TEXT_LENGTH, // 後方互換性のため emojis: await Emojis.packMany(emojis), + defaultLightTheme: instance.defaultLightTheme, + defaultDarkTheme: instance.defaultDarkTheme, ads: ads.map(ad => ({ id: ad.id, url: ad.url, @@ -529,7 +527,6 @@ export default define(meta, async (ps, me) => { pinnedPages: instance.pinnedPages, pinnedClipId: instance.pinnedClipId, cacheRemoteFiles: instance.cacheRemoteFiles, - proxyRemoteFiles: instance.proxyRemoteFiles, requireSetup: (await Users.count({ host: null, })) === 0, diff --git a/packages/backend/src/server/api/endpoints/miauth/gen-token.ts b/packages/backend/src/server/api/endpoints/miauth/gen-token.ts index 158c8877e..73ecdaeb0 100644 --- a/packages/backend/src/server/api/endpoints/miauth/gen-token.ts +++ b/packages/backend/src/server/api/endpoints/miauth/gen-token.ts @@ -1,8 +1,7 @@ -import $ from 'cafy'; -import define from '../../define'; -import { AccessTokens } from '@/models/index'; -import { genId } from '@/misc/gen-id'; -import { secureRndstr } from '@/misc/secure-rndstr'; +import define from '../../define.js'; +import { AccessTokens } from '@/models/index.js'; +import { genId } from '@/misc/gen-id.js'; +import { secureRndstr } from '@/misc/secure-rndstr.js'; export const meta = { tags: ['auth'], @@ -11,28 +10,6 @@ export const meta = { secure: true, - params: { - session: { - validator: $.nullable.str, - }, - - name: { - validator: $.nullable.optional.str, - }, - - description: { - validator: $.nullable.optional.str, - }, - - iconUrl: { - validator: $.nullable.optional.str, - }, - - permission: { - validator: $.arr($.str).unique(), - }, - }, - res: { type: 'object', optional: false, nullable: false, @@ -45,8 +22,22 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + session: { type: 'string', nullable: true }, + name: { type: 'string', nullable: true }, + description: { type: 'string', nullable: true }, + iconUrl: { type: 'string', nullable: true }, + permission: { type: 'array', uniqueItems: true, items: { + type: 'string', + } }, + }, + required: ['session', 'permission'], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, user) => { +export default define(meta, paramDef, async (ps, user) => { // Generate access token const accessToken = secureRndstr(32, true); diff --git a/packages/backend/src/server/api/endpoints/mute/create.ts b/packages/backend/src/server/api/endpoints/mute/create.ts index 6ba5a453c..dacee40d0 100644 --- a/packages/backend/src/server/api/endpoints/mute/create.ts +++ b/packages/backend/src/server/api/endpoints/mute/create.ts @@ -1,12 +1,10 @@ -import $ from 'cafy'; -import { ID } from '@/misc/cafy-id'; -import define from '../../define'; -import { ApiError } from '../../error'; -import { getUser } from '../../common/getters'; -import { genId } from '@/misc/gen-id'; -import { Mutings, NoteWatchings } from '@/models/index'; -import { Muting } from '@/models/entities/muting'; -import { publishUserEvent } from '@/services/stream'; +import define from '../../define.js'; +import { ApiError } from '../../error.js'; +import { getUser } from '../../common/getters.js'; +import { genId } from '@/misc/gen-id.js'; +import { Mutings, NoteWatchings } from '@/models/index.js'; +import { Muting } from '@/models/entities/muting.js'; +import { publishUserEvent } from '@/services/stream.js'; export const meta = { tags: ['account'], @@ -15,12 +13,6 @@ export const meta = { kind: 'write:mutes', - params: { - userId: { - validator: $.type(ID), - }, - }, - errors: { noSuchUser: { message: 'No such user.', @@ -42,8 +34,17 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + userId: { type: 'string', format: 'misskey:id' }, + expiresAt: { type: 'integer', nullable: true }, + }, + required: ['userId'], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, user) => { +export default define(meta, paramDef, async (ps, user) => { const muter = user; // 自分自身 @@ -67,10 +68,15 @@ export default define(meta, async (ps, user) => { throw new ApiError(meta.errors.alreadyMuting); } + if (ps.expiresAt && ps.expiresAt <= Date.now()) { + return; + } + // Create mute await Mutings.insert({ id: genId(), createdAt: new Date(), + expiresAt: ps.expiresAt ? new Date(ps.expiresAt) : null, muterId: muter.id, muteeId: mutee.id, } as Muting); diff --git a/packages/backend/src/server/api/endpoints/mute/delete.ts b/packages/backend/src/server/api/endpoints/mute/delete.ts index 21948dc3d..a8cf2a666 100644 --- a/packages/backend/src/server/api/endpoints/mute/delete.ts +++ b/packages/backend/src/server/api/endpoints/mute/delete.ts @@ -1,10 +1,8 @@ -import $ from 'cafy'; -import { ID } from '@/misc/cafy-id'; -import define from '../../define'; -import { ApiError } from '../../error'; -import { getUser } from '../../common/getters'; -import { Mutings } from '@/models/index'; -import { publishUserEvent } from '@/services/stream'; +import define from '../../define.js'; +import { ApiError } from '../../error.js'; +import { getUser } from '../../common/getters.js'; +import { Mutings } from '@/models/index.js'; +import { publishUserEvent } from '@/services/stream.js'; export const meta = { tags: ['account'], @@ -13,12 +11,6 @@ export const meta = { kind: 'write:mutes', - params: { - userId: { - validator: $.type(ID), - }, - }, - errors: { noSuchUser: { message: 'No such user.', @@ -40,8 +32,16 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + userId: { type: 'string', format: 'misskey:id' }, + }, + required: ['userId'], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, user) => { +export default define(meta, paramDef, async (ps, user) => { const muter = user; // Check if the mutee is yourself diff --git a/packages/backend/src/server/api/endpoints/mute/list.ts b/packages/backend/src/server/api/endpoints/mute/list.ts index 4c6a81b63..31283cf4c 100644 --- a/packages/backend/src/server/api/endpoints/mute/list.ts +++ b/packages/backend/src/server/api/endpoints/mute/list.ts @@ -1,8 +1,6 @@ -import $ from 'cafy'; -import { ID } from '@/misc/cafy-id'; -import define from '../../define'; -import { makePaginationQuery } from '../../common/make-pagination-query'; -import { Mutings } from '@/models/index'; +import define from '../../define.js'; +import { makePaginationQuery } from '../../common/make-pagination-query.js'; +import { Mutings } from '@/models/index.js'; export const meta = { tags: ['account'], @@ -11,21 +9,6 @@ export const meta = { kind: 'read:mutes', - params: { - limit: { - validator: $.optional.num.range(1, 100), - default: 30, - }, - - sinceId: { - validator: $.optional.type(ID), - }, - - untilId: { - validator: $.optional.type(ID), - }, - }, - res: { type: 'array', optional: false, nullable: false, @@ -37,13 +20,23 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + limit: { type: 'integer', minimum: 1, maximum: 100, default: 30 }, + sinceId: { type: 'string', format: 'misskey:id' }, + untilId: { type: 'string', format: 'misskey:id' }, + }, + required: [], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, me) => { +export default define(meta, paramDef, async (ps, me) => { const query = makePaginationQuery(Mutings.createQueryBuilder('muting'), ps.sinceId, ps.untilId) .andWhere(`muting.muterId = :meId`, { meId: me.id }); const mutings = await query - .take(ps.limit!) + .take(ps.limit) .getMany(); return await Mutings.packMany(mutings, me); diff --git a/packages/backend/src/server/api/endpoints/my/apps.ts b/packages/backend/src/server/api/endpoints/my/apps.ts index 42bd5c5f7..85b75c15d 100644 --- a/packages/backend/src/server/api/endpoints/my/apps.ts +++ b/packages/backend/src/server/api/endpoints/my/apps.ts @@ -1,83 +1,40 @@ -import $ from 'cafy'; -import define from '../../define'; -import { Apps } from '@/models/index'; +import define from '../../define.js'; +import { Apps } from '@/models/index.js'; export const meta = { tags: ['account', 'app'], requireCredential: true, - params: { - limit: { - validator: $.optional.num.range(1, 100), - default: 10, - }, - - offset: { - validator: $.optional.num.min(0), - default: 0, - }, - }, - res: { type: 'array', optional: false, nullable: false, items: { type: 'object', optional: false, nullable: false, - properties: { - id: { - type: 'string', - optional: false, nullable: false, - }, - name: { - type: 'string', - optional: false, nullable: false, - }, - callbackUrl: { - type: 'string', - optional: false, nullable: false, - }, - permission: { - type: 'array', - optional: false, nullable: false, - items: { - type: 'string', - optional: false, nullable: false, - }, - }, - secret: { - type: 'string', - optional: true, nullable: false, - }, - isAuthorized: { - type: 'object', - optional: true, nullable: false, - properties: { - appId: { - type: 'string', - optional: false, nullable: false, - }, - userId: { - type: 'string', - optional: false, nullable: false, - }, - }, - }, - }, + ref: 'App', }, }, } as const; +export const paramDef = { + type: 'object', + properties: { + limit: { type: 'integer', minimum: 1, maximum: 100, default: 10 }, + offset: { type: 'integer', default: 0 }, + }, + required: [], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, user) => { +export default define(meta, paramDef, async (ps, user) => { const query = { userId: user.id, }; const apps = await Apps.find({ where: query, - take: ps.limit!, + take: ps.limit, skip: ps.offset, }); diff --git a/packages/backend/src/server/api/endpoints/notes.ts b/packages/backend/src/server/api/endpoints/notes.ts index 9edc6cb11..96657f8d3 100644 --- a/packages/backend/src/server/api/endpoints/notes.ts +++ b/packages/backend/src/server/api/endpoints/notes.ts @@ -1,47 +1,10 @@ -import $ from 'cafy'; -import { ID } from '@/misc/cafy-id'; -import define from '../define'; -import { makePaginationQuery } from '../common/make-pagination-query'; -import { Notes } from '@/models/index'; +import define from '../define.js'; +import { makePaginationQuery } from '../common/make-pagination-query.js'; +import { Notes } from '@/models/index.js'; export const meta = { tags: ['notes'], - params: { - local: { - validator: $.optional.bool, - }, - - reply: { - validator: $.optional.bool, - }, - - renote: { - validator: $.optional.bool, - }, - - withFiles: { - validator: $.optional.bool, - }, - - poll: { - validator: $.optional.bool, - }, - - limit: { - validator: $.optional.num.range(1, 100), - default: 10, - }, - - sinceId: { - validator: $.optional.type(ID), - }, - - untilId: { - validator: $.optional.type(ID), - }, - }, - res: { type: 'array', optional: false, nullable: false, @@ -53,16 +16,37 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + local: { type: 'boolean' }, + reply: { type: 'boolean' }, + renote: { type: 'boolean' }, + withFiles: { type: 'boolean' }, + poll: { type: 'boolean' }, + limit: { type: 'integer', minimum: 1, maximum: 100, default: 10 }, + sinceId: { type: 'string', format: 'misskey:id' }, + untilId: { type: 'string', format: 'misskey:id' }, + }, + required: [], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps) => { +export default define(meta, paramDef, async (ps) => { const query = makePaginationQuery(Notes.createQueryBuilder('note'), ps.sinceId, ps.untilId) .andWhere(`note.visibility = 'public'`) .andWhere(`note.localOnly = FALSE`) .innerJoinAndSelect('note.user', 'user') + .leftJoinAndSelect('user.avatar', 'avatar') + .leftJoinAndSelect('user.banner', 'banner') .leftJoinAndSelect('note.reply', 'reply') .leftJoinAndSelect('note.renote', 'renote') .leftJoinAndSelect('reply.user', 'replyUser') - .leftJoinAndSelect('renote.user', 'renoteUser'); + .leftJoinAndSelect('replyUser.avatar', 'replyUserAvatar') + .leftJoinAndSelect('replyUser.banner', 'replyUserBanner') + .leftJoinAndSelect('renote.user', 'renoteUser') + .leftJoinAndSelect('renoteUser.avatar', 'renoteUserAvatar') + .leftJoinAndSelect('renoteUser.banner', 'renoteUserBanner'); if (ps.local) { query.andWhere('note.userHost IS NULL'); @@ -89,7 +73,7 @@ export default define(meta, async (ps) => { // query.isBot = bot; //} - const notes = await query.take(ps.limit!).getMany(); + const notes = await query.take(ps.limit).getMany(); return await Notes.packMany(notes); }); diff --git a/packages/backend/src/server/api/endpoints/notes/children.ts b/packages/backend/src/server/api/endpoints/notes/children.ts index 088ef65e9..86dde30d6 100644 --- a/packages/backend/src/server/api/endpoints/notes/children.ts +++ b/packages/backend/src/server/api/endpoints/notes/children.ts @@ -1,38 +1,17 @@ -import $ from 'cafy'; -import { ID } from '@/misc/cafy-id'; -import define from '../../define'; -import { makePaginationQuery } from '../../common/make-pagination-query'; -import { generateVisibilityQuery } from '../../common/generate-visibility-query'; -import { generateMutedUserQuery } from '../../common/generate-muted-user-query'; +import define from '../../define.js'; +import { makePaginationQuery } from '../../common/make-pagination-query.js'; +import { generateVisibilityQuery } from '../../common/generate-visibility-query.js'; +import { generateMutedUserQuery } from '../../common/generate-muted-user-query.js'; import { Brackets } from 'typeorm'; -import { Notes } from '@/models/index'; -import { generateBlockedUserQuery } from '../../common/generate-block-query'; -import { generateMutedInstanceQuery } from '../../common/generate-muted-instance-query'; +import { Notes } from '@/models/index.js'; +import { generateBlockedUserQuery } from '../../common/generate-block-query.js'; +import { generateMutedInstanceQuery } from '../../common/generate-muted-instance-query.js'; export const meta = { tags: ['notes'], requireCredential: false, - params: { - noteId: { - validator: $.type(ID), - }, - - limit: { - validator: $.optional.num.range(1, 100), - default: 10, - }, - - sinceId: { - validator: $.optional.type(ID), - }, - - untilId: { - validator: $.optional.type(ID), - }, - }, - res: { type: 'array', optional: false, nullable: false, @@ -44,8 +23,19 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + noteId: { type: 'string', format: 'misskey:id' }, + limit: { type: 'integer', minimum: 1, maximum: 100, default: 10 }, + sinceId: { type: 'string', format: 'misskey:id' }, + untilId: { type: 'string', format: 'misskey:id' }, + }, + required: ['noteId'], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, user) => { +export default define(meta, paramDef, async (ps, user) => { const query = makePaginationQuery(Notes.createQueryBuilder('note'), ps.sinceId, ps.untilId) .andWhere(new Brackets(qb => { qb .where(`note.replyId = :noteId`, { noteId: ps.noteId }) @@ -59,17 +49,23 @@ export default define(meta, async (ps, user) => { })); })) .innerJoinAndSelect('note.user', 'user') + .leftJoinAndSelect('user.avatar', 'avatar') + .leftJoinAndSelect('user.banner', 'banner') .leftJoinAndSelect('note.reply', 'reply') .leftJoinAndSelect('note.renote', 'renote') .leftJoinAndSelect('reply.user', 'replyUser') - .leftJoinAndSelect('renote.user', 'renoteUser'); + .leftJoinAndSelect('replyUser.avatar', 'replyUserAvatar') + .leftJoinAndSelect('replyUser.banner', 'replyUserBanner') + .leftJoinAndSelect('renote.user', 'renoteUser') + .leftJoinAndSelect('renoteUser.avatar', 'renoteUserAvatar') + .leftJoinAndSelect('renoteUser.banner', 'renoteUserBanner'); generateVisibilityQuery(query, user); if (user) generateMutedUserQuery(query, user); if (user) generateBlockedUserQuery(query, user); if (user) generateMutedInstanceQuery(query, user); - const notes = await query.take(ps.limit!).getMany(); + const notes = await query.take(ps.limit).getMany(); return await Notes.packMany(notes, user); }); diff --git a/packages/backend/src/server/api/endpoints/notes/clips.ts b/packages/backend/src/server/api/endpoints/notes/clips.ts index b89c6db4a..9a863b714 100644 --- a/packages/backend/src/server/api/endpoints/notes/clips.ts +++ b/packages/backend/src/server/api/endpoints/notes/clips.ts @@ -1,9 +1,7 @@ -import $ from 'cafy'; -import { ID } from '@/misc/cafy-id'; -import define from '../../define'; -import { ClipNotes, Clips } from '@/models/index'; -import { getNote } from '../../common/getters'; -import { ApiError } from '../../error'; +import define from '../../define.js'; +import { ClipNotes, Clips } from '@/models/index.js'; +import { getNote } from '../../common/getters.js'; +import { ApiError } from '../../error.js'; import { In } from 'typeorm'; export const meta = { @@ -11,12 +9,6 @@ export const meta = { requireCredential: false, - params: { - noteId: { - validator: $.type(ID), - }, - }, - res: { type: 'array', optional: false, nullable: false, @@ -36,8 +28,16 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + noteId: { type: 'string', format: 'misskey:id' }, + }, + required: ['noteId'], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, me) => { +export default define(meta, paramDef, async (ps, me) => { const note = await getNote(ps.noteId).catch(e => { if (e.id === '9725d0ce-ba28-4dde-95a7-2cbb2c15de24') throw new ApiError(meta.errors.noSuchNote); throw e; diff --git a/packages/backend/src/server/api/endpoints/notes/conversation.ts b/packages/backend/src/server/api/endpoints/notes/conversation.ts index 4bd89c32e..2552c0f99 100644 --- a/packages/backend/src/server/api/endpoints/notes/conversation.ts +++ b/packages/backend/src/server/api/endpoints/notes/conversation.ts @@ -1,32 +1,14 @@ -import $ from 'cafy'; -import { ID } from '@/misc/cafy-id'; -import define from '../../define'; -import { ApiError } from '../../error'; -import { getNote } from '../../common/getters'; -import { Note } from '@/models/entities/note'; -import { Notes } from '@/models/index'; +import define from '../../define.js'; +import { ApiError } from '../../error.js'; +import { getNote } from '../../common/getters.js'; +import { Note } from '@/models/entities/note.js'; +import { Notes } from '@/models/index.js'; export const meta = { tags: ['notes'], requireCredential: false, - params: { - noteId: { - validator: $.type(ID), - }, - - limit: { - validator: $.optional.num.range(1, 100), - default: 10, - }, - - offset: { - validator: $.optional.num.min(0), - default: 0, - }, - }, - res: { type: 'array', optional: false, nullable: false, @@ -46,8 +28,18 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + noteId: { type: 'string', format: 'misskey:id' }, + limit: { type: 'integer', minimum: 1, maximum: 100, default: 10 }, + offset: { type: 'integer', default: 0 }, + }, + required: ['noteId'], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, user) => { +export default define(meta, paramDef, async (ps, user) => { const note = await getNote(ps.noteId).catch(e => { if (e.id === '9725d0ce-ba28-4dde-95a7-2cbb2c15de24') throw new ApiError(meta.errors.noSuchNote); throw e; @@ -65,7 +57,7 @@ export default define(meta, async (ps, user) => { conversation.push(p); } - if (conversation.length == ps.limit!) { + if (conversation.length == ps.limit) { return; } diff --git a/packages/backend/src/server/api/endpoints/notes/create.ts b/packages/backend/src/server/api/endpoints/notes/create.ts index 4efa76b24..e4a9b2889 100644 --- a/packages/backend/src/server/api/endpoints/notes/create.ts +++ b/packages/backend/src/server/api/endpoints/notes/create.ts @@ -1,26 +1,14 @@ -import $ from 'cafy'; import ms from 'ms'; -import { length } from 'stringz'; -import create from '@/services/note/create'; -import define from '../../define'; -import { fetchMeta } from '@/misc/fetch-meta'; -import { ApiError } from '../../error'; -import { ID } from '@/misc/cafy-id'; -import { User } from '@/models/entities/user'; -import { Users, DriveFiles, Notes, Channels, Blockings } from '@/models/index'; -import { DriveFile } from '@/models/entities/drive-file'; -import { Note } from '@/models/entities/note'; -import { DB_MAX_NOTE_TEXT_LENGTH } from '@/misc/hard-limits'; -import { noteVisibilities } from '../../../../types'; -import { Channel } from '@/models/entities/channel'; - -let maxNoteTextLength = 500; - -setInterval(() => { - fetchMeta().then(m => { - maxNoteTextLength = m.maxNoteTextLength; - }); -}, 3000); +import create from '@/services/note/create.js'; +import define from '../../define.js'; +import { ApiError } from '../../error.js'; +import { User } from '@/models/entities/user.js'; +import { Users, DriveFiles, Notes, Channels, Blockings } from '@/models/index.js'; +import { DriveFile } from '@/models/entities/drive-file.js'; +import { Note } from '@/models/entities/note.js'; +import { noteVisibilities } from '../../../../types.js'; +import { Channel } from '@/models/entities/channel.js'; +import { MAX_NOTE_TEXT_LENGTH } from '@/const.js'; export const meta = { tags: ['notes'], @@ -34,84 +22,6 @@ export const meta = { kind: 'write:notes', - params: { - visibility: { - validator: $.optional.str.or(noteVisibilities as unknown as string[]), - default: 'public', - }, - - visibleUserIds: { - validator: $.optional.arr($.type(ID)).unique().min(0), - }, - - text: { - validator: $.optional.nullable.str.pipe(text => - text.trim() != '' - && length(text.trim()) <= maxNoteTextLength - && Array.from(text.trim()).length <= DB_MAX_NOTE_TEXT_LENGTH, // DB limit - ), - default: null, - }, - - cw: { - validator: $.optional.nullable.str.pipe(Notes.validateCw), - }, - - localOnly: { - validator: $.optional.bool, - default: false, - }, - - noExtractMentions: { - validator: $.optional.bool, - default: false, - }, - - noExtractHashtags: { - validator: $.optional.bool, - default: false, - }, - - noExtractEmojis: { - validator: $.optional.bool, - default: false, - }, - - fileIds: { - validator: $.optional.arr($.type(ID)).unique().range(1, 16), - }, - - mediaIds: { - validator: $.optional.arr($.type(ID)).unique().range(1, 16), - deprecated: true, - }, - - replyId: { - validator: $.optional.nullable.type(ID), - }, - - renoteId: { - validator: $.optional.nullable.type(ID), - }, - - channelId: { - validator: $.optional.nullable.type(ID), - }, - - poll: { - validator: $.optional.nullable.obj({ - choices: $.arr($.str) - .unique() - .range(2, 10) - .each(c => c.length > 0 && c.length < 50), - multiple: $.optional.bool, - expiresAt: $.optional.nullable.num.int(), - expiredAfter: $.optional.nullable.num.int().min(1), - }).strict(), - ref: 'poll', - }, - }, - res: { type: 'object', optional: false, nullable: false, @@ -175,8 +85,49 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + visibility: { type: 'string', enum: ['public', 'home', 'followers', 'specified'], default: "public" }, + visibleUserIds: { type: 'array', uniqueItems: true, items: { + type: 'string', format: 'misskey:id', + } }, + text: { type: 'string', nullable: true, maxLength: MAX_NOTE_TEXT_LENGTH, default: null }, + cw: { type: 'string', nullable: true, maxLength: 100 }, + localOnly: { type: 'boolean', default: false }, + noExtractMentions: { type: 'boolean', default: false }, + noExtractHashtags: { type: 'boolean', default: false }, + noExtractEmojis: { type: 'boolean', default: false }, + fileIds: { type: 'array', uniqueItems: true, minItems: 1, maxItems: 16, items: { + type: 'string', format: 'misskey:id', + } }, + mediaIds: { type: 'array', uniqueItems: true, minItems: 1, maxItems: 16, items: { + type: 'string', format: 'misskey:id', + } }, + replyId: { type: 'string', format: 'misskey:id', nullable: true }, + renoteId: { type: 'string', format: 'misskey:id', nullable: true }, + channelId: { type: 'string', format: 'misskey:id', nullable: true }, + poll: { + type: 'object', nullable: true, + properties: { + choices: { + type: 'array', uniqueItems: true, minItems: 2, maxItems: 10, + items: { + type: 'string', minLength: 1, maxLength: 50, + }, + }, + multiple: { type: 'boolean', default: false }, + expiresAt: { type: 'integer', nullable: true }, + expiredAfter: { type: 'integer', nullable: true, minimum: 1 }, + }, + required: ['choices'], + }, + }, + required: [], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, user) => { +export default define(meta, paramDef, async (ps, user) => { let visibleUsers: User[] = []; if (ps.visibleUserIds) { visibleUsers = (await Promise.all(ps.visibleUserIds.map(id => Users.findOne(id)))) diff --git a/packages/backend/src/server/api/endpoints/notes/delete.ts b/packages/backend/src/server/api/endpoints/notes/delete.ts index 9e080d9e9..22ff2275c 100644 --- a/packages/backend/src/server/api/endpoints/notes/delete.ts +++ b/packages/backend/src/server/api/endpoints/notes/delete.ts @@ -1,11 +1,9 @@ -import $ from 'cafy'; -import { ID } from '@/misc/cafy-id'; -import deleteNote from '@/services/note/delete'; -import define from '../../define'; +import deleteNote from '@/services/note/delete.js'; +import define from '../../define.js'; import ms from 'ms'; -import { getNote } from '../../common/getters'; -import { ApiError } from '../../error'; -import { Users } from '@/models/index'; +import { getNote } from '../../common/getters.js'; +import { ApiError } from '../../error.js'; +import { Users } from '@/models/index.js'; export const meta = { tags: ['notes'], @@ -20,12 +18,6 @@ export const meta = { minInterval: ms('1sec'), }, - params: { - noteId: { - validator: $.type(ID), - }, - }, - errors: { noSuchNote: { message: 'No such note.', @@ -41,8 +33,16 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + noteId: { type: 'string', format: 'misskey:id' }, + }, + required: ['noteId'], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, user) => { +export default define(meta, paramDef, async (ps, user) => { const note = await getNote(ps.noteId).catch(e => { if (e.id === '9725d0ce-ba28-4dde-95a7-2cbb2c15de24') throw new ApiError(meta.errors.noSuchNote); throw e; diff --git a/packages/backend/src/server/api/endpoints/notes/favorites/create.ts b/packages/backend/src/server/api/endpoints/notes/favorites/create.ts index 78da6a3b0..bcc2c44c0 100644 --- a/packages/backend/src/server/api/endpoints/notes/favorites/create.ts +++ b/packages/backend/src/server/api/endpoints/notes/favorites/create.ts @@ -1,10 +1,8 @@ -import $ from 'cafy'; -import { ID } from '@/misc/cafy-id'; -import define from '../../../define'; -import { ApiError } from '../../../error'; -import { getNote } from '../../../common/getters'; -import { NoteFavorites } from '@/models/index'; -import { genId } from '@/misc/gen-id'; +import define from '../../../define.js'; +import { ApiError } from '../../../error.js'; +import { getNote } from '../../../common/getters.js'; +import { NoteFavorites } from '@/models/index.js'; +import { genId } from '@/misc/gen-id.js'; export const meta = { tags: ['notes', 'favorites'], @@ -13,12 +11,6 @@ export const meta = { kind: 'write:favorites', - params: { - noteId: { - validator: $.type(ID), - }, - }, - errors: { noSuchNote: { message: 'No such note.', @@ -34,8 +26,16 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + noteId: { type: 'string', format: 'misskey:id' }, + }, + required: ['noteId'], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, user) => { +export default define(meta, paramDef, async (ps, user) => { // Get favoritee const note = await getNote(ps.noteId).catch(e => { if (e.id === '9725d0ce-ba28-4dde-95a7-2cbb2c15de24') throw new ApiError(meta.errors.noSuchNote); diff --git a/packages/backend/src/server/api/endpoints/notes/favorites/delete.ts b/packages/backend/src/server/api/endpoints/notes/favorites/delete.ts index 3f3d50f0d..d41fab22d 100644 --- a/packages/backend/src/server/api/endpoints/notes/favorites/delete.ts +++ b/packages/backend/src/server/api/endpoints/notes/favorites/delete.ts @@ -1,9 +1,7 @@ -import $ from 'cafy'; -import { ID } from '@/misc/cafy-id'; -import define from '../../../define'; -import { ApiError } from '../../../error'; -import { getNote } from '../../../common/getters'; -import { NoteFavorites } from '@/models/index'; +import define from '../../../define.js'; +import { ApiError } from '../../../error.js'; +import { getNote } from '../../../common/getters.js'; +import { NoteFavorites } from '@/models/index.js'; export const meta = { tags: ['notes', 'favorites'], @@ -12,12 +10,6 @@ export const meta = { kind: 'write:favorites', - params: { - noteId: { - validator: $.type(ID), - }, - }, - errors: { noSuchNote: { message: 'No such note.', @@ -33,8 +25,16 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + noteId: { type: 'string', format: 'misskey:id' }, + }, + required: ['noteId'], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, user) => { +export default define(meta, paramDef, async (ps, user) => { // Get favoritee const note = await getNote(ps.noteId).catch(e => { if (e.id === '9725d0ce-ba28-4dde-95a7-2cbb2c15de24') throw new ApiError(meta.errors.noSuchNote); diff --git a/packages/backend/src/server/api/endpoints/notes/featured.ts b/packages/backend/src/server/api/endpoints/notes/featured.ts index 5a47fb9e0..6308d2369 100644 --- a/packages/backend/src/server/api/endpoints/notes/featured.ts +++ b/packages/backend/src/server/api/endpoints/notes/featured.ts @@ -1,26 +1,13 @@ -import $ from 'cafy'; -import define from '../../define'; -import { generateMutedUserQuery } from '../../common/generate-muted-user-query'; -import { Notes } from '@/models/index'; -import { generateBlockedUserQuery } from '../../common/generate-block-query'; +import define from '../../define.js'; +import { generateMutedUserQuery } from '../../common/generate-muted-user-query.js'; +import { Notes } from '@/models/index.js'; +import { generateBlockedUserQuery } from '../../common/generate-block-query.js'; export const meta = { tags: ['notes'], requireCredential: false, - params: { - limit: { - validator: $.optional.num.range(1, 100), - default: 10, - }, - - offset: { - validator: $.optional.num.min(0), - default: 0, - }, - }, - res: { type: 'array', optional: false, nullable: false, @@ -32,8 +19,17 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + limit: { type: 'integer', minimum: 1, maximum: 100, default: 10 }, + offset: { type: 'integer', default: 0 }, + }, + required: [], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, user) => { +export default define(meta, paramDef, async (ps, user) => { const max = 30; const day = 1000 * 60 * 60 * 24 * 3; // 3日前まで @@ -44,10 +40,16 @@ export default define(meta, async (ps, user) => { .andWhere(`note.createdAt > :date`, { date: new Date(Date.now() - day) }) .andWhere(`note.visibility = 'public'`) .innerJoinAndSelect('note.user', 'user') + .leftJoinAndSelect('user.avatar', 'avatar') + .leftJoinAndSelect('user.banner', 'banner') .leftJoinAndSelect('note.reply', 'reply') .leftJoinAndSelect('note.renote', 'renote') .leftJoinAndSelect('reply.user', 'replyUser') - .leftJoinAndSelect('renote.user', 'renoteUser'); + .leftJoinAndSelect('replyUser.avatar', 'replyUserAvatar') + .leftJoinAndSelect('replyUser.banner', 'replyUserBanner') + .leftJoinAndSelect('renote.user', 'renoteUser') + .leftJoinAndSelect('renoteUser.avatar', 'renoteUserAvatar') + .leftJoinAndSelect('renoteUser.banner', 'renoteUserBanner'); if (user) generateMutedUserQuery(query, user); if (user) generateBlockedUserQuery(query, user); diff --git a/packages/backend/src/server/api/endpoints/notes/global-timeline.ts b/packages/backend/src/server/api/endpoints/notes/global-timeline.ts index cdd110994..26aaa0919 100644 --- a/packages/backend/src/server/api/endpoints/notes/global-timeline.ts +++ b/packages/backend/src/server/api/endpoints/notes/global-timeline.ts @@ -1,47 +1,18 @@ -import $ from 'cafy'; -import { ID } from '@/misc/cafy-id'; -import define from '../../define'; -import { fetchMeta } from '@/misc/fetch-meta'; -import { ApiError } from '../../error'; -import { makePaginationQuery } from '../../common/make-pagination-query'; -import { Notes } from '@/models/index'; -import { generateMutedUserQuery } from '../../common/generate-muted-user-query'; -import { generateMutedInstanceQuery } from '../../common/generate-muted-instance-query'; -import { activeUsersChart } from '@/services/chart/index'; -import { generateRepliesQuery } from '../../common/generate-replies-query'; -import { generateMutedNoteQuery } from '../../common/generate-muted-note-query'; -import { generateBlockedUserQuery } from '../../common/generate-block-query'; +import define from '../../define.js'; +import { fetchMeta } from '@/misc/fetch-meta.js'; +import { ApiError } from '../../error.js'; +import { makePaginationQuery } from '../../common/make-pagination-query.js'; +import { Notes } from '@/models/index.js'; +import { generateMutedUserQuery } from '../../common/generate-muted-user-query.js'; +import { generateMutedInstanceQuery } from '../../common/generate-muted-instance-query.js'; +import { activeUsersChart } from '@/services/chart/index.js'; +import { generateRepliesQuery } from '../../common/generate-replies-query.js'; +import { generateMutedNoteQuery } from '../../common/generate-muted-note-query.js'; +import { generateBlockedUserQuery } from '../../common/generate-block-query.js'; export const meta = { tags: ['notes'], - params: { - withFiles: { - validator: $.optional.bool, - }, - - limit: { - validator: $.optional.num.range(1, 100), - default: 10, - }, - - sinceId: { - validator: $.optional.type(ID), - }, - - untilId: { - validator: $.optional.type(ID), - }, - - sinceDate: { - validator: $.optional.num, - }, - - untilDate: { - validator: $.optional.num, - }, - }, - res: { type: 'array', optional: false, nullable: false, @@ -61,8 +32,21 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + withFiles: { type: 'boolean' }, + limit: { type: 'integer', minimum: 1, maximum: 100, default: 10 }, + sinceId: { type: 'string', format: 'misskey:id' }, + untilId: { type: 'string', format: 'misskey:id' }, + sinceDate: { type: 'integer' }, + untilDate: { type: 'integer' }, + }, + required: [], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, user) => { +export default define(meta, paramDef, async (ps, user) => { const m = await fetchMeta(); if (m.disableGlobalTimeline) { if (user == null || (!user.isAdmin && !user.isModerator)) { @@ -76,10 +60,16 @@ export default define(meta, async (ps, user) => { .andWhere('note.visibility = \'public\'') .andWhere('note.channelId IS NULL') .innerJoinAndSelect('note.user', 'user') + .leftJoinAndSelect('user.avatar', 'avatar') + .leftJoinAndSelect('user.banner', 'banner') .leftJoinAndSelect('note.reply', 'reply') .leftJoinAndSelect('note.renote', 'renote') .leftJoinAndSelect('reply.user', 'replyUser') - .leftJoinAndSelect('renote.user', 'renoteUser'); + .leftJoinAndSelect('replyUser.avatar', 'replyUserAvatar') + .leftJoinAndSelect('replyUser.banner', 'replyUserBanner') + .leftJoinAndSelect('renote.user', 'renoteUser') + .leftJoinAndSelect('renoteUser.avatar', 'renoteUserAvatar') + .leftJoinAndSelect('renoteUser.banner', 'renoteUserBanner'); generateRepliesQuery(query, user); if (user) generateMutedUserQuery(query, user); @@ -92,7 +82,7 @@ export default define(meta, async (ps, user) => { } //#endregion - const timeline = await query.take(ps.limit!).getMany(); + const timeline = await query.take(ps.limit).getMany(); process.nextTick(() => { if (user) { diff --git a/packages/backend/src/server/api/endpoints/notes/hybrid-timeline.ts b/packages/backend/src/server/api/endpoints/notes/hybrid-timeline.ts index b43849102..9bcb64b65 100644 --- a/packages/backend/src/server/api/endpoints/notes/hybrid-timeline.ts +++ b/packages/backend/src/server/api/endpoints/notes/hybrid-timeline.ts @@ -1,67 +1,23 @@ -import $ from 'cafy'; -import { ID } from '@/misc/cafy-id'; -import define from '../../define'; -import { fetchMeta } from '@/misc/fetch-meta'; -import { ApiError } from '../../error'; -import { makePaginationQuery } from '../../common/make-pagination-query'; -import { Followings, Notes } from '@/models/index'; +import define from '../../define.js'; +import { fetchMeta } from '@/misc/fetch-meta.js'; +import { ApiError } from '../../error.js'; +import { makePaginationQuery } from '../../common/make-pagination-query.js'; +import { Followings, Notes } from '@/models/index.js'; import { Brackets } from 'typeorm'; -import { generateVisibilityQuery } from '../../common/generate-visibility-query'; -import { generateMutedUserQuery } from '../../common/generate-muted-user-query'; -import { generateMutedInstanceQuery } from '../../common/generate-muted-instance-query'; -import { activeUsersChart } from '@/services/chart/index'; -import { generateRepliesQuery } from '../../common/generate-replies-query'; -import { generateMutedNoteQuery } from '../../common/generate-muted-note-query'; -import { generateChannelQuery } from '../../common/generate-channel-query'; -import { generateBlockedUserQuery } from '../../common/generate-block-query'; +import { generateVisibilityQuery } from '../../common/generate-visibility-query.js'; +import { generateMutedUserQuery } from '../../common/generate-muted-user-query.js'; +import { generateMutedInstanceQuery } from '../../common/generate-muted-instance-query.js'; +import { activeUsersChart } from '@/services/chart/index.js'; +import { generateRepliesQuery } from '../../common/generate-replies-query.js'; +import { generateMutedNoteQuery } from '../../common/generate-muted-note-query.js'; +import { generateChannelQuery } from '../../common/generate-channel-query.js'; +import { generateBlockedUserQuery } from '../../common/generate-block-query.js'; export const meta = { tags: ['notes'], requireCredential: true, - params: { - limit: { - validator: $.optional.num.range(1, 100), - default: 10, - }, - - sinceId: { - validator: $.optional.type(ID), - }, - - untilId: { - validator: $.optional.type(ID), - }, - - sinceDate: { - validator: $.optional.num, - }, - - untilDate: { - validator: $.optional.num, - }, - - includeMyRenotes: { - validator: $.optional.bool, - default: true, - }, - - includeRenotedMyNotes: { - validator: $.optional.bool, - default: true, - }, - - includeLocalRenotes: { - validator: $.optional.bool, - default: true, - }, - - withFiles: { - validator: $.optional.bool, - }, - }, - res: { type: 'array', optional: false, nullable: false, @@ -81,8 +37,24 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + limit: { type: 'integer', minimum: 1, maximum: 100, default: 10 }, + sinceId: { type: 'string', format: 'misskey:id' }, + untilId: { type: 'string', format: 'misskey:id' }, + sinceDate: { type: 'integer' }, + untilDate: { type: 'integer' }, + includeMyRenotes: { type: 'boolean', default: true }, + includeRenotedMyNotes: { type: 'boolean', default: true }, + includeLocalRenotes: { type: 'boolean', default: true }, + withFiles: { type: 'boolean' }, + }, + required: [], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, user) => { +export default define(meta, paramDef, async (ps, user) => { const m = await fetchMeta(); if (m.disableLocalTimeline && !user.isAdmin && !user.isModerator) { throw new ApiError(meta.errors.stlDisabled); @@ -100,10 +72,16 @@ export default define(meta, async (ps, user) => { .orWhere('(note.visibility = \'public\') AND (note.userHost IS NULL)'); })) .innerJoinAndSelect('note.user', 'user') + .leftJoinAndSelect('user.avatar', 'avatar') + .leftJoinAndSelect('user.banner', 'banner') .leftJoinAndSelect('note.reply', 'reply') .leftJoinAndSelect('note.renote', 'renote') .leftJoinAndSelect('reply.user', 'replyUser') + .leftJoinAndSelect('replyUser.avatar', 'replyUserAvatar') + .leftJoinAndSelect('replyUser.banner', 'replyUserBanner') .leftJoinAndSelect('renote.user', 'renoteUser') + .leftJoinAndSelect('renoteUser.avatar', 'renoteUserAvatar') + .leftJoinAndSelect('renoteUser.banner', 'renoteUserBanner') .setParameters(followingQuery.getParameters()); generateChannelQuery(query, user); @@ -149,7 +127,7 @@ export default define(meta, async (ps, user) => { } //#endregion - const timeline = await query.take(ps.limit!).getMany(); + const timeline = await query.take(ps.limit).getMany(); process.nextTick(() => { if (user) { diff --git a/packages/backend/src/server/api/endpoints/notes/local-timeline.ts b/packages/backend/src/server/api/endpoints/notes/local-timeline.ts index ce0bcbeb7..12fc88b1f 100644 --- a/packages/backend/src/server/api/endpoints/notes/local-timeline.ts +++ b/packages/backend/src/server/api/endpoints/notes/local-timeline.ts @@ -1,58 +1,20 @@ -import $ from 'cafy'; -import { ID } from '@/misc/cafy-id'; -import define from '../../define'; -import { fetchMeta } from '@/misc/fetch-meta'; -import { ApiError } from '../../error'; -import { Notes } from '@/models/index'; -import { generateMutedUserQuery } from '../../common/generate-muted-user-query'; -import { makePaginationQuery } from '../../common/make-pagination-query'; -import { generateVisibilityQuery } from '../../common/generate-visibility-query'; -import { activeUsersChart } from '@/services/chart/index'; +import define from '../../define.js'; +import { fetchMeta } from '@/misc/fetch-meta.js'; +import { ApiError } from '../../error.js'; +import { Notes } from '@/models/index.js'; +import { generateMutedUserQuery } from '../../common/generate-muted-user-query.js'; +import { makePaginationQuery } from '../../common/make-pagination-query.js'; +import { generateVisibilityQuery } from '../../common/generate-visibility-query.js'; +import { activeUsersChart } from '@/services/chart/index.js'; import { Brackets } from 'typeorm'; -import { generateRepliesQuery } from '../../common/generate-replies-query'; -import { generateMutedNoteQuery } from '../../common/generate-muted-note-query'; -import { generateChannelQuery } from '../../common/generate-channel-query'; -import { generateBlockedUserQuery } from '../../common/generate-block-query'; +import { generateRepliesQuery } from '../../common/generate-replies-query.js'; +import { generateMutedNoteQuery } from '../../common/generate-muted-note-query.js'; +import { generateChannelQuery } from '../../common/generate-channel-query.js'; +import { generateBlockedUserQuery } from '../../common/generate-block-query.js'; export const meta = { tags: ['notes'], - params: { - withFiles: { - validator: $.optional.bool, - }, - - fileType: { - validator: $.optional.arr($.str), - }, - - excludeNsfw: { - validator: $.optional.bool, - default: false, - }, - - limit: { - validator: $.optional.num.range(1, 100), - default: 10, - }, - - sinceId: { - validator: $.optional.type(ID), - }, - - untilId: { - validator: $.optional.type(ID), - }, - - sinceDate: { - validator: $.optional.num, - }, - - untilDate: { - validator: $.optional.num, - }, - }, - res: { type: 'array', optional: false, nullable: false, @@ -72,8 +34,25 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + withFiles: { type: 'boolean' }, + fileType: { type: 'array', items: { + type: 'string', + } }, + excludeNsfw: { type: 'boolean', default: false }, + limit: { type: 'integer', minimum: 1, maximum: 100, default: 10 }, + sinceId: { type: 'string', format: 'misskey:id' }, + untilId: { type: 'string', format: 'misskey:id' }, + sinceDate: { type: 'integer' }, + untilDate: { type: 'integer' }, + }, + required: [], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, user) => { +export default define(meta, paramDef, async (ps, user) => { const m = await fetchMeta(); if (m.disableLocalTimeline) { if (user == null || (!user.isAdmin && !user.isModerator)) { @@ -86,10 +65,16 @@ export default define(meta, async (ps, user) => { ps.sinceId, ps.untilId, ps.sinceDate, ps.untilDate) .andWhere('(note.visibility = \'public\') AND (note.userHost IS NULL)') .innerJoinAndSelect('note.user', 'user') + .leftJoinAndSelect('user.avatar', 'avatar') + .leftJoinAndSelect('user.banner', 'banner') .leftJoinAndSelect('note.reply', 'reply') .leftJoinAndSelect('note.renote', 'renote') .leftJoinAndSelect('reply.user', 'replyUser') - .leftJoinAndSelect('renote.user', 'renoteUser'); + .leftJoinAndSelect('replyUser.avatar', 'replyUserAvatar') + .leftJoinAndSelect('replyUser.banner', 'replyUserBanner') + .leftJoinAndSelect('renote.user', 'renoteUser') + .leftJoinAndSelect('renoteUser.avatar', 'renoteUserAvatar') + .leftJoinAndSelect('renoteUser.banner', 'renoteUserBanner'); generateChannelQuery(query, user); generateRepliesQuery(query, user); @@ -118,7 +103,7 @@ export default define(meta, async (ps, user) => { } //#endregion - const timeline = await query.take(ps.limit!).getMany(); + const timeline = await query.take(ps.limit).getMany(); process.nextTick(() => { if (user) { diff --git a/packages/backend/src/server/api/endpoints/notes/mentions.ts b/packages/backend/src/server/api/endpoints/notes/mentions.ts index 81b384436..eafbba322 100644 --- a/packages/backend/src/server/api/endpoints/notes/mentions.ts +++ b/packages/backend/src/server/api/endpoints/notes/mentions.ts @@ -1,44 +1,18 @@ -import $ from 'cafy'; -import { ID } from '@/misc/cafy-id'; -import define from '../../define'; -import read from '@/services/note/read'; -import { Notes, Followings } from '@/models/index'; -import { generateVisibilityQuery } from '../../common/generate-visibility-query'; -import { generateMutedUserQuery } from '../../common/generate-muted-user-query'; -import { makePaginationQuery } from '../../common/make-pagination-query'; +import define from '../../define.js'; +import read from '@/services/note/read.js'; +import { Notes, Followings } from '@/models/index.js'; +import { generateVisibilityQuery } from '../../common/generate-visibility-query.js'; +import { generateMutedUserQuery } from '../../common/generate-muted-user-query.js'; +import { makePaginationQuery } from '../../common/make-pagination-query.js'; import { Brackets } from 'typeorm'; -import { generateBlockedUserQuery } from '../../common/generate-block-query'; -import { generateMutedNoteThreadQuery } from '../../common/generate-muted-note-thread-query'; +import { generateBlockedUserQuery } from '../../common/generate-block-query.js'; +import { generateMutedNoteThreadQuery } from '../../common/generate-muted-note-thread-query.js'; export const meta = { tags: ['notes'], requireCredential: true, - params: { - following: { - validator: $.optional.bool, - default: false, - }, - - limit: { - validator: $.optional.num.range(1, 100), - default: 10, - }, - - sinceId: { - validator: $.optional.type(ID), - }, - - untilId: { - validator: $.optional.type(ID), - }, - - visibility: { - validator: $.optional.str, - }, - }, - res: { type: 'array', optional: false, nullable: false, @@ -50,8 +24,20 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + following: { type: 'boolean', default: false }, + limit: { type: 'integer', minimum: 1, maximum: 100, default: 10 }, + sinceId: { type: 'string', format: 'misskey:id' }, + untilId: { type: 'string', format: 'misskey:id' }, + visibility: { type: 'string' }, + }, + required: [], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, user) => { +export default define(meta, paramDef, async (ps, user) => { const followingQuery = Followings.createQueryBuilder('following') .select('following.followeeId') .where('following.followerId = :followerId', { followerId: user.id }); @@ -62,10 +48,16 @@ export default define(meta, async (ps, user) => { .orWhere(`'{"${user.id}"}' <@ note.visibleUserIds`); })) .innerJoinAndSelect('note.user', 'user') + .leftJoinAndSelect('user.avatar', 'avatar') + .leftJoinAndSelect('user.banner', 'banner') .leftJoinAndSelect('note.reply', 'reply') .leftJoinAndSelect('note.renote', 'renote') .leftJoinAndSelect('reply.user', 'replyUser') - .leftJoinAndSelect('renote.user', 'renoteUser'); + .leftJoinAndSelect('replyUser.avatar', 'replyUserAvatar') + .leftJoinAndSelect('replyUser.banner', 'replyUserBanner') + .leftJoinAndSelect('renote.user', 'renoteUser') + .leftJoinAndSelect('renoteUser.avatar', 'renoteUserAvatar') + .leftJoinAndSelect('renoteUser.banner', 'renoteUserBanner'); generateVisibilityQuery(query, user); generateMutedUserQuery(query, user); @@ -81,7 +73,7 @@ export default define(meta, async (ps, user) => { query.setParameters(followingQuery.getParameters()); } - const mentions = await query.take(ps.limit!).getMany(); + const mentions = await query.take(ps.limit).getMany(); read(user.id, mentions); diff --git a/packages/backend/src/server/api/endpoints/notes/polls/recommendation.ts b/packages/backend/src/server/api/endpoints/notes/polls/recommendation.ts index 79b558e65..bdd1aeecd 100644 --- a/packages/backend/src/server/api/endpoints/notes/polls/recommendation.ts +++ b/packages/backend/src/server/api/endpoints/notes/polls/recommendation.ts @@ -1,6 +1,5 @@ -import $ from 'cafy'; -import define from '../../../define'; -import { Polls, Mutings, Notes, PollVotes } from '@/models/index'; +import define from '../../../define.js'; +import { Polls, Mutings, Notes, PollVotes } from '@/models/index.js'; import { Brackets, In } from 'typeorm'; export const meta = { @@ -8,18 +7,6 @@ export const meta = { requireCredential: true, - params: { - limit: { - validator: $.optional.num.range(1, 100), - default: 10, - }, - - offset: { - validator: $.optional.num.min(0), - default: 0, - }, - }, - res: { type: 'array', optional: false, nullable: false, @@ -31,8 +18,17 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + limit: { type: 'integer', minimum: 1, maximum: 100, default: 10 }, + offset: { type: 'integer', default: 0 }, + }, + required: [], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, user) => { +export default define(meta, paramDef, async (ps, user) => { const query = Polls.createQueryBuilder('poll') .where('poll.userHost IS NULL') .andWhere(`poll.userId != :meId`, { meId: user.id }) @@ -64,7 +60,7 @@ export default define(meta, async (ps, user) => { query.setParameters(mutingQuery.getParameters()); //#endregion - const polls = await query.take(ps.limit!).skip(ps.offset).getMany(); + const polls = await query.take(ps.limit).skip(ps.offset).getMany(); if (polls.length === 0) return []; diff --git a/packages/backend/src/server/api/endpoints/notes/polls/vote.ts b/packages/backend/src/server/api/endpoints/notes/polls/vote.ts index 77387cacb..ef52d0366 100644 --- a/packages/backend/src/server/api/endpoints/notes/polls/vote.ts +++ b/packages/backend/src/server/api/endpoints/notes/polls/vote.ts @@ -1,18 +1,16 @@ -import $ from 'cafy'; -import { ID } from '@/misc/cafy-id'; -import { publishNoteStream } from '@/services/stream'; -import { createNotification } from '@/services/create-notification'; -import define from '../../../define'; -import { ApiError } from '../../../error'; -import { getNote } from '../../../common/getters'; -import { deliver } from '@/queue/index'; -import { renderActivity } from '@/remote/activitypub/renderer/index'; -import renderVote from '@/remote/activitypub/renderer/vote'; -import { deliverQuestionUpdate } from '@/services/note/polls/update'; -import { PollVotes, NoteWatchings, Users, Polls, Blockings } from '@/models/index'; +import { publishNoteStream } from '@/services/stream.js'; +import { createNotification } from '@/services/create-notification.js'; +import define from '../../../define.js'; +import { ApiError } from '../../../error.js'; +import { getNote } from '../../../common/getters.js'; +import { deliver } from '@/queue/index.js'; +import { renderActivity } from '@/remote/activitypub/renderer/index.js'; +import renderVote from '@/remote/activitypub/renderer/vote.js'; +import { deliverQuestionUpdate } from '@/services/note/polls/update.js'; +import { PollVotes, NoteWatchings, Users, Polls, Blockings } from '@/models/index.js'; import { Not } from 'typeorm'; -import { IRemoteUser } from '@/models/entities/user'; -import { genId } from '@/misc/gen-id'; +import { IRemoteUser } from '@/models/entities/user.js'; +import { genId } from '@/misc/gen-id.js'; export const meta = { tags: ['notes'], @@ -21,16 +19,6 @@ export const meta = { kind: 'write:votes', - params: { - noteId: { - validator: $.type(ID), - }, - - choice: { - validator: $.num, - }, - }, - errors: { noSuchNote: { message: 'No such note.', @@ -70,8 +58,17 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + noteId: { type: 'string', format: 'misskey:id' }, + choice: { type: 'integer' }, + }, + required: ['noteId', 'choice'], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, user) => { +export default define(meta, paramDef, async (ps, user) => { const createdAt = new Date(); // Get votee diff --git a/packages/backend/src/server/api/endpoints/notes/reactions.ts b/packages/backend/src/server/api/endpoints/notes/reactions.ts index 5205a7817..43e5d1ef6 100644 --- a/packages/backend/src/server/api/endpoints/notes/reactions.ts +++ b/packages/backend/src/server/api/endpoints/notes/reactions.ts @@ -1,45 +1,15 @@ -import $ from 'cafy'; -import { ID } from '@/misc/cafy-id'; -import define from '../../define'; -import { getNote } from '../../common/getters'; -import { ApiError } from '../../error'; -import { NoteReactions } from '@/models/index'; +import define from '../../define.js'; +import { getNote } from '../../common/getters.js'; +import { ApiError } from '../../error.js'; +import { NoteReactions } from '@/models/index.js'; import { DeepPartial } from 'typeorm'; -import { NoteReaction } from '@/models/entities/note-reaction'; +import { NoteReaction } from '@/models/entities/note-reaction.js'; export const meta = { tags: ['notes', 'reactions'], requireCredential: false, - params: { - noteId: { - validator: $.type(ID), - }, - - type: { - validator: $.optional.nullable.str, - }, - - limit: { - validator: $.optional.num.range(1, 100), - default: 10, - }, - - offset: { - validator: $.optional.num, - default: 0, - }, - - sinceId: { - validator: $.optional.type(ID), - }, - - untilId: { - validator: $.optional.type(ID), - }, - }, - res: { type: 'array', optional: false, nullable: false, @@ -59,8 +29,21 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + noteId: { type: 'string', format: 'misskey:id' }, + type: { type: 'string', nullable: true }, + limit: { type: 'integer', minimum: 1, maximum: 100, default: 10 }, + offset: { type: 'integer', default: 0 }, + sinceId: { type: 'string', format: 'misskey:id' }, + untilId: { type: 'string', format: 'misskey:id' }, + }, + required: ['noteId'], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, user) => { +export default define(meta, paramDef, async (ps, user) => { const note = await getNote(ps.noteId).catch(e => { if (e.id === '9725d0ce-ba28-4dde-95a7-2cbb2c15de24') throw new ApiError(meta.errors.noSuchNote); throw e; @@ -80,11 +63,12 @@ export default define(meta, async (ps, user) => { const reactions = await NoteReactions.find({ where: query, - take: ps.limit!, + take: ps.limit, skip: ps.offset, order: { id: -1, }, + relations: ['user', 'user.avatar', 'user.banner', 'note'], }); return await Promise.all(reactions.map(reaction => NoteReactions.pack(reaction, user))); diff --git a/packages/backend/src/server/api/endpoints/notes/reactions/create.ts b/packages/backend/src/server/api/endpoints/notes/reactions/create.ts index 1b42781ce..07e52a926 100644 --- a/packages/backend/src/server/api/endpoints/notes/reactions/create.ts +++ b/packages/backend/src/server/api/endpoints/notes/reactions/create.ts @@ -1,9 +1,7 @@ -import $ from 'cafy'; -import { ID } from '@/misc/cafy-id'; -import createReaction from '@/services/note/reaction/create'; -import define from '../../../define'; -import { getNote } from '../../../common/getters'; -import { ApiError } from '../../../error'; +import createReaction from '@/services/note/reaction/create.js'; +import define from '../../../define.js'; +import { getNote } from '../../../common/getters.js'; +import { ApiError } from '../../../error.js'; export const meta = { tags: ['reactions', 'notes'], @@ -12,16 +10,6 @@ export const meta = { kind: 'write:reactions', - params: { - noteId: { - validator: $.type(ID), - }, - - reaction: { - validator: $.str, - }, - }, - errors: { noSuchNote: { message: 'No such note.', @@ -43,8 +31,17 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + noteId: { type: 'string', format: 'misskey:id' }, + reaction: { type: 'string' }, + }, + required: ['noteId', 'reaction'], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, user) => { +export default define(meta, paramDef, async (ps, user) => { const note = await getNote(ps.noteId).catch(e => { if (e.id === '9725d0ce-ba28-4dde-95a7-2cbb2c15de24') throw new ApiError(meta.errors.noSuchNote); throw e; diff --git a/packages/backend/src/server/api/endpoints/notes/reactions/delete.ts b/packages/backend/src/server/api/endpoints/notes/reactions/delete.ts index 1d686b597..639ecae26 100644 --- a/packages/backend/src/server/api/endpoints/notes/reactions/delete.ts +++ b/packages/backend/src/server/api/endpoints/notes/reactions/delete.ts @@ -1,10 +1,8 @@ -import $ from 'cafy'; -import { ID } from '@/misc/cafy-id'; -import define from '../../../define'; +import define from '../../../define.js'; import ms from 'ms'; -import deleteReaction from '@/services/note/reaction/delete'; -import { getNote } from '../../../common/getters'; -import { ApiError } from '../../../error'; +import deleteReaction from '@/services/note/reaction/delete.js'; +import { getNote } from '../../../common/getters.js'; +import { ApiError } from '../../../error.js'; export const meta = { tags: ['reactions', 'notes'], @@ -19,12 +17,6 @@ export const meta = { minInterval: ms('3sec'), }, - params: { - noteId: { - validator: $.type(ID), - }, - }, - errors: { noSuchNote: { message: 'No such note.', @@ -40,8 +32,16 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + noteId: { type: 'string', format: 'misskey:id' }, + }, + required: ['noteId'], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, user) => { +export default define(meta, paramDef, async (ps, user) => { const note = await getNote(ps.noteId).catch(e => { if (e.id === '9725d0ce-ba28-4dde-95a7-2cbb2c15de24') throw new ApiError(meta.errors.noSuchNote); throw e; diff --git a/packages/backend/src/server/api/endpoints/notes/renotes.ts b/packages/backend/src/server/api/endpoints/notes/renotes.ts index f71d23146..87c855a5e 100644 --- a/packages/backend/src/server/api/endpoints/notes/renotes.ts +++ b/packages/backend/src/server/api/endpoints/notes/renotes.ts @@ -1,38 +1,17 @@ -import $ from 'cafy'; -import { ID } from '@/misc/cafy-id'; -import define from '../../define'; -import { getNote } from '../../common/getters'; -import { ApiError } from '../../error'; -import { generateVisibilityQuery } from '../../common/generate-visibility-query'; -import { generateMutedUserQuery } from '../../common/generate-muted-user-query'; -import { makePaginationQuery } from '../../common/make-pagination-query'; -import { Notes } from '@/models/index'; -import { generateBlockedUserQuery } from '../../common/generate-block-query'; +import define from '../../define.js'; +import { getNote } from '../../common/getters.js'; +import { ApiError } from '../../error.js'; +import { generateVisibilityQuery } from '../../common/generate-visibility-query.js'; +import { generateMutedUserQuery } from '../../common/generate-muted-user-query.js'; +import { makePaginationQuery } from '../../common/make-pagination-query.js'; +import { Notes } from '@/models/index.js'; +import { generateBlockedUserQuery } from '../../common/generate-block-query.js'; export const meta = { tags: ['notes'], requireCredential: false, - params: { - noteId: { - validator: $.type(ID), - }, - - limit: { - validator: $.optional.num.range(1, 100), - default: 10, - }, - - sinceId: { - validator: $.optional.type(ID), - }, - - untilId: { - validator: $.optional.type(ID), - }, - }, - res: { type: 'array', optional: false, nullable: false, @@ -52,8 +31,19 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + noteId: { type: 'string', format: 'misskey:id' }, + limit: { type: 'integer', minimum: 1, maximum: 100, default: 10 }, + sinceId: { type: 'string', format: 'misskey:id' }, + untilId: { type: 'string', format: 'misskey:id' }, + }, + required: ['noteId'], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, user) => { +export default define(meta, paramDef, async (ps, user) => { const note = await getNote(ps.noteId).catch(e => { if (e.id === '9725d0ce-ba28-4dde-95a7-2cbb2c15de24') throw new ApiError(meta.errors.noSuchNote); throw e; @@ -62,16 +52,22 @@ export default define(meta, async (ps, user) => { const query = makePaginationQuery(Notes.createQueryBuilder('note'), ps.sinceId, ps.untilId) .andWhere(`note.renoteId = :renoteId`, { renoteId: note.id }) .innerJoinAndSelect('note.user', 'user') + .leftJoinAndSelect('user.avatar', 'avatar') + .leftJoinAndSelect('user.banner', 'banner') .leftJoinAndSelect('note.reply', 'reply') .leftJoinAndSelect('note.renote', 'renote') .leftJoinAndSelect('reply.user', 'replyUser') - .leftJoinAndSelect('renote.user', 'renoteUser'); + .leftJoinAndSelect('replyUser.avatar', 'replyUserAvatar') + .leftJoinAndSelect('replyUser.banner', 'replyUserBanner') + .leftJoinAndSelect('renote.user', 'renoteUser') + .leftJoinAndSelect('renoteUser.avatar', 'renoteUserAvatar') + .leftJoinAndSelect('renoteUser.banner', 'renoteUserBanner'); generateVisibilityQuery(query, user); if (user) generateMutedUserQuery(query, user); if (user) generateBlockedUserQuery(query, user); - const renotes = await query.take(ps.limit!).getMany(); + const renotes = await query.take(ps.limit).getMany(); return await Notes.packMany(renotes, user); }); diff --git a/packages/backend/src/server/api/endpoints/notes/replies.ts b/packages/backend/src/server/api/endpoints/notes/replies.ts index 62c56534e..3053eabe3 100644 --- a/packages/backend/src/server/api/endpoints/notes/replies.ts +++ b/packages/backend/src/server/api/endpoints/notes/replies.ts @@ -1,36 +1,15 @@ -import $ from 'cafy'; -import { ID } from '@/misc/cafy-id'; -import define from '../../define'; -import { Notes } from '@/models/index'; -import { makePaginationQuery } from '../../common/make-pagination-query'; -import { generateVisibilityQuery } from '../../common/generate-visibility-query'; -import { generateMutedUserQuery } from '../../common/generate-muted-user-query'; -import { generateBlockedUserQuery } from '../../common/generate-block-query'; +import define from '../../define.js'; +import { Notes } from '@/models/index.js'; +import { makePaginationQuery } from '../../common/make-pagination-query.js'; +import { generateVisibilityQuery } from '../../common/generate-visibility-query.js'; +import { generateMutedUserQuery } from '../../common/generate-muted-user-query.js'; +import { generateBlockedUserQuery } from '../../common/generate-block-query.js'; export const meta = { tags: ['notes'], requireCredential: false, - params: { - noteId: { - validator: $.type(ID), - }, - - sinceId: { - validator: $.optional.type(ID), - }, - - untilId: { - validator: $.optional.type(ID), - }, - - limit: { - validator: $.optional.num.range(1, 100), - default: 10, - }, - }, - res: { type: 'array', optional: false, nullable: false, @@ -42,21 +21,38 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + noteId: { type: 'string', format: 'misskey:id' }, + sinceId: { type: 'string', format: 'misskey:id' }, + untilId: { type: 'string', format: 'misskey:id' }, + limit: { type: 'integer', minimum: 1, maximum: 100, default: 10 }, + }, + required: ['noteId'], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, user) => { +export default define(meta, paramDef, async (ps, user) => { const query = makePaginationQuery(Notes.createQueryBuilder('note'), ps.sinceId, ps.untilId) .andWhere('note.replyId = :replyId', { replyId: ps.noteId }) .innerJoinAndSelect('note.user', 'user') + .leftJoinAndSelect('user.avatar', 'avatar') + .leftJoinAndSelect('user.banner', 'banner') .leftJoinAndSelect('note.reply', 'reply') .leftJoinAndSelect('note.renote', 'renote') .leftJoinAndSelect('reply.user', 'replyUser') - .leftJoinAndSelect('renote.user', 'renoteUser'); + .leftJoinAndSelect('replyUser.avatar', 'replyUserAvatar') + .leftJoinAndSelect('replyUser.banner', 'replyUserBanner') + .leftJoinAndSelect('renote.user', 'renoteUser') + .leftJoinAndSelect('renoteUser.avatar', 'renoteUserAvatar') + .leftJoinAndSelect('renoteUser.banner', 'renoteUserBanner'); generateVisibilityQuery(query, user); if (user) generateMutedUserQuery(query, user); if (user) generateBlockedUserQuery(query, user); - const timeline = await query.take(ps.limit!).getMany(); + const timeline = await query.take(ps.limit).getMany(); return await Notes.packMany(timeline, user); }); diff --git a/packages/backend/src/server/api/endpoints/notes/search-by-tag.ts b/packages/backend/src/server/api/endpoints/notes/search-by-tag.ts index 87eaffe2f..c6503eb05 100644 --- a/packages/backend/src/server/api/endpoints/notes/search-by-tag.ts +++ b/packages/backend/src/server/api/endpoints/notes/search-by-tag.ts @@ -1,60 +1,16 @@ -import $ from 'cafy'; -import { ID } from '@/misc/cafy-id'; -import define from '../../define'; -import { makePaginationQuery } from '../../common/make-pagination-query'; -import { Notes } from '@/models/index'; -import { generateMutedUserQuery } from '../../common/generate-muted-user-query'; -import { generateVisibilityQuery } from '../../common/generate-visibility-query'; +import define from '../../define.js'; +import { makePaginationQuery } from '../../common/make-pagination-query.js'; +import { Notes } from '@/models/index.js'; +import { generateMutedUserQuery } from '../../common/generate-muted-user-query.js'; +import { generateVisibilityQuery } from '../../common/generate-visibility-query.js'; import { Brackets } from 'typeorm'; -import { safeForSql } from '@/misc/safe-for-sql'; -import { normalizeForSearch } from '@/misc/normalize-for-search'; -import { generateBlockedUserQuery } from '../../common/generate-block-query'; +import { safeForSql } from '@/misc/safe-for-sql.js'; +import { normalizeForSearch } from '@/misc/normalize-for-search.js'; +import { generateBlockedUserQuery } from '../../common/generate-block-query.js'; export const meta = { tags: ['notes', 'hashtags'], - params: { - tag: { - validator: $.optional.str, - }, - - query: { - validator: $.optional.arr($.arr($.str)), - }, - - reply: { - validator: $.optional.nullable.bool, - default: null, - }, - - renote: { - validator: $.optional.nullable.bool, - default: null, - }, - - withFiles: { - validator: $.optional.bool, - }, - - poll: { - validator: $.optional.nullable.bool, - default: null, - }, - - sinceId: { - validator: $.optional.type(ID), - }, - - untilId: { - validator: $.optional.type(ID), - }, - - limit: { - validator: $.optional.num.range(1, 100), - default: 10, - }, - }, - res: { type: 'array', optional: false, nullable: false, @@ -66,14 +22,40 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + tag: { type: 'string' }, + query: { type: 'array', items: { + type: 'array', items: { + type: 'string', + }, + } }, + reply: { type: 'boolean', nullable: true, default: null }, + renote: { type: 'boolean', nullable: true, default: null }, + withFiles: { type: 'boolean' }, + poll: { type: 'boolean', nullable: true, default: null }, + sinceId: { type: 'string', format: 'misskey:id' }, + untilId: { type: 'string', format: 'misskey:id' }, + limit: { type: 'integer', minimum: 1, maximum: 100, default: 10 }, + }, + required: [], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, me) => { +export default define(meta, paramDef, async (ps, me) => { const query = makePaginationQuery(Notes.createQueryBuilder('note'), ps.sinceId, ps.untilId) .innerJoinAndSelect('note.user', 'user') + .leftJoinAndSelect('user.avatar', 'avatar') + .leftJoinAndSelect('user.banner', 'banner') .leftJoinAndSelect('note.reply', 'reply') .leftJoinAndSelect('note.renote', 'renote') .leftJoinAndSelect('reply.user', 'replyUser') - .leftJoinAndSelect('renote.user', 'renoteUser'); + .leftJoinAndSelect('replyUser.avatar', 'replyUserAvatar') + .leftJoinAndSelect('replyUser.banner', 'replyUserBanner') + .leftJoinAndSelect('renote.user', 'renoteUser') + .leftJoinAndSelect('renoteUser.avatar', 'renoteUserAvatar') + .leftJoinAndSelect('renoteUser.banner', 'renoteUserBanner'); generateVisibilityQuery(query, me); if (me) generateMutedUserQuery(query, me); @@ -129,7 +111,7 @@ export default define(meta, async (ps, me) => { } // Search notes - const notes = await query.take(ps.limit!).getMany(); + const notes = await query.take(ps.limit).getMany(); return await Notes.packMany(notes, me); }); diff --git a/packages/backend/src/server/api/endpoints/notes/search.ts b/packages/backend/src/server/api/endpoints/notes/search.ts index e75212b14..e77892b15 100644 --- a/packages/backend/src/server/api/endpoints/notes/search.ts +++ b/packages/backend/src/server/api/endpoints/notes/search.ts @@ -1,54 +1,18 @@ -import $ from 'cafy'; -import es from '../../../../db/elasticsearch'; -import define from '../../define'; -import { Notes } from '@/models/index'; +import es from '../../../../db/elasticsearch.js'; +import define from '../../define.js'; +import { Notes } from '@/models/index.js'; import { In } from 'typeorm'; -import { ID } from '@/misc/cafy-id'; -import config from '@/config/index'; -import { makePaginationQuery } from '../../common/make-pagination-query'; -import { generateVisibilityQuery } from '../../common/generate-visibility-query'; -import { generateMutedUserQuery } from '../../common/generate-muted-user-query'; -import { generateBlockedUserQuery } from '../../common/generate-block-query'; +import config from '@/config/index.js'; +import { makePaginationQuery } from '../../common/make-pagination-query.js'; +import { generateVisibilityQuery } from '../../common/generate-visibility-query.js'; +import { generateMutedUserQuery } from '../../common/generate-muted-user-query.js'; +import { generateBlockedUserQuery } from '../../common/generate-block-query.js'; export const meta = { tags: ['notes'], requireCredential: false, - params: { - query: { - validator: $.str, - }, - - sinceId: { - validator: $.optional.type(ID), - }, - - untilId: { - validator: $.optional.type(ID), - }, - - limit: { - validator: $.optional.num.range(1, 100), - default: 10, - }, - - host: { - validator: $.optional.nullable.str, - default: undefined, - }, - - userId: { - validator: $.optional.nullable.type(ID), - default: null, - }, - - channelId: { - validator: $.optional.nullable.type(ID), - default: null, - }, - }, - res: { type: 'array', optional: false, nullable: false, @@ -63,8 +27,23 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + query: { type: 'string' }, + sinceId: { type: 'string', format: 'misskey:id' }, + untilId: { type: 'string', format: 'misskey:id' }, + limit: { type: 'integer', minimum: 1, maximum: 100, default: 10 }, + offset: { type: 'integer', default: 0 }, + host: { type: 'string', nullable: true }, + userId: { type: 'string', format: 'misskey:id', nullable: true, default: null }, + channelId: { type: 'string', format: 'misskey:id', nullable: true, default: null }, + }, + required: ['query'], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, me) => { +export default define(meta, paramDef, async (ps, me) => { if (es == null) { const query = makePaginationQuery(Notes.createQueryBuilder('note'), ps.sinceId, ps.untilId); @@ -77,16 +56,22 @@ export default define(meta, async (ps, me) => { query .andWhere('note.text ILIKE :q', { q: `%${ps.query}%` }) .innerJoinAndSelect('note.user', 'user') + .leftJoinAndSelect('user.avatar', 'avatar') + .leftJoinAndSelect('user.banner', 'banner') .leftJoinAndSelect('note.reply', 'reply') .leftJoinAndSelect('note.renote', 'renote') .leftJoinAndSelect('reply.user', 'replyUser') - .leftJoinAndSelect('renote.user', 'renoteUser'); + .leftJoinAndSelect('replyUser.avatar', 'replyUserAvatar') + .leftJoinAndSelect('replyUser.banner', 'replyUserBanner') + .leftJoinAndSelect('renote.user', 'renoteUser') + .leftJoinAndSelect('renoteUser.avatar', 'renoteUserAvatar') + .leftJoinAndSelect('renoteUser.banner', 'renoteUserBanner'); generateVisibilityQuery(query, me); if (me) generateMutedUserQuery(query, me); if (me) generateBlockedUserQuery(query, me); - const notes = await query.take(ps.limit!).getMany(); + const notes = await query.take(ps.limit).getMany(); return await Notes.packMany(notes, me); } else { @@ -115,7 +100,7 @@ export default define(meta, async (ps, me) => { const result = await es.search({ index: config.elasticsearch.index || 'misskey_note', body: { - size: ps.limit!, + size: ps.limit, from: ps.offset, query: { bool: { diff --git a/packages/backend/src/server/api/endpoints/notes/show.ts b/packages/backend/src/server/api/endpoints/notes/show.ts index feb94be1a..d6692923c 100644 --- a/packages/backend/src/server/api/endpoints/notes/show.ts +++ b/packages/backend/src/server/api/endpoints/notes/show.ts @@ -1,21 +1,13 @@ -import $ from 'cafy'; -import { ID } from '@/misc/cafy-id'; -import define from '../../define'; -import { getNote } from '../../common/getters'; -import { ApiError } from '../../error'; -import { Notes } from '@/models/index'; +import define from '../../define.js'; +import { getNote } from '../../common/getters.js'; +import { ApiError } from '../../error.js'; +import { Notes } from '@/models/index.js'; export const meta = { tags: ['notes'], requireCredential: false, - params: { - noteId: { - validator: $.type(ID), - }, - }, - res: { type: 'object', optional: false, nullable: false, @@ -31,8 +23,16 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + noteId: { type: 'string', format: 'misskey:id' }, + }, + required: ['noteId'], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, user) => { +export default define(meta, paramDef, async (ps, user) => { const note = await getNote(ps.noteId).catch(e => { if (e.id === '9725d0ce-ba28-4dde-95a7-2cbb2c15de24') throw new ApiError(meta.errors.noSuchNote); throw e; diff --git a/packages/backend/src/server/api/endpoints/notes/state.ts b/packages/backend/src/server/api/endpoints/notes/state.ts index c3e9090bb..6fdb8e88f 100644 --- a/packages/backend/src/server/api/endpoints/notes/state.ts +++ b/packages/backend/src/server/api/endpoints/notes/state.ts @@ -1,19 +1,11 @@ -import $ from 'cafy'; -import { ID } from '@/misc/cafy-id'; -import define from '../../define'; -import { NoteFavorites, Notes, NoteThreadMutings, NoteWatchings } from '@/models/index'; +import define from '../../define.js'; +import { NoteFavorites, Notes, NoteThreadMutings, NoteWatchings } from '@/models/index.js'; export const meta = { tags: ['notes'], requireCredential: true, - params: { - noteId: { - validator: $.type(ID), - }, - }, - res: { type: 'object', optional: false, nullable: false, @@ -34,8 +26,16 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + noteId: { type: 'string', format: 'misskey:id' }, + }, + required: ['noteId'], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, user) => { +export default define(meta, paramDef, async (ps, user) => { const note = await Notes.findOneOrFail(ps.noteId); const [favorite, watching, threadMuting] = await Promise.all([ diff --git a/packages/backend/src/server/api/endpoints/notes/thread-muting/create.ts b/packages/backend/src/server/api/endpoints/notes/thread-muting/create.ts index a8b50d90f..e48a2cf57 100644 --- a/packages/backend/src/server/api/endpoints/notes/thread-muting/create.ts +++ b/packages/backend/src/server/api/endpoints/notes/thread-muting/create.ts @@ -1,11 +1,9 @@ -import $ from 'cafy'; -import { ID } from '@/misc/cafy-id'; -import define from '../../../define'; -import { getNote } from '../../../common/getters'; -import { ApiError } from '../../../error'; -import { Notes, NoteThreadMutings } from '@/models'; -import { genId } from '@/misc/gen-id'; -import readNote from '@/services/note/read'; +import define from '../../../define.js'; +import { getNote } from '../../../common/getters.js'; +import { ApiError } from '../../../error.js'; +import { Notes, NoteThreadMutings } from '@/models/index.js'; +import { genId } from '@/misc/gen-id.js'; +import readNote from '@/services/note/read.js'; export const meta = { tags: ['notes'], @@ -14,12 +12,6 @@ export const meta = { kind: 'write:account', - params: { - noteId: { - validator: $.type(ID), - }, - }, - errors: { noSuchNote: { message: 'No such note.', @@ -29,8 +21,16 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + noteId: { type: 'string', format: 'misskey:id' }, + }, + required: ['noteId'], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, user) => { +export default define(meta, paramDef, async (ps, user) => { const note = await getNote(ps.noteId).catch(e => { if (e.id === '9725d0ce-ba28-4dde-95a7-2cbb2c15de24') throw new ApiError(meta.errors.noSuchNote); throw e; diff --git a/packages/backend/src/server/api/endpoints/notes/thread-muting/delete.ts b/packages/backend/src/server/api/endpoints/notes/thread-muting/delete.ts index f76b526ce..4fb3137a5 100644 --- a/packages/backend/src/server/api/endpoints/notes/thread-muting/delete.ts +++ b/packages/backend/src/server/api/endpoints/notes/thread-muting/delete.ts @@ -1,9 +1,7 @@ -import $ from 'cafy'; -import { ID } from '@/misc/cafy-id'; -import define from '../../../define'; -import { getNote } from '../../../common/getters'; -import { ApiError } from '../../../error'; -import { NoteThreadMutings } from '@/models'; +import define from '../../../define.js'; +import { getNote } from '../../../common/getters.js'; +import { ApiError } from '../../../error.js'; +import { NoteThreadMutings } from '@/models/index.js'; export const meta = { tags: ['notes'], @@ -12,12 +10,6 @@ export const meta = { kind: 'write:account', - params: { - noteId: { - validator: $.type(ID), - }, - }, - errors: { noSuchNote: { message: 'No such note.', @@ -27,8 +19,16 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + noteId: { type: 'string', format: 'misskey:id' }, + }, + required: ['noteId'], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, user) => { +export default define(meta, paramDef, async (ps, user) => { const note = await getNote(ps.noteId).catch(e => { if (e.id === '9725d0ce-ba28-4dde-95a7-2cbb2c15de24') throw new ApiError(meta.errors.noSuchNote); throw e; diff --git a/packages/backend/src/server/api/endpoints/notes/timeline.ts b/packages/backend/src/server/api/endpoints/notes/timeline.ts index f8cd08324..fde66b241 100644 --- a/packages/backend/src/server/api/endpoints/notes/timeline.ts +++ b/packages/backend/src/server/api/endpoints/notes/timeline.ts @@ -1,65 +1,21 @@ -import $ from 'cafy'; -import { ID } from '@/misc/cafy-id'; -import define from '../../define'; -import { makePaginationQuery } from '../../common/make-pagination-query'; -import { Notes, Followings } from '@/models/index'; -import { generateVisibilityQuery } from '../../common/generate-visibility-query'; -import { generateMutedUserQuery } from '../../common/generate-muted-user-query'; -import { generateMutedInstanceQuery } from '../../common/generate-muted-instance-query'; -import { activeUsersChart } from '@/services/chart/index'; +import define from '../../define.js'; +import { makePaginationQuery } from '../../common/make-pagination-query.js'; +import { Notes, Followings } from '@/models/index.js'; +import { generateVisibilityQuery } from '../../common/generate-visibility-query.js'; +import { generateMutedUserQuery } from '../../common/generate-muted-user-query.js'; +import { generateMutedInstanceQuery } from '../../common/generate-muted-instance-query.js'; +import { activeUsersChart } from '@/services/chart/index.js'; import { Brackets } from 'typeorm'; -import { generateRepliesQuery } from '../../common/generate-replies-query'; -import { generateMutedNoteQuery } from '../../common/generate-muted-note-query'; -import { generateChannelQuery } from '../../common/generate-channel-query'; -import { generateBlockedUserQuery } from '../../common/generate-block-query'; +import { generateRepliesQuery } from '../../common/generate-replies-query.js'; +import { generateMutedNoteQuery } from '../../common/generate-muted-note-query.js'; +import { generateChannelQuery } from '../../common/generate-channel-query.js'; +import { generateBlockedUserQuery } from '../../common/generate-block-query.js'; export const meta = { tags: ['notes'], requireCredential: true, - params: { - limit: { - validator: $.optional.num.range(1, 100), - default: 10, - }, - - sinceId: { - validator: $.optional.type(ID), - }, - - untilId: { - validator: $.optional.type(ID), - }, - - sinceDate: { - validator: $.optional.num, - }, - - untilDate: { - validator: $.optional.num, - }, - - includeMyRenotes: { - validator: $.optional.bool, - default: true, - }, - - includeRenotedMyNotes: { - validator: $.optional.bool, - default: true, - }, - - includeLocalRenotes: { - validator: $.optional.bool, - default: true, - }, - - withFiles: { - validator: $.optional.bool, - }, - }, - res: { type: 'array', optional: false, nullable: false, @@ -71,8 +27,24 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + limit: { type: 'integer', minimum: 1, maximum: 100, default: 10 }, + sinceId: { type: 'string', format: 'misskey:id' }, + untilId: { type: 'string', format: 'misskey:id' }, + sinceDate: { type: 'integer' }, + untilDate: { type: 'integer' }, + includeMyRenotes: { type: 'boolean', default: true }, + includeRenotedMyNotes: { type: 'boolean', default: true }, + includeLocalRenotes: { type: 'boolean', default: true }, + withFiles: { type: 'boolean' }, + }, + required: [], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, user) => { +export default define(meta, paramDef, async (ps, user) => { const hasFollowing = (await Followings.count({ where: { followerId: user.id, @@ -92,10 +64,16 @@ export default define(meta, async (ps, user) => { if (hasFollowing) qb.orWhere(`note.userId IN (${ followingQuery.getQuery() })`); })) .innerJoinAndSelect('note.user', 'user') + .leftJoinAndSelect('user.avatar', 'avatar') + .leftJoinAndSelect('user.banner', 'banner') .leftJoinAndSelect('note.reply', 'reply') .leftJoinAndSelect('note.renote', 'renote') .leftJoinAndSelect('reply.user', 'replyUser') + .leftJoinAndSelect('replyUser.avatar', 'replyUserAvatar') + .leftJoinAndSelect('replyUser.banner', 'replyUserBanner') .leftJoinAndSelect('renote.user', 'renoteUser') + .leftJoinAndSelect('renoteUser.avatar', 'renoteUserAvatar') + .leftJoinAndSelect('renoteUser.banner', 'renoteUserBanner') .setParameters(followingQuery.getParameters()); generateChannelQuery(query, user); @@ -141,7 +119,7 @@ export default define(meta, async (ps, user) => { } //#endregion - const timeline = await query.take(ps.limit!).getMany(); + const timeline = await query.take(ps.limit).getMany(); process.nextTick(() => { if (user) { diff --git a/packages/backend/src/server/api/endpoints/notes/translate.ts b/packages/backend/src/server/api/endpoints/notes/translate.ts index ed069cb75..068df6940 100644 --- a/packages/backend/src/server/api/endpoints/notes/translate.ts +++ b/packages/backend/src/server/api/endpoints/notes/translate.ts @@ -1,29 +1,18 @@ -import $ from 'cafy'; -import { ID } from '@/misc/cafy-id'; -import define from '../../define'; -import { getNote } from '../../common/getters'; -import { ApiError } from '../../error'; +import define from '../../define.js'; +import { getNote } from '../../common/getters.js'; +import { ApiError } from '../../error.js'; import fetch from 'node-fetch'; -import config from '@/config/index'; -import { getAgentByUrl } from '@/misc/fetch'; -import { URLSearchParams } from 'url'; -import { fetchMeta } from '@/misc/fetch-meta'; -import { Notes } from '@/models'; +import config from '@/config/index.js'; +import { getAgentByUrl } from '@/misc/fetch.js'; +import { URLSearchParams } from 'node:url'; +import { fetchMeta } from '@/misc/fetch-meta.js'; +import { Notes } from '@/models/index.js'; export const meta = { tags: ['notes'], requireCredential: false, - params: { - noteId: { - validator: $.type(ID), - }, - targetLang: { - validator: $.str, - }, - }, - res: { type: 'object', optional: false, nullable: false, @@ -38,8 +27,17 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + noteId: { type: 'string', format: 'misskey:id' }, + targetLang: { type: 'string' }, + }, + required: ['noteId', 'targetLang'], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, user) => { +export default define(meta, paramDef, async (ps, user) => { const note = await getNote(ps.noteId).catch(e => { if (e.id === '9725d0ce-ba28-4dde-95a7-2cbb2c15de24') throw new ApiError(meta.errors.noSuchNote); throw e; diff --git a/packages/backend/src/server/api/endpoints/notes/unrenote.ts b/packages/backend/src/server/api/endpoints/notes/unrenote.ts index 8db543d32..a9aadba33 100644 --- a/packages/backend/src/server/api/endpoints/notes/unrenote.ts +++ b/packages/backend/src/server/api/endpoints/notes/unrenote.ts @@ -1,11 +1,9 @@ -import $ from 'cafy'; -import { ID } from '@/misc/cafy-id'; -import deleteNote from '@/services/note/delete'; -import define from '../../define'; +import deleteNote from '@/services/note/delete.js'; +import define from '../../define.js'; import ms from 'ms'; -import { getNote } from '../../common/getters'; -import { ApiError } from '../../error'; -import { Notes, Users } from '@/models/index'; +import { getNote } from '../../common/getters.js'; +import { ApiError } from '../../error.js'; +import { Notes, Users } from '@/models/index.js'; export const meta = { tags: ['notes'], @@ -20,12 +18,6 @@ export const meta = { minInterval: ms('1sec'), }, - params: { - noteId: { - validator: $.type(ID), - }, - }, - errors: { noSuchNote: { message: 'No such note.', @@ -35,8 +27,16 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + noteId: { type: 'string', format: 'misskey:id' }, + }, + required: ['noteId'], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, user) => { +export default define(meta, paramDef, async (ps, user) => { const note = await getNote(ps.noteId).catch(e => { if (e.id === '9725d0ce-ba28-4dde-95a7-2cbb2c15de24') throw new ApiError(meta.errors.noSuchNote); throw e; diff --git a/packages/backend/src/server/api/endpoints/notes/user-list-timeline.ts b/packages/backend/src/server/api/endpoints/notes/user-list-timeline.ts index 3512fb363..0829d0e4c 100644 --- a/packages/backend/src/server/api/endpoints/notes/user-list-timeline.ts +++ b/packages/backend/src/server/api/endpoints/notes/user-list-timeline.ts @@ -1,11 +1,9 @@ -import $ from 'cafy'; -import { ID } from '@/misc/cafy-id'; -import define from '../../define'; -import { ApiError } from '../../error'; -import { UserLists, UserListJoinings, Notes } from '@/models/index'; -import { makePaginationQuery } from '../../common/make-pagination-query'; -import { generateVisibilityQuery } from '../../common/generate-visibility-query'; -import { activeUsersChart } from '@/services/chart/index'; +import define from '../../define.js'; +import { ApiError } from '../../error.js'; +import { UserLists, UserListJoinings, Notes } from '@/models/index.js'; +import { makePaginationQuery } from '../../common/make-pagination-query.js'; +import { generateVisibilityQuery } from '../../common/generate-visibility-query.js'; +import { activeUsersChart } from '@/services/chart/index.js'; import { Brackets } from 'typeorm'; export const meta = { @@ -13,52 +11,6 @@ export const meta = { requireCredential: true, - params: { - listId: { - validator: $.type(ID), - }, - - limit: { - validator: $.optional.num.range(1, 100), - default: 10, - }, - - sinceId: { - validator: $.optional.type(ID), - }, - - untilId: { - validator: $.optional.type(ID), - }, - - sinceDate: { - validator: $.optional.num, - }, - - untilDate: { - validator: $.optional.num, - }, - - includeMyRenotes: { - validator: $.optional.bool, - default: true, - }, - - includeRenotedMyNotes: { - validator: $.optional.bool, - default: true, - }, - - includeLocalRenotes: { - validator: $.optional.bool, - default: true, - }, - - withFiles: { - validator: $.optional.bool, - }, - }, - res: { type: 'array', optional: false, nullable: false, @@ -78,8 +30,25 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + listId: { type: 'string', format: 'misskey:id' }, + limit: { type: 'integer', minimum: 1, maximum: 100, default: 10 }, + sinceId: { type: 'string', format: 'misskey:id' }, + untilId: { type: 'string', format: 'misskey:id' }, + sinceDate: { type: 'integer' }, + untilDate: { type: 'integer' }, + includeMyRenotes: { type: 'boolean', default: true }, + includeRenotedMyNotes: { type: 'boolean', default: true }, + includeLocalRenotes: { type: 'boolean', default: true }, + withFiles: { type: 'boolean' }, + }, + required: ['listId'], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, user) => { +export default define(meta, paramDef, async (ps, user) => { const list = await UserLists.findOne({ id: ps.listId, userId: user.id, @@ -97,10 +66,16 @@ export default define(meta, async (ps, user) => { const query = makePaginationQuery(Notes.createQueryBuilder('note'), ps.sinceId, ps.untilId) .andWhere(`note.userId IN (${ listQuery.getQuery() })`) .innerJoinAndSelect('note.user', 'user') + .leftJoinAndSelect('user.avatar', 'avatar') + .leftJoinAndSelect('user.banner', 'banner') .leftJoinAndSelect('note.reply', 'reply') .leftJoinAndSelect('note.renote', 'renote') .leftJoinAndSelect('reply.user', 'replyUser') + .leftJoinAndSelect('replyUser.avatar', 'replyUserAvatar') + .leftJoinAndSelect('replyUser.banner', 'replyUserBanner') .leftJoinAndSelect('renote.user', 'renoteUser') + .leftJoinAndSelect('renoteUser.avatar', 'renoteUserAvatar') + .leftJoinAndSelect('renoteUser.banner', 'renoteUserBanner') .setParameters(listQuery.getParameters()); generateVisibilityQuery(query, user); @@ -140,7 +115,7 @@ export default define(meta, async (ps, user) => { } //#endregion - const timeline = await query.take(ps.limit!).getMany(); + const timeline = await query.take(ps.limit).getMany(); activeUsersChart.read(user); diff --git a/packages/backend/src/server/api/endpoints/notes/watching/create.ts b/packages/backend/src/server/api/endpoints/notes/watching/create.ts index 6433c6bc2..8fdf84624 100644 --- a/packages/backend/src/server/api/endpoints/notes/watching/create.ts +++ b/packages/backend/src/server/api/endpoints/notes/watching/create.ts @@ -1,9 +1,7 @@ -import $ from 'cafy'; -import { ID } from '@/misc/cafy-id'; -import define from '../../../define'; -import watch from '@/services/note/watch'; -import { getNote } from '../../../common/getters'; -import { ApiError } from '../../../error'; +import define from '../../../define.js'; +import watch from '@/services/note/watch.js'; +import { getNote } from '../../../common/getters.js'; +import { ApiError } from '../../../error.js'; export const meta = { tags: ['notes'], @@ -12,12 +10,6 @@ export const meta = { kind: 'write:account', - params: { - noteId: { - validator: $.type(ID), - }, - }, - errors: { noSuchNote: { message: 'No such note.', @@ -27,8 +19,16 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + noteId: { type: 'string', format: 'misskey:id' }, + }, + required: ['noteId'], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, user) => { +export default define(meta, paramDef, async (ps, user) => { const note = await getNote(ps.noteId).catch(e => { if (e.id === '9725d0ce-ba28-4dde-95a7-2cbb2c15de24') throw new ApiError(meta.errors.noSuchNote); throw e; diff --git a/packages/backend/src/server/api/endpoints/notes/watching/delete.ts b/packages/backend/src/server/api/endpoints/notes/watching/delete.ts index 3e9faa2b2..d58f09797 100644 --- a/packages/backend/src/server/api/endpoints/notes/watching/delete.ts +++ b/packages/backend/src/server/api/endpoints/notes/watching/delete.ts @@ -1,9 +1,7 @@ -import $ from 'cafy'; -import { ID } from '@/misc/cafy-id'; -import define from '../../../define'; -import unwatch from '@/services/note/unwatch'; -import { getNote } from '../../../common/getters'; -import { ApiError } from '../../../error'; +import define from '../../../define.js'; +import unwatch from '@/services/note/unwatch.js'; +import { getNote } from '../../../common/getters.js'; +import { ApiError } from '../../../error.js'; export const meta = { tags: ['notes'], @@ -12,12 +10,6 @@ export const meta = { kind: 'write:account', - params: { - noteId: { - validator: $.type(ID), - }, - }, - errors: { noSuchNote: { message: 'No such note.', @@ -27,8 +19,16 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + noteId: { type: 'string', format: 'misskey:id' }, + }, + required: ['noteId'], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, user) => { +export default define(meta, paramDef, async (ps, user) => { const note = await getNote(ps.noteId).catch(e => { if (e.id === '9725d0ce-ba28-4dde-95a7-2cbb2c15de24') throw new ApiError(meta.errors.noSuchNote); throw e; diff --git a/packages/backend/src/server/api/endpoints/notifications/create.ts b/packages/backend/src/server/api/endpoints/notifications/create.ts index bd8a7ba1b..b339c8723 100644 --- a/packages/backend/src/server/api/endpoints/notifications/create.ts +++ b/packages/backend/src/server/api/endpoints/notifications/create.ts @@ -1,6 +1,5 @@ -import $ from 'cafy'; -import define from '../../define'; -import { createNotification } from '@/services/create-notification'; +import define from '../../define.js'; +import { createNotification } from '@/services/create-notification.js'; export const meta = { tags: ['notifications'], @@ -9,26 +8,22 @@ export const meta = { kind: 'write:notifications', - params: { - body: { - validator: $.str, - }, - - header: { - validator: $.optional.nullable.str, - }, - - icon: { - validator: $.optional.nullable.str, - }, - }, - errors: { }, } as const; +export const paramDef = { + type: 'object', + properties: { + body: { type: 'string' }, + header: { type: 'string', nullable: true }, + icon: { type: 'string', nullable: true }, + }, + required: ['body'], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, user, token) => { +export default define(meta, paramDef, async (ps, user, token) => { createNotification(user.id, 'app', { appAccessTokenId: token ? token.id : null, customBody: ps.body, diff --git a/packages/backend/src/server/api/endpoints/notifications/mark-all-as-read.ts b/packages/backend/src/server/api/endpoints/notifications/mark-all-as-read.ts index 4cec38a95..abefe07be 100644 --- a/packages/backend/src/server/api/endpoints/notifications/mark-all-as-read.ts +++ b/packages/backend/src/server/api/endpoints/notifications/mark-all-as-read.ts @@ -1,6 +1,6 @@ -import { publishMainStream } from '@/services/stream'; -import define from '../../define'; -import { Notifications } from '@/models/index'; +import { publishMainStream } from '@/services/stream.js'; +import define from '../../define.js'; +import { Notifications } from '@/models/index.js'; export const meta = { tags: ['notifications', 'account'], @@ -10,8 +10,14 @@ export const meta = { kind: 'write:notifications', } as const; +export const paramDef = { + type: 'object', + properties: {}, + required: [], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, user) => { +export default define(meta, paramDef, async (ps, user) => { // Update documents await Notifications.update({ notifieeId: user.id, diff --git a/packages/backend/src/server/api/endpoints/notifications/read.ts b/packages/backend/src/server/api/endpoints/notifications/read.ts index 7e23bc234..34f4c155f 100644 --- a/packages/backend/src/server/api/endpoints/notifications/read.ts +++ b/packages/backend/src/server/api/endpoints/notifications/read.ts @@ -1,10 +1,8 @@ -import $ from 'cafy'; -import { ID } from '@/misc/cafy-id'; -import { publishMainStream } from '@/services/stream'; -import define from '../../define'; -import { Notifications } from '@/models/index'; -import { readNotification } from '../../common/read-notification'; -import { ApiError } from '../../error'; +import { publishMainStream } from '@/services/stream.js'; +import define from '../../define.js'; +import { Notifications } from '@/models/index.js'; +import { readNotification } from '../../common/read-notification.js'; +import { ApiError } from '../../error.js'; export const meta = { tags: ['notifications', 'account'], @@ -13,12 +11,6 @@ export const meta = { kind: 'write:notifications', - params: { - notificationId: { - validator: $.type(ID), - }, - }, - errors: { noSuchNotification: { message: 'No such notification.', @@ -28,8 +20,16 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + notificationId: { type: 'string', format: 'misskey:id' }, + }, + required: ['notificationId'], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, user) => { +export default define(meta, paramDef, async (ps, user) => { const notification = await Notifications.findOne({ notifieeId: user.id, id: ps.notificationId, diff --git a/packages/backend/src/server/api/endpoints/page-push.ts b/packages/backend/src/server/api/endpoints/page-push.ts index 61c0160f8..acaa11847 100644 --- a/packages/backend/src/server/api/endpoints/page-push.ts +++ b/packages/backend/src/server/api/endpoints/page-push.ts @@ -1,28 +1,12 @@ -import $ from 'cafy'; -import define from '../define'; -import { ID } from '@/misc/cafy-id'; -import { publishMainStream } from '@/services/stream'; -import { Users, Pages } from '@/models/index'; -import { ApiError } from '../error'; +import define from '../define.js'; +import { publishMainStream } from '@/services/stream.js'; +import { Users, Pages } from '@/models/index.js'; +import { ApiError } from '../error.js'; export const meta = { requireCredential: true, secure: true, - params: { - pageId: { - validator: $.type(ID), - }, - - event: { - validator: $.str, - }, - - var: { - validator: $.optional.nullable.any, - }, - }, - errors: { noSuchPage: { message: 'No such page.', @@ -32,8 +16,18 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + pageId: { type: 'string', format: 'misskey:id' }, + event: { type: 'string' }, + var: {}, + }, + required: ['pageId', 'event'], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, user) => { +export default define(meta, paramDef, async (ps, user) => { const page = await Pages.findOne(ps.pageId); if (page == null) { throw new ApiError(meta.errors.noSuchPage); diff --git a/packages/backend/src/server/api/endpoints/pages/create.ts b/packages/backend/src/server/api/endpoints/pages/create.ts index 7ee50fbdf..7cac53060 100644 --- a/packages/backend/src/server/api/endpoints/pages/create.ts +++ b/packages/backend/src/server/api/endpoints/pages/create.ts @@ -1,11 +1,9 @@ -import $ from 'cafy'; import ms from 'ms'; -import define from '../../define'; -import { ID } from '@/misc/cafy-id'; -import { Pages, DriveFiles } from '@/models/index'; -import { genId } from '@/misc/gen-id'; -import { Page } from '@/models/entities/page'; -import { ApiError } from '../../error'; +import define from '../../define.js'; +import { Pages, DriveFiles } from '@/models/index.js'; +import { genId } from '@/misc/gen-id.js'; +import { Page } from '@/models/entities/page.js'; +import { ApiError } from '../../error.js'; export const meta = { tags: ['pages'], @@ -19,51 +17,6 @@ export const meta = { max: 300, }, - params: { - title: { - validator: $.str, - }, - - name: { - validator: $.str.min(1), - }, - - summary: { - validator: $.optional.nullable.str, - }, - - content: { - validator: $.arr($.obj()), - }, - - variables: { - validator: $.arr($.obj()), - }, - - script: { - validator: $.str, - }, - - eyeCatchingImageId: { - validator: $.optional.nullable.type(ID), - }, - - font: { - validator: $.optional.str.or(['serif', 'sans-serif']), - default: 'sans-serif', - }, - - alignCenter: { - validator: $.optional.bool, - default: false, - }, - - hideTitleWhenPinned: { - validator: $.optional.bool, - default: false, - }, - }, - res: { type: 'object', optional: false, nullable: false, @@ -84,8 +37,29 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + title: { type: 'string' }, + name: { type: 'string', minLength: 1 }, + summary: { type: 'string', nullable: true }, + content: { type: 'array', items: { + type: 'object', additionalProperties: true, + } }, + variables: { type: 'array', items: { + type: 'object', additionalProperties: true, + } }, + script: { type: 'string' }, + eyeCatchingImageId: { type: 'string', format: 'misskey:id', nullable: true }, + font: { type: 'string', enum: ['serif', 'sans-serif'], default: "sans-serif" }, + alignCenter: { type: 'boolean', default: false }, + hideTitleWhenPinned: { type: 'boolean', default: false }, + }, + required: ['title', 'name', 'content', 'variables', 'script'], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, user) => { +export default define(meta, paramDef, async (ps, user) => { let eyeCatchingImage = null; if (ps.eyeCatchingImageId != null) { eyeCatchingImage = await DriveFiles.findOne({ diff --git a/packages/backend/src/server/api/endpoints/pages/delete.ts b/packages/backend/src/server/api/endpoints/pages/delete.ts index aeda823e5..ddf691f53 100644 --- a/packages/backend/src/server/api/endpoints/pages/delete.ts +++ b/packages/backend/src/server/api/endpoints/pages/delete.ts @@ -1,8 +1,6 @@ -import $ from 'cafy'; -import define from '../../define'; -import { ApiError } from '../../error'; -import { Pages } from '@/models/index'; -import { ID } from '@/misc/cafy-id'; +import define from '../../define.js'; +import { ApiError } from '../../error.js'; +import { Pages } from '@/models/index.js'; export const meta = { tags: ['pages'], @@ -11,12 +9,6 @@ export const meta = { kind: 'write:pages', - params: { - pageId: { - validator: $.type(ID), - }, - }, - errors: { noSuchPage: { message: 'No such page.', @@ -32,8 +24,16 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + pageId: { type: 'string', format: 'misskey:id' }, + }, + required: ['pageId'], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, user) => { +export default define(meta, paramDef, async (ps, user) => { const page = await Pages.findOne(ps.pageId); if (page == null) { throw new ApiError(meta.errors.noSuchPage); diff --git a/packages/backend/src/server/api/endpoints/pages/featured.ts b/packages/backend/src/server/api/endpoints/pages/featured.ts index 7f0d58b35..eeb6d509c 100644 --- a/packages/backend/src/server/api/endpoints/pages/featured.ts +++ b/packages/backend/src/server/api/endpoints/pages/featured.ts @@ -1,5 +1,5 @@ -import define from '../../define'; -import { Pages } from '@/models/index'; +import define from '../../define.js'; +import { Pages } from '@/models/index.js'; export const meta = { tags: ['pages'], @@ -17,8 +17,14 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: {}, + required: [], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, me) => { +export default define(meta, paramDef, async (ps, me) => { const query = Pages.createQueryBuilder('page') .where('page.visibility = \'public\'') .andWhere('page.likedCount > 0') diff --git a/packages/backend/src/server/api/endpoints/pages/like.ts b/packages/backend/src/server/api/endpoints/pages/like.ts index c479f637a..cab78e576 100644 --- a/packages/backend/src/server/api/endpoints/pages/like.ts +++ b/packages/backend/src/server/api/endpoints/pages/like.ts @@ -1,9 +1,7 @@ -import $ from 'cafy'; -import { ID } from '@/misc/cafy-id'; -import define from '../../define'; -import { ApiError } from '../../error'; -import { Pages, PageLikes } from '@/models/index'; -import { genId } from '@/misc/gen-id'; +import define from '../../define.js'; +import { ApiError } from '../../error.js'; +import { Pages, PageLikes } from '@/models/index.js'; +import { genId } from '@/misc/gen-id.js'; export const meta = { tags: ['pages'], @@ -12,12 +10,6 @@ export const meta = { kind: 'write:page-likes', - params: { - pageId: { - validator: $.type(ID), - }, - }, - errors: { noSuchPage: { message: 'No such page.', @@ -39,8 +31,16 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + pageId: { type: 'string', format: 'misskey:id' }, + }, + required: ['pageId'], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, user) => { +export default define(meta, paramDef, async (ps, user) => { const page = await Pages.findOne(ps.pageId); if (page == null) { throw new ApiError(meta.errors.noSuchPage); diff --git a/packages/backend/src/server/api/endpoints/pages/show.ts b/packages/backend/src/server/api/endpoints/pages/show.ts index 5cda5386d..4e3facae5 100644 --- a/packages/backend/src/server/api/endpoints/pages/show.ts +++ b/packages/backend/src/server/api/endpoints/pages/show.ts @@ -1,29 +1,13 @@ -import $ from 'cafy'; -import define from '../../define'; -import { ApiError } from '../../error'; -import { Pages, Users } from '@/models/index'; -import { ID } from '@/misc/cafy-id'; -import { Page } from '@/models/entities/page'; +import define from '../../define.js'; +import { ApiError } from '../../error.js'; +import { Pages, Users } from '@/models/index.js'; +import { Page } from '@/models/entities/page.js'; export const meta = { tags: ['pages'], requireCredential: false, - params: { - pageId: { - validator: $.optional.type(ID), - }, - - name: { - validator: $.optional.str, - }, - - username: { - validator: $.optional.str, - }, - }, - res: { type: 'object', optional: false, nullable: false, @@ -39,8 +23,18 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + pageId: { type: 'string', format: 'misskey:id' }, + name: { type: 'string' }, + username: { type: 'string' }, + }, + required: [], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, user) => { +export default define(meta, paramDef, async (ps, user) => { let page: Page | undefined; if (ps.pageId) { diff --git a/packages/backend/src/server/api/endpoints/pages/unlike.ts b/packages/backend/src/server/api/endpoints/pages/unlike.ts index cca5e5b5a..31cd1a335 100644 --- a/packages/backend/src/server/api/endpoints/pages/unlike.ts +++ b/packages/backend/src/server/api/endpoints/pages/unlike.ts @@ -1,8 +1,6 @@ -import $ from 'cafy'; -import { ID } from '@/misc/cafy-id'; -import define from '../../define'; -import { ApiError } from '../../error'; -import { Pages, PageLikes } from '@/models/index'; +import define from '../../define.js'; +import { ApiError } from '../../error.js'; +import { Pages, PageLikes } from '@/models/index.js'; export const meta = { tags: ['pages'], @@ -11,12 +9,6 @@ export const meta = { kind: 'write:page-likes', - params: { - pageId: { - validator: $.type(ID), - }, - }, - errors: { noSuchPage: { message: 'No such page.', @@ -32,8 +24,16 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + pageId: { type: 'string', format: 'misskey:id' }, + }, + required: ['pageId'], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, user) => { +export default define(meta, paramDef, async (ps, user) => { const page = await Pages.findOne(ps.pageId); if (page == null) { throw new ApiError(meta.errors.noSuchPage); diff --git a/packages/backend/src/server/api/endpoints/pages/update.ts b/packages/backend/src/server/api/endpoints/pages/update.ts index 991085ee0..24c8f467e 100644 --- a/packages/backend/src/server/api/endpoints/pages/update.ts +++ b/packages/backend/src/server/api/endpoints/pages/update.ts @@ -1,9 +1,7 @@ -import $ from 'cafy'; import ms from 'ms'; -import define from '../../define'; -import { ApiError } from '../../error'; -import { Pages, DriveFiles } from '@/models/index'; -import { ID } from '@/misc/cafy-id'; +import define from '../../define.js'; +import { ApiError } from '../../error.js'; +import { Pages, DriveFiles } from '@/models/index.js'; import { Not } from 'typeorm'; export const meta = { @@ -18,52 +16,6 @@ export const meta = { max: 300, }, - params: { - pageId: { - validator: $.type(ID), - }, - - title: { - validator: $.str, - }, - - name: { - validator: $.str.min(1), - }, - - summary: { - validator: $.optional.nullable.str, - }, - - content: { - validator: $.arr($.obj()), - }, - - variables: { - validator: $.arr($.obj()), - }, - - script: { - validator: $.str, - }, - - eyeCatchingImageId: { - validator: $.optional.nullable.type(ID), - }, - - font: { - validator: $.optional.str.or(['serif', 'sans-serif']), - }, - - alignCenter: { - validator: $.optional.bool, - }, - - hideTitleWhenPinned: { - validator: $.optional.bool, - }, - }, - errors: { noSuchPage: { message: 'No such page.', @@ -90,8 +42,30 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + pageId: { type: 'string', format: 'misskey:id' }, + title: { type: 'string' }, + name: { type: 'string', minLength: 1 }, + summary: { type: 'string', nullable: true }, + content: { type: 'array', items: { + type: 'object', additionalProperties: true, + } }, + variables: { type: 'array', items: { + type: 'object', additionalProperties: true, + } }, + script: { type: 'string' }, + eyeCatchingImageId: { type: 'string', format: 'misskey:id', nullable: true }, + font: { type: 'string', enum: ['serif', 'sans-serif'] }, + alignCenter: { type: 'boolean' }, + hideTitleWhenPinned: { type: 'boolean' }, + }, + required: ['pageId', 'title', 'name', 'content', 'variables', 'script'], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, user) => { +export default define(meta, paramDef, async (ps, user) => { const page = await Pages.findOne(ps.pageId); if (page == null) { throw new ApiError(meta.errors.noSuchPage); diff --git a/packages/backend/src/server/api/endpoints/ping.ts b/packages/backend/src/server/api/endpoints/ping.ts index 3eab70ae2..2891a0860 100644 --- a/packages/backend/src/server/api/endpoints/ping.ts +++ b/packages/backend/src/server/api/endpoints/ping.ts @@ -1,13 +1,10 @@ -import define from '../define'; +import define from '../define.js'; export const meta = { requireCredential: false, tags: ['meta'], - params: { - }, - res: { type: 'object', optional: false, nullable: false, @@ -20,8 +17,14 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: {}, + required: [], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async () => { +export default define(meta, paramDef, async () => { return { pong: Date.now(), }; diff --git a/packages/backend/src/server/api/endpoints/pinned-users.ts b/packages/backend/src/server/api/endpoints/pinned-users.ts index ff0e22555..1d26ab266 100644 --- a/packages/backend/src/server/api/endpoints/pinned-users.ts +++ b/packages/backend/src/server/api/endpoints/pinned-users.ts @@ -1,17 +1,14 @@ -import define from '../define'; -import { Users } from '@/models/index'; -import { fetchMeta } from '@/misc/fetch-meta'; -import * as Acct from 'misskey-js/built/acct'; -import { User } from '@/models/entities/user'; +import define from '../define.js'; +import { Users } from '@/models/index.js'; +import { fetchMeta } from '@/misc/fetch-meta.js'; +import * as Acct from '@/misc/acct.js'; +import { User } from '@/models/entities/user.js'; export const meta = { tags: ['users'], requireCredential: false, - params: { - }, - res: { type: 'array', optional: false, nullable: false, @@ -23,8 +20,14 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: {}, + required: [], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, me) => { +export default define(meta, paramDef, async (ps, me) => { const meta = await fetchMeta(); const users = await Promise.all(meta.pinnedUsers.map(acct => Users.findOne(Acct.parse(acct)))); diff --git a/packages/backend/src/server/api/endpoints/promo/read.ts b/packages/backend/src/server/api/endpoints/promo/read.ts index 8d8c60d75..ea34ca3aa 100644 --- a/packages/backend/src/server/api/endpoints/promo/read.ts +++ b/packages/backend/src/server/api/endpoints/promo/read.ts @@ -1,22 +1,14 @@ -import $ from 'cafy'; -import { ID } from '@/misc/cafy-id'; -import define from '../../define'; -import { ApiError } from '../../error'; -import { getNote } from '../../common/getters'; -import { PromoReads } from '@/models/index'; -import { genId } from '@/misc/gen-id'; +import define from '../../define.js'; +import { ApiError } from '../../error.js'; +import { getNote } from '../../common/getters.js'; +import { PromoReads } from '@/models/index.js'; +import { genId } from '@/misc/gen-id.js'; export const meta = { tags: ['notes'], requireCredential: true, - params: { - noteId: { - validator: $.type(ID), - }, - }, - errors: { noSuchNote: { message: 'No such note.', @@ -26,8 +18,16 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + noteId: { type: 'string', format: 'misskey:id' }, + }, + required: ['noteId'], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, user) => { +export default define(meta, paramDef, async (ps, user) => { const note = await getNote(ps.noteId).catch(e => { if (e.id === '9725d0ce-ba28-4dde-95a7-2cbb2c15de24') throw new ApiError(meta.errors.noSuchNote); throw e; diff --git a/packages/backend/src/server/api/endpoints/request-reset-password.ts b/packages/backend/src/server/api/endpoints/request-reset-password.ts index af1aeb431..18cd98b16 100644 --- a/packages/backend/src/server/api/endpoints/request-reset-password.ts +++ b/packages/backend/src/server/api/endpoints/request-reset-password.ts @@ -1,13 +1,12 @@ -import $ from 'cafy'; -import { publishMainStream } from '@/services/stream'; -import define from '../define'; +import { publishMainStream } from '@/services/stream.js'; +import define from '../define.js'; import rndstr from 'rndstr'; -import config from '@/config/index'; +import config from '@/config/index.js'; import ms from 'ms'; -import { Users, UserProfiles, PasswordResetRequests } from '@/models/index'; -import { sendEmail } from '@/services/send-email'; -import { ApiError } from '../error'; -import { genId } from '@/misc/gen-id'; +import { Users, UserProfiles, PasswordResetRequests } from '@/models/index.js'; +import { sendEmail } from '@/services/send-email.js'; +import { ApiError } from '../error.js'; +import { genId } from '@/misc/gen-id.js'; import { IsNull } from 'typeorm'; export const meta = { @@ -18,23 +17,22 @@ export const meta = { max: 3, }, - params: { - username: { - validator: $.str, - }, - - email: { - validator: $.str, - }, - }, - errors: { }, } as const; +export const paramDef = { + type: 'object', + properties: { + username: { type: 'string' }, + email: { type: 'string' }, + }, + required: ['username', 'email'], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps) => { +export default define(meta, paramDef, async (ps) => { const user = await Users.findOne({ usernameLower: ps.username.toLowerCase(), host: IsNull(), diff --git a/packages/backend/src/server/api/endpoints/reset-db.ts b/packages/backend/src/server/api/endpoints/reset-db.ts index e99dc9db1..dbe64e9a1 100644 --- a/packages/backend/src/server/api/endpoints/reset-db.ts +++ b/packages/backend/src/server/api/endpoints/reset-db.ts @@ -1,21 +1,23 @@ -import $ from 'cafy'; -import define from '../define'; -import { ApiError } from '../error'; -import { resetDb } from '@/db/postgre'; +import define from '../define.js'; +import { ApiError } from '../error.js'; +import { resetDb } from '@/db/postgre.js'; export const meta = { requireCredential: false, - params: { - }, - errors: { }, } as const; +export const paramDef = { + type: 'object', + properties: {}, + required: [], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, user) => { +export default define(meta, paramDef, async (ps, user) => { if (process.env.NODE_ENV !== 'test') throw 'NODE_ENV is not a test'; await resetDb(); diff --git a/packages/backend/src/server/api/endpoints/reset-password.ts b/packages/backend/src/server/api/endpoints/reset-password.ts index a7366584b..3abf232af 100644 --- a/packages/backend/src/server/api/endpoints/reset-password.ts +++ b/packages/backend/src/server/api/endpoints/reset-password.ts @@ -1,30 +1,28 @@ -import $ from 'cafy'; -import * as bcrypt from 'bcryptjs'; -import { publishMainStream } from '@/services/stream'; -import define from '../define'; -import { Users, UserProfiles, PasswordResetRequests } from '@/models/index'; -import { ApiError } from '../error'; +import bcrypt from 'bcryptjs'; +import { publishMainStream } from '@/services/stream.js'; +import define from '../define.js'; +import { Users, UserProfiles, PasswordResetRequests } from '@/models/index.js'; +import { ApiError } from '../error.js'; export const meta = { requireCredential: false, - params: { - token: { - validator: $.str, - }, - - password: { - validator: $.str, - }, - }, - errors: { }, } as const; +export const paramDef = { + type: 'object', + properties: { + token: { type: 'string' }, + password: { type: 'string' }, + }, + required: ['token', 'password'], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, user) => { +export default define(meta, paramDef, async (ps, user) => { const req = await PasswordResetRequests.findOneOrFail({ token: ps.token, }); diff --git a/packages/backend/src/server/api/endpoints/server-info.ts b/packages/backend/src/server/api/endpoints/server-info.ts index 1ad2c54ab..99f3730e9 100644 --- a/packages/backend/src/server/api/endpoints/server-info.ts +++ b/packages/backend/src/server/api/endpoints/server-info.ts @@ -1,21 +1,21 @@ -import * as os from 'os'; -import * as si from 'systeminformation'; -import define from '../define'; +import * as os from 'node:os'; +import si from 'systeminformation'; +import define from '../define.js'; export const meta = { requireCredential: false, - desc: { - }, - tags: ['meta'], +} as const; - params: { - }, +export const paramDef = { + type: 'object', + properties: {}, + required: [], } as const; // eslint-disable-next-line import/no-default-export -export default define(meta, async () => { +export default define(meta, paramDef, async () => { const memStats = await si.mem(); const fsStats = await si.fsSize(); diff --git a/packages/backend/src/server/api/endpoints/stats.ts b/packages/backend/src/server/api/endpoints/stats.ts index 82b0bb329..92fea4de6 100644 --- a/packages/backend/src/server/api/endpoints/stats.ts +++ b/packages/backend/src/server/api/endpoints/stats.ts @@ -1,15 +1,12 @@ -import define from '../define'; -import { Instances, NoteReactions, Notes, Users } from '@/models/index'; -import { } from '@/services/chart/index'; +import define from '../define.js'; +import { Instances, NoteReactions, Notes, Users } from '@/models/index.js'; +import { } from '@/services/chart/index.js'; export const meta = { requireCredential: false, tags: ['meta'], - params: { - }, - res: { type: 'object', optional: false, nullable: false, @@ -46,8 +43,14 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: {}, + required: [], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async () => { +export default define(meta, paramDef, async () => { const [ notesCount, originalNotesCount, diff --git a/packages/backend/src/server/api/endpoints/sw/register.ts b/packages/backend/src/server/api/endpoints/sw/register.ts index ae3e9ce77..6c7714e19 100644 --- a/packages/backend/src/server/api/endpoints/sw/register.ts +++ b/packages/backend/src/server/api/endpoints/sw/register.ts @@ -1,47 +1,42 @@ -import $ from 'cafy'; -import define from '../../define'; -import { fetchMeta } from '@/misc/fetch-meta'; -import { genId } from '@/misc/gen-id'; -import { SwSubscriptions } from '@/models/index'; +import define from '../../define.js'; +import { fetchMeta } from '@/misc/fetch-meta.js'; +import { genId } from '@/misc/gen-id.js'; +import { SwSubscriptions } from '@/models/index.js'; export const meta = { tags: ['account'], requireCredential: true, - params: { - endpoint: { - validator: $.str, - }, - - auth: { - validator: $.str, - }, - - publickey: { - validator: $.str, - }, - }, - res: { type: 'object', optional: false, nullable: false, properties: { state: { type: 'string', - optional: false, nullable: false, + optional: true, nullable: false, enum: ['already-subscribed', 'subscribed'], }, key: { type: 'string', - optional: false, nullable: false, + optional: false, nullable: true, }, }, }, } as const; +export const paramDef = { + type: 'object', + properties: { + endpoint: { type: 'string' }, + auth: { type: 'string' }, + publickey: { type: 'string' }, + }, + required: ['endpoint', 'auth', 'publickey'], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, user) => { +export default define(meta, paramDef, async (ps, user) => { // if already subscribed const exist = await SwSubscriptions.findOne({ userId: user.id, @@ -54,7 +49,7 @@ export default define(meta, async (ps, user) => { if (exist != null) { return { - state: 'already-subscribed', + state: 'already-subscribed' as const, key: instance.swPublicKey, }; } @@ -69,7 +64,7 @@ export default define(meta, async (ps, user) => { }); return { - state: 'subscribed', + state: 'subscribed' as const, key: instance.swPublicKey, }; }); diff --git a/packages/backend/src/server/api/endpoints/sw/unregister.ts b/packages/backend/src/server/api/endpoints/sw/unregister.ts index 6f569e941..9748f2a22 100644 --- a/packages/backend/src/server/api/endpoints/sw/unregister.ts +++ b/packages/backend/src/server/api/endpoints/sw/unregister.ts @@ -1,21 +1,22 @@ -import $ from 'cafy'; -import define from '../../define'; -import { SwSubscriptions } from '../../../../models'; +import define from '../../define.js'; +import { SwSubscriptions } from '@/models/index.js'; export const meta = { tags: ['account'], requireCredential: true, +} as const; - params: { - endpoint: { - validator: $.str, - }, +export const paramDef = { + type: 'object', + properties: { + endpoint: { type: 'string' }, }, + required: ['endpoint'], } as const; // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, user) => { +export default define(meta, paramDef, async (ps, user) => { await SwSubscriptions.delete({ userId: user.id, endpoint: ps.endpoint, diff --git a/packages/backend/src/server/api/endpoints/test.ts b/packages/backend/src/server/api/endpoints/test.ts new file mode 100644 index 000000000..256da1a66 --- /dev/null +++ b/packages/backend/src/server/api/endpoints/test.ts @@ -0,0 +1,22 @@ +import define from '../define.js'; + +export const meta = { + requireCredential: false, +} as const; + +export const paramDef = { + type: 'object', + properties: { + required: { type: 'boolean' }, + string: { type: 'string' }, + default: { type: 'string', default: 'hello' }, + nullableDefault: { type: 'string', nullable: true, default: 'hello' }, + id: { type: 'string', format: 'misskey:id' }, + }, + required: ['required'], +} as const; + +// eslint-disable-next-line import/no-default-export +export default define(meta, paramDef, async (ps, me) => { + return ps; +}); diff --git a/packages/backend/src/server/api/endpoints/username/available.ts b/packages/backend/src/server/api/endpoints/username/available.ts index 74120fc40..5a1c4128a 100644 --- a/packages/backend/src/server/api/endpoints/username/available.ts +++ b/packages/backend/src/server/api/endpoints/username/available.ts @@ -1,18 +1,11 @@ -import $ from 'cafy'; -import define from '../../define'; -import { Users, UsedUsernames } from '@/models/index'; +import define from '../../define.js'; +import { Users, UsedUsernames } from '@/models/index.js'; export const meta = { tags: ['users'], requireCredential: false, - params: { - username: { - validator: $.use(Users.validateLocalUsername), - }, - }, - res: { type: 'object', optional: false, nullable: false, @@ -25,8 +18,16 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + username: Users.localUsernameSchema, + }, + required: ['username'], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps) => { +export default define(meta, paramDef, async (ps) => { // Get exist const exist = await Users.count({ host: null, diff --git a/packages/backend/src/server/api/endpoints/users.ts b/packages/backend/src/server/api/endpoints/users.ts index 6b11ec0f0..10527d15c 100644 --- a/packages/backend/src/server/api/endpoints/users.ts +++ b/packages/backend/src/server/api/endpoints/users.ts @@ -1,57 +1,13 @@ -import $ from 'cafy'; -import define from '../define'; -import { Users } from '@/models/index'; -import { generateMutedUserQueryForUsers } from '../common/generate-muted-user-query'; -import { generateBlockQueryForUsers } from '../common/generate-block-query'; +import define from '../define.js'; +import { Users } from '@/models/index.js'; +import { generateMutedUserQueryForUsers } from '../common/generate-muted-user-query.js'; +import { generateBlockQueryForUsers } from '../common/generate-block-query.js'; export const meta = { tags: ['users'], requireCredential: false, - params: { - limit: { - validator: $.optional.num.range(1, 100), - default: 10, - }, - - offset: { - validator: $.optional.num.min(0), - default: 0, - }, - - sort: { - validator: $.optional.str.or([ - '+follower', - '-follower', - '+createdAt', - '-createdAt', - '+updatedAt', - '-updatedAt', - ]), - }, - - state: { - validator: $.optional.str.or([ - 'all', - 'admin', - 'moderator', - 'adminOrModerator', - 'alive', - ]), - default: 'all', - }, - - origin: { - validator: $.optional.str.or([ - 'combined', - 'local', - 'remote', - ]), - default: 'local', - }, - }, - res: { type: 'array', optional: false, nullable: false, @@ -63,8 +19,20 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + limit: { type: 'integer', minimum: 1, maximum: 100, default: 10 }, + offset: { type: 'integer', default: 0 }, + sort: { type: 'string', enum: ['+follower', '-follower', '+createdAt', '-createdAt', '+updatedAt', '-updatedAt'] }, + state: { type: 'string', enum: ['all', 'admin', 'moderator', 'adminOrModerator', 'alive'], default: "all" }, + origin: { type: 'string', enum: ['combined', 'local', 'remote'], default: "local" }, + }, + required: [], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, me) => { +export default define(meta, paramDef, async (ps, me) => { const query = Users.createQueryBuilder('user'); query.where('user.isExplorable = TRUE'); @@ -93,7 +61,7 @@ export default define(meta, async (ps, me) => { if (me) generateMutedUserQueryForUsers(query, me); if (me) generateBlockQueryForUsers(query, me); - query.take(ps.limit!); + query.take(ps.limit); query.skip(ps.offset); const users = await query.getMany(); diff --git a/packages/backend/src/server/api/endpoints/users/clips.ts b/packages/backend/src/server/api/endpoints/users/clips.ts index d4152fbf5..424c59474 100644 --- a/packages/backend/src/server/api/endpoints/users/clips.ts +++ b/packages/backend/src/server/api/endpoints/users/clips.ts @@ -1,40 +1,30 @@ -import $ from 'cafy'; -import { ID } from '@/misc/cafy-id'; -import define from '../../define'; -import { Clips } from '@/models/index'; -import { makePaginationQuery } from '../../common/make-pagination-query'; +import define from '../../define.js'; +import { Clips } from '@/models/index.js'; +import { makePaginationQuery } from '../../common/make-pagination-query.js'; export const meta = { tags: ['users', 'clips'], +} as const; - params: { - userId: { - validator: $.type(ID), - }, - - limit: { - validator: $.optional.num.range(1, 100), - default: 10, - }, - - sinceId: { - validator: $.optional.type(ID), - }, - - untilId: { - validator: $.optional.type(ID), - }, +export const paramDef = { + type: 'object', + properties: { + userId: { type: 'string', format: 'misskey:id' }, + limit: { type: 'integer', minimum: 1, maximum: 100, default: 10 }, + sinceId: { type: 'string', format: 'misskey:id' }, + untilId: { type: 'string', format: 'misskey:id' }, }, + required: ['userId'], } as const; // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, user) => { +export default define(meta, paramDef, async (ps, user) => { const query = makePaginationQuery(Clips.createQueryBuilder('clip'), ps.sinceId, ps.untilId) .andWhere(`clip.userId = :userId`, { userId: ps.userId }) .andWhere('clip.isPublic = true'); const clips = await query - .take(ps.limit!) + .take(ps.limit) .getMany(); return await Clips.packMany(clips); diff --git a/packages/backend/src/server/api/endpoints/users/followers.ts b/packages/backend/src/server/api/endpoints/users/followers.ts index 6214ab40b..1e104b6bc 100644 --- a/packages/backend/src/server/api/endpoints/users/followers.ts +++ b/packages/backend/src/server/api/endpoints/users/followers.ts @@ -1,43 +1,14 @@ -import $ from 'cafy'; -import { ID } from '@/misc/cafy-id'; -import define from '../../define'; -import { ApiError } from '../../error'; -import { Users, Followings, UserProfiles } from '@/models/index'; -import { makePaginationQuery } from '../../common/make-pagination-query'; -import { toPunyNullable } from '@/misc/convert-host'; +import define from '../../define.js'; +import { ApiError } from '../../error.js'; +import { Users, Followings, UserProfiles } from '@/models/index.js'; +import { makePaginationQuery } from '../../common/make-pagination-query.js'; +import { toPunyNullable } from '@/misc/convert-host.js'; export const meta = { tags: ['users'], requireCredential: false, - params: { - userId: { - validator: $.optional.type(ID), - }, - - username: { - validator: $.optional.str, - }, - - host: { - validator: $.optional.nullable.str, - }, - - sinceId: { - validator: $.optional.type(ID), - }, - - untilId: { - validator: $.optional.type(ID), - }, - - limit: { - validator: $.optional.num.range(1, 100), - default: 10, - }, - }, - res: { type: 'array', optional: false, nullable: false, @@ -63,8 +34,21 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + userId: { type: 'string', format: 'misskey:id' }, + username: { type: 'string' }, + host: { type: 'string', nullable: true }, + sinceId: { type: 'string', format: 'misskey:id' }, + untilId: { type: 'string', format: 'misskey:id' }, + limit: { type: 'integer', minimum: 1, maximum: 100, default: 10 }, + }, + required: [], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, me) => { +export default define(meta, paramDef, async (ps, me) => { const user = await Users.findOne(ps.userId != null ? { id: ps.userId } : { usernameLower: ps.username!.toLowerCase(), host: toPunyNullable(ps.host) }); @@ -98,7 +82,7 @@ export default define(meta, async (ps, me) => { .innerJoinAndSelect('following.follower', 'follower'); const followings = await query - .take(ps.limit!) + .take(ps.limit) .getMany(); return await Followings.packMany(followings, me, { populateFollower: true }); diff --git a/packages/backend/src/server/api/endpoints/users/following.ts b/packages/backend/src/server/api/endpoints/users/following.ts index 76112eab2..b0a1036c7 100644 --- a/packages/backend/src/server/api/endpoints/users/following.ts +++ b/packages/backend/src/server/api/endpoints/users/following.ts @@ -1,43 +1,14 @@ -import $ from 'cafy'; -import { ID } from '@/misc/cafy-id'; -import define from '../../define'; -import { ApiError } from '../../error'; -import { Users, Followings, UserProfiles } from '@/models/index'; -import { makePaginationQuery } from '../../common/make-pagination-query'; -import { toPunyNullable } from '@/misc/convert-host'; +import define from '../../define.js'; +import { ApiError } from '../../error.js'; +import { Users, Followings, UserProfiles } from '@/models/index.js'; +import { makePaginationQuery } from '../../common/make-pagination-query.js'; +import { toPunyNullable } from '@/misc/convert-host.js'; export const meta = { tags: ['users'], requireCredential: false, - params: { - userId: { - validator: $.optional.type(ID), - }, - - username: { - validator: $.optional.str, - }, - - host: { - validator: $.optional.nullable.str, - }, - - sinceId: { - validator: $.optional.type(ID), - }, - - untilId: { - validator: $.optional.type(ID), - }, - - limit: { - validator: $.optional.num.range(1, 100), - default: 10, - }, - }, - res: { type: 'array', optional: false, nullable: false, @@ -63,8 +34,21 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + userId: { type: 'string', format: 'misskey:id' }, + username: { type: 'string' }, + host: { type: 'string', nullable: true }, + sinceId: { type: 'string', format: 'misskey:id' }, + untilId: { type: 'string', format: 'misskey:id' }, + limit: { type: 'integer', minimum: 1, maximum: 100, default: 10 }, + }, + required: [], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, me) => { +export default define(meta, paramDef, async (ps, me) => { const user = await Users.findOne(ps.userId != null ? { id: ps.userId } : { usernameLower: ps.username!.toLowerCase(), host: toPunyNullable(ps.host) }); @@ -98,7 +82,7 @@ export default define(meta, async (ps, me) => { .innerJoinAndSelect('following.followee', 'followee'); const followings = await query - .take(ps.limit!) + .take(ps.limit) .getMany(); return await Followings.packMany(followings, me, { populateFollowee: true }); diff --git a/packages/backend/src/server/api/endpoints/users/gallery/posts.ts b/packages/backend/src/server/api/endpoints/users/gallery/posts.ts index c5f08b4c9..d7c435256 100644 --- a/packages/backend/src/server/api/endpoints/users/gallery/posts.ts +++ b/packages/backend/src/server/api/endpoints/users/gallery/posts.ts @@ -1,39 +1,29 @@ -import $ from 'cafy'; -import { ID } from '@/misc/cafy-id'; -import define from '../../../define'; -import { GalleryPosts } from '@/models/index'; -import { makePaginationQuery } from '../../../common/make-pagination-query'; +import define from '../../../define.js'; +import { GalleryPosts } from '@/models/index.js'; +import { makePaginationQuery } from '../../../common/make-pagination-query.js'; export const meta = { tags: ['users', 'gallery'], +} as const; - params: { - userId: { - validator: $.type(ID), - }, - - limit: { - validator: $.optional.num.range(1, 100), - default: 10, - }, - - sinceId: { - validator: $.optional.type(ID), - }, - - untilId: { - validator: $.optional.type(ID), - }, +export const paramDef = { + type: 'object', + properties: { + userId: { type: 'string', format: 'misskey:id' }, + limit: { type: 'integer', minimum: 1, maximum: 100, default: 10 }, + sinceId: { type: 'string', format: 'misskey:id' }, + untilId: { type: 'string', format: 'misskey:id' }, }, + required: ['userId'], } as const; // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, user) => { +export default define(meta, paramDef, async (ps, user) => { const query = makePaginationQuery(GalleryPosts.createQueryBuilder('post'), ps.sinceId, ps.untilId) .andWhere(`post.userId = :userId`, { userId: ps.userId }); const posts = await query - .take(ps.limit!) + .take(ps.limit) .getMany(); return await GalleryPosts.packMany(posts, user); diff --git a/packages/backend/src/server/api/endpoints/users/get-frequently-replied-users.ts b/packages/backend/src/server/api/endpoints/users/get-frequently-replied-users.ts index d886d3355..73cadc0df 100644 --- a/packages/backend/src/server/api/endpoints/users/get-frequently-replied-users.ts +++ b/packages/backend/src/server/api/endpoints/users/get-frequently-replied-users.ts @@ -1,28 +1,15 @@ -import $ from 'cafy'; -import { ID } from '@/misc/cafy-id'; -import define from '../../define'; -import { maximum } from '@/prelude/array'; -import { ApiError } from '../../error'; -import { getUser } from '../../common/getters'; +import define from '../../define.js'; +import { maximum } from '@/prelude/array.js'; +import { ApiError } from '../../error.js'; +import { getUser } from '../../common/getters.js'; import { Not, In, IsNull } from 'typeorm'; -import { Notes, Users } from '@/models/index'; +import { Notes, Users } from '@/models/index.js'; export const meta = { tags: ['users'], requireCredential: false, - params: { - userId: { - validator: $.type(ID), - }, - - limit: { - validator: $.optional.num.range(1, 100), - default: 10, - }, - }, - res: { type: 'array', optional: false, nullable: false, @@ -52,8 +39,17 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + userId: { type: 'string', format: 'misskey:id' }, + limit: { type: 'integer', minimum: 1, maximum: 100, default: 10 }, + }, + required: ['userId'], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, me) => { +export default define(meta, paramDef, async (ps, me) => { // Lookup user const user = await getUser(ps.userId).catch(e => { if (e.id === '15348ddd-432d-49c2-8a5a-8069753becff') throw new ApiError(meta.errors.noSuchUser); @@ -104,7 +100,7 @@ export default define(meta, async (ps, me) => { const repliedUsersSorted = Object.keys(repliedUsers).sort((a, b) => repliedUsers[b] - repliedUsers[a]); // Extract top replied users - const topRepliedUsers = repliedUsersSorted.slice(0, ps.limit!); + const topRepliedUsers = repliedUsersSorted.slice(0, ps.limit); // Make replies object (includes weights) const repliesObj = await Promise.all(topRepliedUsers.map(async (user) => ({ diff --git a/packages/backend/src/server/api/endpoints/users/groups/create.ts b/packages/backend/src/server/api/endpoints/users/groups/create.ts index 25e29de01..9f6d8464d 100644 --- a/packages/backend/src/server/api/endpoints/users/groups/create.ts +++ b/packages/backend/src/server/api/endpoints/users/groups/create.ts @@ -1,9 +1,8 @@ -import $ from 'cafy'; -import define from '../../../define'; -import { UserGroups, UserGroupJoinings } from '@/models/index'; -import { genId } from '@/misc/gen-id'; -import { UserGroup } from '@/models/entities/user-group'; -import { UserGroupJoining } from '@/models/entities/user-group-joining'; +import define from '../../../define.js'; +import { UserGroups, UserGroupJoinings } from '@/models/index.js'; +import { genId } from '@/misc/gen-id.js'; +import { UserGroup } from '@/models/entities/user-group.js'; +import { UserGroupJoining } from '@/models/entities/user-group-joining.js'; export const meta = { tags: ['groups'], @@ -12,12 +11,6 @@ export const meta = { kind: 'write:user-groups', - params: { - name: { - validator: $.str.range(1, 100), - }, - }, - res: { type: 'object', optional: false, nullable: false, @@ -25,8 +18,16 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + name: { type: 'string', minLength: 1, maxLength: 100 }, + }, + required: ['name'], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, user) => { +export default define(meta, paramDef, async (ps, user) => { const userGroup = await UserGroups.insert({ id: genId(), createdAt: new Date(), diff --git a/packages/backend/src/server/api/endpoints/users/groups/delete.ts b/packages/backend/src/server/api/endpoints/users/groups/delete.ts index f30ab78ca..f4898a3c7 100644 --- a/packages/backend/src/server/api/endpoints/users/groups/delete.ts +++ b/packages/backend/src/server/api/endpoints/users/groups/delete.ts @@ -1,8 +1,6 @@ -import $ from 'cafy'; -import { ID } from '@/misc/cafy-id'; -import define from '../../../define'; -import { ApiError } from '../../../error'; -import { UserGroups } from '@/models/index'; +import define from '../../../define.js'; +import { ApiError } from '../../../error.js'; +import { UserGroups } from '@/models/index.js'; export const meta = { tags: ['groups'], @@ -11,12 +9,6 @@ export const meta = { kind: 'write:user-groups', - params: { - groupId: { - validator: $.type(ID), - }, - }, - errors: { noSuchGroup: { message: 'No such group.', @@ -26,8 +18,16 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + groupId: { type: 'string', format: 'misskey:id' }, + }, + required: ['groupId'], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, user) => { +export default define(meta, paramDef, async (ps, user) => { const userGroup = await UserGroups.findOne({ id: ps.groupId, userId: user.id, diff --git a/packages/backend/src/server/api/endpoints/users/groups/invitations/accept.ts b/packages/backend/src/server/api/endpoints/users/groups/invitations/accept.ts index 7061db538..efbdf968f 100644 --- a/packages/backend/src/server/api/endpoints/users/groups/invitations/accept.ts +++ b/packages/backend/src/server/api/endpoints/users/groups/invitations/accept.ts @@ -1,10 +1,8 @@ -import $ from 'cafy'; -import { ID } from '@/misc/cafy-id'; -import define from '../../../../define'; -import { ApiError } from '../../../../error'; -import { UserGroupJoinings, UserGroupInvitations } from '@/models/index'; -import { genId } from '@/misc/gen-id'; -import { UserGroupJoining } from '@/models/entities/user-group-joining'; +import define from '../../../../define.js'; +import { ApiError } from '../../../../error.js'; +import { UserGroupJoinings, UserGroupInvitations } from '@/models/index.js'; +import { genId } from '@/misc/gen-id.js'; +import { UserGroupJoining } from '@/models/entities/user-group-joining.js'; export const meta = { tags: ['groups', 'users'], @@ -13,12 +11,6 @@ export const meta = { kind: 'write:user-groups', - params: { - invitationId: { - validator: $.type(ID), - }, - }, - errors: { noSuchInvitation: { message: 'No such invitation.', @@ -28,8 +20,16 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + invitationId: { type: 'string', format: 'misskey:id' }, + }, + required: ['invitationId'], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, user) => { +export default define(meta, paramDef, async (ps, user) => { // Fetch the invitation const invitation = await UserGroupInvitations.findOne({ id: ps.invitationId, diff --git a/packages/backend/src/server/api/endpoints/users/groups/invitations/reject.ts b/packages/backend/src/server/api/endpoints/users/groups/invitations/reject.ts index f5ca3dec8..fe5d431ea 100644 --- a/packages/backend/src/server/api/endpoints/users/groups/invitations/reject.ts +++ b/packages/backend/src/server/api/endpoints/users/groups/invitations/reject.ts @@ -1,8 +1,6 @@ -import $ from 'cafy'; -import { ID } from '@/misc/cafy-id'; -import define from '../../../../define'; -import { ApiError } from '../../../../error'; -import { UserGroupInvitations } from '@/models/index'; +import define from '../../../../define.js'; +import { ApiError } from '../../../../error.js'; +import { UserGroupInvitations } from '@/models/index.js'; export const meta = { tags: ['groups', 'users'], @@ -11,12 +9,6 @@ export const meta = { kind: 'write:user-groups', - params: { - invitationId: { - validator: $.type(ID), - }, - }, - errors: { noSuchInvitation: { message: 'No such invitation.', @@ -26,8 +18,16 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + invitationId: { type: 'string', format: 'misskey:id' }, + }, + required: ['invitationId'], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, user) => { +export default define(meta, paramDef, async (ps, user) => { // Fetch the invitation const invitation = await UserGroupInvitations.findOne({ id: ps.invitationId, diff --git a/packages/backend/src/server/api/endpoints/users/groups/invite.ts b/packages/backend/src/server/api/endpoints/users/groups/invite.ts index 3b7a4edb8..10bfb7eca 100644 --- a/packages/backend/src/server/api/endpoints/users/groups/invite.ts +++ b/packages/backend/src/server/api/endpoints/users/groups/invite.ts @@ -1,12 +1,10 @@ -import $ from 'cafy'; -import { ID } from '@/misc/cafy-id'; -import define from '../../../define'; -import { ApiError } from '../../../error'; -import { getUser } from '../../../common/getters'; -import { UserGroups, UserGroupJoinings, UserGroupInvitations } from '@/models/index'; -import { genId } from '@/misc/gen-id'; -import { UserGroupInvitation } from '@/models/entities/user-group-invitation'; -import { createNotification } from '@/services/create-notification'; +import define from '../../../define.js'; +import { ApiError } from '../../../error.js'; +import { getUser } from '../../../common/getters.js'; +import { UserGroups, UserGroupJoinings, UserGroupInvitations } from '@/models/index.js'; +import { genId } from '@/misc/gen-id.js'; +import { UserGroupInvitation } from '@/models/entities/user-group-invitation.js'; +import { createNotification } from '@/services/create-notification.js'; export const meta = { tags: ['groups', 'users'], @@ -15,16 +13,6 @@ export const meta = { kind: 'write:user-groups', - params: { - groupId: { - validator: $.type(ID), - }, - - userId: { - validator: $.type(ID), - }, - }, - errors: { noSuchGroup: { message: 'No such group.', @@ -52,8 +40,17 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + groupId: { type: 'string', format: 'misskey:id' }, + userId: { type: 'string', format: 'misskey:id' }, + }, + required: ['groupId', 'userId'], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, me) => { +export default define(meta, paramDef, async (ps, me) => { // Fetch the group const userGroup = await UserGroups.findOne({ id: ps.groupId, diff --git a/packages/backend/src/server/api/endpoints/users/groups/joined.ts b/packages/backend/src/server/api/endpoints/users/groups/joined.ts index ab48b1910..e52de7859 100644 --- a/packages/backend/src/server/api/endpoints/users/groups/joined.ts +++ b/packages/backend/src/server/api/endpoints/users/groups/joined.ts @@ -1,5 +1,5 @@ -import define from '../../../define'; -import { UserGroups, UserGroupJoinings } from '@/models/index'; +import define from '../../../define.js'; +import { UserGroups, UserGroupJoinings } from '@/models/index.js'; import { Not, In } from 'typeorm'; export const meta = { @@ -20,8 +20,14 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: {}, + required: [], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, me) => { +export default define(meta, paramDef, async (ps, me) => { const ownedGroups = await UserGroups.find({ userId: me.id, }); diff --git a/packages/backend/src/server/api/endpoints/users/groups/leave.ts b/packages/backend/src/server/api/endpoints/users/groups/leave.ts index d2fcdab30..c1a8c2c02 100644 --- a/packages/backend/src/server/api/endpoints/users/groups/leave.ts +++ b/packages/backend/src/server/api/endpoints/users/groups/leave.ts @@ -1,8 +1,6 @@ -import $ from 'cafy'; -import { ID } from '@/misc/cafy-id'; -import define from '../../../define'; -import { ApiError } from '../../../error'; -import { UserGroups, UserGroupJoinings } from '@/models/index'; +import define from '../../../define.js'; +import { ApiError } from '../../../error.js'; +import { UserGroups, UserGroupJoinings } from '@/models/index.js'; export const meta = { tags: ['groups', 'users'], @@ -11,12 +9,6 @@ export const meta = { kind: 'write:user-groups', - params: { - groupId: { - validator: $.type(ID), - }, - }, - errors: { noSuchGroup: { message: 'No such group.', @@ -32,8 +24,16 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + groupId: { type: 'string', format: 'misskey:id' }, + }, + required: ['groupId'], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, me) => { +export default define(meta, paramDef, async (ps, me) => { // Fetch the group const userGroup = await UserGroups.findOne({ id: ps.groupId, diff --git a/packages/backend/src/server/api/endpoints/users/groups/owned.ts b/packages/backend/src/server/api/endpoints/users/groups/owned.ts index 6193a7101..11aad0f73 100644 --- a/packages/backend/src/server/api/endpoints/users/groups/owned.ts +++ b/packages/backend/src/server/api/endpoints/users/groups/owned.ts @@ -1,5 +1,5 @@ -import define from '../../../define'; -import { UserGroups } from '@/models/index'; +import define from '../../../define.js'; +import { UserGroups } from '@/models/index.js'; export const meta = { tags: ['groups', 'account'], @@ -19,8 +19,14 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: {}, + required: [], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, me) => { +export default define(meta, paramDef, async (ps, me) => { const userGroups = await UserGroups.find({ userId: me.id, }); diff --git a/packages/backend/src/server/api/endpoints/users/groups/pull.ts b/packages/backend/src/server/api/endpoints/users/groups/pull.ts index 785bea140..55ec9f915 100644 --- a/packages/backend/src/server/api/endpoints/users/groups/pull.ts +++ b/packages/backend/src/server/api/endpoints/users/groups/pull.ts @@ -1,9 +1,7 @@ -import $ from 'cafy'; -import { ID } from '@/misc/cafy-id'; -import define from '../../../define'; -import { ApiError } from '../../../error'; -import { getUser } from '../../../common/getters'; -import { UserGroups, UserGroupJoinings } from '@/models/index'; +import define from '../../../define.js'; +import { ApiError } from '../../../error.js'; +import { getUser } from '../../../common/getters.js'; +import { UserGroups, UserGroupJoinings } from '@/models/index.js'; export const meta = { tags: ['groups', 'users'], @@ -12,16 +10,6 @@ export const meta = { kind: 'write:user-groups', - params: { - groupId: { - validator: $.type(ID), - }, - - userId: { - validator: $.type(ID), - }, - }, - errors: { noSuchGroup: { message: 'No such group.', @@ -43,8 +31,17 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + groupId: { type: 'string', format: 'misskey:id' }, + userId: { type: 'string', format: 'misskey:id' }, + }, + required: ['groupId', 'userId'], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, me) => { +export default define(meta, paramDef, async (ps, me) => { // Fetch the group const userGroup = await UserGroups.findOne({ id: ps.groupId, diff --git a/packages/backend/src/server/api/endpoints/users/groups/show.ts b/packages/backend/src/server/api/endpoints/users/groups/show.ts index eb26eac2a..28ca1162c 100644 --- a/packages/backend/src/server/api/endpoints/users/groups/show.ts +++ b/packages/backend/src/server/api/endpoints/users/groups/show.ts @@ -1,8 +1,6 @@ -import $ from 'cafy'; -import { ID } from '@/misc/cafy-id'; -import define from '../../../define'; -import { ApiError } from '../../../error'; -import { UserGroups, UserGroupJoinings } from '@/models/index'; +import define from '../../../define.js'; +import { ApiError } from '../../../error.js'; +import { UserGroups, UserGroupJoinings } from '@/models/index.js'; export const meta = { tags: ['groups', 'account'], @@ -11,12 +9,6 @@ export const meta = { kind: 'read:user-groups', - params: { - groupId: { - validator: $.type(ID), - }, - }, - res: { type: 'object', optional: false, nullable: false, @@ -32,8 +24,16 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + groupId: { type: 'string', format: 'misskey:id' }, + }, + required: ['groupId'], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, me) => { +export default define(meta, paramDef, async (ps, me) => { // Fetch the group const userGroup = await UserGroups.findOne({ id: ps.groupId, diff --git a/packages/backend/src/server/api/endpoints/users/groups/transfer.ts b/packages/backend/src/server/api/endpoints/users/groups/transfer.ts index 4b1c8fbbd..f48e1ddbf 100644 --- a/packages/backend/src/server/api/endpoints/users/groups/transfer.ts +++ b/packages/backend/src/server/api/endpoints/users/groups/transfer.ts @@ -1,9 +1,7 @@ -import $ from 'cafy'; -import { ID } from '@/misc/cafy-id'; -import define from '../../../define'; -import { ApiError } from '../../../error'; -import { getUser } from '../../../common/getters'; -import { UserGroups, UserGroupJoinings } from '@/models/index'; +import define from '../../../define.js'; +import { ApiError } from '../../../error.js'; +import { getUser } from '../../../common/getters.js'; +import { UserGroups, UserGroupJoinings } from '@/models/index.js'; export const meta = { tags: ['groups', 'users'], @@ -12,16 +10,6 @@ export const meta = { kind: 'write:user-groups', - params: { - groupId: { - validator: $.type(ID), - }, - - userId: { - validator: $.type(ID), - }, - }, - res: { type: 'object', optional: false, nullable: false, @@ -49,8 +37,17 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + groupId: { type: 'string', format: 'misskey:id' }, + userId: { type: 'string', format: 'misskey:id' }, + }, + required: ['groupId', 'userId'], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, me) => { +export default define(meta, paramDef, async (ps, me) => { // Fetch the group const userGroup = await UserGroups.findOne({ id: ps.groupId, diff --git a/packages/backend/src/server/api/endpoints/users/groups/update.ts b/packages/backend/src/server/api/endpoints/users/groups/update.ts index 6caf90355..b3e17dfd9 100644 --- a/packages/backend/src/server/api/endpoints/users/groups/update.ts +++ b/packages/backend/src/server/api/endpoints/users/groups/update.ts @@ -1,8 +1,6 @@ -import $ from 'cafy'; -import { ID } from '@/misc/cafy-id'; -import define from '../../../define'; -import { ApiError } from '../../../error'; -import { UserGroups } from '@/models/index'; +import define from '../../../define.js'; +import { ApiError } from '../../../error.js'; +import { UserGroups } from '@/models/index.js'; export const meta = { tags: ['groups'], @@ -11,16 +9,6 @@ export const meta = { kind: 'write:user-groups', - params: { - groupId: { - validator: $.type(ID), - }, - - name: { - validator: $.str.range(1, 100), - }, - }, - res: { type: 'object', optional: false, nullable: false, @@ -36,8 +24,17 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + groupId: { type: 'string', format: 'misskey:id' }, + name: { type: 'string', minLength: 1, maxLength: 100 }, + }, + required: ['groupId', 'name'], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, me) => { +export default define(meta, paramDef, async (ps, me) => { // Fetch the group const userGroup = await UserGroups.findOne({ id: ps.groupId, diff --git a/packages/backend/src/server/api/endpoints/users/lists/create.ts b/packages/backend/src/server/api/endpoints/users/lists/create.ts index 945b51162..1a0599f9e 100644 --- a/packages/backend/src/server/api/endpoints/users/lists/create.ts +++ b/packages/backend/src/server/api/endpoints/users/lists/create.ts @@ -1,8 +1,7 @@ -import $ from 'cafy'; -import define from '../../../define'; -import { UserLists } from '@/models/index'; -import { genId } from '@/misc/gen-id'; -import { UserList } from '@/models/entities/user-list'; +import define from '../../../define.js'; +import { UserLists } from '@/models/index.js'; +import { genId } from '@/misc/gen-id.js'; +import { UserList } from '@/models/entities/user-list.js'; export const meta = { tags: ['lists'], @@ -11,12 +10,6 @@ export const meta = { kind: 'write:account', - params: { - name: { - validator: $.str.range(1, 100), - }, - }, - res: { type: 'object', optional: false, nullable: false, @@ -24,8 +17,16 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + name: { type: 'string', minLength: 1, maxLength: 100 }, + }, + required: ['name'], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, user) => { +export default define(meta, paramDef, async (ps, user) => { const userList = await UserLists.insert({ id: genId(), createdAt: new Date(), diff --git a/packages/backend/src/server/api/endpoints/users/lists/delete.ts b/packages/backend/src/server/api/endpoints/users/lists/delete.ts index 3183d2a09..aeefb98c8 100644 --- a/packages/backend/src/server/api/endpoints/users/lists/delete.ts +++ b/packages/backend/src/server/api/endpoints/users/lists/delete.ts @@ -1,8 +1,6 @@ -import $ from 'cafy'; -import { ID } from '@/misc/cafy-id'; -import define from '../../../define'; -import { ApiError } from '../../../error'; -import { UserLists } from '@/models/index'; +import define from '../../../define.js'; +import { ApiError } from '../../../error.js'; +import { UserLists } from '@/models/index.js'; export const meta = { tags: ['lists'], @@ -11,12 +9,6 @@ export const meta = { kind: 'write:account', - params: { - listId: { - validator: $.type(ID), - }, - }, - errors: { noSuchList: { message: 'No such list.', @@ -26,8 +18,16 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + listId: { type: 'string', format: 'misskey:id' }, + }, + required: ['listId'], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, user) => { +export default define(meta, paramDef, async (ps, user) => { const userList = await UserLists.findOne({ id: ps.listId, userId: user.id, diff --git a/packages/backend/src/server/api/endpoints/users/lists/list.ts b/packages/backend/src/server/api/endpoints/users/lists/list.ts index ae66b0aac..a8663ada8 100644 --- a/packages/backend/src/server/api/endpoints/users/lists/list.ts +++ b/packages/backend/src/server/api/endpoints/users/lists/list.ts @@ -1,5 +1,5 @@ -import define from '../../../define'; -import { UserLists } from '@/models/index'; +import define from '../../../define.js'; +import { UserLists } from '@/models/index.js'; export const meta = { tags: ['lists', 'account'], @@ -19,8 +19,14 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: {}, + required: [], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, me) => { +export default define(meta, paramDef, async (ps, me) => { const userLists = await UserLists.find({ userId: me.id, }); diff --git a/packages/backend/src/server/api/endpoints/users/lists/pull.ts b/packages/backend/src/server/api/endpoints/users/lists/pull.ts index 4c74aefa8..2c4c61d51 100644 --- a/packages/backend/src/server/api/endpoints/users/lists/pull.ts +++ b/packages/backend/src/server/api/endpoints/users/lists/pull.ts @@ -1,10 +1,8 @@ -import $ from 'cafy'; -import { ID } from '@/misc/cafy-id'; -import { publishUserListStream } from '@/services/stream'; -import define from '../../../define'; -import { ApiError } from '../../../error'; -import { getUser } from '../../../common/getters'; -import { UserLists, UserListJoinings, Users } from '@/models/index'; +import { publishUserListStream } from '@/services/stream.js'; +import define from '../../../define.js'; +import { ApiError } from '../../../error.js'; +import { getUser } from '../../../common/getters.js'; +import { UserLists, UserListJoinings, Users } from '@/models/index.js'; export const meta = { tags: ['lists', 'users'], @@ -13,16 +11,6 @@ export const meta = { kind: 'write:account', - params: { - listId: { - validator: $.type(ID), - }, - - userId: { - validator: $.type(ID), - }, - }, - errors: { noSuchList: { message: 'No such list.', @@ -38,8 +26,17 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + listId: { type: 'string', format: 'misskey:id' }, + userId: { type: 'string', format: 'misskey:id' }, + }, + required: ['listId', 'userId'], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, me) => { +export default define(meta, paramDef, async (ps, me) => { // Fetch the list const userList = await UserLists.findOne({ id: ps.listId, diff --git a/packages/backend/src/server/api/endpoints/users/lists/push.ts b/packages/backend/src/server/api/endpoints/users/lists/push.ts index 8b50c475b..034a9d2db 100644 --- a/packages/backend/src/server/api/endpoints/users/lists/push.ts +++ b/packages/backend/src/server/api/endpoints/users/lists/push.ts @@ -1,10 +1,8 @@ -import $ from 'cafy'; -import { ID } from '@/misc/cafy-id'; -import define from '../../../define'; -import { ApiError } from '../../../error'; -import { getUser } from '../../../common/getters'; -import { pushUserToUserList } from '@/services/user-list/push'; -import { UserLists, UserListJoinings, Blockings } from '@/models/index'; +import define from '../../../define.js'; +import { ApiError } from '../../../error.js'; +import { getUser } from '../../../common/getters.js'; +import { pushUserToUserList } from '@/services/user-list/push.js'; +import { UserLists, UserListJoinings, Blockings } from '@/models/index.js'; export const meta = { tags: ['lists', 'users'], @@ -13,16 +11,6 @@ export const meta = { kind: 'write:account', - params: { - listId: { - validator: $.type(ID), - }, - - userId: { - validator: $.type(ID), - }, - }, - errors: { noSuchList: { message: 'No such list.', @@ -50,8 +38,17 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + listId: { type: 'string', format: 'misskey:id' }, + userId: { type: 'string', format: 'misskey:id' }, + }, + required: ['listId', 'userId'], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, me) => { +export default define(meta, paramDef, async (ps, me) => { // Fetch the list const userList = await UserLists.findOne({ id: ps.listId, diff --git a/packages/backend/src/server/api/endpoints/users/lists/show.ts b/packages/backend/src/server/api/endpoints/users/lists/show.ts index 06555c1a8..fadb94c90 100644 --- a/packages/backend/src/server/api/endpoints/users/lists/show.ts +++ b/packages/backend/src/server/api/endpoints/users/lists/show.ts @@ -1,8 +1,6 @@ -import $ from 'cafy'; -import { ID } from '@/misc/cafy-id'; -import define from '../../../define'; -import { ApiError } from '../../../error'; -import { UserLists } from '@/models/index'; +import define from '../../../define.js'; +import { ApiError } from '../../../error.js'; +import { UserLists } from '@/models/index.js'; export const meta = { tags: ['lists', 'account'], @@ -11,12 +9,6 @@ export const meta = { kind: 'read:account', - params: { - listId: { - validator: $.type(ID), - }, - }, - res: { type: 'object', optional: false, nullable: false, @@ -32,8 +24,16 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + listId: { type: 'string', format: 'misskey:id' }, + }, + required: ['listId'], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, me) => { +export default define(meta, paramDef, async (ps, me) => { // Fetch the list const userList = await UserLists.findOne({ id: ps.listId, diff --git a/packages/backend/src/server/api/endpoints/users/lists/update.ts b/packages/backend/src/server/api/endpoints/users/lists/update.ts index 02b0d5fe1..5ec99031e 100644 --- a/packages/backend/src/server/api/endpoints/users/lists/update.ts +++ b/packages/backend/src/server/api/endpoints/users/lists/update.ts @@ -1,8 +1,6 @@ -import $ from 'cafy'; -import { ID } from '@/misc/cafy-id'; -import define from '../../../define'; -import { ApiError } from '../../../error'; -import { UserLists } from '@/models/index'; +import define from '../../../define.js'; +import { ApiError } from '../../../error.js'; +import { UserLists } from '@/models/index.js'; export const meta = { tags: ['lists'], @@ -11,16 +9,6 @@ export const meta = { kind: 'write:account', - params: { - listId: { - validator: $.type(ID), - }, - - name: { - validator: $.str.range(1, 100), - }, - }, - res: { type: 'object', optional: false, nullable: false, @@ -36,8 +24,17 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + listId: { type: 'string', format: 'misskey:id' }, + name: { type: 'string', minLength: 1, maxLength: 100 }, + }, + required: ['listId', 'name'], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, user) => { +export default define(meta, paramDef, async (ps, user) => { // Fetch the list const userList = await UserLists.findOne({ id: ps.listId, diff --git a/packages/backend/src/server/api/endpoints/users/notes.ts b/packages/backend/src/server/api/endpoints/users/notes.ts index 99158fb0a..16318d222 100644 --- a/packages/backend/src/server/api/endpoints/users/notes.ts +++ b/packages/backend/src/server/api/endpoints/users/notes.ts @@ -1,70 +1,17 @@ -import $ from 'cafy'; -import { ID } from '@/misc/cafy-id'; -import define from '../../define'; -import { ApiError } from '../../error'; -import { getUser } from '../../common/getters'; -import { makePaginationQuery } from '../../common/make-pagination-query'; -import { generateVisibilityQuery } from '../../common/generate-visibility-query'; -import { Notes } from '@/models/index'; -import { generateMutedUserQuery } from '../../common/generate-muted-user-query'; +import define from '../../define.js'; +import { ApiError } from '../../error.js'; +import { getUser } from '../../common/getters.js'; +import { makePaginationQuery } from '../../common/make-pagination-query.js'; +import { generateVisibilityQuery } from '../../common/generate-visibility-query.js'; +import { Notes } from '@/models/index.js'; +import { generateMutedUserQuery } from '../../common/generate-muted-user-query.js'; import { Brackets } from 'typeorm'; -import { generateBlockedUserQuery } from '../../common/generate-block-query'; -import { generateMutedInstanceQuery } from '../../common/generate-muted-instance-query'; +import { generateBlockedUserQuery } from '../../common/generate-block-query.js'; +import { generateMutedInstanceQuery } from '../../common/generate-muted-instance-query.js'; export const meta = { tags: ['users', 'notes'], - params: { - userId: { - validator: $.type(ID), - }, - - includeReplies: { - validator: $.optional.bool, - default: true, - }, - - limit: { - validator: $.optional.num.range(1, 100), - default: 10, - }, - - sinceId: { - validator: $.optional.type(ID), - }, - - untilId: { - validator: $.optional.type(ID), - }, - - sinceDate: { - validator: $.optional.num, - }, - - untilDate: { - validator: $.optional.num, - }, - - includeMyRenotes: { - validator: $.optional.bool, - default: true, - }, - - withFiles: { - validator: $.optional.bool, - default: false, - }, - - fileType: { - validator: $.optional.arr($.str), - }, - - excludeNsfw: { - validator: $.optional.bool, - default: false, - }, - }, - res: { type: 'array', optional: false, nullable: false, @@ -84,8 +31,28 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + userId: { type: 'string', format: 'misskey:id' }, + includeReplies: { type: 'boolean', default: true }, + limit: { type: 'integer', minimum: 1, maximum: 100, default: 10 }, + sinceId: { type: 'string', format: 'misskey:id' }, + untilId: { type: 'string', format: 'misskey:id' }, + sinceDate: { type: 'integer' }, + untilDate: { type: 'integer' }, + includeMyRenotes: { type: 'boolean', default: true }, + withFiles: { type: 'boolean', default: false }, + fileType: { type: 'array', items: { + type: 'string', + } }, + excludeNsfw: { type: 'boolean', default: false }, + }, + required: ['userId'], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, me) => { +export default define(meta, paramDef, async (ps, me) => { // Lookup user const user = await getUser(ps.userId).catch(e => { if (e.id === '15348ddd-432d-49c2-8a5a-8069753becff') throw new ApiError(meta.errors.noSuchUser); @@ -96,10 +63,16 @@ export default define(meta, async (ps, me) => { const query = makePaginationQuery(Notes.createQueryBuilder('note'), ps.sinceId, ps.untilId, ps.sinceDate, ps.untilDate) .andWhere('note.userId = :userId', { userId: user.id }) .innerJoinAndSelect('note.user', 'user') + .leftJoinAndSelect('user.avatar', 'avatar') + .leftJoinAndSelect('user.banner', 'banner') .leftJoinAndSelect('note.reply', 'reply') .leftJoinAndSelect('note.renote', 'renote') .leftJoinAndSelect('reply.user', 'replyUser') - .leftJoinAndSelect('renote.user', 'renoteUser'); + .leftJoinAndSelect('replyUser.avatar', 'replyUserAvatar') + .leftJoinAndSelect('replyUser.banner', 'replyUserBanner') + .leftJoinAndSelect('renote.user', 'renoteUser') + .leftJoinAndSelect('renoteUser.avatar', 'renoteUserAvatar') + .leftJoinAndSelect('renoteUser.banner', 'renoteUserBanner'); generateVisibilityQuery(query, me); if (me) generateMutedUserQuery(query, me, user); @@ -141,7 +114,7 @@ export default define(meta, async (ps, me) => { //#endregion - const timeline = await query.take(ps.limit!).getMany(); + const timeline = await query.take(ps.limit).getMany(); return await Notes.packMany(timeline, me); }); diff --git a/packages/backend/src/server/api/endpoints/users/pages.ts b/packages/backend/src/server/api/endpoints/users/pages.ts index 6e003dd1a..b8b3e8192 100644 --- a/packages/backend/src/server/api/endpoints/users/pages.ts +++ b/packages/backend/src/server/api/endpoints/users/pages.ts @@ -1,40 +1,30 @@ -import $ from 'cafy'; -import { ID } from '@/misc/cafy-id'; -import define from '../../define'; -import { Pages } from '@/models/index'; -import { makePaginationQuery } from '../../common/make-pagination-query'; +import define from '../../define.js'; +import { Pages } from '@/models/index.js'; +import { makePaginationQuery } from '../../common/make-pagination-query.js'; export const meta = { tags: ['users', 'pages'], +} as const; - params: { - userId: { - validator: $.type(ID), - }, - - limit: { - validator: $.optional.num.range(1, 100), - default: 10, - }, - - sinceId: { - validator: $.optional.type(ID), - }, - - untilId: { - validator: $.optional.type(ID), - }, +export const paramDef = { + type: 'object', + properties: { + userId: { type: 'string', format: 'misskey:id' }, + limit: { type: 'integer', minimum: 1, maximum: 100, default: 10 }, + sinceId: { type: 'string', format: 'misskey:id' }, + untilId: { type: 'string', format: 'misskey:id' }, }, + required: ['userId'], } as const; // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, user) => { +export default define(meta, paramDef, async (ps, user) => { const query = makePaginationQuery(Pages.createQueryBuilder('page'), ps.sinceId, ps.untilId) .andWhere(`page.userId = :userId`, { userId: ps.userId }) .andWhere('page.visibility = \'public\''); const pages = await query - .take(ps.limit!) + .take(ps.limit) .getMany(); return await Pages.packMany(pages); diff --git a/packages/backend/src/server/api/endpoints/users/reactions.ts b/packages/backend/src/server/api/endpoints/users/reactions.ts index 312d4dbf2..7b55a1671 100644 --- a/packages/backend/src/server/api/endpoints/users/reactions.ts +++ b/packages/backend/src/server/api/endpoints/users/reactions.ts @@ -1,43 +1,14 @@ -import $ from 'cafy'; -import { ID } from '@/misc/cafy-id'; -import define from '../../define'; -import { NoteReactions, UserProfiles } from '@/models/index'; -import { makePaginationQuery } from '../../common/make-pagination-query'; -import { generateVisibilityQuery } from '../../common/generate-visibility-query'; -import { ApiError } from '../../error'; +import define from '../../define.js'; +import { NoteReactions, UserProfiles } from '@/models/index.js'; +import { makePaginationQuery } from '../../common/make-pagination-query.js'; +import { generateVisibilityQuery } from '../../common/generate-visibility-query.js'; +import { ApiError } from '../../error.js'; export const meta = { tags: ['users', 'reactions'], requireCredential: false, - params: { - userId: { - validator: $.type(ID), - }, - - limit: { - validator: $.optional.num.range(1, 100), - default: 10, - }, - - sinceId: { - validator: $.optional.type(ID), - }, - - untilId: { - validator: $.optional.type(ID), - }, - - sinceDate: { - validator: $.optional.num, - }, - - untilDate: { - validator: $.optional.num, - }, - }, - res: { type: 'array', optional: false, nullable: false, @@ -57,8 +28,21 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + userId: { type: 'string', format: 'misskey:id' }, + limit: { type: 'integer', minimum: 1, maximum: 100, default: 10 }, + sinceId: { type: 'string', format: 'misskey:id' }, + untilId: { type: 'string', format: 'misskey:id' }, + sinceDate: { type: 'integer' }, + untilDate: { type: 'integer' }, + }, + required: ['userId'], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, me) => { +export default define(meta, paramDef, async (ps, me) => { const profile = await UserProfiles.findOneOrFail(ps.userId); if (me == null || (me.id !== ps.userId && !profile.publicReactions)) { @@ -73,7 +57,7 @@ export default define(meta, async (ps, me) => { generateVisibilityQuery(query, me); const reactions = await query - .take(ps.limit!) + .take(ps.limit) .getMany(); return await Promise.all(reactions.map(reaction => NoteReactions.pack(reaction, me, { withNote: true }))); diff --git a/packages/backend/src/server/api/endpoints/users/recommendation.ts b/packages/backend/src/server/api/endpoints/users/recommendation.ts index 9ea39eb2d..a8f18de52 100644 --- a/packages/backend/src/server/api/endpoints/users/recommendation.ts +++ b/packages/backend/src/server/api/endpoints/users/recommendation.ts @@ -1,9 +1,8 @@ import ms from 'ms'; -import $ from 'cafy'; -import define from '../../define'; -import { Users, Followings } from '@/models/index'; -import { generateMutedUserQueryForUsers } from '../../common/generate-muted-user-query'; -import { generateBlockedUserQuery, generateBlockQueryForUsers } from '../../common/generate-block-query'; +import define from '../../define.js'; +import { Users, Followings } from '@/models/index.js'; +import { generateMutedUserQueryForUsers } from '../../common/generate-muted-user-query.js'; +import { generateBlockedUserQuery, generateBlockQueryForUsers } from '../../common/generate-block-query.js'; export const meta = { tags: ['users'], @@ -12,18 +11,6 @@ export const meta = { kind: 'read:account', - params: { - limit: { - validator: $.optional.num.range(1, 100), - default: 10, - }, - - offset: { - validator: $.optional.num.min(0), - default: 0, - }, - }, - res: { type: 'array', optional: false, nullable: false, @@ -35,8 +22,17 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + limit: { type: 'integer', minimum: 1, maximum: 100, default: 10 }, + offset: { type: 'integer', default: 0 }, + }, + required: [], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, me) => { +export default define(meta, paramDef, async (ps, me) => { const query = Users.createQueryBuilder('user') .where('user.isLocked = FALSE') .andWhere('user.isExplorable = TRUE') @@ -58,7 +54,7 @@ export default define(meta, async (ps, me) => { query.setParameters(followingQuery.getParameters()); - const users = await query.take(ps.limit!).skip(ps.offset).getMany(); + const users = await query.take(ps.limit).skip(ps.offset).getMany(); return await Users.packMany(users, me, { detail: true }); }); diff --git a/packages/backend/src/server/api/endpoints/users/relation.ts b/packages/backend/src/server/api/endpoints/users/relation.ts index 7e319ca10..c6262122d 100644 --- a/packages/backend/src/server/api/endpoints/users/relation.ts +++ b/packages/backend/src/server/api/endpoints/users/relation.ts @@ -1,19 +1,11 @@ -import $ from 'cafy'; -import define from '../../define'; -import { ID } from '@/misc/cafy-id'; -import { Users } from '@/models/index'; +import define from '../../define.js'; +import { Users } from '@/models/index.js'; export const meta = { tags: ['users'], requireCredential: true, - params: { - userId: { - validator: $.either($.type(ID), $.arr($.type(ID)).unique()), - }, - }, - res: { optional: false, nullable: false, oneOf: [ @@ -101,8 +93,24 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + userId: { + anyOf: [ + { type: 'string', format: 'misskey:id' }, + { + type: 'array', + items: { type: 'string', format: 'misskey:id' }, + }, + ], + }, + }, + required: ['userId'], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, me) => { +export default define(meta, paramDef, async (ps, me) => { const ids = Array.isArray(ps.userId) ? ps.userId : [ps.userId]; const relations = await Promise.all(ids.map(id => Users.getRelation(me.id, id))); diff --git a/packages/backend/src/server/api/endpoints/users/report-abuse.ts b/packages/backend/src/server/api/endpoints/users/report-abuse.ts index ed2aa7bb2..e091b8e1b 100644 --- a/packages/backend/src/server/api/endpoints/users/report-abuse.ts +++ b/packages/backend/src/server/api/endpoints/users/report-abuse.ts @@ -1,30 +1,18 @@ -import $ from 'cafy'; import * as sanitizeHtml from 'sanitize-html'; -import { ID } from '@/misc/cafy-id'; -import define from '../../define'; -import { publishAdminStream } from '@/services/stream'; -import { ApiError } from '../../error'; -import { getUser } from '../../common/getters'; -import { AbuseUserReports, Users } from '@/models/index'; -import { genId } from '@/misc/gen-id'; -import { sendEmail } from '@/services/send-email'; -import { fetchMeta } from '@/misc/fetch-meta'; +import define from '../../define.js'; +import { publishAdminStream } from '@/services/stream.js'; +import { ApiError } from '../../error.js'; +import { getUser } from '../../common/getters.js'; +import { AbuseUserReports, Users } from '@/models/index.js'; +import { genId } from '@/misc/gen-id.js'; +import { sendEmail } from '@/services/send-email.js'; +import { fetchMeta } from '@/misc/fetch-meta.js'; export const meta = { tags: ['users'], requireCredential: true, - params: { - userId: { - validator: $.type(ID), - }, - - comment: { - validator: $.str.range(1, 2048), - }, - }, - errors: { noSuchUser: { message: 'No such user.', @@ -46,8 +34,17 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + userId: { type: 'string', format: 'misskey:id' }, + comment: { type: 'string', minLength: 1, maxLength: 2048 }, + }, + required: ['userId', 'comment'], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, me) => { +export default define(meta, paramDef, async (ps, me) => { // Lookup user const user = await getUser(ps.userId).catch(e => { if (e.id === '15348ddd-432d-49c2-8a5a-8069753becff') throw new ApiError(meta.errors.noSuchUser); diff --git a/packages/backend/src/server/api/endpoints/users/search-by-username-and-host.ts b/packages/backend/src/server/api/endpoints/users/search-by-username-and-host.ts index 72e79c882..897b5de3f 100644 --- a/packages/backend/src/server/api/endpoints/users/search-by-username-and-host.ts +++ b/packages/backend/src/server/api/endpoints/users/search-by-username-and-host.ts @@ -1,35 +1,14 @@ -import $ from 'cafy'; -import define from '../../define'; -import { Followings, Users } from '@/models/index'; +import define from '../../define.js'; +import { Followings, Users } from '@/models/index.js'; import { Brackets } from 'typeorm'; -import { USER_ACTIVE_THRESHOLD } from '@/const'; -import { User } from '@/models/entities/user'; +import { USER_ACTIVE_THRESHOLD } from '@/const.js'; +import { User } from '@/models/entities/user.js'; export const meta = { tags: ['users'], requireCredential: false, - params: { - username: { - validator: $.optional.nullable.str, - }, - - host: { - validator: $.optional.nullable.str, - }, - - limit: { - validator: $.optional.num.range(1, 100), - default: 10, - }, - - detail: { - validator: $.optional.bool, - default: true, - }, - }, - res: { type: 'array', optional: false, nullable: false, @@ -41,8 +20,21 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + username: { type: 'string', nullable: true }, + host: { type: 'string', nullable: true }, + limit: { type: 'integer', minimum: 1, maximum: 100, default: 10 }, + detail: { type: 'boolean', default: true }, + }, + required: [], +} as const; + +// TODO: avatar,bannerをJOINしたいけどエラーになる + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, me) => { +export default define(meta, paramDef, async (ps, me) => { const activeThreshold = new Date(Date.now() - (1000 * 60 * 60 * 24 * 30)); // 30日 if (ps.host) { @@ -57,7 +49,7 @@ export default define(meta, async (ps, me) => { q.andWhere('user.updatedAt IS NOT NULL'); q.orderBy('user.updatedAt', 'DESC'); - const users = await q.take(ps.limit!).getMany(); + const users = await q.take(ps.limit).getMany(); return await Users.packMany(users, me, { detail: ps.detail }); } else if (ps.username) { @@ -82,10 +74,10 @@ export default define(meta, async (ps, me) => { users = await query .orderBy('user.usernameLower', 'ASC') - .take(ps.limit!) + .take(ps.limit) .getMany(); - if (users.length < ps.limit!) { + if (users.length < ps.limit) { const otherQuery = await Users.createQueryBuilder('user') .where(`user.id NOT IN (${ followingQuery.getQuery() })`) .andWhere(`user.id != :meId`, { meId: me.id }) @@ -97,7 +89,7 @@ export default define(meta, async (ps, me) => { const otherUsers = await otherQuery .orderBy('user.updatedAt', 'DESC') - .take(ps.limit! - users.length) + .take(ps.limit - users.length) .getMany(); users = users.concat(otherUsers); @@ -108,7 +100,7 @@ export default define(meta, async (ps, me) => { .andWhere('user.usernameLower LIKE :username', { username: ps.username.toLowerCase() + '%' }) .andWhere('user.updatedAt IS NOT NULL') .orderBy('user.updatedAt', 'DESC') - .take(ps.limit! - users.length) + .take(ps.limit - users.length) .getMany(); } diff --git a/packages/backend/src/server/api/endpoints/users/search.ts b/packages/backend/src/server/api/endpoints/users/search.ts index 26f818afc..a72a58a84 100644 --- a/packages/backend/src/server/api/endpoints/users/search.ts +++ b/packages/backend/src/server/api/endpoints/users/search.ts @@ -1,7 +1,6 @@ -import $ from 'cafy'; -import define from '../../define'; -import { UserProfiles, Users } from '@/models/index'; -import { User } from '@/models/entities/user'; +import define from '../../define.js'; +import { UserProfiles, Users } from '@/models/index.js'; +import { User } from '@/models/entities/user.js'; import { Brackets } from 'typeorm'; export const meta = { @@ -9,32 +8,6 @@ export const meta = { requireCredential: false, - params: { - query: { - validator: $.str, - }, - - offset: { - validator: $.optional.num.min(0), - default: 0, - }, - - limit: { - validator: $.optional.num.range(1, 100), - default: 10, - }, - - origin: { - validator: $.optional.str.or(['local', 'remote', 'combined']), - default: 'combined', - }, - - detail: { - validator: $.optional.bool, - default: true, - }, - }, - res: { type: 'array', optional: false, nullable: false, @@ -46,8 +19,20 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + query: { type: 'string' }, + offset: { type: 'integer', default: 0 }, + limit: { type: 'integer', minimum: 1, maximum: 100, default: 10 }, + origin: { type: 'string', enum: ['local', 'remote', 'combined'], default: "combined" }, + detail: { type: 'boolean', default: true }, + }, + required: ['query'], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, me) => { +export default define(meta, paramDef, async (ps, me) => { const activeThreshold = new Date(Date.now() - (1000 * 60 * 60 * 24 * 30)); // 30日 const isUsername = ps.query.startsWith('@'); @@ -71,7 +56,7 @@ export default define(meta, async (ps, me) => { users = await usernameQuery .orderBy('user.updatedAt', 'DESC', 'NULLS LAST') - .take(ps.limit!) + .take(ps.limit) .skip(ps.offset) .getMany(); } else { @@ -91,11 +76,11 @@ export default define(meta, async (ps, me) => { users = await nameQuery .orderBy('user.updatedAt', 'DESC', 'NULLS LAST') - .take(ps.limit!) + .take(ps.limit) .skip(ps.offset) .getMany(); - if (users.length < ps.limit!) { + if (users.length < ps.limit) { const profQuery = UserProfiles.createQueryBuilder('prof') .select('prof.userId') .where('prof.description ILIKE :query', { query: '%' + ps.query + '%' }); @@ -117,7 +102,7 @@ export default define(meta, async (ps, me) => { users = users.concat(await query .orderBy('user.updatedAt', 'DESC', 'NULLS LAST') - .take(ps.limit!) + .take(ps.limit) .skip(ps.offset) .getMany() ); diff --git a/packages/backend/src/server/api/endpoints/users/show.ts b/packages/backend/src/server/api/endpoints/users/show.ts index 92910e9ed..263c102a7 100644 --- a/packages/backend/src/server/api/endpoints/users/show.ts +++ b/packages/backend/src/server/api/endpoints/users/show.ts @@ -1,36 +1,16 @@ -import $ from 'cafy'; -import { resolveUser } from '@/remote/resolve-user'; -import define from '../../define'; -import { apiLogger } from '../../logger'; -import { ApiError } from '../../error'; -import { ID } from '@/misc/cafy-id'; -import { Users } from '@/models/index'; +import { resolveUser } from '@/remote/resolve-user.js'; +import define from '../../define.js'; +import { apiLogger } from '../../logger.js'; +import { ApiError } from '../../error.js'; +import { Users } from '@/models/index.js'; import { In } from 'typeorm'; -import { User } from '@/models/entities/user'; +import { User } from '@/models/entities/user.js'; export const meta = { tags: ['users'], requireCredential: false, - params: { - userId: { - validator: $.optional.type(ID), - }, - - userIds: { - validator: $.optional.arr($.type(ID)).unique(), - }, - - username: { - validator: $.optional.str, - }, - - host: { - validator: $.optional.nullable.str, - }, - }, - res: { optional: false, nullable: false, oneOf: [ @@ -64,8 +44,21 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + userId: { type: 'string', format: 'misskey:id' }, + userIds: { type: 'array', uniqueItems: true, items: { + type: 'string', format: 'misskey:id', + } }, + username: { type: 'string' }, + host: { type: 'string', nullable: true }, + }, + required: [], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, me) => { +export default define(meta, paramDef, async (ps, me) => { let user; const isAdminOrModerator = me && (me.isAdmin || me.isModerator); diff --git a/packages/backend/src/server/api/endpoints/users/stats.ts b/packages/backend/src/server/api/endpoints/users/stats.ts index 381e43347..180a9386d 100644 --- a/packages/backend/src/server/api/endpoints/users/stats.ts +++ b/packages/backend/src/server/api/endpoints/users/stats.ts @@ -1,20 +1,12 @@ -import $ from 'cafy'; -import define from '../../define'; -import { ApiError } from '../../error'; -import { ID } from '@/misc/cafy-id'; -import { DriveFiles, Followings, NoteFavorites, NoteReactions, Notes, PageLikes, PollVotes, Users } from '@/models/index'; +import define from '../../define.js'; +import { ApiError } from '../../error.js'; +import { DriveFiles, Followings, NoteFavorites, NoteReactions, Notes, PageLikes, PollVotes, Users } from '@/models/index.js'; export const meta = { tags: ['users'], requireCredential: false, - params: { - userId: { - validator: $.type(ID), - }, - }, - errors: { noSuchUser: { message: 'No such user.', @@ -24,8 +16,16 @@ export const meta = { }, } as const; +export const paramDef = { + type: 'object', + properties: { + userId: { type: 'string', format: 'misskey:id' }, + }, + required: ['userId'], +} as const; + // eslint-disable-next-line import/no-default-export -export default define(meta, async (ps, me) => { +export default define(meta, paramDef, async (ps, me) => { const user = await Users.findOne(ps.userId); if (user == null) { throw new ApiError(meta.errors.noSuchUser); diff --git a/packages/backend/src/server/api/index.ts b/packages/backend/src/server/api/index.ts index 8f8a9d999..ba2a71951 100644 --- a/packages/backend/src/server/api/index.ts +++ b/packages/backend/src/server/api/index.ts @@ -2,22 +2,22 @@ * API Server */ -import * as Koa from 'koa'; -import * as Router from '@koa/router'; -import * as multer from '@koa/multer'; -import * as bodyParser from 'koa-bodyparser'; -import * as cors from '@koa/cors'; +import Koa from 'koa'; +import Router from '@koa/router'; +import multer from '@koa/multer'; +import bodyParser from 'koa-bodyparser'; +import cors from '@koa/cors'; -import endpoints from './endpoints'; -import handler from './api-handler'; -import signup from './private/signup'; -import signin from './private/signin'; -import signupPending from './private/signup-pending'; -import discord from './service/discord'; -import github from './service/github'; -import twitter from './service/twitter'; -import { Instances, AccessTokens, Users } from '@/models/index'; -import config from '@/config'; +import endpoints from './endpoints.js'; +import handler from './api-handler.js'; +import signup from './private/signup.js'; +import signin from './private/signin.js'; +import signupPending from './private/signup-pending.js'; +import discord from './service/discord.js'; +import github from './service/github.js'; +import twitter from './service/twitter.js'; +import { Instances, AccessTokens, Users } from '@/models/index.js'; +import config from '@/config/index.js'; // Init app const app = new Koa(); diff --git a/packages/backend/src/server/api/limiter.ts b/packages/backend/src/server/api/limiter.ts index 4721f6263..7e6b93b39 100644 --- a/packages/backend/src/server/api/limiter.ts +++ b/packages/backend/src/server/api/limiter.ts @@ -1,9 +1,9 @@ -import * as Limiter from 'ratelimiter'; -import { redisClient } from '../../db/redis'; -import { IEndpoint } from './endpoints'; -import * as Acct from 'misskey-js/built/acct'; -import { User } from '@/models/entities/user'; -import Logger from '@/services/logger'; +import Limiter from 'ratelimiter'; +import { redisClient } from '../../db/redis.js'; +import { IEndpoint } from './endpoints.js'; +import * as Acct from '@/misc/acct.js'; +import { User } from '@/models/entities/user.js'; +import Logger from '@/services/logger.js'; const logger = new Logger('limiter'); diff --git a/packages/backend/src/server/api/logger.ts b/packages/backend/src/server/api/logger.ts index 750defe54..ec22d6c3e 100644 --- a/packages/backend/src/server/api/logger.ts +++ b/packages/backend/src/server/api/logger.ts @@ -1,3 +1,3 @@ -import Logger from '@/services/logger'; +import Logger from '@/services/logger.js'; export const apiLogger = new Logger('api'); diff --git a/packages/backend/src/server/api/openapi/gen-spec.ts b/packages/backend/src/server/api/openapi/gen-spec.ts index 1efef8d26..c6e557aef 100644 --- a/packages/backend/src/server/api/openapi/gen-spec.ts +++ b/packages/backend/src/server/api/openapi/gen-spec.ts @@ -1,8 +1,7 @@ -import endpoints from '../endpoints'; -import { Context } from 'cafy'; -import config from '@/config/index'; -import { errors as basicErrors } from './errors'; -import { schemas, convertSchemaToOpenApiSchema } from './schemas'; +import endpoints from '../endpoints.js'; +import config from '@/config/index.js'; +import { errors as basicErrors } from './errors.js'; +import { schemas, convertSchemaToOpenApiSchema } from './schemas.js'; export function genOpenapiSpec(lang = 'ja-JP') { const spec = { @@ -38,47 +37,7 @@ export function genOpenapiSpec(lang = 'ja-JP') { }, }; - function genProps(props: { [key: string]: Context; }) { - const properties = {} as any; - - for (const [k, v] of Object.entries(props)) { - properties[k] = genProp(v); - } - - return properties; - } - - function genProp(param: Context): any { - const required = param.name === 'Object' ? (param as any).props ? Object.entries((param as any).props).filter(([k, v]: any) => !v.isOptional).map(([k, v]) => k) : [] : []; - return { - description: (param.data || {}).desc, - default: (param.data || {}).default, - deprecated: (param.data || {}).deprecated, - ...((param.data || {}).default ? { default: (param.data || {}).default } : {}), - type: param.name === 'ID' ? 'string' : param.name.toLowerCase(), - ...(param.name === 'ID' ? { example: 'xxxxxxxxxx', format: 'id' } : {}), - nullable: param.isNullable, - ...(param.name === 'String' ? { - ...((param as any).enum ? { enum: (param as any).enum } : {}), - ...((param as any).minLength ? { minLength: (param as any).minLength } : {}), - ...((param as any).maxLength ? { maxLength: (param as any).maxLength } : {}), - } : {}), - ...(param.name === 'Number' ? { - ...((param as any).minimum ? { minimum: (param as any).minimum } : {}), - ...((param as any).maximum ? { maximum: (param as any).maximum } : {}), - } : {}), - ...(param.name === 'Object' ? { - ...(required.length > 0 ? { required } : {}), - properties: (param as any).props ? genProps((param as any).props) : {}, - } : {}), - ...(param.name === 'Array' ? { - items: (param as any).ctx ? genProp((param as any).ctx) : {}, - } : {}), - }; - } - for (const endpoint of endpoints.filter(ep => !ep.meta.secure)) { - const porops = {} as any; const errors = {} as any; if (endpoint.meta.errors) { @@ -91,21 +50,9 @@ export function genOpenapiSpec(lang = 'ja-JP') { } } - if (endpoint.meta.params) { - for (const [k, v] of Object.entries(endpoint.meta.params)) { - if (v.validator.data == null) v.validator.data = {}; - if (v.desc) v.validator.data.desc = v.desc[lang]; - if (v.deprecated) v.validator.data.deprecated = v.deprecated; - if (v.default) v.validator.data.default = v.default; - porops[k] = v.validator; - } - } - - const required = endpoint.meta.params ? Object.entries(endpoint.meta.params).filter(([k, v]) => !v.validator.isOptional).map(([k, v]) => k) : []; - const resSchema = endpoint.meta.res ? convertSchemaToOpenApiSchema(endpoint.meta.res) : {}; - let desc = (endpoint.meta.desc ? endpoint.meta.desc[lang] : 'No description provided.') + '\n\n'; + let desc = (endpoint.meta.description ? endpoint.meta.description : 'No description provided.') + '\n\n'; desc += `**Credential required**: *${endpoint.meta.requireCredential ? 'Yes' : 'No'}*`; if (endpoint.meta.kind) { const kind = endpoint.meta.kind; @@ -132,11 +79,7 @@ export function genOpenapiSpec(lang = 'ja-JP') { required: true, content: { 'application/json': { - schema: { - type: 'object', - ...(required.length > 0 ? { required } : {}), - properties: endpoint.meta.params ? genProps(porops) : {}, - }, + schema: endpoint.params, }, }, }, diff --git a/packages/backend/src/server/api/openapi/schemas.ts b/packages/backend/src/server/api/openapi/schemas.ts index eb42667fd..14bef9cab 100644 --- a/packages/backend/src/server/api/openapi/schemas.ts +++ b/packages/backend/src/server/api/openapi/schemas.ts @@ -1,6 +1,6 @@ -import { refs, MinimumSchema } from '@/misc/schema'; +import { refs, Schema } from '@/misc/schema.js'; -export function convertSchemaToOpenApiSchema(schema: MinimumSchema) { +export function convertSchemaToOpenApiSchema(schema: Schema) { const res: any = schema; if (schema.type === 'object' && schema.properties) { diff --git a/packages/backend/src/server/api/private/signin.ts b/packages/backend/src/server/api/private/signin.ts index 7b733b768..b0f88948a 100644 --- a/packages/backend/src/server/api/private/signin.ts +++ b/packages/backend/src/server/api/private/signin.ts @@ -1,13 +1,13 @@ -import * as Koa from 'koa'; -import * as bcrypt from 'bcryptjs'; +import Koa from 'koa'; +import bcrypt from 'bcryptjs'; import * as speakeasy from 'speakeasy'; -import signin from '../common/signin'; -import config from '@/config/index'; -import { Users, Signins, UserProfiles, UserSecurityKeys, AttestationChallenges } from '@/models/index'; -import { ILocalUser } from '@/models/entities/user'; -import { genId } from '@/misc/gen-id'; -import { verifyLogin, hash } from '../2fa'; -import { randomBytes } from 'crypto'; +import signin from '../common/signin.js'; +import config from '@/config/index.js'; +import { Users, Signins, UserProfiles, UserSecurityKeys, AttestationChallenges } from '@/models/index.js'; +import { ILocalUser } from '@/models/entities/user.js'; +import { genId } from '@/misc/gen-id.js'; +import { verifyLogin, hash } from '../2fa.js'; +import { randomBytes } from 'node:crypto'; export default async (ctx: Koa.Context) => { ctx.set('Access-Control-Allow-Origin', config.url); diff --git a/packages/backend/src/server/api/private/signup-pending.ts b/packages/backend/src/server/api/private/signup-pending.ts index c0638a1cd..1a667ddb4 100644 --- a/packages/backend/src/server/api/private/signup-pending.ts +++ b/packages/backend/src/server/api/private/signup-pending.ts @@ -1,7 +1,7 @@ -import * as Koa from 'koa'; -import { Users, UserPendings, UserProfiles } from '@/models/index'; -import { signup } from '../common/signup'; -import signin from '../common/signin'; +import Koa from 'koa'; +import { Users, UserPendings, UserProfiles } from '@/models/index.js'; +import { signup } from '../common/signup.js'; +import signin from '../common/signin.js'; export default async (ctx: Koa.Context) => { const body = ctx.request.body; diff --git a/packages/backend/src/server/api/private/signup.ts b/packages/backend/src/server/api/private/signup.ts index eaab8e711..01f284a57 100644 --- a/packages/backend/src/server/api/private/signup.ts +++ b/packages/backend/src/server/api/private/signup.ts @@ -1,14 +1,14 @@ -import * as Koa from 'koa'; +import Koa from 'koa'; import rndstr from 'rndstr'; -import * as bcrypt from 'bcryptjs'; -import { fetchMeta } from '@/misc/fetch-meta'; -import { verifyHcaptcha, verifyRecaptcha } from '@/misc/captcha'; -import { Users, RegistrationTickets, UserPendings } from '@/models/index'; -import { signup } from '../common/signup'; -import config from '@/config'; -import { sendEmail } from '@/services/send-email'; -import { genId } from '@/misc/gen-id'; -import { validateEmailForAccount } from '@/services/validate-email-for-account'; +import bcrypt from 'bcryptjs'; +import { fetchMeta } from '@/misc/fetch-meta.js'; +import { verifyHcaptcha, verifyRecaptcha } from '@/misc/captcha.js'; +import { Users, RegistrationTickets, UserPendings } from '@/models/index.js'; +import { signup } from '../common/signup.js'; +import config from '@/config/index.js'; +import { sendEmail } from '@/services/send-email.js'; +import { genId } from '@/misc/gen-id.js'; +import { validateEmailForAccount } from '@/services/validate-email-for-account.js'; export default async (ctx: Koa.Context) => { const body = ctx.request.body; @@ -38,7 +38,7 @@ export default async (ctx: Koa.Context) => { const emailAddress = body['emailAddress']; if (instance.emailRequiredForSignup) { - if (emailAddress == null || typeof emailAddress != 'string') { + if (emailAddress == null || typeof emailAddress !== 'string') { ctx.status = 400; return; } @@ -51,7 +51,7 @@ export default async (ctx: Koa.Context) => { } if (instance.disableRegistration) { - if (invitationCode == null || typeof invitationCode != 'string') { + if (invitationCode == null || typeof invitationCode !== 'string') { ctx.status = 400; return; } diff --git a/packages/backend/src/server/api/service/discord.ts b/packages/backend/src/server/api/service/discord.ts index dd731c422..089f7de0c 100644 --- a/packages/backend/src/server/api/service/discord.ts +++ b/packages/backend/src/server/api/service/discord.ts @@ -1,15 +1,15 @@ -import * as Koa from 'koa'; -import * as Router from '@koa/router'; -import { getJson } from '@/misc/fetch'; +import Koa from 'koa'; +import Router from '@koa/router'; +import { getJson } from '@/misc/fetch.js'; import { OAuth2 } from 'oauth'; -import config from '@/config/index'; -import { publishMainStream } from '@/services/stream'; -import { redisClient } from '../../../db/redis'; +import config from '@/config/index.js'; +import { publishMainStream } from '@/services/stream.js'; +import { redisClient } from '../../../db/redis.js'; import { v4 as uuid } from 'uuid'; -import signin from '../common/signin'; -import { fetchMeta } from '@/misc/fetch-meta'; -import { Users, UserProfiles } from '@/models/index'; -import { ILocalUser } from '@/models/entities/user'; +import signin from '../common/signin.js'; +import { fetchMeta } from '@/misc/fetch-meta.js'; +import { Users, UserProfiles } from '@/models/index.js'; +import { ILocalUser } from '@/models/entities/user.js'; function getUserToken(ctx: Koa.BaseContext): string | null { return ((ctx.headers['cookie'] || '').match(/igi=(\w+)/) || [null, null])[1]; diff --git a/packages/backend/src/server/api/service/github.ts b/packages/backend/src/server/api/service/github.ts index b23219986..ce032db18 100644 --- a/packages/backend/src/server/api/service/github.ts +++ b/packages/backend/src/server/api/service/github.ts @@ -1,15 +1,15 @@ -import * as Koa from 'koa'; -import * as Router from '@koa/router'; -import { getJson } from '@/misc/fetch'; +import Koa from 'koa'; +import Router from '@koa/router'; +import { getJson } from '@/misc/fetch.js'; import { OAuth2 } from 'oauth'; -import config from '@/config/index'; -import { publishMainStream } from '@/services/stream'; -import { redisClient } from '../../../db/redis'; +import config from '@/config/index.js'; +import { publishMainStream } from '@/services/stream.js'; +import { redisClient } from '../../../db/redis.js'; import { v4 as uuid } from 'uuid'; -import signin from '../common/signin'; -import { fetchMeta } from '@/misc/fetch-meta'; -import { Users, UserProfiles } from '@/models/index'; -import { ILocalUser } from '@/models/entities/user'; +import signin from '../common/signin.js'; +import { fetchMeta } from '@/misc/fetch-meta.js'; +import { Users, UserProfiles } from '@/models/index.js'; +import { ILocalUser } from '@/models/entities/user.js'; function getUserToken(ctx: Koa.BaseContext): string | null { return ((ctx.headers['cookie'] || '').match(/igi=(\w+)/) || [null, null])[1]; diff --git a/packages/backend/src/server/api/service/twitter.ts b/packages/backend/src/server/api/service/twitter.ts index bca00b792..e6e4398fa 100644 --- a/packages/backend/src/server/api/service/twitter.ts +++ b/packages/backend/src/server/api/service/twitter.ts @@ -1,14 +1,14 @@ -import * as Koa from 'koa'; -import * as Router from '@koa/router'; +import Koa from 'koa'; +import Router from '@koa/router'; import { v4 as uuid } from 'uuid'; import autwh from 'autwh'; -import { redisClient } from '../../../db/redis'; -import { publishMainStream } from '@/services/stream'; -import config from '@/config/index'; -import signin from '../common/signin'; -import { fetchMeta } from '@/misc/fetch-meta'; -import { Users, UserProfiles } from '@/models/index'; -import { ILocalUser } from '@/models/entities/user'; +import { redisClient } from '../../../db/redis.js'; +import { publishMainStream } from '@/services/stream.js'; +import config from '@/config/index.js'; +import signin from '../common/signin.js'; +import { fetchMeta } from '@/misc/fetch-meta.js'; +import { Users, UserProfiles } from '@/models/index.js'; +import { ILocalUser } from '@/models/entities/user.js'; function getUserToken(ctx: Koa.BaseContext): string | null { return ((ctx.headers['cookie'] || '').match(/igi=(\w+)/) || [null, null])[1]; diff --git a/packages/backend/src/server/api/stream/channel.ts b/packages/backend/src/server/api/stream/channel.ts index 98337bb31..d2cc5122d 100644 --- a/packages/backend/src/server/api/stream/channel.ts +++ b/packages/backend/src/server/api/stream/channel.ts @@ -1,4 +1,3 @@ -import autobind from 'autobind-decorator'; import Connection from '.'; /** @@ -44,7 +43,6 @@ export default abstract class Channel { this.connection = connection; } - @autobind public send(typeOrPayload: any, payload?: any) { const type = payload === undefined ? typeOrPayload.type : typeOrPayload; const body = payload === undefined ? typeOrPayload.body : payload; diff --git a/packages/backend/src/server/api/stream/channels/admin.ts b/packages/backend/src/server/api/stream/channels/admin.ts index 1ff932d1d..945182ea1 100644 --- a/packages/backend/src/server/api/stream/channels/admin.ts +++ b/packages/backend/src/server/api/stream/channels/admin.ts @@ -1,12 +1,10 @@ -import autobind from 'autobind-decorator'; -import Channel from '../channel'; +import Channel from '../channel.js'; export default class extends Channel { public readonly chName = 'admin'; public static shouldShare = true; public static requireCredential = true; - @autobind public async init(params: any) { // Subscribe admin stream this.subscriber.on(`adminStream:${this.user!.id}`, data => { diff --git a/packages/backend/src/server/api/stream/channels/antenna.ts b/packages/backend/src/server/api/stream/channels/antenna.ts index 3cbdfebb4..afd14946e 100644 --- a/packages/backend/src/server/api/stream/channels/antenna.ts +++ b/packages/backend/src/server/api/stream/channels/antenna.ts @@ -1,9 +1,8 @@ -import autobind from 'autobind-decorator'; -import Channel from '../channel'; -import { Notes } from '@/models/index'; -import { isMutedUserRelated } from '@/misc/is-muted-user-related'; -import { isBlockerUserRelated } from '@/misc/is-blocker-user-related'; -import { StreamMessages } from '../types'; +import Channel from '../channel.js'; +import { Notes } from '@/models/index.js'; +import { isMutedUserRelated } from '@/misc/is-muted-user-related.js'; +import { isBlockerUserRelated } from '@/misc/is-blocker-user-related.js'; +import { StreamMessages } from '../types.js'; export default class extends Channel { public readonly chName = 'antenna'; @@ -11,7 +10,11 @@ export default class extends Channel { public static requireCredential = false; private antennaId: string; - @autobind + constructor(id: string, connection: Channel['connection']) { + super(id, connection); + this.onEvent = this.onEvent.bind(this); + } + public async init(params: any) { this.antennaId = params.antennaId as string; @@ -19,7 +22,6 @@ export default class extends Channel { this.subscriber.on(`antennaStream:${this.antennaId}`, this.onEvent); } - @autobind private async onEvent(data: StreamMessages['antenna']['payload']) { if (data.type === 'note') { const note = await Notes.pack(data.body.id, this.user, { detail: true }); @@ -37,7 +39,6 @@ export default class extends Channel { } } - @autobind public dispose() { // Unsubscribe events this.subscriber.off(`antennaStream:${this.antennaId}`, this.onEvent); diff --git a/packages/backend/src/server/api/stream/channels/channel.ts b/packages/backend/src/server/api/stream/channels/channel.ts index 1e51a81c4..16ad80939 100644 --- a/packages/backend/src/server/api/stream/channels/channel.ts +++ b/packages/backend/src/server/api/stream/channels/channel.ts @@ -1,11 +1,10 @@ -import autobind from 'autobind-decorator'; -import Channel from '../channel'; -import { Notes, Users } from '@/models/index'; -import { isMutedUserRelated } from '@/misc/is-muted-user-related'; -import { isBlockerUserRelated } from '@/misc/is-blocker-user-related'; -import { User } from '@/models/entities/user'; -import { StreamMessages } from '../types'; -import { Packed } from '@/misc/schema'; +import Channel from '../channel.js'; +import { Notes, Users } from '@/models/index.js'; +import { isMutedUserRelated } from '@/misc/is-muted-user-related.js'; +import { isBlockerUserRelated } from '@/misc/is-blocker-user-related.js'; +import { User } from '@/models/entities/user.js'; +import { StreamMessages } from '../types.js'; +import { Packed } from '@/misc/schema.js'; export default class extends Channel { public readonly chName = 'channel'; @@ -15,7 +14,11 @@ export default class extends Channel { private typers: Record = {}; private emitTypersIntervalId: ReturnType; - @autobind + constructor(id: string, connection: Channel['connection']) { + super(id, connection); + this.onNote = this.onNote.bind(this); + } + public async init(params: any) { this.channelId = params.channelId as string; @@ -25,7 +28,6 @@ export default class extends Channel { this.emitTypersIntervalId = setInterval(this.emitTypers, 5000); } - @autobind private async onNote(note: Packed<'Note'>) { if (note.channelId !== this.channelId) return; @@ -52,7 +54,6 @@ export default class extends Channel { this.send('note', note); } - @autobind private onEvent(data: StreamMessages['channel']['payload']) { if (data.type === 'typing') { const id = data.body; @@ -64,7 +65,6 @@ export default class extends Channel { } } - @autobind private async emitTypers() { const now = new Date(); @@ -81,7 +81,6 @@ export default class extends Channel { }); } - @autobind public dispose() { // Unsubscribe events this.subscriber.off('notesStream', this.onNote); diff --git a/packages/backend/src/server/api/stream/channels/drive.ts b/packages/backend/src/server/api/stream/channels/drive.ts index 4112dd9b0..140255acd 100644 --- a/packages/backend/src/server/api/stream/channels/drive.ts +++ b/packages/backend/src/server/api/stream/channels/drive.ts @@ -1,12 +1,10 @@ -import autobind from 'autobind-decorator'; -import Channel from '../channel'; +import Channel from '../channel.js'; export default class extends Channel { public readonly chName = 'drive'; public static shouldShare = true; public static requireCredential = true; - @autobind public async init(params: any) { // Subscribe drive stream this.subscriber.on(`driveStream:${this.user!.id}`, data => { diff --git a/packages/backend/src/server/api/stream/channels/global-timeline.ts b/packages/backend/src/server/api/stream/channels/global-timeline.ts index ecd87d093..1c7e038ab 100644 --- a/packages/backend/src/server/api/stream/channels/global-timeline.ts +++ b/packages/backend/src/server/api/stream/channels/global-timeline.ts @@ -1,19 +1,22 @@ -import autobind from 'autobind-decorator'; -import { isMutedUserRelated } from '@/misc/is-muted-user-related'; -import Channel from '../channel'; -import { fetchMeta } from '@/misc/fetch-meta'; -import { Notes } from '@/models/index'; -import { checkWordMute } from '@/misc/check-word-mute'; -import { isBlockerUserRelated } from '@/misc/is-blocker-user-related'; -import { isInstanceMuted } from '@/misc/is-instance-muted'; -import { Packed } from '@/misc/schema'; +import { isMutedUserRelated } from '@/misc/is-muted-user-related.js'; +import Channel from '../channel.js'; +import { fetchMeta } from '@/misc/fetch-meta.js'; +import { Notes } from '@/models/index.js'; +import { checkWordMute } from '@/misc/check-word-mute.js'; +import { isBlockerUserRelated } from '@/misc/is-blocker-user-related.js'; +import { isInstanceMuted } from '@/misc/is-instance-muted.js'; +import { Packed } from '@/misc/schema.js'; export default class extends Channel { public readonly chName = 'globalTimeline'; public static shouldShare = true; public static requireCredential = false; - @autobind + constructor(id: string, connection: Channel['connection']) { + super(id, connection); + this.onNote = this.onNote.bind(this); + } + public async init(params: any) { const meta = await fetchMeta(); if (meta.disableGlobalTimeline) { @@ -24,7 +27,6 @@ export default class extends Channel { this.subscriber.on('notesStream', this.onNote); } - @autobind private async onNote(note: Packed<'Note'>) { if (note.visibility !== 'public') return; if (note.channelId != null) return; @@ -69,7 +71,6 @@ export default class extends Channel { this.send('note', note); } - @autobind public dispose() { // Unsubscribe events this.subscriber.off('notesStream', this.onNote); diff --git a/packages/backend/src/server/api/stream/channels/hashtag.ts b/packages/backend/src/server/api/stream/channels/hashtag.ts index 820095dfc..1b7a58022 100644 --- a/packages/backend/src/server/api/stream/channels/hashtag.ts +++ b/packages/backend/src/server/api/stream/channels/hashtag.ts @@ -1,10 +1,9 @@ -import autobind from 'autobind-decorator'; -import { isMutedUserRelated } from '@/misc/is-muted-user-related'; -import Channel from '../channel'; -import { Notes } from '@/models/index'; -import { normalizeForSearch } from '@/misc/normalize-for-search'; -import { isBlockerUserRelated } from '@/misc/is-blocker-user-related'; -import { Packed } from '@/misc/schema'; +import { isMutedUserRelated } from '@/misc/is-muted-user-related.js'; +import Channel from '../channel.js'; +import { Notes } from '@/models/index.js'; +import { normalizeForSearch } from '@/misc/normalize-for-search.js'; +import { isBlockerUserRelated } from '@/misc/is-blocker-user-related.js'; +import { Packed } from '@/misc/schema.js'; export default class extends Channel { public readonly chName = 'hashtag'; @@ -12,7 +11,11 @@ export default class extends Channel { public static requireCredential = false; private q: string[][]; - @autobind + constructor(id: string, connection: Channel['connection']) { + super(id, connection); + this.onNote = this.onNote.bind(this); + } + public async init(params: any) { this.q = params.q; @@ -22,7 +25,6 @@ export default class extends Channel { this.subscriber.on('notesStream', this.onNote); } - @autobind private async onNote(note: Packed<'Note'>) { const noteTags = note.tags ? note.tags.map((t: string) => t.toLowerCase()) : []; const matched = this.q.some(tags => tags.every(tag => noteTags.includes(normalizeForSearch(tag)))); @@ -45,7 +47,6 @@ export default class extends Channel { this.send('note', note); } - @autobind public dispose() { // Unsubscribe events this.subscriber.off('notesStream', this.onNote); diff --git a/packages/backend/src/server/api/stream/channels/home-timeline.ts b/packages/backend/src/server/api/stream/channels/home-timeline.ts index 445db5c38..3a8e55202 100644 --- a/packages/backend/src/server/api/stream/channels/home-timeline.ts +++ b/packages/backend/src/server/api/stream/channels/home-timeline.ts @@ -1,24 +1,26 @@ -import autobind from 'autobind-decorator'; -import { isMutedUserRelated } from '@/misc/is-muted-user-related'; -import Channel from '../channel'; -import { Notes } from '@/models/index'; -import { checkWordMute } from '@/misc/check-word-mute'; -import { isBlockerUserRelated } from '@/misc/is-blocker-user-related'; -import { isInstanceMuted } from '@/misc/is-instance-muted'; -import { Packed } from '@/misc/schema'; +import { isMutedUserRelated } from '@/misc/is-muted-user-related.js'; +import Channel from '../channel.js'; +import { Notes } from '@/models/index.js'; +import { checkWordMute } from '@/misc/check-word-mute.js'; +import { isBlockerUserRelated } from '@/misc/is-blocker-user-related.js'; +import { isInstanceMuted } from '@/misc/is-instance-muted.js'; +import { Packed } from '@/misc/schema.js'; export default class extends Channel { public readonly chName = 'homeTimeline'; public static shouldShare = true; public static requireCredential = true; - @autobind + constructor(id: string, connection: Channel['connection']) { + super(id, connection); + this.onNote = this.onNote.bind(this); + } + public async init(params: any) { // Subscribe events this.subscriber.on('notesStream', this.onNote); } - @autobind private async onNote(note: Packed<'Note'>) { if (note.channelId) { if (!this.followingChannels.has(note.channelId)) return; @@ -77,7 +79,6 @@ export default class extends Channel { this.send('note', note); } - @autobind public dispose() { // Unsubscribe events this.subscriber.off('notesStream', this.onNote); diff --git a/packages/backend/src/server/api/stream/channels/hybrid-timeline.ts b/packages/backend/src/server/api/stream/channels/hybrid-timeline.ts index c0be71fe2..f3ceeffa1 100644 --- a/packages/backend/src/server/api/stream/channels/hybrid-timeline.ts +++ b/packages/backend/src/server/api/stream/channels/hybrid-timeline.ts @@ -1,19 +1,22 @@ -import autobind from 'autobind-decorator'; -import { isMutedUserRelated } from '@/misc/is-muted-user-related'; -import Channel from '../channel'; -import { fetchMeta } from '@/misc/fetch-meta'; -import { Notes } from '@/models/index'; -import { checkWordMute } from '@/misc/check-word-mute'; -import { isBlockerUserRelated } from '@/misc/is-blocker-user-related'; -import { isInstanceMuted } from '@/misc/is-instance-muted'; -import { Packed } from '@/misc/schema'; +import { isMutedUserRelated } from '@/misc/is-muted-user-related.js'; +import Channel from '../channel.js'; +import { fetchMeta } from '@/misc/fetch-meta.js'; +import { Notes } from '@/models/index.js'; +import { checkWordMute } from '@/misc/check-word-mute.js'; +import { isBlockerUserRelated } from '@/misc/is-blocker-user-related.js'; +import { isInstanceMuted } from '@/misc/is-instance-muted.js'; +import { Packed } from '@/misc/schema.js'; export default class extends Channel { public readonly chName = 'hybridTimeline'; public static shouldShare = true; public static requireCredential = true; - @autobind + constructor(id: string, connection: Channel['connection']) { + super(id, connection); + this.onNote = this.onNote.bind(this); + } + public async init(params: any) { const meta = await fetchMeta(); if (meta.disableLocalTimeline && !this.user!.isAdmin && !this.user!.isModerator) return; @@ -22,7 +25,6 @@ export default class extends Channel { this.subscriber.on('notesStream', this.onNote); } - @autobind private async onNote(note: Packed<'Note'>) { // チャンネルの投稿ではなく、自分自身の投稿 または // チャンネルの投稿ではなく、その投稿のユーザーをフォローしている または @@ -85,7 +87,6 @@ export default class extends Channel { this.send('note', note); } - @autobind public dispose() { // Unsubscribe events this.subscriber.off('notesStream', this.onNote); diff --git a/packages/backend/src/server/api/stream/channels/index.ts b/packages/backend/src/server/api/stream/channels/index.ts index f3826c4cf..d422edde8 100644 --- a/packages/backend/src/server/api/stream/channels/index.ts +++ b/packages/backend/src/server/api/stream/channels/index.ts @@ -1,18 +1,18 @@ -import main from './main'; -import homeTimeline from './home-timeline'; -import localTimeline from './local-timeline'; -import hybridTimeline from './hybrid-timeline'; -import globalTimeline from './global-timeline'; -import serverStats from './server-stats'; -import queueStats from './queue-stats'; -import userList from './user-list'; -import antenna from './antenna'; -import messaging from './messaging'; -import messagingIndex from './messaging-index'; -import drive from './drive'; -import hashtag from './hashtag'; -import channel from './channel'; -import admin from './admin'; +import main from './main.js'; +import homeTimeline from './home-timeline.js'; +import localTimeline from './local-timeline.js'; +import hybridTimeline from './hybrid-timeline.js'; +import globalTimeline from './global-timeline.js'; +import serverStats from './server-stats.js'; +import queueStats from './queue-stats.js'; +import userList from './user-list.js'; +import antenna from './antenna.js'; +import messaging from './messaging.js'; +import messagingIndex from './messaging-index.js'; +import drive from './drive.js'; +import hashtag from './hashtag.js'; +import channel from './channel.js'; +import admin from './admin.js'; export default { main, diff --git a/packages/backend/src/server/api/stream/channels/local-timeline.ts b/packages/backend/src/server/api/stream/channels/local-timeline.ts index ae8f62ba6..4e198482a 100644 --- a/packages/backend/src/server/api/stream/channels/local-timeline.ts +++ b/packages/backend/src/server/api/stream/channels/local-timeline.ts @@ -1,18 +1,21 @@ -import autobind from 'autobind-decorator'; -import { isMutedUserRelated } from '@/misc/is-muted-user-related'; -import Channel from '../channel'; -import { fetchMeta } from '@/misc/fetch-meta'; -import { Notes } from '@/models/index'; -import { checkWordMute } from '@/misc/check-word-mute'; -import { isBlockerUserRelated } from '@/misc/is-blocker-user-related'; -import { Packed } from '@/misc/schema'; +import { isMutedUserRelated } from '@/misc/is-muted-user-related.js'; +import Channel from '../channel.js'; +import { fetchMeta } from '@/misc/fetch-meta.js'; +import { Notes } from '@/models/index.js'; +import { checkWordMute } from '@/misc/check-word-mute.js'; +import { isBlockerUserRelated } from '@/misc/is-blocker-user-related.js'; +import { Packed } from '@/misc/schema.js'; export default class extends Channel { public readonly chName = 'localTimeline'; public static shouldShare = true; public static requireCredential = false; - @autobind + constructor(id: string, connection: Channel['connection']) { + super(id, connection); + this.onNote = this.onNote.bind(this); + } + public async init(params: any) { const meta = await fetchMeta(); if (meta.disableLocalTimeline) { @@ -23,7 +26,6 @@ export default class extends Channel { this.subscriber.on('notesStream', this.onNote); } - @autobind private async onNote(note: Packed<'Note'>) { if (note.user.host !== null) return; if (note.visibility !== 'public') return; @@ -66,7 +68,6 @@ export default class extends Channel { this.send('note', note); } - @autobind public dispose() { // Unsubscribe events this.subscriber.off('notesStream', this.onNote); diff --git a/packages/backend/src/server/api/stream/channels/main.ts b/packages/backend/src/server/api/stream/channels/main.ts index b41eae7c7..9cfea0bfc 100644 --- a/packages/backend/src/server/api/stream/channels/main.ts +++ b/packages/backend/src/server/api/stream/channels/main.ts @@ -1,14 +1,12 @@ -import autobind from 'autobind-decorator'; -import Channel from '../channel'; -import { Notes } from '@/models/index'; -import { isInstanceMuted, isUserFromMutedInstance } from '@/misc/is-instance-muted'; +import Channel from '../channel.js'; +import { Notes } from '@/models/index.js'; +import { isInstanceMuted, isUserFromMutedInstance } from '@/misc/is-instance-muted.js'; export default class extends Channel { public readonly chName = 'main'; public static shouldShare = true; public static requireCredential = true; - @autobind public async init(params: any) { // Subscribe main stream channel this.subscriber.on(`mainStream:${this.user!.id}`, async data => { diff --git a/packages/backend/src/server/api/stream/channels/messaging-index.ts b/packages/backend/src/server/api/stream/channels/messaging-index.ts index 0c495398a..b930785d2 100644 --- a/packages/backend/src/server/api/stream/channels/messaging-index.ts +++ b/packages/backend/src/server/api/stream/channels/messaging-index.ts @@ -1,12 +1,10 @@ -import autobind from 'autobind-decorator'; -import Channel from '../channel'; +import Channel from '../channel.js'; export default class extends Channel { public readonly chName = 'messagingIndex'; public static shouldShare = true; public static requireCredential = true; - @autobind public async init(params: any) { // Subscribe messaging index stream this.subscriber.on(`messagingIndexStream:${this.user!.id}`, data => { diff --git a/packages/backend/src/server/api/stream/channels/messaging.ts b/packages/backend/src/server/api/stream/channels/messaging.ts index d8fccf076..94bbdeca5 100644 --- a/packages/backend/src/server/api/stream/channels/messaging.ts +++ b/packages/backend/src/server/api/stream/channels/messaging.ts @@ -1,10 +1,9 @@ -import autobind from 'autobind-decorator'; -import { readUserMessagingMessage, readGroupMessagingMessage, deliverReadActivity } from '../../common/read-messaging-message'; -import Channel from '../channel'; -import { UserGroupJoinings, Users, MessagingMessages } from '@/models/index'; -import { User, ILocalUser, IRemoteUser } from '@/models/entities/user'; -import { UserGroup } from '@/models/entities/user-group'; -import { StreamMessages } from '../types'; +import { readUserMessagingMessage, readGroupMessagingMessage, deliverReadActivity } from '../../common/read-messaging-message.js'; +import Channel from '../channel.js'; +import { UserGroupJoinings, Users, MessagingMessages } from '@/models/index.js'; +import { User, ILocalUser, IRemoteUser } from '@/models/entities/user.js'; +import { UserGroup } from '@/models/entities/user-group.js'; +import { StreamMessages } from '../types.js'; export default class extends Channel { public readonly chName = 'messaging'; @@ -18,7 +17,13 @@ export default class extends Channel { private typers: Record = {}; private emitTypersIntervalId: ReturnType; - @autobind + constructor(id: string, connection: Channel['connection']) { + super(id, connection); + this.onEvent = this.onEvent.bind(this); + this.onMessage = this.onMessage.bind(this); + this.emitTypers = this.emitTypers.bind(this); + } + public async init(params: any) { this.otherpartyId = params.otherparty; this.otherparty = this.otherpartyId ? await Users.findOneOrFail({ id: this.otherpartyId }) : null; @@ -46,7 +51,6 @@ export default class extends Channel { this.subscriber.on(this.subCh, this.onEvent); } - @autobind private onEvent(data: StreamMessages['messaging']['payload'] | StreamMessages['groupMessaging']['payload']) { if (data.type === 'typing') { const id = data.body; @@ -60,7 +64,6 @@ export default class extends Channel { } } - @autobind public onMessage(type: string, body: any) { switch (type) { case 'read': @@ -80,7 +83,6 @@ export default class extends Channel { } } - @autobind private async emitTypers() { const now = new Date(); @@ -97,7 +99,6 @@ export default class extends Channel { }); } - @autobind public dispose() { this.subscriber.off(this.subCh, this.onEvent); diff --git a/packages/backend/src/server/api/stream/channels/queue-stats.ts b/packages/backend/src/server/api/stream/channels/queue-stats.ts index be18438fa..043d03ab8 100644 --- a/packages/backend/src/server/api/stream/channels/queue-stats.ts +++ b/packages/backend/src/server/api/stream/channels/queue-stats.ts @@ -1,25 +1,27 @@ -import autobind from 'autobind-decorator'; -import Xev from 'xev'; -import Channel from '../channel'; +import { default as Xev } from 'xev'; +import Channel from '../channel.js'; -const ev = new Xev(); +const ev = new Xev.default(); export default class extends Channel { public readonly chName = 'queueStats'; public static shouldShare = true; public static requireCredential = false; - @autobind + constructor(id: string, connection: Channel['connection']) { + super(id, connection); + this.onStats = this.onStats.bind(this); + this.onMessage = this.onMessage.bind(this); + } + public async init(params: any) { ev.addListener('queueStats', this.onStats); } - @autobind private onStats(stats: any) { this.send('stats', stats); } - @autobind public onMessage(type: string, body: any) { switch (type) { case 'requestLog': @@ -34,7 +36,6 @@ export default class extends Channel { } } - @autobind public dispose() { ev.removeListener('queueStats', this.onStats); } diff --git a/packages/backend/src/server/api/stream/channels/server-stats.ts b/packages/backend/src/server/api/stream/channels/server-stats.ts index df89b4c75..0da189576 100644 --- a/packages/backend/src/server/api/stream/channels/server-stats.ts +++ b/packages/backend/src/server/api/stream/channels/server-stats.ts @@ -1,25 +1,27 @@ -import autobind from 'autobind-decorator'; -import Xev from 'xev'; -import Channel from '../channel'; +import { default as Xev } from 'xev'; +import Channel from '../channel.js'; -const ev = new Xev(); +const ev = new Xev.default(); export default class extends Channel { public readonly chName = 'serverStats'; public static shouldShare = true; public static requireCredential = false; - @autobind + constructor(id: string, connection: Channel['connection']) { + super(id, connection); + this.onStats = this.onStats.bind(this); + this.onMessage = this.onMessage.bind(this); + } + public async init(params: any) { ev.addListener('serverStats', this.onStats); } - @autobind private onStats(stats: any) { this.send('stats', stats); } - @autobind public onMessage(type: string, body: any) { switch (type) { case 'requestLog': @@ -34,7 +36,6 @@ export default class extends Channel { } } - @autobind public dispose() { ev.removeListener('serverStats', this.onStats); } diff --git a/packages/backend/src/server/api/stream/channels/user-list.ts b/packages/backend/src/server/api/stream/channels/user-list.ts index b75920a18..57523c848 100644 --- a/packages/backend/src/server/api/stream/channels/user-list.ts +++ b/packages/backend/src/server/api/stream/channels/user-list.ts @@ -1,10 +1,9 @@ -import autobind from 'autobind-decorator'; -import Channel from '../channel'; -import { Notes, UserListJoinings, UserLists } from '@/models/index'; -import { isMutedUserRelated } from '@/misc/is-muted-user-related'; -import { User } from '@/models/entities/user'; -import { isBlockerUserRelated } from '@/misc/is-blocker-user-related'; -import { Packed } from '@/misc/schema'; +import Channel from '../channel.js'; +import { Notes, UserListJoinings, UserLists } from '@/models/index.js'; +import { isMutedUserRelated } from '@/misc/is-muted-user-related.js'; +import { User } from '@/models/entities/user.js'; +import { isBlockerUserRelated } from '@/misc/is-blocker-user-related.js'; +import { Packed } from '@/misc/schema.js'; export default class extends Channel { public readonly chName = 'userList'; @@ -14,7 +13,12 @@ export default class extends Channel { public listUsers: User['id'][] = []; private listUsersClock: NodeJS.Timer; - @autobind + constructor(id: string, connection: Channel['connection']) { + super(id, connection); + this.updateListUsers = this.updateListUsers.bind(this); + this.onNote = this.onNote.bind(this); + } + public async init(params: any) { this.listId = params.listId as string; @@ -34,7 +38,6 @@ export default class extends Channel { this.listUsersClock = setInterval(this.updateListUsers, 5000); } - @autobind private async updateListUsers() { const users = await UserListJoinings.find({ where: { @@ -46,7 +49,6 @@ export default class extends Channel { this.listUsers = users.map(x => x.userId); } - @autobind private async onNote(note: Packed<'Note'>) { if (!this.listUsers.includes(note.userId)) return; @@ -81,7 +83,6 @@ export default class extends Channel { this.send('note', note); } - @autobind public dispose() { // Unsubscribe events this.subscriber.off(`userListStream:${this.listId}`, this.send); diff --git a/packages/backend/src/server/api/stream/index.ts b/packages/backend/src/server/api/stream/index.ts index 84689bca1..0cb38e2a9 100644 --- a/packages/backend/src/server/api/stream/index.ts +++ b/packages/backend/src/server/api/stream/index.ts @@ -1,21 +1,20 @@ -import autobind from 'autobind-decorator'; import * as websocket from 'websocket'; -import { readNotification } from '../common/read-notification'; -import call from '../call'; -import readNote from '@/services/note/read'; -import Channel from './channel'; -import channels from './channels/index'; +import { readNotification } from '../common/read-notification.js'; +import call from '../call.js'; +import readNote from '@/services/note/read.js'; +import Channel from './channel.js'; +import channels from './channels/index.js'; import { EventEmitter } from 'events'; -import { User } from '@/models/entities/user'; -import { Channel as ChannelModel } from '@/models/entities/channel'; -import { Users, Followings, Mutings, UserProfiles, ChannelFollowings, Blockings } from '@/models/index'; -import { ApiError } from '../error'; -import { AccessToken } from '@/models/entities/access-token'; -import { UserProfile } from '@/models/entities/user-profile'; -import { publishChannelStream, publishGroupMessagingStream, publishMessagingStream } from '@/services/stream'; -import { UserGroup } from '@/models/entities/user-group'; -import { StreamEventEmitter, StreamMessages } from './types'; -import { Packed } from '@/misc/schema'; +import { User } from '@/models/entities/user.js'; +import { Channel as ChannelModel } from '@/models/entities/channel.js'; +import { Users, Followings, Mutings, UserProfiles, ChannelFollowings, Blockings } from '@/models/index.js'; +import { ApiError } from '../error.js'; +import { AccessToken } from '@/models/entities/access-token.js'; +import { UserProfile } from '@/models/entities/user-profile.js'; +import { publishChannelStream, publishGroupMessagingStream, publishMessagingStream } from '@/services/stream.js'; +import { UserGroup } from '@/models/entities/user-group.js'; +import { StreamEventEmitter, StreamMessages } from './types.js'; +import { Packed } from '@/misc/schema.js'; /** * Main stream connection @@ -38,13 +37,18 @@ export default class Connection { wsConnection: websocket.connection, subscriber: EventEmitter, user: User | null | undefined, - token: AccessToken | null | undefined + token: AccessToken | null | undefined, ) { this.wsConnection = wsConnection; this.subscriber = subscriber; if (user) this.user = user; if (token) this.token = token; + this.onWsConnectionMessage = this.onWsConnectionMessage.bind(this); + this.onUserEvent = this.onUserEvent.bind(this); + this.onNoteStreamMessage = this.onNoteStreamMessage.bind(this); + this.onBroadcastMessage = this.onBroadcastMessage.bind(this); + this.wsConnection.on('message', this.onWsConnectionMessage); this.subscriber.on('broadcast', data => { @@ -62,7 +66,6 @@ export default class Connection { } } - @autobind private onUserEvent(data: StreamMessages['user']['payload']) { // { type, body }と展開するとそれぞれ型が分離してしまう switch (data.type) { case 'follow': @@ -108,8 +111,8 @@ export default class Connection { /** * クライアントからメッセージ受信時 */ - @autobind - private async onWsConnectionMessage(data: websocket.IMessage) { + private async onWsConnectionMessage(data: websocket.Message) { + if (data.type !== 'utf8') return; if (data.utf8Data == null) return; let obj: Record; @@ -143,12 +146,10 @@ export default class Connection { } } - @autobind private onBroadcastMessage(data: StreamMessages['broadcast']['payload']) { this.sendMessageToWs(data.type, data.body); } - @autobind public cacheNote(note: Packed<'Note'>) { const add = (note: Packed<'Note'>) => { const existIndex = this.cachedNotes.findIndex(n => n.id === note.id); @@ -168,7 +169,6 @@ export default class Connection { if (note.renote) add(note.renote); } - @autobind private readNote(body: any) { const id = body.id; @@ -186,7 +186,6 @@ export default class Connection { /** * APIリクエスト要求時 */ - @autobind private async onApiRequest(payload: any) { // 新鮮なデータを利用するためにユーザーをフェッチ const user = this.user ? await Users.findOne(this.user.id) : null; @@ -209,7 +208,6 @@ export default class Connection { }); } - @autobind private onReadNotification(payload: any) { if (!payload.id) return; readNotification(this.user!.id, [payload.id]); @@ -218,7 +216,6 @@ export default class Connection { /** * 投稿購読要求時 */ - @autobind private onSubscribeNote(payload: any) { if (!payload.id) return; @@ -236,7 +233,6 @@ export default class Connection { /** * 投稿購読解除要求時 */ - @autobind private onUnsubscribeNote(payload: any) { if (!payload.id) return; @@ -247,7 +243,6 @@ export default class Connection { } } - @autobind private async onNoteStreamMessage(data: StreamMessages['note']['payload']) { this.sendMessageToWs('noteUpdated', { id: data.body.id, @@ -259,7 +254,6 @@ export default class Connection { /** * チャンネル接続要求時 */ - @autobind private onChannelConnectRequested(payload: any) { const { channel, id, params, pong } = payload; this.connectChannel(id, params, channel, pong); @@ -268,7 +262,6 @@ export default class Connection { /** * チャンネル切断要求時 */ - @autobind private onChannelDisconnectRequested(payload: any) { const { id } = payload; this.disconnectChannel(id); @@ -277,7 +270,6 @@ export default class Connection { /** * クライアントにメッセージ送信 */ - @autobind public sendMessageToWs(type: string, payload: any) { this.wsConnection.send(JSON.stringify({ type: type, @@ -288,7 +280,6 @@ export default class Connection { /** * チャンネルに接続 */ - @autobind public connectChannel(id: string, params: any, channel: string, pong = false) { if ((channels as any)[channel].requireCredential && this.user == null) { return; @@ -314,7 +305,6 @@ export default class Connection { * チャンネルから切断 * @param id チャンネルコネクションID */ - @autobind public disconnectChannel(id: string) { const channel = this.channels.find(c => c.id === id); @@ -328,7 +318,6 @@ export default class Connection { * チャンネルへメッセージ送信要求時 * @param data メッセージ */ - @autobind private onChannelMessageRequested(data: any) { const channel = this.channels.find(c => c.id === data.id); if (channel != null && channel.onMessage != null) { @@ -336,14 +325,12 @@ export default class Connection { } } - @autobind private typingOnChannel(channel: ChannelModel['id']) { if (this.user) { publishChannelStream(channel, 'typing', this.user.id); } } - @autobind private typingOnMessaging(param: { partner?: User['id']; group?: UserGroup['id']; }) { if (this.user) { if (param.partner) { @@ -354,7 +341,6 @@ export default class Connection { } } - @autobind private async updateFollowing() { const followings = await Followings.find({ where: { @@ -366,7 +352,6 @@ export default class Connection { this.following = new Set(followings.map(x => x.followeeId)); } - @autobind private async updateMuting() { const mutings = await Mutings.find({ where: { @@ -378,7 +363,6 @@ export default class Connection { this.muting = new Set(mutings.map(x => x.muteeId)); } - @autobind private async updateBlocking() { // ここでいうBlockingは被Blockingの意 const blockings = await Blockings.find({ where: { @@ -390,7 +374,6 @@ export default class Connection { this.blocking = new Set(blockings.map(x => x.blockerId)); } - @autobind private async updateFollowingChannels() { const followings = await ChannelFollowings.find({ where: { @@ -402,7 +385,6 @@ export default class Connection { this.followingChannels = new Set(followings.map(x => x.followeeId)); } - @autobind private async updateUserProfile() { this.userProfile = await UserProfiles.findOne({ userId: this.user!.id, @@ -412,7 +394,6 @@ export default class Connection { /** * ストリームが切れたとき */ - @autobind public dispose() { for (const c of this.channels.filter(c => c.dispose)) { if (c.dispose) c.dispose(); diff --git a/packages/backend/src/server/api/stream/types.ts b/packages/backend/src/server/api/stream/types.ts index e2f1c6fc9..90cf59038 100644 --- a/packages/backend/src/server/api/stream/types.ts +++ b/packages/backend/src/server/api/stream/types.ts @@ -1,20 +1,20 @@ import { EventEmitter } from 'events'; import Emitter from 'strict-event-emitter-types'; -import { Channel } from '@/models/entities/channel'; -import { User } from '@/models/entities/user'; -import { UserProfile } from '@/models/entities/user-profile'; -import { Note } from '@/models/entities/note'; -import { Antenna } from '@/models/entities/antenna'; -import { DriveFile } from '@/models/entities/drive-file'; -import { DriveFolder } from '@/models/entities/drive-folder'; -import { Emoji } from '@/models/entities/emoji'; -import { UserList } from '@/models/entities/user-list'; -import { MessagingMessage } from '@/models/entities/messaging-message'; -import { UserGroup } from '@/models/entities/user-group'; -import { AbuseUserReport } from '@/models/entities/abuse-user-report'; -import { Signin } from '@/models/entities/signin'; -import { Page } from '@/models/entities/page'; -import { Packed } from '@/misc/schema'; +import { Channel } from '@/models/entities/channel.js'; +import { User } from '@/models/entities/user.js'; +import { UserProfile } from '@/models/entities/user-profile.js'; +import { Note } from '@/models/entities/note.js'; +import { Antenna } from '@/models/entities/antenna.js'; +import { DriveFile } from '@/models/entities/drive-file.js'; +import { DriveFolder } from '@/models/entities/drive-folder.js'; +import { Emoji } from '@/models/entities/emoji.js'; +import { UserList } from '@/models/entities/user-list.js'; +import { MessagingMessage } from '@/models/entities/messaging-message.js'; +import { UserGroup } from '@/models/entities/user-group.js'; +import { AbuseUserReport } from '@/models/entities/abuse-user-report.js'; +import { Signin } from '@/models/entities/signin.js'; +import { Page } from '@/models/entities/page.js'; +import { Packed } from '@/misc/schema.js'; //#region Stream type-body definitions export interface InternalStreamTypes { @@ -84,6 +84,7 @@ export interface MainStreamTypes { }; driveFileCreated: Packed<'DriveFile'>; readAntenna: Antenna; + receiveFollowRequest: Packed<'User'>; } export interface DriveStreamTypes { diff --git a/packages/backend/src/server/api/streaming.ts b/packages/backend/src/server/api/streaming.ts index b706b1b8d..2a34edac6 100644 --- a/packages/backend/src/server/api/streaming.ts +++ b/packages/backend/src/server/api/streaming.ts @@ -1,14 +1,14 @@ import * as http from 'http'; import * as websocket from 'websocket'; -import MainStreamConnection from './stream/index'; +import MainStreamConnection from './stream/index.js'; import { ParsedUrlQuery } from 'querystring'; -import authenticate from './authenticate'; +import authenticate from './authenticate.js'; import { EventEmitter } from 'events'; -import { subsdcriber as redisClient } from '../../db/redis'; -import { Users } from '@/models/index'; +import { subsdcriber as redisClient } from '../../db/redis.js'; +import { Users } from '@/models/index.js'; -module.exports = (server: http.Server) => { +export const initializeStreamingServer = (server: http.Server) => { // Init websocket server const ws = new websocket.server({ httpServer: server, diff --git a/packages/backend/src/server/file/index.ts b/packages/backend/src/server/file/index.ts index 6fe6110dc..07a493700 100644 --- a/packages/backend/src/server/file/index.ts +++ b/packages/backend/src/server/file/index.ts @@ -2,16 +2,15 @@ * File Server */ -import * as fs from 'fs'; -import { fileURLToPath } from 'url'; -import { dirname } from 'path'; -import * as Koa from 'koa'; -import * as cors from '@koa/cors'; -import * as Router from '@koa/router'; -import sendDriveFile from './send-drive-file'; +import * as fs from 'node:fs'; +import { fileURLToPath } from 'node:url'; +import { dirname } from 'node:path'; +import Koa from 'koa'; +import cors from '@koa/cors'; +import Router from '@koa/router'; +import sendDriveFile from './send-drive-file.js'; -//const _filename = fileURLToPath(import.meta.url); -const _filename = __filename; +const _filename = fileURLToPath(import.meta.url); const _dirname = dirname(_filename); // Init app @@ -38,4 +37,4 @@ router.get('/:key/(.*)', sendDriveFile); // Register router app.use(router.routes()); -module.exports = app; +export default app; diff --git a/packages/backend/src/server/file/send-drive-file.ts b/packages/backend/src/server/file/send-drive-file.ts index f3c6c518f..4e2bba0e2 100644 --- a/packages/backend/src/server/file/send-drive-file.ts +++ b/packages/backend/src/server/file/send-drive-file.ts @@ -1,23 +1,22 @@ -import * as fs from 'fs'; -import { fileURLToPath } from 'url'; -import { dirname } from 'path'; -import * as Koa from 'koa'; +import * as fs from 'node:fs'; +import { fileURLToPath } from 'node:url'; +import { dirname } from 'node:path'; +import Koa from 'koa'; import * as send from 'koa-send'; -import * as rename from 'rename'; +import rename from 'rename'; import * as tmp from 'tmp'; -import { serverLogger } from '../index'; -import { contentDisposition } from '@/misc/content-disposition'; -import { DriveFiles } from '@/models/index'; -import { InternalStorage } from '@/services/drive/internal-storage'; -import { downloadUrl } from '@/misc/download-url'; -import { detectType } from '@/misc/get-file-info'; -import { convertToJpeg, convertToPng, convertToPngOrJpeg } from '@/services/drive/image-processor'; -import { GenerateVideoThumbnail } from '@/services/drive/generate-video-thumbnail'; -import { StatusError } from '@/misc/fetch'; -import { FILE_TYPE_BROWSERSAFE } from '@/const'; +import { serverLogger } from '../index.js'; +import { contentDisposition } from '@/misc/content-disposition.js'; +import { DriveFiles } from '@/models/index.js'; +import { InternalStorage } from '@/services/drive/internal-storage.js'; +import { downloadUrl } from '@/misc/download-url.js'; +import { detectType } from '@/misc/get-file-info.js'; +import { convertToJpeg, convertToPng, convertToPngOrJpeg } from '@/services/drive/image-processor.js'; +import { GenerateVideoThumbnail } from '@/services/drive/generate-video-thumbnail.js'; +import { StatusError } from '@/misc/fetch.js'; +import { FILE_TYPE_BROWSERSAFE } from '@/const.js'; -//const _filename = fileURLToPath(import.meta.url); -const _filename = __filename; +const _filename = fileURLToPath(import.meta.url); const _dirname = dirname(_filename); const assets = `${_dirname}/../../server/file/assets/`; diff --git a/packages/backend/src/server/index.ts b/packages/backend/src/server/index.ts index 4d6b402e6..95a9ec6a0 100644 --- a/packages/backend/src/server/index.ts +++ b/packages/backend/src/server/index.ts @@ -2,28 +2,30 @@ * Core Server */ -import * as fs from 'fs'; +import * as fs from 'node:fs'; import * as http from 'http'; -import * as http2 from 'http2'; -import * as https from 'https'; -import * as Koa from 'koa'; -import * as Router from '@koa/router'; -import * as mount from 'koa-mount'; -import * as koaLogger from 'koa-logger'; +import Koa from 'koa'; +import Router from '@koa/router'; +import mount from 'koa-mount'; +import koaLogger from 'koa-logger'; import * as slow from 'koa-slow'; -import activityPub from './activitypub'; -import nodeinfo from './nodeinfo'; -import wellKnown from './well-known'; -import config from '@/config/index'; -import apiServer from './api/index'; -import Logger from '@/services/logger'; -import { envOption } from '../env'; -import { UserProfiles, Users } from '@/models/index'; -import { genIdenticon } from '@/misc/gen-identicon'; -import { createTemp } from '@/misc/create-temp'; -import { publishMainStream } from '@/services/stream'; -import * as Acct from 'misskey-js/built/acct'; +import activityPub from './activitypub.js'; +import nodeinfo from './nodeinfo.js'; +import wellKnown from './well-known.js'; +import config from '@/config/index.js'; +import apiServer from './api/index.js'; +import fileServer from './file/index.js'; +import proxyServer from './proxy/index.js'; +import webServer from './web/index.js'; +import Logger from '@/services/logger.js'; +import { envOption } from '../env.js'; +import { UserProfiles, Users } from '@/models/index.js'; +import { genIdenticon } from '@/misc/gen-identicon.js'; +import { createTemp } from '@/misc/create-temp.js'; +import { publishMainStream } from '@/services/stream.js'; +import * as Acct from '@/misc/acct.js'; +import { initializeStreamingServer } from './api/streaming.js'; export const serverLogger = new Logger('server', 'gray', false); @@ -55,8 +57,8 @@ if (config.url.startsWith('https') && !config.disableHsts) { } app.use(mount('/api', apiServer)); -app.use(mount('/files', require('./file'))); -app.use(mount('/proxy', require('./proxy'))); +app.use(mount('/files', fileServer)); +app.use(mount('/proxy', proxyServer)); // Init router const router = new Router(); @@ -72,6 +74,8 @@ router.get('/avatar/@:acct', async ctx => { usernameLower: username.toLowerCase(), host: host === config.host ? null : host, isSuspended: false, + }, { + relations: ['avatar'], }); if (user) { @@ -114,29 +118,18 @@ router.get('/verify-email/:code', async ctx => { // Register router app.use(router.routes()); -app.use(mount(require('./web'))); +app.use(mount(webServer)); function createServer() { - if (config.https) { - const certs: any = {}; - for (const k of Object.keys(config.https)) { - certs[k] = fs.readFileSync(config.https[k]); - } - certs['allowHTTP1'] = true; - return http2.createSecureServer(certs, app.callback()) as https.Server; - } else { - return http.createServer(app.callback()); - } + return http.createServer(app.callback()); } // For testing export const startServer = () => { const server = createServer(); - // Init stream server - require('./api/streaming')(server); + initializeStreamingServer(server); - // Listen server.listen(config.port); return server; @@ -145,9 +138,7 @@ export const startServer = () => { export default () => new Promise(resolve => { const server = createServer(); - // Init stream server - require('./api/streaming')(server); + initializeStreamingServer(server); - // Listen server.listen(config.port, resolve); }); diff --git a/packages/backend/src/server/nodeinfo.ts b/packages/backend/src/server/nodeinfo.ts index 4209fc7f1..f4b56fc8a 100644 --- a/packages/backend/src/server/nodeinfo.ts +++ b/packages/backend/src/server/nodeinfo.ts @@ -1,8 +1,9 @@ -import * as Router from '@koa/router'; -import config from '@/config/index'; -import { fetchMeta } from '@/misc/fetch-meta'; -import { Users, Notes } from '@/models/index'; +import Router from '@koa/router'; +import config from '@/config/index.js'; +import { fetchMeta } from '@/misc/fetch-meta.js'; +import { Users, Notes } from '@/models/index.js'; import { MoreThan } from 'typeorm'; +import { MAX_NOTE_TEXT_LENGTH } from '@/const.js'; const router = new Router(); @@ -69,7 +70,7 @@ const nodeinfo2 = async () => { emailRequiredForSignup: meta.emailRequiredForSignup, enableHcaptcha: meta.enableHcaptcha, enableRecaptcha: meta.enableRecaptcha, - maxNoteTextLength: meta.maxNoteTextLength, + maxNoteTextLength: MAX_NOTE_TEXT_LENGTH, enableTwitterIntegration: meta.enableTwitterIntegration, enableGithubIntegration: meta.enableGithubIntegration, enableDiscordIntegration: meta.enableDiscordIntegration, diff --git a/packages/backend/src/server/proxy/index.ts b/packages/backend/src/server/proxy/index.ts index 7a3094311..506ba10ef 100644 --- a/packages/backend/src/server/proxy/index.ts +++ b/packages/backend/src/server/proxy/index.ts @@ -2,10 +2,10 @@ * Media Proxy */ -import * as Koa from 'koa'; -import * as cors from '@koa/cors'; -import * as Router from '@koa/router'; -import { proxyMedia } from './proxy-media'; +import Koa from 'koa'; +import cors from '@koa/cors'; +import Router from '@koa/router'; +import { proxyMedia } from './proxy-media.js'; // Init app const app = new Koa(); @@ -23,4 +23,4 @@ router.get('/:url*', proxyMedia); // Register router app.use(router.routes()); -module.exports = app; +export default app; diff --git a/packages/backend/src/server/proxy/proxy-media.ts b/packages/backend/src/server/proxy/proxy-media.ts index b7dcd0292..3cc5b827a 100644 --- a/packages/backend/src/server/proxy/proxy-media.ts +++ b/packages/backend/src/server/proxy/proxy-media.ts @@ -1,12 +1,12 @@ -import * as fs from 'fs'; -import * as Koa from 'koa'; -import { serverLogger } from '../index'; -import { IImage, convertToPng, convertToJpeg } from '@/services/drive/image-processor'; -import { createTemp } from '@/misc/create-temp'; -import { downloadUrl } from '@/misc/download-url'; -import { detectType } from '@/misc/get-file-info'; -import { StatusError } from '@/misc/fetch'; -import { FILE_TYPE_BROWSERSAFE } from '@/const'; +import * as fs from 'node:fs'; +import Koa from 'koa'; +import { serverLogger } from '../index.js'; +import { IImage, convertToPng, convertToJpeg } from '@/services/drive/image-processor.js'; +import { createTemp } from '@/misc/create-temp.js'; +import { downloadUrl } from '@/misc/download-url.js'; +import { detectType } from '@/misc/get-file-info.js'; +import { StatusError } from '@/misc/fetch.js'; +import { FILE_TYPE_BROWSERSAFE } from '@/const.js'; export async function proxyMedia(ctx: Koa.Context) { const url = 'url' in ctx.query ? ctx.query.url : 'https://' + ctx.params.url; diff --git a/packages/backend/src/server/web/feed.ts b/packages/backend/src/server/web/feed.ts index db589e086..b98e3f8bf 100644 --- a/packages/backend/src/server/web/feed.ts +++ b/packages/backend/src/server/web/feed.ts @@ -1,7 +1,7 @@ import { Feed } from 'feed'; -import config from '@/config/index'; -import { User } from '@/models/entities/user'; -import { Notes, DriveFiles, UserProfiles } from '@/models/index'; +import config from '@/config/index.js'; +import { User } from '@/models/entities/user.js'; +import { Notes, DriveFiles, UserProfiles } from '@/models/index.js'; import { In } from 'typeorm'; export default async function(user: User) { diff --git a/packages/backend/src/server/web/index.ts b/packages/backend/src/server/web/index.ts index 325121bba..cc4c2cc9c 100644 --- a/packages/backend/src/server/web/index.ts +++ b/packages/backend/src/server/web/index.ts @@ -2,24 +2,26 @@ * Web Client Server */ -import { dirname } from 'path'; +import { dirname } from 'node:path'; +import { fileURLToPath } from 'node:url'; import ms from 'ms'; -import * as Koa from 'koa'; -import * as Router from '@koa/router'; -import * as send from 'koa-send'; -import * as favicon from 'koa-favicon'; -import * as views from 'koa-views'; +import Koa from 'koa'; +import Router from '@koa/router'; +import send from 'koa-send'; +import favicon from 'koa-favicon'; +import views from 'koa-views'; -import packFeed from './feed'; -import { fetchMeta } from '@/misc/fetch-meta'; -import { genOpenapiSpec } from '../api/openapi/gen-spec'; -import config from '@/config/index'; -import { Users, Notes, UserProfiles, Pages, Channels, Clips, GalleryPosts } from '@/models/index'; -import * as Acct from 'misskey-js/built/acct'; -import { getNoteSummary } from '@/misc/get-note-summary'; +import packFeed from './feed.js'; +import { fetchMeta } from '@/misc/fetch-meta.js'; +import { genOpenapiSpec } from '../api/openapi/gen-spec.js'; +import config from '@/config/index.js'; +import { Users, Notes, UserProfiles, Pages, Channels, Clips, GalleryPosts } from '@/models/index.js'; +import * as Acct from '@/misc/acct.js'; +import { getNoteSummary } from '@/misc/get-note-summary.js'; +import { urlPreviewHandler } from './url-preview.js'; +import { manifestHandler } from './manifest.js'; -//const _filename = fileURLToPath(import.meta.url); -const _filename = __filename; +const _filename = fileURLToPath(import.meta.url); const _dirname = dirname(_filename); const staticAssets = `${_dirname}/../../../assets/`; @@ -105,7 +107,7 @@ router.get('/sw.js', async ctx => { }); // Manifest -router.get('/manifest.json', require('./manifest')); +router.get('/manifest.json', manifestHandler); router.get('/robots.txt', async ctx => { await send(ctx as any, '/robots.txt', { @@ -123,7 +125,7 @@ router.get('/api-doc', async ctx => { }); // URL preview endpoint -router.get('/url', require('./url-preview')); +router.get('/url', urlPreviewHandler); router.get('/api.json', async ctx => { ctx.body = genOpenapiSpec(); @@ -426,4 +428,4 @@ router.get('(.*)', async ctx => { // Register router app.use(router.routes()); -module.exports = app; +export default app; diff --git a/packages/backend/src/server/web/manifest.ts b/packages/backend/src/server/web/manifest.ts index 464b893d6..bcbf9b76a 100644 --- a/packages/backend/src/server/web/manifest.ts +++ b/packages/backend/src/server/web/manifest.ts @@ -1,8 +1,8 @@ -import * as Koa from 'koa'; -import * as manifest from './manifest.json'; -import { fetchMeta } from '@/misc/fetch-meta'; +import Koa from 'koa'; +import manifest from './manifest.json' assert { type: 'json' }; +import { fetchMeta } from '@/misc/fetch-meta.js'; -module.exports = async (ctx: Koa.Context) => { +export const manifestHandler = async (ctx: Koa.Context) => { const json = JSON.parse(JSON.stringify(manifest)); const instance = await fetchMeta(true); diff --git a/packages/backend/src/server/web/url-preview.ts b/packages/backend/src/server/web/url-preview.ts index 26fffbea8..6bd8ead5b 100644 --- a/packages/backend/src/server/web/url-preview.ts +++ b/packages/backend/src/server/web/url-preview.ts @@ -1,14 +1,14 @@ -import * as Koa from 'koa'; +import Koa from 'koa'; import summaly from 'summaly'; -import { fetchMeta } from '@/misc/fetch-meta'; -import Logger from '@/services/logger'; -import config from '@/config/index'; -import { query } from '@/prelude/url'; -import { getJson } from '@/misc/fetch'; +import { fetchMeta } from '@/misc/fetch-meta.js'; +import Logger from '@/services/logger.js'; +import config from '@/config/index.js'; +import { query } from '@/prelude/url.js'; +import { getJson } from '@/misc/fetch.js'; const logger = new Logger('url-preview'); -module.exports = async (ctx: Koa.Context) => { +export const urlPreviewHandler = async (ctx: Koa.Context) => { const url = ctx.query.url; if (typeof url !== 'string') { ctx.status = 400; @@ -31,7 +31,7 @@ module.exports = async (ctx: Koa.Context) => { const summary = meta.summalyProxy ? await getJson(`${meta.summalyProxy}?${query({ url: url, lang: lang ?? 'ja-JP', - })}`) : await summaly(url, { + })}`) : await summaly.default(url, { followRedirects: false, lang: lang ?? 'ja-JP', }); diff --git a/packages/backend/src/server/web/views/base.pug b/packages/backend/src/server/web/views/base.pug index e1cb2cfa9..abacb1ccf 100644 --- a/packages/backend/src/server/web/views/base.pug +++ b/packages/backend/src/server/web/views/base.pug @@ -59,5 +59,5 @@ html br | Please turn on your JavaScript div#splash - img(src='/favicon.ico') + img(src= icon || '/static-assets/splash.png') block content diff --git a/packages/backend/src/server/well-known.ts b/packages/backend/src/server/well-known.ts index d1f13b70b..7a5d08541 100644 --- a/packages/backend/src/server/well-known.ts +++ b/packages/backend/src/server/well-known.ts @@ -1,11 +1,11 @@ -import * as Router from '@koa/router'; +import Router from '@koa/router'; -import config from '@/config/index'; -import * as Acct from 'misskey-js/built/acct'; -import { links } from './nodeinfo'; -import { escapeAttribute, escapeValue } from '@/prelude/xml'; -import { Users } from '@/models/index'; -import { User } from '@/models/entities/user'; +import config from '@/config/index.js'; +import * as Acct from '@/misc/acct.js'; +import { links } from './nodeinfo.js'; +import { escapeAttribute, escapeValue } from '@/prelude/xml.js'; +import { Users } from '@/models/index.js'; +import { User } from '@/models/entities/user.js'; // Init router const router = new Router(); diff --git a/packages/backend/src/services/add-note-to-antenna.ts b/packages/backend/src/services/add-note-to-antenna.ts index 168e3a614..e88c38723 100644 --- a/packages/backend/src/services/add-note-to-antenna.ts +++ b/packages/backend/src/services/add-note-to-antenna.ts @@ -1,10 +1,10 @@ -import { Antenna } from '@/models/entities/antenna'; -import { Note } from '@/models/entities/note'; -import { AntennaNotes, Mutings, Notes } from '@/models/index'; -import { genId } from '@/misc/gen-id'; -import { isMutedUserRelated } from '@/misc/is-muted-user-related'; -import { publishAntennaStream, publishMainStream } from '@/services/stream'; -import { User } from '@/models/entities/user'; +import { Antenna } from '@/models/entities/antenna.js'; +import { Note } from '@/models/entities/note.js'; +import { AntennaNotes, Mutings, Notes } from '@/models/index.js'; +import { genId } from '@/misc/gen-id.js'; +import { isMutedUserRelated } from '@/misc/is-muted-user-related.js'; +import { publishAntennaStream, publishMainStream } from '@/services/stream.js'; +import { User } from '@/models/entities/user.js'; export async function addNoteToAntenna(antenna: Antenna, note: Note, noteUser: { id: User['id']; }) { // 通知しない設定になっているか、自分自身の投稿なら既読にする diff --git a/packages/backend/src/services/blocking/create.ts b/packages/backend/src/services/blocking/create.ts index 907e4c311..198d28705 100644 --- a/packages/backend/src/services/blocking/create.ts +++ b/packages/backend/src/services/blocking/create.ts @@ -1,15 +1,15 @@ -import { publishMainStream, publishUserEvent } from '@/services/stream'; -import { renderActivity } from '@/remote/activitypub/renderer/index'; -import renderFollow from '@/remote/activitypub/renderer/follow'; -import renderUndo from '@/remote/activitypub/renderer/undo'; -import renderBlock from '@/remote/activitypub/renderer/block'; -import { deliver } from '@/queue/index'; -import renderReject from '@/remote/activitypub/renderer/reject'; -import { User } from '@/models/entities/user'; -import { Blockings, Users, FollowRequests, Followings, UserListJoinings, UserLists } from '@/models/index'; -import { perUserFollowingChart } from '@/services/chart/index'; -import { genId } from '@/misc/gen-id'; -import { IdentifiableError } from '@/misc/identifiable-error'; +import { publishMainStream, publishUserEvent } from '@/services/stream.js'; +import { renderActivity } from '@/remote/activitypub/renderer/index.js'; +import renderFollow from '@/remote/activitypub/renderer/follow.js'; +import renderUndo from '@/remote/activitypub/renderer/undo.js'; +import renderBlock from '@/remote/activitypub/renderer/block.js'; +import { deliver } from '@/queue/index.js'; +import renderReject from '@/remote/activitypub/renderer/reject.js'; +import { User } from '@/models/entities/user.js'; +import { Blockings, Users, FollowRequests, Followings, UserListJoinings, UserLists } from '@/models/index.js'; +import { perUserFollowingChart } from '@/services/chart/index.js'; +import { genId } from '@/misc/gen-id.js'; +import { IdentifiableError } from '@/misc/identifiable-error.js'; export default async function(blocker: User, blockee: User) { await Promise.all([ diff --git a/packages/backend/src/services/blocking/delete.ts b/packages/backend/src/services/blocking/delete.ts index 271bf4854..c4f3784b0 100644 --- a/packages/backend/src/services/blocking/delete.ts +++ b/packages/backend/src/services/blocking/delete.ts @@ -1,10 +1,10 @@ -import { renderActivity } from '@/remote/activitypub/renderer/index'; -import renderBlock from '@/remote/activitypub/renderer/block'; -import renderUndo from '@/remote/activitypub/renderer/undo'; -import { deliver } from '@/queue/index'; -import Logger from '../logger'; -import { User } from '@/models/entities/user'; -import { Blockings, Users } from '@/models/index'; +import { renderActivity } from '@/remote/activitypub/renderer/index.js'; +import renderBlock from '@/remote/activitypub/renderer/block.js'; +import renderUndo from '@/remote/activitypub/renderer/undo.js'; +import { deliver } from '@/queue/index.js'; +import Logger from '../logger.js'; +import { User } from '@/models/entities/user.js'; +import { Blockings, Users } from '@/models/index.js'; const logger = new Logger('blocking/delete'); diff --git a/packages/backend/src/services/chart/charts/active-users.ts b/packages/backend/src/services/chart/charts/active-users.ts index 5baf46f77..d952ea53b 100644 --- a/packages/backend/src/services/chart/charts/active-users.ts +++ b/packages/backend/src/services/chart/charts/active-users.ts @@ -1,8 +1,7 @@ -import autobind from 'autobind-decorator'; -import Chart, { KVs } from '../core'; -import { User } from '@/models/entities/user'; -import { Users } from '@/models/index'; -import { name, schema } from './entities/active-users'; +import Chart, { KVs } from '../core.js'; +import { User } from '@/models/entities/user.js'; +import { Users } from '@/models/index.js'; +import { name, schema } from './entities/active-users.js'; const week = 1000 * 60 * 60 * 24 * 7; const month = 1000 * 60 * 60 * 24 * 30; @@ -17,17 +16,14 @@ export default class ActiveUsersChart extends Chart { super(name, schema); } - @autobind protected async tickMajor(): Promise>> { return {}; } - @autobind protected async tickMinor(): Promise>> { return {}; } - @autobind public async read(user: { id: User['id'], host: null, createdAt: User['createdAt'] }): Promise { await this.commit({ 'read': [user.id], @@ -40,7 +36,6 @@ export default class ActiveUsersChart extends Chart { }); } - @autobind public async write(user: { id: User['id'], host: null, createdAt: User['createdAt'] }): Promise { await this.commit({ 'write': [user.id], diff --git a/packages/backend/src/services/chart/charts/ap-request.ts b/packages/backend/src/services/chart/charts/ap-request.ts index ca763c884..e9e42ade7 100644 --- a/packages/backend/src/services/chart/charts/ap-request.ts +++ b/packages/backend/src/services/chart/charts/ap-request.ts @@ -1,6 +1,5 @@ -import autobind from 'autobind-decorator'; -import Chart, { KVs } from '../core'; -import { name, schema } from './entities/ap-request'; +import Chart, { KVs } from '../core.js'; +import { name, schema } from './entities/ap-request.js'; /** * Chart about ActivityPub requests @@ -11,31 +10,26 @@ export default class ApRequestChart extends Chart { super(name, schema); } - @autobind protected async tickMajor(): Promise>> { return {}; } - @autobind protected async tickMinor(): Promise>> { return {}; } - @autobind public async deliverSucc(): Promise { await this.commit({ 'deliverSucceeded': 1, }); } - @autobind public async deliverFail(): Promise { await this.commit({ 'deliverFailed': 1, }); } - @autobind public async inbox(): Promise { await this.commit({ 'inboxReceived': 1, diff --git a/packages/backend/src/services/chart/charts/drive.ts b/packages/backend/src/services/chart/charts/drive.ts index 288689784..0eeba90dd 100644 --- a/packages/backend/src/services/chart/charts/drive.ts +++ b/packages/backend/src/services/chart/charts/drive.ts @@ -1,9 +1,8 @@ -import autobind from 'autobind-decorator'; -import Chart, { KVs } from '../core'; -import { DriveFiles } from '@/models/index'; +import Chart, { KVs } from '../core.js'; +import { DriveFiles } from '@/models/index.js'; import { Not, IsNull } from 'typeorm'; -import { DriveFile } from '@/models/entities/drive-file'; -import { name, schema } from './entities/drive'; +import { DriveFile } from '@/models/entities/drive-file.js'; +import { name, schema } from './entities/drive.js'; /** * ドライブに関するチャート @@ -14,17 +13,14 @@ export default class DriveChart extends Chart { super(name, schema); } - @autobind protected async tickMajor(): Promise>> { return {}; } - @autobind protected async tickMinor(): Promise>> { return {}; } - @autobind public async update(file: DriveFile, isAdditional: boolean): Promise { const fileSizeKb = file.size / 1000; await this.commit(file.userHost === null ? { diff --git a/packages/backend/src/services/chart/charts/entities/active-users.ts b/packages/backend/src/services/chart/charts/entities/active-users.ts index 843843836..5767b76f8 100644 --- a/packages/backend/src/services/chart/charts/entities/active-users.ts +++ b/packages/backend/src/services/chart/charts/entities/active-users.ts @@ -1,4 +1,4 @@ -import Chart from '../../core'; +import Chart from '../../core.js'; export const name = 'activeUsers'; diff --git a/packages/backend/src/services/chart/charts/entities/ap-request.ts b/packages/backend/src/services/chart/charts/entities/ap-request.ts index 21fb40d13..3a9f3dacf 100644 --- a/packages/backend/src/services/chart/charts/entities/ap-request.ts +++ b/packages/backend/src/services/chart/charts/entities/ap-request.ts @@ -1,4 +1,4 @@ -import Chart from '../../core'; +import Chart from '../../core.js'; export const name = 'apRequest'; diff --git a/packages/backend/src/services/chart/charts/entities/drive.ts b/packages/backend/src/services/chart/charts/entities/drive.ts index c5cdfd85b..4bf5bb729 100644 --- a/packages/backend/src/services/chart/charts/entities/drive.ts +++ b/packages/backend/src/services/chart/charts/entities/drive.ts @@ -1,4 +1,4 @@ -import Chart from '../../core'; +import Chart from '../../core.js'; export const name = 'drive'; diff --git a/packages/backend/src/services/chart/charts/entities/federation.ts b/packages/backend/src/services/chart/charts/entities/federation.ts index 6b2089f0b..a8466b0b4 100644 --- a/packages/backend/src/services/chart/charts/entities/federation.ts +++ b/packages/backend/src/services/chart/charts/entities/federation.ts @@ -1,4 +1,4 @@ -import Chart from '../../core'; +import Chart from '../../core.js'; export const name = 'federation'; @@ -8,6 +8,9 @@ export const schema = { 'stalled': { uniqueIncrement: true, range: 'small' }, 'sub': { accumulate: true, range: 'small' }, 'pub': { accumulate: true, range: 'small' }, + 'pubsub': { accumulate: true, range: 'small' }, + 'subActive': { accumulate: true, range: 'small' }, + 'pubActive': { accumulate: true, range: 'small' }, } as const; export const entity = Chart.schemaToEntity(name, schema); diff --git a/packages/backend/src/services/chart/charts/entities/hashtag.ts b/packages/backend/src/services/chart/charts/entities/hashtag.ts index bd2ae38a1..4d0403904 100644 --- a/packages/backend/src/services/chart/charts/entities/hashtag.ts +++ b/packages/backend/src/services/chart/charts/entities/hashtag.ts @@ -1,4 +1,4 @@ -import Chart from '../../core'; +import Chart from '../../core.js'; export const name = 'hashtag'; diff --git a/packages/backend/src/services/chart/charts/entities/instance.ts b/packages/backend/src/services/chart/charts/entities/instance.ts index b98e1640c..06962120e 100644 --- a/packages/backend/src/services/chart/charts/entities/instance.ts +++ b/packages/backend/src/services/chart/charts/entities/instance.ts @@ -1,4 +1,4 @@ -import Chart from '../../core'; +import Chart from '../../core.js'; export const name = 'instance'; diff --git a/packages/backend/src/services/chart/charts/entities/notes.ts b/packages/backend/src/services/chart/charts/entities/notes.ts index f9b9b20ee..9387dbfb2 100644 --- a/packages/backend/src/services/chart/charts/entities/notes.ts +++ b/packages/backend/src/services/chart/charts/entities/notes.ts @@ -1,4 +1,4 @@ -import Chart from '../../core'; +import Chart from '../../core.js'; export const name = 'notes'; diff --git a/packages/backend/src/services/chart/charts/entities/per-user-drive.ts b/packages/backend/src/services/chart/charts/entities/per-user-drive.ts index 00d85b162..6111640ea 100644 --- a/packages/backend/src/services/chart/charts/entities/per-user-drive.ts +++ b/packages/backend/src/services/chart/charts/entities/per-user-drive.ts @@ -1,4 +1,4 @@ -import Chart from '../../core'; +import Chart from '../../core.js'; export const name = 'perUserDrive'; diff --git a/packages/backend/src/services/chart/charts/entities/per-user-following.ts b/packages/backend/src/services/chart/charts/entities/per-user-following.ts index 1efd4977f..4118daa47 100644 --- a/packages/backend/src/services/chart/charts/entities/per-user-following.ts +++ b/packages/backend/src/services/chart/charts/entities/per-user-following.ts @@ -1,4 +1,4 @@ -import Chart from '../../core'; +import Chart from '../../core.js'; export const name = 'perUserFollowing'; diff --git a/packages/backend/src/services/chart/charts/entities/per-user-notes.ts b/packages/backend/src/services/chart/charts/entities/per-user-notes.ts index 562cde9b0..c1fa17445 100644 --- a/packages/backend/src/services/chart/charts/entities/per-user-notes.ts +++ b/packages/backend/src/services/chart/charts/entities/per-user-notes.ts @@ -1,4 +1,4 @@ -import Chart from '../../core'; +import Chart from '../../core.js'; export const name = 'perUserNotes'; diff --git a/packages/backend/src/services/chart/charts/entities/per-user-reactions.ts b/packages/backend/src/services/chart/charts/entities/per-user-reactions.ts index ab315d24c..5e1a6c7b3 100644 --- a/packages/backend/src/services/chart/charts/entities/per-user-reactions.ts +++ b/packages/backend/src/services/chart/charts/entities/per-user-reactions.ts @@ -1,4 +1,4 @@ -import Chart from '../../core'; +import Chart from '../../core.js'; export const name = 'perUserReaction'; diff --git a/packages/backend/src/services/chart/charts/entities/test-grouped.ts b/packages/backend/src/services/chart/charts/entities/test-grouped.ts index 78c2bbd54..66b6e8e86 100644 --- a/packages/backend/src/services/chart/charts/entities/test-grouped.ts +++ b/packages/backend/src/services/chart/charts/entities/test-grouped.ts @@ -1,4 +1,4 @@ -import Chart from '../../core'; +import Chart from '../../core.js'; export const name = 'testGrouped'; diff --git a/packages/backend/src/services/chart/charts/entities/test-intersection.ts b/packages/backend/src/services/chart/charts/entities/test-intersection.ts index dc56eb93f..a3bdcb367 100644 --- a/packages/backend/src/services/chart/charts/entities/test-intersection.ts +++ b/packages/backend/src/services/chart/charts/entities/test-intersection.ts @@ -1,4 +1,4 @@ -import Chart from '../../core'; +import Chart from '../../core.js'; export const name = 'testIntersection'; diff --git a/packages/backend/src/services/chart/charts/entities/test-unique.ts b/packages/backend/src/services/chart/charts/entities/test-unique.ts index dc7c1520e..b2cfb71b0 100644 --- a/packages/backend/src/services/chart/charts/entities/test-unique.ts +++ b/packages/backend/src/services/chart/charts/entities/test-unique.ts @@ -1,4 +1,4 @@ -import Chart from '../../core'; +import Chart from '../../core.js'; export const name = 'testUnique'; diff --git a/packages/backend/src/services/chart/charts/entities/test.ts b/packages/backend/src/services/chart/charts/entities/test.ts index edfa4c524..7cba21e16 100644 --- a/packages/backend/src/services/chart/charts/entities/test.ts +++ b/packages/backend/src/services/chart/charts/entities/test.ts @@ -1,4 +1,4 @@ -import Chart from '../../core'; +import Chart from '../../core.js'; export const name = 'test'; diff --git a/packages/backend/src/services/chart/charts/entities/users.ts b/packages/backend/src/services/chart/charts/entities/users.ts index d2cec7249..c0b83094a 100644 --- a/packages/backend/src/services/chart/charts/entities/users.ts +++ b/packages/backend/src/services/chart/charts/entities/users.ts @@ -1,4 +1,4 @@ -import Chart from '../../core'; +import Chart from '../../core.js'; export const name = 'users'; diff --git a/packages/backend/src/services/chart/charts/federation.ts b/packages/backend/src/services/chart/charts/federation.ts index 211ba1deb..10221ee1e 100644 --- a/packages/backend/src/services/chart/charts/federation.ts +++ b/packages/backend/src/services/chart/charts/federation.ts @@ -1,7 +1,7 @@ -import autobind from 'autobind-decorator'; -import Chart, { KVs } from '../core'; -import { Followings } from '@/models/index'; -import { name, schema } from './entities/federation'; +import Chart, { KVs } from '../core.js'; +import { Followings, Instances } from '@/models/index.js'; +import { name, schema } from './entities/federation.js'; +import { fetchMeta } from '@/misc/fetch-meta.js'; /** * フェデレーションに関するチャート @@ -12,23 +12,68 @@ export default class FederationChart extends Chart { super(name, schema); } - @autobind protected async tickMajor(): Promise>> { return { }; } - @autobind protected async tickMinor(): Promise>> { - const [sub, pub] = await Promise.all([ + const meta = await fetchMeta(); + + const suspendedInstancesQuery = Instances.createQueryBuilder('instance') + .select('instance.host') + .where('instance.isSuspended = true'); + + const pubsubSubQuery = Followings.createQueryBuilder('f') + .select('f.followerHost') + .where('f.followerHost IS NOT NULL'); + + const subInstancesQuery = Followings.createQueryBuilder('f') + .select('f.followeeHost') + .where('f.followeeHost IS NOT NULL'); + + const pubInstancesQuery = Followings.createQueryBuilder('f') + .select('f.followerHost') + .where('f.followerHost IS NOT NULL'); + + const [sub, pub, pubsub, subActive, pubActive] = await Promise.all([ Followings.createQueryBuilder('following') .select('COUNT(DISTINCT following.followeeHost)') .where('following.followeeHost IS NOT NULL') + .andWhere(meta.blockedHosts.length === 0 ? '1=1' : `following.followeeHost NOT IN (:...blocked)`, { blocked: meta.blockedHosts }) + .andWhere(`following.followeeHost NOT IN (${ suspendedInstancesQuery.getQuery() })`) .getRawOne() .then(x => parseInt(x.count, 10)), Followings.createQueryBuilder('following') .select('COUNT(DISTINCT following.followerHost)') .where('following.followerHost IS NOT NULL') + .andWhere(meta.blockedHosts.length === 0 ? '1=1' : `following.followerHost NOT IN (:...blocked)`, { blocked: meta.blockedHosts }) + .andWhere(`following.followerHost NOT IN (${ suspendedInstancesQuery.getQuery() })`) + .getRawOne() + .then(x => parseInt(x.count, 10)), + Followings.createQueryBuilder('following') + .select('COUNT(DISTINCT following.followeeHost)') + .where('following.followeeHost IS NOT NULL') + .andWhere(meta.blockedHosts.length === 0 ? '1=1' : `following.followeeHost NOT IN (:...blocked)`, { blocked: meta.blockedHosts }) + .andWhere(`following.followeeHost NOT IN (${ suspendedInstancesQuery.getQuery() })`) + .andWhere(`following.followeeHost IN (${ pubsubSubQuery.getQuery() })`) + .setParameters(pubsubSubQuery.getParameters()) + .getRawOne() + .then(x => parseInt(x.count, 10)), + Instances.createQueryBuilder('instance') + .select('COUNT(instance.id)') + .where(`instance.host IN (${ subInstancesQuery.getQuery() })`) + .andWhere(meta.blockedHosts.length === 0 ? '1=1' : `instance.host NOT IN (:...blocked)`, { blocked: meta.blockedHosts }) + .andWhere(`instance.isSuspended = false`) + .andWhere(`instance.lastCommunicatedAt > :gt`, { gt: new Date(Date.now() - (1000 * 60 * 60 * 24 * 30)) }) + .getRawOne() + .then(x => parseInt(x.count, 10)), + Instances.createQueryBuilder('instance') + .select('COUNT(instance.id)') + .where(`instance.host IN (${ pubInstancesQuery.getQuery() })`) + .andWhere(meta.blockedHosts.length === 0 ? '1=1' : `instance.host NOT IN (:...blocked)`, { blocked: meta.blockedHosts }) + .andWhere(`instance.isSuspended = false`) + .andWhere(`instance.lastCommunicatedAt > :gt`, { gt: new Date(Date.now() - (1000 * 60 * 60 * 24 * 30)) }) .getRawOne() .then(x => parseInt(x.count, 10)), ]); @@ -36,10 +81,12 @@ export default class FederationChart extends Chart { return { 'sub': sub, 'pub': pub, + 'pubsub': pubsub, + 'subActive': subActive, + 'pubActive': pubActive, }; } - @autobind public async deliverd(host: string, succeeded: boolean): Promise { await this.commit(succeeded ? { 'deliveredInstances': [host], @@ -48,7 +95,6 @@ export default class FederationChart extends Chart { }); } - @autobind public async inbox(host: string): Promise { await this.commit({ 'inboxInstances': [host], diff --git a/packages/backend/src/services/chart/charts/hashtag.ts b/packages/backend/src/services/chart/charts/hashtag.ts index cbae68683..31f7fa95d 100644 --- a/packages/backend/src/services/chart/charts/hashtag.ts +++ b/packages/backend/src/services/chart/charts/hashtag.ts @@ -1,8 +1,7 @@ -import autobind from 'autobind-decorator'; -import Chart, { KVs } from '../core'; -import { User } from '@/models/entities/user'; -import { Users } from '@/models/index'; -import { name, schema } from './entities/hashtag'; +import Chart, { KVs } from '../core.js'; +import { User } from '@/models/entities/user.js'; +import { Users } from '@/models/index.js'; +import { name, schema } from './entities/hashtag.js'; /** * ハッシュタグに関するチャート @@ -13,17 +12,14 @@ export default class HashtagChart extends Chart { super(name, schema, true); } - @autobind protected async tickMajor(): Promise>> { return {}; } - @autobind protected async tickMinor(): Promise>> { return {}; } - @autobind public async update(hashtag: string, user: { id: User['id'], host: User['host'] }): Promise { await this.commit({ 'local.users': Users.isLocalUser(user) ? [user.id] : [], diff --git a/packages/backend/src/services/chart/charts/instance.ts b/packages/backend/src/services/chart/charts/instance.ts index 930ac4729..f1257fdf1 100644 --- a/packages/backend/src/services/chart/charts/instance.ts +++ b/packages/backend/src/services/chart/charts/instance.ts @@ -1,10 +1,9 @@ -import autobind from 'autobind-decorator'; -import Chart, { KVs } from '../core'; -import { DriveFiles, Followings, Users, Notes } from '@/models/index'; -import { DriveFile } from '@/models/entities/drive-file'; -import { Note } from '@/models/entities/note'; -import { toPuny } from '@/misc/convert-host'; -import { name, schema } from './entities/instance'; +import Chart, { KVs } from '../core.js'; +import { DriveFiles, Followings, Users, Notes } from '@/models/index.js'; +import { DriveFile } from '@/models/entities/drive-file.js'; +import { Note } from '@/models/entities/note.js'; +import { toPuny } from '@/misc/convert-host.js'; +import { name, schema } from './entities/instance.js'; /** * インスタンスごとのチャート @@ -15,7 +14,6 @@ export default class InstanceChart extends Chart { super(name, schema, true); } - @autobind protected async tickMajor(group: string): Promise>> { const [ notesCount, @@ -23,14 +21,12 @@ export default class InstanceChart extends Chart { followingCount, followersCount, driveFiles, - //driveUsage, ] = await Promise.all([ Notes.count({ userHost: group }), Users.count({ host: group }), Followings.count({ followerHost: group }), Followings.count({ followeeHost: group }), DriveFiles.count({ userHost: group }), - //DriveFiles.calcDriveUsageOfHost(group), ]); return { @@ -42,19 +38,16 @@ export default class InstanceChart extends Chart { }; } - @autobind protected async tickMinor(): Promise>> { return {}; } - @autobind public async requestReceived(host: string): Promise { await this.commit({ 'requests.received': 1, }, toPuny(host)); } - @autobind public async requestSent(host: string, isSucceeded: boolean): Promise { await this.commit({ 'requests.succeeded': isSucceeded ? 1 : 0, @@ -62,7 +55,6 @@ export default class InstanceChart extends Chart { }, toPuny(host)); } - @autobind public async newUser(host: string): Promise { await this.commit({ 'users.total': 1, @@ -70,7 +62,6 @@ export default class InstanceChart extends Chart { }, toPuny(host)); } - @autobind public async updateNote(host: string, note: Note, isAdditional: boolean): Promise { await this.commit({ 'notes.total': isAdditional ? 1 : -1, @@ -83,7 +74,6 @@ export default class InstanceChart extends Chart { }, toPuny(host)); } - @autobind public async updateFollowing(host: string, isAdditional: boolean): Promise { await this.commit({ 'following.total': isAdditional ? 1 : -1, @@ -92,7 +82,6 @@ export default class InstanceChart extends Chart { }, toPuny(host)); } - @autobind public async updateFollowers(host: string, isAdditional: boolean): Promise { await this.commit({ 'followers.total': isAdditional ? 1 : -1, @@ -101,7 +90,6 @@ export default class InstanceChart extends Chart { }, toPuny(host)); } - @autobind public async updateDrive(file: DriveFile, isAdditional: boolean): Promise { const fileSizeKb = file.size / 1000; await this.commit({ diff --git a/packages/backend/src/services/chart/charts/notes.ts b/packages/backend/src/services/chart/charts/notes.ts index 624ee5db2..ab6a37e3c 100644 --- a/packages/backend/src/services/chart/charts/notes.ts +++ b/packages/backend/src/services/chart/charts/notes.ts @@ -1,9 +1,8 @@ -import autobind from 'autobind-decorator'; -import Chart, { KVs } from '../core'; -import { Notes } from '@/models/index'; +import Chart, { KVs } from '../core.js'; +import { Notes } from '@/models/index.js'; import { Not, IsNull } from 'typeorm'; -import { Note } from '@/models/entities/note'; -import { name, schema } from './entities/notes'; +import { Note } from '@/models/entities/note.js'; +import { name, schema } from './entities/notes.js'; /** * ノートに関するチャート @@ -14,7 +13,6 @@ export default class NotesChart extends Chart { super(name, schema); } - @autobind protected async tickMajor(): Promise>> { const [localCount, remoteCount] = await Promise.all([ Notes.count({ userHost: null }), @@ -27,12 +25,10 @@ export default class NotesChart extends Chart { }; } - @autobind protected async tickMinor(): Promise>> { return {}; } - @autobind public async update(note: Note, isAdditional: boolean): Promise { const prefix = note.userHost === null ? 'local' : 'remote'; diff --git a/packages/backend/src/services/chart/charts/per-user-drive.ts b/packages/backend/src/services/chart/charts/per-user-drive.ts index ae9e8c569..131befa39 100644 --- a/packages/backend/src/services/chart/charts/per-user-drive.ts +++ b/packages/backend/src/services/chart/charts/per-user-drive.ts @@ -1,8 +1,7 @@ -import autobind from 'autobind-decorator'; -import Chart, { KVs } from '../core'; -import { DriveFiles } from '@/models/index'; -import { DriveFile } from '@/models/entities/drive-file'; -import { name, schema } from './entities/per-user-drive'; +import Chart, { KVs } from '../core.js'; +import { DriveFiles } from '@/models/index.js'; +import { DriveFile } from '@/models/entities/drive-file.js'; +import { name, schema } from './entities/per-user-drive.js'; /** * ユーザーごとのドライブに関するチャート @@ -13,7 +12,6 @@ export default class PerUserDriveChart extends Chart { super(name, schema, true); } - @autobind protected async tickMajor(group: string): Promise>> { const [count, size] = await Promise.all([ DriveFiles.count({ userId: group }), @@ -26,12 +24,10 @@ export default class PerUserDriveChart extends Chart { }; } - @autobind protected async tickMinor(): Promise>> { return {}; } - @autobind public async update(file: DriveFile, isAdditional: boolean): Promise { const fileSizeKb = file.size / 1000; await this.commit({ diff --git a/packages/backend/src/services/chart/charts/per-user-following.ts b/packages/backend/src/services/chart/charts/per-user-following.ts index 0b39881c1..5d5dd1fa1 100644 --- a/packages/backend/src/services/chart/charts/per-user-following.ts +++ b/packages/backend/src/services/chart/charts/per-user-following.ts @@ -1,9 +1,8 @@ -import autobind from 'autobind-decorator'; -import Chart, { KVs } from '../core'; -import { Followings, Users } from '@/models/index'; +import Chart, { KVs } from '../core.js'; +import { Followings, Users } from '@/models/index.js'; import { Not, IsNull } from 'typeorm'; -import { User } from '@/models/entities/user'; -import { name, schema } from './entities/per-user-following'; +import { User } from '@/models/entities/user.js'; +import { name, schema } from './entities/per-user-following.js'; /** * ユーザーごとのフォローに関するチャート @@ -14,7 +13,6 @@ export default class PerUserFollowingChart extends Chart { super(name, schema, true); } - @autobind protected async tickMajor(group: string): Promise>> { const [ localFollowingsCount, @@ -36,12 +34,10 @@ export default class PerUserFollowingChart extends Chart { }; } - @autobind protected async tickMinor(): Promise>> { return {}; } - @autobind public async update(follower: { id: User['id']; host: User['host']; }, followee: { id: User['id']; host: User['host']; }, isFollow: boolean): Promise { const prefixFollower = Users.isLocalUser(follower) ? 'local' : 'remote'; const prefixFollowee = Users.isLocalUser(followee) ? 'local' : 'remote'; diff --git a/packages/backend/src/services/chart/charts/per-user-notes.ts b/packages/backend/src/services/chart/charts/per-user-notes.ts index 01a278515..9c5dea1aa 100644 --- a/packages/backend/src/services/chart/charts/per-user-notes.ts +++ b/packages/backend/src/services/chart/charts/per-user-notes.ts @@ -1,9 +1,8 @@ -import autobind from 'autobind-decorator'; -import Chart, { KVs } from '../core'; -import { User } from '@/models/entities/user'; -import { Notes } from '@/models/index'; -import { Note } from '@/models/entities/note'; -import { name, schema } from './entities/per-user-notes'; +import Chart, { KVs } from '../core.js'; +import { User } from '@/models/entities/user.js'; +import { Notes } from '@/models/index.js'; +import { Note } from '@/models/entities/note.js'; +import { name, schema } from './entities/per-user-notes.js'; /** * ユーザーごとのノートに関するチャート @@ -14,7 +13,6 @@ export default class PerUserNotesChart extends Chart { super(name, schema, true); } - @autobind protected async tickMajor(group: string): Promise>> { const [count] = await Promise.all([ Notes.count({ userId: group }), @@ -25,12 +23,10 @@ export default class PerUserNotesChart extends Chart { }; } - @autobind protected async tickMinor(): Promise>> { return {}; } - @autobind public async update(user: { id: User['id'] }, note: Note, isAdditional: boolean): Promise { await this.commit({ 'total': isAdditional ? 1 : -1, diff --git a/packages/backend/src/services/chart/charts/per-user-reactions.ts b/packages/backend/src/services/chart/charts/per-user-reactions.ts index 59af0e86c..3a830e118 100644 --- a/packages/backend/src/services/chart/charts/per-user-reactions.ts +++ b/packages/backend/src/services/chart/charts/per-user-reactions.ts @@ -1,9 +1,8 @@ -import autobind from 'autobind-decorator'; -import Chart, { KVs } from '../core'; -import { User } from '@/models/entities/user'; -import { Note } from '@/models/entities/note'; -import { Users } from '@/models/index'; -import { name, schema } from './entities/per-user-reactions'; +import Chart, { KVs } from '../core.js'; +import { User } from '@/models/entities/user.js'; +import { Note } from '@/models/entities/note.js'; +import { Users } from '@/models/index.js'; +import { name, schema } from './entities/per-user-reactions.js'; /** * ユーザーごとのリアクションに関するチャート @@ -14,17 +13,14 @@ export default class PerUserReactionsChart extends Chart { super(name, schema, true); } - @autobind protected async tickMajor(group: string): Promise>> { return {}; } - @autobind protected async tickMinor(): Promise>> { return {}; } - @autobind public async update(user: { id: User['id'], host: User['host'] }, note: Note): Promise { const prefix = Users.isLocalUser(user) ? 'local' : 'remote'; this.commit({ diff --git a/packages/backend/src/services/chart/charts/test-grouped.ts b/packages/backend/src/services/chart/charts/test-grouped.ts index 19b213584..d01c9fcbd 100644 --- a/packages/backend/src/services/chart/charts/test-grouped.ts +++ b/packages/backend/src/services/chart/charts/test-grouped.ts @@ -1,6 +1,5 @@ -import autobind from 'autobind-decorator'; -import Chart, { KVs } from '../core'; -import { name, schema } from './entities/test-grouped'; +import Chart, { KVs } from '../core.js'; +import { name, schema } from './entities/test-grouped.js'; /** * For testing @@ -13,19 +12,16 @@ export default class TestGroupedChart extends Chart { super(name, schema, true); } - @autobind protected async tickMajor(group: string): Promise>> { return { 'foo.total': this.total[group], }; } - @autobind protected async tickMinor(): Promise>> { return {}; } - @autobind public async increment(group: string): Promise { if (this.total[group] == null) this.total[group] = 0; diff --git a/packages/backend/src/services/chart/charts/test-intersection.ts b/packages/backend/src/services/chart/charts/test-intersection.ts index 6fd780f9b..88b5a715c 100644 --- a/packages/backend/src/services/chart/charts/test-intersection.ts +++ b/packages/backend/src/services/chart/charts/test-intersection.ts @@ -1,6 +1,5 @@ -import autobind from 'autobind-decorator'; -import Chart, { KVs } from '../core'; -import { name, schema } from './entities/test-intersection'; +import Chart, { KVs } from '../core.js'; +import { name, schema } from './entities/test-intersection.js'; /** * For testing @@ -11,24 +10,20 @@ export default class TestIntersectionChart extends Chart { super(name, schema); } - @autobind protected async tickMajor(): Promise>> { return {}; } - @autobind protected async tickMinor(): Promise>> { return {}; } - @autobind public async addA(key: string): Promise { await this.commit({ a: [key], }); } - @autobind public async addB(key: string): Promise { await this.commit({ b: [key], diff --git a/packages/backend/src/services/chart/charts/test-unique.ts b/packages/backend/src/services/chart/charts/test-unique.ts index 2c9cc2fd6..d714f1d40 100644 --- a/packages/backend/src/services/chart/charts/test-unique.ts +++ b/packages/backend/src/services/chart/charts/test-unique.ts @@ -1,6 +1,5 @@ -import autobind from 'autobind-decorator'; -import Chart, { KVs } from '../core'; -import { name, schema } from './entities/test-unique'; +import Chart, { KVs } from '../core.js'; +import { name, schema } from './entities/test-unique.js'; /** * For testing @@ -11,17 +10,14 @@ export default class TestUniqueChart extends Chart { super(name, schema); } - @autobind protected async tickMajor(): Promise>> { return {}; } - @autobind protected async tickMinor(): Promise>> { return {}; } - @autobind public async uniqueIncrement(key: string): Promise { await this.commit({ foo: [key], diff --git a/packages/backend/src/services/chart/charts/test.ts b/packages/backend/src/services/chart/charts/test.ts index b539625c1..adb2b18c8 100644 --- a/packages/backend/src/services/chart/charts/test.ts +++ b/packages/backend/src/services/chart/charts/test.ts @@ -1,6 +1,5 @@ -import autobind from 'autobind-decorator'; -import Chart, { KVs } from '../core'; -import { name, schema } from './entities/test'; +import Chart, { KVs } from '../core.js'; +import { name, schema } from './entities/test.js'; /** * For testing @@ -13,19 +12,16 @@ export default class TestChart extends Chart { super(name, schema); } - @autobind protected async tickMajor(): Promise>> { return { 'foo.total': this.total, }; } - @autobind protected async tickMinor(): Promise>> { return {}; } - @autobind public async increment(): Promise { this.total++; @@ -35,7 +31,6 @@ export default class TestChart extends Chart { }); } - @autobind public async decrement(): Promise { this.total--; diff --git a/packages/backend/src/services/chart/charts/users.ts b/packages/backend/src/services/chart/charts/users.ts index 70ef89f8c..fb9d5e15f 100644 --- a/packages/backend/src/services/chart/charts/users.ts +++ b/packages/backend/src/services/chart/charts/users.ts @@ -1,9 +1,8 @@ -import autobind from 'autobind-decorator'; -import Chart, { KVs } from '../core'; -import { Users } from '@/models/index'; +import Chart, { KVs } from '../core.js'; +import { Users } from '@/models/index.js'; import { Not, IsNull } from 'typeorm'; -import { User } from '@/models/entities/user'; -import { name, schema } from './entities/users'; +import { User } from '@/models/entities/user.js'; +import { name, schema } from './entities/users.js'; /** * ユーザー数に関するチャート @@ -14,7 +13,6 @@ export default class UsersChart extends Chart { super(name, schema); } - @autobind protected async tickMajor(): Promise>> { const [localCount, remoteCount] = await Promise.all([ Users.count({ host: null }), @@ -27,12 +25,10 @@ export default class UsersChart extends Chart { }; } - @autobind protected async tickMinor(): Promise>> { return {}; } - @autobind public async update(user: { id: User['id'], host: User['host'] }, isAdditional: boolean): Promise { const prefix = Users.isLocalUser(user) ? 'local' : 'remote'; diff --git a/packages/backend/src/services/chart/core.ts b/packages/backend/src/services/chart/core.ts index 61a757570..39fad71dd 100644 --- a/packages/backend/src/services/chart/core.ts +++ b/packages/backend/src/services/chart/core.ts @@ -5,11 +5,10 @@ */ import * as nestedProperty from 'nested-property'; -import autobind from 'autobind-decorator'; -import Logger from '../logger'; +import Logger from '../logger.js'; import { EntitySchema, getRepository, Repository, LessThan, Between } from 'typeorm'; -import { dateUTC, isTimeSame, isTimeBefore, subtractTime, addTime } from '@/prelude/time'; -import { getChartInsertLock } from '@/misc/app-lock'; +import { dateUTC, isTimeSame, isTimeBefore, subtractTime, addTime } from '@/prelude/time.js'; +import { getChartInsertLock } from '@/misc/app-lock.js'; const logger = new Logger('chart', 'white', process.env.NODE_ENV !== 'test'); @@ -17,8 +16,27 @@ const columnPrefix = '___' as const; const uniqueTempColumnPrefix = 'unique_temp___' as const; const columnDot = '_' as const; +type Schema = Record; + + range?: 'big' | 'small' | 'medium'; + + // previousな値を引き継ぐかどうか + accumulate?: boolean; +}>; + type KeyToColumnName = T extends `${infer R1}.${infer R2}` ? `${R1}${typeof columnDot}${KeyToColumnName}` : T; +type Columns = { + [K in keyof S as `${typeof columnPrefix}${KeyToColumnName}`]: number; +}; + +type TempColumnsForUnique = { + [K in keyof S as `${typeof uniqueTempColumnPrefix}${KeyToColumnName}`]: S[K]['uniqueIncrement'] extends true ? string[] : never; +}; + type RawRecord = { id: number; @@ -31,11 +49,7 @@ type RawRecord = { * 集計日時のUnixタイムスタンプ(秒) */ date: number; -} & { - [K in keyof S as `${typeof uniqueTempColumnPrefix}${KeyToColumnName}`]: S[K]['uniqueIncrement'] extends true ? string[] : never; -} & { - [K in keyof S as `${typeof columnPrefix}${KeyToColumnName}`]: number; -}; +} & TempColumnsForUnique & Columns; const camelToSnake = (str: string): string => { return str.replace(/([A-Z])/g, s => '_' + s.charAt(0).toLowerCase()); @@ -43,17 +57,6 @@ const camelToSnake = (str: string): string => { const removeDuplicates = (array: any[]) => Array.from(new Set(array)); -type Schema = Record; - - range?: 'big' | 'small' | 'medium'; - - // previousな値を引き継ぐかどうか - accumulate?: boolean; -}>; - type Commit = { [K in keyof S]?: S[K]['uniqueIncrement'] extends true ? string[] : number; }; @@ -66,6 +69,50 @@ type ChartResult = { [P in keyof T]: number[]; }; +type UnionToIntersection = (T extends any ? (x: T) => any : never) extends (x: infer R) => any ? R : never; + +type UnflattenSingleton = K extends `${infer A}.${infer B}` + ? { [_ in A]: UnflattenSingleton; } + : { [_ in K]: V; }; + +type Unflatten> = UnionToIntersection< + { + [K in Extract]: UnflattenSingleton; + }[Extract] +>; + +type ToJsonSchema = { + type: 'object'; + properties: { + [K in keyof S]: S[K] extends number[] ? { type: 'array'; items: { type: 'number'; }; } : ToJsonSchema; + }, + required: (keyof S)[]; +}; + +export function getJsonSchema(schema: S): ToJsonSchema>> { + const object = {}; + for (const [k, v] of Object.entries(schema)) { + nestedProperty.set(object, k, null); + } + + function f(obj: Record>) { + const jsonSchema = { + type: 'object', + properties: {} as Record, + required: [], + }; + for (const [k, v] of Object.entries(obj)) { + jsonSchema.properties[k] = v === null ? { + type: 'array', + items: { type: 'number' }, + } : f(v as Record>); + } + return jsonSchema; + } + + return f(object) as ToJsonSchema>>; +} + /** * 様々なチャートの管理を司るクラス */ @@ -78,8 +125,11 @@ export default abstract class Chart { diff: Commit; group: string | null; }[] = []; - protected repositoryForHour: Repository>; - protected repositoryForDay: Repository>; + // ↓にしたいけどfindOneとかで型エラーになる + //private repositoryForHour: Repository>; + //private repositoryForDay: Repository>; + private repositoryForHour: Repository<{ id: number; group?: string | null; date: number; }>; + private repositoryForDay: Repository<{ id: number; group?: string | null; date: number; }>; /** * 1日に一回程度実行されれば良いような計算処理を入れる(主にCASCADE削除などアプリケーション側で感知できない変動によるズレの修正用) @@ -91,7 +141,6 @@ export default abstract class Chart { */ protected abstract tickMinor(group: string | null): Promise>>; - @autobind private static convertSchemaToColumnDefinitions(schema: Schema): Record { const columns = {} as Record; for (const [k, v] of Object.entries(schema)) { @@ -117,12 +166,10 @@ export default abstract class Chart { return columns; } - @autobind private static dateToTimestamp(x: Date): number { return Math.floor(x.getTime() / 1000); } - @autobind private static parseDate(date: Date): [number, number, number, number, number, number, number] { const y = date.getUTCFullYear(); const m = date.getUTCMonth(); @@ -135,12 +182,10 @@ export default abstract class Chart { return [y, m, d, h, _m, _s, _ms]; } - @autobind private static getCurrentDate() { return Chart.parseDate(new Date()); } - @autobind public static schemaToEntity(name: string, schema: Schema, grouped = false): { hour: EntitySchema, day: EntitySchema, @@ -196,23 +241,21 @@ export default abstract class Chart { this.schema = schema; const { hour, day } = Chart.schemaToEntity(name, schema, grouped); - this.repositoryForHour = getRepository>(hour); - this.repositoryForDay = getRepository>(day); + this.repositoryForHour = getRepository<{ id: number; group?: string | null; date: number; }>(hour); + this.repositoryForDay = getRepository<{ id: number; group?: string | null; date: number; }>(day); } - @autobind private convertRawRecord(x: RawRecord): KVs { - const kvs = {} as KVs; - for (const k of Object.keys(x).filter(k => k.startsWith(columnPrefix))) { - kvs[k.substr(columnPrefix.length).split(columnDot).join('.')] = x[k]; + const kvs = {} as Record; + for (const k of Object.keys(x).filter((k) => k.startsWith(columnPrefix)) as (keyof Columns)[]) { + kvs[(k as string).substr(columnPrefix.length).split(columnDot).join('.')] = x[k]; } - return kvs; + return kvs as KVs; } - @autobind private getNewLog(latest: KVs | null): KVs { const log = {} as Record; - for (const [k, v] of Object.entries(this.schema)) { + for (const [k, v] of Object.entries(this.schema) as ([keyof typeof this['schema'], this['schema'][string]])[]) { if (v.accumulate && latest) { log[k] = latest[k]; } else { @@ -222,7 +265,6 @@ export default abstract class Chart { return log as KVs; } - @autobind private getLatestLog(group: string | null, span: 'hour' | 'day'): Promise | null> { const repository = span === 'hour' ? this.repositoryForHour : @@ -235,13 +277,12 @@ export default abstract class Chart { order: { date: -1, }, - }).then(x => x || null); + }).then(x => x ?? null) as Promise | null>; } /** * 現在(=今のHour or Day)のログをデータベースから探して、あればそれを返し、なければ作成して返します。 */ - @autobind private async claimCurrentLog(group: string | null, span: 'hour' | 'day'): Promise> { const [y, m, d, h] = Chart.getCurrentDate(); @@ -259,7 +300,7 @@ export default abstract class Chart { const currentLog = await repository.findOne({ date: Chart.dateToTimestamp(current), ...(group ? { group: group } : {}), - }); + }) as RawRecord | undefined; // ログがあればそれを返して終了 if (currentLog != null) { @@ -299,7 +340,7 @@ export default abstract class Chart { const currentLog = await repository.findOne({ date: date, ...(group ? { group: group } : {}), - }); + }) as RawRecord | undefined; // ログがあればそれを返して終了 if (currentLog != null) return currentLog; @@ -315,7 +356,7 @@ export default abstract class Chart { date: date, ...(group ? { group: group } : {}), ...columns, - }).then(x => repository.findOneOrFail(x.identifiers[0])); + }).then(x => repository.findOneOrFail(x.identifiers[0])) as RawRecord; logger.info(`${this.name + (group ? `:${group}` : '')}(${span}): New commit created`); @@ -325,7 +366,6 @@ export default abstract class Chart { } } - @autobind protected commit(diff: Commit, group: string | null = null): void { for (const [k, v] of Object.entries(diff)) { if (v == null || v === 0 || (Array.isArray(v) && v.length === 0)) delete diff[k]; @@ -335,7 +375,6 @@ export default abstract class Chart { }); } - @autobind public async save(): Promise { if (this.buffer.length === 0) { logger.info(`${this.name}: Write skipped`); @@ -349,7 +388,7 @@ export default abstract class Chart { // これを回避するための実装は複雑になりそうなため、一旦保留。 const update = async (logHour: RawRecord, logDay: RawRecord): Promise => { - const finalDiffs = {} as Record; + const finalDiffs = {} as Record; for (const diff of this.buffer.filter(q => q.group == null || (q.group === logHour.group)).map(q => q.diff)) { for (const [k, v] of Object.entries(diff)) { @@ -359,23 +398,23 @@ export default abstract class Chart { if (typeof finalDiffs[k] === 'number') { (finalDiffs[k] as number) += v as number; } else { - (finalDiffs[k] as unknown[]) = (finalDiffs[k] as unknown[]).concat(v); + (finalDiffs[k] as string[]) = (finalDiffs[k] as string[]).concat(v); } } } } - const queryForHour: Record string)> = {}; - const queryForDay: Record string)> = {}; + const queryForHour: Record, number | (() => string)> = {} as any; + const queryForDay: Record, number | (() => string)> = {} as any; for (const [k, v] of Object.entries(finalDiffs)) { if (typeof v === 'number') { - const name = columnPrefix + k.replaceAll('.', columnDot); + const name = columnPrefix + k.replaceAll('.', columnDot) as keyof Columns; if (v > 0) queryForHour[name] = () => `"${name}" + ${v}`; if (v < 0) queryForHour[name] = () => `"${name}" - ${Math.abs(v)}`; if (v > 0) queryForDay[name] = () => `"${name}" + ${v}`; if (v < 0) queryForDay[name] = () => `"${name}" - ${Math.abs(v)}`; } else if (Array.isArray(v) && v.length > 0) { // ユニークインクリメント - const tempColumnName = uniqueTempColumnPrefix + k.replaceAll('.', columnDot); + const tempColumnName = uniqueTempColumnPrefix + k.replaceAll('.', columnDot) as keyof TempColumnsForUnique; // TODO: item をSQLエスケープ const itemsForHour = v.filter(item => !logHour[tempColumnName].includes(item)).map(item => `"${item}"`); const itemsForDay = v.filter(item => !logDay[tempColumnName].includes(item)).map(item => `"${item}"`); @@ -387,10 +426,10 @@ export default abstract class Chart { // bake unique count for (const [k, v] of Object.entries(finalDiffs)) { if (this.schema[k].uniqueIncrement) { - const name = columnPrefix + k.replaceAll('.', columnDot); - const tempColumnName = uniqueTempColumnPrefix + k.replaceAll('.', columnDot); - queryForHour[name] = new Set([...v, ...logHour[tempColumnName]]).size; - queryForDay[name] = new Set([...v, ...logDay[tempColumnName]]).size; + const name = columnPrefix + k.replaceAll('.', columnDot) as keyof Columns; + const tempColumnName = uniqueTempColumnPrefix + k.replaceAll('.', columnDot) as keyof TempColumnsForUnique; + queryForHour[name] = new Set([...(v as string[]), ...logHour[tempColumnName]]).size; + queryForDay[name] = new Set([...(v as string[]), ...logDay[tempColumnName]]).size; } } @@ -399,16 +438,18 @@ export default abstract class Chart { for (const [k, v] of Object.entries(this.schema)) { const intersection = v.intersection; if (intersection) { - const name = columnPrefix + k.replaceAll('.', columnDot); + const name = columnPrefix + k.replaceAll('.', columnDot) as keyof Columns; const firstKey = intersection[0]; - const firstTempColumnName = uniqueTempColumnPrefix + firstKey.replaceAll('.', columnDot); - const currentValuesForHour = new Set([...(finalDiffs[firstKey] ?? []), ...logHour[firstTempColumnName]]); - const currentValuesForDay = new Set([...(finalDiffs[firstKey] ?? []), ...logDay[firstTempColumnName]]); + const firstTempColumnName = uniqueTempColumnPrefix + firstKey.replaceAll('.', columnDot) as keyof TempColumnsForUnique; + const firstValues = finalDiffs[firstKey] as string[] | undefined; + const currentValuesForHour = new Set([...(firstValues ?? []), ...logHour[firstTempColumnName]]); + const currentValuesForDay = new Set([...(firstValues ?? []), ...logDay[firstTempColumnName]]); for (let i = 1; i < intersection.length; i++) { const targetKey = intersection[i]; - const targetTempColumnName = uniqueTempColumnPrefix + targetKey.replaceAll('.', columnDot); - const targetValuesForHour = new Set([...(finalDiffs[targetKey] ?? []), ...logHour[targetTempColumnName]]); - const targetValuesForDay = new Set([...(finalDiffs[targetKey] ?? []), ...logDay[targetTempColumnName]]); + const targetTempColumnName = uniqueTempColumnPrefix + targetKey.replaceAll('.', columnDot) as keyof TempColumnsForUnique; + const targetValues = finalDiffs[targetKey] as string[] | undefined; + const targetValuesForHour = new Set([...(targetValues ?? []), ...logHour[targetTempColumnName]]); + const targetValuesForDay = new Set([...(targetValues ?? []), ...logDay[targetTempColumnName]]); currentValuesForHour.forEach(v => { if (!targetValuesForHour.has(v)) currentValuesForHour.delete(v); }); @@ -425,12 +466,12 @@ export default abstract class Chart { await Promise.all([ this.repositoryForHour.createQueryBuilder() .update() - .set(queryForHour) + .set(queryForHour as any) .where('id = :id', { id: logHour.id }) .execute(), this.repositoryForDay.createQueryBuilder() .update() - .set(queryForDay) + .set(queryForDay as any) .where('id = :id', { id: logDay.id }) .execute(), ]); @@ -452,14 +493,13 @@ export default abstract class Chart { update(logHour, logDay)))); } - @autobind public async tick(major: boolean, group: string | null = null): Promise { const data = major ? await this.tickMajor(group) : await this.tickMinor(group); - const columns = {} as Record; - for (const [k, v] of Object.entries(data)) { - const name = k.replaceAll('.', columnDot); - columns[columnPrefix + name] = v; + const columns = {} as Record, number>; + for (const [k, v] of Object.entries(data) as ([keyof typeof data, number])[]) { + const name = columnPrefix + (k as string).replaceAll('.', columnDot) as keyof Columns; + columns[name] = v; } if (Object.keys(columns).length === 0) { @@ -470,12 +510,12 @@ export default abstract class Chart { await Promise.all([ this.repositoryForHour.createQueryBuilder() .update() - .set(columns as any) + .set(columns) .where('id = :id', { id: logHour.id }) .execute(), this.repositoryForDay.createQueryBuilder() .update() - .set(columns as any) + .set(columns) .where('id = :id', { id: logDay.id }) .execute(), ]); @@ -488,12 +528,10 @@ export default abstract class Chart { update(logHour, logDay)); } - @autobind public resync(group: string | null = null): Promise { return this.tick(true, group); } - @autobind public async clean(): Promise { const current = dateUTC(Chart.getCurrentDate()); @@ -501,11 +539,11 @@ export default abstract class Chart { const gt = Chart.dateToTimestamp(current) - (60 * 60 * 24 * 3); const lt = Chart.dateToTimestamp(current) - (60 * 60 * 24); - const columns = {} as Record; + const columns = {} as Record, []>; for (const [k, v] of Object.entries(this.schema)) { if (v.uniqueIncrement) { - const name = k.replaceAll('.', columnDot); - columns[uniqueTempColumnPrefix + name] = []; + const name = uniqueTempColumnPrefix + k.replaceAll('.', columnDot) as keyof TempColumnsForUnique; + columns[name] = []; } } @@ -516,20 +554,19 @@ export default abstract class Chart { await Promise.all([ this.repositoryForHour.createQueryBuilder() .update() - .set(columns as any) + .set(columns) .where('date > :gt', { gt }) .andWhere('date < :lt', { lt }) .execute(), this.repositoryForDay.createQueryBuilder() .update() - .set(columns as any) + .set(columns) .where('date > :gt', { gt }) .andWhere('date < :lt', { lt }) .execute(), ]); } - @autobind public async getChartRaw(span: 'hour' | 'day', amount: number, cursor: Date | null, group: string | null = null): Promise> { const [y, m, d, h, _m, _s, _ms] = cursor ? Chart.parseDate(subtractTime(addTime(cursor, 1, span), 1)) : Chart.getCurrentDate(); const [y2, m2, d2, h2] = cursor ? Chart.parseDate(addTime(cursor, 1, span)) : [] as never; @@ -555,7 +592,7 @@ export default abstract class Chart { order: { date: -1, }, - }); + }) as RawRecord[]; // 要求された範囲にログがひとつもなかったら if (logs.length === 0) { @@ -567,7 +604,7 @@ export default abstract class Chart { order: { date: -1, }, - }); + }) as RawRecord | undefined; if (recentLog) { logs = [recentLog]; @@ -584,7 +621,7 @@ export default abstract class Chart { order: { date: -1, }, - }); + }) as RawRecord | undefined; if (outdatedLog) { logs.push(outdatedLog); @@ -620,7 +657,7 @@ export default abstract class Chart { * にする */ for (const record of chart) { - for (const [k, v] of Object.entries(record)) { + for (const [k, v] of Object.entries(record) as ([keyof typeof record, number])[]) { if (res[k]) { res[k].push(v); } else { @@ -632,13 +669,12 @@ export default abstract class Chart { return res; } - @autobind - public async getChart(span: 'hour' | 'day', amount: number, cursor: Date | null, group: string | null = null): Promise> { + public async getChart(span: 'hour' | 'day', amount: number, cursor: Date | null, group: string | null = null): Promise>> { const result = await this.getChartRaw(span, amount, cursor, group); const object = {}; for (const [k, v] of Object.entries(result)) { nestedProperty.set(object, k, v); } - return object; + return object as Unflatten>; } } diff --git a/packages/backend/src/services/chart/entities.ts b/packages/backend/src/services/chart/entities.ts index 569b32855..13e994cb6 100644 --- a/packages/backend/src/services/chart/entities.ts +++ b/packages/backend/src/services/chart/entities.ts @@ -1,15 +1,15 @@ -import { entity as FederationChart } from './charts/entities/federation'; -import { entity as NotesChart } from './charts/entities/notes'; -import { entity as UsersChart } from './charts/entities/users'; -import { entity as ActiveUsersChart } from './charts/entities/active-users'; -import { entity as InstanceChart } from './charts/entities/instance'; -import { entity as PerUserNotesChart } from './charts/entities/per-user-notes'; -import { entity as DriveChart } from './charts/entities/drive'; -import { entity as PerUserReactionsChart } from './charts/entities/per-user-reactions'; -import { entity as HashtagChart } from './charts/entities/hashtag'; -import { entity as PerUserFollowingChart } from './charts/entities/per-user-following'; -import { entity as PerUserDriveChart } from './charts/entities/per-user-drive'; -import { entity as ApRequestChart } from './charts/entities/ap-request'; +import { entity as FederationChart } from './charts/entities/federation.js'; +import { entity as NotesChart } from './charts/entities/notes.js'; +import { entity as UsersChart } from './charts/entities/users.js'; +import { entity as ActiveUsersChart } from './charts/entities/active-users.js'; +import { entity as InstanceChart } from './charts/entities/instance.js'; +import { entity as PerUserNotesChart } from './charts/entities/per-user-notes.js'; +import { entity as DriveChart } from './charts/entities/drive.js'; +import { entity as PerUserReactionsChart } from './charts/entities/per-user-reactions.js'; +import { entity as HashtagChart } from './charts/entities/hashtag.js'; +import { entity as PerUserFollowingChart } from './charts/entities/per-user-following.js'; +import { entity as PerUserDriveChart } from './charts/entities/per-user-drive.js'; +import { entity as ApRequestChart } from './charts/entities/ap-request.js'; export const entities = [ FederationChart.hour, FederationChart.day, diff --git a/packages/backend/src/services/chart/index.ts b/packages/backend/src/services/chart/index.ts index 1c0f7aadc..8bf2d8f65 100644 --- a/packages/backend/src/services/chart/index.ts +++ b/packages/backend/src/services/chart/index.ts @@ -1,17 +1,17 @@ -import { beforeShutdown } from '@/misc/before-shutdown'; +import { beforeShutdown } from '@/misc/before-shutdown.js'; -import FederationChart from './charts/federation'; -import NotesChart from './charts/notes'; -import UsersChart from './charts/users'; -import ActiveUsersChart from './charts/active-users'; -import InstanceChart from './charts/instance'; -import PerUserNotesChart from './charts/per-user-notes'; -import DriveChart from './charts/drive'; -import PerUserReactionsChart from './charts/per-user-reactions'; -import HashtagChart from './charts/hashtag'; -import PerUserFollowingChart from './charts/per-user-following'; -import PerUserDriveChart from './charts/per-user-drive'; -import ApRequestChart from './charts/ap-request'; +import FederationChart from './charts/federation.js'; +import NotesChart from './charts/notes.js'; +import UsersChart from './charts/users.js'; +import ActiveUsersChart from './charts/active-users.js'; +import InstanceChart from './charts/instance.js'; +import PerUserNotesChart from './charts/per-user-notes.js'; +import DriveChart from './charts/drive.js'; +import PerUserReactionsChart from './charts/per-user-reactions.js'; +import HashtagChart from './charts/hashtag.js'; +import PerUserFollowingChart from './charts/per-user-following.js'; +import PerUserDriveChart from './charts/per-user-drive.js'; +import ApRequestChart from './charts/ap-request.js'; export const federationChart = new FederationChart(); export const notesChart = new NotesChart(); diff --git a/packages/backend/src/services/create-notification.ts b/packages/backend/src/services/create-notification.ts index 1c1c1fcdf..d78e707ec 100644 --- a/packages/backend/src/services/create-notification.ts +++ b/packages/backend/src/services/create-notification.ts @@ -1,10 +1,10 @@ -import { publishMainStream } from '@/services/stream'; -import pushSw from './push-notification'; -import { Notifications, Mutings, UserProfiles, Users } from '@/models/index'; -import { genId } from '@/misc/gen-id'; -import { User } from '@/models/entities/user'; -import { Notification } from '@/models/entities/notification'; -import { sendEmailNotification } from './send-email-notification'; +import { publishMainStream } from '@/services/stream.js'; +import pushSw from './push-notification.js'; +import { Notifications, Mutings, UserProfiles, Users } from '@/models/index.js'; +import { genId } from '@/misc/gen-id.js'; +import { User } from '@/models/entities/user.js'; +import { Notification } from '@/models/entities/notification.js'; +import { sendEmailNotification } from './send-email-notification.js'; export async function createNotification( notifieeId: User['id'], diff --git a/packages/backend/src/services/create-system-user.ts b/packages/backend/src/services/create-system-user.ts index 82130dd59..781e0560d 100644 --- a/packages/backend/src/services/create-system-user.ts +++ b/packages/backend/src/services/create-system-user.ts @@ -1,13 +1,13 @@ -import * as bcrypt from 'bcryptjs'; +import bcrypt from 'bcryptjs'; import { v4 as uuid } from 'uuid'; -import generateNativeUserToken from '../server/api/common/generate-native-user-token'; -import { genRsaKeyPair } from '@/misc/gen-key-pair'; -import { User } from '@/models/entities/user'; -import { UserProfile } from '@/models/entities/user-profile'; -import { getConnection } from 'typeorm'; -import { genId } from '@/misc/gen-id'; -import { UserKeypair } from '@/models/entities/user-keypair'; -import { UsedUsername } from '@/models/entities/used-username'; +import generateNativeUserToken from '../server/api/common/generate-native-user-token.js'; +import { genRsaKeyPair } from '@/misc/gen-key-pair.js'; +import { User } from '@/models/entities/user.js'; +import { UserProfile } from '@/models/entities/user-profile.js'; +import { getConnection, ObjectLiteral } from 'typeorm'; +import { genId } from '@/misc/gen-id.js'; +import { UserKeypair } from '@/models/entities/user-keypair.js'; +import { UsedUsername } from '@/models/entities/used-username.js'; export async function createSystemUser(username: string) { const password = uuid(); @@ -21,7 +21,7 @@ export async function createSystemUser(username: string) { const keyPair = await genRsaKeyPair(4096); - let account!: User; + let account!: User | ObjectLiteral; // Start transaction await getConnection().transaction(async transactionalEntityManager => { diff --git a/packages/backend/src/services/drive/add-file.ts b/packages/backend/src/services/drive/add-file.ts index 9a8a54390..839794566 100644 --- a/packages/backend/src/services/drive/add-file.ts +++ b/packages/backend/src/services/drive/add-file.ts @@ -1,26 +1,26 @@ -import * as fs from 'fs'; +import * as fs from 'node:fs'; import { v4 as uuid } from 'uuid'; -import { publishMainStream, publishDriveStream } from '@/services/stream'; -import { deleteFile } from './delete-file'; -import { fetchMeta } from '@/misc/fetch-meta'; -import { GenerateVideoThumbnail } from './generate-video-thumbnail'; -import { driveLogger } from './logger'; -import { IImage, convertSharpToJpeg, convertSharpToWebp, convertSharpToPng, convertSharpToPngOrJpeg } from './image-processor'; -import { contentDisposition } from '@/misc/content-disposition'; -import { getFileInfo } from '@/misc/get-file-info'; -import { DriveFiles, DriveFolders, Users, Instances, UserProfiles } from '@/models/index'; -import { InternalStorage } from './internal-storage'; -import { DriveFile } from '@/models/entities/drive-file'; -import { IRemoteUser, User } from '@/models/entities/user'; -import { driveChart, perUserDriveChart, instanceChart } from '@/services/chart/index'; -import { genId } from '@/misc/gen-id'; -import { isDuplicateKeyValueError } from '@/misc/is-duplicate-key-value-error'; -import * as S3 from 'aws-sdk/clients/s3'; -import { getS3 } from './s3'; -import * as sharp from 'sharp'; -import { FILE_TYPE_BROWSERSAFE } from '@/const'; +import { publishMainStream, publishDriveStream } from '@/services/stream.js'; +import { deleteFile } from './delete-file.js'; +import { fetchMeta } from '@/misc/fetch-meta.js'; +import { GenerateVideoThumbnail } from './generate-video-thumbnail.js'; +import { driveLogger } from './logger.js'; +import { IImage, convertSharpToJpeg, convertSharpToWebp, convertSharpToPng, convertSharpToPngOrJpeg } from './image-processor.js'; +import { contentDisposition } from '@/misc/content-disposition.js'; +import { getFileInfo } from '@/misc/get-file-info.js'; +import { DriveFiles, DriveFolders, Users, Instances, UserProfiles } from '@/models/index.js'; +import { InternalStorage } from './internal-storage.js'; +import { DriveFile } from '@/models/entities/drive-file.js'; +import { IRemoteUser, User } from '@/models/entities/user.js'; +import { driveChart, perUserDriveChart, instanceChart } from '@/services/chart/index.js'; +import { genId } from '@/misc/gen-id.js'; +import { isDuplicateKeyValueError } from '@/misc/is-duplicate-key-value-error.js'; +import S3 from 'aws-sdk/clients/s3.js'; +import { getS3 } from './s3.js'; +import sharp from 'sharp'; +import { FILE_TYPE_BROWSERSAFE } from '@/const.js'; const logger = driveLogger.createSubLogger('register', 'yellow'); @@ -484,8 +484,6 @@ export async function addFile({ perUserDriveChart.update(file, true); if (file.userHost !== null) { instanceChart.updateDrive(file, true); - Instances.increment({ host: file.userHost }, 'driveUsage', file.size); - Instances.increment({ host: file.userHost }, 'driveFiles', 1); } return file; diff --git a/packages/backend/src/services/drive/delete-file.ts b/packages/backend/src/services/drive/delete-file.ts index 5cda32c7d..4816a3a31 100644 --- a/packages/backend/src/services/drive/delete-file.ts +++ b/packages/backend/src/services/drive/delete-file.ts @@ -1,10 +1,10 @@ -import { DriveFile } from '@/models/entities/drive-file'; -import { InternalStorage } from './internal-storage'; -import { DriveFiles, Instances } from '@/models/index'; -import { driveChart, perUserDriveChart, instanceChart } from '@/services/chart/index'; -import { createDeleteObjectStorageFileJob } from '@/queue/index'; -import { fetchMeta } from '@/misc/fetch-meta'; -import { getS3 } from './s3'; +import { DriveFile } from '@/models/entities/drive-file.js'; +import { InternalStorage } from './internal-storage.js'; +import { DriveFiles, Instances } from '@/models/index.js'; +import { driveChart, perUserDriveChart, instanceChart } from '@/services/chart/index.js'; +import { createDeleteObjectStorageFileJob } from '@/queue/index.js'; +import { fetchMeta } from '@/misc/fetch-meta.js'; +import { getS3 } from './s3.js'; import { v4 as uuid } from 'uuid'; export async function deleteFile(file: DriveFile, isExpired = false) { @@ -86,8 +86,6 @@ async function postProcess(file: DriveFile, isExpired = false) { perUserDriveChart.update(file, false); if (file.userHost !== null) { instanceChart.updateDrive(file, false); - Instances.decrement({ host: file.userHost }, 'driveUsage', file.size); - Instances.decrement({ host: file.userHost }, 'driveFiles', 1); } } diff --git a/packages/backend/src/services/drive/generate-video-thumbnail.ts b/packages/backend/src/services/drive/generate-video-thumbnail.ts index e8cc952b9..04a7a8334 100644 --- a/packages/backend/src/services/drive/generate-video-thumbnail.ts +++ b/packages/backend/src/services/drive/generate-video-thumbnail.ts @@ -1,6 +1,6 @@ -import * as fs from 'fs'; +import * as fs from 'node:fs'; import * as tmp from 'tmp'; -import { IImage, convertToJpeg } from './image-processor'; +import { IImage, convertToJpeg } from './image-processor.js'; import * as FFmpeg from 'fluent-ffmpeg'; export async function GenerateVideoThumbnail(path: string): Promise { diff --git a/packages/backend/src/services/drive/image-processor.ts b/packages/backend/src/services/drive/image-processor.ts index f3c4a2abd..146dcfb6c 100644 --- a/packages/backend/src/services/drive/image-processor.ts +++ b/packages/backend/src/services/drive/image-processor.ts @@ -1,4 +1,4 @@ -import * as sharp from 'sharp'; +import sharp from 'sharp'; export type IImage = { data: Buffer; diff --git a/packages/backend/src/services/drive/internal-storage.ts b/packages/backend/src/services/drive/internal-storage.ts index fe190a028..8f76c81ca 100644 --- a/packages/backend/src/services/drive/internal-storage.ts +++ b/packages/backend/src/services/drive/internal-storage.ts @@ -1,11 +1,10 @@ -import * as fs from 'fs'; -import * as Path from 'path'; -import { fileURLToPath } from 'url'; -import { dirname } from 'path'; -import config from '@/config/index'; +import * as fs from 'node:fs'; +import * as Path from 'node:path'; +import { fileURLToPath } from 'node:url'; +import { dirname } from 'node:path'; +import config from '@/config/index.js'; -//const _filename = fileURLToPath(import.meta.url); -const _filename = __filename; +const _filename = fileURLToPath(import.meta.url); const _dirname = dirname(_filename); export class InternalStorage { diff --git a/packages/backend/src/services/drive/logger.ts b/packages/backend/src/services/drive/logger.ts index 655d074d6..917a8317e 100644 --- a/packages/backend/src/services/drive/logger.ts +++ b/packages/backend/src/services/drive/logger.ts @@ -1,3 +1,3 @@ -import Logger from '../logger'; +import Logger from '../logger.js'; export const driveLogger = new Logger('drive', 'blue'); diff --git a/packages/backend/src/services/drive/s3.ts b/packages/backend/src/services/drive/s3.ts index 42bf6e187..80e34be95 100644 --- a/packages/backend/src/services/drive/s3.ts +++ b/packages/backend/src/services/drive/s3.ts @@ -1,7 +1,7 @@ -import { URL } from 'url'; -import * as S3 from 'aws-sdk/clients/s3'; -import { Meta } from '@/models/entities/meta'; -import { getAgentByUrl } from '@/misc/fetch'; +import { URL } from 'node:url'; +import S3 from 'aws-sdk/clients/s3.js'; +import { Meta } from '@/models/entities/meta.js'; +import { getAgentByUrl } from '@/misc/fetch.js'; export function getS3(meta: Meta) { const u = meta.objectStorageEndpoint != null diff --git a/packages/backend/src/services/drive/upload-from-url.ts b/packages/backend/src/services/drive/upload-from-url.ts index 7c5fa5ce3..5007fff6e 100644 --- a/packages/backend/src/services/drive/upload-from-url.ts +++ b/packages/backend/src/services/drive/upload-from-url.ts @@ -1,12 +1,12 @@ -import { URL } from 'url'; -import { addFile } from './add-file'; -import { User } from '@/models/entities/user'; -import { driveLogger } from './logger'; -import { createTemp } from '@/misc/create-temp'; -import { downloadUrl } from '@/misc/download-url'; -import { DriveFolder } from '@/models/entities/drive-folder'; -import { DriveFile } from '@/models/entities/drive-file'; -import { DriveFiles } from '@/models/index'; +import { URL } from 'node:url'; +import { addFile } from './add-file.js'; +import { User } from '@/models/entities/user.js'; +import { driveLogger } from './logger.js'; +import { createTemp } from '@/misc/create-temp.js'; +import { downloadUrl } from '@/misc/download-url.js'; +import { DriveFolder } from '@/models/entities/drive-folder.js'; +import { DriveFile } from '@/models/entities/drive-file.js'; +import { DriveFiles } from '@/models/index.js'; const logger = driveLogger.createSubLogger('downloader'); diff --git a/packages/backend/src/services/fetch-instance-metadata.ts b/packages/backend/src/services/fetch-instance-metadata.ts index 2c401508a..f3a0424ab 100644 --- a/packages/backend/src/services/fetch-instance-metadata.ts +++ b/packages/backend/src/services/fetch-instance-metadata.ts @@ -1,11 +1,11 @@ import { DOMWindow, JSDOM } from 'jsdom'; import fetch from 'node-fetch'; -import { getJson, getHtml, getAgentByUrl } from '@/misc/fetch'; -import { Instance } from '@/models/entities/instance'; -import { Instances } from '@/models/index'; -import { getFetchInstanceMetadataLock } from '@/misc/app-lock'; -import Logger from './logger'; -import { URL } from 'url'; +import { getJson, getHtml, getAgentByUrl } from '@/misc/fetch.js'; +import { Instance } from '@/models/entities/instance.js'; +import { Instances } from '@/models/index.js'; +import { getFetchInstanceMetadataLock } from '@/misc/app-lock.js'; +import Logger from './logger.js'; +import { URL } from 'node:url'; const logger = new Logger('metadata', 'cyan'); @@ -156,7 +156,8 @@ async function fetchFaviconUrl(instance: Instance, doc: DOMWindow['document'] | const url = 'https://' + instance.host; if (doc) { - const href = doc.querySelector('link[rel="icon"]')?.getAttribute('href'); + // https://github.com/misskey-dev/misskey/pull/8220#issuecomment-1025104043 + const href = Array.from(doc.getElementsByTagName('link')).reverse().find(link => link.relList.contains('icon'))?.href; if (href) { return (new URL(href, url)).href; @@ -186,11 +187,16 @@ async function fetchIconUrl(instance: Instance, doc: DOMWindow['document'] | nul if (doc) { const url = 'https://' + instance.host; - const hrefAppleTouchIconPrecomposed = doc.querySelector('link[rel="apple-touch-icon-precomposed"]')?.getAttribute('href'); - const hrefAppleTouchIcon = doc.querySelector('link[rel="apple-touch-icon"]')?.getAttribute('href'); - const hrefIcon = doc.querySelector('link[rel="icon"]')?.getAttribute('href'); - - const href = hrefAppleTouchIconPrecomposed || hrefAppleTouchIcon || hrefIcon; + // https://github.com/misskey-dev/misskey/pull/8220#issuecomment-1025104043 + const links = Array.from(doc.getElementsByTagName('link')).reverse(); + // https://github.com/misskey-dev/misskey/pull/8220/files/0ec4eba22a914e31b86874f12448f88b3e58dd5a#r796487559 + const href = + [ + links.find(link => link.relList.contains('apple-touch-icon-precomposed'))?.href, + links.find(link => link.relList.contains('apple-touch-icon'))?.href, + links.find(link => link.relList.contains('icon'))?.href, + ] + .find(href => href); if (href) { return (new URL(href, url)).href; diff --git a/packages/backend/src/services/following/create.ts b/packages/backend/src/services/following/create.ts index bc5ac275b..a41641213 100644 --- a/packages/backend/src/services/following/create.ts +++ b/packages/backend/src/services/following/create.ts @@ -1,20 +1,20 @@ -import { publishMainStream, publishUserEvent } from '@/services/stream'; -import { renderActivity } from '@/remote/activitypub/renderer/index'; -import renderFollow from '@/remote/activitypub/renderer/follow'; -import renderAccept from '@/remote/activitypub/renderer/accept'; -import renderReject from '@/remote/activitypub/renderer/reject'; -import { deliver } from '@/queue/index'; -import createFollowRequest from './requests/create'; -import { registerOrFetchInstanceDoc } from '../register-or-fetch-instance-doc'; -import Logger from '../logger'; -import { IdentifiableError } from '@/misc/identifiable-error'; -import { User } from '@/models/entities/user'; -import { Followings, Users, FollowRequests, Blockings, Instances, UserProfiles } from '@/models/index'; -import { instanceChart, perUserFollowingChart } from '@/services/chart/index'; -import { genId } from '@/misc/gen-id'; -import { createNotification } from '../create-notification'; -import { isDuplicateKeyValueError } from '@/misc/is-duplicate-key-value-error'; -import { Packed } from '@/misc/schema'; +import { publishMainStream, publishUserEvent } from '@/services/stream.js'; +import { renderActivity } from '@/remote/activitypub/renderer/index.js'; +import renderFollow from '@/remote/activitypub/renderer/follow.js'; +import renderAccept from '@/remote/activitypub/renderer/accept.js'; +import renderReject from '@/remote/activitypub/renderer/reject.js'; +import { deliver } from '@/queue/index.js'; +import createFollowRequest from './requests/create.js'; +import { registerOrFetchInstanceDoc } from '../register-or-fetch-instance-doc.js'; +import Logger from '../logger.js'; +import { IdentifiableError } from '@/misc/identifiable-error.js'; +import { User } from '@/models/entities/user.js'; +import { Followings, Users, FollowRequests, Blockings, Instances, UserProfiles } from '@/models/index.js'; +import { instanceChart, perUserFollowingChart } from '@/services/chart/index.js'; +import { genId } from '@/misc/gen-id.js'; +import { createNotification } from '../create-notification.js'; +import { isDuplicateKeyValueError } from '@/misc/is-duplicate-key-value-error.js'; +import { Packed } from '@/misc/schema.js'; const logger = new Logger('following/create'); diff --git a/packages/backend/src/services/following/delete.ts b/packages/backend/src/services/following/delete.ts index 9b7d72e86..d82c0be52 100644 --- a/packages/backend/src/services/following/delete.ts +++ b/packages/backend/src/services/following/delete.ts @@ -1,14 +1,14 @@ -import { publishMainStream, publishUserEvent } from '@/services/stream'; -import { renderActivity } from '@/remote/activitypub/renderer/index'; -import renderFollow from '@/remote/activitypub/renderer/follow'; -import renderUndo from '@/remote/activitypub/renderer/undo'; -import renderReject from '@/remote/activitypub/renderer/reject'; -import { deliver } from '@/queue/index'; -import Logger from '../logger'; -import { registerOrFetchInstanceDoc } from '../register-or-fetch-instance-doc'; -import { User } from '@/models/entities/user'; -import { Followings, Users, Instances } from '@/models/index'; -import { instanceChart, perUserFollowingChart } from '@/services/chart/index'; +import { publishMainStream, publishUserEvent } from '@/services/stream.js'; +import { renderActivity } from '@/remote/activitypub/renderer/index.js'; +import renderFollow from '@/remote/activitypub/renderer/follow.js'; +import renderUndo from '@/remote/activitypub/renderer/undo.js'; +import renderReject from '@/remote/activitypub/renderer/reject.js'; +import { deliver } from '@/queue/index.js'; +import Logger from '../logger.js'; +import { registerOrFetchInstanceDoc } from '../register-or-fetch-instance-doc.js'; +import { User } from '@/models/entities/user.js'; +import { Followings, Users, Instances } from '@/models/index.js'; +import { instanceChart, perUserFollowingChart } from '@/services/chart/index.js'; const logger = new Logger('following/delete'); diff --git a/packages/backend/src/services/following/reject.ts b/packages/backend/src/services/following/reject.ts index 1deabea4f..3b0cb2ba8 100644 --- a/packages/backend/src/services/following/reject.ts +++ b/packages/backend/src/services/following/reject.ts @@ -1,11 +1,11 @@ -import { renderActivity } from '@/remote/activitypub/renderer/index'; -import renderFollow from '@/remote/activitypub/renderer/follow'; -import renderReject from '@/remote/activitypub/renderer/reject'; -import { deliver } from '@/queue/index'; -import { publishMainStream, publishUserEvent } from '@/services/stream'; -import { User, ILocalUser, IRemoteUser } from '@/models/entities/user'; -import { Users, FollowRequests, Followings } from '@/models/index'; -import { decrementFollowing } from './delete'; +import { renderActivity } from '@/remote/activitypub/renderer/index.js'; +import renderFollow from '@/remote/activitypub/renderer/follow.js'; +import renderReject from '@/remote/activitypub/renderer/reject.js'; +import { deliver } from '@/queue/index.js'; +import { publishMainStream, publishUserEvent } from '@/services/stream.js'; +import { User, ILocalUser, IRemoteUser } from '@/models/entities/user.js'; +import { Users, FollowRequests, Followings } from '@/models/index.js'; +import { decrementFollowing } from './delete.js'; type Local = ILocalUser | { id: User['id']; host: User['host']; uri: User['host'] }; type Remote = IRemoteUser; diff --git a/packages/backend/src/services/following/requests/accept-all.ts b/packages/backend/src/services/following/requests/accept-all.ts index 06ff835c0..a240bec8f 100644 --- a/packages/backend/src/services/following/requests/accept-all.ts +++ b/packages/backend/src/services/following/requests/accept-all.ts @@ -1,6 +1,6 @@ -import accept from './accept'; -import { User } from '@/models/entities/user'; -import { FollowRequests, Users } from '@/models/index'; +import accept from './accept.js'; +import { User } from '@/models/entities/user.js'; +import { FollowRequests, Users } from '@/models/index.js'; /** * 指定したユーザー宛てのフォローリクエストをすべて承認 diff --git a/packages/backend/src/services/following/requests/accept.ts b/packages/backend/src/services/following/requests/accept.ts index fcda49758..b8113cd1b 100644 --- a/packages/backend/src/services/following/requests/accept.ts +++ b/packages/backend/src/services/following/requests/accept.ts @@ -1,12 +1,12 @@ -import { renderActivity } from '@/remote/activitypub/renderer/index'; -import renderFollow from '@/remote/activitypub/renderer/follow'; -import renderAccept from '@/remote/activitypub/renderer/accept'; -import { deliver } from '@/queue/index'; -import { publishMainStream } from '@/services/stream'; -import { insertFollowingDoc } from '../create'; -import { User, ILocalUser } from '@/models/entities/user'; -import { FollowRequests, Users } from '@/models/index'; -import { IdentifiableError } from '@/misc/identifiable-error'; +import { renderActivity } from '@/remote/activitypub/renderer/index.js'; +import renderFollow from '@/remote/activitypub/renderer/follow.js'; +import renderAccept from '@/remote/activitypub/renderer/accept.js'; +import { deliver } from '@/queue/index.js'; +import { publishMainStream } from '@/services/stream.js'; +import { insertFollowingDoc } from '../create.js'; +import { User, ILocalUser } from '@/models/entities/user.js'; +import { FollowRequests, Users } from '@/models/index.js'; +import { IdentifiableError } from '@/misc/identifiable-error.js'; export default async function(followee: { id: User['id']; host: User['host']; uri: User['host']; inbox: User['inbox']; sharedInbox: User['sharedInbox']; }, follower: User) { const request = await FollowRequests.findOne({ diff --git a/packages/backend/src/services/following/requests/cancel.ts b/packages/backend/src/services/following/requests/cancel.ts index 53e54f2a1..ca9777d38 100644 --- a/packages/backend/src/services/following/requests/cancel.ts +++ b/packages/backend/src/services/following/requests/cancel.ts @@ -1,11 +1,11 @@ -import { renderActivity } from '@/remote/activitypub/renderer/index'; -import renderFollow from '@/remote/activitypub/renderer/follow'; -import renderUndo from '@/remote/activitypub/renderer/undo'; -import { deliver } from '@/queue/index'; -import { publishMainStream } from '@/services/stream'; -import { IdentifiableError } from '@/misc/identifiable-error'; -import { User, ILocalUser } from '@/models/entities/user'; -import { Users, FollowRequests } from '@/models/index'; +import { renderActivity } from '@/remote/activitypub/renderer/index.js'; +import renderFollow from '@/remote/activitypub/renderer/follow.js'; +import renderUndo from '@/remote/activitypub/renderer/undo.js'; +import { deliver } from '@/queue/index.js'; +import { publishMainStream } from '@/services/stream.js'; +import { IdentifiableError } from '@/misc/identifiable-error.js'; +import { User, ILocalUser } from '@/models/entities/user.js'; +import { Users, FollowRequests } from '@/models/index.js'; export default async function(followee: { id: User['id']; host: User['host']; uri: User['host']; inbox: User['inbox'] }, follower: { id: User['id']; host: User['host']; uri: User['host'] }) { if (Users.isRemoteUser(followee)) { diff --git a/packages/backend/src/services/following/requests/create.ts b/packages/backend/src/services/following/requests/create.ts index e45023015..bca607d7e 100644 --- a/packages/backend/src/services/following/requests/create.ts +++ b/packages/backend/src/services/following/requests/create.ts @@ -1,11 +1,11 @@ -import { publishMainStream } from '@/services/stream'; -import { renderActivity } from '@/remote/activitypub/renderer/index'; -import renderFollow from '@/remote/activitypub/renderer/follow'; -import { deliver } from '@/queue/index'; -import { User } from '@/models/entities/user'; -import { Blockings, FollowRequests, Users } from '@/models/index'; -import { genId } from '@/misc/gen-id'; -import { createNotification } from '../../create-notification'; +import { publishMainStream } from '@/services/stream.js'; +import { renderActivity } from '@/remote/activitypub/renderer/index.js'; +import renderFollow from '@/remote/activitypub/renderer/follow.js'; +import { deliver } from '@/queue/index.js'; +import { User } from '@/models/entities/user.js'; +import { Blockings, FollowRequests, Users } from '@/models/index.js'; +import { genId } from '@/misc/gen-id.js'; +import { createNotification } from '../../create-notification.js'; export default async function(follower: { id: User['id']; host: User['host']; uri: User['host']; inbox: User['inbox']; sharedInbox: User['sharedInbox']; }, followee: { id: User['id']; host: User['host']; uri: User['host']; inbox: User['inbox']; sharedInbox: User['sharedInbox']; }, requestId?: string) { if (follower.id === followee.id) return; diff --git a/packages/backend/src/services/i/pin.ts b/packages/backend/src/services/i/pin.ts index 167dfc10c..06d7e79e8 100644 --- a/packages/backend/src/services/i/pin.ts +++ b/packages/backend/src/services/i/pin.ts @@ -1,15 +1,15 @@ -import config from '@/config/index'; -import renderAdd from '@/remote/activitypub/renderer/add'; -import renderRemove from '@/remote/activitypub/renderer/remove'; -import { renderActivity } from '@/remote/activitypub/renderer/index'; -import { IdentifiableError } from '@/misc/identifiable-error'; -import { User } from '@/models/entities/user'; -import { Note } from '@/models/entities/note'; -import { Notes, UserNotePinings, Users } from '@/models/index'; -import { UserNotePining } from '@/models/entities/user-note-pining'; -import { genId } from '@/misc/gen-id'; -import { deliverToFollowers } from '@/remote/activitypub/deliver-manager'; -import { deliverToRelays } from '../relay'; +import config from '@/config/index.js'; +import renderAdd from '@/remote/activitypub/renderer/add.js'; +import renderRemove from '@/remote/activitypub/renderer/remove.js'; +import { renderActivity } from '@/remote/activitypub/renderer/index.js'; +import { IdentifiableError } from '@/misc/identifiable-error.js'; +import { User } from '@/models/entities/user.js'; +import { Note } from '@/models/entities/note.js'; +import { Notes, UserNotePinings, Users } from '@/models/index.js'; +import { UserNotePining } from '@/models/entities/user-note-pining.js'; +import { genId } from '@/misc/gen-id.js'; +import { deliverToFollowers } from '@/remote/activitypub/deliver-manager.js'; +import { deliverToRelays } from '../relay.js'; /** * 指定した投稿をピン留めします diff --git a/packages/backend/src/services/i/update.ts b/packages/backend/src/services/i/update.ts index f700d9b48..1fbaf40df 100644 --- a/packages/backend/src/services/i/update.ts +++ b/packages/backend/src/services/i/update.ts @@ -1,10 +1,10 @@ -import renderUpdate from '@/remote/activitypub/renderer/update'; -import { renderActivity } from '@/remote/activitypub/renderer/index'; -import { Users } from '@/models/index'; -import { User } from '@/models/entities/user'; -import { renderPerson } from '@/remote/activitypub/renderer/person'; -import { deliverToFollowers } from '@/remote/activitypub/deliver-manager'; -import { deliverToRelays } from '../relay'; +import renderUpdate from '@/remote/activitypub/renderer/update.js'; +import { renderActivity } from '@/remote/activitypub/renderer/index.js'; +import { Users } from '@/models/index.js'; +import { User } from '@/models/entities/user.js'; +import { renderPerson } from '@/remote/activitypub/renderer/person.js'; +import { deliverToFollowers } from '@/remote/activitypub/deliver-manager.js'; +import { deliverToRelays } from '../relay.js'; export async function publishToFollowers(userId: User['id']) { const user = await Users.findOne(userId); diff --git a/packages/backend/src/services/insert-moderation-log.ts b/packages/backend/src/services/insert-moderation-log.ts index affed4095..0a7c472d8 100644 --- a/packages/backend/src/services/insert-moderation-log.ts +++ b/packages/backend/src/services/insert-moderation-log.ts @@ -1,6 +1,6 @@ -import { ModerationLogs } from '@/models/index'; -import { genId } from '@/misc/gen-id'; -import { User } from '@/models/entities/user'; +import { ModerationLogs } from '@/models/index.js'; +import { genId } from '@/misc/gen-id.js'; +import { User } from '@/models/entities/user.js'; export async function insertModerationLog(moderator: { id: User['id'] }, type: string, info?: Record) { await ModerationLogs.insert({ diff --git a/packages/backend/src/services/instance-actor.ts b/packages/backend/src/services/instance-actor.ts index 6f2e32667..e27171048 100644 --- a/packages/backend/src/services/instance-actor.ts +++ b/packages/backend/src/services/instance-actor.ts @@ -1,7 +1,7 @@ -import { createSystemUser } from './create-system-user'; -import { ILocalUser } from '@/models/entities/user'; -import { Users } from '@/models/index'; -import { Cache } from '@/misc/cache'; +import { createSystemUser } from './create-system-user.js'; +import { ILocalUser } from '@/models/entities/user.js'; +import { Users } from '@/models/index.js'; +import { Cache } from '@/misc/cache.js'; const ACTOR_USERNAME = 'instance.actor' as const; diff --git a/packages/backend/src/services/logger.ts b/packages/backend/src/services/logger.ts index 1962088b6..89d6d5720 100644 --- a/packages/backend/src/services/logger.ts +++ b/packages/backend/src/services/logger.ts @@ -1,8 +1,9 @@ -import * as cluster from 'cluster'; -import * as chalk from 'chalk'; +import cluster from 'node:cluster'; +import chalk from 'chalk'; +import { default as convertColor } from 'color-convert'; import { format as dateFormat } from 'date-fns'; -import { envOption } from '../env'; -import config from '@/config/index'; +import { envOption } from '../env.js'; +import config from '@/config/index.js'; import * as SyslogPro from 'syslog-pro'; @@ -66,7 +67,7 @@ export default class Logger { level === 'debug' ? chalk.gray('VERB') : level === 'info' ? chalk.blue('INFO') : null; - const domains = [this.domain].concat(subDomains).map(d => d.color ? chalk.keyword(d.color)(d.name) : chalk.white(d.name)); + const domains = [this.domain].concat(subDomains).map(d => d.color ? chalk.rgb(...convertColor.keyword.rgb(d.color))(d.name) : chalk.white(d.name)); const m = level === 'error' ? chalk.red(message) : level === 'warning' ? chalk.yellow(message) : diff --git a/packages/backend/src/services/messages/create.ts b/packages/backend/src/services/messages/create.ts index e1bef09a7..c3908b255 100644 --- a/packages/backend/src/services/messages/create.ts +++ b/packages/backend/src/services/messages/create.ts @@ -1,19 +1,19 @@ -import { User } from '@/models/entities/user'; -import { UserGroup } from '@/models/entities/user-group'; -import { DriveFile } from '@/models/entities/drive-file'; -import { MessagingMessages, UserGroupJoinings, Mutings, Users } from '@/models/index'; -import { genId } from '@/misc/gen-id'; -import { MessagingMessage } from '@/models/entities/messaging-message'; -import { publishMessagingStream, publishMessagingIndexStream, publishMainStream, publishGroupMessagingStream } from '@/services/stream'; -import pushNotification from '../push-notification'; +import { User } from '@/models/entities/user.js'; +import { UserGroup } from '@/models/entities/user-group.js'; +import { DriveFile } from '@/models/entities/drive-file.js'; +import { MessagingMessages, UserGroupJoinings, Mutings, Users } from '@/models/index.js'; +import { genId } from '@/misc/gen-id.js'; +import { MessagingMessage } from '@/models/entities/messaging-message.js'; +import { publishMessagingStream, publishMessagingIndexStream, publishMainStream, publishGroupMessagingStream } from '@/services/stream.js'; +import pushNotification from '../push-notification.js'; import { Not } from 'typeorm'; -import { Note } from '@/models/entities/note'; -import renderNote from '@/remote/activitypub/renderer/note'; -import renderCreate from '@/remote/activitypub/renderer/create'; -import { renderActivity } from '@/remote/activitypub/renderer/index'; -import { deliver } from '@/queue/index'; +import { Note } from '@/models/entities/note.js'; +import renderNote from '@/remote/activitypub/renderer/note.js'; +import renderCreate from '@/remote/activitypub/renderer/create.js'; +import { renderActivity } from '@/remote/activitypub/renderer/index.js'; +import { deliver } from '@/queue/index.js'; -export async function createMessage(user: { id: User['id']; host: User['host']; }, recipientUser: User | undefined, recipientGroup: UserGroup | undefined, text: string | undefined, file: DriveFile | null, uri?: string) { +export async function createMessage(user: { id: User['id']; host: User['host']; }, recipientUser: User | undefined, recipientGroup: UserGroup | undefined, text: string | null | undefined, file: DriveFile | null, uri?: string) { const message = { id: genId(), createdAt: new Date(), diff --git a/packages/backend/src/services/messages/delete.ts b/packages/backend/src/services/messages/delete.ts index 5c299c9a5..82eb6cb21 100644 --- a/packages/backend/src/services/messages/delete.ts +++ b/packages/backend/src/services/messages/delete.ts @@ -1,11 +1,11 @@ -import config from '@/config/index'; -import { MessagingMessages, Users } from '@/models/index'; -import { MessagingMessage } from '@/models/entities/messaging-message'; -import { publishGroupMessagingStream, publishMessagingStream } from '@/services/stream'; -import { renderActivity } from '@/remote/activitypub/renderer/index'; -import renderDelete from '@/remote/activitypub/renderer/delete'; -import renderTombstone from '@/remote/activitypub/renderer/tombstone'; -import { deliver } from '@/queue/index'; +import config from '@/config/index.js'; +import { MessagingMessages, Users } from '@/models/index.js'; +import { MessagingMessage } from '@/models/entities/messaging-message.js'; +import { publishGroupMessagingStream, publishMessagingStream } from '@/services/stream.js'; +import { renderActivity } from '@/remote/activitypub/renderer/index.js'; +import renderDelete from '@/remote/activitypub/renderer/delete.js'; +import renderTombstone from '@/remote/activitypub/renderer/tombstone.js'; +import { deliver } from '@/queue/index.js'; export async function deleteMessage(message: MessagingMessage) { await MessagingMessages.delete(message.id); diff --git a/packages/backend/src/services/note/create.ts b/packages/backend/src/services/note/create.ts index 7a4c2cef1..8c5f13362 100644 --- a/packages/backend/src/services/note/create.ts +++ b/packages/backend/src/services/note/create.ts @@ -1,39 +1,40 @@ import * as mfm from 'mfm-js'; -import es from '../../db/elasticsearch'; -import { publishMainStream, publishNotesStream } from '@/services/stream'; -import DeliverManager from '@/remote/activitypub/deliver-manager'; -import renderNote from '@/remote/activitypub/renderer/note'; -import renderCreate from '@/remote/activitypub/renderer/create'; -import renderAnnounce from '@/remote/activitypub/renderer/announce'; -import { renderActivity } from '@/remote/activitypub/renderer/index'; -import { resolveUser } from '@/remote/resolve-user'; -import config from '@/config/index'; -import { updateHashtags } from '../update-hashtag'; -import { concat } from '@/prelude/array'; -import { insertNoteUnread } from '@/services/note/unread'; -import { registerOrFetchInstanceDoc } from '../register-or-fetch-instance-doc'; -import { extractMentions } from '@/misc/extract-mentions'; -import { extractCustomEmojisFromMfm } from '@/misc/extract-custom-emojis-from-mfm'; -import { extractHashtags } from '@/misc/extract-hashtags'; -import { Note, IMentionedRemoteUsers } from '@/models/entities/note'; -import { Mutings, Users, NoteWatchings, Notes, Instances, UserProfiles, Antennas, Followings, MutedNotes, Channels, ChannelFollowings, Blockings, NoteThreadMutings } from '@/models/index'; -import { DriveFile } from '@/models/entities/drive-file'; -import { App } from '@/models/entities/app'; +import es from '../../db/elasticsearch.js'; +import { publishMainStream, publishNotesStream } from '@/services/stream.js'; +import DeliverManager from '@/remote/activitypub/deliver-manager.js'; +import renderNote from '@/remote/activitypub/renderer/note.js'; +import renderCreate from '@/remote/activitypub/renderer/create.js'; +import renderAnnounce from '@/remote/activitypub/renderer/announce.js'; +import { renderActivity } from '@/remote/activitypub/renderer/index.js'; +import { resolveUser } from '@/remote/resolve-user.js'; +import config from '@/config/index.js'; +import { updateHashtags } from '../update-hashtag.js'; +import { concat } from '@/prelude/array.js'; +import { insertNoteUnread } from '@/services/note/unread.js'; +import { registerOrFetchInstanceDoc } from '../register-or-fetch-instance-doc.js'; +import { extractMentions } from '@/misc/extract-mentions.js'; +import { extractCustomEmojisFromMfm } from '@/misc/extract-custom-emojis-from-mfm.js'; +import { extractHashtags } from '@/misc/extract-hashtags.js'; +import { Note, IMentionedRemoteUsers } from '@/models/entities/note.js'; +import { Mutings, Users, NoteWatchings, Notes, Instances, UserProfiles, Antennas, Followings, MutedNotes, Channels, ChannelFollowings, Blockings, NoteThreadMutings } from '@/models/index.js'; +import { DriveFile } from '@/models/entities/drive-file.js'; +import { App } from '@/models/entities/app.js'; import { Not, getConnection, In } from 'typeorm'; -import { User, ILocalUser, IRemoteUser } from '@/models/entities/user'; -import { genId } from '@/misc/gen-id'; -import { notesChart, perUserNotesChart, activeUsersChart, instanceChart } from '@/services/chart/index'; -import { Poll, IPoll } from '@/models/entities/poll'; -import { createNotification } from '../create-notification'; -import { isDuplicateKeyValueError } from '@/misc/is-duplicate-key-value-error'; -import { checkHitAntenna } from '@/misc/check-hit-antenna'; -import { checkWordMute } from '@/misc/check-word-mute'; -import { addNoteToAntenna } from '../add-note-to-antenna'; -import { countSameRenotes } from '@/misc/count-same-renotes'; -import { deliverToRelays } from '../relay'; -import { Channel } from '@/models/entities/channel'; -import { normalizeForSearch } from '@/misc/normalize-for-search'; -import { getAntennas } from '@/misc/antenna-cache'; +import { User, ILocalUser, IRemoteUser } from '@/models/entities/user.js'; +import { genId } from '@/misc/gen-id.js'; +import { notesChart, perUserNotesChart, activeUsersChart, instanceChart } from '@/services/chart/index.js'; +import { Poll, IPoll } from '@/models/entities/poll.js'; +import { createNotification } from '../create-notification.js'; +import { isDuplicateKeyValueError } from '@/misc/is-duplicate-key-value-error.js'; +import { checkHitAntenna } from '@/misc/check-hit-antenna.js'; +import { checkWordMute } from '@/misc/check-word-mute.js'; +import { addNoteToAntenna } from '../add-note-to-antenna.js'; +import { countSameRenotes } from '@/misc/count-same-renotes.js'; +import { deliverToRelays } from '../relay.js'; +import { Channel } from '@/models/entities/channel.js'; +import { normalizeForSearch } from '@/misc/normalize-for-search.js'; +import { getAntennas } from '@/misc/antenna-cache.js'; +import { endedPollNotificationQueue } from '@/queue/queues.js'; type NotificationType = 'reply' | 'renote' | 'quote' | 'mention'; @@ -296,6 +297,15 @@ export default async (user: { id: User['id']; username: User['username']; host: incRenoteCount(data.renote); } + if (data.poll && data.poll.expiresAt) { + const delay = data.poll.expiresAt.getTime() - Date.now(); + endedPollNotificationQueue.add({ + noteId: note.id, + }, { + delay + }); + } + if (!silent) { if (Users.isLocalUser(user)) activeUsersChart.write(user); diff --git a/packages/backend/src/services/note/delete.ts b/packages/backend/src/services/note/delete.ts index 77723fe8b..cf23656f8 100644 --- a/packages/backend/src/services/note/delete.ts +++ b/packages/backend/src/services/note/delete.ts @@ -1,18 +1,18 @@ -import { publishNoteStream } from '@/services/stream'; -import renderDelete from '@/remote/activitypub/renderer/delete'; -import renderAnnounce from '@/remote/activitypub/renderer/announce'; -import renderUndo from '@/remote/activitypub/renderer/undo'; -import { renderActivity } from '@/remote/activitypub/renderer/index'; -import renderTombstone from '@/remote/activitypub/renderer/tombstone'; -import config from '@/config/index'; -import { registerOrFetchInstanceDoc } from '../register-or-fetch-instance-doc'; -import { User, ILocalUser, IRemoteUser } from '@/models/entities/user'; -import { Note, IMentionedRemoteUsers } from '@/models/entities/note'; -import { Notes, Users, Instances } from '@/models/index'; -import { notesChart, perUserNotesChart, instanceChart } from '@/services/chart/index'; -import { deliverToFollowers, deliverToUser } from '@/remote/activitypub/deliver-manager'; -import { countSameRenotes } from '@/misc/count-same-renotes'; -import { deliverToRelays } from '../relay'; +import { publishNoteStream } from '@/services/stream.js'; +import renderDelete from '@/remote/activitypub/renderer/delete.js'; +import renderAnnounce from '@/remote/activitypub/renderer/announce.js'; +import renderUndo from '@/remote/activitypub/renderer/undo.js'; +import { renderActivity } from '@/remote/activitypub/renderer/index.js'; +import renderTombstone from '@/remote/activitypub/renderer/tombstone.js'; +import config from '@/config/index.js'; +import { registerOrFetchInstanceDoc } from '../register-or-fetch-instance-doc.js'; +import { User, ILocalUser, IRemoteUser } from '@/models/entities/user.js'; +import { Note, IMentionedRemoteUsers } from '@/models/entities/note.js'; +import { Notes, Users, Instances } from '@/models/index.js'; +import { notesChart, perUserNotesChart, instanceChart } from '@/services/chart/index.js'; +import { deliverToFollowers, deliverToUser } from '@/remote/activitypub/deliver-manager.js'; +import { countSameRenotes } from '@/misc/count-same-renotes.js'; +import { deliverToRelays } from '../relay.js'; import { Brackets, In } from 'typeorm'; /** diff --git a/packages/backend/src/services/note/polls/update.ts b/packages/backend/src/services/note/polls/update.ts index a22ce8e37..88baf16b6 100644 --- a/packages/backend/src/services/note/polls/update.ts +++ b/packages/backend/src/services/note/polls/update.ts @@ -1,10 +1,10 @@ -import renderUpdate from '@/remote/activitypub/renderer/update'; -import { renderActivity } from '@/remote/activitypub/renderer/index'; -import renderNote from '@/remote/activitypub/renderer/note'; -import { Users, Notes } from '@/models/index'; -import { Note } from '@/models/entities/note'; -import { deliverToFollowers } from '@/remote/activitypub/deliver-manager'; -import { deliverToRelays } from '../../relay'; +import renderUpdate from '@/remote/activitypub/renderer/update.js'; +import { renderActivity } from '@/remote/activitypub/renderer/index.js'; +import renderNote from '@/remote/activitypub/renderer/note.js'; +import { Users, Notes } from '@/models/index.js'; +import { Note } from '@/models/entities/note.js'; +import { deliverToFollowers } from '@/remote/activitypub/deliver-manager.js'; +import { deliverToRelays } from '../../relay.js'; export async function deliverQuestionUpdate(noteId: Note['id']) { const note = await Notes.findOne(noteId); diff --git a/packages/backend/src/services/note/polls/vote.ts b/packages/backend/src/services/note/polls/vote.ts index 25c62f3e3..9b83b1953 100644 --- a/packages/backend/src/services/note/polls/vote.ts +++ b/packages/backend/src/services/note/polls/vote.ts @@ -1,10 +1,10 @@ -import { publishNoteStream } from '@/services/stream'; -import { User } from '@/models/entities/user'; -import { Note } from '@/models/entities/note'; -import { PollVotes, NoteWatchings, Polls, Blockings } from '@/models/index'; +import { publishNoteStream } from '@/services/stream.js'; +import { User } from '@/models/entities/user.js'; +import { Note } from '@/models/entities/note.js'; +import { PollVotes, NoteWatchings, Polls, Blockings } from '@/models/index.js'; import { Not } from 'typeorm'; -import { genId } from '@/misc/gen-id'; -import { createNotification } from '../../create-notification'; +import { genId } from '@/misc/gen-id.js'; +import { createNotification } from '../../create-notification.js'; export default async function(user: User, note: Note, choice: number) { const poll = await Polls.findOne(note.id); diff --git a/packages/backend/src/services/note/reaction/create.ts b/packages/backend/src/services/note/reaction/create.ts index c01d43c22..236aa7993 100644 --- a/packages/backend/src/services/note/reaction/create.ts +++ b/packages/backend/src/services/note/reaction/create.ts @@ -1,19 +1,19 @@ -import { publishNoteStream } from '@/services/stream'; -import { renderLike } from '@/remote/activitypub/renderer/like'; -import DeliverManager from '@/remote/activitypub/deliver-manager'; -import { renderActivity } from '@/remote/activitypub/renderer/index'; -import { toDbReaction, decodeReaction } from '@/misc/reaction-lib'; -import { User, IRemoteUser } from '@/models/entities/user'; -import { Note } from '@/models/entities/note'; -import { NoteReactions, Users, NoteWatchings, Notes, Emojis, Blockings } from '@/models/index'; +import { publishNoteStream } from '@/services/stream.js'; +import { renderLike } from '@/remote/activitypub/renderer/like.js'; +import DeliverManager from '@/remote/activitypub/deliver-manager.js'; +import { renderActivity } from '@/remote/activitypub/renderer/index.js'; +import { toDbReaction, decodeReaction } from '@/misc/reaction-lib.js'; +import { User, IRemoteUser } from '@/models/entities/user.js'; +import { Note } from '@/models/entities/note.js'; +import { NoteReactions, Users, NoteWatchings, Notes, Emojis, Blockings } from '@/models/index.js'; import { Not } from 'typeorm'; -import { perUserReactionsChart } from '@/services/chart/index'; -import { genId } from '@/misc/gen-id'; -import { createNotification } from '../../create-notification'; -import deleteReaction from './delete'; -import { isDuplicateKeyValueError } from '@/misc/is-duplicate-key-value-error'; -import { NoteReaction } from '@/models/entities/note-reaction'; -import { IdentifiableError } from '@/misc/identifiable-error'; +import { perUserReactionsChart } from '@/services/chart/index.js'; +import { genId } from '@/misc/gen-id.js'; +import { createNotification } from '../../create-notification.js'; +import deleteReaction from './delete.js'; +import { isDuplicateKeyValueError } from '@/misc/is-duplicate-key-value-error.js'; +import { NoteReaction } from '@/models/entities/note-reaction.js'; +import { IdentifiableError } from '@/misc/identifiable-error.js'; export default async (user: { id: User['id']; host: User['host']; }, note: Note, reaction?: string) => { // Check blocking diff --git a/packages/backend/src/services/note/reaction/delete.ts b/packages/backend/src/services/note/reaction/delete.ts index 21af81953..62b00f56f 100644 --- a/packages/backend/src/services/note/reaction/delete.ts +++ b/packages/backend/src/services/note/reaction/delete.ts @@ -1,13 +1,13 @@ -import { publishNoteStream } from '@/services/stream'; -import { renderLike } from '@/remote/activitypub/renderer/like'; -import renderUndo from '@/remote/activitypub/renderer/undo'; -import { renderActivity } from '@/remote/activitypub/renderer/index'; -import DeliverManager from '@/remote/activitypub/deliver-manager'; -import { IdentifiableError } from '@/misc/identifiable-error'; -import { User, IRemoteUser } from '@/models/entities/user'; -import { Note } from '@/models/entities/note'; -import { NoteReactions, Users, Notes } from '@/models/index'; -import { decodeReaction } from '@/misc/reaction-lib'; +import { publishNoteStream } from '@/services/stream.js'; +import { renderLike } from '@/remote/activitypub/renderer/like.js'; +import renderUndo from '@/remote/activitypub/renderer/undo.js'; +import { renderActivity } from '@/remote/activitypub/renderer/index.js'; +import DeliverManager from '@/remote/activitypub/deliver-manager.js'; +import { IdentifiableError } from '@/misc/identifiable-error.js'; +import { User, IRemoteUser } from '@/models/entities/user.js'; +import { Note } from '@/models/entities/note.js'; +import { NoteReactions, Users, Notes } from '@/models/index.js'; +import { decodeReaction } from '@/misc/reaction-lib.js'; export default async (user: { id: User['id']; host: User['host']; }, note: Note) => { // if already unreacted diff --git a/packages/backend/src/services/note/read.ts b/packages/backend/src/services/note/read.ts index 032f1e84e..28827c596 100644 --- a/packages/backend/src/services/note/read.ts +++ b/packages/backend/src/services/note/read.ts @@ -1,13 +1,13 @@ -import { publishMainStream } from '@/services/stream'; -import { Note } from '@/models/entities/note'; -import { User } from '@/models/entities/user'; -import { NoteUnreads, AntennaNotes, Users, Followings, ChannelFollowings } from '@/models/index'; +import { publishMainStream } from '@/services/stream.js'; +import { Note } from '@/models/entities/note.js'; +import { User } from '@/models/entities/user.js'; +import { NoteUnreads, AntennaNotes, Users, Followings, ChannelFollowings } from '@/models/index.js'; import { Not, IsNull, In } from 'typeorm'; -import { Channel } from '@/models/entities/channel'; -import { checkHitAntenna } from '@/misc/check-hit-antenna'; -import { getAntennas } from '@/misc/antenna-cache'; -import { readNotificationByQuery } from '@/server/api/common/read-notification'; -import { Packed } from '@/misc/schema'; +import { Channel } from '@/models/entities/channel.js'; +import { checkHitAntenna } from '@/misc/check-hit-antenna.js'; +import { getAntennas } from '@/misc/antenna-cache.js'; +import { readNotificationByQuery } from '@/server/api/common/read-notification.js'; +import { Packed } from '@/misc/schema.js'; /** * Mark notes as read diff --git a/packages/backend/src/services/note/unread.ts b/packages/backend/src/services/note/unread.ts index 0b2b5b8d7..ef95dc7e8 100644 --- a/packages/backend/src/services/note/unread.ts +++ b/packages/backend/src/services/note/unread.ts @@ -1,8 +1,8 @@ -import { Note } from '@/models/entities/note'; -import { publishMainStream } from '@/services/stream'; -import { User } from '@/models/entities/user'; -import { Mutings, NoteThreadMutings, NoteUnreads } from '@/models/index'; -import { genId } from '@/misc/gen-id'; +import { Note } from '@/models/entities/note.js'; +import { publishMainStream } from '@/services/stream.js'; +import { User } from '@/models/entities/user.js'; +import { Mutings, NoteThreadMutings, NoteUnreads } from '@/models/index.js'; +import { genId } from '@/misc/gen-id.js'; export async function insertNoteUnread(userId: User['id'], note: Note, params: { // NOTE: isSpecifiedがtrueならisMentionedは必ずfalse diff --git a/packages/backend/src/services/note/unwatch.ts b/packages/backend/src/services/note/unwatch.ts index befdb2aa7..3964b2ba5 100644 --- a/packages/backend/src/services/note/unwatch.ts +++ b/packages/backend/src/services/note/unwatch.ts @@ -1,6 +1,6 @@ -import { User } from '@/models/entities/user'; -import { NoteWatchings } from '@/models/index'; -import { Note } from '@/models/entities/note'; +import { User } from '@/models/entities/user.js'; +import { NoteWatchings } from '@/models/index.js'; +import { Note } from '@/models/entities/note.js'; export default async (me: User['id'], note: Note) => { await NoteWatchings.delete({ diff --git a/packages/backend/src/services/note/watch.ts b/packages/backend/src/services/note/watch.ts index ebaaf3593..2210c44a7 100644 --- a/packages/backend/src/services/note/watch.ts +++ b/packages/backend/src/services/note/watch.ts @@ -1,8 +1,8 @@ -import { User } from '@/models/entities/user'; -import { Note } from '@/models/entities/note'; -import { NoteWatchings } from '@/models/index'; -import { genId } from '@/misc/gen-id'; -import { NoteWatching } from '@/models/entities/note-watching'; +import { User } from '@/models/entities/user.js'; +import { Note } from '@/models/entities/note.js'; +import { NoteWatchings } from '@/models/index.js'; +import { genId } from '@/misc/gen-id.js'; +import { NoteWatching } from '@/models/entities/note-watching.js'; export default async (me: User['id'], note: Note) => { // 自分の投稿はwatchできない diff --git a/packages/backend/src/services/push-notification.ts b/packages/backend/src/services/push-notification.ts index 2133768a9..8d5c09e6a 100644 --- a/packages/backend/src/services/push-notification.ts +++ b/packages/backend/src/services/push-notification.ts @@ -1,9 +1,9 @@ -import * as push from 'web-push'; -import config from '@/config/index'; -import { SwSubscriptions } from '@/models/index'; -import { fetchMeta } from '@/misc/fetch-meta'; -import { Packed } from '@/misc/schema'; -import { getNoteSummary } from '@/misc/get-note-summary'; +import push from 'web-push'; +import config from '@/config/index.js'; +import { SwSubscriptions } from '@/models/index.js'; +import { fetchMeta } from '@/misc/fetch-meta.js'; +import { Packed } from '@/misc/schema.js'; +import { getNoteSummary } from '@/misc/get-note-summary.js'; type notificationType = 'notification' | 'unreadMessagingMessage'; type notificationBody = Packed<'Notification'> | Packed<'MessagingMessage'>; diff --git a/packages/backend/src/services/register-or-fetch-instance-doc.ts b/packages/backend/src/services/register-or-fetch-instance-doc.ts index c42506a2e..152930dbd 100644 --- a/packages/backend/src/services/register-or-fetch-instance-doc.ts +++ b/packages/backend/src/services/register-or-fetch-instance-doc.ts @@ -1,8 +1,8 @@ -import { Instance } from '@/models/entities/instance'; -import { Instances } from '@/models/index'; -import { genId } from '@/misc/gen-id'; -import { toPuny } from '@/misc/convert-host'; -import { Cache } from '@/misc/cache'; +import { Instance } from '@/models/entities/instance.js'; +import { Instances } from '@/models/index.js'; +import { genId } from '@/misc/gen-id.js'; +import { toPuny } from '@/misc/convert-host.js'; +import { Cache } from '@/misc/cache.js'; const cache = new Cache(1000 * 60 * 60); diff --git a/packages/backend/src/services/relay.ts b/packages/backend/src/services/relay.ts index 33a5ef7f9..6f0da503f 100644 --- a/packages/backend/src/services/relay.ts +++ b/packages/backend/src/services/relay.ts @@ -1,11 +1,11 @@ -import { createSystemUser } from './create-system-user'; -import { renderFollowRelay } from '@/remote/activitypub/renderer/follow-relay'; -import { renderActivity, attachLdSignature } from '@/remote/activitypub/renderer/index'; -import renderUndo from '@/remote/activitypub/renderer/undo'; -import { deliver } from '@/queue/index'; -import { ILocalUser, User } from '@/models/entities/user'; -import { Users, Relays } from '@/models/index'; -import { genId } from '@/misc/gen-id'; +import { createSystemUser } from './create-system-user.js'; +import { renderFollowRelay } from '@/remote/activitypub/renderer/follow-relay.js'; +import { renderActivity, attachLdSignature } from '@/remote/activitypub/renderer/index.js'; +import renderUndo from '@/remote/activitypub/renderer/undo.js'; +import { deliver } from '@/queue/index.js'; +import { ILocalUser, User } from '@/models/entities/user.js'; +import { Users, Relays } from '@/models/index.js'; +import { genId } from '@/misc/gen-id.js'; const ACTOR_USERNAME = 'relay.actor' as const; diff --git a/packages/backend/src/services/send-email-notification.ts b/packages/backend/src/services/send-email-notification.ts index 157bacb46..debaf3476 100644 --- a/packages/backend/src/services/send-email-notification.ts +++ b/packages/backend/src/services/send-email-notification.ts @@ -1,28 +1,33 @@ -import { UserProfiles } from '@/models/index'; -import { User } from '@/models/entities/user'; -import { sendEmail } from './send-email'; -import { I18n } from '@/misc/i18n'; -import * as Acct from 'misskey-js/built/acct'; -const locales = require('../../../../locales/index.js'); +import { UserProfiles } from '@/models/index.js'; +import { User } from '@/models/entities/user.js'; +import { sendEmail } from './send-email.js'; +import { I18n } from '@/misc/i18n.js'; +import * as Acct from '@/misc/acct.js'; +// TODO +//const locales = await import('../../../../locales/index.js'); // TODO: locale ファイルをクライアント用とサーバー用で分けたい async function follow(userId: User['id'], follower: User) { + /* 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); // TODO: render user information html sendEmail(userProfile.email, i18n.t('_email._follow.title'), `${follower.name} (@${Acct.toString(follower)})`, `${follower.name} (@${Acct.toString(follower)})`); + */ } async function receiveFollowRequest(userId: User['id'], follower: User) { + /* 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); // TODO: render user information html sendEmail(userProfile.email, i18n.t('_email._receiveFollowRequest.title'), `${follower.name} (@${Acct.toString(follower)})`, `${follower.name} (@${Acct.toString(follower)})`); + */ } export const sendEmailNotification = { diff --git a/packages/backend/src/services/send-email.ts b/packages/backend/src/services/send-email.ts index 1fd406cb6..b35d22548 100644 --- a/packages/backend/src/services/send-email.ts +++ b/packages/backend/src/services/send-email.ts @@ -1,7 +1,7 @@ import * as nodemailer from 'nodemailer'; -import { fetchMeta } from '@/misc/fetch-meta'; -import Logger from './logger'; -import config from '@/config/index'; +import { fetchMeta } from '@/misc/fetch-meta.js'; +import Logger from './logger.js'; +import config from '@/config/index.js'; export const logger = new Logger('email'); diff --git a/packages/backend/src/services/stream.ts b/packages/backend/src/services/stream.ts index c0cefe9af..9fa2b9713 100644 --- a/packages/backend/src/services/stream.ts +++ b/packages/backend/src/services/stream.ts @@ -1,11 +1,11 @@ -import { redisClient } from '../db/redis'; -import { User } from '@/models/entities/user'; -import { Note } from '@/models/entities/note'; -import { UserList } from '@/models/entities/user-list'; -import { UserGroup } from '@/models/entities/user-group'; -import config from '@/config/index'; -import { Antenna } from '@/models/entities/antenna'; -import { Channel } from '@/models/entities/channel'; +import { redisClient } from '../db/redis.js'; +import { User } from '@/models/entities/user.js'; +import { Note } from '@/models/entities/note.js'; +import { UserList } from '@/models/entities/user-list.js'; +import { UserGroup } from '@/models/entities/user-group.js'; +import config from '@/config/index.js'; +import { Antenna } from '@/models/entities/antenna.js'; +import { Channel } from '@/models/entities/channel.js'; import { StreamChannels, AdminStreamTypes, @@ -21,8 +21,8 @@ import { NoteStreamTypes, UserListStreamTypes, UserStreamTypes, -} from '@/server/api/stream/types'; -import { Packed } from '@/misc/schema'; +} from '@/server/api/stream/types.js'; +import { Packed } from '@/misc/schema.js'; class Publisher { private publish = (channel: StreamChannels, type: string | null, value?: any): void => { diff --git a/packages/backend/src/services/suspend-user.ts b/packages/backend/src/services/suspend-user.ts index 262c8df5b..033311a3c 100644 --- a/packages/backend/src/services/suspend-user.ts +++ b/packages/backend/src/services/suspend-user.ts @@ -1,9 +1,9 @@ -import renderDelete from '@/remote/activitypub/renderer/delete'; -import { renderActivity } from '@/remote/activitypub/renderer/index'; -import { deliver } from '@/queue/index'; -import config from '@/config/index'; -import { User } from '@/models/entities/user'; -import { Users, Followings } from '@/models/index'; +import renderDelete from '@/remote/activitypub/renderer/delete.js'; +import { renderActivity } from '@/remote/activitypub/renderer/index.js'; +import { deliver } from '@/queue/index.js'; +import config from '@/config/index.js'; +import { User } from '@/models/entities/user.js'; +import { Users, Followings } from '@/models/index.js'; import { Not, IsNull } from 'typeorm'; export async function doPostSuspend(user: { id: User['id']; host: User['host'] }) { diff --git a/packages/backend/src/services/unsuspend-user.ts b/packages/backend/src/services/unsuspend-user.ts index 04ad65a36..3be081d0e 100644 --- a/packages/backend/src/services/unsuspend-user.ts +++ b/packages/backend/src/services/unsuspend-user.ts @@ -1,10 +1,10 @@ -import renderDelete from '@/remote/activitypub/renderer/delete'; -import renderUndo from '@/remote/activitypub/renderer/undo'; -import { renderActivity } from '@/remote/activitypub/renderer/index'; -import { deliver } from '@/queue/index'; -import config from '@/config/index'; -import { User } from '@/models/entities/user'; -import { Users, Followings } from '@/models/index'; +import renderDelete from '@/remote/activitypub/renderer/delete.js'; +import renderUndo from '@/remote/activitypub/renderer/undo.js'; +import { renderActivity } from '@/remote/activitypub/renderer/index.js'; +import { deliver } from '@/queue/index.js'; +import config from '@/config/index.js'; +import { User } from '@/models/entities/user.js'; +import { Users, Followings } from '@/models/index.js'; import { Not, IsNull } from 'typeorm'; export async function doPostUnsuspend(user: User) { diff --git a/packages/backend/src/services/update-hashtag.ts b/packages/backend/src/services/update-hashtag.ts index e8504f6ff..b6fb38bc5 100644 --- a/packages/backend/src/services/update-hashtag.ts +++ b/packages/backend/src/services/update-hashtag.ts @@ -1,9 +1,9 @@ -import { User } from '@/models/entities/user'; -import { Hashtags, Users } from '@/models/index'; -import { hashtagChart } from '@/services/chart/index'; -import { genId } from '@/misc/gen-id'; -import { Hashtag } from '@/models/entities/hashtag'; -import { normalizeForSearch } from '@/misc/normalize-for-search'; +import { User } from '@/models/entities/user.js'; +import { Hashtags, Users } from '@/models/index.js'; +import { hashtagChart } from '@/services/chart/index.js'; +import { genId } from '@/misc/gen-id.js'; +import { Hashtag } from '@/models/entities/hashtag.js'; +import { normalizeForSearch } from '@/misc/normalize-for-search.js'; export async function updateHashtags(user: { id: User['id']; host: User['host']; }, tags: string[]) { for (const tag of tags) { diff --git a/packages/backend/src/services/user-list/push.ts b/packages/backend/src/services/user-list/push.ts index 2b862ca9c..d073afcd3 100644 --- a/packages/backend/src/services/user-list/push.ts +++ b/packages/backend/src/services/user-list/push.ts @@ -1,11 +1,11 @@ -import { publishUserListStream } from '@/services/stream'; -import { User } from '@/models/entities/user'; -import { UserList } from '@/models/entities/user-list'; -import { UserListJoinings, Users } from '@/models/index'; -import { UserListJoining } from '@/models/entities/user-list-joining'; -import { genId } from '@/misc/gen-id'; -import { fetchProxyAccount } from '@/misc/fetch-proxy-account'; -import createFollowing from '../following/create'; +import { publishUserListStream } from '@/services/stream.js'; +import { User } from '@/models/entities/user.js'; +import { UserList } from '@/models/entities/user-list.js'; +import { UserListJoinings, Users } from '@/models/index.js'; +import { UserListJoining } from '@/models/entities/user-list-joining.js'; +import { genId } from '@/misc/gen-id.js'; +import { fetchProxyAccount } from '@/misc/fetch-proxy-account.js'; +import createFollowing from '../following/create.js'; export async function pushUserToUserList(target: User, list: UserList) { await UserListJoinings.insert({ diff --git a/packages/backend/src/services/validate-email-for-account.ts b/packages/backend/src/services/validate-email-for-account.ts index 1d039fb26..3c49d37ee 100644 --- a/packages/backend/src/services/validate-email-for-account.ts +++ b/packages/backend/src/services/validate-email-for-account.ts @@ -1,5 +1,5 @@ import validateEmail from 'deep-email-validator'; -import { UserProfiles } from '@/models'; +import { UserProfiles } from '@/models/index.js'; export async function validateEmailForAccount(emailAddress: string): Promise<{ available: boolean; diff --git a/packages/backend/src/tools/accept-migration.ts b/packages/backend/src/tools/accept-migration.ts index 2e54fc129..adbfcdadf 100644 --- a/packages/backend/src/tools/accept-migration.ts +++ b/packages/backend/src/tools/accept-migration.ts @@ -1,7 +1,7 @@ // ex) node built/tools/accept-migration Yo 1000000000001 import { createConnection } from 'typeorm'; -import config from '@/config/index'; +import config from '@/config/index.js'; createConnection({ type: 'postgres', diff --git a/packages/backend/src/tools/demote-admin.ts b/packages/backend/src/tools/demote-admin.ts index 45e32b513..7f6722247 100644 --- a/packages/backend/src/tools/demote-admin.ts +++ b/packages/backend/src/tools/demote-admin.ts @@ -1,4 +1,4 @@ -import { initDb } from '../db/postgre'; +import { initDb } from '../db/postgre.js'; async function main(username: string) { if (!username) throw `username required`; diff --git a/packages/backend/src/tools/mark-admin.ts b/packages/backend/src/tools/mark-admin.ts index 88d59518a..630179e7a 100644 --- a/packages/backend/src/tools/mark-admin.ts +++ b/packages/backend/src/tools/mark-admin.ts @@ -1,4 +1,4 @@ -import { initDb } from '../db/postgre'; +import { initDb } from '../db/postgre.js'; async function main(username: string) { if (!username) throw `username required`; diff --git a/packages/backend/src/tools/refresh-question.ts b/packages/backend/src/tools/refresh-question.ts index 3bbb781ae..0111a2257 100644 --- a/packages/backend/src/tools/refresh-question.ts +++ b/packages/backend/src/tools/refresh-question.ts @@ -1,4 +1,4 @@ -import { initDb } from '@/db/postgre'; +import { initDb } from '@/db/postgre.js'; async function main(uri: string): Promise { await initDb(); diff --git a/packages/backend/src/tools/resync-remote-user.ts b/packages/backend/src/tools/resync-remote-user.ts index 22d2f7c89..8c02ef7ef 100644 --- a/packages/backend/src/tools/resync-remote-user.ts +++ b/packages/backend/src/tools/resync-remote-user.ts @@ -1,5 +1,5 @@ -import { initDb } from '@/db/postgre'; -import * as Acct from 'misskey-js/built/acct'; +import { initDb } from '@/db/postgre.js'; +import * as Acct from '@/misc/acct.js'; async function main(acct: string): Promise { await initDb(); diff --git a/packages/backend/src/tools/show-signin-history.ts b/packages/backend/src/tools/show-signin-history.ts index 7db84ece0..c3388fd1b 100644 --- a/packages/backend/src/tools/show-signin-history.ts +++ b/packages/backend/src/tools/show-signin-history.ts @@ -1,4 +1,4 @@ -import { initDb } from '@/db/postgre'; +import { initDb } from '@/db/postgre.js'; // node built/tools/show-signin-history username // => {Success} {Date} {IPAddrsss} diff --git a/packages/backend/src/types.ts b/packages/backend/src/types.ts index 20f6f8bb8..573e2faf8 100644 --- a/packages/backend/src/types.ts +++ b/packages/backend/src/types.ts @@ -1,4 +1,4 @@ -export const notificationTypes = ['follow', 'mention', 'reply', 'renote', 'quote', 'reaction', 'pollVote', 'receiveFollowRequest', 'followRequestAccepted', 'groupInvited', 'app'] as const; +export const notificationTypes = ['follow', 'mention', 'reply', 'renote', 'quote', 'reaction', 'pollVote', 'pollEnded', 'receiveFollowRequest', 'followRequestAccepted', 'groupInvited', 'app'] as const; export const noteVisibilities = ['public', 'home', 'followers', 'specified'] as const; diff --git a/packages/backend/test/activitypub.ts b/packages/backend/test/activitypub.ts index 777e7f355..70f35cafd 100644 --- a/packages/backend/test/activitypub.ts +++ b/packages/backend/test/activitypub.ts @@ -2,7 +2,7 @@ process.env.NODE_ENV = 'test'; import rndstr from 'rndstr'; import * as assert from 'assert'; -import { initTestDb } from './utils'; +import { initTestDb } from './utils.js'; describe('ActivityPub', () => { before(async () => { @@ -33,8 +33,8 @@ describe('ActivityPub', () => { }; it('Minimum Actor', async () => { - const { MockResolver } = await import('./misc/mock-resolver'); - const { createPerson } = await import('../src/remote/activitypub/models/person'); + const { MockResolver } = await import('./misc/mock-resolver.js'); + const { createPerson } = await import('../src/remote/activitypub/models/person.js'); const resolver = new MockResolver(); resolver._register(actor.id, actor); @@ -47,8 +47,8 @@ describe('ActivityPub', () => { }); it('Minimum Note', async () => { - const { MockResolver } = await import('./misc/mock-resolver'); - const { createNote } = await import('../src/remote/activitypub/models/note'); + const { MockResolver } = await import('./misc/mock-resolver.js'); + const { createNote } = await import('../src/remote/activitypub/models/note.js'); const resolver = new MockResolver(); resolver._register(actor.id, actor); @@ -80,8 +80,8 @@ describe('ActivityPub', () => { }; it('Actor', async () => { - const { MockResolver } = await import('./misc/mock-resolver'); - const { createPerson } = await import('../src/remote/activitypub/models/person'); + const { MockResolver } = await import('./misc/mock-resolver.js'); + const { createPerson } = await import('../src/remote/activitypub/models/person.js'); const resolver = new MockResolver(); resolver._register(actor.id, actor); diff --git a/packages/backend/test/ap-request.ts b/packages/backend/test/ap-request.ts index 4a9799eb9..48f4fceb5 100644 --- a/packages/backend/test/ap-request.ts +++ b/packages/backend/test/ap-request.ts @@ -1,7 +1,7 @@ import * as assert from 'assert'; -import { genRsaKeyPair } from '../src/misc/gen-key-pair'; -import { createSignedPost, createSignedGet } from '../src/remote/activitypub/ap-request'; -const httpSignature = require('http-signature'); +import { genRsaKeyPair } from '../src/misc/gen-key-pair.js'; +import { createSignedPost, createSignedGet } from '../src/remote/activitypub/ap-request.js'; +import httpSignature from 'http-signature'; export const buildParsedSignature = (signingString: string, signature: string, algorithm: string) => { return { diff --git a/packages/backend/test/api-visibility.ts b/packages/backend/test/api-visibility.ts index ade7b730b..d946191be 100644 --- a/packages/backend/test/api-visibility.ts +++ b/packages/backend/test/api-visibility.ts @@ -2,7 +2,7 @@ process.env.NODE_ENV = 'test'; import * as assert from 'assert'; import * as childProcess from 'child_process'; -import { async, signup, request, post, startServer, shutdownServer } from './utils'; +import { async, signup, request, post, startServer, shutdownServer } from './utils.js'; describe('API visibility', () => { let p: childProcess.ChildProcess; diff --git a/packages/backend/test/api.ts b/packages/backend/test/api.ts index 99fb196dc..b1b2ecafc 100644 --- a/packages/backend/test/api.ts +++ b/packages/backend/test/api.ts @@ -1,970 +1,83 @@ -/* process.env.NODE_ENV = 'test'; import * as assert from 'assert'; import * as childProcess from 'child_process'; -import { async, signup, request, post, react, uploadFile } from './utils'; +import { async, signup, request, post, react, uploadFile, startServer, shutdownServer } from './utils.js'; describe('API', () => { let p: childProcess.ChildProcess; + let alice: any; + let bob: any; + let carol: any; - beforeEach(done => { - p = childProcess.spawn('node', [__dirname + '/../index.js'], { - stdio: ['inherit', 'inherit', 'ipc'], - env: { NODE_ENV: 'test' } - }); - p.on('message', message => { - if (message === 'ok') { - done(); - } - }); + before(async () => { + p = await startServer(); + alice = await signup({ username: 'alice' }); + bob = await signup({ username: 'bob' }); + carol = await signup({ username: 'carol' }); }); - afterEach(() => { - p.kill(); + after(async () => { + await shutdownServer(p); }); - describe('signup', () => { - it('不正なユーザー名でアカウントが作成できない', async(async () => { - const res = await request('/signup', { - username: 'test.', - password: 'test' + describe('General validation', () => { + it('wrong type', async(async () => { + const res = await request('/test', { + required: true, + string: 42, }); assert.strictEqual(res.status, 400); })); - it('空のパスワードでアカウントが作成できない', async(async () => { - const res = await request('/signup', { - username: 'test', - password: '' + it('missing require param', async(async () => { + const res = await request('/test', { + string: 'a', }); assert.strictEqual(res.status, 400); })); - it('正しくアカウントが作成できる', async(async () => { - const me = { - username: 'test', - password: 'test' - }; - - const res = await request('/signup', me); - - assert.strictEqual(res.status, 200); - assert.strictEqual(typeof res.body === 'object' && !Array.isArray(res.body), true); - assert.strictEqual(res.body.username, me.username); - })); - - it('同じユーザー名のアカウントは作成できない', async(async () => { - await signup({ - username: 'test' - }); - - const res = await request('/signup', { - username: 'test', - password: 'test' - }); - - assert.strictEqual(res.status, 400); - })); - }); - - describe('signin', () => { - it('間違ったパスワードでサインインできない', async(async () => { - await signup({ - username: 'test', - password: 'foo' - }); - - const res = await request('/signin', { - username: 'test', - password: 'bar' - }); - - assert.strictEqual(res.status, 403); - })); - - it('クエリをインジェクションできない', async(async () => { - await signup({ - username: 'test' - }); - - const res = await request('/signin', { - username: 'test', - password: { - $gt: '' - } - }); - - assert.strictEqual(res.status, 400); - })); - - it('正しい情報でサインインできる', async(async () => { - await signup({ - username: 'test', - password: 'foo' - }); - - const res = await request('/signin', { - username: 'test', - password: 'foo' - }); - - assert.strictEqual(res.status, 200); - })); - }); - - describe('i/update', () => { - it('アカウント設定を更新できる', async(async () => { - const me = await signup(); - - const myName = '大室櫻子'; - const myLocation = '七森中'; - const myBirthday = '2000-09-07'; - - const res = await request('/i/update', { - name: myName, - location: myLocation, - birthday: myBirthday - }, me); - - assert.strictEqual(res.status, 200); - assert.strictEqual(typeof res.body === 'object' && !Array.isArray(res.body), true); - assert.strictEqual(res.body.name, myName); - assert.strictEqual(res.body.location, myLocation); - assert.strictEqual(res.body.birthday, myBirthday); - })); - - it('名前を空白にできない', async(async () => { - const me = await signup(); - const res = await request('/i/update', { - name: ' ' - }, me); - assert.strictEqual(res.status, 400); - })); - - it('誕生日の設定を削除できる', async(async () => { - const me = await signup(); - await request('/i/update', { - birthday: '2000-09-07' - }, me); - - const res = await request('/i/update', { - birthday: null - }, me); - - assert.strictEqual(res.status, 200); - assert.strictEqual(typeof res.body === 'object' && !Array.isArray(res.body), true); - assert.strictEqual(res.body.birthday, null); - })); - - it('不正な誕生日の形式で怒られる', async(async () => { - const me = await signup(); - const res = await request('/i/update', { - birthday: '2000/09/07' - }, me); - assert.strictEqual(res.status, 400); - })); - }); - - describe('users/show', () => { - it('ユーザーが取得できる', async(async () => { - const me = await signup(); - - const res = await request('/users/show', { - userId: me.id - }, me); - - assert.strictEqual(res.status, 200); - assert.strictEqual(typeof res.body === 'object' && !Array.isArray(res.body), true); - assert.strictEqual(res.body.id, me.id); - })); - - it('ユーザーが存在しなかったら怒る', async(async () => { - const res = await request('/users/show', { - userId: '000000000000000000000000' + it('invalid misskey:id (empty string)', async(async () => { + const res = await request('/test', { + required: true, + id: '', }); assert.strictEqual(res.status, 400); })); - it('間違ったIDで怒られる', async(async () => { - const res = await request('/users/show', { - userId: 'kyoppie' + it('valid misskey:id', async(async () => { + const res = await request('/test', { + required: true, + id: '8wvhjghbxu', }); - assert.strictEqual(res.status, 400); + assert.strictEqual(res.status, 200); })); - }); - describe('notes/show', () => { - it('投稿が取得できる', async(async () => { - const me = await signup(); - const myPost = await post(me, { - text: 'test' + it('default value', async(async () => { + const res = await request('/test', { + required: true, + string: 'a', }); - - const res = await request('/notes/show', { - noteId: myPost.id - }, me); - assert.strictEqual(res.status, 200); - assert.strictEqual(typeof res.body === 'object' && !Array.isArray(res.body), true); - assert.strictEqual(res.body.id, myPost.id); - assert.strictEqual(res.body.text, myPost.text); + assert.strictEqual(res.body.default, 'hello'); })); - it('投稿が存在しなかったら怒る', async(async () => { - const res = await request('/notes/show', { - noteId: '000000000000000000000000' + it('can set null even if it has default value', async(async () => { + const res = await request('/test', { + required: true, + nullableDefault: null, }); - assert.strictEqual(res.status, 400); + assert.strictEqual(res.status, 200); + assert.strictEqual(res.body.nullableDefault, null); })); - it('間違ったIDで怒られる', async(async () => { - const res = await request('/notes/show', { - noteId: 'kyoppie' + it('cannot set undefined if it has default value', async(async () => { + const res = await request('/test', { + required: true, + nullableDefault: undefined, }); - assert.strictEqual(res.status, 400); - })); - }); - - describe('notes/reactions/create', () => { - it('リアクションできる', async(async () => { - const bob = await signup({ username: 'bob' }); - const bobPost = await post(bob); - - const alice = await signup({ username: 'alice' }); - const res = await request('/notes/reactions/create', { - noteId: bobPost.id, - reaction: 'like' - }, alice); - - assert.strictEqual(res.status, 204); - })); - - it('自分の投稿にはリアクションできない', async(async () => { - const me = await signup(); - const myPost = await post(me); - - const res = await request('/notes/reactions/create', { - noteId: myPost.id, - reaction: 'like' - }, me); - - assert.strictEqual(res.status, 400); - })); - - it('二重にリアクションできない', async(async () => { - const bob = await signup({ username: 'bob' }); - const bobPost = await post(bob); - - const alice = await signup({ username: 'alice' }); - await react(alice, bobPost, 'like'); - - const res = await request('/notes/reactions/create', { - noteId: bobPost.id, - reaction: 'like' - }, alice); - - assert.strictEqual(res.status, 400); - })); - - it('存在しない投稿にはリアクションできない', async(async () => { - const me = await signup(); - - const res = await request('/notes/reactions/create', { - noteId: '000000000000000000000000', - reaction: 'like' - }, me); - - assert.strictEqual(res.status, 400); - })); - - it('空のパラメータで怒られる', async(async () => { - const me = await signup(); - - const res = await request('/notes/reactions/create', {}, me); - - assert.strictEqual(res.status, 400); - })); - - it('間違ったIDで怒られる', async(async () => { - const me = await signup(); - - const res = await request('/notes/reactions/create', { - noteId: 'kyoppie', - reaction: 'like' - }, me); - - assert.strictEqual(res.status, 400); - })); - }); - - describe('following/create', () => { - it('フォローできる', async(async () => { - const alice = await signup({ username: 'alice' }); - const bob = await signup({ username: 'bob' }); - - const res = await request('/following/create', { - userId: alice.id - }, bob); - assert.strictEqual(res.status, 200); - })); - - it('既にフォローしている場合は怒る', async(async () => { - const alice = await signup({ username: 'alice' }); - const bob = await signup({ username: 'bob' }); - await request('/following/create', { - userId: alice.id - }, bob); - - const res = await request('/following/create', { - userId: alice.id - }, bob); - - assert.strictEqual(res.status, 400); - })); - - it('存在しないユーザーはフォローできない', async(async () => { - const alice = await signup({ username: 'alice' }); - - const res = await request('/following/create', { - userId: '000000000000000000000000' - }, alice); - - assert.strictEqual(res.status, 400); - })); - - it('自分自身はフォローできない', async(async () => { - const alice = await signup({ username: 'alice' }); - - const res = await request('/following/create', { - userId: alice.id - }, alice); - - assert.strictEqual(res.status, 400); - })); - - it('空のパラメータで怒られる', async(async () => { - const alice = await signup({ username: 'alice' }); - - const res = await request('/following/create', {}, alice); - - assert.strictEqual(res.status, 400); - })); - - it('間違ったIDで怒られる', async(async () => { - const alice = await signup({ username: 'alice' }); - - const res = await request('/following/create', { - userId: 'foo' - }, alice); - - assert.strictEqual(res.status, 400); - })); - }); - - describe('following/delete', () => { - it('フォロー解除できる', async(async () => { - const alice = await signup({ username: 'alice' }); - const bob = await signup({ username: 'bob' }); - await request('/following/create', { - userId: alice.id - }, bob); - - const res = await request('/following/delete', { - userId: alice.id - }, bob); - - assert.strictEqual(res.status, 200); - })); - - it('フォローしていない場合は怒る', async(async () => { - const alice = await signup({ username: 'alice' }); - const bob = await signup({ username: 'bob' }); - - const res = await request('/following/delete', { - userId: alice.id - }, bob); - - assert.strictEqual(res.status, 400); - })); - - it('存在しないユーザーはフォロー解除できない', async(async () => { - const alice = await signup({ username: 'alice' }); - - const res = await request('/following/delete', { - userId: '000000000000000000000000' - }, alice); - - assert.strictEqual(res.status, 400); - })); - - it('自分自身はフォロー解除できない', async(async () => { - const alice = await signup({ username: 'alice' }); - - const res = await request('/following/delete', { - userId: alice.id - }, alice); - - assert.strictEqual(res.status, 400); - })); - - it('空のパラメータで怒られる', async(async () => { - const alice = await signup({ username: 'alice' }); - - const res = await request('/following/delete', {}, alice); - - assert.strictEqual(res.status, 400); - })); - - it('間違ったIDで怒られる', async(async () => { - const alice = await signup({ username: 'alice' }); - - const res = await request('/following/delete', { - userId: 'kyoppie' - }, alice); - - assert.strictEqual(res.status, 400); - })); - }); - - describe('drive', () => { - it('ドライブ情報を取得できる', async(async () => { - const bob = await signup({ username: 'bob' }); - await uploadFile({ - userId: me.id, - size: 256 - }); - await uploadFile({ - userId: me.id, - size: 512 - }); - await uploadFile({ - userId: me.id, - size: 1024 - }); - const res = await request('/drive', {}, me); - assert.strictEqual(res.status, 200); - assert.strictEqual(typeof res.body === 'object' && !Array.isArray(res.body), true); - expect(res.body).have.property('usage').eql(1792); - })); - }); - - describe('drive/files/create', () => { - it('ファイルを作成できる', async(async () => { - const alice = await signup({ username: 'alice' }); - - const res = await uploadFile(alice); - - assert.strictEqual(res.status, 200); - assert.strictEqual(typeof res.body === 'object' && !Array.isArray(res.body), true); - assert.strictEqual(res.body.name, 'Lenna.png'); - })); - - it('ファイルに名前を付けられる', async(async () => { - const alice = await signup({ username: 'alice' }); - - const res = await assert.request(server) - .post('/drive/files/create') - .field('i', alice.token) - .field('name', 'Belmond.png') - .attach('file', fs.readFileSync(__dirname + '/resources/Lenna.png'), 'Lenna.png'); - - expect(res).have.status(200); - expect(res.body).be.a('object'); - expect(res.body).have.property('name').eql('Belmond.png'); - })); - - it('ファイル無しで怒られる', async(async () => { - const alice = await signup({ username: 'alice' }); - - const res = await request('/drive/files/create', {}, alice); - - assert.strictEqual(res.status, 400); - })); - - it('SVGファイルを作成できる', async(async () => { - const izumi = await signup({ username: 'izumi' }); - - const res = await uploadFile(izumi, __dirname + '/resources/image.svg'); - - assert.strictEqual(res.status, 200); - assert.strictEqual(typeof res.body === 'object' && !Array.isArray(res.body), true); - assert.strictEqual(res.body.name, 'image.svg'); - assert.strictEqual(res.body.type, 'image/svg+xml'); - })); - }); - - describe('drive/files/update', () => { - it('名前を更新できる', async(async () => { - const alice = await signup({ username: 'alice' }); - const file = await uploadFile(alice); - const newName = 'いちごパスタ.png'; - - const res = await request('/drive/files/update', { - fileId: file.id, - name: newName - }, alice); - - assert.strictEqual(res.status, 200); - assert.strictEqual(typeof res.body === 'object' && !Array.isArray(res.body), true); - assert.strictEqual(res.body.name, newName); - })); - - it('他人のファイルは更新できない', async(async () => { - const bob = await signup({ username: 'bob' }); - const alice = await signup({ username: 'alice' }); - const file = await uploadFile(bob); - - const res = await request('/drive/files/update', { - fileId: file.id, - name: 'いちごパスタ.png' - }, alice); - - assert.strictEqual(res.status, 400); - })); - - it('親フォルダを更新できる', async(async () => { - const alice = await signup({ username: 'alice' }); - const file = await uploadFile(alice); - const folder = (await request('/drive/folders/create', { - name: 'test' - }, alice)).body; - - const res = await request('/drive/files/update', { - fileId: file.id, - folderId: folder.id - }, alice); - - assert.strictEqual(res.status, 200); - assert.strictEqual(typeof res.body === 'object' && !Array.isArray(res.body), true); - assert.strictEqual(res.body.folderId, folder.id); - })); - - it('親フォルダを無しにできる', async(async () => { - const alice = await signup({ username: 'alice' }); - const file = await uploadFile(alice); - - const folder = (await request('/drive/folders/create', { - name: 'test' - }, alice)).body; - - await request('/drive/files/update', { - fileId: file.id, - folderId: folder.id - }, alice); - - const res = await request('/drive/files/update', { - fileId: file.id, - folderId: null - }, alice); - - assert.strictEqual(res.status, 200); - assert.strictEqual(typeof res.body === 'object' && !Array.isArray(res.body), true); - assert.strictEqual(res.body.folderId, null); - })); - - it('他人のフォルダには入れられない', async(async () => { - const bob = await signup({ username: 'bob' }); - const alice = await signup({ username: 'alice' }); - const file = await uploadFile(alice); - const folder = (await request('/drive/folders/create', { - name: 'test' - }, bob)).body; - - const res = await request('/drive/files/update', { - fileId: file.id, - folderId: folder.id - }, alice); - - assert.strictEqual(res.status, 400); - })); - - it('存在しないフォルダで怒られる', async(async () => { - const alice = await signup({ username: 'alice' }); - const file = await uploadFile(alice); - - const res = await request('/drive/files/update', { - fileId: file.id, - folderId: '000000000000000000000000' - }, alice); - - assert.strictEqual(res.status, 400); - })); - - it('不正なフォルダIDで怒られる', async(async () => { - const alice = await signup({ username: 'alice' }); - const file = await uploadFile(alice); - - const res = await request('/drive/files/update', { - fileId: file.id, - folderId: 'foo' - }, alice); - - assert.strictEqual(res.status, 400); - })); - - it('ファイルが存在しなかったら怒る', async(async () => { - const alice = await signup({ username: 'alice' }); - - const res = await request('/drive/files/update', { - fileId: '000000000000000000000000', - name: 'いちごパスタ.png' - }, alice); - - assert.strictEqual(res.status, 400); - })); - - it('間違ったIDで怒られる', async(async () => { - const alice = await signup({ username: 'alice' }); - - const res = await request('/drive/files/update', { - fileId: 'kyoppie', - name: 'いちごパスタ.png' - }, alice); - - assert.strictEqual(res.status, 400); - })); - }); - - describe('drive/folders/create', () => { - it('フォルダを作成できる', async(async () => { - const alice = await signup({ username: 'alice' }); - - const res = await request('/drive/folders/create', { - name: 'test' - }, alice); - - assert.strictEqual(res.status, 200); - assert.strictEqual(typeof res.body === 'object' && !Array.isArray(res.body), true); - assert.strictEqual(res.body.name, 'test'); - })); - }); - - describe('drive/folders/update', () => { - it('名前を更新できる', async(async () => { - const alice = await signup({ username: 'alice' }); - const folder = (await request('/drive/folders/create', { - name: 'test' - }, alice)).body; - - const res = await request('/drive/folders/update', { - folderId: folder.id, - name: 'new name' - }, alice); - - assert.strictEqual(res.status, 200); - assert.strictEqual(typeof res.body === 'object' && !Array.isArray(res.body), true); - assert.strictEqual(res.body.name, 'new name'); - })); - - it('他人のフォルダを更新できない', async(async () => { - const bob = await signup({ username: 'bob' }); - const alice = await signup({ username: 'alice' }); - const folder = (await request('/drive/folders/create', { - name: 'test' - }, bob)).body; - - const res = await request('/drive/folders/update', { - folderId: folder.id, - name: 'new name' - }, alice); - - assert.strictEqual(res.status, 400); - })); - - it('親フォルダを更新できる', async(async () => { - const alice = await signup({ username: 'alice' }); - const folder = (await request('/drive/folders/create', { - name: 'test' - }, alice)).body; - const parentFolder = (await request('/drive/folders/create', { - name: 'parent' - }, alice)).body; - - const res = await request('/drive/folders/update', { - folderId: folder.id, - parentId: parentFolder.id - }, alice); - - assert.strictEqual(res.status, 200); - assert.strictEqual(typeof res.body === 'object' && !Array.isArray(res.body), true); - assert.strictEqual(res.body.parentId, parentFolder.id); - })); - - it('親フォルダを無しに更新できる', async(async () => { - const alice = await signup({ username: 'alice' }); - const folder = (await request('/drive/folders/create', { - name: 'test' - }, alice)).body; - const parentFolder = (await request('/drive/folders/create', { - name: 'parent' - }, alice)).body; - await request('/drive/folders/update', { - folderId: folder.id, - parentId: parentFolder.id - }, alice); - - const res = await request('/drive/folders/update', { - folderId: folder.id, - parentId: null - }, alice); - - assert.strictEqual(res.status, 200); - assert.strictEqual(typeof res.body === 'object' && !Array.isArray(res.body), true); - assert.strictEqual(res.body.parentId, null); - })); - - it('他人のフォルダを親フォルダに設定できない', async(async () => { - const bob = await signup({ username: 'bob' }); - const alice = await signup({ username: 'alice' }); - const folder = (await request('/drive/folders/create', { - name: 'test' - }, alice)).body; - const parentFolder = (await request('/drive/folders/create', { - name: 'parent' - }, bob)).body; - - const res = await request('/drive/folders/update', { - folderId: folder.id, - parentId: parentFolder.id - }, alice); - - assert.strictEqual(res.status, 400); - })); - - it('フォルダが循環するような構造にできない', async(async () => { - const alice = await signup({ username: 'alice' }); - const folder = (await request('/drive/folders/create', { - name: 'test' - }, alice)).body; - const parentFolder = (await request('/drive/folders/create', { - name: 'parent' - }, alice)).body; - await request('/drive/folders/update', { - folderId: parentFolder.id, - parentId: folder.id - }, alice); - - const res = await request('/drive/folders/update', { - folderId: folder.id, - parentId: parentFolder.id - }, alice); - - assert.strictEqual(res.status, 400); - })); - - it('フォルダが循環するような構造にできない(再帰的)', async(async () => { - const alice = await signup({ username: 'alice' }); - const folderA = (await request('/drive/folders/create', { - name: 'test' - }, alice)).body; - const folderB = (await request('/drive/folders/create', { - name: 'test' - }, alice)).body; - const folderC = (await request('/drive/folders/create', { - name: 'test' - }, alice)).body; - await request('/drive/folders/update', { - folderId: folderB.id, - parentId: folderA.id - }, alice); - await request('/drive/folders/update', { - folderId: folderC.id, - parentId: folderB.id - }, alice); - - const res = await request('/drive/folders/update', { - folderId: folderA.id, - parentId: folderC.id - }, alice); - - assert.strictEqual(res.status, 400); - })); - - it('フォルダが循環するような構造にできない(自身)', async(async () => { - const arisugawa = await signup({ username: 'arisugawa' }); - const folderA = (await request('/drive/folders/create', { - name: 'test' - }, arisugawa)).body; - - const res = await request('/drive/folders/update', { - folderId: folderA.id, - parentId: folderA.id - }, arisugawa); - - assert.strictEqual(res.status, 400); - })); - - it('存在しない親フォルダを設定できない', async(async () => { - const alice = await signup({ username: 'alice' }); - const folder = (await request('/drive/folders/create', { - name: 'test' - }, alice)).body; - - const res = await request('/drive/folders/update', { - folderId: folder.id, - parentId: '000000000000000000000000' - }, alice); - - assert.strictEqual(res.status, 400); - })); - - it('不正な親フォルダIDで怒られる', async(async () => { - const alice = await signup({ username: 'alice' }); - const folder = (await request('/drive/folders/create', { - name: 'test' - }, alice)).body; - - const res = await request('/drive/folders/update', { - folderId: folder.id, - parentId: 'foo' - }, alice); - - assert.strictEqual(res.status, 400); - })); - - it('存在しないフォルダを更新できない', async(async () => { - const alice = await signup({ username: 'alice' }); - - const res = await request('/drive/folders/update', { - folderId: '000000000000000000000000' - }, alice); - - assert.strictEqual(res.status, 400); - })); - - it('不正なフォルダIDで怒られる', async(async () => { - const alice = await signup({ username: 'alice' }); - - const res = await request('/drive/folders/update', { - folderId: 'foo' - }, alice); - - assert.strictEqual(res.status, 400); - })); - }); - - describe('messaging/messages/create', () => { - it('メッセージを送信できる', async(async () => { - const alice = await signup({ username: 'alice' }); - const bob = await signup({ username: 'bob' }); - - const res = await request('/messaging/messages/create', { - userId: bob.id, - text: 'test' - }, alice); - - assert.strictEqual(res.status, 200); - assert.strictEqual(typeof res.body === 'object' && !Array.isArray(res.body), true); - assert.strictEqual(res.body.text, 'test'); - })); - - it('自分自身にはメッセージを送信できない', async(async () => { - const alice = await signup({ username: 'alice' }); - - const res = await request('/messaging/messages/create', { - userId: alice.id, - text: 'Yo' - }, alice); - - assert.strictEqual(res.status, 400); - })); - - it('存在しないユーザーにはメッセージを送信できない', async(async () => { - const alice = await signup({ username: 'alice' }); - - const res = await request('/messaging/messages/create', { - userId: '000000000000000000000000', - text: 'test' - }, alice); - - assert.strictEqual(res.status, 400); - })); - - it('不正なユーザーIDで怒られる', async(async () => { - const alice = await signup({ username: 'alice' }); - - const res = await request('/messaging/messages/create', { - userId: 'foo', - text: 'test' - }, alice); - - assert.strictEqual(res.status, 400); - })); - - it('テキストが無くて怒られる', async(async () => { - const alice = await signup({ username: 'alice' }); - const bob = await signup({ username: 'bob' }); - - const res = await request('/messaging/messages/create', { - userId: bob.id - }, alice); - - assert.strictEqual(res.status, 400); - })); - - it('文字数オーバーで怒られる', async(async () => { - const alice = await signup({ username: 'alice' }); - const bob = await signup({ username: 'bob' }); - - const res = await request('/messaging/messages/create', { - userId: bob.id, - text: '!'.repeat(1001) - }, alice); - - assert.strictEqual(res.status, 400); - })); - }); - - describe('notes/replies', () => { - it('自分に閲覧権限のない投稿は含まれない', async(async () => { - const alice = await signup({ username: 'alice' }); - const bob = await signup({ username: 'bob' }); - const carol = await signup({ username: 'carol' }); - - const alicePost = await post(alice, { - text: 'foo' - }); - - await post(bob, { - replyId: alicePost.id, - text: 'bar', - visibility: 'specified', - visibleUserIds: [alice.id] - }); - - const res = await request('/notes/replies', { - noteId: alicePost.id - }, carol); - - assert.strictEqual(res.status, 200); - assert.strictEqual(Array.isArray(res.body), true); - assert.strictEqual(res.body.length, 0); - })); - }); - - describe('notes/timeline', () => { - it('フォロワー限定投稿が含まれる', async(async () => { - const alice = await signup({ username: 'alice' }); - const bob = await signup({ username: 'bob' }); - - await request('/following/create', { - userId: alice.id - }, bob); - - const alicePost = await post(alice, { - text: 'foo', - visibility: 'followers' - }); - - const res = await request('/notes/timeline', {}, bob); - - assert.strictEqual(res.status, 200); - assert.strictEqual(Array.isArray(res.body), true); - assert.strictEqual(res.body.length, 1); - assert.strictEqual(res.body[0].id, alicePost.id); + assert.strictEqual(res.body.nullableDefault, 'hello'); })); }); }); -*/ diff --git a/packages/backend/test/block.ts b/packages/backend/test/block.ts index 6d9efb77b..103eec991 100644 --- a/packages/backend/test/block.ts +++ b/packages/backend/test/block.ts @@ -2,7 +2,7 @@ process.env.NODE_ENV = 'test'; import * as assert from 'assert'; import * as childProcess from 'child_process'; -import { async, signup, request, post, startServer, shutdownServer } from './utils'; +import { async, signup, request, post, startServer, shutdownServer } from './utils.js'; describe('Block', () => { let p: childProcess.ChildProcess; diff --git a/packages/backend/test/chart.ts b/packages/backend/test/chart.ts index bd8d4c817..c8cea874f 100644 --- a/packages/backend/test/chart.ts +++ b/packages/backend/test/chart.ts @@ -2,15 +2,15 @@ process.env.NODE_ENV = 'test'; import * as assert from 'assert'; import * as lolex from '@sinonjs/fake-timers'; -import { async, initTestDb } from './utils'; -import TestChart from '../src/services/chart/charts/test'; -import TestGroupedChart from '../src/services/chart/charts/test-grouped'; -import TestUniqueChart from '../src/services/chart/charts/test-unique'; -import TestIntersectionChart from '../src/services/chart/charts/test-intersection'; -import * as _TestChart from '../src/services/chart/charts/entities/test'; -import * as _TestGroupedChart from '../src/services/chart/charts/entities/test-grouped'; -import * as _TestUniqueChart from '../src/services/chart/charts/entities/test-unique'; -import * as _TestIntersectionChart from '../src/services/chart/charts/entities/test-intersection'; +import { async, initTestDb } from './utils.js'; +import TestChart from '../src/services/chart/charts/test.js'; +import TestGroupedChart from '../src/services/chart/charts/test-grouped.js'; +import TestUniqueChart from '../src/services/chart/charts/test-unique.js'; +import TestIntersectionChart from '../src/services/chart/charts/test-intersection.js'; +import * as _TestChart from '../src/services/chart/charts/entities/test.js'; +import * as _TestGroupedChart from '../src/services/chart/charts/entities/test-grouped.js'; +import * as _TestUniqueChart from '../src/services/chart/charts/entities/test-unique.js'; +import * as _TestIntersectionChart from '../src/services/chart/charts/entities/test-intersection.js'; describe('Chart', () => { let testChart: TestChart; diff --git a/packages/backend/test/endpoints.ts b/packages/backend/test/endpoints.ts new file mode 100644 index 000000000..2aedc25f2 --- /dev/null +++ b/packages/backend/test/endpoints.ts @@ -0,0 +1,865 @@ +/* +process.env.NODE_ENV = 'test'; + +import * as assert from 'assert'; +import * as childProcess from 'child_process'; +import { async, signup, request, post, react, uploadFile, startServer, shutdownServer } from './utils.js'; + +describe('API: Endpoints', () => { + let p: childProcess.ChildProcess; + let alice: any; + let bob: any; + let carol: any; + + before(async () => { + p = await startServer(); + alice = await signup({ username: 'alice' }); + bob = await signup({ username: 'bob' }); + carol = await signup({ username: 'carol' }); + }); + + after(async () => { + await shutdownServer(p); + }); + + describe('signup', () => { + it('不正なユーザー名でアカウントが作成できない', async(async () => { + const res = await request('/signup', { + username: 'test.', + password: 'test' + }); + assert.strictEqual(res.status, 400); + })); + + it('空のパスワードでアカウントが作成できない', async(async () => { + const res = await request('/signup', { + username: 'test', + password: '' + }); + assert.strictEqual(res.status, 400); + })); + + it('正しくアカウントが作成できる', async(async () => { + const me = { + username: 'test1', + password: 'test1' + }; + + const res = await request('/signup', me); + + assert.strictEqual(res.status, 200); + assert.strictEqual(typeof res.body === 'object' && !Array.isArray(res.body), true); + assert.strictEqual(res.body.username, me.username); + })); + + it('同じユーザー名のアカウントは作成できない', async(async () => { + await signup({ + username: 'test2' + }); + + const res = await request('/signup', { + username: 'test2', + password: 'test2' + }); + + assert.strictEqual(res.status, 400); + })); + }); + + describe('signin', () => { + it('間違ったパスワードでサインインできない', async(async () => { + await signup({ + username: 'test3', + password: 'foo' + }); + + const res = await request('/signin', { + username: 'test3', + password: 'bar' + }); + + assert.strictEqual(res.status, 403); + })); + + it('クエリをインジェクションできない', async(async () => { + await signup({ + username: 'test4' + }); + + const res = await request('/signin', { + username: 'test4', + password: { + $gt: '' + } + }); + + assert.strictEqual(res.status, 400); + })); + + it('正しい情報でサインインできる', async(async () => { + await signup({ + username: 'test5', + password: 'foo' + }); + + const res = await request('/signin', { + username: 'test5', + password: 'foo' + }); + + assert.strictEqual(res.status, 200); + })); + }); + + describe('i/update', () => { + it('アカウント設定を更新できる', async(async () => { + const myName = '大室櫻子'; + const myLocation = '七森中'; + const myBirthday = '2000-09-07'; + + const res = await request('/i/update', { + name: myName, + location: myLocation, + birthday: myBirthday + }, alice); + + assert.strictEqual(res.status, 200); + assert.strictEqual(typeof res.body === 'object' && !Array.isArray(res.body), true); + assert.strictEqual(res.body.name, myName); + assert.strictEqual(res.body.location, myLocation); + assert.strictEqual(res.body.birthday, myBirthday); + })); + + it('名前を空白にできない', async(async () => { + const res = await request('/i/update', { + name: ' ' + }, alice); + assert.strictEqual(res.status, 400); + })); + + it('誕生日の設定を削除できる', async(async () => { + await request('/i/update', { + birthday: '2000-09-07' + }, alice); + + const res = await request('/i/update', { + birthday: null + }, alice); + + assert.strictEqual(res.status, 200); + assert.strictEqual(typeof res.body === 'object' && !Array.isArray(res.body), true); + assert.strictEqual(res.body.birthday, null); + })); + + it('不正な誕生日の形式で怒られる', async(async () => { + const res = await request('/i/update', { + birthday: '2000/09/07' + }, alice); + assert.strictEqual(res.status, 400); + })); + }); + + describe('users/show', () => { + it('ユーザーが取得できる', async(async () => { + const res = await request('/users/show', { + userId: alice.id + }, alice); + + assert.strictEqual(res.status, 200); + assert.strictEqual(typeof res.body === 'object' && !Array.isArray(res.body), true); + assert.strictEqual(res.body.id, alice.id); + })); + + it('ユーザーが存在しなかったら怒る', async(async () => { + const res = await request('/users/show', { + userId: '000000000000000000000000' + }); + assert.strictEqual(res.status, 400); + })); + + it('間違ったIDで怒られる', async(async () => { + const res = await request('/users/show', { + userId: 'kyoppie' + }); + assert.strictEqual(res.status, 400); + })); + }); + + describe('notes/show', () => { + it('投稿が取得できる', async(async () => { + const myPost = await post(alice, { + text: 'test' + }); + + const res = await request('/notes/show', { + noteId: myPost.id + }, alice); + + assert.strictEqual(res.status, 200); + assert.strictEqual(typeof res.body === 'object' && !Array.isArray(res.body), true); + assert.strictEqual(res.body.id, myPost.id); + assert.strictEqual(res.body.text, myPost.text); + })); + + it('投稿が存在しなかったら怒る', async(async () => { + const res = await request('/notes/show', { + noteId: '000000000000000000000000' + }); + assert.strictEqual(res.status, 400); + })); + + it('間違ったIDで怒られる', async(async () => { + const res = await request('/notes/show', { + noteId: 'kyoppie' + }); + assert.strictEqual(res.status, 400); + })); + }); + + describe('notes/reactions/create', () => { + it('リアクションできる', async(async () => { + const bobPost = await post(bob); + + const alice = await signup({ username: 'alice' }); + const res = await request('/notes/reactions/create', { + noteId: bobPost.id, + reaction: '🚀', + }, alice); + + assert.strictEqual(res.status, 204); + + const resNote = await request('/notes/show', { + noteId: bobPost.id, + }, alice); + + assert.strictEqual(resNote.status, 200); + assert.strictEqual(resNote.body.reactions['🚀'], [alice.id]); + })); + + it('自分の投稿にもリアクションできる', async(async () => { + const myPost = await post(alice); + + const res = await request('/notes/reactions/create', { + noteId: myPost.id, + reaction: '🚀', + }, alice); + + assert.strictEqual(res.status, 204); + })); + + it('二重にリアクションできない', async(async () => { + const bobPost = await post(bob); + + await react(alice, bobPost, 'like'); + + const res = await request('/notes/reactions/create', { + noteId: bobPost.id, + reaction: '🚀', + }, alice); + + assert.strictEqual(res.status, 400); + })); + + it('存在しない投稿にはリアクションできない', async(async () => { + const res = await request('/notes/reactions/create', { + noteId: '000000000000000000000000', + reaction: '🚀', + }, alice); + + assert.strictEqual(res.status, 400); + })); + + it('空のパラメータで怒られる', async(async () => { + const res = await request('/notes/reactions/create', {}, alice); + + assert.strictEqual(res.status, 400); + })); + + it('間違ったIDで怒られる', async(async () => { + const res = await request('/notes/reactions/create', { + noteId: 'kyoppie', + reaction: '🚀', + }, alice); + + assert.strictEqual(res.status, 400); + })); + }); + + describe('following/create', () => { + it('フォローできる', async(async () => { + const res = await request('/following/create', { + userId: alice.id + }, bob); + + assert.strictEqual(res.status, 200); + })); + + it('既にフォローしている場合は怒る', async(async () => { + const res = await request('/following/create', { + userId: alice.id + }, bob); + + assert.strictEqual(res.status, 400); + })); + + it('存在しないユーザーはフォローできない', async(async () => { + const res = await request('/following/create', { + userId: '000000000000000000000000' + }, alice); + + assert.strictEqual(res.status, 400); + })); + + it('自分自身はフォローできない', async(async () => { + const res = await request('/following/create', { + userId: alice.id + }, alice); + + assert.strictEqual(res.status, 400); + })); + + it('空のパラメータで怒られる', async(async () => { + const res = await request('/following/create', {}, alice); + + assert.strictEqual(res.status, 400); + })); + + it('間違ったIDで怒られる', async(async () => { + const res = await request('/following/create', { + userId: 'foo' + }, alice); + + assert.strictEqual(res.status, 400); + })); + }); + + describe('following/delete', () => { + it('フォロー解除できる', async(async () => { + await request('/following/create', { + userId: alice.id + }, bob); + + const res = await request('/following/delete', { + userId: alice.id + }, bob); + + assert.strictEqual(res.status, 200); + })); + + it('フォローしていない場合は怒る', async(async () => { + const res = await request('/following/delete', { + userId: alice.id + }, bob); + + assert.strictEqual(res.status, 400); + })); + + it('存在しないユーザーはフォロー解除できない', async(async () => { + const res = await request('/following/delete', { + userId: '000000000000000000000000' + }, alice); + + assert.strictEqual(res.status, 400); + })); + + it('自分自身はフォロー解除できない', async(async () => { + const res = await request('/following/delete', { + userId: alice.id + }, alice); + + assert.strictEqual(res.status, 400); + })); + + it('空のパラメータで怒られる', async(async () => { + const res = await request('/following/delete', {}, alice); + + assert.strictEqual(res.status, 400); + })); + + it('間違ったIDで怒られる', async(async () => { + const res = await request('/following/delete', { + userId: 'kyoppie' + }, alice); + + assert.strictEqual(res.status, 400); + })); + }); + + describe('drive', () => { + it('ドライブ情報を取得できる', async(async () => { + await uploadFile({ + userId: alice.id, + size: 256 + }); + await uploadFile({ + userId: alice.id, + size: 512 + }); + await uploadFile({ + userId: alice.id, + size: 1024 + }); + const res = await request('/drive', {}, alice); + assert.strictEqual(res.status, 200); + assert.strictEqual(typeof res.body === 'object' && !Array.isArray(res.body), true); + expect(res.body).have.property('usage').eql(1792); + })); + }); + + describe('drive/files/create', () => { + it('ファイルを作成できる', async(async () => { + const res = await uploadFile(alice); + + assert.strictEqual(res.status, 200); + assert.strictEqual(typeof res.body === 'object' && !Array.isArray(res.body), true); + assert.strictEqual(res.body.name, 'Lenna.png'); + })); + + it('ファイルに名前を付けられる', async(async () => { + const res = await assert.request(server) + .post('/drive/files/create') + .field('i', alice.token) + .field('name', 'Belmond.png') + .attach('file', fs.readFileSync(__dirname + '/resources/Lenna.png'), 'Lenna.png'); + + expect(res).have.status(200); + expect(res.body).be.a('object'); + expect(res.body).have.property('name').eql('Belmond.png'); + })); + + it('ファイル無しで怒られる', async(async () => { + const res = await request('/drive/files/create', {}, alice); + + assert.strictEqual(res.status, 400); + })); + + it('SVGファイルを作成できる', async(async () => { + const res = await uploadFile(alice, __dirname + '/resources/image.svg'); + + assert.strictEqual(res.status, 200); + assert.strictEqual(typeof res.body === 'object' && !Array.isArray(res.body), true); + assert.strictEqual(res.body.name, 'image.svg'); + assert.strictEqual(res.body.type, 'image/svg+xml'); + })); + }); + + describe('drive/files/update', () => { + it('名前を更新できる', async(async () => { + const file = await uploadFile(alice); + const newName = 'いちごパスタ.png'; + + const res = await request('/drive/files/update', { + fileId: file.id, + name: newName + }, alice); + + assert.strictEqual(res.status, 200); + assert.strictEqual(typeof res.body === 'object' && !Array.isArray(res.body), true); + assert.strictEqual(res.body.name, newName); + })); + + it('他人のファイルは更新できない', async(async () => { + const file = await uploadFile(bob); + + const res = await request('/drive/files/update', { + fileId: file.id, + name: 'いちごパスタ.png' + }, alice); + + assert.strictEqual(res.status, 400); + })); + + it('親フォルダを更新できる', async(async () => { + const file = await uploadFile(alice); + const folder = (await request('/drive/folders/create', { + name: 'test' + }, alice)).body; + + const res = await request('/drive/files/update', { + fileId: file.id, + folderId: folder.id + }, alice); + + assert.strictEqual(res.status, 200); + assert.strictEqual(typeof res.body === 'object' && !Array.isArray(res.body), true); + assert.strictEqual(res.body.folderId, folder.id); + })); + + it('親フォルダを無しにできる', async(async () => { + const file = await uploadFile(alice); + + const folder = (await request('/drive/folders/create', { + name: 'test' + }, alice)).body; + + await request('/drive/files/update', { + fileId: file.id, + folderId: folder.id + }, alice); + + const res = await request('/drive/files/update', { + fileId: file.id, + folderId: null + }, alice); + + assert.strictEqual(res.status, 200); + assert.strictEqual(typeof res.body === 'object' && !Array.isArray(res.body), true); + assert.strictEqual(res.body.folderId, null); + })); + + it('他人のフォルダには入れられない', async(async () => { + const file = await uploadFile(alice); + const folder = (await request('/drive/folders/create', { + name: 'test' + }, bob)).body; + + const res = await request('/drive/files/update', { + fileId: file.id, + folderId: folder.id + }, alice); + + assert.strictEqual(res.status, 400); + })); + + it('存在しないフォルダで怒られる', async(async () => { + const file = await uploadFile(alice); + + const res = await request('/drive/files/update', { + fileId: file.id, + folderId: '000000000000000000000000' + }, alice); + + assert.strictEqual(res.status, 400); + })); + + it('不正なフォルダIDで怒られる', async(async () => { + const file = await uploadFile(alice); + + const res = await request('/drive/files/update', { + fileId: file.id, + folderId: 'foo' + }, alice); + + assert.strictEqual(res.status, 400); + })); + + it('ファイルが存在しなかったら怒る', async(async () => { + const res = await request('/drive/files/update', { + fileId: '000000000000000000000000', + name: 'いちごパスタ.png' + }, alice); + + assert.strictEqual(res.status, 400); + })); + + it('間違ったIDで怒られる', async(async () => { + const res = await request('/drive/files/update', { + fileId: 'kyoppie', + name: 'いちごパスタ.png' + }, alice); + + assert.strictEqual(res.status, 400); + })); + }); + + describe('drive/folders/create', () => { + it('フォルダを作成できる', async(async () => { + const res = await request('/drive/folders/create', { + name: 'test' + }, alice); + + assert.strictEqual(res.status, 200); + assert.strictEqual(typeof res.body === 'object' && !Array.isArray(res.body), true); + assert.strictEqual(res.body.name, 'test'); + })); + }); + + describe('drive/folders/update', () => { + it('名前を更新できる', async(async () => { + const folder = (await request('/drive/folders/create', { + name: 'test' + }, alice)).body; + + const res = await request('/drive/folders/update', { + folderId: folder.id, + name: 'new name' + }, alice); + + assert.strictEqual(res.status, 200); + assert.strictEqual(typeof res.body === 'object' && !Array.isArray(res.body), true); + assert.strictEqual(res.body.name, 'new name'); + })); + + it('他人のフォルダを更新できない', async(async () => { + const folder = (await request('/drive/folders/create', { + name: 'test' + }, bob)).body; + + const res = await request('/drive/folders/update', { + folderId: folder.id, + name: 'new name' + }, alice); + + assert.strictEqual(res.status, 400); + })); + + it('親フォルダを更新できる', async(async () => { + const folder = (await request('/drive/folders/create', { + name: 'test' + }, alice)).body; + const parentFolder = (await request('/drive/folders/create', { + name: 'parent' + }, alice)).body; + + const res = await request('/drive/folders/update', { + folderId: folder.id, + parentId: parentFolder.id + }, alice); + + assert.strictEqual(res.status, 200); + assert.strictEqual(typeof res.body === 'object' && !Array.isArray(res.body), true); + assert.strictEqual(res.body.parentId, parentFolder.id); + })); + + it('親フォルダを無しに更新できる', async(async () => { + const folder = (await request('/drive/folders/create', { + name: 'test' + }, alice)).body; + const parentFolder = (await request('/drive/folders/create', { + name: 'parent' + }, alice)).body; + await request('/drive/folders/update', { + folderId: folder.id, + parentId: parentFolder.id + }, alice); + + const res = await request('/drive/folders/update', { + folderId: folder.id, + parentId: null + }, alice); + + assert.strictEqual(res.status, 200); + assert.strictEqual(typeof res.body === 'object' && !Array.isArray(res.body), true); + assert.strictEqual(res.body.parentId, null); + })); + + it('他人のフォルダを親フォルダに設定できない', async(async () => { + const folder = (await request('/drive/folders/create', { + name: 'test' + }, alice)).body; + const parentFolder = (await request('/drive/folders/create', { + name: 'parent' + }, bob)).body; + + const res = await request('/drive/folders/update', { + folderId: folder.id, + parentId: parentFolder.id + }, alice); + + assert.strictEqual(res.status, 400); + })); + + it('フォルダが循環するような構造にできない', async(async () => { + const folder = (await request('/drive/folders/create', { + name: 'test' + }, alice)).body; + const parentFolder = (await request('/drive/folders/create', { + name: 'parent' + }, alice)).body; + await request('/drive/folders/update', { + folderId: parentFolder.id, + parentId: folder.id + }, alice); + + const res = await request('/drive/folders/update', { + folderId: folder.id, + parentId: parentFolder.id + }, alice); + + assert.strictEqual(res.status, 400); + })); + + it('フォルダが循環するような構造にできない(再帰的)', async(async () => { + const folderA = (await request('/drive/folders/create', { + name: 'test' + }, alice)).body; + const folderB = (await request('/drive/folders/create', { + name: 'test' + }, alice)).body; + const folderC = (await request('/drive/folders/create', { + name: 'test' + }, alice)).body; + await request('/drive/folders/update', { + folderId: folderB.id, + parentId: folderA.id + }, alice); + await request('/drive/folders/update', { + folderId: folderC.id, + parentId: folderB.id + }, alice); + + const res = await request('/drive/folders/update', { + folderId: folderA.id, + parentId: folderC.id + }, alice); + + assert.strictEqual(res.status, 400); + })); + + it('フォルダが循環するような構造にできない(自身)', async(async () => { + const folderA = (await request('/drive/folders/create', { + name: 'test' + }, alice)).body; + + const res = await request('/drive/folders/update', { + folderId: folderA.id, + parentId: folderA.id + }, alice); + + assert.strictEqual(res.status, 400); + })); + + it('存在しない親フォルダを設定できない', async(async () => { + const folder = (await request('/drive/folders/create', { + name: 'test' + }, alice)).body; + + const res = await request('/drive/folders/update', { + folderId: folder.id, + parentId: '000000000000000000000000' + }, alice); + + assert.strictEqual(res.status, 400); + })); + + it('不正な親フォルダIDで怒られる', async(async () => { + const folder = (await request('/drive/folders/create', { + name: 'test' + }, alice)).body; + + const res = await request('/drive/folders/update', { + folderId: folder.id, + parentId: 'foo' + }, alice); + + assert.strictEqual(res.status, 400); + })); + + it('存在しないフォルダを更新できない', async(async () => { + const res = await request('/drive/folders/update', { + folderId: '000000000000000000000000' + }, alice); + + assert.strictEqual(res.status, 400); + })); + + it('不正なフォルダIDで怒られる', async(async () => { + const res = await request('/drive/folders/update', { + folderId: 'foo' + }, alice); + + assert.strictEqual(res.status, 400); + })); + }); + + describe('messaging/messages/create', () => { + it('メッセージを送信できる', async(async () => { + const res = await request('/messaging/messages/create', { + userId: bob.id, + text: 'test' + }, alice); + + assert.strictEqual(res.status, 200); + assert.strictEqual(typeof res.body === 'object' && !Array.isArray(res.body), true); + assert.strictEqual(res.body.text, 'test'); + })); + + it('自分自身にはメッセージを送信できない', async(async () => { + const res = await request('/messaging/messages/create', { + userId: alice.id, + text: 'Yo' + }, alice); + + assert.strictEqual(res.status, 400); + })); + + it('存在しないユーザーにはメッセージを送信できない', async(async () => { + const res = await request('/messaging/messages/create', { + userId: '000000000000000000000000', + text: 'test' + }, alice); + + assert.strictEqual(res.status, 400); + })); + + it('不正なユーザーIDで怒られる', async(async () => { + const res = await request('/messaging/messages/create', { + userId: 'foo', + text: 'test' + }, alice); + + assert.strictEqual(res.status, 400); + })); + + it('テキストが無くて怒られる', async(async () => { + const res = await request('/messaging/messages/create', { + userId: bob.id + }, alice); + + assert.strictEqual(res.status, 400); + })); + + it('文字数オーバーで怒られる', async(async () => { + const res = await request('/messaging/messages/create', { + userId: bob.id, + text: '!'.repeat(1001) + }, alice); + + assert.strictEqual(res.status, 400); + })); + }); + + describe('notes/replies', () => { + it('自分に閲覧権限のない投稿は含まれない', async(async () => { + const alicePost = await post(alice, { + text: 'foo' + }); + + await post(bob, { + replyId: alicePost.id, + text: 'bar', + visibility: 'specified', + visibleUserIds: [alice.id] + }); + + const res = await request('/notes/replies', { + noteId: alicePost.id + }, carol); + + assert.strictEqual(res.status, 200); + assert.strictEqual(Array.isArray(res.body), true); + assert.strictEqual(res.body.length, 0); + })); + }); + + describe('notes/timeline', () => { + it('フォロワー限定投稿が含まれる', async(async () => { + await request('/following/create', { + userId: alice.id + }, bob); + + const alicePost = await post(alice, { + text: 'foo', + visibility: 'followers' + }); + + const res = await request('/notes/timeline', {}, bob); + + assert.strictEqual(res.status, 200); + assert.strictEqual(Array.isArray(res.body), true); + assert.strictEqual(res.body.length, 1); + assert.strictEqual(res.body[0].id, alicePost.id); + })); + }); +}); +*/ diff --git a/packages/backend/test/extract-mentions.ts b/packages/backend/test/extract-mentions.ts index 9e6d04190..9bfbc4192 100644 --- a/packages/backend/test/extract-mentions.ts +++ b/packages/backend/test/extract-mentions.ts @@ -1,6 +1,6 @@ import * as assert from 'assert'; -import { extractMentions } from '../src/misc/extract-mentions'; +import { extractMentions } from '../src/misc/extract-mentions.js'; import { parse } from 'mfm-js'; describe('Extract mentions', () => { diff --git a/packages/backend/test/fetch-resource.ts b/packages/backend/test/fetch-resource.ts index c403f4d39..4cb4b4256 100644 --- a/packages/backend/test/fetch-resource.ts +++ b/packages/backend/test/fetch-resource.ts @@ -2,7 +2,7 @@ process.env.NODE_ENV = 'test'; import * as assert from 'assert'; import * as childProcess from 'child_process'; -import { async, startServer, signup, post, request, simpleGet, port, shutdownServer } from './utils'; +import { async, startServer, signup, post, request, simpleGet, port, shutdownServer } from './utils.js'; import * as openapi from '@redocly/openapi-core'; // Request Accept diff --git a/packages/backend/test/ff-visibility.ts b/packages/backend/test/ff-visibility.ts index 295ab1933..4f6847be6 100644 --- a/packages/backend/test/ff-visibility.ts +++ b/packages/backend/test/ff-visibility.ts @@ -2,7 +2,7 @@ process.env.NODE_ENV = 'test'; import * as assert from 'assert'; import * as childProcess from 'child_process'; -import { async, signup, request, post, react, connectStream, startServer, shutdownServer, simpleGet } from './utils'; +import { async, signup, request, post, react, connectStream, startServer, shutdownServer, simpleGet } from './utils.js'; describe('FF visibility', () => { let p: childProcess.ChildProcess; diff --git a/packages/backend/test/get-file-info.ts b/packages/backend/test/get-file-info.ts index a0146bd81..20061b870 100644 --- a/packages/backend/test/get-file-info.ts +++ b/packages/backend/test/get-file-info.ts @@ -1,6 +1,6 @@ import * as assert from 'assert'; -import { async } from './utils'; -import { getFileInfo } from '../src/misc/get-file-info'; +import { async } from './utils.js'; +import { getFileInfo } from '../src/misc/get-file-info.js'; describe('Get file info', () => { it('Empty file', async (async () => { diff --git a/packages/backend/test/loader.js b/packages/backend/test/loader.js new file mode 100644 index 000000000..016f32f1a --- /dev/null +++ b/packages/backend/test/loader.js @@ -0,0 +1,37 @@ +import path from 'path' +import typescript from 'typescript' +import { createMatchPath } from 'tsconfig-paths' +import { resolve as BaseResolve, getFormat, transformSource } from 'ts-node/esm' + +const { readConfigFile, parseJsonConfigFileContent, sys } = typescript + +const __dirname = path.dirname(new URL(import.meta.url).pathname) + +const configFile = readConfigFile('./test/tsconfig.json', sys.readFile) +if (typeof configFile.error !== 'undefined') { + throw new Error(`Failed to load tsconfig: ${configFile.error}`) +} + +const { options } = parseJsonConfigFileContent( + configFile.config, + { + fileExists: sys.fileExists, + readFile: sys.readFile, + readDirectory: sys.readDirectory, + useCaseSensitiveFileNames: true, + }, + __dirname +) + +export { getFormat, transformSource } // こいつらはそのまま使ってほしいので re-export する + +const matchPath = createMatchPath(options.baseUrl, options.paths) + +export async function resolve(specifier, context, defaultResolve) { + const matchedSpecifier = matchPath(specifier.replace('.js', '.ts')) + return BaseResolve( // ts-node/esm の resolve に tsconfig-paths で解決したパスを渡す + matchedSpecifier ? `${matchedSpecifier}.ts` : specifier, + context, + defaultResolve + ) +} diff --git a/packages/backend/test/mfm.ts b/packages/backend/test/mfm.ts index ecf886ad6..5218942a5 100644 --- a/packages/backend/test/mfm.ts +++ b/packages/backend/test/mfm.ts @@ -1,8 +1,8 @@ import * as assert from 'assert'; import * as mfm from 'mfm-js'; -import { toHtml } from '../src/mfm/to-html'; -import { fromHtml } from '../src/mfm/from-html'; +import { toHtml } from '../src/mfm/to-html.js'; +import { fromHtml } from '../src/mfm/from-html.js'; describe('toHtml', () => { it('br', () => { diff --git a/packages/backend/test/misc/mock-resolver.ts b/packages/backend/test/misc/mock-resolver.ts index c245c83ba..5a46daf49 100644 --- a/packages/backend/test/misc/mock-resolver.ts +++ b/packages/backend/test/misc/mock-resolver.ts @@ -1,5 +1,5 @@ -import Resolver from '../../src/remote/activitypub/resolver'; -import { IObject } from '../../src/remote/activitypub/type'; +import Resolver from '../../src/remote/activitypub/resolver.js'; +import { IObject } from '../../src/remote/activitypub/type.js'; type MockResponse = { type: string; diff --git a/packages/backend/test/mute.ts b/packages/backend/test/mute.ts index ecac31075..288e8a805 100644 --- a/packages/backend/test/mute.ts +++ b/packages/backend/test/mute.ts @@ -2,7 +2,7 @@ process.env.NODE_ENV = 'test'; import * as assert from 'assert'; import * as childProcess from 'child_process'; -import { async, signup, request, post, react, connectStream, startServer, shutdownServer } from './utils'; +import { async, signup, request, post, react, connectStream, startServer, shutdownServer } from './utils.js'; describe('Mute', () => { let p: childProcess.ChildProcess; diff --git a/packages/backend/test/note.ts b/packages/backend/test/note.ts index ab8b6b190..62cea5208 100644 --- a/packages/backend/test/note.ts +++ b/packages/backend/test/note.ts @@ -2,8 +2,8 @@ process.env.NODE_ENV = 'test'; import * as assert from 'assert'; import * as childProcess from 'child_process'; -import { async, signup, request, post, uploadFile, startServer, shutdownServer, initTestDb } from './utils'; -import { Note } from '../src/models/entities/note'; +import { async, signup, request, post, uploadFile, startServer, shutdownServer, initTestDb } from './utils.js'; +import { Note } from '../src/models/entities/note.js'; describe('Note', () => { let p: childProcess.ChildProcess; diff --git a/packages/backend/test/prelude/maybe.ts b/packages/backend/test/prelude/maybe.ts index 2687a739a..0f4b00065 100644 --- a/packages/backend/test/prelude/maybe.ts +++ b/packages/backend/test/prelude/maybe.ts @@ -1,5 +1,5 @@ import * as assert from 'assert'; -import { just, nothing } from '../../src/prelude/maybe'; +import { just, nothing } from '../../src/prelude/maybe.js'; describe('just', () => { it('has a value', () => { diff --git a/packages/backend/test/prelude/url.ts b/packages/backend/test/prelude/url.ts index 1f814968a..84e43d26c 100644 --- a/packages/backend/test/prelude/url.ts +++ b/packages/backend/test/prelude/url.ts @@ -1,5 +1,5 @@ import * as assert from 'assert'; -import { query } from '../../src/prelude/url'; +import { query } from '../../src/prelude/url.js'; describe('url', () => { it('query', () => { diff --git a/packages/backend/test/reaction-lib.ts b/packages/backend/test/reaction-lib.ts index 59c07de00..7c61dc76c 100644 --- a/packages/backend/test/reaction-lib.ts +++ b/packages/backend/test/reaction-lib.ts @@ -1,7 +1,7 @@ /* import * as assert from 'assert'; -import { toDbReaction } from '../src/misc/reaction-lib'; +import { toDbReaction } from '../src/misc/reaction-lib.js'; describe('toDbReaction', async () => { it('既存の文字列リアクションはそのまま', async () => { diff --git a/packages/backend/test/streaming.ts b/packages/backend/test/streaming.ts index e4b651aa9..8d22b6d3d 100644 --- a/packages/backend/test/streaming.ts +++ b/packages/backend/test/streaming.ts @@ -2,8 +2,8 @@ process.env.NODE_ENV = 'test'; import * as assert from 'assert'; import * as childProcess from 'child_process'; -import { connectStream, signup, request, post, startServer, shutdownServer, initTestDb } from './utils'; -import { Following } from '../src/models/entities/following'; +import { connectStream, signup, request, post, startServer, shutdownServer, initTestDb } from './utils.js'; +import { Following } from '../src/models/entities/following.js'; describe('Streaming', () => { let p: childProcess.ChildProcess; diff --git a/packages/backend/test/thread-mute.ts b/packages/backend/test/thread-mute.ts index 95601cd90..cd3e51939 100644 --- a/packages/backend/test/thread-mute.ts +++ b/packages/backend/test/thread-mute.ts @@ -2,7 +2,7 @@ process.env.NODE_ENV = 'test'; import * as assert from 'assert'; import * as childProcess from 'child_process'; -import { async, signup, request, post, react, connectStream, startServer, shutdownServer } from './utils'; +import { async, signup, request, post, react, connectStream, startServer, shutdownServer } from './utils.js'; describe('Note thread mute', () => { let p: childProcess.ChildProcess; diff --git a/packages/backend/test/tsconfig.json b/packages/backend/test/tsconfig.json index 9f9e724ea..3f9020d46 100644 --- a/packages/backend/test/tsconfig.json +++ b/packages/backend/test/tsconfig.json @@ -10,7 +10,7 @@ "declaration": false, "sourceMap": true, "target": "es2017", - "module": "commonjs", + "module": "es2020", "moduleResolution": "node", "allowSyntheticDefaultImports": true, "removeComments": false, diff --git a/packages/backend/test/user-notes.ts b/packages/backend/test/user-notes.ts index c90c07d75..25ffe0475 100644 --- a/packages/backend/test/user-notes.ts +++ b/packages/backend/test/user-notes.ts @@ -2,7 +2,7 @@ process.env.NODE_ENV = 'test'; import * as assert from 'assert'; import * as childProcess from 'child_process'; -import { async, signup, request, post, uploadFile, startServer, shutdownServer } from './utils'; +import { async, signup, request, post, uploadFile, startServer, shutdownServer } from './utils.js'; describe('users/notes', () => { let p: childProcess.ChildProcess; diff --git a/packages/backend/test/utils.ts b/packages/backend/test/utils.ts index b7f6cfbda..994c098b7 100644 --- a/packages/backend/test/utils.ts +++ b/packages/backend/test/utils.ts @@ -1,14 +1,14 @@ -import * as fs from 'fs'; +import * as fs from 'node:fs'; import * as WebSocket from 'ws'; import * as misskey from 'misskey-js'; import fetch from 'node-fetch'; -const FormData = require('form-data'); +import FormData from 'form-data'; import * as childProcess from 'child_process'; import * as http from 'http'; -import loadConfig from '../src/config/load'; +import loadConfig from '../src/config/load.js'; import { SIGKILL } from 'constants'; import { createConnection, getConnection } from 'typeorm'; -import { entities } from '../src/db/postgre'; +import { entities } from '../src/db/postgre.js'; const config = loadConfig(); export const port = config.port; diff --git a/packages/backend/tsconfig.json b/packages/backend/tsconfig.json index f3252b286..3120851aa 100644 --- a/packages/backend/tsconfig.json +++ b/packages/backend/tsconfig.json @@ -10,7 +10,7 @@ "declaration": false, "sourceMap": false, "target": "es2017", - "module": "commonjs", + "module": "es2020", "moduleResolution": "node", "allowSyntheticDefaultImports": true, "removeComments": false, diff --git a/packages/backend/yarn.lock b/packages/backend/yarn.lock index 878ba11f7..c5b123772 100644 --- a/packages/backend/yarn.lock +++ b/packages/backend/yarn.lock @@ -82,14 +82,14 @@ pump "^3.0.0" secure-json-parse "^2.1.0" -"@eslint/eslintrc@^1.0.5": - version "1.0.5" - resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-1.0.5.tgz#33f1b838dbf1f923bfa517e008362b78ddbbf318" - integrity sha512-BLxsnmK3KyPunz5wmCCpqy0YelEoxxGmH73Is+Z74oOTMtExcjkr3dDR6quwrjh1YspA8DH9gnX1o069KiS9AQ== +"@eslint/eslintrc@^1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-1.2.0.tgz#7ce1547a5c46dfe56e1e45c3c9ed18038c721c6a" + integrity sha512-igm9SjJHNEJRiUnecP/1R5T3wKLEJ7pL6e2P+GUSfCd0dGjPYYZve08uzw8L2J8foVHFz+NGu12JxRcU2gGo6w== dependencies: ajv "^6.12.4" debug "^4.3.2" - espree "^9.2.0" + espree "^9.3.1" globals "^13.9.0" ignore "^4.0.6" import-fresh "^3.2.1" @@ -128,10 +128,10 @@ resolved "https://registry.yarnpkg.com/@koa/multer/-/multer-3.0.0.tgz#439777949f28097d7b329c0b4ce3048074c862f8" integrity sha512-y+OQBmex5D1jIl723gAEUYcAWPEicIXppaAKw/zCMfpllQ08ZNweDPwoCLxEoatqd5pCu2XG6V8dl67JRq3RJw== -"@koa/router@9.0.1": - version "9.0.1" - resolved "https://registry.yarnpkg.com/@koa/router/-/router-9.0.1.tgz#4090a14223ea7e78aa13b632761209cba69acd95" - integrity sha512-OI+OU49CJV4px0WkIMmayBeqVXB/JS1ZMq7UoGlTZt6Y7ijK7kdeQ18+SEHHJPytmtI1y6Hf8XLrpxva3mhv5Q== +"@koa/router@10.1.1": + version "10.1.1" + resolved "https://registry.yarnpkg.com/@koa/router/-/router-10.1.1.tgz#8e5a85c9b243e0bc776802c0de564561e57a5f78" + integrity sha512-ORNjq5z4EmQPriKbR0ER3k4Gh7YGNhWDL7JBW+8wXDrHLbWYKYSJaOJ9aN06npF5tbTxe2JBOsurpJDAvjiXKw== dependencies: debug "^4.1.1" http-errors "^1.7.3" @@ -216,10 +216,10 @@ require-from-string "^2.0.2" uri-js "^4.2.2" -"@redocly/openapi-core@1.0.0-beta.79": - version "1.0.0-beta.79" - resolved "https://registry.yarnpkg.com/@redocly/openapi-core/-/openapi-core-1.0.0-beta.79.tgz#7512b3507ab99dc78226f9069669c5302abb0969" - integrity sha512-do79vGt3iiHsaVG9LKY8dH+d1E7TLHr+3T+CQ1lqagtWVjYOxqGaoxAT8tRD7R1W0z8BmS4e2poNON6c1sxP5g== +"@redocly/openapi-core@1.0.0-beta.83": + version "1.0.0-beta.83" + resolved "https://registry.yarnpkg.com/@redocly/openapi-core/-/openapi-core-1.0.0-beta.83.tgz#df1324cc6f1874ecf3046e503192cf872f134a2f" + integrity sha512-XwlxMAmNEQeyBfODXVg2iBpSUqzCwT2zI+7o5iKxjUwJ+5ZugNOYjZGGM3Q9rJGqzFVwLKdElM5a1MlhPvlu4Q== dependencies: "@redocly/ajv" "^8.6.4" "@types/node" "^14.11.8" @@ -237,10 +237,10 @@ resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-3.1.2.tgz#548650de521b344e3781fbdb0ece4aa6f729afb8" integrity sha512-JiX9vxoKMmu8Y3Zr2RVathBL1Cdu4Nt4MuNWemt1Nc06A0RAin9c5FArkhGsyMBWfCu4zj+9b+GxtjAnE4qqLQ== -"@sindresorhus/is@^4.0.0": - version "4.4.0" - resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-4.4.0.tgz#e277e5bdbdf7cb1e20d320f02f5e2ed113cd3185" - integrity sha512-QppPM/8l3Mawvh4rn9CNEYIU9bxpXUCRMaX9yUpvBk1nMKusLKpfXGDEKExKaPhLzcn3lzil7pR6rnJ11HgeRQ== +"@sindresorhus/is@^4.2.0": + version "4.6.0" + resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-4.6.0.tgz#3c7c9c46e678feefe7a2e5bb609d3dbd665ffb3f" + integrity sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw== "@sinonjs/commons@^1.7.0": version "1.7.2" @@ -249,10 +249,10 @@ dependencies: type-detect "4.0.8" -"@sinonjs/fake-timers@9.1.0": - version "9.1.0" - resolved "https://registry.yarnpkg.com/@sinonjs/fake-timers/-/fake-timers-9.1.0.tgz#8c92c56f195e0bed4c893ba59c8e3d55831ca0df" - integrity sha512-M8vapsv9qQupMdzrVzkn5rb9jG7aUTEPAZdMtME2PuBaefksFZVE2C1g4LBRTkF/k3nRDNbDc5tp5NFC1PEYxA== +"@sinonjs/fake-timers@9.1.1": + version "9.1.1" + resolved "https://registry.yarnpkg.com/@sinonjs/fake-timers/-/fake-timers-9.1.1.tgz#7b698e0b9d12d93611f06ee143c30ced848e2840" + integrity sha512-Wp5vwlZ0lOqpSYGKqr53INws9HLkt6JDc/pDZcPf7bchQnrXJMXPns8CXx0hFikMSGSWfvtvvpb2gtMVfkWagA== dependencies: "@sinonjs/commons" "^1.7.0" @@ -279,6 +279,13 @@ dependencies: defer-to-connect "^2.0.0" +"@szmarczak/http-timer@^5.0.1": + version "5.0.1" + resolved "https://registry.yarnpkg.com/@szmarczak/http-timer/-/http-timer-5.0.1.tgz#c7c1bf1141cdd4751b0399c8fc7b8b664cd5be3a" + integrity sha512-+PmQX0PiAYPMeVYe237LJAYvOMYW1j2rH5YROyS3b4CTVJum34HfRvKvAzozHAQG0TnHNdUfY9nCeUyRAs//cw== + dependencies: + defer-to-connect "^2.0.1" + "@tokenizer/token@^0.3.0": version "0.3.0" resolved "https://registry.yarnpkg.com/@tokenizer/token/-/token-0.3.0.tgz#fe98a93fe789247e998c75e74e9c7c63217aa276" @@ -334,10 +341,10 @@ "@types/connect" "*" "@types/node" "*" -"@types/bull@3.15.7": - version "3.15.7" - resolved "https://registry.yarnpkg.com/@types/bull/-/bull-3.15.7.tgz#a9d7fb332cc02dc021d0eb234b9604b356e9e6de" - integrity sha512-7NC7XN5NoS0A+leJ/dR69ZfKaegOlCZaii/xGgKnCyh1UYisRncibImb7VMwrc3OdJcbDJt6+4om70TeNl3J7g== +"@types/bull@3.15.8": + version "3.15.8" + resolved "https://registry.yarnpkg.com/@types/bull/-/bull-3.15.8.tgz#ae2139f94490d740b37c8da5d828ce75dd82ce7c" + integrity sha512-8DbSPMSsZH5PWPnGEkAZLYgJEH4ghHJNKF7LB6Wr5R0/v6g+Vs+JoaA7kcvLtHE936xg2WpFPkaoaJgExOmKDw== dependencies: "@types/ioredis" "*" "@types/redis" "^2.8.0" @@ -352,6 +359,16 @@ "@types/node" "*" "@types/responselike" "*" +"@types/cacheable-request@^6.0.2": + version "6.0.2" + resolved "https://registry.yarnpkg.com/@types/cacheable-request/-/cacheable-request-6.0.2.tgz#c324da0197de0a98a2312156536ae262429ff6b9" + integrity sha512-B3xVo+dlKM6nnKTcmm5ZtY/OL8bOAOd2Olee9M1zft65ox50OzjEHW91sDiU9j6cvW8Ejg1/Qkf4xd2kugApUA== + dependencies: + "@types/http-cache-semantics" "*" + "@types/keyv" "*" + "@types/node" "*" + "@types/responselike" "*" + "@types/cbor@6.0.0": version "6.0.0" resolved "https://registry.yarnpkg.com/@types/cbor/-/cbor-6.0.0.tgz#ddead015e14ef4463287d40cd92a6297a34dac8d" @@ -421,14 +438,6 @@ dependencies: "@types/node" "*" -"@types/glob@7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@types/glob/-/glob-7.2.0.tgz#bc1b5bf3aa92f25bd5dd39f35c57361bdce5b2eb" - integrity sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA== - dependencies: - "@types/minimatch" "*" - "@types/node" "*" - "@types/http-assert@*": version "1.5.1" resolved "https://registry.yarnpkg.com/@types/http-assert/-/http-assert-1.5.1.tgz#d775e93630c2469c2f980fc27e3143240335db3b" @@ -502,10 +511,10 @@ dependencies: "@types/node" "*" -"@types/koa-bodyparser@4.3.5": - version "4.3.5" - resolved "https://registry.yarnpkg.com/@types/koa-bodyparser/-/koa-bodyparser-4.3.5.tgz#0c5fa44d7150202ffc16b89bd730ce1b6c7bc250" - integrity sha512-NRqqoTtt7cfdDk/KNo+EwCIKRuzPAu/wsaZ7tgIvSIBtNfxuZHYueaLoWdxX3ZftWavQv07NE46TcpyoZGqpgQ== +"@types/koa-bodyparser@4.3.6": + version "4.3.6" + resolved "https://registry.yarnpkg.com/@types/koa-bodyparser/-/koa-bodyparser-4.3.6.tgz#99a7d215560fdc168334ebb6a259c6cec9381a56" + integrity sha512-keCpj2kmoooL2oHC9YIVvciN66uDT21uMp4rvrosyjLsHD1aAipn6cg3xSxav9tR2Ly/NMvs8jdlNPTTQvn8SA== dependencies: "@types/koa" "*" @@ -612,15 +621,10 @@ resolved "https://registry.yarnpkg.com/@types/mime/-/mime-2.0.1.tgz#dc488842312a7f075149312905b5e3c0b054c79d" integrity sha512-FwI9gX75FgVBJ7ywgnq/P7tw+/o1GUbtP0KzbtusLigAOgIgNISRK0ZPl4qertvXSIE8YbsVJueQ90cDt9YYyw== -"@types/minimatch@*": - version "3.0.3" - resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.3.tgz#3dca0e3f33b200fc7d1139c0cd96c1268cadfd9d" - integrity sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA== - -"@types/mocha@8.2.3": - version "8.2.3" - resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-8.2.3.tgz#bbeb55fbc73f28ea6de601fbfa4613f58d785323" - integrity sha512-ekGvFhFgrc2zYQoX4JeZPmVzZxw6Dtllga7iGHzfbYIYkAMUx/sAFP2GdFpLff+vdHXu5fl7WX9AT+TtqYcsyw== +"@types/mocha@9.1.0": + version "9.1.0" + resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-9.1.0.tgz#baf17ab2cca3fcce2d322ebc30454bff487efad5" + integrity sha512-QCWHkbMv4Y5U9oW10Uxbr45qMMSzl4OzijsozynUAgx3kEHUdXB00udx2dWDQ7f2TU2a2uuiFaRZjCe3unPpeg== "@types/node-fetch@3.0.3": version "3.0.3" @@ -634,10 +638,10 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-16.6.2.tgz#331b7b9f8621c638284787c5559423822fdffc50" integrity sha512-LSw8TZt12ZudbpHc6EkIyDM3nHVWKYrAvGy6EAJfNfjusbwnThqjqxUKKRwuV3iWYeW/LYMzNgaq3MaLffQ2xA== -"@types/node@17.0.14": - version "17.0.14" - resolved "https://registry.yarnpkg.com/@types/node/-/node-17.0.14.tgz#33b9b94f789a8fedd30a68efdbca4dbb06b61f20" - integrity sha512-SbjLmERksKOGzWzPNuW7fJM7fk3YXVTFiZWB/Hs99gwhk+/dnrQRPBQjPW9aO+fi1tAffi9PrwFvsmOKmDTyng== +"@types/node@17.0.21": + version "17.0.21" + resolved "https://registry.yarnpkg.com/@types/node/-/node-17.0.21.tgz#864b987c0c68d07b4345845c3e63b75edd143644" + integrity sha512-DBZCJbhII3r90XbQxI8Y9IjjiiOGlZ0Hr32omXIZvwwZ7p4DMMXGrKXVyPfuoBOri9XNtL0UK69jYIBIsRX3QQ== "@types/node@^14.11.8": version "14.17.9" @@ -712,14 +716,6 @@ dependencies: "@types/redis" "^2.8.0" -"@types/readable-stream@^2.3.9": - version "2.3.9" - resolved "https://registry.yarnpkg.com/@types/readable-stream/-/readable-stream-2.3.9.tgz#40a8349e6ace3afd2dd1b6d8e9b02945de4566a9" - integrity sha512-sqsgQqFT7HmQz/V5jH1O0fvQQnXAJO46Gg9LRO/JPfjmVmGUlcx831TZZO3Y3HtWhIkzf3kTsNT0Z0kzIhIvZw== - dependencies: - "@types/node" "*" - safe-buffer "*" - "@types/redis@4.0.11": version "4.0.11" resolved "https://registry.yarnpkg.com/@types/redis/-/redis-4.0.11.tgz#0bb4c11ac9900a21ad40d2a6768ec6aaf651c0e1" @@ -753,11 +749,6 @@ dependencies: htmlparser2 "^6.0.0" -"@types/seedrandom@3.0.1": - version "3.0.1" - resolved "https://registry.yarnpkg.com/@types/seedrandom/-/seedrandom-3.0.1.tgz#1254750a4fec4aff2ebec088ccd0bb02e91fedb4" - integrity sha512-giB9gzDeiCeloIXDgzFBCgjj1k4WxcDrZtGl6h1IqmUPlxF+Nx8Ve+96QCyDZ/HseB/uvDsKbpib9hU5cU53pw== - "@types/serve-static@*": version "1.13.3" resolved "https://registry.yarnpkg.com/@types/serve-static/-/serve-static-1.13.3.tgz#eb7e1c41c4468272557e897e9171ded5e2ded9d1" @@ -824,10 +815,10 @@ dependencies: "@types/node" "*" -"@types/ws@8.2.2": - version "8.2.2" - resolved "https://registry.yarnpkg.com/@types/ws/-/ws-8.2.2.tgz#7c5be4decb19500ae6b3d563043cd407bf366c21" - integrity sha512-NOn5eIcgWLOo6qW8AcuLZ7G8PycXu0xTxxkS6Q18VWFxgPUSOwV0pBj2a/4viNZVu25i7RIB7GttdkAIUUXOOg== +"@types/ws@8.5.2": + version "8.5.2" + resolved "https://registry.yarnpkg.com/@types/ws/-/ws-8.5.2.tgz#77e0c2e360e9579da930ffcfa53c5975ea3bdd26" + integrity sha512-VXI82ykONr5tacHEojnErTQk+KQSoYbW1NB6iz6wUwrNd+BqfkfggQNoNdCqhJSzbNumShPERbM+Pc5zpfhlbw== dependencies: "@types/node" "*" @@ -836,14 +827,14 @@ resolved "https://registry.yarnpkg.com/@types/zen-observable/-/zen-observable-0.8.2.tgz#808c9fa7e4517274ed555fa158f2de4b4f468e71" integrity sha512-HrCIVMLjE1MOozVoD86622S7aunluLb2PJdPfb3nYiEtohm8mIB/vyv0Fd37AdeMFrTUQXEunw78YloMA3Qilg== -"@typescript-eslint/eslint-plugin@5.10.2": - version "5.10.2" - resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.10.2.tgz#f8c1d59fc37bd6d9d11c97267fdfe722c4777152" - integrity sha512-4W/9lLuE+v27O/oe7hXJKjNtBLnZE8tQAFpapdxwSVHqtmIoPB1gph3+ahNwVuNL37BX7YQHyGF9Xv6XCnIX2Q== +"@typescript-eslint/eslint-plugin@5.14.0": + version "5.14.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.14.0.tgz#5119b67152356231a0e24b998035288a9cd21335" + integrity sha512-ir0wYI4FfFUDfLcuwKzIH7sMVA+db7WYen47iRSaCGl+HMAZI9fpBwfDo45ZALD3A45ZGyHWDNLhbg8tZrMX4w== dependencies: - "@typescript-eslint/scope-manager" "5.10.2" - "@typescript-eslint/type-utils" "5.10.2" - "@typescript-eslint/utils" "5.10.2" + "@typescript-eslint/scope-manager" "5.14.0" + "@typescript-eslint/type-utils" "5.14.0" + "@typescript-eslint/utils" "5.14.0" debug "^4.3.2" functional-red-black-tree "^1.0.1" ignore "^5.1.8" @@ -851,69 +842,69 @@ semver "^7.3.5" tsutils "^3.21.0" -"@typescript-eslint/parser@5.10.2": - version "5.10.2" - resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.10.2.tgz#b6076d27cc5499ce3f2c625f5ccde946ecb7db9a" - integrity sha512-JaNYGkaQVhP6HNF+lkdOr2cAs2wdSZBoalE22uYWq8IEv/OVH0RksSGydk+sW8cLoSeYmC+OHvRyv2i4AQ7Czg== +"@typescript-eslint/parser@5.14.0": + version "5.14.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.14.0.tgz#7c79f898aa3cff0ceee6f1d34eeed0f034fb9ef3" + integrity sha512-aHJN8/FuIy1Zvqk4U/gcO/fxeMKyoSv/rS46UXMXOJKVsLQ+iYPuXNbpbH7cBLcpSbmyyFbwrniLx5+kutu1pw== dependencies: - "@typescript-eslint/scope-manager" "5.10.2" - "@typescript-eslint/types" "5.10.2" - "@typescript-eslint/typescript-estree" "5.10.2" + "@typescript-eslint/scope-manager" "5.14.0" + "@typescript-eslint/types" "5.14.0" + "@typescript-eslint/typescript-estree" "5.14.0" debug "^4.3.2" -"@typescript-eslint/scope-manager@5.10.2": - version "5.10.2" - resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.10.2.tgz#92c0bc935ec00f3d8638cdffb3d0e70c9b879639" - integrity sha512-39Tm6f4RoZoVUWBYr3ekS75TYgpr5Y+X0xLZxXqcZNDWZdJdYbKd3q2IR4V9y5NxxiPu/jxJ8XP7EgHiEQtFnw== +"@typescript-eslint/scope-manager@5.14.0": + version "5.14.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.14.0.tgz#ea518962b42db8ed0a55152ea959c218cb53ca7b" + integrity sha512-LazdcMlGnv+xUc5R4qIlqH0OWARyl2kaP8pVCS39qSL3Pd1F7mI10DbdXeARcE62sVQE4fHNvEqMWsypWO+yEw== dependencies: - "@typescript-eslint/types" "5.10.2" - "@typescript-eslint/visitor-keys" "5.10.2" + "@typescript-eslint/types" "5.14.0" + "@typescript-eslint/visitor-keys" "5.14.0" -"@typescript-eslint/type-utils@5.10.2": - version "5.10.2" - resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-5.10.2.tgz#ad5acdf98a7d2ab030bea81f17da457519101ceb" - integrity sha512-uRKSvw/Ccs5FYEoXW04Z5VfzF2iiZcx8Fu7DGIB7RHozuP0VbKNzP1KfZkHBTM75pCpsWxIthEH1B33dmGBKHw== +"@typescript-eslint/type-utils@5.14.0": + version "5.14.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-5.14.0.tgz#711f08105860b12988454e91df433567205a8f0b" + integrity sha512-d4PTJxsqaUpv8iERTDSQBKUCV7Q5yyXjqXUl3XF7Sd9ogNLuKLkxz82qxokqQ4jXdTPZudWpmNtr/JjbbvUixw== dependencies: - "@typescript-eslint/utils" "5.10.2" + "@typescript-eslint/utils" "5.14.0" debug "^4.3.2" tsutils "^3.21.0" -"@typescript-eslint/types@5.10.2": - version "5.10.2" - resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.10.2.tgz#604d15d795c4601fffba6ecb4587ff9fdec68ce8" - integrity sha512-Qfp0qk/5j2Rz3p3/WhWgu4S1JtMcPgFLnmAKAW061uXxKSa7VWKZsDXVaMXh2N60CX9h6YLaBoy9PJAfCOjk3w== +"@typescript-eslint/types@5.14.0": + version "5.14.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.14.0.tgz#96317cf116cea4befabc0defef371a1013f8ab11" + integrity sha512-BR6Y9eE9360LNnW3eEUqAg6HxS9Q35kSIs4rp4vNHRdfg0s+/PgHgskvu5DFTM7G5VKAVjuyaN476LCPrdA7Mw== -"@typescript-eslint/typescript-estree@5.10.2": - version "5.10.2" - resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.10.2.tgz#810906056cd3ddcb35aa333fdbbef3713b0fe4a7" - integrity sha512-WHHw6a9vvZls6JkTgGljwCsMkv8wu8XU8WaYKeYhxhWXH/atZeiMW6uDFPLZOvzNOGmuSMvHtZKd6AuC8PrwKQ== +"@typescript-eslint/typescript-estree@5.14.0": + version "5.14.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.14.0.tgz#78b7f7385d5b6f2748aacea5c9b7f6ae62058314" + integrity sha512-QGnxvROrCVtLQ1724GLTHBTR0lZVu13izOp9njRvMkCBgWX26PKvmMP8k82nmXBRD3DQcFFq2oj3cKDwr0FaUA== dependencies: - "@typescript-eslint/types" "5.10.2" - "@typescript-eslint/visitor-keys" "5.10.2" + "@typescript-eslint/types" "5.14.0" + "@typescript-eslint/visitor-keys" "5.14.0" debug "^4.3.2" globby "^11.0.4" is-glob "^4.0.3" semver "^7.3.5" tsutils "^3.21.0" -"@typescript-eslint/utils@5.10.2": - version "5.10.2" - resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.10.2.tgz#1fcd37547c32c648ab11aea7173ec30060ee87a8" - integrity sha512-vuJaBeig1NnBRkf7q9tgMLREiYD7zsMrsN1DA3wcoMDvr3BTFiIpKjGiYZoKPllfEwN7spUjv7ZqD+JhbVjEPg== +"@typescript-eslint/utils@5.14.0": + version "5.14.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.14.0.tgz#6c8bc4f384298cbbb32b3629ba7415f9f80dc8c4" + integrity sha512-EHwlII5mvUA0UsKYnVzySb/5EE/t03duUTweVy8Zqt3UQXBrpEVY144OTceFKaOe4xQXZJrkptCf7PjEBeGK4w== dependencies: "@types/json-schema" "^7.0.9" - "@typescript-eslint/scope-manager" "5.10.2" - "@typescript-eslint/types" "5.10.2" - "@typescript-eslint/typescript-estree" "5.10.2" + "@typescript-eslint/scope-manager" "5.14.0" + "@typescript-eslint/types" "5.14.0" + "@typescript-eslint/typescript-estree" "5.14.0" eslint-scope "^5.1.1" eslint-utils "^3.0.0" -"@typescript-eslint/visitor-keys@5.10.2": - version "5.10.2" - resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.10.2.tgz#fdbf272d8e61c045d865bd6c8b41bea73d222f3d" - integrity sha512-zHIhYGGGrFJvvyfwHk5M08C5B5K4bewkm+rrvNTKk1/S15YHR+SA/QUF8ZWscXSfEaB8Nn2puZj+iHcoxVOD/Q== +"@typescript-eslint/visitor-keys@5.14.0": + version "5.14.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.14.0.tgz#1927005b3434ccd0d3ae1b2ecf60e65943c36986" + integrity sha512-yL0XxfzR94UEkjBqyymMLgCBdojzEuy/eim7N9/RIcTNxpJudAcqsU8eRyfzBbcEzGoPWfdM3AGak3cN08WOIw== dependencies: - "@typescript-eslint/types" "5.10.2" + "@typescript-eslint/types" "5.14.0" eslint-visitor-keys "^3.0.0" "@ungap/promise-all-settled@1.1.2": @@ -1013,6 +1004,16 @@ ajv-keywords@^3.5.2: resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.5.2.tgz#31f29da5ab6e00d1c2d329acf7b5929614d5014d" integrity sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ== +ajv@8.10.0: + version "8.10.0" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.10.0.tgz#e573f719bd3af069017e3b66538ab968d040e54d" + integrity sha512-bzqAEZOjkrUMl2afH8dknrq5KEk2SrwdBROR+vH1EKVQTqaUbJVPdc/gEdggTMM0Se+s+Ja4ju4TlNcStKl2Hw== + dependencies: + fast-deep-equal "^3.1.1" + json-schema-traverse "^1.0.0" + require-from-string "^2.0.2" + uri-js "^4.2.2" + ajv@^6.10.0, ajv@^6.12.4, ajv@^6.12.5: version "6.12.5" resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.5.tgz#19b0e8bae8f476e5ba666300387775fb1a00a4da" @@ -1242,10 +1243,10 @@ autwh@0.1.0: dependencies: oauth "0.9.15" -aws-sdk@2.1067.0: - version "2.1067.0" - resolved "https://registry.yarnpkg.com/aws-sdk/-/aws-sdk-2.1067.0.tgz#2e7f5a2d765fcf77a45f25fdd1f12a64942628a7" - integrity sha512-3Ys1k4cNQy4z37IpPjQ9c5ldkXMeZGbWoarKHynPPY3WCEj+Nw2u6zk484fA9/lTHNN3YesLuZ0OmEzGgjFEOw== +aws-sdk@2.1079.0: + version "2.1079.0" + resolved "https://registry.yarnpkg.com/aws-sdk/-/aws-sdk-2.1079.0.tgz#41ede54aa4ba5ce77d4ffe202f9a1ee7869da2a8" + integrity sha512-WHYWiye9f2XYQ33Rj/uVw4VF/Qq/xrB9NDnGlRhgK8Ga7T20+8/iZD5/Z8wICVNZTsfUZ3g6LfkeZ1l+LZhHKw== dependencies: buffer "4.9.2" events "1.1.1" @@ -1350,10 +1351,10 @@ bluebird@~3.4.1: resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.4.7.tgz#f72d760be09b7f76d08ed8fae98b289a8d05fab3" integrity sha1-9y12C+Cbf3bQjtj66Ysomo0F+rM= -blurhash@1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/blurhash/-/blurhash-1.1.4.tgz#a7010ceb3019cd2c9809b17c910ebf6175d29244" - integrity sha512-MXIPz6zwYUKayju+Uidf83KhH0vodZfeRl6Ich8Gu+KGl0JgKiFq9LsfqV7cVU5fKD/AotmduZqvOfrGKOfTaA== +blurhash@1.1.5: + version "1.1.5" + resolved "https://registry.yarnpkg.com/blurhash/-/blurhash-1.1.5.tgz#3034104cd5dce5a3e5caa871ae2f0f1f2d0ab566" + integrity sha512-a+LO3A2DfxTaTztsmkbLYmUzUeApi0LZuKalwbNmqAHR6HhJGMt1qSV/R3wc+w4DL28holjqO3Bg74aUGavGjg== bn.js@^4.0.0: version "4.11.8" @@ -1380,10 +1381,10 @@ braces@^3.0.1, braces@~3.0.2: dependencies: fill-range "^7.0.1" -broadcast-channel@4.9.0: - version "4.9.0" - resolved "https://registry.yarnpkg.com/broadcast-channel/-/broadcast-channel-4.9.0.tgz#8af337d4ea19aeb6b819ec2eb3dda942b28c724c" - integrity sha512-xWzFb3wrOZGJF2kOSs2D3KvHXdLDMVb+WypEIoNvwblcHgUBydVy65pDJ9RS4WN9Kyvs0UVQuCCzfKme0G6Qjw== +broadcast-channel@4.10.0: + version "4.10.0" + resolved "https://registry.yarnpkg.com/broadcast-channel/-/broadcast-channel-4.10.0.tgz#d19fb902df227df40b1b580351713d30c302d198" + integrity sha512-hOUh312XyHk6JTVyX9cyXaH1UYs+2gHVtnW16oQAu9FL7ALcXGXc/YoJWqlkV8vUn14URQPMmRi4A9q4UrwVEQ== dependencies: "@babel/runtime" "^7.16.0" detect-node "^2.1.0" @@ -1466,15 +1467,15 @@ bufferutil@^4.0.1: dependencies: node-gyp-build "~3.7.0" -bull@4.5.0: - version "4.5.0" - resolved "https://registry.yarnpkg.com/bull/-/bull-4.5.0.tgz#d6106b011b711ffb76c687d7f2db416955225f64" - integrity sha512-BejJxGwNNQPIrK1jFTN74kymFORYQ6ZyXWNsZx+6jtDtafQNUMHNSdoepabLLmeldmUvgAHvZDDIJWFGEo2MYg== +bull@4.7.0: + version "4.7.0" + resolved "https://registry.yarnpkg.com/bull/-/bull-4.7.0.tgz#89442d4676117edd9f9a1359bb0edfb489595e70" + integrity sha512-rnJIsuXrDjDlz3HMHz6xobiRZAWe3o4MJBkzx7FdUjO+K2nSYrhR2KpcL+ZCNUMPKtONxL4DqmRjat5SBHFlAw== dependencies: cron-parser "^4.2.1" debuglog "^1.0.0" get-port "^5.1.1" - ioredis "^4.27.0" + ioredis "^4.28.5" lodash "^4.17.21" msgpackr "^1.5.2" p-timeout "^3.2.0" @@ -1526,7 +1527,7 @@ cache-content-type@^1.0.0: mime-types "^2.1.18" ylru "^1.2.0" -cacheable-lookup@6.0.4: +cacheable-lookup@6.0.4, cacheable-lookup@^6.0.4: version "6.0.4" resolved "https://registry.yarnpkg.com/cacheable-lookup/-/cacheable-lookup-6.0.4.tgz#65c0e51721bb7f9f2cb513aed6da4a1b93ad7dc8" integrity sha512-mbcDEZCkv2CZF4G01kr8eBd/5agkt9oCqz75tJMSIsquvRZ2sL6Hi5zGVKi/0OSC9oO1GHfJ2AV0ZIOY9vye0A== @@ -1549,6 +1550,19 @@ cacheable-request@^7.0.1: normalize-url "^4.1.0" responselike "^2.0.0" +cacheable-request@^7.0.2: + version "7.0.2" + resolved "https://registry.yarnpkg.com/cacheable-request/-/cacheable-request-7.0.2.tgz#ea0d0b889364a25854757301ca12b2da77f91d27" + integrity sha512-pouW8/FmiPQbuGpkXQ9BAPv/Mo5xDGANgSNXzTzJ8DrKGuXOssM4wIQRjfanNRh3Yu5cfYPvcorqbhg2KIJtew== + dependencies: + clone-response "^1.0.2" + get-stream "^5.1.0" + http-cache-semantics "^4.0.0" + keyv "^4.0.0" + lowercase-keys "^2.0.0" + normalize-url "^6.0.1" + responselike "^2.0.0" + cafy@15.2.1: version "15.2.1" resolved "https://registry.yarnpkg.com/cafy/-/cafy-15.2.1.tgz#5a55eaeb721c604c7dca652f3d555c392e5f995a" @@ -1604,6 +1618,13 @@ chainsaw@~0.1.0: dependencies: traverse ">=0.3.0 <0.4" +chalk-template@0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/chalk-template/-/chalk-template-0.4.0.tgz#692c034d0ed62436b9062c1707fadcd0f753204b" + integrity sha512-/ghrgmhfY8RaSdeo43hNXxpoHAtxdbskUHjPpfqUWGttFgycUhYPGx3YZBCnUCvOa7Doivn1IZec3DEGFoMgLg== + dependencies: + chalk "^4.1.2" + chalk@4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.0.0.tgz#6e98081ed2d17faab615eb52ac66ec1fe6209e72" @@ -1612,13 +1633,10 @@ chalk@4.0.0: ansi-styles "^4.1.0" supports-color "^7.1.0" -chalk@4.1.2: - version "4.1.2" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" - integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== - dependencies: - ansi-styles "^4.1.0" - supports-color "^7.1.0" +chalk@5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-5.0.1.tgz#ca57d71e82bb534a296df63bbacc4a1c22b2a4b6" + integrity sha512-Fo07WOYGqMfCWHOzSXOt2CxDbC6skS/jO9ynEcmpANMoPrD+W1r1K6Vx7iNm+AQmETU1Xr2t+n8nzkV9t6xh3w== chalk@^2.4.2: version "2.4.2" @@ -1637,6 +1655,14 @@ chalk@^4.0.0, chalk@^4.1.0: ansi-styles "^4.1.0" supports-color "^7.1.0" +chalk@^4.1.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" + integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== + dependencies: + ansi-styles "^4.1.0" + supports-color "^7.1.0" + char-regex@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/char-regex/-/char-regex-1.0.2.tgz#d744358226217f981ed58f479b1d6bcc29545dcf" @@ -1671,7 +1697,7 @@ cheerio@0.22.0: lodash.reject "^4.4.0" lodash.some "^4.4.0" -chokidar@3.5.1, chokidar@^3.3.1, chokidar@^3.5.2: +chokidar@3.5.3, chokidar@^3.3.1, chokidar@^3.5.2: version "3.3.1" resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.3.1.tgz#c84e5b3d18d9a4d77558fef466b1bf16bbeb3450" integrity sha512-4QYCEWOcK3OJrxwvyyAOxFuhpvOVCYkr33LPfFNBjAD/w3sEzWsp2BUOkI4l9bHvWioAd0rc6NlHUOEaWkTeqg== @@ -1773,6 +1799,13 @@ code-point-at@^1.0.0: resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" integrity sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c= +color-convert@2.0.1, color-convert@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" + integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== + dependencies: + color-name "~1.1.4" + color-convert@^1.9.0: version "1.9.3" resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" @@ -1780,13 +1813,6 @@ color-convert@^1.9.0: dependencies: color-name "1.1.3" -color-convert@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" - integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== - dependencies: - color-name "~1.1.4" - color-name@1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" @@ -1810,10 +1836,10 @@ color-support@^1.1.2: resolved "https://registry.yarnpkg.com/color-support/-/color-support-1.1.3.tgz#93834379a1cc9a0c61f82f52f0d04322251bd5a2" integrity sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg== -color@^4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/color/-/color-4.2.0.tgz#0c782459a3e98838ea01e4bc0fb43310ca35af78" - integrity sha512-hHTcrbvEnGjC7WBMk6ibQWFVDgEFTVmjrz2Q5HlU6ltwxv0JJN2Z8I7uRbWeQLF04dikxs8zgyZkazRJvSMtyQ== +color@^4.2.1: + version "4.2.1" + resolved "https://registry.yarnpkg.com/color/-/color-4.2.1.tgz#498aee5fce7fc982606c8875cab080ac0547c884" + integrity sha512-MFJr0uY4RvTQUKvPq7dh9grVOTYSFeXja2mBXioCGjnjJoXrAp9jJ1NQTDR73c9nwBSAQiNKloKl5zq9WB9UPw== dependencies: color-convert "^2.0.1" color-string "^1.9.0" @@ -1939,14 +1965,6 @@ core-util-is@1.0.2, core-util-is@~1.0.0: resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac= -crc-32@1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/crc-32/-/crc-32-1.2.1.tgz#436d2bcaad27bcb6bd073a2587139d3024a16460" - integrity sha512-Dn/xm/1vFFgs3nfrpEVScHoIslO9NZRITWGz/1E/St6u4xw99vfZzVkW0OSnzx2h9egej9xwMCEut6sqwokM/w== - dependencies: - exit-on-epipe "~1.0.1" - printj "~1.3.1" - crc-32@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/crc-32/-/crc-32-1.2.0.tgz#cb2db6e29b88508e32d9dd0ec1693e7b41a18208" @@ -2069,7 +2087,7 @@ debug@2, debug@^2.2.0, debug@^2.5.2, debug@^2.6.9: dependencies: ms "2.0.0" -debug@4, debug@4.3.1, debug@^4.0.1, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1: +debug@4, debug@^4.0.1, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1: version "4.3.1" resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.1.tgz#f0d229c505e0c6d8c49ac553d1b13dc183f6b2ee" integrity sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ== @@ -2166,6 +2184,11 @@ defer-to-connect@^2.0.0: resolved "https://registry.yarnpkg.com/defer-to-connect/-/defer-to-connect-2.0.0.tgz#83d6b199db041593ac84d781b5222308ccf4c2c1" integrity sha512-bYL2d05vOSf1JEZNx5vSAtPuBMkX8K9EUutg7zlKvTqKXHt7RhWJFbmd7qakVuf13i+IkGmp6FwSsONOf6VYIg== +defer-to-connect@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/defer-to-connect/-/defer-to-connect-2.0.1.tgz#8016bdb4143e4632b77a3449c6236277de520587" + integrity sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg== + define-properties@^1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1" @@ -2218,6 +2241,11 @@ detect-libc@^2.0.0: resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-2.0.0.tgz#c528bc09bc6d1aa30149228240917c225448f204" integrity sha512-S55LzUl8HUav8l9E2PBTlC5PAJrHK7tkM+XXFGD+fbsbkTzhCpG6K05LxJcUOEWzMa4v6ptcMZ9s3fOdJDu0Zw== +detect-libc@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-2.0.1.tgz#e1897aa88fa6ad197862937fbc0441ef352ee0cd" + integrity sha512-463v3ZeIrcWtdgIg6vI6XUncguvr2TnGl4SzDXinkt9mSLpBJKXT3mW6xT3VQdDN11+WVs29pgvivTc4Lp8v+w== + detect-node@2.1.0, detect-node@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/detect-node/-/detect-node-2.1.0.tgz#c9c70775a49c3d03bc2c06d9a73be550f978f8b1" @@ -2615,10 +2643,10 @@ eslint-scope@^5.1.1: esrecurse "^4.3.0" estraverse "^4.1.1" -eslint-scope@^7.1.0: - version "7.1.0" - resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-7.1.0.tgz#c1f6ea30ac583031f203d65c73e723b01298f153" - integrity sha512-aWwkhnS0qAXqNOgKOK0dJ2nvzEbhEvpy8OlJ9kZ0FeZnA6zpjv1/Vei+puGFFX7zkPCkHHXb7IDX3A+7yPrRWg== +eslint-scope@^7.1.1: + version "7.1.1" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-7.1.1.tgz#fff34894c2f65e5226d3041ac480b4513a163642" + integrity sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw== dependencies: esrecurse "^4.3.0" estraverse "^5.2.0" @@ -2640,17 +2668,17 @@ eslint-visitor-keys@^3.0.0: resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.0.0.tgz#e32e99c6cdc2eb063f204eda5db67bfe58bb4186" integrity sha512-mJOZa35trBTb3IyRmo8xmKBZlxf+N7OnUl4+ZhJHs/r+0770Wh/LEACE2pqMGMe27G/4y8P2bYGk4J70IC5k1Q== -eslint-visitor-keys@^3.1.0, eslint-visitor-keys@^3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.2.0.tgz#6fbb166a6798ee5991358bc2daa1ba76cc1254a1" - integrity sha512-IOzT0X126zn7ALX0dwFiUQEdsfzrm4+ISsQS8nukaJXwEyYKRSnEIIDULYg1mCtGp7UUXgfGl7BIolXREQK+XQ== +eslint-visitor-keys@^3.3.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz#f6480fa6b1f30efe2d1968aa8ac745b862469826" + integrity sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA== -eslint@8.8.0: - version "8.8.0" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.8.0.tgz#9762b49abad0cb4952539ffdb0a046392e571a2d" - integrity sha512-H3KXAzQGBH1plhYS3okDix2ZthuYJlQQEGE5k0IKuEqUSiyu4AmxxlJ2MtTYeJ3xB4jDhcYCwGOg2TXYdnDXlQ== +eslint@8.10.0: + version "8.10.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.10.0.tgz#931be395eb60f900c01658b278e05b6dae47199d" + integrity sha512-tcI1D9lfVec+R4LE1mNDnzoJ/f71Kl/9Cv4nG47jOueCMBrCCKYXr4AUVS7go6mWYGFD4+EoN6+eXSrEbRzXVw== dependencies: - "@eslint/eslintrc" "^1.0.5" + "@eslint/eslintrc" "^1.2.0" "@humanwhocodes/config-array" "^0.9.2" ajv "^6.10.0" chalk "^4.0.0" @@ -2658,10 +2686,10 @@ eslint@8.8.0: debug "^4.3.2" doctrine "^3.0.0" escape-string-regexp "^4.0.0" - eslint-scope "^7.1.0" + eslint-scope "^7.1.1" eslint-utils "^3.0.0" - eslint-visitor-keys "^3.2.0" - espree "^9.3.0" + eslint-visitor-keys "^3.3.0" + espree "^9.3.1" esquery "^1.4.0" esutils "^2.0.2" fast-deep-equal "^3.1.3" @@ -2691,14 +2719,14 @@ esm@^3.2.22: resolved "https://registry.yarnpkg.com/esm/-/esm-3.2.25.tgz#342c18c29d56157688ba5ce31f8431fbb795cc10" integrity sha512-U1suiZ2oDVWv4zPO56S0NcR5QriEahGtdN2OR6FiOG4WJvcjBVFB0qI4+eKoWFH483PKGuLuu6V8Z4T5g63UVA== -espree@^9.2.0, espree@^9.3.0: - version "9.3.0" - resolved "https://registry.yarnpkg.com/espree/-/espree-9.3.0.tgz#c1240d79183b72aaee6ccfa5a90bc9111df085a8" - integrity sha512-d/5nCsb0JcqsSEeQzFZ8DH1RmxPcglRWh24EFTlUEmCKoehXGdpsx0RkHDubqUI8LSAIKMQp4r9SzQ3n+sm4HQ== +espree@^9.3.1: + version "9.3.1" + resolved "https://registry.yarnpkg.com/espree/-/espree-9.3.1.tgz#8793b4bc27ea4c778c19908e0719e7b8f4115bcd" + integrity sha512-bvdyLmJMfwkV3NCRl5ZhJf22zBFo1y8bYh3VYb+bfzqNB4Je68P2sSuXyuFquzWLebHpNd2/d5uv7yoP9ISnGQ== dependencies: acorn "^8.7.0" acorn-jsx "^5.3.1" - eslint-visitor-keys "^3.1.0" + eslint-visitor-keys "^3.3.0" esprima@^4.0.1: version "4.0.1" @@ -2744,7 +2772,7 @@ event-target-shim@^5.0.0: resolved "https://registry.yarnpkg.com/event-target-shim/-/event-target-shim-5.0.1.tgz#5d4d3ebdf9583d63a5333ce2deb7480ab2b05789" integrity sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ== -eventemitter3@4.0.7, eventemitter3@^4.0.4, eventemitter3@^4.0.7: +eventemitter3@^4.0.4, eventemitter3@^4.0.7: version "4.0.7" resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.7.tgz#2de9b68f6528d5644ef5c59526a1b4a07306169f" integrity sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw== @@ -2754,19 +2782,19 @@ events@1.1.1: resolved "https://registry.yarnpkg.com/events/-/events-1.1.1.tgz#9ebdb7635ad099c70dcc4c2a1f5004288e8bd924" integrity sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ= -execa@6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/execa/-/execa-6.0.0.tgz#598b46f09ae44f5d8097a30cfb1681d0f0371503" - integrity sha512-m4wU9j4Z9nXXoqT8RSfl28JSwmMNLFF69OON8H/lL3NeU0tNpGz313bcOfYoBBHokB0dC2tMl3VUcKgHELhL2Q== +execa@6.1.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/execa/-/execa-6.1.0.tgz#cea16dee211ff011246556388effa0818394fb20" + integrity sha512-QVWlX2e50heYJcCPG0iWtf8r0xjEYfz/OYLGDYH+IyjWezzPNxz63qNFOu0l4YftGWuizFVZHHs8PrLU5p2IDA== dependencies: cross-spawn "^7.0.3" get-stream "^6.0.1" human-signals "^3.0.1" is-stream "^3.0.0" merge-stream "^2.0.0" - npm-run-path "^5.0.1" + npm-run-path "^5.1.0" onetime "^6.0.0" - signal-exit "^3.0.5" + signal-exit "^3.0.7" strip-final-newline "^3.0.0" exit-on-epipe@~1.0.1: @@ -2881,14 +2909,14 @@ file-entry-cache@^6.0.1: dependencies: flat-cache "^3.0.4" -file-type@16.5.3: - version "16.5.3" - resolved "https://registry.yarnpkg.com/file-type/-/file-type-16.5.3.tgz#474b7e88c74724046abb505e9b8ed4db30c4fc06" - integrity sha512-uVsl7iFhHSOY4bEONLlTK47iAHtNsFHWP5YE4xJfZ4rnX7S1Q3wce09XgqSC7E/xh8Ncv/be1lNoyprlUH/x6A== +file-type@17.1.1: + version "17.1.1" + resolved "https://registry.yarnpkg.com/file-type/-/file-type-17.1.1.tgz#24c59bc663df0c0c181b31dfacde25e06431afbe" + integrity sha512-heRUMZHby2Qj6wZAA3YHeMlRmZNQTcb6VxctkGmM+mcM6ROQKvHpr7SS6EgdfEhH+s25LDshBjvPx/Ecm+bOVQ== dependencies: - readable-web-to-node-stream "^3.0.0" - strtok3 "^6.2.4" - token-types "^4.1.1" + readable-web-to-node-stream "^3.0.2" + strtok3 "^7.0.0-alpha.7" + token-types "^5.0.0-alpha.2" fill-range@^7.0.1: version "7.0.1" @@ -2969,6 +2997,11 @@ follow-redirects@^1.14.4: resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.14.7.tgz#2004c02eb9436eee9a21446a6477debf17e81685" integrity sha512-+hbxoLbFMbRKDwohX8GkTataGqO6Jb7jGwpAlwgy2bIz25XtRm7KEzJM76R1WiNT5SwZkX4Y75SwBolkpmE7iQ== +form-data-encoder@1.7.1: + version "1.7.1" + resolved "https://registry.yarnpkg.com/form-data-encoder/-/form-data-encoder-1.7.1.tgz#ac80660e4f87ee0d3d3c3638b7da8278ddb8ec96" + integrity sha512-EFRDrsMm/kyqbTQocNvRXMLjc7Es2Vk+IQFx/YW7hkUH1eBl4J1fqiP34l74Yt0pFLCNpc06fkbVk00008mzjg== + form-data@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.0.tgz#93919daeaf361ee529584b9b31664dc12c9fa452" @@ -3147,10 +3180,10 @@ glob-parent@^6.0.1: dependencies: is-glob "^4.0.3" -glob@7.1.6, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6: - version "7.1.6" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6" - integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA== +glob@7.2.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.0.tgz#d15535af7732e02e948f4c41628bd910293f6023" + integrity sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q== dependencies: fs.realpath "^1.0.0" inflight "^1.0.4" @@ -3159,10 +3192,10 @@ glob@7.1.6, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6: once "^1.3.0" path-is-absolute "^1.0.0" -glob@7.2.0: - version "7.2.0" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.0.tgz#d15535af7732e02e948f4c41628bd910293f6023" - integrity sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q== +glob@^7.1.3, glob@^7.1.4, glob@^7.1.6: + version "7.1.6" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6" + integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA== dependencies: fs.realpath "^1.0.0" inflight "^1.0.4" @@ -3234,21 +3267,23 @@ got@11.5.1: p-cancelable "^2.0.0" responselike "^2.0.0" -got@11.8.2: - version "11.8.2" - resolved "https://registry.yarnpkg.com/got/-/got-11.8.2.tgz#7abb3959ea28c31f3576f1576c1effce23f33599" - integrity sha512-D0QywKgIe30ODs+fm8wMZiAcZjypcCodPNuMz5H9Mny7RJ+IjJ10BdmGW7OM7fHXP+O7r6ZwapQ/YQmMSvB0UQ== +got@12.0.1: + version "12.0.1" + resolved "https://registry.yarnpkg.com/got/-/got-12.0.1.tgz#78747f1c5bc7069bbd739636ed8b70c7f2140a39" + integrity sha512-1Zhoh+lDej3t7Ks1BP/Jufn+rNqdiHQgUOcTxHzg2Dao1LQfp5S4Iq0T3iBxN4Zdo7QqCJL+WJUNzDX6rCP2Ew== dependencies: - "@sindresorhus/is" "^4.0.0" - "@szmarczak/http-timer" "^4.0.5" - "@types/cacheable-request" "^6.0.1" + "@sindresorhus/is" "^4.2.0" + "@szmarczak/http-timer" "^5.0.1" + "@types/cacheable-request" "^6.0.2" "@types/responselike" "^1.0.0" - cacheable-lookup "^5.0.3" - cacheable-request "^7.0.1" + cacheable-lookup "^6.0.4" + cacheable-request "^7.0.2" decompress-response "^6.0.0" - http2-wrapper "^1.0.0-beta.5.2" - lowercase-keys "^2.0.0" - p-cancelable "^2.0.0" + form-data-encoder "1.7.1" + get-stream "^6.0.1" + http2-wrapper "^2.1.9" + lowercase-keys "^3.0.0" + p-cancelable "^3.0.0" responselike "^2.0.0" graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.4: @@ -3437,7 +3472,7 @@ http-signature@1.3.6: jsprim "^2.0.2" sshpk "^1.14.1" -http2-wrapper@^1.0.0-beta.5.0, http2-wrapper@^1.0.0-beta.5.2: +http2-wrapper@^1.0.0-beta.5.0: version "1.0.3" resolved "https://registry.yarnpkg.com/http2-wrapper/-/http2-wrapper-1.0.3.tgz#b8f55e0c1f25d4ebd08b3b0c2c079f9590800b3d" integrity sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg== @@ -3445,6 +3480,14 @@ http2-wrapper@^1.0.0-beta.5.0, http2-wrapper@^1.0.0-beta.5.2: quick-lru "^5.1.1" resolve-alpn "^1.0.0" +http2-wrapper@^2.1.9: + version "2.1.10" + resolved "https://registry.yarnpkg.com/http2-wrapper/-/http2-wrapper-2.1.10.tgz#307cd0cee2564723692ad34c2d570d12f10e83be" + integrity sha512-QHgsdYkieKp+6JbXP25P+tepqiHYd+FVnDwXpxi/BlUcoIB0nsmTOymTNvETuTO+pDuwcSklPE72VR3DqV+Haw== + dependencies: + quick-lru "^5.1.1" + resolve-alpn "^1.2.0" + http_ece@1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/http_ece/-/http_ece-1.1.0.tgz#74780c6eb32d8ddfe9e36a83abcd81fe0cd4fb75" @@ -3593,16 +3636,17 @@ internal-slot@^1.0.3: has "^1.0.3" side-channel "^1.0.4" -ioredis@^4.27.0: - version "4.27.6" - resolved "https://registry.yarnpkg.com/ioredis/-/ioredis-4.27.6.tgz#a53d427d3fe75fbd10ed7ad150ce00559df8dcf8" - integrity sha512-6W3ZHMbpCa8ByMyC1LJGOi7P2WiOKP9B3resoZOVLDhi+6dDBOW+KNsRq3yI36Hmnb2sifCxHX+YSarTeXh48A== +ioredis@^4.28.5: + version "4.28.5" + resolved "https://registry.yarnpkg.com/ioredis/-/ioredis-4.28.5.tgz#5c149e6a8d76a7f8fa8a504ffc85b7d5b6797f9f" + integrity sha512-3GYo0GJtLqgNXj4YhrisLaNNvWSNwSS2wS4OELGfGxH8I69+XfNdnmV1AyN+ZqMh0i7eX+SWjrwFKDBDgfBC1A== dependencies: cluster-key-slot "^1.1.0" debug "^4.3.1" denque "^1.1.0" lodash.defaults "^4.2.0" lodash.flatten "^4.4.0" + lodash.isarguments "^3.1.0" p-map "^2.1.0" redis-commands "1.7.0" redis-errors "^1.2.0" @@ -3862,6 +3906,11 @@ is-typedarray@^1.0.0: resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo= +is-unicode-supported@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz#3f26c76a809593b52bfa2ecb5710ed2779b522a7" + integrity sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw== + is-weakref@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/is-weakref/-/is-weakref-1.0.1.tgz#842dba4ec17fa9ac9850df2d6efbc1737274f2a2" @@ -3925,13 +3974,6 @@ js-stringify@^1.0.2: resolved "https://registry.yarnpkg.com/js-stringify/-/js-stringify-1.0.2.tgz#1736fddfd9724f28a3682adc6230ae7e4e9679db" integrity sha1-Fzb939lyTyijaCrcYjCufk6Weds= -js-yaml@4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.0.0.tgz#f426bc0ff4b4051926cd588c71113183409a121f" - integrity sha512-pqon0s+4ScYUvX30wxQi3PogGFAlUyH0awepWvwkj4jD4v+ova3RiYw8bmA6x2rDrEaj8i/oWKoRxpVNW+Re8Q== - dependencies: - argparse "^2.0.1" - js-yaml@4.1.0, js-yaml@^4.0.0, js-yaml@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" @@ -4273,11 +4315,6 @@ ky@^0.25.1: resolved "https://registry.yarnpkg.com/ky/-/ky-0.25.1.tgz#0df0bd872a9cc57e31acd5dbc1443547c881bfbc" integrity sha512-PjpCEWlIU7VpiMVrTwssahkYXX1by6NCT0fhTUX34F3DTinARlgMpriuroolugFPcMgpPWrOW4mTb984Qm1RXA== -langmap@0.0.16: - version "0.0.16" - resolved "https://registry.yarnpkg.com/langmap/-/langmap-0.0.16.tgz#2fe3e98a531fec0fec546624ebe168c2855bab56" - integrity sha512-AtYvBK7BsDvWwnSfmO7CfgeUy7GUT1wK3QX8eKH/Ey/eXodqoHuAtvdQ82hmWD9QVFVKnuiNjym9fGY4qSJeLA== - lazystream@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/lazystream/-/lazystream-1.0.1.tgz#494c831062f1f9408251ec44db1cba29242a2638" @@ -4372,6 +4409,11 @@ lodash.foreach@^4.3.0: resolved "https://registry.yarnpkg.com/lodash.foreach/-/lodash.foreach-4.5.0.tgz#1a6a35eace401280c7f06dddec35165ab27e3e53" integrity sha1-Gmo16s5AEoDH8G3d7DUWWrJ+PlM= +lodash.isarguments@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz#2f573d85c6a24289ff00663b491c1d338ff3458a" + integrity sha1-L1c9hcaiQon/AGY7SRwdM4/zRYo= + lodash.isequal@^4.5.0: version "4.5.0" resolved "https://registry.yarnpkg.com/lodash.isequal/-/lodash.isequal-4.5.0.tgz#415c4478f2bcc30120c22ce10ed3226f7d3e18e0" @@ -4432,18 +4474,24 @@ lodash@^4.17.14, lodash@^4.17.19, lodash@^4.17.21: resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== -log-symbols@4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-4.0.0.tgz#69b3cc46d20f448eccdb75ea1fa733d9e821c920" - integrity sha512-FN8JBzLx6CzeMrB0tg6pqlGU1wCrXW+ZXGH481kfsBqer0hToTIiHdjH4Mq8xJUbvATujKCvaREGWpGUionraA== +log-symbols@4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-4.1.0.tgz#3fbdbb95b4683ac9fc785111e792e558d4abd503" + integrity sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg== dependencies: - chalk "^4.0.0" + chalk "^4.1.0" + is-unicode-supported "^0.1.0" lowercase-keys@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-2.0.0.tgz#2603e78b7b4b0006cbca2fbcc8a3202558ac9479" integrity sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA== +lowercase-keys@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-3.0.0.tgz#c5e7d442e37ead247ae9db117a9d0a467c89d4f2" + integrity sha512-ozCC6gdQ+glXOQsveKD0YsDy8DSQFjDTz4zyzEHNV5+JP5D62LmfDZ6o1cycFx9ouG940M5dE8C8CTewdj2YWQ== + lru-cache@^4.1.5: version "4.1.5" resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.5.tgz#8bbe50ea85bed59bc9e33dcab8235ee9bcf443cd" @@ -4682,33 +4730,32 @@ 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.4.0: - version "8.4.0" - resolved "https://registry.yarnpkg.com/mocha/-/mocha-8.4.0.tgz#677be88bf15980a3cae03a73e10a0fc3997f0cff" - integrity sha512-hJaO0mwDXmZS4ghXsvPVriOhsxQ7ofcpQdm8dE+jISUOKopitvnXFQmpRR7jd2K6VBG6E26gU3IAbXXGIbu4sQ== +mocha@9.2.1: + version "9.2.1" + resolved "https://registry.yarnpkg.com/mocha/-/mocha-9.2.1.tgz#a1abb675aa9a8490798503af57e8782a78f1338e" + integrity sha512-T7uscqjJVS46Pq1XDXyo9Uvey9gd3huT/DD9cYBb4K2Xc/vbKRPUWK067bxDQRK0yIz6Jxk73IrnimvASzBNAQ== dependencies: "@ungap/promise-all-settled" "1.1.2" ansi-colors "4.1.1" browser-stdout "1.3.1" - chokidar "3.5.1" - debug "4.3.1" + chokidar "3.5.3" + debug "4.3.3" diff "5.0.0" escape-string-regexp "4.0.0" find-up "5.0.0" - glob "7.1.6" + glob "7.2.0" growl "1.10.5" he "1.2.0" - js-yaml "4.0.0" - log-symbols "4.0.0" + js-yaml "4.1.0" + log-symbols "4.1.0" minimatch "3.0.4" ms "2.1.3" - nanoid "3.1.20" - serialize-javascript "5.0.1" + nanoid "3.2.0" + serialize-javascript "6.0.0" strip-json-comments "3.1.1" supports-color "8.1.1" which "2.0.2" - wide-align "1.1.3" - workerpool "6.1.0" + workerpool "6.2.0" yargs "16.2.0" yargs-parser "20.2.4" yargs-unparser "2.0.0" @@ -4793,10 +4840,10 @@ nano-time@1.0.0: dependencies: big-integer "^1.6.16" -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== +nanoid@3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.2.0.tgz#62667522da6673971cca916a6d3eff3f415ff80c" + integrity sha512-fmsZYa9lpn69Ad5eDn7FMcnnSR+8R34W9qJEijxYhTbfOWzr22n1QxCMzXLK+ODyW2973V3Fux959iQoUxzUIA== nanoid@^3.1.30: version "3.1.30" @@ -4868,13 +4915,6 @@ node-fetch@*: fetch-blob "^3.1.4" formdata-polyfill "^4.0.10" -node-fetch@2.6.7, node-fetch@^2.6.1: - version "2.6.7" - resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad" - integrity sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ== - dependencies: - whatwg-url "^5.0.0" - node-fetch@3.0.0-beta.9: version "3.0.0-beta.9" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-3.0.0-beta.9.tgz#0a7554cfb824380dd6812864389923c783c80d9b" @@ -4883,6 +4923,22 @@ node-fetch@3.0.0-beta.9: data-uri-to-buffer "^3.0.1" fetch-blob "^2.1.1" +node-fetch@3.2.2: + version "3.2.2" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-3.2.2.tgz#16d33fbe32ca7c6ca1ca8ba5dfea1dd885c59f04" + integrity sha512-Cwhq1JFIoon15wcIkFzubVNFE5GvXGV82pKf4knXXjvGmn7RJKcypeuqcVNZMGDZsAFWyIRya/anwAJr7TWJ7w== + dependencies: + data-uri-to-buffer "^4.0.0" + fetch-blob "^3.1.4" + formdata-polyfill "^4.0.10" + +node-fetch@^2.6.1: + version "2.6.7" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad" + integrity sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ== + dependencies: + whatwg-url "^5.0.0" + node-gyp-build@^4.2.3: version "4.3.0" resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.3.0.tgz#9f256b03e5826150be39c764bf51e993946d71a3" @@ -4951,10 +5007,15 @@ normalize-url@^4.1.0: resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-4.5.1.tgz#0dd90cf1288ee1d1313b87081c9a5932ee48518a" integrity sha512-9UZCFRHQdNrfTpGg8+1INIg93B6zE0aXMVFkw1WFwvO4SlZywU6aLg5Of0Ap/PgcbSw4LNxvMWXMeugwMCX0AA== -npm-run-path@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-5.0.1.tgz#748dd68ed7de377bb1f7132c7dafe657be5ab400" - integrity sha512-ybBJQUSyFwEEhqO2lXmyKOl9ucHtyZBWVM0h0FiMfT/+WKxCUZFa95qAR2X3w/w6oigN3B0b2UNHZbD+kdfD5w== +normalize-url@^6.0.1: + version "6.1.0" + resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-6.1.0.tgz#40d0885b535deffe3f3147bec877d05fe4c5668a" + integrity sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A== + +npm-run-path@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-5.1.0.tgz#bc62f7f3f6952d9894bd08944ba011a6ee7b7e00" + integrity sha512-sJOdmRGrY2sjNTRMbSvluQqg+8X7ZK61yvzBEIDhz4f8z1TZFYABsqjjCBd/0PUNE9M6QDgHJXQkGUEm7Q+l9Q== dependencies: path-key "^4.0.0" @@ -5122,6 +5183,11 @@ p-cancelable@^2.0.0: resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-2.0.0.tgz#4a3740f5bdaf5ed5d7c3e34882c6fb5d6b266a6e" integrity sha512-wvPXDmbMmu2ksjkB4Z3nZWTSkJEb9lqVdMaCKpZUGJG9TMiNp9XcbG3fn9fPKjem04fJMJnXoyFPk2FmgiaiNg== +p-cancelable@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-3.0.0.tgz#63826694b54d61ca1c20ebcb6d3ecf5e14cd8050" + integrity sha512-mlVgR3PGuzlo0MmTdk4cXqXWlwQDLnONTAg6sm62XkMJEiRxN3GL3SffkYvqwonbkJBcrI7Uvv5Zh9yjvn2iUw== + p-finally@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae" @@ -5295,10 +5361,10 @@ path-type@^4.0.0: resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== -peek-readable@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/peek-readable/-/peek-readable-4.0.1.tgz#9a045f291db254111c3412c1ce4fec27ddd4d202" - integrity sha512-7qmhptnR0WMSpxT5rMHG9bW/mYSR1uqaPFj2MHvT+y/aOUu6msJijpKt5SkTDKySwg65OWG2JwTMBlgcbwMHrQ== +peek-readable@^5.0.0-alpha.5: + version "5.0.0-alpha.5" + resolved "https://registry.yarnpkg.com/peek-readable/-/peek-readable-5.0.0-alpha.5.tgz#ace5dfedf7bc33f17c9b5170b9d54f69a4fba79b" + integrity sha512-pJohF/tDwV3ntnT5+EkUo4E700q/j/OCDuPxtM+5/kFGjyOai/sK4/We4Cy1MB2OiTQliWU5DxPvYIKQAdPqAA== pg-connection-string@^2.5.0: version "2.5.0" @@ -5310,10 +5376,10 @@ pg-int8@1.0.1: resolved "https://registry.yarnpkg.com/pg-int8/-/pg-int8-1.0.1.tgz#943bd463bf5b71b4170115f80f8efc9a0c0eb78c" integrity sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw== -pg-pool@^3.4.1: - version "3.4.1" - resolved "https://registry.yarnpkg.com/pg-pool/-/pg-pool-3.4.1.tgz#0e71ce2c67b442a5e862a9c182172c37eda71e9c" - integrity sha512-TVHxR/gf3MeJRvchgNHxsYsTCHQ+4wm3VIHSS19z8NC0+gioEhq1okDY1sm/TYbfoP6JLFx01s0ShvZ3puP/iQ== +pg-pool@^3.5.1: + version "3.5.1" + resolved "https://registry.yarnpkg.com/pg-pool/-/pg-pool-3.5.1.tgz#f499ce76f9bf5097488b3b83b19861f28e4ed905" + integrity sha512-6iCR0wVrro6OOHFsyavV+i6KYL4lVNyYAB9RD18w66xSzN+d8b66HiwuP30Gp1SH5O9T82fckkzsRjlrhD0ioQ== pg-protocol@^1.5.0: version "1.5.0" @@ -5331,15 +5397,15 @@ pg-types@^2.1.0: postgres-date "~1.0.4" postgres-interval "^1.1.0" -pg@8.7.1: - version "8.7.1" - resolved "https://registry.yarnpkg.com/pg/-/pg-8.7.1.tgz#9ea9d1ec225980c36f94e181d009ab9f4ce4c471" - integrity sha512-7bdYcv7V6U3KAtWjpQJJBww0UEsWuh4yQ/EjNf2HeO/NnvKjpvhEIe/A/TleP6wtmSKnUnghs5A9jUoK6iDdkA== +pg@8.7.3: + version "8.7.3" + resolved "https://registry.yarnpkg.com/pg/-/pg-8.7.3.tgz#8a5bdd664ca4fda4db7997ec634c6e5455b27c44" + integrity sha512-HPmH4GH4H3AOprDJOazoIcpI49XFsHCe8xlrjHkWiapdbHK+HLtbm/GQzXYAZwmPju/kzKhjaSfMACG+8cgJcw== dependencies: buffer-writer "2.0.0" packet-reader "1.0.0" pg-connection-string "^2.5.0" - pg-pool "^3.4.1" + pg-pool "^3.5.1" pg-protocol "^1.5.0" pg-types "^2.1.0" pgpass "1.x" @@ -5463,11 +5529,6 @@ printj@~1.1.0: resolved "https://registry.yarnpkg.com/printj/-/printj-1.1.2.tgz#d90deb2975a8b9f600fb3a1c94e3f4c53c78a222" integrity sha512-zA2SmoLaxZyArQTOPj5LXecR+RagfPSU5Kw1qP+jkWeNlrq+eJZyY2oS68SU1Z/7/myXM4lo9716laOFAVStCQ== -printj@~1.3.1: - version "1.3.1" - resolved "https://registry.yarnpkg.com/printj/-/printj-1.3.1.tgz#9af6b1d55647a1587ac44f4c1654a4b95b8e12cb" - integrity sha512-GA3TdL8szPK4AQ2YnOe/b+Y1jUFwmmGMMK/qbY7VcE3Z7FU8JstbKiKRzO6CIiAKPhTO8m01NoQ0V5f3jc4OGg== - private-ip@2.3.3: version "2.3.3" resolved "https://registry.yarnpkg.com/private-ip/-/private-ip-2.3.3.tgz#1e80ff8443e5ac78f555631aec3ea6ff027fa6aa" @@ -5743,10 +5804,10 @@ rdf-canonize@^3.0.0: dependencies: setimmediate "^1.0.5" -re2@1.17.3: - version "1.17.3" - resolved "https://registry.yarnpkg.com/re2/-/re2-1.17.3.tgz#8cceb48f52c45b860b1f67cee8a44726f7d05e9a" - integrity sha512-Dp5iWVR8W3C7Nm9DziMY4BleMPRb/pe6kvfbzLv80dVYaXRc9jRnwwNqU0oE/taRm0qYR1+Qrtzk9rPjS9ecaQ== +re2@1.17.4: + version "1.17.4" + resolved "https://registry.yarnpkg.com/re2/-/re2-1.17.4.tgz#7bf29290bdde963014e77bd2c2e799a6d788386e" + integrity sha512-xyZ4h5PqE8I9tAxTh3G0UttcK5ufrcUxReFjGzfX61vtanNbS1XZHjnwRSyPcLgChI4KLxVgOT/ioZXnUAdoTA== dependencies: install-artifact-from-github "^1.3.0" nan "^2.15.0" @@ -5784,12 +5845,11 @@ readable-stream@^3.1.1, readable-stream@^3.4.0, readable-stream@^3.6.0: string_decoder "^1.1.1" util-deprecate "^1.0.1" -readable-web-to-node-stream@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/readable-web-to-node-stream/-/readable-web-to-node-stream-3.0.0.tgz#4ca5408e70471069119d691934141a52de413955" - integrity sha512-HNmLb3n0SteGAs8HQlErYPGeO+y7cvL/mVUKtXeUkl0iCZ/2GIgKGrCFHyS7UXFnO8uc9U+0y3pYIzAPsjFfvA== +readable-web-to-node-stream@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/readable-web-to-node-stream/-/readable-web-to-node-stream-3.0.2.tgz#5d52bb5df7b54861fd48d015e93a2cb87b3ee0bb" + integrity sha512-ePeK6cc1EcKLEhJFt/AebMCLL+GgSKhuygrZ/GLaKZYEecIgIECf4UaUuaByiGtzckwR4ain9VzUh95T1exYGw== dependencies: - "@types/readable-stream" "^2.3.9" readable-stream "^3.6.0" readdir-glob@^1.0.0: @@ -5901,6 +5961,11 @@ resolve-alpn@^1.0.0: resolved "https://registry.yarnpkg.com/resolve-alpn/-/resolve-alpn-1.0.0.tgz#745ad60b3d6aff4b4a48e01b8c0bdc70959e0e8c" integrity sha512-rTuiIEqFmGxne4IovivKSDzld2lWW9QCjqv80SYjPgf+gS35eaCAjaP54CCwGAwBtnCsvNLYtqxe1Nw+i6JEmA== +resolve-alpn@^1.2.0: + version "1.2.1" + resolved "https://registry.yarnpkg.com/resolve-alpn/-/resolve-alpn-1.2.1.tgz#b7adbdac3546aaaec20b45e7d8265927072726f9" + integrity sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g== + resolve-dir@^1.0.0, resolve-dir@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/resolve-dir/-/resolve-dir-1.0.1.tgz#79a40644c362be82f26effe739c9bb5382046f43" @@ -5979,16 +6044,16 @@ s-age@1.1.2: resolved "https://registry.yarnpkg.com/s-age/-/s-age-1.1.2.tgz#c0cf15233ccc93f41de92ea42c36d957977d1ea2" integrity sha512-aSN2TlF39WLoZA/6cgYSJZhKt63kJ4EaadejPWjWY9/h4rksIqvfWY3gfd+3uAegSM1IXsA9aWeEhJtkxkFQtA== -safe-buffer@*, safe-buffer@5.2.1: - version "5.2.1" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" - integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== - safe-buffer@5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: version "5.1.2" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== +safe-buffer@5.2.1: + version "5.2.1" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" + integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== + safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@~5.2.0: version "5.2.0" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.0.tgz#b74daec49b1148f88c64b68d49b1e815c1f2f519" @@ -5999,10 +6064,10 @@ safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@~5.2.0: resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== -sanitize-html@2.6.1: - version "2.6.1" - resolved "https://registry.yarnpkg.com/sanitize-html/-/sanitize-html-2.6.1.tgz#5d37c08e189c61c0631560a889b10d9d155d000e" - integrity sha512-DzjSz3H5qDntD7s1TcWCSoRPmNR8UmA+y+xZQOvWgjATe2Br9ZW73+vD3Pj6Snrg0RuEuJdXgrKvnYuiuixRkA== +sanitize-html@2.7.0: + version "2.7.0" + resolved "https://registry.yarnpkg.com/sanitize-html/-/sanitize-html-2.7.0.tgz#e106205b468aca932e2f9baf241f24660d34e279" + integrity sha512-jfQelabOn5voO7FAfnQF7v+jsA6z9zC/O4ec0z3E35XPEtHYJT/OdUziVWlKW4irCr2kXaQAyXTXDHWAibg1tA== dependencies: deepmerge "^4.2.2" escape-string-regexp "^4.0.0" @@ -6071,10 +6136,10 @@ semver@^7.3.5: dependencies: lru-cache "^6.0.0" -serialize-javascript@5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-5.0.1.tgz#7886ec848049a462467a97d3d918ebb2aaf934f4" - integrity sha512-SaaNal9imEO737H2c05Og0/8LUXG7EnsZyMa8MzkmuHoELfT6txuj0cMqRj6zfPKnmQ1yasR4PCJc8x+M4JSPA== +serialize-javascript@6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-6.0.0.tgz#efae5d88f45d7924141da8b5c3a7a7e663fefeb8" + integrity sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag== dependencies: randombytes "^2.1.0" @@ -6106,13 +6171,13 @@ sha.js@^2.4.11: inherits "^2.0.1" safe-buffer "^5.0.1" -sharp@0.30.0: - version "0.30.0" - resolved "https://registry.yarnpkg.com/sharp/-/sharp-0.30.0.tgz#b2dd62d5f14088b11c72212354f31dff6511b070" - integrity sha512-L3m/l6yQFr3oGBUzcSAlN/R9yGFPYqM9FpMUe6Z4nHg4sWtP3hW1rcz+aaHklhD4wX5Jqh5PY9z+A1d4Qt3Hfg== +sharp@0.30.2: + version "0.30.2" + resolved "https://registry.yarnpkg.com/sharp/-/sharp-0.30.2.tgz#95b309b2740424702dc19b62a62595dd34a458b1" + integrity sha512-mrMeKI5ECTdYhslPlA2TbBtU3nZXMEBcQwI6qYXjPlu1LpW4HBZLFm6xshMI1HpIdEEJ3UcYp5AKifLT/fEHZQ== dependencies: - color "^4.2.0" - detect-libc "^2.0.0" + color "^4.2.1" + detect-libc "^2.0.1" node-addon-api "^4.3.0" prebuild-install "^7.0.1" semver "^7.3.5" @@ -6151,10 +6216,10 @@ signal-exit@^3.0.0: resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.3.tgz#a1410c2edd8f077b08b4e253c8eacfcaf057461c" integrity sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA== -signal-exit@^3.0.5: - version "3.0.6" - resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.6.tgz#24e630c4b0f03fea446a2bd299e62b4a6ca8d0af" - integrity sha512-sDl4qMFpijcGw22U5w63KmD3cZJfBuFlVNbVMKje2keoKML7X2UzWbc4XrmEbDwg0NXJc3yv4/ox7b+JWb57kQ== +signal-exit@^3.0.7: + version "3.0.7" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" + integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== simple-concat@^1.0.0: version "1.0.1" @@ -6407,13 +6472,13 @@ strip-json-comments@~2.0.1: resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo= -strtok3@^6.2.4: - version "6.2.4" - resolved "https://registry.yarnpkg.com/strtok3/-/strtok3-6.2.4.tgz#302aea64c0fa25d12a0385069ba66253fdc38a81" - integrity sha512-GO8IcFF9GmFDvqduIspUBwCzCbqzegyVKIsSymcMgiZKeCfrN9SowtUoi8+b59WZMAjIzVZic/Ft97+pynR3Iw== +strtok3@^7.0.0-alpha.7: + version "7.0.0-alpha.8" + resolved "https://registry.yarnpkg.com/strtok3/-/strtok3-7.0.0-alpha.8.tgz#23a7870974e0494b58b14af6dd1c2c67cf13314d" + integrity sha512-u+k19v+rTxBjGYxncRQjGvZYwYvEd0uP3D+uHKe/s4WB1eXS5ZwpZsTlBu5xSS4zEd89mTXECXg6WW3FSeV8cA== dependencies: "@tokenizer/token" "^0.3.0" - peek-readable "^4.0.1" + peek-readable "^5.0.0-alpha.5" style-loader@3.3.1: version "3.3.1" @@ -6469,10 +6534,10 @@ syslog-pro@1.0.0: dependencies: moment "^2.22.2" -systeminformation@5.11.0: - version "5.11.0" - resolved "https://registry.yarnpkg.com/systeminformation/-/systeminformation-5.11.0.tgz#2060779e1e7c7372192dbcd850c65cfd85f4ea71" - integrity sha512-mI/5nFK7NUe9Qbmy65WoB5TlCWKAhP4kG0w6uR2mZM8Mpdi8b45b3hTIK3W5+kQYZnYFWeS9/O5nn5rdcSvqfA== +systeminformation@5.11.6: + version "5.11.6" + resolved "https://registry.yarnpkg.com/systeminformation/-/systeminformation-5.11.6.tgz#8624cbb2e95e6fa98a4ebb0d10759427c0e88144" + integrity sha512-7KBXgdnIDxABQ93w+GrPSrK/pup73+fM09VGka4A/+FhgzdlRY0JNGGDFmV8BHnFuzP9zwlI3n64yDbp7emasQ== tapable@^2.2.0: version "2.2.0" @@ -6596,10 +6661,10 @@ token-stream@1.0.0: resolved "https://registry.yarnpkg.com/token-stream/-/token-stream-1.0.0.tgz#cc200eab2613f4166d27ff9afc7ca56d49df6eb4" integrity sha1-zCAOqyYT9BZtJ/+a/HylbUnfbrQ= -token-types@^4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/token-types/-/token-types-4.1.1.tgz#ef9e8c8e2e0ded9f1b3f8dbaa46a3228b113ba1a" - integrity sha512-hD+QyuUAyI2spzsI0B7gf/jJ2ggR4RjkAo37j3StuePhApJUwcWDjnHDOFdIWYSwNR28H14hpwm4EI+V1Ted1w== +token-types@^5.0.0-alpha.2: + version "5.0.0-alpha.2" + resolved "https://registry.yarnpkg.com/token-types/-/token-types-5.0.0-alpha.2.tgz#e43d63b2a8223a593d1c782a5149bec18f1abf97" + integrity sha512-EsG9UxAW4M6VATrEEjhPFTKEUi1OiJqTUMIZOGBN49fGxYjZB36k0p7to3HZSmWRoHm1QfZgrg3e02fpqAt5fQ== dependencies: "@tokenizer/token" "^0.3.0" ieee754 "^1.2.1" @@ -6635,20 +6700,20 @@ trace-redirect@1.0.6: resolved "https://registry.yarnpkg.com/traverse/-/traverse-0.3.9.tgz#717b8f220cc0bb7b44e40514c22b2e8bbc70d8b9" integrity sha1-cXuPIgzAu3tE5AUUwisui7xw2Lk= -ts-loader@9.2.6: - version "9.2.6" - resolved "https://registry.yarnpkg.com/ts-loader/-/ts-loader-9.2.6.tgz#9937c4dd0a1e3dbbb5e433f8102a6601c6615d74" - integrity sha512-QMTC4UFzHmu9wU2VHZEmWWE9cUajjfcdcws+Gh7FhiO+Dy0RnR1bNz0YCHqhI0yRowCE9arVnNxYHqELOy9Hjw== +ts-loader@9.2.7: + version "9.2.7" + resolved "https://registry.yarnpkg.com/ts-loader/-/ts-loader-9.2.7.tgz#948654099ca96992b62ec47bd9cee5632006e101" + integrity sha512-Fxh44mKli9QezgbdCXkEJWxnedQ0ead7DXTH+lfXEPedu+Y9EtMJ2aQ9G3Dj1j7Q612E8931rww8NDZha4Tibg== dependencies: chalk "^4.1.0" enhanced-resolve "^5.0.0" micromatch "^4.0.0" semver "^7.3.4" -ts-node@10.4.0: - version "10.4.0" - resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-10.4.0.tgz#680f88945885f4e6cf450e7f0d6223dd404895f7" - integrity sha512-g0FlPvvCXSIO1JDF6S232P5jPYqBkRL9qly81ZgAOSU7rwI0stphCgd2kLiCrU9DjQCrJMWEqcNSjQL02s6d8A== +ts-node@10.7.0: + version "10.7.0" + resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-10.7.0.tgz#35d503d0fab3e2baa672a0e94f4b40653c2463f5" + integrity sha512-TbIGS4xgJoX2i3do417KSaep1uRAW/Lu+WAL2doDHC0D6ummjirVOXU5/7aiZotbQ5p1Zp9tP7U6cYhA0O7M8A== dependencies: "@cspotcode/source-map-support" "0.7.0" "@tsconfig/node10" "^1.0.7" @@ -6661,6 +6726,7 @@ ts-node@10.4.0: create-require "^1.1.0" diff "^4.0.1" make-error "^1.1.1" + v8-compile-cache-lib "^3.0.0" yn "3.1.1" tsc-alias@1.4.1: @@ -6675,7 +6741,17 @@ tsc-alias@1.4.1: mylas "^2.1.4" normalize-path "^3.0.0" -tsconfig-paths@3.12.0, tsconfig-paths@^3.12.0: +tsconfig-paths@3.13.0: + version "3.13.0" + resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-3.13.0.tgz#f3e9b8f6876698581d94470c03c95b3a48c0e3d7" + integrity sha512-nWuffZppoaYK0vQ1SQmkSsQzJoHA4s6uzdb2waRpD806x9yfq153AdVsWz4je2qZcW+pENrMQXbGQ3sMCkXuhw== + dependencies: + "@types/json5" "^0.0.29" + json5 "^1.0.1" + minimist "^1.2.0" + strip-bom "^3.0.0" + +tsconfig-paths@^3.12.0: version "3.12.0" resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-3.12.0.tgz#19769aca6ee8f6a1a341e38c8fa45dd9fb18899b" integrity sha512-e5adrnOYT6zqVnWqZu7i/BQ3BnhzvGbjEjejFXO20lKIKpwTaupkCPgEfv4GZK1IBciJUEhYs3J3p75FdaTFVg== @@ -6778,10 +6854,10 @@ typedarray@^0.0.6: resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c= -typeorm@0.2.41: - version "0.2.41" - resolved "https://registry.yarnpkg.com/typeorm/-/typeorm-0.2.41.tgz#88758101ac158dc0a0a903d70eaacea2974281cc" - integrity sha512-/d8CLJJxKPgsnrZWiMyPI0rz2MFZnBQrnQ5XP3Vu3mswv2WPexb58QM6BEtmRmlTMYN5KFWUz8SKluze+wS9xw== +typeorm@0.2.45: + version "0.2.45" + resolved "https://registry.yarnpkg.com/typeorm/-/typeorm-0.2.45.tgz#e5bbb3af822dc4646bad96cfa48cd22fa4687cea" + integrity sha512-c0rCO8VMJ3ER7JQ73xfk0zDnVv0WDjpsP6Q1m6CVKul7DB9iVdWLRjPzc8v2eaeBuomsbZ2+gTaYr8k1gm3bYA== dependencies: "@sqltools/formatter" "^1.2.2" app-root-path "^3.0.0" @@ -6796,14 +6872,15 @@ typeorm@0.2.41: reflect-metadata "^0.1.13" sha.js "^2.4.11" tslib "^2.1.0" + uuid "^8.3.2" xml2js "^0.4.23" yargs "^17.0.1" zen-observable-ts "^1.0.0" -typescript@4.5.5: - version "4.5.5" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.5.5.tgz#d8c953832d28924a9e3d37c73d729c846c5896f3" - integrity sha512-TCTIul70LyWe6IJWT8QSYeA54WQe8EjQFU4wY52Fasj5UKx88LNYKCgBEHcOMOrFF1rKGbD8v/xcNWVUq9SymA== +typescript@4.6.2: + version "4.6.2" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.6.2.tgz#fe12d2727b708f4eef40f51598b3398baa9611d4" + integrity sha512-HM/hFigTBHZhLXshn9sN37H085+hQGeJHJ/X7LpBWLID/fbc2acUMfU+lGD98X81sKP+pFa9f0DZmCwB9GnbAg== ulid@2.3.0: version "2.3.0" @@ -6910,11 +6987,16 @@ uuid@7.0.3: resolved "https://registry.yarnpkg.com/uuid/-/uuid-7.0.3.tgz#c5c9f2c8cf25dc0a372c4df1441c41f5bd0c680b" integrity sha512-DPSke0pXhTZgoF/d+WSt2QaKMCFSfx7QegxEWT+JOuHF5aWrKEn0G+ztjuJg/gG8/ItK+rbPCD/yNv8yyih6Cg== -uuid@8.3.2, uuid@^8.3.0: +uuid@8.3.2, uuid@^8.3.0, uuid@^8.3.2: version "8.3.2" resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2" integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg== +v8-compile-cache-lib@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.0.tgz#0582bcb1c74f3a2ee46487ceecf372e46bce53e8" + integrity sha512-mpSYqfsFvASnSn5qMiwrr4VKfumbPyONLCOPmsR3A6pTY/r0+tSaVbgPWSAIuzbk3lCTa+FForeTiO+wBQGkjA== + v8-compile-cache@^2.0.3: version "2.2.0" resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.2.0.tgz#9471efa3ef9128d2f7c6a7ca39c4dd6b5055b132" @@ -7050,7 +7132,7 @@ which@^1.1.1, which@^1.2.14: dependencies: isexe "^2.0.0" -wide-align@1.1.3, wide-align@^1.1.0: +wide-align@^1.1.0: version "1.1.3" resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.3.tgz#ae074e6bdc0c14a431e804e624549c633b000457" integrity sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA== @@ -7079,10 +7161,10 @@ word-wrap@^1.2.3, word-wrap@~1.2.3: resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c" integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ== -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== +workerpool@6.2.0: + version "6.2.0" + resolved "https://registry.yarnpkg.com/workerpool/-/workerpool-6.2.0.tgz#827d93c9ba23ee2019c3ffaff5c27fccea289e8b" + integrity sha512-Rsk5qQHJ9eowMH28Jwhe8HEbmdYDX4lwoMWshiCXugjtHqMD9ZbiqSDLxcsfdqsETPzVUtX5s1Z5kStiIM6l4A== wrap-ansi@^6.2.0: version "6.2.0" @@ -7107,7 +7189,12 @@ wrappy@1: resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= -ws@8.4.2, ws@^8.2.3: +ws@8.5.0: + version "8.5.0" + resolved "https://registry.yarnpkg.com/ws/-/ws-8.5.0.tgz#bfb4be96600757fe5382de12c670dab984a1ed4f" + integrity sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg== + +ws@^8.2.3: version "8.4.2" resolved "https://registry.yarnpkg.com/ws/-/ws-8.4.2.tgz#18e749868d8439f2268368829042894b6907aa0b" integrity sha512-Kbk4Nxyq7/ZWqr/tarI9yIt/+iNNFOjBXEWgTb4ydaNHBNGgvf2QHbS9fdfsndfjFlFwEd4Al+mw83YkaD10ZA== diff --git a/packages/client/.eslintrc.js b/packages/client/.eslintrc.js index acbb7c0c6..a6e23e517 100644 --- a/packages/client/.eslintrc.js +++ b/packages/client/.eslintrc.js @@ -19,6 +19,7 @@ module.exports = { // e の禁止理由: error や event など、複数のキーワードの頭文字であり分かりにくいため "id-denylist": ["error", "window", "data", "e"], 'eqeqeq': ['error', 'always', { 'null': 'ignore' }], + "no-shadow": ["warn"], "vue/attributes-order": ["error", { "alphabetical": false }], diff --git a/packages/client/package.json b/packages/client/package.json index cf4214e72..7a1ae47c0 100644 --- a/packages/client/package.json +++ b/packages/client/package.json @@ -11,7 +11,7 @@ }, "dependencies": { "@discordapp/twemoji": "13.1.0", - "@fortawesome/fontawesome-free": "6.0.0-beta3", + "@fortawesome/fontawesome-free": "6.0.0", "@syuilo/aiscript": "0.11.1", "@types/escape-regexp": "0.0.1", "@types/glob": "7.2.0", @@ -19,44 +19,41 @@ "@types/gulp-rename": "2.0.1", "@types/is-url": "1.2.30", "@types/katex": "0.11.1", - "@types/matter-js": "0.17.6", - "@types/mocha": "8.2.3", + "@types/matter-js": "0.17.7", + "@types/mocha": "9.1.0", "@types/oauth": "0.9.1", "@types/parse5": "6.0.3", "@types/punycode": "2.1.0", "@types/qrcode": "1.4.2", "@types/random-seed": "0.3.3", - "@types/seedrandom": "2.4.28", + "@types/seedrandom": "3.0.2", "@types/throttle-debounce": "2.1.0", "@types/tinycolor2": "1.4.3", - "@types/tmp": "0.2.3", "@types/uuid": "8.3.4", - "@types/web-push": "3.3.2", "@types/webpack": "5.28.0", "@types/webpack-stream": "3.2.12", - "@types/websocket": "1.0.4", - "@types/ws": "8.2.2", - "@typescript-eslint/parser": "5.10.0", - "@vue/compiler-sfc": "3.2.29", + "@types/websocket": "1.0.5", + "@types/ws": "8.5.2", + "@typescript-eslint/parser": "5.14.0", + "@vue/compiler-sfc": "3.2.31", "abort-controller": "3.0.0", "autobind-decorator": "2.4.0", "autosize": "5.0.1", "autwh": "0.1.0", - "blurhash": "1.1.4", - "broadcast-channel": "4.9.0", - "chart.js": "3.7.0", + "blurhash": "1.1.5", + "broadcast-channel": "4.10.0", + "chart.js": "3.7.1", "chartjs-adapter-date-fns": "2.0.0", "chartjs-plugin-gradient": "0.2.1", "chartjs-plugin-zoom": "1.2.0", "compare-versions": "4.1.3", "content-disposition": "0.5.4", - "crc-32": "1.2.0", - "css-loader": "6.5.1", - "cssnano": "5.0.15", + "css-loader": "6.7.1", + "cssnano": "5.1.1", "date-fns": "2.28.0", "escape-regexp": "0.0.1", - "eslint": "8.7.0", - "eslint-plugin-vue": "8.3.0", + "eslint": "8.10.0", + "eslint-plugin-vue": "8.5.0", "eventemitter3": "4.0.7", "feed": "4.2.2", "glob": "7.2.0", @@ -66,19 +63,18 @@ "json5": "2.2.0", "json5-loader": "4.0.1", "katex": "0.15.2", - "langmap": "0.0.16", "matter-js": "0.18.0", "mfm-js": "0.21.0", "misskey-js": "0.0.14", - "mocha": "8.4.0", + "mocha": "9.2.1", "ms": "2.1.3", "nested-property": "4.0.0", "parse5": "6.0.1", "photoswipe": "git+https://github.com/dimsemenov/photoswipe#v5-beta", "portscanner": "2.2.0", - "postcss": "8.4.5", + "postcss": "8.4.8", "postcss-loader": "6.2.1", - "prismjs": "1.26.0", + "prismjs": "1.27.0", "private-ip": "2.3.3", "promise-limit": "2.7.0", "pug": "3.0.2", @@ -89,46 +85,41 @@ "reflect-metadata": "0.1.13", "rndstr": "1.0.0", "s-age": "1.1.2", - "sass": "1.49.0", - "sass-loader": "12.4.0", + "sass": "1.49.9", + "sass-loader": "12.6.0", "seedrandom": "3.0.5", "strict-event-emitter-types": "2.0.0", "stringz": "2.1.0", "style-loader": "3.3.1", "syuilo-password-strength": "0.0.1", "textarea-caret": "3.1.0", - "three": "0.136.0", + "three": "0.138.3", "throttle-debounce": "3.0.1", "tinycolor2": "1.4.2", - "tmp": "0.2.1", - "ts-loader": "9.2.6", - "ts-node": "10.4.0", + "ts-loader": "9.2.7", "tsc-alias": "1.5.0", - "tsconfig-paths": "3.12.0", + "tsconfig-paths": "3.13.0", "twemoji-parser": "13.1.0", - "typescript": "4.5.5", + "typescript": "4.6.2", "uuid": "8.3.2", "v-debounce": "0.1.2", "vanilla-tilt": "1.7.2", - "vue": "3.2.29", + "vue": "3.2.31", "vue-loader": "17.0.0", "vue-prism-editor": "2.0.0-alpha.2", - "vue-router": "4.0.5", + "vue-router": "4.0.13", "vue-style-loader": "4.1.3", "vue-svg-loader": "0.17.0-beta.2", "vuedraggable": "4.0.1", - "web-push": "3.4.5", - "webpack": "5.66.0", - "webpack-cli": "4.9.1", + "webpack": "5.70.0", + "webpack-cli": "4.9.2", "websocket": "1.0.34", - "ws": "8.4.2" + "ws": "8.5.0" }, "devDependencies": { - "@redocly/openapi-core": "1.0.0-beta.79", - "@types/fluent-ffmpeg": "2.1.20", - "@typescript-eslint/eslint-plugin": "5.10.0", + "@typescript-eslint/eslint-plugin": "5.12.1", "cross-env": "7.0.3", - "cypress": "9.3.1", + "cypress": "9.5.1", "eslint-plugin-import": "2.25.4", "start-server-and-test": "1.14.0" } diff --git a/packages/client/src/components/autocomplete.vue b/packages/client/src/components/autocomplete.vue index 91a50ffa5..adeac4e05 100644 --- a/packages/client/src/components/autocomplete.vue +++ b/packages/client/src/components/autocomplete.vue @@ -57,7 +57,7 @@ const lib = emojilist.filter(x => x.category !== 'flags'); const char2file = (char: string) => { let codes = Array.from(char).map(x => x.codePointAt(0)?.toString(16)); - if (!codes.includes('200d')) codes = codes.filter(x => x != 'fe0f'); + if (!codes.includes('200d')) codes = codes.filter(x => x !== 'fe0f'); return codes.filter(x => x && x.length).join('-'); }; @@ -192,8 +192,7 @@ function exec() { const cache = sessionStorage.getItem(cacheKey); if (cache) { - const users = JSON.parse(cache); - users.value = users; + users.value = JSON.parse(cache); fetching.value = false; } else { os.api('users/search-by-username-and-host', { @@ -208,7 +207,7 @@ function exec() { }); } } else if (props.type === 'hashtag') { - if (!props.q || props.q == '') { + if (!props.q || props.q === '') { hashtags.value = JSON.parse(localStorage.getItem('hashtags') || '[]'); fetching.value = false; } else { @@ -231,9 +230,9 @@ function exec() { } } } else if (props.type === 'emoji') { - if (!props.q || props.q == '') { + if (!props.q || props.q === '') { // 最近使った絵文字をサジェスト - emojis.value = defaultStore.state.recentlyUsedEmojis.map(emoji => emojiDb.find(e => e.emoji == emoji)).filter(x => x) as EmojiDef[]; + emojis.value = defaultStore.state.recentlyUsedEmojis.map(emoji => emojiDb.find(e => e.emoji === emoji)).filter(x => x) as EmojiDef[]; return; } @@ -241,37 +240,37 @@ function exec() { const max = 30; emojiDb.some(x => { - if (x.name.startsWith(props.q || '') && !x.aliasOf && !matched.some(y => y.emoji == x.emoji)) matched.push(x); - return matched.length == max; + if (x.name.startsWith(props.q ?? '') && !x.aliasOf && !matched.some(y => y.emoji === x.emoji)) matched.push(x); + return matched.length === max; }); if (matched.length < max) { emojiDb.some(x => { - if (x.name.startsWith(props.q || '') && !matched.some(y => y.emoji == x.emoji)) matched.push(x); - return matched.length == max; + if (x.name.startsWith(props.q ?? '') && !matched.some(y => y.emoji === x.emoji)) matched.push(x); + return matched.length === max; }); } if (matched.length < max) { emojiDb.some(x => { - if (x.name.includes(props.q || '') && !matched.some(y => y.emoji == x.emoji)) matched.push(x); - return matched.length == max; + if (x.name.includes(props.q ?? '') && !matched.some(y => y.emoji === x.emoji)) matched.push(x); + return matched.length === max; }); } emojis.value = matched; } else if (props.type === 'mfmTag') { - if (!props.q || props.q == '') { + if (!props.q || props.q === '') { mfmTags.value = MFM_TAGS; return; } - mfmTags.value = MFM_TAGS.filter(tag => tag.startsWith(props.q || '')); + mfmTags.value = MFM_TAGS.filter(tag => tag.startsWith(props.q ?? '')); } } function onMousedown(e: Event) { - if (!contains(rootEl.value, e.target) && (rootEl.value != e.target)) props.close(); + if (!contains(rootEl.value, e.target) && (rootEl.value !== e.target)) props.close(); } function onKeydown(e: KeyboardEvent) { @@ -348,7 +347,7 @@ function chooseUser() { onUpdated(() => { setPosition(); - items.value = suggests.value?.children || []; + items.value = suggests.value?.children ?? []; }); onMounted(() => { diff --git a/packages/client/src/components/captcha.vue b/packages/client/src/components/captcha.vue index 963ae25f8..ccd8880df 100644 --- a/packages/client/src/components/captcha.vue +++ b/packages/client/src/components/captcha.vue @@ -93,7 +93,7 @@ function requestRender() { } function callback(response?: string) { - emit('update:modelValue', typeof response == 'string' ? response : null); + emit('update:modelValue', typeof response === 'string' ? response : null); } onMounted(() => { diff --git a/packages/client/src/components/chart.vue b/packages/client/src/components/chart.vue index b90c790c3..13ca60efa 100644 --- a/packages/client/src/components/chart.vue +++ b/packages/client/src/components/chart.vue @@ -70,6 +70,8 @@ const colors = { red: '#FF4560', purple: '#e300db', orange: '#fe6919', + lime: '#bde800', + cyan: '#00efef', }; const colorSets = [colors.blue, colors.green, colors.yellow, colors.red, colors.purple]; const getColor = (i) => { @@ -224,7 +226,7 @@ export default defineComponent({ axis: 'y', colors: { 0: alpha(x.color ? x.color : getColor(i), 0), - [maxes[i]]: alpha(x.color ? x.color : getColor(i), 0.15), + [maxes[i]]: alpha(x.color ? x.color : getColor(i), 0.175), }, }, }, @@ -273,7 +275,7 @@ export default defineComponent({ y: { position: 'left', stacked: props.stacked, - suggestedMax: 100, + suggestedMax: 50, grid: { color: gridColor, borderColor: 'rgb(0, 0, 0, 0)', @@ -373,16 +375,6 @@ export default defineComponent({ const raw = await os.api('charts/federation', { limit: props.limit, span: props.span }); return { series: [{ - name: 'Sub', - type: 'area', - data: format(raw.sub), - color: colors.orange, - }, { - name: 'Pub', - type: 'area', - data: format(raw.pub), - color: colors.purple, - }, { name: 'Received', type: 'area', data: format(raw.inboxInstances), @@ -397,6 +389,31 @@ export default defineComponent({ type: 'area', data: format(raw.stalled), color: colors.red, + }, { + name: 'Pub Active', + type: 'line', + data: format(raw.pubActive), + color: colors.purple, + }, { + name: 'Sub Active', + type: 'line', + data: format(raw.subActive), + color: colors.orange, + }, { + name: 'Pub & Sub', + type: 'line', + data: format(raw.pubsub), + color: colors.cyan, + }, { + name: 'Pub', + type: 'line', + data: format(raw.pub), + color: colors.purple, + }, { + name: 'Sub', + type: 'line', + data: format(raw.sub), + color: colors.orange, }], }; }; @@ -529,12 +546,12 @@ export default defineComponent({ name: 'Write', type: 'area', data: format(raw.write), - color: colors.blue, + color: colors.lime, }, { name: 'Read', type: 'area', data: format(raw.read), - color: '#888888', + color: colors.blue, }, { name: '< Week', type: 'area', diff --git a/packages/client/src/components/date-separated-list.vue b/packages/client/src/components/date-separated-list.vue index c85a0a6ff..085ef871e 100644 --- a/packages/client/src/components/date-separated-list.vue +++ b/packages/client/src/components/date-separated-list.vue @@ -53,8 +53,8 @@ export default defineComponent({ if (el.key == null && item.id) el.key = item.id; if ( - i != props.items.length - 1 && - new Date(item.createdAt).getDate() != new Date(props.items[i + 1].createdAt).getDate() + i !== props.items.length - 1 && + new Date(item.createdAt).getDate() !== new Date(props.items[i + 1].createdAt).getDate() ) { const separator = h('div', { class: 'separator', diff --git a/packages/client/src/components/google.vue b/packages/client/src/components/google.vue index 210ca72bf..bb4b439ee 100644 --- a/packages/client/src/components/google.vue +++ b/packages/client/src/components/google.vue @@ -1,7 +1,7 @@ diff --git a/packages/client/src/components/launch-pad.vue b/packages/client/src/components/launch-pad.vue index 9076cfb39..4fe36bfef 100644 --- a/packages/client/src/components/launch-pad.vue +++ b/packages/client/src/components/launch-pad.vue @@ -1,6 +1,6 @@ -