Browse Source

append types

Yuki Takei 2 months ago
parent
commit
2623d4a24c

+ 4 - 0
apps/app/config/next-i18next.config.d.ts

@@ -0,0 +1,4 @@
+import type { UserConfig } from 'next-i18next';
+
+declare const config: UserConfig;
+export = config;

+ 3 - 0
apps/app/src/client/components/Admin/Security/LdapAuthTestModal.jsx

@@ -56,6 +56,9 @@ LdapAuthTestModal.propTypes = {
   onClose: PropTypes.func.isRequired,
 };
 
+/**
+ * @type {React.ComponentType<{ isOpen: boolean, onClose: () => void }>}
+ */
 const LdapAuthTestModalWrapper = withUnstatedContainers(LdapAuthTestModal, []);
 
 export default LdapAuthTestModalWrapper;

+ 4 - 3
apps/app/src/client/components/Admin/Users/GrantAdminButton.tsx

@@ -40,8 +40,9 @@ const GrantAdminButton = (props: GrantAdminButtonProps): JSX.Element => {
 /**
  * Wrapper component for using unstated
  */
-const GrantAdminButtonWrapper: React.ForwardRefExoticComponent<
-  Pick<any, string | number | symbol> & React.RefAttributes<any>
-> = withUnstatedContainers(GrantAdminButton, [AdminUsersContainer]);
+const GrantAdminButtonWrapper = withUnstatedContainers<
+  unknown,
+  GrantAdminButtonProps
+>(GrantAdminButton, [AdminUsersContainer]);
 
 export default GrantAdminButtonWrapper;

+ 3 - 0
apps/app/src/client/components/Admin/Users/SendInvitationEmailButton.jsx

@@ -55,6 +55,9 @@ const SendInvitationEmailButton = (props) => {
   );
 };
 
