рдХреБрдЫ рд╕рдордп рдкрд╣рд▓реЗ рдореИрдВ рдПрдХ рдореЛрдмрд╛рдЗрд▓ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдкрд░ рдХрд╛рдо рдХрд░ рд░рд╣рд╛ рдерд╛, рдЬрд┐рд╕рдХреА рдХрд╛рд░реНрдпрдХреНрд╖рдорддрд╛ рдореЗрдВ рдПрдХ рд╕реБрд╡рд┐рдзрд╛рдЬрдирдХ рдСрдирд▓рд╛рдЗрди рдЪреИрдЯ рд╢рд╛рдорд┐рд▓ рдерд╛ред рдФрд░ рдЕрдм рдореИрдВрдиреЗ рдмреИрдХреЗрдВрдб рдкрд░ рдЕрдкреЛрд▓реЛ рд╕рд░реНрд╡рд░ рдФрд░ рдиреЛрдб.рдЬреЗрдПрд╕ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдЪреИрдЯ рдмрдирд╛рдиреЗ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рд╕рдВрдХреНрд╖рд┐рдкреНрдд рдирд┐рд░реНрджреЗрд╢реЛрдВ рдХреЗ рд╕рд╛рде рдПрдХ рд▓реЗрдЦ рд▓рд┐рдЦрдиреЗ рдХрд╛ рдлреИрд╕рд▓рд╛ рдХрд┐рдпрд╛, рд╕рд╛рде рд╣реА рд╕рд╛рде рдХреНрд▓рд╛рдЗрдВрдЯ рдХреА рдУрд░ рд╕реЗ рджреЗрд╢реА рдФрд░ рдЕрдкреЛрд▓реЛ рдХреНрд▓рд╛рдЗрдВрдЯ рдкрд░ рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рджреАред
рдЖрд╕рд╛рди рдкрдврд╝рдиреЗ рдХреЗ рд▓рд┐рдП рд▓реЗрдЦ рдХреЛ рджреЛ рднрд╛рдЧреЛрдВ рдореЗрдВ рд╡рд┐рднрд╛рдЬрд┐рдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИред рдкрд╣рд▓реЗ рднрд╛рдЧ рдореЗрдВ рдПрдХ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдмреИрдХрдПрдВрдб рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдЧрд╛рдЗрдб рд╣реЛрддрд╛ рд╣реИ, рдФрд░ рджреВрд╕рд░реЗ рднрд╛рдЧ рдореЗрдВ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдлреНрд░рдВрдЯрдПрдВрдб рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдЧрд╛рдЗрдб рд╣реЛрддрд╛ рд╣реИред
рдпрджрд┐ рдЖрдк рдкрдврд╝рдиреЗ рдореЗрдВ рдмрд╣реБрдд рдЖрд▓рд╕реА рд╣реИрдВ, рддреЛ рдЖрдк рддреБрд░рдВрдд
рдпрд╣рд╛рдБ рдФрд░
рдпрд╣рд╛рдБ Github'e рдореЗрдВ рдХреЛрдб рджреЗрдЦ рд╕рдХрддреЗ
рд╣реИрдВ ред
рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХреЗ рд▓рд┐рдП рдореБрдЦреНрдп рддрдХрдиреАрдХреЛрдВ рдХреЗ рд░реВрдк рдореЗрдВ, рдореИрдВрдиреЗ рдиреЛрдб.рдЬреЗрдПрд╕ рдлреНрд░реЗрдорд╡рд░реНрдХ
рдХреЛрдЖ ,
рдкреЛрд╕реНрдЯрдЧреНрд░реИрд╕реНрдХрд▓ рдбреЗрдЯрд╛рдмреЗрд╕, рд╕рд╛рде рд╣реА рдЧреНрд░рд╛рдлрдХреЙрд▓ рд╕рд░реНрд╡рд░ -
рдЕрдкреЛрд▓реЛ-рд╕рд░реНрд╡рд░-рдХреЛрдЖ рдХреЛ рдЪреБрдирд╛ ред
рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ, рдПрдХ рдЦрд╛рд▓реА koa2 рдкрд░рд┐рдпреЛрдЬрдирд╛ рдЙрддреНрдкрдиреНрди рд╣реБрдИ рдереА, рдЗрд╕рдХреЗ рд▓рд┐рдП рдореИрдВрдиреЗ рдЯрд░реНрдорд┐рдирд▓ рдореЗрдВ рдХрдорд╛рдВрдб рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд░рдХреЗ рдПрдХ рд╕рд╛рдзрд╛рд░рдг
рдХреЛрдЖ-рдЬрдирд░реЗрдЯрд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛:
$ koa <project name>
рдлрд┐рд░ рдЖрд╡рд╢реНрдпрдХ рдирд┐рд░реНрднрд░рддрд╛рдПрдВ рд╕реНрдерд╛рдкрд┐рдд рдХреА рдЧрдИрдВ, рдореИрдВ рдЗрд╕реЗ рдпрд╛рд░реНрди рдХреЗ рд╕рд╛рде рдХрд░рддрд╛ рд╣реВрдВ, рд▓реЗрдХрд┐рди рдЖрдк рдПрдирдкреАрдПрдо рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред
$ yarn add apollo-server-koa knex objection pg
рд╕рднреА рдЖрд╡рд╢реНрдпрдХ рд▓рд╛рдЗрдмреНрд░реЗрд░реА рд╕реНрдерд╛рдкрд┐рдд рд╣реИрдВ, рдЕрдм рдЖрдк рдХреЛрдб рд▓рд┐рдЦ рд╕рдХрддреЗ рд╣реИрдВ
рдбреЗрдЯрд╛рдмреЗрд╕ рд╕реЗ рдХрдиреЗрдХреНрдЯ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдЖрдкрдХреЛ рджреЛ рдлрд╝рд╛рдЗрд▓реЛрдВ рдХрд╛ рд╡рд░реНрдгрди рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ, рдкрд╣рд▓реЗ рдПрдХ db.js рд╣реИ, рдЬреЛ knex рдХреНрд▓рд╛рдЗрдВрдЯ рдЙрджрд╛рд╣рд░рдг рдирд┐рд░реНрдпрд╛рдд рдХрд░реЗрдЧрд╛ рдФрд░ рд╣рдорд╛рд░реЗ рдореЙрдбрд▓ рдХреЛ рдбреЗрдЯрд╛рдмреЗрд╕ рд╕реЗ рдбреЗрдЯрд╛ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрдЧрд╛, рджреВрд╕рд░рд╛ рд╣реИ knexfile.js, рдЬрд┐рд╕рдореЗрдВ рдбреЗрдЯрд╛рдмреЗрд╕ рдХрдиреЗрдХреНрд╢рди рд╕реЗрдЯрд┐рдВрдЧреНрд╕ рдмрдирд╛рдиреЗ рдФрд░ рд░реЛрд▓рд┐рдВрдЧ рдкрд▓рд╛рдпрдиред
Db.js рдХреЛрдб рдиреАрдЪреЗ рд╡рд░реНрдгрд┐рдд рд╣реИ, рдзреНрдпрд╛рди рджреЗрдВ рдХрд┐ рд╕рднреА рд╕реЗрдЯрд┐рдВрдЧреНрд╕ рдкрд░реНрдпрд╛рд╡рд░рдг рдЪрд░ рд╕реЗ рд▓реА рдЧрдИ рд╣реИрдВ: const db = require('knex')({ client: 'pg', connection: { host : process.env.POSTGRES_HOST, port: process.env.POSTGRES_PORT, user : process.env.POSTGRES_USER, password : process.env.POSTGRES_PASSWORD, database : process.env.POSTGRES_DATABASE } }); module.exports = db;
рдХреЛрдб knexfile.js
рдпрд╣рд╛рдВ рдЙрдкрд▓рдмреНрдз
рд╣реИ ред
рдЕрдм рдЖрдк рдЙрди рджреЛ рддрд╛рд▓рд┐рдХрд╛рдУрдВ рдХреЛ рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдкрд▓рд╛рдпрди рдХрд╛ рд╡рд░реНрдгрди рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдЬрд┐рдирдХреА рд╣рдореЗрдВ рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред
рддрд╛рд▓рд┐рдХрд╛рдПрдБ рд╕реНрд╡рдпрдВ рдпрдерд╛рд╕рдВрднрд╡ рд╕рд░рд▓ рд╣реЛрдВрдЧреА рдФрд░ рдЗрдирдореЗрдВ рдХреЗрд╡рд▓ рдиреНрдпреВрдирддрдо рдЖрд╡рд╢реНрдпрдХ рдХреНрд╖реЗрддреНрд░ рдирд┐рд░реНрдзрд╛рд░рд┐рдд рд╣реЛрдВрдЧреЗред рдЙрдиреНрд╣реЗрдВ рдмрдирд╛рдиреЗ рдХрд╛ рдЖрджреЗрд╢ рдиреАрдЪреЗ рд╣реИ:
$ knex migrate:make migration_name
рдЖрдк рдорд╛рдЗрдЧреНрд░реЗрд╢рди рдлрд╝рд╛рдЗрд▓реЛрдВ рдХреЛ
рдпрд╣рд╛рдБ рджреЗрдЦ рд╕рдХрддреЗ
рд╣реИрдВ ред
рдЕрдм рдЗрдХрд╛рдИ рдореЙрдбрд▓ рд╕рдВрджреЗрд╢ рдФрд░ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдмрдирд╛рдПрдБ
class Message extends Model { static get tableName() { return 'messages'; } $beforeInsert() { this.created_at = new Date().toISOString(); } static get relationMappings() { return { user: { relation: Model.BelongsToOneRelation, modelClass: User, join: { from: 'messages.user_id', to: 'users.id' } } }; } }
рд╕рдмрд╕реЗ рджрд┐рд▓рдЪрд╕реНрдк рдмрд╛рдд рдмрдиреА рд░рд╣реА - рдЕрдкреЛрд▓реЛ-рд╕рд░реНрд╡рд░-рдХреЛрдЖ рдХреЛ рдЬреЛрдбрд╝рдирд╛ рдФрд░ рдХреЙрдиреНрдлрд╝рд┐рдЧрд░ рдХрд░рдирд╛, рдЧреНрд░реЗрдлрд╝рд▓ рдпреЛрдЬрдирд╛рдУрдВ рдФрд░ рд░рд┐рдЬрд╝реЙрд▓реНрд╡рд░ рдХрд╛ рд╡рд░реНрдгрдиред
рдЕрдкреЛрд▓реЛ-рд╕рд░реНрд╡рд░-рдХреЛрдЖ рдХреЛ рдЬреЛрдбрд╝рдиреЗ рдХреЗ рд▓рд┐рдП, рдмрд╕ рдХреЛрдб рдХреА рдирд┐рдореНрди рдкрдВрдХреНрддрд┐рдпреЛрдВ рдХреЛ рдЬреЛрдбрд╝реЗрдВ
app.js: const { ApolloServer } = require('apollo-server-koa'); const graphqlSchema = require('./graphqlSchema'); тАж const apolloServer = new ApolloServer(graphqlSchema); apolloServer.applyMiddleware({ app });
www: var { app, apolloServer } = require('../app'); ... apolloServer.installSubscriptionHandlers(server);
рдЕрдкреЛрд▓реЛ-рд╕рд░реНрд╡рд░-рдХреЛрдЖ рдХреЛ рдЬреЛрдбрд╝рдиреЗ рдХреЗ рдЕрд▓рд╛рд╡рд╛, рд╣рдордиреЗ рдЧреНрд░рд╛рд╣рдХреЛрдВ рдХреЛ рд╕реВрдЪрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╕рджрд╕реНрдпрддрд╛ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рдиреЗ рдХреА рдХреНрд╖рдорддрд╛ рдХреЛ рд╢рд╛рдорд┐рд▓ рдХрд┐рдпрд╛ рд╣реИ рдХрд┐ рдЪреИрдЯ рдореЗрдВ рдПрдХ рдирдпрд╛ рд╕рдВрджреЗрд╢ рдЖрдпрд╛ рд╣реИред
рдЕрдкреЛрд▓реЛ-рд╕рд░реНрд╡рд░-рдХреЛрдЖ рдЬреБрдбрд╝рд╛ рд╣реБрдЖ рд╣реИ, рдЕрдЧрд▓рд╛ рдЪрд░рдг рдЪреИрдЯ рдХреЗ рд▓рд┐рдП рдЖрд╡рд╢реНрдпрдХ рдкреНрд░рдХрд╛рд░реЛрдВ рдХреЗ рд╕рд╛рде рдЧреНрд░рд╛рдлрд┐рдХрд▓ рдЖрд░реЗрдЦ рдХрд╛ рд╡рд░реНрдгрди рд╣реИ
input UserInput { username: String! } input MessageInput { text: String! user_id: ID! } type User { id: ID username: String } type Message { id: ID text: String created_at: String user: User } type Query { getLast100Messages: [Message] } type Mutation { findOrCreateUser(user: UserInput!): User createMessage(message: MessageInput!): Message } type Subscription { messageCreated: Message }
рд╕рд░реНрдХрд┐рдЯ рддреИрдпрд╛рд░ рд╣реИ, рд╣рдо рд░рд┐рдЬрд╝реЙрд▓реНрд╡рд░ рдХрд╛ рд╡рд░реНрдгрди рдХрд░рддреЗ рд╣реИрдВ
рдПрдХ рдирдпрд╛ рд╕рдВрджреЗрд╢ рднреЗрдЬрдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рд░рд┐рдЬрд╝реЙрд▓реНрд╡рд░ рдХрд╛ рдПрдХ рдЙрджрд╛рд╣рд░рдг: const Message = require('../../models/message'); const { pubsub, MESSAGE_CREATED } = require('../../utils'); module.exports = { createMessage: async (obj, { message }, context, info) => { const createdMessage = await Message .query() .insert(message); const resultMessage = await Message .query() .eager('user') .findById(createdMessage.id); pubsub.publish(MESSAGE_CREATED, { messageCreated: resultMessage }); return resultMessage; }, };
рдПрдХ рджрд┐рд▓рдЪрд╕реНрдк рдмрд╛рдд рдпрд╣ рд╣реИ рдХрд┐ рдбреЗрдЯрд╛рдмреЗрд╕ рдореЗрдВ рд╕рдВрджреЗрд╢ рдХреЛ рд╕рд╣реЗрдЬрдиреЗ рдХреЗ рдЕрд▓рд╛рд╡рд╛, рдкреНрд░рдХрд╛рд╢рди () рдлрд╝рдВрдХреНрд╢рди рдХреЛ рдпрд╣рд╛рдВ рдХрд╣рд╛ рдЬрд╛рддрд╛ рд╣реИ, рдЬреЛ рд╕рднреА рдЧреНрд░рд╛рд╣рдХреЛрдВ рдХреЛ MESSAGE_CREATED рдИрд╡реЗрдВрдЯ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рд╕реВрдЪрд┐рдд рдХрд░рддрд╛ рд╣реИ, рдЙрдиреНрд╣реЗрдВ рдПрдХ рдирдП рд╕рдВрджреЗрд╢ рдХрд╛ рдЙрджреНрджреЗрд╢реНрдп рднреЗрдЬрддрд╛ рд╣реИ (рдЪреМрдХрд╕ рдкрд╛рдардХ рдпрд╣ рдиреЛрдЯрд┐рд╕ рдХрд░реЗрдЧрд╛ рдХрд┐ рдкреНрд░реЗрд╖рдХ рдХреЛ рдЙрд╕рдХреЗ рдирдП рд╕рдВрджреЗрд╢ рдХреА рд╕реВрдЪрдирд╛ рднреА рдорд┐рд▓ рдЬрд╛рдПрдЧреА, рдФрд░ рд╣рдо рдЗрд╕ рдкрд░ рдЖрдЧреЗ рдХреА рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдХрд░реЗрдВрдЧреЗред рдЧреНрд░рд╛рд╣рдХ, рдПрдХ рд╡рд╛рд╕реНрддрд╡рд┐рдХ рдкрд░рд┐рдпреЛрдЬрдирд╛ рдореЗрдВ рдпрд╣ рдмреИрдХреЗрдВрдб рдХреА рдУрд░ рд╕реЗ рдЗрд╕реЗ рд╕рдВрд╕рд╛рдзрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╕рдордЭ рдореЗрдВ рдЖрддрд╛ рд╣реИ, рддрд╛рдХрд┐ рд╡рд┐рднрд┐рдиреНрди рдЧреНрд░рд╛рд╣рдХреЛрдВ рдХреЗ рдмреАрдЪ рддрд░реНрдХ рдХреА рдирдХрд▓ рди рдХрд░реЗрдВ)ред
рд╢реЗрд╖ рд░рд┐рдЬрд╝реЙрд▓реНрд╡рд░ рдХрд╛ рдХреЛрдб
рдпрд╣рд╛рдВ рдкрд╛рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛
рд╣реИ ред
рдЪреИрдЯ рдХрд╛ рд╕рд░реНрд╡рд░ рд╕рд╛рдЗрдб рддреИрдпрд╛рд░ рд╣реИ, рдореИрдВ рдХреИрд╕реЗ рд╕рддреНрдпрд╛рдкрд┐рдд рдХрд░ рд╕рдХрддрд╛ рд╣реВрдВ рдХрд┐ рд╕рдм рдХреБрдЫ рдХрд╛рдо рдХрд░ рд░рд╣рд╛ рд╣реИ?
рдЕрдкрдиреЗ рдмреНрд░рд╛рдЙрдЬрд╝рд░ рдореЗрдВ
рд╣реЛрд╕реНрдЯ рдЦреЛрд▓реЗрдВ рдФрд░ рдЖрдкрдХреЛ рдЗрд╕рдореЗрдВ рдЧреНрд░рд╛рдлрд╝рд┐рдХрд▓ рдЦреЗрд▓ рдХрд╛ рдореИрджрд╛рди рджрд┐рдЦрд╛рдИ рджреЗрдЧрд╛ред
рдЕрдЧрд▓реЗ рднрд╛рдЧ рдореЗрдВ, рд╣рдо рдПрдХ рдореЛрдмрд╛рдЗрд▓ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдмрдирд╛рдПрдВрдЧреЗред