Yuki Takei 6 месяцев назад
Родитель
Сommit
d66d1ae0eb
71 измененных файлов с 120 добавлено и 67 удалено
  1. 0 1
      apps/app/bin/openapi/generate-operation-ids/cli.spec.ts
  2. 0 1
      apps/app/bin/print-memory-consumption.ts
  3. 0 1
      apps/app/playwright.config.ts
  4. 3 3
      apps/app/src/features/external-user-group/client/components/ExternalUserGroup/ExternalUserGroupManagement.tsx
  5. 0 1
      apps/app/src/features/external-user-group/client/components/ExternalUserGroup/KeycloakGroupSyncSettingsForm.tsx
  6. 0 1
      apps/app/src/features/external-user-group/client/components/ExternalUserGroup/LdapGroupManagement.tsx
  7. 0 1
      apps/app/src/features/external-user-group/client/components/ExternalUserGroup/LdapGroupSyncSettingsForm.tsx
  8. 0 1
      apps/app/src/features/external-user-group/client/components/ExternalUserGroup/SyncExecution.tsx
  9. 0 1
      apps/app/src/features/external-user-group/server/models/external-user-group-relation.ts
  10. 1 0
      apps/app/src/features/external-user-group/server/routes/apiv3/external-user-group-relation.ts
  11. 0 1
      apps/app/src/features/external-user-group/server/service/keycloak-user-group-sync.ts
  12. 0 1
      apps/app/src/features/external-user-group/server/service/ldap-user-group-sync.ts
  13. 1 1
      apps/app/src/features/mermaid/components/MermaidViewer.tsx
  14. 0 1
      apps/app/src/features/opentelemetry/server/anonymization/handlers/index.ts
  15. 0 1
      apps/app/src/features/opentelemetry/server/anonymization/handlers/page-access-handler.spec.ts
  16. 0 1
      apps/app/src/features/opentelemetry/server/anonymization/handlers/page-api-handler.spec.ts
  17. 0 1
      apps/app/src/features/opentelemetry/server/anonymization/handlers/page-listing-api-handler.spec.ts
  18. 0 1
      apps/app/src/features/opentelemetry/server/anonymization/handlers/search-api-handler.spec.ts
  19. 0 1
      apps/app/src/features/opentelemetry/server/custom-resource-attributes/os-resource-attributes.ts
  20. 3 1
      apps/app/src/features/page-bulk-export/client/components/PageBulkExportSelectModal.tsx
  21. 0 1
      apps/app/src/features/page-bulk-export/server/service/check-page-bulk-export-job-in-progress-cron.ts
  22. 0 1
      apps/app/src/features/page-bulk-export/server/service/page-bulk-export-job-clean-up-cron.integ.ts
  23. 0 1
      apps/app/src/features/page-bulk-export/server/service/page-bulk-export-job-clean-up-cron.ts
  24. 0 1
      apps/app/src/features/page-bulk-export/server/service/page-bulk-export-job-cron/index.ts
  25. 0 1
      apps/app/src/features/page-bulk-export/server/service/page-bulk-export-job-cron/request-pdf-converter.ts
  26. 1 0
      apps/app/src/features/page-bulk-export/server/service/page-bulk-export-job-cron/steps/compress-and-upload.ts
  27. 1 0
      apps/app/src/features/page-bulk-export/server/service/page-bulk-export-job-cron/steps/create-page-snapshots-async.ts
  28. 1 0
      apps/app/src/features/page-bulk-export/server/service/page-bulk-export-job-cron/steps/export-pages-to-fs-async.ts
  29. 1 1
      apps/app/src/features/search/client/components/SearchHelp.tsx
  30. 1 2
      apps/app/src/features/search/client/components/SearchMethodMenuItem.tsx
  31. 5 1
      apps/app/src/features/search/client/components/SearchPage/SearchModalTriggerinput.tsx
  32. 1 2
      apps/app/src/features/search/client/components/SearchResultMenuItem.tsx
  33. 1 0
      apps/app/src/features/templates/server/routes/apiv3/index.ts
  34. 0 1
      apps/app/src/interfaces/renderer-options.ts
  35. 1 1
      apps/app/src/interfaces/ui.ts
  36. 1 0
      apps/app/src/states/context.ts
  37. 2 0
      apps/app/src/states/global/hydrate.ts
  38. 2 1
      apps/app/src/states/page/hooks.ts
  39. 2 2
      apps/app/src/states/page/use-fetch-current-page.spec.tsx
  40. 2 1
      apps/app/src/states/page/use-fetch-current-page.ts
  41. 2 1
      apps/app/src/states/page/use-set-remote-latest-page-data.ts
  42. 1 1
      apps/app/src/states/server-configurations/server-configurations.ts
  43. 1 1
      apps/app/src/states/socket-io/socket-io.ts
  44. 53 0
      apps/app/src/states/system/socket.ts
  45. 1 1
      apps/app/src/states/ui/device.ts
  46. 1 0
      apps/app/src/states/ui/editor/current-indent-size.ts
  47. 3 1
      apps/app/src/states/ui/editor/editor-mode.ts
  48. 1 0
      apps/app/src/states/ui/editor/selected-grant.ts
  49. 1 1
      apps/app/src/states/ui/modal/delete-attachment.ts
  50. 1 1
      apps/app/src/states/ui/modal/delete-bookmark-folder.ts
  51. 1 1
      apps/app/src/states/ui/modal/empty-trash.ts
  52. 1 1
      apps/app/src/states/ui/modal/page-accessories.ts
  53. 1 1
      apps/app/src/states/ui/modal/page-create.ts
  54. 1 1
      apps/app/src/states/ui/modal/page-delete.ts
  55. 1 1
      apps/app/src/states/ui/modal/page-duplicate.ts
  56. 1 1
      apps/app/src/states/ui/modal/page-presentation.ts
  57. 1 1
      apps/app/src/states/ui/modal/page-rename.ts
  58. 1 1
      apps/app/src/states/ui/modal/page-select.ts
  59. 1 1
      apps/app/src/states/ui/modal/page-status-alert.ts
  60. 1 1
      apps/app/src/states/ui/modal/put-back-page.ts
  61. 1 1
      apps/app/src/states/ui/modal/shortcuts.ts
  62. 1 1
      apps/app/src/states/ui/modal/tag-edit.ts
  63. 1 1
      apps/app/src/states/ui/modal/update-user-group-confirm.ts
  64. 1 0
      apps/app/src/states/ui/page-abilities.ts
  65. 1 1
      apps/app/src/states/ui/page-tree-desc-count-map.ts
  66. 2 1
      apps/app/src/states/ui/sidebar/sidebar.ts
  67. 2 2
      apps/app/src/states/ui/toc.ts
  68. 2 2
      apps/app/src/states/ui/unsaved-warning.ts
  69. 1 0
      apps/app/src/utils/axios/create-custom-axios.ts
  70. 3 2
      apps/app/src/utils/logger/index.ts
  71. 0 1
      apps/app/src/utils/page-delete-config.test.ts

