New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

@fluidframework/id-compressor

Package Overview
Dependencies
Maintainers
1
Versions
136
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@fluidframework/id-compressor - npm Package Compare versions

Comparing version 2.13.0 to 2.20.0

4

CHANGELOG.md
# @fluidframework/id-compressor
## 2.20.0
Dependency updates only.
## 2.13.0

@@ -4,0 +8,0 @@

53

dist/appendOnlySortedMap.d.ts

@@ -17,2 +17,3 @@ /*!

/**
* Gets the size of the map.
* @returns the number of entries in this map

@@ -22,2 +23,3 @@ */

/**
* Gets the min key in the map.
* @returns the min key in the map.

@@ -27,2 +29,3 @@ */

/**
* Gets the max key in the map.
* @returns the max key in the map.

@@ -32,2 +35,3 @@ */

/**
* Gets the min value in the map.
* @returns the min value in the map.

@@ -37,18 +41,24 @@ */

/**
* @returns the min value in the map.
* Gets the max value in the map.
* @returns the max value in the map.
*/
maxValue(): V | undefined;
/**
* @returns the min key in the map.
* Gets the first key/value pair in the map.
* @returns the first pair if it exists, or undefined otherwise.
*/
first(): [K, V] | undefined;
/**
* @returns the max key in the map.
* Gets the last key/value pair in the map.
* @returns the last pair if it exists, or undefined otherwise.
*/
last(): [K, V] | undefined;
/**
* Returns the element at the insertion index.
* Gets the entry at the specified index.
* @param index - the entry index
* @returns the key/value pair if it exists, or undefined otherwise.
*/
getAtIndex(index: number): [K, V] | undefined;
/**
* Gets the entries in the map.
* @returns an iterable of the entries in the map.

@@ -58,2 +68,3 @@ */

/**
* Gets the keys in the map.
* @returns an iterable of the keys in the map.

@@ -63,2 +74,3 @@ */

/**
* Gets the values in the map.
* @returns an iterable of the values in the map.

@@ -68,2 +80,3 @@ */

/**
* Gets the entries in the map, reversed.
* @returns an iterable of the entries in the map, reversed.

@@ -73,26 +86,28 @@ */

/**
* Adds a new key/value pair to the map. `key` must be > to all keys in the map.
* @param key - the key to add.
* @param value - the value to add.
* Appends a new key/value pair at the end of the map. `key` must be greater than all other keys in the map.
* @param key - the key to add
* @param value - the value to add
*/
append(key: K, value: V): void;
/**
* Replaces the last key/value pair with the given one. If the map is empty, it simply appends.
* `key` must be > to all keys in the map prior to the one replaced.
* @param key - the key to add.
* @param value - the value to add.
* Replaces the last key/value pair with a new one. If the map is empty, the new pair is appended.
* 'key' must be greater than all other keys in the map.
* @param key - the key to set
* @param value - the value to set
*/
replaceLast(key: K, value: V): void;
/**
* @param key - the key to lookup.
* @returns the value associated with `key` if such an entry exists, and undefined otherwise.
* Gets the value associated with a given key.
* @param key - the key to lookup
* @returns the value if it exists, or undefined otherwise.
*/
get(key: K): V | undefined;
/**
* @param key - the key to lookup.
* @returns the entry associated with `key` if such an entry exists, the entry associated with the next lower key if such an entry
* exists, and undefined otherwise.
* Gets the pair associated with the given key or the next smaller key.
* @param key - the key to lookup
* @returns the pair if it exists, or undefined otherwise.
*/
getPairOrNextLower(key: K): readonly [K, V] | undefined;
/**
* Gets the pair associated with the given key or the next higher key.
* @param key - the key to lookup.

@@ -120,2 +135,8 @@ * @returns the entry associated with `key` if such an entry exists, the entry associated with the next higher key if such an entry

private getKeyIndexOfOrNextLower;
/**
* Gets the pair associated with the given key or next higher key.
* @param search - the search value
* @param comparator - a comparison function
* @returns the pair if it exists, or undefined otherwise.
*/
protected getPairOrNextHigherBy<T>(search: T, comparator: (search: T, key: K, value: V) => number): readonly [K, V] | undefined;

@@ -122,0 +143,0 @@ private getKeyIndexOfOrNextHigher;

@@ -8,3 +8,2 @@ "use strict";

exports.AppendOnlySortedMap = void 0;
/* eslint-disable tsdoc/syntax */
/* eslint-disable no-bitwise */

@@ -25,2 +24,3 @@ const internal_1 = require("@fluidframework/core-utils/internal");

/**
* Gets the size of the map.
* @returns the number of entries in this map

@@ -32,2 +32,3 @@ */

/**
* Gets the min key in the map.
* @returns the min key in the map.

@@ -39,2 +40,3 @@ */

/**
* Gets the max key in the map.
* @returns the max key in the map.

@@ -46,2 +48,3 @@ */

/**
* Gets the min value in the map.
* @returns the min value in the map.

@@ -53,3 +56,4 @@ */

/**
* @returns the min value in the map.
* Gets the max value in the map.
* @returns the max value in the map.
*/

