Using GraphQl and MongoDB schema as library in NRWL/NX Enviornment - nrwl

I am fairly new to the NRWL/NX world.
What I am trying to accomplish here is, to use the GraphQL (with the MongoDB) for the API.
In past, I've created the GraphQL project with MongoDB in a non-NRWL environment.
However since now we have multiple projects, we are moving to NX.
There are couple of MongoDB schema which are used across multiple projects, so I've decided to use them as a library. I generated a library and added following code
import { MongooseModule } from '#nestjs/mongoose';
import { ConfigService, ConfigModule } from '#another-lib/config-helper';
import { Module } from '#nestjs/common';
import { Location } from './model/location'; //This wouldn't be accessible from elsewhere
export const databaseProviders = [
MongooseModule.forRootAsync({
imports: [ ConfigModule ],
inject: [ ConfigService ],
useFactory: async (config: ConfigService) => ({
uri: config.get('MONGODB_URI'),
useNewUrlParser: true,
useFindAndModify: false,
}),
}),
];
#Module({
imports: [ ...databaseProviders, Location ],
exports: [ ...databaseProviders, Location ],
})
export class DatabaseModule {}
The MongoDB model is pretty standard.
import * as mongoose from 'mongoose';
const LocationSchema = new mongoose.Schema(
{
LocationName: {
type: String,
},
LocationCode: {
type: String,
},
isPickable: {
type: Boolean,
},
TemplateID: {
type: String,
},
},
{ collection: 'locations', timestamps: true },
);
export interface ILocation extends mongoose.Document {
_id: string;
LocationName: string;
LocationCode: string;
isPickable: boolean;
TemplateID: string;
}
//used for the server
export interface ILocationModel extends mongoose.Model<ILocation> {}
// export const LocationSchema = mongoose.model('location', _LocationSchema);
export const Location: ILocationModel = <ILocationModel>mongoose.model<ILocation>('Location', LocationSchema);
How can I access the mongodb model via DatabaseModule, Please suggest.
Thanks
-N Baua

Managed to solved the problem by setting up the correct directory structure and importing them in the datahelper.ts file.
We later exported the referenced interfaces from the datahelper.ts into the index.ts and we were done.
Thanks.

Related

GraphQL Shield with Yoga and Modules

