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
2
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.0.0-rc.2.0.2 to 2.0.0-rc.3.0.0

dist/legacy.d.ts

3

api-report/id-compressor.api.md

@@ -38,2 +38,3 @@ ## API Report File for "@fluidframework/id-compressor"

readonly requestedClusterSize: number;
readonly localIdRanges: [genCount: number, count: number][];
};

@@ -58,3 +59,3 @@ // (undocumented)

export interface IIdCompressorCore {
beginGhostSession(ghostSessionId: SessionId, ghostSessionCallback: () => void): any;
beginGhostSession(ghostSessionId: SessionId, ghostSessionCallback: () => void): void;
finalizeCreationRange(range: IdCreationRange): void;

@@ -61,0 +62,0 @@ serialize(withSession: true): SerializedIdCompressorWithOngoingSession;

# @fluidframework/id-compressor
## 2.0.0-rc.3.0.0
### Major Changes
- Packages now use package.json "exports" and require modern module resolution [97d68aa06b](https://github.com/microsoft/FluidFramework/commit/97d68aa06bd5c022ecb026655814aea222a062ae)
Fluid Framework packages have been updated to use the [package.json "exports"
field](https://nodejs.org/docs/latest-v18.x/api/packages.html#exports) to define explicit entry points for both
TypeScript types and implementation code.
This means that using Fluid Framework packages require the following TypeScript settings in tsconfig.json:
- `"moduleResolution": "Node16"` with `"module": "Node16"`
- `"moduleResolution": "Bundler"` with `"module": "ESNext"`
We recommend using Node16/Node16 unless absolutely necessary. That will produce transpiled JavaScript that is suitable
for use with modern versions of Node.js _and_ Bundlers.
[See the TypeScript documentation](https://www.typescriptlang.org/tsconfig#moduleResolution) for more information
regarding the module and moduleResolution options.
**Node10 moduleResolution is not supported; it does not support Fluid Framework's API structuring pattern that is used
to distinguish stable APIs from those that are in development.**
## 2.0.0-rc.2.0.0

@@ -4,0 +27,0 @@

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

/* eslint-disable no-bitwise */
const core_utils_1 = require("@fluidframework/core-utils");
const internal_1 = require("@fluidframework/core-utils/internal");
/**

@@ -215,3 +215,3 @@ * A map in which entries are always added in key-sorted order.

if (prev !== undefined) {
(0, core_utils_1.assert)(this.comparator(kv[0], prev[0]) > 0, 0x752 /* Keys in map must be sorted. */);
(0, internal_1.assert)(this.comparator(kv[0], prev[0]) > 0, 0x752 /* Keys in map must be sorted. */);
}

@@ -218,0 +218,0 @@ prev = kv;

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

*/
import { FinalCompressedId } from "./identifiers.js";
import { IdCluster } from "./sessions.js";
import { FinalCompressedId } from "./identifiers.js";
/**

@@ -9,0 +9,0 @@ * All IDs that have been finalized (acked), grouped into clusters sorted by their base final IDs.

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

exports.FinalSpace = void 0;
const core_utils_1 = require("@fluidframework/core-utils");
const internal_1 = require("@fluidframework/core-utils/internal");
const sessions_js_1 = require("./sessions.js");

@@ -28,3 +28,3 @@ /**

const lastCluster = this.getLastCluster();
(0, core_utils_1.assert)(lastCluster === undefined ||
(0, internal_1.assert)(lastCluster === undefined ||
// eslint-disable-next-line @typescript-eslint/restrict-plus-operands

@@ -31,0 +31,0 @@ newCluster.baseFinalId === lastCluster.baseFinalId + lastCluster.capacity, 0x753 /* Cluster insert to final_space is out of order. */);

@@ -7,5 +7,5 @@ /*!

import { ITelemetryLoggerExt } from "@fluidframework/telemetry-utils";
import { IdCreationRange, IIdCompressor, IIdCompressorCore, OpSpaceCompressedId, SerializedIdCompressorWithNoSession, SerializedIdCompressorWithOngoingSession, SessionId, SessionSpaceCompressedId, StableId } from "./types/index.js";
import { Index } from "./persistanceUtilities.js";
import { Sessions } from "./sessions.js";
import { IIdCompressor, IIdCompressorCore, IdCreationRange, OpSpaceCompressedId, SerializedIdCompressorWithNoSession, SerializedIdCompressorWithOngoingSession, SessionId, SessionSpaceCompressedId, StableId } from "./types/index.js";
/**

@@ -12,0 +12,0 @@ * See {@link IIdCompressor} and {@link IIdCompressorCore}

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

exports.deserializeIdCompressor = exports.createIdCompressor = exports.IdCompressor = void 0;
const core_utils_1 = require("@fluidframework/core-utils");
const client_utils_1 = require("@fluid-internal/client-utils");
const telemetry_utils_1 = require("@fluidframework/telemetry-utils");
const internal_1 = require("@fluidframework/core-utils/internal");
const internal_2 = require("@fluidframework/telemetry-utils/internal");
const finalSpace_js_1 = require("./finalSpace.js");
const identifiers_js_1 = require("./identifiers.js");
const utilities_js_1 = require("./utilities.js");
const persistanceUtilities_js_1 = require("./persistanceUtilities.js");
const sessionSpaceNormalizer_js_1 = require("./sessionSpaceNormalizer.js");
const sessions_js_1 = require("./sessions.js");
const sessionSpaceNormalizer_js_1 = require("./sessionSpaceNormalizer.js");
const finalSpace_js_1 = require("./finalSpace.js");
const utilities_js_1 = require("./utilities.js");
/**

@@ -64,3 +64,3 @@ * The version of IdCompressor that is currently persisted.

const firstSession = localSessionIdOrDeserialized.sessions().next();
(0, core_utils_1.assert)(!firstSession.done, 0x754 /* First session must be present. */);
(0, internal_1.assert)(!firstSession.done, 0x754 /* First session must be present. */);
this.localSession = firstSession.value;

@@ -115,3 +115,3 @@ this.localSessionId = (0, utilities_js_1.stableIdFromNumericUuid)(this.localSession.sessionUuid);

startGhostSession(ghostSessionId) {
(0, core_utils_1.assert)(!this.ongoingGhostSession, 0x8fe /* Ghost session already in progress. */);
(0, internal_1.assert)(!this.ongoingGhostSession, 0x8fe /* Ghost session already in progress. */);
this.ongoingGhostSession = { ghostSessionId };

@@ -137,3 +137,3 @@ }

takeNextCreationRange() {
(0, core_utils_1.assert)(!this.ongoingGhostSession, 0x8a6 /* IdCompressor should not be operated normally when in a ghost session */);
(0, internal_1.assert)(!this.ongoingGhostSession, 0x8a6 /* IdCompressor should not be operated normally when in a ghost session */);
const count = this.localGenCount - (this.nextRangeBaseGenCount - 1);

@@ -151,2 +151,3 @@ if (count === 0) {

requestedClusterSize: this.nextRequestedClusterSize,
localIdRanges: this.normalizer.getRangesBetween(this.nextRangeBaseGenCount, this.localGenCount),
},

@@ -163,8 +164,8 @@ };

