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

Reply via email to