Skip to content
This repository has been archived by the owner on Sep 3, 2021. It is now read-only.

Input object argument format for mutation API #531

Merged
merged 19 commits into from
Nov 6, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
"build-with-sourcemaps": "babel src --presets @babel/preset-env --out-dir dist --source-maps",
"precommit": "lint-staged",
"prepare": "npm run build",
"test": "nyc --reporter=lcov ava test/unit/**.test.js --verbose",
"test": "nyc --reporter=lcov ava test/unit/augmentSchemaTest.test.js test/unit/configTest.test.js test/unit/assertSchema.test.js test/unit/cypherTest.test.js test/unit/filterTest.test.js test/unit/filterTests.test.js test/unit/experimental/augmentSchemaTest.test.js test/unit/experimental/cypherTest.test.js",
"parse-tck": "babel-node test/helpers/tck/parseTck.js",
"test-tck": "nyc ava --fail-fast test/unit/filterTests.test.js",
"report-coverage": "nyc report --reporter=text-lcov > coverage.lcov && codecov",
Expand Down
13 changes: 6 additions & 7 deletions src/augment/input-values.js
Original file line number Diff line number Diff line change
Expand Up @@ -333,7 +333,7 @@ const LogicalFilteringArgument = {
/**
* Builds the AST definitions for logical filtering arguments
*/
const buildLogicalFilterInputValues = ({ typeName = '' }) => {
export const buildLogicalFilterInputValues = ({ typeName = '' }) => {
return [
buildInputValue({
name: buildName({ name: LogicalFilteringArgument.AND }),
Expand Down Expand Up @@ -361,7 +361,7 @@ const buildLogicalFilterInputValues = ({ typeName = '' }) => {
/**
* Builds the AST definitions for filtering Neo4j property type fields
*/
const buildPropertyFilters = ({
export const buildPropertyFilters = ({
field,
fieldName = '',
outputType = '',
Expand Down Expand Up @@ -512,11 +512,10 @@ export const selectUnselectedOrderedFields = ({
);
const orderingArgumentFieldNames = Object.keys(orderedFieldNameMap);
orderingArgumentFieldNames.forEach(orderedFieldName => {
if (
!fieldSelectionSet.some(
field => field.name && field.name.value === orderedFieldName
)
) {
const orderedFieldAlreadySelected = fieldSelectionSet.some(
field => field.name && field.name.value === orderedFieldName
);
if (!orderedFieldAlreadySelected) {
// add the field so that its data can be used for ordering
// since as it is not actually selected, it will be removed
// by default GraphQL post-processing field resolvers
Expand Down
249 changes: 166 additions & 83 deletions src/augment/types/node/mutation.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,11 @@ import {
useAuthDirective,
isCypherField
} from '../../directives';
import { getPrimaryKey } from './selection';
import {
getPrimaryKey,
buildNodeSelectionInputType,
buildNodeSelectionInputTypes
} from './selection';
import { shouldAugmentType } from '../../augment';
import { OperationType } from '../../types/types';
import {
Expand Down Expand Up @@ -48,6 +52,7 @@ export const augmentNodeMutationAPI = ({
propertyInputValues,
generatedTypeMap,
operationTypeMap,
typeDefinitionMap,
typeExtensionDefinitionMap,
config
}) => {
Expand Down Expand Up @@ -78,89 +83,28 @@ export const augmentNodeMutationAPI = ({
});
});
}
return [operationTypeMap, generatedTypeMap];
};

/**
* Given the results of augmentNodeTypeFields, builds the AST
* definition for a Mutation operation field of a given
* NodeMutation name
*/
const buildNodeMutationField = ({
mutationType,
mutationAction = '',
primaryKey,
typeName,
propertyInputValues,
operationTypeMap,
typeExtensionDefinitionMap,
config
}) => {
const mutationFields = mutationType.fields;
const mutationName = `${mutationAction}${typeName}`;
const mutationTypeName = mutationType ? mutationType.name.value : '';
const mutationTypeExtensions = typeExtensionDefinitionMap[mutationTypeName];
if (
!getFieldDefinition({
fields: mutationFields,
name: mutationName
}) &&
!getTypeExtensionFieldDefinition({
typeExtensions: mutationTypeExtensions,
name: typeName
})
) {
const mutationConfig = {
name: buildName({ name: mutationName }),
args: buildNodeMutationArguments({
operationName: mutationAction,
primaryKey,
args: propertyInputValues
}),
type: buildNamedType({
name: typeName
}),
directives: buildNodeMutationDirectives({
mutationAction,
typeName,
config
})
};
let mutationField = undefined;
let mutationDescriptionUrl = '';
if (mutationAction === NodeMutation.CREATE) {
mutationField = mutationConfig;
mutationDescriptionUrl =
'[creating](https://neo4j.com/docs/cypher-manual/4.1/clauses/create/#create-nodes)';
} else if (mutationAction === NodeMutation.UPDATE) {
if (primaryKey && mutationConfig.args.length > 1) {
mutationField = mutationConfig;
mutationDescriptionUrl =
'[updating](https://neo4j.com/docs/cypher-manual/4.1/clauses/set/#set-update-a-property)';
}
} else if (mutationAction === NodeMutation.MERGE) {
if (primaryKey) {
mutationField = mutationConfig;
mutationDescriptionUrl =
'[merging](https://neo4j.com/docs/cypher-manual/4.1/clauses/merge/#query-merge-node-derived)';
}
} else if (mutationAction === NodeMutation.DELETE) {
if (primaryKey) {
mutationField = mutationConfig;
mutationDescriptionUrl =
'[deleting](https://neo4j.com/docs/cypher-manual/4.1/clauses/delete/#delete-delete-single-node)';
}
}
if (mutationField) {
mutationField.description = buildDescription({
value: `[Generated mutation](${GRANDSTACK_DOCS_SCHEMA_AUGMENTATION}/#${mutationAction.toLowerCase()}) for ${mutationDescriptionUrl} a ${typeName} node.`,
config
});
mutationFields.push(buildField(mutationField));
}
operationTypeMap[OperationType.MUTATION].fields = mutationFields;
if (config.experimental === true) {
generatedTypeMap = buildNodeSelectionInputTypes({
definition,
typeName,
propertyInputValues,
generatedTypeMap,
typeDefinitionMap,
typeExtensionDefinitionMap,
config
});
} else {
generatedTypeMap = buildNodeSelectionInputType({
definition,
typeName,
propertyInputValues,
generatedTypeMap,
typeDefinitionMap,
typeExtensionDefinitionMap,
config
});
}
return operationTypeMap;
return [operationTypeMap, generatedTypeMap];
};

/**
Expand Down Expand Up @@ -258,6 +202,145 @@ const buildNodeMutationArguments = ({
);
};

const buildNodeMutationObjectArguments = ({ typeName, operationName = '' }) => {
const args = [];
const nodeSelectionConfig = {
name: 'where',
type: {
name: `_${typeName}Where`,
wrappers: {
[TypeWrappers.NON_NULL_NAMED_TYPE]: true
}
}
};
const propertyInputConfig = {
name: 'data',
type: {
name: `_${typeName}Data`,
wrappers: {
[TypeWrappers.NON_NULL_NAMED_TYPE]: true
}
}
};
if (operationName === NodeMutation.CREATE) {
args.push(propertyInputConfig);
} else if (operationName === NodeMutation.UPDATE) {
args.push(nodeSelectionConfig);
args.push(propertyInputConfig);
} else if (operationName === NodeMutation.MERGE) {
const keySelectionInputConfig = {
name: 'where',
type: {
name: `_${typeName}Keys`,
wrappers: {
[TypeWrappers.NON_NULL_NAMED_TYPE]: true
}
}
};
args.push(keySelectionInputConfig);
args.push(propertyInputConfig);
} else if (operationName === NodeMutation.DELETE) {
args.push(nodeSelectionConfig);
}
return args.map(arg =>
buildInputValue({
name: buildName({ name: arg.name }),
type: buildNamedType(arg.type)
})
);
};

/**
* Given the results of augmentNodeTypeFields, builds the AST
* definition for a Mutation operation field of a given
* NodeMutation name
*/
const buildNodeMutationField = ({
mutationType,
mutationAction = '',
primaryKey,
typeName,
propertyInputValues,
operationTypeMap,
typeExtensionDefinitionMap,
config
}) => {
const mutationFields = mutationType.fields;
const mutationName = `${mutationAction}${typeName}`;
const mutationTypeName = mutationType ? mutationType.name.value : '';
const mutationTypeExtensions = typeExtensionDefinitionMap[mutationTypeName];
if (
!getFieldDefinition({
fields: mutationFields,
name: mutationName
}) &&
!getTypeExtensionFieldDefinition({
typeExtensions: mutationTypeExtensions,
name: typeName
})
) {
let mutationArgs = [];
if (config.experimental === true) {
mutationArgs = buildNodeMutationObjectArguments({
typeName,
operationName: mutationAction
});
} else {
mutationArgs = buildNodeMutationArguments({
operationName: mutationAction,
primaryKey,
args: propertyInputValues
});
}
const mutationConfig = {
name: buildName({ name: mutationName }),
args: mutationArgs,
type: buildNamedType({
name: typeName
}),
directives: buildNodeMutationDirectives({
mutationAction,
typeName,
config
})
};
let mutationField = undefined;
let mutationDescriptionUrl = '';
if (mutationAction === NodeMutation.CREATE) {
mutationField = mutationConfig;
mutationDescriptionUrl =
'[creating](https://neo4j.com/docs/cypher-manual/4.1/clauses/create/#create-nodes)';
} else if (mutationAction === NodeMutation.UPDATE) {
if (primaryKey && mutationConfig.args.length > 1) {
mutationField = mutationConfig;
mutationDescriptionUrl =
'[updating](https://neo4j.com/docs/cypher-manual/4.1/clauses/set/#set-update-a-property)';
}
} else if (mutationAction === NodeMutation.MERGE) {
if (primaryKey) {
mutationField = mutationConfig;
mutationDescriptionUrl =
'[merging](https://neo4j.com/docs/cypher-manual/4.1/clauses/merge/#query-merge-node-derived)';
}
} else if (mutationAction === NodeMutation.DELETE) {
if (primaryKey) {
mutationField = mutationConfig;
mutationDescriptionUrl =
'[deleting](https://neo4j.com/docs/cypher-manual/4.1/clauses/delete/#delete-delete-single-node)';
}
}
if (mutationField) {
mutationField.description = buildDescription({
value: `[Generated mutation](${GRANDSTACK_DOCS_SCHEMA_AUGMENTATION}/#${mutationAction.toLowerCase()}) for ${mutationDescriptionUrl} a ${typeName} node.`,
config
});
mutationFields.push(buildField(mutationField));
}
operationTypeMap[OperationType.MUTATION].fields = mutationFields;
}
return operationTypeMap;
};

/**
* Builds the AST definitions for directive instances used by
* generated node Mutation fields of NodeMutation names
Expand Down
Loading