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

Add types (#8154)

GitOrigin-RevId: 41ee6b6873a01fbfedc41a884b9e3ebee47fc08f
Alf Eaton 4 лет назад
Родитель
Сommit
910e07ca1c

+ 70 - 17
package-lock.json

@@ -5,6 +5,7 @@
   "packages": {
     "": {
       "name": "overleaf",
+      "hasInstallScript": true,
       "workspaces": [
         "libraries/*",
         "services/analytics",
@@ -5923,6 +5924,12 @@
       "resolved": "https://registry.npmjs.org/@types/underscore/-/underscore-1.11.4.tgz",
       "integrity": "sha512-uO4CD2ELOjw8tasUrAhvnn2W4A0ZECOvMjCivJr4gA9pGgjv+qxKWY9GLTMVEK8ej85BxQOocUyE7hImmSQYcg=="
     },
+    "node_modules/@types/uuid": {
+      "version": "8.3.4",
+      "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-8.3.4.tgz",
+      "integrity": "sha512-c/I8ZRb51j+pYGAu5CrFMRxqZ2ke4y2grEBO5AUjgSkSk+qT2Ea+OdWElz/OiMf5MNpn2b17kuVBwZLQJXzihw==",
+      "dev": true
+    },
     "node_modules/@types/ws": {
       "version": "6.0.4",
       "resolved": "https://registry.npmjs.org/@types/ws/-/ws-6.0.4.tgz",
@@ -35046,7 +35053,7 @@
         "jsonwebtoken": "^8.5.1",
         "ldapjs": "^0.7.1",
         "lodash": "^4.17.19",
-        "lru-cache": "^6.0.0",
+        "lru-cache": "^7.10.1",
         "mailchimp-api-v3": "^1.12.0",
         "marked": "^0.3.5",
         "match-sorter": "^6.2.0",
@@ -35133,6 +35140,7 @@
         "@types/react-bootstrap": "^0.32.29",
         "@types/react-dom": "^17.0.13",
         "@types/sinon-chai": "^3.2.8",
+        "@types/uuid": "^8.3.4",
         "@typescript-eslint/eslint-plugin": "^5.12.1",
         "@typescript-eslint/parser": "^5.3.1",
         "acorn": "^7.1.1",
@@ -35571,6 +35579,18 @@
         "webpack": "^5.0.0"
       }
     },
+    "services/web/node_modules/css-loader/node_modules/lru-cache": {
+      "version": "6.0.0",
+      "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
+      "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
+      "dev": true,
+      "dependencies": {
+        "yallist": "^4.0.0"
+      },
+      "engines": {
+        "node": ">=10"
+      }
+    },
     "services/web/node_modules/css-loader/node_modules/semver": {
       "version": "7.3.5",
       "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz",
@@ -36088,14 +36108,11 @@
       "dev": true
     },
     "services/web/node_modules/lru-cache": {
-      "version": "6.0.0",
-      "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
-      "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
-      "dependencies": {
-        "yallist": "^4.0.0"
-      },
+      "version": "7.10.1",
+      "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.10.1.tgz",
+      "integrity": "sha512-BQuhQxPuRl79J5zSXRP+uNzPOyZw2oFI9JLRQ80XswSvg21KMKNtQza9eF42rfI/3Z40RvzBdXgziEkudzjo8A==",
       "engines": {
-        "node": ">=10"
+        "node": ">=12"
       }
     },
     "services/web/node_modules/marked": {
@@ -36522,6 +36539,18 @@
         "webpack": "^5.0.0"
       }
     },
+    "services/web/node_modules/postcss-loader/node_modules/lru-cache": {
+      "version": "6.0.0",
+      "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
+      "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
+      "dev": true,
+      "dependencies": {
+        "yallist": "^4.0.0"
+      },
+      "engines": {
+        "node": ">=10"
+      }
+    },
     "services/web/node_modules/postcss-loader/node_modules/semver": {
       "version": "7.3.5",
       "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz",
@@ -37237,7 +37266,8 @@
     "services/web/node_modules/yallist": {
       "version": "4.0.0",
       "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
-      "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="
+      "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
+      "dev": true
     }
   },
   "dependencies": {
@@ -42714,6 +42744,7 @@
         "@types/react-bootstrap": "^0.32.29",
         "@types/react-dom": "^17.0.13",
         "@types/sinon-chai": "^3.2.8",
+        "@types/uuid": "^8.3.4",
         "@typescript-eslint/eslint-plugin": "^5.12.1",
         "@typescript-eslint/parser": "^5.3.1",
         "@uppy/core": "^1.15.0",
@@ -42818,7 +42849,7 @@
         "less-loader": "^10.2.0",
         "less-plugin-autoprefix": "^2.0.0",
         "lodash": "^4.17.19",
-        "lru-cache": "^6.0.0",
+        "lru-cache": "^7.10.1",
         "mailchimp-api-v3": "^1.12.0",
         "marked": "^0.3.5",
         "match-sorter": "^6.2.0",
@@ -43194,6 +43225,15 @@
             "semver": "^7.3.5"
           },
           "dependencies": {
+            "lru-cache": {
+              "version": "6.0.0",
+              "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
+              "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
+              "dev": true,
+              "requires": {
+                "yallist": "^4.0.0"
+              }
+            },
             "semver": {
               "version": "7.3.5",
               "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz",
@@ -43567,12 +43607,9 @@
           "dev": true
         },
         "lru-cache": {
-          "version": "6.0.0",
-          "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
-          "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
-          "requires": {
-            "yallist": "^4.0.0"
-          }
+          "version": "7.10.1",
+          "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.10.1.tgz",
+          "integrity": "sha512-BQuhQxPuRl79J5zSXRP+uNzPOyZw2oFI9JLRQ80XswSvg21KMKNtQza9eF42rfI/3Z40RvzBdXgziEkudzjo8A=="
         },
         "marked": {
           "version": "0.3.19",
@@ -43855,6 +43892,15 @@
             "semver": "^7.3.5"
           },
           "dependencies": {
+            "lru-cache": {
+              "version": "6.0.0",
+              "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
+              "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
+              "dev": true,
+              "requires": {
+                "yallist": "^4.0.0"
+              }
+            },
             "semver": {
               "version": "7.3.5",
               "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz",
@@ -44345,7 +44391,8 @@
         "yallist": {
           "version": "4.0.0",
           "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
-          "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="
+          "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
+          "dev": true
         }
       }
     },
@@ -45528,6 +45575,12 @@
       "resolved": "https://registry.npmjs.org/@types/underscore/-/underscore-1.11.4.tgz",
       "integrity": "sha512-uO4CD2ELOjw8tasUrAhvnn2W4A0ZECOvMjCivJr4gA9pGgjv+qxKWY9GLTMVEK8ej85BxQOocUyE7hImmSQYcg=="
     },
+    "@types/uuid": {
+      "version": "8.3.4",
+      "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-8.3.4.tgz",
+      "integrity": "sha512-c/I8ZRb51j+pYGAu5CrFMRxqZ2ke4y2grEBO5AUjgSkSk+qT2Ea+OdWElz/OiMf5MNpn2b17kuVBwZLQJXzihw==",
+      "dev": true
+    },
     "@types/ws": {
       "version": "6.0.4",
       "resolved": "https://registry.npmjs.org/@types/ws/-/ws-6.0.4.tgz",

+ 3 - 1
services/web/.eslintrc

@@ -25,7 +25,9 @@
     "@typescript-eslint/no-unused-vars": "off",
     "@typescript-eslint/no-empty-function": "off",
     "@typescript-eslint/no-explicit-any": "off",
-    "@typescript-eslint/no-this-alias": "off"
+    "@typescript-eslint/no-this-alias": "off",
+    "@typescript-eslint/no-non-null-assertion": "off",
+    "@typescript-eslint/ban-ts-comment": "off"
   },
   "overrides": [
     // NOTE: changing paths may require updating them in the Makefile too.

+ 4 - 4
services/web/frontend/js/features/dictionary/ignored-words.ts

@@ -2,7 +2,7 @@ import getMeta from '../../utils/meta'
 import { IGNORED_MISSPELLINGS } from '../../ide/editor/directives/aceEditor/spell-check/IgnoredMisspellings'
 
 export class IgnoredWords {
-  public learnedWords: Set<string>
+  public learnedWords!: Set<string>
   private ignoredMisspellings: Set<string>
 
   constructor() {
@@ -16,21 +16,21 @@ export class IgnoredWords {
     window.dispatchEvent(new CustomEvent('learnedWords:reset'))
   }
 
-  add(wordText) {
+  add(wordText: string) {
     this.learnedWords.add(wordText)
     window.dispatchEvent(
       new CustomEvent('learnedWords:add', { detail: wordText })
     )
   }
 
-  remove(wordText) {
+  remove(wordText: string) {
     this.learnedWords.delete(wordText)
     window.dispatchEvent(
       new CustomEvent('learnedWords:remove', { detail: wordText })
     )
   }
 
-  has(wordText) {
+  has(wordText: string) {
     return (
       this.ignoredMisspellings.has(wordText) || this.learnedWords.has(wordText)
     )

+ 1 - 1
services/web/frontend/js/shared/hooks/use-persisted-state.ts

@@ -8,7 +8,7 @@ import {
 import _ from 'lodash'
 import localStorage from '../../infrastructure/local-storage'
 
-function usePersistedState<T>(
+function usePersistedState<T = any>(
   key: string,
   defaultValue?: T,
   listen = false

+ 3 - 3
services/web/frontend/js/shared/hooks/use-scope-value-setter-only.ts

@@ -18,13 +18,13 @@ import _ from 'lodash'
 export default function useScopeValueSetterOnly<T = any>(
   path: string, // dot '.' path of a property in the Angular scope.
   defaultValue?: T
-): [T, Dispatch<SetStateAction<T>>] {
+): [T | undefined, Dispatch<SetStateAction<T | undefined>>] {
   const { $scope } = useIdeContext()
 
-  const [value, setValue] = useState<T>(defaultValue)
+  const [value, setValue] = useState<T | undefined>(defaultValue)
 
   const scopeSetter = useCallback(
-    (newValue: SetStateAction<T>) => {
+    (newValue: SetStateAction<T | undefined>) => {
       setValue(val => {
         const actualNewValue = _.isFunction(newValue) ? newValue(val) : newValue
         $scope.$applyAsync(() => _.set($scope, path, actualNewValue))

+ 1 - 1
services/web/frontend/js/shared/hooks/use-scope-value.ts

@@ -24,7 +24,7 @@ export default function useScopeValue<T = any>(
   useEffect(() => {
     return $scope.$watch(
       path,
-      newValue => {
+      (newValue: T) => {
         setValue(() => {
           // NOTE: this is deliberately wrapped in a function,
           // to avoid calling setValue directly with a value that's a function

+ 3 - 1
services/web/frontend/stories/hooks/use-fetch-mock.tsx

@@ -5,7 +5,9 @@ fetchMock.config.fallbackToNetwork = true
 /**
  * Run callback to mock fetch routes, call restore() when unmounted
  */
-export default function useFetchMock(callback) {
+export default function useFetchMock(
+  callback: (value: typeof fetchMock) => void
+) {
   useLayoutEffect(() => {
     callback(fetchMock)
 

+ 1 - 1
services/web/frontend/stories/hooks/use-scope.tsx

@@ -5,7 +5,7 @@ import { useLayoutEffect, useRef } from 'react'
  * Merge properties with the scope object, for use in Storybook stories
  */
 export const useScope = (scope: Record<string, unknown>) => {
-  const scopeRef = useRef(null)
+  const scopeRef = useRef<Record<string, unknown> | null>(null)
   if (scopeRef.current === null) {
     scopeRef.current = scope
   }

+ 2 - 1
services/web/package.json

@@ -131,7 +131,7 @@
     "jsonwebtoken": "^8.5.1",
     "ldapjs": "^0.7.1",
     "lodash": "^4.17.19",
-    "lru-cache": "^6.0.0",
+    "lru-cache": "^7.10.1",
     "mailchimp-api-v3": "^1.12.0",
     "marked": "^0.3.5",
     "match-sorter": "^6.2.0",
@@ -218,6 +218,7 @@
     "@types/react-bootstrap": "^0.32.29",
     "@types/react-dom": "^17.0.13",
     "@types/sinon-chai": "^3.2.8",
+    "@types/uuid": "^8.3.4",
     "@typescript-eslint/eslint-plugin": "^5.12.1",
     "@typescript-eslint/parser": "^5.3.1",
     "acorn": "^7.1.1",

+ 1 - 1
services/web/test/frontend/components/pdf-preview/pdf-logs-entries.spec.tsx

@@ -21,7 +21,7 @@ describe('<PdfLogsEntries/>', function () {
     },
   ]
 
-  let props
+  let props: Record<string, any>
 
   beforeEach(function () {
     props = {

+ 2 - 2
services/web/test/frontend/components/pdf-preview/pdf-preview.spec.tsx

@@ -4,7 +4,7 @@ import PdfPreview from '../../../../frontend/js/features/pdf-preview/components/
 import { EditorProviders } from '../../helpers/editor-providers'
 import { mockScope } from './scope'
 
-const storeAndFireEvent = (win, key, value) => {
+const storeAndFireEvent = (win: typeof window, key: string, value: unknown) => {
   localStorage.setItem(key, value)
   win.dispatchEvent(new StorageEvent('storage', { key }))
 }
@@ -98,7 +98,7 @@ describe('<PdfPreview/>', function () {
   })
 
   it('does not compile while compiling', function () {
-    let compileResolve
+    let compileResolve: (value?: unknown) => void
     let counter = 0
 
     const promise = new Promise(resolve => {

+ 20 - 6
services/web/test/frontend/components/pdf-preview/pdf-synctex-controls.spec.tsx

@@ -25,15 +25,25 @@ const mockHighlights = [
   },
 ]
 
-const mockPosition = {
+type Position = {
+  page: number
+  offset: { top: number; left: number }
+  pageSize: { height: number; width: number }
+}
+
+const mockPosition: Position = {
   page: 1,
   offset: { top: 10, left: 10 },
   pageSize: { height: 500, width: 500 },
 }
 
-const mockSelectedEntities = [{ type: 'doc' }]
+type Entity = {
+  type: string
+}
+
+const mockSelectedEntities: Entity[] = [{ type: 'doc' }]
 
-const WithPosition = ({ mockPosition }) => {
+const WithPosition = ({ mockPosition }: { mockPosition: Position }) => {
   const { setPosition } = useCompileContext()
 
   // mock PDF scroll position update
@@ -44,7 +54,11 @@ const WithPosition = ({ mockPosition }) => {
   return null
 }
 
-const WithSelectedEntities = ({ mockSelectedEntities = [] }) => {
+const WithSelectedEntities = ({
+  mockSelectedEntities = [],
+}: {
+  mockSelectedEntities: Entity[]
+}) => {
   const { setSelectedEntities } = useFileTreeData()
 
   useEffect(() => {
@@ -210,10 +224,10 @@ describe('<PdfSynctexControls/>', function () {
       cy.wait('@sync-code').should(() => {
         const messages = sysendTestHelper
           .getAllBroacastMessages()
-          .map(item => item.args[1])
+          .map((item: any) => item.args[1])
 
         const message = messages.find(
-          message => message.event === 'action-setHighlights'
+          (message: any) => message.event === 'action-setHighlights'
         )
 
         // synctex is called locally and the result are broadcast for the detached tab

+ 1 - 1
services/web/test/frontend/shared/hooks/use-persisted-state.test.tsx

@@ -119,7 +119,7 @@ describe('usePersistedState', function () {
     expect(window.Storage.prototype.setItem).to.have.callCount(1)
 
     const Test = () => {
-      const [value, setValue] = usePersistedState(key)
+      const [value, setValue] = usePersistedState<string>(key)
 
       useEffect(() => {
         setValue(value => value + 'bar')

+ 5 - 0
services/web/types/annotation.ts

@@ -0,0 +1,5 @@
+export type Annotation = {
+  row: number
+  type: 'info' | 'warning' | 'error'
+  text: string
+}

+ 33 - 0
services/web/types/change.ts

@@ -0,0 +1,33 @@
+export interface Operation {
+  p: number
+}
+
+export interface InsertOperation extends Operation {
+  i: string
+  t: string
+}
+
+export interface ChangeOperation extends Operation {
+  c: string
+  t: string
+}
+
+export interface DeleteOperation extends Operation {
+  d: string
+}
+
+export interface CommentOperation extends Operation {
+  c: string
+}
+
+export type AnyOperation =
+  | InsertOperation
+  | ChangeOperation
+  | DeleteOperation
+  | CommentOperation
+
+export type Change<T extends AnyOperation = AnyOperation> = {
+  id: string
+  metadata?: string
+  op: T
+}

+ 32 - 0
services/web/types/current-doc.ts

@@ -0,0 +1,32 @@
+import { EditorFacade } from '../modules/source-editor/frontend/js/extensions/realtime'
+import {
+  AnyOperation,
+  Change,
+  ChangeOperation,
+  CommentOperation,
+  DeleteOperation,
+  InsertOperation,
+} from './change'
+
+export type CurrentDoc = {
+  doc_id: string
+  docName: string
+  track_changes_as: string | null
+  ranges: {
+    changes: Change<InsertOperation | ChangeOperation | DeleteOperation>[]
+    comments: Change<CommentOperation>[]
+    resolvedThreadIds: Record<string, any>
+    removeCommentId: (id: string) => void
+    removeChangeIds: (ids: string[]) => void
+    getChanges: (
+      ids: string[]
+    ) => Change<InsertOperation | ChangeOperation | DeleteOperation>[]
+    validate: (text: string) => void
+  }
+  attachToCM6: (editor: EditorFacade) => void
+  detachFromCM6: () => void
+  on: (eventName: string, listener: EventListener) => void
+  off: (eventName: string) => void
+  submitOp: (op: AnyOperation) => void
+  getSnapshot: () => string
+}

+ 0 - 0
services/web/types/fileref.ts → services/web/types/file-ref.ts


+ 1 - 1
services/web/types/folder.ts

@@ -1,5 +1,5 @@
 import { Doc } from './doc'
-import { FileRef } from './fileref'
+import { FileRef } from './file-ref'
 
 export type Folder = {
   _id: string

+ 5 - 0
services/web/types/highlight.ts

@@ -0,0 +1,5 @@
+export type Highlight = {
+  cursor: { row: number; column: number }
+  hue: string
+  label: string
+}