Node.js、Express、Angular、sequelizeを使ったWebシステムの開発に挑戦中です(MEANスタックに似てますが、データベースにPostgresを使っているので、PEANって事になるんでしょうね)
Angularから、Node.js+Expressにアクセスする方法を調べて見ると、RESTよりGraphqlの方が便利だという記事を読んだので、これを使ってみます。
全体的にTypeScriptで纏めたいので、type-graphqlを使う事にします。
graphsql関連のインストール
graphsql、@types/graphql、type-graphsqlをインストールします。
npm install graphql @types/graphql type-graphql --save
tsconfig.jsonの変更
compilerOptionsに以下の行を追加します。
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
compilerOptionsのtargetをes2016に変更します。
"target": "es2016"
libを以下のように変更します。
"lib": [
"es2016",
"esnext.asynciterable",
"dom"
]
モデルクラスにtype-graphqlの定義を追加
クラスに対して@ObjectType()を、フィールドに対して@Field()を追加します。
importするのは、reflect-metadataとtype-graphqlです。
以下のコードは、sequelize-typescriptも使っているので、その定義も含まれています。
import 'reflect-metadata';
import { ObjectType, Field, ID } from 'type-graphql';
import { Table, Column, Model, DataType, PrimaryKey, Unique, Default } from 'sequelize-typescript';
@ObjectType()
@Table
export class Account extends Model<Account> {
@Field(type => ID)
@PrimaryKey
@Unique
@Default(DataType.UUIDV4)
@Column(DataType.UUID)
id?: string;
@Field()
@Column(DataType.STRING)
name: string;
@Field()
@Column(DataType.STRING)
kana: string;
@Field()
@Column(DataType.STRING)
email: string;
@Field()
@Column(DataType.STRING)
postcode: string;
@Field()
@Column(DataType.STRING)
address: string;
@Field()
@Column(DataType.STRING)
phone: string;
@Field()
@Column(DataType.STRING)
password: string;
constructor(name: string, kana: string, email: string, postcode: string, address: string, phone: string, password: string) {
super();
this.name = name;
this.kana = kana;
this.email = email;
this.postcode = postcode;
this.address = address;
this.phone = phone;
this.password = password;
}
}
Resolverクラスを作成
graphqlのリゾルバクラスを作成します。
import 'reflect-metadata';
import { Resolver, Mutation, Arg, InputType, Field, Query } from 'type-graphql';
import { Account } from '../models/account';
@InputType()
export class AccountInput implements Partial<Account> {
@Field()
name: string;
@Field()
kana: string;
@Field()
email: string;
@Field()
postcode: string;
@Field()
address: string;
@Field()
phone: string;
@Field()
password: string;
constructor(name: string, kana: string, email: string, postcode: string, address: string, phone: string, password: string) {
this.name = name;
this.kana = kana;
this.email = email;
this.postcode = postcode;
this.address = address;
this.phone = phone;
this.password = password;
}
}
@Resolver(of => Account)
export class AccountResolver {
@Query(returns => Account)
async account() {
const acc: Account = new Account('name', 'kana', 'email', 'postcode', 'address', 'phone', 'password');
return Promise.resolve(acc);
}
@Mutation(returns => Account)
addAccount(
@Arg('account') accountInput: AccountInput
): Promise<Account> {
const acc: Account = new Account('name', 'kana', 'email', 'postcode', 'address', 'phone', 'password');
return Promise.resolve(acc);
}
}
expressにGraphqlを組み込む
expressのapp.tsに、Graphqlを組み込んで行きます。
import graphqlHTTP from 'express-graphql';
import { buildSchema } from 'type-graphql';
import { AccountResolver } from './resolvers/accountresolver';
// Graphqlを組み込む
async function bootstrap() {
const schema = await buildSchema({
resolvers: [ AccountResolver ]
});
app.use('/graphql', graphqlHTTP({
schema: schema,
graphiql: true
}));
}
bootstrap().catch(err => {
console.log(err);
});
ビルドしてGraphqlにアクセス
プロジェクトをビルド、実行し、http://localhost:3000/graphqlにアクセスすると、Graphqlのクエリエディタが表示されます(Graphiql)