@fluidframework/presence 2.23.0 → 2.31.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (125) hide show
  1. package/dist/alpha.d.ts +2 -0
  2. package/dist/container-definitions/containerExtensions.d.ts +1 -1
  3. package/dist/container-definitions/containerExtensions.d.ts.map +1 -1
  4. package/dist/container-definitions/containerExtensions.js.map +1 -1
  5. package/dist/exposedInternalTypes.d.ts +1 -1
  6. package/dist/exposedInternalTypes.d.ts.map +1 -1
  7. package/dist/exposedInternalTypes.js.map +1 -1
  8. package/dist/exposedUtilityTypes.d.ts +1 -1
  9. package/dist/exposedUtilityTypes.d.ts.map +1 -1
  10. package/dist/exposedUtilityTypes.js.map +1 -1
  11. package/dist/index.d.ts +2 -0
  12. package/dist/index.d.ts.map +1 -1
  13. package/dist/index.js.map +1 -1
  14. package/dist/latestMapValueManager.d.ts +3 -3
  15. package/dist/latestMapValueManager.d.ts.map +1 -1
  16. package/dist/latestMapValueManager.js.map +1 -1
  17. package/dist/latestValueManager.d.ts +3 -3
  18. package/dist/latestValueManager.d.ts.map +1 -1
  19. package/dist/latestValueManager.js.map +1 -1
  20. package/dist/latestValueTypes.d.ts +2 -2
  21. package/dist/latestValueTypes.d.ts.map +1 -1
  22. package/dist/latestValueTypes.js.map +1 -1
  23. package/dist/notificationsManager.d.ts +2 -2
  24. package/dist/notificationsManager.d.ts.map +1 -1
  25. package/dist/notificationsManager.js.map +1 -1
  26. package/dist/package.json +0 -1
  27. package/dist/presence.d.ts +1 -1
  28. package/dist/presence.js.map +1 -1
  29. package/dist/presenceDatastoreManager.d.ts +4 -2
  30. package/dist/presenceDatastoreManager.d.ts.map +1 -1
  31. package/dist/presenceDatastoreManager.js +26 -8
  32. package/dist/presenceDatastoreManager.js.map +1 -1
  33. package/dist/presenceManager.d.ts.map +1 -1
  34. package/dist/presenceManager.js +1 -1
  35. package/dist/presenceManager.js.map +1 -1
  36. package/dist/types.d.ts +1 -1
  37. package/dist/types.d.ts.map +1 -1
  38. package/dist/types.js.map +1 -1
  39. package/lib/alpha.d.ts +2 -0
  40. package/lib/container-definitions/containerExtensions.d.ts +1 -1
  41. package/lib/container-definitions/containerExtensions.d.ts.map +1 -1
  42. package/lib/container-definitions/containerExtensions.js.map +1 -1
  43. package/lib/exposedInternalTypes.d.ts +1 -1
  44. package/lib/exposedInternalTypes.d.ts.map +1 -1
  45. package/lib/exposedInternalTypes.js.map +1 -1
  46. package/lib/exposedUtilityTypes.d.ts +1 -1
  47. package/lib/exposedUtilityTypes.d.ts.map +1 -1
  48. package/lib/exposedUtilityTypes.js.map +1 -1
  49. package/lib/index.d.ts +2 -0
  50. package/lib/index.d.ts.map +1 -1
  51. package/lib/index.js.map +1 -1
  52. package/lib/latestMapValueManager.d.ts +3 -3
  53. package/lib/latestMapValueManager.d.ts.map +1 -1
  54. package/lib/latestMapValueManager.js.map +1 -1
  55. package/lib/latestValueManager.d.ts +3 -3
  56. package/lib/latestValueManager.d.ts.map +1 -1
  57. package/lib/latestValueManager.js.map +1 -1
  58. package/lib/latestValueTypes.d.ts +2 -2
  59. package/lib/latestValueTypes.d.ts.map +1 -1
  60. package/lib/latestValueTypes.js.map +1 -1
  61. package/lib/notificationsManager.d.ts +2 -2
  62. package/lib/notificationsManager.d.ts.map +1 -1
  63. package/lib/notificationsManager.js.map +1 -1
  64. package/lib/presence.d.ts +1 -1
  65. package/lib/presence.js.map +1 -1
  66. package/lib/presenceDatastoreManager.d.ts +4 -2
  67. package/lib/presenceDatastoreManager.d.ts.map +1 -1
  68. package/lib/presenceDatastoreManager.js +26 -8
  69. package/lib/presenceDatastoreManager.js.map +1 -1
  70. package/lib/presenceManager.d.ts.map +1 -1
  71. package/lib/presenceManager.js +1 -1
  72. package/lib/presenceManager.js.map +1 -1
  73. package/lib/tsdoc-metadata.json +1 -1
  74. package/lib/types.d.ts +1 -1
  75. package/lib/types.d.ts.map +1 -1
  76. package/lib/types.js.map +1 -1
  77. package/package.json +22 -40
  78. package/dist/core-interfaces/exposedUtilityTypes.d.ts +0 -446
  79. package/dist/core-interfaces/exposedUtilityTypes.d.ts.map +0 -1
  80. package/dist/core-interfaces/exposedUtilityTypes.js +0 -11
  81. package/dist/core-interfaces/exposedUtilityTypes.js.map +0 -1
  82. package/dist/core-interfaces/index.d.ts +0 -10
  83. package/dist/core-interfaces/index.d.ts.map +0 -1
  84. package/dist/core-interfaces/index.js +0 -7
  85. package/dist/core-interfaces/index.js.map +0 -1
  86. package/dist/core-interfaces/jsonDeserialized.d.ts +0 -109
  87. package/dist/core-interfaces/jsonDeserialized.d.ts.map +0 -1
  88. package/dist/core-interfaces/jsonDeserialized.js +0 -7
  89. package/dist/core-interfaces/jsonDeserialized.js.map +0 -1
  90. package/dist/core-interfaces/jsonSerializable.d.ts +0 -120
  91. package/dist/core-interfaces/jsonSerializable.d.ts.map +0 -1
  92. package/dist/core-interfaces/jsonSerializable.js +0 -7
  93. package/dist/core-interfaces/jsonSerializable.js.map +0 -1
  94. package/dist/core-interfaces/jsonSerializationErrors.d.ts +0 -31
  95. package/dist/core-interfaces/jsonSerializationErrors.d.ts.map +0 -1
  96. package/dist/core-interfaces/jsonSerializationErrors.js +0 -7
  97. package/dist/core-interfaces/jsonSerializationErrors.js.map +0 -1
  98. package/dist/core-interfaces/jsonType.d.ts +0 -29
  99. package/dist/core-interfaces/jsonType.d.ts.map +0 -1
  100. package/dist/core-interfaces/jsonType.js +0 -7
  101. package/dist/core-interfaces/jsonType.js.map +0 -1
  102. package/lib/core-interfaces/exposedUtilityTypes.d.ts +0 -446
  103. package/lib/core-interfaces/exposedUtilityTypes.d.ts.map +0 -1
  104. package/lib/core-interfaces/exposedUtilityTypes.js +0 -10
  105. package/lib/core-interfaces/exposedUtilityTypes.js.map +0 -1
  106. package/lib/core-interfaces/index.d.ts +0 -10
  107. package/lib/core-interfaces/index.d.ts.map +0 -1
  108. package/lib/core-interfaces/index.js +0 -6
  109. package/lib/core-interfaces/index.js.map +0 -1
  110. package/lib/core-interfaces/jsonDeserialized.d.ts +0 -109
  111. package/lib/core-interfaces/jsonDeserialized.d.ts.map +0 -1
  112. package/lib/core-interfaces/jsonDeserialized.js +0 -6
  113. package/lib/core-interfaces/jsonDeserialized.js.map +0 -1
  114. package/lib/core-interfaces/jsonSerializable.d.ts +0 -120
  115. package/lib/core-interfaces/jsonSerializable.d.ts.map +0 -1
  116. package/lib/core-interfaces/jsonSerializable.js +0 -6
  117. package/lib/core-interfaces/jsonSerializable.js.map +0 -1
  118. package/lib/core-interfaces/jsonSerializationErrors.d.ts +0 -31
  119. package/lib/core-interfaces/jsonSerializationErrors.d.ts.map +0 -1
  120. package/lib/core-interfaces/jsonSerializationErrors.js +0 -6
  121. package/lib/core-interfaces/jsonSerializationErrors.js.map +0 -1
  122. package/lib/core-interfaces/jsonType.d.ts +0 -29
  123. package/lib/core-interfaces/jsonType.d.ts.map +0 -1
  124. package/lib/core-interfaces/jsonType.js +0 -6
  125. package/lib/core-interfaces/jsonType.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"presence.js","sourceRoot":"","sources":["../src/presence.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AA6BH;;;;GAIG;AACU,QAAA,mBAAmB,GAAG;IAClC;;OAEG;IACH,SAAS,EAAE,WAAW;IAEtB;;OAEG;IACH,YAAY,EAAE,cAAc;CACnB,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport type { Listenable } from \"@fluidframework/core-interfaces\";\nimport type { SessionId } from \"@fluidframework/id-compressor\";\n\nimport type { ClientConnectionId } from \"./baseTypes.js\";\nimport type { BroadcastControlSettings } from \"./broadcastControls.js\";\nimport type {\n\tPresenceNotifications,\n\tPresenceNotificationsSchema,\n\tPresenceStates,\n\tPresenceStatesSchema,\n\tPresenceWorkspaceAddress,\n} from \"./types.js\";\n\n/**\n * A Fluid client session identifier.\n *\n * @remarks\n * Each client once connected to a session is given a unique identifier for the\n * duration of the session. If a client disconnects and reconnects, it will\n * retain its identifier. Prefer use of {@link ISessionClient} as a way to\n * identify clients in a session. {@link ISessionClient.sessionId} will provide\n * the session ID.\n *\n * @alpha\n */\nexport type ClientSessionId = SessionId & { readonly ClientSessionId: \"ClientSessionId\" };\n\n/**\n * The connection status of the {@link ISessionClient}.\n *\n * @alpha\n */\nexport const SessionClientStatus = {\n\t/**\n\t * The session client is connected to the Fluid service.\n\t */\n\tConnected: \"Connected\",\n\n\t/**\n\t * The session client is not connected to the Fluid service.\n\t */\n\tDisconnected: \"Disconnected\",\n} as const;\n\n/**\n * Represents the connection status of an {@link ISessionClient}.\n *\n * This type can be either `'Connected'` or `'Disconnected'`, indicating whether\n * the session client is currently connected to the Fluid service.\n *\n * When `'Disconnected'`:\n * - State changes are kept locally and communicated to others upon reconnect.\n * - Notification requests are discarded (silently).\n *\n * @alpha\n */\nexport type SessionClientStatus =\n\t(typeof SessionClientStatus)[keyof typeof SessionClientStatus];\n\n/**\n * A client within a Fluid session (period of container connectivity to service).\n *\n * @remarks\n * Note: This is very preliminary session client representation.\n *\n * `ISessionClient` should be used as key to distinguish between different\n * clients as they join, rejoin, and disconnect from a session. While a\n * client's {@link ClientConnectionId} from {@link ISessionClient.getConnectionStatus}\n * may change over time, `ISessionClient` will be fixed.\n *\n * @privateRemarks\n * As this is evolved, pay attention to how this relates to Audience, Service\n * Audience, and Quorum representations of clients and users.\n *\n * @sealed\n * @alpha\n */\nexport interface ISessionClient<\n\tSpecificSessionClientId extends ClientSessionId = ClientSessionId,\n> {\n\t/**\n\t * The session ID of the client that is stable over all connections.\n\t */\n\treadonly sessionId: SpecificSessionClientId;\n\n\t/**\n\t * Get current client connection ID.\n\t *\n\t * @returns Current client connection ID.\n\t *\n\t * @remarks\n\t * Connection ID will change on reconnect.\n\t *\n\t * If {@link ISessionClient.getConnectionStatus} is {@link (SessionClientStatus:variable).Disconnected}, this will represent the last known connection ID.\n\t */\n\tgetConnectionId(): ClientConnectionId;\n\n\t/**\n\t * Get connection status of session client.\n\t *\n\t * @returns Connection status of session client.\n\t *\n\t */\n\tgetConnectionStatus(): SessionClientStatus;\n}\n\n/**\n * Utility type limiting to a specific session client. (A session client with\n * a specific session ID - not just any session ID.)\n *\n * @internal\n */\nexport type SpecificSessionClient<SpecificSessionClientId extends ClientSessionId> =\n\tstring extends SpecificSessionClientId ? never : ISessionClient<SpecificSessionClientId>;\n\n/**\n * @sealed\n * @alpha\n */\nexport interface PresenceEvents {\n\t/**\n\t * Raised when new client joins session.\n\t *\n\t * @eventProperty\n\t */\n\tattendeeJoined: (attendee: ISessionClient) => void;\n\n\t/**\n\t * Raised when client appears disconnected from session.\n\t *\n\t * @eventProperty\n\t */\n\tattendeeDisconnected: (attendee: ISessionClient) => void;\n\n\t/**\n\t * Raised when a workspace is activated within the session.\n\t *\n\t * \"Activated\" means that a workspace is being used by a client and this\n\t * client is seeing information for the first time.\n\t *\n\t * @remarks\n\t * Local workspaces may be passively acquired/registered when this event\n\t * is raised. For a notifications workspace, that lazy registration must\n\t * be done before the event handler returns to ensure no notifications\n\t * are missed.\n\t */\n\tworkspaceActivated: (\n\t\tworkspaceAddress: PresenceWorkspaceAddress,\n\t\ttype: \"States\" | \"Notifications\" | \"Unknown\",\n\t) => void;\n}\n\n/**\n * Presence represents known clients within a session and their custom states and notifications.\n *\n * @sealed\n * @alpha\n */\nexport interface IPresence {\n\t/**\n\t * Events for Notifications manager.\n\t */\n\treadonly events: Listenable<PresenceEvents>;\n\n\t/**\n\t * Get all attendees in the session.\n\t *\n\t * @remarks\n\t * Attendee states are dynamic and will change as clients join and leave\n\t * the session.\n\t */\n\tgetAttendees(): ReadonlySet<ISessionClient>;\n\n\t/**\n\t * Lookup a specific attendee in the session.\n\t *\n\t * @param clientId - Client connection or session ID\n\t */\n\tgetAttendee(clientId: ClientConnectionId | ClientSessionId): ISessionClient;\n\n\t/**\n\t * Get this client's session client.\n\t *\n\t * @returns This client's session client.\n\t */\n\tgetMyself(): ISessionClient;\n\n\t/**\n\t * Acquires a PresenceStates workspace from store or adds new one.\n\t *\n\t * @param workspaceAddress - Address of the requested PresenceStates Workspace\n\t * @param requestedContent - Requested states for the workspace\n\t * @param controls - Optional settings for default broadcast controls\n\t * @returns A PresenceStates workspace\n\t */\n\tgetStates<StatesSchema extends PresenceStatesSchema>(\n\t\tworkspaceAddress: PresenceWorkspaceAddress,\n\t\trequestedContent: StatesSchema,\n\t\tcontrols?: BroadcastControlSettings,\n\t): PresenceStates<StatesSchema>;\n\n\t/**\n\t * Acquires a Notifications workspace from store or adds new one.\n\t *\n\t * @param workspaceAddress - Address of the requested Notifications Workspace\n\t * @param requestedContent - Requested notifications for the workspace\n\t * @returns A Notifications workspace\n\t */\n\tgetNotifications<NotificationsSchema extends PresenceNotificationsSchema>(\n\t\tnotificationsId: PresenceWorkspaceAddress,\n\t\trequestedContent: NotificationsSchema,\n\t): PresenceNotifications<NotificationsSchema>;\n}\n"]}
1
+ {"version":3,"file":"presence.js","sourceRoot":"","sources":["../src/presence.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AA6BH;;;;GAIG;AACU,QAAA,mBAAmB,GAAG;IAClC;;OAEG;IACH,SAAS,EAAE,WAAW;IAEtB;;OAEG;IACH,YAAY,EAAE,cAAc;CACnB,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport type { Listenable } from \"@fluidframework/core-interfaces\";\nimport type { SessionId } from \"@fluidframework/id-compressor\";\n\nimport type { ClientConnectionId } from \"./baseTypes.js\";\nimport type { BroadcastControlSettings } from \"./broadcastControls.js\";\nimport type {\n\tPresenceNotifications,\n\tPresenceNotificationsSchema,\n\tPresenceStates,\n\tPresenceStatesSchema,\n\tPresenceWorkspaceAddress,\n} from \"./types.js\";\n\n/**\n * A Fluid client session identifier.\n *\n * @remarks\n * Each client once connected to a session is given a unique identifier for the\n * duration of the session. If a client disconnects and reconnects, it will\n * retain its identifier. Prefer use of {@link ISessionClient} as a way to\n * identify clients in a session. {@link ISessionClient.sessionId} will provide\n * the session ID.\n *\n * @alpha\n */\nexport type ClientSessionId = SessionId & { readonly ClientSessionId: \"ClientSessionId\" };\n\n/**\n * The connection status of the {@link ISessionClient}.\n *\n * @alpha\n */\nexport const SessionClientStatus = {\n\t/**\n\t * The session client is connected to the Fluid service.\n\t */\n\tConnected: \"Connected\",\n\n\t/**\n\t * The session client is not connected to the Fluid service.\n\t */\n\tDisconnected: \"Disconnected\",\n} as const;\n\n/**\n * Represents the connection status of an {@link ISessionClient}.\n *\n * This type can be either `'Connected'` or `'Disconnected'`, indicating whether\n * the session client is currently connected to the Fluid service.\n *\n * When `'Disconnected'`:\n * - State changes are kept locally and communicated to others upon reconnect.\n * - Notification requests are discarded (silently).\n *\n * @alpha\n */\nexport type SessionClientStatus =\n\t(typeof SessionClientStatus)[keyof typeof SessionClientStatus];\n\n/**\n * A client within a Fluid session (period of container connectivity to service).\n *\n * @remarks\n * Note: This is very preliminary session client representation.\n *\n * `ISessionClient` should be used as key to distinguish between different\n * clients as they join, rejoin, and disconnect from a session. While a\n * client's {@link ClientConnectionId} from {@link ISessionClient.getConnectionStatus}\n * may change over time, `ISessionClient` will be fixed.\n *\n * @privateRemarks\n * As this is evolved, pay attention to how this relates to Audience, Service\n * Audience, and Quorum representations of clients and users.\n *\n * @sealed\n * @alpha\n */\nexport interface ISessionClient<\n\tSpecificSessionClientId extends ClientSessionId = ClientSessionId,\n> {\n\t/**\n\t * The session ID of the client that is stable over all connections.\n\t */\n\treadonly sessionId: SpecificSessionClientId;\n\n\t/**\n\t * Get current client connection ID.\n\t *\n\t * @returns Current client connection ID.\n\t *\n\t * @remarks\n\t * Connection ID will change on reconnect.\n\t *\n\t * If {@link ISessionClient.getConnectionStatus} is {@link (SessionClientStatus:variable).Disconnected}, this will represent the last known connection ID.\n\t */\n\tgetConnectionId(): ClientConnectionId;\n\n\t/**\n\t * Get connection status of session client.\n\t *\n\t * @returns Connection status of session client.\n\t *\n\t */\n\tgetConnectionStatus(): SessionClientStatus;\n}\n\n/**\n * Utility type limiting to a specific session client. (A session client with\n * a specific session ID - not just any session ID.)\n *\n * @internal\n */\nexport type SpecificSessionClient<SpecificSessionClientId extends ClientSessionId> =\n\tstring extends SpecificSessionClientId ? never : ISessionClient<SpecificSessionClientId>;\n\n/**\n * @sealed\n * @alpha\n */\nexport interface PresenceEvents {\n\t/**\n\t * Raised when new client joins session.\n\t *\n\t * @eventProperty\n\t */\n\tattendeeJoined: (attendee: ISessionClient) => void;\n\n\t/**\n\t * Raised when client appears disconnected from session.\n\t *\n\t * @eventProperty\n\t */\n\tattendeeDisconnected: (attendee: ISessionClient) => void;\n\n\t/**\n\t * Raised when a workspace is activated within the session.\n\t *\n\t * \"Activated\" means that a workspace is being used by a client and this\n\t * client is seeing information for the first time.\n\t *\n\t * @remarks\n\t * Local workspaces may be passively acquired/registered when this event\n\t * is raised. For a notifications workspace, that lazy registration must\n\t * be done before the event handler returns to ensure no notifications\n\t * are missed.\n\t */\n\tworkspaceActivated: (\n\t\tworkspaceAddress: PresenceWorkspaceAddress,\n\t\ttype: \"States\" | \"Notifications\" | \"Unknown\",\n\t) => void;\n}\n\n/**\n * Presence represents known clients within a session and their custom states and notifications.\n *\n * @sealed\n * @alpha\n */\nexport interface IPresence {\n\t/**\n\t * Events for Presence.\n\t */\n\treadonly events: Listenable<PresenceEvents>;\n\n\t/**\n\t * Get all attendees in the session.\n\t *\n\t * @remarks\n\t * Attendee states are dynamic and will change as clients join and leave\n\t * the session.\n\t */\n\tgetAttendees(): ReadonlySet<ISessionClient>;\n\n\t/**\n\t * Lookup a specific attendee in the session.\n\t *\n\t * @param clientId - Client connection or session ID\n\t */\n\tgetAttendee(clientId: ClientConnectionId | ClientSessionId): ISessionClient;\n\n\t/**\n\t * Get this client's session client.\n\t *\n\t * @returns This client's session client.\n\t */\n\tgetMyself(): ISessionClient;\n\n\t/**\n\t * Acquires a PresenceStates workspace from store or adds new one.\n\t *\n\t * @param workspaceAddress - Address of the requested PresenceStates Workspace\n\t * @param requestedContent - Requested states for the workspace\n\t * @param controls - Optional settings for default broadcast controls\n\t * @returns A PresenceStates workspace\n\t */\n\tgetStates<StatesSchema extends PresenceStatesSchema>(\n\t\tworkspaceAddress: PresenceWorkspaceAddress,\n\t\trequestedContent: StatesSchema,\n\t\tcontrols?: BroadcastControlSettings,\n\t): PresenceStates<StatesSchema>;\n\n\t/**\n\t * Acquires a Notifications workspace from store or adds new one.\n\t *\n\t * @param workspaceAddress - Address of the requested Notifications Workspace\n\t * @param requestedContent - Requested notifications for the workspace\n\t * @returns A Notifications workspace\n\t */\n\tgetNotifications<NotificationsSchema extends PresenceNotificationsSchema>(\n\t\tnotificationsId: PresenceWorkspaceAddress,\n\t\trequestedContent: NotificationsSchema,\n\t): PresenceNotifications<NotificationsSchema>;\n}\n"]}
@@ -2,12 +2,13 @@
2
2
  * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
