Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'config/plugins/graphql_known_operations_plugin.js')
-rw-r--r--config/plugins/graphql_known_operations_plugin.js112
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;