рдпрд╣ рд▓реЗрдЦ REST API рдкрд░рд┐рдпреЛрдЬрдирд╛ рдХреЗ рд▓рд┐рдП рдПрдХ рдЙрдкрдпреЛрдЧреА рдФрд░ рдкреНрд░рд╛рд╕рдВрдЧрд┐рдХ рд╡рд┐рдирд┐рд░реНрджреЗрд╢ рд▓рд┐рдЦрдиреЗ рдФрд░ рд╕рдорд░реНрдерди рдХрд░рдиреЗ рдкрд░ рдзреНрдпрд╛рди рдХреЗрдВрджреНрд░рд┐рдд рдХрд░реЗрдЧрд╛, рдЬреЛ рдмрд╣реБрдд рд╕рд╛рд░реЗ рдЕрддрд┐рд░рд┐рдХреНрдд рдХреЛрдб рдХреЛ рдмрдЪрд╛рдПрдЧрд╛, рд╕рд╛рде рд╣реА рд╕рд╛рде рд╕рдордЧреНрд░ рд░реВрдк рд╕реЗ рдкрд░рд┐рдпреЛрдЬрдирд╛ рдХреА рдЕрдЦрдВрдбрддрд╛, рд╡рд┐рд╢реНрд╡рд╕рдиреАрдпрддрд╛ рдФрд░ рдкрд╛рд░рджрд░реНрд╢рд┐рддрд╛ рдореЗрдВ рд╕реБрдзрд╛рд░ рдХрд░реЗрдЧрд╛ред
RESTful API рдХреНрдпрд╛ рд╣реИ?
рдпрд╣ рдПрдХ рдорд┐рдердХ рд╣реИред
рдЧрдВрднреАрд░рддрд╛ рд╕реЗ, рдпрджрд┐ рдЖрдкрдХреЛ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдЖрдкрдХреЗ рдкреНрд░реЛрдЬреЗрдХреНрдЯ рдореЗрдВ рдПрдХ RESTful API рд╣реИ, рддреЛ рдЖрдк рд▓рдЧрднрдЧ рдирд┐рд╢реНрдЪрд┐рдд рд░реВрдк рд╕реЗ рдЧрд▓рдд рд╣реИрдВред рд░реЗрд╕реНрдЯрдлреБрд▓ рдХрд╛ рд╡рд┐рдЪрд╛рд░ рдПрдХ рдПрдкреАрдЖрдИ рдХрд╛ рдирд┐рд░реНрдорд╛рдг рдХрд░рдирд╛ рд╣реИ рдЬреЛ рд╕рднреА рдорд╛рдорд▓реЛрдВ рдореЗрдВ рд╡рд╛рд╕реНрддреБрд╢рд┐рд▓реНрдк рдирд┐рдпрдореЛрдВ рдФрд░ рдЖрд░рдИрдПрд╕рдЯреА рд╢реИрд▓реА рджреНрд╡рд╛рд░рд╛ рд╡рд░реНрдгрд┐рдд рдкреНрд░рддрд┐рдмрдВрдзреЛрдВ рдХрд╛ рдЕрдиреБрдкрд╛рд▓рди рдХрд░рддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рд╡рд╛рд╕реНрддрд╡рд┐рдХ рдкрд░рд┐рд╕реНрдерд┐рддрд┐рдпреЛрдВ рдореЗрдВ рдпрд╣ рд▓рдЧрднрдЧ рдЕрд╕рдВрднрд╡ рд╣реИ ред
рдПрдХ рдУрд░, рдЖрд░рдИрдПрд╕рдЯреА рдореЗрдВ рдмрд╣реБрдд рдЕрдзрд┐рдХ рдЕрд╕реНрдкрд╖реНрдЯ рдФрд░ рдЕрд╕реНрдкрд╖реНрдЯ рдкрд░рд┐рднрд╛рд╖рд╛рдПрдВ рд╣реИрдВред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, HTTP рд╡рд┐рдзрд┐рдпреЛрдВ рдФрд░ рд╕реНрдерд┐рддрд┐ рдХреЛрдб рдХреЗ рд╢рдмреНрджрдХреЛрд╢реЛрдВ рдореЗрдВ рд╕реЗ рдХреБрдЫ рд╢рдмреНрджреЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдЕрднреНрдпрд╛рд╕ рдореЗрдВ рдЙрдирдХреЗ рдЗрдЪреНрдЫрд┐рдд рдЙрджреНрджреЗрд╢реНрдп рдХреЗ рд▓рд┐рдП рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдЬрдмрдХрд┐ рдЙрдирдореЗрдВ рд╕реЗ рдХрдИ рдХрд╛ рдЙрдкрдпреЛрдЧ рдмрд┐рд▓реНрдХреБрд▓ рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред
рджреВрд╕рд░реА рдУрд░, REST рдмрд╣реБрдд рдЕрдзрд┐рдХ рдкреНрд░рддрд┐рдмрдВрдз рдмрдирд╛рддрд╛ рд╣реИред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рд╡рд╛рд╕реНрддрд╡рд┐рдХ рджреБрдирд┐рдпрд╛ рдореЗрдВ рд╕рдВрд╕рд╛рдзрдиреЛрдВ рдХрд╛ рдкрд░рдорд╛рдгреБ рдЙрдкрдпреЛрдЧ рдореЛрдмрд╛рдЗрд▓ рдЕрдиреБрдкреНрд░рдпреЛрдЧреЛрдВ рджреНрд╡рд╛рд░рд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдП рдЬрд╛рдиреЗ рд╡рд╛рд▓реЗ рдПрдкреАрдЖрдИ рдХреЗ рд▓рд┐рдП рддрд░реНрдХрд╕рдВрдЧрдд рдирд╣реАрдВ рд╣реИред рдЕрдиреБрд░реЛрдзреЛрдВ рдХреЗ рдмреАрдЪ рд╕реНрдерд┐рддрд┐ рдХреЛ рд╕реНрдЯреЛрд░ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдкреВрд░реНрдг рдЗрдирдХрд╛рд░ рдЕрдирд┐рд╡рд╛рд░реНрдп рд░реВрдк рд╕реЗ рдХрдИ рдПрдкреАрдЖрдИ рдореЗрдВ рдЙрдкрдпреЛрдЧ рдХрд┐рдП рдЬрд╛рдиреЗ рд╡рд╛рд▓реЗ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рд╕рддреНрд░реЛрдВ рдХреЗ рддрдВрддреНрд░ рдкрд░ рдкреНрд░рддрд┐рдмрдВрдз рд╣реИред
рд▓реЗрдХрд┐рди рд░реБрдХреЛ, рд╕рдм рдХреБрдЫ рдЗрддрдирд╛ рдмреБрд░рд╛ рдирд╣реАрдВ рд╣реИ!
рд╣рдореЗрдВ REST API рд╡рд┐рдирд┐рд░реНрджреЗрд╢рди рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдХреНрдпреЛрдВ рд╣реИ?
рдЗрди рдХрдорд┐рдпреЛрдВ рдХреЗ рдмрд╛рд╡рдЬреВрдж, рдПрдХ рдЙрдЪрд┐рдд рджреГрд╖реНрдЯрд┐рдХреЛрдг рдХреЗ рд╕рд╛рде, REST рдЕрднреА рднреА рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рд╢рд╛рдВрдд рдПрдкреАрдЖрдИ рдбрд┐рдЬрд╛рдЗрди рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдЙрддреНрдХреГрд╖реНрдЯ рдЖрдзрд╛рд░ рдмрдирд╛ рд╣реБрдЖ рд╣реИред рдЗрд╕ рддрд░рд╣ рдХреЗ рдПрдкреАрдЖрдИ рдореЗрдВ рдЖрдВрддрд░рд┐рдХ рдПрдХрд░реВрдкрддрд╛, рдПрдХ рд╕реНрдкрд╖реНрдЯ рд╕рдВрд░рдЪрдирд╛, рд╕реБрд╡рд┐рдзрд╛рдЬрдирдХ рдкреНрд░рд▓реЗрдЦрди рдФрд░ рдЕрдЪреНрдЫреА рдЗрдХрд╛рдИ рдкрд░реАрдХреНрд╖рдг рдХрд╡рд░реЗрдЬ рд╣реЛрдиреА рдЪрд╛рд╣рд┐рдПред рдпрд╣ рд╕рдм рдЖрдкрдХреЗ рдПрдкреАрдЖрдИ рдХреЗ рд▓рд┐рдП рдПрдХ рдЧреБрдгрд╡рддреНрддрд╛ рд╡рд┐рдирд┐рд░реНрджреЗрд╢ рд╡рд┐рдХрд╕рд┐рдд рдХрд░рдХреЗ рдкреНрд░рд╛рдкреНрдд рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред
рд╕рдмрд╕реЗ рдЕрдзрд┐рдХ рдмрд╛рд░, REST рдПрдкреАрдЖрдИ рд╡рд┐рдирд┐рд░реНрджреЗрд╢ рдЗрд╕рдХреЗ рдкреНрд░рд▓реЗрдЦрди рд╕реЗ рдЬреБрдбрд╝рд╛ рд╣реБрдЖ рд╣реИред рдкрд╣рд▓реЗ рдХреЗ рд╡рд┐рдкрд░реАрдд (рдЬреЛ рдЖрдкрдХреЗ рдПрдкреАрдЖрдИ рдХрд╛ рдФрдкрдЪрд╛рд░рд┐рдХ рд╡рд┐рд╡рд░рдг рд╣реИ), рдкреНрд░рд▓реЗрдЦрди рдХрд╛ рдЙрджреНрджреЗрд╢реНрдп рд▓реЛрдЧреЛрдВ рджреНрд╡рд╛рд░рд╛ рдкрдврд╝рд╛ рдЬрд╛рдирд╛ рд╣реИ: рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдЖрдкрдХреЗ рдПрдкреАрдЖрдИ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдореЛрдмрд╛рдЗрд▓ рдпрд╛ рд╡реЗрдм рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдХреЗ рдбреЗрд╡рд▓рдкрд░реНрд╕ рджреНрд╡рд╛рд░рд╛ред
рд╣рд╛рд▓рд╛рдВрдХрд┐, рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдкреНрд░рд▓реЗрдЦрди рдмрдирд╛рдиреЗ рдХреЗ рдЕрд▓рд╛рд╡рд╛, рдПрдХ рдЙрдЪрд┐рдд рдПрдкреАрдЖрдИ рд╡рд┐рд╡рд░рдг рдЕрднреА рднреА рдмрд╣реБрдд рд╕рд╛рд░реЗ рд▓рд╛рдн рд▓рд╛ рд╕рдХрддрд╛ рд╣реИред рдЗрд╕ рд▓реЗрдЦ рдореЗрдВ, рдореИрдВ рд╡рд┐рдирд┐рд░реНрджреЗрд╢ рдХреЗ рд╕рдХреНрд╖рдо рдЙрдкрдпреЛрдЧ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдХреИрд╕реЗ, рдХреЗ рдЙрджрд╛рд╣рд░рдг рд╕рд╛рдЭрд╛ рдХрд░рдирд╛ рдЪрд╛рд╣рддрд╛ рд╣реВрдВ:
- рдЗрдХрд╛рдИ рдкрд░реАрдХреНрд╖рдг рдХреЛ рд╕рд░рд▓ рдФрд░ рдЕрдзрд┐рдХ рд╡рд┐рд╢реНрд╡рд╕рдиреАрдп рдмрдирд╛рдирд╛;
- рдЗрдирдкреБрдЯ рдбреЗрдЯрд╛ рдХреЗ рдкреНрд░реАрдкреНрд░реЛрд╕реЗрд╕рд┐рдВрдЧ рдФрд░ рд╕рддреНрдпрд╛рдкрди рдХреЛ рдХреЙрдиреНрдлрд╝рд┐рдЧрд░ рдХрд░реЗрдВ;
- рдХреНрд░рдордмрджреНрдзрддрд╛ рдХреЛ рд╕реНрд╡рдЪрд╛рд▓рд┐рдд рдХрд░реЗрдВ рдФрд░ рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛рдУрдВ рдХреА рдЕрдЦрдВрдбрддрд╛ рд╕реБрдирд┐рд╢реНрдЪрд┐рдд рдХрд░реЗрдВ;
- рдФрд░ рдпрд╣рд╛рдВ рддрдХ тАЛтАЛрдХрд┐ рд╕реНрдереИрддрд┐рдХ рдЯрд╛рдЗрдкрд┐рдВрдЧ рдХрд╛ рд▓рд╛рдн рдЙрдард╛рдПрдВред
OpenAPI
REST API рдХрд╛ рд╡рд░реНрдгрди рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЖрдорддреМрд░ рдкрд░ рд╕реНрд╡реАрдХреГрдд рдкреНрд░рд╛рд░реВрдк OpenAPI рд╣реИ , рдЬрд┐рд╕реЗ рд╕реНрд╡реИрдЧрд░ рдХреЗ рд░реВрдк рдореЗрдВ рднреА рдЬрд╛рдирд╛ рдЬрд╛рддрд╛ рд╣реИред рдпрд╣ рд╡рд┐рдирд┐рд░реНрджреЗрд╢ JSON рдпрд╛ YAML рдкреНрд░рд╛рд░реВрдк рдореЗрдВ рдПрдХ рдПрдХрд▓ рдлрд╝рд╛рдЗрд▓ рд╣реИ, рдЬрд┐рд╕рдореЗрдВ рддреАрди рдЦрдВрдб рд╣реИрдВ:
- рдПрдХ рд╣реЗрдбрд░ рдЬрд┐рд╕рдореЗрдВ рдПрдкреАрдЖрдИ рдХрд╛ рдирд╛рдо, рд╡рд┐рд╡рд░рдг рдФрд░ рд╕рдВрд╕реНрдХрд░рдг рд╣реИ, рд╕рд╛рде рд╣реА рдЕрддрд┐рд░рд┐рдХреНрдд рдЬрд╛рдирдХрд╛рд░реА рднреА рд╣реИ;
- рдкрд░рд┐рднрд╛рд╖рд╛рдУрдВ рдХреЗ рд▓рд┐рдВрдХ рдХреЗ рд╕рд╛рде рд╕рднреА рд╕рдВрд╕рд╛рдзрдиреЛрдВ рдХрд╛ рд╡рд┐рд╡рд░рдг, рдЬрд┐рд╕рдореЗрдВ рдЙрдирдХреЗ рдкрд╣рдЪрд╛рдирдХрд░реНрддрд╛, HTTP рддрд░реАрдХреЗ, рд╕рднреА рдЗрдирдкреБрдЯ рдкреИрд░рд╛рдореАрдЯрд░ рдФрд░ рд╕рд╛рде рд╣реА рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдирд┐рдХрд╛рдп рдХреЗ рдХреЛрдб рдФрд░ рдкреНрд░рд╛рд░реВрдк рд╢рд╛рдорд┐рд▓ рд╣реИрдВ;
- JSON рд╕реНрдХреАрдорд╛ рдкреНрд░рд╛рд░реВрдк рдореЗрдВ рд╡рд╕реНрддреБрдУрдВ рдХреА рд╕рднреА рдкрд░рд┐рднрд╛рд╖рд╛рдПрдБ рдЬрд┐рдирдХрд╛ рдЙрдкрдпреЛрдЧ рдЗрдирдкреБрдЯ рдорд╛рдкрджрдВрдбреЛрдВ рдФрд░ рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛рдУрдВ рдореЗрдВ рджреЛрдиреЛрдВ рдореЗрдВ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред
OpenAPI рдореЗрдВ рдПрдХ рдЧрдВрднреАрд░ рдЦрд╛рдореА рд╣реИ - рд╕рдВрд░рдЪрдирд╛ рдХреА рдЬрдЯрд┐рд▓рддрд╛ рдФрд░, рдЕрдХреНрд╕рд░, рдЕрддрд┐рд░реЗрдХ ред рдПрдХ рдЫреЛрдЯреА рдкрд░рд┐рдпреЛрдЬрдирд╛ рдХреЗ рд▓рд┐рдП, рд╡рд┐рдирд┐рд░реНрджреЗрд╢рди JSON рдлрд╝рд╛рдЗрд▓ рдХреА рд╕рд╛рдордЧреНрд░реА рдЬрд▓реНрджреА рд╕реЗ рдХрдИ рд╣рдЬрд╛рд░ рд▓рд╛рдЗрдиреЛрдВ рддрдХ рдмрдврд╝ рд╕рдХрддреА рд╣реИред рдЗрд╕ рд░реВрдк рдореЗрдВ рдЗрд╕ рдлрд╝рд╛рдЗрд▓ рдХреЛ рдореИрдиреНрдпреБрдЕрд▓ рд░реВрдк рд╕реЗ рдмрдирд╛рдП рд░рдЦрдирд╛ рд╕рдВрднрд╡ рдирд╣реАрдВ рд╣реИред рдпрд╣ рдореМрдЬреВрджрд╛ рд╡рд┐рдирд┐рд░реНрджреЗрд╢реЛрдВ рдХреЛ рдмрдирд╛рдП рд░рдЦрдиреЗ рдХреЗ рд╡рд┐рдЪрд╛рд░ рдХреЗ рд▓рд┐рдП рдПрдХ рдЧрдВрднреАрд░ рдЦрддрд░рд╛ рд╣реИ рдХреНрдпреЛрдВрдХрд┐ рдПрдкреАрдЖрдИ рд╡рд┐рдХрд╕рд┐рдд рд╣реЛрддрд╛ рд╣реИред
рдХрдИ рджреГрд╢реНрдп рд╕рдВрдкрд╛рджрдХ рд╣реИрдВ рдЬреЛ рдЖрдкрдХреЛ рдПрдкреАрдЖрдИ рдХрд╛ рд╡рд░реНрдгрди рдХрд░рдиреЗ рдФрд░ рдкрд░рд┐рдгрд╛рдорд╕реНрд╡рд░реВрдк рдУрдкрдирдПрдкреАрдЖрдИ рд╡рд┐рдирд┐рд░реНрджреЗрд╢ рдмрдирд╛рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддреЗ рд╣реИрдВред рдмрджрд▓реЗ рдореЗрдВ, рдЕрддрд┐рд░рд┐рдХреНрдд рд╕реЗрд╡рд╛рдПрдВ рдФрд░ рдХреНрд▓рд╛рдЙрдб рд╕рдорд╛рдзрд╛рди рдЙрди рдкрд░ рдЖрдзрд╛рд░рд┐рдд рд╣реИрдВ, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рд╕реНрд╡реИрдЧрд░ , рдПрдкрд░реАрд░ , рд╕реНрдЯреЙрдкрд▓рд╛рдЗрдЯ , рд░реЗрд╕реНрдЯрд▓реЗрдЯ, рдФрд░ рдЕрдиреНрдпред
рд╣рд╛рд▓рд╛рдВрдХрд┐, рдореЗрд░реЗ рд▓рд┐рдП, рдЗрд╕ рддрд░рд╣ рдХреА рд╕реЗрд╡рд╛рдПрдВ рд╡рд┐рдирд┐рд░реНрджреЗрд╢ рдХреЛ рдЬрд▓реНрджреА рд╕реЗ рд╕рдВрдкрд╛рджрд┐рдд рдХрд░рдиреЗ рдФрд░ рдХреЛрдб рд▓реЗрдЦрди рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдХреЗ рд╕рд╛рде рд╕рдВрдпреЛрдЬрди рдХрд░рдиреЗ рдХреА рдХрдард┐рдирд╛рдИ рдХреЗ рдХрд╛рд░рдг рдмрд╣реБрдд рд╕реБрд╡рд┐рдзрд╛рдЬрдирдХ рдирд╣реАрдВ рдереАрдВред рдПрдХ рдФрд░ рдорд╛рдЗрдирд╕ рдкреНрд░рддреНрдпреЗрдХ рд╡рд┐рд╢реЗрд╖ рд╕реЗрд╡рд╛ рдХреЗ рдХрд╛рд░реНрдпреЛрдВ рдХреЗ рд╕реЗрдЯ рдкрд░ рдирд┐рд░реНрднрд░рддрд╛ рд╣реИред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдкреВрд░реНрдг рд╕реЗрд╡рд╛ рдЗрдХрд╛рдИ рдкрд░реАрдХреНрд╖рдг рдХреЛ рдХреЗрд╡рд▓ рдХреНрд▓рд╛рдЙрдб рд╕реЗрд╡рд╛ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рд▓рд╛рдЧреВ рдХрд░рдирд╛ рд▓рдЧрднрдЧ рдЕрд╕рдВрднрд╡ рд╣реИред рдХреЛрдб рдкреАрдврд╝реА рдФрд░ рдпрд╣рд╛рдВ рддрдХ тАЛтАЛрдХрд┐ рдПрдВрдбрдкреЙрдЗрдВрдЯ рдХреЗ рд▓рд┐рдП "рдкреНрд▓рдЧ" рдХрд╛ рдирд┐рд░реНрдорд╛рдг, рд╣рд╛рд▓рд╛рдВрдХрд┐ рдпрд╣ рдмрд╣реБрдд рд╕рдВрднрд╡ рд▓рдЧрддрд╛ рд╣реИ, рд╡реНрдпрд╡рд╣рд╛рд░ рдореЗрдВ рд╡реНрдпрд╛рд╡рд╣рд╛рд░рд┐рдХ рд░реВрдк рд╕реЗ рдмреЗрдХрд╛рд░ рд╣реИрдВред
Tinyspec
рдЗрд╕ рд▓реЗрдЦ рдореЗрдВ, рдореИрдВ рдореВрд▓ REST API рд╡рд┐рд╡рд░рдг рдкреНрд░рд╛рд░реВрдк - tinyspec рдХреЗ рдЖрдзрд╛рд░ рдкрд░ рдЙрджрд╛рд╣рд░рдгреЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реВрдВрдЧрд╛ ред рдкреНрд░рд╛рд░реВрдк рдЫреЛрдЯреА рдлрд╛рдЗрд▓реЗрдВ рд╣реИрдВ рдЬреЛ рдПрдХ рд╕рд╣рдЬ рдЬреНрдЮрд╛рди рдпреБрдХреНрдд рд╡рд╛рдХреНрдпрд╡рд┐рдиреНрдпрд╛рд╕ рдХреЗ рд╕рд╛рде рдкрд░рд┐рдпреЛрдЬрдирд╛ рдореЗрдВ рдЙрдкрдпреЛрдЧ рдХрд┐рдП рдЬрд╛рдиреЗ рд╡рд╛рд▓реЗ рд╕рдорд╛рдкрди рдмрд┐рдВрджреБ рдФрд░ рдбреЗрдЯрд╛ рдореЙрдбрд▓ рдХрд╛ рд╡рд░реНрдгрди рдХрд░рддреЗ рд╣реИрдВред рдлрд╝рд╛рдЗрд▓реЗрдВ рдХреЛрдб рдХреЗ рдмрдЧрд▓ рдореЗрдВ рд╕рдВрдЧреНрд░рд╣реАрдд рдХреА рдЬрд╛рддреА рд╣реИрдВ, рдЬреЛ рдЖрдкрдХреЛ рдЙрдирдХреЗ рд╕рд╛рде рдЬрд╛рдВрдЪ рдХрд░рдиреЗ рдФрд░ рдЙрдиреНрд╣реЗрдВ рд▓рд┐рдЦрдиреЗ рдХреА рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдореЗрдВ рдЙрдиреНрд╣реЗрдВ рд╕рд╣реА рддрд░реАрдХреЗ рд╕реЗ рд╕рдВрдкрд╛рджрд┐рдд рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИред рдЗрд╕реА рд╕рдордп, рдЯрд┐рдирд┐рд╕реНрдкреЗрдХ рд╕реНрд╡рдЪрд╛рд▓рд┐рдд рд░реВрдк рд╕реЗ рдПрдХ рдкреВрд░реНрдг рдУрдкрдирдПрдкреАрдЖрдИ рдореЗрдВ рд╕рдВрдХрд▓рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдЬрд┐рд╕реЗ рддреБрд░рдВрдд рдкрд░рд┐рдпреЛрдЬрдирд╛ рдореЗрдВ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред рдпрд╣ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдЖрдкрдХреЛ рдмрддрд╛рдиреЗ рдХрд╛ рд╕рдордп рд╣реИред
рдЗрд╕ рд▓реЗрдЦ рдореЗрдВ, рдореИрдВ Node.js (koa, express) рдФрд░ рд░реВрдмреА рдСрди рд░реЗрд▓реНрд╕ рд╕реЗ рдЙрджрд╛рд╣рд░рдг рджреВрдВрдЧрд╛, рд╣рд╛рд▓рд╛рдВрдХрд┐ рдпреЗ рдкреНрд░рдерд╛рдПрдВ рдЕрдзрд┐рдХрд╛рдВрд╢ рдкреНрд░реМрджреНрдпреЛрдЧрд┐рдХрд┐рдпреЛрдВ рдкрд░ рд▓рд╛рдЧреВ рд╣реЛрддреА рд╣реИрдВ, рдЬрд┐рдирдореЗрдВ рдкрд╛рдпрдерди, рдкреАрдПрдЪрдкреА рдФрд░ рдЬрд╛рд╡рд╛ рд╢рд╛рдорд┐рд▓ рд╣реИрдВред
рдЬрдм рдХрд▓реНрдкрдирд╛ рдЕрд╡рд┐рд╢реНрд╡рд╕рдиреАрдп рд░реВрдк рд╕реЗ рдЙрдкрдпреЛрдЧреА рд╣реИ
1. рд╕рдорд╛рдкрди рдмрд┐рдВрджреБрдУрдВ рдХреА рдЗрдХрд╛рдИ-рдкрд░реАрдХреНрд╖рдг
рд╡реНрдпрд╡рд╣рд╛рд░ рдЪрд╛рд▓рд┐рдд рд╡рд┐рдХрд╛рд╕ (BDD) REST API рд╡рд┐рдХрд╕рд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЖрджрд░реНрд╢ рд╣реИред рдпреВрдирд┐рдЯ рдкрд░реАрдХреНрд╖рдг рд▓рд┐рдЦрдиреЗ рдХрд╛ рд╕рдмрд╕реЗ рд╕реБрд╡рд┐рдзрд╛рдЬрдирдХ рддрд░реАрдХрд╛ рд╡реНрдпрдХреНрддрд┐рдЧрдд рдХрдХреНрд╖рд╛рдУрдВ, рдореЙрдбрд▓ рдФрд░ рдирд┐рдпрдВрддреНрд░рдХреЛрдВ рдХреЗ рд▓рд┐рдП рдирд╣реАрдВ рд╣реИ, рдмрд▓реНрдХрд┐ рд╡рд┐рд╢рд┐рд╖реНрдЯ рд╕рдорд╛рдкрди рдмрд┐рдВрджреБрдУрдВ рдХреЗ рд▓рд┐рдП рд╣реИред рдкреНрд░рддреНрдпреЗрдХ рдкрд░реАрдХреНрд╖рдг рдореЗрдВ, рдЖрдк рдПрдХ рд╡рд╛рд╕реНрддрд╡рд┐рдХ HTTP рдЕрдиреБрд░реЛрдз рдХрд╛ рдЕрдиреБрдХрд░рдг рдХрд░рддреЗ рд╣реИрдВ рдФрд░ рд╕рд░реНрд╡рд░ рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдХреА рдЬрд╛рдВрдЪ рдХрд░рддреЗ рд╣реИрдВред Node.js рдореЗрдВ, рдкрд░реАрдХреНрд╖рдг рдЕрдиреБрд░реЛрдзреЛрдВ рдХреЗ рдЕрдиреБрдХрд░рдг рдХреЗ рд▓рд┐рдП, рд░реВрдмреА рдСрди рд░реЗрд▓реНрд╕ - рдПрдпрд░рдмреЛрд░реНрди рдореЗрдВ рд╕реБрдкрд░рдЯреЗрд╕реНрдЯ рдФрд░ рдЪреА- http рд╣реИрдВ ред
рдорд╛рди рд▓реЗрдВ рдХрд┐ рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдПрдХ User
рд╕реНрдХреАрдорд╛ рдФрд░ рдПрдХ GET /users
рд╕рдорд╛рдкрди рдмрд┐рдВрджреБ рд╣реИ рдЬреЛ рд╕рднреА рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛рдУрдВ рдХреЛ рд╡рд╛рдкрд╕ рдХрд░рддрд╛ рд╣реИред рдпрд╣рд╛рдБ рдЯрд┐рдирд┐рд╕реЗрдк рд╕рд┐рдВрдЯреИрдХреНрд╕ рд╣реИ рдЬреЛ рдЗрд╕рдХрд╛ рд╡рд░реНрдгрди рдХрд░рддрд╛ рд╣реИ:
- User.models.tinyspec рдлрд╝рд╛рдЗрд▓:
User {name, isAdmin: b, age?: i}
- рдлрд╝рд╛рдЗрд▓ users.endpoint.tinyspec :
GET /users => {users: User[]}
рдЗрд╕ рдкреНрд░рдХрд╛рд░ рд╣рдорд╛рд░рд╛ рдкрд░реАрдХреНрд╖рдг рджрд┐рдЦреЗрдЧрд╛:
Node.js
describe('/users', () => { it('List all users', async () => { const { status, body: { users } } = request.get('/users'); expect(status).to.equal(200); expect(users[0].name).to.be('string'); expect(users[0].isAdmin).to.be('boolean'); expect(users[0].age).to.be.oneOf(['boolean', null]); }); });
рд░реВрдмреА рдСрди рд░реЗрд▓реНрд╕
describe 'GET /users' do it 'List all users' do get '/users' expect_status(200) expect_json_types('users.*', { name: :string, isAdmin: :boolean, age: :integer_or_null, }) end end
рдЬрдм рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдПрдХ рд╡рд┐рдирд┐рд░реНрджреЗрд╢ рд╣реИ рдЬреЛ рд╕рд░реНрд╡рд░ рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рд╕реНрд╡рд░реВрдкреЛрдВ рдХрд╛ рд╡рд░реНрдгрди рдХрд░рддрд╛ рд╣реИ, рддреЛ рд╣рдо рдкрд░реАрдХреНрд╖рдг рдХреЛ рд╕рд░рд▓ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдФрд░ рдмрд╕ рдЗрд╕ рд╡рд┐рдирд┐рд░реНрджреЗрд╢ рдХреЗ рдЦрд┐рд▓рд╛рдл рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдХреА рдЬрд╛рдВрдЪ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рдРрд╕рд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдо рдЗрд╕ рддрдереНрдп рдХрд╛ рд▓рд╛рдн рдЙрдард╛рдПрдВрдЧреЗ рдХрд┐ рд╣рдорд╛рд░реЗ рдЯрд┐рдирд┐рд╕реЗрдк рдореЙрдбрд▓ рдХреЛ рдУрдкрдирдПрдкреАрдЖрдИ рдкрд░рд┐рднрд╛рд╖рд╛рдУрдВ рдореЗрдВ рдмрджрд▓ рджрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ, рдЬреЛ рдХрд┐ JSON рд╕реНрдХреАрдорд╛ рдкреНрд░рд╛рд░реВрдк рдХреЗ рдЕрдиреБрд░реВрдк рд╣реИрдВред
рдЬреЗрдПрд╕ рдореЗрдВ рдХреЛрдИ рд╢рд╛рдмреНрджрд┐рдХ рд╡рд╕реНрддреБ (рдпрд╛ рд░реВрдмреА рдореЗрдВ Hash
, рдкрд╛рдпрдерди рдореЗрдВ рдПрдХ dict
, рдкреАрдПрдЪрдкреА рдореЗрдВ рдПрдХ рд╕рд╛рд╣рдЪрд░реНрдп рд╕рд░рдгреА рдФрд░ рдпрд╣рд╛рдВ рддрдХ тАЛтАЛрдХрд┐ рдЬрд╛рд╡рд╛ рдореЗрдВ рдПрдХ Map
) рдХреЛ JSON рдпреЛрдЬрдирд╛ рдХреЗ рдЕрдиреБрдкрд╛рд▓рди рдХреЗ рд▓рд┐рдП рдкрд░реАрдХреНрд╖рдг рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред рдФрд░ рдЯреЗрд╕реНрдЯрд┐рдВрдЧ рдлреНрд░реЗрдорд╡рд░реНрдХ рдХреЗ рд▓рд┐рдП рднреА рд╕рдорд╛рди рдкреНрд▓рдЧрдЗрдиреНрд╕ рд╣реИрдВ, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП RSPec рдХреЗ рд▓рд┐рдП jest-ajv ( npm ), chai-ajv-json-schema ( npm ) рдФрд░ json_matchers (rubygem)ред
рдпреЛрдЬрдирд╛рдУрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рд╕реЗ рдкрд╣рд▓реЗ, рдЖрдкрдХреЛ рдЙрдиреНрд╣реЗрдВ рдкрд░рд┐рдпреЛрдЬрдирд╛ рд╕реЗ рдЬреЛрдбрд╝рдирд╛ рд╣реЛрдЧрд╛ред рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ, рд╣рдо рдЯрд┐рдирд┐рд╕реНрдкреЗрдХ рдХреЗ рдЖрдзрд╛рд░ рдкрд░ Openapi.json рд╡рд┐рдирд┐рд░реНрджреЗрд╢рди рдлрд╝рд╛рдЗрд▓ рдЬрдирд░реЗрдЯ рдХрд░реЗрдВрдЧреЗ (рдпрд╣ рдХрд╛рд░реНрд░рд╡рд╛рдИ рд╕реНрд╡рдЪрд╛рд▓рд┐рдд рд░реВрдк рд╕реЗ рдкреНрд░рддреНрдпреЗрдХ рд░рди рд░рди рд╕реЗ рдкрд╣рд▓реЗ рдХреА рдЬрд╛ рд╕рдХрддреА рд╣реИ:
tinyspec -j -o openapi.json
Node.js
рдЕрдм рд╣рдо рдкрд░рд┐рдпреЛрдЬрдирд╛ рдореЗрдВ рдкреНрд░рд╛рдкреНрдд JSON рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдФрд░ рдЗрд╕рд╕реЗ definitions
рд▓реЗ рд╕рдХрддреЗ рд╣реИрдВ, рдЬрд┐рд╕рдореЗрдВ JSON рдХреА рд╕рднреА рдпреЛрдЬрдирд╛рдПрдБ рд╢рд╛рдорд┐рд▓ рд╣реИрдВред рдпреЛрдЬрдирд╛рдУрдВ рдореЗрдВ рдХреНрд░реЙрд╕-рд░реЗрдлрд░реЗрдВрд╕ ( $ref
) рд╢рд╛рдорд┐рд▓ рд╣реЛ рд╕рдХрддреЗ рд╣реИрдВ, рдЗрд╕рд▓рд┐рдП, рдЕрдЧрд░ рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдиреЗрд╕реНрдЯреЗрдб рд╕реНрдХреАрдо рд╣реИрдВ (рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, Blog {posts: Post[]}
), рддреЛ рд╣рдореЗрдВ рдЙрдиреНрд╣реЗрдВ рд╕рддреНрдпрд╛рдкрди рдореЗрдВ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП "рд╡рд┐рд╕реНрддрд╛рд░" рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рдРрд╕рд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдо json-schema-deref-sync ( npm ) рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВрдЧреЗред
import deref from 'json-schema-deref-sync'; const spec = require('./openapi.json'); const schemas = deref(spec).definitions; describe('/users', () => { it('List all users', async () => { const { status, body: { users } } = request.get('/users'); expect(status).to.equal(200);
рд░реВрдмреА рдСрди рд░реЗрд▓реНрд╕
json_matchers
$ref
рд▓рд┐рдВрдХ рдХреЛ рд╕рдВрднрд╛рд▓ рд╕рдХрддреЗ рд╣реИрдВ, рд▓реЗрдХрд┐рди рдПрдХ рдирд┐рд╢реНрдЪрд┐рдд рддрд░реАрдХреЗ рд╕реЗ рдлрд╝рд╛рдЗрд▓ рд╕рд┐рд╕реНрдЯрдо рдореЗрдВ рдпреЛрдЬрдирд╛рдУрдВ рдХреЗ рд╕рд╛рде рдЕрд▓рдЧ-рдЕрд▓рдЧ рдлрд╝рд╛рдЗрд▓реЛрдВ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИ, рдЗрд╕рд▓рд┐рдП рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ рдЖрдкрдХреЛ swagger.json
рдХреЛ рдХрдИ рдЫреЛрдЯреА рдлрд╝рд╛рдЗрд▓реЛрдВ рдореЗрдВ рд╡рд┐рднрд╛рдЬрд┐рдд рдХрд░рдирд╛ рд╣реЛрдЧрд╛ ( рдпрд╣рд╛рдБ рдЗрд╕ рдкрд░ рдФрд░ рдЕрдзрд┐рдХ):
рдЙрд╕рдХреЗ рдмрд╛рдж, рд╣рдо рдЕрдкрдирд╛ рдЯреЗрд╕реНрдЯ рдЗрд╕ рддрд░рд╣ рд▓рд┐рдЦ рд╕рдХрддреЗ рд╣реИрдВ:
describe 'GET /users' do it 'List all users' do get '/users' expect_status(200) expect(result[:users][0]).to match_json_schema('User') end end
рдиреЛрдЯ: рдЗрд╕ рддрд░рд╣ рд╕реЗ рдкрд░реАрдХреНрд╖рдг рд▓рд┐рдЦрдирд╛ рдЕрд╡рд┐рд╢реНрд╡рд╕рдиреАрдп рд░реВрдк рд╕реЗ рд╕реБрд╡рд┐рдзрд╛рдЬрдирдХ рд╣реИред рдЦрд╛рд╕рдХрд░ рдЕрдЧрд░ рдЖрдкрдХрд╛ рдЖрдИрдбреАрдИ рд░рдирд┐рдВрдЧ рдЯреЗрд╕реНрдЯ рдФрд░ рдбрд┐рдмрдЧрд┐рдВрдЧ (рдЬреИрд╕реЗ рд╡реЗрдмрд╕реНрдЯреЙрд░реНрдо, рд░реВрдмреАрдорд╛рдЗрди рдФрд░ рд╡рд┐рдЬреБрдЕрд▓ рд╕реНрдЯреВрдбрд┐рдпреЛ) рдХрд╛ рд╕рдорд░реНрдерди рдХрд░рддрд╛ рд╣реИред рдЗрд╕ рдкреНрд░рдХрд╛рд░, рдЖрдк рдХрд┐рд╕реА рдЕрдиреНрдп рд╕реЙрдлрд╝реНрдЯрд╡реЗрдпрд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдирд╣реАрдВ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рдФрд░ рдПрдкреАрдЖрдИ рдХрд╛ рд╕рдВрдкреВрд░реНрдг рд╡рд┐рдХрд╛рд╕ рдЪрдХреНрд░ рд▓рдЧрд╛рддрд╛рд░ 3 рдЪрд░рдгреЛрдВ рддрдХ рдХрдо рд╣реЛ рдЬрд╛рддрд╛ рд╣реИ:
- рд╡рд┐рдирд┐рд░реНрджреЗрд╢ рдбрд┐рдЬрд╛рдЗрди (рдЬреИрд╕реЗ рдЯрд┐рдирд┐рд╕реНрдкреЗрдХ рдореЗрдВ);
- рдЬреЛрдбрд╝рд╛ / рдкрд░рд┐рд╡рд░реНрддрд┐рдд рд╕рдорд╛рдкрди рдмрд┐рдВрджреБрдУрдВ рдХреЗ рд▓рд┐рдП рдкрд░реАрдХреНрд╖рдгреЛрдВ рдХрд╛ рдПрдХ рдкреВрд░рд╛ рд╕реЗрдЯ рд▓рд┐рдЦрдирд╛;
- рд╡рд┐рдХрд╛рд╕рд╢реАрд▓ рдХреЛрдб рдЬреЛ рд╕рднреА рдкрд░реАрдХреНрд╖рдгреЛрдВ рдХреЛ рд╕рдВрддреБрд╖реНрдЯ рдХрд░рддрд╛ рд╣реИред
2. рдЗрдирдкреБрдЯ рдХрд╛ рд╕рддреНрдпрд╛рдкрди
OpenAPI рди рдХреЗрд╡рд▓ рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛рдУрдВ рдХреЗ рдкреНрд░рд╛рд░реВрдк рдХрд╛ рд╡рд░реНрдгрди рдХрд░рддрд╛ рд╣реИ, рдмрд▓реНрдХрд┐ рдЗрдирдкреБрдЯ рдбреЗрдЯрд╛ рднреА рд╣реИред рдпрд╣ рд╣рдореЗрдВ рдЕрдиреБрд░реЛрдз рдХреЗ рджреМрд░рд╛рди рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рд╕реЗ рдкреНрд░рд╛рдкреНрдд рдбреЗрдЯрд╛ рдХреЛ рд╕рд╣реА рддрд░реАрдХреЗ рд╕реЗ рд╕рддреНрдпрд╛рдкрд┐рдд рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИред
рдорд╛рди рд▓реЗрдВ рдХрд┐ рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рд╡рд┐рдирд┐рд░реНрджреЗрд╢ рд╣реИрдВ рдЬреЛ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдбреЗрдЯрд╛ рдХреЛ рдЕрджреНрдпрддрди рдХрд░рдиреЗ рдХреЗ рд╕рд╛рде-рд╕рд╛рде рд╕рднреА рдХреНрд╖реЗрддреНрд░реЛрдВ рдХреЛ рднреА рдмрджрд▓ рд╕рдХрддреЗ рд╣реИрдВ:
рдкрд╣рд▓реЗ рд╣рдордиреЗ рдкрд░реАрдХреНрд╖рдгреЛрдВ рдХреЗ рдЕрдВрджрд░ рд╕рддреНрдпрд╛рдкрди рдХреЗ рд▓рд┐рдП рдкреНрд▓рдЧрдЗрдиреНрд╕ рдХреЛ рджреЗрдЦрд╛, рд╣рд╛рд▓рд╛рдВрдХрд┐ рдЕрдзрд┐рдХ рд╕рд╛рдорд╛рдиреНрдп рдорд╛рдорд▓реЛрдВ рдХреЗ рд▓рд┐рдП ajv ( npm ) рдФрд░ json-schema (rubygem) рд╕рддреНрдпрд╛рдкрди рдореЙрдбреНрдпреВрд▓ рд╣реИрдВ, рдЪрд▓реЛ рдЙрдирдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВ рдФрд░ рд╕рддреНрдпрд╛рдкрди рдХреЗ рд╕рд╛рде рдПрдХ рдирд┐рдпрдВрддреНрд░рдХ рд▓рд┐рдЦрддреЗ рд╣реИрдВред
Node.js (Koa)
рдпрд╣ рдПрдХреНрд╕рдкреНрд░реЗрд╕ рдХреЗ рдЙрддреНрддрд░рд╛рдзрд┐рдХрд╛рд░реА рдХреЛрдП рдХреЗ рд▓рд┐рдП рдПрдХ рдЙрджрд╛рд╣рд░рдг рд╣реИ, рд▓реЗрдХрд┐рди рдПрдХреНрд╕рдкреНрд░реЗрд╕ рдХреЗ рд▓рд┐рдП, рдХреЛрдб рд╕рдорд╛рди рджрд┐рдЦрд╛рдИ рджреЗрдЧрд╛ред
import Router from 'koa-router'; import Ajv from 'ajv'; import { schemas } from './schemas'; const router = new Router();
рдЗрд╕ рдЙрджрд╛рд╣рд░рдг рдореЗрдВ, рдпрджрд┐ рдЗрдирдкреБрдЯ рд╡рд┐рдирд┐рд░реНрджреЗрд╢ рдХреЛ рдкреВрд░рд╛ рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИ, рддреЛ рд╕рд░реНрд╡рд░ рдХреНрд▓рд╛рдЗрдВрдЯ рдХреЛ 500 Internal Server Error
рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рджреЗрдЧрд╛ред рдРрд╕рд╛ рд╣реЛрдиреЗ рд╕реЗ рд░реЛрдХрдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдо рд╕рддреНрдпрд╛рдкрдирдХрд░реНрддрд╛ рддреНрд░реБрдЯрд┐ рдХреЛ рд░реЛрдХ рд╕рдХрддреЗ рд╣реИрдВ рдФрд░ рдЕрдкрдиреА рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдмрдирд╛ рд╕рдХрддреЗ рд╣реИрдВ, рдЬрд┐рд╕рдореЗрдВ рд╡рд┐рд╢рд┐рд╖реНрдЯ рдХреНрд╖реЗрддреНрд░реЛрдВ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдЕрдзрд┐рдХ рд╡рд┐рд╕реНрддреГрдд рдЬрд╛рдирдХрд╛рд░реА рд╣реЛрдЧреА рдЬреЛ рдкрд░реАрдХреНрд╖рдг рдореЗрдВ рдЙрддреНрддреАрд░реНрдг рдирд╣реАрдВ рд╣реБрдП рд╣реИрдВ, рдФрд░ рд╡рд┐рдирд┐рд░реНрджреЗрд╢ рдХрд╛ рдЕрдиреБрдкрд╛рд▓рди рднреА рдХрд░рддреЗ рд╣реИрдВ ред
FieldsValidationError
рдореЙрдбрд▓ рдХрд╛ FieldsValidationError
рдлрд╝рд╛рдЗрд▓ рдореЗрдВ рд╡рд┐рд╡рд░рдг рдЬреЛрдбрд╝реЗрдВ:
Error {error: b, message} InvalidField {name, message} FieldsValidationError < Error {fields: InvalidField[]}
рдФрд░ рдЕрдм рд╣рдо рдЗрд╕реЗ рд╣рдорд╛рд░реЗ рд╕рдорд╛рдкрди рдмрд┐рдВрджреБ рдХреЗ рд╕рдВрднрд╛рд╡рд┐рдд рдЙрддреНрддрд░реЛрдВ рдореЗрдВ рд╕реЗ рдПрдХ рдХреЗ рд░реВрдк рдореЗрдВ рджрд░реНрд╢рд╛рддреЗ рд╣реИрдВ:
PATCH /users/:id {user: UserUpdate} => 200 {success: b} => 422 FieldsValidationError
рдпрд╣ рджреГрд╖реНрдЯрд┐рдХреЛрдг рдЖрдкрдХреЛ рдЗрдХрд╛рдИ рдкрд░реАрдХреНрд╖рдг рд▓рд┐рдЦрдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИ рдЬреЛ рдХреНрд▓рд╛рдЗрдВрдЯ рд╕реЗ рдкреНрд░рд╛рдкреНрдд рдЧрд▓рдд рдбреЗрдЯрд╛ рдХреЗ рд╕рд╛рде рддреНрд░реБрдЯрд┐рдпреЛрдВ рдХреЗ рдЧрдарди рдХреА рд╢реБрджреНрдзрддрд╛ рдХреЛ рд╕рддреНрдпрд╛рдкрд┐рдд рдХрд░рддрд╛ рд╣реИред
3. рдореЙрдбрд▓ рдХрд╛ рд╕реАрд░рд┐рдпрд▓рд╛рдЗрдЬреЗрд╢рди
рд▓рдЧрднрдЧ рд╕рднреА рдЖрдзреБрдирд┐рдХ рд╕рд░реНрд╡рд░ рдлреНрд░реЗрдорд╡рд░реНрдХ рдПрдХ рдпрд╛ рджреВрд╕рд░реЗ рддрд░реАрдХреЗ рд╕реЗ ORM рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВред рдЗрд╕рдХрд╛ рдорддрд▓рдм рд╣реИ рдХрд┐ рд╕рд┐рд╕реНрдЯрдо рдХреЗ рдЕрдВрджрд░ рдПрдкреАрдЖрдИ рдореЗрдВ рдЙрдкрдпреЛрдЧ рдХрд┐рдП рдЬрд╛рдиреЗ рд╡рд╛рд▓реЗ рдЕрдзрд┐рдХрд╛рдВрд╢ рд╕рдВрд╕рд╛рдзрди рдореЙрдбрд▓, рдЙрдирдХреЗ рдЙрджрд╛рд╣рд░рдг рдФрд░ рд╕рдВрдЧреНрд░рд╣ рдХреЗ рд░реВрдк рдореЗрдВ рдкреНрд░рд╕реНрддреБрдд рдХрд┐рдП рдЬрд╛рддреЗ рд╣реИрдВред
рдПрдкреАрдЖрдИ рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдореЗрдВ рд╕рдВрдЪрд░рдг рдХреЗ рд▓рд┐рдП рдЗрди рд╕рдВрд╕реНрдерд╛рдУрдВ рдХреЗ JSON рдкреНрд░рддрд┐рдирд┐рдзрд┐рддреНрд╡ рдХреЛ рдЙрддреНрдкрдиреНрди рдХрд░рдиреЗ рдХреА рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдХреЛ рдХреНрд░рдорд╛рдВрдХрди рдХрд╣рд╛ рдЬрд╛рддрд╛ рд╣реИред рд╡рд┐рднрд┐рдиреНрди рдЪреМрдЦрдЯреЗ рдХреЗ рд▓рд┐рдП рдХрдИ рдкреНрд▓рдЧрдЗрдиреНрд╕ рд╣реИрдВ рдЬреЛ рдХреНрд░рдордмрджреНрдзрддрд╛ рдХреЗ рдХрд╛рд░реНрдп рдХрд░рддреЗ рд╣реИрдВ, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП: рд╕реАрдХреНрд╡рд▓рд╛рдЗрдЬрд╝-рдЯреВ-рдЬреЛрдВрд╕рди (рдПрдирдкреАрдПрдо), рдХреГрддреНрдпреЛрдВ_рд╕_рдкрд╛рдЗ (рд░реВрдмреАрдЧреИрдо), рдЬреЛрдВрд╕рд╛рдкреА-рд░реЗрд▓реНрд╕ (рд░реВрдмреАрдЧреИрдо)ред рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ, рдпреЗ рдкреНрд▓рдЧрдЗрдиреНрд╕ рдПрдХ рд╡рд┐рд╢рд┐рд╖реНрдЯ рдореЙрдбрд▓ рдХреЗ рд▓рд┐рдП рдЙрди рдХреНрд╖реЗрддреНрд░реЛрдВ рдХреА рдПрдХ рд╕реВрдЪреА рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддреЗ рд╣реИрдВ рдЬрд┐рдиреНрд╣реЗрдВ JSON рдСрдмреНрдЬреЗрдХреНрдЯ рдореЗрдВ рд╢рд╛рдорд┐рд▓ рдХрд┐рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдП, рд╕рд╛рде рд╣реА рдЕрддрд┐рд░рд┐рдХреНрдд рдирд┐рдпрдо, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдЙрдирдХрд╛ рдирд╛рдо рдмрджрд▓рдиреЗ рдпрд╛ рдЧрддрд┐рд╢реАрд▓ рд░реВрдк рд╕реЗ рдорд╛рдиреЛрдВ рдХреА рдЧрдгрдирд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдПред
рдХрдард┐рдирд╛рдЗрдпрд╛рдБ рддрдм рд╢реБрд░реВ рд╣реЛрддреА рд╣реИрдВ рдЬрдм рд╣рдореЗрдВ рдПрдХ рд╣реА рдореЙрдбрд▓ рдХреЗ рдХрдИ рдЕрд▓рдЧ-рдЕрд▓рдЧ JSON рдирд┐рд░реВрдкрдг рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИ рдпрд╛ рдЬрдм рдХрд┐рд╕реА рдСрдмреНрдЬреЗрдХреНрдЯ рдореЗрдВ рдиреЗрд╕реНрдЯреЗрдб рд╕рдВрд╕реНрдерд╛рдПрдБ - рд╕рдВрдШ рд╣реЛрддреЗ рд╣реИрдВред рдзрд╛рд░рд╛рд╡рд╛рд╣рд┐рдХреЛрдВ рдХреА рд╡рд┐рд░рд╛рд╕рдд, рдкреБрди: рдЙрдкрдпреЛрдЧ рдФрд░ рдЬреЛрдбрд╝рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ ред
рд╡рд┐рднрд┐рдиреНрди рдореЙрдбреНрдпреВрд▓ рдЗрди рд╕рдорд╕реНрдпрд╛рдУрдВ рдХреЛ рдЕрд▓рдЧ-рдЕрд▓рдЧ рддрд░реАрдХреЛрдВ рд╕реЗ рд╣рд▓ рдХрд░рддреЗ рд╣реИрдВ, рд▓реЗрдХрд┐рди рдЪрд▓реЛ рд╕реЛрдЪрддреЗ рд╣реИрдВ рдХрд┐ рдХреНрдпрд╛ рд╡рд┐рдирд┐рд░реНрджреЗрд╢ рд╣рдореЗрдВ рдлрд┐рд░ рд╕реЗ рдорджрдж рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ? рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ, рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ, JSON рдкреНрд░рддрд┐рдирд┐рдзрд┐рддреНрд╡ рдХреЗ рд▓рд┐рдП рдЖрд╡рд╢реНрдпрдХрддрд╛рдУрдВ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рд╕рднреА рдЬрд╛рдирдХрд╛рд░реА, рдиреЗрд╕реНрдЯреЗрдб рд╕рдВрд╕реНрдерд╛рдУрдВ рд╕рд╣рд┐рдд рдХреНрд╖реЗрддреНрд░реЛрдВ рдХреЗ рд╕рднреА рд╕рдВрднрд╛рд╡рд┐рдд рд╕рдВрдпреЛрдЬрди рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдЗрд╕рдореЗрдВ рд╣реИрдВред рддреЛ рд╣рдо рдПрдХ рд╕реНрд╡рдЪрд╛рд▓рд┐рдд рдХреНрд░рдордмрджреНрдзрдХ рд▓рд┐рдЦ рд╕рдХрддреЗ рд╣реИрдВред
рдореИрдВ рдЖрдкрдХреЗ рдзреНрдпрд╛рди рдореЗрдВ рдПрдХ рдЫреЛрдЯрд╛ рдореЙрдбреНрдпреВрд▓ рд╕реАрдХреНрд╡рд▓-рд╕реАрд░реАрдЬрд╝-рд╕реАрд░реАрдЬрд╝ (рдПрдирдкреАрдПрдо) рд▓рд╛рддрд╛ рд╣реВрдВ , рдЬреЛ рдЖрдкрдХреЛ рд╕реАрдХреНрд╡реЗрд▓рд╛рдЗрдЬрд╝ рдореЙрдбрд▓ рдХреЗ рд▓рд┐рдП рдРрд╕рд╛ рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИред рдпрд╣ рдореЙрдбрд▓ рдпрд╛ рдПрдХ рд╕рд░рдгреА, рд╕рд╛рде рд╣реА рдЖрд╡рд╢реНрдпрдХ рд╕рд░реНрдХрд┐рдЯ рдХрд╛ рдПрдХ рдЙрджрд╛рд╣рд░рдг рд▓реЗрддрд╛ рд╣реИ, рдФрд░ рдкреБрдирд░рд╛рд╡реГрддреНрдд рдХреНрд░рдордмрджреНрдз рдСрдмреНрдЬреЗрдХреНрдЯ рдХрд╛ рдирд┐рд░реНрдорд╛рдг рдХрд░рддрд╛ рд╣реИ, рд╕рднреА рдЖрд╡рд╢реНрдпрдХ рдлрд╝реАрд▓реНрдб рдХреЛ рдзреНрдпрд╛рди рдореЗрдВ рд░рдЦрддрд╛ рд╣реИ рдФрд░ рд╕рдВрдмрдВрдзрд┐рдд рд╕рдВрд╕реНрдерд╛рдУрдВ рдХреЗ рд▓рд┐рдП рдиреЗрд╕реНрдЯреЗрдб рд╕рд░реНрдХрд┐рдЯ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реИред
рддреЛ, рдорд╛рди рд▓реЗрдВ рдХрд┐ рд╣рдореЗрдВ рдПрдкреАрдЖрдИ рд╕реЗ рдЙрди рд╕рднреА рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛рдУрдВ рдХреЛ рд╡рд╛рдкрд╕ рд▓реМрдЯрдирд╛ рд╣реЛрдЧрд╛ рдЬрд┐рдирдХреЗ рдкрд╛рд╕ рдмреНрд▓реЙрдЧ рдкреЛрд╕реНрдЯ рд╣реИрдВ, рдЙрди рдкреЛрд╕реНрдЯ рдкрд░ рдЯрд┐рдкреНрдкрдгрд┐рдпреЛрдВ рд╕рд╣рд┐рддред рд╣рдо рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рд╡рд┐рдирд┐рд░реНрджреЗрд╢рди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реБрдП рдЗрд╕рдХрд╛ рд╡рд░реНрдгрди рдХрд░рддреЗ рд╣реИрдВ:
рдЕрдм рд╣рдо Sequelize рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдХреНрд╡реЗрд░реА рдХрд╛ рдирд┐рд░реНрдорд╛рдг рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдФрд░ рдПрдХ рд╕реАрд░рд┐рдпрд▓рд╛рдЗрдЬреНрдб рдСрдмреНрдЬреЗрдХреНрдЯ рдХреЛ рд╡рд╛рдкрд╕ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдЬреЛ рдХрд┐ рдКрдкрд░ рд╡рд░реНрдгрд┐рдд рд╡рд┐рдирд┐рд░реНрджреЗрд╢ рд╕реЗ рдмрд┐рд▓реНрдХреБрд▓ рдореЗрд▓ рдЦрд╛рддрд╛ рд╣реИ:
import Router from 'koa-router'; import serialize from 'sequelize-serialize'; import { schemas } from './schemas'; const router = new Router(); router.get('/blog/users', async (ctx) => { const users = await User.findAll({ include: [{ association: User.posts, required: true, include: [Post.comments] }] }); ctx.body = serialize(users, schemas.UserWithPosts); });
рдпрд╣ рд▓рдЧрднрдЧ рдЬрд╛рджреВ рд╣реИ, рд╣реИ рдирд╛?
4. рд╕реНрдЯреЗрдЯрд┐рдХ рдЯрд╛рдЗрдкрд┐рдВрдЧ
рдпрджрд┐ рдЖрдк рдЗрддрдиреЗ рд╢рд╛рдВрдд рд╣реИрдВ рдХрд┐ рдЖрдк рдЯрд╛рдЗрдкрд╕реНрдХреНрд░рд┐рдкреНрдЯ рдпрд╛ рдлреНрд▓реЛ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд░рд╣реЗ рд╣реИрдВ, рддреЛ рдЖрдк рдкрд╣рд▓реЗ рд╣реА рд╕реЛрдЪ рд╕рдХрддреЗ рд╣реИрдВ, "рдореЗрд░реЗ рдкреНрд░рд┐рдп рд╕реНрдерд┐рд░ рдкреНрд░рдХрд╛рд░реЛрдВ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдХреНрдпрд╛!" ред Sw2dts рдпрд╛ swagger -to-flowtype рдореЙрдбреНрдпреВрд▓ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реБрдП , рдЖрдк JSON рдпреЛрдЬрдирд╛рдУрдВ рдХреЗ рдЖрдзрд╛рд░ рдкрд░ рд╕рднреА рдЖрд╡рд╢реНрдпрдХ рдкрд░рд┐рднрд╛рд╖рд╛рдПрдБ рддреИрдпрд╛рд░ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдФрд░ рдЙрдирдХрд╛ рдЙрдкрдпреЛрдЧ рдкрд░реАрдХреНрд╖рдг, рдЗрдирдкреБрдЯ рдбреЗрдЯрд╛ рдФрд░ рдХреНрд░рдордмрджреНрдзрдХреЛрдВ рдХреЗ рд╕реНрдереИрддрд┐рдХ рдЯрд╛рдЗрдкрд┐рдВрдЧ рдХреЗ рд▓рд┐рдП рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред
tinyspec -j sw2dts ./swagger.json -o Api.d.ts --namespace Api
рдЕрдм рд╣рдо рдирд┐рдпрдВрддреНрд░рдХреЛрдВ рдореЗрдВ рдкреНрд░рдХрд╛рд░реЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ:
router.patch('/users/:id', async (ctx) => { // Specify type for request data object const userData: Api.UserUpdate = ctx.request.body.user; // Run spec validation await validate(schemas.UserUpdate, userData); // Query the database const user = await User.findById(ctx.params.id); await user.update(userData); // Return serialized result const serialized: Api.User = serialize(user, schemas.User); ctx.body = { user: serialized }; });
рдФрд░ рдкрд░реАрдХреНрд╖рдгреЛрдВ рдореЗрдВ:
it('Update user', async () => { // Static check for test input data. const updateData: Api.UserUpdate = { name: MODIFIED }; const res = await request.patch('/users/1', { user: updateData }); // Type helper for request response: const user: Api.User = res.body.user; expect(user).to.be.validWithSchema(schemas.User); expect(user).to.containSubset(updateData); });
рдХреГрдкрдпрд╛ рдзреНрдпрд╛рди рджреЗрдВ рдХрд┐ рдЙрддреНрдкрдиреНрди рдкреНрд░рдХрд╛рд░ рдХреА рдкрд░рд┐рднрд╛рд╖рд╛рдУрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХреЗрд╡рд▓ рдПрдкреАрдЖрдИ рдкрд░рд┐рдпреЛрдЬрдирд╛ рдореЗрдВ рд╣реА рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ, рдмрд▓реНрдХрд┐ рдХреНрд▓рд╛рдЗрдВрдЯ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдкрд░рд┐рдпреЛрдЬрдирд╛рдУрдВ рдореЗрдВ рднреА рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ, рдЬрд┐рд╕рдореЗрдВ рдЙрди рдкреНрд░рдХрд╛рд░ рдХреЗ рдХрд╛рд░реНрдпреЛрдВ рдХрд╛ рд╡рд░реНрдгрди рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ рдЬрд┐рдирдореЗрдВ рдПрдкреАрдЖрдИ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИред рдХреЛрдгреАрдп рдЧреНрд░рд╛рд╣рдХ рдбреЗрд╡рд▓рдкрд░реНрд╕ рдЗрд╕ рдЙрдкрд╣рд╛рд░ рд╕реЗ рд╡рд┐рд╢реЗрд╖ рд░реВрдк рд╕реЗ рдкреНрд░рд╕рдиреНрди рд╣реЛрдВрдЧреЗред
5. рдХреНрд╡реЗрд░реА рд╕реНрдЯреНрд░рд┐рдВрдЧ рдХрд╛ рд░реВрдкрд╛рдВрддрд░рдг
рдпрджрд┐ рдХрд┐рд╕реА рдХрд╛рд░рдг рд╕реЗ рдЖрдкрдХрд╛ API MIME рдкреНрд░рдХрд╛рд░ рдХреЗ application/x-www-form-urlencoded
рд╕рд╛рде рдЕрдиреБрд░реЛрдз рд╕реНрд╡реАрдХрд╛рд░ рдХрд░рддрд╛ рд╣реИ рдФрд░ application/json
, рддреЛ рдЕрдиреБрд░реЛрдз рдирд┐рдХрд╛рдп рдЗрд╕ рддрд░рд╣ рджрд┐рдЦрд╛рдИ рджреЗрдЧрд╛:
param1=value¶m2=777¶m3=false
рд╡рд╣реА рдХреНрд╡реЗрд░реА рдорд╛рдкрджрдВрдбреЛрдВ рдкрд░ рд▓рд╛рдЧреВ рд╣реЛрддрд╛ рд╣реИ (рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, GET рдЕрдиреБрд░реЛрдзреЛрдВ рдореЗрдВ)ред рдЗрд╕ рдорд╛рдорд▓реЗ рдореЗрдВ, рд╡реЗрдм рд╕рд░реНрд╡рд░ рд╕реНрд╡рдЪрд╛рд▓рд┐рдд рд░реВрдк рд╕реЗ рдкреНрд░рдХрд╛рд░реЛрдВ рдХреЛ рдкрд╣рдЪрд╛рдирдиреЗ рдореЗрдВ рд╕рдХреНрд╖рдо рдирд╣реАрдВ рд╣реЛрдЧрд╛ - рд╕рд╛рд░рд╛ рдбреЗрдЯрд╛ рд╕реНрдЯреНрд░рд┐рдВрдЧреНрд╕ рдХреЗ рд░реВрдк рдореЗрдВ рд╣реЛрдЧрд╛ ( рдпрд╣рд╛рдВ qpm npm рдореЙрдбреНрдпреВрд▓ рд░рд┐рдкреЙрдЬрд┐рдЯрд░реА рдореЗрдВ рдПрдХ рдЪрд░реНрдЪрд╛ рд╣реИ), рдЗрд╕рд▓рд┐рдП рдкрд╛рд░реНрд╕ рдХрд░рдиреЗ рдХреЗ рдмрд╛рдж рдЖрдкрдХреЛ рдирд┐рдореНрди рдСрдмреНрдЬреЗрдХреНрдЯ рдорд┐рд▓реЗрдЧрд╛:
{ param1: 'value', param2: '777', param3: 'false' }
рдЗрд╕ рдорд╛рдорд▓реЗ рдореЗрдВ, рдпреЛрдЬрдирд╛ рдХреЗ рдЕрдиреБрд╕рд╛рд░ рдЕрдиреБрд░реЛрдз рдХреЛ рдорд╛рдиреНрдп рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛, рдЬрд┐рд╕рдХрд╛ рдЕрд░реНрде рд╣реИ рдХрд┐ рдореИрдиреНрдпреБрдЕрд▓ рд░реВрдк рд╕реЗ рд╕рддреНрдпрд╛рдкрд┐рдд рдХрд░рдирд╛ рдЖрд╡рд╢реНрдпрдХ рд╣реЛрдЧрд╛ рдХрд┐ рдкреНрд░рддреНрдпреЗрдХ рдкреИрд░рд╛рдореАрдЯрд░ рдХрд╛ рд╕рд╣реА рдкреНрд░рд╛рд░реВрдк рд╣реИ рдФрд░ рдЗрд╕реЗ рдЖрд╡рд╢реНрдпрдХ рдкреНрд░рдХрд╛рд░ рдкрд░ рд▓рд╛рдПрдВред
рдЬреИрд╕рд╛ рдХрд┐ рдЖрдк рдЕрдиреБрдорд╛рди рд▓рдЧрд╛ рд╕рдХрддреЗ рд╣реИрдВ, рдпрд╣ рд╣рдорд╛рд░реЗ рд╡рд┐рдирд┐рд░реНрджреЗрд╢ рд╕реЗ рд╕рднреА рд╕рдорд╛рди рдпреЛрдЬрдирд╛рдУрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред рдХрд▓реНрдкрдирд╛ рдХреАрдЬрд┐рдП рдХрд┐ рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдРрд╕рд╛ рд╕рдорд╛рдкрди рдмрд┐рдВрджреБ рдФрд░ рдпреЛрдЬрдирд╛ рд╣реИ:
рдЗрд╕ рддрд░рд╣ рдХреЗ рд╕рдорд╛рдкрди рдмрд┐рдВрджреБ рдХреЗ рд▓рд┐рдП рдЕрдиреБрд░реЛрдз рдХрд╛ рдПрдХ рдЙрджрд╛рд╣рд░рдг рдпрд╣рд╛рдВ рджрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ
GET /posts?search=needle&offset=10&limit=1&filter[isRead]=true
рдЖрдЗрдП рдПрдХ castQuery
рдлрд╝рдВрдХреНрд╢рди рд▓рд┐рдЦреЗрдВ, рдЬреЛ рд╕рднреА рдорд╛рдкрджрдВрдбреЛрдВ рдХреЛ рд╣рдорд╛рд░реЗ рд▓рд┐рдП рдЖрд╡рд╢реНрдпрдХ рдкреНрд░рдХрд╛рд░реЛрдВ рдореЗрдВ рдмрджрд▓ рджреЗрдЧрд╛ред рдпрд╣ рдХреБрдЫ рдЗрд╕ рддрд░рд╣ рджрд┐рдЦреЗрдЧрд╛:
function castQuery(query, schema) { _.mapValues(query, (value, key) => { const { type } = schema.properties[key] || {}; if (!value || !type) { return value; } switch (type) { case 'integer': return parseInt(value, 10); case 'number': return parseFloat(value); case 'boolean': return value !== 'false'; default: return value; } }); }
рдиреЗрд╕реНрдЯреЗрдб рд╕реНрдХреАрдореЛрдВ, рд╕рд░рдгрд┐рдпреЛрдВ рдФрд░ null
рдкреНрд░рдХрд╛рд░реЛрдВ рдХреЗ рд╕рдорд░реНрдерди рдХреЗ рд╕рд╛рде рдЗрд╕рдХрд╛ рдЕрдзрд┐рдХ рдкреВрд░реНрдг рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХрд╛рд╕реНрдЯ-рдХреЗ-рд╕реНрдХреАрдорд╛ (рдПрдирдкреАрдПрдо) рдореЗрдВ рдЙрдкрд▓рдмреНрдз рд╣реИред рдЕрдм рд╣рдо рдЗрд╕реЗ рдЕрдкрдиреЗ рдХреЛрдб рдореЗрдВ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ:
router.get('/posts', async (ctx) => {
рдзреНрдпрд╛рди рджреЗрдВ рдХрд┐ рд╕рдорд╛рдкрди рдмрд┐рдВрджреБ рдХреЛрдб рдХреА рдЪрд╛рд░ рдкрдВрдХреНрддрд┐рдпрд╛рдБ, рд╡рд┐рдирд┐рд░реНрджреЗрд╢рди рд╕реЗ рддреАрди рдЙрдкрдпреЛрдЧ рдпреЛрдЬрдирд╛рдПрдБред
рд╕рд░реНрд╡реЛрддреНрддрдо рдЕрднреНрдпрд╛рд╕
рдмрдирд╛рдиреЗ рдФрд░ рд╕рдВрд╢реЛрдзрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЕрд▓рдЧ-рдЕрд▓рдЧ рдпреЛрдЬрдирд╛рдПрдБ
рдЖрдорддреМрд░ рдкрд░, рд╕рд░реНрд╡рд░ рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдХрд╛ рд╡рд░реНрдгрди рдХрд░рдиреЗ рд╡рд╛рд▓реА рдпреЛрдЬрдирд╛рдПрдВ рдЙрди рд▓реЛрдЧреЛрдВ рд╕реЗ рднрд┐рдиреНрди рд╣реЛрддреА рд╣реИрдВ рдЬреЛ рдореЙрдбрд▓ рдмрдирд╛рдиреЗ рдФрд░ рд╕рдВрд╢реЛрдзрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЙрдкрдпреЛрдЧ рдХрд┐рдП рдЧрдП рдЗрдирдкреБрдЯ рдХрд╛ рд╡рд░реНрдгрди рдХрд░рддреЗ рд╣реИрдВред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, POST
рдФрд░ PATCH
рдЕрдиреБрд░реЛрдзреЛрдВ рдХреЗ рд▓рд┐рдП рдЙрдкрд▓рдмреНрдз рдХреНрд╖реЗрддреНрд░реЛрдВ рдХреА рд╕реВрдЪреА рдХреЛ рдХрдбрд╝рд╛рдИ рд╕реЗ рд╕реАрдорд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдП, рдЬрдмрдХрд┐ PATCH
рдЕрдиреБрд░реЛрдзреЛрдВ рдореЗрдВ, рдЖрдорддреМрд░ рдкрд░ рдпреЛрдЬрдирд╛ рдХреЗ рд╕рднреА рдХреНрд╖реЗрддреНрд░реЛрдВ рдХреЛ рд╡реИрдХрд▓реНрдкрд┐рдХ рдмрдирд╛рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рдЙрддреНрддрд░ рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХрд░рдиреЗ рд╡рд╛рд▓реА рдпреЛрдЬрдирд╛рдПрдБ рдЕрдзрд┐рдХ рдирд┐рдГрд╢реБрд▓реНрдХ рд╣реЛ рд╕рдХрддреА рд╣реИрдВред
Tinyspec CRUDL рдПрдВрдбрдкреЙрдЗрдВрдЯ рдХреА рд╕реНрд╡рдЪрд╛рд▓рд┐рдд рдкреАрдврд╝реА New
рдФрд░ Update
рдкреЛрд╕реНрдЯрдлрд┐рдХреНрд╕ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреА рд╣реИред User*
рдХреЛ рдЗрд╕ рдкреНрд░рдХрд╛рд░ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ:
User {id, email, name, isAdmin: b} UserNew !{email, name} UserUpdate !{email?, name?}
рдкреБрд░рд╛рдиреА рдпреЛрдЬрдирд╛рдУрдВ рдХреЗ рдкреБрди: рдЙрдкрдпреЛрдЧ рдпрд╛ рд╡рд┐рд░рд╛рд╕рдд рдХреЗ рдХрд╛рд░рдг рдЖрдХрд╕реНрдорд┐рдХ рд╕реБрд░рдХреНрд╖рд╛ рд╕рдорд╕реНрдпрд╛рдУрдВ рд╕реЗ рдмрдЪрдиреЗ рдХреЗ рд▓рд┐рдП рд╡рд┐рднрд┐рдиреНрди рдкреНрд░рдХрд╛рд░ рдХреЗ рдХрд╛рд░реНрдпреЛрдВ рдХреЗ рд▓рд┐рдП рд╕рдорд╛рди рдпреЛрдЬрдирд╛рдУрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рди рдХрд░рдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХрд░реЗрдВред
рд╕реНрдХреАрдорд╛ рдирд╛рдореЛрдВ рдореЗрдВ рд╢рдмреНрджрд╛рд░реНрде
рдПрдХ рд╣реА рдореЙрдбрд▓ рдХреА рд╕рд╛рдордЧреНрд░реА рдЕрд▓рдЧ-рдЕрд▓рдЧ рд╕рдорд╛рдкрди рдмрд┐рдВрджреБрдУрдВ рдореЗрдВ рднрд┐рдиреНрди рд╣реЛ рд╕рдХрддреА рд╣реИред рд╕реНрдХреАрдорд╛ рдирд╛рдореЛрдВ рдореЗрдВ рдкреЛрд╕реНрдЯ рдХреЗ With*
рдФрд░ For*
рдкреНрд░рдпреЛрдЧ рдХрд░реЗрдВ, рдпрд╣ рджрд┐рдЦрд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд┐ рд╡реЗ рдХреИрд╕реЗ рднрд┐рдиреНрди рд╣реИрдВ рдФрд░ рд╡реЗ рдХрд┐рд╕ рд▓рд┐рдП рд╣реИрдВред рдЯрд┐рдирд┐рд╕реЗрдк рдореЗрдВ рдореЙрдбрд▓ рдПрдХ рджреВрд╕рд░реЗ рд╕реЗ рд╡рд┐рд░рд╛рд╕рдд рдореЗрдВ рднреА рдорд┐рд▓ рд╕рдХрддреЗ рд╣реИрдВред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП:
User {name, surname} UserWithPhotos < User {photos: Photo[]} UserForAdmin < User {id, email, lastLoginAt: d}
рдЙрдкрд╕рд░реНрдЧ рд╡рд┐рд╡рд┐рдз рдФрд░ рд╕рдВрдпреБрдХреНрдд рд╣реЛ рд╕рдХрддреЗ рд╣реИрдВред рдореБрдЦреНрдп рдмрд╛рдд рдпрд╣ рд╣реИ рдХрд┐ рдЙрдирдХрд╛ рдирд╛рдо рд╕рд╛рд░ рдХреЛ рджрд░реНрд╢рд╛рддрд╛ рд╣реИ рдФрд░ рдкреНрд░рд▓реЗрдЦрди рдХреЗ рд╕рд╛рде рдкрд░рд┐рдЪрд┐рддрддрд╛ рдХреЛ рд╕рд░рд▓ рдХрд░рддрд╛ рд╣реИред
рдХреНрд▓рд╛рдЗрдВрдЯ рдкреНрд░рдХрд╛рд░ рджреНрд╡рд╛рд░рд╛ рдПрдВрдбрдкреЙрдЗрдВрдЯ рдХрд╛ рдкреГрдердХреНрдХрд░рдг
рдЕрдХреНрд╕рд░ рдПрдХ рд╣реА рдПрдВрдбрдкреЙрдЗрдВрдЯ рдЧреНрд░рд╛рд╣рдХ рдХреЗ рдкреНрд░рдХрд╛рд░ рдпрд╛ рдПрдВрдбрдкреЙрдЗрдВрдЯ рддрдХ рдкрд╣реБрдВрдЪрдиреЗ рд╡рд╛рд▓реЗ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХреА рднреВрдорд┐рдХрд╛ рдХреЗ рдЖрдзрд╛рд░ рдкрд░ рдЕрд▓рдЧ-рдЕрд▓рдЧ рдбреЗрдЯрд╛ рд▓реМрдЯрд╛рддреЗ рд╣реИрдВред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, GET /users
рдФрд░ GET /messages
рдХреЗ рд╕рдорд╛рдкрди рдмрд┐рдВрджреБ рдЖрдкрдХреЗ рдореЛрдмрд╛рдЗрд▓ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдХреЗ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛рдУрдВ рдФрд░ рдмреИрдХ рдСрдлрд┐рд╕ рдкреНрд░рдмрдВрдзрдХреЛрдВ рдХреЗ рд▓рд┐рдП рдмрд╣реБрдд рднрд┐рдиреНрди рд╣реЛ рд╕рдХрддреЗ рд╣реИрдВред рдПрдХ рд╣реА рд╕рдордп рдореЗрдВ, рд╕рдорд╛рдкрди рдмрд┐рдВрджреБ рдХрд╛ рдирд╛рдо рдмрджрд▓рдиреЗ рд╕реЗ рдмрд╣реБрдд рдЕрдзрд┐рдХ рдЬрдЯрд┐рд▓рддрд╛ рд╣реЛ рд╕рдХрддреА рд╣реИред
рдХрдИ рдмрд╛рд░ рдПрдХ рд╣реА рд╕рдорд╛рдкрди рдмрд┐рдВрджреБ рдХрд╛ рд╡рд░реНрдгрди рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдЖрдк рдкрде рдХреЗ рдмрд╛рдж рдЗрд╕рдХреЗ рдкреНрд░рдХрд╛рд░ рдХреЛрд╖реНрдардХ рдореЗрдВ рдЬреЛрдбрд╝ рд╕рдХрддреЗ рд╣реИрдВред рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рдЯреИрдЧ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ рдЙрдкрдпреЛрдЧреА рд╣реИ: рдпрд╣ рдЖрдкрдХреЗ рд╕рдорд╛рдкрди рдмрд┐рдВрджреБрдУрдВ рдХреЗ рдкреНрд░рд▓реЗрдЦрди рдХреЛ рд╕рдореВрд╣реЛрдВ рдореЗрдВ рд╡рд┐рднрд╛рдЬрд┐рдд рдХрд░рдиреЗ рдореЗрдВ рдорджрдж рдХрд░реЗрдЧрд╛, рдЬрд┐рдирдореЗрдВ рд╕реЗ рдкреНрд░рддреНрдпреЗрдХ рдХреЛ рдЖрдкрдХреЗ рдПрдкреАрдЖрдИ рдХреЗ рдЧреНрд░рд╛рд╣рдХреЛрдВ рдХреЗ рдПрдХ рд╡рд┐рд╢рд┐рд╖реНрдЯ рд╕рдореВрд╣ рдХреЗ рд▓рд┐рдП рдбрд┐рдЬрд╝рд╛рдЗрди рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП:
Mobile app: GET /users (mobile) => UserForMobile[] CRM admin panel: GET /users (admin) => UserForAdmin[]
рдЕрдиреНрдп рдПрдкреАрдЖрдИ рдкреНрд░рд▓реЗрдЦрди
рдПрдХ рдмрд╛рд░ рдЬрдм рдЖрдкрдХреЗ рдкрд╛рд╕ рдЯрд┐рдирд┐рд╕реЗрдк рдпрд╛ рдУрдкрдирдПрдкреАрдЖрдИ рдкреНрд░рд╛рд░реВрдк рдореЗрдВ рдПрдХ рд╡рд┐рдирд┐рд░реНрджреЗрд╢ рд╣реЛрддрд╛ рд╣реИ, рддреЛ рдЖрдк рдПрдЪрдЯреАрдПрдордПрд▓ рдореЗрдВ рд╕реБрдВрджрд░ рджрд╕реНрддрд╛рд╡реЗрдЬ рддреИрдпрд╛рд░ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдФрд░ рдЗрд╕реЗ рдЕрдкрдиреЗ рдПрдкреАрдЖрдИ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдбреЗрд╡рд▓рдкрд░реНрд╕ рдХреА рдЦреБрд╢реА рдХреЗ рд▓рд┐рдП рдкреНрд░рдХрд╛рд╢рд┐рдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред
рдкрд╣рд▓реЗ рдмрддрд╛рдИ рдЧрдИ рдХреНрд▓рд╛рдЙрдб рд╕реЗрд╡рд╛рдУрдВ рдХреЗ рдЕрд▓рд╛рд╡рд╛, CLI рдЙрдкрдХрд░рдг рд╣реИрдВ рдЬреЛ OpenAPI 2.0 рдХреЛ HTML рдФрд░ PDF рдореЗрдВ рдкрд░рд┐рд╡рд░реНрддрд┐рдд рдХрд░рддреЗ рд╣реИрдВ, рдЬрд┐рд╕рдХреЗ рдмрд╛рдж рдЖрдк рдЗрд╕реЗ рдХрд┐рд╕реА рднреА рд╕реНрдереИрддрд┐рдХ рд╣реЛрд╕реНрдЯрд┐рдВрдЧ рдореЗрдВ рдбрд╛рдЙрдирд▓реЛрдб рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рдЙрджрд╛рд╣рд░рдг:
рдХреНрдпрд╛ рдЖрдк рдФрд░ рдЙрджрд╛рд╣рд░рдг рдЬрд╛рдирддреЗ рд╣реИрдВ? рдЙрдиреНрд╣реЗрдВ рдЯрд┐рдкреНрдкрдгрд┐рдпреЛрдВ рдореЗрдВ рд╕рд╛рдЭрд╛ рдХрд░реЗрдВред
рджреБрд░реНрднрд╛рдЧреНрдп рд╕реЗ, OpenAPI 3.0, рдПрдХ рд╕рд╛рд▓ рдкрд╣рд▓реЗ рдЬрд╛рд░реА рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛, рдЕрднреА рднреА рдЦрд░рд╛рдм рд░реВрдк рд╕реЗ рд╕рдорд░реНрдерд┐рдд рд╣реИ, рдФрд░ рдореБрдЭреЗ рдЗрд╕рдХреЗ рдЖрдзрд╛рд░ рдкрд░ рдкреНрд░рд▓реЗрдЦрди рдХреЗ рдХрд┐рд╕реА рднреА рдпреЛрдЧреНрдп рдЙрджрд╛рд╣рд░рдг рдирд╣реАрдВ рдорд┐рд▓реЗ: рди рддреЛ рдХреНрд▓рд╛рдЙрдб рд╕рдорд╛рдзрд╛рдиреЛрдВ рдХреЗ рдмреАрдЪ, рди рд╣реА рд╕реАрдПрд▓рдЖрдИ рдЙрдкрдХрд░рдгреЛрдВ рдХреЗ рдмреАрдЪред рдЗрд╕реА рдХрд╛рд░рдг рд╕реЗ, OpenAPI 3.0 рдЕрднреА рддрдХ рдЯрд┐рдирд┐рд╕реЗрдк рдореЗрдВ рд╕рдорд░реНрдерд┐рдд рдирд╣реАрдВ рд╣реИред
GitHub рдкрд░ рдкреНрд░рдХрд╛рд╢рд┐рдд рдХрд░реЗрдВ
рдкреНрд░рд▓реЗрдЦрди рдкреНрд░рдХрд╛рд╢рд┐рдд рдХрд░рдиреЗ рдХрд╛ рд╕рдмрд╕реЗ рдЖрд╕рд╛рди рддрд░реАрдХрд╛ GitHub Pages рд╣реИ ред рдмрд╕ рдЕрдкрдиреА рд░рд┐рдкреЙрдЬрд┐рдЯрд░реА рд╕реЗрдЯрд┐рдВрдЧреНрд╕ рдореЗрдВ /docs
рдбрд╛рдпрд░реЗрдХреНрдЯрд░реА рдХреЗ рд▓рд┐рдП рд╕реНрдЯреИрдЯрд┐рдХ рдкреЗрдЬ рд╕рдкреЛрд░реНрдЯ рдХреЛ рд╕рдХреНрд╖рдо рдХрд░реЗрдВ рдФрд░ рдЗрд╕ рдлреЛрд▓реНрдбрд░ рдореЗрдВ HTML рдбреЙрдХреНрдпреВрдореЗрдВрдЯ рдХреЛ рд╕реНрдЯреЛрд░ рдХрд░реЗрдВред

рдЖрдк рд╕рдВрдХреБрд▓ рдореЗрдВ scripts
рдореЗрдВ tinyspec рдпрд╛ рдХрд┐рд╕реА рдЕрдиреНрдп CLI рдЯреВрд▓ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдкреНрд░рд▓реЗрдЦрди рдЙрддреНрдкрдиреНрди рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдХрдорд╛рдВрдб рдЬреЛрдбрд╝ рд╕рдХрддреЗ рд╣реИрдВред
"scripts": { "docs": "tinyspec -h -o docs/", "precommit": "npm run docs" }
рдирд┐рд░рдВрддрд░ рдПрдХреАрдХрд░рдг
рдЖрдк рдбреЙрдХреНрдпреВрдореЗрдВрдЯ рдЬрдирд░реЗрд╢рди рдХреЛ CI рдЪрдХреНрд░ рдореЗрдВ рд╢рд╛рдорд┐рд▓ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдФрд░ рдЗрд╕реЗ рдкреНрд░рдХрд╛рд╢рд┐рдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдЕрдореЗрдЬрди S3 рдореЗрдВ рдЖрдкрдХреЗ API рдХреЗ рд╡рд╛рддрд╛рд╡рд░рдг рдпрд╛ рд╕рдВрд╕реНрдХрд░рдг рдХреЗ рдЖрдзрд╛рд░ рдкрд░ рд╡рд┐рднрд┐рдиреНрди рдкрддреЛрдВ рдХреЗ рддрд╣рдд, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП: /docs/2.0
, /docs/stable
, /docs/staging
ред
рдЯрд┐рдирд┐рд╕реЗрдк рдореЗрдШ
рдпрджрд┐ рдЖрдкрдХреЛ рдЯрд┐рдирд┐рд╕реЗрдк рд╕рд┐рдВрдЯреИрдХреНрд╕ рдкрд╕рдВрдж рдЖрдпрд╛ рд╣реИ, рддреЛ рдЖрдк рдЯрд┐рдирд┐рд╕реЗрдкреЗрдХ.рдХреНрд▓рд╛рдЙрдб рдореЗрдВ рдПрдХ рд╢реБрд░реБрдЖрддреА рдЧреЛрдж рд▓реЗрдиреЗ рд╡рд╛рд▓реЗ рдХреЗ рд░реВрдк рдореЗрдВ рдкрдВрдЬреАрдХрд░рдг рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рд╣рдо рдЗрд╕рдХреЗ рдЖрдзрд╛рд░ рдкрд░ рдПрдХ рдХреНрд▓рд╛рдЙрдб рд╕реЗрд╡рд╛ рдФрд░ CLI рдХреЗ рдирд┐рд░реНрдорд╛рдг рдХреЗ рд▓рд┐рдП рдЬрд╛ рд░рд╣реЗ рд╣реИрдВ, рдЬреЛ рджрд╕реНрддрд╛рд╡реЗрдЬреЛрдВ рдХреЗ рдПрдХ рд╡рд┐рд╕реНрддреГрдд рдЪрдпрди рдФрд░ рдЕрдкрдиреЗ рд╕реНрд╡рдпрдВ рдХреЗ рдЯреЗрдореНрдкрд▓реЗрдЯреНрд╕ рдХреЛ рд╡рд┐рдХрд╕рд┐рдд рдХрд░рдиреЗ рдХреА рдХреНрд╖рдорддрд╛ рдХреЗ рд╕рд╛рде рдкреНрд░рд▓реЗрдЦрди рдХреЗ рд╕реНрд╡рдЪрд╛рд▓рд┐рдд рдкреНрд░рдХрд╛рд╢рди рдХреЗ рд▓рд┐рдП CLI рд╣реИред
рдирд┐рд╖реНрдХрд░реНрд╖
REST API рдХрд╛ рд╡рд┐рдХрд╛рд╕ рд╢рд╛рдпрдж рд╕рднреА рдХреА рд╕рдмрд╕реЗ рд╕реБрдЦрдж рдЧрддрд┐рд╡рд┐рдзрд┐ рд╣реИ рдЬреЛ рдЖрдзреБрдирд┐рдХ рд╡реЗрдм рдФрд░ рдореЛрдмрд╛рдЗрд▓ рд╕реЗрд╡рд╛рдУрдВ рдкрд░ рдХрд╛рдо рдХрд░рдиреЗ рдХреА рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдореЗрдВ рдореМрдЬреВрдж рд╣реИред рдмреНрд░рд╛рдЙрдЬрд╝рд░, рдСрдкрд░реЗрдЯрд┐рдВрдЧ рд╕рд┐рд╕реНрдЯрдо рдФрд░ рд╕реНрдХреНрд░реАрди рдЖрдХрд╛рд░ рдХрд╛ рдХреЛрдИ рдЪрд┐рдбрд╝рд┐рдпрд╛рдШрд░ рдирд╣реАрдВ рд╣реИ, рд╕рдм рдХреБрдЫ рдкреВрд░реА рддрд░рд╣ рд╕реЗ рд╣рдорд╛рд░реЗ рдирд┐рдпрдВрддреНрд░рдг рдореЗрдВ рд╣реИ - "рдЖрдкрдХреА рдЙрдВрдЧрд▓рд┐рдпреЛрдВ рдкрд░"ред
рд╡рд┐рднрд┐рдиреНрди рд╕реНрд╡рдЪрд╛рд▓рди рдХреЗ рд░реВрдк рдореЗрдВ рд╡рд░реНрддрдорд╛рди рд╡рд┐рдирд┐рд░реНрджреЗрд╢ рдФрд░ рдмреЛрдирд╕ рдмрдирд╛рдП рд░рдЦрдирд╛, рдЬреЛ рдПрдХ рд╣реА рд╕рдордп рдореЗрдВ рдкреНрд░рджрд╛рди рдХрд┐рдП рдЬрд╛рддреЗ рд╣реИрдВ, рдЗрд╕ рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдХреЛ рдФрд░ рднреА рд╕реБрдЦрдж рдмрдирд╛рддреЗ рд╣реИрдВред рдРрд╕рд╛ рдПрдкреАрдЖрдИ рд╕рдВрд░рдЪрд┐рдд, рдкрд╛рд░рджрд░реНрд╢реА рдФрд░ рд╡рд┐рд╢реНрд╡рд╕рдиреАрдп рд╣реЛ рдЬрд╛рддрд╛ рд╣реИред
рджрд░рдЕрд╕рд▓, рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ, рднрд▓реЗ рд╣реА рд╣рдо рдПрдХ рдорд┐рдердХ рдХреЗ рдирд┐рд░реНрдорд╛рдг рдореЗрдВ рд▓рдЧреЗ рд╣реЛрдВ, рдлрд┐рд░ рднреА рд╣рдо рдЗрд╕реЗ рд╕реБрдВрджрд░ рдХреНрдпреЛрдВ рдирд╣реАрдВ рдмрдирд╛рддреЗ?