@fluidframework/map 2.0.0-internal.2.2.1 → 2.0.0-internal.2.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.eslintrc.js +4 -1
- package/dist/directory.d.ts +5 -4
- package/dist/directory.d.ts.map +1 -1
- package/dist/directory.js +26 -11
- package/dist/directory.js.map +1 -1
- package/dist/interfaces.d.ts +3 -4
- package/dist/interfaces.d.ts.map +1 -1
- package/dist/interfaces.js.map +1 -1
- package/dist/internalInterfaces.d.ts +39 -0
- package/dist/internalInterfaces.d.ts.map +1 -1
- package/dist/internalInterfaces.js.map +1 -1
- package/dist/localValues.d.ts +12 -3
- package/dist/localValues.d.ts.map +1 -1
- package/dist/localValues.js +10 -0
- package/dist/localValues.js.map +1 -1
- package/dist/map.d.ts +4 -4
- package/dist/map.d.ts.map +1 -1
- package/dist/map.js +11 -0
- package/dist/map.js.map +1 -1
- package/dist/mapKernel.d.ts +5 -5
- package/dist/mapKernel.d.ts.map +1 -1
- package/dist/mapKernel.js +25 -11
- package/dist/mapKernel.js.map +1 -1
- package/dist/packageVersion.d.ts +1 -1
- package/dist/packageVersion.js +1 -1
- package/dist/packageVersion.js.map +1 -1
- package/lib/directory.d.ts +5 -4
- package/lib/directory.d.ts.map +1 -1
- package/lib/directory.js +26 -11
- package/lib/directory.js.map +1 -1
- package/lib/interfaces.d.ts +3 -4
- package/lib/interfaces.d.ts.map +1 -1
- package/lib/interfaces.js.map +1 -1
- package/lib/internalInterfaces.d.ts +39 -0
- package/lib/internalInterfaces.d.ts.map +1 -1
- package/lib/internalInterfaces.js.map +1 -1
- package/lib/localValues.d.ts +12 -3
- package/lib/localValues.d.ts.map +1 -1
- package/lib/localValues.js +10 -0
- package/lib/localValues.js.map +1 -1
- package/lib/map.d.ts +4 -4
- package/lib/map.d.ts.map +1 -1
- package/lib/map.js +11 -0
- package/lib/map.js.map +1 -1
- package/lib/mapKernel.d.ts +5 -5
- package/lib/mapKernel.d.ts.map +1 -1
- package/lib/mapKernel.js +25 -11
- package/lib/mapKernel.js.map +1 -1
- package/lib/packageVersion.d.ts +1 -1
- package/lib/packageVersion.js +1 -1
- package/lib/packageVersion.js.map +1 -1
- package/package.json +16 -14
- package/src/directory.ts +85 -54
- package/src/interfaces.ts +19 -9
- package/src/internalInterfaces.ts +45 -0
- package/src/localValues.ts +18 -7
- package/src/map.ts +28 -17
- package/src/mapKernel.ts +50 -32
- package/src/packageVersion.ts +1 -1
package/src/directory.ts
CHANGED
|
@@ -40,7 +40,7 @@ import { pkgVersion } from "./packageVersion";
|
|
|
40
40
|
|
|
41
41
|
// We use path-browserify since this code can run safely on the server or the browser.
|
|
42
42
|
// We standardize on using posix slashes everywhere.
|
|
43
|
-
const posix
|
|
43
|
+
const posix = path.posix;
|
|
44
44
|
|
|
45
45
|
const snapshotFileName = "header";
|
|
46
46
|
|
|
@@ -252,14 +252,14 @@ export class DirectoryFactory implements IChannelFactory {
|
|
|
252
252
|
/**
|
|
253
253
|
* {@inheritDoc @fluidframework/datastore-definitions#IChannelFactory."type"}
|
|
254
254
|
*/
|
|
255
|
-
public get type() {
|
|
255
|
+
public get type(): string {
|
|
256
256
|
return DirectoryFactory.Type;
|
|
257
257
|
}
|
|
258
258
|
|
|
259
259
|
/**
|
|
260
260
|
* {@inheritDoc @fluidframework/datastore-definitions#IChannelFactory.attributes}
|
|
261
261
|
*/
|
|
262
|
-
public get attributes() {
|
|
262
|
+
public get attributes(): IChannelAttributes {
|
|
263
263
|
return DirectoryFactory.Attributes;
|
|
264
264
|
}
|
|
265
265
|
|
|
@@ -355,7 +355,7 @@ export class SharedDirectory extends SharedObject<ISharedDirectoryEvents> implem
|
|
|
355
355
|
* @param runtime - Data store runtime
|
|
356
356
|
* @param type - Type identifier
|
|
357
357
|
*/
|
|
358
|
-
constructor(
|
|
358
|
+
public constructor(
|
|
359
359
|
id: string,
|
|
360
360
|
runtime: IFluidDataStoreRuntime,
|
|
361
361
|
attributes: IChannelAttributes,
|
|
@@ -387,6 +387,8 @@ export class SharedDirectory extends SharedObject<ISharedDirectoryEvents> implem
|
|
|
387
387
|
/**
|
|
388
388
|
* {@inheritDoc IDirectory.get}
|
|
389
389
|
*/
|
|
390
|
+
// TODO: Use `unknown` instead (breaking change).
|
|
391
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
390
392
|
public get<T = any>(key: string): T | undefined {
|
|
391
393
|
return this.root.get<T>(key);
|
|
392
394
|
}
|
|
@@ -394,7 +396,7 @@ export class SharedDirectory extends SharedObject<ISharedDirectoryEvents> implem
|
|
|
394
396
|
/**
|
|
395
397
|
* {@inheritDoc IDirectory.set}
|
|
396
398
|
*/
|
|
397
|
-
public set<T =
|
|
399
|
+
public set<T = unknown>(key: string, value: T): this {
|
|
398
400
|
this.root.set(key, value);
|
|
399
401
|
return this;
|
|
400
402
|
}
|
|
@@ -443,7 +445,10 @@ export class SharedDirectory extends SharedObject<ISharedDirectoryEvents> implem
|
|
|
443
445
|
* Issue a callback on each entry under this IDirectory.
|
|
444
446
|
* @param callback - Callback to issue
|
|
445
447
|
*/
|
|
448
|
+
// TODO: Use `unknown` instead (breaking change).
|
|
449
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
446
450
|
public forEach(callback: (value: any, key: string, map: Map<string, any>) => void): void {
|
|
451
|
+
// eslint-disable-next-line unicorn/no-array-for-each, unicorn/no-array-callback-reference
|
|
447
452
|
this.root.forEach(callback);
|
|
448
453
|
}
|
|
449
454
|
|
|
@@ -451,6 +456,8 @@ export class SharedDirectory extends SharedObject<ISharedDirectoryEvents> implem
|
|
|
451
456
|
* Get an iterator over the entries under this IDirectory.
|
|
452
457
|
* @returns The iterator
|
|
453
458
|
*/
|
|
459
|
+
// TODO: Use `unknown` instead (breaking change).
|
|
460
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
454
461
|
public [Symbol.iterator](): IterableIterator<[string, any]> {
|
|
455
462
|
return this.root[Symbol.iterator]();
|
|
456
463
|
}
|
|
@@ -459,6 +466,8 @@ export class SharedDirectory extends SharedObject<ISharedDirectoryEvents> implem
|
|
|
459
466
|
* Get an iterator over the entries under this IDirectory.
|
|
460
467
|
* @returns The iterator
|
|
461
468
|
*/
|
|
469
|
+
// TODO: Use `unknown` instead (breaking change).
|
|
470
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
462
471
|
public entries(): IterableIterator<[string, any]> {
|
|
463
472
|
return this.root.entries();
|
|
464
473
|
}
|
|
@@ -482,6 +491,8 @@ export class SharedDirectory extends SharedObject<ISharedDirectoryEvents> implem
|
|
|
482
491
|
* Get an iterator over the values under this IDirectory.
|
|
483
492
|
* @returns The iterator
|
|
484
493
|
*/
|
|
494
|
+
// TODO: Use `unknown` instead (breaking change).
|
|
495
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
485
496
|
public values(): IterableIterator<any> {
|
|
486
497
|
return this.root.values();
|
|
487
498
|
}
|
|
@@ -531,7 +542,7 @@ export class SharedDirectory extends SharedObject<ISharedDirectoryEvents> implem
|
|
|
531
542
|
}
|
|
532
543
|
|
|
533
544
|
let currentSubDir = this.root;
|
|
534
|
-
const subdirs = absolutePath.
|
|
545
|
+
const subdirs = absolutePath.slice(1).split(posix.sep);
|
|
535
546
|
for (const subdir of subdirs) {
|
|
536
547
|
currentSubDir = currentSubDir.getSubDirectory(subdir) as SubDirectory;
|
|
537
548
|
if (!currentSubDir) {
|
|
@@ -559,7 +570,7 @@ export class SharedDirectory extends SharedObject<ISharedDirectoryEvents> implem
|
|
|
559
570
|
* this op while it has not been ack'd. This will be sent when we receive this op back from the server.
|
|
560
571
|
* @internal
|
|
561
572
|
*/
|
|
562
|
-
public submitDirectoryMessage(op: IDirectoryOperation, localOpMetadata: unknown) {
|
|
573
|
+
public submitDirectoryMessage(op: IDirectoryOperation, localOpMetadata: unknown): void {
|
|
563
574
|
this.submitLocalMessage(op, localOpMetadata);
|
|
564
575
|
}
|
|
565
576
|
|
|
@@ -567,13 +578,13 @@ export class SharedDirectory extends SharedObject<ISharedDirectoryEvents> implem
|
|
|
567
578
|
* {@inheritDoc @fluidframework/shared-object-base#SharedObject.onDisconnect}
|
|
568
579
|
* @internal
|
|
569
580
|
*/
|
|
570
|
-
protected onDisconnect() { }
|
|
581
|
+
protected onDisconnect(): void { }
|
|
571
582
|
|
|
572
583
|
/**
|
|
573
584
|
* {@inheritDoc @fluidframework/shared-object-base#SharedObject.reSubmitCore}
|
|
574
585
|
* @internal
|
|
575
586
|
*/
|
|
576
|
-
protected reSubmitCore(content:
|
|
587
|
+
protected reSubmitCore(content: unknown, localOpMetadata: unknown): void {
|
|
577
588
|
const message = content as IDirectoryOperation;
|
|
578
589
|
const handler = this.messageHandlers.get(message.type);
|
|
579
590
|
assert(handler !== undefined, 0x00d /* Missing message handler for message type */);
|
|
@@ -584,7 +595,7 @@ export class SharedDirectory extends SharedObject<ISharedDirectoryEvents> implem
|
|
|
584
595
|
* {@inheritDoc @fluidframework/shared-object-base#SharedObject.loadCore}
|
|
585
596
|
* @internal
|
|
586
597
|
*/
|
|
587
|
-
protected async loadCore(storage: IChannelStorageService) {
|
|
598
|
+
protected async loadCore(storage: IChannelStorageService): Promise<void> {
|
|
588
599
|
const data = await readAndParse(storage, snapshotFileName);
|
|
589
600
|
const newFormat = data as IDirectoryNewStorageFormat;
|
|
590
601
|
if (Array.isArray(newFormat.blobs)) {
|
|
@@ -605,7 +616,7 @@ export class SharedDirectory extends SharedObject<ISharedDirectoryEvents> implem
|
|
|
605
616
|
* @param data - A JSON string containing serialized directory data
|
|
606
617
|
* @internal
|
|
607
618
|
*/
|
|
608
|
-
protected populate(data: IDirectoryDataObject) {
|
|
619
|
+
protected populate(data: IDirectoryDataObject): void {
|
|
609
620
|
const stack: [SubDirectory, IDirectoryDataObject][] = [];
|
|
610
621
|
stack.push([this.root, data]);
|
|
611
622
|
while (stack.length > 0) {
|
|
@@ -657,7 +668,7 @@ export class SharedDirectory extends SharedObject<ISharedDirectoryEvents> implem
|
|
|
657
668
|
* {@inheritDoc @fluidframework/shared-object-base#SharedObject.rollback}
|
|
658
669
|
* @internal
|
|
659
670
|
*/
|
|
660
|
-
protected rollback(content:
|
|
671
|
+
protected rollback(content: unknown, localOpMetadata: unknown): void {
|
|
661
672
|
const op: IDirectoryOperation = content as IDirectoryOperation;
|
|
662
673
|
const subdir = this.getWorkingDirectory(op.path) as SubDirectory | undefined;
|
|
663
674
|
if (subdir) {
|
|
@@ -787,7 +798,6 @@ export class SharedDirectory extends SharedObject<ISharedDirectoryEvents> implem
|
|
|
787
798
|
parentSubdir.resubmitSubDirectoryMessage(op, localOpMetadata);
|
|
788
799
|
}
|
|
789
800
|
},
|
|
790
|
-
// eslint-disable-next-line max-len
|
|
791
801
|
applyStashedOp: (op: IDirectoryCreateSubDirectoryOperation): ICreateSubDirLocalOpMetadata | undefined => {
|
|
792
802
|
const parentSubdir = this.getWorkingDirectory(op.path) as SubDirectory | undefined;
|
|
793
803
|
if (parentSubdir) {
|
|
@@ -813,7 +823,6 @@ export class SharedDirectory extends SharedObject<ISharedDirectoryEvents> implem
|
|
|
813
823
|
parentSubdir.resubmitSubDirectoryMessage(op, localOpMetadata);
|
|
814
824
|
}
|
|
815
825
|
},
|
|
816
|
-
// eslint-disable-next-line max-len
|
|
817
826
|
applyStashedOp: (op: IDirectoryDeleteSubDirectoryOperation): IDeleteSubDirLocalOpMetadata | undefined => {
|
|
818
827
|
const parentSubdir = this.getWorkingDirectory(op.path) as SubDirectory | undefined;
|
|
819
828
|
if (parentSubdir) {
|
|
@@ -825,10 +834,11 @@ export class SharedDirectory extends SharedObject<ISharedDirectoryEvents> implem
|
|
|
825
834
|
}
|
|
826
835
|
|
|
827
836
|
/**
|
|
837
|
+
* {@inheritDoc @fluidframework/shared-object-base#SharedObjectCore.applyStashedOp}
|
|
828
838
|
* @internal
|
|
829
839
|
*/
|
|
830
|
-
protected applyStashedOp(op) {
|
|
831
|
-
const handler = this.messageHandlers.get(op.type);
|
|
840
|
+
protected applyStashedOp(op: unknown): unknown {
|
|
841
|
+
const handler = this.messageHandlers.get((op as IDirectoryOperation).type);
|
|
832
842
|
if (handler === undefined) {
|
|
833
843
|
throw new Error("no apply stashed op handler");
|
|
834
844
|
}
|
|
@@ -859,14 +869,13 @@ export class SharedDirectory extends SharedObject<ISharedDirectoryEvents> implem
|
|
|
859
869
|
}
|
|
860
870
|
const result: ISerializableValue = {
|
|
861
871
|
type: value.type,
|
|
862
|
-
// eslint-disable-next-line @typescript-eslint/ban-types
|
|
863
872
|
value: value.value && JSON.parse(value.value) as object,
|
|
864
873
|
};
|
|
865
874
|
if (value.value && value.value.length >= MinValueSizeSeparateSnapshotBlob) {
|
|
866
875
|
const extraContent: IDirectoryDataObject = {};
|
|
867
876
|
let largeContent = extraContent;
|
|
868
877
|
if (currentSubDir.absolutePath !== posix.sep) {
|
|
869
|
-
for (const dir of currentSubDir.absolutePath.
|
|
878
|
+
for (const dir of currentSubDir.absolutePath.slice(1).split(posix.sep)) {
|
|
870
879
|
const subDataObject: IDirectoryDataObject = {};
|
|
871
880
|
largeContent.subdirectories = { [dir]: subDataObject };
|
|
872
881
|
largeContent = subDataObject;
|
|
@@ -929,6 +938,9 @@ interface IDeleteSubDirLocalOpMetadata {
|
|
|
929
938
|
type SubDirLocalOpMetadata = ICreateSubDirLocalOpMetadata | IDeleteSubDirLocalOpMetadata;
|
|
930
939
|
type DirectoryLocalOpMetadata = IClearLocalOpMetadata | IKeyEditLocalOpMetadata | SubDirLocalOpMetadata;
|
|
931
940
|
|
|
941
|
+
|
|
942
|
+
/* eslint-disable @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-member-access */
|
|
943
|
+
|
|
932
944
|
function isKeyEditLocalOpMetadata(metadata: any): metadata is IKeyEditLocalOpMetadata {
|
|
933
945
|
return metadata !== undefined && typeof metadata.pendingMessageId === "number" && metadata.type === "edit";
|
|
934
946
|
}
|
|
@@ -951,6 +963,8 @@ function isDirectoryLocalOpMetadata(metadata: any): metadata is DirectoryLocalOp
|
|
|
951
963
|
(metadata.type === "createSubDir" && typeof metadata.previouslyExisted === "boolean"));
|
|
952
964
|
}
|
|
953
965
|
|
|
966
|
+
/* eslint-enable @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-member-access */
|
|
967
|
+
|
|
954
968
|
/**
|
|
955
969
|
* Node of the directory tree.
|
|
956
970
|
* @sealed
|
|
@@ -1003,7 +1017,7 @@ class SubDirectory extends TypedEventEmitter<IDirectoryEvents> implements IDirec
|
|
|
1003
1017
|
* @param serializer - The serializer to serialize / parse handles
|
|
1004
1018
|
* @param absolutePath - The absolute path of this IDirectory
|
|
1005
1019
|
*/
|
|
1006
|
-
constructor(
|
|
1020
|
+
public constructor(
|
|
1007
1021
|
private readonly directory: SharedDirectory,
|
|
1008
1022
|
private readonly runtime: IFluidDataStoreRuntime,
|
|
1009
1023
|
private readonly serializer: IFluidSerializer,
|
|
@@ -1028,7 +1042,7 @@ class SubDirectory extends TypedEventEmitter<IDirectoryEvents> implements IDirec
|
|
|
1028
1042
|
return this._deleted;
|
|
1029
1043
|
}
|
|
1030
1044
|
|
|
1031
|
-
private throwIfDisposed() {
|
|
1045
|
+
private throwIfDisposed(): void {
|
|
1032
1046
|
if (this._deleted) {
|
|
1033
1047
|
throw new UsageError("Cannot access Disposed subDirectory");
|
|
1034
1048
|
}
|
|
@@ -1047,7 +1061,7 @@ class SubDirectory extends TypedEventEmitter<IDirectoryEvents> implements IDirec
|
|
|
1047
1061
|
/**
|
|
1048
1062
|
* {@inheritDoc IDirectory.get}
|
|
1049
1063
|
*/
|
|
1050
|
-
public get<T =
|
|
1064
|
+
public get<T = unknown>(key: string): T | undefined {
|
|
1051
1065
|
this.throwIfDisposed();
|
|
1052
1066
|
return this._storage.get(key)?.value as T | undefined;
|
|
1053
1067
|
}
|
|
@@ -1055,7 +1069,7 @@ class SubDirectory extends TypedEventEmitter<IDirectoryEvents> implements IDirec
|
|
|
1055
1069
|
/**
|
|
1056
1070
|
* {@inheritDoc IDirectory.set}
|
|
1057
1071
|
*/
|
|
1058
|
-
public set<T =
|
|
1072
|
+
public set<T = unknown>(key: string, value: T): this {
|
|
1059
1073
|
this.throwIfDisposed();
|
|
1060
1074
|
// Undefined/null keys can't be serialized to JSON in the manner we currently snapshot.
|
|
1061
1075
|
if (key === undefined || key === null) {
|
|
@@ -1238,8 +1252,9 @@ class SubDirectory extends TypedEventEmitter<IDirectoryEvents> implements IDirec
|
|
|
1238
1252
|
* Issue a callback on each entry under this IDirectory.
|
|
1239
1253
|
* @param callback - Callback to issue
|
|
1240
1254
|
*/
|
|
1241
|
-
public forEach(callback: (value:
|
|
1255
|
+
public forEach(callback: (value: unknown, key: string, map: Map<string, unknown>) => void): void {
|
|
1242
1256
|
this.throwIfDisposed();
|
|
1257
|
+
// eslint-disable-next-line unicorn/no-array-for-each
|
|
1243
1258
|
this._storage.forEach((localValue, key, map) => {
|
|
1244
1259
|
callback(localValue.value, key, map);
|
|
1245
1260
|
});
|
|
@@ -1257,17 +1272,17 @@ class SubDirectory extends TypedEventEmitter<IDirectoryEvents> implements IDirec
|
|
|
1257
1272
|
* Get an iterator over the entries under this IDirectory.
|
|
1258
1273
|
* @returns The iterator
|
|
1259
1274
|
*/
|
|
1260
|
-
public entries(): IterableIterator<[string,
|
|
1275
|
+
public entries(): IterableIterator<[string, unknown]> {
|
|
1261
1276
|
this.throwIfDisposed();
|
|
1262
1277
|
const localEntriesIterator = this._storage.entries();
|
|
1263
1278
|
const iterator = {
|
|
1264
|
-
next(): IteratorResult<[string,
|
|
1279
|
+
next(): IteratorResult<[string, unknown]> {
|
|
1265
1280
|
const nextVal = localEntriesIterator.next();
|
|
1266
1281
|
return nextVal.done
|
|
1267
1282
|
? { value: undefined, done: true }
|
|
1268
1283
|
: { value: [nextVal.value[0], nextVal.value[1].value], done: false };
|
|
1269
1284
|
},
|
|
1270
|
-
[Symbol.iterator]() {
|
|
1285
|
+
[Symbol.iterator](): IterableIterator<[string, unknown]> {
|
|
1271
1286
|
return this;
|
|
1272
1287
|
},
|
|
1273
1288
|
};
|
|
@@ -1287,17 +1302,17 @@ class SubDirectory extends TypedEventEmitter<IDirectoryEvents> implements IDirec
|
|
|
1287
1302
|
* Get an iterator over the values under this IDirectory.
|
|
1288
1303
|
* @returns The iterator
|
|
1289
1304
|
*/
|
|
1290
|
-
public values(): IterableIterator<
|
|
1305
|
+
public values(): IterableIterator<unknown> {
|
|
1291
1306
|
this.throwIfDisposed();
|
|
1292
1307
|
const localValuesIterator = this._storage.values();
|
|
1293
1308
|
const iterator = {
|
|
1294
|
-
next(): IteratorResult<
|
|
1309
|
+
next(): IteratorResult<unknown> {
|
|
1295
1310
|
const nextVal = localValuesIterator.next();
|
|
1296
1311
|
return nextVal.done
|
|
1297
1312
|
? { value: undefined, done: true }
|
|
1298
1313
|
: { value: nextVal.value.value, done: false };
|
|
1299
1314
|
},
|
|
1300
|
-
[Symbol.iterator]() {
|
|
1315
|
+
[Symbol.iterator](): IterableIterator<unknown> {
|
|
1301
1316
|
return this;
|
|
1302
1317
|
},
|
|
1303
1318
|
};
|
|
@@ -1308,7 +1323,7 @@ class SubDirectory extends TypedEventEmitter<IDirectoryEvents> implements IDirec
|
|
|
1308
1323
|
* Get an iterator over the entries under this IDirectory.
|
|
1309
1324
|
* @returns The iterator
|
|
1310
1325
|
*/
|
|
1311
|
-
public [Symbol.iterator](): IterableIterator<[string,
|
|
1326
|
+
public [Symbol.iterator](): IterableIterator<[string, unknown]> {
|
|
1312
1327
|
this.throwIfDisposed();
|
|
1313
1328
|
return this.entries();
|
|
1314
1329
|
}
|
|
@@ -1673,7 +1688,7 @@ class SubDirectory extends TypedEventEmitter<IDirectoryEvents> implements IDirec
|
|
|
1673
1688
|
* @returns The JSONable string representing the storage of this subdirectory
|
|
1674
1689
|
* @internal
|
|
1675
1690
|
*/
|
|
1676
|
-
public *getSerializedStorage(serializer: IFluidSerializer) {
|
|
1691
|
+
public *getSerializedStorage(serializer: IFluidSerializer): Generator<[string, ISerializedValue], void> {
|
|
1677
1692
|
this.throwIfDisposed();
|
|
1678
1693
|
for (const [key, localValue] of this._storage) {
|
|
1679
1694
|
const value = localValue.makeSerialized(serializer, this.directory.handle);
|
|
@@ -1721,7 +1736,7 @@ class SubDirectory extends TypedEventEmitter<IDirectoryEvents> implements IDirec
|
|
|
1721
1736
|
* @param map - map tracking the pending messages
|
|
1722
1737
|
* @param key - key of the edit in the op
|
|
1723
1738
|
*/
|
|
1724
|
-
private rollbackPendingMessageId(map: Map<string, number[]>, key: string, pendingMessageId) {
|
|
1739
|
+
private rollbackPendingMessageId(map: Map<string, number[]>, key: string, pendingMessageId): void {
|
|
1725
1740
|
const pendingMessageIds = map.get(key);
|
|
1726
1741
|
const lastPendingMessageId = pendingMessageIds?.pop();
|
|
1727
1742
|
if (!pendingMessageIds || lastPendingMessageId !== pendingMessageId) {
|
|
@@ -1732,20 +1747,23 @@ class SubDirectory extends TypedEventEmitter<IDirectoryEvents> implements IDirec
|
|
|
1732
1747
|
}
|
|
1733
1748
|
}
|
|
1734
1749
|
|
|
1750
|
+
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
|
1751
|
+
|
|
1735
1752
|
/**
|
|
1736
1753
|
* Rollback a local op
|
|
1737
1754
|
* @param op - The operation to rollback
|
|
1738
1755
|
* @param localOpMetadata - The local metadata associated with the op.
|
|
1739
1756
|
*/
|
|
1740
|
-
|
|
1757
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
1758
|
+
public rollback(op: any, localOpMetadata: unknown): void {
|
|
1741
1759
|
if (!isDirectoryLocalOpMetadata(localOpMetadata)) {
|
|
1742
1760
|
throw new Error("Invalid localOpMetadata");
|
|
1743
1761
|
}
|
|
1744
1762
|
|
|
1745
1763
|
if (op.type === "clear" && localOpMetadata.type === "clear") {
|
|
1746
|
-
localOpMetadata.previousStorage.
|
|
1764
|
+
for (const [key, localValue] of localOpMetadata.previousStorage.entries()) {
|
|
1747
1765
|
this.setCore(key, localValue, true);
|
|
1748
|
-
}
|
|
1766
|
+
}
|
|
1749
1767
|
|
|
1750
1768
|
const lastPendingClearId = this.pendingClearMessageIds.pop();
|
|
1751
1769
|
if (lastPendingClearId === undefined || lastPendingClearId !== localOpMetadata.pendingMessageId) {
|
|
@@ -1753,32 +1771,42 @@ class SubDirectory extends TypedEventEmitter<IDirectoryEvents> implements IDirec
|
|
|
1753
1771
|
}
|
|
1754
1772
|
} else if ((op.type === "delete" || op.type === "set") && localOpMetadata.type === "edit") {
|
|
1755
1773
|
if (localOpMetadata.previousValue === undefined) {
|
|
1756
|
-
this.deleteCore(op.key, true);
|
|
1774
|
+
this.deleteCore(op.key as string, true);
|
|
1757
1775
|
} else {
|
|
1758
|
-
this.setCore(op.key, localOpMetadata.previousValue, true);
|
|
1776
|
+
this.setCore(op.key as string, localOpMetadata.previousValue, true);
|
|
1759
1777
|
}
|
|
1760
1778
|
|
|
1761
|
-
this.rollbackPendingMessageId(this.pendingKeys, op.key, localOpMetadata.pendingMessageId);
|
|
1779
|
+
this.rollbackPendingMessageId(this.pendingKeys, op.key as string, localOpMetadata.pendingMessageId);
|
|
1762
1780
|
} else if (op.type === "createSubDirectory" && localOpMetadata.type === "createSubDir") {
|
|
1763
1781
|
if (!localOpMetadata.previouslyExisted) {
|
|
1764
|
-
this.deleteSubDirectoryCore(op.subdirName, true);
|
|
1782
|
+
this.deleteSubDirectoryCore(op.subdirName as string, true);
|
|
1765
1783
|
}
|
|
1766
1784
|
|
|
1767
|
-
this.rollbackPendingMessageId(
|
|
1785
|
+
this.rollbackPendingMessageId(
|
|
1786
|
+
this.pendingSubDirectories,
|
|
1787
|
+
op.subdirName as string,
|
|
1788
|
+
localOpMetadata.pendingMessageId
|
|
1789
|
+
);
|
|
1768
1790
|
} else if (op.type === "deleteSubDirectory" && localOpMetadata.type === "deleteSubDir") {
|
|
1769
1791
|
if (localOpMetadata.subDirectory !== undefined) {
|
|
1770
1792
|
this.undeleteSubDirectoryTree(localOpMetadata.subDirectory);
|
|
1771
1793
|
// don't need to register events because deleting never unregistered
|
|
1772
|
-
this._subdirectories.set(op.subdirName, localOpMetadata.subDirectory);
|
|
1794
|
+
this._subdirectories.set(op.subdirName as string, localOpMetadata.subDirectory);
|
|
1773
1795
|
this.emit("subDirectoryCreated", op.subdirName, true, this);
|
|
1774
1796
|
}
|
|
1775
1797
|
|
|
1776
|
-
this.rollbackPendingMessageId(
|
|
1798
|
+
this.rollbackPendingMessageId(
|
|
1799
|
+
this.pendingSubDirectories,
|
|
1800
|
+
op.subdirName as string,
|
|
1801
|
+
localOpMetadata.pendingMessageId
|
|
1802
|
+
);
|
|
1777
1803
|
} else {
|
|
1778
1804
|
throw new Error("Unsupported op for rollback");
|
|
1779
1805
|
}
|
|
1780
1806
|
}
|
|
1781
1807
|
|
|
1808
|
+
/* eslint-enable @typescript-eslint/no-unsafe-member-access */
|
|
1809
|
+
|
|
1782
1810
|
/**
|
|
1783
1811
|
* Converts the given relative path into an absolute path.
|
|
1784
1812
|
* @param path - Relative path to convert
|
|
@@ -1871,25 +1899,28 @@ class SubDirectory extends TypedEventEmitter<IDirectoryEvents> implements IDirec
|
|
|
1871
1899
|
/**
|
|
1872
1900
|
* Clear all keys in memory in response to a remote clear, but retain keys we have modified but not yet been ack'd.
|
|
1873
1901
|
*/
|
|
1874
|
-
private clearExceptPendingKeys(local: boolean) {
|
|
1902
|
+
private clearExceptPendingKeys(local: boolean): void {
|
|
1875
1903
|
// Assuming the pendingKeys is small and the map is large
|
|
1876
1904
|
// we will get the value for the pendingKeys and clear the map
|
|
1877
1905
|
const temp = new Map<string, ILocalValue>();
|
|
1878
|
-
|
|
1906
|
+
|
|
1907
|
+
for (const [key] of this.pendingKeys) {
|
|
1879
1908
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
1880
1909
|
temp.set(key, this._storage.get(key)!);
|
|
1881
|
-
}
|
|
1910
|
+
}
|
|
1911
|
+
|
|
1882
1912
|
this.clearCore(local);
|
|
1883
|
-
|
|
1913
|
+
|
|
1914
|
+
for (const [key, value] of temp.entries()) {
|
|
1884
1915
|
this.setCore(key, value, true);
|
|
1885
|
-
}
|
|
1916
|
+
}
|
|
1886
1917
|
}
|
|
1887
1918
|
|
|
1888
1919
|
/**
|
|
1889
1920
|
* Clear implementation used for both locally sourced clears as well as incoming remote clears.
|
|
1890
1921
|
* @param local - Whether the message originated from the local client
|
|
1891
1922
|
*/
|
|
1892
|
-
private clearCore(local: boolean) {
|
|
1923
|
+
private clearCore(local: boolean): void {
|
|
1893
1924
|
this._storage.clear();
|
|
1894
1925
|
this.directory.emit("clear", local, this.directory);
|
|
1895
1926
|
}
|
|
@@ -1902,7 +1933,7 @@ class SubDirectory extends TypedEventEmitter<IDirectoryEvents> implements IDirec
|
|
|
1902
1933
|
*/
|
|
1903
1934
|
private deleteCore(key: string, local: boolean): ILocalValue | undefined {
|
|
1904
1935
|
const previousLocalValue = this._storage.get(key);
|
|
1905
|
-
const previousValue = previousLocalValue?.value;
|
|
1936
|
+
const previousValue: unknown = previousLocalValue?.value;
|
|
1906
1937
|
const successfullyRemoved = this._storage.delete(key);
|
|
1907
1938
|
if (successfullyRemoved) {
|
|
1908
1939
|
const event: IDirectoryValueChanged = { key, path: this.absolutePath, previousValue };
|
|
@@ -1922,7 +1953,7 @@ class SubDirectory extends TypedEventEmitter<IDirectoryEvents> implements IDirec
|
|
|
1922
1953
|
*/
|
|
1923
1954
|
private setCore(key: string, value: ILocalValue, local: boolean): ILocalValue | undefined {
|
|
1924
1955
|
const previousLocalValue = this._storage.get(key);
|
|
1925
|
-
const previousValue = previousLocalValue?.value;
|
|
1956
|
+
const previousValue: unknown = previousLocalValue?.value;
|
|
1926
1957
|
this._storage.set(key, value);
|
|
1927
1958
|
const event: IDirectoryValueChanged = { key, path: this.absolutePath, previousValue };
|
|
1928
1959
|
this.directory.emit("valueChanged", event, local, this.directory);
|
|
@@ -1949,7 +1980,7 @@ class SubDirectory extends TypedEventEmitter<IDirectoryEvents> implements IDirec
|
|
|
1949
1980
|
return false;
|
|
1950
1981
|
}
|
|
1951
1982
|
|
|
1952
|
-
private registerEventsOnSubDirectory(subDirectory: SubDirectory, subDirName: string) {
|
|
1983
|
+
private registerEventsOnSubDirectory(subDirectory: SubDirectory, subDirName: string): void {
|
|
1953
1984
|
subDirectory.on("subDirectoryCreated", (relativePath: string, local: boolean) => {
|
|
1954
1985
|
this.emit("subDirectoryCreated", posix.join(subDirName, relativePath), local, this);
|
|
1955
1986
|
});
|
|
@@ -1963,7 +1994,7 @@ class SubDirectory extends TypedEventEmitter<IDirectoryEvents> implements IDirec
|
|
|
1963
1994
|
* @param subdirName - The name of the subdirectory being deleted
|
|
1964
1995
|
* @param local - Whether the message originated from the local client
|
|
1965
1996
|
*/
|
|
1966
|
-
private deleteSubDirectoryCore(subdirName: string, local: boolean) {
|
|
1997
|
+
private deleteSubDirectoryCore(subdirName: string, local: boolean): SubDirectory | undefined {
|
|
1967
1998
|
const previousValue = this._subdirectories.get(subdirName);
|
|
1968
1999
|
// This should make the subdirectory structure unreachable so it can be GC'd and won't appear in snapshots
|
|
1969
2000
|
// Might want to consider cleaning out the structure more exhaustively though? But not when rollback.
|
|
@@ -1975,7 +2006,7 @@ class SubDirectory extends TypedEventEmitter<IDirectoryEvents> implements IDirec
|
|
|
1975
2006
|
return previousValue;
|
|
1976
2007
|
}
|
|
1977
2008
|
|
|
1978
|
-
private disposeSubDirectoryTree(directory: IDirectory | undefined) {
|
|
2009
|
+
private disposeSubDirectoryTree(directory: IDirectory | undefined): void {
|
|
1979
2010
|
if (!directory) {
|
|
1980
2011
|
return;
|
|
1981
2012
|
}
|
|
@@ -1989,7 +2020,7 @@ class SubDirectory extends TypedEventEmitter<IDirectoryEvents> implements IDirec
|
|
|
1989
2020
|
}
|
|
1990
2021
|
}
|
|
1991
2022
|
|
|
1992
|
-
private undeleteSubDirectoryTree(directory: SubDirectory) {
|
|
2023
|
+
private undeleteSubDirectoryTree(directory: SubDirectory): void {
|
|
1993
2024
|
// Restore deleted subdirectory tree. This will unmark "deleted" from the subdirectories from bottom to top.
|
|
1994
2025
|
for (const [_, subDirectory] of this._subdirectories.entries()) {
|
|
1995
2026
|
this.undeleteSubDirectoryTree(subDirectory);
|
package/src/interfaces.ts
CHANGED
|
@@ -18,15 +18,18 @@ export interface IValueChanged {
|
|
|
18
18
|
/**
|
|
19
19
|
* The value that was stored at the key prior to the change.
|
|
20
20
|
*/
|
|
21
|
+
// TODO: Use `unknown` instead (breaking change).
|
|
22
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
21
23
|
previousValue: any;
|
|
22
24
|
}
|
|
23
25
|
|
|
24
26
|
/**
|
|
25
27
|
* Interface describing actions on a directory.
|
|
26
28
|
*
|
|
27
|
-
* @remarks
|
|
28
|
-
* When used as a Map, operates on its keys.
|
|
29
|
+
* @remarks When used as a Map, operates on its keys.
|
|
29
30
|
*/
|
|
31
|
+
// TODO: Use `unknown` instead (breaking change).
|
|
32
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
30
33
|
export interface IDirectory extends Map<string, any>, IEventProvider<IDirectoryEvents>, Partial<IDisposable> {
|
|
31
34
|
/**
|
|
32
35
|
* The absolute path of the directory.
|
|
@@ -38,6 +41,8 @@ export interface IDirectory extends Map<string, any>, IEventProvider<IDirectoryE
|
|
|
38
41
|
* @param key - Key to retrieve from
|
|
39
42
|
* @returns The stored value, or undefined if the key is not set
|
|
40
43
|
*/
|
|
44
|
+
// TODO: Use `unknown` instead (breaking change).
|
|
45
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
41
46
|
get<T = any>(key: string): T | undefined;
|
|
42
47
|
|
|
43
48
|
/**
|
|
@@ -46,7 +51,7 @@ export interface IDirectory extends Map<string, any>, IEventProvider<IDirectoryE
|
|
|
46
51
|
* @param value - Value to set
|
|
47
52
|
* @returns The IDirectory itself
|
|
48
53
|
*/
|
|
49
|
-
set<T =
|
|
54
|
+
set<T = unknown>(key: string, value: T): this;
|
|
50
55
|
|
|
51
56
|
/**
|
|
52
57
|
* Get the number of sub directory within the directory.
|
|
@@ -165,7 +170,6 @@ export interface ISharedDirectoryEvents extends ISharedObjectEvents {
|
|
|
165
170
|
*
|
|
166
171
|
* - `target` - The {@link ISharedDirectory} itself.
|
|
167
172
|
*/
|
|
168
|
-
// eslint-disable-next-line @typescript-eslint/unified-signatures
|
|
169
173
|
(event: "subDirectoryDeleted", listener: (
|
|
170
174
|
path: string,
|
|
171
175
|
local: boolean,
|
|
@@ -226,7 +230,6 @@ export interface IDirectoryEvents extends IEvent {
|
|
|
226
230
|
*
|
|
227
231
|
* - `target` - The {@link ISharedDirectory} itself.
|
|
228
232
|
*/
|
|
229
|
-
// eslint-disable-next-line @typescript-eslint/unified-signatures
|
|
230
233
|
(event: "subDirectoryDeleted", listener: (
|
|
231
234
|
path: string,
|
|
232
235
|
local: boolean,
|
|
@@ -250,11 +253,13 @@ export interface IDirectoryEvents extends IEvent {
|
|
|
250
253
|
* The values stored within can be accessed like a map, and the hierarchy can be navigated using path syntax.
|
|
251
254
|
* SubDirectories can be retrieved for use as working directories.
|
|
252
255
|
*/
|
|
253
|
-
export interface ISharedDirectory
|
|
254
|
-
ISharedObject<ISharedDirectoryEvents & IDirectoryEvents>,
|
|
255
|
-
|
|
256
|
+
export interface ISharedDirectory
|
|
257
|
+
extends ISharedObject<ISharedDirectoryEvents & IDirectoryEvents>, Omit<IDirectory, "on" | "once" | "off">
|
|
258
|
+
{
|
|
256
259
|
// The Omit type excludes symbols, which we don't want to exclude. Adding them back here manually.
|
|
257
260
|
// https://github.com/microsoft/TypeScript/issues/31671
|
|
261
|
+
// TODO: Use `unknown` instead (breaking change).
|
|
262
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
258
263
|
[Symbol.iterator](): IterableIterator<[string, any]>;
|
|
259
264
|
readonly [Symbol.toStringTag]: string;
|
|
260
265
|
}
|
|
@@ -312,12 +317,16 @@ export interface ISharedMapEvents extends ISharedObjectEvents {
|
|
|
312
317
|
*
|
|
313
318
|
* For more information, including example usages, see {@link https://fluidframework.com/docs/data-structures/map/}.
|
|
314
319
|
*/
|
|
320
|
+
// TODO: Use `unknown` instead (breaking change).
|
|
321
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
315
322
|
export interface ISharedMap extends ISharedObject<ISharedMapEvents>, Map<string, any> {
|
|
316
323
|
/**
|
|
317
324
|
* Retrieves the given key from the map if it exists.
|
|
318
325
|
* @param key - Key to retrieve from
|
|
319
326
|
* @returns The stored value, or undefined if the key is not set
|
|
320
327
|
*/
|
|
328
|
+
// TODO: Use `unknown` instead (breaking change).
|
|
329
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
321
330
|
get<T = any>(key: string): T | undefined;
|
|
322
331
|
|
|
323
332
|
/**
|
|
@@ -326,7 +335,7 @@ export interface ISharedMap extends ISharedObject<ISharedMapEvents>, Map<string,
|
|
|
326
335
|
* @param value - Value to set
|
|
327
336
|
* @returns The {@link ISharedMap} itself
|
|
328
337
|
*/
|
|
329
|
-
set<T =
|
|
338
|
+
set<T = unknown>(key: string, value: T): this;
|
|
330
339
|
}
|
|
331
340
|
|
|
332
341
|
/**
|
|
@@ -361,6 +370,7 @@ export interface ISerializableValue {
|
|
|
361
370
|
/**
|
|
362
371
|
* The JSONable representation of the value.
|
|
363
372
|
*/
|
|
373
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
364
374
|
value: any;
|
|
365
375
|
}
|
|
366
376
|
|
|
@@ -51,22 +51,67 @@ import { ILocalValue } from "./localValues";
|
|
|
51
51
|
key: string;
|
|
52
52
|
}
|
|
53
53
|
|
|
54
|
+
/**
|
|
55
|
+
* Metadata for an local `edit` operation.
|
|
56
|
+
*/
|
|
54
57
|
export interface IMapKeyEditLocalOpMetadata {
|
|
58
|
+
/**
|
|
59
|
+
* String identifier of the operation type.
|
|
60
|
+
*/
|
|
55
61
|
type: "edit";
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Unique identifier for the local operation.
|
|
65
|
+
*/
|
|
56
66
|
pendingMessageId: number;
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Local value prior to the edit.
|
|
70
|
+
*/
|
|
57
71
|
previousValue: ILocalValue;
|
|
58
72
|
}
|
|
59
73
|
|
|
74
|
+
/**
|
|
75
|
+
* Metadata for an local `add` operation.
|
|
76
|
+
*/
|
|
60
77
|
export interface IMapKeyAddLocalOpMetadata {
|
|
78
|
+
/**
|
|
79
|
+
* String identifier of the operation type.
|
|
80
|
+
*/
|
|
61
81
|
type: "add";
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Unique identifier for the local operation.
|
|
85
|
+
*/
|
|
62
86
|
pendingMessageId: number;
|
|
63
87
|
}
|
|
64
88
|
|
|
89
|
+
/**
|
|
90
|
+
* Metadata for an local `clear` operation.
|
|
91
|
+
*/
|
|
65
92
|
export interface IMapClearLocalOpMetadata {
|
|
93
|
+
/**
|
|
94
|
+
* String identifier of the operation type.
|
|
95
|
+
*/
|
|
66
96
|
type: "clear";
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Unique identifier for the local operation.
|
|
100
|
+
*/
|
|
67
101
|
pendingMessageId: number;
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Local map contents prior to clearing it.
|
|
105
|
+
*/
|
|
68
106
|
previousMap?: Map<string, ILocalValue>;
|
|
69
107
|
}
|
|
70
108
|
|
|
109
|
+
/**
|
|
110
|
+
* Metadata for a local operation associated with a specific key entry in the map.
|
|
111
|
+
*/
|
|
71
112
|
export type MapKeyLocalOpMetadata = IMapKeyEditLocalOpMetadata | IMapKeyAddLocalOpMetadata;
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Metadata for a local operation.
|
|
116
|
+
*/
|
|
72
117
|
export type MapLocalOpMetadata = IMapClearLocalOpMetadata | MapKeyLocalOpMetadata;
|