@fluid-experimental/last-edited 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 +3 -5
- package/README.md +13 -4
- package/api-extractor.json +2 -2
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/interfaces.d.ts.map +1 -1
- package/dist/interfaces.js.map +1 -1
- package/dist/lastEditedTracker.d.ts +1 -1
- package/dist/lastEditedTracker.d.ts.map +1 -1
- package/dist/lastEditedTracker.js.map +1 -1
- package/dist/lastEditedTrackerDataObject.d.ts.map +1 -1
- package/dist/lastEditedTrackerDataObject.js +3 -1
- package/dist/lastEditedTrackerDataObject.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/dist/setup.d.ts.map +1 -1
- package/dist/setup.js.map +1 -1
- package/lib/index.d.ts +1 -1
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +1 -1
- package/lib/index.js.map +1 -1
- package/lib/interfaces.d.ts.map +1 -1
- package/lib/interfaces.js.map +1 -1
- package/lib/lastEditedTracker.d.ts +1 -1
- package/lib/lastEditedTracker.d.ts.map +1 -1
- package/lib/lastEditedTracker.js.map +1 -1
- package/lib/lastEditedTrackerDataObject.d.ts.map +1 -1
- package/lib/lastEditedTrackerDataObject.js +3 -1
- package/lib/lastEditedTrackerDataObject.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/lib/setup.d.ts.map +1 -1
- package/lib/setup.js.map +1 -1
- package/package.json +17 -13
- package/prettier.config.cjs +8 -0
- package/src/index.ts +5 -1
- package/src/interfaces.ts +13 -12
- package/src/lastEditedTracker.ts +21 -21
- package/src/lastEditedTrackerDataObject.ts +43 -39
- package/src/packageVersion.ts +1 -1
- package/src/setup.ts +37 -35
- package/tsconfig.esnext.json +6 -6
- package/tsconfig.json +9 -16
package/.eslintrc.js
CHANGED
package/README.md
CHANGED
|
@@ -3,9 +3,11 @@
|
|
|
3
3
|
LastEditedTracker tracks the last edit to a document, such as the client who last edited the document and the time it happened.
|
|
4
4
|
|
|
5
5
|
It is created by passing a `SharedSummaryBlock`:
|
|
6
|
+
|
|
6
7
|
```
|
|
7
8
|
constructor(private readonly sharedSummaryBlock: SharedSummaryBlock);
|
|
8
9
|
```
|
|
10
|
+
|
|
9
11
|
It uses the SharedSummaryBlock to store the last edit details.
|
|
10
12
|
|
|
11
13
|
## API
|
|
@@ -18,6 +20,7 @@ public updateLastEditDetails(message: ISequencedDocumentMessage);
|
|
|
18
20
|
```
|
|
19
21
|
|
|
20
22
|
The update should always be called in response to a remote op because:
|
|
23
|
+
|
|
21
24
|
1. It updates its state from the remote op.
|
|
22
25
|
2. It uses a SharedSummaryBlock as storage which must be set in response to a remote op.
|
|
23
26
|
|
|
@@ -32,11 +35,14 @@ It implements IProvideFluidLastEditedTracker and returns an IFluidLastEditedTrac
|
|
|
32
35
|
# Setup
|
|
33
36
|
|
|
34
37
|
This package also provides a `setupLastEditedTrackerForContainer` method that can be used to set up a data store that provides IFluidLastEditedTracker to track last edited in a Container:
|
|
35
|
-
|
|
36
|
-
-
|
|
38
|
+
|
|
39
|
+
- This setup function should be called during container instantiation so that ops are not missed.
|
|
40
|
+
- Registers an "op" listener on the runtime. On each message, it calls the shouldDiscardMessageFn to check if the message should be discarded. It also discards all scheduler message. If a message is not discarded, it passes the last edited information from the message to the last edited tracker in the data store.
|
|
37
41
|
|
|
38
42
|
Note:
|
|
39
|
-
|
|
43
|
+
|
|
44
|
+
- By default, message that are not of `"Attach"` and `"Operation"` type are discarded as per the `shouldDiscardMessageDefault` function:
|
|
45
|
+
|
|
40
46
|
```
|
|
41
47
|
function shouldDiscardMessageDefault(message: ISequencedDocumentMessage) {
|
|
42
48
|
if (message.type === MessageType.Attach || message.type === MessageType.Operation) {
|
|
@@ -45,13 +51,15 @@ function shouldDiscardMessageDefault(message: ISequencedDocumentMessage) {
|
|
|
45
51
|
return true;
|
|
46
52
|
}.
|
|
47
53
|
```
|
|
48
|
-
|
|
54
|
+
|
|
55
|
+
- To discard specific ops, provide the `shouldDiscardMessageFn` funtion that takes in the message and returns a boolean indicating if the message should be discarded.
|
|
49
56
|
|
|
50
57
|
# Usage
|
|
51
58
|
|
|
52
59
|
## For tracking the last edit on a Container:
|
|
53
60
|
|
|
54
61
|
In instantiateRuntime, create a data store that implements IFluidLastEditedTracker. Then call `setupLastEditedTrackerForContainer` with the id of the data store:
|
|
62
|
+
|
|
55
63
|
```
|
|
56
64
|
public async instantiateRuntime(context: IContainerContext): Promise<IRuntime> {
|
|
57
65
|
const dataStoreId = "root";
|
|
@@ -73,6 +81,7 @@ public async instantiateRuntime(context: IContainerContext): Promise<IRuntime> {
|
|
|
73
81
|
This will make sure that the root data store loads before any other data store and it tracks every op in the Container.
|
|
74
82
|
|
|
75
83
|
The IFluidLastEditedTracker can be retrieved from the root data store:
|
|
84
|
+
|
|
76
85
|
```
|
|
77
86
|
const response = await containerRuntime.request({ url: "/" });
|
|
78
87
|
const root = response.value;
|
package/api-extractor.json
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
2
|
+
"$schema": "https://developer.microsoft.com/json-schemas/api-extractor/v7/api-extractor.schema.json",
|
|
3
|
+
"extends": "@fluidframework/build-common/api-extractor-common.json"
|
|
4
4
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
|
|
3
3
|
* Licensed under the MIT License.
|
|
4
4
|
*/
|
|
5
|
-
export { IFluidLastEditedTracker, ILastEditDetails, IProvideFluidLastEditedTracker } from "./interfaces";
|
|
5
|
+
export { IFluidLastEditedTracker, ILastEditDetails, IProvideFluidLastEditedTracker, } from "./interfaces";
|
|
6
6
|
export { LastEditedTracker } from "./lastEditedTracker";
|
|
7
7
|
export { LastEditedTrackerDataObject } from "./lastEditedTrackerDataObject";
|
|
8
8
|
export { setupLastEditedTrackerForContainer } from "./setup";
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EACN,uBAAuB,EACvB,gBAAgB,EAChB,8BAA8B,GAC9B,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,2BAA2B,EAAE,MAAM,+BAA+B,CAAC;AAC5E,OAAO,EAAE,kCAAkC,EAAE,MAAM,SAAS,CAAC"}
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA;;;GAGG;AACH,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA;;;GAGG;AACH,2CAIsB;AAHrB,qHAAA,uBAAuB,OAAA;AAIxB,yDAAwD;AAA/C,sHAAA,iBAAiB,OAAA;AAC1B,6EAA4E;AAAnE,0IAAA,2BAA2B,OAAA;AACpC,iCAA6D;AAApD,2HAAA,kCAAkC,OAAA","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\nexport {\n\tIFluidLastEditedTracker,\n\tILastEditDetails,\n\tIProvideFluidLastEditedTracker,\n} from \"./interfaces\";\nexport { LastEditedTracker } from \"./lastEditedTracker\";\nexport { LastEditedTrackerDataObject } from \"./lastEditedTrackerDataObject\";\nexport { setupLastEditedTrackerForContainer } from \"./setup\";\n"]}
|
package/dist/interfaces.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"interfaces.d.ts","sourceRoot":"","sources":["../src/interfaces.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,KAAK,EAAE,MAAM,sCAAsC,CAAC;AAE7D,eAAO,MAAM,uBAAuB,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"interfaces.d.ts","sourceRoot":"","sources":["../src/interfaces.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,KAAK,EAAE,MAAM,sCAAsC,CAAC;AAE7D,eAAO,MAAM,uBAAuB,EAAE,MAAM,8BAClB,CAAC;AAE3B,MAAM,WAAW,8BAA8B;IAC9C,QAAQ,CAAC,uBAAuB,EAAE,uBAAuB,CAAC;CAC1D;AAED,MAAM,WAAW,uBAAwB,SAAQ,8BAA8B;IAC9E;;OAEG;IACH,kBAAkB,IAAI,gBAAgB,GAAG,SAAS,CAAC;IAEnD;;OAEG;IACH,qBAAqB,CAAC,eAAe,EAAE,gBAAgB,GAAG,IAAI,CAAC;CAC/D;AAED,MAAM,WAAW,gBAAgB;IAChC,IAAI,EAAE,KAAK,CAAC;IACZ,SAAS,EAAE,MAAM,CAAC;CAClB"}
|
package/dist/interfaces.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"interfaces.js","sourceRoot":"","sources":["../src/interfaces.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AAIU,QAAA,uBAAuB,
|
|
1
|
+
{"version":3,"file":"interfaces.js","sourceRoot":"","sources":["../src/interfaces.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AAIU,QAAA,uBAAuB,GACnC,yBAAyB,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { IUser } from \"@fluidframework/protocol-definitions\";\n\nexport const IFluidLastEditedTracker: keyof IProvideFluidLastEditedTracker =\n\t\"IFluidLastEditedTracker\";\n\nexport interface IProvideFluidLastEditedTracker {\n\treadonly IFluidLastEditedTracker: IFluidLastEditedTracker;\n}\n\nexport interface IFluidLastEditedTracker extends IProvideFluidLastEditedTracker {\n\t/**\n\t * Returns the details of the last edit to the container.\n\t */\n\tgetLastEditDetails(): ILastEditDetails | undefined;\n\n\t/**\n\t * Updates the details of last edit to the container.\n\t */\n\tupdateLastEditDetails(lastEditDetails: ILastEditDetails): void;\n}\n\nexport interface ILastEditDetails {\n\tuser: IUser;\n\ttimestamp: number;\n}\n"]}
|
|
@@ -17,7 +17,7 @@ export declare class LastEditedTracker implements IFluidLastEditedTracker {
|
|
|
17
17
|
* @param sharedSummaryBlock - The shared summary block where the details will be stored.
|
|
18
18
|
*/
|
|
19
19
|
constructor(sharedSummaryBlock: SharedSummaryBlock);
|
|
20
|
-
get IFluidLastEditedTracker():
|
|
20
|
+
get IFluidLastEditedTracker(): LastEditedTracker;
|
|
21
21
|
/**
|
|
22
22
|
* {@inheritDoc (IFluidLastEditedTracker:interface).getLastEditDetails}
|
|
23
23
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lastEditedTracker.d.ts","sourceRoot":"","sources":["../src/lastEditedTracker.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,kBAAkB,EAAE,MAAM,sCAAsC,CAAC;AAC1E,OAAO,EAAE,uBAAuB,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAEzE;;;;GAIG;AACH,qBAAa,iBAAkB,YAAW,uBAAuB;
|
|
1
|
+
{"version":3,"file":"lastEditedTracker.d.ts","sourceRoot":"","sources":["../src/lastEditedTracker.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,kBAAkB,EAAE,MAAM,sCAAsC,CAAC;AAC1E,OAAO,EAAE,uBAAuB,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAEzE;;;;GAIG;AACH,qBAAa,iBAAkB,YAAW,uBAAuB;IAOpD,OAAO,CAAC,QAAQ,CAAC,kBAAkB;IAN/C,OAAO,CAAC,QAAQ,CAAC,oBAAoB,CAAwB;IAE7D;;;OAGG;gBAC0B,kBAAkB,EAAE,kBAAkB;IAEnE,IAAW,uBAAuB,IAAI,iBAAiB,CAEtD;IAED;;OAEG;IACI,kBAAkB,IAAI,gBAAgB,GAAG,SAAS;IAIzD;;OAEG;IACI,qBAAqB,CAAC,eAAe,EAAE,gBAAgB,GAAG,IAAI;CAGrE"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lastEditedTracker.js","sourceRoot":"","sources":["../src/lastEditedTracker.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AAKH;;;;GAIG;AACH,MAAa,iBAAiB;
|
|
1
|
+
{"version":3,"file":"lastEditedTracker.js","sourceRoot":"","sources":["../src/lastEditedTracker.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AAKH;;;;GAIG;AACH,MAAa,iBAAiB;IAG7B;;;OAGG;IACH,YAA6B,kBAAsC;QAAtC,uBAAkB,GAAlB,kBAAkB,CAAoB;QANlD,yBAAoB,GAAG,oBAAoB,CAAC;IAMS,CAAC;IAEvE,IAAW,uBAAuB;QACjC,OAAO,IAAI,CAAC;IACb,CAAC;IAED;;OAEG;IACI,kBAAkB;QACxB,OAAO,IAAI,CAAC,kBAAkB,CAAC,GAAG,CAAmB,IAAI,CAAC,oBAAoB,CAAC,CAAC;IACjF,CAAC;IAED;;OAEG;IACI,qBAAqB,CAAC,eAAiC;QAC7D,IAAI,CAAC,kBAAkB,CAAC,GAAG,CAAC,IAAI,CAAC,oBAAoB,EAAE,eAAe,CAAC,CAAC;IACzE,CAAC;CACD;AA1BD,8CA0BC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { SharedSummaryBlock } from \"@fluidframework/shared-summary-block\";\nimport { IFluidLastEditedTracker, ILastEditDetails } from \"./interfaces\";\n\n/**\n * Tracks the last edit details such as the last edited user details and the last edited timestamp. The last edited\n * details should be updated (via updateLastEditDetails) in response to a remote op since it uses shared summary block\n * as storage.\n */\nexport class LastEditedTracker implements IFluidLastEditedTracker {\n\tprivate readonly lastEditedDetailsKey = \"lastEditDetailsKey\";\n\n\t/**\n\t * Creates a LastEditedTracker object.\n\t * @param sharedSummaryBlock - The shared summary block where the details will be stored.\n\t */\n\tconstructor(private readonly sharedSummaryBlock: SharedSummaryBlock) {}\n\n\tpublic get IFluidLastEditedTracker(): LastEditedTracker {\n\t\treturn this;\n\t}\n\n\t/**\n\t * {@inheritDoc (IFluidLastEditedTracker:interface).getLastEditDetails}\n\t */\n\tpublic getLastEditDetails(): ILastEditDetails | undefined {\n\t\treturn this.sharedSummaryBlock.get<ILastEditDetails>(this.lastEditedDetailsKey);\n\t}\n\n\t/**\n\t * {@inheritDoc (IFluidLastEditedTracker:interface).updateLastEditDetails}\n\t */\n\tpublic updateLastEditDetails(lastEditDetails: ILastEditDetails): void {\n\t\tthis.sharedSummaryBlock.set(this.lastEditedDetailsKey, lastEditDetails);\n\t}\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lastEditedTrackerDataObject.d.ts","sourceRoot":"","sources":["../src/lastEditedTrackerDataObject.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAGzE,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,8BAA8B,EAAE,MAAM,cAAc,CAAC;AAE9D;;GAEG;AACH,qBAAa,
|
|
1
|
+
{"version":3,"file":"lastEditedTrackerDataObject.d.ts","sourceRoot":"","sources":["../src/lastEditedTrackerDataObject.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAGzE,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,8BAA8B,EAAE,MAAM,cAAc,CAAC;AAE9D;;GAEG;AACH,qBAAa,2BACZ,SAAQ,UACR,YAAW,8BAA8B;IAEzC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,OAAO,CAO5B;WAEW,UAAU,IAAI,iBAAiB,CAAC,2BAA2B,CAAC;IAI1E,OAAO,CAAC,QAAQ,CAAC,oBAAoB,CAA6B;IAClE,OAAO,CAAC,kBAAkB,CAAgC;IAE1D,OAAO,KAAK,iBAAiB,GAM5B;IAED,IAAW,uBAAuB,IAAI,iBAAiB,CAEtD;cAEe,qBAAqB,IAAI,OAAO,CAAC,IAAI,CAAC;cAKtC,cAAc,IAAI,OAAO,CAAC,IAAI,CAAC;CAM/C"}
|
|
@@ -25,7 +25,9 @@ class LastEditedTrackerDataObject extends aqueduct_1.DataObject {
|
|
|
25
25
|
}
|
|
26
26
|
return this._lastEditedTracker;
|
|
27
27
|
}
|
|
28
|
-
get IFluidLastEditedTracker() {
|
|
28
|
+
get IFluidLastEditedTracker() {
|
|
29
|
+
return this.lastEditedTracker;
|
|
30
|
+
}
|
|
29
31
|
async initializingFirstTime() {
|
|
30
32
|
const sharedSummaryBlock = shared_summary_block_1.SharedSummaryBlock.create(this.runtime);
|
|
31
33
|
this.root.set(this.sharedSummaryBlockId, sharedSummaryBlock.handle);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lastEditedTrackerDataObject.js","sourceRoot":"","sources":["../src/lastEditedTrackerDataObject.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AAEH,uDAAyE;AAEzE,+EAA0E;AAC1E,2DAAwD;AAGxD;;GAEG;AACH,MAAa,
|
|
1
|
+
{"version":3,"file":"lastEditedTrackerDataObject.js","sourceRoot":"","sources":["../src/lastEditedTrackerDataObject.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AAEH,uDAAyE;AAEzE,+EAA0E;AAC1E,2DAAwD;AAGxD;;GAEG;AACH,MAAa,2BACZ,SAAQ,qBAAU;IADnB;;QAiBkB,yBAAoB,GAAG,yBAAyB,CAAC;IA0BnE,CAAC;IA9BO,MAAM,CAAC,UAAU;QACvB,OAAO,2BAA2B,CAAC,OAAO,CAAC;IAC5C,CAAC;IAKD,IAAY,iBAAiB;QAC5B,IAAI,IAAI,CAAC,kBAAkB,KAAK,SAAS,EAAE;YAC1C,MAAM,IAAI,KAAK,CAAC,kDAAkD,CAAC,CAAC;SACpE;QAED,OAAO,IAAI,CAAC,kBAAkB,CAAC;IAChC,CAAC;IAED,IAAW,uBAAuB;QACjC,OAAO,IAAI,CAAC,iBAAiB,CAAC;IAC/B,CAAC;IAES,KAAK,CAAC,qBAAqB;QACpC,MAAM,kBAAkB,GAAG,yCAAkB,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACnE,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,oBAAoB,EAAE,kBAAkB,CAAC,MAAM,CAAC,CAAC;IACrE,CAAC;IAES,KAAK,CAAC,cAAc;QAC7B,MAAM,kBAAkB;QACvB,oEAAoE;QACpE,MAAM,IAAI,CAAC,IAAI,CAAC,GAAG,CAAmC,IAAI,CAAC,oBAAoB,CAAE,CAAC,GAAG,EAAE,CAAC;QACzF,IAAI,CAAC,kBAAkB,GAAG,IAAI,qCAAiB,CAAC,kBAAkB,CAAC,CAAC;IACrE,CAAC;;AA1CF,kEA2CC;AAvCwB,mCAAO,GAC9B,IAAI,4BAAiB,CACpB,iCAAiC,EACjC,2BAA2B,EAC3B,CAAC,yCAAkB,CAAC,UAAU,EAAE,CAAC,EACjC,EAAE,EACF,SAAS,CACT,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { DataObject, DataObjectFactory } from \"@fluidframework/aqueduct\";\nimport { IFluidHandle } from \"@fluidframework/core-interfaces\";\nimport { SharedSummaryBlock } from \"@fluidframework/shared-summary-block\";\nimport { LastEditedTracker } from \"./lastEditedTracker\";\nimport { IProvideFluidLastEditedTracker } from \"./interfaces\";\n\n/**\n * LastEditedTrackerDataObject creates a LastEditedTracker that keeps track of the latest edits to the document.\n */\nexport class LastEditedTrackerDataObject\n\textends DataObject\n\timplements IProvideFluidLastEditedTracker\n{\n\tprivate static readonly factory: DataObjectFactory<LastEditedTrackerDataObject> =\n\t\tnew DataObjectFactory(\n\t\t\t\"@fluid-experimental/last-edited\",\n\t\t\tLastEditedTrackerDataObject,\n\t\t\t[SharedSummaryBlock.getFactory()],\n\t\t\t{},\n\t\t\tundefined,\n\t\t);\n\n\tpublic static getFactory(): DataObjectFactory<LastEditedTrackerDataObject> {\n\t\treturn LastEditedTrackerDataObject.factory;\n\t}\n\n\tprivate readonly sharedSummaryBlockId = \"shared-summary-block-id\";\n\tprivate _lastEditedTracker: LastEditedTracker | undefined;\n\n\tprivate get lastEditedTracker(): LastEditedTracker {\n\t\tif (this._lastEditedTracker === undefined) {\n\t\t\tthrow new Error(\"Last Edited tracker was not initialized properly\");\n\t\t}\n\n\t\treturn this._lastEditedTracker;\n\t}\n\n\tpublic get IFluidLastEditedTracker(): LastEditedTracker {\n\t\treturn this.lastEditedTracker;\n\t}\n\n\tprotected async initializingFirstTime(): Promise<void> {\n\t\tconst sharedSummaryBlock = SharedSummaryBlock.create(this.runtime);\n\t\tthis.root.set(this.sharedSummaryBlockId, sharedSummaryBlock.handle);\n\t}\n\n\tprotected async hasInitialized(): Promise<void> {\n\t\tconst sharedSummaryBlock =\n\t\t\t// eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n\t\t\tawait this.root.get<IFluidHandle<SharedSummaryBlock>>(this.sharedSummaryBlockId)!.get();\n\t\tthis._lastEditedTracker = new LastEditedTracker(sharedSummaryBlock);\n\t}\n}\n"]}
|
package/dist/packageVersion.d.ts
CHANGED
|
@@ -5,5 +5,5 @@
|
|
|
5
5
|
* THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY
|
|
6
6
|
*/
|
|
7
7
|
export declare const pkgName = "@fluid-experimental/last-edited";
|
|
8
|
-
export declare const pkgVersion = "2.0.0-dev.
|
|
8
|
+
export declare const pkgVersion = "2.0.0-dev.3.1.0.125672";
|
|
9
9
|
//# sourceMappingURL=packageVersion.d.ts.map
|
package/dist/packageVersion.js
CHANGED
|
@@ -8,5 +8,5 @@
|
|
|
8
8
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
9
|
exports.pkgVersion = exports.pkgName = void 0;
|
|
10
10
|
exports.pkgName = "@fluid-experimental/last-edited";
|
|
11
|
-
exports.pkgVersion = "2.0.0-dev.
|
|
11
|
+
exports.pkgVersion = "2.0.0-dev.3.1.0.125672";
|
|
12
12
|
//# sourceMappingURL=packageVersion.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"packageVersion.js","sourceRoot":"","sources":["../src/packageVersion.ts"],"names":[],"mappings":";AAAA;;;;;GAKG;;;AAEU,QAAA,OAAO,GAAG,iCAAiC,CAAC;AAC5C,QAAA,UAAU,GAAG,wBAAwB,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n *\n * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY\n */\n\nexport const pkgName = \"@fluid-experimental/last-edited\";\nexport const pkgVersion = \"2.0.0-dev.
|
|
1
|
+
{"version":3,"file":"packageVersion.js","sourceRoot":"","sources":["../src/packageVersion.ts"],"names":[],"mappings":";AAAA;;;;;GAKG;;;AAEU,QAAA,OAAO,GAAG,iCAAiC,CAAC;AAC5C,QAAA,UAAU,GAAG,wBAAwB,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n *\n * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY\n */\n\nexport const pkgName = \"@fluid-experimental/last-edited\";\nexport const pkgVersion = \"2.0.0-dev.3.1.0.125672\";\n"]}
|
package/dist/setup.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"setup.d.ts","sourceRoot":"","sources":["../src/setup.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,yBAAyB,EAAkB,MAAM,sCAAsC,CAAC;AAEjG,OAAO,EAAE,iBAAiB,EAAE,MAAM,+CAA+C,CAAC;AAClF,OAAO,EAAoB,uBAAuB,EAAE,MAAM,cAAc,CAAC;AAkCzE;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,kCAAkC,
|
|
1
|
+
{"version":3,"file":"setup.d.ts","sourceRoot":"","sources":["../src/setup.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,yBAAyB,EAAkB,MAAM,sCAAsC,CAAC;AAEjG,OAAO,EAAE,iBAAiB,EAAE,MAAM,+CAA+C,CAAC;AAClF,OAAO,EAAoB,uBAAuB,EAAE,MAAM,cAAc,CAAC;AAkCzE;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,kCAAkC,CACjD,iBAAiB,EAAE,uBAAuB,EAC1C,OAAO,EAAE,iBAAiB,EAC1B,sBAAsB,GAAE,CACvB,OAAO,EAAE,yBAAyB,KAC9B,OAAqC,GACxC,IAAI,CAkBN"}
|
package/dist/setup.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"setup.js","sourceRoot":"","sources":["../src/setup.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AAGH,yEAAyE;AAIzE;;;;;;GAMG;AACH,MAAM,2BAA2B,GAAG,CAAC,OAAkC,
|
|
1
|
+
{"version":3,"file":"setup.js","sourceRoot":"","sources":["../src/setup.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AAGH,yEAAyE;AAIzE;;;;;;GAMG;AACH,MAAM,2BAA2B,GAAG,CAAC,OAAkC,EAAW,EAAE,CACnF,OAAO,CAAC,IAAI,KAAK,wCAAoB,CAAC,MAAM;IAC5C,OAAO,CAAC,IAAI,KAAK,wCAAoB,CAAC,gBAAgB;IACtD,OAAO,CAAC,IAAI,KAAK,wCAAoB,CAAC,KAAK,CAAC;AAE7C;;;GAGG;AACH,SAAS,6BAA6B,CACrC,OAAkC,EAClC,MAAsB;IAEtB,MAAM,eAAe,GAAG,MAAM,CAAC,SAAS,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IAC3D,MAAM,IAAI,GAAG,eAAe,aAAf,eAAe,uBAAf,eAAe,CAAE,MAAM,CAAC,IAAI,CAAC;IAC1C,IAAI,IAAI,KAAK,SAAS,EAAE;QACvB,MAAM,eAAe,GAAqB;YACzC,IAAI;YACJ,SAAS,EAAE,OAAO,CAAC,SAAS;SAC5B,CAAC;QACF,OAAO,eAAe,CAAC;KACvB;IACD,OAAO,SAAS,CAAC;AAClB,CAAC;AAED;;;;;;;;;;;;;;GAcG;AACH,SAAgB,kCAAkC,CACjD,iBAA0C,EAC1C,OAA0B,EAC1B,yBAEe,2BAA2B;IAE1C,+EAA+E;IAC/E,+CAA+C;IAC/C,8GAA8G;IAC9G,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,OAAkC,EAAE,cAAwB,EAAE,EAAE;QACjF,6EAA6E;QAC7E,IAAI,cAAc,KAAK,KAAK,IAAI,sBAAsB,CAAC,OAAO,CAAC,EAAE;YAChE,OAAO;SACP;QAED,6EAA6E;QAC7E,MAAM,eAAe,GAAG,6BAA6B,CAAC,OAAO,EAAE,OAAO,CAAC,SAAS,EAAE,CAAC,CAAC;QACpF,IAAI,eAAe,KAAK,SAAS,EAAE;YAClC,OAAO;SACP;QAED,iBAAiB,CAAC,qBAAqB,CAAC,eAAe,CAAC,CAAC;IAC1D,CAAC,CAAC,CAAC;AACJ,CAAC;AAxBD,gFAwBC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { ISequencedDocumentMessage, IQuorumClients } from \"@fluidframework/protocol-definitions\";\nimport { ContainerMessageType } from \"@fluidframework/container-runtime\";\nimport { IContainerRuntime } from \"@fluidframework/container-runtime-definitions\";\nimport { ILastEditDetails, IFluidLastEditedTracker } from \"./interfaces\";\n\n/**\n * Default implementation of {@link setupLastEditedTrackerForContainer}'s `shouldDiscardMessageFn` parameter,\n * which tells that all messages other than {@link @fluidframework/container-runtime#ContainerMessageType.Alias},\n * {@link @fluidframework/container-runtime#ContainerMessageType.Attach}, and\n * {@link @fluidframework/container-runtime#ContainerMessageType.FluidDataStoreOp} type messages should be\n * discarded.\n */\nconst shouldDiscardMessageDefault = (message: ISequencedDocumentMessage): boolean =>\n\tmessage.type !== ContainerMessageType.Attach &&\n\tmessage.type !== ContainerMessageType.FluidDataStoreOp &&\n\tmessage.type !== ContainerMessageType.Alias;\n\n/**\n * Extracts the user information and timestamp from a message. Returns undefined if the user information for the\n * client who sent the message doesn't exist in the quorum.\n */\nfunction getLastEditDetailsFromMessage(\n\tmessage: ISequencedDocumentMessage,\n\tquorum: IQuorumClients,\n): ILastEditDetails | undefined {\n\tconst sequencedClient = quorum.getMember(message.clientId);\n\tconst user = sequencedClient?.client.user;\n\tif (user !== undefined) {\n\t\tconst lastEditDetails: ILastEditDetails = {\n\t\t\tuser,\n\t\t\ttimestamp: message.timestamp,\n\t\t};\n\t\treturn lastEditDetails;\n\t}\n\treturn undefined;\n}\n\n/**\n * Helper function to set up a data object that provides IFluidLastEditedTracker to track last edited in a Container.\n *\n * It does the following:\n *\n * - Registers an \"op\" listener on the runtime. On each message, it calls the shouldDiscardMessageFn to check\n * if the message should be discarded. It also discards all scheduler message. If a message is not discarded,\n * it passes the last edited information from the message to the last edited tracker.\n *\n * - The last edited information from the last message received before the lastEditedTracker is\n * loaded is stored and passed to the tracker once it loads.\n * @param lastEditedTracker - The last edited tracker.\n * @param runtime - The container runtime whose messages are to be tracked.\n * @param shouldDiscardMessageFn - Function that tells if a message should not be considered in computing last edited.\n */\nexport function setupLastEditedTrackerForContainer(\n\tlastEditedTracker: IFluidLastEditedTracker,\n\truntime: IContainerRuntime,\n\tshouldDiscardMessageFn: (\n\t\tmessage: ISequencedDocumentMessage,\n\t) => boolean = shouldDiscardMessageDefault,\n): void {\n\t// Register an op listener on the runtime. If the lastEditedTracker has loaded,\n\t// it passes the last edited information to its\n\t// last edited tracker. If the lastEditedTracker hasn't loaded, store the last edited information temporarily.\n\truntime.on(\"op\", (message: ISequencedDocumentMessage, runtimeMessage?: boolean) => {\n\t\t// If this message should be discarded as per shouldDiscardMessageFn, return.\n\t\tif (runtimeMessage === false || shouldDiscardMessageFn(message)) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Get the last edited details from the message. If it doesn't exist, return.\n\t\tconst lastEditDetails = getLastEditDetailsFromMessage(message, runtime.getQuorum());\n\t\tif (lastEditDetails === undefined) {\n\t\t\treturn;\n\t\t}\n\n\t\tlastEditedTracker.updateLastEditDetails(lastEditDetails);\n\t});\n}\n"]}
|
package/lib/index.d.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
|
|
3
3
|
* Licensed under the MIT License.
|
|
4
4
|
*/
|
|
5
|
-
export { IFluidLastEditedTracker, ILastEditDetails, IProvideFluidLastEditedTracker } from "./interfaces";
|
|
5
|
+
export { IFluidLastEditedTracker, ILastEditDetails, IProvideFluidLastEditedTracker, } from "./interfaces";
|
|
6
6
|
export { LastEditedTracker } from "./lastEditedTracker";
|
|
7
7
|
export { LastEditedTrackerDataObject } from "./lastEditedTrackerDataObject";
|
|
8
8
|
export { setupLastEditedTrackerForContainer } from "./setup";
|
package/lib/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EACN,uBAAuB,EACvB,gBAAgB,EAChB,8BAA8B,GAC9B,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,2BAA2B,EAAE,MAAM,+BAA+B,CAAC;AAC5E,OAAO,EAAE,kCAAkC,EAAE,MAAM,SAAS,CAAC"}
|
package/lib/index.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
|
|
3
3
|
* Licensed under the MIT License.
|
|
4
4
|
*/
|
|
5
|
-
export { IFluidLastEditedTracker } from "./interfaces";
|
|
5
|
+
export { IFluidLastEditedTracker, } from "./interfaces";
|
|
6
6
|
export { LastEditedTracker } from "./lastEditedTracker";
|
|
7
7
|
export { LastEditedTrackerDataObject } from "./lastEditedTrackerDataObject";
|
|
8
8
|
export { setupLastEditedTrackerForContainer } from "./setup";
|
package/lib/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EACN,uBAAuB,GAGvB,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,2BAA2B,EAAE,MAAM,+BAA+B,CAAC;AAC5E,OAAO,EAAE,kCAAkC,EAAE,MAAM,SAAS,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\nexport {\n\tIFluidLastEditedTracker,\n\tILastEditDetails,\n\tIProvideFluidLastEditedTracker,\n} from \"./interfaces\";\nexport { LastEditedTracker } from \"./lastEditedTracker\";\nexport { LastEditedTrackerDataObject } from \"./lastEditedTrackerDataObject\";\nexport { setupLastEditedTrackerForContainer } from \"./setup\";\n"]}
|
package/lib/interfaces.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"interfaces.d.ts","sourceRoot":"","sources":["../src/interfaces.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,KAAK,EAAE,MAAM,sCAAsC,CAAC;AAE7D,eAAO,MAAM,uBAAuB,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"interfaces.d.ts","sourceRoot":"","sources":["../src/interfaces.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,KAAK,EAAE,MAAM,sCAAsC,CAAC;AAE7D,eAAO,MAAM,uBAAuB,EAAE,MAAM,8BAClB,CAAC;AAE3B,MAAM,WAAW,8BAA8B;IAC9C,QAAQ,CAAC,uBAAuB,EAAE,uBAAuB,CAAC;CAC1D;AAED,MAAM,WAAW,uBAAwB,SAAQ,8BAA8B;IAC9E;;OAEG;IACH,kBAAkB,IAAI,gBAAgB,GAAG,SAAS,CAAC;IAEnD;;OAEG;IACH,qBAAqB,CAAC,eAAe,EAAE,gBAAgB,GAAG,IAAI,CAAC;CAC/D;AAED,MAAM,WAAW,gBAAgB;IAChC,IAAI,EAAE,KAAK,CAAC;IACZ,SAAS,EAAE,MAAM,CAAC;CAClB"}
|
package/lib/interfaces.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"interfaces.js","sourceRoot":"","sources":["../src/interfaces.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,MAAM,CAAC,MAAM,uBAAuB,
|
|
1
|
+
{"version":3,"file":"interfaces.js","sourceRoot":"","sources":["../src/interfaces.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,MAAM,CAAC,MAAM,uBAAuB,GACnC,yBAAyB,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { IUser } from \"@fluidframework/protocol-definitions\";\n\nexport const IFluidLastEditedTracker: keyof IProvideFluidLastEditedTracker =\n\t\"IFluidLastEditedTracker\";\n\nexport interface IProvideFluidLastEditedTracker {\n\treadonly IFluidLastEditedTracker: IFluidLastEditedTracker;\n}\n\nexport interface IFluidLastEditedTracker extends IProvideFluidLastEditedTracker {\n\t/**\n\t * Returns the details of the last edit to the container.\n\t */\n\tgetLastEditDetails(): ILastEditDetails | undefined;\n\n\t/**\n\t * Updates the details of last edit to the container.\n\t */\n\tupdateLastEditDetails(lastEditDetails: ILastEditDetails): void;\n}\n\nexport interface ILastEditDetails {\n\tuser: IUser;\n\ttimestamp: number;\n}\n"]}
|
|
@@ -17,7 +17,7 @@ export declare class LastEditedTracker implements IFluidLastEditedTracker {
|
|
|
17
17
|
* @param sharedSummaryBlock - The shared summary block where the details will be stored.
|
|
18
18
|
*/
|
|
19
19
|
constructor(sharedSummaryBlock: SharedSummaryBlock);
|
|
20
|
-
get IFluidLastEditedTracker():
|
|
20
|
+
get IFluidLastEditedTracker(): LastEditedTracker;
|
|
21
21
|
/**
|
|
22
22
|
* {@inheritDoc (IFluidLastEditedTracker:interface).getLastEditDetails}
|
|
23
23
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lastEditedTracker.d.ts","sourceRoot":"","sources":["../src/lastEditedTracker.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,kBAAkB,EAAE,MAAM,sCAAsC,CAAC;AAC1E,OAAO,EAAE,uBAAuB,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAEzE;;;;GAIG;AACH,qBAAa,iBAAkB,YAAW,uBAAuB;
|
|
1
|
+
{"version":3,"file":"lastEditedTracker.d.ts","sourceRoot":"","sources":["../src/lastEditedTracker.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,kBAAkB,EAAE,MAAM,sCAAsC,CAAC;AAC1E,OAAO,EAAE,uBAAuB,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAEzE;;;;GAIG;AACH,qBAAa,iBAAkB,YAAW,uBAAuB;IAOpD,OAAO,CAAC,QAAQ,CAAC,kBAAkB;IAN/C,OAAO,CAAC,QAAQ,CAAC,oBAAoB,CAAwB;IAE7D;;;OAGG;gBAC0B,kBAAkB,EAAE,kBAAkB;IAEnE,IAAW,uBAAuB,IAAI,iBAAiB,CAEtD;IAED;;OAEG;IACI,kBAAkB,IAAI,gBAAgB,GAAG,SAAS;IAIzD;;OAEG;IACI,qBAAqB,CAAC,eAAe,EAAE,gBAAgB,GAAG,IAAI;CAGrE"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lastEditedTracker.js","sourceRoot":"","sources":["../src/lastEditedTracker.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH;;;;GAIG;AACH,MAAM,OAAO,iBAAiB;
|
|
1
|
+
{"version":3,"file":"lastEditedTracker.js","sourceRoot":"","sources":["../src/lastEditedTracker.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH;;;;GAIG;AACH,MAAM,OAAO,iBAAiB;IAG7B;;;OAGG;IACH,YAA6B,kBAAsC;QAAtC,uBAAkB,GAAlB,kBAAkB,CAAoB;QANlD,yBAAoB,GAAG,oBAAoB,CAAC;IAMS,CAAC;IAEvE,IAAW,uBAAuB;QACjC,OAAO,IAAI,CAAC;IACb,CAAC;IAED;;OAEG;IACI,kBAAkB;QACxB,OAAO,IAAI,CAAC,kBAAkB,CAAC,GAAG,CAAmB,IAAI,CAAC,oBAAoB,CAAC,CAAC;IACjF,CAAC;IAED;;OAEG;IACI,qBAAqB,CAAC,eAAiC;QAC7D,IAAI,CAAC,kBAAkB,CAAC,GAAG,CAAC,IAAI,CAAC,oBAAoB,EAAE,eAAe,CAAC,CAAC;IACzE,CAAC;CACD","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { SharedSummaryBlock } from \"@fluidframework/shared-summary-block\";\nimport { IFluidLastEditedTracker, ILastEditDetails } from \"./interfaces\";\n\n/**\n * Tracks the last edit details such as the last edited user details and the last edited timestamp. The last edited\n * details should be updated (via updateLastEditDetails) in response to a remote op since it uses shared summary block\n * as storage.\n */\nexport class LastEditedTracker implements IFluidLastEditedTracker {\n\tprivate readonly lastEditedDetailsKey = \"lastEditDetailsKey\";\n\n\t/**\n\t * Creates a LastEditedTracker object.\n\t * @param sharedSummaryBlock - The shared summary block where the details will be stored.\n\t */\n\tconstructor(private readonly sharedSummaryBlock: SharedSummaryBlock) {}\n\n\tpublic get IFluidLastEditedTracker(): LastEditedTracker {\n\t\treturn this;\n\t}\n\n\t/**\n\t * {@inheritDoc (IFluidLastEditedTracker:interface).getLastEditDetails}\n\t */\n\tpublic getLastEditDetails(): ILastEditDetails | undefined {\n\t\treturn this.sharedSummaryBlock.get<ILastEditDetails>(this.lastEditedDetailsKey);\n\t}\n\n\t/**\n\t * {@inheritDoc (IFluidLastEditedTracker:interface).updateLastEditDetails}\n\t */\n\tpublic updateLastEditDetails(lastEditDetails: ILastEditDetails): void {\n\t\tthis.sharedSummaryBlock.set(this.lastEditedDetailsKey, lastEditDetails);\n\t}\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lastEditedTrackerDataObject.d.ts","sourceRoot":"","sources":["../src/lastEditedTrackerDataObject.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAGzE,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,8BAA8B,EAAE,MAAM,cAAc,CAAC;AAE9D;;GAEG;AACH,qBAAa,
|
|
1
|
+
{"version":3,"file":"lastEditedTrackerDataObject.d.ts","sourceRoot":"","sources":["../src/lastEditedTrackerDataObject.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAGzE,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,8BAA8B,EAAE,MAAM,cAAc,CAAC;AAE9D;;GAEG;AACH,qBAAa,2BACZ,SAAQ,UACR,YAAW,8BAA8B;IAEzC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,OAAO,CAO5B;WAEW,UAAU,IAAI,iBAAiB,CAAC,2BAA2B,CAAC;IAI1E,OAAO,CAAC,QAAQ,CAAC,oBAAoB,CAA6B;IAClE,OAAO,CAAC,kBAAkB,CAAgC;IAE1D,OAAO,KAAK,iBAAiB,GAM5B;IAED,IAAW,uBAAuB,IAAI,iBAAiB,CAEtD;cAEe,qBAAqB,IAAI,OAAO,CAAC,IAAI,CAAC;cAKtC,cAAc,IAAI,OAAO,CAAC,IAAI,CAAC;CAM/C"}
|
|
@@ -22,7 +22,9 @@ export class LastEditedTrackerDataObject extends DataObject {
|
|
|
22
22
|
}
|
|
23
23
|
return this._lastEditedTracker;
|
|
24
24
|
}
|
|
25
|
-
get IFluidLastEditedTracker() {
|
|
25
|
+
get IFluidLastEditedTracker() {
|
|
26
|
+
return this.lastEditedTracker;
|
|
27
|
+
}
|
|
26
28
|
async initializingFirstTime() {
|
|
27
29
|
const sharedSummaryBlock = SharedSummaryBlock.create(this.runtime);
|
|
28
30
|
this.root.set(this.sharedSummaryBlockId, sharedSummaryBlock.handle);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lastEditedTrackerDataObject.js","sourceRoot":"","sources":["../src/lastEditedTrackerDataObject.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAEzE,OAAO,EAAE,kBAAkB,EAAE,MAAM,sCAAsC,CAAC;AAC1E,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAGxD;;GAEG;AACH,MAAM,OAAO,
|
|
1
|
+
{"version":3,"file":"lastEditedTrackerDataObject.js","sourceRoot":"","sources":["../src/lastEditedTrackerDataObject.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAEzE,OAAO,EAAE,kBAAkB,EAAE,MAAM,sCAAsC,CAAC;AAC1E,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAGxD;;GAEG;AACH,MAAM,OAAO,2BACZ,SAAQ,UAAU;IADnB;;QAiBkB,yBAAoB,GAAG,yBAAyB,CAAC;IA0BnE,CAAC;IA9BO,MAAM,CAAC,UAAU;QACvB,OAAO,2BAA2B,CAAC,OAAO,CAAC;IAC5C,CAAC;IAKD,IAAY,iBAAiB;QAC5B,IAAI,IAAI,CAAC,kBAAkB,KAAK,SAAS,EAAE;YAC1C,MAAM,IAAI,KAAK,CAAC,kDAAkD,CAAC,CAAC;SACpE;QAED,OAAO,IAAI,CAAC,kBAAkB,CAAC;IAChC,CAAC;IAED,IAAW,uBAAuB;QACjC,OAAO,IAAI,CAAC,iBAAiB,CAAC;IAC/B,CAAC;IAES,KAAK,CAAC,qBAAqB;QACpC,MAAM,kBAAkB,GAAG,kBAAkB,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACnE,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,oBAAoB,EAAE,kBAAkB,CAAC,MAAM,CAAC,CAAC;IACrE,CAAC;IAES,KAAK,CAAC,cAAc;QAC7B,MAAM,kBAAkB;QACvB,oEAAoE;QACpE,MAAM,IAAI,CAAC,IAAI,CAAC,GAAG,CAAmC,IAAI,CAAC,oBAAoB,CAAE,CAAC,GAAG,EAAE,CAAC;QACzF,IAAI,CAAC,kBAAkB,GAAG,IAAI,iBAAiB,CAAC,kBAAkB,CAAC,CAAC;IACrE,CAAC;;AAtCuB,mCAAO,GAC9B,IAAI,iBAAiB,CACpB,iCAAiC,EACjC,2BAA2B,EAC3B,CAAC,kBAAkB,CAAC,UAAU,EAAE,CAAC,EACjC,EAAE,EACF,SAAS,CACT,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { DataObject, DataObjectFactory } from \"@fluidframework/aqueduct\";\nimport { IFluidHandle } from \"@fluidframework/core-interfaces\";\nimport { SharedSummaryBlock } from \"@fluidframework/shared-summary-block\";\nimport { LastEditedTracker } from \"./lastEditedTracker\";\nimport { IProvideFluidLastEditedTracker } from \"./interfaces\";\n\n/**\n * LastEditedTrackerDataObject creates a LastEditedTracker that keeps track of the latest edits to the document.\n */\nexport class LastEditedTrackerDataObject\n\textends DataObject\n\timplements IProvideFluidLastEditedTracker\n{\n\tprivate static readonly factory: DataObjectFactory<LastEditedTrackerDataObject> =\n\t\tnew DataObjectFactory(\n\t\t\t\"@fluid-experimental/last-edited\",\n\t\t\tLastEditedTrackerDataObject,\n\t\t\t[SharedSummaryBlock.getFactory()],\n\t\t\t{},\n\t\t\tundefined,\n\t\t);\n\n\tpublic static getFactory(): DataObjectFactory<LastEditedTrackerDataObject> {\n\t\treturn LastEditedTrackerDataObject.factory;\n\t}\n\n\tprivate readonly sharedSummaryBlockId = \"shared-summary-block-id\";\n\tprivate _lastEditedTracker: LastEditedTracker | undefined;\n\n\tprivate get lastEditedTracker(): LastEditedTracker {\n\t\tif (this._lastEditedTracker === undefined) {\n\t\t\tthrow new Error(\"Last Edited tracker was not initialized properly\");\n\t\t}\n\n\t\treturn this._lastEditedTracker;\n\t}\n\n\tpublic get IFluidLastEditedTracker(): LastEditedTracker {\n\t\treturn this.lastEditedTracker;\n\t}\n\n\tprotected async initializingFirstTime(): Promise<void> {\n\t\tconst sharedSummaryBlock = SharedSummaryBlock.create(this.runtime);\n\t\tthis.root.set(this.sharedSummaryBlockId, sharedSummaryBlock.handle);\n\t}\n\n\tprotected async hasInitialized(): Promise<void> {\n\t\tconst sharedSummaryBlock =\n\t\t\t// eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n\t\t\tawait this.root.get<IFluidHandle<SharedSummaryBlock>>(this.sharedSummaryBlockId)!.get();\n\t\tthis._lastEditedTracker = new LastEditedTracker(sharedSummaryBlock);\n\t}\n}\n"]}
|
package/lib/packageVersion.d.ts
CHANGED
|
@@ -5,5 +5,5 @@
|
|
|
5
5
|
* THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY
|
|
6
6
|
*/
|
|
7
7
|
export declare const pkgName = "@fluid-experimental/last-edited";
|
|
8
|
-
export declare const pkgVersion = "2.0.0-dev.
|
|
8
|
+
export declare const pkgVersion = "2.0.0-dev.3.1.0.125672";
|
|
9
9
|
//# sourceMappingURL=packageVersion.d.ts.map
|
package/lib/packageVersion.js
CHANGED
|
@@ -5,5 +5,5 @@
|
|
|
5
5
|
* THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY
|
|
6
6
|
*/
|
|
7
7
|
export const pkgName = "@fluid-experimental/last-edited";
|
|
8
|
-
export const pkgVersion = "2.0.0-dev.
|
|
8
|
+
export const pkgVersion = "2.0.0-dev.3.1.0.125672";
|
|
9
9
|
//# sourceMappingURL=packageVersion.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"packageVersion.js","sourceRoot":"","sources":["../src/packageVersion.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,CAAC,MAAM,OAAO,GAAG,iCAAiC,CAAC;AACzD,MAAM,CAAC,MAAM,UAAU,GAAG,wBAAwB,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n *\n * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY\n */\n\nexport const pkgName = \"@fluid-experimental/last-edited\";\nexport const pkgVersion = \"2.0.0-dev.
|
|
1
|
+
{"version":3,"file":"packageVersion.js","sourceRoot":"","sources":["../src/packageVersion.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,CAAC,MAAM,OAAO,GAAG,iCAAiC,CAAC;AACzD,MAAM,CAAC,MAAM,UAAU,GAAG,wBAAwB,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n *\n * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY\n */\n\nexport const pkgName = \"@fluid-experimental/last-edited\";\nexport const pkgVersion = \"2.0.0-dev.3.1.0.125672\";\n"]}
|
package/lib/setup.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"setup.d.ts","sourceRoot":"","sources":["../src/setup.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,yBAAyB,EAAkB,MAAM,sCAAsC,CAAC;AAEjG,OAAO,EAAE,iBAAiB,EAAE,MAAM,+CAA+C,CAAC;AAClF,OAAO,EAAoB,uBAAuB,EAAE,MAAM,cAAc,CAAC;AAkCzE;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,kCAAkC,
|
|
1
|
+
{"version":3,"file":"setup.d.ts","sourceRoot":"","sources":["../src/setup.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,yBAAyB,EAAkB,MAAM,sCAAsC,CAAC;AAEjG,OAAO,EAAE,iBAAiB,EAAE,MAAM,+CAA+C,CAAC;AAClF,OAAO,EAAoB,uBAAuB,EAAE,MAAM,cAAc,CAAC;AAkCzE;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,kCAAkC,CACjD,iBAAiB,EAAE,uBAAuB,EAC1C,OAAO,EAAE,iBAAiB,EAC1B,sBAAsB,GAAE,CACvB,OAAO,EAAE,yBAAyB,KAC9B,OAAqC,GACxC,IAAI,CAkBN"}
|
package/lib/setup.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"setup.js","sourceRoot":"","sources":["../src/setup.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,oBAAoB,EAAE,MAAM,mCAAmC,CAAC;AAIzE;;;;;;GAMG;AACH,MAAM,2BAA2B,GAAG,CAAC,OAAkC,
|
|
1
|
+
{"version":3,"file":"setup.js","sourceRoot":"","sources":["../src/setup.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,oBAAoB,EAAE,MAAM,mCAAmC,CAAC;AAIzE;;;;;;GAMG;AACH,MAAM,2BAA2B,GAAG,CAAC,OAAkC,EAAW,EAAE,CACnF,OAAO,CAAC,IAAI,KAAK,oBAAoB,CAAC,MAAM;IAC5C,OAAO,CAAC,IAAI,KAAK,oBAAoB,CAAC,gBAAgB;IACtD,OAAO,CAAC,IAAI,KAAK,oBAAoB,CAAC,KAAK,CAAC;AAE7C;;;GAGG;AACH,SAAS,6BAA6B,CACrC,OAAkC,EAClC,MAAsB;IAEtB,MAAM,eAAe,GAAG,MAAM,CAAC,SAAS,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IAC3D,MAAM,IAAI,GAAG,eAAe,aAAf,eAAe,uBAAf,eAAe,CAAE,MAAM,CAAC,IAAI,CAAC;IAC1C,IAAI,IAAI,KAAK,SAAS,EAAE;QACvB,MAAM,eAAe,GAAqB;YACzC,IAAI;YACJ,SAAS,EAAE,OAAO,CAAC,SAAS;SAC5B,CAAC;QACF,OAAO,eAAe,CAAC;KACvB;IACD,OAAO,SAAS,CAAC;AAClB,CAAC;AAED;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,kCAAkC,CACjD,iBAA0C,EAC1C,OAA0B,EAC1B,yBAEe,2BAA2B;IAE1C,+EAA+E;IAC/E,+CAA+C;IAC/C,8GAA8G;IAC9G,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,OAAkC,EAAE,cAAwB,EAAE,EAAE;QACjF,6EAA6E;QAC7E,IAAI,cAAc,KAAK,KAAK,IAAI,sBAAsB,CAAC,OAAO,CAAC,EAAE;YAChE,OAAO;SACP;QAED,6EAA6E;QAC7E,MAAM,eAAe,GAAG,6BAA6B,CAAC,OAAO,EAAE,OAAO,CAAC,SAAS,EAAE,CAAC,CAAC;QACpF,IAAI,eAAe,KAAK,SAAS,EAAE;YAClC,OAAO;SACP;QAED,iBAAiB,CAAC,qBAAqB,CAAC,eAAe,CAAC,CAAC;IAC1D,CAAC,CAAC,CAAC;AACJ,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { ISequencedDocumentMessage, IQuorumClients } from \"@fluidframework/protocol-definitions\";\nimport { ContainerMessageType } from \"@fluidframework/container-runtime\";\nimport { IContainerRuntime } from \"@fluidframework/container-runtime-definitions\";\nimport { ILastEditDetails, IFluidLastEditedTracker } from \"./interfaces\";\n\n/**\n * Default implementation of {@link setupLastEditedTrackerForContainer}'s `shouldDiscardMessageFn` parameter,\n * which tells that all messages other than {@link @fluidframework/container-runtime#ContainerMessageType.Alias},\n * {@link @fluidframework/container-runtime#ContainerMessageType.Attach}, and\n * {@link @fluidframework/container-runtime#ContainerMessageType.FluidDataStoreOp} type messages should be\n * discarded.\n */\nconst shouldDiscardMessageDefault = (message: ISequencedDocumentMessage): boolean =>\n\tmessage.type !== ContainerMessageType.Attach &&\n\tmessage.type !== ContainerMessageType.FluidDataStoreOp &&\n\tmessage.type !== ContainerMessageType.Alias;\n\n/**\n * Extracts the user information and timestamp from a message. Returns undefined if the user information for the\n * client who sent the message doesn't exist in the quorum.\n */\nfunction getLastEditDetailsFromMessage(\n\tmessage: ISequencedDocumentMessage,\n\tquorum: IQuorumClients,\n): ILastEditDetails | undefined {\n\tconst sequencedClient = quorum.getMember(message.clientId);\n\tconst user = sequencedClient?.client.user;\n\tif (user !== undefined) {\n\t\tconst lastEditDetails: ILastEditDetails = {\n\t\t\tuser,\n\t\t\ttimestamp: message.timestamp,\n\t\t};\n\t\treturn lastEditDetails;\n\t}\n\treturn undefined;\n}\n\n/**\n * Helper function to set up a data object that provides IFluidLastEditedTracker to track last edited in a Container.\n *\n * It does the following:\n *\n * - Registers an \"op\" listener on the runtime. On each message, it calls the shouldDiscardMessageFn to check\n * if the message should be discarded. It also discards all scheduler message. If a message is not discarded,\n * it passes the last edited information from the message to the last edited tracker.\n *\n * - The last edited information from the last message received before the lastEditedTracker is\n * loaded is stored and passed to the tracker once it loads.\n * @param lastEditedTracker - The last edited tracker.\n * @param runtime - The container runtime whose messages are to be tracked.\n * @param shouldDiscardMessageFn - Function that tells if a message should not be considered in computing last edited.\n */\nexport function setupLastEditedTrackerForContainer(\n\tlastEditedTracker: IFluidLastEditedTracker,\n\truntime: IContainerRuntime,\n\tshouldDiscardMessageFn: (\n\t\tmessage: ISequencedDocumentMessage,\n\t) => boolean = shouldDiscardMessageDefault,\n): void {\n\t// Register an op listener on the runtime. If the lastEditedTracker has loaded,\n\t// it passes the last edited information to its\n\t// last edited tracker. If the lastEditedTracker hasn't loaded, store the last edited information temporarily.\n\truntime.on(\"op\", (message: ISequencedDocumentMessage, runtimeMessage?: boolean) => {\n\t\t// If this message should be discarded as per shouldDiscardMessageFn, return.\n\t\tif (runtimeMessage === false || shouldDiscardMessageFn(message)) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Get the last edited details from the message. If it doesn't exist, return.\n\t\tconst lastEditDetails = getLastEditDetailsFromMessage(message, runtime.getQuorum());\n\t\tif (lastEditDetails === undefined) {\n\t\t\treturn;\n\t\t}\n\n\t\tlastEditedTracker.updateLastEditDetails(lastEditDetails);\n\t});\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fluid-experimental/last-edited",
|
|
3
|
-
"version": "2.0.0-dev.
|
|
3
|
+
"version": "2.0.0-dev.3.1.0.125672",
|
|
4
4
|
"description": "Tracks the last edited information in the Container.",
|
|
5
5
|
"homepage": "https://fluidframework.com",
|
|
6
6
|
"repository": {
|
|
@@ -27,8 +27,11 @@
|
|
|
27
27
|
"clean": "rimraf dist lib *.tsbuildinfo *.build.log",
|
|
28
28
|
"eslint": "eslint --format stylish src",
|
|
29
29
|
"eslint:fix": "eslint --format stylish src --fix --fix-type problem,suggestion,layout",
|
|
30
|
-
"
|
|
31
|
-
"lint
|
|
30
|
+
"format": "npm run prettier:fix",
|
|
31
|
+
"lint": "npm run prettier && npm run eslint",
|
|
32
|
+
"lint:fix": "npm run prettier:fix && npm run eslint:fix",
|
|
33
|
+
"prettier": "prettier --check . --ignore-path ../../../.prettierignore",
|
|
34
|
+
"prettier:fix": "prettier --write . --ignore-path ../../../.prettierignore",
|
|
32
35
|
"tsc": "tsc"
|
|
33
36
|
},
|
|
34
37
|
"nyc": {
|
|
@@ -52,29 +55,30 @@
|
|
|
52
55
|
"temp-directory": "nyc/.nyc_output"
|
|
53
56
|
},
|
|
54
57
|
"dependencies": {
|
|
55
|
-
"@fluidframework/aqueduct": ">=2.0.0-dev.
|
|
58
|
+
"@fluidframework/aqueduct": ">=2.0.0-dev.3.1.0.125672 <2.0.0-dev.4.0.0",
|
|
56
59
|
"@fluidframework/common-definitions": "^0.20.1",
|
|
57
|
-
"@fluidframework/container-runtime": ">=2.0.0-dev.
|
|
58
|
-
"@fluidframework/container-runtime-definitions": ">=2.0.0-dev.
|
|
59
|
-
"@fluidframework/core-interfaces": ">=2.0.0-dev.
|
|
60
|
+
"@fluidframework/container-runtime": ">=2.0.0-dev.3.1.0.125672 <2.0.0-dev.4.0.0",
|
|
61
|
+
"@fluidframework/container-runtime-definitions": ">=2.0.0-dev.3.1.0.125672 <2.0.0-dev.4.0.0",
|
|
62
|
+
"@fluidframework/core-interfaces": ">=2.0.0-dev.3.1.0.125672 <2.0.0-dev.4.0.0",
|
|
60
63
|
"@fluidframework/protocol-definitions": "^1.1.0",
|
|
61
|
-
"@fluidframework/runtime-utils": ">=2.0.0-dev.
|
|
62
|
-
"@fluidframework/shared-summary-block": ">=2.0.0-dev.
|
|
64
|
+
"@fluidframework/runtime-utils": ">=2.0.0-dev.3.1.0.125672 <2.0.0-dev.4.0.0",
|
|
65
|
+
"@fluidframework/shared-summary-block": ">=2.0.0-dev.3.1.0.125672 <2.0.0-dev.4.0.0"
|
|
63
66
|
},
|
|
64
67
|
"devDependencies": {
|
|
65
|
-
"@fluid-tools/build-cli": "^0.
|
|
68
|
+
"@fluid-tools/build-cli": "^0.8.0",
|
|
66
69
|
"@fluidframework/build-common": "^1.1.0",
|
|
67
|
-
"@fluidframework/eslint-config-fluid": "^
|
|
68
|
-
"@fluidframework/mocha-test-setup": ">=2.0.0-dev.
|
|
70
|
+
"@fluidframework/eslint-config-fluid": "^2.0.0",
|
|
71
|
+
"@fluidframework/mocha-test-setup": ">=2.0.0-dev.3.1.0.125672 <2.0.0-dev.4.0.0",
|
|
69
72
|
"@microsoft/api-extractor": "^7.22.2",
|
|
70
73
|
"@rushstack/eslint-config": "^2.5.1",
|
|
71
74
|
"@types/mocha": "^9.1.1",
|
|
72
|
-
"@types/node": "^14.18.
|
|
75
|
+
"@types/node": "^14.18.36",
|
|
73
76
|
"concurrently": "^6.2.0",
|
|
74
77
|
"copyfiles": "^2.4.1",
|
|
75
78
|
"eslint": "~8.6.0",
|
|
76
79
|
"mocha": "^10.0.0",
|
|
77
80
|
"nyc": "^15.0.0",
|
|
81
|
+
"prettier": "~2.6.2",
|
|
78
82
|
"rimraf": "^2.6.2",
|
|
79
83
|
"typescript": "~4.5.5"
|
|
80
84
|
},
|
package/src/index.ts
CHANGED
|
@@ -2,7 +2,11 @@
|
|
|
2
2
|
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
|
|
3
3
|
* Licensed under the MIT License.
|
|
4
4
|
*/
|
|
5
|
-
export {
|
|
5
|
+
export {
|
|
6
|
+
IFluidLastEditedTracker,
|
|
7
|
+
ILastEditDetails,
|
|
8
|
+
IProvideFluidLastEditedTracker,
|
|
9
|
+
} from "./interfaces";
|
|
6
10
|
export { LastEditedTracker } from "./lastEditedTracker";
|
|
7
11
|
export { LastEditedTrackerDataObject } from "./lastEditedTrackerDataObject";
|
|
8
12
|
export { setupLastEditedTrackerForContainer } from "./setup";
|
package/src/interfaces.ts
CHANGED
|
@@ -5,25 +5,26 @@
|
|
|
5
5
|
|
|
6
6
|
import { IUser } from "@fluidframework/protocol-definitions";
|
|
7
7
|
|
|
8
|
-
export const IFluidLastEditedTracker: keyof IProvideFluidLastEditedTracker =
|
|
8
|
+
export const IFluidLastEditedTracker: keyof IProvideFluidLastEditedTracker =
|
|
9
|
+
"IFluidLastEditedTracker";
|
|
9
10
|
|
|
10
11
|
export interface IProvideFluidLastEditedTracker {
|
|
11
|
-
|
|
12
|
+
readonly IFluidLastEditedTracker: IFluidLastEditedTracker;
|
|
12
13
|
}
|
|
13
14
|
|
|
14
15
|
export interface IFluidLastEditedTracker extends IProvideFluidLastEditedTracker {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
16
|
+
/**
|
|
17
|
+
* Returns the details of the last edit to the container.
|
|
18
|
+
*/
|
|
19
|
+
getLastEditDetails(): ILastEditDetails | undefined;
|
|
19
20
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
21
|
+
/**
|
|
22
|
+
* Updates the details of last edit to the container.
|
|
23
|
+
*/
|
|
24
|
+
updateLastEditDetails(lastEditDetails: ILastEditDetails): void;
|
|
24
25
|
}
|
|
25
26
|
|
|
26
27
|
export interface ILastEditDetails {
|
|
27
|
-
|
|
28
|
-
|
|
28
|
+
user: IUser;
|
|
29
|
+
timestamp: number;
|
|
29
30
|
}
|
package/src/lastEditedTracker.ts
CHANGED
|
@@ -12,29 +12,29 @@ import { IFluidLastEditedTracker, ILastEditDetails } from "./interfaces";
|
|
|
12
12
|
* as storage.
|
|
13
13
|
*/
|
|
14
14
|
export class LastEditedTracker implements IFluidLastEditedTracker {
|
|
15
|
-
|
|
15
|
+
private readonly lastEditedDetailsKey = "lastEditDetailsKey";
|
|
16
16
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
17
|
+
/**
|
|
18
|
+
* Creates a LastEditedTracker object.
|
|
19
|
+
* @param sharedSummaryBlock - The shared summary block where the details will be stored.
|
|
20
|
+
*/
|
|
21
|
+
constructor(private readonly sharedSummaryBlock: SharedSummaryBlock) {}
|
|
22
22
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
23
|
+
public get IFluidLastEditedTracker(): LastEditedTracker {
|
|
24
|
+
return this;
|
|
25
|
+
}
|
|
26
26
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
27
|
+
/**
|
|
28
|
+
* {@inheritDoc (IFluidLastEditedTracker:interface).getLastEditDetails}
|
|
29
|
+
*/
|
|
30
|
+
public getLastEditDetails(): ILastEditDetails | undefined {
|
|
31
|
+
return this.sharedSummaryBlock.get<ILastEditDetails>(this.lastEditedDetailsKey);
|
|
32
|
+
}
|
|
33
33
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
34
|
+
/**
|
|
35
|
+
* {@inheritDoc (IFluidLastEditedTracker:interface).updateLastEditDetails}
|
|
36
|
+
*/
|
|
37
|
+
public updateLastEditDetails(lastEditDetails: ILastEditDetails): void {
|
|
38
|
+
this.sharedSummaryBlock.set(this.lastEditedDetailsKey, lastEditDetails);
|
|
39
|
+
}
|
|
40
40
|
}
|
|
@@ -12,43 +12,47 @@ import { IProvideFluidLastEditedTracker } from "./interfaces";
|
|
|
12
12
|
/**
|
|
13
13
|
* LastEditedTrackerDataObject creates a LastEditedTracker that keeps track of the latest edits to the document.
|
|
14
14
|
*/
|
|
15
|
-
export class LastEditedTrackerDataObject
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
15
|
+
export class LastEditedTrackerDataObject
|
|
16
|
+
extends DataObject
|
|
17
|
+
implements IProvideFluidLastEditedTracker
|
|
18
|
+
{
|
|
19
|
+
private static readonly factory: DataObjectFactory<LastEditedTrackerDataObject> =
|
|
20
|
+
new DataObjectFactory(
|
|
21
|
+
"@fluid-experimental/last-edited",
|
|
22
|
+
LastEditedTrackerDataObject,
|
|
23
|
+
[SharedSummaryBlock.getFactory()],
|
|
24
|
+
{},
|
|
25
|
+
undefined,
|
|
26
|
+
);
|
|
27
|
+
|
|
28
|
+
public static getFactory(): DataObjectFactory<LastEditedTrackerDataObject> {
|
|
29
|
+
return LastEditedTrackerDataObject.factory;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
private readonly sharedSummaryBlockId = "shared-summary-block-id";
|
|
33
|
+
private _lastEditedTracker: LastEditedTracker | undefined;
|
|
34
|
+
|
|
35
|
+
private get lastEditedTracker(): LastEditedTracker {
|
|
36
|
+
if (this._lastEditedTracker === undefined) {
|
|
37
|
+
throw new Error("Last Edited tracker was not initialized properly");
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
return this._lastEditedTracker;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
public get IFluidLastEditedTracker(): LastEditedTracker {
|
|
44
|
+
return this.lastEditedTracker;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
protected async initializingFirstTime(): Promise<void> {
|
|
48
|
+
const sharedSummaryBlock = SharedSummaryBlock.create(this.runtime);
|
|
49
|
+
this.root.set(this.sharedSummaryBlockId, sharedSummaryBlock.handle);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
protected async hasInitialized(): Promise<void> {
|
|
53
|
+
const sharedSummaryBlock =
|
|
54
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
55
|
+
await this.root.get<IFluidHandle<SharedSummaryBlock>>(this.sharedSummaryBlockId)!.get();
|
|
56
|
+
this._lastEditedTracker = new LastEditedTracker(sharedSummaryBlock);
|
|
57
|
+
}
|
|
54
58
|
}
|
package/src/packageVersion.ts
CHANGED
package/src/setup.ts
CHANGED
|
@@ -15,29 +15,29 @@ import { ILastEditDetails, IFluidLastEditedTracker } from "./interfaces";
|
|
|
15
15
|
* {@link @fluidframework/container-runtime#ContainerMessageType.FluidDataStoreOp} type messages should be
|
|
16
16
|
* discarded.
|
|
17
17
|
*/
|
|
18
|
-
const shouldDiscardMessageDefault = (message: ISequencedDocumentMessage) =>
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
18
|
+
const shouldDiscardMessageDefault = (message: ISequencedDocumentMessage): boolean =>
|
|
19
|
+
message.type !== ContainerMessageType.Attach &&
|
|
20
|
+
message.type !== ContainerMessageType.FluidDataStoreOp &&
|
|
21
|
+
message.type !== ContainerMessageType.Alias;
|
|
22
22
|
|
|
23
23
|
/**
|
|
24
24
|
* Extracts the user information and timestamp from a message. Returns undefined if the user information for the
|
|
25
25
|
* client who sent the message doesn't exist in the quorum.
|
|
26
26
|
*/
|
|
27
27
|
function getLastEditDetailsFromMessage(
|
|
28
|
-
|
|
29
|
-
|
|
28
|
+
message: ISequencedDocumentMessage,
|
|
29
|
+
quorum: IQuorumClients,
|
|
30
30
|
): ILastEditDetails | undefined {
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
31
|
+
const sequencedClient = quorum.getMember(message.clientId);
|
|
32
|
+
const user = sequencedClient?.client.user;
|
|
33
|
+
if (user !== undefined) {
|
|
34
|
+
const lastEditDetails: ILastEditDetails = {
|
|
35
|
+
user,
|
|
36
|
+
timestamp: message.timestamp,
|
|
37
|
+
};
|
|
38
|
+
return lastEditDetails;
|
|
39
|
+
}
|
|
40
|
+
return undefined;
|
|
41
41
|
}
|
|
42
42
|
|
|
43
43
|
/**
|
|
@@ -56,25 +56,27 @@ function getLastEditDetailsFromMessage(
|
|
|
56
56
|
* @param shouldDiscardMessageFn - Function that tells if a message should not be considered in computing last edited.
|
|
57
57
|
*/
|
|
58
58
|
export function setupLastEditedTrackerForContainer(
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
59
|
+
lastEditedTracker: IFluidLastEditedTracker,
|
|
60
|
+
runtime: IContainerRuntime,
|
|
61
|
+
shouldDiscardMessageFn: (
|
|
62
|
+
message: ISequencedDocumentMessage,
|
|
63
|
+
) => boolean = shouldDiscardMessageDefault,
|
|
64
|
+
): void {
|
|
65
|
+
// Register an op listener on the runtime. If the lastEditedTracker has loaded,
|
|
66
|
+
// it passes the last edited information to its
|
|
67
|
+
// last edited tracker. If the lastEditedTracker hasn't loaded, store the last edited information temporarily.
|
|
68
|
+
runtime.on("op", (message: ISequencedDocumentMessage, runtimeMessage?: boolean) => {
|
|
69
|
+
// If this message should be discarded as per shouldDiscardMessageFn, return.
|
|
70
|
+
if (runtimeMessage === false || shouldDiscardMessageFn(message)) {
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
71
73
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
74
|
+
// Get the last edited details from the message. If it doesn't exist, return.
|
|
75
|
+
const lastEditDetails = getLastEditDetailsFromMessage(message, runtime.getQuorum());
|
|
76
|
+
if (lastEditDetails === undefined) {
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
77
79
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
+
lastEditedTracker.updateLastEditDetails(lastEditDetails);
|
|
81
|
+
});
|
|
80
82
|
}
|
package/tsconfig.esnext.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
}
|
|
2
|
+
"extends": "./tsconfig.json",
|
|
3
|
+
"compilerOptions": {
|
|
4
|
+
"outDir": "./lib",
|
|
5
|
+
"module": "esnext",
|
|
6
|
+
},
|
|
7
|
+
}
|
package/tsconfig.json
CHANGED
|
@@ -1,17 +1,10 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
"mocha"
|
|
12
|
-
]
|
|
13
|
-
},
|
|
14
|
-
"include": [
|
|
15
|
-
"src/**/*"
|
|
16
|
-
]
|
|
17
|
-
}
|
|
2
|
+
"extends": "@fluidframework/build-common/ts-common-config.json",
|
|
3
|
+
"exclude": ["dist", "node_modules"],
|
|
4
|
+
"compilerOptions": {
|
|
5
|
+
"rootDir": "./src",
|
|
6
|
+
"outDir": "./dist",
|
|
7
|
+
"types": ["mocha"],
|
|
8
|
+
},
|
|
9
|
+
"include": ["src/**/*"],
|
|
10
|
+
}
|