Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@aws-amplify/graphql-model-transformer

Package Overview
Dependencies
Maintainers
7
Versions
451
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@aws-amplify/graphql-model-transformer - npm Package Compare versions

Comparing version 0.6.0 to 0.6.1-beta.0

13

CHANGELOG.md

@@ -6,2 +6,15 @@ # Change Log

## [0.6.1-beta.0](https://github.com/aws-amplify/amplify-cli/compare/@aws-amplify/graphql-model-transformer@0.6.0...@aws-amplify/graphql-model-transformer@0.6.1-beta.0) (2021-08-30)
### Bug Fixes
* add model transformer v2 e2e tests ([#7946](https://github.com/aws-amplify/amplify-cli/issues/7946)) ([351a8bc](https://github.com/aws-amplify/amplify-cli/commit/351a8bce6069398535878fd62886e0ee5c402329))
* model transformer support condition ([#7935](https://github.com/aws-amplify/amplify-cli/issues/7935)) ([fc93dba](https://github.com/aws-amplify/amplify-cli/commit/fc93dbabb38427607ef6abb6f1d7fb2f357a284b))
* update and create input field type known model types filtering ([#7929](https://github.com/aws-amplify/amplify-cli/issues/7929)) ([16334f7](https://github.com/aws-amplify/amplify-cli/commit/16334f7217f0ac751a642d82512240aedec17721))
# [0.6.0](https://github.com/aws-amplify/amplify-cli/compare/@aws-amplify/graphql-model-transformer@0.5.1...@aws-amplify/graphql-model-transformer@0.6.0) (2021-08-24)

@@ -8,0 +21,0 @@

7

lib/graphql-model-transformer.d.ts
import { TransformerModelBase } from '@aws-amplify/graphql-transformer-core';
import { AppSyncDataSourceType, DataSourceInstance, MutationFieldType, QueryFieldType, SubscriptionFieldType, TransformerContextProvider, TransformerModelProvider, TransformerPrepareStepContextProvider, TransformerResolverProvider, TransformerSchemaVisitStepContextProvider, TransformerTransformSchemaStepContextProvider } from '@aws-amplify/graphql-transformer-interfaces';
import { DirectiveNode, FieldDefinitionNode, InputValueDefinitionNode, ObjectTypeDefinitionNode } from 'graphql';
import { DirectiveNode, InputValueDefinitionNode, ObjectTypeDefinitionNode } from 'graphql';
export declare type Nullable<T> = T | null;

@@ -68,3 +68,5 @@ export declare type OptionalAndNullable<T> = Partial<T>;

}>) => string;
createSubscriptionFields: (ctx: TransformerTransformSchemaStepContextProvider, def: ObjectTypeDefinitionNode) => FieldDefinitionNode[];
private createQueryFields;
private createMutationFields;
private createSubscriptionFields;
getSubscriptionFieldNames: (ctx: TransformerTransformSchemaStepContextProvider, type: ObjectTypeDefinitionNode) => Set<{

@@ -93,3 +95,4 @@ fieldName: string;

private getSubscriptionToMutationsReverseMap;
private ensureModelSortDirectionEnum;
}
//# sourceMappingURL=graphql-model-transformer.d.ts.map

@@ -120,26 +120,10 @@ "use strict";

graphql_types_1.addModelConditionInputs(ctx);
this.ensureModelSortDirectionEnum(ctx);
for (const type of this.typesWithModelDirective) {
const def = ctx.output.getObject(type);
this.createNonModelInputs(ctx, def);
const queryFields = this.getQueryFieldNames(ctx, def);
for (const queryField of queryFields.values()) {
const outputType = this.getOutputType(ctx, def, queryField);
const args = this.getInputs(ctx, def, {
fieldName: queryField.fieldName,
typeName: queryField.typeName,
type: queryField.type,
});
const getField = graphql_transformer_common_1.makeField(queryField.fieldName, args, graphql_transformer_common_1.makeNamedType(outputType.name.value));
ctx.output.addQueryFields([getField]);
}
const mutationFields = this.getMutationFieldNames(ctx, def);
for (const mutationField of mutationFields) {
const args = this.getInputs(ctx, def, {
fieldName: mutationField.fieldName,
typeName: mutationField.typeName,
type: mutationField.type,
});
const field = graphql_transformer_common_1.makeField(mutationField.fieldName, args, graphql_transformer_common_1.makeNamedType(def.name.value));
ctx.output.addMutationFields([field]);
}
const queryFields = this.createQueryFields(ctx, def);
ctx.output.addQueryFields(queryFields);
const mutationFields = this.createMutationFields(ctx, def);
ctx.output.addMutationFields(mutationFields);
const subscriptionsFields = this.createSubscriptionFields(ctx, def);

@@ -385,2 +369,29 @@ ctx.output.addSubscriptionFields(subscriptionsFields);

};
this.createQueryFields = (ctx, def) => {
const queryFields = [];
const queryFieldNames = this.getQueryFieldNames(ctx, def);
for (const queryField of queryFieldNames.values()) {
const outputType = this.getOutputType(ctx, def, queryField);
const args = this.getInputs(ctx, def, {
fieldName: queryField.fieldName,
typeName: queryField.typeName,
type: queryField.type,
});
queryFields.push(graphql_transformer_common_1.makeField(queryField.fieldName, args, graphql_transformer_common_1.makeNamedType(outputType.name.value)));
}
return queryFields;
};
this.createMutationFields = (ctx, def) => {
const mutationFields = [];
const mutationFieldNames = this.getMutationFieldNames(ctx, def);
for (const mutationField of mutationFieldNames) {
const args = this.getInputs(ctx, def, {
fieldName: mutationField.fieldName,
typeName: mutationField.typeName,
type: mutationField.type,
});
mutationFields.push(graphql_transformer_common_1.makeField(mutationField.fieldName, args, graphql_transformer_common_1.makeNamedType(def.name.value)));
}
return mutationFields;
};
this.createSubscriptionFields = (ctx, def) => {

@@ -476,4 +487,5 @@ const subscriptionToMutationsMap = this.getSubscriptionToMutationsReverseMap(ctx, def);

const filterInputName = graphql_transformer_common_1.toPascalCase(['Model', type.name.value, 'FilterInput']);
const filterInputs = graphql_types_1.makeListQueryFilterInput(ctx, filterInputName, type);
for (let input of [filterInputs]) {
const filterInputs = graphql_types_1.createEnumModelFilters(ctx, type);
filterInputs.push(graphql_types_1.makeListQueryFilterInput(ctx, filterInputName, type));
for (let input of filterInputs) {
const conditionInputName = input.name.value;

@@ -623,4 +635,10 @@ if (!ctx.output.getType(conditionInputName)) {

}
ensureModelSortDirectionEnum(ctx) {
if (!ctx.output.hasType('ModelSortDirection')) {
const modelSortDirection = graphql_types_1.makeModelSortDirectionEnumObject();
ctx.output.addEnum(modelSortDirection);
}
}
}
exports.ModelTransformer = ModelTransformer;
//# sourceMappingURL=graphql-model-transformer.js.map
import { TransformerTransformSchemaStepContextProvider } from '@aws-amplify/graphql-transformer-interfaces';
import { EnumTypeDefinitionNode, FieldDefinitionNode, InputObjectTypeDefinitionNode, ObjectTypeDefinitionNode } from 'graphql';
import { InputObjectDefinitionWrapper } from '../wrappers/object-definition-wrapper';
import { FieldWrapper, InputObjectDefinitionWrapper } from '../wrappers/object-definition-wrapper';
export declare const makeConditionFilterInput: (ctx: TransformerTransformSchemaStepContextProvider, name: string, object: ObjectTypeDefinitionNode) => InputObjectDefinitionWrapper;

@@ -12,4 +12,4 @@ export declare const addModelConditionInputs: (ctx: TransformerTransformSchemaStepContextProvider) => void;

export declare function makeSizeInputType(): InputObjectTypeDefinitionNode;
export declare function makeEnumFilterInput(name: string): InputObjectTypeDefinitionNode;
export declare function makeEnumFilterInput(fieldWrapper: FieldWrapper): InputObjectTypeDefinitionNode;
export declare function makeModelSortDirectionEnumObject(): EnumTypeDefinitionNode;
//# sourceMappingURL=common.d.ts.map
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.makeModelSortDirectionEnumObject = exports.makeEnumFilterInput = exports.makeSizeInputType = exports.makeSubscriptionField = exports.makeAttributeTypeEnum = exports.makeModelScalarFilterInputObject = exports.createEnumModelFilters = exports.generateModelScalarFilterInputName = exports.addModelConditionInputs = exports.makeConditionFilterInput = void 0;
const graphql_1 = require("graphql");
const graphql_transformer_common_1 = require("graphql-transformer-common");

@@ -8,2 +9,3 @@ const definitions_1 = require("../definitions");

const makeConditionFilterInput = (ctx, name, object) => {
const supportsConditions = true;
const input = object_definition_wrapper_1.InputObjectDefinitionWrapper.create(name);

@@ -13,14 +15,10 @@ const wrappedObject = new object_definition_wrapper_1.ObjectDefinitionWrapper(object);

const fieldType = ctx.output.getType(field.getTypeName());
const isEnumType = fieldType && fieldType.kind === 'EnumTypeDefinition';
if (field.isScalar() || field.isList()) {
const conditionTypeName = field.isList()
? graphql_transformer_common_1.ModelResourceIDs.ModelFilterListInputTypeName(field.getTypeName(), true)
: graphql_transformer_common_1.ModelResourceIDs.ModelFilterScalarInputTypeName(field.getTypeName(), true);
const inputField = object_definition_wrapper_1.InputFieldWrapper.create(field.name, conditionTypeName, true, field.isList());
const isEnumType = fieldType && fieldType.kind === graphql_1.Kind.ENUM_TYPE_DEFINITION;
if (field.isScalar() || isEnumType) {
const conditionTypeName = isEnumType && field.isList()
? graphql_transformer_common_1.ModelResourceIDs.ModelFilterListInputTypeName(field.getTypeName(), !supportsConditions)
: graphql_transformer_common_1.ModelResourceIDs.ModelFilterScalarInputTypeName(field.getTypeName(), !supportsConditions);
const inputField = object_definition_wrapper_1.InputFieldWrapper.create(field.name, conditionTypeName, true);
input.addField(inputField);
}
else if (isEnumType) {
const inputField = object_definition_wrapper_1.InputFieldWrapper.create(field.name, field.getTypeName(), true, field.isList());
input.addField(inputField);
}
}

@@ -39,3 +37,3 @@ for (let additionalField of ['and', 'or']) {

const addModelConditionInputs = (ctx) => {
const conditionsInput = ['String', 'Int', 'Float', 'Boolean', 'ID'].map(scalarName => makeModelScalarFilterInputObject(scalarName, false));
const conditionsInput = ['String', 'Int', 'Float', 'Boolean', 'ID'].map(scalarName => makeModelScalarFilterInputObject(scalarName, true));
conditionsInput.push(makeAttributeTypeEnum());

@@ -66,3 +64,3 @@ conditionsInput.push(makeSizeInputType());

});
return enumFields.map(field => makeEnumFilterInput(field.getTypeName()));
return enumFields.map(field => makeEnumFilterInput(field));
};

@@ -162,9 +160,18 @@ exports.createEnumModelFilters = createEnumModelFilters;

exports.makeSizeInputType = makeSizeInputType;
function makeEnumFilterInput(name) {
const inputName = graphql_transformer_common_1.toPascalCase(['Model', name, 'Input']);
const input = object_definition_wrapper_1.InputObjectDefinitionWrapper.create(inputName);
function makeEnumFilterInput(fieldWrapper) {
const supportsConditions = true;
const conditionTypeName = fieldWrapper.isList()
? graphql_transformer_common_1.ModelResourceIDs.ModelFilterListInputTypeName(fieldWrapper.getTypeName(), !supportsConditions)
: graphql_transformer_common_1.ModelResourceIDs.ModelFilterScalarInputTypeName(fieldWrapper.getTypeName(), !supportsConditions);
const input = object_definition_wrapper_1.InputObjectDefinitionWrapper.create(conditionTypeName);
['eq', 'ne'].forEach(fieldName => {
const field = object_definition_wrapper_1.InputFieldWrapper.create(fieldName, name, true);
const field = object_definition_wrapper_1.InputFieldWrapper.create(fieldName, fieldWrapper.getTypeName(), true, fieldWrapper.isList());
input.addField(field);
});
if (fieldWrapper.isList()) {
['contains', 'notContains'].forEach(fieldName => {
const field = object_definition_wrapper_1.InputFieldWrapper.create(fieldName, fieldWrapper.getTypeName(), true);
input.addField(field);
});
}
return input.serialize();

@@ -171,0 +178,0 @@ }

import { TransformerTransformSchemaStepContextProvider } from '@aws-amplify/graphql-transformer-interfaces';
import { ObjectTypeDefinitionNode, InputObjectTypeDefinitionNode, DocumentNode } from 'graphql';
import { DocumentNode, InputObjectTypeDefinitionNode, ObjectTypeDefinitionNode } from 'graphql';
import { ModelDirectiveConfiguration } from '../graphql-model-transformer';

@@ -4,0 +4,0 @@ export declare const makeUpdateInputField: (obj: ObjectTypeDefinitionNode, modelDirectiveConfig: ModelDirectiveConfiguration, knownModelTypes: Set<string>, document: DocumentNode) => InputObjectTypeDefinitionNode;

@@ -21,3 +21,3 @@ "use strict";

.map(field => {
return field.getTypeName();
return field.name;
});

@@ -72,3 +72,3 @@ const objectTypeDefinition = {

.map(field => {
return field.getTypeName();
return field.name;
});

@@ -102,3 +102,3 @@ const objectTypeDefinition = {

const input = common_1.makeConditionFilterInput(ctx, name, object);
const idField = input.fields.find(f => f.name === 'id' && f.getTypeName() === 'ID');
const idField = input.fields.find(f => f.name === 'id' && f.getTypeName() === 'ModelIDInput');
if (idField) {

@@ -105,0 +105,0 @@ input.removeField(idField);

@@ -28,2 +28,3 @@ import { ArgumentNode, DirectiveNode, DocumentNode, EnumTypeDefinitionNode, FieldDefinitionNode, InputObjectTypeDefinitionNode, InputValueDefinitionNode, Location, NamedTypeNode, NameNode, ObjectTypeDefinitionNode, StringValueNode, TypeNode, ValueNode } from 'graphql';

unWrapListType: () => boolean;
private isListType;
getBaseType: () => NamedTypeNode;

@@ -30,0 +31,0 @@ getTypeName: () => string;

@@ -46,3 +46,3 @@ "use strict";

this.isList = () => {
return graphql_1.isListType(this.type);
return this.isListType(this.type);
};

@@ -82,2 +82,10 @@ this.isNonNullable = () => {

};
this.isListType = (type) => {
if (type.kind === graphql_1.Kind.NON_NULL_TYPE) {
return graphql_1.isListType(type.type);
}
else {
return type.kind === graphql_1.Kind.LIST_TYPE;
}
};
this.getBaseType = () => {

@@ -298,3 +306,3 @@ let node = this.type;

this.removeField = (field) => {
if (this.hasField(field.name)) {
if (!this.hasField(field.name)) {
throw new Error(`type ${this.name} does not have the field with name ${field.name}`);

@@ -301,0 +309,0 @@ }

{
"name": "@aws-amplify/graphql-model-transformer",
"version": "0.6.0",
"version": "0.6.1-beta.0",
"description": "Amplify graphql @model transformer",

@@ -31,4 +31,4 @@ "repository": {

"dependencies": {
"@aws-amplify/graphql-transformer-core": "0.8.2",
"@aws-amplify/graphql-transformer-interfaces": "1.8.2",
"@aws-amplify/graphql-transformer-core": "0.9.0-beta.0",
"@aws-amplify/graphql-transformer-interfaces": "1.9.0-beta.0",
"@aws-cdk/assets": "~1.119.0",

@@ -61,3 +61,3 @@ "@aws-cdk/aws-applicationautoscaling": "~1.119.0",

"graphql-mapping-template": "4.18.3",
"graphql-transformer-common": "4.19.8",
"graphql-transformer-common": "4.19.9-beta.0",
"lodash": "^4.17.21"

@@ -85,3 +85,3 @@ },

},
"gitHead": "5d7ddc369ad90c4d155e808ccd95b71922ee269a"
"gitHead": "120d47266005cf8595781bb738ee36848689c2ee"
}

@@ -474,11 +474,11 @@ import { ModelTransformer } from '@aws-amplify/graphql-model-transformer';

const stringInputType = getInputType(parsed, 'ModelStringFilterInput');
const stringInputType = getInputType(parsed, 'ModelStringInput');
expect(stringInputType).toBeDefined();
const booleanInputType = getInputType(parsed, 'ModelBooleanFilterInput');
const booleanInputType = getInputType(parsed, 'ModelBooleanInput');
expect(booleanInputType).toBeDefined();
const intInputType = getInputType(parsed, 'ModelIntFilterInput');
const intInputType = getInputType(parsed, 'ModelIntInput');
expect(intInputType).toBeDefined();
const floatInputType = getInputType(parsed, 'ModelFloatFilterInput');
const floatInputType = getInputType(parsed, 'ModelFloatInput');
expect(floatInputType).toBeDefined();
const idInputType = getInputType(parsed, 'ModelIDFilterInput');
const idInputType = getInputType(parsed, 'ModelIDInput');
expect(idInputType).toBeDefined();

@@ -490,7 +490,7 @@ const postInputType = getInputType(parsed, 'ModelPostFilterInput');

expect(verifyInputCount(parsed, 'ModelStringFilterInput', 1)).toBeTruthy();
expect(verifyInputCount(parsed, 'ModelBooleanFilterInput', 1)).toBeTruthy();
expect(verifyInputCount(parsed, 'ModelIntFilterInput', 1)).toBeTruthy();
expect(verifyInputCount(parsed, 'ModelFloatFilterInput', 1)).toBeTruthy();
expect(verifyInputCount(parsed, 'ModelIDFilterInput', 1)).toBeTruthy();
expect(verifyInputCount(parsed, 'ModelStringInput', 1)).toBeTruthy();
expect(verifyInputCount(parsed, 'ModelBooleanInput', 1)).toBeTruthy();
expect(verifyInputCount(parsed, 'ModelIntInput', 1)).toBeTruthy();
expect(verifyInputCount(parsed, 'ModelFloatInput', 1)).toBeTruthy();
expect(verifyInputCount(parsed, 'ModelIDInput', 1)).toBeTruthy();
expect(verifyInputCount(parsed, 'ModelPostFilterInput', 1)).toBeTruthy();

@@ -560,3 +560,2 @@ expect(verifyInputCount(parsed, 'ModelUserFilterInput', 1)).toBeTruthy();

const parsed = parse(definition);
validateModelSchema(parsed);

@@ -612,7 +611,7 @@

expect(verifyInputCount(parsed, 'ModelStringFilterInput', 1)).toBeTruthy();
expect(verifyInputCount(parsed, 'ModelBooleanFilterInput', 1)).toBeTruthy();
expect(verifyInputCount(parsed, 'ModelIntFilterInput', 1)).toBeTruthy();
expect(verifyInputCount(parsed, 'ModelFloatFilterInput', 1)).toBeTruthy();
expect(verifyInputCount(parsed, 'ModelIDFilterInput', 1)).toBeTruthy();
expect(verifyInputCount(parsed, 'ModelStringInput', 1)).toBeTruthy();
expect(verifyInputCount(parsed, 'ModelBooleanInput', 1)).toBeTruthy();
expect(verifyInputCount(parsed, 'ModelIntInput', 1)).toBeTruthy();
expect(verifyInputCount(parsed, 'ModelFloatInput', 1)).toBeTruthy();
expect(verifyInputCount(parsed, 'ModelIDInput', 1)).toBeTruthy();
expect(verifyInputCount(parsed, 'ModelPostFilterInput', 1)).toBeTruthy();

@@ -657,2 +656,232 @@ });

});
it('should not generate superfluous input and filter types', () => {
const validSchema = `
type Entity @model(mutations: null, subscriptions: null, queries: {get: "getEntity"}) {
id: ID!
str: String
}
`;
const transformer = new GraphQLTransform({
transformers: [new ModelTransformer()],
featureFlags,
});
const result = transformer.transform(validSchema);
expect(result).toBeDefined();
expect(result.schema).toBeDefined();
expect(result.schema).toMatchSnapshot();
const schema = parse(result.schema);
validateModelSchema(schema);
});
it('should support timestamp parameters when generating pipelineFunctions and output schema', () => {
const validSchema = `
type Post @model(timestamps: { createdAt: "createdOn", updatedAt: "updatedOn"}) {
id: ID!
str: String
}
`;
const transformer = new GraphQLTransform({
transformers: [new ModelTransformer()],
featureFlags,
});
const result = transformer.transform(validSchema);
expect(result).toBeDefined();
expect(result.schema).toBeDefined();
expect(result.schema).toMatchSnapshot();
const schema = parse(result.schema);
validateModelSchema(schema);
expect(result.pipelineFunctions['Mutation.createPost.req.vtl']).toMatchSnapshot();
expect(result.pipelineFunctions['Mutation.updatePost.req.vtl']).toMatchSnapshot();
});
it('should not to auto generate createdAt and updatedAt when the type in schema is not AWSDateTime', () => {
const validSchema = `
type Post @model {
id: ID!
str: String
createdAt: AWSTimestamp
updatedAt: AWSTimestamp
}
`;
const transformer = new GraphQLTransform({
transformers: [new ModelTransformer()],
featureFlags,
});
const result = transformer.transform(validSchema);
expect(result).toBeDefined();
expect(result.schema).toBeDefined();
expect(result.schema).toMatchSnapshot();
const schema = parse(result.schema);
validateModelSchema(schema);
expect(result.pipelineFunctions['Mutation.createPost.req.vtl']).toMatchSnapshot();
expect(result.pipelineFunctions['Mutation.updatePost.req.vtl']).toMatchSnapshot();
});
it('should have timestamps as nullable fields when the type makes it non-nullable', () => {
const validSchema = `
type Post @model {
id: ID!
str: String
createdAt: AWSDateTime!
updatedAt: AWSDateTime!
}
`;
const transformer = new GraphQLTransform({
transformers: [new ModelTransformer()],
featureFlags,
});
const result = transformer.transform(validSchema);
expect(result).toBeDefined();
expect(result.schema).toBeDefined();
expect(result.schema).toMatchSnapshot();
const schema = parse(result.schema);
validateModelSchema(schema);
expect(result.pipelineFunctions['Mutation.createPost.req.vtl']).toMatchSnapshot();
expect(result.pipelineFunctions['Mutation.updatePost.req.vtl']).toMatchSnapshot();
});
it('should not to include createdAt and updatedAt field when timestamps is set to null', () => {
const validSchema = `
type Post @model(timestamps: null) {
id: ID!
str: String
}
`;
const transformer = new GraphQLTransform({
transformers: [new ModelTransformer()],
featureFlags,
});
const result = transformer.transform(validSchema);
expect(result).toBeDefined();
expect(result.schema).toBeDefined();
expect(result.schema).toMatchSnapshot();
const schema = parse(result.schema);
validateModelSchema(schema);
expect(result.pipelineFunctions['Mutation.createPost.req.vtl']).toMatchSnapshot();
expect(result.pipelineFunctions['Mutation.updatePost.req.vtl']).toMatchSnapshot();
});
it('should filter known input types from create and update input fields', () => {
const validSchema = `
type Test @model {
id: ID!
email: Email
}
type Email @model {
id: ID!
}
`;
const transformer = new GraphQLTransform({
transformers: [new ModelTransformer()],
featureFlags,
});
const result = transformer.transform(validSchema);
expect(result).toBeDefined();
expect(result.schema).toBeDefined();
expect(result.schema).toMatchSnapshot();
const schema = parse(result.schema);
validateModelSchema(schema);
const createTestInput = getInputType(schema, 'CreateTestInput');
expect(getFieldOnInputType(createTestInput!, 'email')).toBeUndefined();
const updateTestInput = getInputType(schema, 'UpdateTestInput');
expect(getFieldOnInputType(updateTestInput!, 'email')).toBeUndefined();
});
it('should generate enum input objects', () => {
const validSchema = /* GraphQL */ `
type Post @model {
id: ID!
title: String!
createdAt: AWSDateTime
updatedAt: AWSDateTime
metadata: PostMetadata
entityMetadata: EntityMetadata
appearsIn: [Episode!]
episode: Episode
}
type Author @model {
id: ID!
name: String!
postMetadata: PostMetadata
entityMetadata: EntityMetadata
}
type EntityMetadata {
isActive: Boolean
}
type PostMetadata {
tags: Tag
}
type Tag {
published: Boolean
metadata: PostMetadata
}
enum Episode {
NEWHOPE
EMPIRE
JEDI
}
type Require @model {
id: ID!
requiredField: String!
notRequiredField: String
}
type Comment @model(timestamps: { createdAt: "createdOn", updatedAt: "updatedOn" }) {
id: ID!
title: String!
content: String
updatedOn: Int # No automatic generation of timestamp if its not AWSDateTime
}
`;
const transformer = new GraphQLTransform({
transformers: [new ModelTransformer()],
featureFlags,
});
const result = transformer.transform(validSchema);
expect(result).toBeDefined();
expect(result.schema).toBeDefined();
const schema = parse(result.schema);
validateModelSchema(schema);
expect(result.schema).toMatchSnapshot();
expect(verifyInputCount(schema, 'ModelEpisodeInput', 1)).toBeTruthy();
});
it('should support support scalar list', () => {
const validSchema = /* GraphQL */ `
type Post @model {
id: ID!
author: String!
title: String
content: String
url: String
ups: Int
downs: Int
version: Int
postedAt: String
createdAt: AWSDateTime
comments: [String!]
ratings: [Int!]
percentageUp: Float
isPublished: Boolean
jsonField: AWSJSON
}
`;
const transformer = new GraphQLTransform({
transformers: [new ModelTransformer()],
featureFlags,
});
const out = transformer.transform(validSchema);
expect(out).toBeDefined();
validateModelSchema(parse(out.schema));
});
});

@@ -48,2 +48,3 @@ import { InvalidDirectiveError, MappingTemplate, TransformerModelBase } from '@aws-amplify/graphql-transformer-core';

makeListQueryModel,
makeModelSortDirectionEnumObject,
makeMutationConditionInput,

@@ -196,7 +197,6 @@ makeUpdateInputField,

transformSchema = (ctx: TransformerTransformSchemaStepContextProvider): void => {
// Create Non Model input types
// add the model input conditions
addModelConditionInputs(ctx);
this.ensureModelSortDirectionEnum(ctx);
for (const type of this.typesWithModelDirective) {

@@ -206,25 +206,8 @@ const def = ctx.output.getObject(type)!;

this.createNonModelInputs(ctx, def);
const queryFields = this.getQueryFieldNames(ctx, def!);
for (const queryField of queryFields.values()) {
const outputType = this.getOutputType(ctx, def, queryField);
const args = this.getInputs(ctx, def!, {
fieldName: queryField.fieldName,
typeName: queryField.typeName,
type: queryField.type,
});
const getField = makeField(queryField.fieldName, args, makeNamedType(outputType.name.value));
ctx.output.addQueryFields([getField]);
}
const mutationFields = this.getMutationFieldNames(ctx, def!);
for (const mutationField of mutationFields) {
const args = this.getInputs(ctx, def!, {
fieldName: mutationField.fieldName,
typeName: mutationField.typeName,
type: mutationField.type,
});
const queryFields = this.createQueryFields(ctx, def);
ctx.output.addQueryFields(queryFields);
const field = makeField(mutationField.fieldName, args, makeNamedType(def!.name.value));
ctx.output.addMutationFields([field]);
}
const mutationFields = this.createMutationFields(ctx, def);
ctx.output.addMutationFields(mutationFields);

@@ -625,3 +608,37 @@ const subscriptionsFields = this.createSubscriptionFields(ctx, def!);

createSubscriptionFields = (ctx: TransformerTransformSchemaStepContextProvider, def: ObjectTypeDefinitionNode): FieldDefinitionNode[] => {
private createQueryFields = (ctx: TransformerValidationStepContextProvider, def: ObjectTypeDefinitionNode): FieldDefinitionNode[] => {
const queryFields: FieldDefinitionNode[] = [];
const queryFieldNames = this.getQueryFieldNames(ctx, def!);
for (const queryField of queryFieldNames.values()) {
const outputType = this.getOutputType(ctx, def, queryField);
const args = this.getInputs(ctx, def!, {
fieldName: queryField.fieldName,
typeName: queryField.typeName,
type: queryField.type,
});
queryFields.push(makeField(queryField.fieldName, args, makeNamedType(outputType.name.value)));
}
return queryFields;
};
private createMutationFields = (ctx: TransformerValidationStepContextProvider, def: ObjectTypeDefinitionNode): FieldDefinitionNode[] => {
const mutationFields: FieldDefinitionNode[] = [];
const mutationFieldNames = this.getMutationFieldNames(ctx, def!);
for (const mutationField of mutationFieldNames) {
const args = this.getInputs(ctx, def!, {
fieldName: mutationField.fieldName,
typeName: mutationField.typeName,
type: mutationField.type,
});
mutationFields.push(makeField(mutationField.fieldName, args, makeNamedType(def!.name.value)));
}
return mutationFields;
};
private createSubscriptionFields = (
ctx: TransformerTransformSchemaStepContextProvider,
def: ObjectTypeDefinitionNode,
): FieldDefinitionNode[] => {
const subscriptionToMutationsMap = this.getSubscriptionToMutationsReverseMap(ctx, def);

@@ -773,4 +790,5 @@ const mutationFields = this.getMutationFieldNames(ctx, def!);

const filterInputName = toPascalCase(['Model', type.name.value, 'FilterInput']);
const filterInputs = makeListQueryFilterInput(ctx, filterInputName, type);
for (let input of [filterInputs]) {
const filterInputs = createEnumModelFilters(ctx, type);
filterInputs.push(makeListQueryFilterInput(ctx, filterInputName, type));
for (let input of filterInputs) {
const conditionInputName = input.name.value;

@@ -781,2 +799,3 @@ if (!ctx.output.getType(conditionInputName)) {

}
return [

@@ -960,2 +979,10 @@ makeInputValueDefinition('filter', makeNamedType(filterInputName)),

};
private ensureModelSortDirectionEnum(ctx: TransformerValidationStepContextProvider): void {
if (!ctx.output.hasType('ModelSortDirection')) {
const modelSortDirection = makeModelSortDirectionEnumObject();
ctx.output.addEnum(modelSortDirection);
}
}
}

@@ -6,2 +6,3 @@ import { TransformerTransformSchemaStepContextProvider } from '@aws-amplify/graphql-transformer-interfaces';

InputObjectTypeDefinitionNode,
Kind,
ObjectTypeDefinitionNode,

@@ -18,3 +19,2 @@ TypeDefinitionNode,

ModelResourceIDs,
toPascalCase,
} from 'graphql-transformer-common';

@@ -37,2 +37,3 @@ import {

EnumWrapper,
FieldWrapper,
InputFieldWrapper,

@@ -47,3 +48,3 @@ InputObjectDefinitionWrapper,

* @param name model name
* @param object ModelObjectDefination
* @param object ModelObjectDefinition
*/

@@ -55,2 +56,3 @@ export const makeConditionFilterInput = (

): InputObjectDefinitionWrapper => {
const supportsConditions = true;
const input = InputObjectDefinitionWrapper.create(name);

@@ -60,12 +62,10 @@ const wrappedObject = new ObjectDefinitionWrapper(object);

const fieldType = ctx.output.getType(field.getTypeName());
const isEnumType = fieldType && fieldType.kind === 'EnumTypeDefinition';
if (field.isScalar() || field.isList()) {
const conditionTypeName = field.isList()
? ModelResourceIDs.ModelFilterListInputTypeName(field.getTypeName(), true)
: ModelResourceIDs.ModelFilterScalarInputTypeName(field.getTypeName(), true);
const inputField = InputFieldWrapper.create(field.name, conditionTypeName, true, field.isList());
const isEnumType = fieldType && fieldType.kind === Kind.ENUM_TYPE_DEFINITION;
if (field.isScalar() || isEnumType) {
const conditionTypeName =
isEnumType && field.isList()
? ModelResourceIDs.ModelFilterListInputTypeName(field.getTypeName(), !supportsConditions)
: ModelResourceIDs.ModelFilterScalarInputTypeName(field.getTypeName(), !supportsConditions);
const inputField = InputFieldWrapper.create(field.name, conditionTypeName, true);
input.addField(inputField);
} else if (isEnumType) {
const inputField = InputFieldWrapper.create(field.name, field.getTypeName(), true, field.isList());
input.addField(inputField);
}

@@ -89,3 +89,3 @@ }

const conditionsInput: TypeDefinitionNode[] = ['String', 'Int', 'Float', 'Boolean', 'ID'].map(scalarName =>
makeModelScalarFilterInputObject(scalarName, false),
makeModelScalarFilterInputObject(scalarName, true),
);

@@ -126,3 +126,4 @@ conditionsInput.push(makeAttributeTypeEnum());

});
return enumFields.map(field => makeEnumFilterInput(field.getTypeName()));
return enumFields.map(field => makeEnumFilterInput(field));
};

@@ -234,9 +235,20 @@

export function makeEnumFilterInput(name: string): InputObjectTypeDefinitionNode {
const inputName = toPascalCase(['Model', name, 'Input']);
const input = InputObjectDefinitionWrapper.create(inputName);
export function makeEnumFilterInput(fieldWrapper: FieldWrapper): InputObjectTypeDefinitionNode {
const supportsConditions = true;
const conditionTypeName = fieldWrapper.isList()
? ModelResourceIDs.ModelFilterListInputTypeName(fieldWrapper.getTypeName(), !supportsConditions)
: ModelResourceIDs.ModelFilterScalarInputTypeName(fieldWrapper.getTypeName(), !supportsConditions);
const input = InputObjectDefinitionWrapper.create(conditionTypeName);
['eq', 'ne'].forEach(fieldName => {
const field = InputFieldWrapper.create(fieldName, name, true);
const field = InputFieldWrapper.create(fieldName, fieldWrapper.getTypeName(), true, fieldWrapper.isList());
input.addField(field);
});
if (fieldWrapper.isList()) {
['contains', 'notContains'].forEach(fieldName => {
const field = InputFieldWrapper.create(fieldName, fieldWrapper.getTypeName(), true);
input.addField(field);
});
}
return input.serialize();

@@ -243,0 +255,0 @@ }

import { TransformerTransformSchemaStepContextProvider } from '@aws-amplify/graphql-transformer-interfaces';
import { ObjectTypeDefinitionNode, InputObjectTypeDefinitionNode, DocumentNode } from 'graphql';
import { DocumentNode, InputObjectTypeDefinitionNode, ObjectTypeDefinitionNode } from 'graphql';
import { ModelResourceIDs, toPascalCase } from 'graphql-transformer-common';
import { ModelDirectiveConfiguration } from '../graphql-model-transformer';
import { ObjectDefinitionWrapper, InputObjectDefinitionWrapper, InputFieldWrapper } from '../wrappers/object-definition-wrapper';
import { InputFieldWrapper, InputObjectDefinitionWrapper, ObjectDefinitionWrapper } from '../wrappers/object-definition-wrapper';
import { makeConditionFilterInput } from './common';

@@ -33,3 +33,3 @@

.map(field => {
return field.getTypeName();
return field.name;
});

@@ -107,3 +107,3 @@

.map(field => {
return field.getTypeName();
return field.name;
});

@@ -145,3 +145,3 @@

const input = makeConditionFilterInput(ctx, name, object);
const idField = input.fields.find(f => f.name === 'id' && f.getTypeName() === 'ID');
const idField = input.fields.find(f => f.name === 'id' && f.getTypeName() === 'ModelIDInput');
if (idField) {

@@ -148,0 +148,0 @@ input.removeField(idField);

@@ -91,3 +91,3 @@ import {

isList = (): boolean => {
return isListType(this.type);
return this.isListType(this.type);
};

@@ -132,2 +132,11 @@

};
private isListType = (type: TypeNode): boolean => {
if (type.kind === Kind.NON_NULL_TYPE) {
return isListType(type.type);
} else {
return type.kind === Kind.LIST_TYPE;
}
};
public getBaseType = (): NamedTypeNode => {

@@ -399,3 +408,3 @@ let node = this.type;

removeField = (field: InputFieldWrapper): void => {
if (this.hasField(field.name)) {
if (!this.hasField(field.name)) {
throw new Error(`type ${this.name} does not have the field with name ${field.name}`);

@@ -402,0 +411,0 @@ }

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc