Yuki Takei 7 месяцев назад
Родитель
Сommit
636208c461
1 измененных файлов с 80 добавлено и 80 удалено
  1. 80 80
      apps/app/src/pages/[[...path]]/page-data-props.ts

+ 80 - 80
apps/app/src/pages/[[...path]]/page-data-props.ts

@@ -1,24 +1,64 @@
+import type { IPage, IUser } from '@growi/core/dist/interfaces';
+import { isPermalink as _isPermalink, isCreatablePage, isTopPage } from '@growi/core/dist/utils/page-path-utils';
+import { removeHeadingSlash } from '@growi/core/dist/utils/path-utils';
+import type { model } from 'mongoose';
 import type { GetServerSidePropsContext, GetServerSidePropsResult } from 'next';
 import type { GetServerSidePropsContext, GetServerSidePropsResult } from 'next';
 
 
 import type { CrowiRequest } from '~/interfaces/crowi-request';
 import type { CrowiRequest } from '~/interfaces/crowi-request';
 import type { PageModel } from '~/server/models/page';
 import type { PageModel } from '~/server/models/page';
-import type { PageRedirectModel } from '~/server/models/page-redirect';
+import type { IPageRedirect, PageRedirectModel } from '~/server/models/page-redirect';
 
 
 import type { InitialProps, SameRouteEachProps } from './types';
 import type { InitialProps, SameRouteEachProps } from './types';
 
 
+// Utility to resolve path, redirect, and identical path page check
+type PathResolutionResult = {
+  resolvedPathname: string;
+  isIdenticalPathPage: boolean;
+  redirectFrom?: string;
+};
+
+let mongooseModel: typeof model;
+let Page: PageModel;
+let PageRedirect: PageRedirectModel;
+
+async function resolvePathAndCheckIdentical(
+    path: string,
+    user: IUser | undefined,
+): Promise<PathResolutionResult> {
+  if (mongooseModel == null) {
+    mongooseModel = (await import('mongoose')).model;
+  }
+  if (Page == null) {
+    Page = mongooseModel<IPage, PageModel>('Page');
+  }
+  if (PageRedirect == null) {
+    PageRedirect = mongooseModel<IPageRedirect, PageRedirectModel>('PageRedirect');
+  }
+
+  const isPermalink = _isPermalink(path);
+  let resolvedPathname = path;
+  let redirectFrom: string | undefined;
+  let isIdenticalPathPage = false;
+
+  if (!isPermalink) {
+    const chains = await PageRedirect.retrievePageRedirectEndpoints(path);
+    if (chains != null) {
+      resolvedPathname = chains.end.toPath;
+      redirectFrom = chains.start.fromPath;
+    }
+    const multiplePagesCount = await Page.countByPathAndViewer(resolvedPathname, user, null, true);
+    isIdenticalPathPage = multiplePagesCount > 1;
+  }
+  return { resolvedPathname, isIdenticalPathPage, redirectFrom };
+}
+
 // Page data retrieval for initial load - returns GetServerSidePropsResult
 // Page data retrieval for initial load - returns GetServerSidePropsResult
 export async function getPageDataForInitial(
 export async function getPageDataForInitial(
     context: GetServerSidePropsContext,
     context: GetServerSidePropsContext,
 ): Promise<GetServerSidePropsResult<
 ): Promise<GetServerSidePropsResult<
