moysklad
 # moysklad <!-- omit in toc --> [](https://www.npmjs.com/package/moysklad) [](https://github.com/wmakeev/moysklad/actions/workflows/main.yml) <!-- [](https://app.codecov.io/gh/wmakeev/moysklad/tree/master/) --> ΠΠΈΠ±Π»ΠΈΠΎΡΠ΅ΠΊΠ° Π΄Π»Ρ Π²Π·Π°ΠΈΠΌΠΎΠ΄Π΅ΠΉΡΡΠ²ΠΈΡ Ρ [JSON API ΡΠ΅ΡΠ²ΠΈΡΠ° ΠΠΎΠΉΠ‘ΠΊΠ»Π°Π΄](https://dev.moysklad.ru/) Π΄Π»Ρ node.js. > **ΠΠΠΠΠΠΠΠ!** ΠΠΈΠ±Π»ΠΈΠΎΡΠ΅ΠΊΠ° Π½Π°Ρ ΠΎΠ΄ΠΈΡΡΡ Π² ΡΡΠ°Π΄ΠΈΠΈ ΡΡΠ°Π½ΠΎΠ²Π»Π΅Π½ΠΈΡ. API ΠΌΠΎΠΆΠ΅Ρ Π½Π΅Π·Π½Π°ΡΠΈΡΠ΅Π»ΡΠ½ΠΎ ΠΌΠ΅Π½ΡΡΡΡΡ. ΠΠ΅ΡΠ΅Π΄ ΠΎΠ±Π½ΠΎΠ²Π»Π΅Π½ΠΈΠ΅ΠΌ ΠΌΠΈΠ½ΠΎΡΠ½ΠΎΠΉ Π²Π΅ΡΡΠΈΠΈ ΡΠΌΠΎΡΡΠΈΡΠ΅ [ΠΈΡΡΠΎΡΠΈΡ ΠΈΠ·ΠΌΠ΅Π½Π΅Π½ΠΈΠΉ](https://github.com/wmakeev/moysklad/blob/master/CHANGELOG.md). ΠΠΈΠ±Π»ΠΈΠΎΡΠ΅ΠΊΠ° ΠΏΡΠ΅Π΄ΡΡΠ°Π²Π»ΡΠ΅Ρ ΠΌΠ°ΠΊΡΠΈΠΌΠ°Π»ΡΠ½ΠΎ ΠΏΡΠΎΡΡΠΎΠΉ ΠΈ ΠΏΡΠΎΠ·ΡΠ°ΡΠ½ΡΠΉ ΠΈΠ½ΡΠ΅ΡΡΠ΅ΠΉΡ ΠΊ ΡΡΡΠ΅ΡΡΠ²ΡΡΡΠΈΠΌ ΠΌΠ΅ΡΠΎΠ΄Π°ΠΌ [API ΠΠΎΠΉΠ‘ΠΊΠ»Π°Π΄](https://api.moysklad.ru/api/remap/1.2/doc), Π½Π΅ Π°Π±ΡΡΡΠ°Π³ΠΈΡΡΠ΅Ρ ΡΠ°Π·ΡΠ°Π±ΠΎΡΡΠΈΠΊΠ° ΠΎΡ API ΠΈ Π½Π΅ Π²ΡΠΏΠΎΠ»Π½ΡΠ΅Ρ Π½ΠΈΠΊΠ°ΠΊΠΈΡ Π²Π½ΡΡΡΠ΅Π½Π½ΠΈΡ ΠΏΡΠ΅ΠΎΠ±ΡΠ°Π·ΠΎΠ²Π°Π½ΠΈΠΉ ΠΎΡΠΏΡΠ°Π²Π»ΡΠ΅ΠΌΡΡ ΠΈ ΠΏΠΎΠ»ΡΡΠ°Π΅ΠΌΡΡ Π΄Π°Π½Π½ΡΡ . ΠΡΠ½ΠΎΠ²Π½Π°Ρ Π·Π°Π΄Π°ΡΠ° Π±ΠΈΠ±Π»ΠΈΠΎΡΠ΅ΠΊΠΈ - ΡΠΏΡΠΎΡΡΠΈΡΡ ΡΡΠ΄ ΡΡΡΠΈΠ½Π½ΡΡ Π·Π°Π΄Π°Ρ: - ΡΠΎΡΠΌΠΈΡΠΎΠ²Π°Π½ΠΈΠ΅ ΡΡΡΠΎΠΊΠΈ Π·Π°ΠΏΡΠΎΡΠ° (ΠΏΠ΅ΡΠ΅Π΄Π°ΡΠ° ΠΏΠ°ΡΠ°ΠΌΠ΅ΡΡΠΎΠ², Π·Π°Π³ΠΎΠ»ΠΎΠ²ΠΊΠΎΠ² ΠΈ ΡΠΈΠ»ΡΡΡΠ°ΡΠΈΡ) - ΠΎΠ±ΡΠ°Π±ΠΎΡΠΊΠ° ΠΎΡΠΈΠ±ΠΎΠΊ - ΠΌΠ΅ΡΠΎΠ΄Ρ Π΄Π»Ρ ΠΏΡΠ΅ΠΎΠ±ΡΠ°Π·ΠΎΠ²Π°Π½ΠΈΡ Π΄Π°ΡΡ Π² ΡΠΎΡΠΌΠ°Ρ ΠΠΎΠΉΠ‘ΠΊΠ»Π°Π΄ ΠΈ ΠΎΠ±ΡΠ°ΡΠ½ΠΎ Π² `Date` - Π±Π°Π·ΠΎΠ²ΡΠ΅ ΡΠΈΠΏΡ TypeScript Π΄Π»Ρ ΠΏΠΎΠ΄ΡΠΊΠ°Π·ΠΎΠΊ ΠΏΠΎ API Π±ΠΈΠ±Π»ΠΈΠΎΡΠ΅ΠΊΠΈ (Π½ΠΎ Π½Π΅ Π΄Π»Ρ API ΠΠΎΠΉΠ‘ΠΊΠ»Π°Π΄) ΠΠ°ΠΆΠ½ΠΎ ΠΎΡΠΌΠ΅ΡΠΈΡΡ, ΡΡΠΎ Π±ΠΈΠ±Π»ΠΈΠΎΡΠ΅ΠΊΠ° Π½Π΅ ΠΏΠΎΠΌΠΎΠΆΠ΅Ρ Π²Π°ΠΌ ΡΠ°Π·ΠΎΠ±ΡΠ°ΡΡΡΡ Ρ API ΠΠΎΠΉΠ‘ΠΊΠ»Π°Π΄, Π½ΠΎ Π»ΠΈΡΡ ΡΠΏΡΠΎΡΡΠΈΡ ΡΠ°Π±ΠΎΡΡ Ρ Π½ΠΈΠΌ. ## Π‘ΠΎΠ΄Π΅ΡΠΆΠ°Π½ΠΈΠ΅ <!-- omit in toc --> - [Π£ΡΡΠ°Π½ΠΎΠ²ΠΊΠ°](#ΡΡΡΠ°Π½ΠΎΠ²ΠΊΠ°) - [ΠΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π½ΠΈΠ΅](#ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π½ΠΈΠ΅) - [ΠΠ°ΡΠ°ΠΌΠ΅ΡΡΡ ΠΈΠ½ΠΈΡΠΈΠ°Π»ΠΈΠ·Π°ΡΠΈΠΈ](#ΠΏΠ°ΡΠ°ΠΌΠ΅ΡΡΡ-ΠΈΠ½ΠΈΡΠΈΠ°Π»ΠΈΠ·Π°ΡΠΈΠΈ) - [ΠΡΡΠ΅Π½ΡΠΈΡΠΈΠΊΠ°ΡΠΈΡ](#Π°ΡΡΠ΅Π½ΡΠΈΡΠΈΠΊΠ°ΡΠΈΡ) - [Π‘ΡΠ°ΡΠΈΡΠ΅ΡΠΊΠΈΠ΅ ΠΌΠ΅ΡΠΎΠ΄Ρ](#ΡΡΠ°ΡΠΈΡΠ΅ΡΠΊΠΈΠ΅-ΠΌΠ΅ΡΠΎΠ΄Ρ) - [getTimeString](#gettimestring) - [parseTimeString](#parsetimestring) - [parseUrl (ΡΡΠ°ΡΠΈΡΠ΅ΡΠΊΠΈΠΉ ΠΌΠ΅ΡΠΎΠ΄)](#parseurl-ΡΡΠ°ΡΠΈΡΠ΅ΡΠΊΠΈΠΉ-ΠΌΠ΅ΡΠΎΠ΄) - [buildFilter](#buildfilter) - [buildQuery](#buildquery) - [getVersion](#getversion) - [ΠΠ΅ΡΠΎΠ΄Ρ ΡΠΊΠ·Π΅ΠΌΠΏΠ»ΡΡΠ°](#ΠΌΠ΅ΡΠΎΠ΄Ρ-ΡΠΊΠ·Π΅ΠΌΠΏΠ»ΡΡΠ°) - [GET](#get) - [POST](#post) - [PUT](#put) - [DELETE](#delete) - [getOptions](#getoptions) - [getVersion - ΠΌΠ΅ΡΠΎΠ΄ ΡΠΊΠ·Π΅ΠΌΠΏΠ»ΡΡΠ°](#getversion---ΠΌΠ΅ΡΠΎΠ΄-ΡΠΊΠ·Π΅ΠΌΠΏΠ»ΡΡΠ°) - [buildUrl](#buildurl) - [parseUrl](#parseurl) - [fetchUrl](#fetchurl) - [ΠΡΠ½ΠΎΠ²Π½ΡΠ΅ Π°ΡΠ³ΡΠΌΠ΅Π½ΡΡ](#ΠΎΡΠ½ΠΎΠ²Π½ΡΠ΅-Π°ΡΠ³ΡΠΌΠ΅Π½ΡΡ) - [path](#path) - [query](#query) - [querystring](#querystring) - [filter](#filter) - [order](#order) - [expand ΠΈ limit](#expand-ΠΈ-limit) - [options (ΠΏΠ°ΡΠ°ΠΌΠ΅ΡΡΡ Π·Π°ΠΏΡΠΎΡΠ°)](#options-ΠΏΠ°ΡΠ°ΠΌΠ΅ΡΡΡ-Π·Π°ΠΏΡΠΎΡΠ°) - [Π£ΠΏΡΠ°Π²Π»Π΅Π½ΠΈΠ΅ ΠΏΠΎΡΠΎΠΊΠΎΠΌ Π·Π°ΠΏΡΠΎΡΠΎΠ²](#ΡΠΏΡΠ°Π²Π»Π΅Π½ΠΈΠ΅-ΠΏΠΎΡΠΎΠΊΠΎΠΌ-Π·Π°ΠΏΡΠΎΡΠΎΠ²) - [ΠΠ±ΡΠ°Π±ΠΎΡΠΊΠ° ΠΎΡΠΈΠ±ΠΎΠΊ](#ΠΎΠ±ΡΠ°Π±ΠΎΡΠΊΠ°-ΠΎΡΠΈΠ±ΠΎΠΊ) - [ΠΠΎΠ²ΡΠΎΡ Π·Π°ΠΏΡΠΎΡΠ° ΠΏΡΠΈ ΠΎΡΠΈΠ±ΠΊΠ΅](#ΠΏΠΎΠ²ΡΠΎΡ-Π·Π°ΠΏΡΠΎΡΠ°-ΠΏΡΠΈ-ΠΎΡΠΈΠ±ΠΊΠ΅) - [ΠΠΈΠ΄Ρ ΠΎΡΠΈΠ±ΠΎΠΊ](#Π²ΠΈΠ΄Ρ-ΠΎΡΠΈΠ±ΠΎΠΊ) - [MoyskladError](#moyskladerror) - [MoyskladRequestError](#moyskladrequesterror) - [MoyskladApiError](#moyskladapierror) - [MoyskladCollectionError](#moyskladcollectionerror) - [MoyskladUnexpectedRedirectError](#moyskladunexpectedredirecterror) - [Π‘ΠΎΠ±ΡΡΠΈΡ](#ΡΠΎΠ±ΡΡΠΈΡ) - [ΠΡΡΠΎΡΠΈΡ ΠΈΠ·ΠΌΠ΅Π½Π΅Π½ΠΈΠΉ](#ΠΈΡΡΠΎΡΠΈΡ-ΠΈΠ·ΠΌΠ΅Π½Π΅Π½ΠΈΠΉ) - [ΠΠ»Π°Π½Ρ ΡΠ°Π·Π²ΠΈΡΠΈΡ](#ΠΏΠ»Π°Π½Ρ-ΡΠ°Π·Π²ΠΈΡΠΈΡ) - [TODO](#todo) ## Π£ΡΡΠ°Π½ΠΎΠ²ΠΊΠ° > ΠΠΎΠ΄Π΄Π΅ΡΠΆΠΈΠ²Π°ΡΡΡΡ (ΡΠ΅ΡΡΠΈΡΡΡΡΡΡ) Π²Π΅ΡΡΠΈΠΈ Node.js >=16.8 ```bash npm install moysklad ``` ΠΠ»Ρ Node.js Π΄ΠΎ 18 Π²Π΅ΡΡΠΈΠΈ, Π΄ΠΎΠΏΠΎΠ»Π½ΠΈΡΠ΅Π»ΡΠ½ΠΎ Π½ΡΠΆΠ½ΠΎ ΡΡΡΠ°Π½ΠΎΠ²ΠΈΡΡ Π±ΠΈΠ±Π»ΠΈΠΎΡΠ΅ΠΊΡ Π΄Π»Ρ [Fetch API](https://developer.mozilla.org/en/docs/Web/API/Fetch_API) ΠΈ ΡΠ²Π½ΠΎ ΡΠΊΠ°Π·Π°ΡΡ ΠΌΠΎΠ΄ΡΠ»Ρ Ρ ΡΠΎΠΎΡΠ²Π΅ΡΡΡΠ²ΡΡΡΠΈΠΌ ΠΈΠ½ΡΠ΅ΡΡΠ΅ΠΉΡΠΎΠΌ ΠΏΡΠΈ ΡΠΎΠ·Π΄Π°Π½ΠΈΠΈ ΡΠΊΠ·Π΅ΠΌΠΏΠ»ΡΡΠ° Π±ΠΈΠ±Π»ΠΈΠΎΡΠ΅ΠΊΠΈ ```bash npm install undici ``` [undici.fetch](https://github.com/nodejs/undici#undicifetchinput-init-promise) ```js import { fetch } from 'undici' import Moysklad from 'moysklad' const moysklad = Moysklad({ fetch }) ``` ## ΠΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π½ΠΈΠ΅ ```js import Moysklad from 'moysklad' // ΠΠ»Ρ ΠΈΠ½ΠΈΡΠΈΠ°Π»ΠΈΠ·Π°ΡΠΈΠΈ ΡΠΊΠ·Π΅ΠΌΠΏΠ»ΡΡΠ° Π±ΠΈΠ±Π»ΠΈΠΎΡΠ΅ΠΊΠΈ ΡΠΊΠ°Π·ΡΠ²Π°ΡΡ ΠΊΠ»ΡΡΠ΅Π²ΠΎΠ΅ ΡΠ»ΠΎΠ²ΠΎ new Π½Π΅ Π½ΡΠΆΠ½ΠΎ const ms = Moysklad({ login, password }) ms.GET('entity/customerorder', { filter: { applicable: true, state: { name: 'ΠΡΠ³ΡΡΠΆΠ΅Π½' }, sum: { $gt: 1000000, $lt: 2000000 } }, limit: 10, order: 'moment,desc', expand: 'agent' }).then(({ meta, rows }) => { console.log( `ΠΠΎΡΠ»Π΅Π΄Π½ΠΈΠ΅ ${meta.limit} ΠΈΠ· ${meta.size} ΠΏΡΠΎΠ²Π΅Π΄Π΅Π½Π½ΡΡ Π·Π°ΠΊΠ°Π·ΠΎΠ² ` + `Π² ΡΡΠ°ΡΡΡΠ΅ "ΠΡΠ³ΡΡΠΆΠ΅Π½" Π½Π° ΡΡΠΌΠΌΡ ΠΎΡ 10000 Π΄ΠΎ 20000 ΡΡΠ±` ) // ΠΡΠ²ΠΎΠ΄ΠΈΠΌ ΠΈΠΌΡ Π·Π°ΠΊΠ°Π·Π°, ΠΈΠΌΡ ΠΊΠΎΠ½ΡΡΠ°Π³Π΅Π½ΡΠ° ΠΈ ΡΡΠΌΠΌΡ Π·Π°ΠΊΠ°Π·Π° Π΄Π»Ρ Π²ΡΠ΅Ρ ΠΏΠΎΠ·ΠΈΡΠΈΠΉ rows.forEach(row => { console.log(`${row.name} ${row.agent.name} ${row.sum / 100}`) }) }) ``` > Π‘ΠΎΠ²ΠΌΠ΅ΡΡΠ½ΠΎ Ρ Π±ΠΈΠ±Π»ΠΈΠΎΡΠ΅ΠΊΠΎΠΉ ΡΠ΅ΠΊΠΎΠΌΠ΅Π½Π΄ΡΠ΅ΡΡΡ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΡ [ΠΏΠ»Π°Π½ΠΈΡΠΎΠ²ΡΠΈΠΊ Π·Π°ΠΏΡΠΎΡΠΎΠ²](#ΡΠΏΡΠ°Π²Π»Π΅Π½ΠΈΠ΅-ΠΏΠΎΡΠΎΠΊΠΎΠΌ-Π·Π°ΠΏΡΠΎΡΠΎΠ²) > Π‘ Π΄ΡΡΠ³ΠΈΠΌΠΈ ΠΏΡΠΈΠΌΠ΅ΡΠ°ΠΌΠΈ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π½ΠΈΡ ΠΌΠΎΠΆΠ½ΠΎ ΠΎΠ·Π½Π°ΠΊΠΎΠΌΠΈΡΡΡΡ Π² ΠΏΠ°ΠΏΠΊΠ΅ [examples](https://github.com/wmakeev/moysklad/tree/master/examples) ## ΠΠ°ΡΠ°ΠΌΠ΅ΡΡΡ ΠΈΠ½ΠΈΡΠΈΠ°Π»ΠΈΠ·Π°ΡΠΈΠΈ ΠΡΠ΅ ΠΏΠ°ΡΠ°ΠΌΠ΅ΡΡΡ ΠΎΠΏΡΠΈΠΎΠ½Π°Π»ΡΠ½ΡΠ΅ (ΠΈΠΌΠ΅ΡΡ Π·Π½Π°ΡΠ΅Π½ΠΈΡ ΠΏΠΎ ΡΠΌΠΎΠ»ΡΠ°Π½ΠΈΡ) | ΠΠ°ΡΠ°ΠΌΠ΅ΡΡ | ΠΠ½Π°ΡΠ΅Π½ΠΈΠ΅ ΠΏΠΎ ΡΠΌΠΎΠ»ΡΠ°Π½ΠΈΡ | ΠΠΏΠΈΡΠ°Π½ΠΈΠ΅ | | ------------ | ------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `fetch` | Π³Π»ΠΎΠ±Π°Π»ΡΠ½ΡΠΉ fetch | Π€ΡΠ½ΠΊΡΠΈΡ Ρ ΠΈΠ½ΡΠ΅ΡΡΠ΅ΠΉΡΠΎΠΌ [Fetch API](https://developer.mozilla.org/ru/docs/Web/API/Fetch_API). ΠΡΠ»ΠΈ Π³Π»ΠΎΠ±Π°Π»ΡΠ½ΡΠΉ fetch Π½Π΅ Π½Π°ΠΉΠ΄Π΅Π½, ΡΠΎ Π±ΡΠ΄Π΅Ρ Π²ΡΠ±ΡΠΎΡΠ΅Π½Π° ΠΎΡΠΈΠ±ΠΊΠ° ΠΏΡΠΈ ΠΏΠΎΠΏΡΡΠΊΠ΅ ΠΎΡΡΡΠ΅ΡΡΠ²ΠΈΡΡ http Π·Π°ΠΏΡΠΎΡ. ΠΠ°ΡΠΈΠ½Π°Ρ Ρ Node.js 18 [fetch](https://nodejs.org/dist/latest-v18.x/docs/api/globals.html#fetch) ΡΠ²Π»ΡΠ΅ΡΡΡ ΡΠ°ΡΡΡΡ ΡΡΠ°Π½Π΄Π°ΡΡΠ½ΠΎΠΉ Π±ΠΈΠ±Π»ΠΈΠΎΡΠ΅ΠΊΠΈ. | | `retry` | ΡΡΠ½ΠΊΡΠΈΡ Π²ΠΈΠ΄Π° `(thunk) => thunk()` | Π€ΡΠ½ΠΊΡΠΈΡ Π΄Π»Ρ ΡΠΏΡΠ°Π²Π»Π΅Π½ΠΈΡ ΠΏΠΎΠ²Π΅Π΄Π΅Π½ΠΈΠ΅ΠΌ ΠΏΡΠΈ Π²ΠΎΠ·Π½ΠΈΠΊΠ½ΠΎΠ²Π΅Π½ΠΈΠΈ ΠΎΡΠΈΠ±ΠΎΠΊ (ΡΠΌ. [ΠΠΎΠ²ΡΠΎΡ Π·Π°ΠΏΡΠΎΡΠ° ΠΏΡΠΈ ΠΎΡΠΈΠ±ΠΊΠ΅](#ΠΏΠΎΠ²ΡΠΎΡ-Π·Π°ΠΏΡΠΎΡΠ°-ΠΏΡΠΈ-ΠΎΡΠΈΠ±ΠΊΠ΅)). | | `endpoint` | `"https://api.moysklad.ru/api"` | Π’ΠΎΡΠΊΠ° Π΄ΠΎΡΡΡΠΏΠ° ΠΊ API (Ρ ΠΎΡΡ ΡΠΎΡΠΊΠΈ Π΄ΠΎΡΡΡΠΏΠ° ΠΌΠΎΠΆΠ½ΠΎ ΡΠΊΠ°Π·Π°ΡΡ ΡΠ΅ΡΠ΅Π· ΠΏΠ΅ΡΠ΅ΠΌΠ΅Π½Π½ΡΡ ΠΎΠΊΡΡΠΆΠ΅Π½ΠΈΡ `MOYSKLAD_HOST`, ΠΏΠΎ ΡΠΌΠΎΠ»ΡΠ°Π½ΠΈΡ `api.moysklad.ru`) | | `api` | `"remap"` | Π Π°Π·Π΄Π΅Π» API (ΠΌΠΎΠΆΠ½ΠΎ Π·Π°Π΄Π°ΡΡ ΡΠ΅ΡΠ΅Π· ΠΏΠ΅ΡΠ΅ΠΌΠ΅Π½Π½ΡΡ ΠΎΠΊΡΡΠΆΠ΅Π½ΠΈΡ `MOYSKLAD_API`) | | `apiVersion` | `"1.2"` | ΠΠ΅ΡΡΠΈΡ API (ΠΌΠΎΠΆΠ½ΠΎ Π·Π°Π΄Π°ΡΡ ΡΠ΅ΡΠ΅Π· ΠΏΠ΅ΡΠ΅ΠΌΠ΅Π½Π½ΡΡ ΠΎΠΊΡΡΠΆΠ΅Π½ΠΈΡ `MOYSKLAD_{NAME}_API_VERSION`, Π³Π΄Π΅ `{NAME}` - Π½Π°Π·Π²Π°Π½ΠΈΠ΅ API Π² Π²Π΅ΡΡ Π½Π΅ΠΌ ΡΠ΅Π³ΠΈΡΡΡΠ΅, Π½Π°ΠΏΡ. `MOYSKLAD_REMAP_API_VERSION`) | | `token` | `undefined` | Π’ΠΎΠΊΠ΅Π½ Π΄ΠΎΡΡΡΠΏΠ° ΠΊ API (ΡΠΌ. [ΠΡΡΠ΅Π½ΡΠΈΡΠΈΠΊΠ°ΡΠΈΡ](#Π°ΡΡΠ΅Π½ΡΠΈΡΠΈΠΊΠ°ΡΠΈΡ)) | | `login` | `undefined` | ΠΠΎΠ³ΠΈΠ½ Π΄Π»Ρ Π΄ΠΎΡΡΡΠΏΠ° ΠΊ API (ΡΠΌ. [ΠΡΡΠ΅Π½ΡΠΈΡΠΈΠΊΠ°ΡΠΈΡ](#Π°ΡΡΠ΅Π½ΡΠΈΡΠΈΠΊΠ°ΡΠΈΡ)) | | `password` | `undefined` | ΠΠ°ΡΠΎΠ»Ρ Π΄Π»Ρ Π΄ΠΎΡΡΡΠΏΠ° ΠΊ API (ΡΠΌ. [ΠΡΡΠ΅Π½ΡΠΈΡΠΈΠΊΠ°ΡΠΈΡ](#Π°ΡΡΠ΅Π½ΡΠΈΡΠΈΠΊΠ°ΡΠΈΡ)) | | `emitter` | `undefined` | ΡΠΊΠ·Π΅ΠΌΠΏΠ»ΡΡ [EventEmitter](https://nodejs.org/api/events.html#events_class_eventemitter) Π΄Π»Ρ ΠΏΠ΅ΡΠ΅Π΄Π°ΡΠΈ [ΡΠΎΠ±ΡΡΠΈΠΉ Π±ΠΈΠ±Π»ΠΈΠΎΡΠ΅ΠΊΠΈ](#ΡΠΎΠ±ΡΡΠΈΡ) | | `userAgent` | `moysklad/{ver} (+https://github.com/wmakeev/moysklad)`, Π³Π΄Π΅ `{ver}` - ΡΠ΅ΠΊΡΡΠ°Ρ Π²Π΅ΡΡΠΈΡ Π±ΠΈΠ±Π»ΠΈΠΎΡΠ΅ΠΊΠΈ | Π‘ΠΎΠ΄Π΅ΡΠΆΠΈΠΌΠΎΠ΅ Π·Π°Π³ΠΎΠ»ΠΎΠ²ΠΊΠ° "User-Agent" ΠΏΡΠΈ Π²ΡΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ Π·Π°ΠΏΡΠΎΡΠ°. Π£Π΄ΠΎΠ±Π½ΠΎ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΡ Π΄Π»Ρ ΠΊΠΎΠ½ΡΡΠΎΠ»Ρ ΠΈΠ·ΠΌΠ΅Π½Π΅Π½ΠΈΠΉ ΡΠ΅ΡΠ΅Π· API Π½Π° Π²ΠΊΠ»Π°Π΄ΠΊΠ΅ "ΠΡΠ΄ΠΈΡ". ΠΠΎΠΆΠ½ΠΎ Π·Π°Π΄Π°ΡΡ ΡΠ΅ΡΠ΅Π· ΠΏΠ΅ΡΠ΅ΠΌΠ΅Π½Π½ΡΡ ΠΎΠΊΡΡΠΆΠ΅Π½ΠΈΡ `MOYSKLAD_USER_AGENT`. | Π―Π²Π½ΠΎΠ΅ Π·Π°Π΄Π°Π½ΠΈΠ΅ ΠΏΠ°ΡΠ°ΠΌΠ΅ΡΡΠ° ΠΏΠ΅ΡΠ΅ΠΎΠΏΡΠ΅Π΄Π΅Π»ΡΠ΅Ρ Π·Π½Π°ΡΠ΅Π½ΠΈΠ΅ Π·Π°Π΄Π°Π½Π½ΠΎΠ΅ Π² ΡΠΎΠΎΡΠ². ΠΏΠ΅ΡΠ΅ΠΌΠ΅Π½Π½ΠΎΠΉ ΠΎΠΊΡΡΠΆΠ΅Π½ΠΈΡ. **ΠΡΠΈΠΌΠ΅Ρ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π½ΠΈΡ:** ```js import Moysklad from 'moysklad' // Π―Π²Π½ΠΎΠ΅ ΡΠΊΠ°Π·Π°Π½ΠΈΠ΅ ΠΈΡΠΏΠΎΠ»ΡΠ·ΡΠ΅ΠΌΠΎΠΉ Π²Π΅ΡΡΠΈΠΈ API const moysklad = Moysklad({ apiVersion: '1.2' }) ``` ## ΠΡΡΠ΅Π½ΡΠΈΡΠΈΠΊΠ°ΡΠΈΡ ΠΡΡΡ Π½Π΅ΡΠΊΠΎΠ»ΡΠΊΠΎ ΡΠΏΠΎΡΠΎΠ±ΠΎΠ² ΠΏΠ΅ΡΠ΅Π΄Π°ΡΠΈ ΠΏΠ°ΡΠ°ΠΌΠ΅ΡΡΠΎΠ² Π°ΡΡΠ΅Π½ΡΠΈΡΠΈΠΊΠ°ΡΠΈΠΈ: 1. ΠΠ°ΠΏΡΡΠΌΡΡ ΠΏΡΠΈ ΠΈΠ½ΠΈΡΠΈΠ°Π»ΠΈΠ·Π°ΡΠΈΠΈ ΡΠΊΠ·Π΅ΠΌΠΏΠ»ΡΡΠ° ```js // ΠΡΡΠ΅Π½ΡΠΈΡΠΈΠΊΠ°ΡΠΈΡ ΠΏΠΎ Π»ΠΎΠ³ΠΈΠ½Ρ ΠΈ ΠΏΠ°ΡΠΎΠ»Ρ const moysklad = Moysklad({ login, password }) ``` ```js // ΠΡΡΠ΅Π½ΡΠΈΡΠΈΠΊΠ°ΡΠΈΡ ΠΏΠΎ ΡΠΎΠΊΠ΅Π½Ρ const moysklad = Moysklad({ token }) ``` 2. Π§Π΅ΡΠ΅Π· Π³Π»ΠΎΠ±Π°Π»ΡΠ½ΡΠ΅ ΠΏΠ΅ΡΠ΅ΠΌΠ΅Π½Π½ΡΠ΅ ΠΈΠ»ΠΈ ΠΏΠ΅ΡΠ΅ΠΌΠ΅Π½Π½ΡΠ΅ ΠΎΠΊΡΡΠΆΠ΅Π½ΠΈΡ ΠΡΠ»ΠΈ ΠΏΠ°ΡΠ°ΠΌΠ΅ΡΡΡ Π°ΡΡΠ΅Π½ΡΠΈΡΠΈΠΊΠ°ΡΠΈΠΈ Π½Π΅ ΡΠΊΠ°Π·Π°Π½Ρ ΠΏΡΠΈ ΠΈΠ½ΠΈΡΠΈΠ°Π»ΠΈΠ·Π°ΡΠΈΠΈ ΠΊΠ»ΠΈΠ΅Π½ΡΠ°, ```js const moysklad = Moysklad() ``` ΡΠΎ Π±ΡΠ΄Π΅Ρ ΠΏΡΠΎΠ²Π΅Π΄Π΅Π½ ΠΏΠΎΠΈΡΠΊ ΠΏΠ°ΡΠ°ΠΌΠ΅ΡΡΠΎΠ² Π² ΡΠ»Π΅Π΄ΡΡΡΠ΅ΠΌ ΠΏΠΎΡΡΠ΄ΠΊΠ΅: 1. ΠΠ΅ΡΠ΅ΠΌΠ΅Π½Π½Π°Ρ ΠΎΠΊΡΡΠΆΠ΅Π½ΠΈΡ `process.env.MOYSKLAD_TOKEN` 2. ΠΠ΅ΡΠ΅ΠΌΠ΅Π½Π½ΡΠ΅ ΠΎΠΊΡΡΠΆΠ΅Π½ΠΈΡ `process.env.MOYSKLAD_LOGIN` ΠΈ `process.env.MOYSKLAD_PASSWORD` 3. ΠΠ»ΠΎΠ±Π°Π»ΡΠ½Π°Ρ ΠΏΠ΅ΡΠ΅ΠΌΠ΅Π½Π½Π°Ρ `window.MOYSKLAD_TOKEN` 4. ΠΠ»ΠΎΠ±Π°Π»ΡΠ½ΡΠ΅ ΠΏΠ΅ΡΠ΅ΠΌΠ΅Π½Π½ΡΠ΅ `window.MOYSKLAD_LOGIN` ΠΈ `window.MOYSKLAD_PASSWORD` 5. ΠΠ»ΠΎΠ±Π°Π»ΡΠ½Π°Ρ ΠΏΠ΅ΡΠ΅ΠΌΠ΅Π½Π½Π°Ρ `global.MOYSKLAD_TOKEN` 6. ΠΠ»ΠΎΠ±Π°Π»ΡΠ½ΡΠ΅ ΠΏΠ΅ΡΠ΅ΠΌΠ΅Π½Π½ΡΠ΅ `global.MOYSKLAD_LOGIN` ΠΈ `global.MOYSKLAD_PASSWORD` ## Π‘ΡΠ°ΡΠΈΡΠ΅ΡΠΊΠΈΠ΅ ΠΌΠ΅ΡΠΎΠ΄Ρ ### getTimeString > ΠΡΠ΅ΠΎΠ±ΡΠ°Π·ΡΠ΅Ρ Π»ΠΎΠΊΠ°Π»ΡΠ½ΡΡ Π΄Π°ΡΡ Π² ΡΡΡΠΎΠΊΡ Π² ΡΠΎΡΠΌΠ°ΡΠ΅ API ΠΠΎΠΉΠ‘ΠΊΠ»Π°Π΄ Π² ΡΠ°ΡΠΎΠ²ΠΎΠΌ ΠΏΠΎΡΡΠ΅ ΠΠΎΡΠΊΠ²Ρ ```ts Moysklad.getTimeString(date: Date, includeMs?: boolean): string ``` **ΠΠ°ΡΠ°ΠΌΠ΅ΡΡΡ:** `date` - Π΄Π°ΡΠ° `includeMs` - Π΅ΡΠ»ΠΈ `true`, ΡΠΎ Π² Π΄Π°ΡΡ Π±ΡΠ΄ΡΡ Π²ΠΊΠ»ΡΡΠ΅Π½Ρ ΠΌΠΈΠ»Π»ΠΈΡΠ΅ΠΊΡΠ½Π΄Ρ **ΠΡΠΈΠΌΠ΅Ρ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π½ΠΈΡ:** ```js const date = new Date('2017-02-01T07:10:11.123Z') const timeString = Moysklad.getTimeString(date, true) assert.equal(timeString, '2017-02-01 10:10:11.123') ``` ### parseTimeString > ΠΡΠ΅ΠΎΠ±ΡΠ°Π·ΡΠ΅Ρ ΡΡΡΠΎΠΊΡ Ρ Π΄Π°ΡΠΎΠΉ Π² ΡΠΎΡΠΌΠ°ΡΠ΅ API ΠΠΎΠΉΠ‘ΠΊΠ»Π°Π΄ Π² ΠΎΠ±ΡΠ΅ΠΊΡ Π΄Π°ΡΡ (Ρ ΡΡΠ΅ΡΠΎΠΌ Π»ΠΎΠΊΠ°Π»ΡΠ½ΠΎΠ³ΠΎ ΡΠ°ΡΠΎΠ²ΠΎΠ³ΠΎ ΠΏΠΎΡΡΠ° ΠΈ ΡΠ°ΡΠΎΠ²ΠΎΠ³ΠΎ ΠΏΠΎΡΡΠ° API ΠΠΎΠΉΠ‘ΠΊΠ»Π°Π΄) ```ts Moysklad.parseTimeString(date: string) : Date ``` **ΠΠ°ΡΠ°ΠΌΠ΅ΡΡΡ:** `date` - Π΄Π°ΡΠ° Π² ΡΠΎΡΠΌΠ°ΡΠ΅ ΠΠΎΠΉΠ‘ΠΊΠ»Π°Π΄ (Π½Π°ΠΏΡ. `2017-04-08 13:33:00.123`) **ΠΡΠΈΠΌΠ΅Ρ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π½ΠΈΡ:** ```js const parsedDate = Moysklad.parseTimeString('2017-04-08 13:33:00.123') assert.equal(parsedDate.toISOString(), '2017-04-08T10:33:00.123Z') ``` ### parseUrl (ΡΡΠ°ΡΠΈΡΠ΅ΡΠΊΠΈΠΉ ΠΌΠ΅ΡΠΎΠ΄) > Π Π°Π·Π±ΠΎΡ url Π½Π° ΡΠΎΡΡΠ°Π²Π½ΡΠ΅ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½ΡΡ ΠΠ½Π°Π»ΠΎΠ³ΠΈΡΠ΅Π½ [parseUrl](#parseurl) ΠΌΠ΅ΡΠΎΠ΄Ρ ΡΠΊΠ·Π΅ΠΌΠΏΠ»ΡΡΠ°, Π·Π° ΡΠ΅ΠΌ ΠΈΡΠΊΠ»ΡΡΠ΅Π½ΠΈΠ΅ΠΌ, ΡΡΠΎ Π½Π° Π²Ρ ΠΎΠ΄ ΠΏΡΠΈΠ½ΠΈΠΌΠ°Π΅Ρ ΡΠΎΠ»ΡΠΊΠΎ ΡΡΡΠΎΠΊΡ Π² ΡΠΎΡΠΌΠ°ΡΠ΅ href ΠΠΎΠΉΠ‘ΠΊΠ»Π°Π΄. ### buildFilter > ΠΠΎΠ·Π²ΡΠ°ΡΠ°Π΅Ρ ΡΡΡΠΎΠΊΡ ΡΠΈΠ»ΡΡΡΠ° ΠΏΠΎ ΠΎΠ±ΡΠ΅ΠΊΡΡ `QueryFilter` (ΡΠΌ. [filter](#filter)) ```js Moysklad.buildFilter({ name: { $st: 'foo' } }) // 'code=123;name~=foo' ``` ### buildQuery > Π€ΠΎΡΠΌΠΈΡΡΠ΅Ρ ΡΡΡΠΎΠΊΡ Ρ ΠΏΠ°ΡΠ°ΠΌΠ΅ΡΡΠ°ΠΌΠΈ Π·Π°ΠΏΡΠΎΡΠ° ΠΏΠΎ ΠΎΠ±ΡΠ΅ΠΊΡΡ `Query` (ΡΠΌ. [query](#query)) ```js Moysklad.buildQuery({ filter: { name: 'foo' }, limit: 100, foo: 'bar' }) // 'filter=name%3Dfoo&limit=100&foo=bar' ``` ### getVersion > ΠΠΎΠ·Π²ΡΠ°ΡΠ°Π΅Ρ ΡΠ΅ΠΊΡΡΡΡ Π²Π΅ΡΡΠΈΡ Π±ΠΈΠ±Π»ΠΈΠΎΡΠ΅ΠΊΠΈ. ΠΠ΅ΡΡΠΈΡ ΠΈΠ· package.json (ΠΏΠΎΠ»Π΅ `version`) ## ΠΠ΅ΡΠΎΠ΄Ρ ΡΠΊΠ·Π΅ΠΌΠΏΠ»ΡΡΠ° ### GET > GET Π·Π°ΠΏΡΠΎΡ ```ts ms.GET(path: string, query?: object, options?: object): Promise ``` **ΠΠ°ΡΠ°ΠΌΠ΅ΡΡΡ:** `path` - [url ΡΠ΅ΡΡΡΡΠ°](#path) `query` - [ΠΏΠ°ΡΠ°ΠΌΠ΅ΡΡΡ Π·Π°ΠΏΡΠΎΡΠ°](#query) `options` - [ΠΎΠΏΡΠΈΠΈ Π·Π°ΠΏΡΠΎΡΠ°](#options-ΠΏΠ°ΡΠ°ΠΌΠ΅ΡΡΡ-Π·Π°ΠΏΡΠΎΡΠ°) **ΠΡΠΈΠΌΠ΅Ρ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π½ΠΈΡ:** ```js const productsCollection = await ms.GET('entity/product', { limit: 50 }) const order = await ms.GET(`entity/customerorder/${orderId}`, { expand: 'positions' }) ``` ### POST > POST Π·Π°ΠΏΡΠΎΡ ```ts ms.POST( path: string, payload?: object | Array<object>, query?: object, options?: object ): Promise ``` **ΠΠ°ΡΠ°ΠΌΠ΅ΡΡΡ:** `path` - [url ΡΠ΅ΡΡΡΡΠ°](#path) `payload` - ΠΎΠ±ΡΠ΅ΠΊΡ ΠΈΠ»ΠΈ ΠΊΠΎΠ»Π»Π΅ΠΊΡΠΈΡ ΠΎΠ±ΡΠ΅ΠΊΡΠΎΠ² (Π±ΡΠ΄Π΅Ρ ΠΏΡΠ΅ΠΎΠ±ΡΠ°Π·ΠΎΠ²Π°Π½ΠΎ Π² ΡΡΡΠΎΠΊΡ ΠΌΠ΅ΡΠΎΠ΄ΠΎΠΌ `JSON.stringify`) `query` - [ΠΏΠ°ΡΠ°ΠΌΠ΅ΡΡΡ Π·Π°ΠΏΡΠΎΡΠ°](#query) `options` - [ΠΎΠΏΡΠΈΠΈ Π·Π°ΠΏΡΠΎΡΠ°](#options-ΠΏΠ°ΡΠ°ΠΌΠ΅ΡΡΡ-Π·Π°ΠΏΡΠΎΡΠ°) **ΠΡΠΈΠΌΠ΅Ρ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π½ΠΈΡ:** ```js const newProduct = await ms.POST('entity/product', { name: 'ΠΠΎΠ²ΡΠΉ ΡΠΎΠ²Π°Ρ' }) ``` ΠΠΎ ΡΠΌΠΎΠ»ΡΠ°Π½ΠΈΡ, ΠΏΡΠΈ ΠΌΠ°ΡΡΠΎΠ²ΠΎΠΌ ΠΎΠ±Π½ΠΎΠ²Π»Π΅Π½ΠΈΠΈ ΡΡΡΠ½ΠΎΡΡΠ΅ΠΉ, Π΅ΡΠ»ΠΈ _Ρ ΠΎΡΡ Π±Ρ ΠΎΠ΄ΠΈΠ½_ ΠΈΠ· ΡΠ»Π΅ΠΌΠ΅Π½ΡΠΎΠ² Π² ΠΎΡΠ²Π΅ΡΠ΅ ΡΠΎΠ΄Π΅ΡΠΆΠΈΡ ΠΎΡΠΈΠ±ΠΊΡ, ΡΠΎ ΠΌΠ΅ΡΠΎΠ΄ Π²ΡΠ±ΡΠΎΡΠΈΡ ΠΎΡΠΈΠ±ΠΊΡ [MoyskladCollectionError](#moyskladcollectionerror) . ΠΡΠ»ΠΈ ΡΠ°ΠΊΠΎΠ΅ ΠΏΠΎΠ²Π΅Π΄Π΅Π½ΠΈΠ΅ Π½Π΅ ΡΠ²Π»ΡΠ΅ΡΡΡ ΠΏΡΠ΅Π΄ΠΏΠΎΡΡΠΈΡΠ΅Π»ΡΠ½ΡΠΌ, ΡΠΎ ΠΌΠΎΠΆΠ½ΠΎ ΠΎΠ±ΡΠ°Π±Π°ΡΡΠ²Π°ΡΡ ΠΎΡΠΈΠ±ΠΊΠΈ ΠΏΡΠΈ ΠΌΠ°ΡΡΠΎΠ²ΠΎΠΌ ΠΎΠ±Π½ΠΎΠ²Π»Π΅Π½ΠΈΠΈ/ΡΠΎΠ·Π΄Π°Π½ΠΈΠΈ ΠΎΠ±ΡΠ΅ΠΊΡΠΎΠ² Π²ΡΡΡΠ½ΡΡ (ΡΠΌ. `muteCollectionErrors` Π² [ΠΏΠ°ΡΠ°ΠΌΠ΅ΡΡΠ°Ρ Π·Π°ΠΏΡΠΎΡΠ°](#options-ΠΏΠ°ΡΠ°ΠΌΠ΅ΡΡΡ-Π·Π°ΠΏΡΠΎΡΠ°)): ```js const updated = await ms.POST('entity/supply', supplyList, null, { muteCollectionErrors: true }) const errors = updated .filter(item => item.errors) .map(item => item.errors[0].error) if (errors.length) { console.log('ΠΡΡΡ ΠΎΡΠΈΠ±ΠΊΠΈ:', errors.join(', ')) } const supplyHrefList = updated .filter(item => !item.errors) .map(item => item.meta.href) ``` ### PUT > PUT Π·Π°ΠΏΡΠΎΡ ```ts ms.PUT( path: string | string[], payload?: object, query?: object, options?: object ) : Promise ``` **ΠΠ°ΡΠ°ΠΌΠ΅ΡΡΡ:** `path` - [url ΡΠ΅ΡΡΡΡΠ°](#path) `payload` - ΠΎΠ±Π½ΠΎΠ²Π»ΡΠ΅ΠΌΡΠΉ ΠΎΠ±ΡΠ΅ΠΊΡ (Π±ΡΠ΄Π΅Ρ ΠΏΡΠ΅ΠΎΠ±ΡΠ°Π·ΠΎΠ²Π°Π½ Π² ΡΡΡΠΎΠΊΡ ΠΌΠ΅ΡΠΎΠ΄ΠΎΠΌ `JSON.stringify`) `query` - [ΠΏΠ°ΡΠ°ΠΌΠ΅ΡΡΡ Π·Π°ΠΏΡΠΎΡΠ°](#query) `options` - [ΠΎΠΏΡΠΈΠΈ Π·Π°ΠΏΡΠΎΡΠ°](#options-ΠΏΠ°ΡΠ°ΠΌΠ΅ΡΡΡ-Π·Π°ΠΏΡΠΎΡΠ°) **ΠΡΠΈΠΌΠ΅Ρ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π½ΠΈΡ:** ```js const updatedProduct = await ms.PUT(`entity/product/${id}`, product) ``` ### DELETE > DELETE Π·Π°ΠΏΡΠΎΡ ```ts ms.DELETE(path: string, options?: object): Promise ``` **ΠΠ°ΡΠ°ΠΌΠ΅ΡΡΡ:** `path` - [url ΡΠ΅ΡΡΡΡΠ°](#path) `options` - [ΠΎΠΏΡΠΈΠΈ Π·Π°ΠΏΡΠΎΡΠ°](#options-ΠΏΠ°ΡΠ°ΠΌΠ΅ΡΡΡ-Π·Π°ΠΏΡΠΎΡΠ°) ΠΠ΅ΡΠΎΠ΄ `DELETE` Π²ΠΎΠ·Π²ΡΠ°ΡΠ°Π΅Ρ `undefined` ΠΏΡΠΈ ΡΡΠΏΠ΅ΡΠ½ΠΎΠΌ Π·Π°ΠΏΡΠΎΡΠ΅. **ΠΡΠΈΠΌΠ΅Ρ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π½ΠΈΡ:** ```js await ms.DELETE(`entity/product/${product.id}`) ``` ### getOptions > ΠΠΎΠ·Π²ΡΠ°ΡΠ°Π΅Ρ ΠΎΠΏΡΠΈΠΈ ΠΏΠ΅ΡΠ΅Π΄Π°Π½Π½ΡΠ΅ Π² ΠΌΠΎΠΌΠ΅Π½Ρ ΠΈΠ½ΠΈΡΠΈΠ°Π»ΠΈΠ·Π°ΡΠΈΠΈ ΡΠΊΠ·Π΅ΠΌΠΏΠ»ΡΡΠ° Π±ΠΈΠ±Π»ΠΈΠΎΡΠ΅ΠΊΠΈ **ΠΡΠΈΠΌΠ΅Ρ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π½ΠΈΡ:** ```js const options = { login: 'login', password: 'password' } const ms = Moysklad(options) const msOptions = ms.getOptions() assert.ok(msOptions !== options) assert.equal(msOptions.login, 'login') assert.equal(msOptions.password, 'password') ``` ### getVersion - ΠΌΠ΅ΡΠΎΠ΄ ΡΠΊΠ·Π΅ΠΌΠΏΠ»ΡΡΠ° > ΠΠ½Π°Π»ΠΎΠ³ΠΈΡΠ΅Π½ ΡΡΠ°ΡΠΈΡΠ΅ΡΠΊΠΎΠΌΡ ΠΌΠ΅ΡΠΎΠ΄Ρ [getVersion](#getversion) ### buildUrl > Π€ΠΎΡΠΌΠΈΡΡΠ΅Ρ url Π·Π°ΠΏΡΠΎΡΠ° ```ts ms.buildUrl(url: string, query?: object): string ``` **ΠΠ°ΡΠ°ΠΌΠ΅ΡΡΡ:** `url` - ΠΏΠΎΠ»Π½ΡΠΉ url (Π΄ΠΎΠ»ΠΆΠ΅Π½ ΡΠΎΠΎΡΠ²Π΅ΡΡΡΠ²ΠΎΠ²Π°ΡΡ Π½Π°ΡΡΡΠΎΠΉΠΊΠ°ΠΌ) `path` - [url ΡΠ΅ΡΡΡΡΠ°](#path) `query` - [ΠΏΠ°ΡΠ°ΠΌΠ΅ΡΡΡ Π·Π°ΠΏΡΠΎΡΠ°](#query) **ΠΡΠΈΠΌΠ΅Ρ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π½ΠΈΡ:** ```js const url = ms.buildUrl( 'https://api.moysklad.ru/api/remap/1.2/entity/customerorder?expand=positions', { limit: 100 } ) assert.equal( url, 'https://api.moysklad.ru/api/remap/1.2/entity/customerorder?expand=positions&limit=100' ) ``` ```js const url = ms.buildUrl('entity/customerorder', { expand: 'positions' }) assert.equal( url, 'https://api.moysklad.ru/api/remap/1.2/entity/customerorder?expand=positions' ) ``` ΠΠΎΠΆΠ½ΠΎ Π±Π΅Π·ΠΎΠΏΠ°ΡΠ½ΠΎ Π΄ΡΠ±Π»ΠΈΡΠΎΠ²Π°ΡΡ ΡΠΈΠΌΠ²ΠΎΠ»Ρ `/`, Π»ΠΈΡΠ½ΠΈΠ΅ Π·Π½Π°ΠΊΠΈ Π±ΡΠ΄ΡΡ ΠΈΡΠΊΠ»ΡΡΠ΅Π½Ρ ΠΈΠ· ΡΠ΅Π·ΡΠ»ΡΡΠΈΡΡΡΡΠ΅Π³ΠΎ url ```js const positionUrl = `/positions/${posId}/` const url = ms.buildUrl(`entity/customerorder/` + positionUrl) assert.equal( url, `https://api.moysklad.ru/api/remap/1.2/entity/customerorder/positions/${posId}` ) ``` ### parseUrl > Π Π°Π·Π±ΠΎΡ url Π½Π° ΡΠΎΡΡΠ°Π²Π½ΡΠ΅ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½ΡΡ ```ts ms.parseUrl(url: string): { endpoint: string api: string apiVersion: string path: Array<string> query: object } ``` **ΠΠ°ΡΠ°ΠΌΠ΅ΡΡΡ:** `url` - url ΡΠ΅ΡΡΡΡΠ° **ΠΡΠΈΠΌΠ΅Ρ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π½ΠΈΡ:** ```js const parsedUri = ms.parseUrl('https://api.moysklad.ru/api/remap/1.2/entity/customerorder?expand=positions') assert.deepEqual(parsedUri, { endpoint: 'https://api.moysklad.ru/api', api: 'remap' apiVersion: '1.2', path: ['entity', 'customerorder'], query: { expand: 'positions' } }) ``` ### fetchUrl > ΠΡΠΏΠΎΠ»Π½ΠΈΡΡ Π·Π°ΠΏΡΠΎΡ ΠΏΠΎ ΡΠΊΠ°Π·Π°Π½Π½ΠΎΠΌΡ url ```ts ms.fetchUrl(url: string, options?: object): Promise ``` **ΠΠ°ΡΠ°ΠΌΠ΅ΡΡΡ:** `url` - url ΡΠ΅ΡΡΡΡΠ° `options` - [ΠΎΠΏΡΠΈΠΈ Π·Π°ΠΏΡΠΎΡΠ°](#options-ΠΏΠ°ΡΠ°ΠΌΠ΅ΡΡΡ-Π·Π°ΠΏΡΠΎΡΠ°) **ΠΡΠΈΠΌΠ΅Ρ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π½ΠΈΡ:** ```js const url = `https://api.moysklad.ru/api/remap/1.2/entity/customerorder/eb7bcc22-ae8d-11e3-9e32-002590a28eca` const patch = { applicable: false } const updatedOrder = await ms.fetchUrl(url, { method: 'PUT', body: JSON.stringify(patch) }) ``` ### ΠΡΠ½ΠΎΠ²Π½ΡΠ΅ Π°ΡΠ³ΡΠΌΠ΅Π½ΡΡ #### path Π‘ΡΡΠΎΠΊΠ°. **ΠΡΠΈΠΌΠ΅ΡΡ:** Url Π·Π°ΠΏΡΠΎΡΠ° ΠΌΠΎΠΆΠ½ΠΎ ΡΠΊΠ°Π·Π°ΡΡ ΠΏΠΎΠ»Π½ΠΎΡΡΡΡ ```js ms.GET( `https://api.moysklad.ru/api/remap/1.2/entity/customerorder/${ORDER_ID}/positions/${POSITION_ID}?expand=assortment` ) ``` ΠΠΎ Π³ΠΎΡΠ°Π·Π΄ΠΎ ΡΠ΄ΠΎΠ±Π½Π΅Π΅ ΡΠΊΠ°Π·ΡΠ²Π°ΡΡ ΠΏΡΡΡ ΡΠΎΠ»ΡΠΊΠΎ ΠΏΠΎΡΠ»Π΅ Π²Π΅ΡΡΠΈΠΈ API ΠΈ Π²ΡΠ½ΠΎΡΠΈΡΡ ΠΏΠ°ΡΠ°ΠΌΠ΅ΡΡΡ Π·Π°ΠΏΡΠΎΡΠ° Π² ΠΏΠ°ΡΠ°ΠΌΠ΅ΡΡΡ ΠΌΠ΅ΡΠΎΠ΄Π°. ΠΠΎΠ»Π½ΡΠΉ url Π±ΡΠ΄Π΅Ρ ΡΠ³Π΅Π½Π΅ΡΠΈΡΠΎΠ²Π°Π½ Π°Π²ΡΠΎΠΌΠ°ΡΠΈΡΠ΅ΡΠΊΠΈ, ΡΠΎΠ³Π»Π°ΡΠ½ΠΎ [Π½Π°ΡΡΡΠΎΠΉΠΊΠ°ΠΌ ΡΠΊΠ·Π΅ΠΌΠΏΠ»ΡΡΠ°](#ΠΏΠ°ΡΠ°ΠΌΠ΅ΡΡΡ-ΠΈΠ½ΠΈΡΠΈΠ°Π»ΠΈΠ·Π°ΡΠΈΠΈ). ΠΠΈΠΆΠ΅ ΠΏΡΠΈΠΌΠ΅Ρ Π°Π½Π°Π»ΠΎΠ³ΠΈΡΠ½ΠΎΠ³ΠΎ Π·Π°ΠΏΡΠΎΡΠ°: ```js ms.GET(`entity/customerorder/${ORDER_ID}/positions/${POSITION_ID}`, { expand: 'assortment' }) ``` ΠΠΎΠΆΠ½ΠΎ Π±Π΅Π·ΠΎΠΏΠ°ΡΠ½ΠΎ Π΄ΡΠ±Π»ΠΈΡΠΎΠ²Π°ΡΡ ΡΠΈΠΌΠ²ΠΎΠ»Ρ `/`, Π»ΠΈΡΠ½ΠΈΠ΅ Π·Π½Π°ΠΊΠΈ Π±ΡΠ΄ΡΡ ΠΈΡΠΊΠ»ΡΡΠ΅Π½Ρ ΠΈΠ· ΡΠ΅Π·ΡΠ»ΡΡΠΈΡΡΡΡΠ΅Π³ΠΎ url ```js const positionUrl = `/positions/${posId}` ms.GET(`entity/customerorder/` + positionUrl) ``` #### query ##### querystring ΠΡΠ΅ ΠΏΠΎΠ»Ρ ΠΎΠ±ΡΠ΅ΠΊΡΠ° Π·Π°ΠΏΡΠΎΡΠ° ΠΏΡΠ΅ΠΎΠ±ΡΠ°Π·ΡΡΡΡΡ Π² ΡΠΎΠΎΡΠ²Π΅ΡΡΡΠ²ΡΡΡΡΡ ΡΡΡΠΎΠΊΡ Π·Π°ΠΏΡΠΎΡΠ° url. ΠΠ΅ΠΊΠΎΡΠΎΡΡΠ΅ ΠΏΠΎΠ»Ρ ΠΌΠΎΠ³ΡΡ ΠΏΠΎΠ΄Π²Π΅ΡΠ³Π°ΡΡΡΡ ΠΏΡΠ΅ΠΎΠ±ΡΠ°Π·ΠΎΠ²Π°Π½ΠΈΡ (Π½Π°ΠΏΡ. ΠΏΠΎΠ»Ρ [`filter`](#filter) ΠΈ [`order`](#order)). ΠΠΎΠ»Π΅ ΠΎΠ±ΡΠ΅ΠΊΡΠ° Π·Π°ΠΏΡΠΎΡΠ° Π΄ΠΎΠ»ΠΆΠ½ΠΎ ΠΈΠΌΠ΅ΡΡ ΡΠΈΠΏ: `string`, `number`, `boolean`, `null` ΠΈΠ»ΠΈ `undefined`, Π»ΡΠ±ΠΎΠ΅ Π΄ΡΡΠ³ΠΎΠ΅ Π·Π½Π°ΡΠ΅Π½ΠΈΠ΅ Π²ΡΠ·ΠΎΠ²Π΅Ρ ΠΎΡΠΈΠ±ΠΊΡ. ```js const query = { str: 'some string', num: 1, bool: true, nil: null, // Π±ΡΠ΄Π΅Ρ Π΄ΠΎΠ±Π°Π²Π»Π΅Π½ΠΎ Π² ΡΡΡΠΎΠΊΡ Π·Π°ΠΏΡΠΎΡΠ° Ρ ΠΏΡΡΡΡΠΌ Π·Π½Π°ΡΠ΅Π½ΠΈΠ΅ΠΌ nothing: undefined, // ΠΏΠΎΠ»Π΅ Π±ΡΠ΄Π΅Ρ ΠΏΡΠΎΠΏΡΡΠ΅Π½ΠΎ arr: ['str', 1, true, null, undefined] } // https://api.moysklad.ru/api/remap/1.2/entity/demand?str=some%20string&num=1&bool=true&nil=&arr=str&arr=1&arr=true&arr= ms.GET('entity/demand', query) ``` ##### filter ΠΡΠ»ΠΈ ΠΏΠΎΠ»Π΅ `filter` ΠΎΠ±ΡΠ΅ΠΊΡ, ΡΠΎ Π²Π»ΠΎΠΆΠ΅Π½Π½ΡΠ΅ ΠΏΠΎΠ»Ρ `filter` ΠΏΡΠ΅ΠΎΠ±ΡΠ°Π·ΡΡΡΡΡ Π² ΠΏΠ°ΡΠ°ΠΌΠ΅ΡΡΡ ΡΠΈΠ»ΡΡΡΠ° Π² ΡΡΡΠΎΠΊΠ΅ Π·Π°ΠΏΡΠΎΡΠ° Π² ΡΠΎΠΎΡΠ²Π΅ΡΡΡΠ²ΠΈΠΈ ΡΠΎ ΡΠ»Π΅Π΄ΡΡΡΠΈΠΌΠΈ ΠΏΡΠ°Π²ΠΈΠ»Π°ΠΌΠΈ: - `string`, `number`, `boolean` Π½Π΅ ΠΏΡΠΎΡ ΠΎΠ΄ΡΡ Π΄ΠΎΠΏΠΎΠ»Π½ΠΈΡΠ΅Π»ΡΠ½ΡΡ ΠΏΡΠ΅ΠΎΠ±ΡΠ°Π·ΠΎΠ²Π°Π½ΠΈΠΉ (`key=value`) - `null` ΠΏΡΠ΅ΠΎΠ±ΡΠ°Π·ΡΠ΅ΡΡΡ Π² ΠΏΡΡΡΡΡ ΡΡΡΠΎΠΊΡ (`key=`) - `Date` ΠΏΡΠ΅ΠΎΠ±ΡΠ°Π·ΡΠ΅ΡΡΡ Π² ΡΡΡΠΎΠΊΡ ΠΌΠ΅ΡΠΎΠ΄ΠΎΠΌ [`getTimeString`](#gettimestring) (`key=YYYY-MM-DD HH:mm:ss`) - `object` ΠΈΠ½ΡΠ΅ΡΠΏΡΠ΅ΡΠΈΡΡΠ΅ΡΡΡ ΠΊΠ°ΠΊ Π½Π°Π±ΠΎΡ ΡΠ΅Π»Π΅ΠΊΡΠΎΡΠΎΠ² ΠΈΠ»ΠΈ Π²Π»ΠΎΠΆΠ΅Π½Π½ΡΡ ΠΏΠΎΠ»Π΅ΠΉ (ΡΠΌ. ΠΏΡΠΈΠΌΠ΅Ρ Π½ΠΈΠΆΠ΅) **ΠΡΠΈΠΌΠ΅Ρ ΡΠΈΠ»ΡΡΡΠ°:** ```js const query = { filter: { name: '00001', code: [1, 2, '03'], foo: new Date(2000, 0, 1), state: { name: 'ΠΡΠΎΡΠΌΠ»Π΅Π½' }, moment: { $gt: new Date(2000, 0, 1), $lte: new Date(2001, 0, 2, 10, 0, 15, 123) }, bar: { baz: 1, $exists: true } } } ``` ΡΠΎΠΎΡΠ²Π΅ΡΡΡΠ²ΡΠ΅Ρ ΡΠ»Π΅Π΄ΡΡΡΠ΅ΠΌΡ Π·Π½Π°ΡΠ΅Π½ΠΈΡ ΠΏΠΎΠ»Ρ `filter` Π² Π·Π°ΠΏΡΠΎΡΠ΅ (Π΄Π°ΡΡ ΠΏΠ΅ΡΠ΅Π΄Π°Π½Ρ Π² ΡΠ°ΡΠΎΠ²ΠΎΠΌ ΠΏΠΎΡΡΠ΅ +5): ```txt bar!=;bar.baz=1;code=03;code=1;code=2;foo=1999-12-31 22:00:00;moment<=2001-01-02 08:00:15.123;moment>1999-12-31 22:00:00;name=00001;state.name=ΠΡΠΎΡΠΌΠ»Π΅Π½ ``` ΠΠ»Ρ ΠΏΠΎΡΡΡΠΎΠ΅Π½ΠΈΡ ΡΠΈΠ»ΡΡΡΠ° ΠΌΠΎΠΆΠ½ΠΎ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΡ ΡΠ΅Π»Π΅ΠΊΡΠΎΡΡ Π² ΡΡΠΈΠ»Π΅ Mongo (ΠΊΠ°ΠΊ Π² ΠΏΡΠΈΠΌΠ΅ΡΠ΅ Π²ΡΡΠ΅). ΠΠΎΠ΄ΡΠΎΠ±Π½ΠΎΠ΅ ΠΎΠΏΠΈΡΠ°Π½ΠΈΠ΅ Π²ΡΠ΅Ρ Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΡΡ ΡΠ΅Π»Π΅ΠΊΡΠΎΡΠΎΠ²: | Π‘Π΅Π»Π΅ΠΊΡΠΎΡ | Π€ΠΈΠ»ΡΡΡ ΠΠΎΠΉΠ‘ΠΊΠ»Π°Π΄ | ΠΠΏΠΈΡΠ°Π½ΠΈΠ΅ | | ------------------------------------ | ----------------------------- | -------------------------- | | `key: { $eq: value }` | `key=value` | ΡΠ°Π²Π½ΠΎ | | `key: { $ne: value }` | `key!=value` | Π½Π΅ ΡΠ°Π²Π½ΠΎ | | `key: { $gt: value }` | `key>value` | Π±ΠΎΠ»ΡΡΠ΅ | | `key: { $gte: value }` | `key>=value` | Π±ΠΎΠ»ΡΡΠ΅ ΠΈΠ»ΠΈ ΡΠ°Π²Π½ΠΎ | | `key: { $lt: value }` | `key<value` | ΠΌΠ΅Π½ΡΡΠ΅ | | `key: { $lte: value }` | `key<=value` | ΠΌΠ΅Π½ΡΡΠ΅ ΠΈΠ»ΠΈ ΡΠ°Π²Π½ΠΎ | | `key: { $st: value }` | `key~=value` | Π½Π°ΡΠΈΠ½Π°Π΅ΡΡΡ ΡΠΎ ΡΡΡΠΎΠΊΠΈ | | `key: { $et: value }` | `key=~value` | Π·Π°ΠΊΠ°Π½ΡΠΈΠ²Π°Π΅ΡΡΡ ΡΡΡΠΎΠΊΠΎΠΉ | | `key: { $contains: value }` | `key~value` | ΡΠΎΠ΄Π΅ΡΠΆΠΈΡ ΡΡΡΠΎΠΊΡ | | `key: { $in: [..] }` ΠΈΠ»ΠΈ `key: [..]` | `key=value1;key=value2;...` | Π²Ρ ΠΎΠ΄ΠΈΡ Π² | | `key: { $nin: [..] }` | `key!=value1;key!=value2;...` | Π½Π΅ Π²Ρ ΠΎΠ΄ΠΈΡ Π² | | `key: { $exists: true }` | `key!=` | Π½Π°Π»ΠΈΡΠΈΠ΅ Π·Π½Π°ΡΠ΅Π½ΠΈΡ (Π½Π΅ null) | | `key: { $exists: false }` | `key=` | ΠΏΡΡΡΠΎΠ΅ Π·Π½Π°ΡΠ΅Π½ΠΈΠ΅ (null) | | `key: { $all: [{..}, ..] }` | | ΠΎΠ±ΡΠ΅Π΄ΠΈΠ½Π΅Π½ΠΈΠ΅ ΡΡΠ»ΠΎΠ²ΠΈΠΉ | | `key: { $not: {..} }` | | ΠΎΡΡΠΈΡΠ°Π½ΠΈΠ΅ ΡΡΠ»ΠΎΠ²ΠΈΡ | ΠΠ° ΠΎΠ΄ΠΈΠ½ ΠΊΠ»ΡΡ ΠΌΠΎΠΆΠ½ΠΎ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΡ Π½Π΅ΡΠΊΠΎΠ»ΡΠΊΠΎ ΡΠ΅Π»Π΅ΠΊΡΠΎΡΠΎΠ². ΠΠΎΠ΄ΡΠΎΠ±Π½Π΅Π΅ Ρ ΠΏΡΠ°Π²ΠΈΠ»Π°ΠΌΠΈ ΡΠΈΠ»ΡΡΡΠ°ΡΠΈΠΈ ΠΌΠΎΠΆΠ½ΠΎ ΠΎΠ·Π½Π°ΠΊΠΎΠΌΠΈΡΡΡ Π² Π΄ΠΎΠΊΡΠΌΠ΅Π½ΡΠ°ΡΠΈΠΈ ΠΠΎΠΉΠ‘ΠΊΠ»Π°Π΄: - [Π€ΠΈΠ»ΡΡΡΠ°ΡΠΈΡ Π²ΡΠ±ΠΎΡΠΊΠΈ Ρ ΠΏΠΎΠΌΠΎΡΡΡ ΠΏΠ°ΡΠ°ΠΌΠ΅ΡΡΠ° filter](https://dev.moysklad.ru/doc/api/remap/1.2/#mojsklad-json-api-obschie-swedeniq-fil-traciq-wyborki-s-pomosch-u-parametra-filter) - [ΠΠΏΠ΅ΡΠ°ΡΠΎΡ ΡΠΈΠ»ΡΡΡΠ°ΡΠΈΠΈ "ΠΏΠΎΠ΄ΠΎΠ±ΠΈΠ΅"](https://dev.moysklad.ru/doc/api/remap/1.2/#mojsklad-json-api-obschie-swedeniq-operator-fil-tracii-quot-podobie-quot) - [Π€ΠΈΠ»ΡΡΡΠ°ΡΠΈΡ](https://dev.moysklad.ru/doc/api/remap/1.2/workbook/#workbook-fil-traciq-listanie-poisk-i-sortirowka-fil-traciq) ##### order ΠΡΠ»ΠΈ ΠΏΠΎΠ»Π΅ `order` ΠΌΠ°ΡΡΠΈΠ², ΡΠΎ ΠΏΡΠΎΠΈΠ·ΠΎΠΉΠ΄Π΅Ρ ΠΏΡΠ΅ΠΎΠ±ΡΠ°Π·ΠΎΠ²Π°Π½ΠΈΠ΅ Π·Π°ΠΏΠΈΡΠΈ ΠΈΠ· ΡΠΎΡΠΌΡ ΠΌΠ°ΡΡΠΈΠ²Π° Π² ΡΡΡΠΎΠΊΡ. **ΠΡΠΈΠΌΠ΅ΡΡ:** - `['name']` β `'name'` - `[['code','desc']]` β `'code,desc'` - `['name', ['code','desc']]` β `'name;code,desc'` - `['name,desc', ['code','asc'], ['moment']]` β `'name,desc;code,asc;moment'` π [examples/query.js](https://github.com/wmakeev/moysklad/blob/master/examples/query.js) ##### expand ΠΈ limit ΠΠ±ΡΠ°ΡΠΈΡΠ΅ Π²Π½ΠΈΠΌΠ°Π½ΠΈΠ΅ Π½Π° ΡΠΎ, ΡΡΠΎ Π΅ΡΠ»ΠΈ ΡΠΊΠ°Π·Π°Π½ΠΎ Π·Π½Π°ΡΠ΅Π½ΠΈΠ΅ expand, ΡΠΎ Π½Π΅ΠΎΠ±Ρ ΠΎΠ΄ΠΈΠΌΠΎ ΡΠ²Π½ΠΎ ΡΠΊΠ°Π·Π°ΡΡ Π·Π½Π°ΡΠ΅Π½ΠΈΠ΅ Π΄Π»Ρ limit ΠΌΠ΅Π½ΡΡΠ΅ ΠΈΠ»ΠΈ ΡΠ°Π²Π½ΠΎΠ΅ 100, ΠΈΠ½Π°ΡΠ΅ expand [Π±ΡΠ΄Π΅Ρ ΠΏΡΠΎΠΈΠ³Π½ΠΎΡΠΈΡΠΎΠ²Π°Π½](https://dev.moysklad.ru/doc/api/remap/1.2/workbook/#workbook-chto-takoe-expand). #### options (ΠΏΠ°ΡΠ°ΠΌΠ΅ΡΡΡ Π·Π°ΠΏΡΠΎΡΠ°) ΠΡΠ΅ ΠΏΠΎΠ»Ρ ΡΠΊΠ°Π·Π°Π½Π½ΡΠ΅ Π² ΠΎΠ±ΡΠ΅ΠΊΡΠ΅ `options`, Π·Π° ΠΈΡΠΊΠ»ΡΡΠ΅Π½ΠΈΠ΅ΠΌ ΠΎΠΏΠΈΡΠ°Π½Π½ΡΡ Π² ΡΡΠΎΠΌ ΡΠ°Π·Π΄Π΅Π»Π΅, ΠΏΠ΅ΡΠ΅Π΄Π°ΡΡΡΡ Π½Π°ΠΏΡΡΠΌΡΡ Π² ΠΎΠΏΡΠΈΠΈ fetch ([fetch options](https://developer.mozilla.org/en-US/docs/Web/API/Window/fetch#options)). ΠΠΎΠ»Ρ ΠΎΠΏΠΈΡΠ°Π½Π½ΡΠ΅ Π½ΠΈΠΆΠ΅ ΠΎΠ±ΡΠ°Π±Π°ΡΡΠ²Π°ΡΡΡΡ ΡΠΎΠ»ΡΠΊΠΎ Π±ΠΈΠ±Π»ΠΈΠΎΡΠ΅ΠΊΠΎΠΉ moysklad ΠΈ Π½Π΅ ΠΏΠ΅ΡΠ΅Π΄Π°ΡΡΡΡ Π² fetch: | ΠΠΎΠ»Π΅ | Π’ΠΈΠΏ | ΠΠΏΠΈΡΠ°Π½ΠΈΠ΅ | | --------------------------- | --------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `rawResponse` | `boolean` | ΠΡΠ»ΠΈ `true`, ΡΠΎ ΠΌΠ΅ΡΠΎΠ΄ Π²Π΅ΡΠ½Π΅Ρ ΠΈΡΡ ΠΎΠ΄Π½ΡΠΉ ΠΎΠ±ΡΠ΅ΠΊΡ [Response](https://developer.mozilla.org/en-US/docs/Web/API/Response). ΠΠΎΠ΄ ΠΈ ΡΠΎΠ΄Π΅ΡΠΆΠΈΠΌΠΎΠ΅ ΠΎΡΠ²Π΅ΡΠ° Π½Π΅ ΠΏΡΠΎΠ²Π΅ΡΡΠ΅ΡΡΡ Π½Π° ΠΎΡΠΈΠ±ΠΊΠΈ. Π’Π΅Π»ΠΎ ΠΎΡΠ²Π΅ΡΠ° Π½ΡΠΆΠ½ΠΎ [ΠΏΡΠΎΡΠΈΡΠ°ΡΡ ΡΠ°ΠΌΠΎΡΡΠΎΡΡΠ΅Π»ΡΠ½ΠΎ](https://github.com/nodejs/undici?tab=readme-ov-file#garbage-collection). | | `includeResponse` | `boolean` | ΠΡΠ»ΠΈ `true`, ΡΠΎ ΠΌΠ΅ΡΠΎΠ΄ Π²Π΅ΡΠ½Π΅Ρ ΠΌΠ°ΡΡΠΈΠ² ΠΈΠ· Π΄Π²ΡΡ ΡΠ»Π΅ΠΌΠ΅Π½ΡΠΎΠ² - ΡΠ΅Π·ΡΠ»ΡΡΠ°Ρ ΠΈ ΠΎΠ±ΡΠ΅ΠΊΡ [Response](https://developer.mozilla.org/en-US/docs/Web/API/Response). ΠΡΠΈΠ±ΠΊΠΈ Π±ΡΠ΄ΡΡ ΠΎΠ±ΡΠ°Π±ΠΎΡΠ°Π½Ρ ΠΊΠ°ΠΊ ΠΏΡΠΈ ΠΎΠ±ΡΡΠ½ΠΎΠΌ Π·Π°ΠΏΡΠΎΡΠ΅. | | `rawRedirect` | `boolean` | ΠΡΠ»ΠΈ ΠΎΡΠ²Π΅Ρ ΡΠ΅ΡΠ²Π΅ΡΠ° Ρ ΠΊΠΎΠ΄ΠΎΠΌ Π² Π΄ΠΈΠ°ΠΏΠ°Π·ΠΎΠ½Π΅ 300-399 (ΡΠ΅Π΄ΠΈΡΠ΅ΠΊΡ), ΡΠΎ Π±ΡΠ΄Π΅Ρ Π²ΡΠ±ΡΠΎΡΠ΅Π½Π° ΠΎΡΠΈΠ±ΠΊΠ° [MoyskladUnexpectedRedirectError](#moyskladunexpectedredirecterror), ΠΏΠΎΡΡΠΎΠΌΡ, ΡΠ²Π½ΠΎΠΉ ΠΎΠ±ΡΠ°Π±ΠΎΡΠΊΠΈ ΡΠ΅Π΄ΠΈΡΠ΅ΠΊΡΠ° Π½Π΅ΠΎΠ±Ρ ΠΎΠ΄ΠΈΠΌΠΎ ΡΠΊΠ°Π·Π°ΡΡ ΠΎΠΏΡΠΈΡ `rawRedirect` ΡΠΎ Π·Π½Π°ΡΠ΅Π½ΠΈΠ΅ΠΌ `true`. Π ΡΡΠΎΠΌ ΡΠ»ΡΡΠ°Π΅ ΠΌΠ΅ΡΠΎΠ΄ Π²Π΅ΡΠ½Π΅Ρ ΠΎΠ±ΡΠ΅ΠΊΡ [Response](https://developer.mozilla.org/en-US/docs/Web/API/Response), ΠΈΠ· ΠΊΠΎΡΠΎΡΠΎΠ³ΠΎ ΠΌΠΎΠΆΠ½ΠΎ ΠΏΠΎΠ»ΡΡΠΈΡΡ Location Π·Π°Π³ΠΎΠ»ΠΎΠ²ΠΎΠΊ. Π’Π°ΠΊΠΎΠ΅ ΠΏΠΎΠ²Π΅Π΄Π΅Π½ΠΈΠ΅ ΡΡΠ°Π±ΠΎΡΠ°Π΅Ρ, ΡΠΎΠ»ΡΠΊΠΎ Π΅ΡΠ»ΠΈ ΡΠ²Π½ΠΎ Π½Π΅ ΡΠΊΠ°Π·Π°Π½Π° ΠΎΠΏΡΠΈΡ [redirect](https://developer.mozilla.org/en-US/docs/Web/API/RequestInit#redirect) ΡΠΎ Π·Π½Π°ΡΠ΅Π½ΠΈΠ΅ΠΌ `follow`. | | `muteApiErrors` | `boolean` | ΠΡΠ»ΠΈ `true` ΠΈ Π·Π°ΠΏΡΠΎΡ Π·Π°Π²Π΅ΡΡΠΈΠ»ΡΡ ΠΎΡΠΈΠ±ΠΊΠΎΠΉ API, ΡΠΎ ΠΌΠ΅ΡΠΎΠ΄ Π²Π΅ΡΠ½Π΅Ρ ΠΎΠ±ΡΠ΅ΠΊΡ Ρ ΠΎΠΏΠΈΡΠ°Π½ΠΈΠ΅ΠΌ ΠΎΡΠΈΠ±ΠΊΠΈ ΠΈΠ· ΡΠ΅Π»Π° ΠΎΡΠ²Π΅ΡΠ° ΠΊΠ°ΠΊ ΡΠ΅Π·ΡΠ»ΡΡΠ°Ρ. Π’Π°ΠΊΠΎΠ΅ ΠΏΠΎΠ²Π΅Π΄Π΅Π½ΠΈΠ΅ ΡΠΌΠ΅ΡΡΠ½ΠΎ Π΅ΡΠ»ΠΈ Π²Ρ Ρ ΠΎΡΠΈΡΠ΅ Π²ΡΡΡΠ½ΡΡ ΠΎΠ±ΡΠ°Π±ΠΎΡΠ°ΡΡ ΠΎΡΠΈΠ±ΠΊΡ. ΠΡΠΎΡΠΈΠ΅ ΠΎΡΠΈΠ±ΠΊΠΈ, ΠΊΠΎΡΠΎΡΡΠ΅ Π½Π΅ ΡΠΎΠ΄Π΅ΡΠΆΠ°Ρ JSON ΠΎΡΠ²Π΅ΡΠ° (Π½Π°ΠΏΡ. ΠΎΡΠΈΠ±ΠΊΠΈ ΡΠΎΠ΅Π΄ΠΈΠ½Π΅Π½ΠΈΡ), ΠΏΡΠΎΠ΄ΠΎΠ»ΠΆΠ°Ρ Π²ΡΠ±ΡΠ°ΡΡΠ²Π°ΡΡΡΡ Π² ΡΡΠ°ΡΠ½ΠΎΠΌ ΡΠ΅ΠΆΠΈΠΌΠ΅. ΠΠ»Ρ ΠΈΠ³Π½ΠΎΡΠΈΡΠΎΠ²Π°Π½ΠΈΡ ΠΎΡΠΈΠ±ΠΎΠΊ ΡΠΎΠ»ΡΠΊΠΎ Π²Π½ΡΡΡΠΈ ΠΊΠΎΠ»Π»Π΅ΠΊΡΠΈΠΉ, ΠΈΡΠΏΠΎΠ»ΡΠ·ΡΠΉΡΠ΅ ΠΎΠΏΡΠΈΡ `muteCollectionErrors`. | | `muteCollectionErrors` | `boolean` | ΠΡΠ»ΠΈ `true`, ΡΠΎ Π²ΡΠ΅ ΠΎΡΠΈΠ±ΠΊΠΈ Π²Π½ΡΡΡΠΈ ΠΊΠΎΠ»Π»Π΅ΠΊΡΠΈΠΉ ΠΏΡΠΈ ΠΌΠ°ΡΡΠΎΠ²ΠΎΠΌ ΠΎΠ±Π½ΠΎΠ²Π»Π΅Π½ΠΈΠΈ ΡΡΡΠ½ΠΎΡΡΠ΅ΠΉ Π±ΡΠ΄ΡΡ ΠΏΡΠΎΠΈΠ³Π½ΠΎΡΠΈΡΠΎΠ²Π°Π½Ρ. Π ΡΡΠΎΠΌ ΡΠ»ΡΡΠ°Π΅ ΠΎΡΠΈΠ±ΠΊΠΈ Π½ΡΠΆΠ½ΠΎ Π±ΡΠ΄Π΅Ρ ΠΎΡΡΠΈΠ»ΡΡΡΠΎΠ²Π°ΡΡ ΠΈ ΠΎΠ±ΡΠ°Π±ΠΎΡΠ°ΡΡ Π²ΡΡΡΠ½ΡΡ. | | `precision` | `boolean` | ΠΡΠ»ΠΈ `true`, ΡΠΎ Π² Π·Π°ΠΏΡΠΎΡ Π±ΡΠ΄Π΅Ρ Π²ΠΊΠ»ΡΡΠ΅Π½ Π·Π°Π³ΠΎΠ»ΠΎΠ²ΠΎΠΊ `X-Lognex-Precision` ΡΠΎ Π·Π½Π°ΡΠ΅Π½ΠΈΠ΅ΠΌ `true` (ΠΎΡΠΊΠ»ΡΡΠ΅Π½ΠΈΠ΅ ΠΎΠΊΡΡΠ³Π»Π΅Π½ΠΈΡ ΡΠ΅Π½ ΠΈ ΡΠ΅Π±Π΅ΡΡΠΎΠΈΠΌΠΎΡΡΠΈ Π΄ΠΎ ΠΊΠΎΠΏΠ΅Π΅ΠΊ). | | ~~`webHookDisable`~~ | `boolean` | (deprecated) ΠΡΠ»ΠΈ `true`, ΡΠΎ Π² Π·Π°ΠΏΡΠΎΡ Π±ΡΠ΄Π΅Ρ Π²ΠΊΠ»ΡΡΠ΅Π½ Π·Π°Π³ΠΎΠ»ΠΎΠ²ΠΎΠΊ `X-Lognex-WebHook-Disable` ΡΠΎ Π·Π½Π°ΡΠ΅Π½ΠΈΠ΅ΠΌ `true` (ΠΎΡΠΊΠ»ΡΡΠΈΡΡ ΡΠ²Π΅Π΄ΠΎΠΌΠ»Π΅Π½ΠΈΡ Π²Π΅Π±Ρ ΡΠΊΠΎΠ² Π² ΠΊΠΎΠ½ΡΠ΅ΠΊΡΡΠ΅ Π΄Π°Π½Π½ΠΎΠ³ΠΎ Π·Π°ΠΏΡΠΎΡΠ°). ΠΠ΅ ΡΠ΅ΠΊΠΎΠΌΠ΅Π½Π΄ΡΠ΅ΡΡΡ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΡ Π΄Π°Π½Π½ΡΡ ΠΎΠΏΡΠΈΡ, ΠΏΡΠΈΠΌΠ΅Π½ΡΠΉΡΠ΅ `webHookDisableByPrefix`. | | `webHookDisableByPrefix` | `string` | ΠΡΠ΅ΡΠΈΠΊΡ url Π΄Π»Ρ Π²ΡΠ±ΠΎΡΠΎΡΠ½ΠΎΠ³ΠΎ ΠΎΡΠΊΠ»ΡΡΠ΅Π½ΠΈΡ Π²Π΅Π±Ρ ΡΠΊΠΎΠ², Π±ΡΠ΄Π΅Ρ Π΄ΠΎΠ±Π°Π²Π»Π΅Π½ Π² ΠΊΠ°ΡΠ΅ΡΡΠ²Π΅ Π·Π½Π°ΡΠ΅Π½ΠΈΡ Π·Π°Π³ΠΎΠ»ΠΎΠ²ΠΊΠ° `X-Lognex-WebHook-DisableByPrefix`. | | `downloadExpirationSeconds` | `number` | Π£ΡΡΠ°Π½Π°Π²Π»ΠΈΠ²Π°Π΅Ρ Π·Π½Π°ΡΠ΅Π½ΠΈΠ΅ Π΄Π»Ρ Π·Π°Π³ΠΎΠ»ΠΎΠ²ΠΊΠ° `X-Lognex-Download-Expiration-Seconds` (ΠΏΠΎΠ΄ΡΠΎΠ±Π½Π΅Π΅ ΡΠΌ. [Π‘ΡΡΠ»ΠΊΠΈ Π½Π° ΡΠ°ΠΉΠ»Ρ](https://dev.moysklad.ru/doc/api/remap/1.2/#mojsklad-json-api-obschie-swedeniq-ssylki-na-fajly)) | <details> <summary>ΠΡΠΈΠΌΠ΅ΡΡ</summary> - Π€ΠΎΡΠΌΠΈΡΠΎΠ²Π°Π½ΠΈΠ΅ Π·Π°ΠΏΠΎΠ»Π½Π΅Π½Π½ΠΎΠ³ΠΎ ΡΠ°Π±Π»ΠΎΠ½Π° ΠΏΠ΅ΡΠ°ΡΠ½ΠΎΠΉ ΡΠΎΡΠΌΡ ΠΈ ΠΏΠΎΠ»ΡΡΠ΅Π½ΠΈΠ΅ ΡΡΡΠ»ΠΊΠΈ Π΄Π»Ρ Π·Π°Π³ΡΡΠ·ΠΊΠΈ ([examples/download-print-form.js](https://github.com/wmakeev/moysklad/blob/master/examples/download-print-form.js)): ```js import path from 'node:path' import { writeFile } from 'node:fs/promises' import { fetch } from 'undici' import Moysklad from 'moysklad' const TEMPLATE_ID = '8a686b8a-9e4a-11e5-7a69-97110004af3e' const DEMAND_ID = '13abf361-e9c6-45ea-a940-df70289a7f95' async function downloadPrintForm() { const ms = Moysklad({ fetch }) const body = { template: { meta: { href: ms.buildUrl( `entity/demand/metadata/customtemplate/${TEMPLATE_ID}` ), type: 'customtemplate', mediaType: 'application/json' } }, extension: 'pdf' } /** @type {import('undici').Response} */ const response = await ms.POST( `entity/demand/${DEMAND_ID}/export`, body, null, // Π²Π΅ΡΠ½ΡΡΡ ΡΠ΅Π·ΡΠ»ΡΡΠ°Ρ Π·Π°ΠΏΡΠΎΡΠ° Ρ ΡΠ΅Π΄ΠΈΡΠ΅ΠΊΡΠΎΠΌ Π±Π΅Π· ΠΏΡΠ΅Π΄Π²Π°ΡΠΈΡΠ΅Π»ΡΠ½ΠΎΠ³ΠΎ ΡΠ°Π·Π±ΠΎΡΠ° { rawRedirect: true } ) const location = response.headers.get('location') console.log(location) // 'https://print-prod.moysklad.ru/temp/.../00123.pdf' const formResponse = await fetch(location) const blob = await formResponse.blob() const buffer = Buffer.from(await blob.arrayBuffer()) await writeFile(path.join(process.cwd(), '__temp/form.pdf'), buffer) } downloadPrintForm() ``` - Π£ΠΊΠ°Π·Π°Π½ΠΈΠ΅ HTTP Π·Π°Π³ΠΎΠ»ΠΎΠ²ΠΊΠ° ```js const ms = Moysklad() const folder = { meta: { type: 'productfolder', href: ms.buildUrl(`entity/productfolder/${FOLDER_ID}`) }, description: 'ΠΠΎΠ²ΠΎΠ΅ ΠΎΠΏΠΈΡΠ°Π½ΠΈΠ΅ Π³ΡΡΠΏΠΏΡ ΡΠΎΠ²Π°ΡΠΎΠ²' } // Π£ΠΊΠ°Π·ΡΠ²Π°Π΅ΠΌ ΠΊΠ°ΡΡΠΎΠΌΠ½ΡΠΉ Π·Π°Π³ΠΎΠ»ΠΎΠ²ΠΎΠΊ X-Lognex-WebHook-Disable Π΄Π»Ρ PUT Π·Π°ΠΏΡΠΎΡΠ° const updatedFolder = await ms.PUT( `entity/productfolder/${FOLDER_ID}`, folder, null, { // Π²ΠΌΠ΅ΡΡΠΎ ΡΡΠΎΠ³ΠΎ ΠΌΠΎΠΆΠ½ΠΎ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΡ webHookDisable: true headers: { 'X-Lognex-WebHook-Disable': true } } ) assert.equal(updatedFolder.description, folder.description) ``` - ΠΠ²ΡΠΎΠΌΠ°ΡΠΈΡΠ΅ΡΠΊΠΈΠΉ ΡΠ΅Π΄ΠΈΡΠ΅ΠΊΡ ΠΠ΄Π΅Π½ΡΠΈΡΠΈΠΊΠ°ΡΠΎΡΡ ΡΠΎΠ²Π°ΡΠΎΠ² Π² ΠΏΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠΈ ΠΠΎΠΉΠ‘ΠΊΠ»Π°Π΄ ΠΎΡΠ»ΠΈΡΠ°ΡΡΡΡ ΠΎΡ ΠΈΠ΄Π΅Π½ΡΠΈΡΠΈΠΊΠ°ΡΠΎΡΠΎΠ² Π² API. ΠΠΎΡΡΠΎΠΌΡ, ΠΏΡΠΈ Π·Π°ΠΏΡΠΎΡΠ΅ ΡΠΎΠ²Π°ΡΠ° ΠΏΠΎ id ΠΈΠ· ΠΏΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΡ, Π±ΡΠ΄Π΅Ρ Π²ΡΠΏΠΎΠ»Π½Π΅Π½ ΡΠ΅Π΄ΠΈΡΠ΅ΠΊΡ Π½Π° Π΄ΡΡΠ³ΠΎΠΉ href. ```js const ms = Moysklad({ fetch }) // https://api.moysklad.ru/app/#good/edit?id=cb277549-34f4-4029-b9de-7b37e8e25a54 const PRODUCT_UI_ID = 'cb277549-34f4-4029-b9de-7b37e8e25a54' // Error: 308 Permanent Redirect await ms.fetchUrl(ms.buildUrl(`entity/product/${PRODUCT_UI_ID}`)) // Π£ΠΊΠ°Π·Π°Π½Π° ΠΎΠΏΡΠΈΡ redirect const product = await ms.fetchUrl( ms.buildUrl(`entity/product/${PRODUCT_UI_ID}`), { redirect: 'follow' } ) assert.ok(product) // OK ``` </details> ## Π£ΠΏΡΠ°Π²Π»Π΅Π½ΠΈΠ΅ ΠΏΠΎΡΠΎΠΊΠΎΠΌ Π·Π°ΠΏΡΠΎΡΠΎΠ² ΠΠ»Ρ ΡΠΏΡΠ°Π²Π»Π΅Π½ΠΈΡ ΠΏΠΎΡΠΎΠΊΠΎΠΌ Π·Π°ΠΏΡΠΎΡΠΎΠ² Ρ ΡΠ΅Π»ΡΡ ΡΠ»ΠΎΠΆΠΈΡΡΡΡ Π² [ΠΎΠ³ΡΠ°Π½ΠΈΡΠ΅Π½ΠΈΡ](https://dev.moysklad.ru/doc/api/remap/1.2/#mojsklad-json-api-ogranicheniq) API ΠΠΎΠΉΠ‘ΠΊΠ»Π°Π΄ ΠΌΠΎΠΆΠ½ΠΎ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΡ ΠΏΠ»Π°Π½ΠΈΡΠΎΠ²ΡΠΈΠΊ Π·Π°ΠΏΡΠΎΡΠΎΠ² [moysklad-fetch-planner](https://www.npmjs.com/package/moysklad-fetch-planner). ΠΠ»Π°Π½ΠΈΡΠΎΠ²ΡΠΈΠΊ ΡΡΠΈΡΡΠ²Π°Π΅Ρ ΠΈΠ½ΡΠΎΡΠΌΠ°ΡΠΈΡ ΠΎ ΡΠ΅ΠΊΡΡΠΈΡ Π»ΠΈΠΌΠΈΡΠ°Ρ ΠΈΠ· Π·Π°Π³ΠΎΠ»ΠΎΠ²ΠΊΠΎΠ² ΠΎΡΠ²Π΅ΡΠΎΠ² API ΠΠΎΠΉΠ‘ΠΊΠ»Π°Π΄ ΠΈ ΠΎΠ³ΡΠ°Π½ΠΈΡΠΈΠ²Π°Π΅Ρ ΡΠΊΠΎΡΠΎΡΡΡ Π²ΡΠΏΠΎΠ»Π½Π΅Π½ΠΈΡ Π·Π°ΠΏΡΠΎΡΠΎΠ², ΠΏΡΠ΅Π΄ΠΎΡΠ²ΡΠ°ΡΠ°Ρ ΠΏΠΎΡΠ²Π»Π΅Π½ΠΈΠ΅ ΠΎΡΠΈΠ±ΠΎΠΊ `429 Too Many Requests`. Π ΡΠ»ΡΡΠ°Π΅ Π΅ΡΠ»ΠΈ ΠΎΡΠΈΠ±ΠΊΠΈ 429 ΠΈΠ·Π±Π΅ΠΆΠ°ΡΡ Π½Π΅ ΡΠ΄Π°Π»ΠΎΡΡ, Π·Π°ΠΏΡΠΎΡ Π±ΡΠ΄Π΅Ρ ΠΏΠΎΠ²ΡΠΎΡΠ΅Π½ ΠΏΡΠΈ Π²ΠΎΡΡΡΠ°Π½ΠΎΠ²Π»Π΅Π½ΠΈΠΈ Π΄ΠΎΡΡΡΠΏΠ½ΠΎΠ³ΠΎ Π»ΠΈΠΌΠΈΡΠ°. **ΠΡΠΈΠΌΠ΅Ρ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π½ΠΈΡ:** ```ts import Moysklad from 'moysklad' import { fetch } from 'undici' import { wrapFetchApi } from 'moysklad-fetch-planner' const ms = Moysklad({ fetch: wrapFetchApi(fetch) }) ``` ## ΠΠ±ΡΠ°Π±ΠΎΡΠΊΠ° ΠΎΡΠΈΠ±ΠΎΠΊ ### ΠΠΎΠ²ΡΠΎΡ Π·Π°ΠΏΡΠΎΡΠ° ΠΏΡΠΈ ΠΎΡΠΈΠ±ΠΊΠ΅ ΠΡΠΈ ΠΈΠ½ΠΈΡΠΈΠ°Π»ΠΈΠ·Π°ΡΠΈΠΈ ΠΊΠ»ΠΈΠ΅Π½ΡΠ° Π΅ΡΡΡ Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡΡ Π·Π°Π΄Π°ΡΡ ΡΠ²ΠΎΡ Π»ΠΎΠ³ΠΈΠΊΡ ΠΎΠ±ΡΠ°Π±ΠΎΡΠΊΠΈ ΠΎΡΠΈΠ±ΠΎΡΠ½ΡΡ Π·Π°ΠΏΡΠΎΡΠΎΠ². Π ΠΏΡΠΈΠΌΠ΅ΡΠ΅ Π½ΠΈΠΆΠ΅ ΠΊΠΎΠ΄ Π΄Π»Ρ Π°Π²ΡΠΎΠΌΠ°ΡΠΈΡΠ΅ΡΠΊΠΎΠ³ΠΎ ΠΏΠΎΠ²ΡΠΎΡΠ° Π·Π°ΠΏΡΠΎΡΠ° ΠΏΡΠΈ ΠΏΠΎΠ»ΡΡΠ΅Π½ΠΈΠΈ ΠΎΡΠΈΠ±ΠΊΠΈ. <details> <summary>ΠΡΠΈΠΌΠ΅Ρ</summary> ```js import Moysklad from 'moysklad' import { wrapFetch } from 'moysklad-fetch-planner' import pRetry from 'p-retry' import { fetch } from 'undici' /** * ΠΡΠΈΠΌΠ΅Ρ Π½Π°ΡΡΡΠΎΠΉΠΊΠΈ ΠΊΠ»ΠΈΠ΅Π½ΡΠ° Π΄Π»Ρ API ΠΠΎΠΉΠ‘ΠΊΠ»Π°Π΄. * * 1. ΠΠΎΠ΄ΠΊΠ»ΡΡΠ°Π΅ΡΡΡ ΠΏΠ»Π°Π½ΠΈΡΠΎΠ²ΡΠΈΠΊ Π·Π°ΠΏΡΠΎΡΠΎΠ² `moysklad-fetch-planner` Π΄Π»Ρ Π°Π²ΡΠΎΠΌΠ°ΡΠΈΡΠ΅ΡΠΊΠΎΠ³ΠΎ * ΠΊΠΎΠ½ΡΡΠΎΠ»Ρ Π·Π° Π»ΠΈΠΌΠΈΡΠ°ΠΌΠΈ Π΄Π»Ρ ΠΏΡΠ΅Π΄ΠΎΡΠ²ΡΠ°ΡΠ΅Π½ΠΈΡ Π²ΠΎΠ·Π½ΠΈΠΊΠ½ΠΎΠ²Π΅Π½ΠΈΡ ΠΎΡΠΈΠ±ΠΊΠΈ `429 Too Many Request`. * * 2. ΠΠΎΠ΄ΠΊΠ»ΡΡΠ°Π΅ΡΡΡ ΠΌΠ΅Ρ Π°Π½ΠΈΠ·ΠΌ ΠΏΠΎΠ²ΡΠΎΡΠ° ΠΎΡΠΈΠ±ΠΎΡΠ½ΡΡ Π·Π°ΠΏΡΠΎΡΠΎΠ² Π΄Π»Ρ ΡΠ»ΡΡΠ°Π΅Π² ΠΊΠΎΠ³Π΄Π° ΠΎΡΠΈΠ±ΠΊΠ° * ΠΌΠΎΠ³Π»Π° Π±ΡΡΡ Π²ΡΠ·Π²Π°Π½Π° Π²ΡΠ΅ΠΌΠ΅Π½Π½ΡΠΌΠΈ Π½Π΅ΠΏΠΎΠ»Π°Π΄ΠΊΠ°ΠΌΠΈ Π² ΠΏΡΠΎΡΠ΅ΡΡΠ΅ Π²ΡΠΏΠΎΠ»Π½Π΅Π½ΠΈΡ Π·Π°ΠΏΡΠΎΡΠ° (Π΄Π»Ρ * ΠΏΡΠΈΠΌΠ΅ΡΠ° ΠΈΡΠΏΠΎΠ»ΡΠ·ΡΠ΅ΡΡΡ npm Π±ΠΈΠ±Π»ΠΈΠΎΡΠ΅ΠΊΠ° `p-retry`). */ const ms = Moysklad({ fetch: wrapFetch(fetch), retry: (thunk, signal) => { return pRetry(thunk, { retries: 2, shouldRetry: Moysklad.shouldRetryError, onFailedAttempt: error => { console.log( `Attempt ${error.attemptNumber} failed. There are ${error.retriesLeft} retries left.` ) }, signal }) } }) try { // ΠΠ°ΠΏΡΠΎΡ Ρ ΠΎΡΠΈΠ±ΠΊΠΎΠΉ Π² url-Π·Π°ΠΏΡΠΎΡΠ° ΠΏΠΎΠ²ΡΠΎΡΡΡΡΡΡ Π½Π΅ Π±ΡΠ΄Π΅Ρ, Π΅ΡΠ»ΠΈ API ΠΠΎΠΉΠ‘ΠΊΠ»Π°Π΄ // Π²Π΅ΡΠ½ΡΠ» ΠΎΠ± ΡΡΠΎΠΌ ΡΠΎΠΎΠ±ΡΠ΅Π½ΠΈΠ΅. await ms.GET('foo') // β³ Attempt 1 failed. There are 2 retries left. } catch (err) { console.log(err) // β³ MoyskladApiError: ΠΠ΅ΠΎΠΏΠΎΠ·Π½Π°Π½Π½ΡΠΉ ΠΏΡΡΡ: https://api.moysklad.ru/api/remap/1.2/foo (https://dev.moysklad.ru/doc/api/remap/1.2/#error_1002) } try { // ΠΠ°ΠΏΡΠΎΡ Ρ ΠΎΡΠΈΠ±ΠΊΠΎΠΉ ΠΊΠΎΡΠΎΡΠ°Ρ ΠΈΠΌΠ΅Π΅Ρ HTTP ΠΊΠΎΠ΄ `503` (Π² ΡΠΎΠΌ ΡΠΈΡΠ»Π΅, ΠΈ Π΄ΡΡΠ³ΠΈΠ΅ ΠΊΠΎΠ΄Ρ // `5xx`) Π±ΡΠ΄Π΅Ρ ΠΏΠΎΠ²ΡΠΎΡΡΡΡΡΡ. Π’.ΠΊ. ΠΏΠΎΠ΄ΠΎΠ±Π½Π°Ρ ΠΎΡΠΈΠ±ΠΊΠ° ΠΈΠ½ΠΎΠ³Π΄Π° ΠΌΠΎΠΆΠ΅Ρ Π±ΡΡΡ Π²ΡΠ·Π²Π°Π½Π° // Π²ΡΠ΅ΠΌΠ΅Π½Π½ΡΠΌΠΈ ΡΠ±ΠΎΡΠΌΠΈ Π½Π° ΡΡΠΎΡΠΎΠ½Π΅ ΡΠ΅ΡΠ²Π΅ΡΠ° API ΠΠΎΠΉΠ‘ΠΊΠ»Π°Π΄. await ms.fetchUrl( 'https://api.moysklad.ru/api/remap/1.0/entity/customerorder' ) // β³ Attempt 1 failed. There are 2 retries left. // β³ Attempt 2 failed. There are 1 retries left. // β³ Attempt 3 failed. There are 0 retries left. } catch (err) { console.log(err) // β³ MoyskladRequestError: 503 Service Unavailable } try { // ΠΠ°ΠΏΡΠΎΡ Ρ ΠΎΡΠΈΠ±ΠΊΠΎΠΉ ΠΊΠΎΡΠΎΡΠ°Ρ ΠΈΠΌΠ΅Π΅Ρ ΠΊΠΎΠ΄ `ENOTFOUND` (ΠΈ ΡΡΠ΄ Π΄ΡΡΠ³ΠΈΡ ) Π±ΡΠ΄Π΅Ρ // ΠΏΠΎΠ²ΡΠΎΡΡΡΡΡΡ. Π’.ΠΊ. ΡΠ°ΠΊΠ°Ρ ΠΎΡΠΈΠ±ΠΊΠ° ΠΈΠ½ΠΎΠ³Π΄Π° ΠΌΠΎΠΆΠ΅Ρ Π±ΡΡΡ Π²ΡΠ·Π²Π°Π½Π° ΡΠ±ΠΎΡΠΌΠΈ Π² ΠΏΡΠΎΡΠ΅ΡΡΠ΅ // HTTP ΡΠΎΠ΅Π΄ΠΈΠ½Π΅Π½ΠΈΡ. await ms.fetchUrl('https://example') // β³ Attempt 1 failed. There are 2 retries left. // β³ Attempt 2 failed. There are 1 retries left. // β³ Attempt 3 failed. There are 0 retries left. } catch (err) { console.log(err) // β³ TypeError: fetch failed } // ΠΠ°ΠΏΡΠΎΡΡ Π²ΡΠ·Π²Π°Π²ΡΠΈΠ΅ ΠΎΡΠΈΠ±ΠΊΠΈ Ρ ΠΊΠΎΠ΄Π°ΠΌΠΈ 429 ΠΎΠ±ΡΠ°Π±Π°ΡΡΠ²Π°ΡΡΡΡ ΠΈ ΠΏΠΎΠ²ΡΠΎΡΡΡΡΡΡ Π²Π½ΡΡΡΠΈ // ΠΏΠ»Π°Π½ΠΈΡΠΎΠ²ΡΠΈΠΊΠ°. ΠΡΠΈ ΠΏΠΎΠ΄ΠΊΠ»ΡΡΠ΅Π½ΠΈΠΈ ΠΏΠ»Π°Π½ΠΈΡΠΎΠ²ΡΠΈΠΊΠ° ΠΎΠ±ΡΠ°Π±Π°ΡΡΠ²Π°ΡΡ Π² `retry` ΡΠ°ΠΊΠΈΠ΅ // ΠΎΡΠΈΠ±ΠΊΠΈ Π½Π΅ Π½ΡΠΆΠ½ΠΎ. ``` </details> ### ΠΠΈΠ΄Ρ ΠΎΡΠΈΠ±ΠΎΠΊ Π ΡΠ°ΠΌΠΊΠ°Ρ ΡΠ°Π±ΠΎΡΡ Ρ Π±ΠΈΠ±Π»ΠΈΠΎΡΠ΅ΠΊΠΎΠΉ Π²ΡΠ΄Π΅Π»Π΅Π½Ρ ΡΠ»Π΅Π΄ΡΡΡΠΈΠ΅ Π²ΠΈΠ΄Ρ ΠΎΡΠΈΠ±ΠΎΠΊ: | β | ΠΠ°Π·Π²Π°Π½ΠΈΠ΅ ΠΎΡΠΈΠ±ΠΊΠΈ | ΠΠ»Π°ΡΡ ΠΎΡΠΈΠ±ΠΊΠΈ | ΠΠ°ΡΠ»Π΅Π΄ΡΠ΅Ρ | ΠΠΏΠΈΡΠ°Π½ΠΈΠ΅ | | --- | ----------------------- | ------------------------------------------------------------------- | --------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------- | | 1 | **ΠΡΠΈΠ±ΠΊΠ° Π±ΠΈΠ±Π»ΠΈΠΎΡΠ΅ΠΊΠΈ** | [MoyskladError](#moyskladerror) | Error | ΠΡΠΈΠ±ΠΊΠ° Π±ΠΈΠ±Π»ΠΈΠΎΡΠ΅ΠΊΠΈ (Π½Π°ΠΏΡΠΈΠΌΠ΅Ρ Π½Π΅ Π²Π΅ΡΠ½ΠΎ ΡΠΊΠ°Π·Π°Π½Ρ ΠΏΠ°ΡΠ°ΠΌΠ΅ΡΡΡ ΠΎΠ΄Π½ΠΎΠ³ΠΎ ΠΈΠ· ΠΌΠ΅ΡΠΎΠ΄ΠΎΠ²). | | 2 | **ΠΡΠΈΠ±ΠΊΠ° Π·Π°ΠΏΡΠΎΡΠ°** | [MoyskladRequestError](#moyskladrequesterror) | [MoyskladError](#moyskladerror) | ΠΡΠ²Π΅Ρ ΠΏΠΎΠ»ΡΡΠ΅Π½ Ρ ΠΊΠΎΠ΄ΠΎΠΌ ΠΎΡΠΈΠ±ΠΊΠΈ, ΡΠ΅Π»ΠΎ ΠΎΡΠ²Π΅ΡΠ° ΠΠ ΡΠΎΠ΄Π΅ΡΠΆΠΈΡ JSON Ρ ΠΎΠΏΠΈΡΠ°Π½ΠΈΠ΅ΠΌ ΠΎΡΠΈΠ±ΠΊΠΈ Π² ΡΠΎΡΠΌΠ°ΡΠ΅ ΠΠΎΠΉΠ‘ΠΊΠ»Π°Π΄. | | 3 | **ΠΡΠΈΠ±ΠΊΠ° API ΠΠΎΠΉΠ‘ΠΊΠ»Π°Π΄** | [MoyskladApiError](#moyskladapierror) | [MoyskladRequestError](#moyskladrequesterror) | ΠΡΠ²Π΅Ρ ΠΏΠΎΠ»ΡΡΠ΅Π½ Ρ ΠΊΠΎΠ΄ΠΎΠΌ ΠΎΡΠΈΠ±ΠΊΠΈ, ΡΠ΅Π»ΠΎ ΠΎΡΠ²Π΅ΡΠ° ΡΠΎΠ΄Π΅ΡΠΆΠΈΡ JSON Ρ ΠΎΠΏΠΈΡΠ°Π½ΠΈΠ΅ΠΌ ΠΎΡΠΈΠ±ΠΊΠΈ Π² ΡΠΎΡΠΌΠ°ΡΠ΅ ΠΠΎΠΉΠ‘ΠΊΠ»Π°Π΄. | | 4 | **ΠΡΠΈΠ±ΠΊΠ° Π² ΠΊΠΎΠ»Π»Π΅ΠΊΡΠΈΠΈ** | [MoyskladCollectionError](#moyskladcollectionerror) | [MoyskladApiError](#moyskladapierror) | ΠΡΠΈΠ±ΠΊΠ° Π² ΠΎΠ΄Π½ΠΎΠΌ ΠΈΠ· ΡΠ»Π΅ΠΌΠ΅Π½ΡΠΎΠ² Π²Π½ΡΡΡΠΈ ΠΊΠΎΠ»Π»Π΅ΠΊΡΠΈΠΈ. | | 5 | **ΠΠ΅ΡΠ²Π½ΡΠΉ ΡΠ΅Π΄ΠΈΡΠ΅ΠΊΡ** | [MoyskladUnexpectedRedirectError](#moyskladunexpectedredirecterror) | [MoyskladRequestError](#moyskladrequesterror) | ΠΡΠΈΠ±ΠΊΠ° Π²ΠΎΠ·Π½ΠΈΠΊΠ°Π΅Ρ ΠΊΠΎΠ³Π΄Π° Π·Π°ΠΏΡΠΎΡ Π²Π΅ΡΠ½ΡΠ» ΠΏΠ΅ΡΠ΅Π½Π°ΠΏΡΠ°Π²Π»Π΅Π½ΠΈΠ΅ (ΠΊΠΎΠ΄ `3xx`) ΠΈ ΡΠ²Π½ΠΎ Π½Π΅ ΡΠΊΠ°Π·Π°Π½Π° ΠΎΠΏΡΠΈΡ Π·Π°ΠΏΡΠΎΡΠ° `rawRedirect` (ΠΎΠΏΡΠΈΡ `redirect` Π½Π΅ ΡΠ°Π²Π½Π° `follow`) | ΠΠΈΠ±Π»ΠΈΠΎΡΠ΅ΠΊΠ° Π΄Π°Π΅Ρ Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡΡ ΡΠΊΠ°Π·Π°ΡΡ ΠΏΠ°ΡΠ°ΠΌΠ΅ΡΡΡ Π·Π°ΠΏΡΠΎΡΠ° `muteApiErrors` ΠΈ `muteCollectionErrors` Π΄Π»Ρ ΠΈΠ³Π½ΠΎΡΠΈΡΠΎΠ²Π°Π½ΠΈΡ ΠΎΡΠΈΠ±ΠΎΠΊ API ΠΏ.3 ΠΈ ΠΏ.4 ΡΠΎΠΎΡΠ²Π΅ΡΡΡΠ²Π΅Π½Π½ΠΎ. ΠΡΠΈΠ±ΠΊΠΈ Π³Π»ΠΎΠ±Π°Π»ΡΠ½ΠΎΠ³ΠΎ fetch ΠΌΠΎΠ΄ΡΠ»Ρ ΠΈΠ»ΠΈ ΠΏΠ΅ΡΠ΅Π΄Π°Π½Π½ΠΎΠ³ΠΎ ΠΏΡΠΈ ΠΈΠ½ΠΈΡΠΈΠ°Π»ΠΈΠ·Π°ΡΠΈΠΈ ΡΠΊΠ·Π΅ΠΌΠΏΠ»ΡΡΠ° Π½Π΅ ΠΏΠ΅ΡΠ΅Ρ Π²Π°ΡΡΠ²Π°ΡΡΡΡ Π²Π½ΡΡΡΠΈ Π±ΠΈΠ±Π»ΠΈΠΎΡΠ΅ΠΊΠΈ. Π’.Π΅. Π²ΡΠ΅ ΠΎΠΏΠΈΡΠ°Π½Π½ΡΠ΅ Π²ΡΡΠ΅ ΠΎΡΠΈΠ±ΠΊΠΈ, ΡΠ²ΡΠ·Π°Π½Π½ΡΠ΅ Ρ Π²ΡΠΏΠΎΠ»Π½Π΅Π½ΠΈΠ΅ΠΌ Π·Π°ΠΏΡΠΎΡΠ°, ΡΠΎΡΠΌΠΈΡΡΡΡΡΡ ΡΠΆΠ΅ ΠΏΠΎΡΠ»Π΅ Π°Π½Π°Π»ΠΈΠ·Π° ΠΏΠΎΠ»ΡΡΠ΅Π½Π½ΠΎΠ³ΠΎ ΠΎΡΠ²Π΅ΡΠ°. #### MoyskladError > ΠΠ½ΡΡΡΠ΅Π½Π½ΡΡ ΠΎΡΠΈΠ±ΠΊΠ° Π±ΠΈΠ±Π»ΠΈΠΎΡΠ΅ΠΊΠΈ Π½Π΅ ΡΠ²ΡΠ·Π°Π½Π½Π°Ρ Ρ Π²ΡΠΏΠΎΠ»Π½Π΅Π½ΠΈΠ΅ΠΌ Π·Π°ΠΏΡΠΎΡΠ° ΠΊ API ΠΠ°ΡΠ»Π΅Π΄ΡΠ΅Ρ ΠΊΠ»Π°ΡΡ `Error` <details> <summary>ΠΡΠΈΠΌΠ΅ΡΡ</summary> ΠΠΎΠ΄ Ρ ΠΎΡΠΈΠ±ΠΊΠΎΠΉ: ```js await ms.GET('entity/product', { filter: 123 }) ``` Π‘ΡΡΡΠΊΡΡΡΠ° ΠΎΡΠΈΠ±ΠΊΠΈ: ```json { "name": "MoyskladError", "message": "ΠΠΎΠ»Π΅ filter Π·Π°ΠΏΡΠΎΡΠ° Π΄ΠΎΠ»ΠΆΠ½ΠΎ Π±ΡΡΡ ΡΡΡΠΎΠΊΠΎΠΉ ΠΈΠ»ΠΈ ΠΎΠ±ΡΠ΅ΠΊΡΠΎΠΌ" } ``` </details> #### MoyskladRequestError > ΠΡΠΈΠ±ΠΊΠ° ΠΏΡΠΈ Π²ΡΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ Π·Π°ΠΏΡΠΎΡΠ° ΠΠ°ΡΠ»Π΅Π΄ΡΠ΅Ρ ΠΊΠ»Π°ΡΡ [MoyskladError](#moyskladerror) <details> <summary>ΠΡΠΈΠΌΠ΅ΡΡ</summary> ΠΠΎΠ΄ Ρ ΠΎΡΠΈΠ±ΠΊΠΎΠΉ: ```js const ms = Moysklad({ fetch, api: 'foo', apiVersion: '0' }) await ms.GET('foo/bar') ``` Π‘ΡΡΡΠΊΡΡΡΠ° ΠΎΡΠΈΠ±ΠΊΠΈ: ```json { "name": "MoyskladRequestError", "message": "404 Not Found", "url": "https://api.moysklad.ru/api/foo/0/foo/bar", "status": 404, "statusText": "Not Found" } ``` </details> #### MoyskladApiError > ΠΡΠΈΠ±ΠΊΠ° API ΠΠΎΠΉΠ‘ΠΊΠ»Π°Π΄ ΠΠ°ΡΠ»Π΅Π΄ΡΠ΅Ρ ΠΊΠ»Π°ΡΡ [MoyskladRequestError](#moyskladrequesterror) ΠΡΠΈΠ±ΠΊΠ° ΡΠΎΡΠΌΠΈΡΡΠ΅ΡΡΡ Π² ΡΠ»ΡΡΠ°Π΅, Π΅ΡΠ»ΠΈ API ΠΏΠΎΠΌΠΈΠΌΠΎ HTTP ΠΊΠΎΠ΄Π° ΠΎΡΠΈΠ±ΠΊΠΈ, ΡΠ°ΠΊ ΠΆΠ΅ Π²Π΅ΡΠ½ΡΠ»ΠΎ ΡΡΠ°Π½Π΄Π°ΡΡΠ½ΠΎΠ΅ ΠΎΠΏΠΈΡΠ°Π½ΠΈΠ΅ ΠΎΡΠΈΠ±ΠΊΠΈ ΠΠΎΠΉΠ‘ΠΊΠ»Π°Π΄ Π² ΡΠΎΡΠΌΠ°ΡΠ΅ JSON. Π ΠΎΠ±ΡΠ°ΡΠ½ΠΎΠΌ ΡΠ»ΡΡΠ°Π΅ (ΠΎΡΠ²Π΅Ρ Π½Π΅ ΡΠΎΠ΄Π΅ΡΠΆΠΈΡ JSON Ρ ΠΎΡΠΈΠ±ΠΊΠΎΠΉ) Π±ΡΠ΄Π΅Ρ Π²ΡΠ±ΡΠΎΡΠ΅Π½Π° ΠΎΡΠΈΠ±ΠΊΠ° [MoyskladRequestError](#moyskladrequesterror) <details> <summary>ΠΡΠΈΠΌΠ΅ΡΡ</summary> ΠΠΎΠ΄ Ρ ΠΎΡΠΈΠ±ΠΊΠΎΠΉ: ```js await ms.GET('entity/product2') ``` Π‘ΡΡΡΠΊΡΡΡΠ° ΠΎΡΠΈΠ±ΠΊΠΈ: ```json { "name": "MoyskladApiError", "message": "ΠΠ΅ΠΈΠ·Π²Π΅ΡΡΠ½ΡΠΉ ΡΠΈΠΏ: 'product2' (https://dev.moysklad.ru/doc/api/remap/1.2/#error_1005)", "url": "https://api.moysklad.ru/api/remap/1.2/entity/product2", "status": 412, "statusText": "Precondition Failed", "code": 1005, "moreInfo": "https://dev.moysklad.ru/doc/api/remap/1.2/#error_1005", "errors": [ { "error": "ΠΠ΅ΠΈΠ·Π²Π΅ΡΡΠ½ΡΠΉ ΡΠΈΠΏ: 'product2'", "code": 1005, "moreInfo": "https://dev.moysklad.ru/doc/api/remap/1.2/#error_1005" } ] } ``` ΠΠΎΠΆΠ½ΠΎ ΠΈΠ³Π½ΠΎΡΠΈΡΠΎΠ²Π°ΡΡ ΠΎΡΠΈΠ±ΠΊΡ API, ΡΠΊΠ°Π·Π°Π² `muteApiErrors:true` Π² ΠΎΠΏΡΠΈΡΡ Π·Π°ΠΏΡΠΎΡΠ°. ```js const rawError1 = await ms.GET('entity/product2', null, { muteApiErrors: true }) console.log(rawError1.errors[0].error) // ΠΠ΅ΠΈΠ·Π²Π΅ΡΡΠ½ΡΠΉ ΡΠΈΠΏ: 'product2' ``` </details> #### MoyskladCollectionError > ΠΡΠΈΠ±ΠΊΠ° Π² ΠΊΠΎΠ»Π»Π΅ΠΊΡΠΈΠΈ ΠΏΡΠΈ ΠΌΠ°ΡΡΠΎΠ²ΠΎΠΌ ΡΠΎΠ·Π΄Π°Π½ΠΈΠΈ/ΠΈΠ·ΠΌΠ΅Π½Π΅Π½ΠΈΠΈ ΡΡΡΠ½ΠΎΡΡΠ΅ΠΉ ΠΠ°ΡΠ»Π΅Π΄ΡΠ΅Ρ ΠΊΠ»Π°ΡΡ [MoyskladApiError](#moyskladapierror) ΠΡΠΈΠ±ΠΊΠ° Π²ΡΠ±ΡΠ°ΡΡΠ²Π°Π΅ΡΡΡ ΠΊΠΎΠ³Π΄Π° Π²ΠΎΠ·Π²ΡΠ°ΡΠ°Π΅ΠΌΠ°Ρ ΠΊΠΎΠ»Π»Π΅ΠΊΡΠΈΡ ΡΠΎΠ΄Π΅ΡΠΆΠΈΡ Ρ ΠΎΡΡ Π±Ρ ΠΎΠ΄Π½Ρ ΠΎΡΠΈΠ±ΠΊΡ. ΠΠ°ΠΏΡΠΈΠΌΠ΅Ρ, ΠΊΠΎΠ³Π΄Π° ΠΏΡΠΈ ΠΌΠ°ΡΡΠΎΠ²ΠΎΠΌ ΠΎΠ±Π½ΠΎΠ²Π»Π΅Π½ΠΈΠΈ Π½Π΅ΡΠΊΠΎΠ»ΡΠΊΠΈΡ ΠΎΠ±ΡΠ΅ΠΊΡΠΎΠ² ΡΠ°ΡΡΡ ΠΈΠ· Π½ΠΈΡ Π½Π΅ Π±ΡΠ»ΠΈ ΠΎΠ±Π½ΠΎΠ²Π»Π΅Π½Ρ, ΡΠΎ API Π²Π΅ΡΠ½Π΅Ρ ΠΌΠ°ΡΡΠΈΠ² Ρ ΡΠ΅Π·ΡΠ»ΡΡΠ°ΡΠ°ΠΌΠΈ Π² ΡΠ°ΡΡΠΈ ΠΊΠΎΡΠΎΡΡΡ Π±ΡΠ΄Π΅Ρ ΡΠΊΠ°Π·Π°Π½Π° ΠΎΡΠΈΠ±ΠΊΠ°. <details> <summary>ΠΡΠΈΠΌΠ΅ΡΡ</summary> ΠΠΎΠ΄ Ρ ΠΎΡΠΈΠ±ΠΊΠΎΠΉ: ```js await ms.POST('entity/product', [ { foo: 'bar' }, { meta: { type: 'product', href: ms.buildUrl(`entity/product/${uuidFromApi}`) }, weight: 42 }, { name: 123 } ]) ``` Π‘ΡΡΡΠΊΡΡΡΠ° ΠΎΡΠΈΠ±ΠΊΠΈ: ```json { "name": "MoyskladCollectionError", "message": "ΠΡΠΈΠ±ΠΊΠ° ΡΠΎΡ ΡΠ°Π½Π΅Π½ΠΈΡ ΠΎΠ±ΡΠ΅ΠΊΡΠ°: ΠΏΠΎΠ»Π΅ 'name' Π½Π΅ ΠΌΠΎΠΆΠ΅Ρ Π±ΡΡΡ ΠΏΡΡΡΡΠΌ ΠΈΠ»ΠΈ ΠΎΡΡΡΡΡΡΠ²ΠΎΠ²Π°ΡΡ (https://dev.moysklad.ru/doc/api/remap/1.2/#error_3000)", "url": "https://api.moysklad.ru/api/remap/1.2/entity/product", "status": 400, "statusText": "Bad Request", "code": 3000, "moreInfo": "https://dev.moysklad.ru/doc/api/remap/1.2/#error_3000", "line": 1, "column": 3, "errors": [ { "error": "ΠΡΠΈΠ±ΠΊΠ° ΡΠΎΡ ΡΠ°Π½Π΅Π½ΠΈΡ ΠΎΠ±ΡΠ΅ΠΊΡΠ°: ΠΏΠΎΠ»Π΅ 'name' Π½Π΅ ΠΌΠΎΠΆΠ΅Ρ Π±ΡΡΡ ΠΏΡΡΡΡΠΌ ΠΈΠ»ΠΈ ΠΎΡΡΡΡΡΡΠ²ΠΎΠ²Π°ΡΡ", "code": 3000, "parameter": "name", "moreInfo": "https://dev.moysklad.ru/doc/api/remap/1.2/#error_3000", "line": 1, "column": 3 }, { "error": "ΠΡΠΈΠ±ΠΊΠ° ΡΠΎΡΠΌΠ°ΡΠ°: Π·Π½Π°ΡΠ΅Π½ΠΈΠ΅ ΠΏΠΎΠ»Ρ 'name' Π½Π΅ ΡΠΎΠΎΡΠ²Π΅ΡΡΡΠ²ΡΠ΅Ρ ΡΠΈΠΏΡ ΡΡΡΠΎΠΊΠ°", "code": 2016, "moreInfo": "https://dev.moysklad.ru/doc/api/remap/1.2/#error_2016", "line": 1, "column": 169 } ], "errorsIndexes": [ [ 0, [ { "error": "ΠΡΠΈΠ±ΠΊΠ° ΡΠΎΡ ΡΠ°Π½Π΅Π½ΠΈΡ ΠΎΠ±ΡΠ΅ΠΊΡΠ°: ΠΏΠΎΠ»Π΅ 'name' Π½Π΅ ΠΌΠΎΠΆΠ΅Ρ Π±ΡΡΡ ΠΏΡΡΡΡΠΌ ΠΈΠ»ΠΈ ΠΎΡΡΡΡΡΡΠ²ΠΎΠ²Π°ΡΡ", "code": 3000, "parameter": "name", "moreInfo": "https://dev.moysklad.ru/doc/api/remap/1.2/#error_3000", "line": 1, "column": 3 } ] ], [ 2, [ { "error": "ΠΡΠΈΠ±ΠΊΠ° ΡΠΎΡΠΌΠ°ΡΠ°: Π·Π½Π°ΡΠ΅Π½ΠΈΠ΅ ΠΏΠΎΠ»Ρ 'name' Π½Π΅ ΡΠΎΠΎΡΠ²Π΅ΡΡΡΠ²ΡΠ΅Ρ ΡΠΈΠΏΡ ΡΡΡΠΎΠΊΠ°", "code": 2016, "moreInfo": "https://dev.moysklad.ru/doc/api/remap/1.2/#error_2016", "line": 1, "column": 169 } ] ] ] } ``` ΠΠΎΠΆΠ½ΠΎ ΠΈΠ³Π½ΠΎΡΠΈΡΠΎΠ²Π°ΡΡ ΠΎΡΠΈΠ±ΠΊΠΈ Π² ΠΊΠΎΠ»Π»Π΅ΠΊΡΠΈΠΈ, ΡΠΊΠ°Π·Π°Π² `muteCollectionErrors:true` Π² ΠΎΠΏΡΠΈΡΡ Π·Π°ΠΏΡΠΎΡΠ°. ```js const result2 = await ms.POST( 'entity/product', [ { foo: 'bar' }, { meta: { type: 'product', href: ms.buildUrl(`entity/product/${uuidFromApi}`) }, weight: 42 }, { name: 123 } ], null, { muteCollectionErrors: true } ) const collItemError = result2.find(it => it.errors) if (collItemError) { console.log(collItemError.errors[0].error) // ΠΡΠΈΠ±ΠΊΠ° ΡΠΎΡ ΡΠ°Π½Π΅Π½ΠΈΡ ΠΎΠ±ΡΠ΅ΠΊΡΠ°: ΠΏΠΎΠ»Π΅ 'name' Π½Π΅ ΠΌΠΎΠΆΠ΅Ρ Π±ΡΡΡ ΠΏΡΡΡΡΠΌ ΠΈΠ»ΠΈ ΠΎΡΡΡΡΡΡΠ²ΠΎΠ²Π°ΡΡ } ``` </details> #### MoyskladUnexpectedRedirectError > ΠΡΠΈΠ±ΠΊΠ° Π΅ΡΠ»ΠΈ Π·Π°ΠΏΡΠΎΡ Π²Π΅ΡΠ½ΡΠ» ΠΏΠ΅ΡΠ΅Π½Π°ΠΏΡΠ°Π²Π»Π΅Π½ΠΈΠ΅ (ΠΊΠΎΠ΄ `3xx`), ΠΊΠΎΠ³Π΄Π° ΡΠ²Π½ΠΎ Π½Π΅ ΡΠΊΠ°Π·Π°Π½Π° ΠΎΠΏΡΠΈΡ Π·Π°ΠΏΡΠΎΡΠ° `rawRedirect` ΠΈ ΠΎΠΏΡΠΈΡ `redirect` Π½Π΅ ΡΠ°Π²Π½Π° `follow` ΠΠ°ΡΠ»Π΅Π΄ΡΠ΅Ρ ΠΊΠ»Π°ΡΡ [MoyskladRequestError](#moyskladrequesterror) <details> <summary>ΠΡΠΈΠΌΠ΅ΡΡ</summary> ```js /** id ΡΠΎΠ²Π°ΡΠ° ΠΈΠ· ΠΏΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΡ ΠΠΎΠΉΠ‘ΠΊΠ»Π°Π΄ */ const uuidFromApp = 'cb277549-34f4-4029-b9de-7b37e8e25a54' /** id ΡΠΎΠ²Π°ΡΠ° ΠΈΠ· API (ΠΎΡΠ»ΠΈΡΠ°Π΅ΡΡΡ ΠΎΡ id ΠΈΠ· ΠΏΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΡ) */ let uuidFromApi const getProduct = id => ms.GET(`entity/product/${id}`) try { await getProduct(uuidFromApp) } catch (err) { if (err instanceof Moysklad.MoyskladUnexpectedRedirectError) { uuidFromApi = ms.parseUrl(err.location).path.pop() await getProduct(uuidFromApi) } else { throw err } } ``` ΠΠΎΠΆΠ½ΠΎ ΠΎΠ±ΡΠ°Π±ΠΎΡΠ°ΡΡ ΠΏΠ΅ΡΠ΅Π½Π°ΠΏΡΠ°Π²Π»Π΅Π½ΠΈΠ΅ Π±Π΅Π· ΠΏΠ΅ΡΠ΅Ρ Π²Π°ΡΠ° ΠΎΡΠΈΠ±ΠΊΠΈ: ```js let product = await ms.GET(`entity/product/${uuidFromApp}`, null, { rawRedirect: true }) if (product instanceof Response) { uuidFromApi = ms.parseUrl(product.headers.get('location')).path.pop() product = await ms.GET(`entity/product/${uuidFromApi}`) } console.log(product.id === uuidFromApp) // false ``` ΠΠ»ΠΈ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΡ Π°Π²ΡΠΎΠΌΠ°ΡΠΈΡΠ΅ΡΠΊΠΎΠ΅ ΠΏΠ΅ΡΠ΅Π½Π°ΠΏΡΠ°Π²Π»Π΅Π½ΠΈΠ΅, ΡΠΊΠ°Π·Π°Π² Π·Π½Π°ΡΠ΅Π½ΠΈΠ΅ `follow` Π² ΠΎΠΏΡΠΈΠΈ `redirect`: ```js const product = await ms.GET(`entity/product/${uuidFromApp}`, null, { redirect: 'follow' }) console.log(product.id === uuidFromApp) // false ``` </details> ## Π‘ΠΎΠ±ΡΡΠΈΡ | Π‘ΠΎΠ±ΡΡΠΈΠ΅ | ΠΠ΅ΡΠ΅Π΄Π°Π²Π°Π΅ΠΌΡΠΉ ΠΎΠ±ΡΠ΅ΠΊΡ | ΠΠΎΠΌΠ΅Π½Ρ Π½Π°ΡΡΡΠΏΠ»Π΅Π½ΠΈΡ | | --------------- | --------------------------------------------- | ----------------------------- | | `request` | `{ requestId, url, options }` | ΠΡΠΏΡΠ°Π²Π»Π΅Π½ http Π·Π°ΠΏΡΠΎΡ | | `response` | `{ requestId, url, options, response }` | ΠΠΎΠ»ΡΡΠ΅Π½ ΠΎΡΠ²Π΅Ρ Π½Π° Π·Π°ΠΏΡΠΎΡ | | `response:body` | `{ requestId, url, options, response, body }` | ΠΠ°Π³ΡΡΠΆΠ΅Π½ΠΎ ΡΠ΅Π»ΠΎ ΠΎΡΠ²Π΅ΡΠ° | | `error` | `Error`, `{ requestId }` | ΠΡΠΈΠ±ΠΊΠ° ΠΏΡΠΈ Π²ΡΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ Π·Π°ΠΏΡΠΎΡΠ° | <details> <summary>ΠΡΠΈΠΌΠ΅ΡΡ</summary> ```js import { fetch } from 'undici' import { EventEmitter } from 'events' import Moysklad from 'moysklad' /** @type {Moysklad.MoyskladEmitter} */ const emitter = new EventEmitter() const ms = Moysklad({ fetch, emitter }) emitter .on('request', ({ requestId, url, options }) => { console.log(`${requestId} ${options.method} ${url}`) }) .on('error', (err, { requestId }) => { console.log(requestId, err) }) ms.GET('entity/customerorder', { limit: 1 }).then(res => { console.log('Order name: ' + res.rows[0].name) }) ``` ΠΠΎΠ»Π΅Π΅ ΠΏΠΎΠ΄ΡΠΎΠ±Π½ΡΠΉ ΠΏΡΠΈΠΌΠ΅Ρ ΡΠΌΠΎΡΡΠΈΡΠ΅ Π² [examples/events.js](https://github.com/wmakeev/moysklad/blob/master/examples/events.js). </details> ## ΠΡΡΠΎΡΠΈΡ ΠΈΠ·ΠΌΠ΅Π½Π΅Π½ΠΈΠΉ [CHANGELOG.md](https://github.com/wmakeev/moysklad/blob/master/CHANGELOG.md) ## ΠΠ»Π°Π½Ρ ΡΠ°Π·Π²ΠΈΡΠΈΡ ΠΠ»Π°Π½ΠΈΡΡΠ΅ΡΡΡ Π½Π΅ΠΌΠ½ΠΎΠ³ΠΎ ΠΏΠ΅ΡΠ΅ΡΠ°Π±ΠΎΡΠ°Π½Π½Π°Ρ Π²Π΅ΡΡΠΈΡ Π±ΠΈΠ±Π»ΠΈΠΎΡΠ΅ΠΊΠΈ Π² Π΄ΡΡΠ³ΠΎΠΌ ΡΠ΅ΠΏΠΎΠ·ΠΈΡΠΎΡΠΈΠΈ ΠΈ npm ΠΏΠ°ΠΊΠ΅ΡΠ΅. ΠΠ΅Π· ΠΊΠΎΠ½ΡΠ΅ΠΏΡΡΠ°Π»ΡΠ½ΡΡ ΠΈΠ·ΠΌΠ΅Π½Π΅Π½ΠΈΠΉ, Π½ΠΎ Ρ ΡΠ±ΡΠ°Π½Π½ΡΠΌ Π»Π΅Π³Π°ΡΠΈ ΠΊΠΎΠ΄ΠΎΠΌ. - ΠΠ΅ΡΠ΅ΠΏΠΈΡΠ°ΡΡ Π½Π° TypeScript - ΠΠΎΠ±Π°Π²ΠΈΡΡ Π½ΠΎΠ²ΡΠΉ ΠΌΠ΅ΡΠΎΠ΄ Π΄Π»Ρ ΡΠΎΡΠΌΠΈΡΠΎΠ²Π°Π½ΠΈΡ ΠΎΠ±ΡΠ΅ΠΊΡΠ° Π·Π°ΠΏΡΠΎΡΠ° - Π£Π±ΡΠ°ΡΡ Π²ΡΡ Π»Π΅Π³Π°ΡΠΈ (Π² ΡΠΎΠΌ ΡΠΈΡΠ»Π΅ ΡΠΎ, ΡΡΠΎ ΡΡΠ½Π΅Ρ Π»ΠΈΡΠ½ΠΈΠ΅ Π·Π°Π²ΠΈΡΠΈΠΌΠΎΡΡΠΈ - "have2" ΠΈ "stampit") - ΠΠΎΠ»Π΅Π΅ ΡΠ°Π·Π²Π΅ΡΠ½ΡΡΠ°Ρ Π΄ΠΎΠΊΡΠΌΠ΅Π½ΡΠ°ΡΠΈΡ Ρ Π°Π²ΡΠΎΠ³Π΅Π½Π΅ΡΠ°ΡΠΈΠ΅ΠΉ ΡΠ°ΡΡΠΈ ΠΎΠΏΠΈΡΠ°Π½ΠΈΠΉ ΠΌΠ΅ΡΠΎΠ΄ΠΎΠ² ## TODO Π‘Π²Π°Π»ΠΊΠ° ΠΌΡΡΠ»Π΅ΠΉ ΠΏΠΎ ΡΠ°Π·Π²ΠΈΡΠΈΡ Π±ΠΈΠ±Π»ΠΈΠΎΡΠ΅ΠΊΠΈ - [TODO.md](https://github.com/wmakeev/moysklad/blob/master/TODO.md)