@fluidframework/map 2.0.0-dev.2.2.0.111723 → 2.0.0-dev.3.1.0.125672
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 +12 -14
- package/.mocharc.js +2 -2
- package/README.md +3 -3
- package/api-extractor.json +2 -2
- package/dist/directory.d.ts +6 -5
- package/dist/directory.d.ts.map +1 -1
- package/dist/directory.js +68 -30
- package/dist/directory.js.map +1 -1
- package/dist/interfaces.d.ts +27 -17
- 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 +5 -5
- package/dist/map.d.ts.map +1 -1
- package/dist/map.js +15 -2
- 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 +58 -33
- 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 +6 -5
- package/lib/directory.d.ts.map +1 -1
- package/lib/directory.js +70 -32
- package/lib/directory.js.map +1 -1
- package/lib/interfaces.d.ts +27 -17
- 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 +5 -5
- package/lib/map.d.ts.map +1 -1
- package/lib/map.js +16 -3
- 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 +59 -34
- 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 +25 -22
- package/prettier.config.cjs +1 -1
- package/src/directory.ts +1957 -1848
- package/src/interfaces.ts +309 -288
- package/src/internalInterfaces.ts +83 -38
- package/src/localValues.ts +95 -93
- package/src/map.ts +364 -345
- package/src/mapKernel.ts +729 -676
- package/src/packageVersion.ts +1 -1
- package/tsconfig.esnext.json +5 -5
- package/tsconfig.json +9 -15
package/lib/directory.js
CHANGED
|
@@ -6,11 +6,11 @@ var _a, _b;
|
|
|
6
6
|
import { assert, TypedEventEmitter } from "@fluidframework/common-utils";
|
|
7
7
|
import { UsageError } from "@fluidframework/container-utils";
|
|
8
8
|
import { readAndParse } from "@fluidframework/driver-utils";
|
|
9
|
-
import { MessageType
|
|
9
|
+
import { MessageType } from "@fluidframework/protocol-definitions";
|
|
10
10
|
import { SharedObject, ValueType } from "@fluidframework/shared-object-base";
|
|
11
11
|
import { SummaryTreeBuilder } from "@fluidframework/runtime-utils";
|
|
12
12
|
import * as path from "path-browserify";
|
|
13
|
-
import { LocalValueMaker, makeSerializable
|
|
13
|
+
import { LocalValueMaker, makeSerializable } from "./localValues";
|
|
14
14
|
import { pkgVersion } from "./packageVersion";
|
|
15
15
|
// We use path-browserify since this code can run safely on the server or the browser.
|
|
16
16
|
// We standardize on using posix slashes everywhere.
|
|
@@ -137,6 +137,8 @@ export class SharedDirectory extends SharedObject {
|
|
|
137
137
|
/**
|
|
138
138
|
* {@inheritDoc IDirectory.get}
|
|
139
139
|
*/
|
|
140
|
+
// TODO: Use `unknown` instead (breaking change).
|
|
141
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
140
142
|
get(key) {
|
|
141
143
|
return this.root.get(key);
|
|
142
144
|
}
|
|
@@ -185,13 +187,18 @@ export class SharedDirectory extends SharedObject {
|
|
|
185
187
|
* Issue a callback on each entry under this IDirectory.
|
|
186
188
|
* @param callback - Callback to issue
|
|
187
189
|
*/
|
|
190
|
+
// TODO: Use `unknown` instead (breaking change).
|
|
191
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
188
192
|
forEach(callback) {
|
|
193
|
+
// eslint-disable-next-line unicorn/no-array-for-each, unicorn/no-array-callback-reference
|
|
189
194
|
this.root.forEach(callback);
|
|
190
195
|
}
|
|
191
196
|
/**
|
|
192
197
|
* Get an iterator over the entries under this IDirectory.
|
|
193
198
|
* @returns The iterator
|
|
194
199
|
*/
|
|
200
|
+
// TODO: Use `unknown` instead (breaking change).
|
|
201
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
195
202
|
[(_a = Symbol.toStringTag, Symbol.iterator)]() {
|
|
196
203
|
return this.root[Symbol.iterator]();
|
|
197
204
|
}
|
|
@@ -199,6 +206,8 @@ export class SharedDirectory extends SharedObject {
|
|
|
199
206
|
* Get an iterator over the entries under this IDirectory.
|
|
200
207
|
* @returns The iterator
|
|
201
208
|
*/
|
|
209
|
+
// TODO: Use `unknown` instead (breaking change).
|
|
210
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
202
211
|
entries() {
|
|
203
212
|
return this.root.entries();
|
|
204
213
|
}
|
|
@@ -219,6 +228,8 @@ export class SharedDirectory extends SharedObject {
|
|
|
219
228
|
* Get an iterator over the values under this IDirectory.
|
|
220
229
|
* @returns The iterator
|
|
221
230
|
*/
|
|
231
|
+
// TODO: Use `unknown` instead (breaking change).
|
|
232
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
222
233
|
values() {
|
|
223
234
|
return this.root.values();
|
|
224
235
|
}
|
|
@@ -261,7 +272,7 @@ export class SharedDirectory extends SharedObject {
|
|
|
261
272
|
return this.root;
|
|
262
273
|
}
|
|
263
274
|
let currentSubDir = this.root;
|
|
264
|
-
const subdirs = absolutePath.
|
|
275
|
+
const subdirs = absolutePath.slice(1).split(posix.sep);
|
|
265
276
|
for (const subdir of subdirs) {
|
|
266
277
|
currentSubDir = currentSubDir.getSubDirectory(subdir);
|
|
267
278
|
if (!currentSubDir) {
|
|
@@ -366,7 +377,7 @@ export class SharedDirectory extends SharedObject {
|
|
|
366
377
|
/**
|
|
367
378
|
* {@inheritDoc @fluidframework/shared-object-base#SharedObject.rollback}
|
|
368
379
|
* @internal
|
|
369
|
-
|
|
380
|
+
*/
|
|
370
381
|
rollback(content, localOpMetadata) {
|
|
371
382
|
const op = content;
|
|
372
383
|
const subdir = this.getWorkingDirectory(op.path);
|
|
@@ -392,7 +403,8 @@ export class SharedDirectory extends SharedObject {
|
|
|
392
403
|
* @returns The local value that was produced
|
|
393
404
|
*/
|
|
394
405
|
makeLocal(key, absolutePath, serializable) {
|
|
395
|
-
assert(serializable.type === ValueType[ValueType.Plain] ||
|
|
406
|
+
assert(serializable.type === ValueType[ValueType.Plain] ||
|
|
407
|
+
serializable.type === ValueType[ValueType.Shared], 0x1e4 /* "Unexpected serializable type" */);
|
|
396
408
|
return this.localValueMaker.fromSerializable(serializable);
|
|
397
409
|
}
|
|
398
410
|
/**
|
|
@@ -475,7 +487,6 @@ export class SharedDirectory extends SharedObject {
|
|
|
475
487
|
parentSubdir.resubmitSubDirectoryMessage(op, localOpMetadata);
|
|
476
488
|
}
|
|
477
489
|
},
|
|
478
|
-
// eslint-disable-next-line max-len
|
|
479
490
|
applyStashedOp: (op) => {
|
|
480
491
|
const parentSubdir = this.getWorkingDirectory(op.path);
|
|
481
492
|
if (parentSubdir) {
|
|
@@ -497,7 +508,6 @@ export class SharedDirectory extends SharedObject {
|
|
|
497
508
|
parentSubdir.resubmitSubDirectoryMessage(op, localOpMetadata);
|
|
498
509
|
}
|
|
499
510
|
},
|
|
500
|
-
// eslint-disable-next-line max-len
|
|
501
511
|
applyStashedOp: (op) => {
|
|
502
512
|
const parentSubdir = this.getWorkingDirectory(op.path);
|
|
503
513
|
if (parentSubdir) {
|
|
@@ -507,6 +517,7 @@ export class SharedDirectory extends SharedObject {
|
|
|
507
517
|
});
|
|
508
518
|
}
|
|
509
519
|
/**
|
|
520
|
+
* {@inheritDoc @fluidframework/shared-object-base#SharedObjectCore.applyStashedOp}
|
|
510
521
|
* @internal
|
|
511
522
|
*/
|
|
512
523
|
applyStashedOp(op) {
|
|
@@ -533,14 +544,13 @@ export class SharedDirectory extends SharedObject {
|
|
|
533
544
|
}
|
|
534
545
|
const result = {
|
|
535
546
|
type: value.type,
|
|
536
|
-
// eslint-disable-next-line @typescript-eslint/ban-types
|
|
537
547
|
value: value.value && JSON.parse(value.value),
|
|
538
548
|
};
|
|
539
549
|
if (value.value && value.value.length >= MinValueSizeSeparateSnapshotBlob) {
|
|
540
550
|
const extraContent = {};
|
|
541
551
|
let largeContent = extraContent;
|
|
542
552
|
if (currentSubDir.absolutePath !== posix.sep) {
|
|
543
|
-
for (const dir of currentSubDir.absolutePath.
|
|
553
|
+
for (const dir of currentSubDir.absolutePath.slice(1).split(posix.sep)) {
|
|
544
554
|
const subDataObject = {};
|
|
545
555
|
largeContent.subdirectories = { [dir]: subDataObject };
|
|
546
556
|
largeContent = subDataObject;
|
|
@@ -573,24 +583,33 @@ export class SharedDirectory extends SharedObject {
|
|
|
573
583
|
return builder.getSummaryTree();
|
|
574
584
|
}
|
|
575
585
|
}
|
|
586
|
+
/* eslint-disable @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-member-access */
|
|
576
587
|
function isKeyEditLocalOpMetadata(metadata) {
|
|
577
|
-
return metadata !== undefined &&
|
|
588
|
+
return (metadata !== undefined &&
|
|
589
|
+
typeof metadata.pendingMessageId === "number" &&
|
|
590
|
+
metadata.type === "edit");
|
|
578
591
|
}
|
|
579
592
|
function isClearLocalOpMetadata(metadata) {
|
|
580
|
-
return metadata !== undefined &&
|
|
581
|
-
|
|
593
|
+
return (metadata !== undefined &&
|
|
594
|
+
metadata.type === "clear" &&
|
|
595
|
+
typeof metadata.pendingMessageId === "number" &&
|
|
596
|
+
typeof metadata.previousStorage === "object");
|
|
582
597
|
}
|
|
583
598
|
function isSubDirLocalOpMetadata(metadata) {
|
|
584
|
-
return metadata !== undefined &&
|
|
599
|
+
return (metadata !== undefined &&
|
|
600
|
+
typeof metadata.pendingMessageId === "number" &&
|
|
585
601
|
((metadata.type === "createSubDir" && typeof metadata.previouslyExisted === "boolean") ||
|
|
586
|
-
metadata.type === "deleteSubDir");
|
|
602
|
+
metadata.type === "deleteSubDir"));
|
|
587
603
|
}
|
|
588
604
|
function isDirectoryLocalOpMetadata(metadata) {
|
|
589
|
-
return metadata !== undefined &&
|
|
590
|
-
|
|
605
|
+
return (metadata !== undefined &&
|
|
606
|
+
typeof metadata.pendingMessageId === "number" &&
|
|
607
|
+
(metadata.type === "edit" ||
|
|
608
|
+
metadata.type === "deleteSubDir" ||
|
|
591
609
|
(metadata.type === "clear" && typeof metadata.previousStorage === "object") ||
|
|
592
|
-
(metadata.type === "createSubDir" && typeof metadata.previouslyExisted === "boolean"));
|
|
610
|
+
(metadata.type === "createSubDir" && typeof metadata.previouslyExisted === "boolean")));
|
|
593
611
|
}
|
|
612
|
+
/* eslint-enable @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-member-access */
|
|
594
613
|
/**
|
|
595
614
|
* Node of the directory tree.
|
|
596
615
|
* @sealed
|
|
@@ -647,10 +666,11 @@ class SubDirectory extends TypedEventEmitter {
|
|
|
647
666
|
this.emit("disposed", this);
|
|
648
667
|
}
|
|
649
668
|
/**
|
|
650
|
-
* Unmark the deleted property when rolling back delete.
|
|
669
|
+
* Unmark the deleted property only when rolling back delete.
|
|
651
670
|
*/
|
|
652
671
|
undispose() {
|
|
653
672
|
this._deleted = false;
|
|
673
|
+
this.emit("undisposed", this);
|
|
654
674
|
}
|
|
655
675
|
get disposed() {
|
|
656
676
|
return this._deleted;
|
|
@@ -830,6 +850,7 @@ class SubDirectory extends TypedEventEmitter {
|
|
|
830
850
|
*/
|
|
831
851
|
forEach(callback) {
|
|
832
852
|
this.throwIfDisposed();
|
|
853
|
+
// eslint-disable-next-line unicorn/no-array-for-each
|
|
833
854
|
this._storage.forEach((localValue, key, map) => {
|
|
834
855
|
callback(localValue.value, key, map);
|
|
835
856
|
});
|
|
@@ -957,7 +978,11 @@ class SubDirectory extends TypedEventEmitter {
|
|
|
957
978
|
this.throwIfDisposed();
|
|
958
979
|
const previousValue = this.deleteCore(op.key, true);
|
|
959
980
|
const pendingMessageId = this.getKeyMessageId(op);
|
|
960
|
-
const localMetadata = {
|
|
981
|
+
const localMetadata = {
|
|
982
|
+
type: "edit",
|
|
983
|
+
pendingMessageId,
|
|
984
|
+
previousValue,
|
|
985
|
+
};
|
|
961
986
|
return localMetadata;
|
|
962
987
|
}
|
|
963
988
|
/**
|
|
@@ -989,7 +1014,11 @@ class SubDirectory extends TypedEventEmitter {
|
|
|
989
1014
|
const previousValue = this.setCore(op.key, context, true);
|
|
990
1015
|
// Create metadata
|
|
991
1016
|
const pendingMessageId = this.getKeyMessageId(op);
|
|
992
|
-
const localMetadata = {
|
|
1017
|
+
const localMetadata = {
|
|
1018
|
+
type: "edit",
|
|
1019
|
+
pendingMessageId,
|
|
1020
|
+
previousValue,
|
|
1021
|
+
};
|
|
993
1022
|
return localMetadata;
|
|
994
1023
|
}
|
|
995
1024
|
/**
|
|
@@ -1118,7 +1147,8 @@ class SubDirectory extends TypedEventEmitter {
|
|
|
1118
1147
|
assert(isKeyEditLocalOpMetadata(localOpMetadata), 0x32d /* Invalid localOpMetadata in submit */);
|
|
1119
1148
|
// clear the old pending message id
|
|
1120
1149
|
const pendingMessageIds = this.pendingKeys.get(op.key);
|
|
1121
|
-
assert(pendingMessageIds !== undefined &&
|
|
1150
|
+
assert(pendingMessageIds !== undefined &&
|
|
1151
|
+
pendingMessageIds[0] === localOpMetadata.pendingMessageId, 0x32e /* Unexpected pending message received */);
|
|
1122
1152
|
pendingMessageIds.shift();
|
|
1123
1153
|
if (pendingMessageIds.length === 0) {
|
|
1124
1154
|
this.pendingKeys.delete(op.key);
|
|
@@ -1180,7 +1210,8 @@ class SubDirectory extends TypedEventEmitter {
|
|
|
1180
1210
|
assert(isSubDirLocalOpMetadata(localOpMetadata), 0x32f /* Invalid localOpMetadata for sub directory op */);
|
|
1181
1211
|
// clear the old pending message id
|
|
1182
1212
|
const pendingMessageIds = this.pendingSubDirectories.get(op.subdirName);
|
|
1183
|
-
assert(pendingMessageIds !== undefined &&
|
|
1213
|
+
assert(pendingMessageIds !== undefined &&
|
|
1214
|
+
pendingMessageIds[0] === localOpMetadata.pendingMessageId, 0x330 /* Unexpected pending message received */);
|
|
1184
1215
|
pendingMessageIds.shift();
|
|
1185
1216
|
if (pendingMessageIds.length === 0) {
|
|
1186
1217
|
this.pendingSubDirectories.delete(op.subdirName);
|
|
@@ -1252,21 +1283,24 @@ class SubDirectory extends TypedEventEmitter {
|
|
|
1252
1283
|
map.delete(key);
|
|
1253
1284
|
}
|
|
1254
1285
|
}
|
|
1286
|
+
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
|
1255
1287
|
/**
|
|
1256
1288
|
* Rollback a local op
|
|
1257
1289
|
* @param op - The operation to rollback
|
|
1258
1290
|
* @param localOpMetadata - The local metadata associated with the op.
|
|
1259
1291
|
*/
|
|
1292
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
1260
1293
|
rollback(op, localOpMetadata) {
|
|
1261
1294
|
if (!isDirectoryLocalOpMetadata(localOpMetadata)) {
|
|
1262
1295
|
throw new Error("Invalid localOpMetadata");
|
|
1263
1296
|
}
|
|
1264
1297
|
if (op.type === "clear" && localOpMetadata.type === "clear") {
|
|
1265
|
-
localOpMetadata.previousStorage.
|
|
1298
|
+
for (const [key, localValue] of localOpMetadata.previousStorage.entries()) {
|
|
1266
1299
|
this.setCore(key, localValue, true);
|
|
1267
|
-
}
|
|
1300
|
+
}
|
|
1268
1301
|
const lastPendingClearId = this.pendingClearMessageIds.pop();
|
|
1269
|
-
if (lastPendingClearId === undefined ||
|
|
1302
|
+
if (lastPendingClearId === undefined ||
|
|
1303
|
+
lastPendingClearId !== localOpMetadata.pendingMessageId) {
|
|
1270
1304
|
throw new Error("Rollback op does match last clear");
|
|
1271
1305
|
}
|
|
1272
1306
|
}
|
|
@@ -1298,6 +1332,7 @@ class SubDirectory extends TypedEventEmitter {
|
|
|
1298
1332
|
throw new Error("Unsupported op for rollback");
|
|
1299
1333
|
}
|
|
1300
1334
|
}
|
|
1335
|
+
/* eslint-enable @typescript-eslint/no-unsafe-member-access */
|
|
1301
1336
|
/**
|
|
1302
1337
|
* Converts the given relative path into an absolute path.
|
|
1303
1338
|
* @param path - Relative path to convert
|
|
@@ -1318,7 +1353,8 @@ class SubDirectory extends TypedEventEmitter {
|
|
|
1318
1353
|
needProcessStorageOperation(op, local, localOpMetadata) {
|
|
1319
1354
|
if (this.pendingClearMessageIds.length > 0) {
|
|
1320
1355
|
if (local) {
|
|
1321
|
-
assert(localOpMetadata !== undefined &&
|
|
1356
|
+
assert(localOpMetadata !== undefined &&
|
|
1357
|
+
isKeyEditLocalOpMetadata(localOpMetadata) &&
|
|
1322
1358
|
localOpMetadata.pendingMessageId < this.pendingClearMessageIds[0], 0x010 /* "Received out of order storage op when there is an unackd clear message" */);
|
|
1323
1359
|
}
|
|
1324
1360
|
// If I have a NACK clear, we can ignore all ops.
|
|
@@ -1331,7 +1367,8 @@ class SubDirectory extends TypedEventEmitter {
|
|
|
1331
1367
|
if (local) {
|
|
1332
1368
|
assert(localOpMetadata !== undefined && isKeyEditLocalOpMetadata(localOpMetadata), 0x011 /* pendingMessageId is missing from the local client's operation */);
|
|
1333
1369
|
const pendingMessageIds = this.pendingKeys.get(op.key);
|
|
1334
|
-
assert(pendingMessageIds !== undefined &&
|
|
1370
|
+
assert(pendingMessageIds !== undefined &&
|
|
1371
|
+
pendingMessageIds[0] === localOpMetadata.pendingMessageId, 0x331 /* Unexpected pending message received */);
|
|
1335
1372
|
pendingMessageIds.shift();
|
|
1336
1373
|
if (pendingMessageIds.length === 0) {
|
|
1337
1374
|
this.pendingKeys.delete(op.key);
|
|
@@ -1358,7 +1395,8 @@ class SubDirectory extends TypedEventEmitter {
|
|
|
1358
1395
|
if (local) {
|
|
1359
1396
|
assert(isSubDirLocalOpMetadata(localOpMetadata), 0x012 /* pendingMessageId is missing from the local client's operation */);
|
|
1360
1397
|
const pendingMessageIds = this.pendingSubDirectories.get(op.subdirName);
|
|
1361
|
-
assert(pendingMessageIds !== undefined &&
|
|
1398
|
+
assert(pendingMessageIds !== undefined &&
|
|
1399
|
+
pendingMessageIds[0] === localOpMetadata.pendingMessageId, 0x332 /* Unexpected pending message received */);
|
|
1362
1400
|
pendingMessageIds.shift();
|
|
1363
1401
|
if (pendingMessageIds.length === 0) {
|
|
1364
1402
|
this.pendingSubDirectories.delete(op.subdirName);
|
|
@@ -1375,14 +1413,14 @@ class SubDirectory extends TypedEventEmitter {
|
|
|
1375
1413
|
// Assuming the pendingKeys is small and the map is large
|
|
1376
1414
|
// we will get the value for the pendingKeys and clear the map
|
|
1377
1415
|
const temp = new Map();
|
|
1378
|
-
|
|
1416
|
+
for (const [key] of this.pendingKeys) {
|
|
1379
1417
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
1380
1418
|
temp.set(key, this._storage.get(key));
|
|
1381
|
-
}
|
|
1419
|
+
}
|
|
1382
1420
|
this.clearCore(local);
|
|
1383
|
-
|
|
1421
|
+
for (const [key, value] of temp.entries()) {
|
|
1384
1422
|
this.setCore(key, value, true);
|
|
1385
|
-
}
|
|
1423
|
+
}
|
|
1386
1424
|
}
|
|
1387
1425
|
/**
|
|
1388
1426
|
* Clear implementation used for both locally sourced clears as well as incoming remote clears.
|