UNPKG

3.12 kBJavaScriptView Raw
1import { parseValue, valueFromASTUntyped } from 'graphql';
2import { extractVariables } from './extractVariables.js';
3import { EXPANSION_PREFIX, KEY_DELIMITER, preparseMergeArgsExpr } from './preparseMergeArgsExpr.js';
4import { propertyTreeFromPaths } from './properties.js';
5import { getSourcePaths } from './getSourcePaths.js';
6export function parseMergeArgsExpr(mergeArgsExpr, selectionSet) {
7 const { mergeArgsExpr: newMergeArgsExpr, expansionExpressions } = preparseMergeArgsExpr(mergeArgsExpr);
8 const inputValue = parseValue(`{ ${newMergeArgsExpr} }`, { noLocation: true });
9 const { inputValue: newInputValue, variablePaths } = extractVariables(inputValue);
10 if (!Object.keys(expansionExpressions).length) {
11 if (!Object.keys(variablePaths).length) {
12 throw new Error('Merge arguments must declare a key.');
13 }
14 const mappingInstructions = getMappingInstructions(variablePaths);
15 const usedProperties = propertyTreeFromPaths(getSourcePaths(mappingInstructions, selectionSet));
16 return { args: valueFromASTUntyped(newInputValue), usedProperties, mappingInstructions };
17 }
18 const expansionRegEx = new RegExp(`^${EXPANSION_PREFIX}[0-9]+$`);
19 for (const variableName in variablePaths) {
20 if (!variableName.match(expansionRegEx)) {
21 throw new Error('Expansions cannot be mixed with single key declarations.');
22 }
23 }
24 const expansions = [];
25 const sourcePaths = [];
26 for (const variableName in expansionExpressions) {
27 const str = expansionExpressions[variableName];
28 const valuePath = variablePaths[variableName];
29 const { inputValue: expansionInputValue, variablePaths: expansionVariablePaths } = extractVariables(parseValue(`${str}`, { noLocation: true }));
30 if (!Object.keys(expansionVariablePaths).length) {
31 throw new Error('Merge arguments must declare a key.');
32 }
33 const mappingInstructions = getMappingInstructions(expansionVariablePaths);
34 const value = valueFromASTUntyped(expansionInputValue);
35 sourcePaths.push(...getSourcePaths(mappingInstructions, selectionSet));
36 assertNotWithinList(valuePath);
37 expansions.push({
38 valuePath,
39 value,
40 mappingInstructions,
41 });
42 }
43 const usedProperties = propertyTreeFromPaths(sourcePaths);
44 return { args: valueFromASTUntyped(newInputValue), usedProperties, expansions };
45}
46function getMappingInstructions(variablePaths) {
47 const mappingInstructions = [];
48 for (const keyPath in variablePaths) {
49 const valuePath = variablePaths[keyPath];
50 const splitKeyPath = keyPath.split(KEY_DELIMITER).slice(1);
51 assertNotWithinList(valuePath);
52 mappingInstructions.push({
53 destinationPath: valuePath,
54 sourcePath: splitKeyPath,
55 });
56 }
57 return mappingInstructions;
58}
59function assertNotWithinList(path) {
60 for (const pathSegment of path) {
61 if (typeof pathSegment === 'number') {
62 throw new Error('Insertions cannot be made into a list.');
63 }
64 }
65}