Procházet zdrojové kódy

improve type safety

Yuki Takei před 1 rokem
rodič
revize
2880fa9012

+ 15 - 8
apps/app/src/server/models/page-tag-relation.ts

@@ -1,5 +1,7 @@
 import type { ITag } from '@growi/core';
-import type { Document, Model, ObjectId } from 'mongoose';
+import type {
+  Document, Model, ObjectId, Types,
+} from 'mongoose';
 import mongoose from 'mongoose';
 import mongoosePaginate from 'mongoose-paginate-v2';
 import uniqueValidator from 'mongoose-unique-validator';
@@ -9,7 +11,7 @@ import type { IPageTagRelation } from '~/interfaces/page-tag-relation';
 import type { ObjectIdLike } from '../interfaces/mongoose-utils';
 import { getOrCreateModel } from '../util/mongoose-utils';
 
-import type { IdToNameMap, IdToNamesMap } from './tag';
+import type { IdToNamesMap } from './tag';
 import Tag from './tag';
 
 
@@ -33,14 +35,18 @@ type CreateTagListWithCountResult = {
 }
 type CreateTagListWithCount = (this: PageTagRelationModel, opts?: CreateTagListWithCountOpts) => Promise<CreateTagListWithCountResult>;
 
+type ListTagNamesByPage = (pageId: Types.ObjectId | string) => Promise<PageTagRelationDocument[]>;
+
+type FindByPageId = (pageId: Types.ObjectId | string, options?: { nullable?: boolean }) => Promise<PageTagRelationDocument[]>;
+
 type GetIdToTagNamesMap = (this: PageTagRelationModel, pageIds: string[]) => Promise<IdToNamesMap>;
 
-type UpdatePageTags = (this: PageTagRelationModel, pageId: string, tags: string[]) => Promise<void>
+type UpdatePageTags = (this: PageTagRelationModel, pageId: Types.ObjectId | string, tags: string[]) => Promise<void>
 
 export interface PageTagRelationModel extends Model<PageTagRelationDocument> {
   createTagListWithCount: CreateTagListWithCount
-  findByPageId(pageId: string, options?: { nullable?: boolean }): Promise<PageTagRelationDocument[]>
-  listTagNamesByPage(pageId: string): Promise<PageTagRelationDocument[]>
+  findByPageId: FindByPageId
+  listTagNamesByPage: ListTagNamesByPage
   getIdToTagNamesMap: GetIdToTagNamesMap
   updatePageTags: UpdatePageTags
 }
@@ -102,17 +108,18 @@ const createTagListWithCount: CreateTagListWithCount = async function(this, opts
 };
 schema.statics.createTagListWithCount = createTagListWithCount;
 
