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

graphql-dynamodb-transformer

Package Overview
Dependencies
Maintainers
1
Versions
990
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

graphql-dynamodb-transformer - npm Package Compare versions

Comparing version 1.0.12 to 1.0.13

8

CHANGELOG.md

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

<a name="1.0.13"></a>
## [1.0.13](https://github.com/aws-amplify/amplify-cli/compare/graphql-dynamodb-transformer@1.0.12...graphql-dynamodb-transformer@1.0.13) (2018-08-26)
**Note:** Version bump only for package graphql-dynamodb-transformer
<a name="1.0.12"></a>

@@ -8,0 +16,0 @@ ## [1.0.12](https://github.com/aws-amplify/amplify-cli/compare/graphql-dynamodb-transformer@1.0.11...graphql-dynamodb-transformer@1.0.12) (2018-08-23)

106

lib/__tests__/DynamoDBModelTransformer.test.js

@@ -38,5 +38,11 @@ "use strict";

expectFields(queryType, ['customListPost']);
var subscriptionType = getObjectType(parsed, 'Subscription');
expect(subscriptionType).toBeDefined();
expectFields(subscriptionType, ['onCreatePost', 'onUpdatePost', 'onDeletePost']);
var subField = subscriptionType.fields.find(function (f) { return f.name.value === 'onCreatePost'; });
expect(subField.directives.length).toEqual(1);
expect(subField.directives[0].name.value).toEqual('aws_subscribe');
});
test('Test DynamoDBModelTransformer with mutation overrides', function () {
var validSchema = "type Post @model(mutations: { create: \"customCreatePost\", update: \"customUpdatePost\", delete: \"customDeletePost\" }) { \n id: ID!\n title: String!\n createdAt: String\n updatedAt: String\n }\n ";
var validSchema = "type Post @model(mutations: { create: \"customCreatePost\", update: \"customUpdatePost\", delete: \"customDeletePost\" }) {\n id: ID!\n title: String!\n createdAt: String\n updatedAt: String\n }\n ";
var transformer = new graphql_transformer_core_1.default({

@@ -60,3 +66,3 @@ transformers: [

test('Test DynamoDBModelTransformer with only create mutations', function () {
var validSchema = "type Post @model(mutations: { create: \"customCreatePost\" }) { \n id: ID!\n title: String!\n createdAt: String\n updatedAt: String\n }\n ";
var validSchema = "type Post @model(mutations: { create: \"customCreatePost\" }) {\n id: ID!\n title: String!\n createdAt: String\n updatedAt: String\n }\n ";
var transformer = new graphql_transformer_core_1.default({

@@ -148,2 +154,98 @@ transformers: [

});
test('Test DynamoDBModelTransformer with mutations set to null', function () {
var validSchema = "type Post @model(mutations: null) {\n id: ID!\n title: String!\n createdAt: String\n updatedAt: String\n }\n ";
var transformer = new graphql_transformer_core_1.default({
transformers: [new graphql_appsync_transformer_1.default(), new DynamoDBModelTransformer_1.DynamoDBModelTransformer()]
});
var out = transformer.transform(validSchema);
expect(out).toBeDefined();
var schema = out.Resources[graphql_transformer_common_1.ResourceConstants.RESOURCES.GraphQLSchemaLogicalID];
expect(schema).toBeDefined();
var definition = schema.Properties.Definition;
expect(definition).toBeDefined();
var parsed = graphql_1.parse(definition);
var mutationType = getObjectType(parsed, 'Mutation');
expect(mutationType).not.toBeDefined();
});
test('Test DynamoDBModelTransformer with queries set to null', function () {
var validSchema = "type Post @model(queries: null) {\n id: ID!\n title: String!\n createdAt: String\n updatedAt: String\n }\n ";
var transformer = new graphql_transformer_core_1.default({
transformers: [new graphql_appsync_transformer_1.default(), new DynamoDBModelTransformer_1.DynamoDBModelTransformer()]
});
var out = transformer.transform(validSchema);
expect(out).toBeDefined();
var schema = out.Resources[graphql_transformer_common_1.ResourceConstants.RESOURCES.GraphQLSchemaLogicalID];
expect(schema).toBeDefined();
var definition = schema.Properties.Definition;
expect(definition).toBeDefined();
var parsed = graphql_1.parse(definition);
var mutationType = getObjectType(parsed, 'Mutation');
expect(mutationType).toBeDefined();
var queryType = getObjectType(parsed, 'Query');
expect(queryType).not.toBeDefined();
});
test('Test DynamoDBModelTransformer with subscriptions set to null', function () {
var validSchema = "type Post @model(subscriptions: null) {\n id: ID!\n title: String!\n createdAt: String\n updatedAt: String\n }\n ";
var transformer = new graphql_transformer_core_1.default({
transformers: [new graphql_appsync_transformer_1.default(), new DynamoDBModelTransformer_1.DynamoDBModelTransformer()]
});
var out = transformer.transform(validSchema);
expect(out).toBeDefined();
var schema = out.Resources[graphql_transformer_common_1.ResourceConstants.RESOURCES.GraphQLSchemaLogicalID];
expect(schema).toBeDefined();
var definition = schema.Properties.Definition;
expect(definition).toBeDefined();
var parsed = graphql_1.parse(definition);
var mutationType = getObjectType(parsed, 'Mutation');
expect(mutationType).toBeDefined();
var queryType = getObjectType(parsed, 'Query');
expect(queryType).toBeDefined();
var subscriptionType = getObjectType(parsed, 'Subscription');
expect(subscriptionType).not.toBeDefined();
});
test('Test DynamoDBModelTransformer with queries and mutations set to null', function () {
var validSchema = "type Post @model(queries: null, mutations: null, subscriptions: null) {\n id: ID!\n title: String!\n createdAt: String\n updatedAt: String\n }\n ";
var transformer = new graphql_transformer_core_1.default({
transformers: [new graphql_appsync_transformer_1.default(), new DynamoDBModelTransformer_1.DynamoDBModelTransformer()]
});
var out = transformer.transform(validSchema);
expect(out).toBeDefined();
var schema = out.Resources[graphql_transformer_common_1.ResourceConstants.RESOURCES.GraphQLSchemaLogicalID];
expect(schema).toBeDefined();
var definition = schema.Properties.Definition;
expect(definition).toBeDefined();
var parsed = graphql_1.parse(definition);
var mutationType = getObjectType(parsed, 'Mutation');
expect(mutationType).not.toBeDefined();
var queryType = getObjectType(parsed, 'Query');
expect(queryType).not.toBeDefined();
var subscriptionType = getObjectType(parsed, 'Subscription');
expect(subscriptionType).not.toBeDefined();
});
test('Test DynamoDBModelTransformer with advanced subscriptions', function () {
var validSchema = "type Post @model(subscriptions: {\n onCreate: [\"onFeedUpdated\", \"onCreatePost\"],\n onUpdate: [\"onFeedUpdated\"],\n onDelete: [\"onFeedUpdated\"]\n }) {\n id: ID!\n title: String!\n createdAt: String\n updatedAt: String\n }\n ";
var transformer = new graphql_transformer_core_1.default({
transformers: [new graphql_appsync_transformer_1.default(), new DynamoDBModelTransformer_1.DynamoDBModelTransformer()]
});
var out = transformer.transform(validSchema);
expect(out).toBeDefined();
var schema = out.Resources[graphql_transformer_common_1.ResourceConstants.RESOURCES.GraphQLSchemaLogicalID];
expect(schema).toBeDefined();
var definition = schema.Properties.Definition;
expect(definition).toBeDefined();
var parsed = graphql_1.parse(definition);
var subscriptionType = getObjectType(parsed, 'Subscription');
expect(subscriptionType).toBeDefined();
expectFields(subscriptionType, ['onFeedUpdated', 'onCreatePost']);
var subField = subscriptionType.fields.find(function (f) { return f.name.value === 'onFeedUpdated'; });
expect(subField.directives.length).toEqual(1);
expect(subField.directives[0].name.value).toEqual('aws_subscribe');
var mutationsList = subField.directives[0].arguments.find(function (a) { return a.name.value === 'mutations'; }).value;
console.log(mutationsList.values);
var mutList = mutationsList.values.map(function (v) { return v.value; });
expect(mutList.length).toEqual(3);
expect(mutList).toContain('createPost');
expect(mutList).toContain('updatePost');
expect(mutList).toContain('deletePost');
});
function expectFields(type, fields) {

@@ -150,0 +252,0 @@ var _loop_1 = function (fieldName) {

20

lib/definitions.js

@@ -242,7 +242,13 @@ "use strict";

exports.makeModelConnectionType = makeModelConnectionType;
function makeSubscriptionField(fieldName, returnTypeName, mutations) {
return graphql_transformer_common_1.makeField(fieldName, [], graphql_transformer_common_1.makeNamedType(returnTypeName), [
graphql_transformer_common_1.makeDirective('aws_subscribe', [graphql_transformer_common_1.makeArgument('mutations', graphql_transformer_common_1.makeValueNode(mutations))])
]);
}
exports.makeSubscriptionField = makeSubscriptionField;
function makeModelScanField(fieldName, returnTypeName) {
return graphql_transformer_common_1.makeField(fieldName, [
graphql_transformer_common_1.makeArg('filter', graphql_transformer_common_1.makeNamedType(graphql_transformer_common_1.ModelResourceIDs.ModelFilterInputTypeName(returnTypeName))),
graphql_transformer_common_1.makeArg('limit', graphql_transformer_common_1.makeNamedType('Int')),
graphql_transformer_common_1.makeArg('nextToken', graphql_transformer_common_1.makeNamedType('String'))
graphql_transformer_common_1.makeInputValueDefinition('filter', graphql_transformer_common_1.makeNamedType(graphql_transformer_common_1.ModelResourceIDs.ModelFilterInputTypeName(returnTypeName))),
graphql_transformer_common_1.makeInputValueDefinition('limit', graphql_transformer_common_1.makeNamedType('Int')),
graphql_transformer_common_1.makeInputValueDefinition('nextToken', graphql_transformer_common_1.makeNamedType('String'))
], graphql_transformer_common_1.makeNamedType(graphql_transformer_common_1.ModelResourceIDs.ModelConnectionTypeName(returnTypeName)));

@@ -253,6 +259,6 @@ }

return graphql_transformer_common_1.makeField(fieldName, [
graphql_transformer_common_1.makeArg('filter', graphql_transformer_common_1.makeNamedType(graphql_transformer_common_1.ModelResourceIDs.ModelFilterInputTypeName(returnTypeName))),
graphql_transformer_common_1.makeArg('sortDirection', graphql_transformer_common_1.makeNamedType('ModelSortDirection')),
graphql_transformer_common_1.makeArg('limit', graphql_transformer_common_1.makeNamedType('Int')),
graphql_transformer_common_1.makeArg('nextToken', graphql_transformer_common_1.makeNamedType('String'))
graphql_transformer_common_1.makeInputValueDefinition('filter', graphql_transformer_common_1.makeNamedType(graphql_transformer_common_1.ModelResourceIDs.ModelFilterInputTypeName(returnTypeName))),
graphql_transformer_common_1.makeInputValueDefinition('sortDirection', graphql_transformer_common_1.makeNamedType('ModelSortDirection')),
graphql_transformer_common_1.makeInputValueDefinition('limit', graphql_transformer_common_1.makeNamedType('Int')),
graphql_transformer_common_1.makeInputValueDefinition('nextToken', graphql_transformer_common_1.makeNamedType('String'))
], graphql_transformer_common_1.makeNamedType(graphql_transformer_common_1.ModelResourceIDs.ModelConnectionTypeName(returnTypeName)));

@@ -259,0 +265,0 @@ }

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

function DynamoDBModelTransformer() {
var _this = _super.call(this, 'DynamoDBModelTransformer', "\n directive @model(\n queries: ModelQueryMap,\n mutations: ModelMutationMap\n ) on OBJECT\n input ModelMutationMap { create: String, update: String, delete: String }\n input ModelQueryMap { get: String, list: String }\n ") || this;
var _this = _super.call(this, 'DynamoDBModelTransformer', "\n directive @model(\n queries: ModelQueryMap,\n mutations: ModelMutationMap,\n subscriptions: ModelSubscriptionMap\n ) on OBJECT\n input ModelMutationMap { create: String, update: String, delete: String }\n input ModelQueryMap { get: String, list: String }\n input ModelSubscriptionMap {\n onCreate: [String]\n onUpdate: [String]\n onDelete: [String]\n }\n ") || this;
_this.before = function (ctx) {

@@ -60,2 +60,8 @@ var template = _this.resources.initTemplate();

ctx.setResource(graphql_transformer_common_2.ModelResourceIDs.ModelTableDataSourceID(typeName), _this.resources.makeDynamoDBDataSource(tableLogicalID, iamRoleLogicalID));
_this.createQueries(def, directive, ctx);
_this.createMutations(def, directive, ctx);
_this.createSubscriptions(def, directive, ctx);
};
_this.createMutations = function (def, directive, ctx) {
var typeName = def.name.value;
// Create the input types.

@@ -68,44 +74,20 @@ var createInput = definitions_1.makeCreateInputObject(def);

ctx.addInput(deleteInput);
// Create the mutation & query extension
var mutationType = graphql_transformer_common_1.blankObjectExtension('Mutation');
var queryType = graphql_transformer_common_1.blankObjectExtension('Query');
// Get any name overrides provided by the user. If an empty map it provided
// then we do not generate those fields.
var directiveArguments = _super.prototype.getDirectiveArgumentMap.call(_this, directive);
// Configure mutations based on *mutations* argument
var shouldMakeCreate = true;
var shouldMakeUpdate = true;
var shouldMakeDelete = true;
var shouldMakeGet = true;
// TODO: Re-enable this if needed but its redundant as of now.
var shouldMakeQuery = false;
var shouldMakeList = true;
var createFieldNameOverride = undefined;
var updateFieldNameOverride = undefined;
var deleteFieldNameOverride = undefined;
var getFieldNameOverride = undefined;
var listFieldNameOverride = undefined;
var queryFieldNameOverride = undefined;
// Figure out which queries to make and if they have name overrides.
if (directiveArguments.queries) {
if (!directiveArguments.queries.get) {
shouldMakeGet = false;
}
else {
getFieldNameOverride = directiveArguments.queries.get;
}
if (!directiveArguments.queries.query) {
shouldMakeQuery = false;
}
else {
queryFieldNameOverride = directiveArguments.queries.query;
}
if (!directiveArguments.queries.list) {
shouldMakeList = false;
}
else {
listFieldNameOverride = directiveArguments.queries.list;
}
// Figure out which mutations to make and if they have name overrides
if (directiveArguments.mutations === null) {
shouldMakeCreate = false;
shouldMakeUpdate = false;
shouldMakeDelete = false;
}
// Figure out which mutations to make and if they have name overrides
if (directiveArguments.mutations) {
else if (directiveArguments.mutations) {
if (!directiveArguments.mutations.create) {

@@ -130,4 +112,2 @@ shouldMakeCreate = false;

}
var queryNameMap = directiveArguments.queries;
var mutationNameMap = directiveArguments.mutations;
// Create the mutations.

@@ -137,3 +117,3 @@ if (shouldMakeCreate) {

ctx.setResource(graphql_transformer_common_2.ResolverResourceIDs.DynamoDBCreateResolverResourceID(typeName), createResolver);
mutationType = graphql_transformer_common_1.extensionWithFields(mutationType, [graphql_transformer_common_1.makeField(createResolver.Properties.FieldName, [graphql_transformer_common_1.makeArg('input', graphql_transformer_common_1.makeNonNullType(graphql_transformer_common_1.makeNamedType(createInput.name.value)))], graphql_transformer_common_1.makeNamedType(def.name.value))]);
mutationType = graphql_transformer_common_1.extensionWithFields(mutationType, [graphql_transformer_common_1.makeField(createResolver.Properties.FieldName, [graphql_transformer_common_1.makeInputValueDefinition('input', graphql_transformer_common_1.makeNonNullType(graphql_transformer_common_1.makeNamedType(createInput.name.value)))], graphql_transformer_common_1.makeNamedType(def.name.value))]);
}

@@ -143,3 +123,3 @@ if (shouldMakeUpdate) {

ctx.setResource(graphql_transformer_common_2.ResolverResourceIDs.DynamoDBUpdateResolverResourceID(typeName), updateResolver);
mutationType = graphql_transformer_common_1.extensionWithFields(mutationType, [graphql_transformer_common_1.makeField(updateResolver.Properties.FieldName, [graphql_transformer_common_1.makeArg('input', graphql_transformer_common_1.makeNonNullType(graphql_transformer_common_1.makeNamedType(updateInput.name.value)))], graphql_transformer_common_1.makeNamedType(def.name.value))]);
mutationType = graphql_transformer_common_1.extensionWithFields(mutationType, [graphql_transformer_common_1.makeField(updateResolver.Properties.FieldName, [graphql_transformer_common_1.makeInputValueDefinition('input', graphql_transformer_common_1.makeNonNullType(graphql_transformer_common_1.makeNamedType(updateInput.name.value)))], graphql_transformer_common_1.makeNamedType(def.name.value))]);
}

@@ -149,6 +129,38 @@ if (shouldMakeDelete) {

ctx.setResource(graphql_transformer_common_2.ResolverResourceIDs.DynamoDBDeleteResolverResourceID(typeName), deleteResolver);
mutationType = graphql_transformer_common_1.extensionWithFields(mutationType, [graphql_transformer_common_1.makeField(deleteResolver.Properties.FieldName, [graphql_transformer_common_1.makeArg('input', graphql_transformer_common_1.makeNonNullType(graphql_transformer_common_1.makeNamedType(deleteInput.name.value)))], graphql_transformer_common_1.makeNamedType(def.name.value))]);
mutationType = graphql_transformer_common_1.extensionWithFields(mutationType, [graphql_transformer_common_1.makeField(deleteResolver.Properties.FieldName, [graphql_transformer_common_1.makeInputValueDefinition('input', graphql_transformer_common_1.makeNonNullType(graphql_transformer_common_1.makeNamedType(deleteInput.name.value)))], graphql_transformer_common_1.makeNamedType(def.name.value))]);
}
ctx.addObjectExtension(mutationType);
if (shouldMakeQuery || shouldMakeList) {
};
_this.createQueries = function (def, directive, ctx) {
var typeName = def.name.value;
var queryType = graphql_transformer_common_1.blankObjectExtension('Query');
var directiveArguments = _this.getDirectiveArgumentMap(directive);
// Configure queries based on *queries* argument
var shouldMakeGet = true;
var shouldMakeList = true;
var getFieldNameOverride = undefined;
var listFieldNameOverride = undefined;
// Figure out which queries to make and if they have name overrides.
// If queries is undefined (default), create all queries
// If queries is explicetly set to null, do not create any
// else if queries is defined, check overrides
if (directiveArguments.queries === null) {
shouldMakeGet = false;
shouldMakeList = false;
}
else if (directiveArguments.queries) {
if (!directiveArguments.queries.get) {
shouldMakeGet = false;
}
else {
getFieldNameOverride = directiveArguments.queries.get;
}
if (!directiveArguments.queries.list) {
shouldMakeList = false;
}
else {
listFieldNameOverride = directiveArguments.queries.list;
}
}
if (shouldMakeList) {
if (!_this.typeExist('ModelSortDirection', ctx)) {

@@ -159,10 +171,2 @@ var tableSortDirection = definitions_1.makeModelSortDirectionEnumObject();

}
// Create query queries
if (shouldMakeQuery) {
_this.generateModelXConnectionType(ctx, def);
var queryResolver = _this.resources.makeQueryResolver(def.name.value, queryFieldNameOverride);
ctx.setResource(graphql_transformer_common_2.ResolverResourceIDs.DynamoDBQueryResolverResourceID(typeName), queryResolver);
queryType = graphql_transformer_common_1.extensionWithFields(queryType, [definitions_1.makeModelConnectionField(queryResolver.Properties.FieldName, def.name.value)]);
_this.generateFilterInputs(ctx, def);
}
// Create get queries

@@ -172,3 +176,3 @@ if (shouldMakeGet) {

ctx.setResource(graphql_transformer_common_2.ResolverResourceIDs.DynamoDBGetResolverResourceID(typeName), getResolver);
queryType = graphql_transformer_common_1.extensionWithFields(queryType, [graphql_transformer_common_1.makeField(getResolver.Properties.FieldName, [graphql_transformer_common_1.makeArg('id', graphql_transformer_common_1.makeNonNullType(graphql_transformer_common_1.makeNamedType('ID')))], graphql_transformer_common_1.makeNamedType(def.name.value))]);
queryType = graphql_transformer_common_1.extensionWithFields(queryType, [graphql_transformer_common_1.makeField(getResolver.Properties.FieldName, [graphql_transformer_common_1.makeInputValueDefinition('id', graphql_transformer_common_1.makeNonNullType(graphql_transformer_common_1.makeNamedType('ID')))], graphql_transformer_common_1.makeNamedType(def.name.value))]);
}

@@ -186,2 +190,81 @@ if (shouldMakeList) {

};
/**
* Creates subscriptions for a @model object type. By default creates a subscription for
* create, update, and delete mutations.
*
* Subscriptions are one to many in that a subscription may subscribe to multiple mutations.
* You may thus provide multiple names of the subscriptions that will be triggered by each
* mutation.
*
* type Post @model(subscriptions: { onCreate: ["onPostCreated", "onFeedUpdated"] }) {
* id: ID!
* title: String!
* }
*
* will create two subscription fields:
*
* type Subscription {
* onPostCreated: Post @aws_subscribe(mutations: ["createPost"])
* onFeedUpdated: Post @aws_subscribe(mutations: ["createPost"])
* }
*/
_this.createSubscriptions = function (def, directive, ctx) {
var typeName = def.name.value;
var subscriptionType = graphql_transformer_common_1.blankObjectExtension('Subscription');
var directiveArguments = _this.getDirectiveArgumentMap(directive);
var subscriptionsArgument = directiveArguments.subscriptions;
var createResolver = ctx.getResource(graphql_transformer_common_2.ResolverResourceIDs.DynamoDBCreateResolverResourceID(typeName));
var updateResolver = ctx.getResource(graphql_transformer_common_2.ResolverResourceIDs.DynamoDBUpdateResolverResourceID(typeName));
var deleteResolver = ctx.getResource(graphql_transformer_common_2.ResolverResourceIDs.DynamoDBDeleteResolverResourceID(typeName));
if (subscriptionsArgument === null) {
return;
}
else if (subscriptionsArgument) {
// Add the custom subscriptions
var subscriptionToMutationsMap = {};
var onCreate = subscriptionsArgument.onCreate || [];
var onUpdate = subscriptionsArgument.onUpdate || [];
var onDelete = subscriptionsArgument.onDelete || [];
var subFields = onCreate.concat(onUpdate, onDelete);
// initialize the reverse lookup
for (var _i = 0, subFields_1 = subFields; _i < subFields_1.length; _i++) {
var field = subFields_1[_i];
subscriptionToMutationsMap[field] = [];
}
// Add the correct mutation to the lookup
for (var _a = 0, _b = Object.keys(subscriptionToMutationsMap); _a < _b.length; _a++) {
var field = _b[_a];
if (onCreate.includes(field) && createResolver) {
subscriptionToMutationsMap[field].push(createResolver.Properties.FieldName);
}
if (onUpdate.includes(field) && updateResolver) {
subscriptionToMutationsMap[field].push(updateResolver.Properties.FieldName);
}
if (onDelete.includes(field) && deleteResolver) {
subscriptionToMutationsMap[field].push(deleteResolver.Properties.FieldName);
}
}
for (var _c = 0, _d = Object.keys(subscriptionToMutationsMap); _c < _d.length; _c++) {
var subFieldName = _d[_c];
var subField = definitions_1.makeSubscriptionField(subFieldName, typeName, subscriptionToMutationsMap[subFieldName]);
subscriptionType = graphql_transformer_common_1.extensionWithFields(subscriptionType, [subField]);
}
}
else {
// Add the default subscriptions
if (createResolver) {
var onCreateField = definitions_1.makeSubscriptionField(graphql_transformer_common_2.ModelResourceIDs.ModelOnCreateSubscriptionName(typeName), typeName, [createResolver.Properties.FieldName]);
subscriptionType = graphql_transformer_common_1.extensionWithFields(subscriptionType, [onCreateField]);
}
if (updateResolver) {
var onUpdateField = definitions_1.makeSubscriptionField(graphql_transformer_common_2.ModelResourceIDs.ModelOnUpdateSubscriptionName(typeName), typeName, [updateResolver.Properties.FieldName]);
subscriptionType = graphql_transformer_common_1.extensionWithFields(subscriptionType, [onUpdateField]);
}
if (deleteResolver) {
var onDeleteField = definitions_1.makeSubscriptionField(graphql_transformer_common_2.ModelResourceIDs.ModelOnDeleteSubscriptionName(typeName), typeName, [deleteResolver.Properties.FieldName]);
subscriptionType = graphql_transformer_common_1.extensionWithFields(subscriptionType, [onDeleteField]);
}
}
ctx.addObjectExtension(subscriptionType);
};
_this.resources = new resources_1.ResourceFactory();

@@ -188,0 +271,0 @@ return _this;

{
"name": "graphql-dynamodb-transformer",
"version": "1.0.12",
"version": "1.0.13",
"description": "An AppSync model transform that takes a simple model and creates a DynamoDB table, DynamoDB stream, and ES index with the queries to match.",

@@ -23,4 +23,4 @@ "main": "lib/index.js",

"graphql-mapping-template": "^1.0.12",
"graphql-transformer-common": "^1.0.12",
"graphql-transformer-core": "^1.0.12"
"graphql-transformer-common": "^1.0.13",
"graphql-transformer-core": "^1.0.13"
},

@@ -32,3 +32,3 @@ "devDependencies": {

"aws-sdk": "^2.259.1",
"graphql-appsync-transformer": "^1.0.12",
"graphql-appsync-transformer": "^1.0.13",
"jest": "^23.1.0",

@@ -35,0 +35,0 @@ "ts-jest": "^22.4.6",

import {
ObjectTypeDefinitionNode, parse, FieldDefinitionNode, DocumentNode,
DefinitionNode, Kind, InputObjectTypeDefinitionNode
DefinitionNode, Kind, InputObjectTypeDefinitionNode, ListValueNode
} from 'graphql'

@@ -54,6 +54,12 @@ import GraphQLTransform from 'graphql-transformer-core'

expectFields(queryType, ['customListPost'])
const subscriptionType = getObjectType(parsed, 'Subscription')
expect(subscriptionType).toBeDefined()
expectFields(subscriptionType, ['onCreatePost', 'onUpdatePost', 'onDeletePost'])
const subField = subscriptionType.fields.find(f => f.name.value === 'onCreatePost')
expect(subField.directives.length).toEqual(1)
expect(subField.directives[0].name.value).toEqual('aws_subscribe')
});
test('Test DynamoDBModelTransformer with mutation overrides', () => {
const validSchema = `type Post @model(mutations: { create: "customCreatePost", update: "customUpdatePost", delete: "customDeletePost" }) {
const validSchema = `type Post @model(mutations: { create: "customCreatePost", update: "customUpdatePost", delete: "customDeletePost" }) {
id: ID!

@@ -84,3 +90,3 @@ title: String!

test('Test DynamoDBModelTransformer with only create mutations', () => {
const validSchema = `type Post @model(mutations: { create: "customCreatePost" }) {
const validSchema = `type Post @model(mutations: { create: "customCreatePost" }) {
id: ID!

@@ -205,2 +211,133 @@ title: String!

test('Test DynamoDBModelTransformer with mutations set to null', () => {
const validSchema = `type Post @model(mutations: null) {
id: ID!
title: String!
createdAt: String
updatedAt: String
}
`
const transformer = new GraphQLTransform({
transformers: [new AppSyncTransformer(), new DynamoDBModelTransformer()]
})
const out = transformer.transform(validSchema);
expect(out).toBeDefined()
const schema = out.Resources[ResourceConstants.RESOURCES.GraphQLSchemaLogicalID]
expect(schema).toBeDefined()
const definition = schema.Properties.Definition
expect(definition).toBeDefined()
const parsed = parse(definition);
const mutationType = getObjectType(parsed, 'Mutation')
expect(mutationType).not.toBeDefined()
})
test('Test DynamoDBModelTransformer with queries set to null', () => {
const validSchema = `type Post @model(queries: null) {
id: ID!
title: String!
createdAt: String
updatedAt: String
}
`
const transformer = new GraphQLTransform({
transformers: [new AppSyncTransformer(), new DynamoDBModelTransformer()]
})
const out = transformer.transform(validSchema);
expect(out).toBeDefined()
const schema = out.Resources[ResourceConstants.RESOURCES.GraphQLSchemaLogicalID]
expect(schema).toBeDefined()
const definition = schema.Properties.Definition
expect(definition).toBeDefined()
const parsed = parse(definition);
const mutationType = getObjectType(parsed, 'Mutation')
expect(mutationType).toBeDefined()
const queryType = getObjectType(parsed, 'Query')
expect(queryType).not.toBeDefined()
})
test('Test DynamoDBModelTransformer with subscriptions set to null', () => {
const validSchema = `type Post @model(subscriptions: null) {
id: ID!
title: String!
createdAt: String
updatedAt: String
}
`
const transformer = new GraphQLTransform({
transformers: [new AppSyncTransformer(), new DynamoDBModelTransformer()]
})
const out = transformer.transform(validSchema);
expect(out).toBeDefined()
const schema = out.Resources[ResourceConstants.RESOURCES.GraphQLSchemaLogicalID]
expect(schema).toBeDefined()
const definition = schema.Properties.Definition
expect(definition).toBeDefined()
const parsed = parse(definition);
const mutationType = getObjectType(parsed, 'Mutation')
expect(mutationType).toBeDefined()
const queryType = getObjectType(parsed, 'Query')
expect(queryType).toBeDefined()
const subscriptionType = getObjectType(parsed, 'Subscription')
expect(subscriptionType).not.toBeDefined()
})
test('Test DynamoDBModelTransformer with queries and mutations set to null', () => {
const validSchema = `type Post @model(queries: null, mutations: null, subscriptions: null) {
id: ID!
title: String!
createdAt: String
updatedAt: String
}
`
const transformer = new GraphQLTransform({
transformers: [new AppSyncTransformer(), new DynamoDBModelTransformer()]
})
const out = transformer.transform(validSchema);
expect(out).toBeDefined()
const schema = out.Resources[ResourceConstants.RESOURCES.GraphQLSchemaLogicalID]
expect(schema).toBeDefined()
const definition = schema.Properties.Definition
expect(definition).toBeDefined()
const parsed = parse(definition);
const mutationType = getObjectType(parsed, 'Mutation')
expect(mutationType).not.toBeDefined()
const queryType = getObjectType(parsed, 'Query')
expect(queryType).not.toBeDefined()
const subscriptionType = getObjectType(parsed, 'Subscription')
expect(subscriptionType).not.toBeDefined()
})
test('Test DynamoDBModelTransformer with advanced subscriptions', () => {
const validSchema = `type Post @model(subscriptions: {
onCreate: ["onFeedUpdated", "onCreatePost"],
onUpdate: ["onFeedUpdated"],
onDelete: ["onFeedUpdated"]
}) {
id: ID!
title: String!
createdAt: String
updatedAt: String
}
`
const transformer = new GraphQLTransform({
transformers: [new AppSyncTransformer(), new DynamoDBModelTransformer()]
})
const out = transformer.transform(validSchema);
expect(out).toBeDefined()
const schema = out.Resources[ResourceConstants.RESOURCES.GraphQLSchemaLogicalID]
expect(schema).toBeDefined()
const definition = schema.Properties.Definition
expect(definition).toBeDefined()
const parsed = parse(definition);
const subscriptionType = getObjectType(parsed, 'Subscription')
expect(subscriptionType).toBeDefined()
expectFields(subscriptionType, ['onFeedUpdated', 'onCreatePost'])
const subField = subscriptionType.fields.find(f => f.name.value === 'onFeedUpdated')
expect(subField.directives.length).toEqual(1)
expect(subField.directives[0].name.value).toEqual('aws_subscribe')
const mutationsList = subField.directives[0].arguments.find(a => a.name.value === 'mutations').value as ListValueNode
console.log(mutationsList.values)
const mutList = mutationsList.values.map((v: any) => v.value)
expect(mutList.length).toEqual(3)
expect(mutList).toContain('createPost')
expect(mutList).toContain('updatePost')
expect(mutList).toContain('deletePost')
})
function expectFields(type: ObjectTypeDefinitionNode, fields: string[]) {

@@ -207,0 +344,0 @@ for (const fieldName of fields) {

@@ -9,4 +9,7 @@ import {

isScalar, getBaseType, blankObjectExtension, extensionWithFields, makeField,
makeArg,
ModelResourceIDs
makeInputValueDefinition,
ModelResourceIDs,
makeDirective,
makeArgument,
makeValueNode
} from 'graphql-transformer-common'

@@ -280,2 +283,16 @@

export function makeSubscriptionField(fieldName: string, returnTypeName: string, mutations: string[]): FieldDefinitionNode {
return makeField(
fieldName,
[],
makeNamedType(returnTypeName),
[
makeDirective(
'aws_subscribe',
[makeArgument('mutations', makeValueNode(mutations))]
)
]
)
}
export function makeModelScanField(fieldName: string, returnTypeName: string): FieldDefinitionNode {

@@ -285,5 +302,5 @@ return makeField(

[
makeArg('filter', makeNamedType(ModelResourceIDs.ModelFilterInputTypeName(returnTypeName))),
makeArg('limit', makeNamedType('Int')),
makeArg('nextToken', makeNamedType('String'))
makeInputValueDefinition('filter', makeNamedType(ModelResourceIDs.ModelFilterInputTypeName(returnTypeName))),
makeInputValueDefinition('limit', makeNamedType('Int')),
makeInputValueDefinition('nextToken', makeNamedType('String'))
],

@@ -298,6 +315,6 @@ makeNamedType(ModelResourceIDs.ModelConnectionTypeName(returnTypeName))

[
makeArg('filter', makeNamedType(ModelResourceIDs.ModelFilterInputTypeName(returnTypeName))),
makeArg('sortDirection', makeNamedType('ModelSortDirection')),
makeArg('limit', makeNamedType('Int')),
makeArg('nextToken', makeNamedType('String'))
makeInputValueDefinition('filter', makeNamedType(ModelResourceIDs.ModelFilterInputTypeName(returnTypeName))),
makeInputValueDefinition('sortDirection', makeNamedType('ModelSortDirection')),
makeInputValueDefinition('limit', makeNamedType('Int')),
makeInputValueDefinition('nextToken', makeNamedType('String'))
],

@@ -304,0 +321,0 @@ makeNamedType(ModelResourceIDs.ModelConnectionTypeName(returnTypeName))

@@ -1,2 +0,2 @@

import { Transformer, TransformerContext } from 'graphql-transformer-core'
import { Transformer, TransformerContext, TransformerContractError } from 'graphql-transformer-core'
import {

@@ -10,6 +10,6 @@ DirectiveNode, ObjectTypeDefinitionNode

makeModelConnectionType, makeModelConnectionField,
makeScalarFilterInputs, makeModelScanField
makeScalarFilterInputs, makeModelScanField, makeSubscriptionField
} from './definitions'
import {
blankObject, makeField, makeArg, makeNamedType,
blankObject, makeField, makeInputValueDefinition, makeNamedType,
makeNonNullType, makeSchema, makeOperationType, blankObjectExtension,

@@ -32,5 +32,12 @@ extensionWithFields, ResourceConstants, makeListType

interface SubscriptionNameMap {
onCreate?: string[];
onUpdate?: string[];
onDelete?: string[];
}
interface ModelDirectiveArgs {
queries?: QueryNameMap,
mutations?: MutationNameMap
mutations?: MutationNameMap,
subscriptions?: SubscriptionNameMap
}

@@ -63,6 +70,12 @@

queries: ModelQueryMap,
mutations: ModelMutationMap
mutations: ModelMutationMap,
subscriptions: ModelSubscriptionMap
) on OBJECT
input ModelMutationMap { create: String, update: String, delete: String }
input ModelQueryMap { get: String, list: String }
input ModelSubscriptionMap {
onCreate: [String]
onUpdate: [String]
onDelete: [String]
}
`

@@ -107,2 +120,9 @@ )

this.createQueries(def, directive, ctx)
this.createMutations(def, directive, ctx)
this.createSubscriptions(def, directive, ctx)
}
private createMutations = (def: ObjectTypeDefinitionNode, directive: DirectiveNode, ctx: TransformerContext) => {
const typeName = def.name.value
// Create the input types.

@@ -116,6 +136,3 @@ const createInput = makeCreateInputObject(def)

// Create the mutation & query extension
let mutationType = blankObjectExtension('Mutation')
let queryType = blankObjectExtension('Query')
// Get any name overrides provided by the user. If an empty map it provided

@@ -125,37 +142,17 @@ // then we do not generate those fields.

// Configure mutations based on *mutations* argument
let shouldMakeCreate = true;
let shouldMakeUpdate = true;
let shouldMakeDelete = true;
let shouldMakeGet = true;
// TODO: Re-enable this if needed but its redundant as of now.
let shouldMakeQuery = false;
let shouldMakeList = true;
let createFieldNameOverride = undefined;
let updateFieldNameOverride = undefined;
let deleteFieldNameOverride = undefined;
let getFieldNameOverride = undefined;
let listFieldNameOverride = undefined;
let queryFieldNameOverride = undefined;
// Figure out which queries to make and if they have name overrides.
if (directiveArguments.queries) {
if (!directiveArguments.queries.get) {
shouldMakeGet = false;
} else {
getFieldNameOverride = directiveArguments.queries.get
}
if (!directiveArguments.queries.query) {
shouldMakeQuery = false;
} else {
queryFieldNameOverride = directiveArguments.queries.query
}
if (!directiveArguments.queries.list) {
shouldMakeList = false;
} else {
listFieldNameOverride = directiveArguments.queries.list
}
}
// Figure out which mutations to make and if they have name overrides
if (directiveArguments.mutations) {
if (directiveArguments.mutations === null) {
shouldMakeCreate = false
shouldMakeUpdate = false
shouldMakeDelete = false
} else if (directiveArguments.mutations) {
if (!directiveArguments.mutations.create) {

@@ -178,5 +175,2 @@ shouldMakeCreate = false;

const queryNameMap: QueryNameMap = directiveArguments.queries
const mutationNameMap: MutationNameMap = directiveArguments.mutations
// Create the mutations.

@@ -190,3 +184,3 @@ if (shouldMakeCreate) {

createResolver.Properties.FieldName,
[makeArg('input', makeNonNullType(makeNamedType(createInput.name.value)))],
[makeInputValueDefinition('input', makeNonNullType(makeNamedType(createInput.name.value)))],
makeNamedType(def.name.value)

@@ -204,3 +198,3 @@ )]

updateResolver.Properties.FieldName,
[makeArg('input', makeNonNullType(makeNamedType(updateInput.name.value)))],
[makeInputValueDefinition('input', makeNonNullType(makeNamedType(updateInput.name.value)))],
makeNamedType(def.name.value)

@@ -218,3 +212,3 @@ )]

deleteResolver.Properties.FieldName,
[makeArg('input', makeNonNullType(makeNamedType(deleteInput.name.value)))],
[makeInputValueDefinition('input', makeNonNullType(makeNamedType(deleteInput.name.value)))],
makeNamedType(def.name.value)

@@ -225,4 +219,36 @@ )]

ctx.addObjectExtension(mutationType)
}
if (shouldMakeQuery || shouldMakeList) {
private createQueries = (def: ObjectTypeDefinitionNode, directive: DirectiveNode, ctx: TransformerContext) => {
const typeName = def.name.value
let queryType = blankObjectExtension('Query')
const directiveArguments: ModelDirectiveArgs = this.getDirectiveArgumentMap(directive)
// Configure queries based on *queries* argument
let shouldMakeGet = true;
let shouldMakeList = true;
let getFieldNameOverride = undefined;
let listFieldNameOverride = undefined;
// Figure out which queries to make and if they have name overrides.
// If queries is undefined (default), create all queries
// If queries is explicetly set to null, do not create any
// else if queries is defined, check overrides
if (directiveArguments.queries === null) {
shouldMakeGet = false;
shouldMakeList = false;
} else if (directiveArguments.queries) {
if (!directiveArguments.queries.get) {
shouldMakeGet = false;
} else {
getFieldNameOverride = directiveArguments.queries.get
}
if (!directiveArguments.queries.list) {
shouldMakeList = false;
} else {
listFieldNameOverride = directiveArguments.queries.list
}
}
if (shouldMakeList) {
if (!this.typeExist('ModelSortDirection', ctx)) {

@@ -234,17 +260,2 @@ const tableSortDirection = makeModelSortDirectionEnumObject()

// Create query queries
if (shouldMakeQuery) {
this.generateModelXConnectionType(ctx, def)
const queryResolver = this.resources.makeQueryResolver(def.name.value, queryFieldNameOverride)
ctx.setResource(ResolverResourceIDs.DynamoDBQueryResolverResourceID(typeName), queryResolver)
queryType = extensionWithFields(
queryType,
[makeModelConnectionField(queryResolver.Properties.FieldName, def.name.value)]
)
this.generateFilterInputs(ctx, def)
}
// Create get queries

@@ -259,3 +270,3 @@ if (shouldMakeGet) {

getResolver.Properties.FieldName,
[makeArg('id', makeNonNullType(makeNamedType('ID')))],
[makeInputValueDefinition('id', makeNonNullType(makeNamedType('ID')))],
makeNamedType(def.name.value)

@@ -286,2 +297,108 @@ )]

/**
* Creates subscriptions for a @model object type. By default creates a subscription for
* create, update, and delete mutations.
*
* Subscriptions are one to many in that a subscription may subscribe to multiple mutations.
* You may thus provide multiple names of the subscriptions that will be triggered by each
* mutation.
*
* type Post @model(subscriptions: { onCreate: ["onPostCreated", "onFeedUpdated"] }) {
* id: ID!
* title: String!
* }
*
* will create two subscription fields:
*
* type Subscription {
* onPostCreated: Post @aws_subscribe(mutations: ["createPost"])
* onFeedUpdated: Post @aws_subscribe(mutations: ["createPost"])
* }
*/
private createSubscriptions = (def: ObjectTypeDefinitionNode, directive: DirectiveNode, ctx: TransformerContext) => {
const typeName = def.name.value
let subscriptionType = blankObjectExtension('Subscription')
const directiveArguments: ModelDirectiveArgs = this.getDirectiveArgumentMap(directive)
const subscriptionsArgument = directiveArguments.subscriptions
const createResolver = ctx.getResource(ResolverResourceIDs.DynamoDBCreateResolverResourceID(typeName))
const updateResolver = ctx.getResource(ResolverResourceIDs.DynamoDBUpdateResolverResourceID(typeName))
const deleteResolver = ctx.getResource(ResolverResourceIDs.DynamoDBDeleteResolverResourceID(typeName))
if (subscriptionsArgument === null) {
return;
} else if (subscriptionsArgument) {
// Add the custom subscriptions
const subscriptionToMutationsMap: { [subField: string]: string[] } = {}
const onCreate = subscriptionsArgument.onCreate || []
const onUpdate = subscriptionsArgument.onUpdate || []
const onDelete = subscriptionsArgument.onDelete || []
const subFields = [...onCreate, ...onUpdate, ...onDelete]
// initialize the reverse lookup
for (const field of subFields) {
subscriptionToMutationsMap[field] = []
}
// Add the correct mutation to the lookup
for (const field of Object.keys(subscriptionToMutationsMap)) {
if (onCreate.includes(field) && createResolver) {
subscriptionToMutationsMap[field].push(createResolver.Properties.FieldName)
}
if (onUpdate.includes(field) && updateResolver) {
subscriptionToMutationsMap[field].push(updateResolver.Properties.FieldName)
}
if (onDelete.includes(field) && deleteResolver) {
subscriptionToMutationsMap[field].push(deleteResolver.Properties.FieldName)
}
}
for (const subFieldName of Object.keys(subscriptionToMutationsMap)) {
const subField = makeSubscriptionField(
subFieldName,
typeName,
subscriptionToMutationsMap[subFieldName]
)
subscriptionType = extensionWithFields(
subscriptionType,
[subField]
)
}
} else {
// Add the default subscriptions
if (createResolver) {
const onCreateField = makeSubscriptionField(
ModelResourceIDs.ModelOnCreateSubscriptionName(typeName),
typeName,
[createResolver.Properties.FieldName]
)
subscriptionType = extensionWithFields(
subscriptionType,
[onCreateField]
)
}
if (updateResolver) {
const onUpdateField = makeSubscriptionField(
ModelResourceIDs.ModelOnUpdateSubscriptionName(typeName),
typeName,
[updateResolver.Properties.FieldName]
)
subscriptionType = extensionWithFields(
subscriptionType,
[onUpdateField]
)
}
if (deleteResolver) {
const onDeleteField = makeSubscriptionField(
ModelResourceIDs.ModelOnDeleteSubscriptionName(typeName),
typeName,
[deleteResolver.Properties.FieldName]
)
subscriptionType = extensionWithFields(
subscriptionType,
[onDeleteField]
)
}
}
ctx.addObjectExtension(subscriptionType)
}
private typeExist(type: string, ctx: TransformerContext): boolean {

@@ -288,0 +405,0 @@ return Boolean(type in ctx.nodeMap);

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