@fluid-experimental/oldest-client-observer 2.0.0-rc.2.0.2 → 2.0.0-rc.3.0.1

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/CHANGELOG.md CHANGED
@@ -1,5 +1,28 @@
1
1
  # @fluid-experimental/oldest-client-observer
2
2
 
3
+ ## 2.0.0-rc.3.0.0
4
+
5
+ ### Major Changes
6
+
7
+ - Packages now use package.json "exports" and require modern module resolution [97d68aa06b](https://github.com/microsoft/FluidFramework/commit/97d68aa06bd5c022ecb026655814aea222a062ae)
8
+
9
+ Fluid Framework packages have been updated to use the [package.json "exports"
10
+ field](https://nodejs.org/docs/latest-v18.x/api/packages.html#exports) to define explicit entry points for both
11
+ TypeScript types and implementation code.
12
+
13
+ This means that using Fluid Framework packages require the following TypeScript settings in tsconfig.json:
14
+
15
+ - `"moduleResolution": "Node16"` with `"module": "Node16"`
16
+ - `"moduleResolution": "Bundler"` with `"module": "ESNext"`
17
+
18
+ We recommend using Node16/Node16 unless absolutely necessary. That will produce transpiled JavaScript that is suitable
19
+ for use with modern versions of Node.js _and_ Bundlers.
20
+ [See the TypeScript documentation](https://www.typescriptlang.org/tsconfig#moduleResolution) for more information
21
+ regarding the module and moduleResolution options.
22
+
23
+ **Node10 moduleResolution is not supported; it does not support Fluid Framework's API structuring pattern that is used
24
+ to distinguish stable APIs from those that are in development.**
25
+
3
26
  ## 2.0.0-rc.2.0.0
4
27
 
5
28
  Dependency updates only.
@@ -2,8 +2,8 @@
2
2
  * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
3
3
  * Licensed under the MIT License.
4
4
  */
5
- import { IEvent, IEventProvider } from "@fluidframework/core-interfaces";
6
5
  import { AttachState } from "@fluidframework/container-definitions";
6
+ import { IEvent, IEventProvider } from "@fluidframework/core-interfaces";
7
7
  import { IQuorumClients } from "@fluidframework/protocol-definitions";
8
8
  /**
9
9
  * Events emitted by {@link IOldestClientObservable}.
@@ -1 +1 @@
1
- {"version":3,"file":"interfaces.d.ts","sourceRoot":"","sources":["../src/interfaces.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAC;AACzE,OAAO,EAAE,WAAW,EAAE,MAAM,uCAAuC,CAAC;AACpE,OAAO,EAAE,cAAc,EAAE,MAAM,sCAAsC,CAAC;AAEtE;;;GAGG;AACH,MAAM,WAAW,6BAA8B,SAAQ,MAAM;IAC5D,CAAC,KAAK,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,IAAI,OAAE;IAC3C,CAAC,KAAK,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,IAAI,OAAE;CAC9C;AAED;;;;;;GAMG;AACH,MAAM,WAAW,uBAAwB,SAAQ,cAAc,CAAC,6BAA6B,CAAC;IAC7F,SAAS,IAAI,cAAc,CAAC;IAM5B,WAAW,EAAE,WAAW,CAAC;IACzB,SAAS,EAAE,OAAO,CAAC;IACnB,QAAQ,EAAE,MAAM,GAAG,SAAS,CAAC;CAC7B;AAED;;;GAGG;AACH,MAAM,WAAW,2BAA4B,SAAQ,MAAM;IAC1D,CAAC,KAAK,EAAE,cAAc,GAAG,YAAY,EAAE,QAAQ,EAAE,MAAM,IAAI,OAAE;CAC7D;AAED;;GAEG;AACH,MAAM,WAAW,qBAAsB,SAAQ,cAAc,CAAC,2BAA2B,CAAC;IACzF,QAAQ,IAAI,OAAO,CAAC;CACpB"}
1
+ {"version":3,"file":"interfaces.d.ts","sourceRoot":"","sources":["../src/interfaces.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,uCAAuC,CAAC;AACpE,OAAO,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAC;AACzE,OAAO,EAAE,cAAc,EAAE,MAAM,sCAAsC,CAAC;AAEtE;;;GAGG;AACH,MAAM,WAAW,6BAA8B,SAAQ,MAAM;IAC5D,CAAC,KAAK,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,IAAI,OAAE;IAC3C,CAAC,KAAK,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,IAAI,OAAE;CAC9C;AAED;;;;;;GAMG;AACH,MAAM,WAAW,uBAAwB,SAAQ,cAAc,CAAC,6BAA6B,CAAC;IAC7F,SAAS,IAAI,cAAc,CAAC;IAM5B,WAAW,EAAE,WAAW,CAAC;IACzB,SAAS,EAAE,OAAO,CAAC;IACnB,QAAQ,EAAE,MAAM,GAAG,SAAS,CAAC;CAC7B;AAED;;;GAGG;AACH,MAAM,WAAW,2BAA4B,SAAQ,MAAM;IAC1D,CAAC,KAAK,EAAE,cAAc,GAAG,YAAY,EAAE,QAAQ,EAAE,MAAM,IAAI,OAAE;CAC7D;AAED;;GAEG;AACH,MAAM,WAAW,qBAAsB,SAAQ,cAAc,CAAC,2BAA2B,CAAC;IACzF,QAAQ,IAAI,OAAO,CAAC;CACpB"}
@@ -1 +1 @@
1
- {"version":3,"file":"interfaces.js","sourceRoot":"","sources":["../src/interfaces.ts"],"names":[],"mappings":";AAAA;;;GAGG","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { IEvent, IEventProvider } from \"@fluidframework/core-interfaces\";\nimport { AttachState } from \"@fluidframework/container-definitions\";\nimport { IQuorumClients } from \"@fluidframework/protocol-definitions\";\n\n/**\n * Events emitted by {@link IOldestClientObservable}.\n * @alpha\n */\nexport interface IOldestClientObservableEvents extends IEvent {\n\t(event: \"connected\", listener: () => void);\n\t(event: \"disconnected\", listener: () => void);\n}\n\n/**\n * This is to make OldestClientObserver work with either a ContainerRuntime or an IFluidDataStoreRuntime\n * (both expose the relevant API surface and eventing). However, really this info probably shouldn't live on either,\n * since neither is really the source of truth (they are just the only currently-available plumbing options).\n * It's information about the connection, so the real source of truth is lower (at the connection layer).\n * @alpha\n */\nexport interface IOldestClientObservable extends IEventProvider<IOldestClientObservableEvents> {\n\tgetQuorum(): IQuorumClients;\n\t// Generic usage of attachState is a little unusual here. We will treat ourselves as \"the oldest client that\n\t// has information about this [container | data store]\", which in the case of detached data store may disagree\n\t// with whether we're the oldest client on the connected container. So in the data store case, it's only\n\t// safe use this as an indicator about rights to tasks performed against this specific data store, and not\n\t// more broadly.\n\tattachState: AttachState;\n\tconnected: boolean;\n\tclientId: string | undefined;\n}\n\n/**\n * Events emitted by {@link IOldestClientObservable}.\n * @alpha\n */\nexport interface IOldestClientObserverEvents extends IEvent {\n\t(event: \"becameOldest\" | \"lostOldest\", listener: () => void);\n}\n\n/**\n * @alpha\n */\nexport interface IOldestClientObserver extends IEventProvider<IOldestClientObserverEvents> {\n\tisOldest(): boolean;\n}\n"]}
1
+ {"version":3,"file":"interfaces.js","sourceRoot":"","sources":["../src/interfaces.ts"],"names":[],"mappings":";AAAA;;;GAGG","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { AttachState } from \"@fluidframework/container-definitions\";\nimport { IEvent, IEventProvider } from \"@fluidframework/core-interfaces\";\nimport { IQuorumClients } from \"@fluidframework/protocol-definitions\";\n\n/**\n * Events emitted by {@link IOldestClientObservable}.\n * @alpha\n */\nexport interface IOldestClientObservableEvents extends IEvent {\n\t(event: \"connected\", listener: () => void);\n\t(event: \"disconnected\", listener: () => void);\n}\n\n/**\n * This is to make OldestClientObserver work with either a ContainerRuntime or an IFluidDataStoreRuntime\n * (both expose the relevant API surface and eventing). However, really this info probably shouldn't live on either,\n * since neither is really the source of truth (they are just the only currently-available plumbing options).\n * It's information about the connection, so the real source of truth is lower (at the connection layer).\n * @alpha\n */\nexport interface IOldestClientObservable extends IEventProvider<IOldestClientObservableEvents> {\n\tgetQuorum(): IQuorumClients;\n\t// Generic usage of attachState is a little unusual here. We will treat ourselves as \"the oldest client that\n\t// has information about this [container | data store]\", which in the case of detached data store may disagree\n\t// with whether we're the oldest client on the connected container. So in the data store case, it's only\n\t// safe use this as an indicator about rights to tasks performed against this specific data store, and not\n\t// more broadly.\n\tattachState: AttachState;\n\tconnected: boolean;\n\tclientId: string | undefined;\n}\n\n/**\n * Events emitted by {@link IOldestClientObservable}.\n * @alpha\n */\nexport interface IOldestClientObserverEvents extends IEvent {\n\t(event: \"becameOldest\" | \"lostOldest\", listener: () => void);\n}\n\n/**\n * @alpha\n */\nexport interface IOldestClientObserver extends IEventProvider<IOldestClientObserverEvents> {\n\tisOldest(): boolean;\n}\n"]}
@@ -0,0 +1,18 @@
1
+ /*!
2
+ * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
3
+ * Licensed under the MIT License.
4
+ */
5
+
6
+ /*
7
+ * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
8
+ * Generated by "flub generate entrypoints" in @fluidframework/build-tools.
9
+ */
10
+
11
+ export {
12
+ // alpha APIs
13
+ IOldestClientObservable,
14
+ IOldestClientObservableEvents,
15
+ IOldestClientObserver,
16
+ IOldestClientObserverEvents,
17
+ OldestClientObserver
18
+ } from "./index.js";
@@ -3,7 +3,7 @@
3
3
  * Licensed under the MIT License.
4
4
  */
5
5
  import { TypedEventEmitter } from "@fluid-internal/client-utils";
6
- import { IOldestClientObservable, IOldestClientObserverEvents, IOldestClientObserver } from "./interfaces.js";
6
+ import { IOldestClientObservable, IOldestClientObserver, IOldestClientObserverEvents } from "./interfaces.js";
7
7
  /**
8
8
  * The `OldestClientObserver` is a utility inspect if the local client is the oldest amongst connected clients (in
9
9
  * terms of when they connected) and watch for changes.
@@ -1 +1 @@
1
- {"version":3,"file":"oldestClientObserver.d.ts","sourceRoot":"","sources":["../src/oldestClientObserver.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AAIjE,OAAO,EACN,uBAAuB,EACvB,2BAA2B,EAC3B,qBAAqB,EACrB,MAAM,iBAAiB,CAAC;AAEzB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuDG;AACH,qBAAa,oBACZ,SAAQ,iBAAiB,CAAC,2BAA2B,CACrD,YAAW,qBAAqB;IAIpB,OAAO,CAAC,QAAQ,CAAC,UAAU;IAFvC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAiB;IACxC,OAAO,CAAC,eAAe,CAAkB;gBACZ,UAAU,EAAE,uBAAuB;IAUzD,QAAQ,IAAI,OAAO;IAI1B,OAAO,CAAC,QAAQ,CAAC,YAAY,CAU3B;IAEF,OAAO,CAAC,eAAe;CAkCvB"}
1
+ {"version":3,"file":"oldestClientObserver.d.ts","sourceRoot":"","sources":["../src/oldestClientObserver.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AAKjE,OAAO,EACN,uBAAuB,EACvB,qBAAqB,EACrB,2BAA2B,EAC3B,MAAM,iBAAiB,CAAC;AAEzB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuDG;AACH,qBAAa,oBACZ,SAAQ,iBAAiB,CAAC,2BAA2B,CACrD,YAAW,qBAAqB;IAIpB,OAAO,CAAC,QAAQ,CAAC,UAAU;IAFvC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAiB;IACxC,OAAO,CAAC,eAAe,CAAkB;gBACZ,UAAU,EAAE,uBAAuB;IAUzD,QAAQ,IAAI,OAAO;IAI1B,OAAO,CAAC,QAAQ,CAAC,YAAY,CAU3B;IAEF,OAAO,CAAC,eAAe;CAkCvB"}
@@ -6,8 +6,8 @@
6
6
  Object.defineProperty(exports, "__esModule", { value: true });
7
7
  exports.OldestClientObserver = void 0;
8
8
  const client_utils_1 = require("@fluid-internal/client-utils");
9
- const core_utils_1 = require("@fluidframework/core-utils");
10
9
  const container_definitions_1 = require("@fluidframework/container-definitions");
10
+ const internal_1 = require("@fluidframework/core-utils/internal");
11
11
  /**
12
12
  * The `OldestClientObserver` is a utility inspect if the local client is the oldest amongst connected clients (in
13
13
  * terms of when they connected) and watch for changes.
@@ -101,7 +101,7 @@ class OldestClientObserver extends client_utils_1.TypedEventEmitter {
101
101
  return false;
102
102
  }
103
103
  // TODO: Clean up error code linter violations repo-wide.
104
- (0, core_utils_1.assert)(this.observable.clientId !== undefined,
104
+ (0, internal_1.assert)(this.observable.clientId !== undefined,
105
105
  // eslint-disable-next-line unicorn/numeric-separators-style
106
106
  0x1da /* "Client id should be set if connected" */);
107
107
  const selfSequencedClient = this.quorum.getMember(this.observable.clientId);
@@ -1 +1 @@
1
- {"version":3,"file":"oldestClientObserver.js","sourceRoot":"","sources":["../src/oldestClientObserver.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AAEH,+DAAiE;AACjE,2DAAoD;AACpD,iFAAoE;AAQpE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuDG;AACH,MAAa,oBACZ,SAAQ,gCAA8C;IAKtD,YAA6B,UAAmC;QAC/D,KAAK,EAAE,CAAC;QADoB,eAAU,GAAV,UAAU,CAAyB;QADxD,oBAAe,GAAY,KAAK,CAAC;QAexB,iBAAY,GAAG,GAAS,EAAE;YAC1C,MAAM,MAAM,GAAG,IAAI,CAAC,eAAe,EAAE,CAAC;YACtC,IAAI,IAAI,CAAC,eAAe,KAAK,MAAM,EAAE;gBACpC,IAAI,CAAC,eAAe,GAAG,MAAM,CAAC;gBAC9B,IAAI,MAAM,EAAE;oBACX,IAAI,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;iBAC1B;qBAAM;oBACN,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;iBACxB;aACD;QACF,CAAC,CAAC;QAtBD,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,UAAU,CAAC,SAAS,EAAE,CAAC;QAC1C,IAAI,CAAC,eAAe,GAAG,IAAI,CAAC,eAAe,EAAE,CAAC;QAC9C,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,WAAW,EAAE,IAAI,CAAC,YAAY,CAAC,CAAC;QAC/C,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,cAAc,EAAE,IAAI,CAAC,YAAY,CAAC,CAAC;QAClD,UAAU,CAAC,EAAE,CAAC,WAAW,EAAE,IAAI,CAAC,YAAY,CAAC,CAAC;QAC9C,UAAU,CAAC,EAAE,CAAC,cAAc,EAAE,IAAI,CAAC,YAAY,CAAC,CAAC;IAClD,CAAC;IAEM,QAAQ;QACd,OAAO,IAAI,CAAC,eAAe,CAAC;IAC7B,CAAC;IAcO,eAAe;QACtB,uGAAuG;QACvG,IAAI,IAAI,CAAC,UAAU,CAAC,WAAW,KAAK,mCAAW,CAAC,QAAQ,EAAE;YACzD,OAAO,IAAI,CAAC;SACZ;QAED,kEAAkE;QAClE,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,SAAS,EAAE;YAC/B,OAAO,KAAK,CAAC;SACb;QAED,yDAAyD;QACzD,IAAA,mBAAM,EACL,IAAI,CAAC,UAAU,CAAC,QAAQ,KAAK,SAAS;QACtC,4DAA4D;QAC5D,KAAK,CAAC,4CAA4C,CAClD,CAAC;QAEF,MAAM,mBAAmB,GAAG,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC;QAC5E,wEAAwE;QACxE,IAAI,mBAAmB,KAAK,SAAS,EAAE;YACtC,OAAO,KAAK,CAAC;SACb;QAED,MAAM,OAAO,GAAG,IAAI,CAAC,MAAM,CAAC,UAAU,EAAE,CAAC;QACzC,KAAK,MAAM,eAAe,IAAI,OAAO,CAAC,MAAM,EAAE,EAAE;YAC/C,IAAI,eAAe,CAAC,cAAc,GAAG,mBAAmB,CAAC,cAAc,EAAE;gBACxE,OAAO,KAAK,CAAC;aACb;SACD;QAED,oCAAoC;QACpC,OAAO,IAAI,CAAC;IACb,CAAC;CACD;AAlED,oDAkEC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { TypedEventEmitter } from \"@fluid-internal/client-utils\";\nimport { assert } from \"@fluidframework/core-utils\";\nimport { AttachState } from \"@fluidframework/container-definitions\";\nimport { IQuorumClients } from \"@fluidframework/protocol-definitions\";\nimport {\n\tIOldestClientObservable,\n\tIOldestClientObserverEvents,\n\tIOldestClientObserver,\n} from \"./interfaces.js\";\n\n/**\n * The `OldestClientObserver` is a utility inspect if the local client is the oldest amongst connected clients (in\n * terms of when they connected) and watch for changes.\n *\n * It is still experimental and under development. Please do try it out, but expect breaking changes in the future.\n *\n * @remarks\n * ### Creation\n *\n * The `OldestClientObserver` constructor takes an `IOldestClientObservable`. This is most easily satisfied with\n * either an `IContainerRuntime` or an `IFluidDataStoreRuntime`:\n *\n * ```typescript\n * // E.g. from within a BaseContainerRuntimeFactory:\n * protected async containerHasInitialized(runtime: IContainerRuntime) {\n * const oldestClientObserver = new OldestClientObserver(runtime);\n * // ...\n * }\n * ```\n *\n * ```typescript\n * // From within a DataObject\n * protected async hasInitialized() {\n * const oldestClientObserver = new OldestClientObserver(this.runtime);\n * // ...\n * }\n * ```\n *\n * ### Usage\n *\n * To check if the local client is the oldest, use the `isOldest()` method.\n *\n * ```typescript\n * if (oldestClientObserver.isOldest()) {\n * console.log(\"I'm the oldest\");\n * } else {\n * console.log(\"Someone else is older\");\n * }\n * ```\n *\n * ### Eventing\n *\n * `OldestClientObserver` is an `EventEmitter`, and will emit events when the local client becomes the oldest and when\n * it is no longer the oldest.\n *\n * ```typescript\n * oldestClientObserver.on(\"becameOldest\", () => {\n * console.log(\"I'm the oldest now\");\n * });\n *\n * oldestClientObserver.on(\"lostOldest\", () => {\n * console.log(\"I'm not the oldest anymore\");\n * });\n * ```\n * @alpha\n */\nexport class OldestClientObserver\n\textends TypedEventEmitter<IOldestClientObserverEvents>\n\timplements IOldestClientObserver\n{\n\tprivate readonly quorum: IQuorumClients;\n\tprivate currentIsOldest: boolean = false;\n\tconstructor(private readonly observable: IOldestClientObservable) {\n\t\tsuper();\n\t\tthis.quorum = this.observable.getQuorum();\n\t\tthis.currentIsOldest = this.computeIsOldest();\n\t\tthis.quorum.on(\"addMember\", this.updateOldest);\n\t\tthis.quorum.on(\"removeMember\", this.updateOldest);\n\t\tobservable.on(\"connected\", this.updateOldest);\n\t\tobservable.on(\"disconnected\", this.updateOldest);\n\t}\n\n\tpublic isOldest(): boolean {\n\t\treturn this.currentIsOldest;\n\t}\n\n\tprivate readonly updateOldest = (): void => {\n\t\tconst oldest = this.computeIsOldest();\n\t\tif (this.currentIsOldest !== oldest) {\n\t\t\tthis.currentIsOldest = oldest;\n\t\t\tif (oldest) {\n\t\t\t\tthis.emit(\"becameOldest\");\n\t\t\t} else {\n\t\t\t\tthis.emit(\"lostOldest\");\n\t\t\t}\n\t\t}\n\t};\n\n\tprivate computeIsOldest(): boolean {\n\t\t// If the container is detached, we are the only ones that know about it and are the oldest by default.\n\t\tif (this.observable.attachState === AttachState.Detached) {\n\t\t\treturn true;\n\t\t}\n\n\t\t// If we're not connected we can't be the oldest connected client.\n\t\tif (!this.observable.connected) {\n\t\t\treturn false;\n\t\t}\n\n\t\t// TODO: Clean up error code linter violations repo-wide.\n\t\tassert(\n\t\t\tthis.observable.clientId !== undefined,\n\t\t\t// eslint-disable-next-line unicorn/numeric-separators-style\n\t\t\t0x1da /* \"Client id should be set if connected\" */,\n\t\t);\n\n\t\tconst selfSequencedClient = this.quorum.getMember(this.observable.clientId);\n\t\t// When in readonly mode our clientId will not be present in the quorum.\n\t\tif (selfSequencedClient === undefined) {\n\t\t\treturn false;\n\t\t}\n\n\t\tconst members = this.quorum.getMembers();\n\t\tfor (const sequencedClient of members.values()) {\n\t\t\tif (sequencedClient.sequenceNumber < selfSequencedClient.sequenceNumber) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\n\t\t// No member of the quorum was older\n\t\treturn true;\n\t}\n}\n"]}
1
+ {"version":3,"file":"oldestClientObserver.js","sourceRoot":"","sources":["../src/oldestClientObserver.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AAEH,+DAAiE;AACjE,iFAAoE;AACpE,kEAA6D;AAS7D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuDG;AACH,MAAa,oBACZ,SAAQ,gCAA8C;IAKtD,YAA6B,UAAmC;QAC/D,KAAK,EAAE,CAAC;QADoB,eAAU,GAAV,UAAU,CAAyB;QADxD,oBAAe,GAAY,KAAK,CAAC;QAexB,iBAAY,GAAG,GAAS,EAAE;YAC1C,MAAM,MAAM,GAAG,IAAI,CAAC,eAAe,EAAE,CAAC;YACtC,IAAI,IAAI,CAAC,eAAe,KAAK,MAAM,EAAE;gBACpC,IAAI,CAAC,eAAe,GAAG,MAAM,CAAC;gBAC9B,IAAI,MAAM,EAAE;oBACX,IAAI,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;iBAC1B;qBAAM;oBACN,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;iBACxB;aACD;QACF,CAAC,CAAC;QAtBD,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,UAAU,CAAC,SAAS,EAAE,CAAC;QAC1C,IAAI,CAAC,eAAe,GAAG,IAAI,CAAC,eAAe,EAAE,CAAC;QAC9C,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,WAAW,EAAE,IAAI,CAAC,YAAY,CAAC,CAAC;QAC/C,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,cAAc,EAAE,IAAI,CAAC,YAAY,CAAC,CAAC;QAClD,UAAU,CAAC,EAAE,CAAC,WAAW,EAAE,IAAI,CAAC,YAAY,CAAC,CAAC;QAC9C,UAAU,CAAC,EAAE,CAAC,cAAc,EAAE,IAAI,CAAC,YAAY,CAAC,CAAC;IAClD,CAAC;IAEM,QAAQ;QACd,OAAO,IAAI,CAAC,eAAe,CAAC;IAC7B,CAAC;IAcO,eAAe;QACtB,uGAAuG;QACvG,IAAI,IAAI,CAAC,UAAU,CAAC,WAAW,KAAK,mCAAW,CAAC,QAAQ,EAAE;YACzD,OAAO,IAAI,CAAC;SACZ;QAED,kEAAkE;QAClE,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,SAAS,EAAE;YAC/B,OAAO,KAAK,CAAC;SACb;QAED,yDAAyD;QACzD,IAAA,iBAAM,EACL,IAAI,CAAC,UAAU,CAAC,QAAQ,KAAK,SAAS;QACtC,4DAA4D;QAC5D,KAAK,CAAC,4CAA4C,CAClD,CAAC;QAEF,MAAM,mBAAmB,GAAG,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC;QAC5E,wEAAwE;QACxE,IAAI,mBAAmB,KAAK,SAAS,EAAE;YACtC,OAAO,KAAK,CAAC;SACb;QAED,MAAM,OAAO,GAAG,IAAI,CAAC,MAAM,CAAC,UAAU,EAAE,CAAC;QACzC,KAAK,MAAM,eAAe,IAAI,OAAO,CAAC,MAAM,EAAE,EAAE;YAC/C,IAAI,eAAe,CAAC,cAAc,GAAG,mBAAmB,CAAC,cAAc,EAAE;gBACxE,OAAO,KAAK,CAAC;aACb;SACD;QAED,oCAAoC;QACpC,OAAO,IAAI,CAAC;IACb,CAAC;CACD;AAlED,oDAkEC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { TypedEventEmitter } from \"@fluid-internal/client-utils\";\nimport { AttachState } from \"@fluidframework/container-definitions\";\nimport { assert } from \"@fluidframework/core-utils/internal\";\nimport { IQuorumClients } from \"@fluidframework/protocol-definitions\";\n\nimport {\n\tIOldestClientObservable,\n\tIOldestClientObserver,\n\tIOldestClientObserverEvents,\n} from \"./interfaces.js\";\n\n/**\n * The `OldestClientObserver` is a utility inspect if the local client is the oldest amongst connected clients (in\n * terms of when they connected) and watch for changes.\n *\n * It is still experimental and under development. Please do try it out, but expect breaking changes in the future.\n *\n * @remarks\n * ### Creation\n *\n * The `OldestClientObserver` constructor takes an `IOldestClientObservable`. This is most easily satisfied with\n * either an `IContainerRuntime` or an `IFluidDataStoreRuntime`:\n *\n * ```typescript\n * // E.g. from within a BaseContainerRuntimeFactory:\n * protected async containerHasInitialized(runtime: IContainerRuntime) {\n * const oldestClientObserver = new OldestClientObserver(runtime);\n * // ...\n * }\n * ```\n *\n * ```typescript\n * // From within a DataObject\n * protected async hasInitialized() {\n * const oldestClientObserver = new OldestClientObserver(this.runtime);\n * // ...\n * }\n * ```\n *\n * ### Usage\n *\n * To check if the local client is the oldest, use the `isOldest()` method.\n *\n * ```typescript\n * if (oldestClientObserver.isOldest()) {\n * console.log(\"I'm the oldest\");\n * } else {\n * console.log(\"Someone else is older\");\n * }\n * ```\n *\n * ### Eventing\n *\n * `OldestClientObserver` is an `EventEmitter`, and will emit events when the local client becomes the oldest and when\n * it is no longer the oldest.\n *\n * ```typescript\n * oldestClientObserver.on(\"becameOldest\", () => {\n * console.log(\"I'm the oldest now\");\n * });\n *\n * oldestClientObserver.on(\"lostOldest\", () => {\n * console.log(\"I'm not the oldest anymore\");\n * });\n * ```\n * @alpha\n */\nexport class OldestClientObserver\n\textends TypedEventEmitter<IOldestClientObserverEvents>\n\timplements IOldestClientObserver\n{\n\tprivate readonly quorum: IQuorumClients;\n\tprivate currentIsOldest: boolean = false;\n\tconstructor(private readonly observable: IOldestClientObservable) {\n\t\tsuper();\n\t\tthis.quorum = this.observable.getQuorum();\n\t\tthis.currentIsOldest = this.computeIsOldest();\n\t\tthis.quorum.on(\"addMember\", this.updateOldest);\n\t\tthis.quorum.on(\"removeMember\", this.updateOldest);\n\t\tobservable.on(\"connected\", this.updateOldest);\n\t\tobservable.on(\"disconnected\", this.updateOldest);\n\t}\n\n\tpublic isOldest(): boolean {\n\t\treturn this.currentIsOldest;\n\t}\n\n\tprivate readonly updateOldest = (): void => {\n\t\tconst oldest = this.computeIsOldest();\n\t\tif (this.currentIsOldest !== oldest) {\n\t\t\tthis.currentIsOldest = oldest;\n\t\t\tif (oldest) {\n\t\t\t\tthis.emit(\"becameOldest\");\n\t\t\t} else {\n\t\t\t\tthis.emit(\"lostOldest\");\n\t\t\t}\n\t\t}\n\t};\n\n\tprivate computeIsOldest(): boolean {\n\t\t// If the container is detached, we are the only ones that know about it and are the oldest by default.\n\t\tif (this.observable.attachState === AttachState.Detached) {\n\t\t\treturn true;\n\t\t}\n\n\t\t// If we're not connected we can't be the oldest connected client.\n\t\tif (!this.observable.connected) {\n\t\t\treturn false;\n\t\t}\n\n\t\t// TODO: Clean up error code linter violations repo-wide.\n\t\tassert(\n\t\t\tthis.observable.clientId !== undefined,\n\t\t\t// eslint-disable-next-line unicorn/numeric-separators-style\n\t\t\t0x1da /* \"Client id should be set if connected\" */,\n\t\t);\n\n\t\tconst selfSequencedClient = this.quorum.getMember(this.observable.clientId);\n\t\t// When in readonly mode our clientId will not be present in the quorum.\n\t\tif (selfSequencedClient === undefined) {\n\t\t\treturn false;\n\t\t}\n\n\t\tconst members = this.quorum.getMembers();\n\t\tfor (const sequencedClient of members.values()) {\n\t\t\tif (sequencedClient.sequenceNumber < selfSequencedClient.sequenceNumber) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\n\t\t// No member of the quorum was older\n\t\treturn true;\n\t}\n}\n"]}
@@ -0,0 +1,12 @@
1
+ /*!
2
+ * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
3
+ * Licensed under the MIT License.
4
+ */
5
+
6
+ /*
7
+ * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
8
+ * Generated by "flub generate entrypoints" in @fluidframework/build-tools.
9
+ */
10
+
11
+ export {}
12
+
package/internal.d.ts ADDED
@@ -0,0 +1,11 @@
1
+ /*!
2
+ * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
3
+ * Licensed under the MIT License.
4
+ */
5
+
6
+ /*
7
+ * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
8
+ * Generated by "flub generate entrypoints" in @fluidframework/build-tools.
9
+ */
10
+
11
+ export * from "./lib/index.js";
package/legacy.d.ts ADDED
@@ -0,0 +1,11 @@
1
+ /*!
2
+ * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
3
+ * Licensed under the MIT License.
4
+ */
5
+
6
+ /*
7
+ * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
8
+ * Generated by "flub generate entrypoints" in @fluidframework/build-tools.
9
+ */
10
+
11
+ export * from "./lib/legacy.js";
@@ -2,8 +2,8 @@
2
2
  * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
3
3
  * Licensed under the MIT License.
4
4
  */
5
- import { IEvent, IEventProvider } from "@fluidframework/core-interfaces";
6
5
  import { AttachState } from "@fluidframework/container-definitions";
6
+ import { IEvent, IEventProvider } from "@fluidframework/core-interfaces";
7
7
  import { IQuorumClients } from "@fluidframework/protocol-definitions";
8
8
  /**
9
9
  * Events emitted by {@link IOldestClientObservable}.
@@ -1 +1 @@
1
- {"version":3,"file":"interfaces.d.ts","sourceRoot":"","sources":["../src/interfaces.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAC;AACzE,OAAO,EAAE,WAAW,EAAE,MAAM,uCAAuC,CAAC;AACpE,OAAO,EAAE,cAAc,EAAE,MAAM,sCAAsC,CAAC;AAEtE;;;GAGG;AACH,MAAM,WAAW,6BAA8B,SAAQ,MAAM;IAC5D,CAAC,KAAK,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,IAAI,OAAE;IAC3C,CAAC,KAAK,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,IAAI,OAAE;CAC9C;AAED;;;;;;GAMG;AACH,MAAM,WAAW,uBAAwB,SAAQ,cAAc,CAAC,6BAA6B,CAAC;IAC7F,SAAS,IAAI,cAAc,CAAC;IAM5B,WAAW,EAAE,WAAW,CAAC;IACzB,SAAS,EAAE,OAAO,CAAC;IACnB,QAAQ,EAAE,MAAM,GAAG,SAAS,CAAC;CAC7B;AAED;;;GAGG;AACH,MAAM,WAAW,2BAA4B,SAAQ,MAAM;IAC1D,CAAC,KAAK,EAAE,cAAc,GAAG,YAAY,EAAE,QAAQ,EAAE,MAAM,IAAI,OAAE;CAC7D;AAED;;GAEG;AACH,MAAM,WAAW,qBAAsB,SAAQ,cAAc,CAAC,2BAA2B,CAAC;IACzF,QAAQ,IAAI,OAAO,CAAC;CACpB"}
1
+ {"version":3,"file":"interfaces.d.ts","sourceRoot":"","sources":["../src/interfaces.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,uCAAuC,CAAC;AACpE,OAAO,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAC;AACzE,OAAO,EAAE,cAAc,EAAE,MAAM,sCAAsC,CAAC;AAEtE;;;GAGG;AACH,MAAM,WAAW,6BAA8B,SAAQ,MAAM;IAC5D,CAAC,KAAK,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,IAAI,OAAE;IAC3C,CAAC,KAAK,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,IAAI,OAAE;CAC9C;AAED;;;;;;GAMG;AACH,MAAM,WAAW,uBAAwB,SAAQ,cAAc,CAAC,6BAA6B,CAAC;IAC7F,SAAS,IAAI,cAAc,CAAC;IAM5B,WAAW,EAAE,WAAW,CAAC;IACzB,SAAS,EAAE,OAAO,CAAC;IACnB,QAAQ,EAAE,MAAM,GAAG,SAAS,CAAC;CAC7B;AAED;;;GAGG;AACH,MAAM,WAAW,2BAA4B,SAAQ,MAAM;IAC1D,CAAC,KAAK,EAAE,cAAc,GAAG,YAAY,EAAE,QAAQ,EAAE,MAAM,IAAI,OAAE;CAC7D;AAED;;GAEG;AACH,MAAM,WAAW,qBAAsB,SAAQ,cAAc,CAAC,2BAA2B,CAAC;IACzF,QAAQ,IAAI,OAAO,CAAC;CACpB"}
@@ -1 +1 @@
1
- {"version":3,"file":"interfaces.js","sourceRoot":"","sources":["../src/interfaces.ts"],"names":[],"mappings":"AAAA;;;GAGG","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { IEvent, IEventProvider } from \"@fluidframework/core-interfaces\";\nimport { AttachState } from \"@fluidframework/container-definitions\";\nimport { IQuorumClients } from \"@fluidframework/protocol-definitions\";\n\n/**\n * Events emitted by {@link IOldestClientObservable}.\n * @alpha\n */\nexport interface IOldestClientObservableEvents extends IEvent {\n\t(event: \"connected\", listener: () => void);\n\t(event: \"disconnected\", listener: () => void);\n}\n\n/**\n * This is to make OldestClientObserver work with either a ContainerRuntime or an IFluidDataStoreRuntime\n * (both expose the relevant API surface and eventing). However, really this info probably shouldn't live on either,\n * since neither is really the source of truth (they are just the only currently-available plumbing options).\n * It's information about the connection, so the real source of truth is lower (at the connection layer).\n * @alpha\n */\nexport interface IOldestClientObservable extends IEventProvider<IOldestClientObservableEvents> {\n\tgetQuorum(): IQuorumClients;\n\t// Generic usage of attachState is a little unusual here. We will treat ourselves as \"the oldest client that\n\t// has information about this [container | data store]\", which in the case of detached data store may disagree\n\t// with whether we're the oldest client on the connected container. So in the data store case, it's only\n\t// safe use this as an indicator about rights to tasks performed against this specific data store, and not\n\t// more broadly.\n\tattachState: AttachState;\n\tconnected: boolean;\n\tclientId: string | undefined;\n}\n\n/**\n * Events emitted by {@link IOldestClientObservable}.\n * @alpha\n */\nexport interface IOldestClientObserverEvents extends IEvent {\n\t(event: \"becameOldest\" | \"lostOldest\", listener: () => void);\n}\n\n/**\n * @alpha\n */\nexport interface IOldestClientObserver extends IEventProvider<IOldestClientObserverEvents> {\n\tisOldest(): boolean;\n}\n"]}
1
+ {"version":3,"file":"interfaces.js","sourceRoot":"","sources":["../src/interfaces.ts"],"names":[],"mappings":"AAAA;;;GAGG","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { AttachState } from \"@fluidframework/container-definitions\";\nimport { IEvent, IEventProvider } from \"@fluidframework/core-interfaces\";\nimport { IQuorumClients } from \"@fluidframework/protocol-definitions\";\n\n/**\n * Events emitted by {@link IOldestClientObservable}.\n * @alpha\n */\nexport interface IOldestClientObservableEvents extends IEvent {\n\t(event: \"connected\", listener: () => void);\n\t(event: \"disconnected\", listener: () => void);\n}\n\n/**\n * This is to make OldestClientObserver work with either a ContainerRuntime or an IFluidDataStoreRuntime\n * (both expose the relevant API surface and eventing). However, really this info probably shouldn't live on either,\n * since neither is really the source of truth (they are just the only currently-available plumbing options).\n * It's information about the connection, so the real source of truth is lower (at the connection layer).\n * @alpha\n */\nexport interface IOldestClientObservable extends IEventProvider<IOldestClientObservableEvents> {\n\tgetQuorum(): IQuorumClients;\n\t// Generic usage of attachState is a little unusual here. We will treat ourselves as \"the oldest client that\n\t// has information about this [container | data store]\", which in the case of detached data store may disagree\n\t// with whether we're the oldest client on the connected container. So in the data store case, it's only\n\t// safe use this as an indicator about rights to tasks performed against this specific data store, and not\n\t// more broadly.\n\tattachState: AttachState;\n\tconnected: boolean;\n\tclientId: string | undefined;\n}\n\n/**\n * Events emitted by {@link IOldestClientObservable}.\n * @alpha\n */\nexport interface IOldestClientObserverEvents extends IEvent {\n\t(event: \"becameOldest\" | \"lostOldest\", listener: () => void);\n}\n\n/**\n * @alpha\n */\nexport interface IOldestClientObserver extends IEventProvider<IOldestClientObserverEvents> {\n\tisOldest(): boolean;\n}\n"]}
@@ -0,0 +1,18 @@
1
+ /*!
2
+ * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
3
+ * Licensed under the MIT License.
4
+ */
5
+
6
+ /*
7
+ * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
8
+ * Generated by "flub generate entrypoints" in @fluidframework/build-tools.
9
+ */
10
+
11
+ export {
12
+ // alpha APIs
13
+ IOldestClientObservable,
14
+ IOldestClientObservableEvents,
15
+ IOldestClientObserver,
16
+ IOldestClientObserverEvents,
17
+ OldestClientObserver
18
+ } from "./index.js";
@@ -3,7 +3,7 @@
3
3
  * Licensed under the MIT License.