const { count, requestedClusterSize } = range.ids;
(0, core_utils_1.assert)(count > 0, 0x755 /* Malformed ID Range. */);
(0, core_utils_1.assert)(requestedClusterSize > 0, 0x876 /* Clusters must have a positive capacity. */);
(0, core_utils_1.assert)(requestedClusterSize <= IdCompressor.maxClusterSize, 0x877 /* Clusters must not exceed max cluster size. */);
(0, internal_1.assert)(count > 0, 0x755 /* Malformed ID Range. */);
(0, internal_1.assert)(requestedClusterSize > 0, 0x876 /* Clusters must have a positive capacity. */);
(0, internal_1.assert)(requestedClusterSize <= IdCompressor.maxClusterSize, 0x877 /* Clusters must not exceed max cluster size. */);
}
finalizeCreationRange(range) {
(0, core_utils_1.assert)(!this.ongoingGhostSession, 0x8a7 /* IdCompressor should not be operated normally when in a ghost session */);
(0, internal_1.assert)(!this.ongoingGhostSession, 0x8a7 /* IdCompressor should not be operated normally when in a ghost session */);
// Check if the range has IDs

@@ -209,3 +210,3 @@ if (range.ids === undefined) {

lastCluster.count += count;
(0, core_utils_1.assert)(!this.sessions.clusterCollides(lastCluster), 0x756 /* Cluster collision detected. */);
(0, internal_1.assert)(!this.sessions.clusterCollides(lastCluster), 0x756 /* Cluster collision detected. */);
if (isLocal) {

@@ -244,8 +245,8 @@ this.logger?.sendTelemetryEvent({

}
(0, core_utils_1.assert)(!session.isEmpty(), 0x757 /* Empty sessions should not be created. */);
(0, internal_1.assert)(!session.isEmpty(), 0x757 /* Empty sessions should not be created. */);
}
addEmptyCluster(session, capacity) {
(0, core_utils_1.assert)(!this.ongoingGhostSession?.cluster, 0x8a8 /* IdCompressor should not be operated normally when in a ghost session */);
(0, internal_1.assert)(!this.ongoingGhostSession?.cluster, 0x8a8 /* IdCompressor should not be operated normally when in a ghost session */);
const newCluster = session.addNewCluster(this.finalSpace.getAllocatedIdLimit(), capacity, 0);
(0, core_utils_1.assert)(!this.sessions.clusterCollides(newCluster), 0x758 /* Cluster collision detected. */);
(0, internal_1.assert)(!this.sessions.clusterCollides(newCluster), 0x758 /* Cluster collision detected. */);
this.finalSpace.addCluster(newCluster);

@@ -329,3 +330,3 @@ return newCluster;

if (containingCluster.session === this.localSession) {
(0, core_utils_1.assert)(!this.normalizer.contains(alignedLocal), 0x759 /* Normalizer out of sync. */);
(0, internal_1.assert)(!this.normalizer.contains(alignedLocal), 0x759 /* Normalizer out of sync. */);
}

@@ -375,3 +376,3 @@ else {

else {
(0, core_utils_1.assert)((0, utilities_js_1.genCountFromLocalId)(alignedLocal) <= this.localGenCount, 0x75a /* Clusters out of sync. */);
(0, internal_1.assert)((0, utilities_js_1.genCountFromLocalId)(alignedLocal) <= this.localGenCount, 0x75a /* Clusters out of sync. */);
// Id is an eager final

@@ -390,3 +391,3 @@ return (0, sessions_js_1.getAlignedFinal)(containingCluster, alignedLocal);

serialize(hasLocalState) {
(0, core_utils_1.assert)(!this.ongoingGhostSession, 0x8a9 /* IdCompressor should not be operated normally when in a ghost session */);
(0, internal_1.assert)(!this.ongoingGhostSession, 0x8a9 /* IdCompressor should not be operated normally when in a ghost session */);
const { normalizer, finalSpace, sessions } = this;

@@ -440,3 +441,3 @@ const sessionIndexMap = new Map();

}
(0, core_utils_1.assert)(index === totalSize, 0x75b /* Serialized size was incorrectly calculated. */);
(0, internal_1.assert)(index === totalSize, 0x75b /* Serialized size was incorrectly calculated. */);
this.logger?.sendTelemetryEvent({

@@ -484,3 +485,3 @@ eventName: "RuntimeIdCompressor:SerializedIdCompressorSize",

// If !hasLocalState, there won't be a serialized local session ID so insert one at the beginning
(0, core_utils_1.assert)(sessionId !== undefined, 0x75d /* Local session ID is undefined. */);
(0, internal_1.assert)(sessionId !== undefined, 0x75d /* Local session ID is undefined. */);
const localSessionNumeric = (0, utilities_js_1.numericUuidFromStableId)(sessionId);

@@ -491,3 +492,3 @@ sessions.push([localSessionNumeric, new sessions_js_1.Session(localSessionNumeric)]);

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

@@ -519,3 +520,3 @@ for (let i = 0; i < sessionCount; i++) {

}
(0, core_utils_1.assert)(index.index === index.bufferFloat.length, 0x75f /* Failed to read entire serialized compressor. */);
(0, internal_1.assert)(index.index === index.bufferFloat.length, 0x75f /* Failed to read entire serialized compressor. */);
return compressor;

@@ -557,3 +558,3 @@ }

}
const compressor = new IdCompressor(localSessionId, logger === undefined ? undefined : (0, telemetry_utils_1.createChildLogger)({ logger }));
const compressor = new IdCompressor(localSessionId, logger === undefined ? undefined : (0, internal_2.createChildLogger)({ logger }));
return compressor;

@@ -560,0 +561,0 @@ }

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

export declare const pkgName = "@fluidframework/id-compressor";
export declare const pkgVersion = "2.0.0-rc.2.0.2";
export declare const pkgVersion = "2.0.0-rc.3.0.0";
//# sourceMappingURL=packageVersion.d.ts.map

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

exports.pkgName = "@fluidframework/id-compressor";
exports.pkgVersion = "2.0.0-rc.2.0.2";
exports.pkgVersion = "2.0.0-rc.3.0.0";
//# sourceMappingURL=packageVersion.js.map

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

*/
import { FinalCompressedId, LocalCompressedId, NumericUuid } from "./identifiers.js";
import { SessionId, StableId } from "./types/index.js";
import { FinalCompressedId, LocalCompressedId, NumericUuid } from "./identifiers.js";
/**

@@ -9,0 +9,0 @@ * A collection of all sessions known to the compressor (i.e. all finalized/acked allocated UUIDs and their corresponding local and final forms).

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

exports.lastFinalizedLocal = exports.lastAllocatedLocal = exports.lastFinalizedFinal = exports.lastAllocatedFinal = exports.getAlignedLocal = exports.getAlignedFinal = exports.clustersEqual = exports.Session = exports.Sessions = void 0;
const internal_1 = require("@fluidframework/core-utils/internal");
const sorted_btree_es6_1 = require("@tylerbu/sorted-btree-es6");
const core_utils_1 = require("@fluidframework/core-utils");
const utilities_js_1 = require("./utilities.js");

@@ -44,3 +44,3 @@ /**

const session = new Session(sessionId);
(0, core_utils_1.assert)(this.uuidSpace.set(session.sessionUuid, session), 0x760 /* Duplicate session in map. */);
(0, internal_1.assert)(this.uuidSpace.set(session.sessionUuid, session), 0x760 /* Duplicate session in map. */);
this.sessionCache.set(sessionId, session);

@@ -92,3 +92,3 @@ return session;

const [_, session] = closestMatch;
(0, core_utils_1.assert)(session !== owningSession, 0x761 /* Failed to attempt to detect collisions. */);
(0, internal_1.assert)(session !== owningSession, 0x761 /* Failed to attempt to detect collisions. */);
const lastCluster = session.getLastCluster();

@@ -114,3 +114,3 @@ if (lastCluster === undefined) {

}
(0, core_utils_1.assert)(session === firstSessionThis, 0x762 /* The only non-empty session must be the local session. */);
(0, internal_1.assert)(session === firstSessionThis, 0x762 /* The only non-empty session must be the local session. */);
}

@@ -273,3 +273,3 @@ else if (!session.equals(otherSession)) {

function getAlignedLocal(cluster, finalWithin) {
(0, core_utils_1.assert)(finalWithin >= cluster.baseFinalId && finalWithin <= lastAllocatedFinal(cluster), 0x763 /* Supplied ID is not within the cluster. */);
(0, internal_1.assert)(finalWithin >= cluster.baseFinalId && finalWithin <= lastAllocatedFinal(cluster), 0x763 /* Supplied ID is not within the cluster. */);
const finalDelta = finalWithin - cluster.baseFinalId;

@@ -276,0 +276,0 @@ return (cluster.baseLocalId - finalDelta);

@@ -42,2 +42,4 @@ /*!

get idRanges(): Pick<AppendOnlySortedMap<number, number>, "size" | "entries">;
getRangesBetween(firstGenCount: number, lastGenCount: number): [genCount: number, count: number][];
private rangeContains;
addLocalRange(baseGenCount: number, count: number): void;

@@ -44,0 +46,0 @@ contains(query: LocalCompressedId): boolean;

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

exports.SessionSpaceNormalizer = void 0;
const internal_1 = require("@fluidframework/core-utils/internal");
const appendOnlySortedMap_js_1 = require("./appendOnlySortedMap.js");

@@ -52,2 +53,45 @@ const utilities_js_1 = require("./utilities.js");

}
getRangesBetween(firstGenCount, lastGenCount) {
const ranges = [];
// we need to find the first range that either contains firstGenCount or is after it,
// since this method must find ranges between firstGenCount and lastGenCount
let firstRange = this.localIdRanges.getPairOrNextLower(firstGenCount);
// if the first range does not contain the first ID, next higher range is between but non-containing
if (firstRange === undefined || !this.rangeContains(firstRange, firstGenCount)) {
firstRange = this.localIdRanges.getPairOrNextHigher(firstGenCount);
if (firstRange === undefined) {
return ranges;
}
}
for (const [genCount, count] of this.localIdRanges.getRange(firstRange[0], lastGenCount)) {
ranges.push([genCount, count]);
}
if (ranges.length === 0) {
return ranges;
}
// now we touch up the first and last ranges to ensure that if they contain the
// queried IDs they are trimmed to start/end with the queried IDs
const [baseGenCount, baseCount] = ranges[0];
if (this.rangeContains(ranges[0], firstGenCount)) {
ranges[0] = [firstGenCount, baseCount - (firstGenCount - baseGenCount)];
(0, internal_1.assert)(this.rangeContains(ranges[0], firstGenCount), 0x952 /* Expected the touched up range to contain the queried ID */);
}
else {
(0, internal_1.assert)(baseGenCount > firstGenCount, 0x953 /* Expected the first range to start after the queried ID */);
}
const lastRangeIndex = ranges.length - 1;
const [limitGenCount, limitCount] = ranges[lastRangeIndex];
if (this.rangeContains(ranges[lastRangeIndex], lastGenCount)) {
ranges[lastRangeIndex] = [limitGenCount, lastGenCount - limitGenCount + 1];
(0, internal_1.assert)(this.rangeContains(ranges[lastRangeIndex], lastGenCount), 0x954 /* Expected the touched up range to contain the queried ID */);
}
else {
(0, internal_1.assert)(limitGenCount + limitCount - 1 < lastGenCount, 0x955 /* Expected the last range to end before the queried ID */);
}
return ranges;
}
rangeContains(range, genCount) {
const [baseGenCount, count] = range;
return genCount >= baseGenCount && genCount < baseGenCount + count;
}
addLocalRange(baseGenCount, count) {

@@ -54,0 +98,0 @@ const last = this.localIdRanges.last();

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

*/
import { Generator, SaveInfo, BaseFuzzTestState } from "@fluid-private/stochastic-test-utils";
import { BaseFuzzTestState, Generator, SaveInfo } from "@fluid-private/stochastic-test-utils";
import { ITelemetryBaseLogger } from "@fluidframework/core-interfaces";
import { OpSpaceCompressedId, SerializedIdCompressorWithNoSession, SerializedIdCompressorWithOngoingSession, SessionId, SessionSpaceCompressedId, type IIdCompressor, type IIdCompressorCore } from "..//index.js";
import { IdCompressor } from "../idCompressor.js";
import { type IIdCompressor, type IIdCompressorCore, OpSpaceCompressedId, SerializedIdCompressorWithNoSession, SerializedIdCompressorWithOngoingSession, SessionId, SessionSpaceCompressedId } from "../index.js";
import { ReadonlyIdCompressor } from "./testCommon.js";

@@ -11,0 +11,0 @@ /**

@@ -10,4 +10,4 @@ "use strict";

const stochastic_test_utils_1 = require("@fluid-private/stochastic-test-utils");
const index_js_1 = require("..//index.js");
const idCompressor_js_1 = require("../idCompressor.js");
const index_js_1 = require("../index.js");
const utilities_js_1 = require("../utilities.js");

@@ -77,2 +77,3 @@ const testCommon_js_1 = require("./testCommon.js");

requestedClusterSize: capacity,
localIdRanges: [], // remote session, can safely ignore in tests
},

@@ -223,2 +224,3 @@ });

"nextRequestedClusterSize"],
localIdRanges: [], // remote session, can safely ignore in tests
},

@@ -289,2 +291,24 @@ };

const sequencedLogs = Object.values(Client).map((client) => [this.compressors.get(client), this.getSequencedIdLog(client)]);
// Ensure creation ranges for clients we track contain the correct local ID ranges
this.serverOperations.forEach(([range, opSpaceIds, clientFrom]) => {
const localIdsInCreationRange = new Set();
if (clientFrom !== exports.OriginatingClient.Remote) {
const ids = range.ids;
if (ids !== undefined) {
const { firstGenCount, localIdRanges } = ids;
for (const [genCount, count] of localIdRanges) {
for (let g = genCount; g < genCount + count; g++) {
const local = (0, utilities_js_1.localIdFromGenCount)(g);
assert_1.strict.strictEqual(opSpaceIds[g - firstGenCount], local);
localIdsInCreationRange.add(local);
}
}
}
opSpaceIds.forEach((id) => {
if ((0, testCommon_js_1.isLocalId)(id)) {
(0, assert_1.strict)(localIdsInCreationRange.has(id), "Local ID not in creation range");
}
});
}
});
// First, ensure all clients each generated a unique ID for each of their own calls to generate.

@@ -291,0 +315,0 @@ for (const [compressor, ids] of sequencedLogs) {

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

*/
import { SessionSpaceCompressedId, StableId, OpSpaceCompressedId } from "..//index.js";
import { IdCompressor } from "../idCompressor.js";
import { OpSpaceCompressedId, SessionSpaceCompressedId, StableId } from "../index.js";
/**

@@ -9,0 +9,0 @@ * An identifier (v4 UUID) that has been shortened by a distributed compression algorithm.

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

exports.fail = exports.assertNotUndefined = exports.incrementStableId = exports.getOrCreate = exports.makeLocalId = exports.isLocalId = exports.isFinalId = void 0;
const core_utils_1 = require("@fluidframework/core-utils");
const internal_1 = require("@fluidframework/core-utils/internal");
const utilities_js_1 = require("../utilities.js");

@@ -30,3 +30,3 @@ /**

const id = negativeInteger;
(0, core_utils_1.assert)(isLocalId(id), "Not a negative integer.");
(0, internal_1.assert)(isLocalId(id), "Not a negative integer.");
return id;

@@ -79,3 +79,3 @@ }

function assertNotUndefined(value, message = "value must not be undefined") {
(0, core_utils_1.assert)(value !== undefined, message);
(0, internal_1.assert)(value !== undefined, message);
return value;

@@ -90,5 +90,5 @@ }

function fail(message) {
(0, core_utils_1.assert)(false, message);
(0, internal_1.assert)(false, message);
}
exports.fail = fail;
//# sourceMappingURL=testCommon.js.map

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

*/
import { SessionSpaceCompressedId, OpSpaceCompressedId, SessionId, StableId } from "./identifiers.js";
import { OpSpaceCompressedId, SessionId, SessionSpaceCompressedId, StableId } from "./identifiers.js";
import { IdCreationRange, SerializedIdCompressorWithNoSession, SerializedIdCompressorWithOngoingSession } from "./persisted-types/index.js";

@@ -103,3 +103,3 @@ /**

*/
beginGhostSession(ghostSessionId: SessionId, ghostSessionCallback: () => void): any;
beginGhostSession(ghostSessionId: SessionId, ghostSessionCallback: () => void): void;
/**

@@ -106,0 +106,0 @@ * Returns a persistable form of the current state of this `IdCompressor` which can be rehydrated via `IdCompressor.deserialize()`.

@@ -50,4 +50,8 @@ /*!

readonly requestedClusterSize: number;
/**
* The ranges of IDs that were allocated as local IDs in the range created by `sessionId.`
*/
readonly localIdRanges: [genCount: number, count: number][];
};
}
//# sourceMappingURL=0.0.1.d.ts.map

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

*/
import { LocalCompressedId, NumericUuid } from "./identifiers.js";
import { SessionId, StableId } from "./types/index.js";
import { LocalCompressedId, NumericUuid } from "./identifiers.js";
/**

@@ -9,0 +9,0 @@ * Generate a random session ID

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

/* eslint-disable no-bitwise */
const core_utils_1 = require("@fluidframework/core-utils");
const internal_1 = require("@fluidframework/core-utils/internal");
const uuid_1 = require("uuid");

@@ -31,3 +31,3 @@ const hexadecimalCharCodes = Array.from("09afAF").map((c) => c.charCodeAt(0));

function assertIsStableId(stableId) {
(0, core_utils_1.assert)(isStableId(stableId), 0x4a3 /* Expected a StableId */);
(0, internal_1.assert)(isStableId(stableId), 0x4a3 /* Expected a StableId */);
return stableId;

@@ -34,0 +34,0 @@ }

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

/* eslint-disable no-bitwise */
import { assert } from "@fluidframework/core-utils";
import { assert } from "@fluidframework/core-utils/internal";
/**

@@ -10,0 +10,0 @@ * A map in which entries are always added in key-sorted order.

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

*/
import { FinalCompressedId } from "./identifiers.js";
import { IdCluster } from "./sessions.js";
import { FinalCompressedId } from "./identifiers.js";
/**

@@ -9,0 +9,0 @@ * All IDs that have been finalized (acked), grouped into clusters sorted by their base final IDs.

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

*/
import { assert } from "@fluidframework/core-utils";
import { assert } from "@fluidframework/core-utils/internal";
import { clustersEqual, lastAllocatedFinal, lastFinalizedFinal } from "./sessions.js";

@@ -8,0 +8,0 @@ /**

@@ -7,5 +7,5 @@ /*!

import { ITelemetryLoggerExt } from "@fluidframework/telemetry-utils";
import { IdCreationRange, IIdCompressor, IIdCompressorCore, OpSpaceCompressedId, SerializedIdCompressorWithNoSession, SerializedIdCompressorWithOngoingSession, SessionId, SessionSpaceCompressedId, StableId } from "./types/index.js";
import { Index } from "./persistanceUtilities.js";
import { Sessions } from "./sessions.js";
import { IIdCompressor, IIdCompressorCore, IdCreationRange, OpSpaceCompressedId, SerializedIdCompressorWithNoSession, SerializedIdCompressorWithOngoingSession, SessionId, SessionSpaceCompressedId, StableId } from "./types/index.js";
/**

@@ -12,0 +12,0 @@ * See {@link IIdCompressor} and {@link IIdCompressorCore}

@@ -5,11 +5,11 @@ /*!

*/
import { assert } from "@fluidframework/core-utils";
import { bufferToString, stringToBuffer } from "@fluid-internal/client-utils";
import { createChildLogger } from "@fluidframework/telemetry-utils";
import { assert } from "@fluidframework/core-utils/internal";
import { createChildLogger } from "@fluidframework/telemetry-utils/internal";
import { FinalSpace } from "./finalSpace.js";
import { isFinalId } from "./identifiers.js";
import { createSessionId, localIdFromGenCount, genCountFromLocalId, numericUuidFromStableId, offsetNumericUuid, stableIdFromNumericUuid, subtractNumericUuids, } from "./utilities.js";
import { readBoolean, readNumber, readNumericUuid, writeBoolean, writeNumber, writeNumericUuid, } from "./persistanceUtilities.js";
import { getAlignedLocal, getAlignedFinal, lastFinalizedLocal, Session, Sessions, lastFinalizedFinal, } from "./sessions.js";
import { SessionSpaceNormalizer } from "./sessionSpaceNormalizer.js";
import { FinalSpace } from "./finalSpace.js";
import { Session, Sessions, getAlignedFinal, getAlignedLocal, lastFinalizedFinal, lastFinalizedLocal, } from "./sessions.js";
import { createSessionId, genCountFromLocalId, localIdFromGenCount, numericUuidFromStableId, offsetNumericUuid, stableIdFromNumericUuid, subtractNumericUuids, } from "./utilities.js";
/**

@@ -145,2 +145,3 @@ * The version of IdCompressor that is currently persisted.

requestedClusterSize: this.nextRequestedClusterSize,
localIdRanges: this.normalizer.getRangesBetween(this.nextRangeBaseGenCount, this.localGenCount),
},

@@ -147,0 +148,0 @@ };

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

export declare const pkgName = "@fluidframework/id-compressor";
export declare const pkgVersion = "2.0.0-rc.2.0.2";
export declare const pkgVersion = "2.0.0-rc.3.0.0";
//# sourceMappingURL=packageVersion.d.ts.map

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

export const pkgName = "@fluidframework/id-compressor";
export const pkgVersion = "2.0.0-rc.2.0.2";
export const pkgVersion = "2.0.0-rc.3.0.0";
//# sourceMappingURL=packageVersion.js.map

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

*/
import { FinalCompressedId, LocalCompressedId, NumericUuid } from "./identifiers.js";
import { SessionId, StableId } from "./types/index.js";
import { FinalCompressedId, LocalCompressedId, NumericUuid } from "./identifiers.js";
/**

@@ -9,0 +9,0 @@ * A collection of all sessions known to the compressor (i.e. all finalized/acked allocated UUIDs and their corresponding local and final forms).

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

*/
import { assert } from "@fluidframework/core-utils/internal";
import { BTree } from "@tylerbu/sorted-btree-es6";
import { assert } from "@fluidframework/core-utils";
import { compareBigints, localIdFromGenCount, genCountFromLocalId, numericUuidFromStableId, stableIdFromNumericUuid, subtractNumericUuids, offsetNumericUuid, } from "./utilities.js";
import { compareBigints, genCountFromLocalId, localIdFromGenCount, numericUuidFromStableId, offsetNumericUuid, stableIdFromNumericUuid, subtractNumericUuids, } from "./utilities.js";
/**

@@ -10,0 +10,0 @@ * A collection of all sessions known to the compressor (i.e. all finalized/acked allocated UUIDs and their corresponding local and final forms).

@@ -42,2 +42,4 @@ /*!

get idRanges(): Pick<AppendOnlySortedMap<number, number>, "size" | "entries">;
getRangesBetween(firstGenCount: number, lastGenCount: number): [genCount: number, count: number][];
private rangeContains;
addLocalRange(baseGenCount: number, count: number): void;

@@ -44,0 +46,0 @@ contains(query: LocalCompressedId): boolean;

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

*/
import { assert } from "@fluidframework/core-utils/internal";
import { AppendOnlySortedMap } from "./appendOnlySortedMap.js";

@@ -49,2 +50,45 @@ import { compareFiniteNumbers, genCountFromLocalId } from "./utilities.js";

}
getRangesBetween(firstGenCount, lastGenCount) {
const ranges = [];
// we need to find the first range that either contains firstGenCount or is after it,
// since this method must find ranges between firstGenCount and lastGenCount
let firstRange = this.localIdRanges.getPairOrNextLower(firstGenCount);
// if the first range does not contain the first ID, next higher range is between but non-containing
if (firstRange === undefined || !this.rangeContains(firstRange, firstGenCount)) {
firstRange = this.localIdRanges.getPairOrNextHigher(firstGenCount);
if (firstRange === undefined) {
return ranges;
}
}
for (const [genCount, count] of this.localIdRanges.getRange(firstRange[0], lastGenCount)) {
ranges.push([genCount, count]);
}
if (ranges.length === 0) {
return ranges;
}
// now we touch up the first and last ranges to ensure that if they contain the
// queried IDs they are trimmed to start/end with the queried IDs
const [baseGenCount, baseCount] = ranges[0];
if (this.rangeContains(ranges[0], firstGenCount)) {
ranges[0] = [firstGenCount, baseCount - (firstGenCount - baseGenCount)];
assert(this.rangeContains(ranges[0], firstGenCount), 0x952 /* Expected the touched up range to contain the queried ID */);
}
else {
assert(baseGenCount > firstGenCount, 0x953 /* Expected the first range to start after the queried ID */);
}
const lastRangeIndex = ranges.length - 1;
const [limitGenCount, limitCount] = ranges[lastRangeIndex];
if (this.rangeContains(ranges[lastRangeIndex], lastGenCount)) {
ranges[lastRangeIndex] = [limitGenCount, lastGenCount - limitGenCount + 1];
assert(this.rangeContains(ranges[lastRangeIndex], lastGenCount), 0x954 /* Expected the touched up range to contain the queried ID */);
}
else {
assert(limitGenCount + limitCount - 1 < lastGenCount, 0x955 /* Expected the last range to end before the queried ID */);
}
return ranges;
}
rangeContains(range, genCount) {
const [baseGenCount, count] = range;
return genCount >= baseGenCount && genCount < baseGenCount + count;
}
addLocalRange(baseGenCount, count) {

@@ -51,0 +95,0 @@ const last = this.localIdRanges.last();

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

*/
import { Generator, SaveInfo, BaseFuzzTestState } from "@fluid-private/stochastic-test-utils";
import { BaseFuzzTestState, Generator, SaveInfo } from "@fluid-private/stochastic-test-utils";
import { ITelemetryBaseLogger } from "@fluidframework/core-interfaces";
import { OpSpaceCompressedId, SerializedIdCompressorWithNoSession, SerializedIdCompressorWithOngoingSession, SessionId, SessionSpaceCompressedId, type IIdCompressor, type IIdCompressorCore } from "..//index.js";
import { IdCompressor } from "../idCompressor.js";
import { type IIdCompressor, type IIdCompressorCore, OpSpaceCompressedId, SerializedIdCompressorWithNoSession, SerializedIdCompressorWithOngoingSession, SessionId, SessionSpaceCompressedId } from "../index.js";
import { ReadonlyIdCompressor } from "./testCommon.js";

@@ -11,0 +11,0 @@ /**

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

import { createWeightedGenerator, interleave, makeRandom, performFuzzActions as performFuzzActionsBase, repeat, take, } from "@fluid-private/stochastic-test-utils";
import { createIdCompressor, } from "..//index.js";
import { IdCompressor } from "../idCompressor.js";
import { assertIsSessionId, createSessionId } from "../utilities.js";
import { getOrCreate, incrementStableId, isFinalId, isLocalId, fail, } from "./testCommon.js";
import { createIdCompressor, } from "../index.js";
import { assertIsSessionId, createSessionId, localIdFromGenCount } from "../utilities.js";
import { fail, getOrCreate, incrementStableId, isFinalId, isLocalId, } from "./testCommon.js";
/** Identifies a compressor in a network */

@@ -73,2 +73,3 @@ export var Client;

requestedClusterSize: capacity,
localIdRanges: [], // remote session, can safely ignore in tests
},