+/**
+ * @type {React.ComponentType<{ user: import('@growi/core').IUserHasId, isInvitationEmailSended: boolean, onSuccessfullySentInvitationEmail: () => void }>}
+ */
 const SendInvitationEmailButtonWrapper = withUnstatedContainers(
   SendInvitationEmailButton,
   [AdminUsersContainer],

+ 1 - 0
apps/app/src/client/components/Admin/Users/StatusActivateButton.jsx

@@ -52,6 +52,7 @@ const StatusActivateFormWrapperFC = (props) => {
 
 /**
  * Wrapper component for using unstated
+ * @type {React.ComponentType<{ user: import('@growi/core').IUserHasId }>}
  */
 const StatusActivateFormWrapper = withUnstatedContainers(
   StatusActivateFormWrapperFC,

+ 4 - 3
apps/app/src/client/components/Admin/Users/UserMenu.tsx

@@ -146,8 +146,9 @@ const UserMenu = (props: UserMenuProps) => {
 /**
  * Wrapper component for using unstated
  */
-const UserMenuWrapper: React.ForwardRefExoticComponent<
-  Pick<any, string | number | symbol> & React.RefAttributes<any>
-> = withUnstatedContainers(UserMenu, [AdminUsersContainer]);
+const UserMenuWrapper = withUnstatedContainers<unknown, UserMenuProps>(
+  UserMenu,
+  [AdminUsersContainer],
+);
 
 export default UserMenuWrapper;

+ 1 - 0
apps/app/src/client/components/Admin/Users/UserRemoveButton.jsx

@@ -60,6 +60,7 @@ const UserRemoveButtonWrapperFC = (props) => {
 
 /**
  * Wrapper component for using unstated
+ * @type {React.ComponentType<{ user: import('@growi/core').IUserHasId }>}
  */
 const UserRemoveButtonWrapper = withUnstatedContainers(
   UserRemoveButtonWrapperFC,

+ 3 - 1
apps/app/src/client/components/InstallerForm.tsx

@@ -5,7 +5,7 @@ import { AllLang, Lang } from '@growi/core';
 import { LoadingSpinner } from '@growi/ui/dist/components';
 import { useTranslation } from 'next-i18next';
 
-import { i18n as i18nConfig } from '^/config/next-i18next.config';
+import * as nextI18nConfig from '^/config/next-i18next.config';
 
 import { apiv3Post } from '~/client/util/apiv3-client';
 import { useTWithOpt } from '~/client/util/t-with-opt';
@@ -16,6 +16,8 @@ import styles from './InstallerForm.module.scss';
 
 const moduleClass = styles['installer-form'] ?? '';
 
+const i18nConfig = nextI18nConfig.i18n;
+
 type Props = {
   minPasswordLength: number;
 };

+ 4 - 2
apps/app/src/client/components/Me/BasicInfoSettings.tsx

@@ -1,9 +1,9 @@
-import React, { type JSX, useEffect, useState } from 'react';
+import { type JSX, useEffect, useState } from 'react';
 import type { IUser } from '@growi/core/dist/interfaces';
 import { useAtomValue } from 'jotai';
 import { i18n, useTranslation } from 'next-i18next';
 
-import { i18n as i18nConfig } from '^/config/next-i18next.config';
+import * as nextI18nConfig from '^/config/next-i18next.config';
 
 import { toastError, toastSuccess } from '~/client/util/toastr';
 import { registrationWhitelistAtom } from '~/states/server-configurations';
@@ -12,6 +12,8 @@ import {
   useUpdateBasicInfo,
 } from '~/stores/personal-settings';
 
+const i18nConfig = nextI18nConfig.i18n;
+
 export const BasicInfoSettings = (): JSX.Element => {
   const { t } = useTranslation();
   const registrationWhitelist = useAtomValue(registrationWhitelistAtom);

+ 5 - 4
apps/app/src/features/openai/server/services/openai.ts

@@ -1,4 +1,7 @@
 import assert from 'node:assert';
+import fs from 'node:fs';
+import { Readable, Transform, Writable } from 'node:stream';
+import { pipeline } from 'node:stream/promises';
 import type { IPage, IUser, Lang, Nullable, Ref } from '@growi/core';
 import {
   getIdForRef,
@@ -10,13 +13,11 @@ import {
 import { deepEquals } from '@growi/core/dist/utils';
 import { isGlobPatternPath } from '@growi/core/dist/utils/page-path-utils';
 import escapeStringRegexp from 'escape-string-regexp';
-import fs from 'fs';
 import createError from 'http-errors';
 import mongoose, { type HydratedDocument, type Types } from 'mongoose';
-import { type OpenAI, toFile } from 'openai';
+import type { OpenAI } from 'openai';
+import { toFile } from 'openai';
 import type { ChatCompletionChunk } from 'openai/resources/chat/completions';
-import { Readable, Transform, Writable } from 'stream';
-import { pipeline } from 'stream/promises';
 
 import ExternalUserGroupRelation from '~/features/external-user-group/server/models/external-user-group-relation';
 import ThreadRelationModel, {

+ 22 - 7
apps/app/src/server/models/vo/s2c-message.js → apps/app/src/server/models/vo/s2c-message.ts

@@ -1,14 +1,33 @@
-const { serializePageSecurely } = require('../serializers/page-serializer');
+import type { IPage, IUser } from '@growi/core/dist/interfaces';
+import { isPopulated } from '@growi/core/dist/interfaces';
+
+import { serializePageSecurely } from '../serializers/page-serializer';
 
 /**
  * Server-to-client message VO
  */
-class S2cMessagePageUpdated {
-  constructor(page, user) {
+export class S2cMessagePageUpdated {
+  pageId: string;
+
+  revisionId: string;
+
+  revisionBody: string;
+
+  revisionUpdateAt: Date;
+
+  revisionOrigin: string | undefined;
+
+  remoteLastUpdateUser?: IUser;
+
+  lastUpdateUsername?: string;
+
+  constructor(page: IPage, user?: IUser) {
     const serializedPage = serializePageSecurely(page);
 
     const { _id, revision, updatedAt } = serializedPage;
 
+    assert(page.revision != null && isPopulated(page.revision));
+
     this.pageId = _id;
     this.revisionId = revision;
     this.revisionBody = page.revision.body;
@@ -22,7 +41,3 @@ class S2cMessagePageUpdated {
     }
   }
 }
-
-module.exports = {
-  S2cMessagePageUpdated,
-};

+ 11 - 8
apps/app/src/server/routes/apiv3/app-settings/index.ts

@@ -1,10 +1,13 @@
 import { ConfigSource, SCOPE } from '@growi/core/dist/interfaces';
 import { ErrorV3 } from '@growi/core/dist/models';
+import pathUtils from '@growi/core/dist/utils/path-utils';
+import express from 'express';
 import { body } from 'express-validator';
 
-import { i18n } from '^/config/next-i18next.config';
+import * as nextI18nConfig from '^/config/next-i18next.config';
 
 import { SupportedAction } from '~/interfaces/activity';
+import type { CrowiRequest } from '~/interfaces/crowi-request';
 import { accessTokenParser } from '~/server/middlewares/access-token-parser';
 import { configManager } from '~/server/service/config-manager';
 import { getTranslation } from '~/server/service/i18next';
@@ -12,11 +15,11 @@ import loggerFactory from '~/utils/logger';
 
 import { generateAddActivityMiddleware } from '../../../middlewares/add-activity';
 import { apiV3FormValidator } from '../../../middlewares/apiv3-form-validator';
+import type { ApiV3Response } from '../interfaces/apiv3-response';
 
 const logger = loggerFactory('growi:routes:apiv3:app-settings');
 
-const { pathUtils } = require('@growi/core/dist/utils');
-const express = require('express');
+const { i18n } = nextI18nConfig;
 
 const router = express.Router();
 
@@ -392,7 +395,7 @@ module.exports = (crowi) => {
     accessTokenParser([SCOPE.READ.ADMIN.APP], { acceptLegacy: true }),
     loginRequiredStrictly,
     adminRequired,
-    async (req, res) => {
+    (_req: CrowiRequest, res: ApiV3Response) => {
       const appSettingsParams = {
         title: configManager.getConfig('app:title'),
         confidential: configManager.getConfig('app:confidential'),
@@ -850,11 +853,11 @@ module.exports = (crowi) => {
     loginRequiredStrictly,
     adminRequired,
     addActivity,
-    async (req, res) => {
-      const { t } = await getTranslation({ lang: req.user.lang });
+    async (req: CrowiRequest, res: ApiV3Response) => {
+      const { t } = await getTranslation({ lang: req.user?.lang });
 
       try {
-        await sendTestEmail(req.user.email);
+        await sendTestEmail(req.user?.email);
         const parameters = {
           action: SupportedAction.ACTION_ADMIN_MAIL_TEST_SUBMIT,
         };
@@ -1005,7 +1008,7 @@ module.exports = (crowi) => {
     accessTokenParser([SCOPE.WRITE.ADMIN.APP], { acceptLegacy: true }),
     loginRequiredStrictly,
     adminRequired,
-    async (req, res) => {
+    (_req: CrowiRequest, res: ApiV3Response) => {
       const isMaintenanceMode = crowi.appService.isMaintenanceMode();
       if (!isMaintenanceMode) {
         return res.apiv3Err(

+ 6 - 4
apps/app/src/server/service/g2g-transfer.ts

@@ -1,12 +1,12 @@
+import type { ReadStream } from 'node:fs';
+import { createReadStream } from 'node:fs';
 import { ConfigSource } from '@growi/core';
 import type { IUser } from '@growi/core/dist/interfaces';
 // biome-ignore lint/style/noRestrictedImports: TODO: check effects of using custom axios
 import rawAxios, { type AxiosRequestConfig } from 'axios';
-import FormData from 'form-data';
-import type { ReadStream } from 'fs';
-import { createReadStream } from 'fs';
+import * as FormDataModule from 'form-data';
 import mongoose, { Types as MongooseTypes } from 'mongoose';
-import { basename } from 'path';
+import { basename } from 'pathe';
 
 import { G2G_PROGRESS_STATUS } from '~/interfaces/g2g-transfer';
 import { GrowiArchiveImportOption } from '~/models/admin/growi-archive-import-option';
@@ -32,6 +32,8 @@ import { generateOverwriteParams } from './import/overwrite-params';
 
 const logger = loggerFactory('growi:service:g2g-transfer');
 
+const FormData = FormDataModule.default ?? FormDataModule;
+
 /**
  * Header name for transfer key
  */

+ 6 - 6
apps/app/src/server/service/import/import.ts

@@ -1,5 +1,8 @@
+import fs from 'node:fs';
+import type { EventEmitter } from 'node:stream';
+import { Transform, Writable } from 'node:stream';
+import { pipeline } from 'node:stream/promises';
 import gc from 'expose-gc/function';
-import fs from 'fs';
 import type {
   BulkOperationBase,
   BulkWriteResult,
@@ -9,10 +12,7 @@ import type {
 } from 'mongodb';
 import type { Document } from 'mongoose';
 import mongoose from 'mongoose';
-import path from 'path';
-import type { EventEmitter } from 'stream';
-import { Transform, Writable } from 'stream';
-import { pipeline } from 'stream/promises';
+import path from 'pathe';
 import unzipStream from 'unzip-stream';
 
 import { ImportMode } from '~/models/admin/import-mode';
@@ -31,7 +31,7 @@ import { getModelFromCollectionName } from './get-model-from-collection-name';
 import type { ImportSettings, OverwriteParams } from './import-settings';
 import { keepOriginal } from './overwrite-function';
 
-import JSONStream from 'JSONStream';
+import * as JSONStream from 'JSONStream';
 
 const logger = loggerFactory('growi:services:ImportService');
 

+ 4 - 8
apps/app/src/server/util/batch-stream.js → apps/app/src/server/util/batch-stream.ts

@@ -1,13 +1,13 @@
-const { Transform } = require('stream');
+import { Transform } from 'node:stream';
 
-function createBatchStream(batchSize) {
-  let batchBuffer = [];
+export function createBatchStream<T>(batchSize: number): Transform {
+  let batchBuffer: T[] = [];
 
   return new Transform({
     // object mode
     objectMode: true,
 
-    transform(doc, encoding, callback) {
+    transform(doc: T, _encoding, callback) {
       batchBuffer.push(doc);
 
       if (batchBuffer.length >= batchSize) {
@@ -28,7 +28,3 @@ function createBatchStream(batchSize) {
     },
   });
 }
-
-module.exports = {
-  createBatchStream,
-};