在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
开源软件名称(OpenSource Name):arackaf/mongo-graphql-starter开源软件地址(OpenSource Url):https://github.com/arackaf/mongo-graphql-starter开源编程语言(OpenSource Language):JavaScript 99.9%开源软件介绍(OpenSource Introduction):mongo-graphql-starterThis utility will scaffold GraphQL schema and resolvers, with queries, filters and mutations working out of the box, based on metadata you enter about your Mongo db. The idea is to auto-generate the mundane, repetitive boilerplate needed for a graphQL endpoint, then get out of your way, leaving you to code anything else you need.
Prior artThis project is heavily inspired by Graph.Cool. It was an amazing graphQL-as-a-service that got me hooked on the idea of auto-generating a graphQL endpoint on your data store. The only thing I disliked about it was that you lost control of your data. You lacked the ability to connect directly to your database and index tune, bulk insert data, bulk update data, etc. This project aims to provide the best of both worlds: your graphQL endpoint is auto generated, but on top of the database you provide, and by extension retain control of. And integrating your own arbitrary content is directly supported. How do you use it?Let's work through a simple example. NOTE: All of the code below assumes you're using John Dalton's ESM loader. Do not try to run this code with Node's native ESM. First, create your db metadata like this. Each mongo collection you'd like added to your GraphQL endpoint needs to contain the table name, and all of the fields, keyed off of the data types provided. If you're creating a type which will only exist inside another type's Mongo fields, then you can omit the table property. For any type which is contained in a Mongo collection—ie has a projectSetupA.js import { dataTypes } from "mongo-graphql-starter";
const {
MongoIdType,
MongoIdArrayType,
StringType,
StringArrayType,
BoolType,
IntType,
IntArrayType,
FloatType,
FloatArrayType,
DateType,
arrayOf,
objectOf,
formattedDate,
JSONType,
typeLiteral
} = dataTypes;
export const Author = {
fields: {
name: StringType,
birthday: DateType
}
};
export const Book = {
table: "books",
fields: {
_id: MongoIdType,
title: StringType,
pages: IntType,
weight: FloatType,
keywords: StringArrayType,
editions: IntArrayType,
prices: FloatArrayType,
isRead: BoolType,
mongoIds: MongoIdArrayType,
authors: arrayOf(Author),
primaryAuthor: objectOf(Author),
strArrs: typeLiteral("[[String]]"),
createdOn: DateType,
createdOnYearOnly: formattedDate({ format: "%Y" }),
jsonContent: JSONType
}
};
export const Subject = {
table: "subjects",
fields: {
_id: MongoIdType,
name: StringType
}
}; Now create your schema and resolvers import { createGraphqlSchema } from "mongo-graphql-starter";
import * as projectSetup from "./projectSetupA";
import path from "path";
createGraphqlSchema(projectSetup, path.resolve("./test/testProject1")); There should now be a graphQL folder containing schema, resolver, and type metadata files for your types, as well as a master resolver and schema file, which are aggregates over all the types. Now tell Express about it—and don't forget to add a root object with a If needed, Here's what a minimal, complete example might look like. import { MongoClient } from "mongodb";
import { graphqlHTTP } from "express-graphql";
import resolvers from "./graphQL/resolver";
import schema from "./graphQL/schema";
import { makeExecutableSchema } from "@graphql-tools/schema";
import express from "express";
const app = express();
const mongoClientPromise = MongoClient.connect(connString, { useNewUrlParser: true });
const mongoDbPromise = mongoClientPromise.then(client => client.db(dbName));
const root = { client: mongoClientPromise, db: mongoDbPromise };
const executableSchema = makeExecutableSchema({ typeDefs: schema, resolvers });
app.use(
"/graphql",
graphqlHTTP({
schema: executableSchema,
graphiql: true,
rootValue: root
})
);
app.listen(3000); Now Valid types for your fieldsHere are the valid types you can import from import { dataTypes } from "mongo-graphql-starter";
const {
MongoIdType,
MongoIdArrayType,
StringType,
StringArrayType,
BoolType,
IntType,
IntArrayType,
FloatType,
FloatArrayType,
DateType,
arrayOf,
objectOf,
formattedDate,
JSONType,
typeLiteral
} = dataTypes;
Adding property traitsIf you'd like to modify the default behavior of a type's properties, you can use the For now, the only available trait is import { MongoIdType, StringType, fieldOf } from "../../src/dataTypes";
export const Book = {
table: "books",
fields: {
_id: fieldOf(MongoIdType).nonQueryable(),
title: fieldOf(StringType).nonQueryable(),
isRead: BoolType
}
}; Readonly typesAdd Circular dependencies are fineFeel free to have your types reference each other. Just use a getter to reference types created downstream. For example, the following will generate a valid schema. import { dataTypes } from "mongo-graphql-starter";
const { MongoIdType, StringType, arrayOf } = dataTypes;
export const Tag = {
table: "tags",
fields: {
_id: MongoIdType,
tagName: StringType,
get authors() {
return arrayOf(Author);
}
}
};
export const Author = {
table: "authors",
fields: {
name: StringType,
tags: arrayOf(Tag)
}
}; VS Code integrationAt the root of the GraphQL folder that's created with your endpoint code, there should be an TypeScript integrationIn order to generate TypeScript typings for the various types, query responses, etc. in your endpoint, just specify a createGraphqlSchema(projectSetupTS, path.resolve("./my/path"), { typings: path.resolve("./path/to/graphql-types.ts") }); That'll create The typings are created with GraphQL Code Generator. In addition the types in your endpoint, this library also inserts some helpers for typing queries and mutations. The let queryResults = useQuery<QueryOf<"allSubjects">>(packet); That will generate a type with an let queryResults = useQuery<QueryOf<"allSubjects" | "allBooks">>(packet); If you'd like some autocomplete for your query names, you can use the let queryResults = useQuery<QueryOf<Queries["allSubjects"] | Queries["allBooks"]>>(packet); The result is the same, but inside If you have aliased queries, specify them like this let queryResults = useQuery<QueryOf<{ bookQuery: "allBooks" }>>(packet); or of course you can still use the let queryResults = useQuery<QueryOf<{ bookQuery: Queries["allBooks"] }>>(packet); And if you have both, together, then just add a second generic type for each (order doesn't matter; either can be first). let queryResults = useQuery<QueryOf<{ bookQuery: Queries["allBooks"] }, Queries["allSubjects"] | Queries["allBooks"]>>(packet); For mutations, there are These types (and the rest from your endpoint) are generated from the typings file you specified above import { QueryOf, Queries, MutationOf, Mutations } from "./path/to/graphql-typings"; Queries createdFor each queryable type, there will be a For example {getBook(_id: "59e3dbdf94dc6983d41deece"){Book{createdOn}}} will retrieve that book, bringing back only the There will also be an For example {allBooks(SORT: {title: 1}, PAGE: 1, PAGE_SIZE: 5){Books{title}, Meta{count}}} will retrieve the first page of books' titles, as well as the Note, if you don't query The generated resolvers will analyze the AST and only query what you ask for. Projecting results from queriesUse standard GraphQL syntax to select only the fields you want from your query. The incoming ast will be parsed, and the generated query will only pull what was requested. This applies to nested fields as well. For example, given this GraphQL setup, this unit test, and the others in the suite demonstrate the degree to which you can select nested field values. Fragment supportAs of version 0.11.1, fragments are now supported fragment d1 on Book {
title
}
fragment d2 on Book {
...d1
pages
}
fragment d3 on Book {
...d2
isRead
}
query {
getBook(_id: "59e3dbdf94dc6983d41deece") {
Book {
...d3
weight
}
}
} Custom query argumentsIf you'd like to add custom arguments to these queries, you can do so like this export const Thing = {
table: "things",
fields: {
name: StringType,
strs: StringArrayType,
ints: IntArrayType,
floats: FloatArrayType
},
manualQueryArgs: [{ name: "ManualArg", type: "String" }]
}; Now Filters createdAll scalar fields, and scalar array fields ( Exact match
Not equal
For Date fields, the strings you send over will be converted to Date objects before being passed to Mongo. Similarly, for MongoIds, the Mongo
All array types, both of scalars, like Count
null valuesIf you pass If you pass String filtersIf your field is named
String array filtersIf your field is named
Int filtersIf your field is named
Int array filtersIf your field is named
全部评论
专题导读
热门推荐
热门话题
阅读排行榜
|
请发表评论