@@ -60,3 +64,4 @@ maxValue() {

/**
* @returns the min key in the map.
* Gets the first key/value pair in the map.
* @returns the first pair if it exists, or undefined otherwise.
*/

@@ -72,3 +77,4 @@ first() {

/**
* @returns the max key in the map.
* Gets the last key/value pair in the map.
* @returns the last pair if it exists, or undefined otherwise.
*/

@@ -85,3 +91,5 @@ last() {

/**
* Returns the element at the insertion index.
* Gets the entry at the specified index.
* @param index - the entry index
* @returns the key/value pair if it exists, or undefined otherwise.
*/

@@ -97,2 +105,3 @@ getAtIndex(index) {

/**
* Gets the entries in the map.
* @returns an iterable of the entries in the map.

@@ -107,2 +116,3 @@ */

/**
* Gets the keys in the map.
* @returns an iterable of the keys in the map.

@@ -117,2 +127,3 @@ */

/**
* Gets the values in the map.
* @returns an iterable of the values in the map.

@@ -127,2 +138,3 @@ */

/**
* Gets the entries in the map, reversed.
* @returns an iterable of the entries in the map, reversed.

@@ -137,5 +149,5 @@ */

/**
* Adds a new key/value pair to the map. `key` must be > to all keys in the map.
* @param key - the key to add.
* @param value - the value to add.
* Appends a new key/value pair at the end of the map. `key` must be greater than all other keys in the map.
* @param key - the key to add
* @param value - the value to add
*/

@@ -148,10 +160,9 @@ append(key, value) {

}
elements.push(key);
elements.push(value);
elements.push(key, value);
}
/**
* Replaces the last key/value pair with the given one. If the map is empty, it simply appends.
* `key` must be > to all keys in the map prior to the one replaced.
* @param key - the key to add.
* @param value - the value to add.
* Replaces the last key/value pair with a new one. If the map is empty, the new pair is appended.
* 'key' must be greater than all other keys in the map.
* @param key - the key to set
* @param value - the value to set
*/

@@ -168,8 +179,8 @@ replaceLast(key, value) {

}
elements.push(key);
elements.push(value);
elements.push(key, value);
}
/**
* @param key - the key to lookup.
* @returns the value associated with `key` if such an entry exists, and undefined otherwise.
* Gets the value associated with a given key.
* @param key - the key to lookup
* @returns the value if it exists, or undefined otherwise.
*/

@@ -184,5 +195,5 @@ get(key) {

/**
* @param key - the key to lookup.
* @returns the entry associated with `key` if such an entry exists, the entry associated with the next lower key if such an entry
* exists, and undefined otherwise.
* Gets the pair associated with the given key or the next smaller key.
* @param key - the key to lookup
* @returns the pair if it exists, or undefined otherwise.
*/

@@ -193,2 +204,3 @@ getPairOrNextLower(key) {

/**
* Gets the pair associated with the given key or the next higher key.
* @param key - the key to lookup.

@@ -278,2 +290,8 @@ * @returns the entry associated with `key` if such an entry exists, the entry associated with the next higher key if such an entry

}
/**
* Gets the pair associated with the given key or next higher key.
* @param search - the search value
* @param comparator - a comparison function
* @returns the pair if it exists, or undefined otherwise.
*/
getPairOrNextHigherBy(search, comparator) {

@@ -280,0 +298,0 @@ const keyIndex = this.getKeyIndexOfOrNextHigher(search, comparator);

@@ -18,3 +18,3 @@ /*!

/**
* @returns the upper bound (exclusive) of finalized IDs in final space, i.e. one greater than the last final ID in the last cluster.
* Gets the upper bound (exclusive) of finalized IDs in final space, i.e. one greater than the last final ID in the last cluster.
* Note: this does not include allocated but unfinalized space in clusters.

@@ -24,3 +24,3 @@ */

/**
* @returns the upper bound (exclusive) of allocated IDs in final space, i.e. one greater than the last final ID in the last cluster.
* Gets the upper bound (exclusive) of allocated IDs in final space, i.e. one greater than the last final ID in the last cluster.
* Note: this does includes all allocated IDs in clusters.

@@ -27,0 +27,0 @@ */

@@ -32,3 +32,3 @@ "use strict";

/**
* @returns the upper bound (exclusive) of finalized IDs in final space, i.e. one greater than the last final ID in the last cluster.
* Gets the upper bound (exclusive) of finalized IDs in final space, i.e. one greater than the last final ID in the last cluster.
* Note: this does not include allocated but unfinalized space in clusters.

@@ -43,3 +43,3 @@ */

/**
* @returns the upper bound (exclusive) of allocated IDs in final space, i.e. one greater than the last final ID in the last cluster.
* Gets the upper bound (exclusive) of allocated IDs in final space, i.e. one greater than the last final ID in the last cluster.
* Note: this does includes all allocated IDs in clusters.

@@ -54,4 +54,5 @@ */

equals(other) {
for (const [index, value] of Object.entries(this.clusterList)) {
if (!(0, sessions_js_1.clustersEqual)(value, other.clusterList[index])) {
for (let i = 0; i < this.clusterList.length; i++) {
const cluster = this.clusterList[i];
if (!(0, sessions_js_1.clustersEqual)(cluster, other.clusterList[i])) {
return false;

@@ -58,0 +59,0 @@ }

@@ -21,3 +21,3 @@ "use strict";

*/
const currentWrittenVersion = 2.0;
const currentWrittenVersion = 2;
function rangeFinalizationError(expectedStart, actualStart) {

@@ -420,3 +420,3 @@ return new internal_2.LoggingError("Ranges finalized out of order", {

(0, internal_1.assert)(!this.ongoingGhostSession, 0x8a9 /* IdCompressor should not be operated normally when in a ghost session */);
const { normalizer, finalSpace, sessions } = this;
const { normalizer, finalSpace, sessions, localGenCount, logger, nextRangeBaseGenCount } = this;
const sessionIndexMap = new Map();

@@ -435,3 +435,3 @@ let sessionIndex = 0;

1 + // count of normalizer pairs
this.normalizer.idRanges.size * 2 // pairs
normalizer.idRanges.size * 2 // pairs
: 0;

@@ -456,10 +456,10 @@ // Layout size, in 8 byte increments

}
finalSpace.clusters.forEach((cluster) => {
for (const cluster of finalSpace.clusters) {
index = (0, persistanceUtilities_js_1.writeNumber)(serializedFloat, index, sessionIndexMap.get(cluster.session));
index = (0, persistanceUtilities_js_1.writeNumber)(serializedFloat, index, cluster.capacity);
index = (0, persistanceUtilities_js_1.writeNumber)(serializedFloat, index, cluster.count);
});
}
if (hasLocalState) {
index = (0, persistanceUtilities_js_1.writeNumber)(serializedFloat, index, this.localGenCount);
index = (0, persistanceUtilities_js_1.writeNumber)(serializedFloat, index, this.nextRangeBaseGenCount);
index = (0, persistanceUtilities_js_1.writeNumber)(serializedFloat, index, localGenCount);
index = (0, persistanceUtilities_js_1.writeNumber)(serializedFloat, index, nextRangeBaseGenCount);
index = (0, persistanceUtilities_js_1.writeNumber)(serializedFloat, index, normalizer.idRanges.size);

@@ -472,3 +472,3 @@ for (const [leadingGenCount, count] of normalizer.idRanges.entries()) {

(0, internal_1.assert)(index === totalSize, 0x75b /* Serialized size was incorrectly calculated. */);
this.logger?.sendTelemetryEvent({
logger?.sendTelemetryEvent({
eventName: "RuntimeIdCompressor:SerializedIdCompressorSize",

@@ -498,8 +498,11 @@ size: serializedFloat.byteLength,

switch (version) {
case 1.0:
case 1: {
throw new Error("IdCompressor version 1.0 is no longer supported.");
case 2.0:
}
case 2: {
return IdCompressor.deserialize2_0(index, sessionId, logger);
default:
}
default: {
throw new Error("Unknown IdCompressor serialized version.");
}
}

@@ -514,3 +517,6 @@ }

const sessions = [];
if (!hasLocalState) {
if (hasLocalState) {
(0, internal_1.assert)(sessionId === undefined, 0x75e /* Local state should not exist in serialized form. */);
}
else {
// If !hasLocalState, there won't be a serialized local session ID so insert one at the beginning

@@ -522,5 +528,2 @@ (0, internal_1.assert)(sessionId !== undefined, 0x75d /* Local session ID is undefined. */);

}
else {
(0, internal_1.assert)(sessionId === undefined, 0x75e /* Local state should not exist in serialized form. */);
}
for (let i = 0; i < sessionCount; i++) {

@@ -527,0 +530,0 @@ const numeric = (0, persistanceUtilities_js_1.readNumericUuid)(index);

@@ -23,3 +23,3 @@ /*!

/**
* @returns true if the supplied ID is a final ID.
* Returns true if the supplied ID is a final ID.
*/

@@ -26,0 +26,0 @@ export declare function isFinalId(id: SessionSpaceCompressedId | OpSpaceCompressedId): id is FinalCompressedId;

@@ -9,3 +9,3 @@ "use strict";

/**
* @returns true if the supplied ID is a final ID.
* Returns true if the supplied ID is a final ID.
*/

@@ -12,0 +12,0 @@ function isFinalId(id) {

{
"type": "commonjs"
"type": "commonjs",
"sideEffects": false
}

@@ -8,3 +8,3 @@ /*!

export declare const pkgName = "@fluidframework/id-compressor";
export declare const pkgVersion = "2.13.0";
export declare const pkgVersion = "2.20.0";
//# sourceMappingURL=packageVersion.d.ts.map

@@ -11,3 +11,3 @@ "use strict";

exports.pkgName = "@fluidframework/id-compressor";
exports.pkgVersion = "2.13.0";
exports.pkgVersion = "2.20.0";
//# sourceMappingURL=packageVersion.js.map

@@ -16,3 +16,5 @@ /*!

}
/** Identifies a compressor in a network */
/**
* Identifies a compressor in a network
*/
export declare enum Client {

@@ -23,7 +25,11 @@ Client1 = "Client1",

}
/** Identifies categories of compressors */
/**
* Identifies categories of compressors
*/
export declare enum MetaClient {
All = "All"
}
/** Identifies a compressor inside the network but outside the three specially tracked clients. */
/**
* Identifies a compressor inside the network but outside the three specially tracked clients.
*/
export declare enum OutsideClient {

@@ -43,3 +49,5 @@ Remote = "Remote"

};
/** Identifies a compressor to which to send an operation */
/**
* Identifies a compressor to which to send an operation
*/
export type DestinationClient = Client | MetaClient;

@@ -75,3 +83,5 @@ export declare const DestinationClient: {

export declare const sessionIds: ClientMap<SessionId>;
/** Information about a generated ID in a network to be validated by tests */
/**
* Information about a generated ID in a network to be validated by tests
*/
export interface TestIdData {

@@ -89,11 +99,21 @@ readonly id: SessionSpaceCompressedId;

readonly initialClusterSize: number;
/** The compressors used in this network */
/**
* The compressors used in this network
*/
private readonly compressors;
/** The log of operations seen by the server so far. Append-only. */
/**
* The log of operations seen by the server so far. Append-only.
*/
private readonly serverOperations;
/** An index into `serverOperations` for each client which represents how many operations have been delivered to that client */
/**
* An index into `serverOperations` for each client which represents how many operations have been delivered to that client
*/
private readonly clientProgress;
/** All ids (local and sequenced) that a client has created or received, in order. */
/**
* All ids (local and sequenced) that a client has created or received, in order.
*/
private readonly idLogs;
/** All ids that a client has received from the server, in order. */
/**
* All ids that a client has received from the server, in order.
*/
private readonly sequencedIdLogs;

@@ -217,7 +237,13 @@ constructor(initialClusterSize?: number);

export interface OperationGenerationConfig {
/** maximum cluster size of the network. Default: 25 */
/**
* maximum cluster size of the network. Default: 25
*/
maxClusterSize?: number;
/** Number of ops between validation ops. Default: 200 */
/**
* Number of ops between validation ops. Default: 200
*/
validateInterval?: number;
/** Fraction of ID allocations that are from an outside client (not Client1/2/3). */
/**
* Fraction of ID allocations that are from an outside client (not Client1/2/3).
*/
outsideAllocationFraction?: number;

@@ -224,0 +250,0 @@ }

@@ -8,3 +8,4 @@ "use strict";

exports.createAlwaysFinalizedIdCompressor = exports.generateCompressedIds = exports.performFuzzActions = exports.makeOpGenerator = exports.mergeArrayMaps = exports.expectSerializes = exports.roundtrip = exports.IdCompressorTestNetwork = exports.sessionIds = exports.buildHugeCompressor = exports.CompressorFactory = exports.DestinationClient = exports.OriginatingClient = exports.OutsideClient = exports.MetaClient = exports.Client = void 0;
const assert_1 = require("assert");
// eslint-disable-next-line import/no-nodejs-modules
const node_assert_1 = require("node:assert");
const stochastic_test_utils_1 = require("@fluid-private/stochastic-test-utils");

@@ -16,3 +17,5 @@ const idCompressor_js_1 = require("../idCompressor.js");

const testCommon_js_1 = require("./testCommon.js");
/** Identifies a compressor in a network */
/**
* Identifies a compressor in a network
*/
var Client;

@@ -24,3 +27,5 @@ (function (Client) {

})(Client || (exports.Client = Client = {}));
/** Identifies categories of compressors */
/**
* Identifies categories of compressors
*/
var MetaClient;

@@ -30,3 +35,5 @@ (function (MetaClient) {

})(MetaClient || (exports.MetaClient = MetaClient = {}));
/** Identifies a compressor inside the network but outside the three specially tracked clients. */
/**
* Identifies a compressor inside the network but outside the three specially tracked clients.
*/
var OutsideClient;

@@ -110,3 +117,5 @@ (function (OutsideClient) {

this.initialClusterSize = initialClusterSize;
/** The log of operations seen by the server so far. Append-only. */
/**
* The log of operations seen by the server so far. Append-only.
*/
this.serverOperations = [];

@@ -217,3 +226,3 @@ const compressors = new Map();

allocateAndSendIdsFromRemoteClient(clientFrom, sessionIdFrom, numIds) {
(0, assert_1.strict)(numIds > 0, "Must allocate a non-zero number of IDs");
(0, node_assert_1.strict)(numIds > 0, "Must allocate a non-zero number of IDs");
if (clientFrom === exports.OriginatingClient.Remote) {

@@ -225,2 +234,3 @@ const range = {

count: numIds,
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
requestedClusterSize: this.getCompressor(Client.Client1)[

@@ -240,3 +250,3 @@ // eslint-disable-next-line @typescript-eslint/dot-notation

else {
(0, assert_1.strict)(sessionIdFrom === exports.sessionIds.get(clientFrom));
(0, node_assert_1.strict)(sessionIdFrom === exports.sessionIds.get(clientFrom));
const compressor = this.compressors.get(clientFrom);

@@ -259,3 +269,3 @@ const sessionSpaceIds = generateCompressedIds(compressor, numIds);

if (clientTakingDelivery === exports.DestinationClient.All) {
(0, assert_1.strict)(opsToDeliver === undefined);
(0, node_assert_1.strict)(opsToDeliver === undefined);
opIndexBound = this.serverOperations.length;

@@ -265,5 +275,5 @@ }

opIndexBound =
opsToDeliver !== undefined
? this.clientProgress.get(clientTakingDelivery) + opsToDeliver
: this.serverOperations.length;
opsToDeliver === undefined
? this.serverOperations.length
: this.clientProgress.get(clientTakingDelivery) + opsToDeliver;
}

@@ -307,3 +317,3 @@ for (const [clientTo, compressorTo] of this.getTargetCompressors(clientTakingDelivery)) {

if (opSpaceIds) {
assert_1.strict.strictEqual(opSpaceIds[g - firstGenCount], local);
node_assert_1.strict.strictEqual(opSpaceIds[g - firstGenCount], local);
}

@@ -317,17 +327,17 @@ localIdsInCreationRange.add(local);

// Ensure creation ranges for clients we track contain the correct local ID ranges
this.serverOperations.forEach(([range, opSpaceIds, clientFrom]) => {
for (const [range, opSpaceIds, clientFrom] of this.serverOperations) {
if (clientFrom !== exports.OriginatingClient.Remote) {
const localIdsInCreationRange = getLocalIdsInRange(range, opSpaceIds);
let localCount = 0;
opSpaceIds.forEach((id) => {
for (const id of opSpaceIds) {
if ((0, testCommon_js_1.isLocalId)(id)) {
localCount++;
(0, assert_1.strict)(localIdsInCreationRange.has(id), "Local ID not in creation range");
(0, node_assert_1.strict)(localIdsInCreationRange.has(id), "Local ID not in creation range");
}
});
assert_1.strict.strictEqual(localCount, localIdsInCreationRange.size, "Local ID count mismatch");
}
node_assert_1.strict.strictEqual(localCount, localIdsInCreationRange.size, "Local ID count mismatch");
}
});
}
const undeliveredRanges = new Map();
this.clientProgress.forEach((progress, client) => {
for (const [client, progress] of this.clientProgress.entries()) {
const ranges = this.serverOperations

@@ -338,4 +348,4 @@ .slice(progress)

undeliveredRanges.set(client, ranges);
});
undeliveredRanges.forEach((ranges, client) => {
}
for (const [client, ranges] of undeliveredRanges.entries()) {
const compressor = this.compressors.get(client);

@@ -345,4 +355,4 @@ let firstGenCount;

const unionedLocalRanges = new sessionSpaceNormalizer_js_1.SessionSpaceNormalizer();
ranges.forEach((range) => {
(0, assert_1.strict)(range.sessionId === compressor.localSessionId);
for (const range of ranges) {
(0, node_assert_1.strict)(range.sessionId === compressor.localSessionId);
if (range.ids !== undefined) {

@@ -354,22 +364,22 @@ // initialize firstGenCount if not set

totalCount += range.ids.count;
range.ids.localIdRanges.forEach(([genCount, count]) => {
for (const [genCount, count] of range.ids.localIdRanges) {
unionedLocalRanges.addLocalRange(genCount, count);
});
}
}
});
}
const retakenRange = compressor.takeUnfinalizedCreationRange();
if (retakenRange.ids !== undefined) {
if (retakenRange.ids === undefined) {
node_assert_1.strict.strictEqual(totalCount, 0);
node_assert_1.strict.strictEqual(unionedLocalRanges.idRanges.size, 0);
}
else {
const retakenLocalIds = new sessionSpaceNormalizer_js_1.SessionSpaceNormalizer();
retakenRange.ids.localIdRanges.forEach(([genCount, count]) => {
for (const [genCount, count] of retakenRange.ids.localIdRanges) {
retakenLocalIds.addLocalRange(genCount, count);
});
assert_1.strict.strictEqual(retakenLocalIds.equals(unionedLocalRanges), true, "Local ID ranges mismatch");
assert_1.strict.strictEqual(retakenRange.ids.count, totalCount, "Count mismatch");
assert_1.strict.strictEqual(retakenRange.ids.firstGenCount, firstGenCount, "Count mismatch");
}
node_assert_1.strict.strictEqual(retakenLocalIds.equals(unionedLocalRanges), true, "Local ID ranges mismatch");
node_assert_1.strict.strictEqual(retakenRange.ids.count, totalCount, "Count mismatch");
node_assert_1.strict.strictEqual(retakenRange.ids.firstGenCount, firstGenCount, "Count mismatch");
}
else {
assert_1.strict.strictEqual(totalCount, 0);
assert_1.strict.strictEqual(unionedLocalRanges.idRanges.size, 0);
}
});
}
// First, ensure all clients each generated a unique ID for each of their own calls to generate.

@@ -380,3 +390,3 @@ for (const [compressor, ids] of sequencedLogs) {

const uuid = compressor.decompress(idData.id);
assert_1.strict.strictEqual(!allUuids.has(uuid), true, "Duplicate UUID generated.");
node_assert_1.strict.strictEqual(!allUuids.has(uuid), true, "Duplicate UUID generated.");
allUuids.add(uuid);

@@ -387,2 +397,3 @@ }

.map(([_, data]) => data.length)
// eslint-disable-next-line unicorn/no-array-reduce
.reduce((p, n) => Math.max(p, n));

@@ -427,7 +438,7 @@ function getNextLogWithEntryAt(logsIndex, entryIndex) {

originatingSession ?? (originatingSession = idDataA.sessionId);
(0, assert_1.strict)(idDataA.sessionId === originatingSession, "Test infra gave wrong originating client to TestIdData");
(0, node_assert_1.strict)(idDataA.sessionId === originatingSession, "Test infra gave wrong originating client to TestIdData");
// Only one client should have this ID as local in its session space, as only one client could have created this ID
if ((0, testCommon_js_1.isLocalId)(sessionSpaceIdA)) {
if (originatingSession !== exports.OriginatingClient.Remote) {
assert_1.strict.strictEqual(idDataA.sessionId, this.compressors.get(idDataA.originatingClient).localSessionId);
node_assert_1.strict.strictEqual(idDataA.sessionId, this.compressors.get(idDataA.originatingClient).localSessionId);
}

@@ -437,4 +448,4 @@ idCreatorCount++;

const uuidASessionSpace = compressorA.decompress(sessionSpaceIdA);
assert_1.strict.strictEqual(uuidASessionSpace, (0, testCommon_js_1.incrementStableId)(idDataA.sessionId, idIndex));
assert_1.strict.strictEqual(compressorA.recompress(uuidASessionSpace), sessionSpaceIdA);
node_assert_1.strict.strictEqual(uuidASessionSpace, (0, testCommon_js_1.incrementStableId)(idDataA.sessionId, idIndex));
node_assert_1.strict.strictEqual(compressorA.recompress(uuidASessionSpace), sessionSpaceIdA);
uuids.add(uuidASessionSpace);

@@ -446,6 +457,6 @@ const opSpaceIdA = compressorA.normalizeToOpSpace(sessionSpaceIdA);

const reNormalizedIdA = compressorA.normalizeToSessionSpace(opSpaceIdA, compressorA.localSessionId);
assert_1.strict.strictEqual(reNormalizedIdA, sessionSpaceIdA);
node_assert_1.strict.strictEqual(reNormalizedIdA, sessionSpaceIdA);
finalIds.add(opSpaceIdA);
const uuidAOpSpace = compressorA.decompress(reNormalizedIdA);
assert_1.strict.strictEqual(uuidASessionSpace, uuidAOpSpace);
node_assert_1.strict.strictEqual(uuidASessionSpace, uuidAOpSpace);
if (next !== undefined) {

@@ -455,3 +466,3 @@ const [compressorB, idDataB] = next;

const uuidBSessionSpace = compressorB.decompress(sessionSpaceIdB);
assert_1.strict.strictEqual(uuidASessionSpace, uuidBSessionSpace);
node_assert_1.strict.strictEqual(uuidASessionSpace, uuidBSessionSpace);
const opSpaceIdB = compressorB.normalizeToOpSpace(sessionSpaceIdB);

@@ -462,3 +473,3 @@ if (opSpaceIdA !== opSpaceIdB) {

}
assert_1.strict.strictEqual(opSpaceIdA, opSpaceIdB);
node_assert_1.strict.strictEqual(opSpaceIdA, opSpaceIdB);
if (!(0, testCommon_js_1.isFinalId)(opSpaceIdB)) {

@@ -468,8 +479,8 @@ (0, testCommon_js_1.fail)("IDs should have been finalized.");

const uuidBOpSpace = compressorB.decompress(opSpaceIdB);
assert_1.strict.strictEqual(uuidAOpSpace, uuidBOpSpace);
node_assert_1.strict.strictEqual(uuidAOpSpace, uuidBOpSpace);
}
}
(0, assert_1.strict)(idCreatorCount <= 1, "Only one client can create an ID.");
assert_1.strict.strictEqual(uuids.size, finalIds.size);
(0, assert_1.strict)(originatingSession !== undefined, "Expected originating client to be defined");
(0, node_assert_1.strict)(idCreatorCount <= 1, "Only one client can create an ID.");
node_assert_1.strict.strictEqual(uuids.size, finalIds.size);
(0, node_assert_1.strict)(originatingSession !== undefined, "Expected originating client to be defined");
idIndicesAggregator.set(originatingSession, (idIndicesAggregator.get(originatingSession) ??

@@ -491,3 +502,3 @@ (0, testCommon_js_1.fail)("Expected pre-existing index for originating client")) + 1);

// to a default on construction (deserialization)
// eslint-disable-next-line @typescript-eslint/dot-notation
// eslint-disable-next-line @typescript-eslint/dot-notation, @typescript-eslint/no-unsafe-assignment
const capacity = compressor["nextRequestedClusterSize"];

@@ -521,3 +532,3 @@ if (withSession) {

}
assert_1.strict.strictEqual(compressor.equals(deserialized, withSession), true);
node_assert_1.strict.strictEqual(compressor.equals(deserialized, withSession), true);
return serialized;

@@ -537,7 +548,7 @@ }

const entry = to.get(key);
if (entry !== undefined) {
entry.push(...value);
if (entry === undefined) {
to.set(key, [...value]);
}
else {
to.set(key, [...value]);
entry.push(...value);
}

@@ -558,3 +569,3 @@ }

};
(0, assert_1.strict)(outsideAllocationFraction >= 0 && outsideAllocationFraction <= 1);
(0, node_assert_1.strict)(outsideAllocationFraction >= 0 && outsideAllocationFraction <= 1);
function allocateIdsGenerator({ activeClients, clusterSize, random, }) {

@@ -561,0 +572,0 @@ const client = random.pick(activeClients);

@@ -29,2 +29,3 @@ /*!

/**
* Returns true if the supplied ID is a final ID.
* @returns true if the supplied ID is a final ID.

@@ -34,2 +35,3 @@ */

/**
* Returns true if the supplied ID is a local ID.
* @returns true if the supplied ID is a local ID.

@@ -57,3 +59,5 @@ */

export declare function incrementStableId(stableId: StableId, offset: number): StableId;
/** An immutable view of an `IdCompressor` */
/**
* An immutable view of an `IdCompressor`
*/
export type ReadonlyIdCompressor = Omit<IdCompressor, "generateCompressedId" | "generateCompressedIdRange" | "takeNextCreationRange" | "finalizeCreationRange">;

@@ -60,0 +64,0 @@ /**

@@ -11,2 +11,3 @@ "use strict";

/**
* Returns true if the supplied ID is a final ID.
* @returns true if the supplied ID is a final ID.

@@ -19,2 +20,3 @@ */

/**
* Returns true if the supplied ID is a local ID.
* @returns true if the supplied ID is a local ID.

@@ -21,0 +23,0 @@ */

@@ -11,3 +11,3 @@ "use strict";

const uuid_1 = require("uuid");
const hexadecimalCharCodes = Array.from("09afAF").map((c) => c.charCodeAt(0));
const hexadecimalCharCodes = [..."09afAF"].map((c) => c.codePointAt(0));
function isHexadecimalCharacter(charCode) {

@@ -66,3 +66,3 @@ return ((charCode >= hexadecimalCharCodes[0] && charCode <= hexadecimalCharCodes[1]) ||

case 18:
case 23:
case 23: {
if (str.charAt(i) !== "-") {

@@ -72,3 +72,4 @@ return false;

break;
case 14:
}
case 14: {
if (str.charAt(i) !== "4") {

@@ -78,2 +79,3 @@ return false;

break;
}
case 19: {

@@ -86,7 +88,10 @@ const char = str.charAt(i);

}
default:
if (!isHexadecimalCharacter(str.charCodeAt(i))) {
default: {
const codePoint = str.codePointAt(i);
(0, internal_1.assert)(codePoint !== undefined, 0xaaf /* Unexpected undefined code point */);
if (!isHexadecimalCharacter(codePoint)) {
return false;
}
break;
}
}

@@ -159,3 +164,3 @@ }

const uuidString = uuidU128.toString(16).padStart(32, "0");
return `${uuidString.substring(0, 8)}-${uuidString.substring(8, 12)}-${uuidString.substring(12, 16)}-${uuidString.substring(16, 20)}-${uuidString.substring(20, 32)}`;
return `${uuidString.slice(0, 8)}-${uuidString.slice(8, 12)}-${uuidString.slice(12, 16)}-${uuidString.slice(16, 20)}-${uuidString.slice(20, 32)}`;
}

@@ -162,0 +167,0 @@ exports.stableIdFromNumericUuid = stableIdFromNumericUuid;

@@ -17,2 +17,3 @@ /*!

/**
* Gets the size of the map.
* @returns the number of entries in this map

@@ -22,2 +23,3 @@ */

/**
* Gets the min key in the map.
* @returns the min key in the map.

@@ -27,2 +29,3 @@ */

/**
* Gets the max key in the map.
* @returns the max key in the map.

@@ -32,2 +35,3 @@ */

/**
* Gets the min value in the map.
* @returns the min value in the map.

@@ -37,18 +41,24 @@ */

/**
* @returns the min value in the map.
* Gets the max value in the map.
* @returns the max value in the map.
*/
maxValue(): V | undefined;
/**
* @returns the min key in the map.
* Gets the first key/value pair in the map.
* @returns the first pair if it exists, or undefined otherwise.
*/
first(): [K, V] | undefined;
/**
* @returns the max key in the map.
* Gets the last key/value pair in the map.
* @returns the last pair if it exists, or undefined otherwise.
*/
last(): [K, V] | undefined;
/**
* Returns the element at the insertion index.
* Gets the entry at the specified index.
* @param index - the entry index
* @returns the key/value pair if it exists, or undefined otherwise.
*/
getAtIndex(index: number): [K, V] | undefined;
/**
* Gets the entries in the map.
* @returns an iterable of the entries in the map.

@@ -58,2 +68,3 @@ */

/**
* Gets the keys in the map.
* @returns an iterable of the keys in the map.

@@ -63,2 +74,3 @@ */

/**
* Gets the values in the map.
* @returns an iterable of the values in the map.

@@ -68,2 +80,3 @@ */

/**
* Gets the entries in the map, reversed.
* @returns an iterable of the entries in the map, reversed.

@@ -73,26 +86,28 @@ */

/**
* Adds a new key/value pair to the map. `key` must be > to all keys in the map.
* @param key - the key to add.
* @param value - the value to add.
* Appends a new key/value pair at the end of the map. `key` must be greater than all other keys in the map.
* @param key - the key to add
* @param value - the value to add
*/
append(key: K, value: V): void;
/**
* Replaces the last key/value pair with the given one. If the map is empty, it simply appends.
* `key` must be > to all keys in the map prior to the one replaced.
* @param key - the key to add.
* @param value - the value to add.
* Replaces the last key/value pair with a new one. If the map is empty, the new pair is appended.
* 'key' must be greater than all other keys in the map.
* @param key - the key to set
* @param value - the value to set
*/
replaceLast(key: K, value: V): void;
/**
* @param key - the key to lookup.
* @returns the value associated with `key` if such an entry exists, and undefined otherwise.
* Gets the value associated with a given key.
* @param key - the key to lookup
* @returns the value if it exists, or undefined otherwise.
*/
get(key: K): V | undefined;
/**
* @param key - the key to lookup.
* @returns the entry associated with `key` if such an entry exists, the entry associated with the next lower key if such an entry
* exists, and undefined otherwise.
* Gets the pair associated with the given key or the next smaller key.
* @param key - the key to lookup
* @returns the pair if it exists, or undefined otherwise.
*/
getPairOrNextLower(key: K): readonly [K, V] | undefined;
/**
* Gets the pair associated with the given key or the next higher key.
* @param key - the key to lookup.

@@ -120,2 +135,8 @@ * @returns the entry associated with `key` if such an entry exists, the entry associated with the next higher key if such an entry

private getKeyIndexOfOrNextLower;
/**
* Gets the pair associated with the given key or next higher key.
* @param search - the search value
* @param comparator - a comparison function
* @returns the pair if it exists, or undefined otherwise.
*/
protected getPairOrNextHigherBy<T>(search: T, comparator: (search: T, key: K, value: V) => number): readonly [K, V] | undefined;

@@ -122,0 +143,0 @@ private getKeyIndexOfOrNextHigher;

@@ -5,3 +5,2 @@ /*!

*/
/* eslint-disable tsdoc/syntax */
/* eslint-disable no-bitwise */

@@ -22,2 +21,3 @@ import { assert } from "@fluidframework/core-utils/internal";

/**
* Gets the size of the map.
* @returns the number of entries in this map

@@ -29,2 +29,3 @@ */

/**
* Gets the min key in the map.
* @returns the min key in the map.

@@ -36,2 +37,3 @@ */

/**
* Gets the max key in the map.
* @returns the max key in the map.

@@ -43,2 +45,3 @@ */

/**
* Gets the min value in the map.
* @returns the min value in the map.

@@ -50,3 +53,4 @@ */

/**
* @returns the min value in the map.
* Gets the max value in the map.
* @returns the max value in the map.
*/

@@ -57,3 +61,4 @@ maxValue() {

/**
* @returns the min key in the map.
* Gets the first key/value pair in the map.
* @returns the first pair if it exists, or undefined otherwise.
*/

@@ -69,3 +74,4 @@ first() {

/**
* @returns the max key in the map.
* Gets the last key/value pair in the map.
* @returns the last pair if it exists, or undefined otherwise.
*/

@@ -82,3 +88,5 @@ last() {

/**
* Returns the element at the insertion index.
* Gets the entry at the specified index.
* @param index - the entry index
* @returns the key/value pair if it exists, or undefined otherwise.
*/

@@ -94,2 +102,3 @@ getAtIndex(index) {

/**
* Gets the entries in the map.
* @returns an iterable of the entries in the map.

@@ -104,2 +113,3 @@ */

/**
* Gets the keys in the map.
* @returns an iterable of the keys in the map.

@@ -114,2 +124,3 @@ */

/**
* Gets the values in the map.
* @returns an iterable of the values in the map.

@@ -124,2 +135,3 @@ */

/**
* Gets the entries in the map, reversed.
* @returns an iterable of the entries in the map, reversed.

@@ -134,5 +146,5 @@ */

/**
* Adds a new key/value pair to the map. `key` must be > to all keys in the map.
* @param key - the key to add.
* @param value - the value to add.
* Appends a new key/value pair at the end of the map. `key` must be greater than all other keys in the map.
* @param key - the key to add
* @param value - the value to add
*/

@@ -145,10 +157,9 @@ append(key, value) {

}
elements.push(key);
elements.push(value);
elements.push(key, value);
}
/**
* Replaces the last key/value pair with the given one. If the map is empty, it simply appends.
* `key` must be > to all keys in the map prior to the one replaced.
* @param key - the key to add.
* @param value - the value to add.
* Replaces the last key/value pair with a new one. If the map is empty, the new pair is appended.
* 'key' must be greater than all other keys in the map.
* @param key - the key to set
* @param value - the value to set
*/

@@ -165,8 +176,8 @@ replaceLast(key, value) {

}
elements.push(key);
elements.push(value);
elements.push(key, value);
}
/**
* @param key - the key to lookup.
* @returns the value associated with `key` if such an entry exists, and undefined otherwise.
* Gets the value associated with a given key.
* @param key - the key to lookup
* @returns the value if it exists, or undefined otherwise.
*/

@@ -181,5 +192,5 @@ get(key) {

/**
* @param key - the key to lookup.
* @returns the entry associated with `key` if such an entry exists, the entry associated with the next lower key if such an entry
* exists, and undefined otherwise.
* Gets the pair associated with the given key or the next smaller key.
* @param key - the key to lookup
* @returns the pair if it exists, or undefined otherwise.
*/

@@ -190,2 +201,3 @@ getPairOrNextLower(key) {

/**
* Gets the pair associated with the given key or the next higher key.
* @param key - the key to lookup.

@@ -275,2 +287,8 @@ * @returns the entry associated with `key` if such an entry exists, the entry associated with the next higher key if such an entry

}
/**
* Gets the pair associated with the given key or next higher key.
* @param search - the search value
* @param comparator - a comparison function
* @returns the pair if it exists, or undefined otherwise.
*/
getPairOrNextHigherBy(search, comparator) {

@@ -277,0 +295,0 @@ const keyIndex = this.getKeyIndexOfOrNextHigher(search, comparator);

@@ -18,3 +18,3 @@ /*!

/**
* @returns the upper bound (exclusive) of finalized IDs in final space, i.e. one greater than the last final ID in the last cluster.
* Gets the upper bound (exclusive) of finalized IDs in final space, i.e. one greater than the last final ID in the last cluster.
* Note: this does not include allocated but unfinalized space in clusters.

@@ -24,3 +24,3 @@ */

/**
* @returns the upper bound (exclusive) of allocated IDs in final space, i.e. one greater than the last final ID in the last cluster.
* Gets the upper bound (exclusive) of allocated IDs in final space, i.e. one greater than the last final ID in the last cluster.
* Note: this does includes all allocated IDs in clusters.

@@ -27,0 +27,0 @@ */

@@ -29,3 +29,3 @@ /*!

/**
* @returns the upper bound (exclusive) of finalized IDs in final space, i.e. one greater than the last final ID in the last cluster.
* Gets the upper bound (exclusive) of finalized IDs in final space, i.e. one greater than the last final ID in the last cluster.
* Note: this does not include allocated but unfinalized space in clusters.

@@ -40,3 +40,3 @@ */

/**
* @returns the upper bound (exclusive) of allocated IDs in final space, i.e. one greater than the last final ID in the last cluster.
* Gets the upper bound (exclusive) of allocated IDs in final space, i.e. one greater than the last final ID in the last cluster.
* Note: this does includes all allocated IDs in clusters.

@@ -51,4 +51,5 @@ */

equals(other) {
for (const [index, value] of Object.entries(this.clusterList)) {
if (!clustersEqual(value, other.clusterList[index])) {
for (let i = 0; i < this.clusterList.length; i++) {
const cluster = this.clusterList[i];
if (!clustersEqual(cluster, other.clusterList[i])) {
return false;

@@ -55,0 +56,0 @@ }

@@ -18,3 +18,3 @@ /*!

*/
const currentWrittenVersion = 2.0;
const currentWrittenVersion = 2;
function rangeFinalizationError(expectedStart, actualStart) {

@@ -417,3 +417,3 @@ return new LoggingError("Ranges finalized out of order", {

assert(!this.ongoingGhostSession, 0x8a9 /* IdCompressor should not be operated normally when in a ghost session */);
const { normalizer, finalSpace, sessions } = this;
const { normalizer, finalSpace, sessions, localGenCount, logger, nextRangeBaseGenCount } = this;
const sessionIndexMap = new Map();

@@ -432,3 +432,3 @@ let sessionIndex = 0;

1 + // count of normalizer pairs
this.normalizer.idRanges.size * 2 // pairs
normalizer.idRanges.size * 2 // pairs
: 0;

@@ -453,10 +453,10 @@ // Layout size, in 8 byte increments

}
finalSpace.clusters.forEach((cluster) => {
for (const cluster of finalSpace.clusters) {
index = writeNumber(serializedFloat, index, sessionIndexMap.get(cluster.session));
index = writeNumber(serializedFloat, index, cluster.capacity);
index = writeNumber(serializedFloat, index, cluster.count);
});
}
if (hasLocalState) {
index = writeNumber(serializedFloat, index, this.localGenCount);
index = writeNumber(serializedFloat, index, this.nextRangeBaseGenCount);
index = writeNumber(serializedFloat, index, localGenCount);
index = writeNumber(serializedFloat, index, nextRangeBaseGenCount);
index = writeNumber(serializedFloat, index, normalizer.idRanges.size);

@@ -469,3 +469,3 @@ for (const [leadingGenCount, count] of normalizer.idRanges.entries()) {

assert(index === totalSize, 0x75b /* Serialized size was incorrectly calculated. */);
this.logger?.sendTelemetryEvent({
logger?.sendTelemetryEvent({
eventName: "RuntimeIdCompressor:SerializedIdCompressorSize",

@@ -495,8 +495,11 @@ size: serializedFloat.byteLength,

switch (version) {
case 1.0:
case 1: {
throw new Error("IdCompressor version 1.0 is no longer supported.");
case 2.0:
}
case 2: {
return IdCompressor.deserialize2_0(index, sessionId, logger);
default:
}
default: {
throw new Error("Unknown IdCompressor serialized version.");
}
}

@@ -511,3 +514,6 @@ }

const sessions = [];
if (!hasLocalState) {
if (hasLocalState) {
assert(sessionId === undefined, 0x75e /* Local state should not exist in serialized form. */);
}
else {
// If !hasLocalState, there won't be a serialized local session ID so insert one at the beginning

@@ -519,5 +525,2 @@ assert(sessionId !== undefined, 0x75d /* Local session ID is undefined. */);

}
else {
assert(sessionId === undefined, 0x75e /* Local state should not exist in serialized form. */);
}
for (let i = 0; i < sessionCount; i++) {

@@ -524,0 +527,0 @@ const numeric = readNumericUuid(index);

@@ -23,3 +23,3 @@ /*!

/**
* @returns true if the supplied ID is a final ID.
* Returns true if the supplied ID is a final ID.
*/

@@ -26,0 +26,0 @@ export declare function isFinalId(id: SessionSpaceCompressedId | OpSpaceCompressedId): id is FinalCompressedId;

@@ -6,3 +6,3 @@ /*!

/**
* @returns true if the supplied ID is a final ID.
* Returns true if the supplied ID is a final ID.
*/

@@ -9,0 +9,0 @@ export function isFinalId(id) {

@@ -8,3 +8,3 @@ /*!

export declare const pkgName = "@fluidframework/id-compressor";
export declare const pkgVersion = "2.13.0";
export declare const pkgVersion = "2.20.0";
//# sourceMappingURL=packageVersion.d.ts.map

@@ -8,3 +8,3 @@ /*!

export const pkgName = "@fluidframework/id-compressor";
export const pkgVersion = "2.13.0";
export const pkgVersion = "2.20.0";
//# sourceMappingURL=packageVersion.js.map

@@ -16,3 +16,5 @@ /*!

}
/** Identifies a compressor in a network */
/**
* Identifies a compressor in a network
*/
export declare enum Client {

@@ -23,7 +25,11 @@ Client1 = "Client1",

}
/** Identifies categories of compressors */
/**
* Identifies categories of compressors
*/
export declare enum MetaClient {
All = "All"
}
/** Identifies a compressor inside the network but outside the three specially tracked clients. */
/**
* Identifies a compressor inside the network but outside the three specially tracked clients.
*/
export declare enum OutsideClient {

@@ -43,3 +49,5 @@ Remote = "Remote"

};
/** Identifies a compressor to which to send an operation */
/**
* Identifies a compressor to which to send an operation
*/
export type DestinationClient = Client | MetaClient;

@@ -75,3 +83,5 @@ export declare const DestinationClient: {

export declare const sessionIds: ClientMap<SessionId>;
/** Information about a generated ID in a network to be validated by tests */
/**
* Information about a generated ID in a network to be validated by tests
*/
export interface TestIdData {

@@ -89,11 +99,21 @@ readonly id: SessionSpaceCompressedId;

readonly initialClusterSize: number;
/** The compressors used in this network */
/**
* The compressors used in this network
*/
private readonly compressors;
/** The log of operations seen by the server so far. Append-only. */
/**
* The log of operations seen by the server so far. Append-only.
*/
private readonly serverOperations;
/** An index into `serverOperations` for each client which represents how many operations have been delivered to that client */
/**
* An index into `serverOperations` for each client which represents how many operations have been delivered to that client
*/
private readonly clientProgress;
/** All ids (local and sequenced) that a client has created or received, in order. */
/**
* All ids (local and sequenced) that a client has created or received, in order.
*/
private readonly idLogs;
/** All ids that a client has received from the server, in order. */
/**
* All ids that a client has received from the server, in order.
*/
private readonly sequencedIdLogs;

@@ -217,7 +237,13 @@ constructor(initialClusterSize?: number);

export interface OperationGenerationConfig {
/** maximum cluster size of the network. Default: 25 */
/**
* maximum cluster size of the network. Default: 25
*/
maxClusterSize?: number;
/** Number of ops between validation ops. Default: 200 */
/**
* Number of ops between validation ops. Default: 200
*/
validateInterval?: number;
/** Fraction of ID allocations that are from an outside client (not Client1/2/3). */
/**
* Fraction of ID allocations that are from an outside client (not Client1/2/3).
*/
outsideAllocationFraction?: number;

@@ -224,0 +250,0 @@ }

@@ -5,3 +5,4 @@ /*!

*/
import { strict as assert } from "assert";
// eslint-disable-next-line import/no-nodejs-modules
import { strict as assert } from "node:assert";
import { createWeightedGenerator, interleave, makeRandom, performFuzzActions as performFuzzActionsBase, repeat, take, } from "@fluid-private/stochastic-test-utils";

@@ -13,3 +14,5 @@ import { IdCompressor } from "../idCompressor.js";

import { fail, getOrCreate, incrementStableId, isFinalId, isLocalId, } from "./testCommon.js";
/** Identifies a compressor in a network */
/**
* Identifies a compressor in a network
*/
export var Client;

@@ -21,3 +24,5 @@ (function (Client) {

})(Client || (Client = {}));
/** Identifies categories of compressors */
/**
* Identifies categories of compressors
*/
export var MetaClient;

@@ -27,3 +32,5 @@ (function (MetaClient) {

})(MetaClient || (MetaClient = {}));
/** Identifies a compressor inside the network but outside the three specially tracked clients. */
/**
* Identifies a compressor inside the network but outside the three specially tracked clients.
*/
export var OutsideClient;

@@ -105,3 +112,5 @@ (function (OutsideClient) {

this.initialClusterSize = initialClusterSize;
/** The log of operations seen by the server so far. Append-only. */
/**
* The log of operations seen by the server so far. Append-only.
*/
this.serverOperations = [];

@@ -219,2 +228,3 @@ const compressors = new Map();

count: numIds,
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
requestedClusterSize: this.getCompressor(Client.Client1)[

@@ -257,5 +267,5 @@ // eslint-disable-next-line @typescript-eslint/dot-notation

opIndexBound =
opsToDeliver !== undefined
? this.clientProgress.get(clientTakingDelivery) + opsToDeliver
: this.serverOperations.length;
opsToDeliver === undefined
? this.serverOperations.length
: this.clientProgress.get(clientTakingDelivery) + opsToDeliver;
}

@@ -308,7 +318,7 @@ for (const [clientTo, compressorTo] of this.getTargetCompressors(clientTakingDelivery)) {

// Ensure creation ranges for clients we track contain the correct local ID ranges
this.serverOperations.forEach(([range, opSpaceIds, clientFrom]) => {
for (const [range, opSpaceIds, clientFrom] of this.serverOperations) {
if (clientFrom !== OriginatingClient.Remote) {
const localIdsInCreationRange = getLocalIdsInRange(range, opSpaceIds);
let localCount = 0;
opSpaceIds.forEach((id) => {
for (const id of opSpaceIds) {
if (isLocalId(id)) {

@@ -318,8 +328,8 @@ localCount++;

}
});
}
assert.strictEqual(localCount, localIdsInCreationRange.size, "Local ID count mismatch");
}
});
}
const undeliveredRanges = new Map();
this.clientProgress.forEach((progress, client) => {
for (const [client, progress] of this.clientProgress.entries()) {
const ranges = this.serverOperations

@@ -330,4 +340,4 @@ .slice(progress)

undeliveredRanges.set(client, ranges);
});
undeliveredRanges.forEach((ranges, client) => {
}
for (const [client, ranges] of undeliveredRanges.entries()) {
const compressor = this.compressors.get(client);

@@ -337,3 +347,3 @@ let firstGenCount;

const unionedLocalRanges = new SessionSpaceNormalizer();
ranges.forEach((range) => {
for (const range of ranges) {
assert(range.sessionId === compressor.localSessionId);

@@ -346,13 +356,17 @@ if (range.ids !== undefined) {

totalCount += range.ids.count;
range.ids.localIdRanges.forEach(([genCount, count]) => {
for (const [genCount, count] of range.ids.localIdRanges) {
unionedLocalRanges.addLocalRange(genCount, count);
});
}
}
});
}
const retakenRange = compressor.takeUnfinalizedCreationRange();
if (retakenRange.ids !== undefined) {
if (retakenRange.ids === undefined) {
assert.strictEqual(totalCount, 0);
assert.strictEqual(unionedLocalRanges.idRanges.size, 0);
}
else {
const retakenLocalIds = new SessionSpaceNormalizer();
retakenRange.ids.localIdRanges.forEach(([genCount, count]) => {
for (const [genCount, count] of retakenRange.ids.localIdRanges) {
retakenLocalIds.addLocalRange(genCount, count);
});
}
assert.strictEqual(retakenLocalIds.equals(unionedLocalRanges), true, "Local ID ranges mismatch");

@@ -362,7 +376,3 @@ assert.strictEqual(retakenRange.ids.count, totalCount, "Count mismatch");

}
else {
assert.strictEqual(totalCount, 0);
assert.strictEqual(unionedLocalRanges.idRanges.size, 0);
}
});
}
// First, ensure all clients each generated a unique ID for each of their own calls to generate.

@@ -379,2 +389,3 @@ for (const [compressor, ids] of sequencedLogs) {

.map(([_, data]) => data.length)
// eslint-disable-next-line unicorn/no-array-reduce
.reduce((p, n) => Math.max(p, n));

@@ -476,3 +487,3 @@ function getNextLogWithEntryAt(logsIndex, entryIndex) {

// to a default on construction (deserialization)
// eslint-disable-next-line @typescript-eslint/dot-notation
// eslint-disable-next-line @typescript-eslint/dot-notation, @typescript-eslint/no-unsafe-assignment
const capacity = compressor["nextRequestedClusterSize"];

@@ -519,7 +530,7 @@ if (withSession) {

const entry = to.get(key);
if (entry !== undefined) {
entry.push(...value);
if (entry === undefined) {
to.set(key, [...value]);
}
else {
to.set(key, [...value]);
entry.push(...value);
}

@@ -526,0 +537,0 @@ }

@@ -29,2 +29,3 @@ /*!

/**
* Returns true if the supplied ID is a final ID.
* @returns true if the supplied ID is a final ID.

@@ -34,2 +35,3 @@ */

/**
* Returns true if the supplied ID is a local ID.
* @returns true if the supplied ID is a local ID.

@@ -57,3 +59,5 @@ */

export declare function incrementStableId(stableId: StableId, offset: number): StableId;
/** An immutable view of an `IdCompressor` */
/**
* An immutable view of an `IdCompressor`
*/
export type ReadonlyIdCompressor = Omit<IdCompressor, "generateCompressedId" | "generateCompressedIdRange" | "takeNextCreationRange" | "finalizeCreationRange">;

@@ -60,0 +64,0 @@ /**

@@ -8,2 +8,3 @@ /*!

/**
* Returns true if the supplied ID is a final ID.
* @returns true if the supplied ID is a final ID.

@@ -15,2 +16,3 @@ */

/**
* Returns true if the supplied ID is a local ID.
* @returns true if the supplied ID is a local ID.

@@ -17,0 +19,0 @@ */

@@ -8,3 +8,3 @@ /*!

import { v4 } from "uuid";
const hexadecimalCharCodes = Array.from("09afAF").map((c) => c.charCodeAt(0));
const hexadecimalCharCodes = [..."09afAF"].map((c) => c.codePointAt(0));
function isHexadecimalCharacter(charCode) {

@@ -59,3 +59,3 @@ return ((charCode >= hexadecimalCharCodes[0] && charCode <= hexadecimalCharCodes[1]) ||

case 18:
case 23:
case 23: {
if (str.charAt(i) !== "-") {

@@ -65,3 +65,4 @@ return false;

break;
case 14:
}
case 14: {
if (str.charAt(i) !== "4") {

@@ -71,2 +72,3 @@ return false;

break;
}
case 19: {

@@ -79,7 +81,10 @@ const char = str.charAt(i);

}
default:
if (!isHexadecimalCharacter(str.charCodeAt(i))) {
default: {
const codePoint = str.codePointAt(i);
assert(codePoint !== undefined, 0xaaf /* Unexpected undefined code point */);
if (!isHexadecimalCharacter(codePoint)) {
return false;
}
break;
}
}

@@ -145,3 +150,3 @@ }

const uuidString = uuidU128.toString(16).padStart(32, "0");
return `${uuidString.substring(0, 8)}-${uuidString.substring(8, 12)}-${uuidString.substring(12, 16)}-${uuidString.substring(16, 20)}-${uuidString.substring(20, 32)}`;
return `${uuidString.slice(0, 8)}-${uuidString.slice(8, 12)}-${uuidString.slice(12, 16)}-${uuidString.slice(16, 20)}-${uuidString.slice(20, 32)}`;
}

@@ -148,0 +153,0 @@ export function offsetNumericUuid(numericUuid, offset) {

{
"name": "@fluidframework/id-compressor",
"version": "2.13.0",
"version": "2.20.0",
"description": "ID compressor",

@@ -84,6 +84,6 @@ "homepage": "https://fluidframework.com",

"dependencies": {
"@fluid-internal/client-utils": "~2.13.0",
"@fluidframework/core-interfaces": "~2.13.0",
"@fluidframework/core-utils": "~2.13.0",
"@fluidframework/telemetry-utils": "~2.13.0",
"@fluid-internal/client-utils": "~2.20.0",
"@fluidframework/core-interfaces": "~2.20.0",
"@fluidframework/core-utils": "~2.20.0",
"@fluidframework/telemetry-utils": "~2.20.0",
"@tylerbu/sorted-btree-es6": "^1.8.0",

@@ -95,4 +95,4 @@ "uuid": "^9.0.0"

"@biomejs/biome": "~1.9.3",
"@fluid-internal/mocha-test-setup": "~2.13.0",
"@fluid-private/stochastic-test-utils": "~2.13.0",
"@fluid-internal/mocha-test-setup": "~2.20.0",
"@fluid-private/stochastic-test-utils": "~2.20.0",
"@fluid-tools/benchmark": "^0.50.0",

@@ -103,3 +103,3 @@ "@fluid-tools/build-cli": "^0.51.0",

"@fluidframework/eslint-config-fluid": "^5.6.0",
"@fluidframework/id-compressor-previous": "npm:@fluidframework/id-compressor@2.12.0",
"@fluidframework/id-compressor-previous": "npm:@fluidframework/id-compressor@2.13.0",
"@microsoft/api-extractor": "7.47.8",

@@ -106,0 +106,0 @@ "@types/mocha": "^10.0.10",

@@ -6,3 +6,2 @@ /*!

/* eslint-disable tsdoc/syntax */
/* eslint-disable no-bitwise */

@@ -24,2 +23,3 @@ import { assert } from "@fluidframework/core-utils/internal";

/**
* Gets the size of the map.
* @returns the number of entries in this map

@@ -32,2 +32,3 @@ */

/**
* Gets the min key in the map.
* @returns the min key in the map.

@@ -40,2 +41,3 @@ */

/**
* Gets the max key in the map.
* @returns the max key in the map.

@@ -48,2 +50,3 @@ */

/**
* Gets the min value in the map.
* @returns the min value in the map.

@@ -56,3 +59,4 @@ */

/**
* @returns the min value in the map.
* Gets the max value in the map.
* @returns the max value in the map.
*/

@@ -64,3 +68,4 @@ public maxValue(): V | undefined {

/**
* @returns the min key in the map.
* Gets the first key/value pair in the map.
* @returns the first pair if it exists, or undefined otherwise.
*/

@@ -77,3 +82,4 @@ public first(): [K, V] | undefined {

/**
* @returns the max key in the map.
* Gets the last key/value pair in the map.
* @returns the last pair if it exists, or undefined otherwise.
*/

@@ -91,3 +97,5 @@ public last(): [K, V] | undefined {

/**
* Returns the element at the insertion index.
* Gets the entry at the specified index.
* @param index - the entry index
* @returns the key/value pair if it exists, or undefined otherwise.
*/

@@ -104,2 +112,3 @@ public getAtIndex(index: number): [K, V] | undefined {

/**
* Gets the entries in the map.
* @returns an iterable of the entries in the map.

@@ -115,2 +124,3 @@ */

/**
* Gets the keys in the map.
* @returns an iterable of the keys in the map.

@@ -126,2 +136,3 @@ */

/**
* Gets the values in the map.
* @returns an iterable of the values in the map.

@@ -137,2 +148,3 @@ */

/**
* Gets the entries in the map, reversed.
* @returns an iterable of the entries in the map, reversed.

@@ -148,5 +160,5 @@ */

/**
* Adds a new key/value pair to the map. `key` must be > to all keys in the map.
* @param key - the key to add.
* @param value - the value to add.
* Appends a new key/value pair at the end of the map. `key` must be greater than all other keys in the map.
* @param key - the key to add
* @param value - the value to add
*/

@@ -159,11 +171,10 @@ public append(key: K, value: V): void {

}
elements.push(key);
elements.push(value);
elements.push(key, value);
}
/**
* Replaces the last key/value pair with the given one. If the map is empty, it simply appends.
* `key` must be > to all keys in the map prior to the one replaced.
* @param key - the key to add.
* @param value - the value to add.
* Replaces the last key/value pair with a new one. If the map is empty, the new pair is appended.
* 'key' must be greater than all other keys in the map.
* @param key - the key to set
* @param value - the value to set
*/

@@ -180,9 +191,9 @@ public replaceLast(key: K, value: V): void {

}
elements.push(key);
elements.push(value);
elements.push(key, value);
}
/**
* @param key - the key to lookup.
* @returns the value associated with `key` if such an entry exists, and undefined otherwise.
* Gets the value associated with a given key.
* @param key - the key to lookup
* @returns the value if it exists, or undefined otherwise.
*/

@@ -198,5 +209,5 @@ public get(key: K): V | undefined {

/**
* @param key - the key to lookup.
* @returns the entry associated with `key` if such an entry exists, the entry associated with the next lower key if such an entry
* exists, and undefined otherwise.
* Gets the pair associated with the given key or the next smaller key.
* @param key - the key to lookup
* @returns the pair if it exists, or undefined otherwise.
*/

@@ -208,2 +219,3 @@ public getPairOrNextLower(key: K): readonly [K, V] | undefined {

/**
* Gets the pair associated with the given key or the next higher key.
* @param key - the key to lookup.

@@ -314,2 +326,8 @@ * @returns the entry associated with `key` if such an entry exists, the entry associated with the next higher key if such an entry

/**
* Gets the pair associated with the given key or next higher key.
* @param search - the search value
* @param comparator - a comparison function
* @returns the pair if it exists, or undefined otherwise.
*/
protected getPairOrNextHigherBy<T>(

@@ -316,0 +334,0 @@ search: T,

@@ -32,3 +32,3 @@ /*!

public addCluster(newCluster: IdCluster) {
public addCluster(newCluster: IdCluster): void {
const lastCluster = this.getLastCluster();

@@ -44,3 +44,3 @@ assert(

/**
* @returns the upper bound (exclusive) of finalized IDs in final space, i.e. one greater than the last final ID in the last cluster.
* Gets the upper bound (exclusive) of finalized IDs in final space, i.e. one greater than the last final ID in the last cluster.
* Note: this does not include allocated but unfinalized space in clusters.

@@ -56,3 +56,3 @@ */

/**
* @returns the upper bound (exclusive) of allocated IDs in final space, i.e. one greater than the last final ID in the last cluster.
* Gets the upper bound (exclusive) of allocated IDs in final space, i.e. one greater than the last final ID in the last cluster.
* Note: this does includes all allocated IDs in clusters.

@@ -68,4 +68,5 @@ */

public equals(other: FinalSpace): boolean {
for (const [index, value] of Object.entries(this.clusterList)) {
if (!clustersEqual(value, other.clusterList[index])) {
for (let i = 0; i < this.clusterList.length; i++) {
const cluster = this.clusterList[i] as IdCluster;
if (!clustersEqual(cluster, other.clusterList[i] as IdCluster)) {
return false;

@@ -72,0 +73,0 @@ }

@@ -67,3 +67,3 @@ /*!

*/
const currentWrittenVersion = 2.0;
const currentWrittenVersion = 2;

@@ -206,3 +206,3 @@ function rangeFinalizationError(expectedStart: number, actualStart: number): LoggingError {

*/
public beginGhostSession(ghostSessionId: SessionId, ghostSessionCallback: () => void) {
public beginGhostSession(ghostSessionId: SessionId, ghostSessionCallback: () => void): void {
this.startGhostSession(ghostSessionId);

@@ -559,3 +559,4 @@ try {

);
const { normalizer, finalSpace, sessions } = this;
const { normalizer, finalSpace, sessions, localGenCount, logger, nextRangeBaseGenCount } =
this;
const sessionIndexMap = new Map<Session, number>();

@@ -574,3 +575,3 @@ let sessionIndex = 0;

1 + // count of normalizer pairs
this.normalizer.idRanges.size * 2 // pairs
normalizer.idRanges.size * 2 // pairs
: 0;

@@ -599,3 +600,3 @@ // Layout size, in 8 byte increments

finalSpace.clusters.forEach((cluster) => {
for (const cluster of finalSpace.clusters) {
index = writeNumber(

@@ -608,7 +609,7 @@ serializedFloat,

index = writeNumber(serializedFloat, index, cluster.count);
});
}
if (hasLocalState) {
index = writeNumber(serializedFloat, index, this.localGenCount);
index = writeNumber(serializedFloat, index, this.nextRangeBaseGenCount);
index = writeNumber(serializedFloat, index, localGenCount);
index = writeNumber(serializedFloat, index, nextRangeBaseGenCount);
index = writeNumber(serializedFloat, index, normalizer.idRanges.size);

@@ -622,3 +623,3 @@ for (const [leadingGenCount, count] of normalizer.idRanges.entries()) {

assert(index === totalSize, 0x75b /* Serialized size was incorrectly calculated. */);
this.logger?.sendTelemetryEvent({
logger?.sendTelemetryEvent({
eventName: "RuntimeIdCompressor:SerializedIdCompressorSize",

@@ -662,8 +663,11 @@ size: serializedFloat.byteLength,

switch (version) {
case 1.0:
case 1: {
throw new Error("IdCompressor version 1.0 is no longer supported.");
case 2.0:
}
case 2: {
return IdCompressor.deserialize2_0(index, sessionId, logger);
default:
}
default: {
throw new Error("Unknown IdCompressor serialized version.");
}
}

@@ -684,3 +688,8 @@ }

const sessions: [NumericUuid, Session][] = [];
if (!hasLocalState) {
if (hasLocalState) {
assert(
sessionId === undefined,
0x75e /* Local state should not exist in serialized form. */,
);
} else {
// If !hasLocalState, there won't be a serialized local session ID so insert one at the beginning

@@ -691,7 +700,2 @@ assert(sessionId !== undefined, 0x75d /* Local session ID is undefined. */);

sessionOffset = 1;
} else {
assert(
sessionId === undefined,
0x75e /* Local state should not exist in serialized form. */,
);
}

@@ -698,0 +702,0 @@

@@ -29,3 +29,3 @@ /*!

/**
* @returns true if the supplied ID is a final ID.
* Returns true if the supplied ID is a final ID.
*/

@@ -32,0 +32,0 @@ export function isFinalId(

@@ -9,2 +9,2 @@ /*!

export const pkgName = "@fluidframework/id-compressor";
export const pkgVersion = "2.13.0";
export const pkgVersion = "2.20.0";

@@ -134,3 +134,3 @@ /*!

public equals(other: Sessions, includeLocalState: boolean): boolean {
const checkIsSubset = (sessionsA: Sessions, sessionsB: Sessions) => {
const checkIsSubset = (sessionsA: Sessions, sessionsB: Sessions): boolean => {
const first = sessionsA.sessions().next();

@@ -300,3 +300,3 @@ const firstSessionThis = first.done ? undefined : first.value;

for (const [index, value] of Object.entries(this.clusterChain)) {
if (!clustersEqual(value, other.clusterChain[index])) {
if (!clustersEqual(value, other.clusterChain[index] as IdCluster)) {
return false;

@@ -303,0 +303,0 @@ }

@@ -6,3 +6,4 @@ /*!

import { strict as assert } from "assert";
// eslint-disable-next-line import/no-nodejs-modules
import { strict as assert } from "node:assert";

@@ -55,3 +56,5 @@ import {

/** Identifies a compressor in a network */
/**
* Identifies a compressor in a network
*/
export enum Client {

@@ -63,3 +66,5 @@ Client1 = "Client1",

/** Identifies categories of compressors */
/**
* Identifies categories of compressors
*/
export enum MetaClient {

@@ -69,3 +74,5 @@ All = "All",

/** Identifies a compressor inside the network but outside the three specially tracked clients. */
/**
* Identifies a compressor inside the network but outside the three specially tracked clients.
*/
export enum OutsideClient {

@@ -82,3 +89,5 @@ Remote = "Remote",

/** Identifies a compressor to which to send an operation */
/**
* Identifies a compressor to which to send an operation
*/
export type DestinationClient = Client | MetaClient;

@@ -179,3 +188,5 @@ export const DestinationClient = { ...Client, ...MetaClient };

/** Information about a generated ID in a network to be validated by tests */
/**
* Information about a generated ID in a network to be validated by tests
*/
export interface TestIdData {

@@ -193,5 +204,9 @@ readonly id: SessionSpaceCompressedId;

export class IdCompressorTestNetwork {
/** The compressors used in this network */
/**
* The compressors used in this network
*/
private readonly compressors: ClientMap<IdCompressor>;
/** The log of operations seen by the server so far. Append-only. */
/**
* The log of operations seen by the server so far. Append-only.
*/
private readonly serverOperations: [

@@ -203,7 +218,13 @@ creationRange: IdCreationRange,

][] = [];
/** An index into `serverOperations` for each client which represents how many operations have been delivered to that client */
/**
* An index into `serverOperations` for each client which represents how many operations have been delivered to that client
*/
private readonly clientProgress: ClientMap<number>;
/** All ids (local and sequenced) that a client has created or received, in order. */
/**
* All ids (local and sequenced) that a client has created or received, in order.
*/
private readonly idLogs: ClientMap<TestIdData[]>;
/** All ids that a client has received from the server, in order. */
/**
* All ids that a client has received from the server, in order.
*/
private readonly sequencedIdLogs: ClientMap<TestIdData[]>;

@@ -352,2 +373,3 @@

count: numIds,
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
requestedClusterSize: this.getCompressor(Client.Client1)[

@@ -403,5 +425,5 @@ // eslint-disable-next-line @typescript-eslint/dot-notation

opIndexBound =
opsToDeliver !== undefined
? this.clientProgress.get(clientTakingDelivery) + opsToDeliver
: this.serverOperations.length;
opsToDeliver === undefined
? this.serverOperations.length
: this.clientProgress.get(clientTakingDelivery) + opsToDeliver;
}

@@ -465,7 +487,7 @@ for (const [clientTo, compressorTo] of this.getTargetCompressors(clientTakingDelivery)) {

// Ensure creation ranges for clients we track contain the correct local ID ranges
this.serverOperations.forEach(([range, opSpaceIds, clientFrom]) => {
for (const [range, opSpaceIds, clientFrom] of this.serverOperations) {
if (clientFrom !== OriginatingClient.Remote) {
const localIdsInCreationRange = getLocalIdsInRange(range, opSpaceIds);
let localCount = 0;
opSpaceIds.forEach((id) => {
for (const id of opSpaceIds) {
if (isLocalId(id)) {

@@ -475,3 +497,3 @@ localCount++;

}
});
}
assert.strictEqual(

@@ -483,6 +505,6 @@ localCount,

}
});
}
const undeliveredRanges = new Map<Client, IdCreationRange[]>();
this.clientProgress.forEach((progress, client) => {
for (const [client, progress] of this.clientProgress.entries()) {
const ranges = this.serverOperations

@@ -493,4 +515,4 @@ .slice(progress)

undeliveredRanges.set(client, ranges);
});
undeliveredRanges.forEach((ranges, client) => {
}
for (const [client, ranges] of undeliveredRanges.entries()) {
const compressor = this.compressors.get(client);

@@ -500,3 +522,3 @@ let firstGenCount: number | undefined;

const unionedLocalRanges = new SessionSpaceNormalizer();
ranges.forEach((range) => {
for (const range of ranges) {
assert(range.sessionId === compressor.localSessionId);

@@ -509,14 +531,17 @@ if (range.ids !== undefined) {

totalCount += range.ids.count;
range.ids.localIdRanges.forEach(([genCount, count]) => {
for (const [genCount, count] of range.ids.localIdRanges) {
unionedLocalRanges.addLocalRange(genCount, count);
});
}
}
});
}
const retakenRange = compressor.takeUnfinalizedCreationRange();
if (retakenRange.ids !== undefined) {
if (retakenRange.ids === undefined) {
assert.strictEqual(totalCount, 0);
assert.strictEqual(unionedLocalRanges.idRanges.size, 0);
} else {
const retakenLocalIds = new SessionSpaceNormalizer();
retakenRange.ids.localIdRanges.forEach(([genCount, count]) => {
for (const [genCount, count] of retakenRange.ids.localIdRanges) {
retakenLocalIds.addLocalRange(genCount, count);
});
}
assert.strictEqual(

@@ -529,7 +554,4 @@ retakenLocalIds.equals(unionedLocalRanges),

assert.strictEqual(retakenRange.ids.firstGenCount, firstGenCount, "Count mismatch");
} else {
assert.strictEqual(totalCount, 0);
assert.strictEqual(unionedLocalRanges.idRanges.size, 0);
}
});
}

@@ -548,2 +570,3 @@ // First, ensure all clients each generated a unique ID for each of their own calls to generate.

.map(([_, data]) => data.length)
// eslint-disable-next-line unicorn/no-array-reduce
.reduce((p, n) => Math.max(p, n));

@@ -701,4 +724,4 @@

// to a default on construction (deserialization)
// eslint-disable-next-line @typescript-eslint/dot-notation
const capacity = compressor["nextRequestedClusterSize"];
// eslint-disable-next-line @typescript-eslint/dot-notation, @typescript-eslint/no-unsafe-assignment
const capacity: number = compressor["nextRequestedClusterSize"];
if (withSession) {

@@ -754,6 +777,6 @@ const serialized = compressor.serialize(withSession);

const entry = to.get(key);
if (entry !== undefined) {
if (entry === undefined) {
to.set(key, [...value]);
} else {
entry.push(...value);
} else {
to.set(key, [...value]);
}

@@ -819,7 +842,13 @@ }

export interface OperationGenerationConfig {
/** maximum cluster size of the network. Default: 25 */
/**
* maximum cluster size of the network. Default: 25
*/
maxClusterSize?: number;
/** Number of ops between validation ops. Default: 200 */
/**
* Number of ops between validation ops. Default: 200
*/
validateInterval?: number;
/** Fraction of ID allocations that are from an outside client (not Client1/2/3). */
/**
* Fraction of ID allocations that are from an outside client (not Client1/2/3).
*/
outsideAllocationFraction?: number;

@@ -826,0 +855,0 @@ }

@@ -47,2 +47,3 @@ /*!

/**
* Returns true if the supplied ID is a final ID.
* @returns true if the supplied ID is a final ID.

@@ -55,2 +56,3 @@ */

/**
* Returns true if the supplied ID is a local ID.
* @returns true if the supplied ID is a local ID.

@@ -96,3 +98,5 @@ */

/** An immutable view of an `IdCompressor` */
/**
* An immutable view of an `IdCompressor`
*/
export type ReadonlyIdCompressor = Omit<

@@ -99,0 +103,0 @@ IdCompressor,

@@ -13,3 +13,3 @@ /*!

const hexadecimalCharCodes = Array.from("09afAF").map((c) => c.charCodeAt(0)) as [
const hexadecimalCharCodes = [..."09afAF"].map((c) => c.codePointAt(0)) as [
zero: number,

@@ -80,3 +80,3 @@ nine: number,

case 18:
case 23:
case 23: {
if (str.charAt(i) !== "-") {

@@ -86,4 +86,5 @@ return false;

break;
}
case 14:
case 14: {
if (str.charAt(i) !== "4") {

@@ -93,2 +94,3 @@ return false;

break;
}

@@ -103,7 +105,10 @@ case 19: {

default:
if (!isHexadecimalCharacter(str.charCodeAt(i))) {
default: {
const codePoint = str.codePointAt(i);
assert(codePoint !== undefined, 0xaaf /* Unexpected undefined code point */);
if (!isHexadecimalCharacter(codePoint)) {
return false;
}
break;
}
}

@@ -180,6 +185,6 @@ }

const uuidString = uuidU128.toString(16).padStart(32, "0");
return `${uuidString.substring(0, 8)}-${uuidString.substring(8, 12)}-${uuidString.substring(
return `${uuidString.slice(0, 8)}-${uuidString.slice(8, 12)}-${uuidString.slice(
12,
16,
)}-${uuidString.substring(16, 20)}-${uuidString.substring(20, 32)}` as StableId;
)}-${uuidString.slice(16, 20)}-${uuidString.slice(20, 32)}` as StableId;
}

@@ -186,0 +191,0 @@

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc