Tsify app.js (#4767)

I forgot about app.js, now this is actually the last file in our ts
conversion (other than test/)
This commit is contained in:
Jeremy Rifkin
2023-02-23 17:15:59 -05:00
committed by GitHub
parent 46f99a15f9
commit 6bd5c43f62
12 changed files with 78 additions and 51 deletions

View File

@@ -1,5 +1,5 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="app.js" type="NodeJSConfigurationType" application-parameters="--language c++" nameIsGenerated="true" node-parameters="-r esm -r ts-node/register" path-to-js-file="app.js" working-dir="$PROJECT_DIR$">
<configuration default="false" name="app.ts" type="NodeJSConfigurationType" application-parameters="--language c++" nameIsGenerated="true" node-parameters="-r esm -r ts-node/register" path-to-js-file="app.ts" working-dir="$PROJECT_DIR$">
<method v="2" />
</configuration>
</component>

View File

@@ -1,3 +1,3 @@
<component name="DependencyValidationManager">
<scope name="Server" pattern="file[compiler-explorer]:lib//*||file[compiler-explorer]:app.js||file[compiler-explorer]:test//*" />
<scope name="Server" pattern="file[compiler-explorer]:lib//*||file[compiler-explorer]:app.ts||file[compiler-explorer]:test//*" />
</component>

View File

@@ -86,15 +86,15 @@ run: ## Runs the site like it runs in production
.PHONY: dev
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 -r ts-node/register ./app.js $(EXTRA_ARGS)
./node_modules/.bin/supervisor -w app.ts,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.ts $(EXTRA_ARGS)
.PHONY: gpu-dev
gpu-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 -r ts-node/register ./app.js --env gpu $(EXTRA_ARGS)
./node_modules/.bin/supervisor -w app.ts,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.ts --env gpu $(EXTRA_ARGS)
.PHONY: debug
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 -r ts-node/register ./app.js --debug $(EXTRA_ARGS)
./node_modules/.bin/supervisor -w app.ts,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.ts --debug $(EXTRA_ARGS)
.PHONY:
asm-docs:

View File

@@ -45,6 +45,7 @@ import urljoin from 'url-join';
import * as aws from './lib/aws';
import * as normalizer from './lib/clientstate-normalizer';
import {ElementType} from './lib/common-utils';
import {CompilationEnvironment} from './lib/compilation-env';
import {CompilationQueue} from './lib/compilation-queue';
import {CompilerFinder} from './lib/compiler-finder';
@@ -66,6 +67,7 @@ import {sources} from './lib/sources';
import {loadSponsorsFromString} from './lib/sponsors';
import {getStorageTypeByKey} from './lib/storage';
import * as utils from './lib/utils';
import {Language, LanguageKey} from './types/languages.interfaces';
// Used by assert.ts
global.ce_base_directory = __dirname; // eslint-disable-line unicorn/prefer-module
@@ -106,7 +108,8 @@ if (opts.debug) logger.level = 'debug';
// AP: Detect if we're running under Windows Subsystem for Linux. Temporary modification
// of process.env is allowed: https://nodejs.org/api/process.html#process_process_env
if (process.platform === 'linux' && child_process.execSync('uname -a').toString().includes('Microsoft')) {
process.env.wsl = true;
// Node wants process.env is essentially a Record<key, string | undefined>. Any non-empty string should be fine.
process.env.wsl = 'true';
}
// AP: Allow setting of tmpDir (used in lib/base-compiler.js & lib/exec.js) through opts.
@@ -214,22 +217,24 @@ props.initialize(configDir, propHierarchy);
const ceProps = props.propsFor('compiler-explorer');
defArgs.wantedLanguages = ceProps('restrictToLanguages', defArgs.wantedLanguages);
let languages = allLanguages;
if (defArgs.wantedLanguages) {
const filteredLangs = {};
const passedLangs = defArgs.wantedLanguages.split(',');
for (const wantedLang of passedLangs) {
for (const langId in languages) {
const lang = languages[langId];
if (lang.id === wantedLang || lang.name === wantedLang || lang.alias === wantedLang) {
filteredLangs[lang.id] = lang;
const languages = (() => {
if (defArgs.wantedLanguages) {
const filteredLangs: Partial<Record<LanguageKey, Language>> = {};
const passedLangs = defArgs.wantedLanguages.split(',');
for (const wantedLang of passedLangs) {
for (const lang of Object.values(allLanguages)) {
if (lang.id === wantedLang || lang.name === wantedLang || lang.alias === wantedLang) {
filteredLangs[lang.id] = lang;
}
}
}
// Always keep cmake for IDE mode, just in case
filteredLangs[allLanguages.cmake.id] = allLanguages.cmake;
return filteredLangs;
} else {
return allLanguages;
}
// Always keep cmake for IDE mode, just in case
filteredLangs[languages.cmake.id] = languages.cmake;
languages = filteredLangs;
}
})();
if (Object.keys(languages).length === 0) {
logger.error('Trying to start Compiler Explorer without a language');
@@ -253,15 +258,15 @@ function staticHeaders(res) {
}
}
function contentPolicyHeader(/*res*/) {
function contentPolicyHeader(res: express.Response) {
// TODO: re-enable CSP
// if (csp) {
// res.setHeader('Content-Security-Policy', csp);
// }
}
function measureEventLoopLag(delayMs) {
return new Promise(resolve => {
function measureEventLoopLag(delayMs: number) {
return new Promise<number>(resolve => {
const start = process.hrtime.bigint();
setTimeout(() => {
const elapsed = process.hrtime.bigint() - start;
@@ -301,11 +306,11 @@ function setupEventLoopLagLogging() {
}
}
let pugRequireHandler = () => {
let pugRequireHandler: (path: string) => any = () => {
logger.error('pug require handler not configured');
};
async function setupWebPackDevMiddleware(router) {
async function setupWebPackDevMiddleware(router: express.Router) {
logger.info(' using webpack dev middleware');
/* eslint-disable node/no-unpublished-import,import/extensions, */
@@ -313,8 +318,9 @@ async function setupWebPackDevMiddleware(router) {
const {default: webpackConfig} = await import('./webpack.config.esm.js');
const {default: webpack} = await import('webpack');
/* eslint-enable */
type WebpackConfiguration = ElementType<Parameters<typeof webpack>[0]>;
const webpackCompiler = webpack(webpackConfig);
const webpackCompiler = webpack([webpackConfig as WebpackConfiguration]);
router.use(
webpackDevMiddleware(webpackCompiler, {
publicPath: '/static',
@@ -328,7 +334,7 @@ async function setupWebPackDevMiddleware(router) {
pugRequireHandler = path => urljoin(httpRoot, 'static', path);
}
async function setupStaticMiddleware(router) {
async function setupStaticMiddleware(router: express.Router) {
const staticManifest = await fs.readJson(path.join(distPath, 'manifest.json'));
if (staticUrl) {
@@ -353,7 +359,7 @@ async function setupStaticMiddleware(router) {
};
}
function shouldRedactRequestData(data) {
function shouldRedactRequestData(data: string) {
try {
const parsed = JSON.parse(data);
return !parsed['allowStoreCodeDebug'];
@@ -364,14 +370,14 @@ function shouldRedactRequestData(data) {
const googleShortUrlResolver = new ShortLinkResolver();
function oldGoogleUrlHandler(req, res, next) {
function oldGoogleUrlHandler(req: express.Request, res: express.Response, next: express.NextFunction) {
const id = req.params.id;
const googleUrl = `https://goo.gl/${encodeURIComponent(id)}`;
googleShortUrlResolver
.resolve(googleUrl)
.then(resultObj => {
const parsed = new url.URL(resultObj.longUrl);
const allowedRe = new RegExp(ceProps('allowedShortUrlHostRe'));
const allowedRe = new RegExp(ceProps<string>('allowedShortUrlHostRe'));
if (parsed.host.match(allowedRe) === null) {
logger.warn(`Denied access to short URL ${id} - linked to ${resultObj.longUrl}`);
return next({
@@ -394,13 +400,13 @@ function oldGoogleUrlHandler(req, res, next) {
});
}
function startListening(server) {
function startListening(server: express.Express) {
const ss = systemdSocket();
let _port;
if (ss) {
// ms (5 min default)
const idleTimeout = process.env.IDLE_TIMEOUT;
const timeout = (idleTimeout === undefined ? 300 : idleTimeout) * 1000;
const timeout = (idleTimeout === undefined ? 300 : parseInt(idleTimeout)) * 1000;
if (idleTimeout) {
const exit = () => {
logger.info('Inactivity timeout reached, exiting.');
@@ -440,7 +446,7 @@ function startListening(server) {
}
}
function setupSentry(sentryDsn) {
function setupSentry(sentryDsn: string) {
if (!sentryDsn) {
logger.info('Not configuring sentry');
return;
@@ -489,7 +495,7 @@ async function main() {
let prevCompilers;
if (opts.prediscovered) {
const prediscoveredCompilersJson = await fs.readFile(opts.prediscovered);
const prediscoveredCompilersJson = await fs.readFile(opts.prediscovered, 'utf8');
initialCompilers = JSON.parse(prediscoveredCompilersJson);
await compilerFinder.loadPrediscovered(initialCompilers);
} else {
@@ -538,7 +544,7 @@ async function main() {
};
const noscriptHandler = new NoScriptHandler(router, handlerConfig);
const routeApi = new RouteAPI(router, handlerConfig, noscriptHandler.renderNoScriptLayout);
const routeApi = new RouteAPI(router, handlerConfig);
async function onCompilerChange(compilers) {
if (JSON.stringify(prevCompilers) === JSON.stringify(compilers)) {
@@ -616,7 +622,7 @@ async function main() {
loadSiteTemplates(configDir);
function renderConfig(extra, urlOptions) {
function renderConfig(extra, urlOptions?) {
const urlOptionsAllowed = ['readOnly', 'hideEditorToolbars', 'language'];
const filteredUrlOptions = _.mapObject(_.pick(urlOptions, urlOptionsAllowed), val => utils.toProperty(val));
const allExtraOptions = _.extend({}, filteredUrlOptions, extra);
@@ -667,7 +673,7 @@ async function main() {
);
}
const embeddedHandler = function (req, res) {
const embeddedHandler = function (req: express.Request, res: express.Response) {
staticHeaders(res);
contentPolicyHeader(res);
res.render(
@@ -684,7 +690,7 @@ async function main() {
await (isDevMode() ? setupWebPackDevMiddleware(router) : setupStaticMiddleware(router));
morgan.token('gdpr_ip', req => (req.ip ? utils.anonymizeIp(req.ip) : ''));
morgan.token('gdpr_ip', (req: any) => (req.ip ? utils.anonymizeIp(req.ip) : ''));
// Based on combined format, but: GDPR compliant IP, no timestamp & no unused fields for our usecase
const morganFormat = isDevMode() ? 'dev' : ':gdpr_ip ":method :url" :status';
@@ -837,14 +843,14 @@ process.on('SIGINT', signalHandler('SIGINT'));
process.on('SIGTERM', signalHandler('SIGTERM'));
process.on('SIGQUIT', signalHandler('SIGQUIT'));
function signalHandler(name) {
function signalHandler(name: string) {
return () => {
logger.info(`stopping process: ${name}`);
process.exit(0);
};
}
function uncaughtHandler(err, origin) {
function uncaughtHandler(err: Error, origin: NodeJS.UncaughtExceptionOrigin) {
logger.info(`stopping process: Uncaught exception: ${err}\nException origin: ${origin}`);
// The app will exit naturally from here, but if we call `process.exit()` we may lose log lines.
// see https://github.com/winstonjs/winston/issues/1504#issuecomment-1033087411

View File

@@ -55,3 +55,6 @@ export function basic_comparator<T>(a: T, b: T) {
return 0;
}
}
// https://stackoverflow.com/questions/41253310/typescript-retrieve-element-type-information-from-array-type
export type ElementType<ArrayType extends readonly unknown[]> = ArrayType extends readonly (infer T)[] ? T : never;

View File

@@ -37,7 +37,7 @@ import {fileExists, resolvePathFromAppRoot} from './utils';
export class CompilerArguments implements ICompilerArguments {
private readonly compilerId: string;
private possibleArguments: PossibleArguments = {};
public possibleArguments: PossibleArguments = {};
private readonly maxPopularArguments = 5;
private readonly storeSpecificArguments = false;
private loadedFromFile = false;

View File

@@ -55,7 +55,7 @@ export class ApiHandler {
private usedLangIds: LanguageKey[] = [];
private options: ClientOptionsHandler | null = null;
public readonly handle: express.Router;
private readonly shortener: BaseShortener;
public readonly shortener: BaseShortener;
private release = {
gitReleaseName: '',
releaseBuildNumber: '',

View File

@@ -51,7 +51,7 @@ export class NoScriptHandler {
formDataParser: ReturnType<typeof bodyParser.urlencoded> | undefined;
/* the type for config makes the most sense to define in app.js or api.js */
/* the type for config makes the most sense to define in app.ts or api.ts */
constructor(private readonly router: express.Router, config: any) {
this.staticHeaders = config.staticHeaders;
this.contentPolicyHeader = config.contentPolicyHeader;

17
package-lock.json generated
View File

@@ -13,6 +13,7 @@
"@fortawesome/fontawesome-free": "^6.2.1",
"@sentry/browser": "^7.28.1",
"@sentry/node": "^7.28.1",
"@types/morgan": "^1.9.4",
"aws-sdk": "^2.1048.0",
"big-integer": "^1.6.51",
"body-parser": "^1.19.1",
@@ -1916,6 +1917,14 @@
"integrity": "sha512-ekGvFhFgrc2zYQoX4JeZPmVzZxw6Dtllga7iGHzfbYIYkAMUx/sAFP2GdFpLff+vdHXu5fl7WX9AT+TtqYcsyw==",
"dev": true
},
"node_modules/@types/morgan": {
"version": "1.9.4",
"resolved": "https://registry.npmjs.org/@types/morgan/-/morgan-1.9.4.tgz",
"integrity": "sha512-cXoc4k+6+YAllH3ZHmx4hf7La1dzUk6keTR4bF4b4Sc0mZxU/zK4wO7l+ZzezXm/jkYj/qC+uYGZrarZdIVvyQ==",
"dependencies": {
"@types/node": "*"
}
},
"node_modules/@types/node": {
"version": "18.11.18",
"resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.18.tgz",
@@ -16971,6 +16980,14 @@
"integrity": "sha512-ekGvFhFgrc2zYQoX4JeZPmVzZxw6Dtllga7iGHzfbYIYkAMUx/sAFP2GdFpLff+vdHXu5fl7WX9AT+TtqYcsyw==",
"dev": true
},
"@types/morgan": {
"version": "1.9.4",
"resolved": "https://registry.npmjs.org/@types/morgan/-/morgan-1.9.4.tgz",
"integrity": "sha512-cXoc4k+6+YAllH3ZHmx4hf7La1dzUk6keTR4bF4b4Sc0mZxU/zK4wO7l+ZzezXm/jkYj/qC+uYGZrarZdIVvyQ==",
"requires": {
"@types/node": "*"
}
},
"@types/node": {
"version": "18.11.18",
"resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.18.tgz",

View File

@@ -14,7 +14,7 @@
"engines": {
"node": ">=16"
},
"main": "./app.js",
"main": "./app.ts",
"esm": {
"mode": "all",
"cache": false
@@ -24,6 +24,7 @@
"@fortawesome/fontawesome-free": "^6.2.1",
"@sentry/browser": "^7.28.1",
"@sentry/node": "^7.28.1",
"@types/morgan": "^1.9.4",
"aws-sdk": "^2.1048.0",
"big-integer": "^1.6.51",
"body-parser": "^1.19.1",
@@ -100,8 +101,8 @@
"@types/file-saver": "^2.0.5",
"@types/fs-extra": "^9.0.13",
"@types/http-proxy": "^1.17.9",
"@types/js-cookie": "^3.0.2",
"@types/jquery": "^3.5.10",
"@types/js-cookie": "^3.0.2",
"@types/mocha": "^8.2.2",
"@types/node-targz": "^0.2.0",
"@types/qs": "^6.9.7",
@@ -172,14 +173,14 @@
"lint": "eslint --max-warnings=0 . --fix",
"lint-check": "eslint --max-warnings=0 .",
"lint-files": "eslint --max-warnings=0",
"test": "mocha -b -r ts-node/register 'test/**/*.ts' 'test/**/*.js'",
"test": "mocha -b -r ts-node/register 'test/**/*.ts' 'test/**/*.ts'",
"test-min": "mocha -b --config .mocharc-min.yml",
"fix": "npm run lint && npm run format && npm run ts-check",
"check": "npm run ts-check && npm run lint-check && npm run test-min -- --reporter min",
"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",
"dev": "cross-env NODE_ENV=DEV node -r esm -r ts-node/register app.ts",
"debugger": "cross-env NODE_ENV=DEV node --inspect -r esm -r ts-node/register app.ts --debug",
"debug": "cross-env NODE_ENV=DEV node -r esm -r ts-node/register app.ts --debug",
"start": "webpack && cross-env NODE_ENV=LOCAL node -r esm -r ts-node/register app.ts",
"codecov": "codecov --disable=gcov",
"sentry": "npx -p @sentry/cli sentry-cli",
"update-browserslist": "npx browserslist@latest -- --update-db",

View File

@@ -1,6 +1,6 @@
{
"extends": "./tsconfig.base.json",
"files": ["app.js", "compiler-args-app.ts"],
"files": ["app.ts", "compiler-args-app.ts"],
"include": ["**/*.js", "**/*.ts"],
"exclude": ["out", "test", "etc", "examples", "static", "**/*.d.ts"],
"compilerOptions": {

View File

@@ -9,5 +9,5 @@
"strictPropertyInitialization": false,
"lib": ["dom", "es5", "dom.iterable"]
},
"exclude": ["out", "test", "etc", "examples", "app.js", "compiler-args-app.ts", "lib", "examples"]
"exclude": ["out", "test", "etc", "examples", "app.ts", "compiler-args-app.ts", "lib", "examples"]
}