@@ -218,2 +219,3 @@ });

"nextRequestedClusterSize"],
localIdRanges: [], // remote session, can safely ignore in tests
},

@@ -284,2 +286,24 @@ };

const sequencedLogs = Object.values(Client).map((client) => [this.compressors.get(client), this.getSequencedIdLog(client)]);
// Ensure creation ranges for clients we track contain the correct local ID ranges
this.serverOperations.forEach(([range, opSpaceIds, clientFrom]) => {
const localIdsInCreationRange = new Set();
if (clientFrom !== OriginatingClient.Remote) {
const ids = range.ids;
if (ids !== undefined) {
const { firstGenCount, localIdRanges } = ids;
for (const [genCount, count] of localIdRanges) {
for (let g = genCount; g < genCount + count; g++) {
const local = localIdFromGenCount(g);
assert.strictEqual(opSpaceIds[g - firstGenCount], local);
localIdsInCreationRange.add(local);
}
}
}
opSpaceIds.forEach((id) => {
if (isLocalId(id)) {
assert(localIdsInCreationRange.has(id), "Local ID not in creation range");
}
});
}
});
// First, ensure all clients each generated a unique ID for each of their own calls to generate.

@@ -286,0 +310,0 @@ for (const [compressor, ids] of sequencedLogs) {

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

*/
import { SessionSpaceCompressedId, StableId, OpSpaceCompressedId } from "..//index.js";
import { IdCompressor } from "../idCompressor.js";
import { OpSpaceCompressedId, SessionSpaceCompressedId, StableId } from "../index.js";
/**

@@ -9,0 +9,0 @@ * An identifier (v4 UUID) that has been shortened by a distributed compression algorithm.

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

*/
import { assert } from "@fluidframework/core-utils";
import { assert } from "@fluidframework/core-utils/internal";
import { numericUuidFromStableId, offsetNumericUuid, stableIdFromNumericUuid, } from "../utilities.js";

@@ -8,0 +8,0 @@ /**

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

*/
import { SessionSpaceCompressedId, OpSpaceCompressedId, SessionId, StableId } from "./identifiers.js";
import { OpSpaceCompressedId, SessionId, SessionSpaceCompressedId, StableId } from "./identifiers.js";
import { IdCreationRange, SerializedIdCompressorWithNoSession, SerializedIdCompressorWithOngoingSession } from "./persisted-types/index.js";

@@ -103,3 +103,3 @@ /**

*/
beginGhostSession(ghostSessionId: SessionId, ghostSessionCallback: () => void): any;
beginGhostSession(ghostSessionId: SessionId, ghostSessionCallback: () => void): void;
/**

@@ -106,0 +106,0 @@ * Returns a persistable form of the current state of this `IdCompressor` which can be rehydrated via `IdCompressor.deserialize()`.

@@ -50,4 +50,8 @@ /*!

readonly requestedClusterSize: number;
/**
* The ranges of IDs that were allocated as local IDs in the range created by `sessionId.`
*/
readonly localIdRanges: [genCount: number, count: number][];
};
}
//# sourceMappingURL=0.0.1.d.ts.map

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

