I am using graphql-tools for mocking the response from Appsync and it is failing for schema which has AWSDateTime as datatype of some fields. Following is the error I am getting:
Uncaught Error: Unknown type "AWSDateTime".
Unknown type "AWSDateTime".
Unknown type "AWSDateTime".
And this is code for which it is failing:
import { SchemaLink } from "apollo-link-schema";
import { makeExecutableSchema, addMockFunctionsToSchema } from "graphql-tools";
const typeDefs = `
type Dates {
createdAt: AWSDateTime
updatedAt: AWSDateTime
}
type Query {
getDates(id: ID!): Dates
}`;
const schema = makeExecutableSchema({ typeDefs });
Any idea how can I fix this issue? I know AWSDateTime is scalar type defined specially for appsync, so it may not work. But is there any workaround. With ApolloLink client, it works just fine.
Every scalar you use, with the exception of the 5 built-in scalars, has to be explicitly defined inside your schema. This is a two-step process:
First, add the type definition:
scalar AWSDateTime
Second, provide a GraphQLScalarType object, which encapsulates the parsing and serialization logic of the scalar. With makeExecutableSchema, this is provided through the resolver map.
const resolvers = {
...
AWSDateTime: new GraphQLScalarType({ ... }),
}
See the docs for additional details. If the serialization and parsing logic doesn't really matter because this is just for mocking anyway, then you could use the methods of an existing scalar, like String.
const resolvers = {
...
AWSDateTime: new GraphQLScalarType({
name: 'AWSDateTime',
parseValue: GraphQLString.parseValue,
parseLiteral: GraphQLString.parseLiteral,
serialize: GraphQLString.serialize,
}),
}
Related
I'm fairly new to Amplify. I ran the amplify commands to create the src/models/index.d.ts and the generated API file, src/app/API.ts files. Each of these have the same types generated except that embedded collections generated via #belogsTo and #hasMany is not on the type in API.ts but IS on index.d.ts. When I try running the code I have a JSON object that I've cast to the model in src/app/API.ts. Like I say, there is an embedded collection that does NOT show up on the API file. Here is what I have for the schema file schema.graphql.
EDIT: It appears there are multiple ways to do the same thing, such as getting, updating, and deleting data. I think that using API.ts is the latests way to do it? I'm just totally confused by all of this.
type Blog #model {
id: ID! #primaryKey
name: String!
posts: [Post] #hasMany
}
type Post #model {
id: ID! #primaryKey
title: String!
blog: Blog #belongsTo
comments: [Comment] #hasMany
}
type Comment #model {
id: ID! #primaryKey
post: Post #belongsTo
content: String!
}
The API model that was generated does not have comments on type Post. Here is the generated code in the API file:
export type CreatePostInput = {
id?: string | null;
title: string;
blogPostsId?: string | null;
};
That is the type that is passed into CreatePostInput. When I try to specify the json:
const json = {
blogPostsId: 'Some Random UUID String',
title: 'MyPost',
} as Post;
I cannot add a comments array to this json because CreatePostInput and Post models does not contain comments that I specified on the schema.graphql.
My question is, first, what definition of Blog should I be using, the one in the index.t.ds file or the definition in the API file? If the answer is the one in index.d.ts, how to do go about creating one because the CreateBlogInput is the type that CreatePost in API.ts file.
I've tried different things that I've found on the interwebs from AWS blogs to Medium posts.
I don't want to create a property for loading relation into it (as shown in all the examples). The only thing I need is to have an explicit foreign key property so that the migration will be able to create appropriate constraints for it in the database. The closest decorator to the one I need is #RelationId but it still requires the presence of a property of the relational class.
For clarity let's take the example from the documentation:
#Entity()
export class Post {
#ManyToOne(type => Category)
category: Category;
#RelationId((post: Post) => post.category) // it still requires the presence of the `category` proeprty
categoryId: number;
}
I don't need the category property here. I want to have the categoryId property and mark it as foreign key to Category.Id. It should look like this:
#Entity()
export class Post {
#ForeignKey((category: Category) => category.Id) // it's a foreign key to Category.Id
categoryId: number;
}
Is it possible?
"I need is to have an explicit foreign key property"...
No, you could not. TypeOrm will automatically create foreign key property when you use #ManyToOne decorator. Just combine #ManyToOne and #JoinColumn decorators together like this:
#ManyToOne(type => Category)
#JoinColumn({ name: 'custom_field_name_if_you_want' })
category: Category;
Maybe you can create and write your own migration and use it like this :
const queryRunner = connection.createQueryRunner();
await queryRunner.createTable(new Table({
name: "question",
columns: [
{
name: "id",
type: "int",
isPrimary: true
},
{
name: "name",
type: "varchar",
}
]
}), true);
await queryRunner.createTable(new Table({
name: "answer",
columns: [
{
name: "id",
type: "int",
isPrimary: true
},
{
name: "name",
type: "varchar",
},
{
name: "questionId",
isUnique: connection.driver instanceof CockroachDriver, // CockroachDB requires UNIQUE constraints on referenced columns
type: "int",
}
]
}), true);
// clear sqls in memory to avoid removing tables when down queries executed.
queryRunner.clearSqlMemory();
const foreignKey = new TableForeignKey({
columnNames: ["questionId"],
referencedColumnNames: ["id"],
referencedTableName: "question",
onDelete: "CASCADE"
});
await queryRunner.createForeignKey("answer", foreignKey);
This code snippet is extracted from the functional test of type orm and you can use it to create your own constraint on the database I think.
It's actually possible to do so:
#Entity()
export class Post {
// this will add categoryId
#ManyToOne(type => Category)
category: Category;
// and you can use this for accessing post.categoryId
// only column you mark with #Column decorator will be mapped to a database column
// Ref: https://typeorm.io/#/entities
categoryId: number;
}
The added categoryId won't be mapped to column and will then be use for setting explicitly the id or for accessing its value as in:
post.categoryId = 1;
// or
const id = post.categoryId
Check with these two places Auth module(JwtModule.register()) and JWT strategy(super({...})). Make sure you have secret /secretOrKey is set to the same key. In my case "secret: process.env.JWT_SECRET_KEY" & "secretOrKey: process.env.JWT_SECRET_KEY"
I have encountered the same problem recently.
I still use the Entity but only with the primary key value of the referenced entity.
i.e. I do not query the database for the referenced entity.
Suppose your category entity looks like this:
#Entity()
export class Category{
#PrimaryGeneratedColumn()
id: number;
// ... other stuff
}
Now using your codes as example.
Dircely assigning relation using a foreign key value would be like.
// You wish to assign category #12 to a certain post
post.category = { id: 12 } as Category
The question is about the interaction of a mutation, optimistic response, and a watchQuery.
I have a mutation "myMutation" which has an "optimisticResponse" and an implemented "update" function.
Every time I do a mutation query the "update" function is called twice, the first time with optimistic response data and the second one with real data. All is Ok and all as described in the documentation.
Into my "update" function I modify "myQuery" cache data through using readQuery/writeQuery methods.
Every time I modify "myQuery" cache data a watchQuery (based on "myQuery") subscription is called. All is Ok and all as described in the documentation.
But the problem is that I cannot distinguish into my watchQuery whether I receive optimistic response data or real response data. It is crucial for me because the reaction must be different since valuable part of data can be provided by a server only.
I should show a GUI element with a special style when I receive an optimistic response and I should prohibit any interactions with it until I receive a real response.
Unfortunately, I can't solve this matter. At a glance, there is no difference between optimistic and real responses. I've googled a lot and haven't found a solution. The only idea I have is adding a special field to my GraphQL data which will show whether a response is received from a server or not. But it looks ugly and smells bad. I am sure, there must be a simple correct way to overcome the problem.
Maybe there is an easier way or there will be one in the future but here is what I know.
The data in optimisticResponse is only provided during the first call to update. That is where you can flag to your update function that it is dealing with optimistic data. You can put any data you want there. I put isOptimistic: true,.
To deal with the watchQuery issue, I recommend you make use of apollo-link-state to add a client-only field or fields to the areas of your data model where optimistic upserts should be known to the display. Don't include isOptimistic in your mutation query so you know it's from the server and not the optimistic response and force it to false if it's not true. See this example:
const SUBMIT_COMMENT_MUTATION = gql`
mutation submitComment($repoFullName: String!, $commentContent: String!) {
submitComment(repoFullName: $repoFullName, commentContent: $commentContent) {
postedBy {
login
html_url
}
createdAt
content
}
}
`;
const CommentsPageWithMutations = ({ currentUser }) => (
<Mutation mutation={SUBMIT_COMMENT_MUTATION}>
{(mutate) => (
<CommentsPage
submit={(repoFullName, commentContent) =>
mutate({
variables: { repoFullName, commentContent },
optimisticResponse: {
__typename: 'Mutation',
submitComment: {
__typename: 'Comment',
postedBy: currentUser,
createdAt: new Date(),
content: commentContent,
isOptimistic: true, // Only provided to update on the optimistic call
},
},
update: (proxy, { data: { submitComment } }) => {
// Make sure CommentAppQuery includes isOptimistic for each comment added by apollo-link-state
// submitComment.isOptimistic will be undefined here if it's from the server
const newComment = {
...submitComment,
isOptimistic: submitCommit.isOptimistic ? true : false,
};
// Read the data from our cache for this query.
const data = proxy.readQuery({ query: CommentAppQuery });
// Add our comment from the mutation to the end.
data.comments.push(newComment);
// Write our data back to the cache.
proxy.writeQuery({ query: CommentAppQuery, data });
},
})
}
/>
)}
</Mutation>
);
See https://www.apollographql.com/docs/link/links/state.html.
I couldn't get this to work on Apollo 3.X by only adding a property on the optimistic response, the property was getting stripped away. To get it to work I had to add a local variable to the query.
fragment object on Object {
id
isOptimistic #client
...
Once that is done, I was able to add the local-only flag to my optimistic response.
const optimisticResponse = {
object: {
id: "temp-id",
isOptimistic: true,
...
}
}
Long story short, I'm trying to retrieve a single record in ember (more specifically a user object that contains vital information following a login).
However, when I try to use #store.find "user", query, I receive Error: Assertion Failed: The response from a findQuery must be an Array, not undefined
Any thoughts?
Assuming you are querying for user type and query from above is a POJO your code may look like so:
var usersPromise = store.find('user', {foo:'bar', bla: 'baz'});
The response from your server would look something like this (note: users is plural), this is why you're receiving the error (ember.js Error: Assertion Failed: The response from a findAll must be an Array, not undefined).
{
users: [
{
id: 1,
name: 'Santa Clause'
}
]
}
Since you are querying by POJO Ember assumes there are 0+ results. After the promise has resolved you can return the first object from that, since the collection will only have one.
usersPromise.then(function(users){
return users.get('firstObject');
});
so in your case you would probably do something like this
this.store.find('user', {foo:'bar', bla: 'baz'}).then(function(users){
return users.get('firstObject');
});
Is it possible to find an individual record based on its property in the views in Ember 1.0.0-rc.5? I've been searching around for days, but I still can't find anything that works.
For example, I would like to be able to do this:
App.Tag.find({name: 'some tag'}) which is supposed to return one record, but instead returns an array.
The name field is unique for all tags, so it should return only one object.
How can this be done?
Thanks
Problem solved! For people who might encounter the same problem, I will answer my question here. I ended up using the filter method to select one object. Details here http://emberjs.com/api/classes/Ember.Enumerable.html#method_filter
Code:
...
tagList = App.Tag.find().filter (item, index, enumerable) ->
return item.get('slug') is "slug title"
tag = tagList.get('firstObject')
...
When passing a query to a model's find method, you're invoking the findQuery method, which is designed to populate an array.
This is findQuery's definition:
findQuery: function(store, type, query, recordArray) {
var root = this.rootForType(type),
adapter = this;
return this.ajax(this.buildURL(root), "GET", {
data: query
}).then(function(json){
adapter.didFindQuery(store, type, json, recordArray);
}).then(null, rejectionHandler);
},
Which then calls didFindQuery upon success, to populate the array which is returned:
didFindQuery: function(store, type, payload, recordArray) {
var loader = DS.loaderFor(store);
loader.populateArray = function(data) {
recordArray.load(data);
};
get(this, 'serializer').extractMany(loader, payload, type);
},
So, assuming my understanding is correct, given that each 'name' in your case is unique, just get the first key of your array:
var tags = App.Tag.find({name: 'some tag'});
var tag = tags[0];