Просмотр исходного кода

typescriptize GlobalNotification services

Yuki Takei 2 месяцев назад
Родитель
Сommit
6c489f05d5

+ 3 - 1
apps/app/src/server/crowi/index.ts

@@ -670,7 +670,9 @@ class Crowi {
    * setup GlobalNotificationService
    */
   async setUpGlobalNotification(): Promise<void> {
-    const GlobalNotificationService = require('../service/global-notification');
+    const GlobalNotificationService = (
+      await import('../service/global-notification')
+    ).default;
     if (this.globalNotificationService == null) {
       this.globalNotificationService = new GlobalNotificationService(this);
     }

+ 47 - 27
apps/app/src/server/service/global-notification/global-notification-mail.js → apps/app/src/server/service/global-notification/global-notification-mail.ts

@@ -1,24 +1,33 @@
+import type { IUser } from '@growi/core/dist/interfaces';
 import nodePath from 'path';
 
+import type Crowi from '~/server/crowi';
 import {
   GlobalNotificationSettingEvent,
   GlobalNotificationSettingType,
 } from '~/server/models/GlobalNotificationSetting';
+import type { PageDocument } from '~/server/models/page';
 import { configManager } from '~/server/service/config-manager';
 import { growiInfoService } from '~/server/service/growi-info';
 import loggerFactory from '~/utils/logger';
 
+import type { GlobalNotificationEventVars } from './types';
+
 const _logger = loggerFactory('growi:service:GlobalNotificationMailService');
 
+interface MailOption {
+  subject: string;
+  template: string;
+  vars: Record<string, unknown>;
+}
+
 /**
  * sub service class of GlobalNotificationSetting
  */
 class GlobalNotificationMailService {
-  /** @type {import('~/server/crowi').default} Crowi instance */
-  crowi;
+  crowi: Crowi;
 
-  /** @param {import('~/server/crowi').default} crowi Crowi instance */
-  constructor(crowi) {
+  constructor(crowi: Crowi) {
     this.crowi = crowi;
   }
 
@@ -27,27 +36,33 @@ class GlobalNotificationMailService {
    *
    * @memberof GlobalNotificationMailService
    *
-   * @param {string} event event name triggered
-   * @param {import('~/server/models/page').PageDocument} page page triggered the event
-   * @param {User} triggeredBy user who triggered the event
-   * @param {{ comment: Comment, oldPath: string }} _ event specific vars
+   * @param event event name triggered
+   * @param page page triggered the event
+   * @param triggeredBy user who triggered the event
+   * @param vars event specific vars
    */
-  async fire(event, page, triggeredBy, vars) {
+  async fire(
+    event: string,
+    page: PageDocument,
+    triggeredBy: IUser,
+    vars: GlobalNotificationEventVars,
+  ): Promise<void> {
     const { mailService } = this.crowi;
 
     const { GlobalNotificationSetting } = this.crowi.models;
-    const notifications =
-      await GlobalNotificationSetting.findSettingByPathAndEvent(
-        event,
-        page.path,
-        GlobalNotificationSettingType.MAIL,
-      );
+    const notifications = await (
+      GlobalNotificationSetting as any
+    ).findSettingByPathAndEvent(
+      event,
+      page.path,
+      GlobalNotificationSettingType.MAIL,
+    );
 
     const option = this.generateOption(event, page, triggeredBy, vars);
 
     await Promise.all(
-      notifications.map((notification) => {
-        return mailService.send({ ...option, to: notification.toEmail });
+      notifications.map((notification: { toEmail: string }) => {
+        return mailService?.send({ ...option, to: notification.toEmail });
       }),
     );
   }
@@ -57,14 +72,19 @@ class GlobalNotificationMailService {
    *
    * @memberof GlobalNotificationMailService
    *
-   * @param {string} event event name triggered
-   * @param {import('~/server/models/page').PageDocument} page path triggered the event
-   * @param {User} triggeredBy user triggered the event
-   * @param {{ comment: Comment, oldPath: string }} _ event specific vars
+   * @param event event name triggered
+   * @param page path triggered the event
+   * @param triggeredBy user triggered the event
+   * @param vars event specific vars
    *
-   * @return  {{ subject: string, template: string, vars: object }}
+   * @return {{ subject: string, template: string, vars: object }}
    */
-  generateOption(event, page, triggeredBy, { comment, oldPath }) {
+  generateOption(
+    event: string,
+    page: PageDocument,
+    triggeredBy: IUser,
+    { comment, oldPath }: GlobalNotificationEventVars,
+  ): MailOption {
     const locale = configManager.getConfig('app:globalLang');
     // validate for all events
     if (event == null || page == null || triggeredBy == null) {
@@ -81,10 +101,10 @@ class GlobalNotificationMailService {
     const path = page.path;
     const appTitle = this.crowi.appService.getAppTitle();
     const siteUrl = growiInfoService.getSiteUrl();
-    const pageUrl = new URL(page._id, siteUrl);
+    const pageUrl = new URL(page._id?.toString() ?? '', siteUrl);
 
-    let subject;
-    let vars = {
+    let subject: string;
+    let vars: Record<string, unknown> = {
       appTitle,
       siteUrl,
       path,
@@ -151,4 +171,4 @@ class GlobalNotificationMailService {
   }
 }
 
-module.exports = GlobalNotificationMailService;
+export default GlobalNotificationMailService;

+ 63 - 36
apps/app/src/server/service/global-notification/global-notification-slack.js → apps/app/src/server/service/global-notification/global-notification-slack.ts

@@ -1,5 +1,8 @@
+import type { IUser } from '@growi/core/dist/interfaces';
 import { pagePathUtils } from '@growi/core/dist/utils';
+import urljoin from 'url-join';
 
+import type Crowi from '~/server/crowi';
 import {
   GlobalNotificationSettingEvent,
   GlobalNotificationSettingType,
@@ -8,21 +11,23 @@ import loggerFactory from '~/utils/logger';
 
 import { prepareSlackMessageForGlobalNotification } from '../../util/slack';
 import { growiInfoService } from '../growi-info';
+import type { GlobalNotificationEventVars } from './types';
 
 const _logger = loggerFactory('growi:service:GlobalNotificationSlackService');
-const urljoin = require('url-join');
 
 const { encodeSpaces } = pagePathUtils;
 
+interface GlobalNotificationSlackSetting {
+  slackChannels: string;
+}
+
 /**
  * sub service class of GlobalNotificationSetting
  */
 class GlobalNotificationSlackService {
-  /** @type {import('~/server/crowi').default} Crowi instance */
-  crowi;
+  crowi: Crowi;
 
-  /** @param {import('~/server/crowi').default} crowi Crowi instance */
-  constructor(crowi) {
+  constructor(crowi: Crowi) {
     this.crowi = crowi;
   }
 
@@ -31,22 +36,31 @@ class GlobalNotificationSlackService {
    *
    * @memberof GlobalNotificationSlackService
    *
-   * @param {string} event
-   * @param {string} id
-   * @param {string} path
-   * @param {User} triggeredBy user who triggered the event
-   * @param {{ comment: Comment, oldPath: string }} _ event specific vars
+   * @param event event name
+   * @param id page id
+   * @param path page path
+   * @param triggeredBy user who triggered the event
+   * @param vars event specific vars
    */
-  async fire(event, id, path, triggeredBy, vars) {
+
+  // biome-ignore lint/nursery/useMaxParams: ignore
+  async fire(
+    event: string,
+    id: string,
+    path: string,
+    triggeredBy: IUser,
+    vars: GlobalNotificationEventVars,
+  ): Promise<void> {
     const { appService, slackIntegrationService } = this.crowi;
 
     const { GlobalNotificationSetting } = this.crowi.models;
-    const notifications =
-      await GlobalNotificationSetting.findSettingByPathAndEvent(
-        event,
-        path,
-        GlobalNotificationSettingType.SLACK,
-      );
+    const notifications = (
+      GlobalNotificationSetting as any
+    ).findSettingByPathAndEvent(
+      event,
+      path,
+      GlobalNotificationSettingType.SLACK,
+    );
 
     const messageBody = this.generateMessageBody(
       event,
@@ -66,14 +80,15 @@ class GlobalNotificationSlackService {
     const appTitle = appService.getAppTitle();
 
     await Promise.all(
-      notifications.map((notification) => {
+      notifications.map((notification: GlobalNotificationSlackSetting) => {
         const messageObj = prepareSlackMessageForGlobalNotification(
           messageBody,
           attachmentBody,
           appTitle,
           notification.slackChannels,
         );
-        return slackIntegrationService.postMessage(messageObj);
+        // eslint-disable-next-line @typescript-eslint/no-explicit-any
+        return slackIntegrationService.postMessage(messageObj as any);
       }),
     );
   }
@@ -83,20 +98,26 @@ class GlobalNotificationSlackService {
    *
    * @memberof GlobalNotificationSlackService
    *
-   * @param {string} event event name triggered
-   * @param {string} id page id
-   * @param {string} path path triggered the event
-   * @param {User} triggeredBy user triggered the event
-   * @param {{ comment: Comment, oldPath: string }} _ event specific vars
+   * @param event event name triggered
+   * @param id page id
+   * @param path path triggered the event
+   * @param triggeredBy user triggered the event
+   * @param vars event specific vars
    *
-   * @return  {string} slack message body
+   * @return slack message body
    */
-  generateMessageBody(event, id, path, triggeredBy, { comment, oldPath }) {
+  generateMessageBody(
+    event: string,
+    id: string,
+    path: string,
+    triggeredBy: IUser,
+    { comment, oldPath }: GlobalNotificationEventVars,
+  ): string {
     const siteUrl = growiInfoService.getSiteUrl();
     const parmaLink = `<${urljoin(siteUrl, id)}|${path}>`;
-    const pathLink = `<${urljoin(siteUrl, encodeSpaces(path))}|${path}>`;
+    const pathLink = `<${urljoin(siteUrl, encodeSpaces(path) ?? '')}|${path}>`;
     const username = `<${urljoin(siteUrl, 'user', triggeredBy.username)}|${triggeredBy.username}>`;
-    let messageBody;
+    let messageBody: string;
 
     switch (event) {
       case GlobalNotificationSettingEvent.PAGE_CREATE:
@@ -141,15 +162,21 @@ class GlobalNotificationSlackService {
    *
    * @memberof GlobalNotificationSlackService
    *
-   * @param {string} event event name triggered
-   * @param {string} id page id
-   * @param {string} path path triggered the event
-   * @param {User} triggeredBy user triggered the event
-   * @param {{ comment: Comment, oldPath: string }} _ event specific vars
+   * @param event event name triggered
+   * @param id page id
+   * @param path path triggered the event
+   * @param triggeredBy user triggered the event
+   * @param vars event specific vars
    *
-   * @return  {string} slack attachment body
+   * @return slack attachment body
    */
-  generateAttachmentBody(event, id, path, triggeredBy, { comment, oldPath }) {
+  generateAttachmentBody(
+    _event: string,
+    _id: string,
+    _path: string,
+    _triggeredBy: IUser,
+    _vars: GlobalNotificationEventVars,
+  ): string {
     const attachmentBody = '';
 
     // TODO: create attachment
@@ -176,4 +203,4 @@ class GlobalNotificationSlackService {
   }
 }
 
-module.exports = GlobalNotificationSlackService;
+export default GlobalNotificationSlackService;

+ 55 - 31
apps/app/src/server/service/global-notification/index.ts

@@ -1,25 +1,38 @@
+import { PageGrant } from '@growi/core';
+import type { IUser } from '@growi/core/dist/interfaces';
+
+import type Crowi from '~/server/crowi';
+import type { PageDocument } from '~/server/models/page';
 import loggerFactory from '~/utils/logger';
 
+import GlobalNotificationMailService from './global-notification-mail';
+import GlobalNotificationSlackService from './global-notification-slack';
+import type { GlobalNotificationEventVars } from './types';
+
 const logger = loggerFactory('growi:service:GlobalNotificationService');
-const GloabalNotificationMail = require('./global-notification-mail');
-const GloabalNotificationSlack = require('./global-notification-slack');
 
 /**
  * service class of GlobalNotificationSetting
  */
 class GlobalNotificationService {
-  /** @type {import('~/server/crowi').default} Crowi instance */
-  crowi;
+  crowi: Crowi;
+
+  defaultLang: string;
+
+  globalNotificationMailService: GlobalNotificationMailService;
 
-  /** @param {import('~/server/crowi').default} crowi Crowi instance */
-  constructor(crowi) {
+  globalNotificationSlackService: GlobalNotificationSlackService;
+
+  constructor(crowi: Crowi) {
     this.crowi = crowi;
     this.defaultLang = 'en_US'; // TODO: get defaultLang from app global config
 
-    this.gloabalNotificationMail = new GloabalNotificationMail(crowi);
-    this.gloabalNotificationSlack = new GloabalNotificationSlack(crowi);
-
-    this.Page = this.crowi.models.Page;
+    this.globalNotificationMailService = new GlobalNotificationMailService(
+      crowi,
+    );
+    this.globalNotificationSlackService = new GlobalNotificationSlackService(
+      crowi,
+    );
   }
 
   /**
@@ -27,12 +40,17 @@ class GlobalNotificationService {
    *
    * @memberof GlobalNotificationService
    *
-   * @param {string} event event name triggered
-   * @param {string} page page triggered the event
-   * @param {User} triggeredBy user who triggered the event
-   * @param {object} vars event specific vars
+   * @param event event name triggered
+   * @param page page triggered the event
+   * @param triggeredBy user who triggered the event
+   * @param vars event specific vars
    */
-  async fire(event, page, triggeredBy, vars = {}) {
+  async fire(
+    event: string,
+    page: PageDocument,
+    triggeredBy: IUser,
+    vars: GlobalNotificationEventVars = {},
+  ): Promise<void> {
     logger.debug(`global notficatoin event ${event} was triggered`);
 
     // validation
@@ -48,10 +66,10 @@ class GlobalNotificationService {
     }
 
     await Promise.all([
-      this.gloabalNotificationMail.fire(event, page, triggeredBy, vars),
-      this.gloabalNotificationSlack.fire(
+      this.globalNotificationMailService.fire(event, page, triggeredBy, vars),
+      this.globalNotificationSlackService.fire(
         event,
-        page.id,
+        page.id ?? page._id?.toString(),
         page.path,
         triggeredBy,
         vars,
@@ -64,27 +82,33 @@ class GlobalNotificationService {
    *
    * @memberof GlobalNotificationService
    *
-   * @param {number} grant page grant
-   * @return {boolean} isSendNotification
+   * @param grant page grant
+   * @return isSendNotification
    */
-  isSendNotification(grant) {
+  isSendNotification(grant: number): boolean {
     switch (grant) {
-      case this.Page.GRANT_PUBLIC:
+      case PageGrant.GRANT_PUBLIC:
         return true;
-      case this.Page.GRANT_RESTRICTED:
+      case PageGrant.GRANT_RESTRICTED:
         return false;
-      case this.Page.GRANT_SPECIFIED:
+      case PageGrant.GRANT_SPECIFIED:
         return false;
-      case this.Page.GRANT_OWNER:
-        return this.crowi.configManager.getConfig(
-          'notification:owner-page:isEnabled',
+      case PageGrant.GRANT_OWNER:
+        return (
+          this.crowi.configManager.getConfig(
+            'notification:owner-page:isEnabled',
+          ) ?? false
         );
-      case this.Page.GRANT_USER_GROUP:
-        return this.crowi.configManager.getConfig(
-          'notification:group-page:isEnabled',
+      case PageGrant.GRANT_USER_GROUP:
+        return (
+          this.crowi.configManager.getConfig(
+            'notification:group-page:isEnabled',
+          ) ?? false
         );
+      default:
+        return false;
     }
   }
 }
 
-module.exports = GlobalNotificationService;
+export default GlobalNotificationService;

+ 4 - 0
apps/app/src/server/service/global-notification/types.d.ts

@@ -0,0 +1,4 @@
+export interface GlobalNotificationEventVars {
+  comment?: IComment;
+  oldPath?: string;
+}