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

Merge pull request #6283 from weseek/support/refactor-pageinfo-types

support: Refactor PageInfo types
Yuki Takei 3 лет назад
Родитель
Сommit
237d9aff85

+ 1 - 11
packages/app/src/components/LikeButtons.tsx

@@ -85,14 +85,4 @@ const LikeButtons: FC<LikeButtonsProps> = (props: LikeButtonsProps) => {
 
 
 };
 };
 
 
-/**
- * Wrapper component for using unstated
- */
-const LikeButtonsUnstatedWrapper = withUnstatedContainers(LikeButtons, [AppContainer]);
-
-// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
-const LikeButtonsWrapper = (props) => {
-  return <LikeButtonsUnstatedWrapper {...props}></LikeButtonsUnstatedWrapper>;
-};
-
-export default LikeButtonsWrapper;
+export default LikeButtons;

+ 8 - 8
packages/app/src/components/Navbar/GlobalSearch.tsx

@@ -1,19 +1,19 @@
 import React, {
 import React, {
   FC, useState, useCallback, useRef,
   FC, useState, useCallback, useRef,
 } from 'react';
 } from 'react';
-import { useTranslation } from 'react-i18next';
+
 import assert from 'assert';
 import assert from 'assert';
 
 
-import AppContainer from '~/client/services/AppContainer';
+import { useTranslation } from 'react-i18next';
+
 import { IFocusable } from '~/client/interfaces/focusable';
 import { IFocusable } from '~/client/interfaces/focusable';
+import AppContainer from '~/client/services/AppContainer';
+import { IPageWithSearchMeta } from '~/interfaces/search';
+import { useCurrentPagePath } from '~/stores/context';
 import { useGlobalSearchFormRef } from '~/stores/ui';
 import { useGlobalSearchFormRef } from '~/stores/ui';
-import { IPageSearchMeta } from '~/interfaces/search';
-import { IPageWithMeta } from '~/interfaces/page';
-
-import { withUnstatedContainers } from '../UnstatedUtils';
 
 
 import SearchForm from '../SearchForm';
 import SearchForm from '../SearchForm';
