@graphql-codegen/hasura-allow-list 1.1.1-alpha-7e47fba48.0 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/cjs/index.js CHANGED
@@ -42,20 +42,59 @@ function getOperationFragmentsRecursively(operationDefinition, fragmentDefinitio
42
42
  });
43
43
  }
44
44
  }
45
+ /**
46
+ * Gets a list of fragments from all documents. Will enforce fragment name uniqueness
47
+ * @param documents All the documents from which fragments will be extracted
48
+ * @returns global fragment definitions, guaranteed to have unique names
49
+ */
50
+ function getGlobalFragments(documents) {
51
+ // keep a dictionary of each fragment and its location for better error messages
52
+ const fragmentDictionary = new Map();
53
+ // iterate over each document's fragments, and add them to the map
54
+ for (const document of documents) {
55
+ const fragmentDefinitions = document.document.definitions.filter(namedFragmentDefinitionFilter);
56
+ for (const fragment of fragmentDefinitions) {
57
+ const fragmentName = fragment.name.value;
58
+ // if the map already has a fragment by that name, throw an error with locations for both definitions
59
+ if (fragmentDictionary.has(fragment.name.value)) {
60
+ const locationA = document.location;
61
+ const locationB = fragmentDictionary.get(fragmentName);
62
+ throw new Error(`Duplicate fragment definitions for ${fragmentName} in files ${locationA}, ${locationB}`);
63
+ }
64
+ fragmentDictionary.set(fragmentName, document.location);
65
+ }
66
+ }
67
+ return documents.flatMap(document => document.document.definitions.filter(namedFragmentDefinitionFilter));
68
+ }
69
+ function getDocumentFragments(document) {
70
+ return document.document.definitions.filter(namedFragmentDefinitionFilter);
71
+ }
72
+ function namedOperationDefinitionFilter(definition) {
73
+ return definition.kind === graphql_1.Kind.OPERATION_DEFINITION && !!definition.name;
74
+ }
75
+ function namedFragmentDefinitionFilter(definition) {
76
+ return definition.kind === graphql_1.Kind.FRAGMENT_DEFINITION && !!definition.name;
77
+ }
45
78
  const plugin = async (schema, documents, config) => {
46
79
  var _a;
80
+ if ('config_version' in config) {
81
+ throw new Error(`[hasura allow list plugin] Configuration error: configuration property config_version has been renamed configVersion. Please update your configuration accordingly.`);
82
+ }
83
+ if ('collection_name' in config) {
84
+ throw new Error(`[hasura allow list plugin] Configuration error: configuration property collection_name has been renamed collectionName. Please update your configuration accordingly.`);
85
+ }
47
86
  const queries = [];
48
- // each document (graphql file) is handled independently.
49
- // any fragment required by an operation will need to be definied in the same file as the operation.
87
+ // if config globalFragments is set, get fragments from all documents
88
+ const globalFragments = !config.globalFragments ? false : getGlobalFragments(documents);
50
89
  for (const document of documents) {
51
90
  // filter out anonymous operations
52
- const documentOperations = document.document.definitions.filter((definition) => definition.kind === graphql_1.Kind.OPERATION_DEFINITION && !!definition.name);
53
- // filter out anonymous fragments
54
- const documentFragments = document.document.definitions.filter((definition) => definition.kind === graphql_1.Kind.FRAGMENT_DEFINITION && !!definition.name);
91
+ const documentOperations = document.document.definitions.filter(namedOperationDefinitionFilter);
92
+ // depending on globalFragments settings, either use document level or global level fragments
93
+ const fragments = globalFragments || getDocumentFragments(document);
55
94
  // for each operation in the document
56
95
  for (const operation of documentOperations) {
57
96
  // get fragments required by the operations
58
- const requiredFragmentDefinitions = getOperationFragmentsRecursively(operation, documentFragments, document.location);
97
+ const requiredFragmentDefinitions = getOperationFragmentsRecursively(operation, fragments, document.location);
59
98
  // insert the operation and any fragments to our queries definition.
60
99
  // fragment order is preserved, and each fragment is separated by a new line
61
100
  queries.push({
@@ -66,7 +105,7 @@ const plugin = async (schema, documents, config) => {
66
105
  }
67
106
  return yaml_1.default.stringify([
68
107
  {
69
- name: (_a = config.collection_name) !== null && _a !== void 0 ? _a : 'allowed-queries',
108
+ name: (_a = config.collectionName) !== null && _a !== void 0 ? _a : 'allowed-queries',
70
109
  definition: {
71
110
  queries,
72
111
  },
package/esm/index.js CHANGED
@@ -38,20 +38,59 @@ function getOperationFragmentsRecursively(operationDefinition, fragmentDefinitio
38
38
  });
39
39
  }
40
40
  }
41
+ /**
42
+ * Gets a list of fragments from all documents. Will enforce fragment name uniqueness
43
+ * @param documents All the documents from which fragments will be extracted
44
+ * @returns global fragment definitions, guaranteed to have unique names
45
+ */
46
+ function getGlobalFragments(documents) {
47
+ // keep a dictionary of each fragment and its location for better error messages
48
+ const fragmentDictionary = new Map();
49
+ // iterate over each document's fragments, and add them to the map
50
+ for (const document of documents) {
51
+ const fragmentDefinitions = document.document.definitions.filter(namedFragmentDefinitionFilter);
52
+ for (const fragment of fragmentDefinitions) {
53
+ const fragmentName = fragment.name.value;
54
+ // if the map already has a fragment by that name, throw an error with locations for both definitions
55
+ if (fragmentDictionary.has(fragment.name.value)) {
56
+ const locationA = document.location;
57
+ const locationB = fragmentDictionary.get(fragmentName);
58
+ throw new Error(`Duplicate fragment definitions for ${fragmentName} in files ${locationA}, ${locationB}`);
59
+ }
60
+ fragmentDictionary.set(fragmentName, document.location);
61
+ }
62
+ }
63
+ return documents.flatMap(document => document.document.definitions.filter(namedFragmentDefinitionFilter));
64
+ }
65
+ function getDocumentFragments(document) {
66
+ return document.document.definitions.filter(namedFragmentDefinitionFilter);
67
+ }
68
+ function namedOperationDefinitionFilter(definition) {
69
+ return definition.kind === Kind.OPERATION_DEFINITION && !!definition.name;
70
+ }
71
+ function namedFragmentDefinitionFilter(definition) {
72
+ return definition.kind === Kind.FRAGMENT_DEFINITION && !!definition.name;
73
+ }
41
74
  export const plugin = async (schema, documents, config) => {
42
75
  var _a;
76
+ if ('config_version' in config) {
77
+ throw new Error(`[hasura allow list plugin] Configuration error: configuration property config_version has been renamed configVersion. Please update your configuration accordingly.`);
78
+ }
79
+ if ('collection_name' in config) {
80
+ throw new Error(`[hasura allow list plugin] Configuration error: configuration property collection_name has been renamed collectionName. Please update your configuration accordingly.`);
81
+ }
43
82
  const queries = [];
44
- // each document (graphql file) is handled independently.
45
- // any fragment required by an operation will need to be definied in the same file as the operation.
83
+ // if config globalFragments is set, get fragments from all documents
84
+ const globalFragments = !config.globalFragments ? false : getGlobalFragments(documents);
46
85
  for (const document of documents) {
47
86
  // filter out anonymous operations
48
- const documentOperations = document.document.definitions.filter((definition) => definition.kind === Kind.OPERATION_DEFINITION && !!definition.name);
49
- // filter out anonymous fragments
50
- const documentFragments = document.document.definitions.filter((definition) => definition.kind === Kind.FRAGMENT_DEFINITION && !!definition.name);
87
+ const documentOperations = document.document.definitions.filter(namedOperationDefinitionFilter);
88
+ // depending on globalFragments settings, either use document level or global level fragments
89
+ const fragments = globalFragments || getDocumentFragments(document);
51
90
  // for each operation in the document
52
91
  for (const operation of documentOperations) {
53
92
  // get fragments required by the operations
54
- const requiredFragmentDefinitions = getOperationFragmentsRecursively(operation, documentFragments, document.location);
93
+ const requiredFragmentDefinitions = getOperationFragmentsRecursively(operation, fragments, document.location);
55
94
  // insert the operation and any fragments to our queries definition.
56
95
  // fragment order is preserved, and each fragment is separated by a new line
57
96
  queries.push({
@@ -62,7 +101,7 @@ export const plugin = async (schema, documents, config) => {
62
101
  }
63
102
  return yaml.stringify([
64
103
  {
65
- name: (_a = config.collection_name) !== null && _a !== void 0 ? _a : 'allowed-queries',
104
+ name: (_a = config.collectionName) !== null && _a !== void 0 ? _a : 'allowed-queries',
66
105
  definition: {
67
106
  queries,
68
107
  },
package/package.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@graphql-codegen/hasura-allow-list",
3
- "version": "1.1.1-alpha-7e47fba48.0",
3
+ "version": "2.0.0",
4
4
  "description": "GraphQL Code Generator plugin to generate hasura allow liste metadata from graphql files",
5
5
  "peerDependencies": {
6
6
  "graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0"
7
7
  },
8
8
  "dependencies": {
9
- "@graphql-codegen/plugin-helpers": "^2.6.1-alpha-7e47fba48.0",
9
+ "@graphql-codegen/plugin-helpers": "^2.6.2",
10
10
  "tslib": "~2.4.0",
11
11
  "yaml": "^1.10.2"
12
12
  },
@@ -26,7 +26,7 @@
26
26
  "exports": {
27
27
  ".": {
28
28
  "require": {
29
- "types": "./typings/index.d.ts",
29
+ "types": "./typings/index.d.cts",
30
30
  "default": "./cjs/index.js"
31
31
  },
32
32
  "import": {
@@ -0,0 +1,19 @@
1
+ export interface HasuraAllowListPluginConfig {
2
+ /**
3
+ * @default allowed-queries
4
+ * @description Choose the collection name to be generated. Defaults to allowed-queries
5
+ */
6
+ collectionName?: string;
7
+ /**
8
+ * @default 3
9
+ * @description Target metadata config version. Supported versions are 2 and 3.
10
+ * This is mostly for future proofing, currently has no impact as both versions use the same format.
11
+ * The default value _will change_ in the future if/when newer config versions are released.
12
+ */
13
+ configVersion?: 2 | 3;
14
+ /**
15
+ * @default false
16
+ * @description Whether to source fragments per-document, or globally. If set, will enforce fragment name uniqueness
17
+ */
18
+ globalFragments?: boolean;
19
+ }
@@ -3,12 +3,17 @@ export interface HasuraAllowListPluginConfig {
3
3
  * @default allowed-queries
4
4
  * @description Choose the collection name to be generated. Defaults to allowed-queries
5
5
  */
6
- collection_name?: string;
6
+ collectionName?: string;
7
7
  /**
8
8
  * @default 3
9
9
  * @description Target metadata config version. Supported versions are 2 and 3.
10
10
  * This is mostly for future proofing, currently has no impact as both versions use the same format.
11
11
  * The default value _will change_ in the future if/when newer config versions are released.
12
12
  */
13
- config_version?: 2 | 3;
13
+ configVersion?: 2 | 3;
14
+ /**
15
+ * @default false
16
+ * @description Whether to source fragments per-document, or globally. If set, will enforce fragment name uniqueness
17
+ */
18
+ globalFragments?: boolean;
14
19
  }
@@ -0,0 +1,7 @@
1
+ import { PluginFunction, Types } from '@graphql-codegen/plugin-helpers';
2
+ import { HasuraAllowListPluginConfig } from './config.cjs';
3
+ export declare const plugin: PluginFunction<HasuraAllowListPluginConfig>;
4
+ declare const _default: {
5
+ plugin: PluginFunction<HasuraAllowListPluginConfig, Types.PluginOutput>;
6
+ };
7
+ export default _default;