Giter Club home page Giter Club logo

bitrix's Introduction

@2bad/bitrix

Bitrix24 REST API client that doesn't suck

NPM version License Code coverage Travis Build Status GitHub Build Status Written in TypeScript

  • ๐Ÿ”ฅ No bullshit
  • โœจ Expressive API
  • ๐Ÿ’ช Strongly typed methods and requests results with TypeScript
  • ๐Ÿš€ Handles records batching and rate limiting for you
  • โค๏ธ Promise-based

@2bad/bitrix usage example

Install

npm install @2bad/bitrix

Usage

Init client with Bitrix API endpoint and access token and use the client to ease your Bitrix pain:

import Bitrix from '@2bad/bitrix'
// or for ESM
import { Bitrix } from '@2bad/bitrix'

const bitrix = Bitrix('https://PORTAL_NAME.bitrix24.ru/rest', 'ACCESS_TOKEN')

// Get deal
bitrix.deals.get('77')
  .then(({ result }) => {
    // Get typed payload
    const { TITLE } = result // string
    console.log(TITLE)
  })
  .catch(console.error)

// Get all deals
bitrix.deals.list({ select: ["*", "UF_*"] })
  .then(({ result }) => {
    const titles = result.map((e) => e.TITLE)
    console.log(titles)
  })
  .catch(console.error)

Authentication

Before you'll be able to use Bitrix REST API, you need to authenticate.

There are two ways to do that:

  1. A harder, but proper way โ€” create a Bitrix application and then authenticate with an OAuth.

    Authentication with an OAuth requires some additional steps and that's up to you to deal with it using a lambda function, some server or a Postman.

    That will yield an access token. Use it to init the client:

    const bitrix = Bitrix('https://PORTAL_NAME.bitrix24.ru/rest', 'ACCESS_TOKEN')

    Note, that access token lives only 30 minutes and should be refreshed periodically with provided by OAuth refresh token, which in turn lives 1 month.

  2. An easier way โ€” create a Bitrix inbound webhook with required permissions.

    It will instantly give you an endpoint with a token inside of it. No additional authentication or access tokens required to use it:

    const bitrix = Bitrix('https://PORTAL_NAME.bitrix24.ru/rest/1/WEBHOOK_TOKEN')

    That endpoint lives indefinitely. Rejoice and hope that it won't backfire on you.

API

How it works

The client tries hard to provide a consistent, strongly typed and at the same time effortless experience.

It takes care of the any necessary batching to run "large" commands, like retrieving all deals or leads with least possible network request. That allows achieving a reading of the 250 000 and updating of 5000 entries per minute with a single line of code.

All client methods are automatically rate-limited and queued if needed to cope with Bitrix REST API limitation of 2 requests per second, so you should never see Bitrix errors about exceeding rate limits.

Methods required params and returned payload types are automatically resolved based on Methods interface, which effectively describes all currently supported methods.

To facilitate better architecture, the client divided into layers:

  1. Methods โ€” a mostly generic methods like call to work with Bitrix API methods. They take care of the routine and provide a foundation for more complex operations.
  2. Client โ€” a generic client, which takes care of some additional routine tasks like setting access token on every request, setting up a queue for the rate limiting, and providing generic methods.
  3. Services โ€” each service provides an expressive interface to work with a specific group of Bitrix REST API operations. In essence, they do orchestrate generic client methods and parameters to get proper results.
  4. Bitrix client โ€” a top-level provider of generic method and services. An effortless way to deal with Bitrix REST API by using an intuitive API, which takes care of all underlying complexity.

FAQ

Is it finished?

The core is ready and stable. It can be used to arbitrary invoke any Bitrix REST API methods.

However, not all Bitrix REST API methods are exposed as convenient client services yet (the ones like bitrix.deals.list()).

If you need specific service, add one by making a Pull Request, following the structure of already existing services and "Adding new methods" instructions.

I'm not a Typed Language Master Race user. Can I use it with a regular JavaScript?

Sure. Just install and import it as any other NPM module. But The Type Police is already on the way for you.

Note that this library wasn't designed with regular JavaScript in mind, so it doesn't make unnecessary dynamic checks. Don't be too persistent in passing on wrong parameters โ€” it might yield unexpected results. After all, TypeScript is a recommended way to use it.

Should I check payloads error properties for errors?

You shouldn't. Catch rejections instead, as the library will reject if there are any errors in a payload.

List method does not return user fields!

Bitrix API doesn't do that by default. Use wildcards in select param to force inclusion of user fields:

bitrix.deals.list({ select: ['*', 'UF_*'] })

User fields are not typed properly

Client can't know about non-default properties in payloads. Because of that, it assumes that any payload can have any additional fields of type [key: string]: string:

