@bitrix24/b24jssdk
Version:
Bitrix24 REST API JavaScript SDK
167 lines (163 loc) • 6.86 kB
JavaScript
/**
* @package @bitrix24/b24jssdk
* @version 3.0.0
* @copyright (c) 2026 Bitrix24
* @license MIT
* @see https://github.com/bitrix24/b24jssdk
* @see https://bitrix24.github.io/b24jssdk/
*/
;
const sdkError = require('../../sdk-error.cjs');
const loggerFactory = require('../../../logger/logger-factory.cjs');
var __defProp = Object.defineProperty;
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
const READ_COMMAND_KEYS = ["method", "params", "as", "parallel"];
class AbstractInteractionBatch {
static {
__name(this, "AbstractInteractionBatch");
}
parallelDefaultValue;
requestId;
restrictionManager;
logger;
// @memo this regeneration -> isObjectMode
processingStrategy;
_commands = [];
constructor(options) {
this.parallelDefaultValue = options.parallelDefaultValue;
this.requestId = options.requestId;
this.restrictionManager = options.restrictionManager;
this.processingStrategy = options.processingStrategy;
this.logger = options.logger;
}
// region Setter Strategy ////
setProcessingStrategy(processingStrategy) {
this.processingStrategy = processingStrategy;
}
// endregion ////
// region Getter ////
get size() {
return this._commands.length;
}
get maxSize() {
return 0;
}
// endregion ////
// region Request ////
addCommands(calls) {
if (!this.processingStrategy) {
throw new sdkError.SdkError({
code: "JSSDK_INTERACTION_BATCH_EMPTY_PROCESSING_STRATEGY",
description: "ProcessingStrategy not set",
status: 500
});
}
try {
this._warnUnreadCommandKeys(calls);
} catch {
}
this._commands = this.processingStrategy.prepareCommands(calls, {
parallelDefaultValue: this.parallelDefaultValue
});
}
/**
* Warns, once per `addCommands`, when a batch command lost its arguments to a
* key the parser does not read — a command with no `params`, or one naming
* `query`. A key beside a populated `params` is left alone.
*
* `query` is the reason this exists. On `restApi:v3` the portal's own
* reference calls a command's arguments `query`, and so does every `curl`
* example; the SDK's key is `params`, and it writes the wire name for you.
* Write `query` yourself and the arguments are read by nobody — the command
* goes out with an empty `query`, which the portal **accepts**. Measured on
* `main.eventlog.list` with `select: ['id']` and `pagination: { limit: 2 }`:
* under `params` the portal answered 2 rows of 1 field, the same request
* spelled `query` answered 50 rows of 13 fields — the whole default page, with
* the `select` and the limit both gone. HTTP 200 either way, no error
* anywhere.
*
* `restApi:v2` loses them just as quietly by a different route: there the
* arguments are serialised into the `cmd` querystring from `params`, so the
* command goes out as `method?` with nothing after it. Measured on `user.get`
* with `filter: { ACTIVE: 'N' }`, against a portal whose only user is active:
* under `params` the portal answered 0 rows — the filter worked — and the same
* request spelled `query` answered 1 row, the user the filter was meant to
* exclude.
*
* So there is nothing to notice on either version: no error, no empty result,
* just an answer to a question nobody asked.
*
* TypeScript catches a fresh object literal and nothing more — assign it to a
* variable first, or build the commands from a config object, a `JSON.parse`,
* or plain JavaScript, and the compiler never sees it. Same hole
* `_warnMisplacedOptions` was written for (#426), and the same trade: warn
* rather than throw, because the call still does something. Through
* `forcedLog`, because the default logger is silent and a caller who has not
* wired one up is exactly who this is for (#483).
*
* Once per `addCommands` — i.e. once per batch **request** — not once per
* command: 50 commands built from one bad template would otherwise be 50
* identical console lines. The keys are collected across the batch and
* reported together, with the positions that carried them. A `batchByChunk`
* walk still warns once per chunk, since each chunk is its own request.
*
* Own enumerable string keys only, so a key on a prototype, a symbol key, or a
* non-enumerable one is not seen — and a tuple carrying extra elements is not
* checked at all. All are the quiet direction: this exists to catch the
* ordinary mistake, not to validate every shape a caller can build.
*
* `forcedLog` reaches the console only while the app has wired no logger of
* its own. One that filters by level may drop this, like every other SDK
* warning.
*/
_warnUnreadCommandKeys(calls) {
const unread = /* @__PURE__ */ new Set();
const positions = [];
for (const [index, row] of Object.entries(calls)) {
if (!row || typeof row !== "object" || Array.isArray(row)) {
continue;
}
const rowUnread = Object.keys(row).filter((key) => !READ_COMMAND_KEYS.includes(key) && void 0 !== row[key]);
if (0 === rowUnread.length) {
continue;
}
const params = row.params;
const hasParams = null !== params && "object" === typeof params && Object.keys(params).length > 0;
const namesTheWireKey = rowUnread.some((key) => "query" === key.toLowerCase());
if (hasParams && !namesTheWireKey) {
continue;
}
rowUnread.forEach((key) => unread.add(key));
positions.push(index);
}
if (0 === unread.size) {
return;
}
const keys = [...unread];
loggerFactory.LoggerFactory.forcedLog(
this.logger ?? loggerFactory.LoggerFactory.createNullLogger(),
"warning",
`[b24jssdk] batch command: ${keys.join(", ")} ${1 === keys.length ? "is" : "are"} ignored \u2014 a command's arguments go in \`params\`. Write \`params: { \u2026 }\`. (\`query\` is the portal's own wire spelling on \`restApi:v3\`, which the SDK writes for you; on \`restApi:v2\` the arguments are serialised into the \`cmd\` querystring instead.)`,
{
code: "JSSDK_BATCH_UNREAD_COMMAND_KEY",
unread: keys.join(", "),
read: READ_COMMAND_KEYS.join(", "),
commands: positions.join(", ")
}
).catch(() => {
});
}
getCommandsForCall() {
if (!this.processingStrategy) {
throw new sdkError.SdkError({
code: "JSSDK_INTERACTION_BATCH_EMPTY_PROCESSING_STRATEGY",
description: "ProcessingStrategy not set",
status: 500
});
}
return this.processingStrategy.buildCommands(this._commands);
}
// endregion ////
}
exports.AbstractInteractionBatch = AbstractInteractionBatch;
//# sourceMappingURL=abstract-interaction-batch.cjs.map