+ 0 - 1
apps/app/bin/openapi/generate-operation-ids/cli.spec.ts

@@ -1,5 +1,4 @@
 import { writeFileSync } from 'node:fs';
-
 import { beforeEach, describe, expect, it, vi } from 'vitest';
 
 import { generateOperationIds } from './generate-operation-ids';

+ 0 - 1
apps/app/bin/print-memory-consumption.ts

@@ -12,7 +12,6 @@
  */
 
 import { get } from 'node:http';
-
 import WebSocket from 'ws';
 
 interface MemoryInfo {

+ 0 - 1
apps/app/playwright.config.ts

@@ -1,6 +1,5 @@
 import fs from 'node:fs';
 import path from 'node:path';
-
 import { defineConfig, devices, type Project } from '@playwright/test';
 
 const authFile = path.resolve(__dirname, './playwright/.auth/admin.json');

+ 3 - 3
apps/app/src/features/external-user-group/client/components/ExternalUserGroup/ExternalUserGroupManagement.tsx

@@ -1,10 +1,11 @@
+import type { FC } from 'react';
+import { useCallback, useMemo, useState } from 'react';
 import type { IGrantedGroup } from '@growi/core';
 import { GroupType, getIdForRef } from '@growi/core';
 import { useAtomValue } from 'jotai';
-import type { FC } from 'react';
-import { useCallback, useMemo, useState } from 'react';
 import { useTranslation } from 'react-i18next';
 import { TabContent, TabPane } from 'reactstrap';
+
 import { UserGroupDeleteModal } from '~/client/components/Admin/UserGroup/UserGroupDeleteModal';
 import { UserGroupModal } from '~/client/components/Admin/UserGroup/UserGroupModal';
 import { UserGroupTable } from '~/client/components/Admin/UserGroup/UserGroupTable';
@@ -21,7 +22,6 @@ import {
   useSWRxExternalUserGroupList,
   useSWRxExternalUserGroupRelationList,
 } from '../../stores/external-user-group';
-
 import { KeycloakGroupManagement } from './KeycloakGroupManagement';
 import { LdapGroupManagement } from './LdapGroupManagement';
 

+ 0 - 1
apps/app/src/features/external-user-group/client/components/ExternalUserGroup/KeycloakGroupSyncSettingsForm.tsx

@@ -1,6 +1,5 @@
 import type { FC } from 'react';
 import { useCallback, useEffect, useState } from 'react';
-
 import { useTranslation } from 'react-i18next';
 
 import { apiv3Put } from '~/client/util/apiv3-client';

+ 0 - 1
apps/app/src/features/external-user-group/client/components/ExternalUserGroup/LdapGroupManagement.tsx

@@ -1,6 +1,5 @@
 import type { FC } from 'react';
 import { type JSX, useCallback, useEffect, useState } from 'react';
-
 import { useTranslation } from 'react-i18next';
 
 import { apiv3Get, apiv3Put } from '~/client/util/apiv3-client';

+ 0 - 1
apps/app/src/features/external-user-group/client/components/ExternalUserGroup/LdapGroupSyncSettingsForm.tsx

@@ -1,6 +1,5 @@
 import type { FC } from 'react';
 import { useCallback, useEffect, useState } from 'react';
-
 import { useTranslation } from 'react-i18next';
 
 import { apiv3Put } from '~/client/util/apiv3-client';

+ 0 - 1
apps/app/src/features/external-user-group/client/components/ExternalUserGroup/SyncExecution.tsx

@@ -1,6 +1,5 @@
 import type { FC, JSX } from 'react';
 import { useCallback, useEffect, useState } from 'react';
-
 import { useTranslation } from 'react-i18next';
 import { Modal, ModalBody, ModalHeader } from 'reactstrap';
 

+ 0 - 1
apps/app/src/features/external-user-group/server/models/external-user-group-relation.ts

@@ -6,7 +6,6 @@ import UserGroupRelation from '~/server/models/user-group-relation';
 
 import { getOrCreateModel } from '../../../../server/util/mongoose-utils';
 import type { IExternalUserGroupRelation } from '../../interfaces/external-user-group';
-
 import type { ExternalUserGroupDocument } from './external-user-group';
 
 export interface ExternalUserGroupRelationDocument

+ 1 - 0
apps/app/src/features/external-user-group/server/routes/apiv3/external-user-group-relation.ts

@@ -1,6 +1,7 @@
 import { SCOPE } from '@growi/core/dist/interfaces';
 import { ErrorV3 } from '@growi/core/dist/models';
 import type { Request, Router } from 'express';
+
 import type { IExternalUserGroupRelationHasId } from '~/features/external-user-group/interfaces/external-user-group';
 import ExternalUserGroupRelation from '~/features/external-user-group/server/models/external-user-group-relation';
 import type Crowi from '~/server/crowi';

+ 0 - 1
apps/app/src/features/external-user-group/server/service/keycloak-user-group-sync.ts

@@ -12,7 +12,6 @@ import type {
   ExternalUserInfo,
 } from '../../interfaces/external-user-group';
 import { ExternalGroupProviderType } from '../../interfaces/external-user-group';
-
 import ExternalUserGroupSyncService from './external-user-group-sync';
 
 const logger = loggerFactory('growi:service:keycloak-user-group-sync-service');

+ 0 - 1
apps/app/src/features/external-user-group/server/service/ldap-user-group-sync.ts

@@ -14,7 +14,6 @@ import {
   ExternalGroupProviderType,
   LdapGroupMembershipAttributeType,
 } from '../../interfaces/external-user-group';
-
 import ExternalUserGroupSyncService from './external-user-group-sync';
 
 const logger = loggerFactory('growi:service:ldap-user-group-sync-service');

+ 1 - 1
apps/app/src/features/mermaid/components/MermaidViewer.tsx

@@ -1,5 +1,5 @@
-import mermaid from 'mermaid';
 import React, { type JSX, useEffect, useRef } from 'react';
+import mermaid from 'mermaid';
 import { v7 as uuidV7 } from 'uuid';
 
 import { useNextThemes } from '~/stores-universal/use-next-themes';

+ 0 - 1
apps/app/src/features/opentelemetry/server/anonymization/handlers/index.ts

@@ -1,5 +1,4 @@
 import type { AnonymizationModule } from '../interfaces/anonymization-module';
-
 import { pageAccessModule } from './page-access-handler';
 import { pageApiModule } from './page-api-handler';
 import { pageListingApiModule } from './page-listing-api-handler';

+ 0 - 1
apps/app/src/features/opentelemetry/server/anonymization/handlers/page-access-handler.spec.ts

@@ -1,5 +1,4 @@
 import type { IncomingMessage } from 'node:http';
-
 import { describe, expect, it } from 'vitest';
 
 import { pageAccessModule } from './page-access-handler';

+ 0 - 1
apps/app/src/features/opentelemetry/server/anonymization/handlers/page-api-handler.spec.ts

@@ -1,5 +1,4 @@
 import type { IncomingMessage } from 'node:http';
-
 import { beforeEach, describe, expect, it } from 'vitest';
 
 import { pageApiModule } from './page-api-handler';

+ 0 - 1
apps/app/src/features/opentelemetry/server/anonymization/handlers/page-listing-api-handler.spec.ts

@@ -1,5 +1,4 @@
 import type { IncomingMessage } from 'node:http';
-
 import { beforeEach, describe, expect, it } from 'vitest';
 
 import { pageListingApiModule } from './page-listing-api-handler';

+ 0 - 1
apps/app/src/features/opentelemetry/server/anonymization/handlers/search-api-handler.spec.ts

@@ -1,5 +1,4 @@
 import type { IncomingMessage } from 'node:http';
-
 import { beforeEach, describe, expect, it } from 'vitest';
 
 import { searchApiModule } from './search-api-handler';

+ 0 - 1
apps/app/src/features/opentelemetry/server/custom-resource-attributes/os-resource-attributes.ts

@@ -1,5 +1,4 @@
 import * as os from 'node:os';
-
 import type { Attributes } from '@opentelemetry/api';
 
 import loggerFactory from '~/utils/logger';

+ 3 - 1
apps/app/src/features/page-bulk-export/client/components/PageBulkExportSelectModal.tsx

@@ -1,12 +1,14 @@
+import { type JSX, useCallback, useMemo, useState } from 'react';
 import { format } from 'date-fns/format';
 import { useAtomValue } from 'jotai';
 import { useTranslation } from 'next-i18next';
-import { type JSX, useCallback, useMemo, useState } from 'react';
 import { Modal, ModalBody, ModalHeader } from 'reactstrap';
+
 import { apiv3Post } from '~/client/util/apiv3-client';
 import { toastError, toastSuccess } from '~/client/util/toastr';
 import { useCurrentPagePath } from '~/states/page';
 import { isPdfBulkExportEnabledAtom } from '~/states/server-configurations';
+
 import { PageBulkExportFormat } from '../../interfaces/page-bulk-export';
 import {
   usePageBulkExportSelectModalActions,

+ 0 - 1
apps/app/src/features/page-bulk-export/server/service/check-page-bulk-export-job-in-progress-cron.ts

@@ -4,7 +4,6 @@ import loggerFactory from '~/utils/logger';
 
 import { PageBulkExportJobInProgressStatus } from '../../interfaces/page-bulk-export';
 import PageBulkExportJob from '../models/page-bulk-export-job';
-
 import { pageBulkExportJobCronService } from './page-bulk-export-job-cron';
 
 const logger = loggerFactory(

+ 0 - 1
apps/app/src/features/page-bulk-export/server/service/page-bulk-export-job-clean-up-cron.integ.ts

@@ -8,7 +8,6 @@ import {
   PageBulkExportJobStatus,
 } from '../../interfaces/page-bulk-export';
 import PageBulkExportJob from '../models/page-bulk-export-job';
-
 import instanciatePageBulkExportJobCleanUpCronService, {
   pageBulkExportJobCleanUpCronService,
 } from './page-bulk-export-job-clean-up-cron';

+ 0 - 1
apps/app/src/features/page-bulk-export/server/service/page-bulk-export-job-clean-up-cron.ts

@@ -11,7 +11,6 @@ import {
 } from '../../interfaces/page-bulk-export';
 import type { PageBulkExportJobDocument } from '../models/page-bulk-export-job';
 import PageBulkExportJob from '../models/page-bulk-export-job';
-
 import { pageBulkExportJobCronService } from './page-bulk-export-job-cron';
 
 const logger = loggerFactory(

+ 0 - 1
apps/app/src/features/page-bulk-export/server/service/page-bulk-export-job-cron/index.ts

@@ -23,7 +23,6 @@ import {
 import type { PageBulkExportJobDocument } from '../../models/page-bulk-export-job';
 import PageBulkExportJob from '../../models/page-bulk-export-job';
 import PageBulkExportPageSnapshot from '../../models/page-bulk-export-page-snapshot';
-
 import {
   BulkExportJobExpiredError,
   BulkExportJobRestartedError,

+ 0 - 1
apps/app/src/features/page-bulk-export/server/service/page-bulk-export-job-cron/request-pdf-converter.ts

@@ -9,7 +9,6 @@ import { configManager } from '~/server/service/config-manager';
 import { PageBulkExportJobStatus } from '../../../interfaces/page-bulk-export';
 import type { PageBulkExportJobDocument } from '../../models/page-bulk-export-job';
 import PageBulkExportPageSnapshot from '../../models/page-bulk-export-page-snapshot';
-
 import { BulkExportJobExpiredError } from './errors';
 
 /**

+ 1 - 0
apps/app/src/features/page-bulk-export/server/service/page-bulk-export-job-cron/steps/compress-and-upload.ts

@@ -8,6 +8,7 @@ import type { IAttachmentDocument } from '~/server/models/attachment';
 import { Attachment } from '~/server/models/attachment';
 import type { FileUploader } from '~/server/service/file-uploader';
 import loggerFactory from '~/utils/logger';
+
 import type { PageBulkExportJobDocument } from '../../../models/page-bulk-export-job';
 import type { IPageBulkExportJobCronService } from '..';
 

+ 1 - 0
apps/app/src/features/page-bulk-export/server/service/page-bulk-export-job-cron/steps/create-page-snapshots-async.ts

@@ -7,6 +7,7 @@ import mongoose from 'mongoose';
 import { PageBulkExportJobStatus } from '~/features/page-bulk-export/interfaces/page-bulk-export';
 import { SupportedAction } from '~/interfaces/activity';
 import type { PageDocument, PageModel } from '~/server/models/page';
+
 import type { PageBulkExportJobDocument } from '../../../models/page-bulk-export-job';
 import PageBulkExportJob from '../../../models/page-bulk-export-job';
 import PageBulkExportPageSnapshot from '../../../models/page-bulk-export-page-snapshot';

+ 1 - 0
apps/app/src/features/page-bulk-export/server/service/page-bulk-export-job-cron/steps/export-pages-to-fs-async.ts

@@ -16,6 +16,7 @@ import {
   PageBulkExportFormat,
   PageBulkExportJobStatus,
 } from '~/features/page-bulk-export/interfaces/page-bulk-export';
+
 import type { PageBulkExportJobDocument } from '../../../models/page-bulk-export-job';
 import type { PageBulkExportPageSnapshotDocument } from '../../../models/page-bulk-export-page-snapshot';
 import PageBulkExportPageSnapshot from '../../../models/page-bulk-export-page-snapshot';

+ 1 - 1
apps/app/src/features/search/client/components/SearchHelp.tsx

@@ -1,5 +1,5 @@
+import { type JSX, useState } from 'react';
 import { useTranslation } from 'next-i18next';
-import React, { type JSX, useState } from 'react';
 import { Collapse } from 'reactstrap';
 
 export const SearchHelp = (): JSX.Element => {

+ 1 - 2
apps/app/src/features/search/client/components/SearchMethodMenuItem.tsx

@@ -1,11 +1,10 @@
+import type { JSX } from 'react';
 import { DevidedPagePath } from '@growi/core/dist/models';
 import { useTranslation } from 'next-i18next';
-import React, { type JSX } from 'react';
 
 import { useCurrentPagePath } from '~/states/page';
 
 import type { GetItemProps } from '../interfaces/downshift';
-
 import { SearchMenuItem } from './SearchMenuItem';
 
 type Props = {

+ 5 - 1
apps/app/src/features/search/client/components/SearchPage/SearchModalTriggerinput.tsx

@@ -21,7 +21,11 @@ export const SearchModalTriggerinput: React.FC<Props> = (props: Props) => {
       <span className="text-secondary material-symbols-outlined fs-4 me-2">
         search
       </span>
-      <form className="w-100 position-relative" onClick={inputClickHandler}>
+      <form
+        className="w-100 position-relative"
+        onClick={inputClickHandler}
+        onKeyDown={inputClickHandler}
+      >
         <input
           className="form-control"
           type="input"

+ 1 - 2
apps/app/src/features/search/client/components/SearchResultMenuItem.tsx

@@ -1,11 +1,10 @@
+import { type JSX, useCallback } from 'react';
 import { PagePathLabel, UserPicture } from '@growi/ui/dist/components';
-import React, { type JSX, useCallback } from 'react';
 import { useDebounce } from 'usehooks-ts';
 
 import { useSWRxSearch } from '~/stores/search';
 
 import type { GetItemProps } from '../interfaces/downshift';
-
 import { SearchMenuItem } from './SearchMenuItem';
 
 type Props = {

+ 1 - 0
apps/app/src/features/templates/server/routes/apiv3/index.ts

@@ -8,6 +8,7 @@ import {
 } from '@growi/pluginkit/dist/v4/server/index.cjs';
 import express from 'express';
 import { param, query } from 'express-validator';
+
 import { PLUGIN_STORING_PATH } from '~/features/growi-plugin/server/consts';
 import { GrowiPlugin } from '~/features/growi-plugin/server/models';
 import type Crowi from '~/server/crowi';

+ 0 - 1
apps/app/src/interfaces/renderer-options.ts

@@ -1,5 +1,4 @@
 import type { ComponentType } from 'react';
-
 import type {
   Components,
   Options as ReactMarkdownOptions,

+ 1 - 1
apps/app/src/interfaces/ui.ts

@@ -1,5 +1,5 @@
-import type { Nullable } from '@growi/core';
 import type { JSX } from 'react';
+import type { Nullable } from '@growi/core';
 
 import type { IPageForItem } from '~/interfaces/page';
 

+ 1 - 0
apps/app/src/states/context.ts

@@ -1,4 +1,5 @@
 import { atom, useAtomValue, useSetAtom } from 'jotai';
+
 import { currentUserAtomGetter, growiCloudUriAtomGetter } from './global';
 
 /**

+ 2 - 0
apps/app/src/states/global/hydrate.ts

@@ -1,5 +1,7 @@
 import { useHydrateAtoms } from 'jotai/utils';
+
 import type { CommonEachProps, CommonInitialProps } from '~/pages/common-props';
+
 import { _atomsForHydration } from './global';
 
 const {

+ 2 - 1
apps/app/src/states/page/hooks.ts

@@ -1,10 +1,11 @@
+import { useCallback, useMemo } from 'react';
 import {
   isCreatablePage,
   isPermalink,
 } from '@growi/core/dist/utils/page-path-utils';
 import { useAtomValue, useSetAtom } from 'jotai';
 import { useAtomCallback } from 'jotai/utils';
-import { useCallback, useMemo } from 'react';
+
 import { useIsGuestUser, useIsReadOnlyUser } from '../context';
 import { useCurrentPathname } from '../global';
 import {

+ 2 - 2
apps/app/src/states/page/use-fetch-current-page.spec.tsx

@@ -1,3 +1,5 @@
+import type { NextRouter } from 'next/router';
+import { useRouter } from 'next/router';
 import type {
   IPagePopulatedToShowRevision,
   IRevisionHasId,
@@ -10,8 +12,6 @@ import { renderHook, waitFor } from '@testing-library/react';
 // eslint-disable-next-line no-restricted-imports
 import type { AxiosResponse } from 'axios';
 import { createStore, Provider } from 'jotai';
-import type { NextRouter } from 'next/router';
-import { useRouter } from 'next/router';
 import { vi } from 'vitest';
 import { mockDeep } from 'vitest-mock-extended';
 

+ 2 - 1
apps/app/src/states/page/use-fetch-current-page.ts

@@ -1,3 +1,4 @@
+import { useCallback } from 'react';
 import {
   type IPagePopulatedToShowRevision,
   isIPageNotFoundInfo,
@@ -8,10 +9,10 @@ import { isPermalink } from '@growi/core/dist/utils/page-path-utils';
 import { removeHeadingSlash } from '@growi/core/dist/utils/path-utils';
 import { useAtomValue } from 'jotai';
 import { useAtomCallback } from 'jotai/utils';
-import { useCallback } from 'react';
 
 import { apiv3Get } from '~/client/util/apiv3-client';
 import loggerFactory from '~/utils/logger';
+
 import {
   currentPageDataAtom,
   currentPageIdAtom,

+ 2 - 1
apps/app/src/states/page/use-set-remote-latest-page-data.ts

@@ -1,6 +1,7 @@
+import { useCallback } from 'react';
 import type { IUserHasId } from '@growi/core/dist/interfaces';
 import { useSetAtom } from 'jotai/react';
-import { useCallback } from 'react';
+
 import {
   remoteRevisionBodyAtom,
   remoteRevisionIdAtom,

+ 1 - 1
apps/app/src/states/server-configurations/server-configurations.ts

@@ -1,6 +1,6 @@
 import { atom, useAtomValue } from 'jotai';
-import type { SupportedActionType } from '~/interfaces/activity';
 
+import type { SupportedActionType } from '~/interfaces/activity';
 import type { RendererConfig } from '~/interfaces/services/renderer';
 
 /**

+ 1 - 1
apps/app/src/states/socket-io/socket-io.ts

@@ -1,6 +1,6 @@
+import { useCallback, useEffect } from 'react';
 import { GLOBAL_SOCKET_NS } from '@growi/core/dist/swr';
 import { atom, useAtomValue, useSetAtom } from 'jotai';
-import { useCallback, useEffect } from 'react';
 import type { Socket } from 'socket.io-client';
 
 import { SocketEventName } from '~/interfaces/websocket';

+ 53 - 0
apps/app/src/states/system/socket.ts

@@ -0,0 +1,53 @@
+import { useAtomValue } from 'jotai';
+import { atomWithLazy } from 'jotai/utils';
+import type { Socket } from 'socket.io-client';
+import io from 'socket.io-client';
+
+import loggerFactory from '~/utils/logger';
+
+const logger = loggerFactory('growi:cli:states:socket');
+
+const socketFactory = (namespace: string): Socket => {
+  const socket = io(namespace, {
+    transports: ['websocket'],
+  });
+
+  socket.on('connect_error', (error) => {
+    logger.error(namespace, error);
+  });
+  socket.on('error', (error) => {
+    logger.error(namespace, error);
+  });
+
+  return socket;
+};
+
+// Lazy atoms for socket instances (created only when accessed)
+const defaultSocketAtom = atomWithLazy(() => socketFactory('/'));
+const adminSocketAtom = atomWithLazy(() => socketFactory('/admin'));
+
+// Hooks for socket access
+export const useDefaultSocket = (): Socket => {
+  return useAtomValue(defaultSocketAtom);
+};
+
+export const useAdminSocket = (): Socket => {
+  return useAtomValue(adminSocketAtom);
+};
+
+// Generic socket hook (for custom namespaces if needed)
+const socketCacheMap = new Map<
+  string,
+  ReturnType<typeof atomWithLazy<Socket>>
+>();
+
+export const useSocket = (namespace: string): Socket => {
+  if (!socketCacheMap.has(namespace)) {
+    socketCacheMap.set(
+      namespace,
+      atomWithLazy<Socket>(() => socketFactory(namespace)),
+    );
+  }
+  const socketAtom = socketCacheMap.get(namespace)!;
+  return useAtomValue(socketAtom);
+};

+ 1 - 1
apps/app/src/states/ui/device.ts

@@ -1,10 +1,10 @@
+import { useEffect } from 'react';
 import { Breakpoint } from '@growi/ui/dist/interfaces';
 import {
   addBreakpointListener,
   cleanupBreakpointListener,
 } from '@growi/ui/dist/utils';
 import { atom, useAtom } from 'jotai';
-import { useEffect } from 'react';
 
 // Device state atoms
 export const isDeviceLargerThanXlAtom = atom(false);

+ 1 - 0
apps/app/src/states/ui/editor/current-indent-size.ts

@@ -1,4 +1,5 @@
 import { atom, useAtomValue, useSetAtom } from 'jotai';
+
 import { defaultIndentSizeAtom } from '~/states/server-configurations';
 
 // Current indent size state - can be undefined to use default

+ 3 - 1
apps/app/src/states/ui/editor/editor-mode.ts

@@ -1,7 +1,9 @@
+import { useCallback } from 'react';
 import { isServer } from '@growi/core/dist/utils';
 import { atom, useAtom } from 'jotai';
-import { useCallback } from 'react';
+
 import { useIsEditable, usePageNotFound } from '~/states/page';
+
 import { EditorMode, EditorModeHash, type UseEditorModeReturn } from './types';
 import { determineEditorModeByHash } from './utils';
 

+ 1 - 0
apps/app/src/states/ui/editor/selected-grant.ts

@@ -1,5 +1,6 @@
 import { PageGrant } from '@growi/core/dist/interfaces';
 import { atom, useAtom } from 'jotai';
+
 import type { IPageSelectedGrant } from '~/interfaces/page';
 
 /**

+ 1 - 1
apps/app/src/states/ui/modal/delete-attachment.ts

@@ -1,6 +1,6 @@
+import { useCallback } from 'react';
 import type { IAttachmentHasId } from '@growi/core';
 import { atom, useAtomValue, useSetAtom } from 'jotai';
-import { useCallback } from 'react';
 
 type Remove = (body: { attachment_id: string }) => Promise<void>;
 

+ 1 - 1
apps/app/src/states/ui/modal/delete-bookmark-folder.ts

@@ -1,5 +1,5 @@
-import { atom, useAtomValue, useSetAtom } from 'jotai';
 import { useCallback } from 'react';
+import { atom, useAtomValue, useSetAtom } from 'jotai';
 
 import type { BookmarkFolderItems } from '../../../interfaces/bookmark-info';
 import type { onDeletedBookmarkFolderFunction } from '../../../interfaces/ui';

+ 1 - 1
apps/app/src/states/ui/modal/empty-trash.ts

@@ -1,6 +1,6 @@
+import { useCallback } from 'react';
 import type { IPageToDeleteWithMeta } from '@growi/core';
 import { atom, useAtomValue, useSetAtom } from 'jotai';
-import { useCallback } from 'react';
 
 type IEmptyTrashModalOption = {
   onEmptiedTrash?: () => void;

+ 1 - 1
apps/app/src/states/ui/modal/page-accessories.ts

@@ -1,5 +1,5 @@
-import { atom, useAtomValue, useSetAtom } from 'jotai';
 import { useCallback } from 'react';
+import { atom, useAtomValue, useSetAtom } from 'jotai';
 
 // Constants to match the original implementation
 export const PageAccessoriesModalContents = {

+ 1 - 1
apps/app/src/states/ui/modal/page-create.ts

@@ -1,5 +1,5 @@
-import { atom, useAtomValue, useSetAtom } from 'jotai';
 import { useCallback } from 'react';
+import { atom, useAtomValue, useSetAtom } from 'jotai';
 
 // Type definitions
 export type CreateModalStatus = {

+ 1 - 1
apps/app/src/states/ui/modal/page-delete.ts

@@ -1,6 +1,6 @@
+import { useCallback } from 'react';
 import type { IPageToDeleteWithMeta } from '@growi/core';
 import { atom, useAtomValue, useSetAtom } from 'jotai';
-import { useCallback } from 'react';
 
 import type { OnDeletedFunction } from '../../../interfaces/ui';
 

+ 1 - 1
apps/app/src/states/ui/modal/page-duplicate.ts

@@ -1,5 +1,5 @@
-import { atom, useAtomValue, useSetAtom } from 'jotai';
 import { useCallback } from 'react';
+import { atom, useAtomValue, useSetAtom } from 'jotai';
 
 import type { OnDuplicatedFunction } from '../../../interfaces/ui';
 

+ 1 - 1
apps/app/src/states/ui/modal/page-presentation.ts

@@ -1,5 +1,5 @@
-import { atom, useAtomValue, useSetAtom } from 'jotai';
 import { useCallback } from 'react';
+import { atom, useAtomValue, useSetAtom } from 'jotai';
 
 export type PresentationModalStatus = {
   isOpened: boolean;

+ 1 - 1
apps/app/src/states/ui/modal/page-rename.ts

@@ -1,6 +1,6 @@
+import { useCallback } from 'react';
 import type { IPageToRenameWithMeta } from '@growi/core';
 import { atom, useAtomValue, useSetAtom } from 'jotai';
-import { useCallback } from 'react';
 
 import type { OnRenamedFunction } from '../../../interfaces/ui';
 

+ 1 - 1
apps/app/src/states/ui/modal/page-select.ts

@@ -1,5 +1,5 @@
-import { atom, useAtomValue, useSetAtom } from 'jotai';
 import { useCallback } from 'react';
+import { atom, useAtomValue, useSetAtom } from 'jotai';
 
 import type { OnSelectedFunction } from '../../../interfaces/ui';
 

+ 1 - 1
apps/app/src/states/ui/modal/page-status-alert.ts

@@ -1,5 +1,5 @@
-import { atom, useAtomValue, useSetAtom } from 'jotai';
 import { useCallback } from 'react';
+import { atom, useAtomValue, useSetAtom } from 'jotai';
 
 import type { EditorMode } from '../editor';
 

+ 1 - 1
apps/app/src/states/ui/modal/put-back-page.ts

@@ -1,5 +1,5 @@
-import { atom, useAtomValue, useSetAtom } from 'jotai';
 import { useCallback } from 'react';
+import { atom, useAtomValue, useSetAtom } from 'jotai';
 
 import type { OnPutBackedFunction } from '../../../interfaces/ui';
 

+ 1 - 1
apps/app/src/states/ui/modal/shortcuts.ts

@@ -1,5 +1,5 @@
-import { atom, useAtomValue, useSetAtom } from 'jotai';
 import { useCallback } from 'react';
+import { atom, useAtomValue, useSetAtom } from 'jotai';
 
 // Type definitions
 export type ShortcutsModalStatus = {

+ 1 - 1
apps/app/src/states/ui/modal/tag-edit.ts

@@ -1,5 +1,5 @@
-import { atom, useAtomValue, useSetAtom } from 'jotai';
 import { useCallback } from 'react';
+import { atom, useAtomValue, useSetAtom } from 'jotai';
 
 // Type definitions to match the original implementation
 export type TagEditModalStatus = {

+ 1 - 1
apps/app/src/states/ui/modal/update-user-group-confirm.ts

@@ -1,6 +1,6 @@
+import { useCallback } from 'react';
 import type { IUserGroupHasId } from '@growi/core';
 import { atom, useAtomValue, useSetAtom } from 'jotai';
-import { useCallback } from 'react';
 
 export type UpdateUserGroupConfirmModalStatus = {
   isOpened: boolean;

+ 1 - 0
apps/app/src/states/ui/page-abilities.ts

@@ -1,5 +1,6 @@
 import { pagePathUtils } from '@growi/core/dist/utils';
 import { atom, useAtomValue } from 'jotai';
+
 import {
   _atomsForDerivedAbilities as contextAtoms,
   useIsSharedUser,

+ 1 - 1
apps/app/src/states/ui/page-tree-desc-count-map.ts

@@ -1,5 +1,5 @@
-import { atom, useAtomValue, useSetAtom } from 'jotai';
 import { useCallback } from 'react';
+import { atom, useAtomValue, useSetAtom } from 'jotai';
 
 // Type definitions
 export type UpdateDescCountData = Map<string, number>;

+ 2 - 1
apps/app/src/states/ui/sidebar/sidebar.ts

@@ -1,8 +1,9 @@
-import { atom, useAtom, useAtomValue, useSetAtom } from 'jotai';
 import { type RefObject, useCallback, useMemo } from 'react';
+import { atom, useAtom, useAtomValue, useSetAtom } from 'jotai';
 
 import { scheduleToPut } from '~/client/services/user-ui-settings';
 import { SidebarContentsType, SidebarMode } from '~/interfaces/ui';
+
 import { isDeviceLargerThanXlAtom } from '../device';
 import { EditorMode } from '../editor';
 import { editorModeAtom } from '../editor/editor-mode'; // import the atom directly

+ 2 - 2
apps/app/src/states/ui/toc.ts

@@ -1,9 +1,9 @@
-import { atom, useAtomValue, useSetAtom } from 'jotai';
 import { type RefObject, useCallback, useEffect, useState } from 'react';
+import { atom, useAtomValue, useSetAtom } from 'jotai';
 import type { HtmlElementNode } from 'rehype-toc';
+
 import type { generateTocOptions } from '~/client/services/renderer/renderer';
 import type { RendererOptions } from '~/interfaces/renderer-options';
-import type { RendererConfigExt } from '~/interfaces/services/renderer';
 import { useCurrentPagePath } from '~/states/page';
 import { useRendererConfig } from '~/states/server-configurations';
 import { useNextThemes } from '~/stores-universal/use-next-themes';

+ 2 - 2
apps/app/src/states/ui/unsaved-warning.ts

@@ -1,6 +1,6 @@
-import { atom, useAtomValue, useSetAtom } from 'jotai';
-import { useRouter } from 'next/router';
 import { useCallback, useLayoutEffect } from 'react';
+import { useRouter } from 'next/router';
+import { atom, useAtomValue, useSetAtom } from 'jotai';
 
 // Type definitions
 type CommentEditorDirtyMapData = Map<string, boolean>;

+ 1 - 0
apps/app/src/utils/axios/create-custom-axios.ts

@@ -3,6 +3,7 @@ import type { AxiosRequestConfig } from 'axios';
 import axios from 'axios';
 import { formatISO } from 'date-fns';
 import qs from 'qs';
+
 import { convertStringsToDates } from './convert-strings-to-dates';
 
 export const createCustomAxios = (config?: AxiosRequestConfig) => {

+ 3 - 2
apps/app/src/utils/logger/index.ts

@@ -1,8 +1,9 @@
-import configForDev from '^/config/logger/config.dev';
-import configForProd from '^/config/logger/config.prod';
 import type Logger from 'bunyan';
 import { createLogger, type UniversalBunyanConfig } from 'universal-bunyan';
 
+import configForDev from '^/config/logger/config.dev';
+import configForProd from '^/config/logger/config.prod';
+
 const isProduction = process.env.NODE_ENV === 'production';
 const config = (
   isProduction ? configForProd : configForDev

+ 0 - 1
apps/app/src/utils/page-delete-config.test.ts

@@ -1,5 +1,4 @@
 import { PageDeleteConfigValue } from '../interfaces/page-delete-config';
-
 import { validateDeleteConfigs } from './page-delete-config';
 
 describe('validateDeleteConfigs utility function', () => {