この記事では、私の経験に基づいて、私が助けてくれた小さなnpmモジュールをどのように書いたのかを説明します。
すべては、次のテクノロジーを使用して、私のプロジェクトの1つに同形CMSを作成することに決めたという事実から始まりました。
- React -UIを構築するため
- Express-サーバーとして
- MongoDb + Mongoose -noSQLデータベース
- graphQL-データベースと対話するためのメインAPI
- Apollo-Client -graphQLを介した便利な呼び出しクエリと突然変異のためのコネクタ
- webpack-プロジェクトをビルドし、クライアントとサーバーのコードを分離するため
簡略化されたアーキテクチャは次のとおりです。
__root 1 |__client 2 |__public 3 |__middleware 4 |__server
- 反応コンポーネント
- クライアントコードバンドルおよびその他のパブリックファイル
- Mongoose:スキーマ、追加のメソッド、graphQL:タイプ、クエリを含むクラス、突然変異を含むクラス、スキーマ
- エクスプレスサーバーを含むサーバーコードバンドル
したがって、データベース内のエンティティごとに、データを操作できるようにMongooseスキームを作成する必要があります。 次のようになります。
let couponSchema = mongoose.Schema({ couponCode: Array, description: String, discountAmount: String, minimumAmount: String, singleUseOnly: Boolean, createdAt: mongoose.Schema.Types.Date, updatedAt: mongoose.Schema.Types.Date, expirationDate: mongoose.Schema.Types.Date });
ここで、graphQLを使用する場合、データベース内の各エンティティに対してタイプを作成する必要があり、各プロパティのタイプはMongooseスキームと同じでなければなりません。 graphQLタイプがなければ、単純にgraphQLスキーマを生成できません。 タイプは次のとおりです。
let couponType = new GraphQLObjectType({ name: 'couponType', description: 'single use coupon', fields: { _id: {type: GraphQLString}, couponCode: {type: new GraphQLList(GraphQLString)}, description: {type: GraphQLString}, discountAmount: {type: GraphQLString}, minimumAmount: {type: GraphQLString}, singleUseOnly: {type: GraphQLBoolean}, createdAt: {type: GraphQLString}, updatedAt: {type: GraphQLString}, expirationDate: {type: GraphQLString} } });
類似性は明らかだと思いますか? ここで、数十個のエンティティがあり、それぞれについて同じロジックを実際に複製する必要があると想像してください。 ただし、型には、他の型の配列や他の多くのネストされた要素を含めることができます。
実際、この問題を解決するために、論理的に同一のコードの重複を回避し、コードをほぼ半分にする小さなモジュール(3kbのみ)を作成しました。私の場合、コードを2000行以上削減しました。
最初に、モジュールをインストールします。
npm i mongoose-schema-to-graphql
このモジュールには、1つの関数「MTGQL」が含まれています。この関数は、引数として構成を持つ1つのオブジェクトを取ります。 オブジェクトの構造は次のとおりです。
let configs = { name: 'couponType',
以下のモジュールの使用例:
dbSchema.js import mongoose from 'mongoose'; let selectObj = { value: String, label: String }; let answerSchema = mongoose.Schema({ createdAt: mongoose.Schema.Types.Date, updatedAt: mongoose.Schema.Types.Date, title: String, answersImage: String, recommended: [selectObj], isPublished: Boolean }); export let questionSchema = mongoose.Schema({ question: String, defRecommended: [selectObj], createdAt: mongoose.Schema.Types.Date, updatedAt: mongoose.Schema.Types.Date, isPublished: Boolean, multipleChoice: Boolean, answers: [answerSchema] });
graphQLタイプのファイル内:
type.js import MTGQL from 'mongoose-schema-to-graphql'; import {questionSchema} from './dbSchemas'; let config = { name: 'questionType', description: 'Question collection\'s type', class: 'GraphQLObjectType', schema: questionSchema, exclude: ['_id'] }; export let questionType = MTGQL(config);
実際には、次のコードに相当するコードは10行のみです。
import { GraphQLObjectType, GraphQLString, GraphQLBoolean, GraphQLList, GraphQLInt } from 'graphql'; let selectType = new GraphQLObjectType({ name: 'selectType', fields: { value: {type: GraphQLString}, label: {type: GraphQLString} } }); let answerType = new GraphQLObjectType({ name: 'answerType', description: 'answer type for question', fields: { title: {type: GraphQLString}, answersImage: {type: GraphQLString}, recommended: {type: new GraphQLList(selectType)}, createdAt: {type: GraphQLString}, updatedAt: {type: GraphQLString}, isPublished: {type: GraphQLBoolean} } }); export let questionType = new GraphQLObjectType({ name: 'questionType', description: 'Question collection\'s type', fields: { question: {type: GraphQLString}, defRecommended: {type: new GraphQLList(selectType)}, createdAt: {type: GraphQLString}, updatedAt: {type: GraphQLString}, isPublished: {type: GraphQLBoolean}, multipleChoice: {type: GraphQLBoolean}, answers: {type: new GraphQLList(answerType)} } });
その違いは明らかだと思います。 このモジュールは、「GraphQLFloat」を直接サポートしていません。これは、Mongooseスキーマでは、タイプを整数に等しい「Number」にしか設定できないためです。 しかし、この問題は、目的のプロパティを構成オブジェクトに渡すことで簡単に解決できます。
モジュールの動作の詳細については、
GitHubをご覧ください。
この記事がお役に立てば幸いです。改善のための提案があれば、書いてください。間違いなく検討します。 ご清聴ありがとうございました。
元の記事は
medium.comにあります。