Migrate current override implementation to dedicated service

This commit is contained in:
Mark Kaylor 2023-03-17 10:28:31 +01:00
parent ff971821fb
commit 743139db75
5 changed files with 99 additions and 50 deletions

View File

@ -4,6 +4,7 @@ const fse = require('fs-extra');
const SwaggerParser = require('@apidevtools/swagger-parser');
const { api, plugins, components, contentTypes } = require('../__mocks__/mock-strapi-data');
const documentation = require('../documentation');
const override = require('../override');
const defaultConfig = require('../../config/default-plugin-config');
const mockStrapiInstance = {
@ -18,7 +19,7 @@ const mockStrapiInstance = {
api,
plugins,
config: {
get: jest.fn(() => defaultConfig),
get: () => defaultConfig,
},
log: {
info: jest.fn(),
@ -42,6 +43,16 @@ describe('Documentation service', () => {
return global.strapi.contentTypes[uid];
});
global.strapi.plugin = jest.fn((name) => global.strapi.plugins[name]);
global.strapi.plugins.documentation = {
service: jest.fn((name) => {
const mockServices = {
override: override({ strapi: global.strapi }),
};
return mockServices[name];
}),
};
});
afterAll(() => {
@ -49,6 +60,11 @@ describe('Documentation service', () => {
global.strapi = {};
});
afterEach(() => {
// Reset the mocked strapi config
global.strapi.config.get = () => defaultConfig;
});
it('generates a valid openapi schema', async () => {
const docService = documentation({ strapi: global.strapi });
await docService.generateFullDoc();
@ -72,7 +88,7 @@ describe('Documentation service', () => {
});
it("generates documentation only for plugins in the user's config", async () => {
global.strapi.config.get.mockReturnValueOnce({
global.strapi.config.get = () => ({
...defaultConfig,
'x-strapi-config': { ...defaultConfig['x-strapi-config'], plugins: ['upload'] },
});
@ -86,7 +102,7 @@ describe('Documentation service', () => {
});
it('does not generate documentation for any plugins', async () => {
global.strapi.config.get.mockReturnValueOnce({
global.strapi.config.get = () => ({
...defaultConfig,
'x-strapi-config': { ...defaultConfig['x-strapi-config'], plugins: [] },
});
@ -138,7 +154,7 @@ describe('Documentation service', () => {
},
],
};
global.strapi.config.get.mockReturnValueOnce({ ...userConfig });
global.strapi.config.get = () => ({ ...userConfig });
const docService = documentation({ strapi: global.strapi });
await docService.generateFullDoc();
const lastMockCall = fse.writeJson.mock.calls[fse.writeJson.mock.calls.length - 1];
@ -150,8 +166,9 @@ describe('Documentation service', () => {
expect(mockFinalDoc.security).toEqual(userConfig.security);
expect(mockFinalDoc.webhooks).toEqual(userConfig.webhooks);
});
it("does not apply an override if the plugin providing the override isn't specified in the x-strapi-config.plugins", async () => {
global.strapi.config.get.mockReturnValueOnce({
global.strapi.config.get = () => ({
...defaultConfig,
'x-strapi-config': { ...defaultConfig['x-strapi-config'], plugins: [] },
});

View File

@ -8,54 +8,23 @@ const { getAbsoluteServerUrl } = require('@strapi/utils');
const { builApiEndpointPath, buildComponentSchema } = require('./helpers');
const defaultOpenApiComponents = require('./utils/default-openapi-components');
const { getPluginsThatNeedDocumentation } = require('./utils/get-plugins-that-need-documentation');
module.exports = ({ strapi }) => {
console.log('documentation arg', strapi.config.get());
const config = strapi.config.get('plugin.documentation');
const registeredDocs = [];
const pluginsThatNeedDocumentation = getPluginsThatNeedDocumentation(config);
const getPluginsThatNeedDocumentation = () => {
// Default plugins that need documentation generated
const defaultPlugins = ['upload', 'users-permissions'];
// User specified plugins that need documentation generated
const userPluginsConfig = config['x-strapi-config'].plugins;
if (userPluginsConfig === null) {
// The user hasn't specified any plugins to document, use the defaults
return defaultPlugins;
}
if (userPluginsConfig.length) {
// The user has specified certain plugins to document, use them
return userPluginsConfig;
}
// The user has specified that no plugins should be documented
return [];
};
const overrideService = strapi.plugin('documentation').service('override');
return {
/**
* @TODO: Make both parameters required in next major release
* @param {*} doc - The openapi specifcation to override
* @param {*} pluginOrigin - The name of the plugin that is overriding the documentation
*/
registerDoc(doc, pluginOrigin) {
const plugins = getPluginsThatNeedDocumentation();
let registeredDoc = doc;
if (pluginOrigin) {
if (!plugins.includes(pluginOrigin)) {
return strapi.log.info(
`@strapi/documentation will not use the override provided by ${pluginOrigin} since the plugin was not specified in the x-strapi-config.plugins array`
);
}
} else {
strapi.log.warn(
'@strapi/documentation received an override that did not specify its origin, this could cause unexpected schema generation'
);
}
// parseYaml
if (typeof doc === 'string') {
registeredDoc = require('yaml').parse(registeredDoc);
}
// receive an object we can register it directly
registeredDocs.push(registeredDoc);
overrideService.registerDoc(doc, pluginOrigin);
},
getDocumentationVersion() {
@ -138,8 +107,7 @@ module.exports = ({ strapi }) => {
},
getPluginAndApiInfo() {
const plugins = getPluginsThatNeedDocumentation();
const pluginsToDocument = plugins.map((plugin) => {
const pluginsToDocument = pluginsThatNeedDocumentation.map((plugin) => {
return {
name: plugin,
getter: 'plugin',
@ -209,7 +177,7 @@ module.exports = ({ strapi }) => {
]);
_.set(config, ['info', 'x-generation-date'], new Date().toISOString());
_.set(config, ['info', 'version'], version);
_.set(config, ['x-strapi-config', 'plugins'], getPluginsThatNeedDocumentation());
_.set(config, ['x-strapi-config', 'plugins'], pluginsThatNeedDocumentation);
// Prepare final doc with default config and generated paths
const finalDoc = { ...config, paths };
// Add the default components to the final doc
@ -217,7 +185,7 @@ module.exports = ({ strapi }) => {
// Merge the generated component schemas with the defaults
_.merge(finalDoc.components, { schemas });
// Apply the the registered overrides
registeredDocs.forEach((doc) => {
overrideService.registeredDocs.forEach((doc) => {
// Merge ovveride tags with the generated tags
finalDoc.tags = finalDoc.tags || [];
finalDoc.tags.push(...(doc.tags || []));

View File

@ -1,7 +1,9 @@
'use strict';
const documentation = require('./documentation');
const override = require('./override');
module.exports = {
documentation,
override,
};

View File

@ -0,0 +1,38 @@
'use strict';
const { getPluginsThatNeedDocumentation } = require('./utils/get-plugins-that-need-documentation');
module.exports = ({ strapi }) => {
const registeredDocs = [];
return {
registeredDocs,
registerDoc(doc, pluginOrigin) {
const pluginsThatNeedDocumentation = getPluginsThatNeedDocumentation(
strapi.config.get('plugin.documentation')
);
console.log('adding override from', pluginOrigin, doc);
let registeredDoc = doc;
if (pluginOrigin) {
if (!pluginsThatNeedDocumentation.includes(pluginOrigin)) {
return strapi.log.info(
`@strapi/documentation will not use the override provided by ${pluginOrigin} since the plugin was not specified in the x-strapi-config.plugins array`
);
}
} else {
strapi.log.warn(
'@strapi/documentation received an override that did not specify its origin, this could cause unexpected schema generation'
);
}
// parseYaml
if (typeof doc === 'string') {
registeredDoc = require('yaml').parse(registeredDoc);
}
// receive an object we can register it directly
registeredDocs.push(registeredDoc);
console.log('adding override', registeredDocs);
},
};
};

View File

@ -0,0 +1,24 @@
'use strict';
const getPluginsThatNeedDocumentation = (config) => {
// Default plugins that need documentation generated
const defaultPlugins = ['upload', 'users-permissions'];
// User specified plugins that need documentation generated
const userPluginsConfig = config['x-strapi-config'].plugins;
if (userPluginsConfig === null) {
// The user hasn't specified any plugins to document, use the defaults
return defaultPlugins;
}
if (userPluginsConfig.length) {
// The user has specified certain plugins to document, use them
return userPluginsConfig;
}
// The user has specified that no plugins should be documented
return [];
};
module.exports = { getPluginsThatNeedDocumentation };