4
4
  */
5
5
  import { TypedEventEmitter } from "@fluid-internal/client-utils";
6
- import { IOldestClientObservable, IOldestClientObserverEvents, IOldestClientObserver } from "./interfaces.js";
6
+ import { IOldestClientObservable, IOldestClientObserver, IOldestClientObserverEvents } from "./interfaces.js";
7
7
  /**
8
8
  * The `OldestClientObserver` is a utility inspect if the local client is the oldest amongst connected clients (in
9
9
  * terms of when they connected) and watch for changes.
@@ -1 +1 @@
1
- {"version":3,"file":"oldestClientObserver.d.ts","sourceRoot":"","sources":["../src/oldestClientObserver.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AAIjE,OAAO,EACN,uBAAuB,EACvB,2BAA2B,EAC3B,qBAAqB,EACrB,MAAM,iBAAiB,CAAC;AAEzB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuDG;AACH,qBAAa,oBACZ,SAAQ,iBAAiB,CAAC,2BAA2B,CACrD,YAAW,qBAAqB;IAIpB,OAAO,CAAC,QAAQ,CAAC,UAAU;IAFvC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAiB;IACxC,OAAO,CAAC,eAAe,CAAkB;gBACZ,UAAU,EAAE,uBAAuB;IAUzD,QAAQ,IAAI,OAAO;IAI1B,OAAO,CAAC,QAAQ,CAAC,YAAY,CAU3B;IAEF,OAAO,CAAC,eAAe;CAkCvB"}
1
+ {"version":3,"file":"oldestClientObserver.d.ts","sourceRoot":"","sources":["../src/oldestClientObserver.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AAKjE,OAAO,EACN,uBAAuB,EACvB,qBAAqB,EACrB,2BAA2B,EAC3B,MAAM,iBAAiB,CAAC;AAEzB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuDG;AACH,qBAAa,oBACZ,SAAQ,iBAAiB,CAAC,2BAA2B,CACrD,YAAW,qBAAqB;IAIpB,OAAO,CAAC,QAAQ,CAAC,UAAU;IAFvC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAiB;IACxC,OAAO,CAAC,eAAe,CAAkB;gBACZ,UAAU,EAAE,uBAAuB;IAUzD,QAAQ,IAAI,OAAO;IAI1B,OAAO,CAAC,QAAQ,CAAC,YAAY,CAU3B;IAEF,OAAO,CAAC,eAAe;CAkCvB"}
@@ -3,8 +3,8 @@
3
3
  * Licensed under the MIT License.
4
4
  */
