Skip to content

Commit

Permalink
prepare 5.0.0 release (#83)
Browse files Browse the repository at this point in the history
* copyedits

* fix misnamed directory

* use spread operator instead of Object.assign

* add issue templates

* add babel-eslint

* add event capacity config property

* re-add deprecation warning on samplingInterval

* better config validation

* remove rollup-plugins-node-resolve

* use newer Rollup node-resolve plugin

* rm rollup-plugin-includepaths (unused)

* npm audit fix (handlebars dependency from jest)

* comment

* copyedit

* use new test helpers + misc test cleanup

* clean up stream testing logic

* fix hash parameter

* linter

* clearer way to model the config option defaults/types

* test improvements

* change internal param name

* comment

* fix default logger logic

* simpler way to enforce minimum values

* implement diagnostic events in common JS package (#11)

* add support for function type in config options

* add support for function type in config options (#13)

* add wrapper metadata options and fix custom header logic

* lint

* lint

* remove image-loading logic from common code, replace it with an abstraction

* add validation for options.streaming

* typo

* rm unused params

* typo in comment

* misc fixes to merged code from external PR

* add event payload ID header

* npm audit fix

* change exact dependencies to best-compatible

* standardize linting

* disallow "window" and "document"

* improve diag event tests + debug logging

* misc cleanup

* fix updating secure mode hash with identify()

* don't omit streamInits.failed when it's false

* clean up init state logic, prevent unhandled rejections

* lint

* less strict matching of json content-type header

* remove unsafe usage of hasOwnProperty

* console logger must tolerate console object not always existing

* fix double initialization of diagnostics manager

* fix TypeScript declaration for track() and add more TS compilation tests (#27)

* remove startsWith usage (#28)

* prevent poll caused by a stream ping from overwriting later poll for another user (#29)

* upgrade jest dependency and transitive yargs-parser dependency (#30)

* Add null to LDEvaluationDetail.reason type (#31)

* Revert "Add null to LDEvaluationDetail.reason type (#31)"

This reverts commit bcb1573.

* Revert "Add null to LDEvaluationDetail.reason type (#31)"

This reverts commit bcb1573.

* nullable evaluation reason (#32)

* adding alias event functionality (#33)

* set stream read timeout

* Add prepare script (#34)

* add a missing typescript verification (#36)

* Removed the guides link

* Correct doc link (#36)

* Fix typo in LDClient.on jsdoc (#37)

* add inlineUsersInEvents option in TypeScript (#37)

* Filter private attributes on debug event users. Send variation for debug events.

* update uuid package version (#39)

* use Releaser v2 config + newer CI image

* First half, add the type, create the new options, add the new util method, and add tests

* Second half, call the tranform util method before calling any HTTP requests

* Update the transform to work on a copy of headers instead of mutating it

* add comments about removing custom event warning logic in the future

* revert updating of UUID dependency (#43)

* Revert "update uuid package version (#39)"

This reverts commit 3b2ff6c.

* update package-lock.json

* better error handling for local storage operations (#44)

* better error handling for local storage operations

* lint

* fix obsolete comments

* add basic logger similar to server-side Node SDK (#45)

* fix exports and add validation of custom logger (#46)

* remove typedoc.js file that interferes with Releaser's docs build

* update typescript version

* add maintenance branch

* remove deprecated things (#48)

* remove deprecated options and function

* rm references to obsolete function

* restore deprecation logic, just leave the data empty

* remove samplingInterval from TS test code

* fix TS test code again

* fix EvaluationDetail.reason to be nullable so we can get rid of NonNullableLDEvaluationReason type (#49)

* remove deprecated options and function

* rm references to obsolete function

* restore deprecation logic, just leave the data empty

* remove samplingInterval from TS test code

* fix TS test code again

* fix EvaluationDetail.reason to be nullable so we can get rid of NonNullableLDEvaluationReason type

* fix TS test code

* re-bump uuid package (#50)

* Revert "Revert "update uuid package version (#39)""

This reverts commit 89359b1bf4ddbe6b2fedb95f1dc11240483c60f7.

* remove lockfile (sc-107301)

* use regular User-Agent header name unless overridden by js-client-sdk (#52)

* switch to publishing js-sdk-common as a regular Node module (#51)

* fix CI

* remove `version` constant which can't be exported from js-sdk-common (#53)

* catch errors in JSON parsing of stream data (#54)

* catch errors in JSON parsing of stream data

* lint

* backport sc-142333 fix

* prepare 3.5.1 release (#63)

* initial move of code from js-client-sdk-private

* changelog note

* rm obsolete comment

* add npm audit helper

* update babel, jest, rollup

* fix rollup config

* fix ES build, dependency cleanup

* add Releaser metadata

* Update babel config to work in `test` without `useBuiltIns`

* copyedits

* fix misnamed directory

* use spread operator instead of Object.assign

* add issue templates

* add babel-eslint

* add event capacity config property

* re-add deprecation warning on samplingInterval

* better config validation

* remove rollup-plugins-node-resolve

* use newer Rollup node-resolve plugin

* rm rollup-plugin-includepaths (unused)

* npm audit fix (handlebars dependency from jest)

* comment

* copyedit

* use new test helpers + misc test cleanup

* clean up stream testing logic

* fix hash parameter

* linter

* clearer way to model the config option defaults/types

* test improvements

* change internal param name

* comment

* fix default logger logic

* simpler way to enforce minimum values

* implement diagnostic events in common JS package (#11)

* add support for function type in config options

* add support for function type in config options (#13)

* add wrapper metadata options and fix custom header logic

* lint

* lint

* remove image-loading logic from common code, replace it with an abstraction

* add validation for options.streaming

* typo

* rm unused params

* typo in comment

* misc fixes to merged code from external PR

* add event payload ID header

* npm audit fix

* change exact dependencies to best-compatible

* standardize linting

* disallow "window" and "document"

* improve diag event tests + debug logging

* misc cleanup

* fix updating secure mode hash with identify()

* don't omit streamInits.failed when it's false

* clean up init state logic, prevent unhandled rejections

* lint

* less strict matching of json content-type header

* remove unsafe usage of hasOwnProperty

* console logger must tolerate console object not always existing

* fix double initialization of diagnostics manager

* fix TypeScript declaration for track() and add more TS compilation tests (#27)

* remove startsWith usage (#28)

* prevent poll caused by a stream ping from overwriting later poll for another user (#29)

* upgrade jest dependency and transitive yargs-parser dependency (#30)

* Add null to LDEvaluationDetail.reason type (#31)

* Revert "Add null to LDEvaluationDetail.reason type (#31)"

This reverts commit bcb1573.

* Revert "Add null to LDEvaluationDetail.reason type (#31)"

This reverts commit bcb1573.

* nullable evaluation reason (#32)

* adding alias event functionality (#33)

* set stream read timeout

* Add prepare script (#34)

* add a missing typescript verification (#36)

* Removed the guides link

* Correct doc link (#36)

* Fix typo in LDClient.on jsdoc (#37)

* add inlineUsersInEvents option in TypeScript (#37)

* Filter private attributes on debug event users. Send variation for debug events.

* update uuid package version (#39)

* use Releaser v2 config + newer CI image

* First half, add the type, create the new options, add the new util method, and add tests

* Second half, call the tranform util method before calling any HTTP requests

* Update the transform to work on a copy of headers instead of mutating it

* add comments about removing custom event warning logic in the future

* revert updating of UUID dependency (#43)

* Revert "update uuid package version (#39)"

This reverts commit 3b2ff6c.

* update package-lock.json

* better error handling for local storage operations (#44)

* better error handling for local storage operations

* lint

* fix obsolete comments

* add basic logger similar to server-side Node SDK (#45)

* fix exports and add validation of custom logger (#46)

* remove typedoc.js file that interferes with Releaser's docs build

* update typescript version

* add maintenance branch

* backport sc-142333 fix

Co-authored-by: Eli Bishop <[email protected]>
Co-authored-by: Zach Davis <[email protected]>
Co-authored-by: LaunchDarklyCI <[email protected]>
Co-authored-by: Ben Woskow <[email protected]>
Co-authored-by: Ben Woskow <[email protected]>
Co-authored-by: Michael Siadak <[email protected]>
Co-authored-by: Jeff Wen <[email protected]>
Co-authored-by: Andrey Krasnov <[email protected]>
Co-authored-by: Gavin Whelan <[email protected]>
Co-authored-by: LaunchDarklyReleaseBot <[email protected]>
Co-authored-by: Louis Chan <[email protected]>
Co-authored-by: Louis Chan <[email protected]>

* Releasing version 3.5.1

* rm obsolete file to fix merge

* Releasing version 3.5.1

* Migrate context code (#56)

* Migrate attribute reference code from node. (#57)

* Add U2C types and make minimal adjustments for type changes. (#58)

* Add U2C types.

* Update typings.d.ts. Make minimal adjustments for changes to typings.

* make URL path concatenation work right whether base URL has a trailing slash or not (#61)

* make URL path concatenation work right whether base URL has a trailing slash or not

* lint

* Update event format and filtering for contexts. (#59)

* Update persistence of generated keys for transient contexts. (#60)

* Implement support for application tags. (#55)

* Fix typing of LDOptionsBase. (#63)

* Implement application tags for 3.x. (#62)

* lint

* Add a line to refer to sendEventsOnlyForVariation

* Rename additional items. Functions, comments, variables. (#64)

* don't include deleted flags in allFlags (#66)

* Clear last seen cache on identity change. (#67)

* Enforce 64 character limit for tag value. (#68)

* Enforce 64 character limit for tag value.

* Lint. Comments. Remove unused param.

* Rename transient back to anonymous. (#70)

* [sc-160947] Switch to partial URL encoding. (#72)

* Remove the last seen cache, deprecate allowFrequentDuplicateEvents. (#73)

* Update with changes from main, remove frequent duplicate events option. (#75)

* Inspector proposal V2. (#71)

* Fix invoking flagUsed. (#77)

* Port jitter and backoff. (#79) (#81)

* Update U2C branch with inspection interfaces. (#80)

Co-authored-by: Eli Bishop <[email protected]>
Co-authored-by: Zach Davis <[email protected]>
Co-authored-by: LaunchDarklyCI <[email protected]>
Co-authored-by: Ben Woskow <[email protected]>
Co-authored-by: Ben Woskow <[email protected]>
Co-authored-by: Michael Siadak <[email protected]>
Co-authored-by: Jeff Wen <[email protected]>
Co-authored-by: Andrey Krasnov <[email protected]>
Co-authored-by: Gavin Whelan <[email protected]>
Co-authored-by: LaunchDarklyReleaseBot <[email protected]>
Co-authored-by: Louis Chan <[email protected]>
Co-authored-by: Louis Chan <[email protected]>
Co-authored-by: Ryan Lamb <[email protected]>
Co-authored-by: LaunchDarklyReleaseBot <[email protected]>

* Merge jitter/backoff to 5.0. (#85)

* Merge: Remove flatmap (#84)

Co-authored-by: Mateusz Sikora <[email protected]>

* remove flatMap usage to support older browsers (#82)

Co-authored-by: Mateusz Sikora <[email protected]>

* Remove support for secondary attribute. (#86)

* [sc-176610] Import messages specifically from './messages' not '.'. (#87)

* Update with changes from main. (#88)

* Update comments for U2C. (#89)

* Fixes from contract tests. (#90)

* Remove deprecation code.

* [sc-177798] Export getContextKeys function for reuse

* Added unit tests

* Moved getContextKeys to context.js

* Update EventProcessor.js

* Ignore null and empty string keys. Added more tests.

* Added warnings if kind is null or ''

* Added types for getContextKeys

* Update test-types.ts

* Port event summarizer from node. (#97)

* Fix handling of results from sendingEvents. (#98)

* [sc-178144] Undefined case versus typeof. (#99)

* Fix copy/paste doc comment. (#96)

* [sc-178313] Replace minor instances of user

* More replacements.

* Update InspectorManager-test.js

* Update utils-test.js

* Adding kind to context for tests

* Revert to create maintenance branch. (#103)

* Restore U2C functionality. (#104)

* Update release config for 5.x (#102)

Co-authored-by: Eli Bishop <[email protected]>
Co-authored-by: LaunchDarklyCI <[email protected]>
Co-authored-by: Ben Woskow <[email protected]>
Co-authored-by: Ben Woskow <[email protected]>
Co-authored-by: Michael Siadak <[email protected]>
Co-authored-by: Jeff Wen <[email protected]>
Co-authored-by: Andrey Krasnov <[email protected]>
Co-authored-by: Gavin Whelan <[email protected]>
Co-authored-by: LaunchDarklyReleaseBot <[email protected]>
Co-authored-by: Louis Chan <[email protected]>
Co-authored-by: Louis Chan <[email protected]>
Co-authored-by: Zach Davis <[email protected]>
Co-authored-by: Ryan Lamb <[email protected]>
Co-authored-by: Mateusz Sikora <[email protected]>
Co-authored-by: Yusinto Ngadiman <[email protected]>
Co-authored-by: Yusinto Ngadiman <[email protected]>
  • Loading branch information
17 people authored Nov 30, 2022
1 parent b6bb30b commit b746d19
Show file tree
Hide file tree
Showing 43 changed files with 2,348 additions and 972 deletions.
3 changes: 2 additions & 1 deletion .ldrelease/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ repo:

branches:
- name: main
description: 4.x
description: 5.x
- name: 4.x
- name: 3.x

publications:
Expand Down
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
"scripts": {
"lint": "eslint --format 'node_modules/eslint-formatter-pretty' --ignore-path .eslintignore",
"lint:all": "eslint --format 'node_modules/eslint-formatter-pretty' --ignore-path .eslintignore src",
"lint-fix:all": "eslint --fix --format 'node_modules/eslint-formatter-pretty' --ignore-path .eslintignore src",
"format": "npm run format:md && npm run format:js",
"format:md": "prettier --parser markdown --ignore-path .prettierignore --write '*.md'",
"format:js": "prettier --ignore-path .prettierignore --write 'src/**/*.js'",
Expand All @@ -26,6 +27,7 @@
"@babel/preset-env": "^7.6.3",
"@babel/runtime": "7.6.3",
"@rollup/plugin-replace": "^2.2.0",
"@types/jest": "^27.4.1",
"babel-eslint": "^10.1.0",
"babel-jest": "^25.1.0",
"cross-env": "^5.1.4",
Expand Down
95 changes: 95 additions & 0 deletions src/AnonymousContextProcessor.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
const { v1: uuidv1 } = require('uuid');
const { getContextKinds } = require('./context');

const errors = require('./errors');
const messages = require('./messages');
const utils = require('./utils');

const ldUserIdKey = 'ld:$anonUserId';

/**
* Create an object which can process a context and populate any required keys
* for anonymous objects.
*
* @param {Object} persistentStorage The persistent storage from which to store
* and access persisted anonymous context keys.
* @returns An AnonymousContextProcessor.
*/
function AnonymousContextProcessor(persistentStorage) {
function getContextKeyIdString(kind) {
if (kind === undefined || kind === null || kind === 'user') {
return ldUserIdKey;
}
return `ld:$contextKey:${kind}`;
}

function getCachedContextKey(kind) {
return persistentStorage.get(getContextKeyIdString(kind));
}

function setCachedContextKey(id, kind) {
return persistentStorage.set(getContextKeyIdString(kind), id);
}

/**
* Process a single kind context, or a single context within a multi-kind context.
* @param {string} kind The kind of the context. Independent because the kind is not prevent
* within a context in a multi-kind context.
* @param {Object} context
* @returns {Promise} a promise that resolves to a processed contexts, or rejects
* a context which cannot be processed.
*/
function processSingleKindContext(kind, context) {
// We are working on a copy of an original context, so we want to re-assign
// versus duplicating it again.

/* eslint-disable no-param-reassign */
if (context.key !== null && context.key !== undefined) {
context.key = context.key.toString();
return Promise.resolve(context);
}

if (context.anonymous) {
// If the key doesn't exist, then the persistent storage will resolve
// with undefined.
return getCachedContextKey(kind).then(cachedId => {
if (cachedId) {
context.key = cachedId;
return context;
} else {
const id = uuidv1();
context.key = id;
return setCachedContextKey(id, kind).then(() => context);
}
});
} else {
return Promise.reject(new errors.LDInvalidUserError(messages.invalidContext()));
}
/* eslint-enable no-param-reassign */
}

/**
* Process the context, returning a Promise that resolves to the processed context, or rejects if there is an error.
* @param {Object} context
* @returns {Promise} A promise which resolves to a processed context, or a rejection if the context cannot be
* processed. The context should still be checked for overall validity after being processed.
*/
this.processContext = context => {
if (!context) {
return Promise.reject(new errors.LDInvalidUserError(messages.contextNotSpecified()));
}

const processedContext = utils.clone(context);

if (context.kind === 'multi') {
const kinds = getContextKinds(processedContext);

return Promise.all(kinds.map(kind => processSingleKindContext(kind, processedContext[kind]))).then(
() => processedContext
);
}
return processSingleKindContext(context.kind, processedContext);
};
}

module.exports = AnonymousContextProcessor;
137 changes: 137 additions & 0 deletions src/ContextFilter.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
const AttributeReference = require('./attributeReference');

function ContextFilter(config) {
const filter = {};

const allAttributesPrivate = config.allAttributesPrivate;
const privateAttributes = config.privateAttributes || [];

// These attributes cannot be removed via a private attribute.
const protectedAttributes = ['key', 'kind', '_meta', 'anonymous'];

const legacyTopLevelCopyAttributes = ['name', 'ip', 'firstName', 'lastName', 'email', 'avatar', 'country'];

/**
* For the given context and configuration get a list of attributes to filter.
* @param {Object} context
* @returns {string[]} A list of the attributes to filter.
*/
const getAttributesToFilter = context =>
(allAttributesPrivate
? Object.keys(context)
: [...privateAttributes, ...((context._meta && context._meta.privateAttributes) || [])]
).filter(attr => !protectedAttributes.some(protectedAttr => AttributeReference.compare(attr, protectedAttr)));

/**
* @param {Object} context
* @returns {Object} A copy of the context with private attributes removed,
* and the redactedAttributes meta populated.
*/
const filterSingleKind = context => {
if (typeof context !== 'object' || context === null || Array.isArray(context)) {
return undefined;
}

const { cloned, excluded } = AttributeReference.cloneExcluding(context, getAttributesToFilter(context));
cloned.key = String(cloned.key);
if (excluded.length) {
if (!cloned._meta) {
cloned._meta = {};
}
cloned._meta.redactedAttributes = excluded;
}
if (cloned._meta) {
delete cloned._meta['privateAttributes'];
if (Object.keys(cloned._meta).length === 0) {
delete cloned._meta;
}
}
// Make sure anonymous is boolean if present.
// Null counts as present, and would be falsy, which is the default.
if (cloned.anonymous !== undefined) {
cloned.anonymous = !!cloned.anonymous;
}

return cloned;
};

/**
* @param {Object} context
* @returns {Object} A copy of the context with the private attributes removed,
* and the redactedAttributes meta populated for each sub-context.
*/
const filterMultiKind = context => {
const filtered = {
kind: context.kind,
};
const contextKeys = Object.keys(context);

for (const contextKey of contextKeys) {
if (contextKey !== 'kind') {
const filteredContext = filterSingleKind(context[contextKey]);
if (filteredContext) {
filtered[contextKey] = filteredContext;
}
}
}
return filtered;
};

/**
* Convert the LDUser object into an LDContext object.
* @param {Object} user The LDUser to produce an LDContext for.
* @returns {Object} A single kind context based on the provided user.
*/
const legacyToSingleKind = user => {
const filtered = {
/* Destructure custom items into the top level.
Duplicate keys will be overridden by previously
top level items.
*/
...(user.custom || {}),

// Implicity a user kind.
kind: 'user',

key: user.key,
};

if (user.anonymous !== undefined) {
filtered.anonymous = !!user.anonymous;
}

// Copy top level keys and convert them to strings.
// Remove keys that may have been destructured from `custom`.
for (const key of legacyTopLevelCopyAttributes) {
delete filtered[key];
if (user[key] !== undefined && user[key] !== null) {
filtered[key] = String(user[key]);
}
}

if (user.privateAttributeNames !== undefined && user.privateAttributeNames !== null) {
filtered._meta = filtered._meta || {};
// If any private attributes started with '/' we need to convert them to references, otherwise the '/' will
// cause the literal to incorrectly be treated as a reference.
filtered._meta.privateAttributes = user.privateAttributeNames.map(
literal => (literal.startsWith('/') ? AttributeReference.literalToReference(literal) : literal)
);
}

return filtered;
};

filter.filter = context => {
if (context.kind === undefined || context.kind === null) {
return filterSingleKind(legacyToSingleKind(context));
} else if (context.kind === 'multi') {
return filterMultiKind(context);
} else {
return filterSingleKind(context);
}
};

return filter;
}

module.exports = ContextFilter;
29 changes: 15 additions & 14 deletions src/EventProcessor.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
const EventSender = require('./EventSender');
const EventSummarizer = require('./EventSummarizer');
const UserFilter = require('./UserFilter');
const ContextFilter = require('./ContextFilter');
const errors = require('./errors');
const messages = require('./messages');
const utils = require('./utils');
const { getContextKeys } = require('./context');

function EventProcessor(
platform,
Expand All @@ -17,8 +18,7 @@ function EventProcessor(
const eventSender = sender || EventSender(platform, environmentId, options);
const mainEventsUrl = utils.appendUrlPath(options.eventsUrl, '/events/bulk/' + environmentId);
const summarizer = EventSummarizer();
const userFilter = UserFilter(options);
const inlineUsers = options.inlineUsersInEvents;
const contextFilter = ContextFilter(options);
const samplingInterval = options.samplingInterval;
const eventCapacity = options.eventCapacity;
const flushInterval = options.flushInterval;
Expand Down Expand Up @@ -47,16 +47,12 @@ function EventProcessor(
// Transform an event from its internal format to the format we use when sending a payload.
function makeOutputEvent(e) {
const ret = utils.extend({}, e);
if (e.kind === 'alias') {
// alias events do not require any transformation
return ret;
}
if (inlineUsers || e.kind === 'identify') {
// identify events always have an inline user
ret.user = userFilter.filterUser(e.user);
if (e.kind === 'identify') {
// identify events always have an inline context
ret.context = contextFilter.filter(e.context);
} else {
ret.userKey = e.user.key;
delete ret['user'];
ret.contextKeys = getContextKeysFromEvent(e);
delete ret['context'];
}
if (e.kind === 'feature') {
delete ret['trackEvents'];
Expand All @@ -65,6 +61,10 @@ function EventProcessor(
return ret;
}

function getContextKeysFromEvent(event) {
return getContextKeys(event.context, logger);
}

function addToOutbox(event) {
if (queue.length < eventCapacity) {
queue.push(event);
Expand Down Expand Up @@ -107,7 +107,7 @@ function EventProcessor(
}
if (addDebugEvent) {
const debugEvent = utils.extend({}, event, { kind: 'debug' });
debugEvent.user = userFilter.filterUser(debugEvent.user);
debugEvent.context = contextFilter.filter(debugEvent.context);
delete debugEvent['trackEvents'];
delete debugEvent['debugEventsUntilDate'];
addToOutbox(debugEvent);
Expand Down Expand Up @@ -136,7 +136,8 @@ function EventProcessor(
}
queue = [];
logger.debug(messages.debugPostingEvents(eventsToSend.length));
return eventSender.sendEvents(eventsToSend, mainEventsUrl).then(responseInfo => {
return eventSender.sendEvents(eventsToSend, mainEventsUrl).then(responses => {
const responseInfo = responses && responses[0];
if (responseInfo) {
if (responseInfo.serverTime) {
lastKnownPastTime = responseInfo.serverTime;
Expand Down
4 changes: 2 additions & 2 deletions src/EventSender.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ function EventSender(platform, environmentId, options) {
const headers = isDiagnostic
? baseHeaders
: utils.extend({}, baseHeaders, {
'X-LaunchDarkly-Event-Schema': '3',
'X-LaunchDarkly-Event-Schema': '4',
'X-LaunchDarkly-Payload-ID': payloadId,
});
return platform
Expand Down Expand Up @@ -73,7 +73,7 @@ function EventSender(platform, environmentId, options) {
// no need to break up events into chunks if we can send a POST
chunks = [events];
} else {
chunks = utils.chunkUserEventsForUrl(MAX_URL_LENGTH - url.length, events);
chunks = utils.chunkEventsForUrl(MAX_URL_LENGTH - url.length, events);
}
const results = [];
for (let i = 0; i < chunks.length; i++) {
Expand Down
Loading

0 comments on commit b746d19

Please sign in to comment.