{"id":457692,"date":"2025-04-28T03:22:59","date_gmt":"2025-04-28T03:22:59","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=457692"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=457692","title":{"rendered":"<span>Swift: \u0448\u0430\u0431\u043b\u043e\u043d\u043d\u044b\u0439 \u0431\u044d\u043a\u0435\u043d\u0434 \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c Vapor<\/span>"},"content":{"rendered":"<div><!--[--><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/93e\/b79\/f2e\/93eb79f2e11542f247ba7edebf0e445e.jpg\" width=\"1792\" height=\"1024\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/93e\/b79\/f2e\/93eb79f2e11542f247ba7edebf0e445e.jpg 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/93e\/b79\/f2e\/93eb79f2e11542f247ba7edebf0e445e.jpg 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<p>\u0412 \u043c\u043e\u0431\u0438\u043b\u044c\u043d\u0443\u044e \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0443 \u043f\u0440\u0438\u0445\u043e\u0434\u044f\u0442 \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u043c\u0438 \u043f\u0443\u0442\u044f\u043c\u0438. \u041d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0440\u043e\u0436\u0434\u0430\u044e\u0442\u0441\u044f \u0441 \u0434\u0435\u0432\u0430\u0439\u0441\u043e\u043c \u0432 \u0440\u0443\u043a\u0430\u0445, \u0434\u0440\u0443\u0433\u0438\u0445 \u0432\u0435\u0434\u0435\u0442 \u0438\u0437\u0432\u0438\u043b\u0438\u0441\u0442\u0430\u044f \u0434\u043e\u0440\u043e\u0433\u0430 \u0432\u0434\u043e\u043b\u044c \u0441\u0435\u0440\u0432\u0435\u0440\u043e\u0432, \u043c\u0430\u0439\u043d\u0444\u0440\u0435\u0439\u043c\u043e\u0432, \u0434\u0435\u0441\u0442\u043e\u043f\u043d\u044b\u0445 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439. \u041d\u043e\u00a0\u043a\u0430\u0436\u0434\u044b\u0439 \u043a\u0442\u043e \u0432\u00a0\u043d\u0435\u0435 \u043f\u043e\u043f\u0430\u0434\u0430\u0435\u0442 \u043e\u0449\u0443\u0449\u0430\u0435\u0442 \u0441\u0432\u043e\u044e \u043d\u0435\u0437\u0430\u0449\u0438\u0449\u0435\u043d\u043d\u043e\u0441\u0442\u044c \u0441\u00a0\u0442\u044b\u043b\u0430, \u0435\u0441\u043b\u0438 \u043d\u0435\u0442 \u043d\u0430\u0434\u0435\u0436\u043d\u043e\u0433\u043e \u043f\u0430\u0440\u0442\u043d\u0435\u0440\u0430 \u0432\u00a0\u043b\u0438\u0446\u0435 \u0431\u044d\u043a\u0435\u043d\u0434\u2011\u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0430. \u0418, \u0431\u0443\u043a\u0432\u0430\u043b\u044c\u043d\u043e, \u043a\u0430\u0436\u0434\u044b\u0439 \u043c\u043e\u0431\u0438\u043b\u044c\u0449\u0438\u043a \u043e\u0436\u0438\u0434\u0430\u0435\u0442, \u0447\u0442\u043e\u00a0\u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u0439 API \u0431\u0443\u0434\u0435\u0442 \u0433\u043e\u0442\u043e\u0432 \u0445\u043e\u0442\u044f\u00a0\u0431\u044b \u0437\u0430\u00a0\u043e\u0434\u0438\u043d \u0441\u043f\u0440\u0438\u043d\u0442, \u0434\u043e\u00a0\u0442\u043e\u0433\u043e, \u043a\u0430\u043a\u00a0\u0432\u00a0\u043d\u0435\u043c \u0432\u043e\u0437\u043d\u0438\u043a\u043d\u0435\u0442 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u044c. \u041a\u043e\u043d\u0435\u0447\u043d\u043e\u00a0\u0436\u0435, \u043c\u0438\u0440 IT \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0440\u0435\u0434\u043a\u043e \u0434\u043e\u043f\u0443\u0441\u043a\u0430\u0435\u0442 \u0442\u0430\u043a\u0443\u044e \u0440\u043e\u0441\u043a\u043e\u0448\u044c\u00a0\u2014 \u0437\u0430\u00a0\u043d\u0435\u0435 \u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0431\u043e\u0440\u043e\u0442\u044c\u0441\u044f \u0441\u00a0\u041f\u041c \u0438 \u0431\u0438\u0437\u043d\u0435\u0441\u2011\u0430\u043d\u0430\u043b\u0438\u0442\u0438\u043a\u043e\u043c. \u041a\u00a0\u0442\u043e\u043c\u0443\u00a0\u0436\u0435 \u043d\u0435\u00a0\u0440\u0435\u0434\u043a\u0438 \u0441\u0438\u0442\u0443\u0430\u0446\u0438\u0438, \u043a\u043e\u0433\u0434\u0430 \u0442\u043e, \u0447\u0442\u043e\u00a0\u0434\u043e\u043b\u0436\u043d\u043e\u00a0\u0431\u044b\u0442\u044c \u0441\u0434\u0435\u043b\u0430\u043d\u043e \u00ab\u043d\u0430 \u0432\u0447\u0435\u0440\u0430\u00bb, \u0431\u0443\u0434\u0435\u0442 \u0433\u043e\u0442\u043e\u0432\u043e \u00ab\u043d\u0430 \u043f\u043e\u0441\u043b\u0435\u0437\u0430\u0432\u0442\u0440\u0430\u00bb. \u0422\u0435 \u043a\u0442\u043e \u0438\u043c\u0435\u044e\u0442 \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u043e\u043f\u044b\u0442\u0430 \u043a\u0430\u043a\u00a0\u0432\u00a0\u043d\u0430\u0437\u0435\u043c\u043d\u043e\u043c, \u0442\u0430\u043a \u0438 \u043f\u043e\u0434\u0437\u0435\u043c\u043d\u043e\u043c \u043c\u0438\u0440\u0435\u00a0\u2014 \u0431\u0435\u0440\u0443\u0442 \u0438\u043d\u0438\u0446\u0438\u0430\u0442\u0438\u0432\u0443 \u0441\u00a0\u0441\u0432\u043e\u0438 \u0440\u0443\u043a\u0438, \u0438 \u0441\u0430\u043c\u0438 \u043f\u0440\u0435\u0434\u043b\u0430\u0433\u0430\u044e\u0442 \u043a\u043b\u0438\u0435\u043d\u0442\u2011\u0441\u0435\u0440\u0432\u0435\u0440\u043d\u044b\u0439 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441.<\/p>\n<p>\u0414\u043b\u044f\u00a0\u043c\u043e\u0431\u0438\u043b\u044c\u043d\u043e\u0433\u043e \u043c\u0438\u0440\u0430 C# \u0438 Java\u00a0\u2014 \u043f\u0430\u0434\u0435\u043d\u0438\u044f \u0438\u0437\u00a0\u0440\u0430\u044f \u0432\u00a0\u0430\u0434\u00a0\u2014 \u044d\u0442\u043e \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u0435\u0441\u0442\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0439 \u043f\u0440\u043e\u0446\u0435\u0441\u0441, \u043f\u043e\u0441\u043a\u043e\u043b\u044c\u043a\u0443 \u043f\u0440\u0438\u0441\u0443\u0449\u0438\u0435 \u0438\u043c \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u044b \u0438\u0437\u043d\u0430\u0447\u0430\u043b\u044c\u043d\u043e \u0446\u0435\u043b\u0438\u043b\u0438\u0441\u044c \u043d\u0430\u00a0\u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0443 \u0442<s>\u0435\u043c\u043d\u044b\u0445 \u0441\u0438\u043b<\/s> \u0431\u044d\u043a\u0435\u043d\u0434\u0430. \u0422\u043e\u00a0\u043b\u0438 \u0434\u0435\u043b\u043e Swift\u00a0\u2014 \u043f\u043e\u0437\u043d\u0430\u0432\u0448\u0435\u043c\u0443 \u043d\u0435\u0431\u043e\u00a0\u2014 \u043d\u0435\u00a0\u043b\u0435\u0433\u043a\u043e \u0434\u0430\u0435\u0442\u0441\u044f \u0436\u0438\u0437\u043d\u044c \u043d\u0430\u00a0\u043b\u044c\u0434\u0438\u043d\u0435, \u0432\u043c\u0435\u0441\u0442\u0435 \u0441\u00a0\u043b\u0430\u0441\u0442\u043e\u043d\u043e\u0433\u0438\u043c\u0438. <\/p>\n<p>\u041f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u043b\u0443\u0447\u0448\u0435\u0435 \u0438\u0437\u00a0\u043e\u0431\u043e\u0438\u0445 \u043c\u0438\u0440\u043e\u0432, \u0438 \u043d\u0435\u00a0\u043f\u043e\u0442\u0435\u0440\u044f\u0442\u044c \u0442\u0435\u043c\u043f \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u044e\u0442 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u044d\u043a\u0437\u043e\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u044f, \u043d\u0430\u043f\u043e\u0434\u043e\u0431\u0438\u0435 Perfect \u0438 Vapor. \u041e\u0434\u043d\u0430\u043a\u043e, \u043e\u043d\u0438 \u0432\u00a0\u0431\u043e\u043b\u044c\u0448\u0435\u0439 \u0441\u0442\u0435\u043f\u0435\u043d\u0438 \u043e\u0442\u0432\u0435\u0447\u0430\u044e\u0442 \u043d\u0430\u00a0\u0432\u043e\u043f\u0440\u043e\u0441 \u00ab\u041a\u0430\u043a?\u00bb \u0432\u043c\u0435\u0441\u0442\u043e \u0442\u043e\u0433\u043e, \u0447\u0442\u043e\u0431 \u043f\u0440\u0435\u0434\u043b\u043e\u0436\u0438\u0442\u044c \u043a\u0430\u043a\u043e\u0435\u2011\u043d\u0438\u0431\u0443\u0434\u044c \u0443\u0434\u043e\u0432\u043b\u0435\u0442\u0432\u043e\u0440\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0435 \u043c\u0438\u043d\u0438\u043c\u0430\u043b\u044c\u043d\u043e\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u0435. \u0421\u00a0\u0434\u0440\u0443\u0433\u043e\u0439 \u0441\u0442\u043e\u0440\u043e\u043d\u044b, \u043a\u0430\u043a\u00a0\u043f\u0440\u0430\u0432\u0438\u043b\u043e, \u0438\u0441\u0445\u043e\u0434\u043d\u044b\u0435 \u0442\u0440\u0435\u0431\u043e\u0432\u0430\u043d\u0438\u044f \u043c\u043e\u0431\u0438\u043b\u044c\u043d\u043e\u0439 \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u0443\u043c\u0435\u0440\u0435\u043d\u044b \u0438 \u0441\u0442\u0435\u0440\u0435\u043e\u0442\u0438\u043f\u043d\u044b \u043e\u0442\u00a0\u043e\u0434\u043d\u043e\u0433\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u043a\u00a0\u0434\u0440\u0443\u0433\u043e\u043c\u0443. \u041e\u0431\u044b\u0447\u043d\u043e \u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0430 \u0438 \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0442\u0430\u043a\u0438\u043c\u0438 \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u044f\u043c\u0438 \u043a\u0430\u043a\u00a0\u0430\u043a\u043a\u0430\u0443\u043d\u0442 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f, \u043f\u0440\u043e\u0444\u0438\u043b\u044c, \u043f\u0440\u043e\u0434\u0443\u043a\u0442 \u0438 \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f.<\/p>\n<p>\u0427\u0442\u043e\u0431 \u0440\u0435\u0448\u0438\u0442\u044c \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u044b\u0435 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u044b \u0431\u044b\u043b \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0430\u043d, \u0438 \u043e\u0431\u043a\u0430\u0442\u0430\u043d \u043d\u0430 AWS \u043f\u0440\u043e\u0435\u043a\u0442 REST API \u0441\u0435\u0440\u0432\u0435\u0440\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0432\u044b\u043a\u043b\u0430\u0434\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0432\u00a0\u043e\u0431\u0449\u0438\u0439 \u0434\u043e\u0441\u0442\u0443\u043f. \u0424\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u043d\u0435 \u043e\u0447\u0435\u043d\u044c \u0431\u043e\u043b\u044c\u0448\u0430\u044f, \u043d\u043e \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u0430\u044f \u0434\u043b\u044f \u0442\u043e\u0433\u043e, \u0447\u0442\u043e\u0431 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0438 \u043d\u0435 \u0432\u043b\u0430\u0434\u0435\u044e\u0449\u0438\u0435 \u0433\u043b\u0443\u0431\u043e\u043a\u043e \u043d\u0430\u0432\u044b\u043a\u0430\u043c\u0438 \u0441\u0435\u0440\u0432\u0435\u0440\u043d\u043e\u0439 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u043c\u043e\u0433\u043b\u0438 \u0441\u043e\u0431\u0440\u0430\u0442\u044c \u0438 \u0432\u044b\u043b\u043e\u0436\u0438\u0442\u044c \u0433\u043e\u0442\u043e\u0432\u043e\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u0435 \u0432 \u0432\u0438\u0434\u0435 Docker \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u0430, \u0430 \u043f\u0440\u0438 \u0436\u0435\u043b\u0430\u043d\u0438\u0438, \u0440\u0430\u0437\u0432\u0438\u0442\u044c \u043f\u0440\u043e\u0435\u043a\u0442 \u043f\u043e\u0434 \u0441\u0432\u043e\u0438 \u043d\u0443\u0436\u0434\u044b.<\/p>\n<p>\u0412 \u043d\u0430\u0441\u0442\u043e\u044f\u0449\u0435\u0435 \u0432\u0440\u0435\u043c\u044f, \u0441\u043e\u0431\u0440\u0430\u043d\u043d\u044b\u0439 \u0441\u0435\u0440\u0432\u0435\u0440, \u0440\u0435\u0448\u0430\u0435\u0442 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u0437\u0430\u0434\u0430\u0447\u0438:<\/p>\n<p>\u0410\u041a\u041a\u0410\u0423\u041d\u0422<\/p>\n<ul>\n<li>\n<p>\u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u0430\u043a\u043a\u0430\u0443\u043d\u0442\u0430 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u043f\u043e email \/ password<\/p>\n<\/li>\n<li>\n<p>Basic \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u043f\u043e email \/ password \u0438 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0435 bearer \u0442\u043e\u043a\u0435\u043d\u0430.<\/p>\n<\/li>\n<li>\n<p>\u041f\u0435\u0440\u0435\u0434\u0430\u0447\u0430 bearer \u0432 \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u0435 \u043e\u0442\u0432\u0435\u0442\u0430 \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u0438 \/ \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438.<\/p>\n<\/li>\n<li>\n<p>\u041d\u0435\u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0435 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435 \u043b\u043e\u0433\u0438\u043d\u0430 \u0438 \u043f\u0430\u0440\u043e\u043b\u044f.<\/p>\n<\/li>\n<li>\n<p>\u0412\u043e\u0441\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435 \u043f\u0430\u0440\u043e\u043b\u044f.<\/p>\n<\/li>\n<li>\n<p>Email \u0441 \u043f\u043e\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043d\u0438\u0435\u043c \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u044d\u043b\u0435\u043a\u0442\u0440\u043e\u043d\u043d\u043e\u0433\u043e \u0430\u0434\u0440\u0435\u0441\u0430.<\/p>\n<\/li>\n<li>\n<p>Email \u0441 \u043f\u043e\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043d\u0438\u0435\u043c \u0441\u0431\u0440\u043e\u0441\u0430 \u043f\u0430\u0440\u043e\u043b\u044f.<\/p>\n<\/li>\n<li>\n<p>\u0420\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u044f \u0438 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u044f \u0447\u0435\u0440\u0435\u0437 Apple.<\/p>\n<\/li>\n<li>\n<p>\u0420\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u044f \u0438 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u044f \u0447\u0435\u0440\u0435\u0437 Google.<\/p>\n<\/li>\n<li>\n<p>\u041c\u044f\u0433\u043a\u043e\u0435 \u0443\u0434\u0430\u043b\u0435\u043d\u0438\u0435 \u0430\u043a\u043a\u0430\u0443\u043d\u0442\u0430.<\/p>\n<\/li>\n<li>\n<p>\u0412\u043e\u0441\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435 \u0430\u043a\u043a\u0430\u0443\u043d\u0442\u0430 \u0432 \u0442\u0435\u0447\u0435\u043d\u0438\u0435 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u043e\u0433\u043e \u0441\u0440\u043e\u043a\u0430 (30 \u0434\u043d\u0435\u0439).<\/p>\n<\/li>\n<\/ul>\n<p>\u041f\u0420\u041e\u0424\u0418\u041b\u042c:<\/p>\n<ul>\n<li>\n<p>\u041f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0435 \u043f\u0440\u043e\u0444\u0438\u043b\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f.<\/p>\n<\/li>\n<li>\n<p>\u041e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435 \u043f\u0440\u043e\u0444\u0438\u043b\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f.<\/p>\n<\/li>\n<li>\n<p>\u041e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435 \u0430\u0432\u0430\u0442\u0430\u0440\u0430 \u0442\u0435\u043a\u0443\u0449\u0435\u0433\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f<\/p>\n<\/li>\n<li>\n<p>\u041f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0435 \u0430\u0432\u0430\u0442\u0430\u0440\u0430 \u0442\u0435\u043a\u0443\u0449\u0435\u0433\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f.<\/p>\n<\/li>\n<li>\n<p>\u041f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0435 \u0430\u0432\u0430\u0442\u0430\u0440\u0430 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u043b\u044c\u043d\u043e\u0433\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u043f\u043e ID \u0430\u0432\u0430\u0442\u0430\u0440\u0430.<\/p>\n<\/li>\n<li>\n<p>\u041f\u043e\u0438\u0441\u043a \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u0441 \u0443\u0447\u0435\u0442\u043e\u043c \u0443\u0440\u043e\u0432\u043d\u044f \u0434\u043e\u0441\u0442\u0443\u043f\u0430.<\/p>\n<\/li>\n<li>\n<p>\u0418\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0435 \u0440\u043e\u043b\u0438 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u043b\u044c\u043d\u043e\u0433\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u0441 \u0443\u0447\u0435\u0442\u043e\u043c \u0440\u043e\u043b\u0438 \u0442\u0435\u043a\u0443\u0449\u0435\u0433\u043e.<\/p>\n<\/li>\n<li>\n<p>\u041f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0435 \u043f\u0440\u043e\u0444\u0438\u043b\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u043f\u043e \u0435\u0433\u043e ID<\/p>\n<\/li>\n<\/ul>\n<p>\u041f\u0420\u041e\u0414\u0423\u041a\u0422\u042b:<\/p>\n<ul>\n<li>\n<p>\u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u043f\u0440\u043e\u0434\u0443\u043a\u0442\u0430 (\u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435, \u0432\u0435\u0441)<\/p>\n<\/li>\n<li>\n<p>\u041f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0435 \u0441\u043f\u0438\u0441\u043a\u0430 \u0442\u043e\u0432\u0430\u0440\u043e\u0432.<\/p>\n<\/li>\n<li>\n<p>\u041e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435 \u043f\u0440\u043e\u0434\u0443\u043a\u0442\u0430 \u043f\u043e ID \u0442\u043e\u0432\u0430\u0440\u0430.<\/p>\n<\/li>\n<li>\n<p>\u0423\u0434\u0430\u043b\u0435\u043d\u0438\u0435 \u043f\u0440\u043e\u0434\u0443\u043a\u0442\u0430.<\/p>\n<\/li>\n<\/ul>\n<p>\u0418\u0417\u041e\u0411\u0420\u0410\u0416\u0415\u041d\u0418\u042f:<\/p>\n<ul>\n<li>\n<p>\u0417\u0430\u0433\u0440\u0443\u0437\u043a\u0430 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u043b\u044c\u043d\u044b\u0445 \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440.<\/p>\n<\/li>\n<li>\n<p>\u041f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0435 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u043b\u044c\u043d\u044b\u0445 \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0439 \u043d\u0430 \u043a\u043b\u0438\u0435\u043d\u0442\u0435.<\/p>\n<\/li>\n<\/ul>\n<p>\u041d\u041e\u0422\u0418\u0424\u0418\u041a\u0410\u0426\u0418\u0418:<\/p>\n<ul>\n<li>\n<p>\u041e\u0442\u043f\u0440\u0430\u0432\u043a\u0430 \u041f\u0443\u0448-\u043d\u043e\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0439, \u0441 \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0435\u0439 title, subtitle, body, payload, \u0437\u0432\u0443\u043a\u0430 \u0438 badge.<\/p>\n<\/li>\n<li>\n<p>\u041f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0435 \u0441\u043f\u0438\u0441\u043a\u0430 \u0440\u0430\u043d\u0435\u0435 \u0441\u043e\u0437\u0434\u0430\u043d\u043d\u044b\u0445 \u043d\u043e\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0439.<\/p>\n<\/li>\n<li>\n<p>\u041e\u0442\u043c\u0435\u0442\u043a\u0430 \u043d\u043e\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 \u043a\u0430\u043a \u043f\u0440\u043e\u0447\u0438\u0442\u0430\u043d\u043d\u043e\u0439.<\/p>\n<\/li>\n<\/ul>\n<p>\u0418\u041d\u0424\u0420\u0410\u0421\u0422\u0420\u0423\u041a\u0422\u0423\u0420\u0410:<\/p>\n<ul>\n<li>\n<p>\u0418\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u044f \u043f\u043b\u0430\u0442\u0435\u0436\u043d\u043e\u0439 \u0441\u0438\u0441\u0442\u0435\u043c\u044b Stripe\u00a0<\/p>\n<\/li>\n<li>\n<p>\u041e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f API \u043f\u043e X-Token \u043f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u0435\u043c\u043e\u0433\u043e \u0432 \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u0430\u0445 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432.<\/p>\n<\/li>\n<li>\n<p>\u041e\u0431\u0441\u043b\u0443\u0436\u0438\u0432\u0430\u043d\u0438\u0435 \u0431\u0430\u0437\u044b, \u0432 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0435 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438.<\/p>\n<\/li>\n<li>\n<p>\u0414\u0430\u0442\u0430 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u0438 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u043a\u0430\u0436\u0434\u043e\u0439 \u0437\u0430\u043f\u0438\u0441\u0438.<\/p>\n<\/li>\n<\/ul>\n<p>\u0421\u0445\u0435\u043c\u0430 \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442 \u043e\u0442\u043d\u043e\u0448\u0435\u043d\u0438\u0435 \u043c\u0435\u0436\u0434\u0443 \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u044f\u043c\u0438 \u0431\u0430\u0437\u044b \u0434\u0430\u043d\u043d\u044b\u0445 (Postgresql)<\/p>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/c1b\/93a\/a55\/c1b93aa5577640376b9ba7c4e49a4145.jpg\" alt=\"\u0421\u0445\u0435\u043c\u0430 \u0411\u0414\" title=\"\u0421\u0445\u0435\u043c\u0430 \u0411\u0414\" width=\"942\" height=\"683\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/c1b\/93a\/a55\/c1b93aa5577640376b9ba7c4e49a4145.jpg 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/c1b\/93a\/a55\/c1b93aa5577640376b9ba7c4e49a4145.jpg 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption>\u0421\u0445\u0435\u043c\u0430 \u0411\u0414<\/figcaption><\/div>\n<\/figure>\n<p>\u041f\u0440\u043e\u0444\u0438\u043b\u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f\u00a0\u2014 \u043a\u043e\u0440\u043d\u0435\u0432\u043e\u0439 \u044d\u043b\u0435\u043c\u0435\u043d\u0442 \u0431\u0438\u043d\u0435\u0441\u2011\u043b\u043e\u0433\u0438\u043a\u0438. \u041a\u00a0\u043d\u0435\u043c\u0443 \u0432\u00a0\u0442\u043e\u0439 \u0438\u043b\u0438\u00a0\u0438\u043d\u043e\u0439 \u0441\u0442\u0435\u043f\u0435\u043d\u0438 \u043f\u043e\u0434\u0432\u044f\u0437\u0430\u043d\u044b \u0432\u0441\u0435 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u044b, \u0441\u0432\u044f\u0437\u0430\u043d\u043d\u044b\u0435 \u0441\u043e \u0441\u0442\u0430\u0440\u0442\u043e\u043c \u043c\u043e\u0431\u0438\u043b\u044c\u043d\u043e\u0433\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0438 \u043e\u043d\u0431\u043e\u0440\u0434\u0438\u043d\u0433\u043e\u043c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f. \u041e\u0434\u043d\u0430\u043a\u043e, \u043d\u0430\u00a0\u0441\u0445\u0435\u043c\u0435 \u0432\u0438\u0434\u043d\u043e, \u0447\u0442\u043e\u00a0\u0435\u0441\u0442\u044c \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0435 \u0440\u0430\u0437\u043b\u0438\u0447\u0438\u0435 \u0432\u00a0\u0442\u043e\u043c, \u043e\u0442\u043d\u043e\u0441\u044f\u0442\u0441\u044f\u00a0\u043b\u0438 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u043a\u00a0\u0441\u0444\u0435\u0440\u0435 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438, \u0438\u043b\u0438\u00a0\u043e\u0441\u043d\u043e\u0432\u043d\u043e\u0439 \u0440\u0430\u0431\u043e\u0442\u044b \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f. \u0422\u0430\u043a\u043e\u0435 \u0440\u0430\u0437\u0434\u0435\u043b\u0435\u043d\u0438\u0435 \u043f\u0440\u0435\u0434\u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u043e \u0434\u043b\u044f\u00a0\u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0435\u043d\u0438\u044f \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e\u0441\u0442\u0438 \u0434\u0430\u043d\u043d\u044b\u0445\u00a0\u2014 \u043f\u043e\u0441\u043b\u0435 \u043f\u0440\u043e\u0445\u043e\u0436\u0434\u0435\u043d\u0438\u044f \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u0445 \u043f\u0440\u043e\u0446\u0435\u0434\u0443\u0440 \u0432\u0435\u0440\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438\u00a0\u2014 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0441\u043e \u0441\u0432\u043e\u0438\u043c \u043f\u0440\u043e\u0444\u0438\u043b\u0435\u043c \u0438 \u043d\u0438\u043a\u0430\u043a \u043d\u0435\u00a0\u0441\u043e\u043f\u0440\u0438\u043a\u0430\u0441\u0430\u0435\u0442\u0441\u044f \u0441\u00a0\u043a\u0440\u0435\u0434\u0430\u043c\u0438.<\/p>\n<p>\u0421\u0435\u0440\u0432\u0435\u0440 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0430\u0442\u0441\u044f \u043e\u0434\u043d\u043e\u043c\u0443 \u0438 \u0442\u043e\u043c\u0443\u00a0\u0436\u0435 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044e \u0441\u00a0\u0440\u0430\u0437\u043d\u044b\u0445 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432 \u043e\u0434\u043d\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e. \u0412\u00a0\u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0442\u0435\u0441\u0442\u043e\u0432\u043e\u0433\u043e \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c\u0430\u00a0\u0431\u044b\u043b\u0430 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u0430 \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0430 \u043f\u0443\u0448\u2011\u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0439 \u0430\u043a\u0442\u0438\u0432\u043d\u043e\u0439 \u043a\u043b\u0438\u0435\u043d\u0442\u0441\u043a\u043e\u0439 \u0441\u0435\u0441\u0441\u0438\u0438. \u041a\u0430\u0436\u0434\u043e\u0435 \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0435 \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u0442\u0441\u044f \u0432\u00a0\u0431\u0430\u0437\u0435 \u0434\u0430\u043d\u043d\u044b\u0445, \u0438 \u043c\u043e\u0436\u0435\u0442\u00a0\u0431\u044b\u0442\u044c \u043f\u0440\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u043d\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u043c \u043f\u043e\u0432\u0442\u043e\u0440\u043d\u043e, \u043a\u0430\u043a\u00a0\u0432\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 \u0432\u00a0\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0438. \u0422\u0430\u043a\u0438\u043c\u00a0\u0436\u0435 \u043e\u0431\u0440\u0430\u0437\u043e\u043c \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u0441\u043f\u0438\u0441\u043e\u043a \u0437\u0430\u0433\u0440\u0443\u0436\u0435\u043d\u043d\u044b\u0445 \u043d\u0430\u00a0\u0441\u0435\u0440\u0432\u0435\u0440 \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0439.<\/p>\n<p>\u041e\u0434\u043d\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e \u0441\u00a0\u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u043e\u0439 \u0441\u0435\u0440\u0432\u0435\u0440\u0430, \u0432\u0435\u043b\u0430\u0441\u044c \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u0438 \u0431\u0430\u0437\u043e\u0432\u043e\u0433\u043e iOS \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f, \u0441\u00a0\u043a\u043e\u0442\u043e\u0440\u043e\u043c\u0443 \u043f\u0440\u0435\u0434\u044a\u044f\u0432\u043b\u044f\u043b\u0438\u0441\u044c \u0442\u0440\u0435\u0431\u043e\u0432\u0430\u043d\u0438\u0435 \u043f\u0440\u0438\u0441\u0443\u0449\u0438\u0435 Apple \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0435. \u0412\u00a0\u0447\u0430\u0441\u0442\u043d\u043e\u0441\u0442\u0438, \u0441\u0447\u0438\u0442\u0430\u0435\u0442\u0441\u044f \u043f\u0440\u0438\u0437\u043d\u0430\u043a\u043e\u043c \u0445\u043e\u0440\u043e\u0448\u0435\u0433\u043e \u0442\u043e\u043d\u0430 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0442\u044c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044e \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0447\u0435\u0440\u0435\u0437 \u0441\u043e\u0446\u0438\u0430\u043b\u044c\u043d\u044b\u0435 \u0441\u0435\u0442\u0438. \u041d\u043e\u00a0Apple \u0442\u0440\u0435\u0431\u0443\u0435\u0442, \u0447\u0442\u043e\u00a0\u0435\u0441\u043b\u0438 \u043f\u0440\u0438\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u043f\u0440\u043e\u0432\u0430\u0439\u0434\u0435\u0440 \u0441\u043e\u0446\u0438\u0430\u043b\u044c\u043d\u043e\u0439 \u0441\u0435\u0442\u0438, \u0442\u043e, \u0432\u00a0\u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u043c \u043f\u043e\u0440\u044f\u0434\u043a\u0435, \u0434\u043e\u043b\u0436\u043d\u0430\u00a0\u0431\u044b\u0442\u044c \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0430 \u0438 Apple \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u044f. \u041d\u043e, \u043a\u043e\u043d\u0435\u0447\u043d\u043e, \u043d\u0435\u043b\u044c\u0437\u044f \u0441\u0431\u0440\u0430\u0441\u044b\u0432\u0430\u0442\u044c \u0441\u043e \u0441\u0447\u0435\u0442\u043e\u0432\u00a0\u0436\u0435\u043b\u0430\u043d\u0438\u0435 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439 \u0437\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0447\u0435\u0440\u0435\u0437 \u0441\u0432\u043e\u0439\u00a0\u043b\u0438\u0447\u043d\u044b\u0439 email.<\/p>\n<p>\u041e\u0440\u0433\u0430\u043d\u0438\u0437\u0430\u0446\u0438\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u043f\u043e\u00a0\u0432\u043e\u0441\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044e \/ \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044e \u043f\u0430\u0440\u043e\u043b\u044f \u0441\u0434\u0435\u043b\u0430\u043d\u0430 \u0447\u0435\u0440\u0435\u0437 \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0443 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u0434\u0438\u043f\u043b\u0438\u043d\u043a\u043e\u0432\u00a0\u2014 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435, \u0432\u00a0\u043a\u043e\u0442\u043e\u0440\u043e\u043c \u043f\u0440\u0438\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u043e\u0434\u043d\u0430 \u0438\u0437\u00a0\u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0445 \u043a\u043e\u043c\u0430\u043d\u0434:<\/p>\n<ul>\n<li>\n<p>\u0412\u043e\u0441\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435 \u0430\u043a\u043a\u0430\u0443\u043d\u0442\u0430<\/p>\n<\/li>\n<li>\n<p>\u0421\u0431\u0440\u043e\u0441 \u043f\u0430\u0440\u043e\u043b\u044f<\/p>\n<\/li>\n<li>\n<p>\u041f\u043e\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043d\u0438\u0435<\/p>\n<\/li>\n<\/ul>\n<p>\u0412 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0438 \u0441\u0435\u0440\u0432\u0435\u0440\u0430 \u043f\u0440\u0438\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u043f\u043e \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0439 \u0447\u0435\u0440\u0435\u0437 SMTP \u0441\u0435\u0440\u0432\u0435\u0440. \u041d\u0430 \u044d\u0442\u0430\u043f\u0435 \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0442\u0430\u043a\u0438\u043c \u0441\u0435\u0440\u0432\u0435\u0440\u043e\u043c \u0432\u044b\u0441\u0442\u0443\u043f\u0430\u043b GMail, \u043d\u043e \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a \u0432\u043f\u0440\u0430\u0432\u0435 \u0438\u0437\u043c\u0435\u043d\u0438\u0442\u044c \u044d\u0442\u0443 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044e \u043d\u0430 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u043f\u043e\u0447\u0442\u043e\u0432\u043e\u0433\u043e \u0441\u0435\u0440\u0432\u0435\u0440\u0430 \u0441\u0432\u043e\u0435\u0439 \u043a\u043e\u043c\u043f\u0430\u043d\u0438\u0438.<\/p>\n<p>\u0422\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c, \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u043e\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u0435 \u043a\u043e\u043c\u0430\u043d\u0434\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u044e\u0442 \u043c\u043e\u0431\u0438\u043b\u044c\u043d\u043e\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0438 \u043f\u0435\u0440\u0435\u0430\u0434\u0440\u0435\u0441\u043e\u0432\u044b\u0432\u0430\u044e\u0442 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u043d\u0430 \u043d\u0443\u0436\u043d\u044b\u0435 \u044d\u043a\u0440\u0430\u043d\u044b, \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0430\u043a\u043a\u0430\u0443\u043d\u0442\u043e\u043c.<\/p>\n<h3>\u0420\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f<\/h3>\n<h4>\u0418\u043c\u0435\u043d\u043e\u0432\u0430\u043d\u0438\u0435<\/h4>\n<p>\u041f\u0440\u043e\u0435\u043a\u0442 \u043d\u0430\u0437\u0432\u0430\u043d Hermes. \u0413\u0435\u0440\u043c\u0435\u0441, \u043e\u043d\u00a0\u0436\u0435 \u041c\u0435\u0440\u043a\u0443\u0440\u0438\u0439\u00a0\u2014 \u043f\u0435\u0440\u0432\u0430\u044f \u043e\u0442\u00a0\u0421\u043e\u043b\u043d\u0446\u0430 \u043f\u043b\u0430\u043d\u0435\u0442\u0430. \u041a\u0430\u043a\u00a0\u0438 \u0441\u0442\u0440\u0438\u0436 (Swift) \u0413\u0435\u0440\u043c\u0435\u0441 \u0441\u0438\u043c\u0432\u043e\u043b\u0438\u0437\u0438\u0440\u0443\u0435\u0442 \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u044c. \u0413\u0435\u0440\u043c\u0435\u0441\u00a0\u2014 \u043f\u043e\u043a\u0440\u043e\u0432\u0438\u0442\u0435\u043b\u044c \u0442\u043e\u0440\u0433\u043e\u0432\u043b\u0438 \u0438 \u0433\u0438\u0431\u043a\u043e\u0441\u0442\u0438. \u0410\u00a0\u043a\u0440\u043e\u043c\u0435 \u0442\u043e\u0433\u043e, \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0435\u0449\u0435 \u0438 \u043f\u0440\u043e\u0432\u043e\u0434\u043d\u0438\u043a\u043e\u043c \u043c\u0435\u0436\u0434\u0443 \u043f\u043e\u0434\u0437\u0435\u043c\u043d\u044b\u043c \u0438 \u043d\u0435\u0431\u0435\u0441\u043d\u044b\u043c \u043c\u0438\u0440\u043e\u043c. \u0412\u00a0\u043e\u0431\u0449\u0435\u043c, \u0430\u043b\u043b\u044e\u0437\u0438\u0439 \u043c\u043d\u043e\u0433\u043e. \u042d\u0442\u043e \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u0447\u0430\u0441\u0442\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0432\u00a0\u0438\u043c\u0435\u043d\u043e\u0432\u0430\u043d\u0438\u044f\u0445 \u0438 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044f\u0445 \u0441\u0435\u0440\u0432\u0435\u0440\u0430.<\/p>\n<h4>\u0421\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u043f\u0440\u043e\u0435\u043a\u0442\u0430<\/h4>\n<p>\u0412 \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u043c, \u0434\u043b\u044f \u0441\u0435\u0440\u0432\u0435\u0440\u043d\u043e\u0439 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438, XCode \u043d\u0435 \u043f\u0440\u0438\u043c\u0435\u043d\u044f\u0435\u0442\u0441\u044f. \u0421\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u0431\u043e\u043b\u044c\u0448\u0435 \u043d\u0430\u043f\u043e\u043c\u0438\u043d\u0430\u0435\u0442 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443 \u043f\u0440\u043e\u0435\u043a\u0442\u043e\u0432 \u043d\u0430 \u044f\u0437\u044b\u043a\u0430\u0445 Go, Rust, C++. \u0427\u0430\u0441\u0442\u0438\u0447\u043d\u043e \u044d\u0442\u043e \u043e\u0431\u0443\u0441\u043b\u043e\u0432\u043b\u0435\u043d\u043e \u0442\u0435\u043c, \u0447\u0442\u043e \u0432 \u044d\u0442\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u0443\u0434\u043e\u0431\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043d\u0435 \u043f\u043e\u043b\u043d\u043e\u0446\u0435\u043d\u043d\u044b\u0435 IDE, \u0430 \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440\u044b \u043a\u043e\u0434\u0430, \u0442\u0430\u043a\u0438\u0435 \u043a\u0430\u043a VSCode,\u00a0Sublime \u0438\u043b\u0438 Atom. \u0421\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0435\u043d\u043d\u043e, \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u0442\u0441\u044f \u0444\u0438\u0437\u0438\u0447\u0435\u0441\u043a\u043e\u0439 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u043e\u0439 \u043f\u0430\u043f\u043e\u043a\u00a0\u2014 \u0447\u0442\u043e\u0431 \u043d\u0430\u0447\u0430\u0442\u044c \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441 \u043f\u0440\u043e\u0435\u043a\u0442\u043e\u043c \u043d\u0443\u0436\u043d\u043e \u043d\u0435 \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c (\u043e\u0442\u043a\u0440\u044b\u0442\u044c) \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u044b\u0439 \u043f\u0440\u043e\u0435\u043a\u0442\u043d\u044b\u0439 \u0444\u0430\u0439\u043b, \u0430 \u043e\u0442\u043a\u0440\u044b\u0442\u044c \u0432 \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440\u0435 \u043a\u043e\u0440\u043d\u0435\u0432\u0443\u044e \u043f\u0430\u043f\u043a\u0443. \u0412 \u043d\u0430\u0448\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u043a\u0430\u0442\u0430\u043b\u043e\u0433 \u00abhermes\u00bb.<\/p>\n<p>\u041a\u043e\u0440\u043d\u0435\u0432\u0430\u044f \u043f\u0430\u043f\u043a\u0430 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u00a0<strong><u>\u043a\u0430\u0442\u0430\u043b\u043e\u0433\u0438<\/u><\/strong>\u00a0\u0438 \u0444\u0430\u0439\u043b\u044b:<\/p>\n<ul>\n<li>\n<p><strong><u>Public<\/u><\/strong>\u00a0\u2014 \u0432\u00a0\u043e\u0441\u043d\u043e\u0432\u043d\u043e\u043c, \u043f\u0443\u0441\u0442\u0430\u044f \u043f\u0430\u043f\u043a\u0430. \u041d\u043e\u00a0\u0432\u00a0\u043d\u0435\u0435 \u0437\u0430\u043f\u0438\u0441\u044b\u0432\u0430\u044e\u0442\u0441\u044f \u0441\u043a\u0440\u044b\u0442\u044b\u0435 \u0444\u0430\u0439\u043b\u044b \u0433\u0438\u0442\u0430.<\/p>\n<\/li>\n<li>\n<p><strong><u>Sources<\/u><\/strong>\u00a0\u2014 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0432\u0435\u0441\u044c \u0438\u0441\u0445\u043e\u0434\u043d\u044b\u0439 \u043a\u043e\u0434 \u043f\u0440\u043e\u0435\u043a\u0442\u0430<\/p>\n<\/li>\n<li>\n<p><strong><u>Tests<\/u><\/strong>\u00a0\u2014 \u0442\u0435\u0441\u0442\u044b, \u0434\u043b\u044f\u00a0\u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u0433\u043e \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f.<\/p>\n<\/li>\n<li>\n<p>docker\u2011compose.yml\u00a0\u2014 \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u0439 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438 \u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0430 \u0434\u043e\u043a\u0435\u0440 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u0430.<\/p>\n<\/li>\n<li>\n<p>Dockerfile\u00a0\u2014 \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u0439 \u0441\u0431\u043e\u0440\u043a\u0438 \u0434\u043e\u043a\u0435\u0440 \u043e\u0431\u0440\u0430\u0437\u0430.<\/p>\n<\/li>\n<li>\n<p>Package.resolved\u00a0\u2014 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0444\u043e\u0440\u043c\u0438\u0440\u0443\u0435\u043c\u044b\u0439 \u0444\u0430\u0439\u043b \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0435\u0439.<\/p>\n<\/li>\n<li>\n<p>Package.swift\u00a0\u2014 \u0444\u0430\u0439\u043b \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0438 \u0438 \u0438\u043c\u043f\u043e\u0440\u0442\u0430 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0435\u0439.<\/p>\n<\/li>\n<li>\n<p>AuthKey.p8\u00a0\u2014 \u044d\u0442\u043e\u0442 \u0444\u0430\u0439\u043b \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u0432 GitHub \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0438. \u0415\u0433\u043e \u0441\u043b\u0435\u0434\u0443\u0435\u0442 \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u043d\u0430\u00a0<a href=\"https:\/\/developer.apple.com\/account\/resources\/authkeys\/list\" rel=\"noopener noreferrer nofollow\">\u043f\u043e\u0440\u0442\u0430\u043b\u0435 Apple<\/a>\u00a0\u0438 \u0440\u0430\u0437\u043c\u0435\u0442\u0438\u0442\u044c \u0432 \u043a\u043e\u0440\u043d\u0435\u0432\u043e\u043c \u043a\u0430\u0442\u0430\u043b\u043e\u0433\u0435.\u00a0<\/p>\n<\/li>\n<\/ul>\n<p>\u0412 \u043e\u0442\u043b\u0438\u0447\u0438\u0435 \u043e\u0442 XCode \u2013 \u043c\u0435\u043d\u044f\u0442\u044c \u043c\u0435\u043d\u044f\u0442\u044c \u0430\u043b\u0444\u0430\u0432\u0438\u0442\u043d\u043e\u0435 \u0440\u0430\u0441\u043f\u043e\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0444\u0430\u0439\u043b\u043e\u0432 \u043d\u0435\u0434\u043e\u043f\u0443\u0441\u0442\u0438\u043c\u043e.<\/p>\n<p>\u041f\u0430\u043f\u043a\u0430\u00a0<strong><u>Sources<\/u> <\/strong>\u0438\u043c\u0435\u0435\u0442 \u0434\u0432\u0430 \u043a\u0430\u0442\u0430\u043b\u043e\u0433\u0430:<\/p>\n<ul>\n<li>\n<p><strong><u>App<\/u><\/strong> \u2014 \u0438\u0441\u0445\u043e\u0434\u043d\u044b\u0439 \u043a\u043e\u0434 \u043f\u0440\u043e\u0435\u043a\u0442\u0430.<\/p>\n<\/li>\n<li>\n<p><strong><u>Run<\/u><\/strong> \u2014 \u0444\u0430\u0439\u043b main.swift\u00a0\u2014 \u0434\u043b\u044f\u00a0\u0437\u0430\u043f\u0443\u0441\u043a\u0430 \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u0441\u0440\u0435\u0434\u0441\u0442\u0432\u0430\u043c\u0438 \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440\u0430\u00a0\u2014 \u0444\u0430\u0439\u043b main.swift \u0434\u043e\u043b\u0436\u0435\u043d\u00a0\u0431\u044b\u0442\u044c \u0432\u044b\u0431\u0440\u0430\u043d. \u0421\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0435\u043d\u043d\u043e, \u043e\u043d \u0432\u0441\u0435\u0433\u0434\u0430 \u0434\u043e\u043b\u0436\u0435\u043d \u043e\u0441\u0442\u0430\u0432\u0430\u0442\u044c\u0441\u044f \u0432 \u0448\u0430\u0433\u043e\u0432\u043e\u0439 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u043e\u0441\u0442\u0438.<\/p>\n<\/li>\n<\/ul>\n<p>\u0412 \u043f\u0430\u043f\u043a\u0435 App \u0440\u0430\u0441\u043f\u043e\u043b\u043e\u0436\u0435\u043d\u044b \u043e\u0441\u043d\u043e\u0432\u043d\u044b\u0435 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u043d\u044b\u0435 \u0435\u0434\u0438\u043d\u0438\u0446\u044b \u043f\u0440\u043e\u0435\u043a\u0442\u0430:<\/p>\n<ul>\n<li>\n<p>Classes\u00a0\u2014 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u0430\u044f \u043e\u0431\u0432\u044f\u0437\u043a\u0430 \u041e\u041e\u041f \u0431\u0438\u0437\u043d\u0435\u0441\u2011\u043b\u043e\u0433\u0438\u043a\u0438.<\/p>\n<\/li>\n<li>\n<p>Controllers\u00a0\u2014 \u043a\u043b\u0430\u0441\u0441\u044b, \u043d\u0435\u043f\u043e\u0441\u0440\u0435\u0434\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u044e\u0449\u0438\u0435 REST API.<\/p>\n<\/li>\n<li>\n<p>Extensions\u00a0\u2014 Swift \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f \u0434\u043b\u044f\u00a0\u043a\u043b\u0430\u0441\u0441\u043e\u0432 Date \u0438 String.<\/p>\n<\/li>\n<li>\n<p>Migrations\u00a0\u2014 \u0444\u0430\u0439\u043b \u0434\u0435\u043a\u043b\u0430\u0440\u0430\u0446\u0438\u0439, \u0434\u043b\u044f\u00a0\u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u0442\u0430\u0431\u043b\u0438\u0446 \u0440\u0435\u043b\u044f\u0446\u0438\u043e\u043d\u043d\u043e\u0439 \u0431\u0430\u0437\u044b \u0434\u0430\u043d\u043d\u044b\u0445 (\u043f\u0440\u0438\u0432\u0435\u0434\u0435\u043d\u043d\u044b\u0445 \u043d\u0430\u00a0\u0441\u0445\u0435\u043c\u0435 \u0432\u044b\u0448\u0435).<\/p>\n<\/li>\n<li>\n<p>Models\u00a0\u2014 \u043c\u043e\u0434\u0435\u043b\u0438 \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432 \u0434\u0430\u043d\u043d\u044b\u0445.<\/p>\n<\/li>\n<li>\n<p>Models\u2011ext\u00a0\u2014 Swift \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f \u0434\u043b\u044f \u043c\u043e\u0434\u0435\u043b\u0435\u0439.<\/p>\n<\/li>\n<\/ul>\n<h4>\u041a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0438<\/h4>\n<p><strong>Dockerfile<\/strong><\/p>\n<p>Dockerfile\u00a0\u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442 \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u0439 \u0441\u0431\u043e\u0440\u043a\u0438\u00a0Linux \u043e\u0431\u0440\u0430\u0437\u0430, \u0434\u043b\u044f \u0440\u0430\u0437\u043c\u0435\u0449\u0435\u043d\u0438\u044f \u0435\u0433\u043e \u0432 \u0432\u0438\u0434\u0435 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u0430 Docker. \u0412 \u043d\u0435\u043c \u043f\u0440\u0438\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u0443\u043a\u0430\u0437\u0430\u043d\u0438\u0435 \u043d\u0430 \u0432\u0435\u0440\u0441\u0438\u044e Swift \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d \u0434\u043b\u044f \u0441\u0431\u043e\u0440\u043a\u0438, \u0432\u0435\u0440\u0441\u0438\u044e \u044f\u0434\u0440\u0430 Linux, \u0430 \u0442\u0430\u043a \u0436\u0435 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0441\u044f \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u043f\u043e\u0440\u0442\u043e\u0432 \u0441\u0435\u0440\u0432\u0435\u0440\u0430 \u043d\u0430 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e\u043c \u0445\u043e\u0441\u0442\u0435. \u041f\u0440\u0438 \u0438\u0441\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0438 \u0444\u0430\u0439\u043b\u0430\u00a0AuthKey.p8\u0440\u0430\u0437\u043c\u0435\u0449\u0430\u0435\u0442\u0441\u044f \u0432 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e\u0439 \u043f\u0430\u043f\u043a\u0435 \u0431\u0438\u043d\u0430\u0440\u043d\u043e\u0433\u043e \u0444\u0430\u0439\u043b\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0430.<\/p>\n<details class=\"spoiler\">\n<summary>Dockerfile<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"bash\"># ================================ # Build image # ================================ FROM swift:5.7-jammy as build  # Install OS updates and, if needed, sqlite3 RUN export DEBIAN_FRONTEND=noninteractive DEBCONF_NONINTERACTIVE_SEEN=true \\     &amp;&amp; apt-get -q update \\     &amp;&amp; apt-get -q dist-upgrade -y\\     &amp;&amp; rm -rf \/var\/lib\/apt\/lists\/*  # Set up a build area WORKDIR \/build  # First just resolve dependencies. # This creates a cached layer that can be reused # as long as your Package.swift\/Package.resolved # files do not change. COPY .\/Package.* .\/ RUN swift package resolve  # Copy entire repo into container COPY . .  # Build everything, with optimizations RUN swift build -c release --static-swift-stdlib  # Switch to the staging area WORKDIR \/staging  # Copy main executable to staging area RUN cp \"$(swift build --package-path \/build -c release --show-bin-path)\/Run\" .\/  # Copy resources bundled by SPM to staging area RUN find -L \"$(swift build --package-path \/build -c release --show-bin-path)\/\" -regex '.*\\.resources$' -exec cp -Ra {} .\/ \\;  # Copy any resources from the public directory and views directory if the directories exist # Ensure that by default, neither the directory nor any of its contents are writable. RUN [ -d \/build\/Public ] &amp;&amp; { mv \/build\/Public .\/Public &amp;&amp; chmod -R a-w .\/Public; } || true RUN [ -d \/build\/Resources ] &amp;&amp; { mv \/build\/Resources .\/Resources &amp;&amp; chmod -R a-w .\/Resources; } || true  # ================================ # Run image # ================================ FROM ubuntu:jammy  # Make sure all system packages are up to date, and install only essential packages. RUN export DEBIAN_FRONTEND=noninteractive DEBCONF_NONINTERACTIVE_SEEN=true \\     &amp;&amp; apt-get -q update \\     &amp;&amp; apt-get -q dist-upgrade -y \\     &amp;&amp; apt-get -q install -y \\       ca-certificates \\       tzdata \\ # If your app or its dependencies import FoundationNetworking, also install `libcurl4`.       # libcurl4 \\ # If your app or its dependencies import FoundationXML, also install `libxml2`.       # libxml2 \\     &amp;&amp; rm -r \/var\/lib\/apt\/lists\/*  # Create a vapor user and group with \/app as its home directory RUN useradd --user-group --create-home --system --skel \/dev\/null --home-dir \/app vapor  # Switch to the new home directory WORKDIR \/app  # Create Storage RUN mkdir -p \/app\/storage\/avatars RUN mkdir -p \/app\/storage\/images RUN chmod a+w \/app\/storage\/avatars RUN chmod a+w \/app\/storage\/images  # Copy APNS to container COPY .\/AuthKey.p8 \/app  # Copy built executable and any staged resources from builder COPY --from=build --chown=vapor:vapor \/staging \/app  # Ensure all further commands run as the vapor user USER vapor:vapor  # Let Docker bind to port 8080 EXPOSE 8080  # Start the Vapor service when the image is run, default to listening on 8080 in production environment ENTRYPOINT [\".\/Run\"] CMD [\"serve\", \"--env\", \"production\", \"--hostname\", \"0.0.0.0\", \"--port\", \"8080\"] <\/code><\/pre>\n<\/div>\n<\/details>\n<p><strong>Docker-compose<\/strong><\/p>\n<details class=\"spoiler\">\n<summary>Docker-compose<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"bash\">version: '3.7'  x-shared_environment: &amp;shared_environment   LOG_LEVEL: ${LOG_LEVEL:-debug}   DATABASE_HOST: db   DATABASE_NAME: ${POSTGRES_DB:-hermes_database}   DATABASE_USERNAME: ${POSTGRES_USER:-hermes_username}   DATABASE_PASSWORD: ${POSTGRES_PASSWORD:-hermes_password}   STORAGE_AVATARS: storage\/avatars   STORAGE_IMAGES: storage\/images   SMTP_HOST: smtp.gmail.com   SMTP_PORT: 465   SMTP_AUTH: &lt;YOUR email on mail server&gt;   SMTP_PASS: &lt;YOUR password to your mail server&gt;     services:   db:     image: postgres:14-alpine     volumes:       - db_data:\/var\/lib\/postgresql\/data\/     environment:       POSTGRES_USER: ${POSTGRES_USER:-hermes_username}       POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-hermes_password}       POSTGRES_DB: ${POSTGRES_DB:-hermes_database}     ports:       - \"5432:5432\"     networks:         - hermes   app:     image: hermes:latest     build:       context: .     environment:       &lt;&lt;: *shared_environment     depends_on:       - db     ports:       - \"8080:8080\"     # user: '0' # uncomment to run as root for testing purposes even though Dockerfile defines 'vapor' user.     command: [\"serve\", \"--env\", \"production\", \"--hostname\", \"0.0.0.0\", \"--port\", \"8080\"]     volumes:       - ..\/storage\/avatars:\/app\/storage\/avatars       - ..\/storage\/images:\/app\/storage\/images     networks:         - hermes   migrate:     image: hermes:latest     build:       context: .     environment:       &lt;&lt;: *shared_environment     depends_on:       - db     command: [\"migrate\", \"--yes\"]     deploy:       replicas: 0   revert:     image: hermes:latest     build:       context: .     environment:       &lt;&lt;: *shared_environment     depends_on:       - db     command: [\"migrate\", \"--revert\", \"--yes\"]     deploy:       replicas: 0  #  mosquitto: #    image: eclipse-mosquitto:latest #    ports: #        - 1883:1883 #        - 8883:8883 #        - 9001:9001 #    volumes: #        - ..\/storage\/mosquitto\/data:\/mosquitto\/data #        - ..\/storage\/mosquitto\/log:\/mosquitto\/log #    networks: #        - hermes    mqtt:     image: demonsoft\/hermes_mqtt:v1     ports:         - 1883:1883         - 8883:8883         - 9001:9001     volumes:         - ..\/storage\/mosquitto\/data:\/mosquitto\/data         - ..\/storage\/mosquitto\/log:\/mosquitto\/log     networks:         - hermes  networks:     hermes:         name: hermes         driver: bridge   volumes:   storage:   db_data:<\/code><\/pre>\n<\/div>\n<\/details>\n<p>\u0421\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044e \u0441\u0442\u0430\u0440\u0442\u0430 \u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u0430, \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0449\u0438\u0439 \u0440\u0430\u043d\u0435\u0435 \u0441\u043a\u043e\u043c\u043f\u0438\u043b\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u043e\u0431\u0440\u0430\u0437. \u0417\u0434\u0435\u0441\u044c \u0434\u0430\u0435\u0442\u0441\u044f \u0443\u043a\u0430\u0437\u0430\u043d\u0438\u0435 \u043d\u0430 \u0440\u0430\u0437\u0432\u0435\u0440\u0442\u044b\u0432\u0430\u043d\u0438\u044f \u0441\u0435\u0440\u0432\u0435\u0440\u0430 \u0431\u0430\u0437\u044b \u0434\u0430\u043d\u043d\u044b\u0445, \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u0445 \u0442\u0430\u0431\u043b\u0438\u0446, \u043f\u043e\u0440\u0442\u043e\u0432 \u0438 \u043f\u0430\u0440\u043e\u043b\u0435\u0439. \u0412\u00a0\u0441\u0435\u043a\u0446\u0438\u0438 volumes \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u044e\u0442\u0441\u044f \u043f\u0443\u0442\u0438 \u0435 \u0444\u0430\u0439\u043b\u043e\u0432\u043e\u043c\u0443 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0443 \u0434\u043b\u044f\u00a0\u0440\u0430\u0437\u043c\u0435\u0449\u0435\u043d\u0438\u044f \u0444\u0430\u0439\u043b\u043e\u0432 \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0439 \u0438 \u0430\u0432\u0430\u0442\u0430\u0440\u043e\u0432 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f. \u041a\u0440\u043e\u043c\u0435 \u0442\u043e\u0433\u043e, \u043f\u043e\u0441\u043a\u043e\u043b\u044c\u043a\u0443 \u043c\u043e\u0431\u0438\u043b\u044c\u043d\u043e\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 \u0447\u0430\u0441\u0442 \u043c\u0435\u0436\u0434\u0443 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f\u043c\u0438, \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442\u0441\u044f \u0441\u0435\u0440\u0432\u0438\u0441 MQTT. \u041e\u0434\u043d\u0430\u043a\u043e, \u043e\u043d \u043d\u0435\u00a0\u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u043c \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u043c, \u0438 \u043c\u043e\u0436\u0435\u0442\u00a0\u0431\u044b\u0442\u044c \u0438\u0441\u043a\u043b\u044e\u0447\u0435\u043d (\u0437\u0430\u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0438\u0440\u043e\u0432\u0430\u043d) \u0432\u00a0\u044d\u0442\u043e\u043c \u0444\u0430\u0439\u043b\u0435.<\/p>\n<p>\u041e\u0431\u0440\u0430\u0442\u0438\u0442\u0435 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435 \u043d\u0430\u00a0\u0441\u0435\u043a\u0446\u0438\u044e x\u2011shared_environment. \u0412\u00a0\u043d\u0435\u0439 \u0437\u0430\u0434\u0430\u043d\u044b \u043e\u0447\u0435\u043d\u044c \u0432\u0430\u0436\u043d\u044b\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u0434\u043b\u044f\u00a0\u0441\u0442\u0430\u0440\u0442\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0430:<\/p>\n<p>\u041f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u0441\u00a0\u043f\u0440\u0435\u0444\u0438\u043a\u0441\u043e\u043c DATABASE_\u00a0\u2014 \u044d\u0442\u043e \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b, \u0441\u00a0\u043a\u043e\u0442\u043e\u0440\u044b\u043c\u0438 \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0430 \u043f\u0435\u0440\u0432\u0438\u0447\u043d\u0430\u044f \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044f \u0431\u0430\u0437\u044b \u0434\u0430\u043d\u043d\u044b\u0445. \u0418\u043c\u0435\u043d\u043d\u043e \u044d\u0442\u0438 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0431\u0443\u0434\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0447\u0442\u043e\u0431 \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0434\u043e\u0441\u0442\u0443\u043f \u043a\u0430\u043a\u00a0\u0438\u0437\u043d\u0443\u0442\u0440\u0438 \u0441\u0435\u0440\u0432\u0435\u0440\u0430 (hermes), \u0442\u0430\u043a \u0438 \u0438\u0437\u0432\u043d\u0435 \u043f\u0440\u0438\u00a0\u043f\u043e\u043c\u043e\u0449\u0438 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u043e\u0432 \u0440\u0430\u0431\u043e\u0442\u044b \u0441\u00a0\u0431\u0430\u0437\u043e\u0439 \u0434\u0430\u043d\u043d\u044b\u0445, \u043a\u00a0\u043f\u0440\u0438\u043c\u0435\u0440\u0443, DBeaver.<\/p>\n<p>\u041f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u0441\u00a0\u043f\u0440\u0435\u0444\u0438\u043a\u0441\u043e\u043c SMTP_\u00a0\u2014 \u044d\u0442\u043e \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u043f\u043e\u0447\u0442\u043e\u0432\u043e\u0433\u043e \u0441\u0435\u0440\u0432\u0435\u0440\u0430, \u043f\u0440\u0438\u00a0\u043f\u043e\u043c\u043e\u0449\u0438 \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044e \u0431\u0443\u0434\u0443\u0442 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c\u0441\u044f \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f. \u0415\u0441\u043b\u0438 \u043d\u0430\u0433\u0440\u0443\u0437\u043a\u0430 \u0431\u0443\u0434\u0435\u0442 \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u043e\u0439\u00a0\u2014 \u043c\u043e\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c GMail \u0434\u043b\u044f\u00a0\u044d\u0442\u0438\u0445 \u0446\u0435\u043b\u0435\u0439. \u041d\u043e\u00a0\u0432\u00a0\u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044e \u043d\u0443\u0436\u043d\u043e \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u043e\u043f\u0438\u0441\u0430\u0442\u044c email \u0441\u00a0\u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u0431\u0443\u0434\u0443\u0442 \u0443\u0445\u043e\u0434\u0438\u0442\u044c \u043f\u043e\u0447\u0442\u043e\u0432\u044b\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f \u0438 \u043f\u0430\u0440\u043e\u043b\u044c \u043e\u0442 \u043f\u043e\u0447\u0442\u043e\u0432\u043e\u0433\u043e \u044f\u0449\u0438\u043a\u0430 (\u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b\u00a0SMTP_AUTH\u00a0\u0438\u00a0SMTP_PASS).\u00a0SMTP_HOST\u00a0\u0438\u00a0SMTP_PORT \u0434\u043b\u044f GMail \u043c\u043e\u0436\u043d\u043e \u043e\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u043a\u0430\u043a \u0435\u0441\u0442\u044c.<\/p>\n<details class=\"spoiler\">\n<summary>configure.swift<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"swift\">import Fluent import FluentPostgresDriver import Vapor import Smtp import APNS import JWTKit  \/\/ configures your application public func configure(_ app: Application) throws {     \/\/ uncomment to serve files from \/Public folder     \/\/ app.middleware.use(FileMiddleware(publicDirectory: app.directory.publicDirectory))      app.databases.use(.postgres(         hostname: Environment.get(\"DATABASE_HOST\")      ?? \"localhost\",         port: Environment.get(\"DATABASE_PORT\").flatMap(Int.init(_:)) ?? PostgresConfiguration.ianaPortNumber,         username: Environment.get(\"DATABASE_USERNAME\")  ?? \"hermes_username\",         password: Environment.get(\"DATABASE_PASSWORD\")  ?? \"hermes_password\",         database: Environment.get(\"DATABASE_NAME\")      ?? \"hermes_database\"     ), as: .psql)      app.migrations.add(Profile.Migration())     app.migrations.add(User.Migration())     app.migrations.add(Product.Migration())     app.migrations.add(UserToken.Migration())     app.migrations.add(Confirmation.Migration())     app.migrations.add(Image.Migration())     app.migrations.add(PushToken.Migration())     app.migrations.add(Push.Migration())     try app.autoMigrate().wait()          \/\/ SMTP     let smtp_host = Environment.get(\"SMTP_HOST\")        ?? \"smtp.gmail.com\"     let smtp_port = Int(Environment.get(\"SMTP_PORT\")    ?? \"\") ?? 465     let smtp_auth = Environment.get(\"SMTP_AUTH\")        ?? \"&lt;YOUR email on mail server&gt;\"     let smtp_pass = Environment.get(\"SMTP_PASS\")        ?? \"&lt;YOUR password to your mail server&gt;\"     app.smtp.configuration.hostname     = smtp_host     app.smtp.configuration.port         = smtp_port     app.smtp.configuration.secure       = .ssl     app.smtp.configuration.signInMethod = .credentials(username: smtp_auth, password: smtp_pass)                                                                   \/\/ ONLY FOR PRODUCT - It restricts using API     \/\/ app.middleware.use(CerberusMiddleware())      \/\/ register routes     try routes(app)                    \/\/ THIS IS TEMPORARY CODE ---------------------------     \/\/    let fileMngr = FileManager.default     \/\/    let current = \"\\(fileMngr.currentDirectoryPath)\"     \/\/    print(\"[ PATH: ] \\(current)\")     \/\/    let files = try fileMngr.contentsOfDirectory(atPath:current)     \/\/    print(\"[ FILES: ] \\(files)\")     \/\/ THIS IS TEMPORARY CODE ---------------------------      \/\/ Configure APNS using JWT authentication.     app.apns.configuration = try .init(         authenticationMethod: .jwt(             key: .private(filePath: Constants.apnCertPath),             keyIdentifier: JWKIdentifier(string: Constants.keyIdentifier),             teamIdentifier: Constants.teamIdentifier         ),         topic: Constants.apnTopic,         environment: .sandbox     )          \/\/app.lifecycle.use(Storage()) } <\/code><\/pre>\n<\/div>\n<\/details>\n<p>\u0412 \u0444\u0430\u0439\u043b\u0435\u00a0configure.swift\u00a0\u0437\u0430\u0434\u0430\u043d\u044b \u0442\u0435 \u0436\u0435 \u0441\u0430\u043c\u044b\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0442\u0441\u044f \u0432\u00a0Docker-compose. \u0420\u0430\u0437\u0443\u043c\u0435\u0435\u0442\u0441\u044f, \u0432 \u0438\u0434\u0435\u0430\u043b\u0435 \u0431\u044b\u043b\u043e \u0431\u044b \u043b\u0443\u0447\u0448\u0435 \u0432\u044b\u043d\u0435\u0441\u0442\u0438 \u0438\u0445 \u0432 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 \u0444\u0430\u0439\u043b, \u043f\u0440\u0435\u0434\u0432\u0430\u0440\u0438\u0442\u0435\u043b\u044c\u043d\u043e, \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u043c\u044b\u0439 \u043f\u0440\u0438 \u0441\u0442\u0430\u0440\u0442\u0435 \u0431\u0438\u043d\u0430\u0440\u043d\u043e\u0433\u043e \u0444\u0430\u0439\u043b\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0430, \u0438 \u0438\u0441\u043a\u043b\u044e\u0447\u0435\u043d\u043d\u044b\u0439 \u0438\u0437 Git \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u044f.<\/p>\n<details class=\"spoiler\">\n<summary>Constants.swift<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"swift\">\/\/ \/\/  File.swift \/\/   \/\/ \/\/  Created by Dmitriy Soloshenko on 13.03.2023. \/\/  import Foundation import RoutingKit  struct Constants {     static let lifetime        = 30 \/\/ Lifetime of auth token. 30 days     static let lifetimePass    = Date.oneHour \/\/ Lifetime of change password. 1 hour     static let restoreAcc      = 30 \/\/ Duration that user can restore account after delete. 30 days     static let xTokenHeader    = \"X-Token\"     static let xTokenValue     = \"&lt;UUID&gt;\"     static let bcryptSalt      = \"&lt;ANY LONG STRING&gt;\"     static let xBearer         = \"Bearer\"     static let avatarStorage   = \"storage\/avatars\/\"     static let imageStorage    = \"storage\/images\/\"     static let avatarExtension = \".jpg\"     static let imageExtension  = \".jpg\"     static let minimalPassword = 8     static let iosAppName      = \"hermesApp\"      \/\/ MARK: - NETWORK     static let restRootGroup   = PathComponent(\"api\")     static let restVersion     = PathComponent(\"v.1\")          static let backEmail       = \"&lt;YOUR email&gt;\"     static let serviceName     = \"Hermes Core Server\"               \/\/ MARK: - APN     static let apnCertPath       = \"AuthKey.p8\"     static let keyIdentifier     = \"&lt;Key identifier&gt;\"     static let teamIdentifier    = \"&lt;Team identifier&gt;\"     static let apnTopic          = \"com.&lt;YOUR HOST&gt;.&lt;YOUR APP NAME&gt;\"           \/\/ MARK: - Deep links     static let restoreAccDL       = \":\/\/restore-acc\/\"     static let resetPassDL        = \":\/\/reset-password\/\"     static let confirmChangeDL    = \":\/\/confirm-change\/\"               \/\/ MARK: - STRIPE     static let stipePublicKey =     \"pk_test_&lt;STRIPE PUBLIC KEY&gt;\"     static let stipePrivateKey =     \"sk_test_&lt;STRIPE PRIVATE KEY&gt;\"      }<\/code><\/pre>\n<\/div>\n<\/details>\n<p>\u0421\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0442\u0441\u044f \u043a\u043e\u043d\u0441\u0442\u0430\u043d\u0442\u043d\u044b\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0438. \u041f\u0440\u0438 \u043f\u0440\u043e\u043c\u044b\u0448\u043b\u0435\u043d\u043d\u043e\u0439 \u044d\u043a\u0441\u043f\u043b\u0443\u0430\u0442\u0430\u0446\u0438\u0438 \u0441\u0435\u0440\u0432\u0435\u0440\u0430 \u0438\u0445 \u0442\u0430\u043a \u0436\u0435 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0432\u044b\u043d\u0435\u0441\u0442\u0438 \u0432 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 \u0444\u0430\u0439\u043b, \u043d\u0435\u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b\u0439 \u0432 Git \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435.<\/p>\n<ul>\n<li>\n<p>xToken\u00a0\u2014 \u043f\u0440\u0438\u043c\u0435\u043d\u044f\u0435\u0442\u0441\u044f \u0434\u043b\u044f\u00a0\u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439 \u043d\u0430\u00a0\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 API. \u0412\u00a0middleware \u0441\u043b\u043e\u0435 \u0441\u0435\u0440\u0432\u0435\u0440\u0430 \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u043d\u0430\u00a0\u043d\u0430\u043b\u0438\u0447\u0438\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f, \u0438 \u0435\u0441\u043b\u0438 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043d\u0435\u00a0\u0441\u043e\u0432\u043f\u0430\u0434\u0430\u0435\u0442, \u0442\u043e \u043a\u043b\u0438\u0435\u043d\u0442\u0441\u043a\u043e\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442 \u043e\u0442\u043a\u0430\u0437 \u0432\u00a0\u043e\u0431\u0441\u043b\u0443\u0436\u0438\u0432\u0430\u043d\u0438\u0438.<\/p>\n<\/li>\n<li>\n<p>xTokenHeader\u00a0\u2014 \u0438\u043c\u044f \u043f\u043e\u043b\u044f \u0434\u043b\u044f\u00a0\u0440\u0430\u0437\u043c\u0435\u0449\u0435\u043d\u0438\u044f \u0442\u043e\u043a\u0435\u043d\u0430.<\/p>\n<\/li>\n<li>\n<p>xTokenValue\u00a0\u2014 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0442\u043e\u043a\u0435\u043d\u0430 \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u0437\u043d\u0430\u0435\u0442 \u043b\u0435\u0433\u0430\u043b\u044c\u043d\u044b\u0439 \u043a\u043b\u0438\u0435\u043d\u0442, \u0438 \u043f\u0435\u0440\u0435\u0434\u0430\u0435\u0442 \u0432\u00a0\u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u0435 REST \u0437\u0430\u043f\u0440\u043e\u0441\u0430.<\/p>\n<\/li>\n<li>\n<p>bcryptSalt\u00a0\u2014 \u0441\u0442\u0440\u043e\u043a\u043e\u0432\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u043e\u0435 \u0432\u00a0\u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0441\u043e\u043b\u0438 \u0448\u0438\u0444\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0442\u043e\u043a\u0435\u043d\u043e\u0432 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438 \u0438 \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0438 Push \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0439.<\/p>\n<\/li>\n<li>\n<p>iosAppName\u00a0\u2014 \u0441\u0445\u0435\u043c\u0430 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f, \u0434\u043b\u044f\u00a0\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u0435\u0435 \u043f\u0440\u0438\u00a0\u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0438 DeepLinks.<\/p>\n<\/li>\n<li>\n<p>backEmail\u00a0\u2014 email\u00a0\u2014 \u0430\u0434\u0440\u0435\u0441 \u043e\u0442\u00a0\u0438\u043c\u0435\u043d\u0438 \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u0431\u0443\u0434\u0443\u0442 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c\u0441\u044f \u044d\u043b\u0435\u043a\u0442\u0440\u043e\u043d\u043d\u044b\u0435 \u043f\u0438\u0441\u044c\u043c\u0430.<\/p>\n<\/li>\n<\/ul>\n<p>\u041a\u043b\u044e\u0447\u0438 \u0434\u043b\u044f Push Notofocation Server<\/p>\n<ul>\n<li>\n<p>serviceName\u00a0\u2014 \u0438\u043c\u044f \u0441\u0435\u0440\u0432\u0438\u0441\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0432\u00a0\u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u0430\u0445 \u043f\u0438\u0441\u0435\u043c.<\/p>\n<\/li>\n<li>\n<p>apnCertPath\u00a0\u2014 \u0438\u043c\u044f \u0444\u0430\u0439\u043b\u0430, \u043f\u0440\u0438\u0432\u0430\u0442\u043d\u043e\u0433\u043e \u043a\u043b\u044e\u0447\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0434\u043b\u044f\u00a0\u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0438 Push \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0439.<\/p>\n<\/li>\n<li>\n<p>keyIdentifier\u00a0\u2014 \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0440\u0430\u0441\u043f\u043e\u043b\u043e\u0436\u0435\u043d \u043d\u0430\u00a0\u043f\u043e\u0440\u0442\u0430\u043b\u0435 Apple.<\/p>\n<\/li>\n<li>\n<p>teamIdentifier\u00a0\u2014 \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u043a\u0430\u0442\u043e\u0440 \u043a\u043e\u043c\u043f\u0430\u043d\u0438\u0438, \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u043f\u0440\u0438\u043d\u0430\u0434\u043b\u0435\u0436\u0438\u0442 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435, \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c\u043e\u0435 Push \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u044f.<\/p>\n<\/li>\n<li>\n<p>apnTopic\u00a0\u2014 \u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440, \u043a\u0430\u043a\u00a0\u043f\u0440\u0430\u0432\u0438\u043b\u043e, \u0441\u043e\u0432\u043f\u0430\u0434\u0430\u044e\u0449\u0438\u0439 \u0441\u00a0Bundle id iOS \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f.<\/p>\n<\/li>\n<\/ul>\n<p>\u041a\u043b\u044e\u0447\u0438 \u043f\u043b\u0430\u0442\u0435\u0436\u043d\u043e\u0439 \u0441\u0438\u0441\u0442\u0435\u043c\u044b Stripe \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c <a href=\"https:\/\/marketplace.stripe.com\/\" rel=\"noopener noreferrer nofollow\">\u043d\u0430\u00a0\u043e\u0444\u0438\u0446\u0438\u0430\u043b\u044c\u043d\u043e\u043c \u043f\u043e\u0440\u0442\u0430\u043b\u0435<\/a>.<\/p>\n<ul>\n<li>\n<p>stipePublicKey\u00a0\u2014 \u043f\u0443\u0431\u0438\u0447\u043d\u044b\u0439 \u043a\u043b\u044e\u0447.<\/p>\n<\/li>\n<li>\n<p>stipePrivateKey\u00a0\u2014 \u043f\u0440\u0438\u0432\u0430\u0442\u043d\u044b\u0439 \u043a\u043b\u044e\u0447.<\/p>\n<\/li>\n<\/ul>\n<p>\u041e\u0441\u0442\u0430\u043b\u044c\u043d\u044b\u0435 \u043a\u043b\u044e\u0447\u0438\u00a0\u2014 \u0441\u0430\u043c\u043e\u043e\u0447\u0435\u0432\u0438\u0434\u043d\u044b, \u0438 \u043d\u0435\u00a0\u0442\u0440\u0435\u0431\u0443\u044e\u0442 \u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u0435\u0432. \u041c\u043e\u0436\u043d\u043e \u043e\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u043a\u0430\u043a \u0435\u0441\u0442\u044c.<\/p>\n<h4>\u041c\u043e\u0434\u0435\u043b\u0438<\/h4>\n<p>\u041f\u043e \u0431\u043e\u043b\u044c\u0448\u043e\u043c\u0443 \u0441\u0447\u0435\u0442\u0443 \u043c\u043e\u0434\u0435\u043b\u0438 \u0434\u0435\u043b\u044f\u0442\u0441\u044f \u043d\u0430\u00a0\u0434\u0432\u0430 \u0442\u0438\u043f\u0430\u00a0\u2014 \u0432\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u044f\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0431\u0438\u0437\u043d\u0435\u0441\u2011\u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432, \u0438 Data Transfer Models (DTO)\u00a0\u2014 \u043c\u043e\u0434\u0435\u043b\u0438 \u043f\u0440\u0438\u00a0\u043f\u043e\u043c\u043e\u0449\u0438 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u043e\u0431\u043c\u0435\u043d \u0434\u0430\u043d\u043d\u044b\u043c\u0438 \u0432\u00a0Rest \u0437\u0430\u043f\u0440\u043e\u0441\u0430\u0445. \u0421\u043b\u0435\u0434\u0443\u0435\u0442 \u043e\u0431\u0440\u0430\u0442\u0438\u0442\u044c \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435 \u043d\u0430\u00a0\u0442\u043e, \u0447\u0442\u043e\u00a0\u044d\u0442\u0438 \u043c\u043e\u0434\u0435\u043b\u0438 \u0443\u043d\u0430\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u043d\u044b \u043e\u0442\u00a0\u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b\u043e\u0432 Model \u0438 Content \u0438 \u0438\u043c\u0435\u044e\u0442 \u0431\u043e\u043b\u044c\u0448\u043e\u0435 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u043e\u0432 \u043f\u0440\u0438\u00a0\u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0438 \u0441\u0432\u043e\u0438\u0445 \u043f\u043e\u043b\u0435\u0439. DTO \u0440\u0430\u0437\u043c\u0435\u0449\u0430\u0435\u0442\u0441\u044f \u0432\u00a0\u0432\u0438\u0434\u0435 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u044b Public \u0432\u043d\u0443\u0442\u0440\u0438 \u0431\u0438\u0437\u043d\u0435\u0441-\u043c\u043e\u0434\u0435\u043b\u0438.<\/p>\n<p>\u0420\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u043c\u043e\u0434\u0435\u043b\u0438\u00a0User\u00a0\u0438\u00a0Profile.<\/p>\n<details class=\"spoiler\">\n<summary>User.swift<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"swift\">import Fluent import Vapor  final class User: Model, Content {     static var schema: String = \"users\"      @ID                         var id: UUID?     @Field(key: \"email\")        var email: String     @Field(key: \"password\")     var password: String     @Field(key: \"social_id\")    var socialId: String?     @Parent(key: \"profile_id\")  var profile: Profile     @Timestamp(key: \"created_at\", on: .create)  var createdAt: Date?     @Timestamp(key: \"updated_at\", on: .update)  var updatedAt: Date?     @Timestamp(key: \"deleted_at\", on: .delete)  var deletedAt: Date?          init() {}          init(id: UUID? = nil,          email: String,          password: String,          socialId: String? = nil,          profile: Profile.IDValue) {         self.id           = id         self.email        = email         self.password     = password         self.socialId     = socialId         self.$profile.id  = profile     } }<\/code><\/pre>\n<\/div>\n<\/details>\n<details class=\"spoiler\">\n<summary>Profile.swift<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"swift\">import Fluent import Vapor  final class Profile: Model, Content {     enum Gender: String, Codable {         case unknown, male, female     }      static var schema: String = \"profiles\"      @ID(key: .id)              var id: UUID?     @Field(key: \"first_name\")  var first_name: String     @Field(key: \"last_name\")   var last_name: String     @Field(key: \"nickname\")    var nickname: String     @Enum(key: \"gender\")       var gender: Gender     @Field(key: \"age\")         var age: Int?     @Enum(key: \"role\")         var role: Role     @Field(key: \"avatar\")      var avatar: UUID?     @Timestamp(key: \"created_at\", on: .create)  var createdAt: Date?     @Timestamp(key: \"updated_at\", on: .update)  var updatedAt: Date?     @Timestamp(key: \"deleted_at\", on: .delete)  var deletedAt: Date?      init() {}          init(id: UUID = UUID(),          first_name: String = \"\",          last_name: String = \"\",          nickname: String = \"\",          gender: Gender = .unknown,          age: Int? = nil,          role: Role = .user,          avatar: UUID? = nil) {         self.id          = id         self.first_name  = first_name         self.last_name   = last_name         self.nickname    = nickname         self.gender      = gender         self.age         = age         self.role        = role         self.avatar      = avatar     }          struct Public: Content, Encodable, Hashable {         let id: UUID?         let first_name: String         let last_name: String         let nickname: String         let gender: Gender         let age: Int?         let role: Role?         let avatar: UUID?     } }<\/code><\/pre>\n<\/div>\n<\/details>\n<p>\u041f\u043e\u0441\u043b\u0435 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u044f \u043a\u043b\u0430\u0441\u0441\u0430 \u0441\u043b\u0435\u0434\u0443\u0435\u0442 \u0443\u043a\u0430\u0437\u0430\u043d\u0438\u0435 \u043d\u0430 \u0442\u043e, \u0438\u0437 \u043a\u0430\u043a\u043e\u0439 \u0442\u0430\u0431\u043b\u0438\u0446\u044b \u0431\u0430\u0437\u044b \u0434\u0430\u043d\u043d\u044b\u0445 \u0431\u0443\u0434\u0443\u0442 \u0438\u0437\u0432\u043b\u0435\u0447\u0435\u043d\u044b \u0437\u0430\u043f\u0438\u0441\u0438. \u042d\u0442\u0438 \u0436\u0435 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u044f \u0444\u0438\u0433\u0443\u0440\u0438\u0440\u0443\u044e\u0442 \u0432 \u0444\u0430\u0439\u043b\u0430\u0445\u00a0CreateUsers.swift \u0438 CreateProfiles.swift\u00a0\u2014 \u0432\u00a0\u044d\u0442\u0438\u0445 \u0444\u0430\u0439\u043b\u0430\u0445 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u044b \u043f\u0440\u0430\u0432\u0438\u043b\u0430 \u043c\u0438\u0433\u0440\u0430\u0446\u0438\u0438 (\u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u0442\u0430\u0431\u043b\u0438\u0446 \u0431\u0430\u0437 \u0434\u0430\u043d\u043d\u044b\u0445). \u041f\u0440\u0438\u0447\u0435\u043c, \u043c\u0438\u0433\u0440\u0430\u0446\u0438\u0438 \u044f\u0432\u043b\u044f\u044e\u0442\u0441\u044f Swift \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f\u043c\u0438 \u043c\u043e\u0434\u0435\u043b\u0435\u0439 \u0434\u0430\u043d\u043d\u044b\u0445.<\/p>\n<details class=\"spoiler\">\n<summary>\u041c\u0438\u0433\u0440\u0430\u0446\u0438\u044f Profile<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"swift\">import Fluent  extension Profile {     struct Migration: AsyncMigration {         func prepare(on database: Database) async throws {             try await database.schema(\"profiles\")                 .id()                 .field(\"first_name\",    .string, .required)                 .field(\"last_name\",     .string, .required)                 .field(\"nickname\",      .string, .required)                 .field(\"gender\",        .string, .required)                 .field(\"age\",           .int)                 .field(\"role\",          .string, .required)                 .field(\"avatar\",        .uuid)                 .field(\"created_at\",    .datetime)                 .field(\"updated_at\",    .datetime)                 .field(\"deleted_at\",    .datetime)                 .create()         }                  func revert(on database: Database) async throws {             try await database.schema(\"profiles\").delete()         }     } }<\/code><\/pre>\n<\/div>\n<\/details>\n<details class=\"spoiler\">\n<summary>\u041c\u0438\u0433\u0440\u0430\u0446\u0438\u044f User<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"swift\">import Fluent  extension User {     struct Migration: AsyncMigration {         func prepare(on database: Database) async throws {             try await database.schema(\"users\")                 .id()                 .field(\"email\",       .string, .required)                 .field(\"password\",    .string, .required)                 .field(\"social_id\",   .string)                 .field(\"profile_id\",  .uuid,   .required, .references(\"profiles\", \"id\"))                 .field(\"created_at\",  .datetime)                 .field(\"updated_at\",  .datetime)                 .field(\"deleted_at\",  .datetime)                 .unique(on: \"email\")                 .create()         }                  func revert(on database: Database) async throws {             try await database.schema(\"users\").delete()         }     } }<\/code><\/pre>\n<\/div>\n<\/details>\n<p>\u0410\u0442\u0440\u0438\u0431\u0443\u0442\u00a0@ID\u00a0\u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u0442, \u0447\u0442\u043e \u043f\u043e\u043b\u0435 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043f\u0435\u0440\u0432\u0438\u0447\u043d\u044b\u043c \u043a\u043b\u044e\u0447\u043e\u043c \u0442\u0430\u0431\u043b\u0438\u0446\u044b \u0431\u0430\u0437\u044b \u0434\u0430\u043d\u043d\u044b\u0445.<\/p>\n<p>\u0410\u0442\u0442\u0440\u0438\u0431\u0443\u0442\u00a0@Field\u00a0\u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u0443\u0435\u0442 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u043f\u043e\u043b\u044f \u0438\u0437 snake-case \u0441\u0442\u0438\u043b\u044f, \u0432 camel-case.<\/p>\n<p>\u0410\u0442\u0442\u0440\u0438\u0431\u0443\u0442\u00a0@Parent \u0441\u0432\u044f\u0437\u044b\u0432\u0430\u0435\u0442 \u043f\u043e\u043b\u0435\u00a0profile_id\u00a0\u0441 \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u043c Profile \u043f\u043e \u0435\u0433\u043e \u043f\u0435\u0440\u0432\u0438\u0447\u043d\u043e\u043c\u0443 \u043a\u043b\u044e\u0447\u0443.<\/p>\n<p>\u0410\u0442\u0442\u0440\u0438\u0431\u0443\u0442\u00a0@Timestamp \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u0442 \u0442\u0438\u043f \u043f\u043e\u043b\u044f, \u0430 \u0442\u0430\u043a \u0436\u0435 \u043f\u0440\u0430\u0432\u0438\u043b\u0430, \u0434\u043b\u044f \u0435\u0433\u043e \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u0433\u043e \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f (\u043f\u0440\u0438 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0438, \u0443\u0434\u0430\u043b\u0435\u043d\u0438\u0438 \u0438 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0438).<\/p>\n<p>\u0412 \u043c\u043e\u0434\u0435\u043b\u0438\u00a0Profile\u00a0\u0435\u0441\u0442\u044c \u043f\u0430\u0440\u0443 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u044b\u0445 \u043e\u0442\u043b\u0438\u0447\u0438\u0439,<\/p>\n<p>\u0410\u0442\u0442\u0440\u0438\u0431\u0443\u0442\u00a0@Enum\u00a0\u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0437\u0430\u0434\u0430\u0442\u044c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0438\u0437 \u043f\u0435\u0440\u0435\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u044f.<\/p>\n<p>\u0421\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u043e, DTO \u043e\u0431\u044a\u0435\u043a\u0442 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u044b\u0439 Public \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u043e\u0439. \u0418\u043c\u0435\u043d\u043d\u043e \u044d\u0442\u0438 \u043f\u043e\u043b\u044f \u0431\u0443\u0434\u0443\u0442 \u043f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u0442\u044c\u0441\u044f \u043f\u0440\u0438 \u043e\u0442\u0432\u0435\u0442\u0430\u0445 \u0441\u0435\u0440\u0432\u0435\u0440\u0430.<\/p>\n<h4>REST API<\/h4>\n<p>\u0412\u0441\u0435 REST \u0437\u0430\u043f\u0440\u043e\u0441\u044b \u043a \u0441\u0435\u0440\u0432\u0435\u0440\u0443 \u0444\u043e\u0440\u043c\u0438\u0440\u0443\u044e\u0442\u0441\u044f \u0432\u043e\u043a\u0440\u0443\u0433 CRUD \u043a\u043e\u043d\u0446\u0435\u043f\u0446\u0438\u0438 (Create, Read, Update, Delete), \u043a\u043e\u043d\u0435\u0447\u043d\u043e, \u0435\u0441\u043b\u0438 \u0432 \u043a\u0430\u043a\u0438\u0445-\u0442\u043e \u0438\u0437 \u044d\u0442\u0438\u0445 \u043a\u043e\u043c\u0430\u043d\u0434 \u0435\u0441\u0442\u044c \u0441\u043c\u044b\u0441\u043b. \u0421\u0435\u043c\u0435\u0439\u0441\u0442\u0432\u0430 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u043e\u0431\u044a\u0435\u0434\u0438\u043d\u0435\u043d\u044b \u0432 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u044b:\u00a0ProductController\u043e\u0442\u0432\u0435\u0447\u0430\u0435\u0442 \u0437\u0430 \u0431\u0438\u0437\u043d\u0435\u0441 \u043b\u043e\u0433\u0438\u043a\u0443 \u0440\u0430\u0431\u043e\u0442\u044b \u043c\u043e\u0434\u0435\u043b\u044c\u044e \u043f\u0440\u043e\u0434\u0443\u043a\u0442\u043e\u0432.<\/p>\n<p>\u041a\u0430\u0436\u0434\u044b\u0439 \u043a\u043b\u0430\u0441\u0441 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u0430 \u0443\u043d\u0430\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u043d \u043e\u0442\u00a0RouteCollection, \u0438 \u0434\u043e\u043b\u0436\u0435\u043d \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0442\u044c \u043c\u0435\u0442\u043e\u0434 boot, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u044b \u0432\u0441\u0435 \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u0441\u0435\u043c\u0435\u0439\u0441\u0442\u0432\u0430.\u00a0<\/p>\n<details class=\"spoiler\">\n<summary>\u041f\u0440\u0438\u043c\u0435\u0440 CRUD \u0434\u043b\u044f Product<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"swift\">import Fluent import Vapor  struct ProductController: RouteCollection {     func boot(routes: RoutesBuilder) throws {         let products = routes.root.grouped(\"products\")          let protected = products.grouped(UserToken.authenticator())         protected.get(use: index)         protected.post(use: create)         protected.put(\":id\", use: update)         protected.delete(\":id\", use: delete)     }          func index(req: Request) async throws -&gt; Response {         try await Profile.auth(req)         let products =  try await Product.query(on: req.db).all()         return Response.success(products)     }          func create(req: Request) async throws -&gt; Response {         try await Profile.auth(req)         guard let product = try? req.content.decode(Product.self) else {             return Response.fail(Mistakes.iAmTeapot)         }         try await product.save(on: req.db)         return Response.success(product)     }      func update(req: Request) async throws -&gt; Response {         try await Profile.auth(req)         guard let product = try await Product.find(req.parameters.get(\"id\"), on: req.db) else {             return Response.fail(Mistakes.idNotFound)         }                  let updated      = try req.content.decode(Product.self)         product.name     = updated.name         product.weight   = updated.weight         product.price    = updated.price         product.currency = product.currency         try await product.save(on: req.db)                  return Response.success(product)     }          func delete(req: Request) async throws -&gt; Response {         try await Profile.auth(req)         guard let product = try await Product.find(req.parameters.get(\"id\"), on: req.db) else {             return Response.fail(Mistakes.productCannotDelete)         }         try await product.delete(on: req.db)         return Response.success(\"OK\")     } } <\/code><\/pre>\n<\/div>\n<\/details>\n<p>\u0412 \u043f\u0440\u0438\u043c\u0435\u0440\u0435 \u043f\u043e\u043a\u0430\u0437\u0430\u043d\u043e \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0435 GET, POST, PUT \u0438 DELETE \u043a\u043e\u043c\u0430\u043d\u0434 \u0434\u043b\u044f \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u0432 \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u0438 products. \u0412\u0441\u0435 \u0447\u0435\u0442\u044b\u0440\u0435 \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u0437\u0430\u0449\u0438\u0449\u0435\u043d\u044b \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u043e\u043d\u043d\u044b\u043c \u0442\u043e\u043a\u0435\u043d\u043e\u043c. \u0422. \u0435. \u0431\u0435\u0437 \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0438 \u0432\u0430\u043b\u0438\u0434\u043d\u043e\u0433\u043e \u0442\u043e\u043a\u0435\u043d\u0430 \u043a\u043b\u0438\u0435\u043d\u0442\u0441\u043a\u043e\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0431\u0443\u0434\u0435\u0442 \u043f\u043e\u043b\u0443\u0447\u0430\u0442\u044c \u043e\u0442\u043b\u0443\u043f.<\/p>\n<p>Middlewares<\/p>\n<p>\u0412\u00a0\u043a\u043e\u0434\u0435 \u0441\u0435\u0440\u0432\u0435\u0440\u0430 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d \u0432\u044b\u0437\u043e\u0432 \u0434\u0432\u0443\u0445 middlewares\u00a0\u2014 Cerberus \u0438 Roles.<\/p>\n<p>Cerberus \u043f\u0440\u0435\u0434\u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d \u0434\u043b\u044f \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 xToken \u0434\u043b\u044f \u0432\u0441\u0435\u0445 \u0432\u044b\u0437\u043e\u0432\u043e\u0432 \u0441\u0435\u0440\u0432\u0435\u0440\u0430. \u0415\u0433\u043e \u0430\u043a\u0442\u0438\u0432\u0430\u0446\u0438\u044f \u043f\u0440\u043e\u0438\u0445\u0432\u043e\u0434\u0438\u0442\u0441\u044f \u0432 \u0444\u0430\u0439\u043b\u0435 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0438. \u0410\u043a\u0442\u0438\u0432\u0430\u0446\u0438\u044f \u0437\u0430\u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0430, \u043f\u043e\u0441\u043a\u043e\u043b\u044c\u043a\u0443 \u043d\u0430 \u0441\u0442\u0430\u0434\u0438\u0438 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438, \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 xToken \u043d\u0430 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e\u0439 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0435 \u043d\u0435 \u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f. \u041f\u0435\u0440\u0435\u0434 \u043f\u0443\u0431\u043b\u0438\u043a\u0430\u0446\u0438\u0435\u0439 \u043d\u0430 \u0440\u0430\u0431\u043e\u0447\u0435\u043c \u0441\u0435\u0440\u0432\u0435\u0440\u0435 \u0430\u043a\u0442\u0438\u0432\u0430\u0446\u0438\u044e \u0441\u043b\u0435\u0434\u0443\u0435\u0442 \u0440\u0430\u0441\u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c, \u0438\u043b\u0438 \u043a\u0430\u043a \u0432\u0430\u0440\u0438\u0430\u043d\u0442, \u0432\u043e \u0432\u0441\u0435 \u0442\u0435\u0441\u0442\u043e\u0432\u044b\u0435 \u0437\u0430\u043f\u0440\u043e\u0441\u044b \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0442\u044c \u0432\u0430\u043b\u0438\u0434\u043d\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 xToken.<\/p>\n<details class=\"spoiler\">\n<summary>CerberusMiddleware<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"swift\">import Vapor import Fluent  final class CerberusMiddleware: AsyncMiddleware {     func respond(to request: Request, chainingTo next: AsyncResponder) async throws -&gt; Response {         guard request.headers.contains(name: Constants.xTokenHeader),               let value = request.headers[Constants.xTokenHeader].first,               value == Constants.xTokenValue         else { throw self.exception(request) }                  return try await next.respond(to: request)     }          private func exception(_ request: Request) -&gt; Abort {         let errorResponse = Response(status: .forbidden)         let message = \"This API isn't accessible for public using.\"         errorResponse.body = .init(string: message)         return Abort(.badRequest, reason: message)     } } <\/code><\/pre>\n<\/div>\n<\/details>\n<details class=\"spoiler\">\n<summary>RolesMiddleware<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"swift\">import Vapor import Fluent  final class RolesMiddleware: AsyncMiddleware {     func respond(to request: Request, chainingTo next: AsyncResponder) async throws -&gt; Response {         let profile = try await request.me()         guard profile.role.available(.manager) else {             throw Abort (.forbidden)         }                  return try await next.respond(to: request)     } }<\/code><\/pre>\n<\/div>\n<\/details>\n<p>Roles\u00a0\u2014 middleware \u043f\u0440\u0435\u0434\u0440\u0430\u043d\u0437\u0430\u0447\u0435\u043d \u0434\u043b\u044f\u00a0\u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u0442\u043e\u0433\u043e, \u0441\u00a0\u043a\u0430\u043a\u043e\u0439 \u0440\u043e\u043b\u044c\u044e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u0432\u0445\u043e\u0434\u0438\u0442 \u043d\u0430\u00a0\u0441\u0435\u0440\u0432\u0435\u0440. \u0412\u00a0\u043f\u0435\u0440\u0435\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u0438 Roles \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043e \u043f\u044f\u0442\u044c \u0440\u043e\u043b\u0435\u0439: owner, admin, manager, user, lowest. \u041e\u043f\u0435\u0440\u0430\u0446\u0438\u044f \u043f\u043e\u00a0\u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044e \u0441\u0432\u0435\u0434\u0435\u043d\u0438\u044f \u043e\u00a0\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f\u0445 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b \u0442\u043e\u043b\u044c\u043a\u043e \u0434\u043b\u044f\u00a0\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0438\u043c\u0435\u044e \u0440\u043e\u043b\u044c manager \u0438 \u0432\u044b\u0448\u0435.<\/p>\n<p>Storage<\/p>\n<p>\u041f\u0440\u0438 \u0441\u0442\u0430\u0440\u0442\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u043d\u0430 \u043d\u0430\u043b\u0438\u0447\u0438\u0435 \u043a\u0430\u0442\u0430\u043b\u043e\u0433\u043e\u0432 \u0434\u043b\u044f\u00a0\u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u0438\u0437\u043e\u0431\u0440\u0436\u0435\u043d\u0438\u0439 \u0438 \u0430\u0432\u0430\u0442\u0430\u0440\u043e\u0432 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439. \u0415\u0441\u043b\u0438 \u043a\u043e\u0440\u0435\u0432\u044b\u0435 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0438 \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u044e\u0442\u00a0\u2014 \u043e\u043d\u0438 \u0441\u043e\u0437\u0434\u0430\u044e\u0442\u0441\u044f. \u0418\u043c\u0435\u043d\u0430 \u0431\u0435\u0440\u0443\u0442\u0441\u044f \u0438\u0437\u00a0\u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0438 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f.<\/p>\n<details class=\"spoiler\">\n<summary>Storage.swift<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"swift\">import Foundation import Vapor  class Storage: LifecycleHandler {     \/\/ Called before application boots.     func willBoot(_ app: Application) throws {                  do {             try createIfNotExist(app, Environment.get(\"STORAGE_AVATARS\") ?? Constants.avatarStorage)             try createIfNotExist(app, Environment.get(\"STORAGE_IMAGES\") ?? Constants.imageStorage)         }         catch let e {             print(\"FILE SYSTEM: \\(e.localizedDescription)\")         }     }          private func createIfNotExist(_ app: Application, _ path: String) throws {         let fullPath = app.directory.workingDirectory + path         try FileManager.default.createDirectory(atPath: fullPath, withIntermediateDirectories: true)     } }<\/code><\/pre>\n<\/div>\n<\/details>\n<p>APNS<\/p>\n<p>\u0421\u0435\u0440\u0435\u0440 \u043c\u043e\u0436\u0435\u0442 \u0443\u0432\u0435\u0434\u043e\u043c\u0438\u0442\u044c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u043a\u043b\u0438\u0435\u043d\u0442\u0441\u043a\u043e\u0433\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u043e \u043a\u0430\u043a\u043e\u043c-\u043b\u0438\u0431\u043e \u0441\u043e\u0431\u044b\u0442\u0438\u0438 \u043f\u0443\u0442\u0435\u043c \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0438 Apple Push Notification. \u0412\u0441\u0435 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u043f\u043e\u043b\u0443\u0447\u0430\u044e\u0442 \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0435, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0442\u0438\u0442\u0443\u0442\u043b, \u0441\u0430\u043c\u0442\u0438\u0442\u0443\u043b, \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u0439 \u0442\u0435\u043a\u0441\u0442 \u0438 \u0437\u0432\u0443\u043a\u043e\u0432\u043e\u0439 \u0441\u0438\u0433\u043d\u0430\u043b. \u041a\u0440\u043e\u043c\u0435 \u0442\u043e\u0433\u043e, \u043d\u0430 \u0437\u043d\u0430\u0447\u043a\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0438\u043d\u0434\u0435\u043a\u0441 \u043e \u043d\u0435 \u043f\u0440\u043e\u0447\u0438\u0442\u0430\u043d\u043d\u043e\u043c \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0438. \u0421\u0435\u0440\u0432\u0435\u0440 \u0432\u0435\u0434\u0435\u0442 \u0443\u0447\u0435\u0442 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u043d\u044b\u0445 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0439, \u0438 \u043e\u0442\u0441\u043b\u0435\u0436\u0438\u0432\u0430\u0435\u0442, \u0431\u044b\u043b\u043e \u043b\u0438 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 \u043f\u0440\u043e\u0447\u0438\u0442\u0430\u043d\u043e \u043d\u0430 \u043a\u043b\u0438\u0435\u043d\u0442\u0435 \u0432\u043d\u0443\u0442\u0440\u0438 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f.<\/p>\n<details class=\"spoiler\">\n<summary>PushSender.swift<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"swift\">import Fluent import Vapor import APNS  class PushSender {     func send(req: Request, tokens:[PushToken], title: String, subtitle: String?, body: String?) async throws {         for token in tokens {             let unread = try await token.countUnread(req)             let alert  = APNSwiftAlert(title: title, subtitle: subtitle, body: body)             let aps    = APNSwiftPayload(alert: alert, badge: unread + 1, sound: .normal(\"cow.wav\"))             let _      = req.apns.send(aps, to: token.token)                          guard let id = token.id else { throw Abort(.internalServerError) }             let push = Push(pushToken: id, title: title, subtitle: subtitle, body: body)             try await push.save(on: req.db)         }     } }<\/code><\/pre>\n<\/div>\n<\/details>\n<h3>\u0417\u0430\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435<\/h3>\n<p>\u0420\u0430\u0437\u0443\u043c\u0435\u0435\u0442\u0441\u044f, \u043f\u0440\u0438\u0432\u0435\u0434\u0435\u043d\u043d\u044b\u0445 \u0438\u0441\u0445\u043e\u0434\u043d\u044b\u0439 \u043a\u043e\u0434 \u043d\u0435 \u043c\u043e\u0436\u0435\u0442 \u043f\u043e\u043a\u0440\u044b\u0442\u044c \u0432\u0435\u0441\u044c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u0439 \u0434\u043b\u044f \u043b\u044e\u0431\u043e\u0433\u043e REST API \u0441\u0435\u0440\u0432\u0438\u0441\u0430 \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b. \u041d\u043e \u043e\u043d \u043c\u043e\u0436\u0435\u0442 \u0441\u0442\u0430\u0442\u044c \u0441\u0442\u0430\u0440\u0442\u043e\u0432\u044b\u043c \u044d\u0442\u0430\u043f\u043e\u043c \u0434\u043b\u044f \u0431\u044b\u0441\u0442\u0440\u043e\u0433\u043e \u0440\u0430\u0437\u0432\u0435\u0440\u0442\u044b\u0432\u0430\u043d\u0438\u044f \u0412\u0430\u0448\u0438\u0445 \u0440\u0435\u0448\u0435\u043d\u0438\u0439, \u043f\u043e\u0441\u043a\u043e\u043b\u044c\u043a\u0443 \u0438\u043c\u0435\u0435\u0442 \u043e\u0442\u043b\u0430\u0436\u0435\u043d\u043d\u044b\u0435 \u043c\u0435\u0442\u043e\u0434\u044b \u0434\u043b\u044f \u0442\u0438\u043f\u043e\u0432\u044b\u0445 \u0437\u0430\u0434\u0430\u0447 \u0441\u0435\u0440\u0432\u0435\u0440\u0430 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0438 \u043c\u043e\u0431\u0438\u043b\u044c\u043d\u043e\u0433\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f.<\/p>\n<p><a href=\"https:\/\/github.com\/DemonSoft\/Swift-Vapor-Server\" rel=\"noopener noreferrer nofollow\">\u0418\u0441\u0445\u043e\u0434\u043d\u044b\u0439 \u043a\u043e\u0434 \u0434\u043e\u0441\u0442\u0443\u043f\u0435\u043d \u0432 GitHub.<\/a><\/p>\n<p>\u041e\u0431\u0441\u0443\u0434\u0438\u0442\u044c \u043c\u043e\u0436\u043d\u043e \u0432\u00a0<a href=\"https:\/\/t.me\/+TjI9YXI0EXZ190Ht\" rel=\"noopener noreferrer nofollow\">\u0442\u0435\u043b\u0435\u0433\u0440\u0430\u043c \u0447\u0430\u0442\u0435<\/a>.<\/p>\n<\/div>\n<\/div>\n<\/div>\n<p><!----><!----><\/div>\n<p><!----><!----><br \/> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/articles\/900634\/\"> https:\/\/habr.com\/ru\/articles\/900634\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<div><!--[--><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<figure class=\"full-width\"><\/figure>\n<p>\u0412 \u043c\u043e\u0431\u0438\u043b\u044c\u043d\u0443\u044e \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0443 \u043f\u0440\u0438\u0445\u043e\u0434\u044f\u0442 \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u043c\u0438 \u043f\u0443\u0442\u044f\u043c\u0438. \u041d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0440\u043e\u0436\u0434\u0430\u044e\u0442\u0441\u044f \u0441 \u0434\u0435\u0432\u0430\u0439\u0441\u043e\u043c \u0432 \u0440\u0443\u043a\u0430\u0445, \u0434\u0440\u0443\u0433\u0438\u0445 \u0432\u0435\u0434\u0435\u0442 \u0438\u0437\u0432\u0438\u043b\u0438\u0441\u0442\u0430\u044f \u0434\u043e\u0440\u043e\u0433\u0430 \u0432\u0434\u043e\u043b\u044c \u0441\u0435\u0440\u0432\u0435\u0440\u043e\u0432, \u043c\u0430\u0439\u043d\u0444\u0440\u0435\u0439\u043c\u043e\u0432, \u0434\u0435\u0441\u0442\u043e\u043f\u043d\u044b\u0445 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439. \u041d\u043e\u00a0\u043a\u0430\u0436\u0434\u044b\u0439 \u043a\u0442\u043e \u0432\u00a0\u043d\u0435\u0435 \u043f\u043e\u043f\u0430\u0434\u0430\u0435\u0442 \u043e\u0449\u0443\u0449\u0430\u0435\u0442 \u0441\u0432\u043e\u044e \u043d\u0435\u0437\u0430\u0449\u0438\u0449\u0435\u043d\u043d\u043e\u0441\u0442\u044c \u0441\u00a0\u0442\u044b\u043b\u0430, \u0435\u0441\u043b\u0438 \u043d\u0435\u0442 \u043d\u0430\u0434\u0435\u0436\u043d\u043e\u0433\u043e \u043f\u0430\u0440\u0442\u043d\u0435\u0440\u0430 \u0432\u00a0\u043b\u0438\u0446\u0435 \u0431\u044d\u043a\u0435\u043d\u0434\u2011\u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0430. \u0418, \u0431\u0443\u043a\u0432\u0430\u043b\u044c\u043d\u043e, \u043a\u0430\u0436\u0434\u044b\u0439 \u043c\u043e\u0431\u0438\u043b\u044c\u0449\u0438\u043a \u043e\u0436\u0438\u0434\u0430\u0435\u0442, \u0447\u0442\u043e\u00a0\u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u0439 API \u0431\u0443\u0434\u0435\u0442 \u0433\u043e\u0442\u043e\u0432 \u0445\u043e\u0442\u044f\u00a0\u0431\u044b \u0437\u0430\u00a0\u043e\u0434\u0438\u043d \u0441\u043f\u0440\u0438\u043d\u0442, \u0434\u043e\u00a0\u0442\u043e\u0433\u043e, \u043a\u0430\u043a\u00a0\u0432\u00a0\u043d\u0435\u043c \u0432\u043e\u0437\u043d\u0438\u043a\u043d\u0435\u0442 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u044c. \u041a\u043e\u043d\u0435\u0447\u043d\u043e\u00a0\u0436\u0435, \u043c\u0438\u0440 IT \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0440\u0435\u0434\u043a\u043e \u0434\u043e\u043f\u0443\u0441\u043a\u0430\u0435\u0442 \u0442\u0430\u043a\u0443\u044e \u0440\u043e\u0441\u043a\u043e\u0448\u044c\u00a0\u2014 \u0437\u0430\u00a0\u043d\u0435\u0435 \u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0431\u043e\u0440\u043e\u0442\u044c\u0441\u044f \u0441\u00a0\u041f\u041c \u0438 \u0431\u0438\u0437\u043d\u0435\u0441\u2011\u0430\u043d\u0430\u043b\u0438\u0442\u0438\u043a\u043e\u043c. \u041a\u00a0\u0442\u043e\u043c\u0443\u00a0\u0436\u0435 \u043d\u0435\u00a0\u0440\u0435\u0434\u043a\u0438 \u0441\u0438\u0442\u0443\u0430\u0446\u0438\u0438, \u043a\u043e\u0433\u0434\u0430 \u0442\u043e, \u0447\u0442\u043e\u00a0\u0434\u043e\u043b\u0436\u043d\u043e\u00a0\u0431\u044b\u0442\u044c \u0441\u0434\u0435\u043b\u0430\u043d\u043e \u00ab\u043d\u0430 \u0432\u0447\u0435\u0440\u0430\u00bb, \u0431\u0443\u0434\u0435\u0442 \u0433\u043e\u0442\u043e\u0432\u043e \u00ab\u043d\u0430 \u043f\u043e\u0441\u043b\u0435\u0437\u0430\u0432\u0442\u0440\u0430\u00bb. \u0422\u0435 \u043a\u0442\u043e \u0438\u043c\u0435\u044e\u0442 \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u043e\u043f\u044b\u0442\u0430 \u043a\u0430\u043a\u00a0\u0432\u00a0\u043d\u0430\u0437\u0435\u043c\u043d\u043e\u043c, \u0442\u0430\u043a \u0438 \u043f\u043e\u0434\u0437\u0435\u043c\u043d\u043e\u043c \u043c\u0438\u0440\u0435\u00a0\u2014 \u0431\u0435\u0440\u0443\u0442 \u0438\u043d\u0438\u0446\u0438\u0430\u0442\u0438\u0432\u0443 \u0441\u00a0\u0441\u0432\u043e\u0438 \u0440\u0443\u043a\u0438, \u0438 \u0441\u0430\u043c\u0438 \u043f\u0440\u0435\u0434\u043b\u0430\u0433\u0430\u044e\u0442 \u043a\u043b\u0438\u0435\u043d\u0442\u2011\u0441\u0435\u0440\u0432\u0435\u0440\u043d\u044b\u0439 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441.<\/p>\n<p>\u0414\u043b\u044f\u00a0\u043c\u043e\u0431\u0438\u043b\u044c\u043d\u043e\u0433\u043e \u043c\u0438\u0440\u0430 C# \u0438 Java\u00a0\u2014 \u043f\u0430\u0434\u0435\u043d\u0438\u044f \u0438\u0437\u00a0\u0440\u0430\u044f \u0432\u00a0\u0430\u0434\u00a0\u2014 \u044d\u0442\u043e \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u0435\u0441\u0442\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0439 \u043f\u0440\u043e\u0446\u0435\u0441\u0441, \u043f\u043e\u0441\u043a\u043e\u043b\u044c\u043a\u0443 \u043f\u0440\u0438\u0441\u0443\u0449\u0438\u0435 \u0438\u043c \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u044b \u0438\u0437\u043d\u0430\u0447\u0430\u043b\u044c\u043d\u043e \u0446\u0435\u043b\u0438\u043b\u0438\u0441\u044c \u043d\u0430\u00a0\u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0443 \u0442<s>\u0435\u043c\u043d\u044b\u0445 \u0441\u0438\u043b<\/s> \u0431\u044d\u043a\u0435\u043d\u0434\u0430. \u0422\u043e\u00a0\u043b\u0438 \u0434\u0435\u043b\u043e Swift\u00a0\u2014 \u043f\u043e\u0437\u043d\u0430\u0432\u0448\u0435\u043c\u0443 \u043d\u0435\u0431\u043e\u00a0\u2014 \u043d\u0435\u00a0\u043b\u0435\u0433\u043a\u043e \u0434\u0430\u0435\u0442\u0441\u044f \u0436\u0438\u0437\u043d\u044c \u043d\u0430\u00a0\u043b\u044c\u0434\u0438\u043d\u0435, \u0432\u043c\u0435\u0441\u0442\u0435 \u0441\u00a0\u043b\u0430\u0441\u0442\u043e\u043d\u043e\u0433\u0438\u043c\u0438. <\/p>\n<p>\u041f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u043b\u0443\u0447\u0448\u0435\u0435 \u0438\u0437\u00a0\u043e\u0431\u043e\u0438\u0445 \u043c\u0438\u0440\u043e\u0432, \u0438 \u043d\u0435\u00a0\u043f\u043e\u0442\u0435\u0440\u044f\u0442\u044c \u0442\u0435\u043c\u043f \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u044e\u0442 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u044d\u043a\u0437\u043e\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u044f, \u043d\u0430\u043f\u043e\u0434\u043e\u0431\u0438\u0435 Perfect \u0438 Vapor. \u041e\u0434\u043d\u0430\u043a\u043e, \u043e\u043d\u0438 \u0432\u00a0\u0431\u043e\u043b\u044c\u0448\u0435\u0439 \u0441\u0442\u0435\u043f\u0435\u043d\u0438 \u043e\u0442\u0432\u0435\u0447\u0430\u044e\u0442 \u043d\u0430\u00a0\u0432\u043e\u043f\u0440\u043e\u0441 \u00ab\u041a\u0430\u043a?\u00bb \u0432\u043c\u0435\u0441\u0442\u043e \u0442\u043e\u0433\u043e, \u0447\u0442\u043e\u0431 \u043f\u0440\u0435\u0434\u043b\u043e\u0436\u0438\u0442\u044c \u043a\u0430\u043a\u043e\u0435\u2011\u043d\u0438\u0431\u0443\u0434\u044c \u0443\u0434\u043e\u0432\u043b\u0435\u0442\u0432\u043e\u0440\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0435 \u043c\u0438\u043d\u0438\u043c\u0430\u043b\u044c\u043d\u043e\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u0435. \u0421\u00a0\u0434\u0440\u0443\u0433\u043e\u0439 \u0441\u0442\u043e\u0440\u043e\u043d\u044b, \u043a\u0430\u043a\u00a0\u043f\u0440\u0430\u0432\u0438\u043b\u043e, \u0438\u0441\u0445\u043e\u0434\u043d\u044b\u0435 \u0442\u0440\u0435\u0431\u043e\u0432\u0430\u043d\u0438\u044f \u043c\u043e\u0431\u0438\u043b\u044c\u043d\u043e\u0439 \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u0443\u043c\u0435\u0440\u0435\u043d\u044b \u0438 \u0441\u0442\u0435\u0440\u0435\u043e\u0442\u0438\u043f\u043d\u044b \u043e\u0442\u00a0\u043e\u0434\u043d\u043e\u0433\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u043a\u00a0\u0434\u0440\u0443\u0433\u043e\u043c\u0443. \u041e\u0431\u044b\u0447\u043d\u043e \u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0430 \u0438 \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0442\u0430\u043a\u0438\u043c\u0438 \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u044f\u043c\u0438 \u043a\u0430\u043a\u00a0\u0430\u043a\u043a\u0430\u0443\u043d\u0442 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f, \u043f\u0440\u043e\u0444\u0438\u043b\u044c, \u043f\u0440\u043e\u0434\u0443\u043a\u0442 \u0438 \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f.<\/p>\n<p>\u0427\u0442\u043e\u0431 \u0440\u0435\u0448\u0438\u0442\u044c \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u044b\u0435 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u044b \u0431\u044b\u043b \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0430\u043d, \u0438 \u043e\u0431\u043a\u0430\u0442\u0430\u043d \u043d\u0430 AWS \u043f\u0440\u043e\u0435\u043a\u0442 REST API \u0441\u0435\u0440\u0432\u0435\u0440\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0432\u044b\u043a\u043b\u0430\u0434\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0432\u00a0\u043e\u0431\u0449\u0438\u0439 \u0434\u043e\u0441\u0442\u0443\u043f. \u0424\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u043d\u0435 \u043e\u0447\u0435\u043d\u044c \u0431\u043e\u043b\u044c\u0448\u0430\u044f, \u043d\u043e \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u0430\u044f \u0434\u043b\u044f \u0442\u043e\u0433\u043e, \u0447\u0442\u043e\u0431 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0438 \u043d\u0435 \u0432\u043b\u0430\u0434\u0435\u044e\u0449\u0438\u0435 \u0433\u043b\u0443\u0431\u043e\u043a\u043e \u043d\u0430\u0432\u044b\u043a\u0430\u043c\u0438 \u0441\u0435\u0440\u0432\u0435\u0440\u043d\u043e\u0439 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u043c\u043e\u0433\u043b\u0438 \u0441\u043e\u0431\u0440\u0430\u0442\u044c \u0438 \u0432\u044b\u043b\u043e\u0436\u0438\u0442\u044c \u0433\u043e\u0442\u043e\u0432\u043e\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u0435 \u0432 \u0432\u0438\u0434\u0435 Docker \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u0430, \u0430 \u043f\u0440\u0438 \u0436\u0435\u043b\u0430\u043d\u0438\u0438, \u0440\u0430\u0437\u0432\u0438\u0442\u044c \u043f\u0440\u043e\u0435\u043a\u0442 \u043f\u043e\u0434 \u0441\u0432\u043e\u0438 \u043d\u0443\u0436\u0434\u044b.<\/p>\n<p>\u0412 \u043d\u0430\u0441\u0442\u043e\u044f\u0449\u0435\u0435 \u0432\u0440\u0435\u043c\u044f, \u0441\u043e\u0431\u0440\u0430\u043d\u043d\u044b\u0439 \u0441\u0435\u0440\u0432\u0435\u0440, \u0440\u0435\u0448\u0430\u0435\u0442 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u0437\u0430\u0434\u0430\u0447\u0438:<\/p>\n<p>\u0410\u041a\u041a\u0410\u0423\u041d\u0422<\/p>\n<ul>\n<li>\n<p>\u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u0430\u043a\u043a\u0430\u0443\u043d\u0442\u0430 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u043f\u043e email \/ password<\/p>\n<\/li>\n<li>\n<p>Basic \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u043f\u043e email \/ password \u0438 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0435 bearer \u0442\u043e\u043a\u0435\u043d\u0430.<\/p>\n<\/li>\n<li>\n<p>\u041f\u0435\u0440\u0435\u0434\u0430\u0447\u0430 bearer \u0432 \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u0435 \u043e\u0442\u0432\u0435\u0442\u0430 \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u0438 \/ \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438.<\/p>\n<\/li>\n<li>\n<p>\u041d\u0435\u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0435 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435 \u043b\u043e\u0433\u0438\u043d\u0430 \u0438 \u043f\u0430\u0440\u043e\u043b\u044f.<\/p>\n<\/li>\n<li>\n<p>\u0412\u043e\u0441\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435 \u043f\u0430\u0440\u043e\u043b\u044f.<\/p>\n<\/li>\n<li>\n<p>Email \u0441 \u043f\u043e\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043d\u0438\u0435\u043c \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u044d\u043b\u0435\u043a\u0442\u0440\u043e\u043d\u043d\u043e\u0433\u043e \u0430\u0434\u0440\u0435\u0441\u0430.<\/p>\n<\/li>\n<li>\n<p>Email \u0441 \u043f\u043e\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043d\u0438\u0435\u043c \u0441\u0431\u0440\u043e\u0441\u0430 \u043f\u0430\u0440\u043e\u043b\u044f.<\/p>\n<\/li>\n<li>\n<p>\u0420\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u044f \u0438 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u044f \u0447\u0435\u0440\u0435\u0437 Apple.<\/p>\n<\/li>\n<li>\n<p>\u0420\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u044f \u0438 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u044f \u0447\u0435\u0440\u0435\u0437 Google.<\/p>\n<\/li>\n<li>\n<p>\u041c\u044f\u0433\u043a\u043e\u0435 \u0443\u0434\u0430\u043b\u0435\u043d\u0438\u0435 \u0430\u043a\u043a\u0430\u0443\u043d\u0442\u0430.<\/p>\n<\/li>\n<li>\n<p>\u0412\u043e\u0441\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435 \u0430\u043a\u043a\u0430\u0443\u043d\u0442\u0430 \u0432 \u0442\u0435\u0447\u0435\u043d\u0438\u0435 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u043e\u0433\u043e \u0441\u0440\u043e\u043a\u0430 (30 \u0434\u043d\u0435\u0439).<\/p>\n<\/li>\n<\/ul>\n<p>\u041f\u0420\u041e\u0424\u0418\u041b\u042c:<\/p>\n<ul>\n<li>\n<p>\u041f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0435 \u043f\u0440\u043e\u0444\u0438\u043b\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f.<\/p>\n<\/li>\n<li>\n<p>\u041e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435 \u043f\u0440\u043e\u0444\u0438\u043b\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f.<\/p>\n<\/li>\n<li>\n<p>\u041e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435 \u0430\u0432\u0430\u0442\u0430\u0440\u0430 \u0442\u0435\u043a\u0443\u0449\u0435\u0433\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f<\/p>\n<\/li>\n<li>\n<p>\u041f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0435 \u0430\u0432\u0430\u0442\u0430\u0440\u0430 \u0442\u0435\u043a\u0443\u0449\u0435\u0433\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f.<\/p>\n<\/li>\n<li>\n<p>\u041f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0435 \u0430\u0432\u0430\u0442\u0430\u0440\u0430 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u043b\u044c\u043d\u043e\u0433\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u043f\u043e ID \u0430\u0432\u0430\u0442\u0430\u0440\u0430.<\/p>\n<\/li>\n<li>\n<p>\u041f\u043e\u0438\u0441\u043a \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u0441 \u0443\u0447\u0435\u0442\u043e\u043c \u0443\u0440\u043e\u0432\u043d\u044f \u0434\u043e\u0441\u0442\u0443\u043f\u0430.<\/p>\n<\/li>\n<li>\n<p>\u0418\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0435 \u0440\u043e\u043b\u0438 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u043b\u044c\u043d\u043e\u0433\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u0441 \u0443\u0447\u0435\u0442\u043e\u043c \u0440\u043e\u043b\u0438 \u0442\u0435\u043a\u0443\u0449\u0435\u0433\u043e.<\/p>\n<\/li>\n<li>\n<p>\u041f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0435 \u043f\u0440\u043e\u0444\u0438\u043b\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u043f\u043e \u0435\u0433\u043e ID<\/p>\n<\/li>\n<\/ul>\n<p>\u041f\u0420\u041e\u0414\u0423\u041a\u0422\u042b:<\/p>\n<ul>\n<li>\n<p>\u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u043f\u0440\u043e\u0434\u0443\u043a\u0442\u0430 (\u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435, \u0432\u0435\u0441)<\/p>\n<\/li>\n<li>\n<p>\u041f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0435 \u0441\u043f\u0438\u0441\u043a\u0430 \u0442\u043e\u0432\u0430\u0440\u043e\u0432.<\/p>\n<\/li>\n<li>\n<p>\u041e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435 \u043f\u0440\u043e\u0434\u0443\u043a\u0442\u0430 \u043f\u043e ID \u0442\u043e\u0432\u0430\u0440\u0430.<\/p>\n<\/li>\n<li>\n<p>\u0423\u0434\u0430\u043b\u0435\u043d\u0438\u0435 \u043f\u0440\u043e\u0434\u0443\u043a\u0442\u0430.<\/p>\n<\/li>\n<\/ul>\n<p>\u0418\u0417\u041e\u0411\u0420\u0410\u0416\u0415\u041d\u0418\u042f:<\/p>\n<ul>\n<li>\n<p>\u0417\u0430\u0433\u0440\u0443\u0437\u043a\u0430 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u043b\u044c\u043d\u044b\u0445 \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440.<\/p>\n<\/li>\n<li>\n<p>\u041f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0435 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u043b\u044c\u043d\u044b\u0445 \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0439 \u043d\u0430 \u043a\u043b\u0438\u0435\u043d\u0442\u0435.<\/p>\n<\/li>\n<\/ul>\n<p>\u041d\u041e\u0422\u0418\u0424\u0418\u041a\u0410\u0426\u0418\u0418:<\/p>\n<ul>\n<li>\n<p>\u041e\u0442\u043f\u0440\u0430\u0432\u043a\u0430 \u041f\u0443\u0448-\u043d\u043e\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0439, \u0441 \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0435\u0439 title, subtitle, body, payload, \u0437\u0432\u0443\u043a\u0430 \u0438 badge.<\/p>\n<\/li>\n<li>\n<p>\u041f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0435 \u0441\u043f\u0438\u0441\u043a\u0430 \u0440\u0430\u043d\u0435\u0435 \u0441\u043e\u0437\u0434\u0430\u043d\u043d\u044b\u0445 \u043d\u043e\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0439.<\/p>\n<\/li>\n<li>\n<p>\u041e\u0442\u043c\u0435\u0442\u043a\u0430 \u043d\u043e\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 \u043a\u0430\u043a \u043f\u0440\u043e\u0447\u0438\u0442\u0430\u043d\u043d\u043e\u0439.<\/p>\n<\/li>\n<\/ul>\n<p>\u0418\u041d\u0424\u0420\u0410\u0421\u0422\u0420\u0423\u041a\u0422\u0423\u0420\u0410:<\/p>\n<ul>\n<li>\n<p>\u0418\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u044f \u043f\u043b\u0430\u0442\u0435\u0436\u043d\u043e\u0439 \u0441\u0438\u0441\u0442\u0435\u043c\u044b Stripe\u00a0<\/p>\n<\/li>\n<li>\n<p>\u041e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f API \u043f\u043e X-Token \u043f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u0435\u043c\u043e\u0433\u043e \u0432 \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u0430\u0445 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432.<\/p>\n<\/li>\n<li>\n<p>\u041e\u0431\u0441\u043b\u0443\u0436\u0438\u0432\u0430\u043d\u0438\u0435 \u0431\u0430\u0437\u044b, \u0432 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0435 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438.<\/p>\n<\/li>\n<li>\n<p>\u0414\u0430\u0442\u0430 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u0438 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u043a\u0430\u0436\u0434\u043e\u0439 \u0437\u0430\u043f\u0438\u0441\u0438.<\/p>\n<\/li>\n<\/ul>\n<p>\u0421\u0445\u0435\u043c\u0430 \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442 \u043e\u0442\u043d\u043e\u0448\u0435\u043d\u0438\u0435 \u043c\u0435\u0436\u0434\u0443 \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u044f\u043c\u0438 \u0431\u0430\u0437\u044b \u0434\u0430\u043d\u043d\u044b\u0445 (Postgresql)<\/p>\n<figure class=\"full-width\">\n<div><figcaption>\u0421\u0445\u0435\u043c\u0430 \u0411\u0414<\/figcaption><\/div>\n<\/figure>\n<p>\u041f\u0440\u043e\u0444\u0438\u043b\u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f\u00a0\u2014 \u043a\u043e\u0440\u043d\u0435\u0432\u043e\u0439 \u044d\u043b\u0435\u043c\u0435\u043d\u0442 \u0431\u0438\u043d\u0435\u0441\u2011\u043b\u043e\u0433\u0438\u043a\u0438. \u041a\u00a0\u043d\u0435\u043c\u0443 \u0432\u00a0\u0442\u043e\u0439 \u0438\u043b\u0438\u00a0\u0438\u043d\u043e\u0439 \u0441\u0442\u0435\u043f\u0435\u043d\u0438 \u043f\u043e\u0434\u0432\u044f\u0437\u0430\u043d\u044b \u0432\u0441\u0435 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u044b, \u0441\u0432\u044f\u0437\u0430\u043d\u043d\u044b\u0435 \u0441\u043e \u0441\u0442\u0430\u0440\u0442\u043e\u043c \u043c\u043e\u0431\u0438\u043b\u044c\u043d\u043e\u0433\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0438 \u043e\u043d\u0431\u043e\u0440\u0434\u0438\u043d\u0433\u043e\u043c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f. \u041e\u0434\u043d\u0430\u043a\u043e, \u043d\u0430\u00a0\u0441\u0445\u0435\u043c\u0435 \u0432\u0438\u0434\u043d\u043e, \u0447\u0442\u043e\u00a0\u0435\u0441\u0442\u044c \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0435 \u0440\u0430\u0437\u043b\u0438\u0447\u0438\u0435 \u0432\u00a0\u0442\u043e\u043c, \u043e\u0442\u043d\u043e\u0441\u044f\u0442\u0441\u044f\u00a0\u043b\u0438 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u043a\u00a0\u0441\u0444\u0435\u0440\u0435 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438, \u0438\u043b\u0438\u00a0\u043e\u0441\u043d\u043e\u0432\u043d\u043e\u0439 \u0440\u0430\u0431\u043e\u0442\u044b \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f. \u0422\u0430\u043a\u043e\u0435 \u0440\u0430\u0437\u0434\u0435\u043b\u0435\u043d\u0438\u0435 \u043f\u0440\u0435\u0434\u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u043e \u0434\u043b\u044f\u00a0\u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0435\u043d\u0438\u044f \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e\u0441\u0442\u0438 \u0434\u0430\u043d\u043d\u044b\u0445\u00a0\u2014 \u043f\u043e\u0441\u043b\u0435 \u043f\u0440\u043e\u0445\u043e\u0436\u0434\u0435\u043d\u0438\u044f \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u0445 \u043f\u0440\u043e\u0446\u0435\u0434\u0443\u0440 \u0432\u0435\u0440\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438\u00a0\u2014 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0441\u043e \u0441\u0432\u043e\u0438\u043c \u043f\u0440\u043e\u0444\u0438\u043b\u0435\u043c \u0438 \u043d\u0438\u043a\u0430\u043a \u043d\u0435\u00a0\u0441\u043e\u043f\u0440\u0438\u043a\u0430\u0441\u0430\u0435\u0442\u0441\u044f \u0441\u00a0\u043a\u0440\u0435\u0434\u0430\u043c\u0438.<\/p>\n<p>\u0421\u0435\u0440\u0432\u0435\u0440 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0430\u0442\u0441\u044f \u043e\u0434\u043d\u043e\u043c\u0443 \u0438 \u0442\u043e\u043c\u0443\u00a0\u0436\u0435 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044e \u0441\u00a0\u0440\u0430\u0437\u043d\u044b\u0445 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432 \u043e\u0434\u043d\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e. \u0412\u00a0\u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0442\u0435\u0441\u0442\u043e\u0432\u043e\u0433\u043e \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c\u0430\u00a0\u0431\u044b\u043b\u0430 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u0430 \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0430 \u043f\u0443\u0448\u2011\u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0439 \u0430\u043a\u0442\u0438\u0432\u043d\u043e\u0439 \u043a\u043b\u0438\u0435\u043d\u0442\u0441\u043a\u043e\u0439 \u0441\u0435\u0441\u0441\u0438\u0438. \u041a\u0430\u0436\u0434\u043e\u0435 \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0435 \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u0442\u0441\u044f \u0432\u00a0\u0431\u0430\u0437\u0435 \u0434\u0430\u043d\u043d\u044b\u0445, \u0438 \u043c\u043e\u0436\u0435\u0442\u00a0\u0431\u044b\u0442\u044c \u043f\u0440\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u043d\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u043c \u043f\u043e\u0432\u0442\u043e\u0440\u043d\u043e, \u043a\u0430\u043a\u00a0\u0432\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 \u0432\u00a0\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0438. \u0422\u0430\u043a\u0438\u043c\u00a0\u0436\u0435 \u043e\u0431\u0440\u0430\u0437\u043e\u043c \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u0441\u043f\u0438\u0441\u043e\u043a \u0437\u0430\u0433\u0440\u0443\u0436\u0435\u043d\u043d\u044b\u0445 \u043d\u0430\u00a0\u0441\u0435\u0440\u0432\u0435\u0440 \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0439.<\/p>\n<p>\u041e\u0434\u043d\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e \u0441\u00a0\u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u043e\u0439 \u0441\u0435\u0440\u0432\u0435\u0440\u0430, \u0432\u0435\u043b\u0430\u0441\u044c \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u0438 \u0431\u0430\u0437\u043e\u0432\u043e\u0433\u043e iOS \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f, \u0441\u00a0\u043a\u043e\u0442\u043e\u0440\u043e\u043c\u0443 \u043f\u0440\u0435\u0434\u044a\u044f\u0432\u043b\u044f\u043b\u0438\u0441\u044c \u0442\u0440\u0435\u0431\u043e\u0432\u0430\u043d\u0438\u0435 \u043f\u0440\u0438\u0441\u0443\u0449\u0438\u0435 Apple \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0435. \u0412\u00a0\u0447\u0430\u0441\u0442\u043d\u043e\u0441\u0442\u0438, \u0441\u0447\u0438\u0442\u0430\u0435\u0442\u0441\u044f \u043f\u0440\u0438\u0437\u043d\u0430\u043a\u043e\u043c \u0445\u043e\u0440\u043e\u0448\u0435\u0433\u043e \u0442\u043e\u043d\u0430 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0442\u044c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044e \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0447\u0435\u0440\u0435\u0437 \u0441\u043e\u0446\u0438\u0430\u043b\u044c\u043d\u044b\u0435 \u0441\u0435\u0442\u0438. \u041d\u043e\u00a0Apple \u0442\u0440\u0435\u0431\u0443\u0435\u0442, \u0447\u0442\u043e\u00a0\u0435\u0441\u043b\u0438 \u043f\u0440\u0438\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u043f\u0440\u043e\u0432\u0430\u0439\u0434\u0435\u0440 \u0441\u043e\u0446\u0438\u0430\u043b\u044c\u043d\u043e\u0439 \u0441\u0435\u0442\u0438, \u0442\u043e, \u0432\u00a0\u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u043c \u043f\u043e\u0440\u044f\u0434\u043a\u0435, \u0434\u043e\u043b\u0436\u043d\u0430\u00a0\u0431\u044b\u0442\u044c \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0430 \u0438 Apple \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u044f. \u041d\u043e, \u043a\u043e\u043d\u0435\u0447\u043d\u043e, \u043d\u0435\u043b\u044c\u0437\u044f \u0441\u0431\u0440\u0430\u0441\u044b\u0432\u0430\u0442\u044c \u0441\u043e \u0441\u0447\u0435\u0442\u043e\u0432\u00a0\u0436\u0435\u043b\u0430\u043d\u0438\u0435 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439 \u0437\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0447\u0435\u0440\u0435\u0437 \u0441\u0432\u043e\u0439\u00a0\u043b\u0438\u0447\u043d\u044b\u0439 email.<\/p>\n<p>\u041e\u0440\u0433\u0430\u043d\u0438\u0437\u0430\u0446\u0438\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u043f\u043e\u00a0\u0432\u043e\u0441\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044e \/ \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044e \u043f\u0430\u0440\u043e\u043b\u044f \u0441\u0434\u0435\u043b\u0430\u043d\u0430 \u0447\u0435\u0440\u0435\u0437 \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0443 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u0434\u0438\u043f\u043b\u0438\u043d\u043a\u043e\u0432\u00a0\u2014 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435, \u0432\u00a0\u043a\u043e\u0442\u043e\u0440\u043e\u043c \u043f\u0440\u0438\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u043e\u0434\u043d\u0430 \u0438\u0437\u00a0\u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0445 \u043a\u043e\u043c\u0430\u043d\u0434:<\/p>\n<ul>\n<li>\n<p>\u0412\u043e\u0441\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435 \u0430\u043a\u043a\u0430\u0443\u043d\u0442\u0430<\/p>\n<\/li>\n<li>\n<p>\u0421\u0431\u0440\u043e\u0441 \u043f\u0430\u0440\u043e\u043b\u044f<\/p>\n<\/li>\n<li>\n<p>\u041f\u043e\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043d\u0438\u0435<\/p>\n<\/li>\n<\/ul>\n<p>\u0412 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0438 \u0441\u0435\u0440\u0432\u0435\u0440\u0430 \u043f\u0440\u0438\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u043f\u043e \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0439 \u0447\u0435\u0440\u0435\u0437 SMTP \u0441\u0435\u0440\u0432\u0435\u0440. \u041d\u0430 \u044d\u0442\u0430\u043f\u0435 \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0442\u0430\u043a\u0438\u043c \u0441\u0435\u0440\u0432\u0435\u0440\u043e\u043c \u0432\u044b\u0441\u0442\u0443\u043f\u0430\u043b GMail, \u043d\u043e \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a \u0432\u043f\u0440\u0430\u0432\u0435 \u0438\u0437\u043c\u0435\u043d\u0438\u0442\u044c \u044d\u0442\u0443 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044e \u043d\u0430 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u043f\u043e\u0447\u0442\u043e\u0432\u043e\u0433\u043e \u0441\u0435\u0440\u0432\u0435\u0440\u0430 \u0441\u0432\u043e\u0435\u0439 \u043a\u043e\u043c\u043f\u0430\u043d\u0438\u0438.<\/p>\n<p>\u0422\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c, \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u043e\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u0435 \u043a\u043e\u043c\u0430\u043d\u0434\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u044e\u0442 \u043c\u043e\u0431\u0438\u043b\u044c\u043d\u043e\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0438 \u043f\u0435\u0440\u0435\u0430\u0434\u0440\u0435\u0441\u043e\u0432\u044b\u0432\u0430\u044e\u0442 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u043d\u0430 \u043d\u0443\u0436\u043d\u044b\u0435 \u044d\u043a\u0440\u0430\u043d\u044b, \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0430\u043a\u043a\u0430\u0443\u043d\u0442\u043e\u043c.<\/p>\n<h3>\u0420\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f<\/h3>\n<h4>\u0418\u043c\u0435\u043d\u043e\u0432\u0430\u043d\u0438\u0435<\/h4>\n<p>\u041f\u0440\u043e\u0435\u043a\u0442 \u043d\u0430\u0437\u0432\u0430\u043d Hermes. \u0413\u0435\u0440\u043c\u0435\u0441, \u043e\u043d\u00a0\u0436\u0435 \u041c\u0435\u0440\u043a\u0443\u0440\u0438\u0439\u00a0\u2014 \u043f\u0435\u0440\u0432\u0430\u044f \u043e\u0442\u00a0\u0421\u043e\u043b\u043d\u0446\u0430 \u043f\u043b\u0430\u043d\u0435\u0442\u0430. \u041a\u0430\u043a\u00a0\u0438 \u0441\u0442\u0440\u0438\u0436 (Swift) \u0413\u0435\u0440\u043c\u0435\u0441 \u0441\u0438\u043c\u0432\u043e\u043b\u0438\u0437\u0438\u0440\u0443\u0435\u0442 \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u044c. \u0413\u0435\u0440\u043c\u0435\u0441\u00a0\u2014 \u043f\u043e\u043a\u0440\u043e\u0432\u0438\u0442\u0435\u043b\u044c \u0442\u043e\u0440\u0433\u043e\u0432\u043b\u0438 \u0438 \u0433\u0438\u0431\u043a\u043e\u0441\u0442\u0438. \u0410\u00a0\u043a\u0440\u043e\u043c\u0435 \u0442\u043e\u0433\u043e, \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0435\u0449\u0435 \u0438 \u043f\u0440\u043e\u0432\u043e\u0434\u043d\u0438\u043a\u043e\u043c \u043c\u0435\u0436\u0434\u0443 \u043f\u043e\u0434\u0437\u0435\u043c\u043d\u044b\u043c \u0438 \u043d\u0435\u0431\u0435\u0441\u043d\u044b\u043c \u043c\u0438\u0440\u043e\u043c. \u0412\u00a0\u043e\u0431\u0449\u0435\u043c, \u0430\u043b\u043b\u044e\u0437\u0438\u0439 \u043c\u043d\u043e\u0433\u043e. \u042d\u0442\u043e \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u0447\u0430\u0441\u0442\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0432\u00a0\u0438\u043c\u0435\u043d\u043e\u0432\u0430\u043d\u0438\u044f\u0445 \u0438 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044f\u0445 \u0441\u0435\u0440\u0432\u0435\u0440\u0430.<\/p>\n<h4>\u0421\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u043f\u0440\u043e\u0435\u043a\u0442\u0430<\/h4>\n<p>\u0412 \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u043c, \u0434\u043b\u044f \u0441\u0435\u0440\u0432\u0435\u0440\u043d\u043e\u0439 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438, XCode \u043d\u0435 \u043f\u0440\u0438\u043c\u0435\u043d\u044f\u0435\u0442\u0441\u044f. \u0421\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u0431\u043e\u043b\u044c\u0448\u0435 \u043d\u0430\u043f\u043e\u043c\u0438\u043d\u0430\u0435\u0442 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443 \u043f\u0440\u043e\u0435\u043a\u0442\u043e\u0432 \u043d\u0430 \u044f\u0437\u044b\u043a\u0430\u0445 Go, Rust, C++. \u0427\u0430\u0441\u0442\u0438\u0447\u043d\u043e \u044d\u0442\u043e \u043e\u0431\u0443\u0441\u043b\u043e\u0432\u043b\u0435\u043d\u043e \u0442\u0435\u043c, \u0447\u0442\u043e \u0432 \u044d\u0442\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u0443\u0434\u043e\u0431\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043d\u0435 \u043f\u043e\u043b\u043d\u043e\u0446\u0435\u043d\u043d\u044b\u0435 IDE, \u0430 \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440\u044b \u043a\u043e\u0434\u0430, \u0442\u0430\u043a\u0438\u0435 \u043a\u0430\u043a VSCode,\u00a0Sublime \u0438\u043b\u0438 Atom. \u0421\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0435\u043d\u043d\u043e, \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u0442\u0441\u044f \u0444\u0438\u0437\u0438\u0447\u0435\u0441\u043a\u043e\u0439 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u043e\u0439 \u043f\u0430\u043f\u043e\u043a\u00a0\u2014 \u0447\u0442\u043e\u0431 \u043d\u0430\u0447\u0430\u0442\u044c \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441 \u043f\u0440\u043e\u0435\u043a\u0442\u043e\u043c \u043d\u0443\u0436\u043d\u043e \u043d\u0435 \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c (\u043e\u0442\u043a\u0440\u044b\u0442\u044c) \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u044b\u0439 \u043f\u0440\u043e\u0435\u043a\u0442\u043d\u044b\u0439 \u0444\u0430\u0439\u043b, \u0430 \u043e\u0442\u043a\u0440\u044b\u0442\u044c \u0432 \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440\u0435 \u043a\u043e\u0440\u043d\u0435\u0432\u0443\u044e \u043f\u0430\u043f\u043a\u0443. \u0412 \u043d\u0430\u0448\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u043a\u0430\u0442\u0430\u043b\u043e\u0433 \u00abhermes\u00bb.<\/p>\n<p>\u041a\u043e\u0440\u043d\u0435\u0432\u0430\u044f \u043f\u0430\u043f\u043a\u0430 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u00a0<strong><u>\u043a\u0430\u0442\u0430\u043b\u043e\u0433\u0438<\/u><\/strong>\u00a0\u0438 \u0444\u0430\u0439\u043b\u044b:<\/p>\n<ul>\n<li>\n<p><strong><u>Public<\/u><\/strong>\u00a0\u2014 \u0432\u00a0\u043e\u0441\u043d\u043e\u0432\u043d\u043e\u043c, \u043f\u0443\u0441\u0442\u0430\u044f \u043f\u0430\u043f\u043a\u0430. \u041d\u043e\u00a0\u0432\u00a0\u043d\u0435\u0435 \u0437\u0430\u043f\u0438\u0441\u044b\u0432\u0430\u044e\u0442\u0441\u044f \u0441\u043a\u0440\u044b\u0442\u044b\u0435 \u0444\u0430\u0439\u043b\u044b \u0433\u0438\u0442\u0430.<\/p>\n<\/li>\n<li>\n<p><strong><u>Sources<\/u><\/strong>\u00a0\u2014 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0432\u0435\u0441\u044c \u0438\u0441\u0445\u043e\u0434\u043d\u044b\u0439 \u043a\u043e\u0434 \u043f\u0440\u043e\u0435\u043a\u0442\u0430<\/p>\n<\/li>\n<li>\n<p><strong><u>Tests<\/u><\/strong>\u00a0\u2014 \u0442\u0435\u0441\u0442\u044b, \u0434\u043b\u044f\u00a0\u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u0433\u043e \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f.<\/p>\n<\/li>\n<li>\n<p>docker\u2011compose.yml\u00a0\u2014 \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u0439 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438 \u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0430 \u0434\u043e\u043a\u0435\u0440 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u0430.<\/p>\n<\/li>\n<li>\n<p>Dockerfile\u00a0\u2014 \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u0439 \u0441\u0431\u043e\u0440\u043a\u0438 \u0434\u043e\u043a\u0435\u0440 \u043e\u0431\u0440\u0430\u0437\u0430.<\/p>\n<\/li>\n<li>\n<p>Package.resolved\u00a0\u2014 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0444\u043e\u0440\u043c\u0438\u0440\u0443\u0435\u043c\u044b\u0439 \u0444\u0430\u0439\u043b \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0435\u0439.<\/p>\n<\/li>\n<li>\n<p>Package.swift\u00a0\u2014 \u0444\u0430\u0439\u043b \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0438 \u0438 \u0438\u043c\u043f\u043e\u0440\u0442\u0430 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0435\u0439.<\/p>\n<\/li>\n<li>\n<p>AuthKey.p8\u00a0\u2014 \u044d\u0442\u043e\u0442 \u0444\u0430\u0439\u043b \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u0432 GitHub \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0438. \u0415\u0433\u043e \u0441\u043b\u0435\u0434\u0443\u0435\u0442 \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u043d\u0430\u00a0<a href=\"https:\/\/developer.apple.com\/account\/resources\/authkeys\/list\" rel=\"noopener noreferrer nofollow\">\u043f\u043e\u0440\u0442\u0430\u043b\u0435 Apple<\/a>\u00a0\u0438 \u0440\u0430\u0437\u043c\u0435\u0442\u0438\u0442\u044c \u0432 \u043a\u043e\u0440\u043d\u0435\u0432\u043e\u043c \u043a\u0430\u0442\u0430\u043b\u043e\u0433\u0435.\u00a0<\/p>\n<\/li>\n<\/ul>\n<p>\u0412 \u043e\u0442\u043b\u0438\u0447\u0438\u0435 \u043e\u0442 XCode \u2013 \u043c\u0435\u043d\u044f\u0442\u044c \u043c\u0435\u043d\u044f\u0442\u044c \u0430\u043b\u0444\u0430\u0432\u0438\u0442\u043d\u043e\u0435 \u0440\u0430\u0441\u043f\u043e\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0444\u0430\u0439\u043b\u043e\u0432 \u043d\u0435\u0434\u043e\u043f\u0443\u0441\u0442\u0438\u043c\u043e.<\/p>\n<p>\u041f\u0430\u043f\u043a\u0430\u00a0<strong><u>Sources<\/u> <\/strong>\u0438\u043c\u0435\u0435\u0442 \u0434\u0432\u0430 \u043a\u0430\u0442\u0430\u043b\u043e\u0433\u0430:<\/p>\n<ul>\n<li>\n<p><strong><u>App<\/u><\/strong> \u2014 \u0438\u0441\u0445\u043e\u0434\u043d\u044b\u0439 \u043a\u043e\u0434 \u043f\u0440\u043e\u0435\u043a\u0442\u0430.<\/p>\n<\/li>\n<li>\n<p><strong><u>Run<\/u><\/strong> \u2014 \u0444\u0430\u0439\u043b main.swift\u00a0\u2014 \u0434\u043b\u044f\u00a0\u0437\u0430\u043f\u0443\u0441\u043a\u0430 \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u0441\u0440\u0435\u0434\u0441\u0442\u0432\u0430\u043c\u0438 \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440\u0430\u00a0\u2014 \u0444\u0430\u0439\u043b main.swift \u0434\u043e\u043b\u0436\u0435\u043d\u00a0\u0431\u044b\u0442\u044c \u0432\u044b\u0431\u0440\u0430\u043d. \u0421\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0435\u043d\u043d\u043e, \u043e\u043d \u0432\u0441\u0435\u0433\u0434\u0430 \u0434\u043e\u043b\u0436\u0435\u043d \u043e\u0441\u0442\u0430\u0432\u0430\u0442\u044c\u0441\u044f \u0432 \u0448\u0430\u0433\u043e\u0432\u043e\u0439 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u043e\u0441\u0442\u0438.<\/p>\n<\/li>\n<\/ul>\n<p>\u0412 \u043f\u0430\u043f\u043a\u0435 App \u0440\u0430\u0441\u043f\u043e\u043b\u043e\u0436\u0435\u043d\u044b \u043e\u0441\u043d\u043e\u0432\u043d\u044b\u0435 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u043d\u044b\u0435 \u0435\u0434\u0438\u043d\u0438\u0446\u044b \u043f\u0440\u043e\u0435\u043a\u0442\u0430:<\/p>\n<ul>\n<li>\n<p>Classes\u00a0\u2014 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u0430\u044f \u043e\u0431\u0432\u044f\u0437\u043a\u0430 \u041e\u041e\u041f \u0431\u0438\u0437\u043d\u0435\u0441\u2011\u043b\u043e\u0433\u0438\u043a\u0438.<\/p>\n<\/li>\n<li>\n<p>Controllers\u00a0\u2014 \u043a\u043b\u0430\u0441\u0441\u044b, \u043d\u0435\u043f\u043e\u0441\u0440\u0435\u0434\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u044e\u0449\u0438\u0435 REST API.<\/p>\n<\/li>\n<li>\n<p>Extensions\u00a0\u2014 Swift \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f \u0434\u043b\u044f\u00a0\u043a\u043b\u0430\u0441\u0441\u043e\u0432 Date \u0438 String.<\/p>\n<\/li>\n<li>\n<p>Migrations\u00a0\u2014 \u0444\u0430\u0439\u043b \u0434\u0435\u043a\u043b\u0430\u0440\u0430\u0446\u0438\u0439, \u0434\u043b\u044f\u00a0\u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u0442\u0430\u0431\u043b\u0438\u0446 \u0440\u0435\u043b\u044f\u0446\u0438\u043e\u043d\u043d\u043e\u0439 \u0431\u0430\u0437\u044b \u0434\u0430\u043d\u043d\u044b\u0445 (\u043f\u0440\u0438\u0432\u0435\u0434\u0435\u043d\u043d\u044b\u0445 \u043d\u0430\u00a0\u0441\u0445\u0435\u043c\u0435 \u0432\u044b\u0448\u0435).<\/p>\n<\/li>\n<li>\n<p>Models\u00a0\u2014 \u043c\u043e\u0434\u0435\u043b\u0438 \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432 \u0434\u0430\u043d\u043d\u044b\u0445.<\/p>\n<\/li>\n<li>\n<p>Models\u2011ext\u00a0\u2014 Swift \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f \u0434\u043b\u044f \u043c\u043e\u0434\u0435\u043b\u0435\u0439.<\/p>\n<\/li>\n<\/ul>\n<h4>\u041a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0438<\/h4>\n<p><strong>Dockerfile<\/strong><\/p>\n<p>Dockerfile\u00a0\u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442 \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u0439 \u0441\u0431\u043e\u0440\u043a\u0438\u00a0Linux \u043e\u0431\u0440\u0430\u0437\u0430, \u0434\u043b\u044f \u0440\u0430\u0437\u043c\u0435\u0449\u0435\u043d\u0438\u044f \u0435\u0433\u043e \u0432 \u0432\u0438\u0434\u0435 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u0430 Docker. \u0412 \u043d\u0435\u043c \u043f\u0440\u0438\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u0443\u043a\u0430\u0437\u0430\u043d\u0438\u0435 \u043d\u0430 \u0432\u0435\u0440\u0441\u0438\u044e Swift \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d \u0434\u043b\u044f \u0441\u0431\u043e\u0440\u043a\u0438, \u0432\u0435\u0440\u0441\u0438\u044e \u044f\u0434\u0440\u0430 Linux, \u0430 \u0442\u0430\u043a \u0436\u0435 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0441\u044f \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u043f\u043e\u0440\u0442\u043e\u0432 \u0441\u0435\u0440\u0432\u0435\u0440\u0430 \u043d\u0430 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e\u043c \u0445\u043e\u0441\u0442\u0435. \u041f\u0440\u0438 \u0438\u0441\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0438 \u0444\u0430\u0439\u043b\u0430\u00a0AuthKey.p8\u0440\u0430\u0437\u043c\u0435\u0449\u0430\u0435\u0442\u0441\u044f \u0432 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e\u0439 \u043f\u0430\u043f\u043a\u0435 \u0431\u0438\u043d\u0430\u0440\u043d\u043e\u0433\u043e \u0444\u0430\u0439\u043b\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0430.<\/p>\n<details class=\"spoiler\">\n<summary>Dockerfile<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"bash\"># ================================ # Build image # ================================ FROM swift:5.7-jammy as build  # Install OS updates and, if needed, sqlite3 RUN export DEBIAN_FRONTEND=noninteractive DEBCONF_NONINTERACTIVE_SEEN=true \\     &amp;&amp; apt-get -q update \\     &amp;&amp; apt-get -q dist-upgrade -y\\     &amp;&amp; rm -rf \/var\/lib\/apt\/lists\/*  # Set up a build area WORKDIR \/build  # First just resolve dependencies. # This creates a cached layer that can be reused # as long as your Package.swift\/Package.resolved # files do not change. COPY .\/Package.* .\/ RUN swift package resolve  # Copy entire repo into container COPY . .  # Build everything, with optimizations RUN swift build -c release --static-swift-stdlib  # Switch to the staging area WORKDIR \/staging  # Copy main executable to staging area RUN cp \"$(swift build --package-path \/build -c release --show-bin-path)\/Run\" .\/  # Copy resources bundled by SPM to staging area RUN find -L \"$(swift build --package-path \/build -c release --show-bin-path)\/\" -regex '.*\\.resources$' -exec cp -Ra {} .\/ \\;  # Copy any resources from the public directory and views directory if the directories exist # Ensure that by default, neither the directory nor any of its contents are writable. RUN [ -d \/build\/Public ] &amp;&amp; { mv \/build\/Public .\/Public &amp;&amp; chmod -R a-w .\/Public; } || true RUN [ -d \/build\/Resources ] &amp;&amp; { mv \/build\/Resources .\/Resources &amp;&amp; chmod -R a-w .\/Resources; } || true  # ================================ # Run image # ================================ FROM ubuntu:jammy  # Make sure all system packages are up to date, and install only essential packages. RUN export DEBIAN_FRONTEND=noninteractive DEBCONF_NONINTERACTIVE_SEEN=true \\     &amp;&amp; apt-get -q update \\     &amp;&amp; apt-get -q dist-upgrade -y \\     &amp;&amp; apt-get -q install -y \\<\/code><\/pre>\n<\/div>\n<\/details>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-457692","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/457692","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=457692"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/457692\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=457692"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=457692"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=457692"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}