diff --git a/CHANGELOG.md b/CHANGELOG.md index 1769f7e24d..e00eea7321 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased +### New features + +- [#2382: Make any npm module a plugin via a proxy plugin config](https://github.com/alphagov/govuk-prototype-kit/pull/2382) + ## 13.15.3 ### Fixes diff --git a/lib/manage-prototype-handlers.js b/lib/manage-prototype-handlers.js index aca27037f4..bcab6d9171 100644 --- a/lib/manage-prototype-handlers.js +++ b/lib/manage-prototype-handlers.js @@ -444,7 +444,11 @@ async function prepareForPluginPage (isInstalledPage, search) { const plugins = isInstalledPage ? installedPlugins : allPlugins.filter(plugin => { - const pluginName = plugin.packageName?.toLowerCase() + const { packageName, available, installed } = plugin || {} + const pluginName = packageName?.toLowerCase() + if (!pluginName || (!available && !installed)) { + return false + } return pluginName.indexOf(search.toLowerCase()) >= 0 }) diff --git a/lib/manage-prototype-handlers.test.js b/lib/manage-prototype-handlers.test.js index 591b73d2ff..a0d0b57385 100644 --- a/lib/manage-prototype-handlers.test.js +++ b/lib/manage-prototype-handlers.test.js @@ -60,6 +60,7 @@ jest.mock('../known-plugins.json', () => { plugins: {} } }) + jest.mock('fs-extra', () => { return { readFile: jest.fn().mockResolvedValue(''), @@ -90,6 +91,12 @@ jest.mock('./plugins/plugins', () => { } }) +jest.mock('./plugins/plugin-utils', () => { + return { + getProxyPluginConfig: jest.fn().mockReturnValue({}) + } +}) + jest.mock('./plugins/packages', () => { const packageWithPluginConfig = { packageName: 'test-package', diff --git a/lib/plugins/plugin-utils.js b/lib/plugins/plugin-utils.js index 63154073d7..c673591fb6 100644 --- a/lib/plugins/plugin-utils.js +++ b/lib/plugins/plugin-utils.js @@ -1,6 +1,12 @@ // This allows npm modules to act as if they are plugins by providing the plugin config for them +const fs = require('fs') +const fse = require('fs-extra') +const { projectDir } = require('../utils/paths') +const path = require('path') + +let proxyPluginError = false function getProxyPluginConfig (packageName) { - const proxyPluginConfig = { + let proxyPluginConfig = { jquery: { scripts: ['/dist/jquery.js'], assets: ['/dist'], @@ -14,6 +20,23 @@ function getProxyPluginConfig (packageName) { } } } + const proxyPluginsPath = path.join(projectDir, 'app', 'plugin-proxy.json') + if (fse.existsSync(proxyPluginsPath)) { + let userProxyPluginsContent + try { + userProxyPluginsContent = fs.readFileSync(proxyPluginsPath, 'utf8') + const userProxyPlugins = JSON.parse(userProxyPluginsContent) + proxyPluginConfig = { ...proxyPluginConfig, ...userProxyPlugins } + proxyPluginError = false + } catch (err) { + if (!proxyPluginError) { + console.error(err.message) + console.error(proxyPluginsPath) + console.error(userProxyPluginsContent) + proxyPluginError = true + } + } + } return proxyPluginConfig[packageName] ? { ...proxyPluginConfig[packageName] } : undefined } diff --git a/lib/plugins/plugin-utils.spec.js b/lib/plugins/plugin-utils.spec.js new file mode 100644 index 0000000000..c64e9fb845 --- /dev/null +++ b/lib/plugins/plugin-utils.spec.js @@ -0,0 +1,40 @@ +/* eslint-env jest */ + +// npm dependencies +const fs = require('fs') + +// local dependencies +const { getProxyPluginConfig } = require('./plugin-utils') + +const testPluginConfig = { + scripts: './dist/test-script.js' +} +jest.mock('fs-extra', () => { + return { + existsSync: jest.fn().mockReturnValue(true) + } +}) + +describe('getProxyPluginConfig', () => { + beforeEach(() => { + jest.spyOn(fs, 'readFileSync').mockImplementation(() => { + return JSON.stringify({ + 'test-plugin-config': testPluginConfig + }) + }) + }) + + afterEach(() => { + jest.restoreAllMocks() + }) + + it('get jquery proxy plugin config', () => { + const pluginConfig = getProxyPluginConfig('jquery') + expect(Object.keys(pluginConfig)).toEqual(['scripts', 'assets', 'meta']) + }) + + it('get test script proxy plugin config', () => { + const pluginConfig = getProxyPluginConfig('test-plugin-config') + expect(pluginConfig).toEqual(testPluginConfig) + }) +}) diff --git a/lib/plugins/plugins.js b/lib/plugins/plugins.js index eb3c088512..f8523286cc 100644 --- a/lib/plugins/plugins.js +++ b/lib/plugins/plugins.js @@ -173,7 +173,11 @@ let pluginsByType * @private */ function setPluginsByType () { - pluginsByType = getPluginsByType() + try { + pluginsByType = getPluginsByType() + } catch (err) { + pluginsByType = {} + } } setPluginsByType()