-schema.statics.findByPageId = async function(pageId, options = {}) {
+const findByPageId: FindByPageId = async function(pageId, options = {}) {
   const isAcceptRelatedTagNull = options.nullable || null;
   const relations = await this.find({ relatedPage: pageId }).populate('relatedTag').select('relatedTag');
   return isAcceptRelatedTagNull ? relations : relations.filter((relation) => { return relation.relatedTag !== null });
 };
+schema.statics.findByPageId = findByPageId;
 
-schema.statics.listTagNamesByPage = async function(pageId) {
+const listTagNamesByPage: ListTagNamesByPage = async function(pageId) {
   const relations = await this.findByPageId(pageId);
   return relations.map((relation) => { return relation.relatedTag.name });
 };
-
+schema.statics.listTagNamesByPage = listTagNamesByPage;
 
 const getIdToTagNamesMap: GetIdToTagNamesMap = async function(this, pageIds) {
   /**

+ 4 - 4
apps/app/src/server/models/page.ts

@@ -82,6 +82,7 @@ export type CreateMethod = (path: string, body: string, user, options: IOptionsF
 
 export interface PageModel extends Model<PageDocument> {
   [x: string]: any; // for obsolete static methods
+  createEmptyPage(path: string, parent, descendantCount?: number): Promise<HydratedDocument<PageDocument>>
   findByIdAndViewer(pageId: ObjectIdLike, user, userGroups?, includeEmpty?: boolean): Promise<HydratedDocument<PageDocument> | null>
   findByIdsAndViewer(
     pageIds: ObjectIdLike[], user, userGroups?, includeEmpty?: boolean, includeAnyoneWithTheLink?: boolean,
@@ -570,14 +571,13 @@ export class PageQueryBuilder {
 }
 
 schema.statics.createEmptyPage = async function(
-    path: string, parent: any, descendantCount = 0, // TODO: improve type including IPage at https://redmine.weseek.co.jp/issues/86506
-): Promise<PageDocument & { _id: any }> {
+    path: string, parent: any, descendantCount = 0,
+): Promise<HydratedDocument<PageDocument>> {
   if (parent == null) {
     throw Error('parent must not be null');
   }
 
-  const Page = this;
-  const page = new Page();
+  const page = new this();
   page.path = path;
   page.isEmpty = true;
   page.parent = parent;

+ 3 - 2
apps/app/src/server/routes/apiv3/page/create-page.ts

@@ -8,6 +8,7 @@ import { attachTitleHeader, normalizePath } from '@growi/core/dist/utils/path-ut
 import type { Request, RequestHandler } from 'express';
 import type { ValidationChain } from 'express-validator';
 import { body } from 'express-validator';
+import type { HydratedDocument } from 'mongoose';
 import mongoose from 'mongoose';
 
 import { SupportedAction, SupportedTargetModel } from '~/interfaces/activity';
@@ -158,7 +159,7 @@ export const createPageHandlersFactory: CreatePageHandlersFactory = (crowi) => {
     return PageTagRelation.listTagNamesByPage(createdPage.id);
   }
 
-  async function postAction(req: CreatePageRequest, res: ApiV3Response, createdPage: PageDocument) {
+  async function postAction(req: CreatePageRequest, res: ApiV3Response, createdPage: HydratedDocument<PageDocument>) {
     // persist activity
     const parameters = {
       targetModel: SupportedTargetModel.MODEL_PAGE,
@@ -238,7 +239,7 @@ export const createPageHandlersFactory: CreatePageHandlersFactory = (crowi) => {
 
       const { body, tags } = await determineBodyAndTags(pathToCreate, bodyByParam, tagsByParam);
 
-      let createdPage;
+      let createdPage: HydratedDocument<PageDocument>;
       try {
         const {
           grant, grantUserGroupIds, onlyInheritUserRelatedGrantedGroups, overwriteScopesOfDescendants, wip, origin,

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

@@ -29,7 +29,7 @@ export interface IOpenaiService {
   createVectorStoreFile(pages: PageDocument[]): Promise<void>;
   deleteVectorStoreFile(pageId: Types.ObjectId): Promise<void>;
   rebuildVectorStoreAll(): Promise<void>;
-  rebuildVectorStore(page: PageDocument): Promise<void>;
+  rebuildVectorStore(page: HydratedDocument<PageDocument>): Promise<void>;
 }
 class OpenaiService implements IOpenaiService {
 
@@ -143,11 +143,9 @@ class OpenaiService implements IOpenaiService {
       .pipe(createVectorStoreFileStream);
   }
 
-  async rebuildVectorStore(page: PageDocument) {
-    if (page._id != null) {
-      await this.deleteVectorStoreFile(page._id);
-      await this.createVectorStoreFile([page]);
-    }
+  async rebuildVectorStore(page: HydratedDocument<PageDocument>) {
+    await this.deleteVectorStoreFile(page._id);
+    await this.createVectorStoreFile([page]);
   }
 
 }

+ 1 - 1
apps/app/src/server/service/page/index.ts

@@ -1165,7 +1165,7 @@ class PageService implements IPageService {
       grant,
       grantUserGroupIds: grantedGroupIds,
     };
-    let duplicatedTarget;
+    let duplicatedTarget: HydratedDocument<PageDocument>;
     if (page.isEmpty) {
       const parent = await this.getParentAndFillAncestorsByUser(user, newPagePath);
       duplicatedTarget = await Page.createEmptyPage(newPagePath, parent);