Home
Softono
w

wmakeev

Professional software vendor delivering innovative solutions on the Softono platform. Specialized in both open-source and proprietary software development.

Total Products
1

Software by wmakeev

moysklad
Open Source

moysklad

![moysklad](https://wmakeev-public-files.s3-eu-west-1.amazonaws.com/images/logos/logoMS500x350.png) # moysklad <!-- omit in toc --> [![npm](https://img.shields.io/npm/v/moysklad.svg?cacheSeconds=1800&style=flat-square)](https://www.npmjs.com/package/moysklad) [![GitHub Actions Workflow Status](https://img.shields.io/github/actions/workflow/status/wmakeev/moysklad/main.yml?style=flat-square)](https://github.com/wmakeev/moysklad/actions/workflows/main.yml) <!-- [![Codecov](https://img.shields.io/codecov/c/github/wmakeev/moysklad?style=flat-square)](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)

Inventory Management API Tools
44 Github Stars