5
5
  import { TypedEventEmitter } from "@fluid-internal/client-utils";
6
- import { assert } from "@fluidframework/core-utils";
7
6
  import { AttachState } from "@fluidframework/container-definitions";
7
+ import { assert } from "@fluidframework/core-utils/internal";
8
8
  /**
9
9
  * The `OldestClientObserver` is a utility inspect if the local client is the oldest amongst connected clients (in
10
10
  * terms of when they connected) and watch for changes.
@@ -1 +1 @@
1
- {"version":3,"file":"oldestClientObserver.js","sourceRoot":"","sources":["../src/oldestClientObserver.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AACjE,OAAO,EAAE,MAAM,EAAE,MAAM,4BAA4B,CAAC;AACpD,OAAO,EAAE,WAAW,EAAE,MAAM,uCAAuC,CAAC;AAQpE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuDG;AACH,MAAM,OAAO,oBACZ,SAAQ,iBAA8C;IAKtD,YAA6B,UAAmC;QAC/D,KAAK,EAAE,CAAC;QADoB,eAAU,GAAV,UAAU,CAAyB;QADxD,oBAAe,GAAY,KAAK,CAAC;QAexB,iBAAY,GAAG,GAAS,EAAE;YAC1C,MAAM,MAAM,GAAG,IAAI,CAAC,eAAe,EAAE,CAAC;YACtC,IAAI,IAAI,CAAC,eAAe,KAAK,MAAM,EAAE;gBACpC,IAAI,CAAC,eAAe,GAAG,MAAM,CAAC;gBAC9B,IAAI,MAAM,EAAE;oBACX,IAAI,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;iBAC1B;qBAAM;oBACN,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;iBACxB;aACD;QACF,CAAC,CAAC;QAtBD,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,UAAU,CAAC,SAAS,EAAE,CAAC;QAC1C,IAAI,CAAC,eAAe,GAAG,IAAI,CAAC,eAAe,EAAE,CAAC;QAC9C,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,WAAW,EAAE,IAAI,CAAC,YAAY,CAAC,CAAC;QAC/C,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,cAAc,EAAE,IAAI,CAAC,YAAY,CAAC,CAAC;QAClD,UAAU,CAAC,EAAE,CAAC,WAAW,EAAE,IAAI,CAAC,YAAY,CAAC,CAAC;QAC9C,UAAU,CAAC,EAAE,CAAC,cAAc,EAAE,IAAI,CAAC,YAAY,CAAC,CAAC;IAClD,CAAC;IAEM,QAAQ;QACd,OAAO,IAAI,CAAC,eAAe,CAAC;IAC7B,CAAC;IAcO,eAAe;QACtB,uGAAuG;QACvG,IAAI,IAAI,CAAC,UAAU,CAAC,WAAW,KAAK,WAAW,CAAC,QAAQ,EAAE;YACzD,OAAO,IAAI,CAAC;SACZ;QAED,kEAAkE;QAClE,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,SAAS,EAAE;YAC/B,OAAO,KAAK,CAAC;SACb;QAED,yDAAyD;QACzD,MAAM,CACL,IAAI,CAAC,UAAU,CAAC,QAAQ,KAAK,SAAS;QACtC,4DAA4D;QAC5D,KAAK,CAAC,4CAA4C,CAClD,CAAC;QAEF,MAAM,mBAAmB,GAAG,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC;QAC5E,wEAAwE;QACxE,IAAI,mBAAmB,KAAK,SAAS,EAAE;YACtC,OAAO,KAAK,CAAC;SACb;QAED,MAAM,OAAO,GAAG,IAAI,CAAC,MAAM,CAAC,UAAU,EAAE,CAAC;QACzC,KAAK,MAAM,eAAe,IAAI,OAAO,CAAC,MAAM,EAAE,EAAE;YAC/C,IAAI,eAAe,CAAC,cAAc,GAAG,mBAAmB,CAAC,cAAc,EAAE;gBACxE,OAAO,KAAK,CAAC;aACb;SACD;QAED,oCAAoC;QACpC,OAAO,IAAI,CAAC;IACb,CAAC;CACD","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { TypedEventEmitter } from \"@fluid-internal/client-utils\";\nimport { assert } from \"@fluidframework/core-utils\";\nimport { AttachState } from \"@fluidframework/container-definitions\";\nimport { IQuorumClients } from \"@fluidframework/protocol-definitions\";\nimport {\n\tIOldestClientObservable,\n\tIOldestClientObserverEvents,\n\tIOldestClientObserver,\n} from \"./interfaces.js\";\n\n/**\n * The `OldestClientObserver` is a utility inspect if the local client is the oldest amongst connected clients (in\n * terms of when they connected) and watch for changes.\n *\n * It is still experimental and under development. Please do try it out, but expect breaking changes in the future.\n *\n * @remarks\n * ### Creation\n *\n * The `OldestClientObserver` constructor takes an `IOldestClientObservable`. This is most easily satisfied with\n * either an `IContainerRuntime` or an `IFluidDataStoreRuntime`:\n *\n * ```typescript\n * // E.g. from within a BaseContainerRuntimeFactory:\n * protected async containerHasInitialized(runtime: IContainerRuntime) {\n * const oldestClientObserver = new OldestClientObserver(runtime);\n * // ...\n * }\n * ```\n *\n * ```typescript\n * // From within a DataObject\n * protected async hasInitialized() {\n * const oldestClientObserver = new OldestClientObserver(this.runtime);\n * // ...\n * }\n * ```\n *\n * ### Usage\n *\n * To check if the local client is the oldest, use the `isOldest()` method.\n *\n * ```typescript\n * if (oldestClientObserver.isOldest()) {\n * console.log(\"I'm the oldest\");\n * } else {\n * console.log(\"Someone else is older\");\n * }\n * ```\n *\n * ### Eventing\n *\n * `OldestClientObserver` is an `EventEmitter`, and will emit events when the local client becomes the oldest and when\n * it is no longer the oldest.\n *\n * ```typescript\n * oldestClientObserver.on(\"becameOldest\", () => {\n * console.log(\"I'm the oldest now\");\n * });\n *\n * oldestClientObserver.on(\"lostOldest\", () => {\n * console.log(\"I'm not the oldest anymore\");\n * });\n * ```\n * @alpha\n */\nexport class OldestClientObserver\n\textends TypedEventEmitter<IOldestClientObserverEvents>\n\timplements IOldestClientObserver\n{\n\tprivate readonly quorum: IQuorumClients;\n\tprivate currentIsOldest: boolean = false;\n\tconstructor(private readonly observable: IOldestClientObservable) {\n\t\tsuper();\n\t\tthis.quorum = this.observable.getQuorum();\n\t\tthis.currentIsOldest = this.computeIsOldest();\n\t\tthis.quorum.on(\"addMember\", this.updateOldest);\n\t\tthis.quorum.on(\"removeMember\", this.updateOldest);\n\t\tobservable.on(\"connected\", this.updateOldest);\n\t\tobservable.on(\"disconnected\", this.updateOldest);\n\t}\n\n\tpublic isOldest(): boolean {\n\t\treturn this.currentIsOldest;\n\t}\n\n\tprivate readonly updateOldest = (): void => {\n\t\tconst oldest = this.computeIsOldest();\n\t\tif (this.currentIsOldest !== oldest) {\n\t\t\tthis.currentIsOldest = oldest;\n\t\t\tif (oldest) {\n\t\t\t\tthis.emit(\"becameOldest\");\n\t\t\t} else {\n\t\t\t\tthis.emit(\"lostOldest\");\n\t\t\t}\n\t\t}\n\t};\n\n\tprivate computeIsOldest(): boolean {\n\t\t// If the container is detached, we are the only ones that know about it and are the oldest by default.\n\t\tif (this.observable.attachState === AttachState.Detached) {\n\t\t\treturn true;\n\t\t}\n\n\t\t// If we're not connected we can't be the oldest connected client.\n\t\tif (!this.observable.connected) {\n\t\t\treturn false;\n\t\t}\n\n\t\t// TODO: Clean up error code linter violations repo-wide.\n\t\tassert(\n\t\t\tthis.observable.clientId !== undefined,\n\t\t\t// eslint-disable-next-line unicorn/numeric-separators-style\n\t\t\t0x1da /* \"Client id should be set if connected\" */,\n\t\t);\n\n\t\tconst selfSequencedClient = this.quorum.getMember(this.observable.clientId);\n\t\t// When in readonly mode our clientId will not be present in the quorum.\n\t\tif (selfSequencedClient === undefined) {\n\t\t\treturn false;\n\t\t}\n\n\t\tconst members = this.quorum.getMembers();\n\t\tfor (const sequencedClient of members.values()) {\n\t\t\tif (sequencedClient.sequenceNumber < selfSequencedClient.sequenceNumber) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\n\t\t// No member of the quorum was older\n\t\treturn true;\n\t}\n}\n"]}
1
+ {"version":3,"file":"oldestClientObserver.js","sourceRoot":"","sources":["../src/oldestClientObserver.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AACjE,OAAO,EAAE,WAAW,EAAE,MAAM,uCAAuC,CAAC;AACpE,OAAO,EAAE,MAAM,EAAE,MAAM,qCAAqC,CAAC;AAS7D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuDG;AACH,MAAM,OAAO,oBACZ,SAAQ,iBAA8C;IAKtD,YAA6B,UAAmC;QAC/D,KAAK,EAAE,CAAC;QADoB,eAAU,GAAV,UAAU,CAAyB;QADxD,oBAAe,GAAY,KAAK,CAAC;QAexB,iBAAY,GAAG,GAAS,EAAE;YAC1C,MAAM,MAAM,GAAG,IAAI,CAAC,eAAe,EAAE,CAAC;YACtC,IAAI,IAAI,CAAC,eAAe,KAAK,MAAM,EAAE;gBACpC,IAAI,CAAC,eAAe,GAAG,MAAM,CAAC;gBAC9B,IAAI,MAAM,EAAE;oBACX,IAAI,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;iBAC1B;qBAAM;oBACN,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;iBACxB;aACD;QACF,CAAC,CAAC;QAtBD,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,UAAU,CAAC,SAAS,EAAE,CAAC;QAC1C,IAAI,CAAC,eAAe,GAAG,IAAI,CAAC,eAAe,EAAE,CAAC;QAC9C,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,WAAW,EAAE,IAAI,CAAC,YAAY,CAAC,CAAC;QAC/C,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,cAAc,EAAE,IAAI,CAAC,YAAY,CAAC,CAAC;QAClD,UAAU,CAAC,EAAE,CAAC,WAAW,EAAE,IAAI,CAAC,YAAY,CAAC,CAAC;QAC9C,UAAU,CAAC,EAAE,CAAC,cAAc,EAAE,IAAI,CAAC,YAAY,CAAC,CAAC;IAClD,CAAC;IAEM,QAAQ;QACd,OAAO,IAAI,CAAC,eAAe,CAAC;IAC7B,CAAC;IAcO,eAAe;QACtB,uGAAuG;QACvG,IAAI,IAAI,CAAC,UAAU,CAAC,WAAW,KAAK,WAAW,CAAC,QAAQ,EAAE;YACzD,OAAO,IAAI,CAAC;SACZ;QAED,kEAAkE;QAClE,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,SAAS,EAAE;YAC/B,OAAO,KAAK,CAAC;SACb;QAED,yDAAyD;QACzD,MAAM,CACL,IAAI,CAAC,UAAU,CAAC,QAAQ,KAAK,SAAS;QACtC,4DAA4D;QAC5D,KAAK,CAAC,4CAA4C,CAClD,CAAC;QAEF,MAAM,mBAAmB,GAAG,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC;QAC5E,wEAAwE;QACxE,IAAI,mBAAmB,KAAK,SAAS,EAAE;YACtC,OAAO,KAAK,CAAC;SACb;QAED,MAAM,OAAO,GAAG,IAAI,CAAC,MAAM,CAAC,UAAU,EAAE,CAAC;QACzC,KAAK,MAAM,eAAe,IAAI,OAAO,CAAC,MAAM,EAAE,EAAE;YAC/C,IAAI,eAAe,CAAC,cAAc,GAAG,mBAAmB,CAAC,cAAc,EAAE;gBACxE,OAAO,KAAK,CAAC;aACb;SACD;QAED,oCAAoC;QACpC,OAAO,IAAI,CAAC;IACb,CAAC;CACD","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { TypedEventEmitter } from \"@fluid-internal/client-utils\";\nimport { AttachState } from \"@fluidframework/container-definitions\";\nimport { assert } from \"@fluidframework/core-utils/internal\";\nimport { IQuorumClients } from \"@fluidframework/protocol-definitions\";\n\nimport {\n\tIOldestClientObservable,\n\tIOldestClientObserver,\n\tIOldestClientObserverEvents,\n} from \"./interfaces.js\";\n\n/**\n * The `OldestClientObserver` is a utility inspect if the local client is the oldest amongst connected clients (in\n * terms of when they connected) and watch for changes.\n *\n * It is still experimental and under development. Please do try it out, but expect breaking changes in the future.\n *\n * @remarks\n * ### Creation\n *\n * The `OldestClientObserver` constructor takes an `IOldestClientObservable`. This is most easily satisfied with\n * either an `IContainerRuntime` or an `IFluidDataStoreRuntime`:\n *\n * ```typescript\n * // E.g. from within a BaseContainerRuntimeFactory:\n * protected async containerHasInitialized(runtime: IContainerRuntime) {\n * const oldestClientObserver = new OldestClientObserver(runtime);\n * // ...\n * }\n * ```\n *\n * ```typescript\n * // From within a DataObject\n * protected async hasInitialized() {\n * const oldestClientObserver = new OldestClientObserver(this.runtime);\n * // ...\n * }\n * ```\n *\n * ### Usage\n *\n * To check if the local client is the oldest, use the `isOldest()` method.\n *\n * ```typescript\n * if (oldestClientObserver.isOldest()) {\n * console.log(\"I'm the oldest\");\n * } else {\n * console.log(\"Someone else is older\");\n * }\n * ```\n *\n * ### Eventing\n *\n * `OldestClientObserver` is an `EventEmitter`, and will emit events when the local client becomes the oldest and when\n * it is no longer the oldest.\n *\n * ```typescript\n * oldestClientObserver.on(\"becameOldest\", () => {\n * console.log(\"I'm the oldest now\");\n * });\n *\n * oldestClientObserver.on(\"lostOldest\", () => {\n * console.log(\"I'm not the oldest anymore\");\n * });\n * ```\n * @alpha\n */\nexport class OldestClientObserver\n\textends TypedEventEmitter<IOldestClientObserverEvents>\n\timplements IOldestClientObserver\n{\n\tprivate readonly quorum: IQuorumClients;\n\tprivate currentIsOldest: boolean = false;\n\tconstructor(private readonly observable: IOldestClientObservable) {\n\t\tsuper();\n\t\tthis.quorum = this.observable.getQuorum();\n\t\tthis.currentIsOldest = this.computeIsOldest();\n\t\tthis.quorum.on(\"addMember\", this.updateOldest);\n\t\tthis.quorum.on(\"removeMember\", this.updateOldest);\n\t\tobservable.on(\"connected\", this.updateOldest);\n\t\tobservable.on(\"disconnected\", this.updateOldest);\n\t}\n\n\tpublic isOldest(): boolean {\n\t\treturn this.currentIsOldest;\n\t}\n\n\tprivate readonly updateOldest = (): void => {\n\t\tconst oldest = this.computeIsOldest();\n\t\tif (this.currentIsOldest !== oldest) {\n\t\t\tthis.currentIsOldest = oldest;\n\t\t\tif (oldest) {\n\t\t\t\tthis.emit(\"becameOldest\");\n\t\t\t} else {\n\t\t\t\tthis.emit(\"lostOldest\");\n\t\t\t}\n\t\t}\n\t};\n\n\tprivate computeIsOldest(): boolean {\n\t\t// If the container is detached, we are the only ones that know about it and are the oldest by default.\n\t\tif (this.observable.attachState === AttachState.Detached) {\n\t\t\treturn true;\n\t\t}\n\n\t\t// If we're not connected we can't be the oldest connected client.\n\t\tif (!this.observable.connected) {\n\t\t\treturn false;\n\t\t}\n\n\t\t// TODO: Clean up error code linter violations repo-wide.\n\t\tassert(\n\t\t\tthis.observable.clientId !== undefined,\n\t\t\t// eslint-disable-next-line unicorn/numeric-separators-style\n\t\t\t0x1da /* \"Client id should be set if connected\" */,\n\t\t);\n\n\t\tconst selfSequencedClient = this.quorum.getMember(this.observable.clientId);\n\t\t// When in readonly mode our clientId will not be present in the quorum.\n\t\tif (selfSequencedClient === undefined) {\n\t\t\treturn false;\n\t\t}\n\n\t\tconst members = this.quorum.getMembers();\n\t\tfor (const sequencedClient of members.values()) {\n\t\t\tif (sequencedClient.sequenceNumber < selfSequencedClient.sequenceNumber) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\n\t\t// No member of the quorum was older\n\t\treturn true;\n\t}\n}\n"]}
@@ -0,0 +1,12 @@
1
+ /*!
2
+ * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
3
+ * Licensed under the MIT License.
4
+ */
5
+
6
+ /*
7
+ * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
8
+ * Generated by "flub generate entrypoints" in @fluidframework/build-tools.
9
+ */
10
+
11
+ export {}
12
+
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fluid-experimental/oldest-client-observer",
3
- "version": "2.0.0-rc.2.0.2",
3
+ "version": "2.0.0-rc.3.0.1",
4
4
  "description": "Data object to determine if the local client is the oldest amongst connected clients",
5
5
  "homepage": "https://fluidframework.com",
6
6
  "repository": {
@@ -15,31 +15,21 @@
15
15
  "exports": {
16
16
  ".": {
17
17
  "import": {
18
- "types": "./lib/index.d.ts",
19
- "default": "./lib/index.js"
20
- },
21
- "require": {
22
- "types": "./dist/index.d.ts",
23
- "default": "./dist/index.js"
24
- }
25
- },
26
- "./public": {
27
- "import": {
28
- "types": "./lib/oldest-client-observer-public.d.ts",
18
+ "types": "./lib/public.d.ts",
29
19
  "default": "./lib/index.js"
30
20
  },
31
21
  "require": {
32
- "types": "./dist/oldest-client-observer-public.d.ts",
22
+ "types": "./dist/public.d.ts",
33
23
  "default": "./dist/index.js"
34
24
  }
35
25
  },
36
- "./alpha": {
26
+ "./legacy": {
37
27
  "import": {
38
- "types": "./lib/oldest-client-observer-alpha.d.ts",
28
+ "types": "./lib/legacy.d.ts",
39
29
  "default": "./lib/index.js"
40
30
  },
41
31
  "require": {
42
- "types": "./dist/oldest-client-observer-alpha.d.ts",
32
+ "types": "./dist/legacy.d.ts",
43
33
  "default": "./dist/index.js"
44
34
  }
45
35
  },
@@ -54,8 +44,8 @@
54
44
  }
55
45
  }
56
46
  },
57
- "main": "dist/index.js",
58
- "types": "dist/index.d.ts",
47
+ "main": "lib/index.js",
48
+ "types": "lib/public.d.ts",
59
49
  "c8": {
60
50
  "all": true,
61
51
  "cache-dir": "nyc/.cache",
@@ -77,19 +67,20 @@
77
67
  "temp-directory": "nyc/.nyc_output"
78
68
  },
79
69
  "dependencies": {
80
- "@fluid-internal/client-utils": ">=2.0.0-rc.2.0.2 <2.0.0-rc.2.1.0",
81
- "@fluidframework/container-definitions": ">=2.0.0-rc.2.0.2 <2.0.0-rc.2.1.0",
82
- "@fluidframework/core-interfaces": ">=2.0.0-rc.2.0.2 <2.0.0-rc.2.1.0",
83
- "@fluidframework/core-utils": ">=2.0.0-rc.2.0.2 <2.0.0-rc.2.1.0",
70
+ "@fluid-internal/client-utils": ">=2.0.0-rc.3.0.1 <2.0.0-rc.3.1.0",
71
+ "@fluidframework/container-definitions": ">=2.0.0-rc.3.0.1 <2.0.0-rc.3.1.0",
72
+ "@fluidframework/core-interfaces": ">=2.0.0-rc.3.0.1 <2.0.0-rc.3.1.0",
73
+ "@fluidframework/core-utils": ">=2.0.0-rc.3.0.1 <2.0.0-rc.3.1.0",
84
74
  "@fluidframework/protocol-definitions": "^3.2.0"
85
75
  },
86
76
  "devDependencies": {
87
- "@arethetypeswrong/cli": "^0.13.3",
88
- "@fluid-private/test-dds-utils": ">=2.0.0-rc.2.0.2 <2.0.0-rc.2.1.0",
89
- "@fluid-tools/build-cli": "^0.34.0",
77
+ "@arethetypeswrong/cli": "^0.15.2",
78
+ "@biomejs/biome": "^1.6.2",
79
+ "@fluid-private/test-dds-utils": ">=2.0.0-rc.3.0.1 <2.0.0-rc.3.1.0",
80
+ "@fluid-tools/build-cli": "^0.37.0",
90
81
  "@fluidframework/build-common": "^2.0.3",
91
- "@fluidframework/build-tools": "^0.34.0",
92
- "@fluidframework/eslint-config-fluid": "^4.0.0",
82
+ "@fluidframework/build-tools": "^0.37.0",
83
+ "@fluidframework/eslint-config-fluid": "^5.1.0",
93
84
  "@microsoft/api-extractor": "^7.42.3",
94
85
  "@types/node": "^18.19.0",
95
86
  "copyfiles": "^2.4.1",
@@ -101,14 +92,6 @@
101
92
  },
102
93
  "fluidBuild": {
103
94
  "tasks": {
104
- "build:docs": {
105
- "dependsOn": [
106
- "...",
107
- "api-extractor:commonjs",
108
- "api-extractor:esnext"
109
- ],
110
- "script": false
111
- },
112
95
  "tsc": [
113
96
  "...",
114
97
  "typetests:gen"
@@ -121,24 +104,24 @@
121
104
  },
122
105
  "scripts": {
123
106
  "api": "fluid-build . --task api",
124
- "api-extractor:commonjs": "api-extractor run --config ./api-extractor-cjs.json",
125
- "api-extractor:esnext": "api-extractor run --local",
107
+ "api-extractor:commonjs": "flub generate entrypoints --outFileAlpha legacy --outDir ./dist",
108
+ "api-extractor:esnext": "flub generate entrypoints --outFileAlpha legacy --outDir ./lib --node10TypeCompat",
126
109
  "build": "fluid-build . --task build",
127
110
  "build:commonjs": "fluid-build . --task commonjs",
128
111
  "build:compile": "fluid-build . --task compile",
129
- "build:docs": "fluid-build . --task api",
112
+ "build:docs": "api-extractor run --local",
130
113
  "build:esnext": "tsc --project ./tsconfig.json",
131
- "check:are-the-types-wrong": "attw --pack . --entrypoints .",
114
+ "check:are-the-types-wrong": "attw --pack .",
115
+ "check:prettier": "prettier --check . --cache --ignore-path ../../../.prettierignore",
132
116
  "check:release-tags": "api-extractor run --local --config ./api-extractor-lint.json",
133
117
  "ci:build:docs": "api-extractor run",
134
- "clean": "rimraf --glob dist lib \"**/*.tsbuildinfo\" \"**/*.build.log\" _api-extractor-temp",
118
+ "clean": "rimraf --glob dist lib \"*.d.ts\" \"**/*.tsbuildinfo\" \"**/*.build.log\" _api-extractor-temp",
135
119
  "eslint": "eslint --format stylish src",
136
120
  "eslint:fix": "eslint --format stylish src --fix --fix-type problem,suggestion,layout",
137
- "format": "npm run prettier:fix",
138
- "lint": "npm run prettier && npm run check:release-tags && npm run eslint",
139
- "lint:fix": "npm run prettier:fix && npm run eslint:fix",
140
- "prettier": "prettier --check . --cache --ignore-path ../../../.prettierignore",
141
- "prettier:fix": "prettier --write . --cache --ignore-path ../../../.prettierignore",
121
+ "format": "fluid-build --task format .",
122
+ "format:prettier": "prettier --write . --cache --ignore-path ../../../.prettierignore",
123
+ "lint": "fluid-build . --task lint",
124
+ "lint:fix": "fluid-build . --task eslint:fix --task format",
142
125
  "tsc": "fluid-tsc commonjs --project ./tsconfig.cjs.json && copyfiles -f ../../../common/build/build-common/src/cjs/package.json ./dist",
143
126
  "typetests:gen": "fluid-type-test-generator",
144
127
  "typetests:prepare": "flub typetests --dir . --reset --previous --normalize"
package/src/interfaces.ts CHANGED
@@ -3,8 +3,8 @@
3
3
  * Licensed under the MIT License.
4
4
  */
5
5
 
6
- import { IEvent, IEventProvider } from "@fluidframework/core-interfaces";
7
6
  import { AttachState } from "@fluidframework/container-definitions";
7
+ import { IEvent, IEventProvider } from "@fluidframework/core-interfaces";
8
8
  import { IQuorumClients } from "@fluidframework/protocol-definitions";
9
9
 
10
10
  /**
@@ -4,13 +4,14 @@
4
4
  */
5
5
 
6
6
  import { TypedEventEmitter } from "@fluid-internal/client-utils";
7
- import { assert } from "@fluidframework/core-utils";
8
7
  import { AttachState } from "@fluidframework/container-definitions";
8
+ import { assert } from "@fluidframework/core-utils/internal";
9
9
  import { IQuorumClients } from "@fluidframework/protocol-definitions";
10
+
10
11
  import {
11
12
  IOldestClientObservable,
12
- IOldestClientObserverEvents,
13
13
  IOldestClientObserver,
14
+ IOldestClientObserverEvents,
14
15
  } from "./interfaces.js";
15
16
 
16
17
  /**
@@ -1,8 +0,0 @@
1
- {
2
- "$schema": "https://developer.microsoft.com/json-schemas/api-extractor/v7/api-extractor.schema.json",
3
- "extends": "../../../common/build/build-common/api-extractor-base.cjs.primary.json",
4
- // CJS is actually secondary; so, no report.
5
- "apiReport": {
6
- "enabled": false
7
- }
8
- }
@@ -1,111 +0,0 @@
1
- import { AttachState } from '@fluidframework/container-definitions';
2
- import { IEvent } from '@fluidframework/core-interfaces';
3
- import { IEventProvider } from '@fluidframework/core-interfaces';
4
- import { IQuorumClients } from '@fluidframework/protocol-definitions';
5
- import { TypedEventEmitter } from '@fluid-internal/client-utils';
6
-
7
- /**
8
- * This is to make OldestClientObserver work with either a ContainerRuntime or an IFluidDataStoreRuntime
9
- * (both expose the relevant API surface and eventing). However, really this info probably shouldn't live on either,
10
- * since neither is really the source of truth (they are just the only currently-available plumbing options).
11
- * It's information about the connection, so the real source of truth is lower (at the connection layer).
12
- * @alpha
13
- */
14
- export declare interface IOldestClientObservable extends IEventProvider<IOldestClientObservableEvents> {
15
- getQuorum(): IQuorumClients;
16
- attachState: AttachState;
17
- connected: boolean;
18
- clientId: string | undefined;
19
- }
20
-
21
- /**
22
- * Events emitted by {@link IOldestClientObservable}.
23
- * @alpha
24
- */
25
- export declare interface IOldestClientObservableEvents extends IEvent {
26
- (event: "connected", listener: () => void): any;
27
- (event: "disconnected", listener: () => void): any;
28
- }
29
-
30
- /**
31
- * @alpha
32
- */
33
- export declare interface IOldestClientObserver extends IEventProvider<IOldestClientObserverEvents> {
34
- isOldest(): boolean;
35
- }
36
-
37
- /**
38
- * Events emitted by {@link IOldestClientObservable}.
39
- * @alpha
40
- */
41
- export declare interface IOldestClientObserverEvents extends IEvent {
42
- (event: "becameOldest" | "lostOldest", listener: () => void): any;
43
- }
44
-
45
- /**
46
- * The `OldestClientObserver` is a utility inspect if the local client is the oldest amongst connected clients (in
47
- * terms of when they connected) and watch for changes.
48
- *
49
- * It is still experimental and under development. Please do try it out, but expect breaking changes in the future.
50
- *
51
- * @remarks
52
- * ### Creation
53
- *
54
- * The `OldestClientObserver` constructor takes an `IOldestClientObservable`. This is most easily satisfied with
55
- * either an `IContainerRuntime` or an `IFluidDataStoreRuntime`:
56
- *
57
- * ```typescript
58
- * // E.g. from within a BaseContainerRuntimeFactory:
59
- * protected async containerHasInitialized(runtime: IContainerRuntime) {
60
- * const oldestClientObserver = new OldestClientObserver(runtime);
61
- * // ...
62
- * }
63
- * ```
64
- *
65
- * ```typescript
66
- * // From within a DataObject
67
- * protected async hasInitialized() {
68
- * const oldestClientObserver = new OldestClientObserver(this.runtime);
69
- * // ...
70
- * }
71
- * ```
72
- *
73
- * ### Usage
74
- *
75
- * To check if the local client is the oldest, use the `isOldest()` method.
76
- *
77
- * ```typescript
78
- * if (oldestClientObserver.isOldest()) {
79
- * console.log("I'm the oldest");
80
- * } else {
81
- * console.log("Someone else is older");
82
- * }
83
- * ```
84
- *
85
- * ### Eventing
86
- *
87
- * `OldestClientObserver` is an `EventEmitter`, and will emit events when the local client becomes the oldest and when
88
- * it is no longer the oldest.
89
- *
90
- * ```typescript
91
- * oldestClientObserver.on("becameOldest", () => {
92
- * console.log("I'm the oldest now");
93
- * });
94
- *
95
- * oldestClientObserver.on("lostOldest", () => {
96
- * console.log("I'm not the oldest anymore");
97
- * });
98
- * ```
99
- * @alpha
100
- */
101
- export declare class OldestClientObserver extends TypedEventEmitter<IOldestClientObserverEvents> implements IOldestClientObserver {
102
- private readonly observable;
103
- private readonly quorum;
104
- private currentIsOldest;
105
- constructor(observable: IOldestClientObservable);
106
- isOldest(): boolean;
107
- private readonly updateOldest;
108
- private computeIsOldest;
109
- }
110
-
111
- export { }
@@ -1,17 +0,0 @@
1
- import { AttachState } from '@fluidframework/container-definitions';
2
- import { IEvent } from '@fluidframework/core-interfaces';
3
- import { IEventProvider } from '@fluidframework/core-interfaces';
4
- import { IQuorumClients } from '@fluidframework/protocol-definitions';
5
- import { TypedEventEmitter } from '@fluid-internal/client-utils';
6
-
7
- /* Excluded from this release type: IOldestClientObservable */
8
-
9
- /* Excluded from this release type: IOldestClientObservableEvents */
10
-
11
- /* Excluded from this release type: IOldestClientObserver */
12
-
13
- /* Excluded from this release type: IOldestClientObserverEvents */
14
-
15
- /* Excluded from this release type: OldestClientObserver */
16
-
17
- export { }
@@ -1,17 +0,0 @@
1
- import { AttachState } from '@fluidframework/container-definitions';
2
- import { IEvent } from '@fluidframework/core-interfaces';
3
- import { IEventProvider } from '@fluidframework/core-interfaces';
4
- import { IQuorumClients } from '@fluidframework/protocol-definitions';
5
- import { TypedEventEmitter } from '@fluid-internal/client-utils';
6
-
7
- /* Excluded from this release type: IOldestClientObservable */
8
-
9
- /* Excluded from this release type: IOldestClientObservableEvents */
10
-
11
- /* Excluded from this release type: IOldestClientObserver */
12
-
13
- /* Excluded from this release type: IOldestClientObserverEvents */
14
-
15
- /* Excluded from this release type: OldestClientObserver */
16
-
17
- export { }
@@ -1,111 +0,0 @@
1
- import { AttachState } from '@fluidframework/container-definitions';
2
- import { IEvent } from '@fluidframework/core-interfaces';
3
- import { IEventProvider } from '@fluidframework/core-interfaces';
4
- import { IQuorumClients } from '@fluidframework/protocol-definitions';
5
- import { TypedEventEmitter } from '@fluid-internal/client-utils';
6
-
7
- /**
8
- * This is to make OldestClientObserver work with either a ContainerRuntime or an IFluidDataStoreRuntime
9
- * (both expose the relevant API surface and eventing). However, really this info probably shouldn't live on either,
10
- * since neither is really the source of truth (they are just the only currently-available plumbing options).
11
- * It's information about the connection, so the real source of truth is lower (at the connection layer).
12
- * @alpha
13
- */
14
- export declare interface IOldestClientObservable extends IEventProvider<IOldestClientObservableEvents> {
15
- getQuorum(): IQuorumClients;
16
- attachState: AttachState;
17
- connected: boolean;
18
- clientId: string | undefined;
19
- }
20
-
21
- /**
22
- * Events emitted by {@link IOldestClientObservable}.
23
- * @alpha
24
- */
25
- export declare interface IOldestClientObservableEvents extends IEvent {
26
- (event: "connected", listener: () => void): any;
27
- (event: "disconnected", listener: () => void): any;
28
- }
29
-
30
- /**
31
- * @alpha
32
- */
33
- export declare interface IOldestClientObserver extends IEventProvider<IOldestClientObserverEvents> {
34
- isOldest(): boolean;
35
- }
36
-
37
- /**
38
- * Events emitted by {@link IOldestClientObservable}.
39
- * @alpha
40
- */
41
- export declare interface IOldestClientObserverEvents extends IEvent {
42
- (event: "becameOldest" | "lostOldest", listener: () => void): any;
43
- }
44
-
45
- /**
46
- * The `OldestClientObserver` is a utility inspect if the local client is the oldest amongst connected clients (in
47
- * terms of when they connected) and watch for changes.
48
- *
49
- * It is still experimental and under development. Please do try it out, but expect breaking changes in the future.
50
- *
51
- * @remarks
52
- * ### Creation
53
- *
54
- * The `OldestClientObserver` constructor takes an `IOldestClientObservable`. This is most easily satisfied with
55
- * either an `IContainerRuntime` or an `IFluidDataStoreRuntime`:
56
- *
57
- * ```typescript
58
- * // E.g. from within a BaseContainerRuntimeFactory:
59
- * protected async containerHasInitialized(runtime: IContainerRuntime) {
60
- * const oldestClientObserver = new OldestClientObserver(runtime);
61
- * // ...
62
- * }
63
- * ```
64
- *
65
- * ```typescript
66
- * // From within a DataObject
67
- * protected async hasInitialized() {
68
- * const oldestClientObserver = new OldestClientObserver(this.runtime);
69
- * // ...
70
- * }
71
- * ```
72
- *
73
- * ### Usage
74
- *
75
- * To check if the local client is the oldest, use the `isOldest()` method.
76
- *
77
- * ```typescript
78
- * if (oldestClientObserver.isOldest()) {
79
- * console.log("I'm the oldest");
80
- * } else {
81
- * console.log("Someone else is older");
82
- * }
83
- * ```
84
- *
85
- * ### Eventing
86
- *
87
- * `OldestClientObserver` is an `EventEmitter`, and will emit events when the local client becomes the oldest and when
88
- * it is no longer the oldest.
89
- *
90
- * ```typescript
91
- * oldestClientObserver.on("becameOldest", () => {
92
- * console.log("I'm the oldest now");
93
- * });
94
- *
95
- * oldestClientObserver.on("lostOldest", () => {
96
- * console.log("I'm not the oldest anymore");
97
- * });
98
- * ```
99
- * @alpha
100
- */
101
- export declare class OldestClientObserver extends TypedEventEmitter<IOldestClientObserverEvents> implements IOldestClientObserver {
102
- private readonly observable;
103
- private readonly quorum;
104
- private currentIsOldest;
105
- constructor(observable: IOldestClientObservable);
106
- isOldest(): boolean;
107
- private readonly updateOldest;
108
- private computeIsOldest;
109
- }
110
-
111
- export { }
@@ -1,111 +0,0 @@
1
- import { AttachState } from '@fluidframework/container-definitions';
2
- import { IEvent } from '@fluidframework/core-interfaces';
3
- import { IEventProvider } from '@fluidframework/core-interfaces';
4
- import { IQuorumClients } from '@fluidframework/protocol-definitions';
5
- import { TypedEventEmitter } from '@fluid-internal/client-utils';
6
-
7
- /**
8
- * This is to make OldestClientObserver work with either a ContainerRuntime or an IFluidDataStoreRuntime
9
- * (both expose the relevant API surface and eventing). However, really this info probably shouldn't live on either,
10
- * since neither is really the source of truth (they are just the only currently-available plumbing options).
11
- * It's information about the connection, so the real source of truth is lower (at the connection layer).
12
- * @alpha
13
- */
14
- export declare interface IOldestClientObservable extends IEventProvider<IOldestClientObservableEvents> {
15
- getQuorum(): IQuorumClients;
16
- attachState: AttachState;
17
- connected: boolean;
18
- clientId: string | undefined;
19
- }
20
-
21
- /**
22
- * Events emitted by {@link IOldestClientObservable}.
23
- * @alpha
24
- */
25
- export declare interface IOldestClientObservableEvents extends IEvent {
26
- (event: "connected", listener: () => void): any;
27
- (event: "disconnected", listener: () => void): any;
28
- }
29
-
30
- /**
31
- * @alpha
32
- */
33
- export declare interface IOldestClientObserver extends IEventProvider<IOldestClientObserverEvents> {
34
- isOldest(): boolean;
35
- }
36
-
37
- /**
38
- * Events emitted by {@link IOldestClientObservable}.
39
- * @alpha
40
- */
41
- export declare interface IOldestClientObserverEvents extends IEvent {
42
- (event: "becameOldest" | "lostOldest", listener: () => void): any;
43
- }
44
-
45
- /**
46
- * The `OldestClientObserver` is a utility inspect if the local client is the oldest amongst connected clients (in
47
- * terms of when they connected) and watch for changes.
48
- *
49
- * It is still experimental and under development. Please do try it out, but expect breaking changes in the future.
50
- *
51
- * @remarks
52
- * ### Creation
53
- *
54
- * The `OldestClientObserver` constructor takes an `IOldestClientObservable`. This is most easily satisfied with
55
- * either an `IContainerRuntime` or an `IFluidDataStoreRuntime`:
56
- *
57
- * ```typescript
58
- * // E.g. from within a BaseContainerRuntimeFactory:
59
- * protected async containerHasInitialized(runtime: IContainerRuntime) {
60
- * const oldestClientObserver = new OldestClientObserver(runtime);
61
- * // ...
62
- * }
63
- * ```
64
- *
65
- * ```typescript
66
- * // From within a DataObject
67
- * protected async hasInitialized() {
68
- * const oldestClientObserver = new OldestClientObserver(this.runtime);
69
- * // ...
70
- * }
71
- * ```
72
- *
73
- * ### Usage
74
- *
75
- * To check if the local client is the oldest, use the `isOldest()` method.
76
- *
77
- * ```typescript
78
- * if (oldestClientObserver.isOldest()) {
79
- * console.log("I'm the oldest");
80
- * } else {
81
- * console.log("Someone else is older");
82
- * }
83
- * ```
84
- *
85
- * ### Eventing
86
- *
87
- * `OldestClientObserver` is an `EventEmitter`, and will emit events when the local client becomes the oldest and when
88
- * it is no longer the oldest.
89
- *
90
- * ```typescript
91
- * oldestClientObserver.on("becameOldest", () => {
92
- * console.log("I'm the oldest now");
93
- * });
94
- *
95
- * oldestClientObserver.on("lostOldest", () => {
96
- * console.log("I'm not the oldest anymore");
97
- * });
98
- * ```
99
- * @alpha
100
- */
101
- export declare class OldestClientObserver extends TypedEventEmitter<IOldestClientObserverEvents> implements IOldestClientObserver {
102
- private readonly observable;
103
- private readonly quorum;
104
- private currentIsOldest;
105
- constructor(observable: IOldestClientObservable);
106
- isOldest(): boolean;
107
- private readonly updateOldest;
108
- private computeIsOldest;
109
- }
110
-
111
- export { }
@@ -1,17 +0,0 @@
1
- import { AttachState } from '@fluidframework/container-definitions';
2
- import { IEvent } from '@fluidframework/core-interfaces';
3
- import { IEventProvider } from '@fluidframework/core-interfaces';
4
- import { IQuorumClients } from '@fluidframework/protocol-definitions';
5
- import { TypedEventEmitter } from '@fluid-internal/client-utils';
6
-
7
- /* Excluded from this release type: IOldestClientObservable */
8
-
9
- /* Excluded from this release type: IOldestClientObservableEvents */
10
-
11
- /* Excluded from this release type: IOldestClientObserver */
12
-
13
- /* Excluded from this release type: IOldestClientObserverEvents */
14
-
15
- /* Excluded from this release type: OldestClientObserver */
16
-
17
- export { }
@@ -1,17 +0,0 @@
1
- import { AttachState } from '@fluidframework/container-definitions';
2
- import { IEvent } from '@fluidframework/core-interfaces';
3
- import { IEventProvider } from '@fluidframework/core-interfaces';
4
- import { IQuorumClients } from '@fluidframework/protocol-definitions';
5
- import { TypedEventEmitter } from '@fluid-internal/client-utils';
6
-
7
- /* Excluded from this release type: IOldestClientObservable */
8
-
9
- /* Excluded from this release type: IOldestClientObservableEvents */
10
-
11
- /* Excluded from this release type: IOldestClientObserver */
12
-
13
- /* Excluded from this release type: IOldestClientObserverEvents */
14
-
15
- /* Excluded from this release type: OldestClientObserver */
16
-
17
- export { }
@@ -1,111 +0,0 @@
1
- import { AttachState } from '@fluidframework/container-definitions';
2
- import { IEvent } from '@fluidframework/core-interfaces';
3
- import { IEventProvider } from '@fluidframework/core-interfaces';
4
- import { IQuorumClients } from '@fluidframework/protocol-definitions';
5
- import { TypedEventEmitter } from '@fluid-internal/client-utils';
6
-
7
- /**
8
- * This is to make OldestClientObserver work with either a ContainerRuntime or an IFluidDataStoreRuntime
9
- * (both expose the relevant API surface and eventing). However, really this info probably shouldn't live on either,
10
- * since neither is really the source of truth (they are just the only currently-available plumbing options).
11
- * It's information about the connection, so the real source of truth is lower (at the connection layer).
12
- * @alpha
13
- */
14
- export declare interface IOldestClientObservable extends IEventProvider<IOldestClientObservableEvents> {
15
- getQuorum(): IQuorumClients;
16
- attachState: AttachState;
17
- connected: boolean;
18
- clientId: string | undefined;
19
- }
20
-
21
- /**
22
- * Events emitted by {@link IOldestClientObservable}.
23
- * @alpha
24
- */
25
- export declare interface IOldestClientObservableEvents extends IEvent {
26
- (event: "connected", listener: () => void): any;
27
- (event: "disconnected", listener: () => void): any;
28
- }
29
-
30
- /**
31
- * @alpha
32
- */
33
- export declare interface IOldestClientObserver extends IEventProvider<IOldestClientObserverEvents> {
34
- isOldest(): boolean;
35
- }
36
-
37
- /**
38
- * Events emitted by {@link IOldestClientObservable}.
39
- * @alpha
40
- */
41
- export declare interface IOldestClientObserverEvents extends IEvent {
42
- (event: "becameOldest" | "lostOldest", listener: () => void): any;
43
- }
44
-
45
- /**
46
- * The `OldestClientObserver` is a utility inspect if the local client is the oldest amongst connected clients (in
47
- * terms of when they connected) and watch for changes.
48
- *
49
- * It is still experimental and under development. Please do try it out, but expect breaking changes in the future.
50
- *
51
- * @remarks
52
- * ### Creation
53
- *
54
- * The `OldestClientObserver` constructor takes an `IOldestClientObservable`. This is most easily satisfied with
55
- * either an `IContainerRuntime` or an `IFluidDataStoreRuntime`:
56
- *
57
- * ```typescript
58
- * // E.g. from within a BaseContainerRuntimeFactory:
59
- * protected async containerHasInitialized(runtime: IContainerRuntime) {
60
- * const oldestClientObserver = new OldestClientObserver(runtime);
61
- * // ...
62
- * }
63
- * ```
64
- *
65
- * ```typescript
66
- * // From within a DataObject
67
- * protected async hasInitialized() {
68
- * const oldestClientObserver = new OldestClientObserver(this.runtime);
69
- * // ...
70
- * }
71
- * ```
72
- *
73
- * ### Usage
74
- *
75
- * To check if the local client is the oldest, use the `isOldest()` method.
76
- *
77
- * ```typescript
78
- * if (oldestClientObserver.isOldest()) {
79
- * console.log("I'm the oldest");
80
- * } else {
81
- * console.log("Someone else is older");
82
- * }
83
- * ```
84
- *
85
- * ### Eventing
86
- *
87
- * `OldestClientObserver` is an `EventEmitter`, and will emit events when the local client becomes the oldest and when
88
- * it is no longer the oldest.
89
- *
90
- * ```typescript
91
- * oldestClientObserver.on("becameOldest", () => {
92
- * console.log("I'm the oldest now");
93
- * });
94
- *
95
- * oldestClientObserver.on("lostOldest", () => {
96
- * console.log("I'm not the oldest anymore");
97
- * });
98
- * ```
99
- * @alpha
100
- */
101
- export declare class OldestClientObserver extends TypedEventEmitter<IOldestClientObserverEvents> implements IOldestClientObserver {
102
- private readonly observable;
103
- private readonly quorum;
104
- private currentIsOldest;
105
- constructor(observable: IOldestClientObservable);
106
- isOldest(): boolean;
107
- private readonly updateOldest;
108
- private computeIsOldest;
109
- }
110
-
111
- export { }
File without changes