bitrix.leads.get({ ID: '77' })
  .then(({ result }) => {
    // known property of type `string`
    const title = result.TITLE

    // unknown property of type `string`
    const someData = result.UF_23232323

    console.log(title, someData)
  })

I need to call a Bitrix method which isn't supported yet

Use appropriate low-level client methods with a casting, like so:

bitrix.call('some.new.get' as any, { ID: '77' } as any)
  .then((payload) => payload as GetPayload<NewPayload>)

bitrix.list('some.new.list' as any, { select: ["TITLE"] })
  .then((payload) => payload as ListPayload<NewPayload>)

I need to call a specific set of commands. How to do that effectively?

Use the batch method. It will handle all routine:

bitrix.batch({
  lead: { method: Method.GET_LEAD, params: { ID: '77' } },
  deals: { method: Method.LIST_DEALS, params: {} }
})

I'm using a self-signed SSL certificate and I'm getting a [RequestError]: self signed certificate. What should I do?

Override got options in constructor:

const bitrix = Bitrix('https://PORTAL_NAME.bitrix24.ru/rest', 'ACCESS_TOKEN', {https: { rejectUnauthorized: false }})

Development

  • npm test โ€” run all tests and collect full coverage report
  • npm run test:unit โ€” run unit tests and collect coverage report
  • npm run test:integration โ€” run integration tests and collect coverage report
  • npm run test:watch โ€” watch for changes and run all tests
  • npm run test:unit:watch โ€” watch for changes and run unit tests
  • npm run test:integration:watch โ€” watch for changes and run integration tests
  • npm run build โ€” build the library for the release

Adding new methods

Proper method parameters and payload types handling requires some routine when adding any new method. Hopefully, we can do it better in future, but for now follow those steps:

  1. Add new method into the Method enum.
  2. Add it into the LISTABLE_METHODS array if it is listable (paginated). Not everything that lists is listable, so check it.
  3. Add or update related service:
    1. Put exposed by the service public methods into the index.ts file. Ensure that you're properly mapping service method arguments to call or list params.
    2. Add related entities into the entities.ts.
    3. Add interface describing service methods into the methods.ts. Test and check method payload type to be sure you've described it correctly!
    4. Extend Methods interface with the added service-specific interface. That way the client will know how to resolve parameters and payload types for the added method.
    5. Add tests into the index.unit.test.ts.
  4. Re-export service public types like Entities in the bitrix.ts to make them available to the end-users.
  5. Document addition in the docs.

bitrix's People

Contributors

armordarks avatar mrhyde avatar newsiberian avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

bitrix's Issues

crm.livefeedmessage.add

crm.livefeedmessage.add is there any way to make it work?

I'm trying to enter an activity when I make a change to a lead but it won't let me use it.

image

Using list methods where result is not an array

Hello,

I'm trying to use the crm.stagehistory.list method the following way:

bitrix.list('crm.stagehistory.list' as any, { entityTypeId: 2 } as any)
    .then((payload) => 
          {
              console.log(payload);
          });

However, if you try that you will see that it fails on batchToListPayload because it assumes result is iterable, however, result in this call is an object and items inside that is an array.

Maybe there could be a way to specify how to batch, or at least a way to pass a different batchToListPayload?

Kind regards,

I think it's an issue with old version of got

Hello,

I think I'm experiencing an issues with the old version of got in this library:

TypeError: URL is not a constructor
at normalize (normalize-arguments.js?9801:124)
at got (create.js?4b17:32)
at Function.got. [as get] (create.js?4b17:64)
at eval (index.js?5442:26)
at run (index.js?6520:249)
at PQueue._tryToStartAnother (index.js?6520:197)
at eval (index.js?6520:263)
at new Promise ()
at PQueue.add (index.js?6520:244)
at queuedGet (index.js?5442:26)

Can you please advise a path to work around this? Thank you.

Bitrix Constructor Error

When attempting to call the Bitrix constructor in my code, I consistently encounter the following error message:

TypeError: Bitrix is not a function
    at Object.<anonymous> (/Users/work/workspace/get_leads.js:2:16)
    at Module._compile (node:internal/modules/cjs/loader:1159:14)
    at Module._extensions..js (node:internal/modules/cjs/loader:1213:10)
    at Module.load (node:internal/modules/cjs/loader:1037:32)
    at Module._load (node:internal/modules/cjs/loader:878:12)
    at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:82:12)
    at node:internal/main/run_main_module:23:47

The relevant code snippet is as follows (I have also attempted using import, but encountered the same error):
get_leads.js

const Bitrix = require('@2bad/bitrix');

const bitrix = Bitrix('https://PORTAL_NAME.bitrix24.ru/rest', 'ACCESS_TOKEN');

I appreciate any assistance in resolving this issue.

Node.js version: v19.0.1