-    Pick<InitialProps, 'pageWithMeta' | 'isNotFound' | 'isNotCreatable' | 'isForbidden' | 'skipSSR'> &
-    Pick<SameRouteEachProps, 'currentPathname' | 'isIdenticalPathPage'>
-  >> {
-  const { pagePathUtils, pathUtils } = await import('@growi/core/dist/utils');
-  const { model: mongooseModel } = await import('mongoose');
-
-  const { isPermalink: _isPermalink, isCreatablePage } = pagePathUtils;
-  const { removeHeadingSlash } = pathUtils;
-
+  Pick<InitialProps, 'pageWithMeta' | 'isNotFound' | 'isNotCreatable' | 'isForbidden' | 'skipSSR'> &
+  Pick<SameRouteEachProps, 'currentPathname' | 'isIdenticalPathPage'>
+>> {
   const req: CrowiRequest = context.req as CrowiRequest;
   const req: CrowiRequest = context.req as CrowiRequest;
   const { crowi, user } = req;
   const { crowi, user } = req;
   const { revisionId } = req.query;
   const { revisionId } = req.query;
@@ -29,44 +69,29 @@ export async function getPageDataForInitial(
   let pathFromUrl = `/${pathFromQuery.join('/')}`;
   let pathFromUrl = `/${pathFromQuery.join('/')}`;
   pathFromUrl = pathFromUrl === '//' ? '/' : pathFromUrl;
   pathFromUrl = pathFromUrl === '//' ? '/' : pathFromUrl;
 
 
-  const Page = crowi.model('Page') as PageModel;
-  const PageRedirect = mongooseModel('PageRedirect') as PageRedirectModel;
   const { pageService, configManager } = crowi;
   const { pageService, configManager } = crowi;
 
 
   const pageId = _isPermalink(pathFromUrl) ? removeHeadingSlash(pathFromUrl) : null;
   const pageId = _isPermalink(pathFromUrl) ? removeHeadingSlash(pathFromUrl) : null;
   const isPermalink = _isPermalink(pathFromUrl);
   const isPermalink = _isPermalink(pathFromUrl);
 
 
-  let currentPathname = pathFromUrl;
+  const { resolvedPathname, isIdenticalPathPage } = await resolvePathAndCheckIdentical(pathFromUrl, user);
 
 
-  // Check for redirects and whether the path is identical
-  if (!isPermalink) {
-    const chains = await PageRedirect.retrievePageRedirectEndpoints(pathFromUrl);
-    if (chains != null) {
-      currentPathname = chains.end.toPath;
-    }
-
-    // Check multiple pages hits
-    const multiplePagesCount = await Page.countByPathAndViewer(currentPathname, user, null, true);
-    const isIdenticalPathPage = multiplePagesCount > 1;
-
-    // Early return for identical path pages
-    if (isIdenticalPathPage) {
-      return {
-        props: {
-          currentPathname,
-          isIdenticalPathPage: true,
-          pageWithMeta: null,
-          isNotFound: false,
-          isNotCreatable: true,
-          isForbidden: false,
-          skipSSR: false,
-        },
-      };
-    }
+  if (isIdenticalPathPage) {
+    return {
+      props: {
+        currentPathname: resolvedPathname,
+        isIdenticalPathPage: true,
+        pageWithMeta: null,
+        isNotFound: false,
+        isNotCreatable: true,
+        isForbidden: false,
+        skipSSR: false,
+      },
+    };
   }
   }
 
 
   // Get full page data
   // Get full page data
-  const pageWithMeta = await pageService.findPageAndMetaDataByViewer(pageId, currentPathname, user, true);
+  const pageWithMeta = await pageService.findPageAndMetaDataByViewer(pageId, resolvedPathname, user, true);
   const { data: page, meta } = pageWithMeta ?? {};
   const { data: page, meta } = pageWithMeta ?? {};
 
 
   // Add user to seen users
   // Add user to seen users
@@ -86,13 +111,13 @@ export async function getPageDataForInitial(
     const populatedPage = await page.populateDataToShowRevision(skipSSR);
     const populatedPage = await page.populateDataToShowRevision(skipSSR);
 
 
     // Handle URL conversion
     // Handle URL conversion
-    let finalPathname = currentPathname;
+    let finalPathname = resolvedPathname;
     if (page != null && !page.isEmpty) {
     if (page != null && !page.isEmpty) {
       if (isPermalink) {
       if (isPermalink) {
         finalPathname = page.path;
         finalPathname = page.path;
       }
       }
       else {
       else {
-        const isToppage = pagePathUtils.isTopPage(currentPathname);
+        const isToppage = isTopPage(resolvedPathname);
         if (!isToppage) {
         if (!isToppage) {
           finalPathname = `/${page._id}`;
           finalPathname = `/${page._id}`;
         }
         }
@@ -115,15 +140,15 @@ export async function getPageDataForInitial(
   // Handle non-existent page
   // Handle non-existent page
   const count = isPermalink
   const count = isPermalink
     ? await Page.count({ _id: pageId })
     ? await Page.count({ _id: pageId })
-    : await Page.count({ path: currentPathname });
+    : await Page.count({ path: resolvedPathname });
 
 
   return {
   return {
     props: {
     props: {
-      currentPathname,
+      currentPathname: resolvedPathname,
       isIdenticalPathPage: false,
       isIdenticalPathPage: false,
       pageWithMeta: null,
       pageWithMeta: null,
       isNotFound: true,
       isNotFound: true,
-      isNotCreatable: !isCreatablePage(currentPathname),
+      isNotCreatable: !isCreatablePage(resolvedPathname),
       isForbidden: count > 0,
       isForbidden: count > 0,
       skipSSR: false,
       skipSSR: false,
     },
     },
@@ -134,48 +159,23 @@ export async function getPageDataForInitial(
 export async function getPageDataForSameRoute(
 export async function getPageDataForSameRoute(
     context: GetServerSidePropsContext,
     context: GetServerSidePropsContext,
 ): Promise<GetServerSidePropsResult<Pick<SameRouteEachProps, 'currentPathname' | 'isIdenticalPathPage' | 'redirectFrom'>>> {
 ): Promise<GetServerSidePropsResult<Pick<SameRouteEachProps, 'currentPathname' | 'isIdenticalPathPage' | 'redirectFrom'>>> {
-  const { pagePathUtils, pathUtils } = await import('@growi/core/dist/utils');
-  const { model: mongooseModel } = await import('mongoose');
-
-  const { isPermalink: _isPermalink } = pagePathUtils;
-  const { removeHeadingSlash } = pathUtils;
-
   const req: CrowiRequest = context.req as CrowiRequest;
   const req: CrowiRequest = context.req as CrowiRequest;
-  const { crowi, user } = req;
-
-  const Page = crowi.model('Page') as PageModel;
-  const PageRedirect = mongooseModel('PageRedirect') as PageRedirectModel;
+  const { user } = req;
 
 
   const currentPathname = decodeURIComponent(context.resolvedUrl?.split('?')[0] ?? '/');
   const currentPathname = decodeURIComponent(context.resolvedUrl?.split('?')[0] ?? '/');
   const pageId = _isPermalink(currentPathname) ? removeHeadingSlash(currentPathname) : null;
   const pageId = _isPermalink(currentPathname) ? removeHeadingSlash(currentPathname) : null;
   const isPermalink = _isPermalink(currentPathname);
   const isPermalink = _isPermalink(currentPathname);
 
 
-  // Handle redirects
-  let resolvedPathname = currentPathname;
-  let redirectFrom: string | undefined;
-
-  // Check for redirects and whether the path is identical
-  if (!isPermalink) {
-    const chains = await PageRedirect.retrievePageRedirectEndpoints(currentPathname);
-    if (chains != null) {
-      resolvedPathname = chains.end.toPath;
-      redirectFrom = chains.start.fromPath;
-    }
+  const { resolvedPathname, isIdenticalPathPage, redirectFrom } = await resolvePathAndCheckIdentical(currentPathname, user);
 
 
-    // Check multiple pages hits
-    const multiplePagesCount = await Page.countByPathAndViewer(resolvedPathname, user, null, true);
-    const isIdenticalPathPage = multiplePagesCount > 1;
-
-    // Early return for identical path pages
-    if (isIdenticalPathPage) {
-      return {
-        props: {
-          currentPathname: resolvedPathname,
-          isIdenticalPathPage: true,
-          redirectFrom,
-        },
-      };
-    }
+  if (isIdenticalPathPage) {
+    return {
+      props: {
+        currentPathname: resolvedPathname,
+        isIdenticalPathPage: true,
+        redirectFrom,
+      },
+    };
   }
   }
 
 
   // For same route access, do minimal page lookup
   // For same route access, do minimal page lookup
@@ -189,7 +189,7 @@ export async function getPageDataForSameRoute(
       finalPathname = basicPageInfo.path;
       finalPathname = basicPageInfo.path;
     }
     }
     else {
     else {
-      const isToppage = pagePathUtils.isTopPage(resolvedPathname);
+      const isToppage = isTopPage(resolvedPathname);
       if (!isToppage) {
       if (!isToppage) {
         finalPathname = `/${basicPageInfo._id}`;
         finalPathname = `/${basicPageInfo._id}`;
       }
       }