Niedzielski has submitted this change and it was merged. ( https://gerrit.wikimedia.org/r/371012 )
Change subject: Chore: Compile server side code ...................................................................... Chore: Compile server side code Using typescript and as much of the config of the client code shared in the root tsconfig.json, compile sources to our node target, ES2015. * Installed node.js typings for node, mocha & express * Compile server side code to dist/ * Add an example of common code (src/common/components/app) used on the server and the client. * Add specific formatting & linting for typescript files given typescript-eslint-parser has problems and is experimental Bug: T172439 Change-Id: Ia489def195b6aa8f7279f692d2fb2e2c9351dbd4 --- M .eslintrc.json M package-lock.json M package.json M src/client/index.ts A src/common/components/app/index.ts D src/server/index.js A src/server/index.ts D src/server/templates/page.js A src/server/templates/page.ts A src/server/tsconfig.json A test/mocha.opts D test/server/templates/page.test.js A test/server/templates/page.test.ts 13 files changed, 253 insertions(+), 68 deletions(-) Approvals: Niedzielski: Verified; Looks good to me, approved diff --git a/.eslintrc.json b/.eslintrc.json index e4630e8..086e06c 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -7,9 +7,8 @@ "prettier" ], "rules": { - "prettier/prettier": ["error", {"parser": "typescript"}] + "prettier/prettier": "error" }, - "parser": "typescript-eslint-parser", "parserOptions": { "ecmaVersion": 2016, "sourceType": "module", diff --git a/package-lock.json b/package-lock.json index 2ecb354..363b7c8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4,6 +4,53 @@ "lockfileVersion": 1, "requires": true, "dependencies": { + "@types/express": { + "version": "4.0.36", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.0.36.tgz", + "integrity": "sha512-bT9q2eqH/E72AGBQKT50dh6AXzheTqigGZ1GwDiwmx7vfHff0bZOrvUWjvGpNWPNkRmX1vDF6wonG6rlpBHb1A==", + "dev": true, + "requires": { + "@types/express-serve-static-core": "4.0.49", + "@types/serve-static": "1.7.31" + } + }, + "@types/express-serve-static-core": { + "version": "4.0.49", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.0.49.tgz", + "integrity": "sha512-b7mVHoURu1xaP/V6xw1sYwyv9V0EZ7euyi+sdnbnTZxEkAh4/hzPsI6Eflq+ZzHQ/Tgl7l16Jz+0oz8F46MLnA==", + "dev": true, + "requires": { + "@types/node": "8.0.20" + } + }, + "@types/mime": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.1.tgz", + "integrity": "sha512-rek8twk9C58gHYqIrUlJsx8NQMhlxqHzln9Z9ODqiNgv3/s+ZwIrfr+djqzsnVM12xe9hL98iJ20lj2RvCBv6A==", + "dev": true + }, + "@types/mocha": { + "version": "2.2.41", + "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-2.2.41.tgz", + "integrity": "sha1-4nzwgXFT658nE7LT9saPHhw8pgg=", + "dev": true + }, + "@types/node": { + "version": "8.0.20", + "resolved": "https://registry.npmjs.org/@types/node/-/node-8.0.20.tgz", + "integrity": "sha512-MnB7YEpmLUyEWRVRhKpRs4swwqITnY8BcVFPoTuCl99SCplI/lLUiU5vcJ/OANDqwkpdIg0pDEM38K22KQT2RA==", + "dev": true + }, + "@types/serve-static": { + "version": "1.7.31", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.7.31.tgz", + "integrity": "sha1-FUVt6NmNa0z/Mb5savdJKuY/Uho=", + "dev": true, + "requires": { + "@types/express-serve-static-core": "4.0.49", + "@types/mime": "1.3.1" + } + }, "abbrev": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.0.tgz", @@ -3490,6 +3537,12 @@ "yallist": "2.1.2" } }, + "make-error": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.0.tgz", + "integrity": "sha1-Uq06M5zPEM5itAQLcI/nByRLi5Y=", + "dev": true + }, "map-stream": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/map-stream/-/map-stream-0.1.0.tgz", @@ -4759,6 +4812,15 @@ "integrity": "sha1-dc449SvwczxafwwRjYEzSiu19BI=", "dev": true }, + "source-map-support": { + "version": "0.4.15", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.4.15.tgz", + "integrity": "sha1-AyAt9lwG0r2MfsI2KhkwVv7407E=", + "dev": true, + "requires": { + "source-map": "0.5.6" + } + }, "spdx-correct": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-1.0.2.tgz", @@ -5075,6 +5137,71 @@ } } }, + "ts-node": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-3.3.0.tgz", + "integrity": "sha1-wTxqMCTjC+EYDdUwOPwgkonUv2k=", + "dev": true, + "requires": { + "arrify": "1.0.1", + "chalk": "2.1.0", + "diff": "3.2.0", + "make-error": "1.3.0", + "minimist": "1.2.0", + "mkdirp": "0.5.1", + "source-map-support": "0.4.15", + "tsconfig": "6.0.0", + "v8flags": "3.0.0", + "yn": "2.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz", + "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==", + "dev": true, + "requires": { + "color-convert": "1.9.0" + } + }, + "chalk": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.1.0.tgz", + "integrity": "sha512-LUHGS/dge4ujbXMJrnihYMcL4AoOweGnw9Tp3kQuqy1Kx5c1qKjqvMJZ6nVJPMWJtKCTN72ZogH3oeSO9g9rXQ==", + "dev": true, + "requires": { + "ansi-styles": "3.2.0", + "escape-string-regexp": "1.0.5", + "supports-color": "4.2.1" + } + }, + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + }, + "supports-color": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.2.1.tgz", + "integrity": "sha512-qxzYsob3yv6U+xMzPrv170y8AwGP7i74g+pbixCfD6rgso8BscLT2qXIuz6TpOaiJZ3mFgT5O9lyT9nMU4LfaA==", + "dev": true, + "requires": { + "has-flag": "2.0.0" + } + } + } + }, + "tsconfig": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/tsconfig/-/tsconfig-6.0.0.tgz", + "integrity": "sha1-aw6DdgA9evGGT434+J3QBZ/80DI=", + "dev": true, + "requires": { + "strip-bom": "3.0.0", + "strip-json-comments": "2.0.1" + } + }, "tty-browserify": { "version": "0.0.0", "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz", @@ -5264,6 +5391,23 @@ "resolved": "https://registry.npmjs.org/uuid/-/uuid-2.0.3.tgz", "integrity": "sha1-Z+LoY3lyFVMN/zGOW/nc6/1Hsho=", "dev": true + }, + "v8flags": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-3.0.0.tgz", + "integrity": "sha512-AGl+C+4qpeSu2g3JxCD/mGFFOs/vVZ3XREkD3ibQXEqr4Y4zgIrPWW124/IKJFHOIVFIoH8miWrLf0o84HYjwA==", + "dev": true, + "requires": { + "user-home": "1.1.1" + }, + "dependencies": { + "user-home": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/user-home/-/user-home-1.1.1.tgz", + "integrity": "sha1-K1viOjK2Onyd640PKNSFcko98ZA=", + "dev": true + } + } }, "validate-npm-package-license": { "version": "3.0.1", @@ -5523,6 +5667,12 @@ "dev": true } } + }, + "yn": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/yn/-/yn-2.0.0.tgz", + "integrity": "sha1-5a2ryKz0CPY4X8dklWhMiOavaJo=", + "dev": true } } } diff --git a/package.json b/package.json index af6420b..f52ba40 100644 --- a/package.json +++ b/package.json @@ -4,17 +4,26 @@ "description": "An API driven skin for MediaWiki", "scripts": { "start": "run-p -sn dev:\\*", - "dev:client": "NODE_ENV=development webpack -w", - "dev:server": "NODE_ENV=development nodemon -q src/server/index.js", - "prod:build": "NODE_ENV=production webpack -p", - "format": "npm run lint -s -- --fix", - "format:all": "npm run format -s -- .", - "lint": "eslint --cache --max-warnings 0 --ext ts,tsx,js,json", - "lint:all": "npm run lint -s -- .", - "pretest": "npm run lint:all -s", - "test": "mocha '{src,test}/**/*.test.js'", - "test:watch": "nodemon -q -x 'npm test'", - "precommit": "npm run test -s" + "dev:client": "webpack -w", + "dev:server": "run-p -sn dev:server:\\*", + "dev:server:build": "npm run -s server:build -- -w", + "dev:server:watch": "nodemon -e js,json,ts,tsx -q dist/server/index.js", + "server:build": "tsc -p src/server/tsconfig.json", + "client:build": "webpack -p", + "prod:build": "NODE_ENV=production run-s -s server:build client:build", + "format:ts": "prettier --write --parser typescript", + "format:ts:all": "npm run -s format:ts -- '{src,test}/**/*.{ts,tsx}'", + "format:js": "npm run -s lint -- --fix", + "format:js:all": "npm run -s format:js -- .", + "format:all": "run-s -s format:js:all format:ts:all", + "lint": "eslint --cache --max-warnings 0 --ext js,json", + "lint:ts": "prettier --parser typescript -l", + "lint:ts:all": "npm run -s lint:ts -- '{src,test}/**/*.{ts,tsx}'", + "lint:all": "npm run -s lint -- . && npm run -s lint:ts:all", + "pretest": "run-s -s lint:all prod:build", + "test": "mocha '{src,test}/**/*.test.{ts,js}'", + "test:watch": "nodemon -e js,json,ts,tsx -q -x 'npm test'", + "precommit": "npm run -s test" }, "repository": { "type": "git", @@ -41,6 +50,9 @@ "express": "^4.15.3" }, "devDependencies": { + "@types/express": "^4.0.36", + "@types/mocha": "^2.2.41", + "@types/node": "^8.0.20", "assets-webpack-plugin": "^3.5.1", "clean-webpack-plugin": "^0.1.16", "eslint": "^3.19.0", @@ -57,6 +69,7 @@ "prettier": "^1.5.3", "sinon": "^3.0.0", "ts-loader": "^2.3.2", + "ts-node": "^3.3.0", "typescript": "^2.4.2", "typescript-eslint-parser": "^5.0.1", "webpack": "^3.4.1" diff --git a/src/client/index.ts b/src/client/index.ts index 0b8fccf..cc57a6b 100644 --- a/src/client/index.ts +++ b/src/client/index.ts @@ -1 +1,3 @@ -console.log("Hello from the browser"); // eslint-disable-line no-console +import app from "../common/components/app"; + +console.log(`${app()}, from the browser`); // eslint-disable-line no-console diff --git a/src/common/components/app/index.ts b/src/common/components/app/index.ts new file mode 100644 index 0000000..7739917 --- /dev/null +++ b/src/common/components/app/index.ts @@ -0,0 +1,3 @@ +export default function app() { + return "Hello world"; +} diff --git a/src/server/index.js b/src/server/index.js deleted file mode 100644 index 04ec4b8..0000000 --- a/src/server/index.js +++ /dev/null @@ -1,20 +0,0 @@ -const express = require("express"); -const page = require("./templates/page"); -const assets = require("../../dist/public/assets-manifest.json"); - -const { PORT = 3000 } = process.env; -const server = express(); - -server.use(express.static("dist/public")); - -server.get("/", (req, res) => { - res.status(200).send(page({ body: "Hello World!", assets })); -}); - -server.get("*", (req, res) => { - res.status(404).send("Not found"); -}); - -server.listen(PORT, () => { - console.log(`Server started on port ${PORT}`); // eslint-disable-line no-console -}); diff --git a/src/server/index.ts b/src/server/index.ts new file mode 100644 index 0000000..76673c0 --- /dev/null +++ b/src/server/index.ts @@ -0,0 +1,22 @@ +import * as express from "express"; +import page, { AssetsManifest } from "./templates/page"; +import app from "../common/components/app"; + +const assets: AssetsManifest = require("../../dist/public/assets-manifest.json"); + +const { PORT = 3000 } = process.env; +const server = express(); + +server.use(express.static("dist/public")); + +server.get("/", (_req: express.Request, res: express.Response) => { + res.status(200).send(page({ title: "", body: app(), assets })); +}); + +server.get("*", (_req: express.Request, res: express.Response) => { + res.status(404).send("Not found"); +}); + +server.listen(PORT, () => { + console.log(`Server started on port ${PORT}`); // eslint-disable-line no-console +}); diff --git a/src/server/templates/page.js b/src/server/templates/page.js deleted file mode 100644 index dba5ca4..0000000 --- a/src/server/templates/page.js +++ /dev/null @@ -1,24 +0,0 @@ -/** - * Render a full HTML page - * @param {!Object} params - * @param {?string} params.title Title of the page - * @param {string} [params.body = ""] HTML to render in the body of the page - * @param {!Object.<string, !Object.<string, !string>>} params.assets Manifest of filename entry points to bundled assets. - * @return {!string} HTML - */ -module.exports = function page({ body = "", assets, title }) { - return ` -<!DOCTYPE html> -<html lang="en"> - <head> - <meta charset="utf-8"/> - <meta http-equiv="x-ua-compatible" content="ie=edge"> - <meta name="viewport" content="width=device-width,initial-scale=1"/> - <title>${title ? `${title} - ` : ""}Marvin</title> - </head> - <body> - <div id="root">${body}</div> - <script type="text/javascript" src="./${assets.index.js}"></script> - </body> -</html>`; -}; diff --git a/src/server/templates/page.ts b/src/server/templates/page.ts new file mode 100644 index 0000000..4929a35 --- /dev/null +++ b/src/server/templates/page.ts @@ -0,0 +1,31 @@ +export interface AssetsManifest { + [entrypoint: string]: { + [format: string]: string; + }; +} + +export interface PageParams { + // Title of the page + title: string; + // HTML to render in the body of the page + body: string; + // Manifest of filename entry points to bundled assets. + assets: AssetsManifest; +} + +export default function page({ title, body = "", assets }: PageParams): string { + return ` +<!DOCTYPE html> +<html lang="en"> + <head> + <meta charset="utf-8"/> + <meta http-equiv="x-ua-compatible" content="ie=edge"> + <meta name="viewport" content="width=device-width,initial-scale=1"/> + <title>${title ? `${title} - ` : ""}Marvin</title> + </head> + <body> + <div id="root">${body}</div> + <script type="text/javascript" src="./${assets.index.js}"></script> + </body> +</html>`; +} diff --git a/src/server/tsconfig.json b/src/server/tsconfig.json new file mode 100644 index 0000000..947ab9f --- /dev/null +++ b/src/server/tsconfig.json @@ -0,0 +1,8 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "target": "ES2015", + "module": "commonjs", + "outDir": "../../dist" + } +} diff --git a/test/mocha.opts b/test/mocha.opts new file mode 100644 index 0000000..14d88f9 --- /dev/null +++ b/test/mocha.opts @@ -0,0 +1 @@ +--compilers ts:ts-node/register,tsx:ts-node/register diff --git a/test/server/templates/page.test.js b/test/server/templates/page.test.js deleted file mode 100644 index ad38b51..0000000 --- a/test/server/templates/page.test.js +++ /dev/null @@ -1,10 +0,0 @@ -const assert = require("assert"); -const { describe, it } = require("mocha"); -const page = require("../../../src/server/templates/page"); - -describe("page()", () => { - it("incorporeal", () => { - const assets = { index: {} }; - assert.ok(page({ assets })); - }); -}); diff --git a/test/server/templates/page.test.ts b/test/server/templates/page.test.ts new file mode 100644 index 0000000..4b0bb29 --- /dev/null +++ b/test/server/templates/page.test.ts @@ -0,0 +1,10 @@ +/* eslint-env mocha */ +import * as assert from "assert"; +import page from "../../../src/server/templates/page"; + +describe("page()", () => { + it("incorporeal", () => { + const assets = { index: { js: "index.js" } }; + assert.ok(page({ title: "Test", body: "Body", assets })); + }); +}); -- To view, visit https://gerrit.wikimedia.org/r/371012 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: merged Gerrit-Change-Id: Ia489def195b6aa8f7279f692d2fb2e2c9351dbd4 Gerrit-PatchSet: 9 Gerrit-Project: marvin Gerrit-Branch: master Gerrit-Owner: Jhernandez <jhernan...@wikimedia.org> Gerrit-Reviewer: Jhernandez <jhernan...@wikimedia.org> Gerrit-Reviewer: Niedzielski <sniedziel...@wikimedia.org> _______________________________________________ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits