From f74cdbcf33cefae5c94f4578fa6a2292bbc04c1f Mon Sep 17 00:00:00 2001 From: Brandon Istenes Date: Sat, 26 Oct 2019 16:39:06 -0500 Subject: [PATCH] MF-74 Config library should import default config file using import-map (#2) * Import config.json from import map working. Jest failing. 404s print to console. * Fix tests * Do lookup per Joel's advice -- much better error handling * Get tests working; put config-file resolution into a function; weird eslint error? * Fixing build --- packages/esm-config/jest.config.js | 2 +- packages/esm-config/package-lock.json | 219 +++++++++++++++++- packages/esm-config/package.json | 4 +- .../src/module-config/module-config.test.ts | 38 +++ .../src/module-config/module-config.ts | 22 ++ packages/esm-config/src/setup-tests.js | 9 + packages/esm-config/webpack.config.js | 1 - 7 files changed, 284 insertions(+), 11 deletions(-) create mode 100644 packages/esm-config/src/setup-tests.js diff --git a/packages/esm-config/jest.config.js b/packages/esm-config/jest.config.js index 64d73dfb73ea..31537b272f35 100644 --- a/packages/esm-config/jest.config.js +++ b/packages/esm-config/jest.config.js @@ -1,3 +1,3 @@ module.exports = { - setupFiles: [] + setupFiles: ["/src/setup-tests.js"] }; diff --git a/packages/esm-config/package-lock.json b/packages/esm-config/package-lock.json index 08d88d291a5c..8d0bdcf60ef3 100644 --- a/packages/esm-config/package-lock.json +++ b/packages/esm-config/package-lock.json @@ -1213,6 +1213,12 @@ "integrity": "sha512-l42BggppR6zLmpfU6fq9HEa2oGPEI8yrSPL3GITjfRInppYFahObbIQOQK3UGxEnyQpltZLaPe75046NOZQikw==", "dev": true }, + "@types/systemjs": { + "version": "0.20.6", + "resolved": "https://registry.npmjs.org/@types/systemjs/-/systemjs-0.20.6.tgz", + "integrity": "sha512-p3yv9sBBJXi3noUG216BpUI7VtVBUAvBIfZNTiDROUY31YBfsFHM4DreS7XMekN8IjtX0ysvCnm6r3WnirnNeA==", + "dev": true + }, "@types/tapable": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/@types/tapable/-/tapable-1.0.4.tgz", @@ -1855,17 +1861,26 @@ } }, "babel-eslint": { - "version": "10.0.3", - "resolved": "https://registry.npmjs.org/babel-eslint/-/babel-eslint-10.0.3.tgz", - "integrity": "sha512-z3U7eMY6r/3f3/JB9mTsLjyxrv0Yb1zb8PCWCLpguxfCzBIZUwy23R1t/XKewP+8mEN2Ck8Dtr4q20z6ce6SoA==", + "version": "11.0.0-beta.0", + "resolved": "https://registry.npmjs.org/babel-eslint/-/babel-eslint-11.0.0-beta.0.tgz", + "integrity": "sha512-GJTX0XL22be/A5sFp1/4qQIOnZJ/KJ8YrA0aW07SZoDXTMLB1KQT0rYl4a9Y5DfJGPuVDVf0bMYyvLLXmXPpHw==", "dev": true, "requires": { - "@babel/code-frame": "^7.0.0", - "@babel/parser": "^7.0.0", - "@babel/traverse": "^7.0.0", - "@babel/types": "^7.0.0", + "eslint-scope": "3.7.1", "eslint-visitor-keys": "^1.0.0", - "resolve": "^1.12.0" + "semver": "^5.6.0" + }, + "dependencies": { + "eslint-scope": { + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-3.7.1.tgz", + "integrity": "sha1-PWPD7f2gLgbgGkUq2IyqzHzctug=", + "dev": true, + "requires": { + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" + } + } } }, "babel-jest": { @@ -2669,6 +2684,176 @@ "typedarray": "^0.0.6" } }, + "concurrently": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/concurrently/-/concurrently-5.0.0.tgz", + "integrity": "sha512-1yDvK8mduTIdxIxV9C60KoiOySUl/lfekpdbI+U5GXaPrgdffEavFa9QZB3vh68oWOpbCC+TuvxXV9YRPMvUrA==", + "dev": true, + "requires": { + "chalk": "^2.4.2", + "date-fns": "^2.0.1", + "lodash": "^4.17.15", + "read-pkg": "^4.0.1", + "rxjs": "^6.5.2", + "spawn-command": "^0.0.2-1", + "supports-color": "^4.5.0", + "tree-kill": "^1.2.1", + "yargs": "^12.0.5" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "cliui": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-4.1.0.tgz", + "integrity": "sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ==", + "dev": true, + "requires": { + "string-width": "^2.1.1", + "strip-ansi": "^4.0.0", + "wrap-ansi": "^2.0.0" + } + }, + "get-caller-file": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz", + "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==", + "dev": true + }, + "has-flag": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", + "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=", + "dev": true + }, + "read-pkg": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-4.0.1.tgz", + "integrity": "sha1-ljYlN48+HE1IyFhytabsfV0JMjc=", + "dev": true, + "requires": { + "normalize-package-data": "^2.3.2", + "parse-json": "^4.0.0", + "pify": "^3.0.0" + } + }, + "require-main-filename": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", + "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=", + "dev": true + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true, + "requires": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + } + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" + } + }, + "supports-color": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz", + "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=", + "dev": true, + "requires": { + "has-flag": "^2.0.0" + } + }, + "wrap-ansi": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", + "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", + "dev": true, + "requires": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "dev": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + } + } + }, + "yargs": { + "version": "12.0.5", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-12.0.5.tgz", + "integrity": "sha512-Lhz8TLaYnxq/2ObqHDql8dX8CJi97oHxrjUcYtzKbbykPtVW9WB+poxI+NM2UIzsMgNCZTIf0AQwsjK5yMAqZw==", + "dev": true, + "requires": { + "cliui": "^4.0.0", + "decamelize": "^1.2.0", + "find-up": "^3.0.0", + "get-caller-file": "^1.0.1", + "os-locale": "^3.0.0", + "require-directory": "^2.1.1", + "require-main-filename": "^1.0.1", + "set-blocking": "^2.0.0", + "string-width": "^2.0.0", + "which-module": "^2.0.0", + "y18n": "^3.2.1 || ^4.0.0", + "yargs-parser": "^11.1.1" + } + }, + "yargs-parser": { + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-11.1.1.tgz", + "integrity": "sha512-C6kB/WJDiaxONLJQnF8ccx9SEeoTTLek8RVbaOIsrAUS8VrBEXfmeSnCZxygc+XC2sNMBIwOOnfcxiynjHsVSQ==", + "dev": true, + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } + } + } + }, "connect-history-api-fallback": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-1.6.0.tgz", @@ -2934,6 +3119,12 @@ } } }, + "date-fns": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.6.0.tgz", + "integrity": "sha512-F55YxqRdEfP/eYQmQjLN798v0AwLjmZ8nMBjdQvNwEE3N/zWVrlkkqT+9seBlPlsbkybG4JmWg3Ee3dIV9BcGQ==", + "dev": true + }, "date-now": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz", @@ -8665,6 +8856,12 @@ "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=", "dev": true }, + "spawn-command": { + "version": "0.0.2-1", + "resolved": "https://registry.npmjs.org/spawn-command/-/spawn-command-0.0.2-1.tgz", + "integrity": "sha1-YvXpRmmBwbeW3Fkpk34RycaSG9A=", + "dev": true + }, "spdx-correct": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.0.tgz", @@ -9214,6 +9411,12 @@ "punycode": "^2.1.0" } }, + "tree-kill": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.1.tgz", + "integrity": "sha512-4hjqbObwlh2dLyW4tcz0Ymw0ggoaVDMveUB9w8kFSQScdRLo0gxO9J7WFcUBo+W3C1TLdFIEwNOWebgZZ0RH9Q==", + "dev": true + }, "trim-right": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz", diff --git a/packages/esm-config/package.json b/packages/esm-config/package.json index 3cf257e17dff..ea94202d4d2c 100644 --- a/packages/esm-config/package.json +++ b/packages/esm-config/package.json @@ -37,12 +37,14 @@ "@babel/preset-env": "^7.6.0", "@babel/preset-typescript": "^7.6.0", "@types/jest": "^24.0.18", - "babel-eslint": "^10.0.3", + "@types/systemjs": "^0.20.6", + "babel-eslint": "^11.0.0-beta.0", "babel-jest": "^24.9.0", "babel-loader": "^8.0.6", "babel-plugin-ramda": "^2.0.0", "browserslist-config-openmrs": "^1.0.0", "clean-webpack-plugin": "^3.0.0", + "concurrently": "^5.0.0", "eslint": "^6.5.1", "eslint-config-prettier": "^6.3.0", "eslint-config-ts-important-stuff": "^1.0.0", diff --git a/packages/esm-config/src/module-config/module-config.test.ts b/packages/esm-config/src/module-config/module-config.test.ts index ccdb72cf83c8..ee66f7c10daf 100644 --- a/packages/esm-config/src/module-config/module-config.test.ts +++ b/packages/esm-config/src/module-config/module-config.test.ts @@ -76,3 +76,41 @@ describe("getConfig", () => { expect(config.foo.baz.quy).toBe("xyz"); }); }); + +describe("resolveImportMapConfig", () => { + afterEach(() => { + Config.clearAll(); + (window).System.resolve.mockReset(); + (window).System.import.mockReset(); + }); + + it("gets config file from import map", async () => { + Config.defineConfigSchema("foo-module", { foo: { default: "qux" } }); + const testConfig = { "foo-module": { foo: "bar" } }; + (window).System.resolve = jest.fn(); + (window).System.import = jest.fn().mockResolvedValue(testConfig); + await Config.resolveImportMapConfig(); + const config = Config.getConfig("foo-module"); + expect(config.foo).toBe("bar"); + }); + + it("always puts config file from import map at lowest priority", async () => { + Config.defineConfigSchema("foo-module", { foo: { default: "qux" } }); + const importedConfig = { "foo-module": { foo: "bar" } }; + (window).System.resolve = jest.fn(); + (window).System.import = jest.fn().mockResolvedValue(importedConfig); + const providedConfig = { "foo-module": { foo: "baz" } }; + Config.provide(providedConfig); + await Config.resolveImportMapConfig(); + const config = Config.getConfig("foo-module"); + expect(config.foo).toBe("baz"); + }); + + it("does not 404 when no config file is in the import map", async () => { + Config.defineConfigSchema("foo-module", { foo: { default: "qux" } }); + // this line below is actually all that the test requires, the rest is sanity checking + expect(Config.resolveImportMapConfig).not.toThrow(); + const config = Config.getConfig("foo-module"); + expect(config.foo).toBe("qux"); + }); +}); diff --git a/packages/esm-config/src/module-config/module-config.ts b/packages/esm-config/src/module-config/module-config.ts index 800ad7216def..20f7adb2bbd4 100644 --- a/packages/esm-config/src/module-config/module-config.ts +++ b/packages/esm-config/src/module-config/module-config.ts @@ -6,6 +6,28 @@ const configs: object[] = []; // An object with module names for keys and schemas for values. const schemas = {}; +// resolveImportMapConfig -- not working +// Pull default config file from the import map. Module 'config-file' +// TODO: Get this to actually work +let importMapConfigHasBeenAdded = false; +export async function resolveImportMapConfig() { + if (importMapConfigHasBeenAdded) return; + let importMapConfigExists; + try { + System.resolve("config-file"); + importMapConfigExists = true; + } catch { + importMapConfigExists = false; + } + + if (importMapConfigExists) { + await System.import("config-file").then(res => { + configs.unshift(res); + importMapConfigHasBeenAdded = true; + }); + } +} + export function defineConfigSchema(moduleName, schema) { // console.log( "defineConfigSchema received schema for " + moduleName + ": " + JSON.stringify(schema)); schemas[moduleName] = schema; diff --git a/packages/esm-config/src/setup-tests.js b/packages/esm-config/src/setup-tests.js new file mode 100644 index 000000000000..da97af9e3082 --- /dev/null +++ b/packages/esm-config/src/setup-tests.js @@ -0,0 +1,9 @@ +window.System = { + import: jest + .fn() + .mockRejectedValue(new Error("config.json not available in import map")), + resolve: jest.fn().mockImplementation(() => { + throw new Error("config.json not available in import map"); + }), + register: jest.fn() +}; diff --git a/packages/esm-config/webpack.config.js b/packages/esm-config/webpack.config.js index b2e1fbc9b1da..5ceee35d42ec 100644 --- a/packages/esm-config/webpack.config.js +++ b/packages/esm-config/webpack.config.js @@ -27,7 +27,6 @@ module.exports = { resolve: { extensions: [".ts", ".js", ".tsx", ".jsx"] }, - externals: ["openmrs-config"], plugins: [new CleanWebpackPlugin(), new ForkTsCheckerWebpackPlugin()], devServer: { disableHostCheck: true,