Schema mutation for deleteMany({}) - prisma

I have this simple resolver:
removeAllMovies: () => {
return prisma.movie.deleteMany({});
},
When I run my apollo client I get an error:
Mutation.removeAllMovies defined in resolvers, but not in schema
So I want to add the mutation to the schema but I can't find the correct syntax. I want to remove all the movies, not based on a id or a filter:
type Mutation {
removeAllMovies()
}
This shows an error while starting the Apollo server:
Syntax Error: Expected Name, found ")".
What's the correct schema syntax for a deleteMany({}) resolver?

This should do it:
type BatchPayload {
count: Int!
}
type Mutation {
removeAllMovies: BatchPayload
}
And the resolver is correct so no changes there.

Related

Prisma Typescript where clause inside include?

I am trying to query the database (Postgres) through Prisma. My query is
const products = await prisma.products.findMany({
where: { category: ProductsCategoryEnum[category] },
include: {
vehicles: {
include: {
manufacturers: { name: { in: { manufacturers.map(item => `"${item}"`) } } },
},
},
},
});
The error message is
Type '{ name: { in: { manufacturers: string; "": any; }; }; }' is not assignable to type 'boolean | manufacturersArgs'.
Object literal may only specify known properties, and 'name' does not exist in type 'manufacturersArgs'.ts(2322)
Manufacturers have the field name and it is unique; I am not sure why this is not working or how I can update this code to be able to query the database. It is like I should cast the values into Prisma arguments.
The TypeScript error is pretty self-explanatory: the name property does not exist in manufacturersArgs. The emitted Prisma Client does a great job of telling you what properties do and do not exist when filtering.
If you are trying to perform a nested filter, you need to use select instead of include.
Documentation: https://www.prisma.io/docs/concepts/components/prisma-client/relation-queries#filter-a-list-of-relations
Your query is going to look something like this:
const products = await prisma.products.findMany({
where: { category: ProductsCategoryEnum[category] },
select: {
// also need to select any other fields you need here
vehicles: {
// Updated this
select: { manufacturers: true },
// Updated this to add an explicit "where" clause
where: {
manufacturers: { name: { in: { manufacturers.map(item => `"${item}"`) } } },
},
},
},
});
The final code ultimately depends on your Prisma schema. If you are using an editor like VS Code, it should provide Intellisense into the Prisma Client's TypeScript definitions. You can use that to navigate the full Prisma Client and construct your query based on exactly what is and is not available. In VS Code, hold control [Windows] or command [macOS] and click on findMany in prisma.products.findMany. This lets you browse the full Prisma Client and construct your query!
The in keyword isn't working for me. I use hasSome to find items in an array. hasEvery is also available depending what the requirements are.
hasSome: manufacturers.map(item => `"${item}"`),
See https://www.prisma.io/docs/reference/api-reference/prisma-client-reference#scalar-list-filters

Meteor Mongo Collection is not using typescript interface

I want to describe Mongo.Collection schema via typescript interface to have a strict check for type on fetch, forEach, etc.
interface IChat {
_id: string;
name?: string
};
const Chats = new Mongo.Collection<IChat>('chat');
// (method) Mongo.Cursor<IChat>.forEach(callback: <T>(doc: T, index: number, cursor: Mongo.Cursor<T>) => void, thisArg?: any): void
Chats.find().forEach(c => {
console.log(c._id); // Property '_id' does not exist on type 'T'.
// Why "type T" if it should be the type IChat???
});
But facing next error: Property '_id' does not exist on type 'T'.
What I'm doing wrong?
Link to typescript playground
Error
Collection.find().forEach() definition
In this case you're missing the .fetch() call after .find().
It may be that mathamagically Meteor+Mongo can handle the syntax as you have it now but the easy way to make Typescript happy here is adjusting it to be the following:
interface IChat {
_id: string;
name?: string
};
const Chats = new Mongo.Collection<IChat>('chat');
Chats.find().fetch().forEach(c => {
console.log(c._id);
});
link to the solution in Typescript Playground

Typescript with MongoDB findOne method not working with generic

I am writing a class to clean up a lot of my existing database code. The first step for this was writing a class to manage Collections for me, which I attempted to do using a class with a generic.
interface MongodbItem {
_id?: ObjectID
}
class CollectionManager<DataType extends MongodbItem> {
database: Database;
collection: Collection<DataType>;
// ...
async get(id?: ObjectID) {
if (!id) return await this.collection.find({}).toArray();
return await this.collection.findOne({ _id: id });
}
}
However, despite defining the DataType generic as having that _id Typescript gives me the following error (On the line with the .findOne):
Argument of type '{ _id: ObjectID; }' is not assignable to parameter of type 'FilterQuery<DataType>'.
Type '{ _id: ObjectID; }' is not assignable to type '{ [P in keyof DataType]?: Condition<DataType[P]>; }'
reading through the handbook it looks like extending the generic in the way I am should enforce that it has an _id property, so I do not know why this error is still occuring.
Appears to be a but with Typescript itself:
https://github.com/DefinitelyTyped/DefinitelyTyped/issues/40584
https://github.com/DefinitelyTyped/DefinitelyTyped/issues/39358
Solved using workaround
return this.collection.findOne({ _id: id } as FilterQuery<DataType>);

