opencrud / opencrud Goto Github PK
View Code? Open in Web Editor NEWOpenCRUD is a GraphQL CRUD API specification for databases
Home Page: https://www.opencrud.org
License: MIT License
OpenCRUD is a GraphQL CRUD API specification for databases
Home Page: https://www.opencrud.org
License: MIT License
OpenCRUD currently uses the word "multi" to designate queries that return multiple documents (as opposed to "single"). Currently, in Vulcan we use the word "list". I think "multi" is better actually, but before I make the switch I was just wondering if other alternatives had been explored? What kind of nomenclature do other data layers (dbs, etc.) use?
Also, what about "Where"? Coming from a Mongo background the word "Selector" seems more natural since "where" isn't really a noun ("what is this mutation's where?" sounds weird).
Finally, the mutation argument is named data
. I wonder if that could be ambiguous in certain cases since that's also the name of Apollo Client's return value. What about document
instead?
Currently mutations look like:
updateUser(where: { id: "1" }, data: { name: "Karl" })
This goes against the guidelines outlined here:
Mutations should only ever have one input argument.
https://dev-blog.apollodata.com/designing-graphql-mutations-e09de826ed97
updatePost(input: { id: 4, newText: "..." })
Thoughts?
WIP
There is a broken link (the most interesting) in the index about CRUD mutations
I think we should cover how to specify that a field should be deleted. Personally I like the convention of setting the field to null
:
mutation {
updateUser(where: { id: "1" }, data: { name: "Karl", bio: null }) {
id
}
}
I'm gonna preface this by saying I don't have high hopes for it being implemented, since it'd be, among other things, a breaking change.
Let's say I have a query like this
query getBooks {
books {
author {
name
}
datePublished
genre {
name
}
title
}
}
Things get a bit more verbose when you want to let the user apply some filters
query getBooks(
$titleStartsWith: String
$genres: [String!]
$publishedAfter: DateTime
$publishedBefore: DateTime
) {
books(
where: {
title_starts_with: $titleStartsWith
genre_in: $genres
datePublished_gte: $publishedAfter
datePublished_lt: $publishedBefore
}
) {
author {
name
}
datePublished
genre {
name
}
title
}
}
but it's still manageable. The problem is when more filtering comes into play (user wants to filter by title/author name starting with/ending with/equals). Each variable is its own thing, and each one gets hooked to a specific part of the where input, so the queries for dynamic front-end's can get pretty big.
query getBooks(
$titleStartsWith: String
$titleEndsWith: String
$titleEquals: String
$authorNameStartsWith: String
) # And so on.
{
books(
where: {
title_starts_with: $titleStartsWith
title_ends_with: $titleEndsWith
title: $titleEquals
author: { name_starts_with: $authorNameStartsWith }
# And so forth.
}
) {
author {
name
}
datePublished
genre {
name
}
title
}
}
Things get worse when actually populating the variables. For example, if I had a filter option for each field
function getVariables(filters) {
return {
titleStartsWith: filters.title.startsWith,
titleEndsWith: filters.title.endsWith,
titleEquals: filters.title.equals,
authorNameStartsWith: filter.authorName.startsWith,
};
}
To make matters worse, this isn't reusable. It works for this table, but the same plumbing has to be redone if you want to apply this style to a table of magazine articles or blog posts. The interesting thing is that the part for filtering on the author can be made reusable, by passing an AuthorWhereInput as a variable
query getBooks($author) {
books(where: {author: $author}) {
name
}
}
query getArticles($author) {
articles(where: {author: $author}) {
name
}
}
So, for relational fields, filtering can be delegated from the query to the variables. The same query can be used (and persisted) to get information by any criteria of a relational field. So, I'm proposing something similar for the field itself.
query getBooks(
$title: StringWhereInput
$genre: GenreWhereInput
$author: AuthorWhereInput
) {
books(
where: {
title: $title
genre: $genre
author: $author
}
) {
author {
name
}
datePublished
genre {
name
}
title
}
}
Not sure if there's a link to this repo anywhere in the document?
One of our users (see strapi/strapi#1198) faced an issue due to some English words which have particular plural forms. For example:
How is the specification handling this case? Currently, I don't see anything which can manage it.
query {
news(where: { id: "1" }) {
name
}
news(where: { name_contains: "Karl" }) {
name
}
}
Should we put the prefix all
before the plural name of the query?
query {
news(where: { id: "1" }) {
name
}
allNews(where: { name_contains: "Karl" }) {
name
}
}
skip/after/before/first/last don't seem to be documented anywhere?
The document mentions an @relation
directive but then never uses or explains it?
Why are the return type of a "get many entity query" [T]!
and not [T!]!
?
Is it expected that it can return null items? i.e: [T, null, T]
And for to-many relationships where the relationship is defined [T!]!
why is the generated schema posts(...): [Post!]
and not posts(...): [Post!]!
? Is it here expected that it can return null instead of an empty array?
If it is not intentional it would be really helpful if the types could be changed. Its a bit frustrating that we have to check for null everywhere. If the return type was [T!]!
it would clean up our code a lot.
Example:
Datamodel
type User {
id: ID! @unique
name: String!
posts: [Post!]!
}
type Post {
id: ID! @unique
title: String!
}
Generated Schema
type User implements Node {
id: ID!
name: String!
posts(
where: PostWhereInput
orderBy: PostOrderByInput
skip: Int
after: String
before: String
first: Int
last: Int
): [Post!] # Why not [Post!]! here?
postsConnection(
where: PostWhereInput
orderBy: PostOrderByInput
skip: Int
after: String
before: String
first: Int
last: Int
): PostConnection!
}
type Post implements Node {
id: ID!
title: String!
}
type Query {
users(
where: UserWhereInput
orderBy: UserOrderByInput
skip: Int
after: String
before: String
first: Int
last: Int
): [User]! # Why not [User!]! here?
user(where: UserWhereUniqueInput!): User
}
As this git seems not active it is probably useless to leave an issue here. But, still, the openCRUD convention is supposed to be a working draft, so I am giving some work to think about.
Coming from strapi ( https://github.com/strapi/strapi/issues/8646 ), where similar issues have been pointed out. There is clearly a problem with the naming convention 2.4.1.6, especially for non-english languages.
English is a de facto standard in IT, ok, but why could we not name something in our databases using our own language? Let's say that non-developpers or non-english-speakers (they exist) would, for instance, use the strapi dashboard where everything is named according to the openCRUD convention and, thus, where everything is in english. It is a problem.
It'd be nice to show an example for the UserOrderByInput type.
How are JSONB types represented using OpenCRUD?
Article: https://hackernoon.com/how-to-query-jsonb-beginner-sheet-cheat-4da3aa5082a3
@hasura @shahidhk @praveenweb @arvi3411301 @rakeshkky @0x777 @dsandip Is there an intention to participate in the improvement of OpenCRUD API spec? Your experience and vision be helpful.
It would be useful to have a way to do full-text search without using external services such as Algolia. But we need a spec for that.
This project has potential. However it hasn't been updated for 2 years now and I wonder what's the next development plan.
Especially that now Prisma v2 is already in beta, is OpenCRUD still used by the new Prisma.
I'd love us to have something "like OData but for GraphQL". I do like the way OpenCRUD reuses Relay Connections for the resultset format.
Other existing GraphQL CRUD-like specs:
We should specify how directives are translated from the data model to the generated GraphQL API.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.