diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2021-11-18 13:16:36 +0000 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2021-11-18 13:16:36 +0000 |
commit | 311b0269b4eb9839fa63f80c8d7a58f32b8138a0 (patch) | |
tree | 07e7870bca8aed6d61fdcc810731c50d2c40af47 /config/plugins | |
parent | 27909cef6c4170ed9205afa7426b8d3de47cbb0c (diff) | |
download | gitlab-ce-311b0269b4eb9839fa63f80c8d7a58f32b8138a0.tar.gz |
Add latest changes from gitlab-org/gitlab@14-5-stable-eev14.5.0-rc42
Diffstat (limited to 'config/plugins')
-rw-r--r-- | config/plugins/graphql_known_operations_plugin.js | 112 |
1 files changed, 112 insertions, 0 deletions
diff --git a/config/plugins/graphql_known_operations_plugin.js b/config/plugins/graphql_known_operations_plugin.js new file mode 100644 index 00000000000..164b34c1dd1 --- /dev/null +++ b/config/plugins/graphql_known_operations_plugin.js @@ -0,0 +1,112 @@ +/* eslint-disable no-underscore-dangle */ +const yaml = require('js-yaml'); + +const PLUGIN_NAME = 'GraphqlKnownOperationsPlugin'; +const GRAPHQL_PATH_REGEX = /(query|mutation)\.graphql$/; +const OPERATION_NAME_SOURCE_REGEX = /^\s*module\.exports.*oneQuery.*"(\w+)"/gm; + +/** + * Returns whether a given webpack module is a "graphql" module + */ +const isGraphqlModule = (module) => { + return GRAPHQL_PATH_REGEX.test(module.resource); +}; + +/** + * Returns graphql operation names we can parse from the given module + * + * Since webpack gives us the source **after** the graphql-tag/loader runs, + * we can look for specific lines we're guaranteed to have from the + * graphql-tag/loader. + */ +const getOperationNames = (module) => { + const originalSource = module.originalSource(); + + if (!originalSource) { + return []; + } + + const matches = originalSource.source().toString().matchAll(OPERATION_NAME_SOURCE_REGEX); + + return Array.from(matches).map((match) => match[1]); +}; + +const createFileContents = (knownOperations) => { + const sourceData = Array.from(knownOperations.values()).sort((a, b) => a.localeCompare(b)); + + return yaml.dump(sourceData); +}; + +/** + * Creates a webpack4 compatible "RawSource" + * + * Inspired from https://sourcegraph.com/github.com/FormidableLabs/webpack-stats-plugin@e050ff8c362d5ddd45c66ade724d4a397ace3e5c/-/blob/lib/stats-writer-plugin.js?L144 + */ +const createWebpackRawSource = (source) => { + const buff = Buffer.from(source, 'utf-8'); + + return { + source() { + return buff; + }, + size() { + return buff.length; + }, + }; +}; + +const onSucceedModule = ({ module, knownOperations }) => { + if (!isGraphqlModule(module)) { + return; + } + + getOperationNames(module).forEach((x) => knownOperations.add(x)); +}; + +const onCompilerEmit = ({ compilation, knownOperations, filename }) => { + const contents = createFileContents(knownOperations); + const source = createWebpackRawSource(contents); + + const asset = compilation.getAsset(filename); + if (asset) { + compilation.updateAsset(filename, source); + } else { + compilation.emitAsset(filename, source); + } +}; + +/** + * Webpack plugin that outputs a file containing known graphql operations. + * + * A lot of the mechanices was expired from [this example][1]. + * + * [1]: https://sourcegraph.com/github.com/FormidableLabs/webpack-stats-plugin@e050ff8c362d5ddd45c66ade724d4a397ace3e5c/-/blob/lib/stats-writer-plugin.js?L136 + */ +class GraphqlKnownOperationsPlugin { + constructor({ filename }) { + this._filename = filename; + } + + apply(compiler) { + const knownOperations = new Set(); + + compiler.hooks.emit.tap(PLUGIN_NAME, (compilation) => { + onCompilerEmit({ + compilation, + knownOperations, + filename: this._filename, + }); + }); + + compiler.hooks.compilation.tap(PLUGIN_NAME, (compilation) => { + compilation.hooks.succeedModule.tap(PLUGIN_NAME, (module) => { + onSucceedModule({ + module, + knownOperations, + }); + }); + }); + } +} + +module.exports = GraphqlKnownOperationsPlugin; |