diff options
author | Patrick Quist <partouf@gmail.com> | 2021-12-22 20:44:51 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-12-22 20:44:51 +0100 |
commit | 6e79e098c45cbd01796aa61444809d512e536296 (patch) | |
tree | 17108245b9d12356d1ffda6e92488d97bebe74e5 | |
parent | b11155c79263cecc035428050e10fc94ab1eaf38 (diff) | |
download | compiler-explorer-6e79e098c45cbd01796aa61444809d512e536296.tar.gz compiler-explorer-6e79e098c45cbd01796aa61444809d512e536296.zip |
Minimal backend typescript support (#3207)gh-1454
* minimal ts support
Co-authored-by: Matt Godbolt <matt@godbolt.org>
-rw-r--r-- | .eslintrc.yml | 15 | ||||
-rw-r--r-- | .mocharc.yml | 5 | ||||
-rw-r--r-- | .nycrc.yml | 3 | ||||
-rw-r--r-- | Makefile | 15 | ||||
-rwxr-xr-x | app.js | 4 | ||||
-rw-r--r-- | lib/utils.ts (renamed from lib/utils.js) | 26 | ||||
-rw-r--r-- | package.json | 10 | ||||
-rw-r--r-- | tsconfig.json | 71 | ||||
-rw-r--r-- | webpack.config.esm.js | 6 |
9 files changed, 131 insertions, 24 deletions
diff --git a/.eslintrc.yml b/.eslintrc.yml index c65dcbb91..6f9cd59a5 100644 --- a/.eslintrc.yml +++ b/.eslintrc.yml @@ -7,6 +7,7 @@ plugins: - promise - sonarjs - unicorn + - '@typescript-eslint' extends: - ./.eslint-license-header.yml - eslint:recommended @@ -14,6 +15,9 @@ extends: - plugin:node/recommended - plugin:unicorn/recommended - prettier + - plugin:@typescript-eslint/eslint-recommended + - plugin:@typescript-eslint/recommended + - plugin:import/typescript env: mocha: true node: true @@ -28,6 +32,7 @@ rules: eqeqeq: - error - smart + import/default: off # fs-extra trips this. the ts compiler catches actual errors import/extensions: error import/first: error import/newline-after-import: error @@ -36,6 +41,7 @@ rules: import/no-default-export: warn import/no-deprecated: warn import/no-mutable-exports: error + import/no-named-as-default-member: off # Far too many things (express, morgan, fs) trip this import/no-self-import: error import/no-useless-path-segments: error import/no-webpack-loader-syntax: error @@ -138,8 +144,17 @@ rules: unicorn/no-array-callback-reference: off unicorn/prefer-switch: off unicorn/no-static-only-class: off + unicorn/no-process-exit: off + '@typescript-eslint/no-empty-function': off + '@typescript-eslint/no-unused-vars': off parserOptions: sourceType: module ecmaVersion: 2020 globals: BigInt: true +settings: + node: + tryExtensions: [ .js, .ts ] + import/parsers: + "@typescript-eslint/parser": [ .ts, .tsx ] + import/resolver: "typescript" diff --git a/.mocharc.yml b/.mocharc.yml new file mode 100644 index 000000000..0fe58d691 --- /dev/null +++ b/.mocharc.yml @@ -0,0 +1,5 @@ +recursive: true +require: + - esm + - ts-node/register + - source-map-support/register diff --git a/.nycrc.yml b/.nycrc.yml index e0174ab1d..749a1cbbf 100644 --- a/.nycrc.yml +++ b/.nycrc.yml @@ -1,6 +1,7 @@ all: true include: - lib/**/*.js + - lib/**/*.ts exclude: - lib/handlers/asm-docs-amd64.js - lib/handlers/asm-docs-arm32.js @@ -11,3 +12,5 @@ reporter: - lcov require: - esm + - source-map-support/register + - ts-node/register
\ No newline at end of file @@ -43,7 +43,7 @@ $(NODE_MODULES): package.json | node-installed WEBPACK:=./node_modules/webpack-cli/bin/cli.js $(WEBPACK): $(NODE_MODULES) -lint: $(NODE_MODULES) ## Checks if the source currently matches code conventions +lint: $(NODE_MODULES) ts-compile ## Checks if the source currently matches code conventions $(NPM) run lint lint-fix: $(NODE_MODULES) ## Checks if everything matches code conventions & fixes those which are trivial to do so @@ -72,20 +72,25 @@ clean: ## Cleans up everything run: export NODE_ENV=production run: export WEBPACK_ARGS="--node-env=production" run: prereqs webpack ## Runs the site normally - ./node_modules/.bin/supervisor -w app.js,lib,etc/config,static/tsconfig.json -e 'js|ts|node|properties|yaml' --exec $(NODE) $(NODE_ARGS) -- -r esm ./app.js $(EXTRA_ARGS) + ./node_modules/.bin/supervisor -w app.js,lib,etc/config,static/tsconfig.json -e 'js|ts|node|properties|yaml' --exec $(NODE) $(NODE_ARGS) -- -r esm -r ts-node/register ./app.js $(EXTRA_ARGS) dev: export NODE_ENV=development dev: prereqs ## Runs the site as a developer; including live reload support and installation of git hooks - ./node_modules/.bin/supervisor -w app.js,lib,etc/config,static/tsconfig.json -e 'js|ts|node|properties|yaml' -n exit --exec $(NODE) $(NODE_ARGS) -- -r esm ./app.js $(EXTRA_ARGS) + ./node_modules/.bin/supervisor -w app.js,lib,etc/config,static/tsconfig.json -e 'js|ts|node|properties|yaml' -n exit --exec $(NODE) $(NODE_ARGS) -- -r esm -r ts-node/register ./app.js $(EXTRA_ARGS) debug: export NODE_ENV=development debug: prereqs ## Runs the site as a developer with full debugging; including live reload support and installation of git hooks - ./node_modules/.bin/supervisor -w app.js,lib,etc/config,static/tsconfig.json -e 'js|ts|node|properties|yaml' -n exit --inspect 9229 --exec $(NODE) $(NODE_ARGS) -- -r esm ./app.js --debug $(EXTRA_ARGS) + ./node_modules/.bin/supervisor -w app.js,lib,etc/config,static/tsconfig.json -e 'js|ts|node|properties|yaml' -n exit --inspect 9229 --exec $(NODE) $(NODE_ARGS) -- -r esm -r ts-node/register ./app.js --debug $(EXTRA_ARGS) + +.PHONY: ts-compile +# one day we'll put `--strict` in this +ts-compile: prereqs + ./node_modules/.bin/tsc HASH := $(shell git rev-parse HEAD) dist: export NODE_ENV=production dist: export WEBPACK_ARGS="--node-env=production" -dist: prereqs webpack ## Creates a distribution +dist: prereqs webpack ts-compile ## Creates a distribution echo $(HASH) > out/dist/git_hash RELEASE_FILE_NAME=$(GITHUB_RUN_NUMBER) @@ -1,7 +1,3 @@ -#!/usr/bin/env node -// shebang interferes with license header plugin -/* eslint-disable header/header */ - // Copyright (c) 2012, Compiler Explorer Authors // All rights reserved. // diff --git a/lib/utils.js b/lib/utils.ts index 97d864c34..fea13bc6e 100644 --- a/lib/utils.js +++ b/lib/utils.ts @@ -30,6 +30,18 @@ import fs from 'fs-extra'; import quote from 'shell-quote'; import _ from 'underscore'; +interface IResultLineTag { + line?: number; + column?: number; + file?: string; + text: string; +} + +interface IResultLine { + text: string; + tag?: IResultLineTag; +} + const tabsRe = /\t/g; const lineRe = /\r?\n/; @@ -58,7 +70,7 @@ export function splitLines(text) { * @param {eachLineFunc} func * @param {*} [context] */ -export function eachLine(text, func, context) { +export function eachLine(text: string, func, context?): IResultLine[] { return _.each(splitLines(text), func, context); } @@ -133,7 +145,7 @@ export function parseOutput(lines, inputFilename, pathPrefix) { line = maskRootdir(line); } if (line !== null) { - const lineObj = {text: line}; + const lineObj: IResultLine = { text: line }; const filteredline = line.replace(ansiColoursRe, ''); let match = filteredline.match(re); if (match) { @@ -172,7 +184,7 @@ export function parseRustOutput(lines, inputFilename, pathPrefix) { eachLine(lines, line => { line = _parseOutputLine(line, inputFilename, pathPrefix); if (line !== null) { - const lineObj = {text: line}; + const lineObj: IResultLine = { text: line }; const match = line.replace(ansiColoursRe, '').match(re); if (match) { @@ -307,13 +319,13 @@ export function getHash(object, HashVersion = DefaultHash) { * @returns {glContents} */ export function glGetMainContents(content) { - let contents = {editors: [], compilers: []}; + const contents = { editors: [], compilers: [] }; _.each(content, element => { if (element.type === 'component') { if (element.componentName === 'codeEditor') { - contents.editors.push({source: element.componentState.source, language: element.componentState.lang}); + contents.editors.push({ source: element.componentState.source, language: element.componentState.lang }); } else if (element.componentName === 'compiler') { - contents.compilers.push({compiler: element.componentState.compiler}); + contents.compilers.push({ compiler: element.componentState.compiler }); } } else { const subComponents = glGetMainContents(element.content); @@ -459,7 +471,7 @@ export async function dirExists(dir) { export function countOccurrences(collection, item) { // _.reduce(collection, (total, value) => value === item ? total + 1 : total, 0) would work, but is probably slower let result = 0; - for (let element of collection) { + for (const element of collection) { if (element === item) { result++; } diff --git a/package.json b/package.json index 2abea5374..bfaccf5c6 100644 --- a/package.json +++ b/package.json @@ -149,15 +149,15 @@ }, "scripts": { "ci-lint": "eslint --format github .", - "ci-test": "nyc mocha --recursive", + "ci-test": "nyc npm run test", "lint": "eslint .", "lint-fix": "eslint --fix .", "test": "mocha --recursive", "check": "npm run lint && npm run test", - "dev": "cross-env NODE_ENV=DEV node -r esm app.js", - "debugger": "cross-env NODE_ENV=DEV node --inspect -r esm app.js --debug", - "debug": "cross-env NODE_ENV=DEV node -r esm app.js --debug", - "start": "webpack && cross-env NODE_ENV=LOCAL node -r esm app.js", + "dev": "cross-env NODE_ENV=DEV node -r esm -r ts-node/register app.js", + "debugger": "cross-env NODE_ENV=DEV node --inspect -r esm -r ts-node/register app.js --debug", + "debug": "cross-env NODE_ENV=DEV node -r esm -r ts-node/register app.js --debug", + "start": "webpack && cross-env NODE_ENV=LOCAL node -r esm -r ts-node/register app.js", "codecov": "codecov --disable=gcov", "sentry": "npx -p @sentry/cli sentry-cli", "update-browserslist": "npx browserslist@latest -- --update-db", diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 000000000..79d079aee --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,71 @@ +{ + "include": ["lib/**/*"], + "compilerOptions": { + /* Visit https://aka.ms/tsconfig.json to read more about this file */ + + /* Basic Options */ + // "incremental": true, /* Enable incremental compilation */ + "target": "esnext" /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */, + "module": "esnext" /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */, + // "lib": [], /* Specify library files to be included in the compilation. */ + // "allowJs": true, /* Allow javascript files to be compiled. */ + // "checkJs": true, /* Report errors in .js files. */ + // "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */ + // "declaration": true, /* Generates corresponding '.d.ts' file. */ + // "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */ + // "sourceMap": true, /* Generates corresponding '.map' file. */ + // "outFile": "./", /* Concatenate and emit output to single file. */ + "outDir": "./out/app" /* Redirect output structure to the directory. */, + // "rootDir": "./", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */ + // "composite": true, /* Enable project compilation */ + // "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */ + // "removeComments": true, /* Do not emit comments to output. */ + // "noEmit": true, /* Do not emit outputs. */ + // "importHelpers": true, /* Import emit helpers from 'tslib'. */ + // "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */ + // "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */ + + /* Strict Type-Checking Options */ + // "strict": true, /* Enable all strict type-checking options. */ + // "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */ + // "strictNullChecks": true, /* Enable strict null checks. */ + // "strictFunctionTypes": true, /* Enable strict checking of function types. */ + // "strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */ + // "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */ + // "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */ + // "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */ + + /* Additional Checks */ + // "noUnusedLocals": true, /* Report errors on unused locals. */ + // "noUnusedParameters": true, /* Report errors on unused parameters. */ + // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ + // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ + + /* Module Resolution Options */ + "moduleResolution": "node" /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */, + // "baseUrl": "./", /* Base directory to resolve non-absolute module names. */ + // "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */ + // "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */ + // "typeRoots": [], /* List of folders to include type definitions from. */ + "typeRoots": ["./typings", "./node_modules/@types"], + // "types": [], /* Type declaration files to be included in compilation. */ + // "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */ + "esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */, + // "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */ + // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ + + /* Source Map Options */ + "sourceRoot": "/" /* Specify the location where debugger should locate TypeScript files instead of source locations. */, + // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ + "inlineSourceMap": true /* Emit a single file with source maps instead of having a separate file. */, + // "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */ + + /* Experimental Options */ + // "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */ + // "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */ + + /* Advanced Options */ + "skipLibCheck": true /* Skip type checking of declaration files. */, + "forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */ + } +} diff --git a/webpack.config.esm.js b/webpack.config.esm.js index 82f06d67b..464b8d2ff 100644 --- a/webpack.config.esm.js +++ b/webpack.config.esm.js @@ -31,7 +31,7 @@ import CssMinimizerPlugin from 'css-minimizer-webpack-plugin'; import MiniCssExtractPlugin from 'mini-css-extract-plugin'; import MonacoEditorWebpackPlugin from 'monaco-editor-webpack-plugin'; import TerserPlugin from 'terser-webpack-plugin'; -import webpack from 'webpack'; +import {HotModuleReplacementPlugin, ProvidePlugin} from 'webpack'; import {WebpackManifestPlugin} from 'webpack-manifest-plugin'; const __dirname = path.resolve(path.dirname(fileURLToPath(import.meta.url))); @@ -57,7 +57,7 @@ const plugins = [ }, ], }), - new webpack.ProvidePlugin({ + new ProvidePlugin({ $: 'jquery', jQuery: 'jquery', }), @@ -71,7 +71,7 @@ const plugins = [ ]; if (isDev) { - plugins.push(new webpack.HotModuleReplacementPlugin()); + plugins.push(new HotModuleReplacementPlugin()); } // eslint-disable-next-line import/no-default-export |