*/
import { LocalCompressedId, NumericUuid } from "./identifiers.js";
import { SessionId, StableId } from "./types/index.js";
import { LocalCompressedId, NumericUuid } from "./identifiers.js";
/**

@@ -9,0 +9,0 @@ * Generate a random session ID

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

/* eslint-disable no-bitwise */
import { assert } from "@fluidframework/core-utils";
import { assert } from "@fluidframework/core-utils/internal";
import { v4 } from "uuid";

@@ -9,0 +9,0 @@ const hexadecimalCharCodes = Array.from("09afAF").map((c) => c.charCodeAt(0));

{
"name": "@fluidframework/id-compressor",
"version": "2.0.0-rc.2.0.2",
"version": "2.0.0-rc.3.0.0",
"description": "ID compressor",

@@ -18,30 +18,20 @@ "homepage": "https://fluidframework.com",

"import": {
"types": "./lib/index.d.ts",
"types": "./lib/public.d.ts",
"default": "./lib/index.js"
},
"require": {
"types": "./dist/index.d.ts",
"types": "./dist/public.d.ts",
"default": "./dist/index.js"
}
},
"./public": {
"./legacy": {
"import": {
"types": "./lib/id-compressor-public.d.ts",
"types": "./lib/legacy.d.ts",
"default": "./lib/index.js"
},
"require": {
"types": "./dist/id-compressor-public.d.ts",
"types": "./dist/legacy.d.ts",
"default": "./dist/index.js"
}
},
"./alpha": {
"import": {
"types": "./lib/id-compressor-alpha.d.ts",
"default": "./lib/index.js"
},
"require": {
"types": "./dist/id-compressor-alpha.d.ts",
"default": "./dist/index.js"
}
},
"./internal": {

@@ -57,3 +47,3 @@ "import": {

},
"./test": {
"./internal/test-utils": {
"import": {

@@ -67,16 +57,6 @@ "types": "./lib/test/index.d.ts",

}
},
"./test/idCompressorTestUtilities": {
"import": {
"types": "./lib/test/idCompressorTestUtilities.d.ts",
"default": "./lib/test/idCompressorTestUtilities.js"
},
"require": {
"types": "./dist/test/idCompressorTestUtilities.d.ts",
"default": "./dist/test/idCompressorTestUtilities.js"
}
}
},
"main": "dist/index.js",
"types": "dist/index.d.ts",
"main": "lib/index.js",
"types": "lib/public.d.ts",
"c8": {

@@ -87,3 +67,3 @@ "all": true,

"src/test/**/*.*ts",
"dist/test/**/*.*js"
"lib/test/**/*.*js"
],

@@ -93,3 +73,3 @@ "exclude-after-remap": false,

"src/**/*.*ts",
"dist/**/*.*js"
"lib/**/*.*js"
],

@@ -105,6 +85,6 @@ "report-dir": "nyc/report",

"dependencies": {
"@fluid-internal/client-utils": ">=2.0.0-rc.2.0.2 <2.0.0-rc.2.1.0",
"@fluidframework/core-interfaces": ">=2.0.0-rc.2.0.2 <2.0.0-rc.2.1.0",
"@fluidframework/core-utils": ">=2.0.0-rc.2.0.2 <2.0.0-rc.2.1.0",
"@fluidframework/telemetry-utils": ">=2.0.0-rc.2.0.2 <2.0.0-rc.2.1.0",
"@fluid-internal/client-utils": ">=2.0.0-rc.3.0.0 <2.0.0-rc.3.1.0",
"@fluidframework/core-interfaces": ">=2.0.0-rc.3.0.0 <2.0.0-rc.3.1.0",
"@fluidframework/core-utils": ">=2.0.0-rc.3.0.0 <2.0.0-rc.3.1.0",
"@fluidframework/telemetry-utils": ">=2.0.0-rc.3.0.0 <2.0.0-rc.3.1.0",
"@tylerbu/sorted-btree-es6": "^1.8.0",

@@ -114,13 +94,15 @@ "uuid": "^9.0.0"

"devDependencies": {
"@arethetypeswrong/cli": "^0.13.3",
"@fluid-internal/mocha-test-setup": ">=2.0.0-rc.2.0.2 <2.0.0-rc.2.1.0",
"@fluid-private/stochastic-test-utils": ">=2.0.0-rc.2.0.2 <2.0.0-rc.2.1.0",
"@arethetypeswrong/cli": "^0.15.2",
"@biomejs/biome": "^1.6.2",
"@fluid-internal/mocha-test-setup": ">=2.0.0-rc.3.0.0 <2.0.0-rc.3.1.0",
"@fluid-private/stochastic-test-utils": ">=2.0.0-rc.3.0.0 <2.0.0-rc.3.1.0",
"@fluid-tools/benchmark": "^0.48.0",
"@fluid-tools/build-cli": "^0.34.0",
"@fluid-tools/build-cli": "^0.37.0",
"@fluidframework/build-common": "^2.0.3",
"@fluidframework/build-tools": "^0.34.0",
"@fluidframework/eslint-config-fluid": "^4.0.0",
"@fluidframework/build-tools": "^0.37.0",
"@fluidframework/eslint-config-fluid": "^5.1.0",
"@fluidframework/id-compressor-previous": "npm:@fluidframework/id-compressor@2.0.0-internal.8.0.0",
"@microsoft/api-extractor": "^7.42.3",
"@types/mocha": "^9.1.1",
"@types/node": "^18.19.0",
"@types/uuid": "^9.0.2",

@@ -139,14 +121,2 @@ "c8": "^8.0.1",

},
"fluidBuild": {
"tasks": {
"build:docs": {
"dependsOn": [
"...",
"api-extractor:commonjs",
"api-extractor:esnext"
],
"script": false
}
}
},
"typeValidation": {

@@ -157,8 +127,8 @@ "broken": {}

"api": "fluid-build . --task api",
"api-extractor:commonjs": "api-extractor run --config ./api-extractor-cjs.json",
"api-extractor:esnext": "api-extractor run --local",
"api-extractor:commonjs": "flub generate entrypoints --outFileAlpha legacy --outDir ./dist",
"api-extractor:esnext": "flub generate entrypoints --outFileAlpha legacy --outDir ./lib --node10TypeCompat",
"build": "fluid-build . --task build",
"build:commonjs": "fluid-build . --task commonjs",
"build:compile": "fluid-build . --task compile",
"build:docs": "fluid-build . --task api",
"build:docs": "api-extractor run --local",
"build:esnext": "tsc --project ./tsconfig.json",

@@ -169,15 +139,15 @@ "build:genver": "gen-version",

"build:test:esm": "tsc --project ./src/test/tsconfig.json",
"check:are-the-types-wrong": "attw --pack . --entrypoints .",
"check:are-the-types-wrong": "attw --pack . --exclude-entrypoints ./internal/test-utils",
"check:prettier": "prettier --check . --cache --ignore-path ../../../.prettierignore",
"check:release-tags": "api-extractor run --local --config ./api-extractor-lint.json",
"ci:build:docs": "api-extractor run",
"clean": "rimraf --glob dist lib \"**/*.tsbuildinfo\" \"**/*.build.log\" _api-extractor-temp nyc",
"clean": "rimraf --glob dist lib \"*.d.ts\" \"**/*.tsbuildinfo\" \"**/*.build.log\" _api-extractor-temp nyc",
"eslint": "eslint --format stylish src",
"eslint:fix": "eslint --format stylish src --fix --fix-type problem,suggestion,layout",
"format": "npm run prettier:fix",
"lint": "npm run prettier && npm run check:release-tags && npm run eslint",
"lint:fix": "npm run prettier:fix && npm run eslint:fix",
"prettier": "prettier --check . --cache --ignore-path ../../../.prettierignore",
"prettier:fix": "prettier --write . --cache --ignore-path ../../../.prettierignore",
"format": "fluid-build --task format .",
"format:prettier": "prettier --write . --cache --ignore-path ../../../.prettierignore",
"lint": "fluid-build . --task lint",
"lint:fix": "fluid-build . --task eslint:fix --task format",
"test": "npm run test:mocha",
"test:benchmark:report": "mocha --timeout 999999 --perfMode --parentProcess --fgrep @Benchmark --reporter @fluid-tools/benchmark/dist/MochaReporter.js \"./dist/**/*.perf.spec.*js\"",
"test:benchmark:report": "mocha --timeout 999999 --perfMode --parentProcess --fgrep @Benchmark --reporter @fluid-tools/benchmark/dist/MochaReporter.js \"./lib/**/*.perf.spec.*js\"",
"test:coverage": "c8 npm test",

@@ -190,4 +160,4 @@ "test:mocha": "npm run test:mocha:esm && echo skipping cjs to avoid overhead - npm run test:mocha:cjs",

"tsc": "fluid-tsc commonjs --project ./tsconfig.cjs.json && copyfiles -f ../../../common/build/build-common/src/cjs/package.json ./dist",
"tsc:watch": "tsc --watch"
"tsc:watch": "copyfiles -f ../../../common/build/build-common/src/cjs/package.json ./dist && fluid-tsc commonjs --watch --project ./tsconfig.cjs.json"
}
}

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

/* eslint-disable no-bitwise */
import { assert } from "@fluidframework/core-utils";
import { assert } from "@fluidframework/core-utils/internal";

@@ -11,0 +11,0 @@ /**

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

import { assert } from "@fluidframework/core-utils";
import { assert } from "@fluidframework/core-utils/internal";
import { FinalCompressedId } from "./identifiers.js";
import { IdCluster, clustersEqual, lastAllocatedFinal, lastFinalizedFinal } from "./sessions.js";
import { FinalCompressedId } from "./identifiers.js";

@@ -11,0 +12,0 @@ /**

@@ -6,10 +6,33 @@ /*!

import { assert } from "@fluidframework/core-utils";
import { bufferToString, stringToBuffer } from "@fluid-internal/client-utils";
import { ITelemetryBaseLogger } from "@fluidframework/core-interfaces";
import { ITelemetryLoggerExt, createChildLogger } from "@fluidframework/telemetry-utils";
import { assert } from "@fluidframework/core-utils/internal";
import { ITelemetryLoggerExt } from "@fluidframework/telemetry-utils";
import { createChildLogger } from "@fluidframework/telemetry-utils/internal";
import { FinalSpace } from "./finalSpace.js";
import { FinalCompressedId, LocalCompressedId, NumericUuid, isFinalId } from "./identifiers.js";
import {
IdCreationRange,
Index,
readBoolean,
readNumber,
readNumericUuid,
writeBoolean,
writeNumber,
writeNumericUuid,
} from "./persistanceUtilities.js";
import { SessionSpaceNormalizer } from "./sessionSpaceNormalizer.js";
import {
IdCluster,
Session,
Sessions,
getAlignedFinal,
getAlignedLocal,
lastFinalizedFinal,
lastFinalizedLocal,
} from "./sessions.js";
import {
IIdCompressor,
IIdCompressorCore,
IdCreationRange,
OpSpaceCompressedId,

@@ -23,7 +46,6 @@ SerializedIdCompressor,

} from "./types/index.js";
import { FinalCompressedId, isFinalId, LocalCompressedId, NumericUuid } from "./identifiers.js";
import {
createSessionId,
genCountFromLocalId,
localIdFromGenCount,
genCountFromLocalId,
numericUuidFromStableId,

@@ -34,22 +56,2 @@ offsetNumericUuid,

} from "./utilities.js";
import {
Index,
readBoolean,
readNumber,
readNumericUuid,
writeBoolean,
writeNumber,
writeNumericUuid,
} from "./persistanceUtilities.js";
import {
getAlignedLocal,
getAlignedFinal,
IdCluster,
lastFinalizedLocal,
Session,
Sessions,
lastFinalizedFinal,
} from "./sessions.js";
import { SessionSpaceNormalizer } from "./sessionSpaceNormalizer.js";
import { FinalSpace } from "./finalSpace.js";

@@ -221,2 +223,6 @@ /**

requestedClusterSize: this.nextRequestedClusterSize,
localIdRanges: this.normalizer.getRangesBetween(
this.nextRangeBaseGenCount,
this.localGenCount,
),
},

@@ -223,0 +229,0 @@ };

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

export const pkgName = "@fluidframework/id-compressor";
export const pkgVersion = "2.0.0-rc.2.0.2";
export const pkgVersion = "2.0.0-rc.3.0.0";

@@ -6,15 +6,16 @@ /*!

import { assert } from "@fluidframework/core-utils/internal";
import { BTree } from "@tylerbu/sorted-btree-es6";
import { assert } from "@fluidframework/core-utils";
import { FinalCompressedId, LocalCompressedId, NumericUuid } from "./identifiers.js";
import { SessionId, StableId } from "./types/index.js";
import {
compareBigints,
genCountFromLocalId,
localIdFromGenCount,
genCountFromLocalId,
numericUuidFromStableId,
offsetNumericUuid,
stableIdFromNumericUuid,
subtractNumericUuids,
offsetNumericUuid,
} from "./utilities.js";
import { FinalCompressedId, LocalCompressedId, NumericUuid } from "./identifiers.js";

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

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

import { assert } from "@fluidframework/core-utils/internal";
import { AppendOnlySortedMap } from "./appendOnlySortedMap.js";

@@ -52,2 +53,64 @@ import { LocalCompressedId } from "./identifiers.js";

public getRangesBetween(
firstGenCount: number,
lastGenCount: number,
): [genCount: number, count: number][] {
const ranges: [genCount: number, count: number][] = [];
// we need to find the first range that either contains firstGenCount or is after it,
// since this method must find ranges between firstGenCount and lastGenCount
let firstRange = this.localIdRanges.getPairOrNextLower(firstGenCount);
// if the first range does not contain the first ID, next higher range is between but non-containing
if (firstRange === undefined || !this.rangeContains(firstRange, firstGenCount)) {
firstRange = this.localIdRanges.getPairOrNextHigher(firstGenCount);
if (firstRange === undefined) {
return ranges;
}
}
for (const [genCount, count] of this.localIdRanges.getRange(firstRange[0], lastGenCount)) {
ranges.push([genCount, count]);
}
if (ranges.length === 0) {
return ranges;
}
// now we touch up the first and last ranges to ensure that if they contain the
// queried IDs they are trimmed to start/end with the queried IDs
const [baseGenCount, baseCount] = ranges[0];
if (this.rangeContains(ranges[0], firstGenCount)) {
ranges[0] = [firstGenCount, baseCount - (firstGenCount - baseGenCount)];
assert(
this.rangeContains(ranges[0], firstGenCount),
0x952 /* Expected the touched up range to contain the queried ID */,
);
} else {
assert(
baseGenCount > firstGenCount,
0x953 /* Expected the first range to start after the queried ID */,
);
}
const lastRangeIndex = ranges.length - 1;
const [limitGenCount, limitCount] = ranges[lastRangeIndex];
if (this.rangeContains(ranges[lastRangeIndex], lastGenCount)) {
ranges[lastRangeIndex] = [limitGenCount, lastGenCount - limitGenCount + 1];
assert(
this.rangeContains(ranges[lastRangeIndex], lastGenCount),
0x954 /* Expected the touched up range to contain the queried ID */,
);
} else {
assert(
limitGenCount + limitCount - 1 < lastGenCount,
0x955 /* Expected the last range to end before the queried ID */,
);
}
return ranges;
}
private rangeContains(range: readonly [number, number], genCount: number): boolean {
const [baseGenCount, count] = range;
return genCount >= baseGenCount && genCount < baseGenCount + count;
}
public addLocalRange(baseGenCount: number, count: number): void {

@@ -54,0 +117,0 @@ const last = this.localIdRanges.last();

@@ -7,4 +7,7 @@ /*!

import { strict as assert } from "assert";
import {
BaseFuzzTestState,
Generator,
SaveInfo,
createWeightedGenerator,

@@ -15,9 +18,10 @@ interleave,

repeat,
SaveInfo,
take,
BaseFuzzTestState,
} from "@fluid-private/stochastic-test-utils";
import { ITelemetryBaseLogger } from "@fluidframework/core-interfaces";
import { IdCompressor } from "../idCompressor.js";
import {
createIdCompressor,
type IIdCompressor,
type IIdCompressorCore,
IdCreationRange,

@@ -30,9 +34,10 @@ OpSpaceCompressedId,

StableId,
type IIdCompressor,
type IIdCompressorCore,
} from "..//index.js";
import { IdCompressor } from "../idCompressor.js";
import { assertIsSessionId, createSessionId } from "../utilities.js";
createIdCompressor,
} from "../index.js";
import { assertIsSessionId, createSessionId, localIdFromGenCount } from "../utilities.js";
import {
FinalCompressedId,
ReadonlyIdCompressor,
fail,
getOrCreate,

@@ -42,4 +47,2 @@ incrementStableId,

isLocalId,
ReadonlyIdCompressor,
fail,
} from "./testCommon.js";

@@ -142,2 +145,3 @@

requestedClusterSize: capacity,
localIdRanges: [], // remote session, can safely ignore in tests
},

@@ -346,2 +350,3 @@ });

],
localIdRanges: [], // remote session, can safely ignore in tests
},

@@ -431,2 +436,25 @@ };

// Ensure creation ranges for clients we track contain the correct local ID ranges
this.serverOperations.forEach(([range, opSpaceIds, clientFrom]) => {
const localIdsInCreationRange = new Set<SessionSpaceCompressedId>();
if (clientFrom !== OriginatingClient.Remote) {
const ids = range.ids;
if (ids !== undefined) {
const { firstGenCount, localIdRanges } = ids;
for (const [genCount, count] of localIdRanges) {
for (let g = genCount; g < genCount + count; g++) {
const local = localIdFromGenCount(g);
assert.strictEqual(opSpaceIds[g - firstGenCount], local);
localIdsInCreationRange.add(local);
}
}
}
opSpaceIds.forEach((id) => {
if (isLocalId(id)) {
assert(localIdsInCreationRange.has(id), "Local ID not in creation range");
}
});
}
});
// First, ensure all clients each generated a unique ID for each of their own calls to generate.

@@ -433,0 +461,0 @@ for (const [compressor, ids] of sequencedLogs) {

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

import { assert } from "@fluidframework/core-utils";
import { SessionSpaceCompressedId, StableId, OpSpaceCompressedId } from "..//index.js";
import { assert } from "@fluidframework/core-utils/internal";
import { IdCompressor } from "../idCompressor.js";
import { OpSpaceCompressedId, SessionSpaceCompressedId, StableId } from "../index.js";
import {

@@ -14,3 +16,2 @@ numericUuidFromStableId,

} from "../utilities.js";
import { IdCompressor } from "../idCompressor.js";

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

@@ -6,3 +6,3 @@ {

"outDir": "../../lib/test",
"types": ["mocha"],
"types": ["mocha", "node"],

@@ -9,0 +9,0 @@ // The package exports utilities for test code from the test folder, so we need to build types for test files, which we typically

@@ -7,5 +7,5 @@ /*!

import {
SessionSpaceCompressedId,
OpSpaceCompressedId,
SessionId,
SessionSpaceCompressedId,
StableId,

@@ -116,3 +116,3 @@ } from "./identifiers.js";

*/
beginGhostSession(ghostSessionId: SessionId, ghostSessionCallback: () => void);
beginGhostSession(ghostSessionId: SessionId, ghostSessionCallback: () => void): void;

@@ -119,0 +119,0 @@ /**

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

readonly requestedClusterSize: number;
/**
* The ranges of IDs that were allocated as local IDs in the range created by `sessionId.`
*/
readonly localIdRanges: [genCount: number, count: number][];
};
}

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

/* eslint-disable no-bitwise */
import { assert } from "@fluidframework/core-utils";
import { assert } from "@fluidframework/core-utils/internal";
import { v4 } from "uuid";
import { LocalCompressedId, NumericUuid } from "./identifiers.js";
import { SessionId, StableId } from "./types/index.js";
import { LocalCompressedId, NumericUuid } from "./identifiers.js";

@@ -13,0 +14,0 @@ const hexadecimalCharCodes = Array.from("09afAF").map((c) => c.charCodeAt(0)) as [

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

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