3
3
  * Licensed under the MIT License.
4
4
  */
5
+ import type { IEmitter } from "@fluidframework/core-interfaces/internal";
5
6
  import type { IInboundSignalMessage } from "@fluidframework/runtime-definitions/internal";
6
7
  import type { ITelemetryLoggerExt } from "@fluidframework/telemetry-utils/internal";
7
8
  import type { ClientConnectionId } from "./baseTypes.js";
8
9
  import type { BroadcastControlSettings } from "./broadcastControls.js";
9
10
  import type { IEphemeralRuntime } from "./internalTypes.js";
10
- import type { ClientSessionId, ISessionClient } from "./presence.js";
11
+ import type { ClientSessionId, ISessionClient, PresenceEvents } from "./presence.js";
11
12
  import type { ClientUpdateEntry, PresenceStatesInternal } from "./presenceStates.js";
12
13
  import type { SystemWorkspaceDatastore } from "./systemWorkspace.js";
13
14
  import type { PresenceStates, PresenceStatesSchema, PresenceWorkspaceAddress } from "./types.js";
@@ -64,13 +65,14 @@ export declare class PresenceDatastoreManagerImpl implements PresenceDatastoreMa
64
65
  private readonly runtime;
65
66
  private readonly lookupClient;
66
67
  private readonly logger;
68
+ private readonly events;
67
69
  private readonly datastore;
68
70
  private averageLatency;
69
71
  private returnedMessages;
70
72
  private refreshBroadcastRequested;
71
73
  private readonly timer;
72
74
  private readonly workspaces;
73
- constructor(clientSessionId: ClientSessionId, runtime: IEphemeralRuntime, lookupClient: (clientId: ClientSessionId) => ISessionClient, logger: ITelemetryLoggerExt | undefined, systemWorkspaceDatastore: SystemWorkspaceDatastore, systemWorkspace: PresenceWorkspaceEntry<PresenceStatesSchema>);
75
+ constructor(clientSessionId: ClientSessionId, runtime: IEphemeralRuntime, lookupClient: (clientId: ClientSessionId) => ISessionClient, logger: ITelemetryLoggerExt | undefined, events: IEmitter<Pick<PresenceEvents, "workspaceActivated">>, systemWorkspaceDatastore: SystemWorkspaceDatastore, systemWorkspace: PresenceWorkspaceEntry<PresenceStatesSchema>);
74
76
  joinSession(clientId: ClientConnectionId): void;
75
77
  getWorkspace<TSchema extends PresenceStatesSchema>(internalWorkspaceAddress: InternalWorkspaceAddress, requestedContent: TSchema, controls?: BroadcastControlSettings): PresenceStates<TSchema>;