I've been developing a site that uses Yoga Server, and Modules, and looking at using Shield for security.
However no matter what I seem to do, I can't get Shield to integrate with Yoga, and Modules.
Here is my code (note I have stripped parts out for ease of understanding):
index.ts
import { useGraphQLModules as GraphQLModules } from '#envelop/graphql-modules';
import { createYoga } from 'graphql-yoga';
import type { NextApiRequest, NextApiResponse } from 'next';
import application from './schema';
export default createYoga<{req: NextApiRequest; res: NextApiResponse;}>({
plugins: [GraphQLModules(application)],`
});
schema.ts
import { createApplication } from 'graphql-modules';
import accounting from './accounting';
import users from './users';
const application = createApplication({
modules: [
accounting,
users
],
});
export default application;
accounting.ts
import { createModule, gql } from 'graphql-modules';
export default createModule({
id: 'accounting',
dirname: __dirname,
typeDefs: [
gql`
type Query {
fees: [Fee]
}
type Fee {
id: UUID!
feeName: String
dueDate: Date
amount: Float
description: String
createdDateTime: DateTime
emailSentDateTime: DateTime
}
`,
],
resolvers: {
Query: { ... }
},
});
My code all works fine, but I can't for the life of me get Shield to work when I use Modules...

Can't query data from contentful to gatsby project

Don't get the query to contentful to work.
Receive error message:
TypeError: Cannot read property 'allContentfulMagArticle' of undefined
datais undefined inside the Posts component. Can't see what i'm doing wrong here.
import { graphql } from 'gatsby';
import Post from "./post.js";
import './posts.css';
export const query = graphql`
query {
allContentfulMagArticle{
edges{
node{
index
title
name
subHeading
extract {
raw
}
slug
}
}
}
}
`
const Posts = ({ data }) => {
return (
<section className="posts">
<ul className="post-list">
{data.allContentfulMagArticle.edges.map(({ node }) => (
<Post
key={node.index}
id={node.index}
node={node}
title={node.title}
name={node.name}
// image={node.frontmatter.featuredImage.childImageSharp.fluid}
subheading={node.subheading}
body={node.extract.raw}
/>
))}
</ul>
</section>
)
}
export default Posts
Here my gatsby-config.js:
require('dotenv').config({
path: `.env`,
})
module.exports = {
siteMetadata: {
title: `XX`,
description: `XX`,
author: `Lisa Lee`,
url: `https://www.tortmagazine.com`
},
plugins: [
`gatsby-plugin-react-helmet`,
'gatsby-plugin-fontawesome-css',
'gatsby-plugin-sharp',
`gatsby-transformer-sharp`,
`gatsby-transformer-remark`,
{
resolve: `gatsby-source-filesystem`,
options: {
path: `${__dirname}/src/`,
},
},
{
resolve: `gatsby-source-contentful`,
options: {
spaceId: process.env.GATSBY_CONTENTFUL_SPACE_ID,
accessToken: process.env.GATSBY_CONTENTFUL_ACCESS_TOKEN,
},
},
],
}
You used the word "component" to describe your Posts but the query you are using only works in a page, or in the context of createPage (so in a template file as well). If you are indeed in a component, that will be the issue. If not, then I'm not clear what is wrong, I use the same pattern (eg: data.edges.node.map()) and it works for me.
The only other difference I noticed is in gatsby-config, I define an environment key. I'm not sure what the behavior is if none is defined, probably defaults to master so you may also want to confirm you're on the right environment.

ApolloServer using mergeSchemas, Error: Apollo Server requires either an existing schema, modules or typeDefs

I think I am just using this module wrong and that is the reason I am getting an error. According to the documentation I can pass an array of resolvers and schemas to the mergeSchemas function from graphql-tools. But I am getting this error:
Error: Apollo Server requires either an existing schema, modules or typeDefs
Here is the code:
app.js
import { ApolloServer } from 'apollo-server'
import schema from './modules'
const server = new ApolloServer({
schema
})
server.listen().then(({ url }) => {
console.log(`🚀 Server ready at ${url}`)
})
Merging Schemas
import { mergeSchemas } from 'graphql-tools'
import bookSchema from './book/schema/book.gql'
import bookResolver from './book/resolvers/book'
export const schema = mergeSchemas({
schemas: [bookSchema],
resolvers: [bookResolver] // ==> Maybe I have to merge these before hand?
})
Schema
type Query {
book(id: String!): Book
bookList: [Book]
}
type Book {
id: String
name: String
genre: String
}
Resolver
export default {
Query: {
book: (parent, args, context, info) => {
console.log(parent, args, context, info)
return {
id: `1`,
name: `name`,
genre: `scary`
}
},
bookList: (parent, args, context, info) => {
console.log(parent, args, context, info)
return [
{ id: `1`, name: `name`, genre: `scary` },
{ id: `2`, name: `name`, genre: `scary` }
]
}
}
}
Silly mistake:
Needed to import schema object from de structuring it:
import { schema } from './modules'
For my scenario, I was getting the above error when I passed the argument like below.
const server = new ApolloServer(typeDefs, resolvers);
then it changed to
const server = new ApolloServer({typeDefs, resolvers});
the below error has gone up.
Error: Apollo Server requires either an existing schema, modules or typeDefs

Switching from graphql-js to native graphql schemas?

