@bitrix24/b24jssdk
Version:
Bitrix24 REST API JavaScript SDK
129 lines (126 loc) • 4.84 kB
JavaScript
/**
* @package @bitrix24/b24jssdk
* @version 2.2.0
* @copyright (c) 2026 Bitrix24
* @license MIT
* @see https://github.com/bitrix24/b24jssdk
* @see https://bitrix24.github.io/b24jssdk/
*/
import { SdkError } from '../core/sdk-error.mjs';
import { AbstractB24 } from '../core/abstract-b24.mjs';
import { HttpV2 } from '../core/http/v2.mjs';
import { HttpV3 } from '../core/http/v3.mjs';
import { AuthHookManager } from './auth.mjs';
import { versionManager } from '../core/version-manager.mjs';
var __defProp = Object.defineProperty;
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
class B24Hook extends AbstractB24 {
static {
__name(this, "B24Hook");
}
#authHookManager;
// region Init ////
constructor(b24HookParams, options) {
super();
this.#authHookManager = new AuthHookManager(
b24HookParams
);
const warningText = "The B24Hook object is intended exclusively for use on the server.\nA webhook contains a secret access key, which MUST NOT be used in client-side code (browser, mobile app).";
this._httpV2 = new HttpV2(this.#authHookManager, this._getHttpOptions(), options?.restrictionParams);
this._httpV2.setClientSideWarning(true, warningText);
this._httpV3 = new HttpV3(this.#authHookManager, this._getHttpOptions(), options?.restrictionParams);
this._httpV3.setClientSideWarning(true, warningText);
this._isInit = true;
}
// endregion ////
get auth() {
return this.#authHookManager;
}
// region Core ////
/**
* Disables warning about client-side query execution
*/
offClientSideWarning() {
versionManager.getAllApiVersions().forEach((version) => {
this.getHttpClient(version).setClientSideWarning(false, "");
});
}
// endregion ////
// region Get ////
/**
* @inheritDoc
*/
getTargetOrigin() {
this._ensureInitialized();
return this.#authHookManager.getTargetOrigin();
}
/**
* @inheritDoc
*/
getTargetOriginWithPath() {
this._ensureInitialized();
return this.#authHookManager.getTargetOriginWithPath();
}
// endregion ////
// region Tools ////
/**
* Creates a `B24Hook` instance from a webhook URL.
*
* Accepts both REST API v2 and v3 webhook formats:
* - v2: `https://your_domain.bitrix24.com/rest/{userId}/{secret}`
* - v3: `https://your_domain.bitrix24.com/rest/api/{userId}/{secret}`
*
* Validates that the URL uses HTTPS, has the correct path structure, and
* contains a numeric user ID. Throws a descriptive `Error` on any violation
* without echoing the URL (which contains the secret).
*
* @param url - Full webhook URL as shown in the Bitrix24 admin panel.
* @param options - Optional restriction parameters (rate limits, etc.).
* @returns A ready-to-use `B24Hook` instance.
* @throws {SdkError} If the URL is empty (`JSSDK_HOOK_URL_EMPTY`), unparseable
* (`JSSDK_HOOK_URL_INVALID`), not HTTPS (`JSSDK_HOOK_URL_NOT_HTTPS`),
* malformed (`JSSDK_HOOK_URL_MALFORMED`), or the userId segment is not
* numeric (`JSSDK_HOOK_URL_USER_ID_NOT_NUMERIC`).
*/
static fromWebhookUrl(url, options) {
if (!url.trim()) {
throw new SdkError({ code: "JSSDK_HOOK_URL_EMPTY", description: "Webhook URL cannot be empty", status: 0 });
}
let parsedUrl;
try {
parsedUrl = new URL(url.replace("/rest/api", "/rest"));
} catch {
throw new SdkError({ code: "JSSDK_HOOK_URL_INVALID", description: "Invalid webhook URL format", status: 0 });
}
if (parsedUrl.protocol !== "https:") {
throw new SdkError({ code: "JSSDK_HOOK_URL_NOT_HTTPS", description: "Webhook requires HTTPS protocol", status: 0 });
}
const pathParts = parsedUrl.pathname.split("/").filter(Boolean);
const isValidFormat = (
// Format: /rest/{id}/{webhook}
pathParts.length === 3 && pathParts[0] === "rest" || pathParts.length === 4 && pathParts[0] === "rest" && pathParts[1] === "api"
);
if (!isValidFormat) {
throw new SdkError({ code: "JSSDK_HOOK_URL_MALFORMED", description: "Webhook URL must follow format: /rest/<userId>/<secret> or /rest/api/<userId>/<secret>", status: 0 });
}
const userIdIndex = pathParts[1] === "api" ? 2 : 1;
const secretIndex = pathParts[1] === "api" ? 3 : 2;
const userIdStr = pathParts[userIdIndex];
const secret = pathParts[secretIndex];
if (!/^\d+$/.test(userIdStr)) {
throw new SdkError({ code: "JSSDK_HOOK_URL_USER_ID_NOT_NUMERIC", description: "User ID must be numeric in webhook URL", status: 0 });
}
const userId = Number.parseInt(userIdStr, 10);
return new B24Hook(
{
b24Url: parsedUrl.origin,
userId,
secret
},
options
);
}
// endregion ////
}
export { B24Hook };
//# sourceMappingURL=b24.mjs.map