76
78
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"presenceDatastoreManager.d.ts","sourceRoot":"","sources":["../src/presenceDatastoreManager.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"presenceDatastoreManager.d.ts","sourceRoot":"","sources":["../src/presenceDatastoreManager.ts"],"names":[],"mappings":"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"}
@@ -10,6 +10,10 @@ const internalUtils_js_1 = require("./internalUtils.js");
10
10
  const presenceStates_js_1 = require("./presenceStates.js");
11
11
  const timerManager_js_1 = require("./timerManager.js");
12
12
  const datastoreUpdateMessageType = "Pres:DatastoreUpdate";
13
+ const internalWorkspaceTypes = {
14
+ s: "States",
15
+ n: "Notifications",
16
+ };
13
17
  const joinMessageType = "Pres:ClientJoin";
14
18
  function isPresenceMessage(message) {
15
19
  return message.type.startsWith("Pres:");
@@ -42,11 +46,12 @@ function mergeGeneralDatastoreMessageContent(base, newData) {
42
46
  * Manages singleton datastore for all Presence.
43
47
  */
44
48
  class PresenceDatastoreManagerImpl {
45
- constructor(clientSessionId, runtime, lookupClient, logger, systemWorkspaceDatastore, systemWorkspace) {
49
+ constructor(clientSessionId, runtime, lookupClient, logger, events, systemWorkspaceDatastore, systemWorkspace) {
46
50
  this.clientSessionId = clientSessionId;
47
51
  this.runtime = runtime;
48
52
  this.lookupClient = lookupClient;
49
53
  this.logger = logger;
54
+ this.events = events;
50
55
  this.averageLatency = 0;
51
56
  this.returnedMessages = 0;
52
57
  this.refreshBroadcastRequested = false;
@@ -228,6 +233,24 @@ class PresenceDatastoreManagerImpl {
228
233
  this.refreshBroadcastRequested = false;
229
234
  }
230
235
  }
236
+ // Handle activation of unregistered workspaces before processing updates.
237
+ for (const [workspaceAddress] of Object.entries(message.content.data)) {
238
+ // The first part of OR condition checks if workspace is already registered.
239
+ // The second part checks if the workspace has already been seen before.
240
+ // In either case we can skip emitting 'workspaceActivated' event.
241
+ if (this.workspaces.has(workspaceAddress) || this.datastore[workspaceAddress]) {
242
+ continue;
243
+ }
244
+ // Separate internal type prefix from public workspace address
245
+ const match = workspaceAddress.match(/^([^:]):([^:]+:.+)$/);
246
+ if (match === null) {
247
+ continue;
248
+ }
249
+ const prefix = match[1];
250
+ const publicWorkspaceAddress = match[2];
251
+ const internalWorkspaceType = internalWorkspaceTypes[prefix] ?? "Unknown";
252
+ this.events.emit("workspaceActivated", publicWorkspaceAddress, internalWorkspaceType);
253
+ }
231
254
  const postUpdateActions = [];
232
255
  for (const [workspaceAddress, remoteDatastore] of Object.entries(message.content.data)) {
233
256
  // Direct to the appropriate Presence Workspace, if present.
@@ -238,13 +261,8 @@ class PresenceDatastoreManagerImpl {
238
261
  else {
239
262
  // All broadcast state is kept even if not currently registered, unless a value
240
263
  // notes itself to be ignored.
241
- let workspaceDatastore = this.datastore[workspaceAddress];
242
- if (workspaceDatastore === undefined) {
243
- workspaceDatastore = this.datastore[workspaceAddress] = {};
244
- if (!workspaceAddress.startsWith("system:")) {
245
- // TODO: Emit workspaceActivated event for PresenceEvents
246
- }
247
- }
264
+ // Ensure there is a datastore at this address and get it.
265
+ const workspaceDatastore = (this.datastore[workspaceAddress] ??= {});
248
266
  for (const [key, remoteAllKnownState] of Object.entries(remoteDatastore)) {
249
267
  (0, presenceStates_js_1.mergeUntrackedDatastore)(key, remoteAllKnownState, workspaceDatastore, timeModifier);
250
268
  }
@@ -1 +1 @@
1
- {"version":3,"file":"presenceDatastoreManager.js","sourceRoot":"","sources":["../src/presenceDatastoreManager.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { assert } from \"@fluidframework/core-utils/internal\";\nimport type { IInboundSignalMessage } from \"@fluidframework/runtime-definitions/internal\";\nimport type { ITelemetryLoggerExt } from \"@fluidframework/telemetry-utils/internal\";\n\nimport type { ClientConnectionId } from \"./baseTypes.js\";\nimport type { BroadcastControlSettings } from \"./broadcastControls.js\";\nimport type { IEphemeralRuntime, PostUpdateAction } from \"./internalTypes.js\";\nimport { objectEntries } from \"./internalUtils.js\";\nimport type { ClientSessionId, ISessionClient } from \"./presence.js\";\nimport type {\n\tClientUpdateEntry,\n\tRuntimeLocalUpdateOptions,\n\tPresenceStatesInternal,\n\tValueElementMap,\n} from \"./presenceStates.js\";\nimport {\n\tcreatePresenceStates,\n\tmergeUntrackedDatastore,\n\tmergeValueDirectory,\n} from \"./presenceStates.js\";\nimport type { SystemWorkspaceDatastore } from \"./systemWorkspace.js\";\nimport { TimerManager } from \"./timerManager.js\";\nimport type {\n\tPresenceStates,\n\tPresenceStatesSchema,\n\tPresenceWorkspaceAddress,\n} from \"./types.js\";\n\nimport type { IExtensionMessage } from \"@fluidframework/presence/internal/container-definitions/internal\";\n\ninterface PresenceWorkspaceEntry<TSchema extends PresenceStatesSchema> {\n\tpublic: PresenceStates<TSchema>;\n\tinternal: PresenceStatesInternal;\n}\n\ninterface SystemDatastore {\n\t\"system:presence\": SystemWorkspaceDatastore;\n}\n\ntype InternalWorkspaceAddress = `${\"s\" | \"n\"}:${PresenceWorkspaceAddress}`;\n\ntype PresenceDatastore = SystemDatastore & {\n\t[WorkspaceAddress: string]: ValueElementMap<PresenceStatesSchema>;\n};\n\ninterface GeneralDatastoreMessageContent {\n\t[WorkspaceAddress: string]: {\n\t\t[StateValueManagerKey: string]: {\n\t\t\t[ClientSessionId: ClientSessionId]: ClientUpdateEntry;\n\t\t};\n\t};\n}\n\ntype DatastoreMessageContent = SystemDatastore & GeneralDatastoreMessageContent;\n\nconst datastoreUpdateMessageType = \"Pres:DatastoreUpdate\";\ninterface DatastoreUpdateMessage extends IInboundSignalMessage {\n\ttype: typeof datastoreUpdateMessageType;\n\tcontent: {\n\t\tsendTimestamp: number;\n\t\tavgLatency: number;\n\t\tisComplete?: true;\n\t\tdata: DatastoreMessageContent;\n\t};\n}\n\nconst joinMessageType = \"Pres:ClientJoin\";\ninterface ClientJoinMessage extends IInboundSignalMessage {\n\ttype: typeof joinMessageType;\n\tcontent: {\n\t\tupdateProviders: ClientConnectionId[];\n\t\tsendTimestamp: number;\n\t\tavgLatency: number;\n\t\tdata: DatastoreMessageContent;\n\t};\n}\n\nfunction isPresenceMessage(\n\tmessage: IInboundSignalMessage,\n): message is DatastoreUpdateMessage | ClientJoinMessage {\n\treturn message.type.startsWith(\"Pres:\");\n}\n\n/**\n * @internal\n */\nexport interface PresenceDatastoreManager {\n\tjoinSession(clientId: ClientConnectionId): void;\n\tgetWorkspace<TSchema extends PresenceStatesSchema>(\n\t\tinternalWorkspaceAddress: InternalWorkspaceAddress,\n\t\trequestedContent: TSchema,\n\t\tcontrols?: BroadcastControlSettings,\n\t): PresenceStates<TSchema>;\n\tprocessSignal(message: IExtensionMessage, local: boolean): void;\n}\n\nfunction mergeGeneralDatastoreMessageContent(\n\tbase: GeneralDatastoreMessageContent | undefined,\n\tnewData: GeneralDatastoreMessageContent,\n): GeneralDatastoreMessageContent {\n\t// This function-local \"datastore\" will hold the merged message data.\n\tconst queueDatastore = base ?? {};\n\n\t// Merge the current data with the existing data, if any exists.\n\t// Iterate over the current message data; individual items are workspaces.\n\tfor (const [workspaceName, workspaceData] of Object.entries(newData)) {\n\t\t// Initialize the merged data as the queued datastore entry for the workspace.\n\t\t// Since the key might not exist, create an empty object in that case. It will\n\t\t// be set explicitly after the loop.\n\t\tconst mergedData = queueDatastore[workspaceName] ?? {};\n\n\t\t// Iterate over each value manager and its data, merging it as needed.\n\t\tfor (const [valueManagerKey, valueManagerValue] of objectEntries(workspaceData)) {\n\t\t\tfor (const [clientSessionId, value] of objectEntries(valueManagerValue)) {\n\t\t\t\tconst mergeObject = (mergedData[valueManagerKey] ??= {});\n\t\t\t\tconst oldData = mergeObject[clientSessionId];\n\t\t\t\tmergeObject[clientSessionId] = mergeValueDirectory(\n\t\t\t\t\toldData,\n\t\t\t\t\tvalue,\n\t\t\t\t\t0, // local values do not need a time shift\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\t// Store the merged data in the function-local queue workspace. The whole contents of this\n\t\t// datastore will be sent as the message data.\n\t\tqueueDatastore[workspaceName] = mergedData;\n\t}\n\treturn queueDatastore;\n}\n\n/**\n * Manages singleton datastore for all Presence.\n */\nexport class PresenceDatastoreManagerImpl implements PresenceDatastoreManager {\n\tprivate readonly datastore: PresenceDatastore;\n\tprivate averageLatency = 0;\n\tprivate returnedMessages = 0;\n\tprivate refreshBroadcastRequested = false;\n\tprivate readonly timer = new TimerManager();\n\tprivate readonly workspaces = new Map<\n\t\tstring,\n\t\tPresenceWorkspaceEntry<PresenceStatesSchema>\n\t>();\n\n\tpublic constructor(\n\t\tprivate readonly clientSessionId: ClientSessionId,\n\t\tprivate readonly runtime: IEphemeralRuntime,\n\t\tprivate readonly lookupClient: (clientId: ClientSessionId) => ISessionClient,\n\t\tprivate readonly logger: ITelemetryLoggerExt | undefined,\n\t\tsystemWorkspaceDatastore: SystemWorkspaceDatastore,\n\t\tsystemWorkspace: PresenceWorkspaceEntry<PresenceStatesSchema>,\n\t) {\n\t\t// eslint-disable-next-line @typescript-eslint/consistent-type-assertions\n\t\tthis.datastore = { \"system:presence\": systemWorkspaceDatastore } as PresenceDatastore;\n\t\tthis.workspaces.set(\"system:presence\", systemWorkspace);\n\t}\n\n\tpublic joinSession(clientId: ClientConnectionId): void {\n\t\t// Broadcast join message to all clients\n\t\tconst updateProviders = [...this.runtime.getQuorum().getMembers().keys()].filter(\n\t\t\t(quorumClientId) => quorumClientId !== clientId,\n\t\t);\n\t\t// Limit to three providers to prevent flooding the network.\n\t\t// If none respond, others present will (should) after a delay.\n\t\tif (updateProviders.length > 3) {\n\t\t\tupdateProviders.length = 3;\n\t\t}\n\t\tthis.runtime.submitSignal(joinMessageType, {\n\t\t\tsendTimestamp: Date.now(),\n\t\t\tavgLatency: this.averageLatency,\n\t\t\tdata: this.datastore,\n\t\t\tupdateProviders,\n\t\t} satisfies ClientJoinMessage[\"content\"]);\n\t}\n\n\tpublic getWorkspace<TSchema extends PresenceStatesSchema>(\n\t\tinternalWorkspaceAddress: InternalWorkspaceAddress,\n\t\trequestedContent: TSchema,\n\t\tcontrols?: BroadcastControlSettings,\n\t): PresenceStates<TSchema> {\n\t\tconst existing = this.workspaces.get(internalWorkspaceAddress);\n\t\tif (existing) {\n\t\t\treturn existing.internal.ensureContent(requestedContent, controls);\n\t\t}\n\n\t\tlet workspaceDatastore: ValueElementMap<PresenceStatesSchema> | undefined =\n\t\t\tthis.datastore[internalWorkspaceAddress];\n\t\tif (workspaceDatastore === undefined) {\n\t\t\tworkspaceDatastore = this.datastore[internalWorkspaceAddress] = {};\n\t\t}\n\n\t\tconst localUpdate = (\n\t\t\tstates: { [key: string]: ClientUpdateEntry },\n\t\t\toptions: RuntimeLocalUpdateOptions,\n\t\t): void => {\n\t\t\t// Check for connectivity before sending updates.\n\t\t\tif (!this.runtime.connected) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst updates: GeneralDatastoreMessageContent[InternalWorkspaceAddress] = {};\n\t\t\tfor (const [key, value] of Object.entries(states)) {\n\t\t\t\tupdates[key] = { [this.clientSessionId]: value };\n\t\t\t}\n\n\t\t\tthis.enqueueMessage(\n\t\t\t\t{\n\t\t\t\t\t[internalWorkspaceAddress]: updates,\n\t\t\t\t},\n\t\t\t\toptions,\n\t\t\t);\n\t\t};\n\n\t\tconst entry = createPresenceStates(\n\t\t\t{\n\t\t\t\tclientSessionId: this.clientSessionId,\n\t\t\t\tlookupClient: this.lookupClient,\n\t\t\t\tlocalUpdate,\n\t\t\t},\n\t\t\tworkspaceDatastore,\n\t\t\trequestedContent,\n\t\t\tcontrols,\n\t\t);\n\n\t\tthis.workspaces.set(internalWorkspaceAddress, entry);\n\t\treturn entry.public;\n\t}\n\n\t/**\n\t * The combined contents of all queued updates. Will be undefined when no messages are queued.\n\t */\n\tprivate queuedData: GeneralDatastoreMessageContent | undefined;\n\n\t/**\n\t * Enqueues a new message to be sent. The message may be queued or may be sent immediately depending on the state of\n\t * the send timer, other messages in the queue, the configured allowed latency, etc.\n\t */\n\tprivate enqueueMessage(\n\t\tdata: GeneralDatastoreMessageContent,\n\t\toptions: RuntimeLocalUpdateOptions,\n\t): void {\n\t\t// Merging the message with any queued messages effectively queues the message.\n\t\t// It is OK to queue all incoming messages as long as when we send, we send the queued data.\n\t\tthis.queuedData = mergeGeneralDatastoreMessageContent(this.queuedData, data);\n\n\t\tconst { allowableUpdateLatencyMs } = options;\n\t\tconst now = Date.now();\n\t\tconst thisMessageDeadline = now + allowableUpdateLatencyMs;\n\n\t\tif (\n\t\t\t// If the timer has not expired, we can short-circuit because the timer will fire\n\t\t\t// and cover this update. In other words, queuing this will be fast enough to\n\t\t\t// meet its deadline, because a timer is already scheduled to fire before its deadline.\n\t\t\t!this.timer.hasExpired() &&\n\t\t\t// If the deadline for this message is later than the overall send deadline, then\n\t\t\t// we can exit early since a timer will take care of sending it.\n\t\t\tthisMessageDeadline >= this.timer.expireTime\n\t\t) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Either we need to send this message immediately, or we need to schedule a timer\n\t\t// to fire at the send deadline that will take care of it.\n\n\t\t// Note that timeoutInMs === allowableUpdateLatency, but the calculation is done this way for clarity.\n\t\tconst timeoutInMs = thisMessageDeadline - now;\n\t\tconst scheduleForLater = timeoutInMs > 0;\n\n\t\tif (scheduleForLater) {\n\t\t\t// Schedule the queued messages to be sent at the updateDeadline\n\t\t\tthis.timer.setTimeout(this.sendQueuedMessage.bind(this), timeoutInMs);\n\t\t} else {\n\t\t\tthis.sendQueuedMessage();\n\t\t}\n\t}\n\n\t/**\n\t * Send any queued signal immediately. Does nothing if no message is queued.\n\t */\n\tprivate sendQueuedMessage(): void {\n\t\tthis.timer.clearTimeout();\n\n\t\tif (this.queuedData === undefined) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Check for connectivity before sending updates.\n\t\tif (!this.runtime.connected) {\n\t\t\t// Clear the queued data since we're disconnected. We don't want messages\n\t\t\t// to queue infinitely while disconnected.\n\t\t\tthis.queuedData = undefined;\n\t\t\treturn;\n\t\t}\n\n\t\tconst clientConnectionId = this.runtime.clientId;\n\t\tassert(clientConnectionId !== undefined, 0xa59 /* Client connected without clientId */);\n\t\tconst currentClientToSessionValueState =\n\t\t\t// When connected, `clientToSessionId` must always have current connection entry.\n\t\t\t// eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n\t\t\tthis.datastore[\"system:presence\"].clientToSessionId[clientConnectionId]!;\n\n\t\tconst newMessage = {\n\t\t\tsendTimestamp: Date.now(),\n\t\t\tavgLatency: this.averageLatency,\n\t\t\t// isComplete: false,\n\t\t\tdata: {\n\t\t\t\t// Always send current connection mapping for some resiliency against\n\t\t\t\t// lost signals. This ensures that client session id found in `updates`\n\t\t\t\t// (which is this client's client session id) is always represented in\n\t\t\t\t// system workspace of recipient clients.\n\t\t\t\t\"system:presence\": {\n\t\t\t\t\tclientToSessionId: {\n\t\t\t\t\t\t[clientConnectionId]: { ...currentClientToSessionValueState },\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\t...this.queuedData,\n\t\t\t},\n\t\t} satisfies DatastoreUpdateMessage[\"content\"];\n\t\tthis.queuedData = undefined;\n\t\tthis.runtime.submitSignal(datastoreUpdateMessageType, newMessage);\n\t}\n\n\tprivate broadcastAllKnownState(): void {\n\t\tthis.runtime.submitSignal(datastoreUpdateMessageType, {\n\t\t\tsendTimestamp: Date.now(),\n\t\t\tavgLatency: this.averageLatency,\n\t\t\tisComplete: true,\n\t\t\tdata: this.datastore,\n\t\t} satisfies DatastoreUpdateMessage[\"content\"]);\n\t\tthis.refreshBroadcastRequested = false;\n\t}\n\n\tpublic processSignal(\n\t\t// Note: IInboundSignalMessage is used here in place of IExtensionMessage\n\t\t// as IExtensionMessage's strictly JSON `content` creates type compatibility\n\t\t// issues with `ClientSessionId` keys and really unknown value content.\n\t\t// IExtensionMessage is a subset of IInboundSignalMessage so this is safe.\n\t\t// Change types of DatastoreUpdateMessage | ClientJoinMessage to\n\t\t// IExtensionMessage<> derivatives to see the issues.\n\t\tmessage: IInboundSignalMessage | DatastoreUpdateMessage | ClientJoinMessage,\n\t\tlocal: boolean,\n\t): void {\n\t\tconst received = Date.now();\n\t\tassert(message.clientId !== null, 0xa3a /* Map received signal without clientId */);\n\t\tif (!isPresenceMessage(message)) {\n\t\t\treturn;\n\t\t}\n\t\tif (local) {\n\t\t\tconst deliveryDelta = received - message.content.sendTimestamp;\n\t\t\t// Limit returnedMessages count to 256 such that newest message\n\t\t\t// always contributes at least 1/256th to the average. Older\n\t\t\t// messages have more weight, but that diminishes as new messages\n\t\t\t// contribute.\n\t\t\tthis.returnedMessages = Math.min(this.returnedMessages + 1, 256);\n\t\t\tthis.averageLatency =\n\t\t\t\t(this.averageLatency * (this.returnedMessages - 1) + deliveryDelta) /\n\t\t\t\tthis.returnedMessages;\n\t\t\treturn;\n\t\t}\n\n\t\tconst timeModifier =\n\t\t\treceived -\n\t\t\t(this.averageLatency + message.content.avgLatency + message.content.sendTimestamp);\n\n\t\tif (message.type === joinMessageType) {\n\t\t\t// It is possible for some signals to come in while client is not connected due\n\t\t\t// to how work is scheduled. If we are not connected, we can't respond to the\n\t\t\t// join request. We will make our own Join request once we are connected.\n\t\t\tif (this.runtime.connected) {\n\t\t\t\tthis.prepareJoinResponse(message.content.updateProviders, message.clientId);\n\t\t\t}\n\t\t\t// It is okay to continue processing the contained updates even if we are not\n\t\t\t// connected.\n\t\t} else {\n\t\t\tassert(message.type === datastoreUpdateMessageType, 0xa3b /* Unexpected message type */);\n\t\t\tif (message.content.isComplete) {\n\t\t\t\tthis.refreshBroadcastRequested = false;\n\t\t\t}\n\t\t}\n\t\tconst postUpdateActions: PostUpdateAction[] = [];\n\t\tfor (const [workspaceAddress, remoteDatastore] of Object.entries(message.content.data)) {\n\t\t\t// Direct to the appropriate Presence Workspace, if present.\n\t\t\tconst workspace = this.workspaces.get(workspaceAddress);\n\t\t\tif (workspace) {\n\t\t\t\tpostUpdateActions.push(\n\t\t\t\t\t...workspace.internal.processUpdate(\n\t\t\t\t\t\treceived,\n\t\t\t\t\t\ttimeModifier,\n\t\t\t\t\t\tremoteDatastore,\n\t\t\t\t\t\tmessage.clientId,\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\t// All broadcast state is kept even if not currently registered, unless a value\n\t\t\t\t// notes itself to be ignored.\n\t\t\t\tlet workspaceDatastore = this.datastore[workspaceAddress];\n\t\t\t\tif (workspaceDatastore === undefined) {\n\t\t\t\t\tworkspaceDatastore = this.datastore[workspaceAddress] = {};\n\t\t\t\t\tif (!workspaceAddress.startsWith(\"system:\")) {\n\t\t\t\t\t\t// TODO: Emit workspaceActivated event for PresenceEvents\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tfor (const [key, remoteAllKnownState] of Object.entries(remoteDatastore)) {\n\t\t\t\t\tmergeUntrackedDatastore(key, remoteAllKnownState, workspaceDatastore, timeModifier);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tfor (const action of postUpdateActions) {\n\t\t\taction();\n\t\t}\n\t}\n\n\t/**\n\t * Handles responding to another client joining the session.\n\t *\n\t * @param updateProviders - list of client connection id's that requestor selected\n\t * to provide response\n\t * @param requestor - `requestor` is only used in telemetry. While it is the requestor's\n\t * client connection id, that is not most important. It is important that this is a\n\t * unique shared id across all clients that might respond as we want to monitor the\n\t * response patterns. The convenience of being client connection id will allow\n\t * correlation with other telemetry where it is often called just `clientId`.\n\t */\n\tprivate prepareJoinResponse(\n\t\tupdateProviders: ClientConnectionId[],\n\t\trequestor: ClientConnectionId,\n\t): void {\n\t\tthis.refreshBroadcastRequested = true;\n\t\t// We must be connected to receive this message, so clientId should be defined.\n\t\t// If it isn't then, not really a problem; just won't be in provider or quorum list.\n\t\t// eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n\t\tconst clientId = this.runtime.clientId!;\n\t\t// const requestor = message.clientId;\n\t\tif (updateProviders.includes(clientId)) {\n\t\t\t// Send all current state to the new client\n\t\t\tthis.broadcastAllKnownState();\n\t\t\tthis.logger?.sendTelemetryEvent({\n\t\t\t\teventName: \"JoinResponse\",\n\t\t\t\tdetails: {\n\t\t\t\t\ttype: \"broadcastAll\",\n\t\t\t\t\trequestor,\n\t\t\t\t\trole: \"primary\",\n\t\t\t\t},\n\t\t\t});\n\t\t} else {\n\t\t\t// Schedule a broadcast to the new client after a delay only to send if\n\t\t\t// another broadcast hasn't been seen in the meantime. The delay is based\n\t\t\t// on the position in the quorum list. It doesn't have to be a stable\n\t\t\t// list across all clients. We need something to provide suggested order\n\t\t\t// to prevent a flood of broadcasts.\n\t\t\tlet relativeResponseOrder;\n\t\t\tconst quorumMembers = this.runtime.getQuorum().getMembers();\n\t\t\tconst self = quorumMembers.get(clientId);\n\t\t\tif (self) {\n\t\t\t\t// Compute order quorum join order (indicated by sequenceNumber)\n\t\t\t\trelativeResponseOrder = 0;\n\t\t\t\tfor (const { sequenceNumber } of quorumMembers.values()) {\n\t\t\t\t\tif (sequenceNumber < self.sequenceNumber) {\n\t\t\t\t\t\trelativeResponseOrder++;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// Order past quorum members + arbitrary additional offset up to 10\n\t\t\t\trelativeResponseOrder = quorumMembers.size + Math.random() * 10;\n\t\t\t}\n\t\t\t// These numbers have been chosen arbitrarily to start with.\n\t\t\t// 20 is minimum wait time, 20 is the additional wait time per provider\n\t\t\t// given an chance before us with named providers given more time.\n\t\t\tconst waitTime = 20 + 20 * (3 * updateProviders.length + relativeResponseOrder);\n\t\t\tsetTimeout(() => {\n\t\t\t\t// Make sure a broadcast is still needed and we are currently connected.\n\t\t\t\t// If not connected, nothing we can do.\n\t\t\t\tif (this.refreshBroadcastRequested && this.runtime.connected) {\n\t\t\t\t\tthis.broadcastAllKnownState();\n\t\t\t\t\tthis.logger?.sendTelemetryEvent({\n\t\t\t\t\t\teventName: \"JoinResponse\",\n\t\t\t\t\t\tdetails: {\n\t\t\t\t\t\t\ttype: \"broadcastAll\",\n\t\t\t\t\t\t\trequestor,\n\t\t\t\t\t\t\trole: \"secondary\",\n\t\t\t\t\t\t\torder: relativeResponseOrder,\n\t\t\t\t\t\t},\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}, waitTime);\n\t\t}\n\t}\n}\n"]}
1
+ {"version":3,"file":"presenceDatastoreManager.js","sourceRoot":"","sources":["../src/presenceDatastoreManager.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport type { IEmitter } from \"@fluidframework/core-interfaces/internal\";\nimport { assert } from \"@fluidframework/core-utils/internal\";\nimport type { IInboundSignalMessage } from \"@fluidframework/runtime-definitions/internal\";\nimport type { ITelemetryLoggerExt } from \"@fluidframework/telemetry-utils/internal\";\n\nimport type { ClientConnectionId } from \"./baseTypes.js\";\nimport type { BroadcastControlSettings } from \"./broadcastControls.js\";\nimport type { IEphemeralRuntime, PostUpdateAction } from \"./internalTypes.js\";\nimport { objectEntries } from \"./internalUtils.js\";\nimport type { ClientSessionId, ISessionClient, PresenceEvents } from \"./presence.js\";\nimport type {\n\tClientUpdateEntry,\n\tRuntimeLocalUpdateOptions,\n\tPresenceStatesInternal,\n\tValueElementMap,\n} from \"./presenceStates.js\";\nimport {\n\tcreatePresenceStates,\n\tmergeUntrackedDatastore,\n\tmergeValueDirectory,\n} from \"./presenceStates.js\";\nimport type { SystemWorkspaceDatastore } from \"./systemWorkspace.js\";\nimport { TimerManager } from \"./timerManager.js\";\nimport type {\n\tPresenceStates,\n\tPresenceStatesSchema,\n\tPresenceWorkspaceAddress,\n} from \"./types.js\";\n\nimport type { IExtensionMessage } from \"@fluidframework/presence/internal/container-definitions/internal\";\n\ninterface PresenceWorkspaceEntry<TSchema extends PresenceStatesSchema> {\n\tpublic: PresenceStates<TSchema>;\n\tinternal: PresenceStatesInternal;\n}\n\ninterface SystemDatastore {\n\t\"system:presence\": SystemWorkspaceDatastore;\n}\n\ntype InternalWorkspaceAddress = `${\"s\" | \"n\"}:${PresenceWorkspaceAddress}`;\n\ntype PresenceDatastore = SystemDatastore & {\n\t[WorkspaceAddress: string]: ValueElementMap<PresenceStatesSchema>;\n};\n\ninterface GeneralDatastoreMessageContent {\n\t[WorkspaceAddress: string]: {\n\t\t[StateValueManagerKey: string]: {\n\t\t\t[ClientSessionId: ClientSessionId]: ClientUpdateEntry;\n\t\t};\n\t};\n}\n\ntype DatastoreMessageContent = SystemDatastore & GeneralDatastoreMessageContent;\n\nconst datastoreUpdateMessageType = \"Pres:DatastoreUpdate\";\n\nconst internalWorkspaceTypes: Readonly<Record<string, \"States\" | \"Notifications\">> = {\n\ts: \"States\",\n\tn: \"Notifications\",\n} as const;\n\ninterface DatastoreUpdateMessage extends IInboundSignalMessage {\n\ttype: typeof datastoreUpdateMessageType;\n\tcontent: {\n\t\tsendTimestamp: number;\n\t\tavgLatency: number;\n\t\tisComplete?: true;\n\t\tdata: DatastoreMessageContent;\n\t};\n}\n\nconst joinMessageType = \"Pres:ClientJoin\";\ninterface ClientJoinMessage extends IInboundSignalMessage {\n\ttype: typeof joinMessageType;\n\tcontent: {\n\t\tupdateProviders: ClientConnectionId[];\n\t\tsendTimestamp: number;\n\t\tavgLatency: number;\n\t\tdata: DatastoreMessageContent;\n\t};\n}\n\nfunction isPresenceMessage(\n\tmessage: IInboundSignalMessage,\n): message is DatastoreUpdateMessage | ClientJoinMessage {\n\treturn message.type.startsWith(\"Pres:\");\n}\n/**\n * @internal\n */\nexport interface PresenceDatastoreManager {\n\tjoinSession(clientId: ClientConnectionId): void;\n\tgetWorkspace<TSchema extends PresenceStatesSchema>(\n\t\tinternalWorkspaceAddress: InternalWorkspaceAddress,\n\t\trequestedContent: TSchema,\n\t\tcontrols?: BroadcastControlSettings,\n\t): PresenceStates<TSchema>;\n\tprocessSignal(message: IExtensionMessage, local: boolean): void;\n}\n\nfunction mergeGeneralDatastoreMessageContent(\n\tbase: GeneralDatastoreMessageContent | undefined,\n\tnewData: GeneralDatastoreMessageContent,\n): GeneralDatastoreMessageContent {\n\t// This function-local \"datastore\" will hold the merged message data.\n\tconst queueDatastore = base ?? {};\n\n\t// Merge the current data with the existing data, if any exists.\n\t// Iterate over the current message data; individual items are workspaces.\n\tfor (const [workspaceName, workspaceData] of Object.entries(newData)) {\n\t\t// Initialize the merged data as the queued datastore entry for the workspace.\n\t\t// Since the key might not exist, create an empty object in that case. It will\n\t\t// be set explicitly after the loop.\n\t\tconst mergedData = queueDatastore[workspaceName] ?? {};\n\n\t\t// Iterate over each value manager and its data, merging it as needed.\n\t\tfor (const [valueManagerKey, valueManagerValue] of objectEntries(workspaceData)) {\n\t\t\tfor (const [clientSessionId, value] of objectEntries(valueManagerValue)) {\n\t\t\t\tconst mergeObject = (mergedData[valueManagerKey] ??= {});\n\t\t\t\tconst oldData = mergeObject[clientSessionId];\n\t\t\t\tmergeObject[clientSessionId] = mergeValueDirectory(\n\t\t\t\t\toldData,\n\t\t\t\t\tvalue,\n\t\t\t\t\t0, // local values do not need a time shift\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\t// Store the merged data in the function-local queue workspace. The whole contents of this\n\t\t// datastore will be sent as the message data.\n\t\tqueueDatastore[workspaceName] = mergedData;\n\t}\n\treturn queueDatastore;\n}\n\n/**\n * Manages singleton datastore for all Presence.\n */\nexport class PresenceDatastoreManagerImpl implements PresenceDatastoreManager {\n\tprivate readonly datastore: PresenceDatastore;\n\tprivate averageLatency = 0;\n\tprivate returnedMessages = 0;\n\tprivate refreshBroadcastRequested = false;\n\tprivate readonly timer = new TimerManager();\n\tprivate readonly workspaces = new Map<\n\t\tstring,\n\t\tPresenceWorkspaceEntry<PresenceStatesSchema>\n\t>();\n\n\tpublic constructor(\n\t\tprivate readonly clientSessionId: ClientSessionId,\n\t\tprivate readonly runtime: IEphemeralRuntime,\n\t\tprivate readonly lookupClient: (clientId: ClientSessionId) => ISessionClient,\n\t\tprivate readonly logger: ITelemetryLoggerExt | undefined,\n\t\tprivate readonly events: IEmitter<Pick<PresenceEvents, \"workspaceActivated\">>,\n\t\tsystemWorkspaceDatastore: SystemWorkspaceDatastore,\n\t\tsystemWorkspace: PresenceWorkspaceEntry<PresenceStatesSchema>,\n\t) {\n\t\t// eslint-disable-next-line @typescript-eslint/consistent-type-assertions\n\t\tthis.datastore = { \"system:presence\": systemWorkspaceDatastore } as PresenceDatastore;\n\t\tthis.workspaces.set(\"system:presence\", systemWorkspace);\n\t}\n\n\tpublic joinSession(clientId: ClientConnectionId): void {\n\t\t// Broadcast join message to all clients\n\t\tconst updateProviders = [...this.runtime.getQuorum().getMembers().keys()].filter(\n\t\t\t(quorumClientId) => quorumClientId !== clientId,\n\t\t);\n\t\t// Limit to three providers to prevent flooding the network.\n\t\t// If none respond, others present will (should) after a delay.\n\t\tif (updateProviders.length > 3) {\n\t\t\tupdateProviders.length = 3;\n\t\t}\n\t\tthis.runtime.submitSignal(joinMessageType, {\n\t\t\tsendTimestamp: Date.now(),\n\t\t\tavgLatency: this.averageLatency,\n\t\t\tdata: this.datastore,\n\t\t\tupdateProviders,\n\t\t} satisfies ClientJoinMessage[\"content\"]);\n\t}\n\n\tpublic getWorkspace<TSchema extends PresenceStatesSchema>(\n\t\tinternalWorkspaceAddress: InternalWorkspaceAddress,\n\t\trequestedContent: TSchema,\n\t\tcontrols?: BroadcastControlSettings,\n\t): PresenceStates<TSchema> {\n\t\tconst existing = this.workspaces.get(internalWorkspaceAddress);\n\t\tif (existing) {\n\t\t\treturn existing.internal.ensureContent(requestedContent, controls);\n\t\t}\n\n\t\tlet workspaceDatastore: ValueElementMap<PresenceStatesSchema> | undefined =\n\t\t\tthis.datastore[internalWorkspaceAddress];\n\t\tif (workspaceDatastore === undefined) {\n\t\t\tworkspaceDatastore = this.datastore[internalWorkspaceAddress] = {};\n\t\t}\n\n\t\tconst localUpdate = (\n\t\t\tstates: { [key: string]: ClientUpdateEntry },\n\t\t\toptions: RuntimeLocalUpdateOptions,\n\t\t): void => {\n\t\t\t// Check for connectivity before sending updates.\n\t\t\tif (!this.runtime.connected) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst updates: GeneralDatastoreMessageContent[InternalWorkspaceAddress] = {};\n\t\t\tfor (const [key, value] of Object.entries(states)) {\n\t\t\t\tupdates[key] = { [this.clientSessionId]: value };\n\t\t\t}\n\n\t\t\tthis.enqueueMessage(\n\t\t\t\t{\n\t\t\t\t\t[internalWorkspaceAddress]: updates,\n\t\t\t\t},\n\t\t\t\toptions,\n\t\t\t);\n\t\t};\n\n\t\tconst entry = createPresenceStates(\n\t\t\t{\n\t\t\t\tclientSessionId: this.clientSessionId,\n\t\t\t\tlookupClient: this.lookupClient,\n\t\t\t\tlocalUpdate,\n\t\t\t},\n\t\t\tworkspaceDatastore,\n\t\t\trequestedContent,\n\t\t\tcontrols,\n\t\t);\n\n\t\tthis.workspaces.set(internalWorkspaceAddress, entry);\n\t\treturn entry.public;\n\t}\n\n\t/**\n\t * The combined contents of all queued updates. Will be undefined when no messages are queued.\n\t */\n\tprivate queuedData: GeneralDatastoreMessageContent | undefined;\n\n\t/**\n\t * Enqueues a new message to be sent. The message may be queued or may be sent immediately depending on the state of\n\t * the send timer, other messages in the queue, the configured allowed latency, etc.\n\t */\n\tprivate enqueueMessage(\n\t\tdata: GeneralDatastoreMessageContent,\n\t\toptions: RuntimeLocalUpdateOptions,\n\t): void {\n\t\t// Merging the message with any queued messages effectively queues the message.\n\t\t// It is OK to queue all incoming messages as long as when we send, we send the queued data.\n\t\tthis.queuedData = mergeGeneralDatastoreMessageContent(this.queuedData, data);\n\n\t\tconst { allowableUpdateLatencyMs } = options;\n\t\tconst now = Date.now();\n\t\tconst thisMessageDeadline = now + allowableUpdateLatencyMs;\n\n\t\tif (\n\t\t\t// If the timer has not expired, we can short-circuit because the timer will fire\n\t\t\t// and cover this update. In other words, queuing this will be fast enough to\n\t\t\t// meet its deadline, because a timer is already scheduled to fire before its deadline.\n\t\t\t!this.timer.hasExpired() &&\n\t\t\t// If the deadline for this message is later than the overall send deadline, then\n\t\t\t// we can exit early since a timer will take care of sending it.\n\t\t\tthisMessageDeadline >= this.timer.expireTime\n\t\t) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Either we need to send this message immediately, or we need to schedule a timer\n\t\t// to fire at the send deadline that will take care of it.\n\n\t\t// Note that timeoutInMs === allowableUpdateLatency, but the calculation is done this way for clarity.\n\t\tconst timeoutInMs = thisMessageDeadline - now;\n\t\tconst scheduleForLater = timeoutInMs > 0;\n\n\t\tif (scheduleForLater) {\n\t\t\t// Schedule the queued messages to be sent at the updateDeadline\n\t\t\tthis.timer.setTimeout(this.sendQueuedMessage.bind(this), timeoutInMs);\n\t\t} else {\n\t\t\tthis.sendQueuedMessage();\n\t\t}\n\t}\n\n\t/**\n\t * Send any queued signal immediately. Does nothing if no message is queued.\n\t */\n\tprivate sendQueuedMessage(): void {\n\t\tthis.timer.clearTimeout();\n\n\t\tif (this.queuedData === undefined) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Check for connectivity before sending updates.\n\t\tif (!this.runtime.connected) {\n\t\t\t// Clear the queued data since we're disconnected. We don't want messages\n\t\t\t// to queue infinitely while disconnected.\n\t\t\tthis.queuedData = undefined;\n\t\t\treturn;\n\t\t}\n\n\t\tconst clientConnectionId = this.runtime.clientId;\n\t\tassert(clientConnectionId !== undefined, 0xa59 /* Client connected without clientId */);\n\t\tconst currentClientToSessionValueState =\n\t\t\t// When connected, `clientToSessionId` must always have current connection entry.\n\t\t\t// eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n\t\t\tthis.datastore[\"system:presence\"].clientToSessionId[clientConnectionId]!;\n\n\t\tconst newMessage = {\n\t\t\tsendTimestamp: Date.now(),\n\t\t\tavgLatency: this.averageLatency,\n\t\t\t// isComplete: false,\n\t\t\tdata: {\n\t\t\t\t// Always send current connection mapping for some resiliency against\n\t\t\t\t// lost signals. This ensures that client session id found in `updates`\n\t\t\t\t// (which is this client's client session id) is always represented in\n\t\t\t\t// system workspace of recipient clients.\n\t\t\t\t\"system:presence\": {\n\t\t\t\t\tclientToSessionId: {\n\t\t\t\t\t\t[clientConnectionId]: { ...currentClientToSessionValueState },\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\t...this.queuedData,\n\t\t\t},\n\t\t} satisfies DatastoreUpdateMessage[\"content\"];\n\t\tthis.queuedData = undefined;\n\t\tthis.runtime.submitSignal(datastoreUpdateMessageType, newMessage);\n\t}\n\n\tprivate broadcastAllKnownState(): void {\n\t\tthis.runtime.submitSignal(datastoreUpdateMessageType, {\n\t\t\tsendTimestamp: Date.now(),\n\t\t\tavgLatency: this.averageLatency,\n\t\t\tisComplete: true,\n\t\t\tdata: this.datastore,\n\t\t} satisfies DatastoreUpdateMessage[\"content\"]);\n\t\tthis.refreshBroadcastRequested = false;\n\t}\n\n\tpublic processSignal(\n\t\t// Note: IInboundSignalMessage is used here in place of IExtensionMessage\n\t\t// as IExtensionMessage's strictly JSON `content` creates type compatibility\n\t\t// issues with `ClientSessionId` keys and really unknown value content.\n\t\t// IExtensionMessage is a subset of IInboundSignalMessage so this is safe.\n\t\t// Change types of DatastoreUpdateMessage | ClientJoinMessage to\n\t\t// IExtensionMessage<> derivatives to see the issues.\n\t\tmessage: IInboundSignalMessage | DatastoreUpdateMessage | ClientJoinMessage,\n\t\tlocal: boolean,\n\t): void {\n\t\tconst received = Date.now();\n\t\tassert(message.clientId !== null, 0xa3a /* Map received signal without clientId */);\n\t\tif (!isPresenceMessage(message)) {\n\t\t\treturn;\n\t\t}\n\t\tif (local) {\n\t\t\tconst deliveryDelta = received - message.content.sendTimestamp;\n\t\t\t// Limit returnedMessages count to 256 such that newest message\n\t\t\t// always contributes at least 1/256th to the average. Older\n\t\t\t// messages have more weight, but that diminishes as new messages\n\t\t\t// contribute.\n\t\t\tthis.returnedMessages = Math.min(this.returnedMessages + 1, 256);\n\t\t\tthis.averageLatency =\n\t\t\t\t(this.averageLatency * (this.returnedMessages - 1) + deliveryDelta) /\n\t\t\t\tthis.returnedMessages;\n\t\t\treturn;\n\t\t}\n\n\t\tconst timeModifier =\n\t\t\treceived -\n\t\t\t(this.averageLatency + message.content.avgLatency + message.content.sendTimestamp);\n\n\t\tif (message.type === joinMessageType) {\n\t\t\t// It is possible for some signals to come in while client is not connected due\n\t\t\t// to how work is scheduled. If we are not connected, we can't respond to the\n\t\t\t// join request. We will make our own Join request once we are connected.\n\t\t\tif (this.runtime.connected) {\n\t\t\t\tthis.prepareJoinResponse(message.content.updateProviders, message.clientId);\n\t\t\t}\n\t\t\t// It is okay to continue processing the contained updates even if we are not\n\t\t\t// connected.\n\t\t} else {\n\t\t\tassert(message.type === datastoreUpdateMessageType, 0xa3b /* Unexpected message type */);\n\t\t\tif (message.content.isComplete) {\n\t\t\t\tthis.refreshBroadcastRequested = false;\n\t\t\t}\n\t\t}\n\n\t\t// Handle activation of unregistered workspaces before processing updates.\n\t\tfor (const [workspaceAddress] of Object.entries(message.content.data)) {\n\t\t\t// The first part of OR condition checks if workspace is already registered.\n\t\t\t// The second part checks if the workspace has already been seen before.\n\t\t\t// In either case we can skip emitting 'workspaceActivated' event.\n\t\t\tif (this.workspaces.has(workspaceAddress) || this.datastore[workspaceAddress]) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// Separate internal type prefix from public workspace address\n\t\t\tconst match = workspaceAddress.match(/^([^:]):([^:]+:.+)$/) as\n\t\t\t\t| null\n\t\t\t\t| [string, string, PresenceWorkspaceAddress];\n\n\t\t\tif (match === null) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tconst prefix = match[1];\n\t\t\tconst publicWorkspaceAddress = match[2];\n\n\t\t\tconst internalWorkspaceType = internalWorkspaceTypes[prefix] ?? \"Unknown\";\n\n\t\t\tthis.events.emit(\"workspaceActivated\", publicWorkspaceAddress, internalWorkspaceType);\n\t\t}\n\n\t\tconst postUpdateActions: PostUpdateAction[] = [];\n\t\tfor (const [workspaceAddress, remoteDatastore] of Object.entries(message.content.data)) {\n\t\t\t// Direct to the appropriate Presence Workspace, if present.\n\t\t\tconst workspace = this.workspaces.get(workspaceAddress);\n\t\t\tif (workspace) {\n\t\t\t\tpostUpdateActions.push(\n\t\t\t\t\t...workspace.internal.processUpdate(\n\t\t\t\t\t\treceived,\n\t\t\t\t\t\ttimeModifier,\n\t\t\t\t\t\tremoteDatastore,\n\t\t\t\t\t\tmessage.clientId,\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\t// All broadcast state is kept even if not currently registered, unless a value\n\t\t\t\t// notes itself to be ignored.\n\n\t\t\t\t// Ensure there is a datastore at this address and get it.\n\t\t\t\tconst workspaceDatastore = (this.datastore[workspaceAddress] ??= {});\n\t\t\t\tfor (const [key, remoteAllKnownState] of Object.entries(remoteDatastore)) {\n\t\t\t\t\tmergeUntrackedDatastore(key, remoteAllKnownState, workspaceDatastore, timeModifier);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tfor (const action of postUpdateActions) {\n\t\t\taction();\n\t\t}\n\t}\n\n\t/**\n\t * Handles responding to another client joining the session.\n\t *\n\t * @param updateProviders - list of client connection id's that requestor selected\n\t * to provide response\n\t * @param requestor - `requestor` is only used in telemetry. While it is the requestor's\n\t * client connection id, that is not most important. It is important that this is a\n\t * unique shared id across all clients that might respond as we want to monitor the\n\t * response patterns. The convenience of being client connection id will allow\n\t * correlation with other telemetry where it is often called just `clientId`.\n\t */\n\tprivate prepareJoinResponse(\n\t\tupdateProviders: ClientConnectionId[],\n\t\trequestor: ClientConnectionId,\n\t): void {\n\t\tthis.refreshBroadcastRequested = true;\n\t\t// We must be connected to receive this message, so clientId should be defined.\n\t\t// If it isn't then, not really a problem; just won't be in provider or quorum list.\n\t\t// eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n\t\tconst clientId = this.runtime.clientId!;\n\t\t// const requestor = message.clientId;\n\t\tif (updateProviders.includes(clientId)) {\n\t\t\t// Send all current state to the new client\n\t\t\tthis.broadcastAllKnownState();\n\t\t\tthis.logger?.sendTelemetryEvent({\n\t\t\t\teventName: \"JoinResponse\",\n\t\t\t\tdetails: {\n\t\t\t\t\ttype: \"broadcastAll\",\n\t\t\t\t\trequestor,\n\t\t\t\t\trole: \"primary\",\n\t\t\t\t},\n\t\t\t});\n\t\t} else {\n\t\t\t// Schedule a broadcast to the new client after a delay only to send if\n\t\t\t// another broadcast hasn't been seen in the meantime. The delay is based\n\t\t\t// on the position in the quorum list. It doesn't have to be a stable\n\t\t\t// list across all clients. We need something to provide suggested order\n\t\t\t// to prevent a flood of broadcasts.\n\t\t\tlet relativeResponseOrder;\n\t\t\tconst quorumMembers = this.runtime.getQuorum().getMembers();\n\t\t\tconst self = quorumMembers.get(clientId);\n\t\t\tif (self) {\n\t\t\t\t// Compute order quorum join order (indicated by sequenceNumber)\n\t\t\t\trelativeResponseOrder = 0;\n\t\t\t\tfor (const { sequenceNumber } of quorumMembers.values()) {\n\t\t\t\t\tif (sequenceNumber < self.sequenceNumber) {\n\t\t\t\t\t\trelativeResponseOrder++;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// Order past quorum members + arbitrary additional offset up to 10\n\t\t\t\trelativeResponseOrder = quorumMembers.size + Math.random() * 10;\n\t\t\t}\n\t\t\t// These numbers have been chosen arbitrarily to start with.\n\t\t\t// 20 is minimum wait time, 20 is the additional wait time per provider\n\t\t\t// given an chance before us with named providers given more time.\n\t\t\tconst waitTime = 20 + 20 * (3 * updateProviders.length + relativeResponseOrder);\n\t\t\tsetTimeout(() => {\n\t\t\t\t// Make sure a broadcast is still needed and we are currently connected.\n\t\t\t\t// If not connected, nothing we can do.\n\t\t\t\tif (this.refreshBroadcastRequested && this.runtime.connected) {\n\t\t\t\t\tthis.broadcastAllKnownState();\n\t\t\t\t\tthis.logger?.sendTelemetryEvent({\n\t\t\t\t\t\teventName: \"JoinResponse\",\n\t\t\t\t\t\tdetails: {\n\t\t\t\t\t\t\ttype: \"broadcastAll\",\n\t\t\t\t\t\t\trequestor,\n\t\t\t\t\t\t\trole: \"secondary\",\n\t\t\t\t\t\t\torder: relativeResponseOrder,\n\t\t\t\t\t\t},\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}, waitTime);\n\t\t}\n\t}\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"presenceManager.d.ts","sourceRoot":"","sources":["../src/presenceManager.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAaH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAC5D,OAAO,KAAK,EACX,eAAe,EACf,SAAS,EAGT,MAAM,eAAe,CAAC;AAWvB,OAAO,KAAK,EACX,mBAAmB,EAEnB,MAAM,kEAAkE,CAAC;AAE1E;;;;GAIG;AACH,MAAM,MAAM,0BAA0B,GAAG,QAAQ,CAChD,IAAI,CAAC,mBAAmB,CAAC,KAAK,CAAC,EAAE,eAAe,CAAC,CACjD,CAAC;AAyIF;;;;GAIG;AACH,wBAAgB,qBAAqB,CACpC,OAAO,EAAE,iBAAiB,EAC1B,eAAe,GAAE,eAAsD,GACrE,SAAS,GAAG,0BAA0B,CAExC"}
1
+ {"version":3,"file":"presenceManager.d.ts","sourceRoot":"","sources":["../src/presenceManager.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAaH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAC5D,OAAO,KAAK,EACX,eAAe,EACf,SAAS,EAGT,MAAM,eAAe,CAAC;AAWvB,OAAO,KAAK,EACX,mBAAmB,EAEnB,MAAM,kEAAkE,CAAC;AAE1E;;;;GAIG;AACH,MAAM,MAAM,0BAA0B,GAAG,QAAQ,CAChD,IAAI,CAAC,mBAAmB,CAAC,KAAK,CAAC,EAAE,eAAe,CAAC,CACjD,CAAC;AA0IF;;;;GAIG;AACH,wBAAgB,qBAAqB,CACpC,OAAO,EAAE,iBAAiB,EAC1B,eAAe,GAAE,eAAsD,GACrE,SAAS,GAAG,0BAA0B,CAExC"}
@@ -89,7 +89,7 @@ function setupSubComponents(clientSessionId, runtime, events, logger) {
89
89
  clientToSessionId: {},
90
90
  };
91
91
  const systemWorkspaceConfig = (0, systemWorkspace_js_1.createSystemWorkspace)(clientSessionId, systemWorkspaceDatastore, events, runtime.getAudience());
92
- const datastoreManager = new presenceDatastoreManager_js_1.PresenceDatastoreManagerImpl(clientSessionId, runtime, systemWorkspaceConfig.workspace.getAttendee.bind(systemWorkspaceConfig.workspace), logger, systemWorkspaceDatastore, systemWorkspaceConfig.statesEntry);
92
+ const datastoreManager = new presenceDatastoreManager_js_1.PresenceDatastoreManagerImpl(clientSessionId, runtime, systemWorkspaceConfig.workspace.getAttendee.bind(systemWorkspaceConfig.workspace), logger, events, systemWorkspaceDatastore, systemWorkspaceConfig.statesEntry);
93
93
  return [datastoreManager, systemWorkspaceConfig.workspace];
94
94
  }
95
95
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"presenceManager.js","sourceRoot":"","sources":["../src/presenceManager.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { createEmitter } from \"@fluid-internal/client-utils\";\nimport type { IEmitter } from \"@fluidframework/core-interfaces/internal\";\nimport { createSessionId } from \"@fluidframework/id-compressor/internal\";\nimport type {\n\tITelemetryLoggerExt,\n\tMonitoringContext,\n} from \"@fluidframework/telemetry-utils/internal\";\nimport { createChildMonitoringContext } from \"@fluidframework/telemetry-utils/internal\";\n\nimport type { ClientConnectionId } from \"./baseTypes.js\";\nimport type { BroadcastControlSettings } from \"./broadcastControls.js\";\nimport type { IEphemeralRuntime } from \"./internalTypes.js\";\nimport type {\n\tClientSessionId,\n\tIPresence,\n\tISessionClient,\n\tPresenceEvents,\n} from \"./presence.js\";\nimport type { PresenceDatastoreManager } from \"./presenceDatastoreManager.js\";\nimport { PresenceDatastoreManagerImpl } from \"./presenceDatastoreManager.js\";\nimport type { SystemWorkspace, SystemWorkspaceDatastore } from \"./systemWorkspace.js\";\nimport { createSystemWorkspace } from \"./systemWorkspace.js\";\nimport type {\n\tPresenceStates,\n\tPresenceWorkspaceAddress,\n\tPresenceStatesSchema,\n} from \"./types.js\";\n\nimport type {\n\tIContainerExtension,\n\tIExtensionMessage,\n} from \"@fluidframework/presence/internal/container-definitions/internal\";\n\n/**\n * Portion of the container extension requirements ({@link IContainerExtension}) that are delegated to presence manager.\n *\n * @internal\n */\nexport type PresenceExtensionInterface = Required<\n\tPick<IContainerExtension<never>, \"processSignal\">\n>;\n\n/**\n * The Presence manager\n */\nclass PresenceManager implements IPresence, PresenceExtensionInterface {\n\tprivate readonly datastoreManager: PresenceDatastoreManager;\n\tprivate readonly systemWorkspace: SystemWorkspace;\n\n\tpublic readonly events = createEmitter<PresenceEvents>();\n\n\tprivate readonly mc: MonitoringContext | undefined = undefined;\n\n\tpublic constructor(runtime: IEphemeralRuntime, clientSessionId: ClientSessionId) {\n\t\tconst logger = runtime.logger;\n\t\tif (logger) {\n\t\t\tthis.mc = createChildMonitoringContext({ logger, namespace: \"Presence\" });\n\t\t\tthis.mc.logger.sendTelemetryEvent({ eventName: \"PresenceInstantiated\" });\n\t\t}\n\n\t\t[this.datastoreManager, this.systemWorkspace] = setupSubComponents(\n\t\t\tclientSessionId,\n\t\t\truntime,\n\t\t\tthis.events,\n\t\t\tthis.mc?.logger,\n\t\t);\n\n\t\truntime.on(\"connected\", this.onConnect.bind(this));\n\n\t\truntime.on(\"disconnected\", () => {\n\t\t\tif (runtime.clientId !== undefined) {\n\t\t\t\tthis.removeClientConnectionId(runtime.clientId);\n\t\t\t}\n\t\t});\n\n\t\truntime.getAudience().on(\"removeMember\", this.removeClientConnectionId.bind(this));\n\n\t\t// Check if already connected at the time of construction.\n\t\t// If constructed during data store load, the runtime may already be connected\n\t\t// and the \"connected\" event will be raised during completion. With construction\n\t\t// delayed we expect that \"connected\" event has passed.\n\t\t// Note: In some manual testing, this does not appear to be enough to\n\t\t// always trigger an initial connect.\n\t\tconst clientId = runtime.clientId;\n\t\tif (clientId !== undefined && runtime.connected) {\n\t\t\tthis.onConnect(clientId);\n\t\t}\n\t}\n\n\tprivate onConnect(clientConnectionId: ClientConnectionId): void {\n\t\tthis.systemWorkspace.onConnectionAdded(clientConnectionId);\n\t\tthis.datastoreManager.joinSession(clientConnectionId);\n\t}\n\n\tprivate removeClientConnectionId(clientConnectionId: ClientConnectionId): void {\n\t\tthis.systemWorkspace.removeClientConnectionId(clientConnectionId);\n\t}\n\n\tpublic getAttendees(): ReadonlySet<ISessionClient> {\n\t\treturn this.systemWorkspace.getAttendees();\n\t}\n\n\tpublic getAttendee(clientId: ClientConnectionId | ClientSessionId): ISessionClient {\n\t\treturn this.systemWorkspace.getAttendee(clientId);\n\t}\n\n\tpublic getMyself(): ISessionClient {\n\t\treturn this.systemWorkspace.getMyself();\n\t}\n\n\tpublic getStates<TSchema extends PresenceStatesSchema>(\n\t\tworkspaceAddress: PresenceWorkspaceAddress,\n\t\trequestedContent: TSchema,\n\t\tcontrols?: BroadcastControlSettings,\n\t): PresenceStates<TSchema> {\n\t\treturn this.datastoreManager.getWorkspace(\n\t\t\t`s:${workspaceAddress}`,\n\t\t\trequestedContent,\n\t\t\tcontrols,\n\t\t);\n\t}\n\n\tpublic getNotifications<TSchema extends PresenceStatesSchema>(\n\t\tworkspaceAddress: PresenceWorkspaceAddress,\n\t\trequestedContent: TSchema,\n\t): PresenceStates<TSchema> {\n\t\treturn this.datastoreManager.getWorkspace(`n:${workspaceAddress}`, requestedContent);\n\t}\n\n\t/**\n\t * Check for Presence message and process it.\n\t *\n\t * @param address - Address of the message\n\t * @param message - Message to be processed\n\t * @param local - Whether the message originated locally (`true`) or remotely (`false`)\n\t */\n\tpublic processSignal(address: string, message: IExtensionMessage, local: boolean): void {\n\t\tthis.datastoreManager.processSignal(message, local);\n\t}\n}\n\n/**\n * Helper for Presence Manager setup\n *\n * Presence Manager is outermost layer of the presence system and has two main\n * sub-components:\n * 1. PresenceDatastoreManager: Manages the unified general data for states and\n * registry for workspaces.\n * 2. SystemWorkspace: Custom internal workspace for system states including\n * attendee management. It is registered with the PresenceDatastoreManager.\n */\nfunction setupSubComponents(\n\tclientSessionId: ClientSessionId,\n\truntime: IEphemeralRuntime,\n\tevents: IEmitter<PresenceEvents>,\n\tlogger: ITelemetryLoggerExt | undefined,\n): [PresenceDatastoreManager, SystemWorkspace] {\n\tconst systemWorkspaceDatastore: SystemWorkspaceDatastore = {\n\t\tclientToSessionId: {},\n\t};\n\tconst systemWorkspaceConfig = createSystemWorkspace(\n\t\tclientSessionId,\n\t\tsystemWorkspaceDatastore,\n\t\tevents,\n\t\truntime.getAudience(),\n\t);\n\tconst datastoreManager = new PresenceDatastoreManagerImpl(\n\t\tclientSessionId,\n\t\truntime,\n\t\tsystemWorkspaceConfig.workspace.getAttendee.bind(systemWorkspaceConfig.workspace),\n\t\tlogger,\n\t\tsystemWorkspaceDatastore,\n\t\tsystemWorkspaceConfig.statesEntry,\n\t);\n\treturn [datastoreManager, systemWorkspaceConfig.workspace];\n}\n\n/**\n * Instantiates Presence Manager\n *\n * @internal\n */\nexport function createPresenceManager(\n\truntime: IEphemeralRuntime,\n\tclientSessionId: ClientSessionId = createSessionId() as ClientSessionId,\n): IPresence & PresenceExtensionInterface {\n\treturn new PresenceManager(runtime, clientSessionId);\n}\n"]}
1
+ {"version":3,"file":"presenceManager.js","sourceRoot":"","sources":["../src/presenceManager.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { createEmitter } from \"@fluid-internal/client-utils\";\nimport type { IEmitter } from \"@fluidframework/core-interfaces/internal\";\nimport { createSessionId } from \"@fluidframework/id-compressor/internal\";\nimport type {\n\tITelemetryLoggerExt,\n\tMonitoringContext,\n} from \"@fluidframework/telemetry-utils/internal\";\nimport { createChildMonitoringContext } from \"@fluidframework/telemetry-utils/internal\";\n\nimport type { ClientConnectionId } from \"./baseTypes.js\";\nimport type { BroadcastControlSettings } from \"./broadcastControls.js\";\nimport type { IEphemeralRuntime } from \"./internalTypes.js\";\nimport type {\n\tClientSessionId,\n\tIPresence,\n\tISessionClient,\n\tPresenceEvents,\n} from \"./presence.js\";\nimport type { PresenceDatastoreManager } from \"./presenceDatastoreManager.js\";\nimport { PresenceDatastoreManagerImpl } from \"./presenceDatastoreManager.js\";\nimport type { SystemWorkspace, SystemWorkspaceDatastore } from \"./systemWorkspace.js\";\nimport { createSystemWorkspace } from \"./systemWorkspace.js\";\nimport type {\n\tPresenceStates,\n\tPresenceWorkspaceAddress,\n\tPresenceStatesSchema,\n} from \"./types.js\";\n\nimport type {\n\tIContainerExtension,\n\tIExtensionMessage,\n} from \"@fluidframework/presence/internal/container-definitions/internal\";\n\n/**\n * Portion of the container extension requirements ({@link IContainerExtension}) that are delegated to presence manager.\n *\n * @internal\n */\nexport type PresenceExtensionInterface = Required<\n\tPick<IContainerExtension<never>, \"processSignal\">\n>;\n\n/**\n * The Presence manager\n */\nclass PresenceManager implements IPresence, PresenceExtensionInterface {\n\tprivate readonly datastoreManager: PresenceDatastoreManager;\n\tprivate readonly systemWorkspace: SystemWorkspace;\n\n\tpublic readonly events = createEmitter<PresenceEvents>();\n\n\tprivate readonly mc: MonitoringContext | undefined = undefined;\n\n\tpublic constructor(runtime: IEphemeralRuntime, clientSessionId: ClientSessionId) {\n\t\tconst logger = runtime.logger;\n\t\tif (logger) {\n\t\t\tthis.mc = createChildMonitoringContext({ logger, namespace: \"Presence\" });\n\t\t\tthis.mc.logger.sendTelemetryEvent({ eventName: \"PresenceInstantiated\" });\n\t\t}\n\n\t\t[this.datastoreManager, this.systemWorkspace] = setupSubComponents(\n\t\t\tclientSessionId,\n\t\t\truntime,\n\t\t\tthis.events,\n\t\t\tthis.mc?.logger,\n\t\t);\n\n\t\truntime.on(\"connected\", this.onConnect.bind(this));\n\n\t\truntime.on(\"disconnected\", () => {\n\t\t\tif (runtime.clientId !== undefined) {\n\t\t\t\tthis.removeClientConnectionId(runtime.clientId);\n\t\t\t}\n\t\t});\n\n\t\truntime.getAudience().on(\"removeMember\", this.removeClientConnectionId.bind(this));\n\n\t\t// Check if already connected at the time of construction.\n\t\t// If constructed during data store load, the runtime may already be connected\n\t\t// and the \"connected\" event will be raised during completion. With construction\n\t\t// delayed we expect that \"connected\" event has passed.\n\t\t// Note: In some manual testing, this does not appear to be enough to\n\t\t// always trigger an initial connect.\n\t\tconst clientId = runtime.clientId;\n\t\tif (clientId !== undefined && runtime.connected) {\n\t\t\tthis.onConnect(clientId);\n\t\t}\n\t}\n\n\tprivate onConnect(clientConnectionId: ClientConnectionId): void {\n\t\tthis.systemWorkspace.onConnectionAdded(clientConnectionId);\n\t\tthis.datastoreManager.joinSession(clientConnectionId);\n\t}\n\n\tprivate removeClientConnectionId(clientConnectionId: ClientConnectionId): void {\n\t\tthis.systemWorkspace.removeClientConnectionId(clientConnectionId);\n\t}\n\n\tpublic getAttendees(): ReadonlySet<ISessionClient> {\n\t\treturn this.systemWorkspace.getAttendees();\n\t}\n\n\tpublic getAttendee(clientId: ClientConnectionId | ClientSessionId): ISessionClient {\n\t\treturn this.systemWorkspace.getAttendee(clientId);\n\t}\n\n\tpublic getMyself(): ISessionClient {\n\t\treturn this.systemWorkspace.getMyself();\n\t}\n\n\tpublic getStates<TSchema extends PresenceStatesSchema>(\n\t\tworkspaceAddress: PresenceWorkspaceAddress,\n\t\trequestedContent: TSchema,\n\t\tcontrols?: BroadcastControlSettings,\n\t): PresenceStates<TSchema> {\n\t\treturn this.datastoreManager.getWorkspace(\n\t\t\t`s:${workspaceAddress}`,\n\t\t\trequestedContent,\n\t\t\tcontrols,\n\t\t);\n\t}\n\n\tpublic getNotifications<TSchema extends PresenceStatesSchema>(\n\t\tworkspaceAddress: PresenceWorkspaceAddress,\n\t\trequestedContent: TSchema,\n\t): PresenceStates<TSchema> {\n\t\treturn this.datastoreManager.getWorkspace(`n:${workspaceAddress}`, requestedContent);\n\t}\n\n\t/**\n\t * Check for Presence message and process it.\n\t *\n\t * @param address - Address of the message\n\t * @param message - Message to be processed\n\t * @param local - Whether the message originated locally (`true`) or remotely (`false`)\n\t */\n\tpublic processSignal(address: string, message: IExtensionMessage, local: boolean): void {\n\t\tthis.datastoreManager.processSignal(message, local);\n\t}\n}\n\n/**\n * Helper for Presence Manager setup\n *\n * Presence Manager is outermost layer of the presence system and has two main\n * sub-components:\n * 1. PresenceDatastoreManager: Manages the unified general data for states and\n * registry for workspaces.\n * 2. SystemWorkspace: Custom internal workspace for system states including\n * attendee management. It is registered with the PresenceDatastoreManager.\n */\nfunction setupSubComponents(\n\tclientSessionId: ClientSessionId,\n\truntime: IEphemeralRuntime,\n\tevents: IEmitter<PresenceEvents>,\n\tlogger: ITelemetryLoggerExt | undefined,\n): [PresenceDatastoreManager, SystemWorkspace] {\n\tconst systemWorkspaceDatastore: SystemWorkspaceDatastore = {\n\t\tclientToSessionId: {},\n\t};\n\tconst systemWorkspaceConfig = createSystemWorkspace(\n\t\tclientSessionId,\n\t\tsystemWorkspaceDatastore,\n\t\tevents,\n\t\truntime.getAudience(),\n\t);\n\tconst datastoreManager = new PresenceDatastoreManagerImpl(\n\t\tclientSessionId,\n\t\truntime,\n\t\tsystemWorkspaceConfig.workspace.getAttendee.bind(systemWorkspaceConfig.workspace),\n\t\tlogger,\n\t\tevents,\n\t\tsystemWorkspaceDatastore,\n\t\tsystemWorkspaceConfig.statesEntry,\n\t);\n\treturn [datastoreManager, systemWorkspaceConfig.workspace];\n}\n\n/**\n * Instantiates Presence Manager\n *\n * @internal\n */\nexport function createPresenceManager(\n\truntime: IEphemeralRuntime,\n\tclientSessionId: ClientSessionId = createSessionId() as ClientSessionId,\n): IPresence & PresenceExtensionInterface {\n\treturn new PresenceManager(runtime, clientSessionId);\n}\n"]}
package/dist/types.d.ts CHANGED
@@ -3,8 +3,8 @@
3
3
  * Licensed under the MIT License.
4
4
  */
5
5
  import type { BroadcastControls } from "./broadcastControls.js";
6
+ import type { InternalTypes } from "./exposedInternalTypes.js";
6
7
  import type { NotificationsManager } from "./notificationsManager.js";
7
- import type { InternalTypes } from "@fluidframework/presence/internal/exposedInternalTypes";
8
8
  /**
9
9
  * Unique address within a session.
10
10
  *
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
package/dist/types.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":";AAAA;;;GAGG;;AAmKH,mCAAmC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport type { BroadcastControls } from \"./broadcastControls.js\";\nimport type { NotificationsManager } from \"./notificationsManager.js\";\n\nimport type { InternalTypes } from \"@fluidframework/presence/internal/exposedInternalTypes\";\n\n/**\n * Unique address within a session.\n *\n * @remarks\n * A string known to all clients working with a certain Workspace and unique\n * among Workspaces. Recommend using specifying concatenation of: type of\n * unique identifier, `:` (required), and unique identifier.\n *\n * @example Examples\n * ```typescript\n * \"guid:g0fl001d-1415-5000-c00l-g0fa54g0b1g1\"\n * \"address:object0/sub-object2:pointers\"\n * ```\n *\n * @alpha\n */\nexport type PresenceWorkspaceAddress = `${string}:${string}`;\n\n/**\n * Single entry in {@link PresenceStatesSchema} or {@link PresenceNotificationsSchema}.\n *\n * @alpha\n */\nexport type PresenceWorkspaceEntry<\n\tTKey extends string,\n\tTValue extends InternalTypes.ValueDirectoryOrState<unknown>,\n\tTManager = unknown,\n> = InternalTypes.ManagerFactory<TKey, TValue, TManager>;\n\n// #region PresenceStates\n\n/**\n * Schema for a {@link PresenceStates} workspace.\n *\n * Keys of schema are the keys of the {@link PresenceStates} providing access to `Value Manager`s.\n *\n * @alpha\n */\nexport interface PresenceStatesSchema {\n\t[key: string]: PresenceWorkspaceEntry<typeof key, InternalTypes.ValueDirectoryOrState<any>>;\n}\n\n/**\n * Map of `Value Manager`s registered with {@link PresenceStates}.\n *\n * @sealed\n * @alpha\n */\nexport type PresenceStatesEntries<TSchema extends PresenceStatesSchema> = {\n\t/**\n\t * Registered `Value Manager`s\n\t */\n\treadonly [Key in keyof TSchema]: ReturnType<\n\t\tTSchema[Key]\n\t>[\"manager\"] extends InternalTypes.StateValue<infer TManager>\n\t\t? TManager\n\t\t: never;\n};\n\n/**\n * `PresenceStates` maintains a registry of `Value Manager`s that all share and provide access to\n * presence state values across client members in a session.\n *\n * `Value Manager`s offer variations on how to manage states, but all share same principle that\n * each client's state is independent and may only be updated by originating client.\n *\n * @sealed\n * @alpha\n */\nexport interface PresenceStates<\n\tTSchema extends PresenceStatesSchema,\n\tTManagerConstraints = unknown,\n> {\n\t/**\n\t * Registers a new `Value Manager` with the {@link PresenceStates}.\n\t * @param key - new unique key for the `Value Manager` within the workspace\n\t * @param manager - factory for creating a `Value Manager`\n\t */\n\tadd<\n\t\tTKey extends string,\n\t\tTValue extends InternalTypes.ValueDirectoryOrState<any>,\n\t\tTManager extends TManagerConstraints,\n\t>(\n\t\tkey: TKey,\n\t\tmanager: InternalTypes.ManagerFactory<TKey, TValue, TManager>,\n\t): asserts this is PresenceStates<\n\t\tTSchema & Record<TKey, InternalTypes.ManagerFactory<TKey, TValue, TManager>>,\n\t\tTManagerConstraints\n\t>;\n\n\t/**\n\t * Registry of `Value Manager`s.\n\t */\n\treadonly props: PresenceStatesEntries<TSchema>;\n\n\t/**\n\t * Default controls for management of broadcast updates.\n\t */\n\treadonly controls: BroadcastControls;\n}\n\n// #endregion PresenceStates\n\n// #region PresenceNotifications\n\n/**\n * Schema for a {@link PresenceNotifications} workspace.\n *\n * Keys of schema are the keys of the {@link PresenceNotifications} providing access to {@link NotificationsManager}s.\n *\n * @alpha\n */\nexport interface PresenceNotificationsSchema {\n\t[key: string]: InternalTypes.ManagerFactory<\n\t\ttypeof key,\n\t\tInternalTypes.ValueRequiredState<InternalTypes.NotificationType>,\n\t\tNotificationsManager<any>\n\t>;\n}\n\n/**\n * `PresenceNotifications` maintains a registry of {@link NotificationsManager}s\n * that facilitate messages across client members in a session.\n *\n * @privateRemarks\n * This should be kept mostly in sync with {@link PresenceStates}. Notably the\n * return type of `add` is limited here and the `controls` property is omitted.\n * The `PresenceStatesImpl` class implements `PresenceStates` and therefore\n * `PresenceNotifications`, so long as this is proper subset.\n *\n * @sealed\n * @alpha\n */\nexport interface PresenceNotifications<TSchema extends PresenceNotificationsSchema> {\n\t/**\n\t * Registers a new `Value Manager` with the {@link PresenceNotifications}.\n\t * @param key - new unique key for the `Value Manager` within the workspace\n\t * @param manager - factory for creating a `Value Manager`\n\t */\n\tadd<\n\t\tTKey extends string,\n\t\tTValue extends InternalTypes.ValueDirectoryOrState<any>,\n\t\tTManager extends NotificationsManager<any>,\n\t>(\n\t\tkey: TKey,\n\t\tmanager: InternalTypes.ManagerFactory<TKey, TValue, TManager>,\n\t): asserts this is PresenceNotifications<\n\t\tTSchema & Record<TKey, InternalTypes.ManagerFactory<TKey, TValue, TManager>>\n\t>;\n\n\t/**\n\t * Registry of `Value Manager`s.\n\t */\n\treadonly props: PresenceStatesEntries<TSchema>;\n}\n\n// #endregion PresenceNotifications\n"]}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":";AAAA;;;GAGG;;AAkKH,mCAAmC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport type { BroadcastControls } from \"./broadcastControls.js\";\nimport type { InternalTypes } from \"./exposedInternalTypes.js\";\nimport type { NotificationsManager } from \"./notificationsManager.js\";\n\n/**\n * Unique address within a session.\n *\n * @remarks\n * A string known to all clients working with a certain Workspace and unique\n * among Workspaces. Recommend using specifying concatenation of: type of\n * unique identifier, `:` (required), and unique identifier.\n *\n * @example Examples\n * ```typescript\n * \"guid:g0fl001d-1415-5000-c00l-g0fa54g0b1g1\"\n * \"address:object0/sub-object2:pointers\"\n * ```\n *\n * @alpha\n */\nexport type PresenceWorkspaceAddress = `${string}:${string}`;\n\n/**\n * Single entry in {@link PresenceStatesSchema} or {@link PresenceNotificationsSchema}.\n *\n * @alpha\n */\nexport type PresenceWorkspaceEntry<\n\tTKey extends string,\n\tTValue extends InternalTypes.ValueDirectoryOrState<unknown>,\n\tTManager = unknown,\n> = InternalTypes.ManagerFactory<TKey, TValue, TManager>;\n\n// #region PresenceStates\n\n/**\n * Schema for a {@link PresenceStates} workspace.\n *\n * Keys of schema are the keys of the {@link PresenceStates} providing access to `Value Manager`s.\n *\n * @alpha\n */\nexport interface PresenceStatesSchema {\n\t[key: string]: PresenceWorkspaceEntry<typeof key, InternalTypes.ValueDirectoryOrState<any>>;\n}\n\n/**\n * Map of `Value Manager`s registered with {@link PresenceStates}.\n *\n * @sealed\n * @alpha\n */\nexport type PresenceStatesEntries<TSchema extends PresenceStatesSchema> = {\n\t/**\n\t * Registered `Value Manager`s\n\t */\n\treadonly [Key in keyof TSchema]: ReturnType<\n\t\tTSchema[Key]\n\t>[\"manager\"] extends InternalTypes.StateValue<infer TManager>\n\t\t? TManager\n\t\t: never;\n};\n\n/**\n * `PresenceStates` maintains a registry of `Value Manager`s that all share and provide access to\n * presence state values across client members in a session.\n *\n * `Value Manager`s offer variations on how to manage states, but all share same principle that\n * each client's state is independent and may only be updated by originating client.\n *\n * @sealed\n * @alpha\n */\nexport interface PresenceStates<\n\tTSchema extends PresenceStatesSchema,\n\tTManagerConstraints = unknown,\n> {\n\t/**\n\t * Registers a new `Value Manager` with the {@link PresenceStates}.\n\t * @param key - new unique key for the `Value Manager` within the workspace\n\t * @param manager - factory for creating a `Value Manager`\n\t */\n\tadd<\n\t\tTKey extends string,\n\t\tTValue extends InternalTypes.ValueDirectoryOrState<any>,\n\t\tTManager extends TManagerConstraints,\n\t>(\n\t\tkey: TKey,\n\t\tmanager: InternalTypes.ManagerFactory<TKey, TValue, TManager>,\n\t): asserts this is PresenceStates<\n\t\tTSchema & Record<TKey, InternalTypes.ManagerFactory<TKey, TValue, TManager>>,\n\t\tTManagerConstraints\n\t>;\n\n\t/**\n\t * Registry of `Value Manager`s.\n\t */\n\treadonly props: PresenceStatesEntries<TSchema>;\n\n\t/**\n\t * Default controls for management of broadcast updates.\n\t */\n\treadonly controls: BroadcastControls;\n}\n\n// #endregion PresenceStates\n\n// #region PresenceNotifications\n\n/**\n * Schema for a {@link PresenceNotifications} workspace.\n *\n * Keys of schema are the keys of the {@link PresenceNotifications} providing access to {@link NotificationsManager}s.\n *\n * @alpha\n */\nexport interface PresenceNotificationsSchema {\n\t[key: string]: InternalTypes.ManagerFactory<\n\t\ttypeof key,\n\t\tInternalTypes.ValueRequiredState<InternalTypes.NotificationType>,\n\t\tNotificationsManager<any>\n\t>;\n}\n\n/**\n * `PresenceNotifications` maintains a registry of {@link NotificationsManager}s\n * that facilitate messages across client members in a session.\n *\n * @privateRemarks\n * This should be kept mostly in sync with {@link PresenceStates}. Notably the\n * return type of `add` is limited here and the `controls` property is omitted.\n * The `PresenceStatesImpl` class implements `PresenceStates` and therefore\n * `PresenceNotifications`, so long as this is proper subset.\n *\n * @sealed\n * @alpha\n */\nexport interface PresenceNotifications<TSchema extends PresenceNotificationsSchema> {\n\t/**\n\t * Registers a new `Value Manager` with the {@link PresenceNotifications}.\n\t * @param key - new unique key for the `Value Manager` within the workspace\n\t * @param manager - factory for creating a `Value Manager`\n\t */\n\tadd<\n\t\tTKey extends string,\n\t\tTValue extends InternalTypes.ValueDirectoryOrState<any>,\n\t\tTManager extends NotificationsManager<any>,\n\t>(\n\t\tkey: TKey,\n\t\tmanager: InternalTypes.ManagerFactory<TKey, TValue, TManager>,\n\t): asserts this is PresenceNotifications<\n\t\tTSchema & Record<TKey, InternalTypes.ManagerFactory<TKey, TValue, TManager>>\n\t>;\n\n\t/**\n\t * Registry of `Value Manager`s.\n\t */\n\treadonly props: PresenceStatesEntries<TSchema>;\n}\n\n// #endregion PresenceNotifications\n"]}
package/lib/alpha.d.ts CHANGED
@@ -26,6 +26,8 @@ export {
26
26
  ExperimentalPresenceManager,
27
27
  IPresence,
28
28
  ISessionClient,
29
+ InternalTypes,
30
+ InternalUtilityTypes,
29
31
  Latest,
30
32
  LatestMap,
31
33
  LatestMapItemRemovedClientData,
@@ -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
- import type { JsonDeserialized, JsonSerializable } from "@fluidframework/presence/internal/core-interfaces";
5
+ import type { JsonDeserialized, JsonSerializable } from "@fluidframework/core-interfaces/internal";
6
6
  /**
7
7
  * While connected, the id of a client within a session.
8
8
  *
@@ -1 +1 @@
1
- {"version":3,"file":"containerExtensions.d.ts","sourceRoot":"","sources":["../../src/container-definitions/containerExtensions.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EACX,gBAAgB,EAChB,gBAAgB,EAChB,MAAM,mDAAmD,CAAC;AAE3D;;;;GAIG;AACH,MAAM,MAAM,kBAAkB,GAAG,MAAM,CAAC;AAExC;;;;;GAKG;AACH,MAAM,WAAW,iBAAiB,CAAC,KAAK,SAAS,MAAM,GAAG,MAAM,EAAE,QAAQ,GAAG,OAAO;IACnF;;OAEG;IACH,IAAI,EAAE,KAAK,CAAC;IAEZ;;OAEG;IACH,OAAO,EAAE,gBAAgB,CAAC,QAAQ,CAAC,CAAC;IAEpC;;;OAGG;IAEH,QAAQ,EAAE,kBAAkB,GAAG,IAAI,CAAC;IAEpC;;;OAGG;IACH,cAAc,CAAC,EAAE,kBAAkB,CAAC;CACpC;AAED;;;;GAIG;AACH,MAAM,WAAW,mBAAmB,CAAC,QAAQ,SAAS,OAAO,EAAE;IAC9D;;;;OAIG;IACH,YAAY,CAAC,GAAG,OAAO,EAAE,QAAQ,GAAG,IAAI,CAAC;IAEzC;;;;;;OAMG;IACH,aAAa,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,iBAAiB,EAAE,KAAK,EAAE,OAAO,GAAG,IAAI,CAAC;CACjF;AAED;;;;;;GAMG;AACH,MAAM,WAAW,iBAAiB;IACjC;;OAEG;IACH,IAAI,QAAQ,IAAI,kBAAkB,GAAG,SAAS,CAAC;IAE/C;;;;;;;;;OASG;IACH,qBAAqB,CAAC,CAAC,EACtB,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,gBAAgB,CAAC,CAAC,CAAC,EAC5B,cAAc,CAAC,EAAE,kBAAkB,GACjC,IAAI,CAAC;CACR;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,MAAM,yBAAyB,CAAC,CAAC,EAAE,QAAQ,SAAS,OAAO,EAAE,IAAI,KACtE,OAAO,EAAE,iBAAiB,EAC1B,GAAG,OAAO,EAAE,QAAQ,KAChB;IAAE,QAAQ,CAAC,SAAS,EAAE,CAAC,CAAC;IAAC,QAAQ,CAAC,SAAS,EAAE,mBAAmB,CAAC,QAAQ,CAAC,CAAA;CAAE,CAAC;AAElF;;;;;;;;;;;;;;;GAeG;AACH,MAAM,MAAM,oBAAoB,GAAG,GAAG,MAAM,IAAI,MAAM,EAAE,CAAC;AAEzD;;;GAGG;AACH,MAAM,WAAW,uBAAuB;IACvC;;;;;;OAMG;IACH,gBAAgB,CAAC,CAAC,EAAE,QAAQ,SAAS,OAAO,EAAE,EAC7C,EAAE,EAAE,oBAAoB,EACxB,OAAO,EAAE,yBAAyB,CAAC,CAAC,EAAE,QAAQ,CAAC,EAC/C,GAAG,OAAO,EAAE,QAAQ,GAClB,CAAC,CAAC;CACL"}
1
+ {"version":3,"file":"containerExtensions.d.ts","sourceRoot":"","sources":["../../src/container-definitions/containerExtensions.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EACX,gBAAgB,EAChB,gBAAgB,EAChB,MAAM,0CAA0C,CAAC;AAElD;;;;GAIG;AACH,MAAM,MAAM,kBAAkB,GAAG,MAAM,CAAC;AAExC;;;;;GAKG;AACH,MAAM,WAAW,iBAAiB,CAAC,KAAK,SAAS,MAAM,GAAG,MAAM,EAAE,QAAQ,GAAG,OAAO;IACnF;;OAEG;IACH,IAAI,EAAE,KAAK,CAAC;IAEZ;;OAEG;IACH,OAAO,EAAE,gBAAgB,CAAC,QAAQ,CAAC,CAAC;IAEpC;;;OAGG;IAEH,QAAQ,EAAE,kBAAkB,GAAG,IAAI,CAAC;IAEpC;;;OAGG;IACH,cAAc,CAAC,EAAE,kBAAkB,CAAC;CACpC;AAED;;;;GAIG;AACH,MAAM,WAAW,mBAAmB,CAAC,QAAQ,SAAS,OAAO,EAAE;IAC9D;;;;OAIG;IACH,YAAY,CAAC,GAAG,OAAO,EAAE,QAAQ,GAAG,IAAI,CAAC;IAEzC;;;;;;OAMG;IACH,aAAa,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,iBAAiB,EAAE,KAAK,EAAE,OAAO,GAAG,IAAI,CAAC;CACjF;AAED;;;;;;GAMG;AACH,MAAM,WAAW,iBAAiB;IACjC;;OAEG;IACH,IAAI,QAAQ,IAAI,kBAAkB,GAAG,SAAS,CAAC;IAE/C;;;;;;;;;OASG;IACH,qBAAqB,CAAC,CAAC,EACtB,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,gBAAgB,CAAC,CAAC,CAAC,EAC5B,cAAc,CAAC,EAAE,kBAAkB,GACjC,IAAI,CAAC;CACR;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,MAAM,yBAAyB,CAAC,CAAC,EAAE,QAAQ,SAAS,OAAO,EAAE,IAAI,KACtE,OAAO,EAAE,iBAAiB,EAC1B,GAAG,OAAO,EAAE,QAAQ,KAChB;IAAE,QAAQ,CAAC,SAAS,EAAE,CAAC,CAAC;IAAC,QAAQ,CAAC,SAAS,EAAE,mBAAmB,CAAC,QAAQ,CAAC,CAAA;CAAE,CAAC;AAElF;;;;;;;;;;;;;;;GAeG;AACH,MAAM,MAAM,oBAAoB,GAAG,GAAG,MAAM,IAAI,MAAM,EAAE,CAAC;AAEzD;;;GAGG;AACH,MAAM,WAAW,uBAAuB;IACvC;;;;;;OAMG;IACH,gBAAgB,CAAC,CAAC,EAAE,QAAQ,SAAS,OAAO,EAAE,EAC7C,EAAE,EAAE,oBAAoB,EACxB,OAAO,EAAE,yBAAyB,CAAC,CAAC,EAAE,QAAQ,CAAC,EAC/C,GAAG,OAAO,EAAE,QAAQ,GAClB,CAAC,CAAC;CACL"}
@@ -1 +1 @@
1
- {"version":3,"file":"containerExtensions.js","sourceRoot":"","sources":["../../src/container-definitions/containerExtensions.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 type {\n\tJsonDeserialized,\n\tJsonSerializable,\n} from \"@fluidframework/presence/internal/core-interfaces\";\n\n/**\n * While connected, the id of a client within a session.\n *\n * @internal\n */\nexport type ClientConnectionId = string;\n\n/**\n * Common interface between incoming and outgoing extension signals.\n *\n * @sealed\n * @internal\n */\nexport interface IExtensionMessage<TType extends string = string, TContent = unknown> {\n\t/**\n\t * Message type\n\t */\n\ttype: TType;\n\n\t/**\n\t * Message content\n\t */\n\tcontent: JsonDeserialized<TContent>;\n\n\t/**\n\t * The client ID that submitted the message.\n\t * For server generated messages the clientId will be null.\n\t */\n\t// eslint-disable-next-line @rushstack/no-new-null\n\tclientId: ClientConnectionId | null;\n\n\t/**\n\t * Client ID of the singular client the message is being (or has been) sent to.\n\t * May only be specified when IConnect.supportedFeatures['submit_signals_v2'] is true, will throw otherwise.\n\t */\n\ttargetClientId?: ClientConnectionId;\n}\n\n/**\n * Defines requirements for a component to register with container as an extension.\n *\n * @internal\n */\nexport interface IContainerExtension<TContext extends unknown[]> {\n\t/**\n\t * Notifies the extension of a new use context.\n\t *\n\t * @param context - Context new reference to extension is acquired within\n\t */\n\tonNewContext(...context: TContext): void;\n\n\t/**\n\t * Callback for signal sent by this extension.\n\t *\n\t * @param address - Address of the signal\n\t * @param signal - Signal content and metadata\n\t * @param local - True if signal was sent by this client\n\t */\n\tprocessSignal?(address: string, signal: IExtensionMessage, local: boolean): void;\n}\n\n/**\n * Defines the runtime interface an extension may access.\n * In most cases this is a subset of {@link @fluidframework/container-runtime-definitions#IContainerRuntime}.\n *\n * @sealed\n * @internal\n */\nexport interface IExtensionRuntime {\n\t/**\n\t * {@inheritdoc @fluidframework/container-runtime-definitions#IContainerRuntime.clientId}\n\t */\n\tget clientId(): ClientConnectionId | undefined;\n\n\t/**\n\t * Submits a signal to be sent to other clients.\n\t * @param address - Custom address for the signal.\n\t * @param type - Custom type of the signal.\n\t * @param content - Custom content of the signal. Should be a JSON serializable object or primitive via {@link https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify|JSON.stringify}.\n\t * @param targetClientId - When specified, the signal is only sent to the provided client id.\n\t *\n\t * Upon receipt of signal, {@link IContainerExtension.processSignal} will be called with the same\n\t * address, type, and content (less any non-{@link https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify|JSON.stringify}-able data).\n\t */\n\tsubmitAddressedSignal<T>(\n\t\taddress: string,\n\t\ttype: string,\n\t\tcontent: JsonSerializable<T>,\n\t\ttargetClientId?: ClientConnectionId,\n\t): void;\n}\n\n/**\n * Factory method to create an extension instance.\n *\n * Any such method provided to {@link ContainerExtensionStore.acquireExtension}\n * must use the same value for a given {@link ContainerExtensionId} so that an\n * `instanceof` check may be performed at runtime.\n *\n * @typeParam T - Type of extension to create\n * @typeParam TContext - Array of optional custom context\n *\n * @param runtime - Runtime for extension to work against\n * @param context - Custom context for extension.\n * @returns Record providing:\n * `interface` instance (type `T`) that is provided to caller of\n * {@link ContainerExtensionStore.acquireExtension} and\n * `extension` store/runtime uses to interact with extension.\n *\n * @internal\n */\nexport type ContainerExtensionFactory<T, TContext extends unknown[]> = new (\n\truntime: IExtensionRuntime,\n\t...context: TContext\n) => { readonly interface: T; readonly extension: IContainerExtension<TContext> };\n\n/**\n * Unique identifier for extension\n *\n * @remarks\n * A string known to all clients working with a certain ContainerExtension and unique\n * among ContainerExtensions. Not `/` may be used in the string. Recommend using\n * concatenation of: type of unique identifier, `:` (required), and unique identifier.\n *\n * @example Examples\n * ```typescript\n * \"guid:g0fl001d-1415-5000-c00l-g0fa54g0b1g1\"\n * \"name:@foo-scope_bar:v1\"\n * ```\n *\n * @internal\n */\nexport type ContainerExtensionId = `${string}:${string}`;\n\n/**\n * @sealed\n * @internal\n */\nexport interface ContainerExtensionStore {\n\t/**\n\t * Acquires an extension from store or adds new one.\n\t *\n\t * @param id - Identifier for the requested extension\n\t * @param factory - Factory to create the extension if not found\n\t * @returns The extension\n\t */\n\tacquireExtension<T, TContext extends unknown[]>(\n\t\tid: ContainerExtensionId,\n\t\tfactory: ContainerExtensionFactory<T, TContext>,\n\t\t...context: TContext\n\t): T;\n}\n"]}
1
+ {"version":3,"file":"containerExtensions.js","sourceRoot":"","sources":["../../src/container-definitions/containerExtensions.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 type {\n\tJsonDeserialized,\n\tJsonSerializable,\n} from \"@fluidframework/core-interfaces/internal\";\n\n/**\n * While connected, the id of a client within a session.\n *\n * @internal\n */\nexport type ClientConnectionId = string;\n\n/**\n * Common interface between incoming and outgoing extension signals.\n *\n * @sealed\n * @internal\n */\nexport interface IExtensionMessage<TType extends string = string, TContent = unknown> {\n\t/**\n\t * Message type\n\t */\n\ttype: TType;\n\n\t/**\n\t * Message content\n\t */\n\tcontent: JsonDeserialized<TContent>;\n\n\t/**\n\t * The client ID that submitted the message.\n\t * For server generated messages the clientId will be null.\n\t */\n\t// eslint-disable-next-line @rushstack/no-new-null\n\tclientId: ClientConnectionId | null;\n\n\t/**\n\t * Client ID of the singular client the message is being (or has been) sent to.\n\t * May only be specified when IConnect.supportedFeatures['submit_signals_v2'] is true, will throw otherwise.\n\t */\n\ttargetClientId?: ClientConnectionId;\n}\n\n/**\n * Defines requirements for a component to register with container as an extension.\n *\n * @internal\n */\nexport interface IContainerExtension<TContext extends unknown[]> {\n\t/**\n\t * Notifies the extension of a new use context.\n\t *\n\t * @param context - Context new reference to extension is acquired within\n\t */\n\tonNewContext(...context: TContext): void;\n\n\t/**\n\t * Callback for signal sent by this extension.\n\t *\n\t * @param address - Address of the signal\n\t * @param signal - Signal content and metadata\n\t * @param local - True if signal was sent by this client\n\t */\n\tprocessSignal?(address: string, signal: IExtensionMessage, local: boolean): void;\n}\n\n/**\n * Defines the runtime interface an extension may access.\n * In most cases this is a subset of {@link @fluidframework/container-runtime-definitions#IContainerRuntime}.\n *\n * @sealed\n * @internal\n */\nexport interface IExtensionRuntime {\n\t/**\n\t * {@inheritdoc @fluidframework/container-runtime-definitions#IContainerRuntime.clientId}\n\t */\n\tget clientId(): ClientConnectionId | undefined;\n\n\t/**\n\t * Submits a signal to be sent to other clients.\n\t * @param address - Custom address for the signal.\n\t * @param type - Custom type of the signal.\n\t * @param content - Custom content of the signal. Should be a JSON serializable object or primitive via {@link https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify|JSON.stringify}.\n\t * @param targetClientId - When specified, the signal is only sent to the provided client id.\n\t *\n\t * Upon receipt of signal, {@link IContainerExtension.processSignal} will be called with the same\n\t * address, type, and content (less any non-{@link https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify|JSON.stringify}-able data).\n\t */\n\tsubmitAddressedSignal<T>(\n\t\taddress: string,\n\t\ttype: string,\n\t\tcontent: JsonSerializable<T>,\n\t\ttargetClientId?: ClientConnectionId,\n\t): void;\n}\n\n/**\n * Factory method to create an extension instance.\n *\n * Any such method provided to {@link ContainerExtensionStore.acquireExtension}\n * must use the same value for a given {@link ContainerExtensionId} so that an\n * `instanceof` check may be performed at runtime.\n *\n * @typeParam T - Type of extension to create\n * @typeParam TContext - Array of optional custom context\n *\n * @param runtime - Runtime for extension to work against\n * @param context - Custom context for extension.\n * @returns Record providing:\n * `interface` instance (type `T`) that is provided to caller of\n * {@link ContainerExtensionStore.acquireExtension} and\n * `extension` store/runtime uses to interact with extension.\n *\n * @internal\n */\nexport type ContainerExtensionFactory<T, TContext extends unknown[]> = new (\n\truntime: IExtensionRuntime,\n\t...context: TContext\n) => { readonly interface: T; readonly extension: IContainerExtension<TContext> };\n\n/**\n * Unique identifier for extension\n *\n * @remarks\n * A string known to all clients working with a certain ContainerExtension and unique\n * among ContainerExtensions. Not `/` may be used in the string. Recommend using\n * concatenation of: type of unique identifier, `:` (required), and unique identifier.\n *\n * @example Examples\n * ```typescript\n * \"guid:g0fl001d-1415-5000-c00l-g0fa54g0b1g1\"\n * \"name:@foo-scope_bar:v1\"\n * ```\n *\n * @internal\n */\nexport type ContainerExtensionId = `${string}:${string}`;\n\n/**\n * @sealed\n * @internal\n */\nexport interface ContainerExtensionStore {\n\t/**\n\t * Acquires an extension from store or adds new one.\n\t *\n\t * @param id - Identifier for the requested extension\n\t * @param factory - Factory to create the extension if not found\n\t * @returns The extension\n\t */\n\tacquireExtension<T, TContext extends unknown[]>(\n\t\tid: ContainerExtensionId,\n\t\tfactory: ContainerExtensionFactory<T, TContext>,\n\t\t...context: TContext\n\t): T;\n}\n"]}
@@ -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
- import type { JsonDeserialized, JsonSerializable } from "@fluidframework/presence/internal/core-interfaces";
5
+ import type { JsonDeserialized, JsonSerializable } from "@fluidframework/core-interfaces/internal/exposedUtilityTypes";
6
6
  /**
7
7
  * Collection of value types that are not intended to be used/imported
8
8
  * directly outside of this package.
@@ -1 +1 @@
1
- {"version":3,"file":"exposedInternalTypes.d.ts","sourceRoot":"","sources":["../src/exposedInternalTypes.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EACX,gBAAgB,EAChB,gBAAgB,EAChB,MAAM,mDAAmD,CAAC;AAE3D;;;;;;GAMG;AAEH,yBAAiB,aAAa,CAAC;IAC9B;;OAEG;IACH,UAAiB,kBAAkB;QAClC,GAAG,EAAE,MAAM,CAAC;QACZ,SAAS,EAAE,MAAM,CAAC;KAClB;IAED;;OAEG;IACH,UAAiB,kBAAkB,CAAC,MAAM,CAAE,SAAQ,kBAAkB;QACrE,KAAK,CAAC,EAAE,gBAAgB,CAAC,MAAM,CAAC,CAAC;KACjC;IAED;;OAEG;IACH,UAAiB,kBAAkB,CAAC,MAAM,CAAE,SAAQ,kBAAkB;QACrE,KAAK,EAAE,gBAAgB,CAAC,MAAM,CAAC,CAAC;KAChC;IAED;;OAEG;IACH,UAAiB,cAAc,CAAC,CAAC;QAChC,GAAG,EAAE,MAAM,CAAC;QACZ,KAAK,EAAE;YAIN,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,kBAAkB,CAAC,CAAC,CAAC,GAAG,cAAc,CAAC,CAAC,CAAC,CAAC;SACnE,CAAC;KACF;IAED;;OAEG;IACH,KAAY,qBAAqB,CAAC,CAAC,IAAI,kBAAkB,CAAC,CAAC,CAAC,GAAG,cAAc,CAAC,CAAC,CAAC,CAAC;IAEjF;;OAEG;IACH,UAAiB,aAAa,CAAC,CAAC,EAAE,IAAI,SAAS,MAAM,GAAG,MAAM;QAC7D,GAAG,EAAE,MAAM,CAAC;QACZ,KAAK,EAAE;aAIL,IAAI,IAAI,IAAI,GAAG,kBAAkB,CAAC,CAAC,CAAC;SACrC,CAAC;KACF;IAED;;OAEG;IACH,MAAqB,oBAAoB,CAAC,IAAI,EAAE,MAAM,SAAS,qBAAqB,CAAC,GAAG,CAAC;QACxF,OAAO,CAAC,QAAQ,CAAC,oBAAoB,CAAqC;KAC1E;IAED;;;;;OAKG;IACH,MAAqB,eAAe,CAAC,CAAC;QACrC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAgB;KAC3C;IAED;;;;;;;;;OASG;IACH,KAAY,UAAU,CAAC,CAAC,IAAI,CAAC,GAAG,eAAe,CAAC,CAAC,CAAC,CAAC;IAEnD;;;;OAIG;IACH,KAAY,cAAc,CACzB,IAAI,SAAS,MAAM,EACnB,MAAM,SAAS,qBAAqB,CAAC,GAAG,CAAC,EACzC,QAAQ,IACL;QAAE,YAAY,EAAE,KAAK,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,GAAG,CAAA;KAAE,GAAG,CAAC,CACpD,GAAG,EAAE,IAAI,EACT,eAAe,EAAE,oBAAoB,CAAC,IAAI,EAAE,MAAM,CAAC,KAC/C;QACJ,WAAW,CAAC,EAAE;YAAE,KAAK,EAAE,MAAM,CAAC;YAAC,wBAAwB,EAAE,MAAM,GAAG,SAAS,CAAA;SAAE,CAAC;QAC9E,OAAO,EAAE,UAAU,CAAC,QAAQ,CAAC,CAAC;KAC9B,CAAC,CAAC;IAEH;;OAEG;IACH,UAAiB,gBAAgB;QAChC,IAAI,EAAE,MAAM,CAAC;QACb,IAAI,EAAE,CAAC,gBAAgB,CAAC,OAAO,CAAC,GAAG,gBAAgB,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC;KAChE;CACD"}
1
+ {"version":3,"file":"exposedInternalTypes.d.ts","sourceRoot":"","sources":["../src/exposedInternalTypes.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EACX,gBAAgB,EAChB,gBAAgB,EAChB,MAAM,8DAA8D,CAAC;AAEtE;;;;;;GAMG;AAEH,yBAAiB,aAAa,CAAC;IAC9B;;OAEG;IACH,UAAiB,kBAAkB;QAClC,GAAG,EAAE,MAAM,CAAC;QACZ,SAAS,EAAE,MAAM,CAAC;KAClB;IAED;;OAEG;IACH,UAAiB,kBAAkB,CAAC,MAAM,CAAE,SAAQ,kBAAkB;QACrE,KAAK,CAAC,EAAE,gBAAgB,CAAC,MAAM,CAAC,CAAC;KACjC;IAED;;OAEG;IACH,UAAiB,kBAAkB,CAAC,MAAM,CAAE,SAAQ,kBAAkB;QACrE,KAAK,EAAE,gBAAgB,CAAC,MAAM,CAAC,CAAC;KAChC;IAED;;OAEG;IACH,UAAiB,cAAc,CAAC,CAAC;QAChC,GAAG,EAAE,MAAM,CAAC;QACZ,KAAK,EAAE;YAIN,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,kBAAkB,CAAC,CAAC,CAAC,GAAG,cAAc,CAAC,CAAC,CAAC,CAAC;SACnE,CAAC;KACF;IAED;;OAEG;IACH,KAAY,qBAAqB,CAAC,CAAC,IAAI,kBAAkB,CAAC,CAAC,CAAC,GAAG,cAAc,CAAC,CAAC,CAAC,CAAC;IAEjF;;OAEG;IACH,UAAiB,aAAa,CAAC,CAAC,EAAE,IAAI,SAAS,MAAM,GAAG,MAAM;QAC7D,GAAG,EAAE,MAAM,CAAC;QACZ,KAAK,EAAE;aAIL,IAAI,IAAI,IAAI,GAAG,kBAAkB,CAAC,CAAC,CAAC;SACrC,CAAC;KACF;IAED;;OAEG;IACH,MAAqB,oBAAoB,CAAC,IAAI,EAAE,MAAM,SAAS,qBAAqB,CAAC,GAAG,CAAC;QACxF,OAAO,CAAC,QAAQ,CAAC,oBAAoB,CAAqC;KAC1E;IAED;;;;;OAKG;IACH,MAAqB,eAAe,CAAC,CAAC;QACrC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAgB;KAC3C;IAED;;;;;;;;;OASG;IACH,KAAY,UAAU,CAAC,CAAC,IAAI,CAAC,GAAG,eAAe,CAAC,CAAC,CAAC,CAAC;IAEnD;;;;OAIG;IACH,KAAY,cAAc,CACzB,IAAI,SAAS,MAAM,EACnB,MAAM,SAAS,qBAAqB,CAAC,GAAG,CAAC,EACzC,QAAQ,IACL;QAAE,YAAY,EAAE,KAAK,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,GAAG,CAAA;KAAE,GAAG,CAAC,CACpD,GAAG,EAAE,IAAI,EACT,eAAe,EAAE,oBAAoB,CAAC,IAAI,EAAE,MAAM,CAAC,KAC/C;QACJ,WAAW,CAAC,EAAE;YAAE,KAAK,EAAE,MAAM,CAAC;YAAC,wBAAwB,EAAE,MAAM,GAAG,SAAS,CAAA;SAAE,CAAC;QAC9E,OAAO,EAAE,UAAU,CAAC,QAAQ,CAAC,CAAC;KAC9B,CAAC,CAAC;IAEH;;OAEG;IACH,UAAiB,gBAAgB;QAChC,IAAI,EAAE,MAAM,CAAC;QACb,IAAI,EAAE,CAAC,gBAAgB,CAAC,OAAO,CAAC,GAAG,gBAAgB,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC;KAChE;CACD"}
@@ -1 +1 @@
1
- {"version":3,"file":"exposedInternalTypes.js","sourceRoot":"","sources":["../src/exposedInternalTypes.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAOH;;;;;;GAMG;AACH,2DAA2D;AAC3D,MAAM,KAAW,aAAa,CA2G7B;AA3GD,WAAiB,aAAa;AA2G9B,CAAC,EA3GgB,aAAa,KAAb,aAAa,QA2G7B","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport type {\n\tJsonDeserialized,\n\tJsonSerializable,\n} from \"@fluidframework/presence/internal/core-interfaces\";\n\n/**\n * Collection of value types that are not intended to be used/imported\n * directly outside of this package.\n *\n * @alpha\n * @system\n */\n// eslint-disable-next-line @typescript-eslint/no-namespace\nexport namespace InternalTypes {\n\t/**\n\t * @system\n\t */\n\texport interface ValueStateMetadata {\n\t\trev: number;\n\t\ttimestamp: number;\n\t}\n\n\t/**\n\t * @system\n\t */\n\texport interface ValueOptionalState<TValue> extends ValueStateMetadata {\n\t\tvalue?: JsonDeserialized<TValue>;\n\t}\n\n\t/**\n\t * @system\n\t */\n\texport interface ValueRequiredState<TValue> extends ValueStateMetadata {\n\t\tvalue: JsonDeserialized<TValue>;\n\t}\n\n\t/**\n\t * @system\n\t */\n\texport interface ValueDirectory<T> {\n\t\trev: number;\n\t\titems: {\n\t\t\t// Caution: any particular item may or may not exist\n\t\t\t// Typescript does not support absent keys without forcing type to also be undefined.\n\t\t\t// See https://github.com/microsoft/TypeScript/issues/42810.\n\t\t\t[name: string | number]: ValueOptionalState<T> | ValueDirectory<T>;\n\t\t};\n\t}\n\n\t/**\n\t * @system\n\t */\n\texport type ValueDirectoryOrState<T> = ValueRequiredState<T> | ValueDirectory<T>;\n\n\t/**\n\t * @system\n\t */\n\texport interface MapValueState<T, Keys extends string | number> {\n\t\trev: number;\n\t\titems: {\n\t\t\t// Caution: any particular item may or may not exist\n\t\t\t// Typescript does not support absent keys without forcing type to also be undefined.\n\t\t\t// See https://github.com/microsoft/TypeScript/issues/42810.\n\t\t\t[name in Keys]: ValueOptionalState<T>;\n\t\t};\n\t}\n\n\t/**\n\t * @system\n\t */\n\texport declare class StateDatastoreHandle<TKey, TValue extends ValueDirectoryOrState<any>> {\n\t\tprivate readonly StateDatastoreHandle: StateDatastoreHandle<TKey, TValue>;\n\t}\n\n\t/**\n\t * Brand to ensure state values internal type safety without revealing\n\t * internals that are subject to change.\n\t *\n\t * @system\n\t */\n\texport declare class StateValueBrand<T> {\n\t\tprivate readonly StateValue: StateValue<T>;\n\t}\n\n\t/**\n\t * This type provides no additional functionality over the type it wraps.\n\t * It is used to ensure type safety within package.\n\t * Users may find it convenient to just use the type it wraps directly.\n\t *\n\t * @privateRemarks\n\t * Checkout filtering omitting unknown from T (`Omit<T,unknown> &`).\n\t *\n\t * @system\n\t */\n\texport type StateValue<T> = T & StateValueBrand<T>;\n\n\t/**\n\t * Package internal function declaration for value manager instantiation.\n\t *\n\t * @system\n\t */\n\texport type ManagerFactory<\n\t\tTKey extends string,\n\t\tTValue extends ValueDirectoryOrState<any>,\n\t\tTManager,\n\t> = { instanceBase: new (...args: any[]) => any } & ((\n\t\tkey: TKey,\n\t\tdatastoreHandle: StateDatastoreHandle<TKey, TValue>,\n\t) => {\n\t\tinitialData?: { value: TValue; allowableUpdateLatencyMs: number | undefined };\n\t\tmanager: StateValue<TManager>;\n\t});\n\n\t/**\n\t * @system\n\t */\n\texport interface NotificationType {\n\t\tname: string;\n\t\targs: (JsonSerializable<unknown> & JsonDeserialized<unknown>)[];\n\t}\n}\n"]}
1
+ {"version":3,"file":"exposedInternalTypes.js","sourceRoot":"","sources":["../src/exposedInternalTypes.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAOH;;;;;;GAMG;AACH,2DAA2D;AAC3D,MAAM,KAAW,aAAa,CA2G7B;AA3GD,WAAiB,aAAa;AA2G9B,CAAC,EA3GgB,aAAa,KAAb,aAAa,QA2G7B","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport type {\n\tJsonDeserialized,\n\tJsonSerializable,\n} from \"@fluidframework/core-interfaces/internal/exposedUtilityTypes\";\n\n/**\n * Collection of value types that are not intended to be used/imported\n * directly outside of this package.\n *\n * @alpha\n * @system\n */\n// eslint-disable-next-line @typescript-eslint/no-namespace\nexport namespace InternalTypes {\n\t/**\n\t * @system\n\t */\n\texport interface ValueStateMetadata {\n\t\trev: number;\n\t\ttimestamp: number;\n\t}\n\n\t/**\n\t * @system\n\t */\n\texport interface ValueOptionalState<TValue> extends ValueStateMetadata {\n\t\tvalue?: JsonDeserialized<TValue>;\n\t}\n\n\t/**\n\t * @system\n\t */\n\texport interface ValueRequiredState<TValue> extends ValueStateMetadata {\n\t\tvalue: JsonDeserialized<TValue>;\n\t}\n\n\t/**\n\t * @system\n\t */\n\texport interface ValueDirectory<T> {\n\t\trev: number;\n\t\titems: {\n\t\t\t// Caution: any particular item may or may not exist\n\t\t\t// Typescript does not support absent keys without forcing type to also be undefined.\n\t\t\t// See https://github.com/microsoft/TypeScript/issues/42810.\n\t\t\t[name: string | number]: ValueOptionalState<T> | ValueDirectory<T>;\n\t\t};\n\t}\n\n\t/**\n\t * @system\n\t */\n\texport type ValueDirectoryOrState<T> = ValueRequiredState<T> | ValueDirectory<T>;\n\n\t/**\n\t * @system\n\t */\n\texport interface MapValueState<T, Keys extends string | number> {\n\t\trev: number;\n\t\titems: {\n\t\t\t// Caution: any particular item may or may not exist\n\t\t\t// Typescript does not support absent keys without forcing type to also be undefined.\n\t\t\t// See https://github.com/microsoft/TypeScript/issues/42810.\n\t\t\t[name in Keys]: ValueOptionalState<T>;\n\t\t};\n\t}\n\n\t/**\n\t * @system\n\t */\n\texport declare class StateDatastoreHandle<TKey, TValue extends ValueDirectoryOrState<any>> {\n\t\tprivate readonly StateDatastoreHandle: StateDatastoreHandle<TKey, TValue>;\n\t}\n\n\t/**\n\t * Brand to ensure state values internal type safety without revealing\n\t * internals that are subject to change.\n\t *\n\t * @system\n\t */\n\texport declare class StateValueBrand<T> {\n\t\tprivate readonly StateValue: StateValue<T>;\n\t}\n\n\t/**\n\t * This type provides no additional functionality over the type it wraps.\n\t * It is used to ensure type safety within package.\n\t * Users may find it convenient to just use the type it wraps directly.\n\t *\n\t * @privateRemarks\n\t * Checkout filtering omitting unknown from T (`Omit<T,unknown> &`).\n\t *\n\t * @system\n\t */\n\texport type StateValue<T> = T & StateValueBrand<T>;\n\n\t/**\n\t * Package internal function declaration for value manager instantiation.\n\t *\n\t * @system\n\t */\n\texport type ManagerFactory<\n\t\tTKey extends string,\n\t\tTValue extends ValueDirectoryOrState<any>,\n\t\tTManager,\n\t> = { instanceBase: new (...args: any[]) => any } & ((\n\t\tkey: TKey,\n\t\tdatastoreHandle: StateDatastoreHandle<TKey, TValue>,\n\t) => {\n\t\tinitialData?: { value: TValue; allowableUpdateLatencyMs: number | undefined };\n\t\tmanager: StateValue<TManager>;\n\t});\n\n\t/**\n\t * @system\n\t */\n\texport interface NotificationType {\n\t\tname: string;\n\t\targs: (JsonSerializable<unknown> & JsonDeserialized<unknown>)[];\n\t}\n}\n"]}
@@ -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
- import type { InternalUtilityTypes as CoreInternalUtilityTypes, JsonDeserialized, JsonSerializable } from "@fluidframework/presence/internal/core-interfaces";
5
+ import type { InternalUtilityTypes as CoreInternalUtilityTypes, JsonDeserialized, JsonSerializable } from "@fluidframework/core-interfaces/internal/exposedUtilityTypes";
6
6
  /**
7
7
  * Collection of utility types that are not intended to be used/imported
8
8
  * directly outside of this package.
@@ -1 +1 @@
1
- {"version":3,"file":"exposedUtilityTypes.d.ts","sourceRoot":"","sources":["../src/exposedUtilityTypes.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EACX,oBAAoB,IAAI,wBAAwB,EAChD,gBAAgB,EAChB,gBAAgB,EAChB,MAAM,mDAAmD,CAAC;AAE3D;;;;;;GAMG;AAEH,yBAAiB,oBAAoB,CAAC;IACrC;;;;OAIG;IACH,KAAY,aAAa,CAAC,CAAC,IAAI;QAC9B,QAAQ,EAAE,CAAC,IAAI,MAAM,CAAC,GAAG,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;KAC5C,CAAC;IAEF;;;;OAIG;IACH,KAAY,sBAAsB,CAAC,KAAK,IAAI,KAAK,SAAS,CAAC,GAAG,IAAI,EAAE,MAAM,CAAC,KAAK,IAAI,GACjF,wBAAwB,CAAC,UAAU,CACnC,CAAC,EACD,gBAAgB,CAAC,CAAC,CAAC,GAAG,gBAAgB,CAAC,CAAC,CAAC,EACzC,IAAI,EACJ,KAAK,CACL,GACA,KAAK,CAAC;IAET;;;;;;;;;;;;;;;;;;OAkBG;IACH,KAAY,qBAAqB,CAAC,CAAC,IAAI;SACrC,CAAC,IAAI,MAAM,GAAG,MAAM,CAAC,IAAI,sBAAsB,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,IAAI,GAAG,CAAC,GAAG,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC;KACtF,CAAC;IAEF;;;;OAIG;IACH,KAAY,0BAA0B,CAAC,CAAC,SAAS,CAAC,GAAG,IAAI,EAAE,GAAG,KAAK,GAAG,IAAI,CAAC,SAAS,CACnF,GAAG,IAAI,EAAE,MAAM,CAAC,KACZ,GAAG,GACL,gBAAgB,CAAC,CAAC,CAAC,GACnB,KAAK,CAAC;IAET;;;;OAIG;IACH,KAAY,0BAA0B,CAAC,CAAC,SAAS,CAAC,GAAG,IAAI,EAAE,GAAG,KAAK,GAAG,IAAI,CAAC,SAAS,CACnF,GAAG,IAAI,EAAE,MAAM,CAAC,KACZ,GAAG,GACL,gBAAgB,CAAC,CAAC,CAAC,GACnB,KAAK,CAAC;CACT"}
1
+ {"version":3,"file":"exposedUtilityTypes.d.ts","sourceRoot":"","sources":["../src/exposedUtilityTypes.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EACX,oBAAoB,IAAI,wBAAwB,EAChD,gBAAgB,EAChB,gBAAgB,EAChB,MAAM,8DAA8D,CAAC;AAEtE;;;;;;GAMG;AAEH,yBAAiB,oBAAoB,CAAC;IACrC;;;;OAIG;IACH,KAAY,aAAa,CAAC,CAAC,IAAI;QAC9B,QAAQ,EAAE,CAAC,IAAI,MAAM,CAAC,GAAG,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;KAC5C,CAAC;IAEF;;;;OAIG;IACH,KAAY,sBAAsB,CAAC,KAAK,IAAI,KAAK,SAAS,CAAC,GAAG,IAAI,EAAE,MAAM,CAAC,KAAK,IAAI,GACjF,wBAAwB,CAAC,UAAU,CACnC,CAAC,EACD,gBAAgB,CAAC,CAAC,CAAC,GAAG,gBAAgB,CAAC,CAAC,CAAC,EACzC,IAAI,EACJ,KAAK,CACL,GACA,KAAK,CAAC;IAET;;;;;;;;;;;;;;;;;;OAkBG;IACH,KAAY,qBAAqB,CAAC,CAAC,IAAI;SACrC,CAAC,IAAI,MAAM,GAAG,MAAM,CAAC,IAAI,sBAAsB,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,IAAI,GAAG,CAAC,GAAG,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC;KACtF,CAAC;IAEF;;;;OAIG;IACH,KAAY,0BAA0B,CAAC,CAAC,SAAS,CAAC,GAAG,IAAI,EAAE,GAAG,KAAK,GAAG,IAAI,CAAC,SAAS,CACnF,GAAG,IAAI,EAAE,MAAM,CAAC,KACZ,GAAG,GACL,gBAAgB,CAAC,CAAC,CAAC,GACnB,KAAK,CAAC;IAET;;;;OAIG;IACH,KAAY,0BAA0B,CAAC,CAAC,SAAS,CAAC,GAAG,IAAI,EAAE,GAAG,KAAK,GAAG,IAAI,CAAC,SAAS,CACnF,GAAG,IAAI,EAAE,MAAM,CAAC,KACZ,GAAG,GACL,gBAAgB,CAAC,CAAC,CAAC,GACnB,KAAK,CAAC;CACT"}
@@ -1 +1 @@
1
- {"version":3,"file":"exposedUtilityTypes.js","sourceRoot":"","sources":["../src/exposedUtilityTypes.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 type {\n\tInternalUtilityTypes as CoreInternalUtilityTypes,\n\tJsonDeserialized,\n\tJsonSerializable,\n} from \"@fluidframework/presence/internal/core-interfaces\";\n\n/**\n * Collection of utility types that are not intended to be used/imported\n * directly outside of this package.\n *\n * @alpha\n * @system\n */\n// eslint-disable-next-line @typescript-eslint/no-namespace\nexport namespace InternalUtilityTypes {\n\t/**\n\t * Recursively/deeply makes all properties of a type readonly.\n\t *\n\t * @system\n\t */\n\texport type FullyReadonly<T> = {\n\t\treadonly [K in keyof T]: FullyReadonly<T[K]>;\n\t};\n\n\t/**\n\t * `true` iff the given type is an acceptable shape for a notification.\n\t *\n\t * @system\n\t */\n\texport type IsNotificationListener<Event> = Event extends (...args: infer P) => void\n\t\t? CoreInternalUtilityTypes.IfSameType<\n\t\t\t\tP,\n\t\t\t\tJsonSerializable<P> & JsonDeserialized<P>,\n\t\t\t\ttrue,\n\t\t\t\tfalse\n\t\t\t>\n\t\t: false;\n\n\t/**\n\t * Used to specify the kinds of notifications emitted by a {@link NotificationListenable}.\n\t *\n\t * @remarks\n\t *\n\t * Any object type is a valid NotificationListeners, but only the notification-like\n\t * properties of that type will be included.\n\t *\n\t * @example\n\t *\n\t * ```typescript\n\t * interface MyNotifications {\n\t * load: (user: string, data: IUserData) => void;\n\t * requestPause: (period: number) => void;\n\t * }\n\t * ```\n\t *\n\t * @system\n\t */\n\texport type NotificationListeners<E> = {\n\t\t[P in string & keyof E as IsNotificationListener<E[P]> extends true ? P : never]: E[P];\n\t};\n\n\t/**\n\t * {@link @fluidframework/core-interfaces#JsonDeserialized} version of the parameters of a function.\n\t *\n\t * @system\n\t */\n\texport type JsonDeserializedParameters<T extends (...args: any) => any> = T extends (\n\t\t...args: infer P\n\t) => any\n\t\t? JsonDeserialized<P>\n\t\t: never;\n\n\t/**\n\t * {@link @fluidframework/core-interfaces#JsonSerializable} version of the parameters of a function.\n\t *\n\t * @system\n\t */\n\texport type JsonSerializableParameters<T extends (...args: any) => any> = T extends (\n\t\t...args: infer P\n\t) => any\n\t\t? JsonSerializable<P>\n\t\t: never;\n}\n"]}
1
+ {"version":3,"file":"exposedUtilityTypes.js","sourceRoot":"","sources":["../src/exposedUtilityTypes.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 type {\n\tInternalUtilityTypes as CoreInternalUtilityTypes,\n\tJsonDeserialized,\n\tJsonSerializable,\n} from \"@fluidframework/core-interfaces/internal/exposedUtilityTypes\";\n\n/**\n * Collection of utility types that are not intended to be used/imported\n * directly outside of this package.\n *\n * @alpha\n * @system\n */\n// eslint-disable-next-line @typescript-eslint/no-namespace\nexport namespace InternalUtilityTypes {\n\t/**\n\t * Recursively/deeply makes all properties of a type readonly.\n\t *\n\t * @system\n\t */\n\texport type FullyReadonly<T> = {\n\t\treadonly [K in keyof T]: FullyReadonly<T[K]>;\n\t};\n\n\t/**\n\t * `true` iff the given type is an acceptable shape for a notification.\n\t *\n\t * @system\n\t */\n\texport type IsNotificationListener<Event> = Event extends (...args: infer P) => void\n\t\t? CoreInternalUtilityTypes.IfSameType<\n\t\t\t\tP,\n\t\t\t\tJsonSerializable<P> & JsonDeserialized<P>,\n\t\t\t\ttrue,\n\t\t\t\tfalse\n\t\t\t>\n\t\t: false;\n\n\t/**\n\t * Used to specify the kinds of notifications emitted by a {@link NotificationListenable}.\n\t *\n\t * @remarks\n\t *\n\t * Any object type is a valid NotificationListeners, but only the notification-like\n\t * properties of that type will be included.\n\t *\n\t * @example\n\t *\n\t * ```typescript\n\t * interface MyNotifications {\n\t * load: (user: string, data: IUserData) => void;\n\t * requestPause: (period: number) => void;\n\t * }\n\t * ```\n\t *\n\t * @system\n\t */\n\texport type NotificationListeners<E> = {\n\t\t[P in string & keyof E as IsNotificationListener<E[P]> extends true ? P : never]: E[P];\n\t};\n\n\t/**\n\t * {@link @fluidframework/core-interfaces#JsonDeserialized} version of the parameters of a function.\n\t *\n\t * @system\n\t */\n\texport type JsonDeserializedParameters<T extends (...args: any) => any> = T extends (\n\t\t...args: infer P\n\t) => any\n\t\t? JsonDeserialized<P>\n\t\t: never;\n\n\t/**\n\t * {@link @fluidframework/core-interfaces#JsonSerializable} version of the parameters of a function.\n\t *\n\t * @system\n\t */\n\texport type JsonSerializableParameters<T extends (...args: any) => any> = T extends (\n\t\t...args: infer P\n\t) => any\n\t\t? JsonSerializable<P>\n\t\t: never;\n}\n"]}
package/lib/index.d.ts CHANGED
@@ -19,4 +19,6 @@ export { LatestMap, type LatestMapItemRemovedClientData, type LatestMapItemValue
19
19
  export { Latest, type LatestValueManager, type LatestValueManagerEvents, } from "./latestValueManager.js";
20
20
  export type { LatestValueClientData, LatestValueData, LatestValueMetadata, } from "./latestValueTypes.js";
21
21
  export { type NotificationEmitter, type NotificationListenable, type NotificationSubscriptions, Notifications, type NotificationsManager, type NotificationsManagerEvents, } from "./notificationsManager.js";
22
+ export type { InternalTypes } from "./exposedInternalTypes.js";
23
+ export type { InternalUtilityTypes } from "./exposedUtilityTypes.js";
22
24
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;;;;;GAMG;AASH,YAAY,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AAEzD,YAAY,EACX,qBAAqB,EACrB,2BAA2B,EAC3B,cAAc,EACd,qBAAqB,EACrB,oBAAoB,EACpB,wBAAwB,EACxB,sBAAsB,GACtB,MAAM,YAAY,CAAC;AAEpB,OAAO,EACN,KAAK,eAAe,EACpB,KAAK,SAAS,EACd,KAAK,cAAc,EACnB,KAAK,cAAc,EACnB,mBAAmB,GACnB,MAAM,eAAe,CAAC;AAEvB,YAAY,EACX,iBAAiB,EACjB,wBAAwB,GACxB,MAAM,wBAAwB,CAAC;AAEhC,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAE1D,OAAO,EACN,4BAA4B,EAC5B,KAAK,sBAAsB,EAC3B,2BAA2B,GAC3B,MAAM,sCAAsC,CAAC;AAE9C,OAAO,EACN,SAAS,EACT,KAAK,8BAA8B,EACnC,KAAK,4BAA4B,EACjC,KAAK,wBAAwB,EAC7B,KAAK,qBAAqB,EAC1B,KAAK,2BAA2B,EAChC,KAAK,QAAQ,GACb,MAAM,4BAA4B,CAAC;AACpC,OAAO,EACN,MAAM,EACN,KAAK,kBAAkB,EACvB,KAAK,wBAAwB,GAC7B,MAAM,yBAAyB,CAAC;AACjC,YAAY,EACX,qBAAqB,EACrB,eAAe,EACf,mBAAmB,GACnB,MAAM,uBAAuB,CAAC;AAE/B,OAAO,EACN,KAAK,mBAAmB,EACxB,KAAK,sBAAsB,EAC3B,KAAK,yBAAyB,EAC9B,aAAa,EACb,KAAK,oBAAoB,EACzB,KAAK,0BAA0B,GAC/B,MAAM,2BAA2B,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;;;;;GAMG;AAEH,YAAY,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AAEzD,YAAY,EACX,qBAAqB,EACrB,2BAA2B,EAC3B,cAAc,EACd,qBAAqB,EACrB,oBAAoB,EACpB,wBAAwB,EACxB,sBAAsB,GACtB,MAAM,YAAY,CAAC;AAEpB,OAAO,EACN,KAAK,eAAe,EACpB,KAAK,SAAS,EACd,KAAK,cAAc,EACnB,KAAK,cAAc,EACnB,mBAAmB,GACnB,MAAM,eAAe,CAAC;AAEvB,YAAY,EACX,iBAAiB,EACjB,wBAAwB,GACxB,MAAM,wBAAwB,CAAC;AAEhC,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAE1D,OAAO,EACN,4BAA4B,EAC5B,KAAK,sBAAsB,EAC3B,2BAA2B,GAC3B,MAAM,sCAAsC,CAAC;AAE9C,OAAO,EACN,SAAS,EACT,KAAK,8BAA8B,EACnC,KAAK,4BAA4B,EACjC,KAAK,wBAAwB,EAC7B,KAAK,qBAAqB,EAC1B,KAAK,2BAA2B,EAChC,KAAK,QAAQ,GACb,MAAM,4BAA4B,CAAC;AACpC,OAAO,EACN,MAAM,EACN,KAAK,kBAAkB,EACvB,KAAK,wBAAwB,GAC7B,MAAM,yBAAyB,CAAC;AACjC,YAAY,EACX,qBAAqB,EACrB,eAAe,EACf,mBAAmB,GACnB,MAAM,uBAAuB,CAAC;AAE/B,OAAO,EACN,KAAK,mBAAmB,EACxB,KAAK,sBAAsB,EAC3B,KAAK,yBAAyB,EAC9B,aAAa,EACb,KAAK,oBAAoB,EACzB,KAAK,0BAA0B,GAC/B,MAAM,2BAA2B,CAAC;AAEnC,YAAY,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAC/D,YAAY,EAAE,oBAAoB,EAAE,MAAM,0BAA0B,CAAC"}