Currently trying to switch from graphql-js to literal GraphQL types/schemas, I'd like to know if anyone has had any experience with this.
Let's take this really simple one :
const Person = new GraphQLObjectType({
name: 'Person',
fields: () => ({
name: {
type: GraphQLString,
description: 'Person name',
},
}),
});
I'd like to switch to the native GraphQL schema syntax i.e
type Person {
# Person name
name: String
}
However this would have to be incremental, and given the use of graphql-js, the best solution for now would be to parse GraphQL template literals to GraphQLObjectType (or any other type for that matter). Does anyone have experience doing this, I cannot seem to find any library for it unfortunately.
import { printType } from 'graphql';
printType(Person)
output:
type Person {
"""Person name"""
name: String
}
Here is the demo:
import { expect } from 'chai';
import { printType, printSchema, buildSchema, GraphQLSchema } from 'graphql';
import { logger } from '../util';
import { Person } from './';
describe('test suites', () => {
it('convert constructor types to string types', () => {
const stringTypeDefs = printType(Person).replace(/\s/g, '');
logger.info(printType(Person));
const expectValue = `
type Person {
"""Person name"""
name: String
}
`.replace(/\s/g, '');
expect(stringTypeDefs).to.be.equal(expectValue);
});
it('buildSchema', () => {
const stringTypeDefs = printType(Person);
const schema = buildSchema(stringTypeDefs);
expect(schema).to.be.an.instanceof(GraphQLSchema);
});
it('printSchema', () => {
const stringTypeDefs = printType(Person);
const schema = printSchema(buildSchema(stringTypeDefs));
logger.info(schema);
const expectValue = `
type Person {
"""Person name"""
name: String
}
`.replace(/\s/g, '');
expect(schema.replace(/\s/g, '')).to.be.eql(expectValue);
});
});
source code:
https://github.com/mrdulin/nodejs-graphql/blob/master/src/convert-constructor-types-to-string-types/index.spec.ts
You can use graphql-cli to extract a native graphql schema from a graphql server. All you need to do is..
Download the tool | npm i -g graphql-cli
Run graphql init in the directory of your project to
create .graphqlconfig file
Start your graphql server
Run graphql get-schema and this will generate a your schema in native graphql
SAMPLE .graphqlconfig
{
"projects": {
"my_sample_project": {
"schemaPath": "schema.graphql",
"extensions": {
"endpoints": {
"local": "http://localhost:8080/graphql"
}
}
}
}
}
We leverage the auto-generation of graphql schema/queries/mutations for our CI workflows.

Autoform with Meteor React and Simple-Schema

Is there any possibility to make meteor-autoform work with meteor-collection2-core and react-meteor?
MWE
Preferably I would like to have something like this.
./imports/api/Books.js
import { Mongo } from 'meteor/mongo';
import SimpleSchema from 'simpl-schema';
const Books = new Mongo.Collection("books");
Books.attachSchema(new SimpleSchema({
title: {
type: String,
label: "Title",
max: 200
},
author: {
type: String,
label: "Author"
},
}));
if (Meteor.isServer) {
Meteor.publish('allBooks', function () {
return Books.find({}, );
});
};
export default Books;
./imports/client/NewBooks.js
import React, { Component, PropTypes } from 'react';
import { createContainer } from 'meteor/react-meteor-data';
import { quickForm } from 'meteor-autoform';
import Books from '../api/Books';
class NewBooks extends Component {
constructor(props) {
super(props)
this.state = {}
}
render() {
return (
<div className="container">
<quickForm
collection={Books}
id="insertBookForm"
type="insert">
</quickForm>
</div>
)
}
};
export default createContainer(() => {
Meteor.subscribe('allBooks');
return {
books: Books.find().fetch()
}
}, NewBooks);
The npm package Uniforms worked super easy with Bootstrap.
Addition to ./imports/client/NewBooks.js
import AutoForm from 'uniforms-unstyled/AutoForm';
...
<AutoForm
schema={Books._collection.simpleSchema()}
onSubmit={doc => console.log(doc)}
/>
To my knowledge, Autoform depends heavily on Blaze, so, you could either use blaze autoform components in react (see here), or you can use a different library for this. I used this in a recent project: github.com/nicolaslopezj/simple-react-form. It's powerful, but much more 'hands-on' than the magical Autoform (you have to write your own form and field components).

Resources