-import { useCurrentPagePath } from '~/stores/context';
+import { withUnstatedContainers } from '../UnstatedUtils';
 
 
 
 
 type Props = {
 type Props = {
@@ -36,7 +36,7 @@ const GlobalSearch: FC<Props> = (props: Props) => {
 
 
   const { data: currentPagePath } = useCurrentPagePath();
   const { data: currentPagePath } = useCurrentPagePath();
 
 
-  const gotoPage = useCallback((data: IPageWithMeta<IPageSearchMeta>[]) => {
+  const gotoPage = useCallback((data: IPageWithSearchMeta[]) => {
     assert(data.length > 0);
     assert(data.length > 0);
 
 
     const page = data[0].data; // should be single page selected
     const page = data[0].data; // should be single page selected

+ 4 - 4
packages/app/src/components/PageList/PageList.tsx

@@ -2,7 +2,7 @@ import React from 'react';
 
 
 import { useTranslation } from 'react-i18next';
 import { useTranslation } from 'react-i18next';
 
 
-import { IPageWithMeta } from '~/interfaces/page';
+import { IPageInfoForEntity, IPageWithMeta } from '~/interfaces/page';
 import { OnDeletedFunction, OnPutBackedFunction } from '~/interfaces/ui';
 import { OnDeletedFunction, OnPutBackedFunction } from '~/interfaces/ui';
 
 
 import { ForceHideMenuItems } from '../Common/Dropdown/PageItemControl';
 import { ForceHideMenuItems } from '../Common/Dropdown/PageItemControl';
@@ -10,15 +10,15 @@ import { ForceHideMenuItems } from '../Common/Dropdown/PageItemControl';
 import { PageListItemL } from './PageListItemL';
 import { PageListItemL } from './PageListItemL';
 
 
 
 
-type Props = {
-  pages: IPageWithMeta[],
+type Props<M extends IPageInfoForEntity> = {
+  pages: IPageWithMeta<M>[],
   isEnableActions?: boolean,
   isEnableActions?: boolean,
   forceHideMenuItems?: ForceHideMenuItems,
   forceHideMenuItems?: ForceHideMenuItems,
   onPagesDeleted?: OnDeletedFunction,
   onPagesDeleted?: OnDeletedFunction,
   onPagePutBacked?: OnPutBackedFunction,
   onPagePutBacked?: OnPutBackedFunction,
 }
 }
 
 
-const PageList = (props: Props): JSX.Element => {
+const PageList = (props: Props<IPageInfoForEntity>): JSX.Element => {
   const { t } = useTranslation();
   const { t } = useTranslation();
   const {
   const {
     pages, isEnableActions, forceHideMenuItems, onPagesDeleted, onPagePutBacked,
     pages, isEnableActions, forceHideMenuItems, onPagesDeleted, onPagePutBacked,

+ 3 - 3
packages/app/src/components/PageList/PageListItemL.tsx

@@ -16,9 +16,9 @@ import urljoin from 'url-join';
 import { ISelectable } from '~/client/interfaces/selectable-all';
 import { ISelectable } from '~/client/interfaces/selectable-all';
 import { bookmark, unbookmark } from '~/client/services/page-operation';
 import { bookmark, unbookmark } from '~/client/services/page-operation';
 import {
 import {
-  IPageInfoAll, IPageInfoForEntity, IPageInfoForListing, IPageWithMeta, isIPageInfoForListing, isIPageInfoForEntity,
+  IPageInfoAll, isIPageInfoForListing, isIPageInfoForEntity, IPageWithMeta, IPageInfoForListing,
 } from '~/interfaces/page';
 } from '~/interfaces/page';
-import { IPageSearchMeta, isIPageSearchMeta } from '~/interfaces/search';
+import { IPageSearchMeta, IPageWithSearchMeta, isIPageSearchMeta } from '~/interfaces/search';
 import {
 import {
   OnDuplicatedFunction, OnRenamedFunction, OnDeletedFunction, OnPutBackedFunction,
   OnDuplicatedFunction, OnRenamedFunction, OnDeletedFunction, OnPutBackedFunction,
 } from '~/interfaces/ui';
 } from '~/interfaces/ui';
@@ -33,7 +33,7 @@ import { ForceHideMenuItems, PageItemControl } from '../Common/Dropdown/PageItem
 import PagePathHierarchicalLink from '../PagePathHierarchicalLink';
 import PagePathHierarchicalLink from '../PagePathHierarchicalLink';
 
 
 type Props = {
 type Props = {
-  page: IPageWithMeta<IPageInfoForEntity> | IPageWithMeta<IPageSearchMeta> | IPageWithMeta<IPageInfoForListing & IPageSearchMeta>,
+  page: IPageWithSearchMeta | IPageWithMeta<IPageInfoForListing & IPageSearchMeta>,
   isSelected?: boolean, // is item selected(focused)
   isSelected?: boolean, // is item selected(focused)
   isEnableActions?: boolean,
   isEnableActions?: boolean,
   forceHideMenuItems?: ForceHideMenuItems,
   forceHideMenuItems?: ForceHideMenuItems,

+ 3 - 3
packages/app/src/components/SearchForm.tsx

@@ -2,12 +2,12 @@ import React, {
   FC, forwardRef, ForwardRefRenderFunction, useImperativeHandle,
   FC, forwardRef, ForwardRefRenderFunction, useImperativeHandle,
   useRef, useState,
   useRef, useState,
 } from 'react';
 } from 'react';
+
 import { useTranslation } from 'react-i18next';
 import { useTranslation } from 'react-i18next';
 
 
 import { IFocusable } from '~/client/interfaces/focusable';
 import { IFocusable } from '~/client/interfaces/focusable';
 import { TypeaheadProps } from '~/client/interfaces/react-bootstrap-typeahead';
 import { TypeaheadProps } from '~/client/interfaces/react-bootstrap-typeahead';
-import { IPageWithMeta } from '~/interfaces/page';
-import { IPageSearchMeta } from '~/interfaces/search';
+import { IPageWithSearchMeta } from '~/interfaces/search';
 
 
 import SearchTypeahead from './SearchTypeahead';
 import SearchTypeahead from './SearchTypeahead';
 
 
@@ -81,7 +81,7 @@ type Props = TypeaheadProps & {
 
 
   keywordOnInit?: string,
   keywordOnInit?: string,
   disableIncrementalSearch?: boolean,
   disableIncrementalSearch?: boolean,
-  onChange?: (data: IPageWithMeta<IPageSearchMeta>[]) => void,
+  onChange?: (data: IPageWithSearchMeta[]) => void,
   onSubmit?: (input: string) => void,
   onSubmit?: (input: string) => void,
 };
 };
 
 

+ 2 - 2
packages/app/src/components/SearchPage/SearchResultContent.tsx

@@ -9,7 +9,7 @@ import { exportAsMarkdown } from '~/client/services/page-operation';
 import { toastSuccess } from '~/client/util/apiNotification';
 import { toastSuccess } from '~/client/util/apiNotification';
 import { smoothScrollIntoView } from '~/client/util/smooth-scroll';
 import { smoothScrollIntoView } from '~/client/util/smooth-scroll';
 import { IPageToDeleteWithMeta, IPageToRenameWithMeta, IPageWithMeta } from '~/interfaces/page';
 import { IPageToDeleteWithMeta, IPageToRenameWithMeta, IPageWithMeta } from '~/interfaces/page';
-import { IPageSearchMeta } from '~/interfaces/search';
+import { IPageWithSearchMeta } from '~/interfaces/search';
 import { OnDuplicatedFunction, OnRenamedFunction, OnDeletedFunction } from '~/interfaces/ui';
 import { OnDuplicatedFunction, OnRenamedFunction, OnDeletedFunction } from '~/interfaces/ui';
 import {
 import {
   usePageDuplicateModal, usePageRenameModal, usePageDeleteModal,
   usePageDuplicateModal, usePageRenameModal, usePageDeleteModal,
@@ -56,7 +56,7 @@ const MUTATION_OBSERVER_CONFIG = { childList: true, subtree: true };
 
 
 type Props ={
 type Props ={
   appContainer: AppContainer,
   appContainer: AppContainer,
-  pageWithMeta : IPageWithMeta<IPageSearchMeta>,
+  pageWithMeta : IPageWithSearchMeta,
   highlightKeywords?: string[],
   highlightKeywords?: string[],
   showPageControlDropdown?: boolean,
   showPageControlDropdown?: boolean,
   forceHideMenuItems?: ForceHideMenuItems,
   forceHideMenuItems?: ForceHideMenuItems,

+ 7 - 5
packages/app/src/components/SearchPage/SearchResultList.tsx

@@ -2,28 +2,30 @@ import React, {
   forwardRef,
   forwardRef,
   ForwardRefRenderFunction, useCallback, useImperativeHandle, useRef,
   ForwardRefRenderFunction, useCallback, useImperativeHandle, useRef,
 } from 'react';
 } from 'react';
+
 import { useTranslation } from 'react-i18next';
 import { useTranslation } from 'react-i18next';
+
 import { ISelectable, ISelectableAll } from '~/client/interfaces/selectable-all';
 import { ISelectable, ISelectableAll } from '~/client/interfaces/selectable-all';
 import { toastSuccess } from '~/client/util/apiNotification';
 import { toastSuccess } from '~/client/util/apiNotification';
 import {
 import {
   IPageInfoForListing, IPageWithMeta, isIPageInfoForListing,
   IPageInfoForListing, IPageWithMeta, isIPageInfoForListing,
 } from '~/interfaces/page';
 } from '~/interfaces/page';
-import { IPageSearchMeta } from '~/interfaces/search';
+import { IPageSearchMeta, IPageWithSearchMeta } from '~/interfaces/search';
 import { OnDuplicatedFunction, OnRenamedFunction, OnDeletedFunction } from '~/interfaces/ui';
 import { OnDuplicatedFunction, OnRenamedFunction, OnDeletedFunction } from '~/interfaces/ui';
 import { useIsGuestUser } from '~/stores/context';
 import { useIsGuestUser } from '~/stores/context';
 import { useSWRxPageInfoForList } from '~/stores/page';
 import { useSWRxPageInfoForList } from '~/stores/page';
 import { usePageTreeTermManager } from '~/stores/page-listing';
 import { usePageTreeTermManager } from '~/stores/page-listing';
 import { useFullTextSearchTermManager } from '~/stores/search';
 import { useFullTextSearchTermManager } from '~/stores/search';
-import { ForceHideMenuItems } from '../Common/Dropdown/PageItemControl';
 
 
+import { ForceHideMenuItems } from '../Common/Dropdown/PageItemControl';
 import { PageListItemL } from '../PageList/PageListItemL';
 import { PageListItemL } from '../PageList/PageListItemL';
 
 
 
 
 type Props = {
 type Props = {
-  pages: IPageWithMeta<IPageSearchMeta>[],
+  pages: IPageWithSearchMeta[],
   selectedPageId?: string,
   selectedPageId?: string,
   forceHideMenuItems?: ForceHideMenuItems,
   forceHideMenuItems?: ForceHideMenuItems,
-  onPageSelected?: (page?: IPageWithMeta<IPageSearchMeta>) => void,
+  onPageSelected?: (page?: IPageWithSearchMeta) => void,
   onCheckboxChanged?: (isChecked: boolean, pageId: string) => void,
   onCheckboxChanged?: (isChecked: boolean, pageId: string) => void,
 }
 }
 
 
@@ -72,7 +74,7 @@ const SearchResultListSubstance: ForwardRefRenderFunction<ISelectableAll, Props>
     }
     }
   }, [onPageSelected, pages]);
   }, [onPageSelected, pages]);
 
 
-  let injectedPages: (IPageWithMeta<IPageSearchMeta> | IPageWithMeta<IPageInfoForListing & IPageSearchMeta>)[] | undefined;
+  let injectedPages: (IPageWithSearchMeta | IPageWithMeta<IPageInfoForListing & IPageSearchMeta>)[] | undefined;
   // inject data to list
   // inject data to list
   if (idToPageInfo != null) {
   if (idToPageInfo != null) {
     injectedPages = pages.map((page) => {
     injectedPages = pages.map((page) => {

+ 3 - 4
packages/app/src/components/SearchPage2/SearchPageBase.tsx

@@ -7,8 +7,7 @@ import { useTranslation } from 'react-i18next';
 import { ISelectableAll } from '~/client/interfaces/selectable-all';
 import { ISelectableAll } from '~/client/interfaces/selectable-all';
 import AppContainer from '~/client/services/AppContainer';
 import AppContainer from '~/client/services/AppContainer';
 import { toastSuccess } from '~/client/util/apiNotification';
 import { toastSuccess } from '~/client/util/apiNotification';
-import { IPageWithMeta } from '~/interfaces/page';
-import { IFormattedSearchResult, IPageSearchMeta } from '~/interfaces/search';
+import { IFormattedSearchResult, IPageWithSearchMeta } from '~/interfaces/search';
 import { OnDeletedFunction } from '~/interfaces/ui';
 import { OnDeletedFunction } from '~/interfaces/ui';
 import { useIsGuestUser, useIsSearchServiceConfigured, useIsSearchServiceReachable } from '~/stores/context';
 import { useIsGuestUser, useIsSearchServiceConfigured, useIsSearchServiceReachable } from '~/stores/context';
 import { usePageDeleteModal } from '~/stores/modal';
 import { usePageDeleteModal } from '~/stores/modal';
@@ -31,7 +30,7 @@ export interface IReturnSelectedPageIds {
 type Props = {
 type Props = {
   appContainer: AppContainer,
   appContainer: AppContainer,
 
 
-  pages?: IPageWithMeta<IPageSearchMeta>[],
+  pages?: IPageWithSearchMeta[],
   searchingKeyword?: string,
   searchingKeyword?: string,
 
 
   forceHideMenuItems?: ForceHideMenuItems,
   forceHideMenuItems?: ForceHideMenuItems,
@@ -61,7 +60,7 @@ const SearchPageBaseSubstance: ForwardRefRenderFunction<ISelectableAll & IReturn
 
 
   const [selectedPageIdsByCheckboxes] = useState<Set<string>>(new Set());
   const [selectedPageIdsByCheckboxes] = useState<Set<string>>(new Set());
   // const [allPageIds] = useState<Set<string>>(new Set());
   // const [allPageIds] = useState<Set<string>>(new Set());
-  const [selectedPageWithMeta, setSelectedPageWithMeta] = useState<IPageWithMeta<IPageSearchMeta> | undefined>();
+  const [selectedPageWithMeta, setSelectedPageWithMeta] = useState<IPageWithSearchMeta | undefined>();
 
 
   // publish selectAll()
   // publish selectAll()
   useImperativeHandle(ref, () => ({
   useImperativeHandle(ref, () => ({

+ 6 - 7
packages/app/src/components/SearchTypeahead.tsx

@@ -3,14 +3,13 @@ import React, {
   KeyboardEvent, useCallback, useRef, useState, MouseEvent, useEffect,
   KeyboardEvent, useCallback, useRef, useState, MouseEvent, useEffect,
 } from 'react';
 } from 'react';
 
 
+import { UserPicture, PageListMeta, PagePathLabel } from '@growi/ui';
 import { AsyncTypeahead, Menu, MenuItem } from 'react-bootstrap-typeahead';
 import { AsyncTypeahead, Menu, MenuItem } from 'react-bootstrap-typeahead';
 
 
-import { UserPicture, PageListMeta, PagePathLabel } from '@growi/ui';
 
 
 import { IFocusable } from '~/client/interfaces/focusable';
 import { IFocusable } from '~/client/interfaces/focusable';
 import { TypeaheadProps } from '~/client/interfaces/react-bootstrap-typeahead';
 import { TypeaheadProps } from '~/client/interfaces/react-bootstrap-typeahead';
-import { IPageSearchMeta } from '~/interfaces/search';
-import { IPageWithMeta } from '~/interfaces/page';
+import { IPageWithSearchMeta } from '~/interfaces/search';
 import { useSWRxSearch } from '~/stores/search';
 import { useSWRxSearch } from '~/stores/search';
 
 
 
 
@@ -47,7 +46,7 @@ type TypeaheadInstance = {
   clear: () => void,
   clear: () => void,
   focus: () => void,
   focus: () => void,
   toggleMenu: () => void,
   toggleMenu: () => void,
-  state: { selected: IPageWithMeta<IPageSearchMeta>[] }
+  state: { selected: IPageWithSearchMeta[] }
 }
 }
 
 
 const SearchTypeahead: ForwardRefRenderFunction<IFocusable, Props> = (props: Props, ref) => {
 const SearchTypeahead: ForwardRefRenderFunction<IFocusable, Props> = (props: Props, ref) => {
@@ -130,7 +129,7 @@ const SearchTypeahead: ForwardRefRenderFunction<IFocusable, Props> = (props: Pro
   const DELAY_FOR_SUBMISSION = 100;
   const DELAY_FOR_SUBMISSION = 100;
   const timeoutIdRef = useRef<NodeJS.Timeout>();
   const timeoutIdRef = useRef<NodeJS.Timeout>();
 
 
-  const changeHandler = useCallback((selectedItems: IPageWithMeta<IPageSearchMeta>[]) => {
+  const changeHandler = useCallback((selectedItems: IPageWithSearchMeta[]) => {
     // cancel schedule to submit
     // cancel schedule to submit
     if (timeoutIdRef.current != null) {
     if (timeoutIdRef.current != null) {
       clearTimeout(timeoutIdRef.current);
       clearTimeout(timeoutIdRef.current);
@@ -163,11 +162,11 @@ const SearchTypeahead: ForwardRefRenderFunction<IFocusable, Props> = (props: Pro
     }
     }
   }, [onSearchError, searchError]);
   }, [onSearchError, searchError]);
 
 
-  const labelKey = useCallback((option?: IPageWithMeta<IPageSearchMeta>) => {
+  const labelKey = useCallback((option?: IPageWithSearchMeta) => {
     return option?.data.path ?? '';
     return option?.data.path ?? '';
   }, []);
   }, []);
 
 
-  const renderMenu = useCallback((options: IPageWithMeta<IPageSearchMeta>[], menuProps) => {
+  const renderMenu = useCallback((options: IPageWithSearchMeta[], menuProps) => {
     if (!isForcused) {
     if (!isForcused) {
       return <></>;
       return <></>;
     }
     }

+ 6 - 6
packages/app/src/interfaces/page.ts

@@ -56,11 +56,11 @@ export type IPageInfo = {
 }
 }
 
 
 export type IPageInfoForEntity = IPageInfo & {
 export type IPageInfoForEntity = IPageInfo & {
-  bookmarkCount?: number,
-  sumOfLikers?: number,
-  likerIds?: string[],
-  sumOfSeenUsers?: number,
-  seenUserIds?: string[],
+  bookmarkCount: number,
+  sumOfLikers: number,
+  likerIds: string[],
+  sumOfSeenUsers: number,
+  seenUserIds: string[],
 }
 }
 
 
 export type IPageInfoForOperation = IPageInfoForEntity & {
 export type IPageInfoForOperation = IPageInfoForEntity & {
@@ -113,7 +113,7 @@ export type IDataWithMeta<D = unknown, M = unknown> = {
   meta?: M,
   meta?: M,
 }
 }
 
 
-export type IPageWithMeta<M = IPageInfoAll> = IDataWithMeta<IPageHasId, M>;
+export type IPageWithMeta<M extends IPageInfo = IPageInfo> = IDataWithMeta<IPageHasId, M>;
 
 
 export type IPageToDeleteWithMeta<T = IPageInfoForEntity | unknown> = IDataWithMeta<HasObjectId & (IPage | { path: string, revision: string | null}), T>;
 export type IPageToDeleteWithMeta<T = IPageInfoForEntity | unknown> = IDataWithMeta<HasObjectId & (IPage | { path: string, revision: string | null}), T>;
 export type IPageToRenameWithMeta<T = IPageInfoForEntity | unknown> = IPageToDeleteWithMeta<T>;
 export type IPageToRenameWithMeta<T = IPageInfoForEntity | unknown> = IPageToDeleteWithMeta<T>;

+ 10 - 6
packages/app/src/interfaces/search.ts

@@ -1,4 +1,4 @@
-import { IPageWithMeta } from './page';
+import { IDataWithMeta, IPageHasId } from './page';
 
 
 export type IPageSearchMeta = {
 export type IPageSearchMeta = {
   bookmarkCount?: number,
   bookmarkCount?: number,
@@ -14,10 +14,6 @@ export const isIPageSearchMeta = (meta: any): meta is IPageSearchMeta => {
   return meta != null && 'elasticSearchResult' in meta;
   return meta != null && 'elasticSearchResult' in meta;
 };
 };
 
 
-export type ISearchResult<T > = ISearchResultMeta & {
-  data: T[],
-}
-
 export type ISearchResultMeta = {
 export type ISearchResultMeta = {
   meta: {
   meta: {
     took?: number
     took?: number
@@ -26,7 +22,15 @@ export type ISearchResultMeta = {
   },
   },
 }
 }
 
 
-export type IFormattedSearchResult = ISearchResult<IPageWithMeta<IPageSearchMeta>>;
+export type ISearchResult<T> = ISearchResultMeta & {
+  data: T[],
+}
+
+export type IPageWithSearchMeta = IDataWithMeta<IPageHasId, IPageSearchMeta>;
+
+export type IFormattedSearchResult = ISearchResultMeta & {
+  data: IPageWithSearchMeta[],
+}
 
 
 export const SORT_AXIS = {
 export const SORT_AXIS = {
   RELATION_SCORE: 'relationScore',
   RELATION_SCORE: 'relationScore',

+ 2 - 2
packages/app/src/server/routes/apiv3/page-listing.ts

@@ -2,7 +2,7 @@ import express, { Request, Router } from 'express';
 import { query, oneOf } from 'express-validator';
 import { query, oneOf } from 'express-validator';
 import mongoose from 'mongoose';
 import mongoose from 'mongoose';
 
 
-import { IPageInfoAll, isIPageInfoForEntity, IPageInfoForListing } from '~/interfaces/page';
+import { isIPageInfoForEntity, IPageInfoForListing, IPageInfo } from '~/interfaces/page';
 import { IUserHasId } from '~/interfaces/user';
 import { IUserHasId } from '~/interfaces/user';
 import loggerFactory from '~/utils/logger';
 import loggerFactory from '~/utils/logger';
 
 
@@ -127,7 +127,7 @@ export default (crowi: Crowi): Router => {
         bookmarkCountMap = await Bookmark.getPageIdToCountMap(foundIds) as Record<string, number>;
         bookmarkCountMap = await Bookmark.getPageIdToCountMap(foundIds) as Record<string, number>;
       }
       }
 
 
-      const idToPageInfoMap: Record<string, IPageInfoAll> = {};
+      const idToPageInfoMap: Record<string, IPageInfo | IPageInfoForListing> = {};
 
 
       const isGuestUser = req.user == null;
       const isGuestUser = req.user == null;
       for (const page of pages) {
       for (const page of pages) {

+ 4 - 2
packages/app/src/server/service/page.ts

@@ -10,7 +10,7 @@ import { Ref } from '~/interfaces/common';
 import { V5ConversionErrCode } from '~/interfaces/errors/v5-conversion-error';
 import { V5ConversionErrCode } from '~/interfaces/errors/v5-conversion-error';
 import { HasObjectId } from '~/interfaces/has-object-id';
 import { HasObjectId } from '~/interfaces/has-object-id';
 import {
 import {
-  IPage, IPageInfo, IPageInfoForEntity, IPageWithMeta,
+  IPage, IPageInfo, IPageInfoAll, IPageInfoForEntity, IPageWithMeta,
 } from '~/interfaces/page';
 } from '~/interfaces/page';
 import {
 import {
   PageDeleteConfigValue, IPageDeleteConfigValueToProcessValidation,
   PageDeleteConfigValue, IPageDeleteConfigValueToProcessValidation,
@@ -216,7 +216,9 @@ class PageService {
   }
   }
 
 
   // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
   // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
-  async findPageAndMetaDataByViewer(pageId: string, path: string, user: IUserHasId, includeEmpty = false, isSharedPage = false): Promise<IPageWithMeta|null> {
+  async findPageAndMetaDataByViewer(
+      pageId: string, path: string, user: IUserHasId, includeEmpty = false, isSharedPage = false,
+  ): Promise<IPageWithMeta<IPageInfoAll>|null> {
 
 
     const Page = this.crowi.model('Page');
     const Page = this.crowi.model('Page');
 
 

+ 19 - 19
packages/app/src/server/service/search.ts

@@ -1,24 +1,24 @@
-import xss from 'xss';
 import mongoose from 'mongoose';
 import mongoose from 'mongoose';
+import xss from 'xss';
 
 
 import { SearchDelegatorName } from '~/interfaces/named-query';
 import { SearchDelegatorName } from '~/interfaces/named-query';
-import { IPageWithMeta } from '~/interfaces/page';
-import { IFormattedSearchResult, IPageSearchMeta, ISearchResult } from '~/interfaces/search';
+import { IPageHasId } from '~/interfaces/page';
+import { IFormattedSearchResult, IPageWithSearchMeta, ISearchResult } from '~/interfaces/search';
 import loggerFactory from '~/utils/logger';
 import loggerFactory from '~/utils/logger';
 
 
-import NamedQuery from '../models/named-query';
+import { ObjectIdLike } from '../interfaces/mongoose-utils';
 import {
 import {
   SearchDelegator, SearchQueryParser, SearchResolver, ParsedQuery, SearchableData, QueryTerms,
   SearchDelegator, SearchQueryParser, SearchResolver, ParsedQuery, SearchableData, QueryTerms,
 } from '../interfaces/search';
 } from '../interfaces/search';
-import ElasticsearchDelegator from './search-delegator/elasticsearch';
-import PrivateLegacyPagesDelegator from './search-delegator/private-legacy-pages';
-
+import NamedQuery from '../models/named-query';
 import { PageModel } from '../models/page';
 import { PageModel } from '../models/page';
 import { serializeUserSecurely } from '../models/serializers/user-serializer';
 import { serializeUserSecurely } from '../models/serializers/user-serializer';
-
-import { ObjectIdLike } from '../interfaces/mongoose-utils';
 import { SearchError } from '../models/vo/search-error';
 import { SearchError } from '../models/vo/search-error';
 
 
+import ElasticsearchDelegator from './search-delegator/elasticsearch';
+import PrivateLegacyPagesDelegator from './search-delegator/private-legacy-pages';
+
+
 // eslint-disable-next-line no-unused-vars
 // eslint-disable-next-line no-unused-vars
 const logger = loggerFactory('growi:service:search');
 const logger = loggerFactory('growi:service:search');
 
 
@@ -71,17 +71,17 @@ const findPageListByIds = async(pageIds: ObjectIdLike[], crowi: any) => {
 
 
 class SearchService implements SearchQueryParser, SearchResolver {
 class SearchService implements SearchQueryParser, SearchResolver {
 
 
-  crowi!: any
+  crowi!: any;
 
 
-  configManager!: any
+  configManager!: any;
 
 
-  isErrorOccuredOnHealthcheck: boolean | null
+  isErrorOccuredOnHealthcheck: boolean | null;
 
 
-  isErrorOccuredOnSearching: boolean | null
+  isErrorOccuredOnSearching: boolean | null;
 
 
-  fullTextSearchDelegator: any & ElasticsearchDelegator
+  fullTextSearchDelegator: any & ElasticsearchDelegator;
 
 
-  nqDelegators: {[key in SearchDelegatorName]: SearchDelegator}
+  nqDelegators: {[key in SearchDelegatorName]: SearchDelegator};
 
 
   constructor(crowi) {
   constructor(crowi) {
     this.crowi = crowi;
     this.crowi = crowi;
@@ -400,9 +400,9 @@ class SearchService implements SearchQueryParser, SearchResolver {
    */
    */
   async formatSearchResult(searchResult: ISearchResult<any>, delegatorName: SearchDelegatorName, user, userGroups): Promise<IFormattedSearchResult> {
   async formatSearchResult(searchResult: ISearchResult<any>, delegatorName: SearchDelegatorName, user, userGroups): Promise<IFormattedSearchResult> {
     if (!this.checkIsFormattable(searchResult, delegatorName)) {
     if (!this.checkIsFormattable(searchResult, delegatorName)) {
-      const data: IPageWithMeta<IPageSearchMeta>[] = searchResult.data.map((page) => {
+      const data: IPageWithSearchMeta[] = searchResult.data.map((page) => {
         return {
         return {
-          data: page,
+          data: page as IPageHasId,
         };
         };
       });
       });
 
 
@@ -419,7 +419,7 @@ class SearchService implements SearchQueryParser, SearchResolver {
     const result = {} as IFormattedSearchResult;
     const result = {} as IFormattedSearchResult;
 
 
     // get page data
     // get page data
-    const pageIds = searchResult.data.map((page) => { return page._id });
+    const pageIds: string[] = searchResult.data.map((page) => { return page._id });
 
 
     const findPageResult = await findPageListByIds(pageIds, this.crowi);
     const findPageResult = await findPageListByIds(pageIds, this.crowi);
 
 
@@ -427,7 +427,7 @@ class SearchService implements SearchQueryParser, SearchResolver {
     result.meta = searchResult.meta;
     result.meta = searchResult.meta;
 
 
     // set search result page data
     // set search result page data
-    const pages: (IPageWithMeta<IPageSearchMeta> | null)[] = searchResult.data.map((data) => {
+    const pages: (IPageWithSearchMeta | null)[] = searchResult.data.map((data) => {
       const pageData = findPageResult.pages.find((pageData) => {
       const pageData = findPageResult.pages.find((pageData) => {
         return pageData.id === data._id;
         return pageData.id === data._id;
       });
       });