Browse Source

chore(common): implement enforced pre-commit type checks for FE service files (#3472)

James George 1 year ago
parent
commit
b5307e4a89

+ 2 - 1
packages/hoppscotch-common/package.json

@@ -17,7 +17,7 @@
     "postinstall": "pnpm run gql-codegen",
     "postinstall": "pnpm run gql-codegen",
     "do-test": "pnpm run test",
     "do-test": "pnpm run test",
     "do-lint": "pnpm run prod-lint",
     "do-lint": "pnpm run prod-lint",
-    "do-typecheck": "pnpm run lint",
+    "do-typecheck": "node type-check.mjs",
     "do-lintfix": "pnpm run lintfix"
     "do-lintfix": "pnpm run lintfix"
   },
   },
   "dependencies": {
   "dependencies": {
@@ -136,6 +136,7 @@
     "eslint": "^8.47.0",
     "eslint": "^8.47.0",
     "eslint-plugin-prettier": "^5.0.0",
     "eslint-plugin-prettier": "^5.0.0",
     "eslint-plugin-vue": "^9.17.0",
     "eslint-plugin-vue": "^9.17.0",
+    "glob": "^10.3.10",
     "npm-run-all": "^4.1.5",
     "npm-run-all": "^4.1.5",
     "openapi-types": "^12.1.3",
     "openapi-types": "^12.1.3",
     "rollup-plugin-polyfill-node": "^0.12.0",
     "rollup-plugin-polyfill-node": "^0.12.0",

+ 7 - 2
packages/hoppscotch-common/src/modules/i18n.ts

@@ -58,7 +58,13 @@ export const FALLBACK_LANG = pipe(
 )
 )
 
 
 // A reference to the i18n instance
 // A reference to the i18n instance
-let i18nInstance: I18n<any, any, any> | null = null
+let i18nInstance: I18n<
+  Record<string, unknown>,
+  Record<string, unknown>,
+  Record<string, unknown>,
+  string,
+  true
+> | null = null
 
 
 const resolveCurrentLocale = () =>
 const resolveCurrentLocale = () =>
   pipe(
   pipe(
@@ -119,7 +125,6 @@ export const changeAppLanguage = async (locale: string) => {
  * Returns the i18n instance
  * Returns the i18n instance
  */
  */
 export function getI18n() {
 export function getI18n() {
-  // @ts-expect-error Something weird with the i18n errors
   return i18nInstance!.global.t
   return i18nInstance!.global.t
 }
 }
 
 

+ 92 - 0
packages/hoppscotch-common/type-check.mjs

@@ -0,0 +1,92 @@
+import fs from "fs"
+import { glob } from "glob"
+import path from "path"
+import ts from "typescript"
+import vueTsc from "vue-tsc"
+
+import { fileURLToPath } from "url"
+
+/**
+ * Helper function to find files to perform type check on
+ */
+const findFilesToPerformTypeCheck = (directoryPaths, filePatterns) => {
+  const files = []
+
+  directoryPaths.forEach((directoryPath) => {
+    if (!fs.existsSync(directoryPath)) {
+      console.error(`Directory not found: ${directoryPath}`)
+      process.exit(1)
+    }
+
+    files.push(
+      ...glob.sync(filePatterns, {
+        cwd: directoryPath,
+        ignore: ["**/__tests__/**", "**/*.d.ts"],
+        absolute: true,
+      })
+    )
+  })
+  return files
+}
+
+// Derive the current file's directory path `__dirname` from the URL of this module `__filename`
+const __filename = fileURLToPath(import.meta.url)
+const __dirname = path.dirname(__filename)
+
+// Define the directory paths and file patterns to perform type checks on
+const directoryPaths = [path.resolve(__dirname, "src", "services")]
+const filePatterns = ["**/*.ts"]
+
+const tsConfigFileName = path.resolve(__dirname, "tsconfig.json")
+const tsConfig = ts.readConfigFile(tsConfigFileName, ts.sys.readFile)
+const { options } = ts.parseJsonConfigFileContent(
+  tsConfig.config,
+  ts.sys,
+  __dirname
+)
+
+const files = findFilesToPerformTypeCheck(directoryPaths, filePatterns)
+
+const host = ts.createCompilerHost(options)
+const program = vueTsc.createProgram({
+  rootNames: files,
+  options: { ...options, noEmit: true },
+  host,
+})
+
+// Perform type checking
+const diagnostics = ts
+  .getPreEmitDiagnostics(program)
+  // Filter diagnostics to include only errors from files in the specified directory
+  .filter(({ file }) => {
+    if (!file) {
+      return false
+    }
+    return directoryPaths.some((directoryPath) =>
+      path.resolve(file.fileName).includes(directoryPath)
+    )
+  })
+
+if (!diagnostics.length) {
+  console.log("Type checking passed.")
+
+  // Success
+  process.exit(0)
+}
+
+console.log("TypeScript diagnostics:")
+
+const formatHost = {
+  getCanonicalFileName: (fileName) => fileName,
+  getCurrentDirectory: host.getCurrentDirectory,
+  getNewLine: () => ts.sys.newLine,
+}
+
+const formattedDiagnostics = ts.formatDiagnosticsWithColorAndContext(
+  diagnostics,
+  formatHost
+)
+console.error(formattedDiagnostics)
+
+// Failure
+process.exit(1)

File diff suppressed because it is too large
+ 144 - 140
pnpm-lock.yaml


Some files were not shown because too many files changed in this diff