{"id":307926,"date":"2020-08-03T21:00:35","date_gmt":"2020-08-03T21:00:35","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=307926"},"modified":"-0001-11-30T00:00:00","modified_gmt":"2020-08-03T21:00:35","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=307926","title":{"rendered":"Javascript \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0430 Objectum"},"content":{"rendered":"\n<div class=\"post__text post__text-html post__text_v1\" id=\"post-content-body\" data-io-article-url=\"https:\/\/habr.com\/ru\/post\/513648\/\">\n<p>\u0415\u0441\u043b\u0438 \u0432\u0430\u043c \u043d\u0443\u0436\u0435\u043d \u043f\u0440\u043e\u0441\u0442\u043e\u0439 \u0441\u043f\u043e\u0441\u043e\u0431 \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c \u0432\u0435\u0431-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f \u0442\u043e\u043b\u044c\u043a\u043e javascript (full-stack), \u0442\u043e \u043f\u0440\u0435\u0434\u043b\u0430\u0433\u0430\u044e \u0432\u0430\u043c \u043e\u0437\u043d\u0430\u043a\u043e\u043c\u0438\u0442\u044c\u0441\u044f \u0441 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u043e\u0439 objectum. \u041d\u043e\u0432\u0430\u044f \u0432\u0435\u0440\u0441\u0438\u044f \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u044b \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u043e\u043c \u043e\u043f\u044b\u0442\u0430 \u0440\u0430\u0431\u043e\u0442\u044b \u043d\u0430\u0434 \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0435\u0439 \u0432\u0435\u0440\u0441\u0438\u0435\u0439, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f 10 \u043b\u0435\u0442. \u041e\u0431\u0435 \u0432\u0435\u0440\u0441\u0438\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442\u0441\u044f \u0432 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0435 \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0445 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u043e\u043d\u043d\u044b\u0445 \u0441\u0438\u0441\u0442\u0435\u043c \u2014 \u044d\u0442\u043e \u0440\u0435\u0433\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u044b\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u044f \u0438 \u0441\u0438\u0441\u0442\u0435\u043c\u044b \u0434\u043b\u044f \u043e\u0440\u0433\u0430\u043d\u0438\u0437\u0430\u0446\u0438\u0439. \u041f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0430 \u043d\u043e\u0432\u043e\u0439 \u0432\u0435\u0440\u0441\u0438\u0438 \u0443\u0436\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u043d\u0430 \u043f\u0440\u043e\u0434\u0430\u043a\u0448\u043d \u0441\u0435\u0440\u0432\u0435\u0440\u0430\u0445 \u0438 \u0431\u0443\u0434\u0435\u0442 \u0440\u0430\u0437\u0432\u0438\u0432\u0430\u0442\u044c\u0441\u044f \u0434\u043b\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0435 \u0432\u0440\u0435\u043c\u044f. \u0414\u0430\u043b\u0435\u0435 \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e\u0441\u0442\u0438.<\/p>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/webt\/ae\/e5\/80\/aee580edcg_urdy37zuwrrst38y.png\" alt=\"logo\"\/><\/p>\n<p><a name=\"habracut\"><\/a>  <\/p>\n<h3 id=\"skriny-iz-suschestvuyuschih-razrabotok\">\u0421\u043a\u0440\u0438\u043d\u044b \u0438\u0437 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0445 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043e\u043a<\/h3>\n<p>  <\/p>\n<p>\u041f\u0440\u0438\u043c\u0435\u0440 \u0432\u0435\u0431-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f:<\/p>\n<p>  <\/p>\n<hr\/>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/webt\/u7\/qs\/0w\/u7qs0wvvsjw14l_t0lhzxde4xss.png\" alt=\"\u041f\u0440\u0438\u043c\u0435\u0440 1\"\/><\/p>\n<p>  <\/p>\n<hr\/>\n<p>  <\/p>\n<p>\u041f\u0440\u0438\u043c\u0435\u0440 \u0441\u0430\u0439\u0442\u0430 (\u0431\u0435\u0437 \u0441\u0435\u0440\u0432\u0435\u0440\u043d\u043e\u0433\u043e \u0440\u0435\u043d\u0434\u0435\u0440\u0430):<\/p>\n<p>  <\/p>\n<hr\/>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/webt\/7a\/4y\/_t\/7a4y_tw-zrpwivwt7kx-udvqgyu.png\" alt=\"\u041f\u0440\u0438\u043c\u0435\u0440 2\"\/><\/p>\n<p>  <\/p>\n<hr\/>\n<p>  <\/p>\n<h2 id=\"pakety-platformy\">\u041f\u0430\u043a\u0435\u0442\u044b \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u044b<\/h2>\n<p>  <\/p>\n<p>\u041f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0430 \u0441\u043e\u0441\u0442\u043e\u0438\u0442 \u0438\u0437 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0445 npm \u043f\u0430\u043a\u0435\u0442\u043e\u0432: <a href=\"https:\/\/github.com\/objectum\/objectum\">objectum<\/a>, <a href=\"https:\/\/github.com\/objectum\/objectum-client\">objectum-client<\/a>, <a href=\"https:\/\/github.com\/objectum\/objectum-proxy\">objectum-proxy<\/a>, <a href=\"https:\/\/github.com\/objectum\/objectum-react\">objectum-react<\/a>, <a href=\"https:\/\/github.com\/objectum\/objectum-cli\">objectum-cli<\/a> <\/p>\n<p>  <\/p>\n<h3 id=\"objectum\">objectum<\/h3>\n<p>  <\/p>\n<p>\u0421\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u0441\u0430\u043c\u0430 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0430, \u0441\u0435\u0440\u0432\u0435\u0440 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439. \u0420\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d ORM \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 PostgreSQL. \u0420\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0431\u044b\u0441\u0442\u0440\u043e \u0431\u043b\u0430\u0433\u043e\u0434\u0430\u0440\u044f \u043d\u0430\u0431\u043e\u0440\u0443 \u0442\u0440\u0438\u0433\u0433\u0435\u0440\u043e\u0432 \u0438 \u0444\u0443\u043d\u043a\u0446\u0438\u0439 (Objectum Database Engine), \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u043d\u044b\u0445 \u043d\u0430 PL\/pgSQL. \u041a\u044d\u0448\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0432 Redis. \u041c\u043e\u0436\u0435\u0442 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0432 node cluster. \u0418\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0434\u0430\u043d\u043d\u044b\u0445 \u0436\u0443\u0440\u043d\u0430\u043b\u0438\u0440\u0443\u044e\u0442\u0441\u044f \u0438 \u0432 \u0441\u043b\u0443\u0447\u0430\u0435 \u0447\u0435\u0433\u043e \u0432\u0438\u043d\u043e\u0432\u043d\u0438\u043a\u0430 \u043d\u0430\u0439\u0442\u0438 \u043d\u0435 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0430.<br \/>  \u2028<\/p>\n<p>  <\/p>\n<h3 id=\"objectum-client\">objectum-client<\/h3>\n<p>  <\/p>\n<p>\u0418\u0437\u043e\u043c\u043e\u0440\u0444\u043d\u044b\u0439 \u043a\u043b\u0438\u0435\u043d\u0442 \u0434\u043b\u044f \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f \u0441 objectum-proxy \u0438\u043b\u0438 objectum. \u0418\u0441\u0445\u043e\u0434\u043d\u044b\u0439 \u043a\u043e\u0434, \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0449\u0438\u0439 \u0441 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435\u043c, \u0431\u0435\u0437 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0439 \u043c\u043e\u0436\u043d\u043e \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c \u043d\u0430 \u043a\u043b\u0438\u0435\u043d\u0442\u0435 \u0438\u043b\u0438 \u0441\u0435\u0440\u0432\u0435\u0440\u0435. \u041a\u043b\u0438\u0435\u043d\u0442 \u0443\u0434\u043e\u0431\u043d\u044b\u0439, \u043d\u043e \u0435\u0441\u043b\u0438 \u043d\u0443\u0436\u043d\u043e, \u0442\u043e \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u043e\u0432\u0430\u0442\u044c \u0441 \u0441\u0435\u0440\u0432\u0435\u0440\u043e\u043c \u043c\u043e\u0436\u043d\u043e \u0431\u0435\u0437 \u043a\u043b\u0438\u0435\u043d\u0442\u0430 \u0442.\u043a. \u0437\u0430\u043f\u0440\u043e\u0441\u044b, \u043e\u0442\u0432\u0435\u0442\u044b \u0432 JSON. <\/p>\n<p>  <\/p>\n<h3 id=\"objectum-proxy\">objectum-proxy<\/h3>\n<p>  <\/p>\n<p>\u041f\u0440\u043e\u043a\u0441\u0438 \u0440\u0430\u0441\u043f\u043e\u043b\u043e\u0436\u0435\u043d \u043c\u0435\u0436\u0434\u0443 objectum \u0438 objectum-client. \u0412\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u0437\u0430\u0434\u0430\u0447\u0438:<\/p>\n<p>  <\/p>\n<ul>\n<li>\u0412\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u0441\u0435\u0440\u0432\u0435\u0440\u043d\u044b\u0445 \u043c\u0435\u0442\u043e\u0434\u043e\u0432 \u043c\u043e\u0434\u0435\u043b\u0435\u0439<\/li>\n<li>\u0412\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u0441\u0435\u0440\u0432\u0435\u0440\u043d\u044b\u0445 \u043c\u0435\u0442\u043e\u0434\u043e\u0432 \u0441 \u043f\u0440\u0430\u0432\u0430\u043c\u0438 \u0430\u0434\u043c\u0438\u043d\u0438\u0441\u0442\u0440\u0430\u0442\u043e\u0440\u0430<\/li>\n<li>\u041a\u043e\u043d\u0442\u0440\u043e\u043b\u044c \u0434\u043e\u0441\u0442\u0443\u043f\u0430 \u043a \u0431\u0430\u0437\u0435 \u0434\u0430\u043d\u043d\u044b\u0445. \u041e\u0442\u0441\u043b\u0435\u0436\u0438\u0432\u0430\u044e\u0442\u0441\u044f \u0432\u0441\u0435 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f \u2014 \u044d\u0442\u043e \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f CRUD \u0438 \u0432\u044b\u0431\u043e\u0440\u043a\u0430 \u0434\u0430\u043d\u043d\u044b\u0445 \u0447\u0435\u0440\u0435\u0437 SQL.<\/li>\n<li>\u0417\u0430\u0433\u0440\u0443\u0437\u043a\u0430 \u0438 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0435 \u0444\u0430\u0439\u043b\u043e\u0432<\/li>\n<\/ul>\n<p>  <\/p>\n<h3 id=\"objectum-react\">objectum-react<\/h3>\n<p>  <\/p>\n<p>\u041d\u0430\u0431\u043e\u0440 react \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432 UI. \u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442\u0441\u044f bootstrap \u0438 fontawesome. \u0411\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 redux, mobx \u043d\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442\u0441\u044f.<br \/>  \u041e\u0444\u043e\u0440\u043c\u043b\u0435\u043d\u0438\u0435 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0430\u0435\u0442\u0441\u044f \u0432 App.js. \u041f\u043e\u0434 \u043a\u0430\u0436\u0434\u044b\u0439 \u043f\u0440\u043e\u0435\u043a\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e \u0440\u0430\u0437\u043d\u044b\u0435 bootstrap.css:<\/p>\n<p>  <\/p>\n<pre><code class=\"javascript\">import &quot;objectum-react\/lib\/css\/bootstrap.css&quot;; import &quot;objectum-react\/lib\/css\/objectum.css&quot;; import &quot;objectum-react\/lib\/fontawesome\/css\/all.css&quot;;<\/code><\/pre>\n<p>  <\/p>\n<h3 id=\"objectum-cli\">objectum-cli<\/h3>\n<p>  <\/p>\n<p>\u0423\u0442\u0438\u043b\u0438\u0442\u0430 \u043a\u043e\u043c\u0430\u043d\u0434\u043d\u043e\u0439 \u0441\u0442\u0440\u043e\u043a\u0438. \u0412\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442 \u0441\u0435\u0440\u0432\u0438\u0441\u043d\u044b\u0435 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f \u0441 \u043f\u0440\u043e\u0435\u043a\u0442\u0430\u043c\u0438, \u0432\u043a\u043b\u044e\u0447\u0430\u044f \u0431\u0430\u0437\u044b \u0434\u0430\u043d\u043d\u044b\u0445. \u0423\u0434\u043e\u0431\u0435\u043d \u0434\u043b\u044f \u0431\u044b\u0441\u0442\u0440\u043e\u0433\u043e \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u043c\u043e\u0434\u0435\u043b\u0435\u0439 \u0438 \u0437\u0430\u043f\u0438\u0441\u0435\u0439.<\/p>\n<p>  <\/p>\n<h1 id=\"razrabotka\">\u0420\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0430<\/h1>\n<p>  <\/p>\n<p>\u0427\u0442\u043e\u0431\u044b \u043d\u0435 \u0431\u044b\u0442\u044c \u043c\u043d\u043e\u0433\u043e\u0441\u043b\u043e\u0432\u043d\u044b\u043c, \u0432 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u043d\u0430\u043f\u0438\u0448\u0443 \u043e \u0441\u0430\u043c\u043e\u043c \u043f\u0440\u043e\u0441\u0442\u043e\u043c \u043f\u043e\u0434\u0445\u043e\u0434\u0435, \u0433\u0434\u0435 \u043d\u0435 \u043d\u0443\u0436\u043d\u043e \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c \u0441\u0432\u043e\u0438 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b React. \u0412 \u0441\u0432\u043e\u0438\u0445 \u043f\u0440\u043e\u0435\u043a\u0442\u0430\u0445 \u044f \u0441\u0442\u0430\u0440\u0430\u044e\u0441\u044c \u043f\u043e \u043c\u0430\u043a\u0441\u0438\u043c\u0443\u043c\u0443 \u0432\u0441\u044e \u0441\u0438\u0441\u0442\u0435\u043c\u0443 \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0442\u0430\u043a\u0438\u043c \u0441\u043f\u043e\u0441\u043e\u0431\u043e\u043c. \u0414\u043b\u044f \u0441\u043b\u043e\u0436\u043d\u044b\u0445 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u043e\u0432 \u043d\u0443\u0436\u043d\u043e \u043f\u0438\u0441\u0430\u0442\u044c \u0441\u0432\u043e\u0438 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b, \u0433\u0434\u0435 \u0443\u0434\u043e\u0431\u043d\u043e \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0430\u0442\u044c \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b \u0438\u0437 objectum-react.<br \/>  \u0422\u0435\u043f\u0435\u0440\u044c \u043f\u043e \u043f\u043e\u0440\u044f\u0434\u043a\u0443 \u043a\u0430\u043a \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u043f\u0440\u043e\u0435\u043a\u0442 objectum. \u041f\u0435\u0440\u0435\u0434 \u043d\u0430\u0447\u0430\u043b\u043e\u043c \u0443\u0431\u0435\u0434\u0438\u0442\u0435\u0441\u044c, \u0447\u0442\u043e \u0443 \u0432\u0430\u0441 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u044b NodeJS, PostgreSQL \u0438 Redis.<br \/>  \u0413\u043e\u0442\u043e\u0432\u044b\u0439 \u0434\u0435\u043c\u043e-\u043f\u0440\u043e\u0435\u043a\u0442 <strong>catalog<\/strong> \u0432\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c <a href=\"https:\/\/github.com\/objectum\/catalog\">\u043e\u0442\u0441\u044e\u0434\u0430<\/a>.<\/p>\n<p>  <\/p>\n<hr\/>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/webt\/9l\/au\/ms\/9laumspf9bsqcvhunuinxas0_wq.png\" alt=\"catalog\"\/><\/p>\n<p>  <\/p>\n<hr\/>\n<p>  <\/p>\n<h2 id=\"ustanovka-platformy\">\u0423\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u044b<\/h2>\n<p>  <\/p>\n<p>\u0423\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u043c \u0443\u0442\u0438\u043b\u0438\u0442\u0443 \u043a\u043e\u043c\u0430\u043d\u0434\u043d\u043e\u0439 \u0441\u0442\u0440\u043e\u043a\u0438:<\/p>\n<p>  <\/p>\n<pre><code class=\"bash\">npm i -g objectum-cli<\/code><\/pre>\n<p>  <\/p>\n<p>\u0423\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u043c \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0443 \u0432 \u043f\u0430\u043f\u043a\u0443 \/opt\/objectum<\/p>\n<p>  <\/p>\n<pre><code class=\"bash\">mkdir \/opt\/objectum objectum-cli --create-platform --path \/opt\/objectum<\/code><\/pre>\n<p>  <\/p>\n<p>\u0433\u0434\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e:<\/p>\n<p>  <\/p>\n<pre><code class=\"plaintext\">--redis-host 127.0.0.1 - \u0445\u043e\u0441\u0442 \u0438 \u043f\u043e\u0440\u0442 \u0441\u0435\u0440\u0432\u0435\u0440\u0430 Redis --redis-port 6379 --objectum-port 8200 - \u043f\u043e\u0440\u0442, \u0433\u0434\u0435 \u0431\u0443\u0434\u0435\u0442 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c objectum<\/code><\/pre>\n<p>  <\/p>\n<h2 id=\"sozdanie-proekta\">\u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u043f\u0440\u043e\u0435\u043a\u0442\u0430<\/h2>\n<p>  <\/p>\n<p>\u0421\u043e\u0437\u0434\u0430\u0435\u043c \u043f\u0440\u043e\u0435\u043a\u0442 &quot;catalog&quot;:<\/p>\n<p>  <\/p>\n<pre><code class=\"bash\">objectum-cli --create-project catalog --path \/opt\/objectum<\/code><\/pre>\n<p>  <\/p>\n<p>\u041f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e:<\/p>\n<p>  <\/p>\n<pre><code class=\"plaintext\">--project-port 3100 - \u043f\u043e\u0440\u0442, \u0433\u0434\u0435 \u0431\u0443\u0434\u0435\u0442 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u043f\u0440\u043e\u0435\u043a\u0442 --db-host 127.0.0.1 - \u0445\u043e\u0441\u0442 \u0438 \u043f\u043e\u0440\u0442 \u0441\u0435\u0440\u0432\u0435\u0440\u0430 PostgreSQL --db-port 5432 --db-dbPassword 1 - \u043f\u0430\u0440\u043e\u043b\u044c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f catalog --db-dbaPassword 12345 - \u043f\u0430\u0440\u043e\u043b\u044c \u0430\u0434\u043c\u0438\u043d\u0438\u0441\u0442\u0440\u0430\u0442\u043e\u0440\u0430 postgres --password admin - \u043f\u0430\u0440\u043e\u043b\u044c \u0430\u0434\u043c\u0438\u043d\u0438\u0441\u0442\u0440\u0430\u0442\u043e\u0440\u0430 \u043f\u0440\u043e\u0435\u043a\u0442\u0430<\/code><\/pre>\n<p>  <\/p>\n<p>\u041f\u0430\u043f\u043a\u0430 \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u0441\u043e\u0437\u0434\u0430\u0435\u0442\u0441\u044f \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u043e\u043c create-react-app. \u041d\u0430 \u043a\u043b\u0438\u0435\u043d\u0442\u0435 \u0438 \u0441\u0435\u0440\u0432\u0435\u0440\u0435 \u043c\u043e\u0434\u0443\u043b\u0438 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0430\u044e\u0442\u0441\u044f \u043a\u0430\u043a ES Modules.<\/p>\n<p>  <\/p>\n<h2 id=\"zapusk\">\u0417\u0430\u043f\u0443\u0441\u043a<\/h2>\n<p>  <\/p>\n<p>\u0417\u0430\u043f\u0443\u0441\u043a \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u044b:<\/p>\n<p>  <\/p>\n<pre><code class=\"bash\">cd \/opt\/objectum\/server  node index-8200.js<\/code><\/pre>\n<p>  <\/p>\n<p>\u0417\u0430\u043f\u0443\u0441\u043a \u043f\u0440\u043e\u0435\u043a\u0442\u0430:<\/p>\n<p>  <\/p>\n<pre><code class=\"bash\">cd \/opt\/objectum\/projects\/catalog  node index-3100.js npm start<\/code><\/pre>\n<p>  <\/p>\n<p>\u0414\u043e\u043b\u0436\u043d\u0430 \u043e\u0442\u043a\u0440\u044b\u0442\u044c\u0441\u044f \u0441\u0441\u044b\u043b\u043a\u0430 <a href=\"http:\/\/localhost:3000\">http:\/\/localhost:3000<\/a><br \/>  \u0412 \u043e\u043a\u043d\u0435 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438 \u0432 \u043f\u043e\u043b\u044f\u0445 \u043b\u043e\u0433\u0438\u043d, \u043f\u0430\u0440\u043e\u043b\u044c \u0432\u0432\u043e\u0434\u0438\u043c: admin <\/p>\n<p>  <\/p>\n<hr\/>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/webt\/kv\/jj\/f1\/kvjjf1sbewbv7lovbbjjpoyrjlw.png\" alt=\"auth\"\/><\/p>\n<p>  <\/p>\n<hr\/>\n<p>  <\/p>\n<h2 id=\"instrumenty-razrabotchika\">\u0418\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u044b \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0430<\/h2>\n<p>  <\/p>\n<p>\u041c\u0435\u043d\u044e &quot;Objectum&quot; \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u043f\u0443\u043d\u043a\u0442\u044b: <\/p>\n<p>  <\/p>\n<ul>\n<li>\u041c\u043e\u0434\u0435\u043b\u0438 \u2014 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u043c\u043e\u0434\u0435\u043b\u0435\u0439 \u0438 \u0441\u0432\u043e\u0439\u0441\u0442\u0432<\/li>\n<li>\u0417\u0430\u043f\u0440\u043e\u0441\u044b \u2014 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0435 SQL \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u0434\u043b\u044f \u0432\u044b\u0431\u043e\u0440\u043a\u0438 \u0434\u0430\u043d\u043d\u044b\u0445<\/li>\n<li>\u041c\u0435\u043d\u044e \u2014 \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440 \u043c\u0435\u043d\u044e \u0434\u043b\u044f \u0440\u043e\u043b\u0435\u0439 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439<\/li>\n<li>\u0420\u043e\u043b\u0438 \u2014 \u0437\u0434\u0435\u0441\u044c \u0437\u0430\u0434\u0430\u0435\u0442\u0441\u044f \u0441\u043f\u0438\u0441\u043e\u043a \u0440\u043e\u043b\u0435\u0439 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439<\/li>\n<li>\u041f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0438 \u2014 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439<\/li>\n<\/ul>\n<p>  <\/p>\n<hr\/>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/webt\/s8\/qf\/k_\/s8qfk_qdzqxkuzncay-devmxcmy.png\" alt=\"auth\"\/><\/p>\n<p>  <\/p>\n<hr\/>\n<p>  <\/p>\n<h2 id=\"paketnoe-dobavlenie-dannyh-v-hranilische\">\u041f\u0430\u043a\u0435\u0442\u043d\u043e\u0435 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0434\u0430\u043d\u043d\u044b\u0445 \u0432 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435<\/h2>\n<p>  <\/p>\n<p>\u0421\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0430 \u0444\u043e\u0440\u043c\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e UI, \u043d\u043e \u0434\u043b\u044f \u0431\u044b\u0441\u0442\u0440\u043e\u0433\u043e \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0431\u043e\u043b\u044c\u0448\u043e\u0433\u043e \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u0430 \u0434\u0430\u043d\u043d\u044b\u0445 \u043b\u0443\u0447\u0448\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c objectum-cli. <\/p>\n<p>  <\/p>\n<h3 id=\"import-json\">\u0418\u043c\u043f\u043e\u0440\u0442 JSON<\/h3>\n<p>  <\/p>\n<pre><code class=\"bash\">cd \/opt\/objectum\/projects\/catalog   objectum-cli --import-json scripts\/catalog-cli.json --file-directory scripts\/files<\/code><\/pre>\n<p>  <\/p>\n<div class=\"spoiler\" role=\"button\" tabindex=\"0\">                         <b class=\"spoiler_title\">\u0417\u0434\u0435\u0441\u044c \u0441\u043a\u0440\u0438\u043f\u0442 catalog-cli.json<\/b>                         <\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"json\">{     &quot;createModel&quot;: [         {             &quot;name&quot;: &quot;Item&quot;,              &quot;code&quot;: &quot;item&quot;         },         {             &quot;name&quot;: &quot;Item&quot;,              &quot;code&quot;: &quot;item&quot;,             &quot;parent&quot;: &quot;d&quot;         },         {             &quot;name&quot;: &quot;Type&quot;,              &quot;code&quot;: &quot;type&quot;,             &quot;parent&quot;: &quot;d.item&quot;         },         {             &quot;name&quot;: &quot;Item&quot;,              &quot;code&quot;: &quot;item&quot;,             &quot;parent&quot;: &quot;t&quot;         },         {             &quot;name&quot;: &quot;Comment&quot;,              &quot;code&quot;: &quot;comment&quot;,             &quot;parent&quot;: &quot;t.item&quot;         }     ],     &quot;createProperty&quot;: [         {             &quot;model&quot;: &quot;d.item.type&quot;,              &quot;name&quot;: &quot;Name&quot;,              &quot;code&quot;: &quot;name&quot;,             &quot;type&quot;: &quot;string&quot;         },         {             &quot;model&quot;: &quot;t.item.comment&quot;,              &quot;name&quot;: &quot;Item&quot;,              &quot;code&quot;: &quot;item&quot;,             &quot;type&quot;: &quot;item&quot;         },         {             &quot;model&quot;: &quot;t.item.comment&quot;,              &quot;name&quot;: &quot;Date&quot;,             &quot;code&quot;: &quot;date&quot;,             &quot;type&quot;: &quot;date&quot;         },         {             &quot;model&quot;: &quot;t.item.comment&quot;,             &quot;name&quot;: &quot;Text&quot;,             &quot;code&quot;: &quot;text&quot;,             &quot;type&quot;: &quot;string&quot;         },         {             &quot;model&quot;: &quot;item&quot;,              &quot;name&quot;: &quot;Date&quot;,              &quot;code&quot;: &quot;date&quot;,             &quot;type&quot;: &quot;date&quot;         },         {             &quot;model&quot;: &quot;item&quot;,              &quot;name&quot;: &quot;Name&quot;,              &quot;code&quot;: &quot;name&quot;,             &quot;type&quot;: &quot;string&quot;         },         {             &quot;model&quot;: &quot;item&quot;,             &quot;name&quot;: &quot;Description&quot;,             &quot;code&quot;: &quot;description&quot;,             &quot;type&quot;: &quot;string&quot;,             &quot;opts&quot;: {                 &quot;wysiwyg&quot;: true             }         },         {             &quot;model&quot;: &quot;item&quot;,              &quot;name&quot;: &quot;Cost&quot;,              &quot;code&quot;: &quot;cost&quot;,             &quot;type&quot;: &quot;number&quot;,             &quot;opts&quot;: {                 &quot;min&quot;: 0             }         },         {             &quot;model&quot;: &quot;item&quot;,              &quot;name&quot;: &quot;Type&quot;,              &quot;code&quot;: &quot;type&quot;,             &quot;type&quot;: &quot;d.item.type&quot;         },         {             &quot;model&quot;: &quot;item&quot;,              &quot;name&quot;: &quot;Photo&quot;,              &quot;code&quot;: &quot;photo&quot;,             &quot;type&quot;: &quot;file&quot;,             &quot;opts&quot;: {                 &quot;image&quot;: {                     &quot;width&quot;: 300,                     &quot;height&quot;: 200,                     &quot;aspect&quot;: 1.5                 }             }         }     ],     &quot;createQuery&quot;: [         {             &quot;name&quot;: &quot;Item&quot;,             &quot;code&quot;: &quot;item&quot;         },         {             &quot;name&quot;: &quot;List&quot;,             &quot;code&quot;: &quot;list&quot;,             &quot;parent&quot;: &quot;item&quot;,             &quot;query&quot;: [                 &quot;{\\&quot;data\\&quot;: \\&quot;begin\\&quot;}&quot;,                 &quot;select&quot;,                 &quot;    {\\&quot;prop\\&quot;: \\&quot;a.id\\&quot;, \\&quot;as\\&quot;: \\&quot;id\\&quot;},&quot;,                 &quot;    {\\&quot;prop\\&quot;: \\&quot;a.name\\&quot;, \\&quot;as\\&quot;: \\&quot;name\\&quot;},&quot;,                 &quot;    {\\&quot;prop\\&quot;: \\&quot;a.description\\&quot;, \\&quot;as\\&quot;: \\&quot;description\\&quot;},&quot;,                 &quot;    {\\&quot;prop\\&quot;: \\&quot;a.cost\\&quot;, \\&quot;as\\&quot;: \\&quot;cost\\&quot;},&quot;,                 &quot;    {\\&quot;prop\\&quot;: \\&quot;a.date\\&quot;, \\&quot;as\\&quot;: \\&quot;date\\&quot;},&quot;,                 &quot;    {\\&quot;prop\\&quot;: \\&quot;a.photo\\&quot;, \\&quot;as\\&quot;: \\&quot;photo\\&quot;},&quot;,                 &quot;    {\\&quot;prop\\&quot;: \\&quot;a.type\\&quot;, \\&quot;as\\&quot;: \\&quot;type\\&quot;}&quot;,                 &quot;{\\&quot;data\\&quot;: \\&quot;end\\&quot;}&quot;,                 &quot;&quot;,                 &quot;{\\&quot;count\\&quot;: \\&quot;begin\\&quot;}&quot;,                 &quot;select&quot;,                 &quot;    count (*) as num&quot;,                 &quot;{\\&quot;count\\&quot;: \\&quot;end\\&quot;}&quot;,                 &quot;&quot;,                 &quot;from&quot;,                 &quot;    {\\&quot;model\\&quot;: \\&quot;item\\&quot;, \\&quot;alias\\&quot;: \\&quot;a\\&quot;}&quot;,                 &quot;&quot;,                 &quot;{\\&quot;where\\&quot;: \\&quot;empty\\&quot;}&quot;,                 &quot;&quot;,                 &quot;{\\&quot;order\\&quot;: \\&quot;empty\\&quot;}&quot;,                 &quot;&quot;,                 &quot;limit {\\&quot;param\\&quot;: \\&quot;limit\\&quot;}&quot;,                 &quot;offset {\\&quot;param\\&quot;: \\&quot;offset\\&quot;}&quot;             ]         },         {             &quot;name&quot;: &quot;Item&quot;,             &quot;code&quot;: &quot;item&quot;,             &quot;parent&quot;: &quot;t&quot;         },         {             &quot;name&quot;: &quot;Comment&quot;,             &quot;code&quot;: &quot;comment&quot;,             &quot;parent&quot;: &quot;t.item&quot;,             &quot;query&quot;: [                 &quot;{\\&quot;data\\&quot;: \\&quot;begin\\&quot;}&quot;,                 &quot;select&quot;,                 &quot;    {\\&quot;prop\\&quot;: \\&quot;a.id\\&quot;, \\&quot;as\\&quot;: \\&quot;id\\&quot;},&quot;,                 &quot;    {\\&quot;prop\\&quot;: \\&quot;a.item\\&quot;, \\&quot;as\\&quot;: \\&quot;item\\&quot;},&quot;,                 &quot;    {\\&quot;prop\\&quot;: \\&quot;a.date\\&quot;, \\&quot;as\\&quot;: \\&quot;date\\&quot;},&quot;,                 &quot;    {\\&quot;prop\\&quot;: \\&quot;a.text\\&quot;, \\&quot;as\\&quot;: \\&quot;text\\&quot;}&quot;,                 &quot;{\\&quot;data\\&quot;: \\&quot;end\\&quot;}&quot;,                 &quot;&quot;,                 &quot;{\\&quot;count\\&quot;: \\&quot;begin\\&quot;}&quot;,                 &quot;select&quot;,                 &quot;    count (*) as num&quot;,                 &quot;{\\&quot;count\\&quot;: \\&quot;end\\&quot;}&quot;,                 &quot;&quot;,                 &quot;from&quot;,                 &quot;    {\\&quot;model\\&quot;: \\&quot;t.item.comment\\&quot;, \\&quot;alias\\&quot;: \\&quot;a\\&quot;}&quot;,                 &quot;&quot;,                 &quot;{\\&quot;where\\&quot;: \\&quot;empty\\&quot;}&quot;,                 &quot;&quot;,                 &quot;{\\&quot;order\\&quot;: \\&quot;empty\\&quot;}&quot;,                 &quot;&quot;,                 &quot;limit {\\&quot;param\\&quot;: \\&quot;limit\\&quot;}&quot;,                 &quot;offset {\\&quot;param\\&quot;: \\&quot;offset\\&quot;}&quot;             ]         }     ],     &quot;createRecord&quot;: [         {             &quot;_model&quot;: &quot;d.item.type&quot;,             &quot;name&quot;: &quot;Videocard&quot;,             &quot;_ref&quot;: &quot;videocardType&quot;         },         {             &quot;_model&quot;: &quot;d.item.type&quot;,             &quot;name&quot;: &quot;Processor&quot;         },         {             &quot;_model&quot;: &quot;d.item.type&quot;,             &quot;name&quot;: &quot;Motherboard&quot;         },         {             &quot;_model&quot;: &quot;objectum.menu&quot;,             &quot;name&quot;: &quot;User&quot;,             &quot;code&quot;: &quot;user&quot;,             &quot;_ref&quot;: &quot;userMenu&quot;         },         {             &quot;_model&quot;: &quot;objectum.menuItem&quot;,             &quot;menu&quot;: {                 &quot;_ref&quot;: &quot;userMenu&quot;             },             &quot;name&quot;: &quot;Items&quot;,             &quot;icon&quot;: &quot;fas fa-list&quot;,             &quot;order&quot;: 1,             &quot;path&quot;: &quot;\/model_list\/item&quot;         },         {             &quot;_model&quot;: &quot;objectum.menuItem&quot;,             &quot;menu&quot;: {                 &quot;_ref&quot;: &quot;userMenu&quot;             },             &quot;name&quot;: &quot;Dictionary&quot;,             &quot;icon&quot;: &quot;fas fa-book&quot;,             &quot;order&quot;: 2,             &quot;_ref&quot;: &quot;dictionaryMenuItem&quot;         },         {             &quot;_model&quot;: &quot;objectum.menuItem&quot;,             &quot;menu&quot;: {                 &quot;_ref&quot;: &quot;userMenu&quot;             },             &quot;name&quot;: &quot;Item type&quot;,             &quot;icon&quot;: &quot;fas fa-book&quot;,             &quot;parent&quot;: {                 &quot;_ref&quot;: &quot;dictionaryMenuItem&quot;             },             &quot;order&quot;: 1,             &quot;path&quot;: &quot;\/model_list\/d_item_type&quot;         },         {             &quot;_model&quot;: &quot;objectum.role&quot;,             &quot;name&quot;: &quot;User&quot;,             &quot;code&quot;: &quot;user&quot;,             &quot;menu&quot;: {                 &quot;_ref&quot;: &quot;userMenu&quot;             },             &quot;_ref&quot;: &quot;userRole&quot;         },         {             &quot;_model&quot;: &quot;objectum.user&quot;,             &quot;name&quot;: &quot;User&quot;,             &quot;login&quot;: &quot;user&quot;,             &quot;password&quot;: &quot;user&quot;,             &quot;role&quot;: {                 &quot;_ref&quot;: &quot;userRole&quot;             }         },         {             &quot;_model&quot;: &quot;objectum.menu&quot;,             &quot;name&quot;: &quot;Guest&quot;,             &quot;code&quot;: &quot;guest&quot;,             &quot;_ref&quot;: &quot;guestMenu&quot;         },         {             &quot;_model&quot;: &quot;objectum.menuItem&quot;,             &quot;menu&quot;: {                 &quot;_ref&quot;: &quot;guestMenu&quot;             },             &quot;name&quot;: &quot;Items&quot;,             &quot;icon&quot;: &quot;fas fa-list&quot;,             &quot;order&quot;: 1,             &quot;path&quot;: &quot;\/model_list\/item&quot;         },         {             &quot;_model&quot;: &quot;objectum.role&quot;,             &quot;name&quot;: &quot;Guest&quot;,             &quot;code&quot;: &quot;guest&quot;,             &quot;menu&quot;: {                 &quot;_ref&quot;: &quot;guestMenu&quot;             },             &quot;_ref&quot;: &quot;guestRole&quot;         },         {             &quot;_model&quot;: &quot;objectum.user&quot;,             &quot;name&quot;: &quot;Guest&quot;,             &quot;login&quot;: &quot;guest&quot;,             &quot;password&quot;: &quot;guest&quot;,             &quot;role&quot;: {                 &quot;_ref&quot;: &quot;guestRole&quot;             }         },         {             &quot;_model&quot;: &quot;item&quot;,             &quot;name&quot;: &quot;RTX 2080&quot;,             &quot;description&quot;: [                 &quot;&lt;ul&gt;&quot;,                 &quot;&lt;li&gt;11GB GDDR6&lt;\/span&gt;&lt;\/li&gt;&quot;,                 &quot;&lt;li&gt;CUDA Cores: 4352&lt;\/span&gt;&lt;\/li&gt;&quot;,                 &quot;&lt;li&gt;Display Connectors: DisplayPort, HDMI, USB Type-C&lt;\/span&gt;&lt;\/li&gt;&quot;,                 &quot;&lt;li&gt;Maximum Digital Resolution: 7680x4320&lt;\/span&gt;&lt;\/li&gt;&quot;,                 &quot;&lt;\/ul&gt;&quot;             ],             &quot;date&quot;: &quot;2020-06-03T19:27:38.292Z&quot;,             &quot;type&quot;: {                 &quot;_ref&quot;: &quot;videocardType&quot;             },             &quot;cost&quot;: &quot;800&quot;,             &quot;photo&quot;: &quot;rtx2080.png&quot;         }     ] }<\/code><\/pre>\n<\/div><\/div>\n<p>  <\/p>\n<p>\u0427\u0442\u043e \u0432\u0441\u0451 \u044d\u0442\u043e \u0437\u043d\u0430\u0447\u0438\u0442:<\/p>\n<p>  <\/p>\n<ul>\n<li>createModel \u2014 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u043c\u043e\u0434\u0435\u043b\u0435\u0439, \u0433\u0434\u0435 name \u2014 \u043d\u0430\u0438\u043c\u0435\u043d\u043e\u0432\u0430\u043d\u0438\u0435, code \u2014 \u0442\u0435\u043a\u0441\u0442\u043e\u0432\u044b\u0439 \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440, parent \u2014 \u0440\u043e\u0434\u0438\u0442\u0435\u043b\u044c. \u0418\u0435\u0440\u0430\u0440\u0445\u0438\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0434\u043b\u044f \u0433\u0440\u0443\u043f\u043f\u0438\u0440\u043e\u0432\u043a\u0438 \u043c\u043e\u0434\u0435\u043b\u0435\u0439.<br \/> \n<ul>\n<li>\u0412 \u043f\u0440\u0438\u043c\u0435\u0440\u0435 \u0441\u043e\u0437\u0434\u0430\u044e\u0442\u0441\u044f \u043c\u043e\u0434\u0435\u043b\u0438 item, d.item.type, t.item.comment.<\/li>\n<li>\u041c\u043e\u0434\u0435\u043b\u044c &quot;d.item.type&quot; \u2014 \u044d\u0442\u043e \u0441\u043f\u0440\u0430\u0432\u043e\u0447\u043d\u0438\u043a. \u0412 \u043c\u043e\u0434\u0435\u043b\u0438 &quot;item&quot; \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u0441\u043f\u0440\u0430\u0432\u043e\u0447\u043d\u0438\u043a \u0438\u0437 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430 &quot;type&quot;. \u0412\u0441\u0435 \u0441\u043f\u0440\u0430\u0432\u043e\u0447\u043d\u0438\u043a\u0438 \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0443\u0435\u0442\u0441\u044f \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0442\u044c \u0432 \u0443\u0437\u0435\u043b &quot;d&quot;. <\/li>\n<li>\u041c\u043e\u0434\u0435\u043b\u044c &quot;t.item.comment&quot; \u2014 \u044d\u0442\u043e \u0442\u0430\u0431\u043b\u0438\u0447\u043d\u0430\u044f \u0447\u0430\u0441\u0442\u044c. \u041a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u0438 \u0438\u043c\u0435\u044e\u0442 \u0441\u0441\u044b\u043b\u043a\u0443 \u043d\u0430 &quot;item&quot;. \u0412\u0441\u0435 \u0442\u0430\u0431\u043b\u0438\u0447\u043d\u044b\u0435 \u0447\u0430\u0441\u0442\u0438 \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0443\u0435\u0442\u0441\u044f \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0442\u044c \u0432 \u0443\u0437\u0435\u043b &quot;t&quot;.<\/li>\n<\/ul>\n<\/li>\n<li>createProperty \u2014 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u0441\u0432\u043e\u0439\u0441\u0442\u0432 \u043c\u043e\u0434\u0435\u043b\u0435\u0439, \u0433\u0434\u0435 name \u2014 \u043d\u0430\u0438\u043c\u0435\u043d\u043e\u0432\u0430\u043d\u0438\u0435, code \u2014 \u0442\u0435\u043a\u0441\u0442\u043e\u0432\u044b\u0439 \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440, model \u2014 \u043c\u043e\u0434\u0435\u043b\u044c, type \u2014 \u0442\u0438\u043f \u0434\u0430\u043d\u043d\u044b\u0445 \u0432 \u0442.\u0447. \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043b\u044e\u0431\u0443\u044e \u043c\u043e\u0434\u0435\u043b\u044c, opts \u2014 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \u0442\u0435\u043a\u0441\u0442\u043e\u0432\u043e\u0433\u043e \u043f\u043e\u043b\u044f \u043a\u0430\u043a wysiwyg \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440. <\/li>\n<li>createQuery \u2014 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0435 SQL \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u0441 JSON \u0432\u0441\u0442\u0430\u0432\u043a\u0430\u043c\u0438 \u0431\u043b\u043e\u043a\u043e\u0432, \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432, \u043c\u043e\u0434\u0435\u043b\u0435\u0439, \u0441\u0432\u043e\u0439\u0441\u0442\u0432.<br \/> \n<ul>\n<li>[] \u2014 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043c\u0430\u0441\u0441\u0438\u0432\u0430 \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0447\u0438\u0442\u0430\u0435\u043c\u044b\u0439 \u043c\u043d\u043e\u0433\u043e\u0441\u0442\u0440\u043e\u0447\u043d\u044b\u0439 \u0442\u0435\u043a\u0441\u0442.<\/li>\n<li>\u0431\u043b\u043e\u043a\u0438 {&quot;&#8230;&quot;: &quot;begin&quot;}&#8230;{&quot;&#8230;&quot;: &quot;end&quot;} \u043f\u043e\u043c\u043e\u0433\u0430\u044e\u0442 \u043f\u0430\u0440\u0441\u0435\u0440\u0443 \u0441\u0442\u0440\u043e\u0438\u0442\u044c SQL \u0437\u0430\u043f\u0440\u043e\u0441\u044b \u0434\u043b\u044f \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0445 \u0446\u0435\u043b\u0435\u0439: \u0432\u044b\u0431\u043e\u0440\u043a\u0430 (data), \u0440\u0430\u0441\u0447\u0435\u0442 \u043a\u043e\u043b-\u0432\u0430 \u0437\u0430\u043f\u0438\u0441\u0435\u0439 (count), \u0444\u0438\u043b\u044c\u0442\u0440\u0430\u0446\u0438\u044f (where), \u0441\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u043a\u0430 (order), \u0440\u0430\u0441\u0447\u0435\u0442 \u043a\u043e\u043b-\u0432\u0430 \u0434\u043e\u0447\u0435\u0440\u043d\u0438\u0445 \u0443\u0437\u043b\u043e\u0432 (tree).<\/li>\n<li>\u043c\u043e\u0434\u0435\u043b\u044c {&quot;model&quot;: &quot;item&quot;, &quot;alias&quot;: &quot;a&quot;} \u043a\u043e\u043d\u0432\u0435\u0440\u0442\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u0432 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u0442\u0430\u0431\u043b\u0438\u0446\u044b &quot;\u043a\u043e\u0434_id a&quot;.<\/li>\n<li>\u0441\u0432\u043e\u0439\u0441\u0442\u0432\u043e {&quot;prop&quot;: &quot;a.name&quot;} \u043a\u043e\u043d\u0432\u0435\u0440\u0442\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u0432 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u0441\u0442\u043e\u043b\u0431\u0446\u0430 &quot;a.\u043a\u043e\u0434_id&quot;.<\/li>\n<li>\u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440 {&quot;prop&quot;: &quot;limit&quot;} \u0434\u043e\u043b\u0436\u0435\u043d \u0431\u044b\u0442\u044c \u043f\u0435\u0440\u0435\u0434\u0430\u043d \u0437\u0430\u043f\u0440\u043e\u0441\u0443 \u043f\u0440\u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0438.<\/li>\n<\/ul>\n<\/li>\n<li>createRecord \u2014 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0437\u0430\u043f\u0438\u0441\u0435\u0439 \u043c\u043e\u0434\u0435\u043b\u0435\u0439.<br \/> \n<ul>\n<li>_model \u2014 \u043c\u043e\u0434\u0435\u043b\u044c<\/li>\n<li>name \u2014 \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u043c \u043b\u044e\u0431\u044b\u0435 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430<\/li>\n<li>[] \u2014 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043c\u0430\u0441\u0441\u0438\u0432\u0430 \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0447\u0438\u0442\u0430\u0435\u043c\u044b\u0439 \u043c\u043d\u043e\u0433\u043e\u0441\u0442\u0440\u043e\u0447\u043d\u044b\u0439 \u0442\u0435\u043a\u0441\u0442.<\/li>\n<li>_ref \u2014 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u044d\u0442\u043e\u0439 \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u0441\u0441\u044b\u043b\u043a\u0438 \u043d\u0430 \u0434\u0440\u0443\u0433\u0438\u0435 \u0437\u0430\u043f\u0438\u0441\u0438 \u0442.\u043a. \u0437\u0430\u0440\u0430\u043d\u0435\u0435 id \u0437\u0430\u043f\u0438\u0441\u0438 \u043d\u0435\u0438\u0437\u0432\u0435\u0441\u0442\u043d\u043e.<\/li>\n<li>JSON \u043a\u043e\u043d\u0432\u0435\u0440\u0442\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u0432 \u0442\u0435\u043a\u0441\u0442.<\/li>\n<li>&quot;photo&quot;: &quot;rtx2080.png&quot; \u2014 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0444\u0430\u0439\u043b\u043e\u0432. \u0412 photo \u0437\u0430\u043f\u0438\u0448\u0435\u0442\u0441\u044f &quot;rtx2080.png&quot; \u0438 \u0437\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u0441\u044f \u0444\u0430\u0439\u043b \u0438\u0437 \u043f\u0430\u043f\u043a\u0438 scripts\/files.<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<p>  <\/p>\n<h3 id=\"import-csv\">\u0418\u043c\u043f\u043e\u0440\u0442 CSV<\/h3>\n<p>  <\/p>\n<pre><code class=\"bash\">cd \/opt\/objectum\/projects\/catalog   objectum-cli --import-csv scripts\/stationery.csv --model item --file-directory\/script\/files --handler scripts\/csv-handler.js objectum-cli --import-csv scripts\/tv.csv --model item --file-directory\/script\/files --handler scripts\/csv-handler.js<\/code><\/pre>\n<p>  <\/p>\n<p>\u0412\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u0438\u043c\u043f\u043e\u0440\u0442\u0430 CSV:<\/p>\n<p>  <\/p>\n<ul>\n<li>\u0418\u043c\u043f\u043e\u0440\u0442\u0438\u0440\u0443\u0435\u0442 \u0441\u0442\u0440\u043e\u043a\u0438 \u0438\u0437 CSV \u043a\u0430\u043a \u0437\u0430\u043f\u0438\u0441\u0438 \u0432 \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u0443\u044e \u043c\u043e\u0434\u0435\u043b\u044c (item)<\/li>\n<li>\u0418\u043c\u043f\u043e\u0440\u0442\u0438\u0440\u0443\u0435\u0442 \u0444\u0430\u0439\u043b\u044b (\u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f) \u0438\u0437 \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u043e\u0433\u043e \u043a\u0430\u0442\u0430\u043b\u043e\u0433\u0430<\/li>\n<li>\u0421 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0430 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u043c\u0435\u043d\u044f\u044e\u0442\u0441\u044f \u0437\u0430\u043f\u0438\u0441\u0438 \u043f\u0440\u0438 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u0438 (csv-handler.js):<br \/> \n<ul>\n<li>\u0421\u043a\u0440\u0438\u043f\u0442 \u0434\u043e\u043f\u043e\u043b\u043d\u044f\u0435\u0442 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u0432 \u0441\u043f\u0440\u0430\u0432\u043e\u0447\u043d\u0438\u043a\u0438 \u0432 \u0442.\u0447. \u0432 \u0434\u0440\u0435\u0432\u043e\u0432\u0438\u0434\u043d\u044b\u0439 (\u043a\u0430\u0442\u0435\u0433\u043e\u0440\u0438\u044f)<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<p>  <\/p>\n<h2 id=\"ishodnyy-kod-modeley\">\u0418\u0441\u0445\u043e\u0434\u043d\u044b\u0439 \u043a\u043e\u0434 \u043c\u043e\u0434\u0435\u043b\u0435\u0439<\/h2>\n<p>  <\/p>\n<p>\u0418\u0441\u0445\u043e\u0434\u043d\u044b\u0439 \u043a\u043e\u0434 ItemModel \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0430\u0435\u0442\u0441\u044f \u043d\u0430 \u043a\u043b\u0438\u0435\u043d\u0442\u0435 \u0438 \u0441\u0435\u0440\u0432\u0435\u0440\u0435. \u0414\u043b\u044f \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u044f ReactJS \u0438\u043b\u0438 NodeJS \u043a\u043e\u0434\u0430 \u043d\u0443\u0436\u043d\u043e \u0440\u0430\u0437\u0434\u0435\u043b\u0438\u0442\u044c \u043a\u043e\u0434 \u043d\u0430 ItemClientModel, ItemServerModel \u0438\u043b\u0438 \u043d\u0430 ItemModel, ItemClientModel extends ItemModel, ItemServerModel extends ItemModel. <\/p>\n<p>  <\/p>\n<h2 id=\"klient\">\u041a\u043b\u0438\u0435\u043d\u0442<\/h2>\n<p>  <\/p>\n<p>\u041f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 \u0432 App.js:<\/p>\n<p>  <\/p>\n<pre><code class=\"javascript\">import ItemModel from &quot;.\/models\/ItemModel&quot;;  store.register (&quot;item&quot;, ItemModel);<\/code><\/pre>\n<p>  <\/p>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0435\u043c\u044b\u0435 \u0437\u0430\u043f\u0438\u0441\u0438 \u043c\u043e\u0434\u0435\u043b\u0438 &quot;item&quot; \u0431\u0443\u0434\u0443\u0442 \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440\u0430\u043c\u0438 \u043a\u043b\u0430\u0441\u0441\u0430 ItemModel:<\/p>\n<p>  <\/p>\n<pre><code class=\"javascript\">let record = await store.createRecord ({     _model: &quot;item&quot;,     name: &quot;Foo&quot; });<\/code><\/pre>\n<p>  <\/p>\n<p>\u0427\u0442\u043e \u044d\u0442\u043e \u0434\u0430\u0435\u0442:<\/p>\n<p>  <\/p>\n<ul>\n<li>\u041f\u0440\u044f\u043c\u043e\u0435 \u043e\u0431\u0440\u0430\u0449\u0435\u043d\u0438\u0435 \u043a \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430\u043c record.name = &quot;Bar&quot;;<\/li>\n<li>\u0421\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435 record.store<\/li>\n<li>\u0421\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u0435 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0439 await record.sync ()<\/li>\n<\/ul>\n<p>  <\/p>\n<div class=\"spoiler\" role=\"button\" tabindex=\"0\">                         <b class=\"spoiler_title\">ItemModel.js<\/b>                         <\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"javascript\">import React from &quot;react&quot;; import {Record, factory} from &quot;objectum-client&quot;; import {Action} from &quot;objectum-react&quot;;  class ItemModel extends Record {     static _renderGrid ({grid, store}) {         return React.cloneElement (grid, {             label: &quot;Items&quot;, \/\/ grid label             query: &quot;item.list&quot;, \/\/ grid query             onRenderTable: ItemModel.onRenderTable, \/\/ grid table custom render             children: store.roleCode === &quot;guest&quot; ? null : &lt;div className=&quot;d-flex&quot;&gt;                 {grid.props.children}                 &lt;Action label=&quot;Server action: getComments&quot; onClickSelected={async ({progress, id}) =&gt; {                     let recs = await store.remote ({                         model: &quot;item&quot;,                         method: &quot;getComments&quot;,                         id,                         progress                     });                     return JSON.stringify (recs)                 }} \/&gt;             &lt;\/div&gt;         });     }      static onRenderTable ({grid, cols, colMap, recs, store}) {         return (             &lt;div className=&quot;p-1&quot;&gt;                 {recs.map ((rec, i) =&gt; {                     let record = factory ({rsc: &quot;record&quot;, data: Object.assign (rec, {_model: &quot;item&quot;}), store});                      return (                         &lt;div key={i} className={`row border-bottom my-1 p-1 no-gutters ${grid.state.selected === i ? &quot;bg-secondary text-white&quot; : &quot;&quot;}`} onClick={() =&gt; grid.onRowClick (i)} &gt;                             &lt;div className=&quot;col-6&quot;&gt;                                 &lt;div className=&quot;p-1&quot;&gt;                                     &lt;div&gt;                                         &lt;strong className=&quot;mr-1&quot;&gt;Name:&lt;\/strong&gt;{rec.name}                                     &lt;\/div&gt;                                     &lt;div&gt;                                         &lt;strong className=&quot;mr-1&quot;&gt;Date:&lt;\/strong&gt;{rec.date &amp;&amp; rec.date.toLocaleString ()}                                     &lt;\/div&gt;                                     &lt;div&gt;                                         &lt;strong className=&quot;mr-1&quot;&gt;Type:&lt;\/strong&gt;{rec.type &amp;&amp; store.dict [&quot;d.item.type&quot;][rec.type].name}                                     &lt;\/div&gt;                                     &lt;div&gt;                                         &lt;strong className=&quot;mr-1&quot;&gt;Cost:&lt;\/strong&gt;{rec.cost}                                     &lt;\/div&gt;                                     &lt;div&gt;                                         &lt;strong&gt;Description:&lt;\/strong&gt;                                     &lt;\/div&gt;                                     &lt;div dangerouslySetInnerHTML={{__html: `${record.description || &quot;&quot;}`}} \/&gt;                                 &lt;\/div&gt;                             &lt;\/div&gt;                             &lt;div className=&quot;col-6 text-right&quot;&gt;                                 {record.photo &amp;&amp; &lt;div&gt;                                      &lt;img src={record.getRef (&quot;photo&quot;)} className=&quot;img-fluid&quot; width={400} height={300} alt={record.photo} \/&gt;                                 &lt;\/div&gt;}                             &lt;\/div&gt;                         &lt;\/div&gt;                     );                 })}             &lt;\/div&gt;         );     }      \/\/ item form layout     static _layout () {         return {             &quot;Information&quot;: [                 &quot;id&quot;,                 [                     &quot;name&quot;, &quot;date&quot;                 ],                 [                     &quot;type&quot;, &quot;cost&quot;                 ],                 [                     &quot;description&quot;                 ],                 [                     &quot;photo&quot;                 ],                 [                     &quot;t.item.comment&quot;                 ]             ]         };     }      static _renderForm ({form, store}) {         return React.cloneElement (form, {             defaults: {                 date: new Date ()             }         });     }      \/\/ new item render     static _renderField ({field, store}) {         if (field.props.property === &quot;date&quot;) {             return React.cloneElement (field, {showTime: true});         } else {             return field;         }     }      \/\/ item render     _renderField ({field, store}) {         return ItemModel._renderField ({field, store});     } };  export default ItemModel;<\/code><\/pre>\n<\/div><\/div>\n<p>  <\/p>\n<p>\u0412 \u043c\u043e\u0434\u0435\u043b\u044f\u0445 \u0437\u0430\u0440\u0435\u0437\u0435\u0440\u0432\u0438\u0440\u043e\u0432\u0430\u043d\u044b \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u044f \u043c\u0435\u0442\u043e\u0434\u043e\u0432 \u0434\u043b\u044f \u0440\u0435\u0448\u0435\u043d\u0438\u044f \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0445 \u0437\u0430\u0434\u0430\u0447: <\/p>\n<p>  <\/p>\n<ul>\n<li>_renderGrid \u2014 \u043c\u043e\u0434\u0435\u043b\u044c &quot;item&quot; \u0438\u043c\u0435\u0435\u0442 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e \u0432 \u043c\u0430\u0440\u0448\u0440\u0443\u0442\u0435 \/model_list\/item. \u041e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0435\u0442 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 ModelList, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442 \u0434\u0430\u043d\u043d\u044b\u0439 \u043c\u0435\u0442\u043e\u0434 \u043f\u0440\u0438 \u0440\u0435\u043d\u0434\u0435\u0440\u0435 Grid.<\/li>\n<li>_layout \u2014 \u043f\u043e \u043c\u0430\u0440\u0448\u0440\u0443\u0442\u0443 \/model_record\/:id \u0437\u0430\u043f\u0438\u0441\u044c \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0435\u0442 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 ModelRecord, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442 \u0434\u0430\u043d\u043d\u044b\u0439 \u043c\u0435\u0442\u043e\u0434 \u0434\u043b\u044f \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u0440\u0430\u0437\u043c\u0435\u0442\u043a\u0438. \u0415\u0441\u043b\u0438 \u043c\u0435\u0442\u043e\u0434 \u043d\u0435 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d, \u0442\u043e \u043c\u0430\u043a\u0435\u0442 \u0444\u043e\u0440\u043c\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u0439, \u0433\u0434\u0435 \u0432\u0441\u0435 \u043f\u043e\u043b\u044f \u043f\u043e \u043e\u0434\u043d\u043e\u0439 \u043d\u0430 \u0441\u0442\u0440\u043e\u043a\u0443, \u0430 \u0442\u0430\u0431\u043b\u0438\u0447\u043d\u044b\u0435 \u0447\u0430\u0441\u0442\u0438 \u0432 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0445 \u0437\u0430\u043a\u043b\u0430\u0434\u043a\u0430\u0445 \u0444\u043e\u0440\u043c\u044b.<\/li>\n<li>_renderForm \u2014 \u0440\u0435\u043d\u0434\u0435\u0440 \u0444\u043e\u0440\u043c\u044b <\/li>\n<li>_renderField \u2014 \u0440\u0435\u043d\u0434\u0435\u0440 \u043f\u043e\u043b\u044f. \u0421\u0442\u0430\u0442\u0438\u0447\u043d\u044b\u0439 \u043c\u0435\u0442\u043e\u0434 \u0434\u043b\u044f \u043d\u043e\u0432\u043e\u0439 \u0437\u0430\u043f\u0438\u0441\u0438 \u0438 \u043e\u0431\u044b\u0447\u043d\u044b\u0439 \u043c\u0435\u0442\u043e\u0434 \u0434\u043b\u044f \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044e\u0449\u0435\u0439 \u0437\u0430\u043f\u0438\u0441\u0438.<\/li>\n<\/ul>\n<p>  <\/p>\n<p>\u041c\u043e\u0434\u0438\u0444\u0438\u0446\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u0430\u044f \u0444\u043e\u0440\u043c\u0430:<\/p>\n<p>  <\/p>\n<hr\/>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/webt\/uj\/ml\/wi\/ujmlwiwg9rpyhi1injt4afodvvc.png\" alt=\"auth\"\/><\/p>\n<p>  <\/p>\n<hr\/>\n<p>  <\/p>\n<h2 id=\"server\">\u0421\u0435\u0440\u0432\u0435\u0440<\/h2>\n<p>  <\/p>\n<p>\u041f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 \u0432 index.js:<\/p>\n<p>  <\/p>\n<pre><code class=\"javascript\">import ItemModel from &quot;.\/src\/models\/ItemServerModel.js&quot;;  proxy.register (&quot;item&quot;, ItemModel);<\/code><\/pre>\n<p>  <\/p>\n<p>\u041c\u0435\u0442\u043e\u0434\u044b \u0438 \u0440\u0430\u0431\u043e\u0442\u0430 \u0441 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435\u043c store \u0442\u0430\u043a\u0430\u044f \u0436\u0435. \u0421\u0435\u0441\u0441\u0438\u0438 \u043c\u0435\u0436\u0434\u0443 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f\u043c\u0438 \u0440\u0430\u0437\u0434\u0435\u043b\u0435\u043d\u044b.<\/p>\n<p>  <\/p>\n<div class=\"spoiler\" role=\"button\" tabindex=\"0\">                         <b class=\"spoiler_title\">ItemServerModel.js<\/b>                         <\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"javascript\">import objectumClient from &quot;objectum-client&quot;; const {Record} = objectumClient;  function timeout (ms = 500) {     return new Promise (resolve =&gt; setTimeout (() =&gt; resolve (), ms)); };  class ItemModel extends Record {     async getComments ({progress}) {         for (let i = 0; i &lt; 10; i ++) {             await timeout (1000);             progress ({label: &quot;processing&quot;, value: i + 1, max: 10});         }         return await this.store.getRecs ({             model: &quot;t.item.comment&quot;,             filters: [                 [&quot;item&quot;, &quot;=&quot;, this.id]             ]         });     } };  export default ItemModel;<\/code><\/pre>\n<\/div><\/div>\n<p>  <\/p>\n<p>\u0421 \u043a\u043b\u0438\u0435\u043d\u0442\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u043d\u044b\u0435 \u043c\u0435\u0442\u043e\u0434\u044b \u0432\u044b\u0437\u044b\u0432\u0430\u044e\u0442\u0441\u044f \u0442\u0430\u043a:<\/p>\n<p>  <\/p>\n<pre><code class=\"javascript\">getComments () {     return await store.remote ({         model: &quot;item&quot;,         method: &quot;getComments&quot;,         myArg: &quot;&quot;      }); }<\/code><\/pre>\n<p>  <\/p>\n<h2 id=\"dostup\">\u0414\u043e\u0441\u0442\u0443\u043f<\/h2>\n<p>  <\/p>\n<p>\u041f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 \u0432 index.js:<\/p>\n<p>  <\/p>\n<pre><code class=\"javascript\">import accessMethods from &quot;.\/src\/modules\/access.js&quot;;  proxy.registerAccessMethods (accessMethods);<\/code><\/pre>\n<p>  <\/p>\n<div class=\"spoiler\" role=\"button\" tabindex=\"0\">                         <b class=\"spoiler_title\">access.js<\/b>                         <\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"javascript\">let map = {     &quot;guest&quot;: {         &quot;data&quot;: {             &quot;model&quot;: {                 &quot;item&quot;: true, &quot;d.item.type&quot;: true, &quot;t.item.comment&quot;: true             },             &quot;query&quot;: {                 &quot;objectum.userMenuItems&quot;: true             }         },         &quot;read&quot;: {             &quot;objectum.role&quot;: true, &quot;objectum.user&quot;: true, &quot;objectum.menu&quot;: true, &quot;objectum.menuItem&quot;: true         }     } }; async function _init ({store}) { };  function _accessData ({store, data}) {     if (store.roleCode == &quot;guest&quot;) {         if (data.model) {             return map.guest.data.model [store.getModel (data.model).getPath ()];         }         if (data.query) {             return map.guest.data.query [store.getQuery (data.query).getPath ()];         }     } else {         return true;     } };  function _accessFilter ({store, model, alias}) { };  function _accessCreate ({store, model, data}) {     return store.roleCode != &quot;guest&quot;; };  function _accessRead ({store, model, record}) {     let modelPath = model.getPath ();      if (store.roleCode == &quot;guest&quot;) {         if (modelPath == &quot;objectum.user&quot;) {             return record.login == &quot;guest&quot;;         }         return map.guest.read [modelPath];     }     return true; };  function _accessUpdate ({store, model, record, data}) {     return store.roleCode != &quot;guest&quot;; };  function _accessDelete ({store, model, record}) {     return store.roleCode != &quot;guest&quot;; };  export default {     _init,     _accessData,     _accessFilter,     _accessCreate,     _accessRead,     _accessUpdate,     _accessDelete };<\/code><\/pre>\n<\/div><\/div>\n<p>  <\/p>\n<p>\u041b\u044e\u0431\u043e\u0439 \u0437\u0430\u043f\u0440\u043e\u0441 \u043a \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0443 \u043c\u043e\u0436\u043d\u043e \u0437\u0430\u043f\u0440\u0435\u0442\u0438\u0442\u044c \u0438\u043b\u0438 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0438\u0442\u044c. \u0414\u043e\u0441\u0442\u0443\u043f\u043d\u044b\u0435 \u043c\u0435\u0442\u043e\u0434\u044b:<\/p>\n<p>  <\/p>\n<ul>\n<li>_init \u2014 \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u043c\u043e\u0434\u0443\u043b\u044f.<\/li>\n<li>_accessCreate \u2014 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u0437\u0430\u043f\u0438\u0441\u0435\u0439.<\/li>\n<li>_accessRead \u2014 \u0447\u0442\u0435\u043d\u0438\u0435 \u0437\u0430\u043f\u0438\u0441\u0435\u0439.<\/li>\n<li>_accessUpdate \u2014 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0439 \u0437\u0430\u043f\u0438\u0441\u0435\u0439.<\/li>\n<li>_accessDelete \u2014 \u0443\u0434\u0430\u043b\u0435\u043d\u0438\u0435 \u0437\u0430\u043f\u0438\u0441\u0435\u0439.<\/li>\n<li>_accessData \u2014 \u0432\u044b\u0431\u043e\u0440\u043a\u0430 \u0434\u0430\u043d\u043d\u044b\u0445 \u043c\u0435\u0442\u043e\u0434\u043e\u043c getData<\/li>\n<li>_accessFilter \u2014 \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0439 \u043c\u043e\u0434\u0435\u043b\u0438 \u0432 SQL \u0437\u0430\u043f\u0440\u043e\u0441\u0435 \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u044d\u0442\u043e\u0442 \u043c\u0435\u0442\u043e\u0434. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0438\u0432\u0430\u0435\u043c \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u043e\u043c\u0443 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044e \u0432\u044b\u0431\u043e\u0440\u043a\u0443 \u0437\u0430\u043f\u0438\u0441\u0435\u0439. \u0422.\u043e. \u0432 \u043b\u044e\u0431\u043e\u043c \u043d\u043e\u0432\u043e\u043c \u0437\u0430\u043f\u0440\u043e\u0441\u0435 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u044f \u0431\u0443\u0434\u0443\u0442 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c.<\/li>\n<\/ul>\n<p>  <\/p>\n<p>\u0414\u0435\u0439\u0441\u0442\u0432\u0438\u044f \u043c\u043e\u0436\u043d\u043e \u0437\u0430\u043f\u0440\u0435\u0442\u0438\u0442\u044c \u0438\u043b\u0438 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0438\u0442\u044c, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 \u0440\u0430\u0437\u0440\u0435\u0448\u0430\u0442\u044c \u0438\u0437\u043c\u0435\u043d\u044f\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u043d\u0430\u0431\u043e\u0440 \u0441\u0432\u043e\u0439\u0441\u0442\u0432 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u043e\u0439 \u0440\u043e\u043b\u0438.<br \/>  \u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435, \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0435, \u0443\u0434\u0430\u043b\u0435\u043d\u0438\u0435 \u043c\u043e\u0434\u0435\u043b\u0435\u0439, \u0441\u0432\u043e\u0439\u0441\u0442\u0432, \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u0438 \u0441\u0442\u043e\u043b\u0431\u0446\u043e\u0432 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u043e \u0442\u043e\u043b\u044c\u043a\u043e \u0441\u0443\u043f\u0435\u0440\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044e admin.<\/p>\n<p>  <\/p>\n<h2 id=\"deystviya-administratora\">\u0414\u0435\u0439\u0441\u0442\u0432\u0438\u044f \u0430\u0434\u043c\u0438\u043d\u0438\u0441\u0442\u0440\u0430\u0442\u043e\u0440\u0430<\/h2>\n<p>  <\/p>\n<p>\u0418\u043d\u043e\u0433\u0434\u0430 \u043d\u0443\u0436\u043d\u043e \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u044c \u0441\u0435\u0440\u0432\u0435\u0440\u043d\u043e\u0435 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0435 \u0441 \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u044b\u043c\u0438 \u043f\u0440\u0430\u0432\u0430\u043c\u0438. \u042d\u0442\u043e \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u0438\u043b\u0438 \u043a\u0430\u043a\u0430\u044f-\u0442\u043e \u043e\u0431\u0440\u0430\u0442\u043d\u0430\u044f \u0441\u0432\u044f\u0437\u044c.<br \/>  \u041f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 \u0432 index.js:<\/p>\n<p>  <\/p>\n<pre><code class=\"javascript\">import adminMethods from &quot;.\/src\/modules\/admin.js&quot;;  proxy.registerAdminMethods (adminMethods);<\/code><\/pre>\n<p>  <\/p>\n<div class=\"spoiler\" role=\"button\" tabindex=\"0\">                         <b class=\"spoiler_title\">admin.js<\/b>                         <\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"javascript\">import fs from &quot;fs&quot;; import util from &quot;util&quot;;  fs.readFileAsync = util.promisify (fs.readFile);  function timeout (ms = 500) {     return new Promise (resolve =&gt; setTimeout (() =&gt; resolve (), ms)); };  async function readFile ({store, progress, filename}) {     for (let i = 0; i &lt; 10; i ++) {         await timeout (1000);         progress ({label: &quot;processing&quot;, value: i + 1, max: 10});     }     return await fs.readFileAsync (filename, &quot;utf8&quot;); };  async function increaseCost ({store, progress}) {     await store.startTransaction (&quot;demo&quot;);      let records = await store.getRecords ({model: &quot;item&quot;});      for (let i = 0; i &lt; records.length; i ++) {         let record = records [i];          record.cost = record.cost + 1;         await record.sync ();     }     await store.commitTransaction ();      return &quot;ok&quot;; };  export default {     readFile,     increaseCost };<\/code><\/pre>\n<\/div><\/div>\n<p>  <\/p>\n<p>\u041a\u0430\u043a \u0432\u0438\u0434\u043d\u043e \u0438\u0437 admin.js. \u0417\u0434\u0435\u0441\u044c \u0447\u0438\u0442\u0430\u0435\u043c \u0444\u0430\u0439\u043b\u044b \u0438 \u043c\u0435\u043d\u044f\u0435\u043c \u0434\u0430\u043d\u043d\u044b\u0435 \u0438\u0437 \u043f\u043e\u0434 \u043b\u044e\u0431\u043e\u0439 \u0443\u0447\u0435\u0442\u043d\u043e\u0439 \u0437\u0430\u043f\u0438\u0441\u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f (guest).<br \/>  \u0421 \u043a\u043b\u0438\u0435\u043d\u0442\u0430 \u0432\u044b\u0437\u043e\u0432 \u0442\u0430\u043a\u043e\u0439:<\/p>\n<p>  <\/p>\n<pre><code class=\"javascript\">await store.remote ({     model: &quot;admin&quot;,     method: &quot;readFile&quot;,     filename: &quot;package.json&quot; });<\/code><\/pre>\n<p>  <\/p>\n<h2 id=\"komponenty-react\">\u041a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b React<\/h2>\n<p>  <\/p>\n<p>\u0411\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b:<\/p>\n<p>  <\/p>\n<ul>\n<li>ObjectumApp \u2014 \u0432\u0435\u0431-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 <\/li>\n<li>ObjectumRoute \u2014 \u043c\u0430\u0440\u0448\u0440\u0443\u0442 <\/li>\n<li>Auth \u2014 \u0444\u043e\u0440\u043c\u0430 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438<\/li>\n<li>Grid \u2014 \u0442\u0430\u0431\u043b\u0438\u0446\u0430<br \/> \n<ul>\n<li>\u041f\u0430\u0440\u0430\u043c\u0435\u0442\u0440 tree \u0432\u043a\u043b\u044e\u0447\u0430\u0435\u0442 \u0434\u0440\u0435\u0432\u043e\u0432\u0438\u0434\u043d\u0443\u044e \u0442\u0430\u0431\u043b\u0438\u0446\u0443 <\/li>\n<\/ul>\n<\/li>\n<li>Form \u2014 \u0444\u043e\u0440\u043c\u0430 <\/li>\n<li>Tabs, Tab \u2014 \u0437\u0430\u043a\u043b\u0430\u0434\u043a\u0438 <\/li>\n<li>Fields \u2014 \u043f\u043e\u043b\u044f \u0434\u043b\u044f \u0440\u0430\u0437\u043d\u044b\u0445 \u0442\u0438\u043f\u043e\u0432 \u0434\u0430\u043d\u043d\u044b\u0445 <br \/> \n<ul>\n<li>StringField \u2014 \u0441\u0442\u0440\u043e\u043a\u0430. \u0415\u0441\u0442\u044c \u043e\u043f\u0446\u0438\u0438: textarea, wysiwyg<\/li>\n<li>NumberField \u2014 \u0447\u0438\u0441\u043b\u043e<\/li>\n<li>BooleanField \u2014 \u0447\u0435\u043a\u0435\u0440<\/li>\n<li>DateField \u2014 \u0434\u0430\u0442\u0430. \u041f\u0430\u0440\u0430\u043c\u0435\u0442\u0440 showTime \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u0442 \u0432\u0440\u0435\u043c\u044f. <\/li>\n<li>FileField \u2014 \u0444\u0430\u0439\u043b (\u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435). \u0415\u0441\u0442\u044c \u043e\u0431\u0440\u0435\u0437\u0430\u043d\u0438\u0435 \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u043f\u0435\u0440\u0435\u0434 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u043e\u0439. <\/li>\n<li>DictField \u2014 \u0432\u044b\u0431\u043e\u0440 \u0438\u0437 \u0441\u043f\u0440\u0430\u0432\u043e\u0447\u043d\u0438\u043a\u0430<\/li>\n<li>SelectField \u2014 \u0432\u044b\u0431\u043e\u0440 \u0438\u0437 \u0441\u043f\u0438\u0441\u043a\u0430<\/li>\n<li>ChooseField \u2014 \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u0437\u0430\u043f\u0438\u0441\u044c. \u0412\u044b\u0431\u043e\u0440 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430 \u0438\u0437 \u0434\u0440\u0443\u0433\u043e\u0433\u043e \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430 <\/li>\n<li>JsonField \u2014 \u0441\u043e\u0441\u0442\u0430\u0432\u043d\u043e\u0435 \u043f\u043e\u043b\u0435. \u0421\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0432 \u0441\u0435\u0431\u0435 \u043b\u044e\u0431\u043e\u0435 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u043f\u043e\u043b\u0435\u0439 \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u043e\u0433\u043e \u0442\u0438\u043f\u0430. \u0417\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u044e\u0442\u0441\u044f \u0432 \u0432\u0438\u0434\u0435 \u0441\u0442\u0440\u043e\u043a\u0438 JSON<\/li>\n<li>Field \u2014 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0432\u043d\u0443\u0442\u0440\u0438 \u0444\u043e\u0440\u043c\u044b. \u0422\u0438\u043f \u043f\u043e\u043b\u044f \u0432\u044b\u0431\u0438\u0440\u0430\u0435\u0442\u0441\u044f \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 <\/li>\n<li>JsonEditor \u2014 \u043c\u043d\u043e\u0433\u043e\u0441\u0442\u0440\u043e\u0447\u043d\u044b\u0439 \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440 \u0441\u0432\u043e\u0439\u0441\u0442\u0432 JSON <\/li>\n<\/ul>\n<\/li>\n<li>Tooltip \u2014 \u0432\u0441\u043f\u043b\u044b\u0432\u0430\u044e\u0449\u0430\u044f \u043f\u043e\u0434\u0441\u043a\u0430\u0437\u043a\u0430<\/li>\n<li>Fade \u2014 \u0430\u043d\u0438\u043c\u0430\u0446\u0438\u044f \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f <\/li>\n<li>Action \u2014 \u043a\u043d\u043e\u043f\u043a\u0430 \u0434\u043b\u044f \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u0438 <\/li>\n<\/ul>\n<p>  <\/p>\n<h2 id=\"objectumapp\">ObjectumApp<\/h2>\n<p>  <\/p>\n<p>props:<\/p>\n<p>  <\/p>\n<ul>\n<li>locale \u2014 \u043b\u043e\u043a\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f. \u0415\u0441\u0442\u044c &quot;ru&quot;.<\/li>\n<li>onCustomRender \u2014 \u0441\u0432\u043e\u0439 \u0440\u0435\u043d\u0434\u0435\u0440 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f<\/li>\n<li>username, password \u2014 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0430\u044f \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u044f \u043f\u043e\u0434 \u0432\u044b\u0431\u0440\u0430\u043d\u043d\u044b\u043c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u043c (guest). <\/li>\n<\/ul>\n<p>  <\/p>\n<h3 id=\"grid\">Grid<\/h3>\n<p>  <\/p>\n<p>\u0414\u043b\u044f \u0432\u044b\u0431\u043e\u0440\u043a\u0438 \u0434\u0430\u043d\u043d\u044b\u0445 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0443 \u043d\u0443\u0436\u043d\u043e \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u0437\u0430\u043f\u0440\u043e\u0441 (query) \u0438\u043b\u0438 \u043c\u043e\u0434\u0435\u043b\u044c (model). \u041f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u0438:<\/p>\n<p>  <\/p>\n<ul>\n<li>\u0421\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u043a\u0430 \u043f\u043e \u0432\u044b\u0431\u0440\u0430\u043d\u043d\u043e\u043c\u0443 \u0441\u0442\u043e\u043b\u0431\u0446\u0443<\/li>\n<li>\u0424\u0438\u043b\u044c\u0442\u0440\u044b \u043f\u043e \u043b\u044e\u0431\u044b\u043c \u0441\u0442\u043e\u043b\u0431\u0446\u0430\u043c \u0432 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0438\u0438 \u0441 \u0442\u0438\u043f\u043e\u043c \u0434\u0430\u043d\u043d\u044b\u0445 \u0441\u0442\u043e\u043b\u0431\u0446\u0430 <br \/> \n<ul>\n<li>\u0421\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u0435 \u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u044b\u0445 \u0444\u0438\u043b\u044c\u0442\u0440\u043e\u0432 \u0432 localStorage<\/li>\n<\/ul>\n<\/li>\n<li>\u0412\u044b\u0431\u043e\u0440 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0435\u043c\u044b\u0445 \u0441\u0442\u043e\u043b\u0431\u0446\u043e\u0432<\/li>\n<\/ul>\n<p>  <\/p>\n<h3 id=\"form\">Form<\/h3>\n<p>  <\/p>\n<p>\u0424\u043e\u0440\u043c\u0430 \u0433\u0440\u0443\u043f\u043f\u0438\u0440\u0443\u0435\u0442 \u043f\u043e\u043b\u044f. \u041f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0441\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f, \u0438 \u0437\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u044c \u0444\u0430\u0439\u043b\u044b. \u041a\u043d\u043e\u043f\u043a\u0430 &quot;\u0418\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f&quot; \u0432 \u0444\u043e\u0440\u043c\u0435 \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442 \u0442\u0430\u0431\u043b\u0438\u0446\u0443 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0439 \u043f\u043e \u0432\u044b\u0431\u0440\u0430\u043d\u043d\u043e\u043c\u0443 \u043f\u043e\u043b\u044e. \u0412\u0438\u0434\u043d\u043e \u043a\u0430\u043a\u043e\u0439 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c, \u043a\u043e\u0433\u0434\u0430 \u0438 \u0441 \u043a\u0430\u043a\u043e\u0433\u043e IP-\u0430\u0434\u0440\u0435\u0441\u0430 \u0432\u043d\u0435\u0441 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f.<\/p>\n<p>  <\/p>\n<h3 id=\"action\">Action<\/h3>\n<p>  <\/p>\n<p>\u041a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0443\u0434\u043e\u0431\u043d\u044b\u0439 \u0437\u0430\u043f\u0443\u0441\u043a \u0444\u0443\u043d\u043a\u0446\u0438\u0439:<\/p>\n<p>  <\/p>\n<ul>\n<li>\u041f\u0430\u0440\u0430\u043c\u0435\u0442\u0440 confirm \u2014 \u043f\u043e\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043d\u0438\u0435 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f<\/li>\n<li>\u0424\u0443\u043d\u043a\u0446\u0438\u044f \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u043e\u0439 \u0438\u043b\u0438 \u0430\u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u043e\u0439<\/li>\n<li>\u0412\u043e \u0432\u0440\u0435\u043c\u044f \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f:<br \/> \n<ul>\n<li>\u041e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \u043f\u0440\u043e\u0433\u0440\u0435\u0441\u0441\u0430 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f, \u0432\u043a\u043b\u044e\u0447\u0430\u044f \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0435<\/li>\n<li>\u0417\u0430\u043f\u0440\u043e\u0441 \u043f\u043e\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043d\u0438\u044f \u0432\u043e \u0432\u0440\u0435\u043c\u044f \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f<\/li>\n<li>\u0412 \u0441\u043b\u0443\u0447\u0430\u0435 \u0438\u0441\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442 \u043e\u0448\u0438\u0431\u043a\u0443<\/li>\n<\/ul>\n<\/li>\n<li>\u041f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0435\u0441\u043b\u0438 \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u0432\u0435\u0440\u043d\u0443\u043b\u0430 \u0441\u0442\u0440\u043e\u043a\u0443 <\/li>\n<\/ul>\n<p>  <\/p>\n<h2 id=\"otchety\">\u041e\u0442\u0447\u0435\u0442\u044b<\/h2>\n<p>  <\/p>\n<p>\u0414\u043b\u044f \u043f\u043e\u0441\u0442\u0440\u043e\u0435\u043d\u0438\u044f \u043d\u0435\u0441\u043b\u043e\u0436\u043d\u044b\u0445 \u043e\u0442\u0447\u0435\u0442\u043e\u0432 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f createReport, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0441\u0442\u0440\u043e\u0438\u0442 XLSX \u043e\u0442\u0447\u0435\u0442. \u041f\u0440\u0438\u043c\u0435\u0440:<\/p>\n<p>  <\/p>\n<pre><code class=\"javascript\">import {createReport} from &quot;objectum-react&quot;;  let recs = await store.getRecs ({model: &quot;item&quot;}); let rows = [     [         {text: &quot;\u0421\u043f\u0438\u0441\u043e\u043a&quot;, style: &quot;border_center&quot;, colSpan: 3}     ],     [         {text: &quot;\u041d\u0430\u0438\u043c\u0435\u043d\u043e\u0432\u0430\u043d\u0438\u0435&quot;, style: &quot;border&quot;},         {text: &quot;\u0414\u0430\u0442\u0430&quot;, style: &quot;border&quot;},         {text: &quot;\u0421\u0442\u043e\u0438\u043c\u043e\u0441\u0442\u044c&quot;, style: &quot;border&quot;}     ],     ...recs.map (rec =&gt; {         return [             {text: rec.name, style: &quot;border&quot;},             {text: rec.date.toLocaleString (), style: &quot;border&quot;},             {text: rec.cost, style: &quot;border&quot;}                     ];     }) ]; createReport ({     rows,     columns: [40, 10, 10],     font: {         name: &quot;Arial&quot;,         size: 10     } });<\/code><\/pre>\n<p>  <\/p>\n<p>\u0413\u0434\u0435:<\/p>\n<p>  <\/p>\n<ul>\n<li>rows \u2014 \u044d\u0442\u043e \u0441\u0442\u0440\u043e\u043a\u0438 (row) \u043e\u0442\u0447\u0435\u0442\u0430<\/li>\n<li>colSpan, rowSpan \u2014 \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0442 \u043a\u0430\u043a \u0432 HTML \u0442\u0430\u0431\u043b\u0438\u0446\u0435<\/li>\n<li>columns \u2014 \u0448\u0438\u0440\u0438\u043d\u0430 \u043a\u043e\u043b\u043e\u043d\u043e\u043a<\/li>\n<\/ul>\n<p>  <\/p>\n<h2 id=\"razvertyvanie\">\u0420\u0430\u0437\u0432\u0435\u0440\u0442\u044b\u0432\u0430\u043d\u0438\u0435<\/h2>\n<p>  <\/p>\n<p>\u041f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0430 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 \u0432\u0438\u0440\u0442\u0443\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449. \u0411\u0430\u0437\u0430 \u043b\u044e\u0431\u043e\u0433\u043e \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u044d\u043a\u0441\u043f\u043e\u0440\u0442\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u0432 \u0444\u0430\u0439\u043b \u0438 \u0438\u043c\u043f\u043e\u0440\u0442\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u0432 \u0434\u0440\u0443\u0433\u0443\u044e \u0431\u0430\u0437\u0443. \u0412 \u043d\u043e\u0432\u043e\u0439 \u0431\u0430\u0437\u0435 \u0443 \u0440\u0435\u0441\u0443\u0440\u0441\u043e\u0432 \u0441\u043e\u0437\u0434\u0430\u044e\u0442\u0441\u044f \u0441\u0441\u044b\u043b\u043a\u0438 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b\u044c\u043d\u0443\u044e \u0431\u0430\u0437\u0443, \u043f\u043e \u043a\u043e\u0442\u043e\u0440\u044b\u043c \u0432\u0438\u0440\u0442\u0443\u0430\u043b\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u0430\u044f \u0431\u0430\u0437\u0430 \u043e\u0431\u043d\u043e\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0432 \u0434\u0430\u043b\u044c\u043d\u0435\u0439\u0448\u0435\u043c. \u041c\u043e\u0434\u0435\u043b\u0438, \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430, \u0437\u0430\u043f\u0440\u043e\u0441\u044b, \u0437\u0430\u043f\u0438\u0441\u0438 \u0441\u043e\u0437\u0434\u0430\u044e\u0442\u0441\u044f, \u0438\u0437\u043c\u0435\u043d\u044f\u044e\u0442\u0441\u044f \u0438\u043b\u0438 \u0443\u0434\u0430\u043b\u044f\u044e\u0442\u0441\u044f. \u041f\u0440\u0438\u043c\u0435\u0440\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f:<\/p>\n<p>  <\/p>\n<ul>\n<li>\u042f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e \u0442\u0430\u043a\u0443\u044e \u0441\u0445\u0435\u043c\u0443<br \/> \n<ul>\n<li>\u0411\u0414 catalog_dev \u2014 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0430<\/li>\n<li>\u0411\u0414 catalog_test (\u0438\u043c\u043f\u043e\u0440\u0442 \u0438\u0437 catalog_dev) \u2014 \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435<\/li>\n<li>\u0411\u0414 catalog_&quot;\u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440 \u043a\u043b\u0438\u0435\u043d\u0442\u0430&quot; (\u0438\u043c\u043f\u043e\u0440\u0442 \u0438\u0437 catalog_dev) \u2014 \u043f\u0440\u043e\u0434\u0430\u043a\u0448\u043d<\/li>\n<\/ul>\n<\/li>\n<li>\u041e\u0431\u0449\u0438\u0435 \u0438 \u0440\u0435\u0433\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u044b\u0435 \u0441\u043f\u0440\u0430\u0432\u043e\u0447\u043d\u0438\u043a\u0438<br \/> \n<ul>\n<li>\u0411\u0414 region_dev \u2014 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u0438 \u043e\u0431\u0449\u0438\u0435 \u0441\u043f\u0440\u0430\u0432\u043e\u0447\u043d\u0438\u043a\u0438<\/li>\n<li>\u0411\u0414 region_&quot;\u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440 \u0440\u0435\u0433\u0438\u043e\u043d\u0430&quot; (\u0438\u043c\u043f\u043e\u0440\u0442 \u0438\u0437 region_dev) \u2014 \u043c\u043e\u0434\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044f \u043e\u0431\u0449\u0438\u0445 \u0441\u043f\u0440\u0430\u0432\u043e\u0447\u043d\u0438\u043a\u043e\u0432 \u0438 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0440\u0435\u0433\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u044b\u0445 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432 \u0432 \u0441\u043f\u0440\u0430\u0432\u043e\u0447\u043d\u0438\u043a\u0438<\/li>\n<li>\u0411\u0414 region<em>&quot;\u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440 \u043a\u043b\u0438\u0435\u043d\u0442\u0430 \u0440\u0435\u0433\u0438\u043e\u043d\u0430&quot; (\u0438\u043c\u043f\u043e\u0440\u0442 \u0438\u0437 region<\/em>&quot;\u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440 \u0440\u0435\u0433\u0438\u043e\u043d\u0430&quot;) \u2014 \u043f\u0440\u043e\u0434\u0430\u043a\u0448\u043d<\/li>\n<\/ul>\n<\/li>\n<li>\u0412 \u043e\u0434\u043d\u0443 \u0411\u0414 \u043c\u043e\u0436\u0435\u0442\u0435 \u0438\u043c\u043f\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0434\u0440\u0443\u0433\u0438\u0445 \u0411\u0414, \u043d\u043e \u0432 \u0440\u0435\u0430\u043b\u044c\u043d\u043e\u0441\u0442\u0438 \u043c\u043d\u0435 \u044d\u0442\u043e \u043d\u0435 \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u0438\u043b\u043e\u0441\u044c<\/li>\n<\/ul>\n<p>  <\/p>\n<p>\u042d\u043a\u0441\u043f\u043e\u0440\u0442 \u0441\u0445\u0435\u043c\u044b catalog:<\/p>\n<p>  <\/p>\n<pre><code class=\"javascript\">let $o = require (&quot;..\/..\/server\/objectum&quot;);  $o.db.execute ({     &quot;code&quot;: &quot;catalog&quot;,     &quot;fn&quot;: &quot;export&quot;,     &quot;exceptRecords&quot;: [&quot;item&quot;],     &quot;file&quot;: &quot;..\/schema\/schema-catalog.json&quot; });<\/code><\/pre>\n<p>  <\/p>\n<p>\u041f\u0430\u0440\u0430\u043c\u0435\u0442\u0440 exceptRecords \u043e\u0442\u043a\u043b\u044e\u0447\u0430\u0435\u0442 \u044d\u043a\u0441\u043f\u043e\u0440\u0442 \u0437\u0430\u043f\u0438\u0441\u0435\u0439 \u043f\u043e \u0432\u044b\u0431\u0440\u0430\u043d\u043d\u044b\u043c \u043c\u043e\u0434\u0435\u043b\u044f\u043c, \u0432\u043a\u043b\u044e\u0447\u0430\u044f \u0434\u043e\u0447\u0435\u0440\u043d\u0438\u0435 \u043c\u043e\u0434\u0435\u043b\u0438.<\/p>\n<p>  <\/p>\n<p>\u0418\u043c\u043f\u043e\u0440\u0442 \u0441\u0445\u0435\u043c\u044b:<\/p>\n<p>  <\/p>\n<pre><code class=\"javascript\">let $o = require (&quot;..\/..\/..\/server\/objectum&quot;);  $o.db.execute ({     &quot;code&quot;: &quot;catalog_test&quot;,     &quot;fn&quot;: &quot;import&quot;,     &quot;file&quot;: &quot;..\/schema\/schema-catalog.json&quot; });<\/code><\/pre>\n<p>  <\/p>\n<h2 id=\"proizvoditelnost\">\u041f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c<\/h2>\n<p>  <\/p>\n<p>\u0412 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0439 \u0442\u0430\u0431\u043b\u0438\u0446\u0435 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u044b \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u043d\u0430\u0438\u0431\u043e\u043b\u0435\u0435 \u0442\u0440\u0443\u0434\u043e\u0435\u043c\u043a\u043e\u0439 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u2014 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u0437\u0430\u043f\u0438\u0441\u0435\u0439. \u0422\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043b\u043e\u0441\u044c \u043d\u0430 MacBook Pro Mid 2014 (MGX82).<\/p>\n<p>  <\/p>\n<p>\u0416\u0443\u0440\u043d\u0430\u043b\u0438\u0440\u0443\u0435\u043c\u044b\u0435 \u043c\u043e\u0434\u0435\u043b\u0438 (model.unlogged: false):<\/p>\n<p>  <\/p>\n<div class=\"scrollable-table\">\n<table>\n<thead>\n<tr>\n<th>\u0421\u0432\u043e\u0439\u0441\u0442\u0432\u0430<\/th>\n<th>100 \u0437\u0430\u043f\u0438\u0441\u0435\u0439 (\u0441\u0435\u043a.)<\/th>\n<th>1000 \u0437\u0430\u043f\u0438\u0441\u0435\u0439 (\u0441\u0435\u043a.)<\/th>\n<th>\u0417\u0430\u043f\u0438\u0441\u0435\u0439 \u0432 \u0441\u0435\u043a.<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>\u041a\u043e\u043b-\u0432\u043e: 1, \u0427\u0438\u0441\u043b\u043e: 1<\/td>\n<td>0.5<\/td>\n<td>4.9<\/td>\n<td>204<\/td>\n<\/tr>\n<tr>\n<td>\u041a\u043e\u043b-\u0432\u043e: 1, \u0421\u0442\u0440\u043e\u043a\u0430: 1<\/td>\n<td>0.5<\/td>\n<td>4.6<\/td>\n<td>215<\/td>\n<\/tr>\n<tr>\n<td>\u041a\u043e\u043b-\u0432\u043e: 1, \u0414\u0430\u0442\u0430: 1<\/td>\n<td>0.5<\/td>\n<td>4.4<\/td>\n<td>227<\/td>\n<\/tr>\n<tr>\n<td>\u041a\u043e\u043b-\u0432\u043e: 3, \u0427\u0438\u0441\u043b\u043e: 1, \u0421\u0442\u0440\u043e\u043a\u0430: 1, \u0414\u0430\u0442\u0430: 1<\/td>\n<td>0.5<\/td>\n<td>4.8<\/td>\n<td>209<\/td>\n<\/tr>\n<tr>\n<td>\u041a\u043e\u043b-\u0432\u043e: 10, \u0427\u0438\u0441\u043b\u043e: 10<\/td>\n<td>0.6<\/td>\n<td>5.8<\/td>\n<td>172<\/td>\n<\/tr>\n<tr>\n<td>\u041a\u043e\u043b-\u0432\u043e: 10, \u0421\u0442\u0440\u043e\u043a\u0430: 10<\/td>\n<td>0.6<\/td>\n<td>7.1<\/td>\n<td>140<\/td>\n<\/tr>\n<tr>\n<td>\u041a\u043e\u043b-\u0432\u043e: 10, \u0414\u0430\u0442\u0430: 10<\/td>\n<td>0.6<\/td>\n<td>10.1<\/td>\n<td>98<\/td>\n<\/tr>\n<tr>\n<td>\u041a\u043e\u043b-\u0432\u043e: 30, \u0427\u0438\u0441\u043b\u043e: 10, \u0421\u0442\u0440\u043e\u043a\u0430: 10, \u0414\u0430\u0442\u0430: 10<\/td>\n<td>1.2<\/td>\n<td>14.7<\/td>\n<td>68<\/td>\n<\/tr>\n<tr>\n<td>\u041a\u043e\u043b-\u0432\u043e: 100 \u0427\u0438\u0441\u043b\u043e: 100<\/td>\n<td>2.3<\/td>\n<td>27.3<\/td>\n<td>37<\/td>\n<\/tr>\n<tr>\n<td>\u041a\u043e\u043b-\u0432\u043e: 100 \u0421\u0442\u0440\u043e\u043a\u0430: 100<\/td>\n<td>2.4<\/td>\n<td>24.1<\/td>\n<td>42<\/td>\n<\/tr>\n<tr>\n<td>\u041a\u043e\u043b-\u0432\u043e: 100 \u0414\u0430\u0442\u0430: 100<\/td>\n<td>2.3<\/td>\n<td>24.6<\/td>\n<td>40<\/td>\n<\/tr>\n<tr>\n<td>\u041a\u043e\u043b-\u0432\u043e: 300 \u0427\u0438\u0441\u043b\u043e: 100, \u0421\u0442\u0440\u043e\u043a\u0430: 100, \u0414\u0430\u0442\u0430: 100<\/td>\n<td>8.9<\/td>\n<td>88.3<\/td>\n<td>11<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<p>  <\/p>\n<p>\u041d\u0435\u0436\u0443\u0440\u043d\u0430\u043b\u0438\u0440\u0443\u0435\u043c\u044b\u0435 \u043c\u043e\u0434\u0435\u043b\u0438 (model.unlogged: true):<\/p>\n<p>  <\/p>\n<div class=\"scrollable-table\">\n<table>\n<thead>\n<tr>\n<th>\u0421\u0432\u043e\u0439\u0441\u0442\u0432\u0430<\/th>\n<th>100 \u0437\u0430\u043f\u0438\u0441\u0435\u0439 (\u0441\u0435\u043a.)<\/th>\n<th>1000 \u0437\u0430\u043f\u0438\u0441\u0435\u0439 (\u0441\u0435\u043a.)<\/th>\n<th>\u0417\u0430\u043f\u0438\u0441\u0435\u0439 \u0432 \u0441\u0435\u043a.<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>\u041a\u043e\u043b-\u0432\u043e: 1, \u0427\u0438\u0441\u043b\u043e: 1<\/td>\n<td>0.5<\/td>\n<td>4.3<\/td>\n<td>233<\/td>\n<\/tr>\n<tr>\n<td>\u041a\u043e\u043b-\u0432\u043e: 1, \u0421\u0442\u0440\u043e\u043a\u0430: 1<\/td>\n<td>0.4<\/td>\n<td>4.1<\/td>\n<td>244<\/td>\n<\/tr>\n<tr>\n<td>\u041a\u043e\u043b-\u0432\u043e: 1, \u0414\u0430\u0442\u0430: 1<\/td>\n<td>0.4<\/td>\n<td>3.7<\/td>\n<td>268<\/td>\n<\/tr>\n<tr>\n<td>\u041a\u043e\u043b-\u0432\u043e: 3, \u0427\u0438\u0441\u043b\u043e: 1, \u0421\u0442\u0440\u043e\u043a\u0430: 1, \u0414\u0430\u0442\u0430: 1<\/td>\n<td>0.5<\/td>\n<td>3.8<\/td>\n<td>261<\/td>\n<\/tr>\n<tr>\n<td>\u041a\u043e\u043b-\u0432\u043e: 10, \u0427\u0438\u0441\u043b\u043e: 10<\/td>\n<td>0.5<\/td>\n<td>4.1<\/td>\n<td>243<\/td>\n<\/tr>\n<tr>\n<td>\u041a\u043e\u043b-\u0432\u043e: 10, \u0421\u0442\u0440\u043e\u043a\u0430: 10<\/td>\n<td>0.4<\/td>\n<td>4.0<\/td>\n<td>251<\/td>\n<\/tr>\n<tr>\n<td>\u041a\u043e\u043b-\u0432\u043e: 10, \u0414\u0430\u0442\u0430: 10<\/td>\n<td>0.4<\/td>\n<td>4.2<\/td>\n<td>239<\/td>\n<\/tr>\n<tr>\n<td>\u041a\u043e\u043b-\u0432\u043e: 30, \u0427\u0438\u0441\u043b\u043e: 10, \u0421\u0442\u0440\u043e\u043a\u0430: 10, \u0414\u0430\u0442\u0430: 10<\/td>\n<td>0.5<\/td>\n<td>4.9<\/td>\n<td>202<\/td>\n<\/tr>\n<tr>\n<td>\u041a\u043e\u043b-\u0432\u043e: 100 \u0427\u0438\u0441\u043b\u043e: 100<\/td>\n<td>0.6<\/td>\n<td>12.4<\/td>\n<td>81<\/td>\n<\/tr>\n<tr>\n<td>\u041a\u043e\u043b-\u0432\u043e: 100 \u0421\u0442\u0440\u043e\u043a\u0430: 100<\/td>\n<td>0.7<\/td>\n<td>6.1<\/td>\n<td>162<\/td>\n<\/tr>\n<tr>\n<td>\u041a\u043e\u043b-\u0432\u043e: 100 \u0414\u0430\u0442\u0430: 100<\/td>\n<td>0.9<\/td>\n<td>7.2<\/td>\n<td>140<\/td>\n<\/tr>\n<tr>\n<td>\u041a\u043e\u043b-\u0432\u043e: 300 \u0427\u0438\u0441\u043b\u043e: 100, \u0421\u0442\u0440\u043e\u043a\u0430: 100, \u0414\u0430\u0442\u0430: 100<\/td>\n<td>1.1<\/td>\n<td>11.1<\/td>\n<td>90<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<p>  <\/p>\n<p>\u2028<br \/>  \u041f\u043e \u0441\u0442\u043e\u043b\u0431\u0446\u0430\u043c:<\/p>\n<p>  <\/p>\n<ul>\n<li>\u0432 1-\u043c \u0441\u0442\u043e\u043b\u0431\u0446\u0435 \u0443\u043a\u0430\u0437\u0430\u043d\u043e \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0441\u0432\u043e\u0439\u0441\u0442\u0432 \u043c\u043e\u0434\u0435\u043b\u0438 \u0438 \u0442\u0438\u043f\u044b \u0434\u0430\u043d\u043d\u044b\u0445<\/li>\n<li>\u0432\u043e 2-\u043c \u0438 3-\u043c \u0441\u0442\u043e\u043b\u0431\u0446\u0435 \u0443\u043a\u0430\u0437\u0430\u043d\u0430 \u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0437\u0430\u043f\u0438\u0441\u0435\u0439<\/li>\n<li>\u0432 4-\u043c \u0441\u0442\u043e\u043b\u0431\u0446\u0435 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0435\u043c\u044b\u0445 \u0437\u0430\u043f\u0438\u0441\u0435\u0439 \u0432 \u0441\u0435\u043a\u0443\u043d\u0434\u0443.<\/li>\n<\/ul>\n<p>  <\/p>\n<p>\u0421\u043a\u0440\u0438\u043f\u0442 <a href=\"https:\/\/github.com\/objectum\/catalog\/blob\/master\/scripts\/test.js\">test.js<\/a><\/p>\n<p>  <\/p>\n<h2 id=\"zaklyuchenie\">\u0417\u0430\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435<\/h2>\n<p>  <\/p>\n<p>\u0414\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u0443\u044e \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u0441\u043c\u043e\u0442\u0440\u0438\u0442\u0435 \u043d\u0430 \u0434\u043e\u043c\u0430\u0448\u043d\u0438\u0445 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430\u0445 \u043f\u0430\u043a\u0435\u0442\u043e\u0432 \u043d\u0430 github. \u041a\u0430\u044e\u0441\u044c, \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f \u0442\u0430\u043c \u0441\u043a\u0443\u0434\u043d\u0430\u044f, \u0431\u0443\u0434\u0443 \u0441\u0442\u0430\u0440\u0430\u0442\u044c\u0441\u044f \u0434\u043e\u043f\u043e\u043b\u043d\u044f\u0442\u044c. \u041b\u0438\u0446\u0435\u043d\u0437\u0438\u044f \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u044b MIT. \u0412 \u043f\u043b\u0430\u043d\u0430\u0445 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0445 \u043f\u0430\u043a\u0435\u0442\u043e\u0432 \u043f\u043e \u0430\u043d\u0430\u043b\u0438\u0442\u0438\u043a\u0435 \u0438 \u0434\u0440\u0443\u0433\u0438\u043c \u043d\u0443\u0436\u043d\u044b\u043c \u043d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f\u043c.<br \/>  \u0421\u043f\u0430\u0441\u0438\u0431\u043e \u0437\u0430 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435.<\/p>\n<\/div>\n<p> \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\/post\/513648\/\"> https:\/\/habr.com\/ru\/post\/513648\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"\n<div class=\"post__text post__text-html post__text_v1\" id=\"post-content-body\" data-io-article-url=\"https:\/\/habr.com\/ru\/post\/513648\/\">\n<p>\u0415\u0441\u043b\u0438 \u0432\u0430\u043c \u043d\u0443\u0436\u0435\u043d \u043f\u0440\u043e\u0441\u0442\u043e\u0439 \u0441\u043f\u043e\u0441\u043e\u0431 \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c \u0432\u0435\u0431-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f \u0442\u043e\u043b\u044c\u043a\u043e javascript (full-stack), \u0442\u043e \u043f\u0440\u0435\u0434\u043b\u0430\u0433\u0430\u044e \u0432\u0430\u043c \u043e\u0437\u043d\u0430\u043a\u043e\u043c\u0438\u0442\u044c\u0441\u044f \u0441 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u043e\u0439 objectum. \u041d\u043e\u0432\u0430\u044f \u0432\u0435\u0440\u0441\u0438\u044f \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u044b \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u043e\u043c \u043e\u043f\u044b\u0442\u0430 \u0440\u0430\u0431\u043e\u0442\u044b \u043d\u0430\u0434 \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0435\u0439 \u0432\u0435\u0440\u0441\u0438\u0435\u0439, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f 10 \u043b\u0435\u0442. \u041e\u0431\u0435 \u0432\u0435\u0440\u0441\u0438\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442\u0441\u044f \u0432 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0435 \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0445 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u043e\u043d\u043d\u044b\u0445 \u0441\u0438\u0441\u0442\u0435\u043c \u2014 \u044d\u0442\u043e \u0440\u0435\u0433\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u044b\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u044f \u0438 \u0441\u0438\u0441\u0442\u0435\u043c\u044b \u0434\u043b\u044f \u043e\u0440\u0433\u0430\u043d\u0438\u0437\u0430\u0446\u0438\u0439. \u041f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0430 \u043d\u043e\u0432\u043e\u0439 \u0432\u0435\u0440\u0441\u0438\u0438 \u0443\u0436\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u043d\u0430 \u043f\u0440\u043e\u0434\u0430\u043a\u0448\u043d \u0441\u0435\u0440\u0432\u0435\u0440\u0430\u0445 \u0438 \u0431\u0443\u0434\u0435\u0442 \u0440\u0430\u0437\u0432\u0438\u0432\u0430\u0442\u044c\u0441\u044f \u0434\u043b\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0435 \u0432\u0440\u0435\u043c\u044f. \u0414\u0430\u043b\u0435\u0435 \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e\u0441\u0442\u0438.<\/p>\n<p>  <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/webt\/ae\/e5\/80\/aee580edcg_urdy37zuwrrst38y.png\" alt=\"logo\"\/><\/p>\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-307926","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/307926","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=307926"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/307926\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=307926"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=307926"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=307926"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}