Ideas for v3

  • Switch all requests to POST by default (especially if Bitrix doesn't cache GET requests which I doubt they do)
  • Move to got v11
  • Simplify services by using generics. Adding new methods should be as easy as call<Leads>(params)
  • Implements tests for file uploads

URL is not a constructor

Hi, I using this in vue.js app

import Bitrix from '@2bad/bitrix'

const bitrix = Bitrix('https://portal.bitrix24.ru/rest/7/token/')

bitrix.deals.list({ select: ['*', 'UF_*'] })
  .then(({ result }) => {
    const titles = result.map((e) => e.TITLE)
    console.log(titles)
  })
  .catch(console.error)

and I get output in console:

TypeError: URL is not a constructor
    at normalize (normalize-arguments.js?c218:124)
    at got (create.js?71a9:32)
    at Function.got.<computed> [as get] (create.js?71a9:64)
    at eval (index.js?d476:26)
    at run (index.js?987e:249)
    at PQueue._tryToStartAnother (index.js?987e:197)
    at eval (index.js?987e:263)
    at new Promise (<anonymous>)
    at PQueue.add (index.js?987e:244)
    at queuedGet (index.js?d476:26)

What is fuck?

Config option for disable SSL check

Sending request to host that has self-signed cert raises an error

GotError [RequestError]: self signed certificate

any options to avoid this?

Get Invoice list without pagination

Good day!

Since I couldn't find methods for work with Invoice object, I tried to use call with argument 'crm.invoice.list'. And got only 50 objects.

Is there nice solution to get all Invoices at once?

Userfield at company

Hi,
i needed to create a company and set data for a userfield. This is possible for deals, but not for companies.

I fixed this issue locally by adding the following line to the Company interface in entities.d.ts.

readonly [key: string]: string | ReadonlyArray<MultiField> | null;

I have to tell you, i am really than thankfull that you created this project. This is definitly the easiest way to work with the bitrix "REST" API. (I think no one of the developers of bitrix ever heared what REST really is, when i look at their crappy API)

Response code 414 (Request-URI Too Large)

Good day!

I'm trying to call the list method for deals using select, including about a dozen field names, including custom ones. However, I am encountering the following error.

Using select: ['*', 'UF_'] leads to an undesired inflation of the response to the query, which is highly undesirable.

Any possible solutions?

Adding a file to a custom field when creating a deal

I'm trying to add an image to a custom field when I create a deal, but I've been receiving the same HTTPError.

I'm trying to execute the code below:

const imgData = [{
  fileData: [ "test-st.png", "iVBORw0KGgoAAAANSUh..." ] // fileData[1] is a base64 str 
}]

let data = await bitrix.deals.create({
    fields: {
      TITLE: "ST-TEST",
      CATEGORY_ID: 18,
      UF_CRM_1659988440473: 4759,
      UF_CRM_1678981077892: imgData, 
    },
  }, {
    REGISTER_SONET_EVENT: 'Y'
})

The full error is:

{
    "name": "HTTPError",
    "timings": {
        "start": 1684867744230,
        "socket": 1684867744231,
        "lookup": 1684867744255,
        "connect": 1684867744410,
        "secureConnect": 1684867744568,
        "upload": 1684867744568,
        "response": 1684867744880,
        "end": 1684867744881,
        "phases": {
            "wait": 1,
            "dns": 24,
            "tcp": 155,
            "tls": 158,
            "request": 0,
            "firstByte": 312,
            "download": 1,
            "total": 651
        }
    }
}

What can I do to solve this?

Error in batch response

In the batch response, why not return the full object? with erros and result?.

by doind bitrix.batch, if there is an error in the array, it will throw error and the error is just a string "Error: [batch] failed to process. Received errors in 1 commands:
[object Object]"

this is a big problem, cause, after the batch, how can i know which commans have worked and which didnt?

I would like to, after the batch, know the commands that worked and those that didnt

414 Request-URI Too Large

So, i'm doing bitrix.call('crm.product.property.add', query) with a list property which has really large amount of options, and i'm getting 414 error. Is there any way to fix that? Aren't queries supposed to be POST requests?

authentication error

Good morning, I'm having trouble using and configuring oauth authentication and from what I realized it is no longer possible to use via webhook, I would like to put a tutorial on how to use oauth from bitrix24 or release via webhook. thanks. Obs. Was translated in google translator in case of spelling errors

Data marshalling and aggregation

Those have relation to the client, though, in future might be implemented as standalone solutions.

This issue is for keeping information about possible solutions since there is no other place to keep it.

Some useful findings:

Data structures

Tools

Guides

Smart Process Automation (SPA) issue

it seems bitrix.list() does not work correctly with SPA

To make my code work:
bitrix.list('crm.item.list', { entityTypeId: '138', select: ['ufCrm4_1654801473656', 'ID'] })

I had to change one line in the source code:
node_modules/@2bad/bitrix/build/main/client/methods/list.js:39

I changed it and it works:
...r -> ...r.items

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.