must have a selection of subfields. Did you mean \"createEvent { ... }\"?", [graphql] [duplicate]

Hi I am trying to learn GraphQL language. I have below snippet of code.
// Welcome to Launchpad!
// Log in to edit and save pads, run queries in GraphiQL on the right.
// Click "Download" above to get a zip with a standalone Node.js server.
// See docs and examples at https://github.com/apollographql/awesome-launchpad
// graphql-tools combines a schema string with resolvers.
import { makeExecutableSchema } from 'graphql-tools';
// Construct a schema, using GraphQL schema language
const typeDefs = `
type User {
name: String!
age: Int!
}
type Query {
me: User
}
`;
const user = { name: 'Williams', age: 26};
// Provide resolver functions for your schema fields
const resolvers = {
Query: {
me: (root, args, context) => {
return user;
},
},
};
// Required: Export the GraphQL.js schema object as "schema"
export const schema = makeExecutableSchema({
typeDefs,
resolvers,
});
// Optional: Export a function to get context from the request. It accepts two
// parameters - headers (lowercased http headers) and secrets (secrets defined
// in secrets section). It must return an object (or a promise resolving to it).
export function context(headers, secrets) {
return {
headers,
secrets,
};
};
// Optional: Export a root value to be passed during execution
// export const rootValue = {};
// Optional: Export a root function, that returns root to be passed
// during execution, accepting headers and secrets. It can return a
// promise. rootFunction takes precedence over rootValue.
// export function rootFunction(headers, secrets) {
// return {
// headers,
// secrets,
// };
// };
Request:
{
me
}
Response:
{
"errors": [
{
"message": "Field \"me\" of type \"User\" must have a selection of subfields. Did you mean \"me { ... }\"?",
"locations": [
{
"line": 4,
"column": 3
}
]
}
]
}
Does anyone know what I am doing wrong ? How to fix it ?
From the docs:
A GraphQL object type has a name and fields, but at some point those
fields have to resolve to some concrete data. That's where the scalar
types come in: they represent the leaves of the query.
GraphQL requires that you construct your queries in a way that only returns concrete data. Each field has to ultimately resolve to one or more scalars (or enums). That means you cannot just request a field that resolves to a type without also indicating which fields of that type you want to get back.
That's what the error message you received is telling you -- you requested a User type, but you didn't tell GraphQL at least one field to get back from that type.
To fix it, just change your request to include name like this:
{
me {
name
}
}
... or age. Or both. You cannot, however, request a specific type and expect GraphQL to provide all the fields for it -- you will always have to provide a selection (one or more) of fields for that type.

Meteor-Mongo: Error handling for findone

I am trying to handle errors using findOne in meteor-mongo.
From this stackoverflow question, it appears that I should be able to handle errors by doing collection.findOne({query}, function(err, result){ <handleError> }, but doing so results in an errormessage:
"Match error: Failed Match.OneOf, Match.Maybe or Match.Optional validation"
The following code works:
export default createContainer((props) => {
let theID = props.params.theID;
Meteor.subscribe('thePubSub');
return {
x: theData.findOne({_id: theID}),
};
}, App);
The following code does not:
export default createContainer((props) => {
let theID = props.params.theID;
Meteor.subscribe('thePubSub');
return {
x: theData.findOne({_id: theID}, function(err,result){
if(!result){
return {}
};
}),
};
}, App);
What am I doing wrong and how should I be resolving this error? Is this a meteor specific error?
Any help is greatly appreciated!
What kind of error are you exactly trying to handle with your callback?
Meteor's findOne is different from node's mongodb driver's findOne that the post you link to uses.
The expected signature is:
collection.findOne([selector], [options])
There is no callback involved, since the method runs synchronously (but is reactive).
If you want to return a default value when the document is not found, you can simply use a JS logical OR:
// Provide an alternative value on the right that will be used
// if the left one is falsy.
theData.findOne({_id: theID}) || {};
A more rigorous approach would be to compare its type with
typeof queryResult === 'undefined'
Note that if theData collection is fed by the above subscription Meteor.subscribe('thePubSub'), I doubt Meteor will have time to populate the collection on the client by the time you query it…