@graphql-tools/merge 8.3.18 → 8.4.0-alpha-20230301043849-3d59d581
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/typedefs-mergers/arguments.js +7 -4
- package/cjs/typedefs-mergers/fields.js +24 -28
- package/esm/typedefs-mergers/arguments.js +7 -4
- package/esm/typedefs-mergers/fields.js +24 -28
- package/package.json +1 -1
- package/typings/typedefs-mergers/fields.d.cts +7 -1
- package/typings/typedefs-mergers/fields.d.ts +7 -1
- package/typings/typedefs-mergers/merge-typedefs.d.cts +18 -0
- package/typings/typedefs-mergers/merge-typedefs.d.ts +18 -0
|
@@ -3,19 +3,22 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.mergeArguments = void 0;
|
|
4
4
|
const utils_1 = require("@graphql-tools/utils");
|
|
5
5
|
function mergeArguments(args1, args2, config) {
|
|
6
|
-
const result = deduplicateArguments([...args2, ...args1].filter(utils_1.isSome));
|
|
6
|
+
const result = deduplicateArguments([...args2, ...args1].filter(utils_1.isSome), config);
|
|
7
7
|
if (config && config.sort) {
|
|
8
8
|
result.sort(utils_1.compareNodes);
|
|
9
9
|
}
|
|
10
10
|
return result;
|
|
11
11
|
}
|
|
12
12
|
exports.mergeArguments = mergeArguments;
|
|
13
|
-
function deduplicateArguments(args) {
|
|
13
|
+
function deduplicateArguments(args, config) {
|
|
14
14
|
return args.reduce((acc, current) => {
|
|
15
|
-
const
|
|
16
|
-
if (
|
|
15
|
+
const dupIndex = acc.findIndex(arg => arg.name.value === current.name.value);
|
|
16
|
+
if (dupIndex === -1) {
|
|
17
17
|
return acc.concat([current]);
|
|
18
18
|
}
|
|
19
|
+
else if (!(config === null || config === void 0 ? void 0 : config.reverseArguments)) {
|
|
20
|
+
acc[dupIndex] = current;
|
|
21
|
+
}
|
|
19
22
|
return acc;
|
|
20
23
|
}, []);
|
|
21
24
|
}
|
|
@@ -5,16 +5,9 @@ const utils_js_1 = require("./utils.js");
|
|
|
5
5
|
const directives_js_1 = require("./directives.js");
|
|
6
6
|
const utils_1 = require("@graphql-tools/utils");
|
|
7
7
|
const arguments_js_1 = require("./arguments.js");
|
|
8
|
-
function fieldAlreadyExists(fieldsArr, otherField
|
|
9
|
-
const
|
|
10
|
-
|
|
11
|
-
const t1 = (0, utils_js_1.extractType)(result.type);
|
|
12
|
-
const t2 = (0, utils_js_1.extractType)(otherField.type);
|
|
13
|
-
if (t1.name.value !== t2.name.value) {
|
|
14
|
-
throw new Error(`Field "${otherField.name.value}" already defined with a different type. Declared as "${t1.name.value}", but you tried to override with "${t2.name.value}"`);
|
|
15
|
-
}
|
|
16
|
-
}
|
|
17
|
-
return !!result;
|
|
8
|
+
function fieldAlreadyExists(fieldsArr, otherField) {
|
|
9
|
+
const resultIndex = fieldsArr.findIndex(field => field.name.value === otherField.name.value);
|
|
10
|
+
return [resultIndex > -1 ? fieldsArr[resultIndex] : null, resultIndex];
|
|
18
11
|
}
|
|
19
12
|
function mergeFields(type, f1, f2, config) {
|
|
20
13
|
const result = [];
|
|
@@ -23,22 +16,14 @@ function mergeFields(type, f1, f2, config) {
|
|
|
23
16
|
}
|
|
24
17
|
if (f1 != null) {
|
|
25
18
|
for (const field of f1) {
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
}
|
|
35
|
-
if ((0, utils_js_1.isNonNullTypeNode)(field.type) && !(0, utils_js_1.isNonNullTypeNode)(existing.type)) {
|
|
36
|
-
existing.type = field.type;
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
existing.arguments = (0, arguments_js_1.mergeArguments)(field['arguments'] || [], existing.arguments || [], config);
|
|
40
|
-
existing.directives = (0, directives_js_1.mergeDirectives)(field.directives, existing.directives, config);
|
|
41
|
-
existing.description = field.description || existing.description;
|
|
19
|
+
const [existing, existingIndex] = fieldAlreadyExists(result, field);
|
|
20
|
+
if (existing && !(config === null || config === void 0 ? void 0 : config.ignoreFieldConflicts)) {
|
|
21
|
+
const newField = ((config === null || config === void 0 ? void 0 : config.onFieldTypeConflict) && config.onFieldTypeConflict(existing, field, type, config === null || config === void 0 ? void 0 : config.throwOnConflict)) ||
|
|
22
|
+
preventConflicts(type, existing, field, config === null || config === void 0 ? void 0 : config.throwOnConflict);
|
|
23
|
+
newField.arguments = (0, arguments_js_1.mergeArguments)(field['arguments'] || [], existing['arguments'] || [], config);
|
|
24
|
+
newField.directives = (0, directives_js_1.mergeDirectives)(field.directives, existing.directives, config);
|
|
25
|
+
newField.description = field.description || existing.description;
|
|
26
|
+
result[existingIndex] = newField;
|
|
42
27
|
}
|
|
43
28
|
else {
|
|
44
29
|
result.push(field);
|
|
@@ -58,9 +43,20 @@ exports.mergeFields = mergeFields;
|
|
|
58
43
|
function preventConflicts(type, a, b, ignoreNullability = false) {
|
|
59
44
|
const aType = (0, utils_js_1.printTypeNode)(a.type);
|
|
60
45
|
const bType = (0, utils_js_1.printTypeNode)(b.type);
|
|
61
|
-
if (aType !== bType
|
|
62
|
-
|
|
46
|
+
if (aType !== bType) {
|
|
47
|
+
const t1 = (0, utils_js_1.extractType)(a.type);
|
|
48
|
+
const t2 = (0, utils_js_1.extractType)(b.type);
|
|
49
|
+
if (t1.name.value !== t2.name.value) {
|
|
50
|
+
throw new Error(`Field "${b.name.value}" already defined with a different type. Declared as "${t1.name.value}", but you tried to override with "${t2.name.value}"`);
|
|
51
|
+
}
|
|
52
|
+
if (!safeChangeForFieldType(a.type, b.type, !ignoreNullability)) {
|
|
53
|
+
throw new Error(`Field '${type.name.value}.${a.name.value}' changed type from '${aType}' to '${bType}'`);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
if ((0, utils_js_1.isNonNullTypeNode)(b.type) && !(0, utils_js_1.isNonNullTypeNode)(a.type)) {
|
|
57
|
+
a.type = b.type;
|
|
63
58
|
}
|
|
59
|
+
return a;
|
|
64
60
|
}
|
|
65
61
|
function safeChangeForFieldType(oldType, newType, ignoreNullability = false) {
|
|
66
62
|
// both are named
|
|
@@ -1,17 +1,20 @@
|
|
|
1
1
|
import { compareNodes, isSome } from '@graphql-tools/utils';
|
|
2
2
|
export function mergeArguments(args1, args2, config) {
|
|
3
|
-
const result = deduplicateArguments([...args2, ...args1].filter(isSome));
|
|
3
|
+
const result = deduplicateArguments([...args2, ...args1].filter(isSome), config);
|
|
4
4
|
if (config && config.sort) {
|
|
5
5
|
result.sort(compareNodes);
|
|
6
6
|
}
|
|
7
7
|
return result;
|
|
8
8
|
}
|
|
9
|
-
function deduplicateArguments(args) {
|
|
9
|
+
function deduplicateArguments(args, config) {
|
|
10
10
|
return args.reduce((acc, current) => {
|
|
11
|
-
const
|
|
12
|
-
if (
|
|
11
|
+
const dupIndex = acc.findIndex(arg => arg.name.value === current.name.value);
|
|
12
|
+
if (dupIndex === -1) {
|
|
13
13
|
return acc.concat([current]);
|
|
14
14
|
}
|
|
15
|
+
else if (!(config === null || config === void 0 ? void 0 : config.reverseArguments)) {
|
|
16
|
+
acc[dupIndex] = current;
|
|
17
|
+
}
|
|
15
18
|
return acc;
|
|
16
19
|
}, []);
|
|
17
20
|
}
|
|
@@ -2,16 +2,9 @@ import { extractType, isWrappingTypeNode, isListTypeNode, isNonNullTypeNode, pri
|
|
|
2
2
|
import { mergeDirectives } from './directives.js';
|
|
3
3
|
import { compareNodes } from '@graphql-tools/utils';
|
|
4
4
|
import { mergeArguments } from './arguments.js';
|
|
5
|
-
function fieldAlreadyExists(fieldsArr, otherField
|
|
6
|
-
const
|
|
7
|
-
|
|
8
|
-
const t1 = extractType(result.type);
|
|
9
|
-
const t2 = extractType(otherField.type);
|
|
10
|
-
if (t1.name.value !== t2.name.value) {
|
|
11
|
-
throw new Error(`Field "${otherField.name.value}" already defined with a different type. Declared as "${t1.name.value}", but you tried to override with "${t2.name.value}"`);
|
|
12
|
-
}
|
|
13
|
-
}
|
|
14
|
-
return !!result;
|
|
5
|
+
function fieldAlreadyExists(fieldsArr, otherField) {
|
|
6
|
+
const resultIndex = fieldsArr.findIndex(field => field.name.value === otherField.name.value);
|
|
7
|
+
return [resultIndex > -1 ? fieldsArr[resultIndex] : null, resultIndex];
|
|
15
8
|
}
|
|
16
9
|
export function mergeFields(type, f1, f2, config) {
|
|
17
10
|
const result = [];
|
|
@@ -20,22 +13,14 @@ export function mergeFields(type, f1, f2, config) {
|
|
|
20
13
|
}
|
|
21
14
|
if (f1 != null) {
|
|
22
15
|
for (const field of f1) {
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
}
|
|
32
|
-
if (isNonNullTypeNode(field.type) && !isNonNullTypeNode(existing.type)) {
|
|
33
|
-
existing.type = field.type;
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
existing.arguments = mergeArguments(field['arguments'] || [], existing.arguments || [], config);
|
|
37
|
-
existing.directives = mergeDirectives(field.directives, existing.directives, config);
|
|
38
|
-
existing.description = field.description || existing.description;
|
|
16
|
+
const [existing, existingIndex] = fieldAlreadyExists(result, field);
|
|
17
|
+
if (existing && !(config === null || config === void 0 ? void 0 : config.ignoreFieldConflicts)) {
|
|
18
|
+
const newField = ((config === null || config === void 0 ? void 0 : config.onFieldTypeConflict) && config.onFieldTypeConflict(existing, field, type, config === null || config === void 0 ? void 0 : config.throwOnConflict)) ||
|
|
19
|
+
preventConflicts(type, existing, field, config === null || config === void 0 ? void 0 : config.throwOnConflict);
|
|
20
|
+
newField.arguments = mergeArguments(field['arguments'] || [], existing['arguments'] || [], config);
|
|
21
|
+
newField.directives = mergeDirectives(field.directives, existing.directives, config);
|
|
22
|
+
newField.description = field.description || existing.description;
|
|
23
|
+
result[existingIndex] = newField;
|
|
39
24
|
}
|
|
40
25
|
else {
|
|
41
26
|
result.push(field);
|
|
@@ -54,9 +39,20 @@ export function mergeFields(type, f1, f2, config) {
|
|
|
54
39
|
function preventConflicts(type, a, b, ignoreNullability = false) {
|
|
55
40
|
const aType = printTypeNode(a.type);
|
|
56
41
|
const bType = printTypeNode(b.type);
|
|
57
|
-
if (aType !== bType
|
|
58
|
-
|
|
42
|
+
if (aType !== bType) {
|
|
43
|
+
const t1 = extractType(a.type);
|
|
44
|
+
const t2 = extractType(b.type);
|
|
45
|
+
if (t1.name.value !== t2.name.value) {
|
|
46
|
+
throw new Error(`Field "${b.name.value}" already defined with a different type. Declared as "${t1.name.value}", but you tried to override with "${t2.name.value}"`);
|
|
47
|
+
}
|
|
48
|
+
if (!safeChangeForFieldType(a.type, b.type, !ignoreNullability)) {
|
|
49
|
+
throw new Error(`Field '${type.name.value}.${a.name.value}' changed type from '${aType}' to '${bType}'`);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
if (isNonNullTypeNode(b.type) && !isNonNullTypeNode(a.type)) {
|
|
53
|
+
a.type = b.type;
|
|
59
54
|
}
|
|
55
|
+
return a;
|
|
60
56
|
}
|
|
61
57
|
function safeChangeForFieldType(oldType, newType, ignoreNullability = false) {
|
|
62
58
|
// both are named
|
package/package.json
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
import { Config } from './merge-typedefs.cjs';
|
|
2
2
|
import { FieldDefinitionNode, InputValueDefinitionNode, NameNode } from 'graphql';
|
|
3
|
-
|
|
3
|
+
type FieldDefNode = FieldDefinitionNode | InputValueDefinitionNode;
|
|
4
|
+
type NamedDefNode = {
|
|
5
|
+
name: NameNode;
|
|
6
|
+
};
|
|
7
|
+
export type OnFieldTypeConflict = (existingField: FieldDefNode, otherField: FieldDefNode, type: NamedDefNode, ignoreNullability: boolean | undefined) => FieldDefNode;
|
|
8
|
+
export declare function mergeFields<T extends FieldDefNode>(type: {
|
|
4
9
|
name: NameNode;
|
|
5
10
|
}, f1: ReadonlyArray<T> | undefined, f2: ReadonlyArray<T> | undefined, config?: Config): T[];
|
|
11
|
+
export {};
|
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
import { Config } from './merge-typedefs.js';
|
|
2
2
|
import { FieldDefinitionNode, InputValueDefinitionNode, NameNode } from 'graphql';
|
|
3
|
-
|
|
3
|
+
type FieldDefNode = FieldDefinitionNode | InputValueDefinitionNode;
|
|
4
|
+
type NamedDefNode = {
|
|
5
|
+
name: NameNode;
|
|
6
|
+
};
|
|
7
|
+
export type OnFieldTypeConflict = (existingField: FieldDefNode, otherField: FieldDefNode, type: NamedDefNode, ignoreNullability: boolean | undefined) => FieldDefNode;
|
|
8
|
+
export declare function mergeFields<T extends FieldDefNode>(type: {
|
|
4
9
|
name: NameNode;
|
|
5
10
|
}, f1: ReadonlyArray<T> | undefined, f2: ReadonlyArray<T> | undefined, config?: Config): T[];
|
|
11
|
+
export {};
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { DefinitionNode, DocumentNode, ParseOptions } from 'graphql';
|
|
2
2
|
import { CompareFn } from './utils.cjs';
|
|
3
3
|
import { GetDocumentNodeFromSchemaOptions, TypeSource } from '@graphql-tools/utils';
|
|
4
|
+
import { OnFieldTypeConflict } from './fields.cjs';
|
|
4
5
|
type Omit<T, K extends keyof any> = Pick<T, Exclude<keyof T, K>>;
|
|
5
6
|
export interface Config extends ParseOptions, GetDocumentNodeFromSchemaOptions {
|
|
6
7
|
/**
|
|
@@ -54,6 +55,23 @@ export interface Config extends ParseOptions, GetDocumentNodeFromSchemaOptions {
|
|
|
54
55
|
convertExtensions?: boolean;
|
|
55
56
|
consistentEnumMerge?: boolean;
|
|
56
57
|
ignoreFieldConflicts?: boolean;
|
|
58
|
+
/**
|
|
59
|
+
* Called if types of the same fields are different
|
|
60
|
+
*
|
|
61
|
+
* Default: false
|
|
62
|
+
*
|
|
63
|
+
* @example:
|
|
64
|
+
* Given:
|
|
65
|
+
* ```graphql
|
|
66
|
+
* type User { a: String }
|
|
67
|
+
* type User { a: Int }
|
|
68
|
+
* ```
|
|
69
|
+
*
|
|
70
|
+
* Instead of throwing `already defined with a different type` error,
|
|
71
|
+
* `onFieldTypeConflict` function is called.
|
|
72
|
+
*/
|
|
73
|
+
onFieldTypeConflict?: OnFieldTypeConflict;
|
|
74
|
+
reverseArguments?: boolean;
|
|
57
75
|
}
|
|
58
76
|
/**
|
|
59
77
|
* Merges multiple type definitions into a single `DocumentNode`
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { DefinitionNode, DocumentNode, ParseOptions } from 'graphql';
|
|
2
2
|
import { CompareFn } from './utils.js';
|
|
3
3
|
import { GetDocumentNodeFromSchemaOptions, TypeSource } from '@graphql-tools/utils';
|
|
4
|
+
import { OnFieldTypeConflict } from './fields.js';
|
|
4
5
|
type Omit<T, K extends keyof any> = Pick<T, Exclude<keyof T, K>>;
|
|
5
6
|
export interface Config extends ParseOptions, GetDocumentNodeFromSchemaOptions {
|
|
6
7
|
/**
|
|
@@ -54,6 +55,23 @@ export interface Config extends ParseOptions, GetDocumentNodeFromSchemaOptions {
|
|
|
54
55
|
convertExtensions?: boolean;
|
|
55
56
|
consistentEnumMerge?: boolean;
|
|
56
57
|
ignoreFieldConflicts?: boolean;
|
|
58
|
+
/**
|
|
59
|
+
* Called if types of the same fields are different
|
|
60
|
+
*
|
|
61
|
+
* Default: false
|
|
62
|
+
*
|
|
63
|
+
* @example:
|
|
64
|
+
* Given:
|
|
65
|
+
* ```graphql
|
|
66
|
+
* type User { a: String }
|
|
67
|
+
* type User { a: Int }
|
|
68
|
+
* ```
|
|
69
|
+
*
|
|
70
|
+
* Instead of throwing `already defined with a different type` error,
|
|
71
|
+
* `onFieldTypeConflict` function is called.
|
|
72
|
+
*/
|
|
73
|
+
onFieldTypeConflict?: OnFieldTypeConflict;
|
|
74
|
+
reverseArguments?: boolean;
|
|
57
75
|
}
|
|
58
76
|
/**
|
|
59
77
|
* Merges multiple type definitions into a single `DocumentNode`
|