Skip to content

Commit 0b24d03

Browse files
authored
feat(odsp-client): Add OdspContainerServices readonly and sensitivity label event emitters (#25800)
## Description Portion of #25597 to add read-only state and sensitivity labels events to OdspContainerServices. ## Reviewer Guidance I think this PR could be better if it separated read-only events and sensitivity label events, but it will introduce either merge conflicts or blocking on either. I think it would be weird to extend `IEventProvider` without any events, which would allow for async feature introduction.
1 parent 93ec6c7 commit 0b24d03

File tree

8 files changed

+119
-7
lines changed

8 files changed

+119
-7
lines changed

PACKAGES.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,7 @@ The dependencies between layers are enforced by the layer-check command._
183183

184184
| Packages | Layer Dependencies |
185185
| --- | --- |
186-
| - [@fluidframework/azure-client](/packages/service-clients/azure-client)</br>- [@fluidframework/odsp-client](/packages/service-clients/odsp-client)</br>- [@fluidframework/tinylicious-client](/packages/service-clients/tinylicious-client)</br>&nbsp;</br>&nbsp;</br>&nbsp;</br>&nbsp;</br>&nbsp;</br>&nbsp;</br>&nbsp;</br>&nbsp;</br>&nbsp; | - [Core-Interfaces](#Core-Interfaces)</br>- [Driver-Definitions](#Driver-Definitions)</br>- [Container-Definitions](#Container-Definitions)</br>- [Core-Utils](#Core-Utils)</br>- [Telemetry-Utils](#Telemetry-Utils)</br>- [Driver-Utils](#Driver-Utils)</br>- [Other-Utils](#Other-Utils)</br>- [Driver](#Driver)</br>- [Loader](#Loader)</br>- [Runtime](#Runtime)</br>- [Framework](#Framework)</br>- [Routerlicious-Driver](#Routerlicious-Driver) |
186+
| - [@fluidframework/azure-client](/packages/service-clients/azure-client)</br>- [@fluidframework/odsp-client](/packages/service-clients/odsp-client)</br>- [@fluidframework/tinylicious-client](/packages/service-clients/tinylicious-client)</br>&nbsp;</br>&nbsp;</br>&nbsp;</br>&nbsp;</br>&nbsp;</br>&nbsp;</br>&nbsp;</br>&nbsp;</br>&nbsp;</br>&nbsp; | - [Core-Interfaces](#Core-Interfaces)</br>- [Driver-Definitions](#Driver-Definitions)</br>- [Container-Definitions](#Container-Definitions)</br>- [Core-Utils](#Core-Utils)</br>- [Client-Utils](#Client-Utils)</br>- [Telemetry-Utils](#Telemetry-Utils)</br>- [Driver-Utils](#Driver-Utils)</br>- [Other-Utils](#Other-Utils)</br>- [Driver](#Driver)</br>- [Loader](#Loader)</br>- [Runtime](#Runtime)</br>- [Framework](#Framework)</br>- [Routerlicious-Driver](#Routerlicious-Driver) |
187187

188188
### Examples
189189

packages/service-clients/odsp-client/api-report/odsp-client.alpha.api.md

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,12 @@
77
// @beta
88
export type IOdspAudience = IServiceAudience<OdspMember>;
99

10+
// @beta @sealed
11+
export interface IOdspContainerServicesEvents {
12+
readOnlyStateChanged: () => void;
13+
sensitivityLabelsInfoChanged: () => void;
14+
}
15+
1016
// @beta
1117
export interface IOdspFluidContainer<TContainerSchema extends ContainerSchema = ContainerSchema> extends IFluidContainer<TContainerSchema> {
1218
attach(props?: ContainerAttachProps<OdspContainerAttachProps>): Promise<string>;
@@ -54,9 +60,13 @@ export interface OdspContainerAttachProps {
5460
filePath: string | undefined;
5561
}
5662

57-
// @beta
58-
export interface OdspContainerServices {
63+
// @beta @sealed
64+
export interface OdspContainerServices extends IDisposable {
5965
audience: IOdspAudience;
66+
// (undocumented)
67+
events: Listenable<IOdspContainerServicesEvents>;
68+
getReadOnlyState(): boolean | undefined;
69+
getSensitivityLabelsInfo(): string | undefined;
6070
}
6171

6272
// @beta

packages/service-clients/odsp-client/api-report/odsp-client.beta.api.md

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,12 @@
77
// @beta
88
export type IOdspAudience = IServiceAudience<OdspMember>;
99

10+
// @beta @sealed
11+
export interface IOdspContainerServicesEvents {
12+
readOnlyStateChanged: () => void;
13+
sensitivityLabelsInfoChanged: () => void;
14+
}
15+
1016
// @beta
1117
export interface IOdspFluidContainer<TContainerSchema extends ContainerSchema = ContainerSchema> extends IFluidContainer<TContainerSchema> {
1218
attach(props?: ContainerAttachProps<OdspContainerAttachProps>): Promise<string>;
@@ -54,9 +60,13 @@ export interface OdspContainerAttachProps {
5460
filePath: string | undefined;
5561
}
5662

57-
// @beta
58-
export interface OdspContainerServices {
63+
// @beta @sealed
64+
export interface OdspContainerServices extends IDisposable {
5965
audience: IOdspAudience;
66+
// (undocumented)
67+
events: Listenable<IOdspContainerServicesEvents>;
68+
getReadOnlyState(): boolean | undefined;
69+
getSensitivityLabelsInfo(): string | undefined;
6070
}
6171

6272
// @beta

packages/service-clients/odsp-client/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,7 @@
104104
"temp-directory": "nyc/.nyc_output"
105105
},
106106
"dependencies": {
107+
"@fluid-internal/client-utils": "workspace:~",
107108
"@fluidframework/container-definitions": "workspace:~",
108109
"@fluidframework/container-loader": "workspace:~",
109110
"@fluidframework/core-interfaces": "workspace:~",

packages/service-clients/odsp-client/src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515

1616
export type {
1717
IOdspAudience,
18+
IOdspContainerServicesEvents,
1819
IOdspFluidContainer,
1920
OdspClientProps,
2021
OdspConnectionConfig,

packages/service-clients/odsp-client/src/interfaces.ts

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,9 @@
55

66
import type {
77
IConfigProviderBase,
8+
IDisposable,
89
ITelemetryBaseLogger,
10+
Listenable,
911
} from "@fluidframework/core-interfaces";
1012
import type {
1113
ContainerAttachProps,
@@ -79,6 +81,25 @@ export interface OdspContainerAttachProps {
7981
fileName: string | undefined;
8082
}
8183

84+
/**
85+
* Events emitted by the ODSP container service to notify consumers of select
86+
* container changes.
87+
* @beta
88+
* @sealed
89+
*/
90+
export interface IOdspContainerServicesEvents {
91+
/**
92+
* Emitted when the read-only state of the container changes.
93+
* Consumers can call `OdspContainerServices.getReadOnlyState()` to get the updated value.
94+
*/
95+
readOnlyStateChanged: () => void;
96+
/**
97+
* Emitted when the sensitivity label of the container changes.
98+
* Consumers can call `OdspContainerServices.getSensitivityLabelsInfo()` to get the updated value.
99+
*/
100+
sensitivityLabelsInfoChanged: () => void;
101+
}
102+
82103
/**
83104
* ODSP version of the IFluidContainer interface.
84105
* @beta
@@ -106,12 +127,32 @@ export interface IOdspFluidContainer<
106127
* how the data is handled within the FluidContainer itself, i.e. which data objects or DDSes to
107128
* use, will not be included here but rather on the FluidContainer class itself.
108129
* @beta
130+
* @sealed
109131
*/
110-
export interface OdspContainerServices {
132+
export interface OdspContainerServices extends IDisposable {
133+
events: Listenable<IOdspContainerServicesEvents>;
111134
/**
112135
* Provides an object that facilitates obtaining information about users present in the Fluid session, as well as listeners for roster changes triggered by users joining or leaving the session.
113136
*/
114137
audience: IOdspAudience;
138+
139+
/**
140+
* Gets the read-only state of the container, if available.
141+
* This is not available until the container is in the "Connected" state.
142+
* @remarks
143+
* In the case that the read-only state cannot be determined, wait for the "readOnlyStateChanged" event to be emitted.
144+
* @returns The read-only state (true when readonly, false when editable), or undefined if not available.
145+
*/
146+
getReadOnlyState(): boolean | undefined;
147+
/**
148+
* Gets the sensitivity labels info of the container, if available.
149+
* This is not available until the container is in the "Connected" state, and will only be available
150+
* if sensitivity labels have been applied to the container.
151+
* @remarks
152+
* In the case that the sensitivity labels info are expected but cannot be determined, wait for the "sensitivityLabelChanged" event to be emitted.
153+
* @returns The sensitivity labels info string, or undefined if not available.
154+
*/
155+
getSensitivityLabelsInfo(): string | undefined;
115156
}
116157

117158
/**

packages/service-clients/odsp-client/src/odspContainerServices.ts

Lines changed: 47 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,25 +3,71 @@
33
* Licensed under the MIT License.
44
*/
55

6+
import { createEmitter } from "@fluid-internal/client-utils";
67
import type { IContainer } from "@fluidframework/container-definitions/internal";
8+
import type { IDisposable, Listenable } from "@fluidframework/core-interfaces";
79
import { createServiceAudience } from "@fluidframework/fluid-static/internal";
810

911
import type {
1012
IOdspAudience,
1113
OdspContainerServices as IOdspContainerServices,
14+
IOdspContainerServicesEvents,
1215
} from "./interfaces.js";
1316
import { createOdspAudienceMember } from "./odspAudience.js";
1417

1518
/**
1619
* @internal
1720
*/
18-
export class OdspContainerServices implements IOdspContainerServices {
21+
export class OdspContainerServices implements IOdspContainerServices, IDisposable {
22+
#disposed = false;
23+
readonly #container: IContainer;
24+
1925
public readonly audience: IOdspAudience;
2026

27+
readonly #events = createEmitter<IOdspContainerServicesEvents>();
28+
public get events(): Listenable<IOdspContainerServicesEvents> {
29+
return this.#events;
30+
}
31+
2132
public constructor(container: IContainer) {
33+
this.#container = container;
34+
this.#container.on("readonly", this.#readonlyEventHandler);
35+
this.#container.on("metadataUpdate", this.#metadataUpdateEventHandler);
2236
this.audience = createServiceAudience({
2337
container,
2438
createServiceMember: createOdspAudienceMember,
2539
});
2640
}
41+
42+
readonly #readonlyEventHandler = (): void => {
43+
this.#events.emit("readOnlyStateChanged");
44+
};
45+
46+
readonly #metadataUpdateEventHandler = (metadata: Record<string, string>): void => {
47+
if (metadata.sensitivityLabelsInfo !== undefined) {
48+
this.#events.emit("sensitivityLabelsInfoChanged");
49+
}
50+
};
51+
52+
public get disposed(): boolean {
53+
return this.#disposed;
54+
}
55+
56+
public dispose(): void {
57+
if (this.#disposed) {
58+
return;
59+
}
60+
61+
this.#disposed = true;
62+
this.#container.off("readonly", this.#readonlyEventHandler);
63+
this.#container.off("metadataUpdate", this.#metadataUpdateEventHandler);
64+
}
65+
66+
public getReadOnlyState(): boolean | undefined {
67+
return this.#container.readOnlyInfo.readonly;
68+
}
69+
70+
public getSensitivityLabelsInfo(): string | undefined {
71+
return this.#container.containerMetadata.sensitivityLabelsInfo;
72+
}
2773
}

pnpm-lock.yaml

Lines changed: 3 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)