Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move events library to core-interfaces and client-utils #23141

Merged

Conversation

sonalideshpandemsft
Copy link
Contributor

@sonalideshpandemsft sonalideshpandemsft commented Nov 19, 2024

This change relocates event library from SharedTree to client-utils and core-interfaces.

Old PR: #23037

ADO#6595

@github-actions github-actions bot added area: dds Issues related to distributed data structures area: dds: tree changeset-present public api change Changes to a public API base: main PRs targeted against main branch labels Nov 19, 2024
@sonalideshpandemsft sonalideshpandemsft changed the title Move events library to core-interfaces and core-utils Move events library to core-interfaces and client-utils Nov 19, 2024
Copy link
Collaborator

@msfluid-bot msfluid-bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Coverage Summary

↑ packages.dds.tree.src.core.tree:
Line Coverage Change: 0.01%    Branch Coverage Change: No change
Metric NameBaseline coveragePR coverageCoverage Diff
Branch Coverage 96.56% 96.56% → No change
Line Coverage 88.09% 88.10% ↑ 0.01%

Baseline commit: f1c1c31
Baseline build: 309286
Happy Coding!!

Code coverage comparison check passed!!

@msfluid-bot
Copy link
Collaborator

msfluid-bot commented Nov 19, 2024

@fluid-example/bundle-size-tests: +391 Bytes
Metric NameBaseline SizeCompare SizeSize Diff
aqueduct.js 467.24 KB 467.27 KB +35 Bytes
azureClient.js 564.01 KB 564.06 KB +49 Bytes
connectionState.js 724 Bytes 724 Bytes No change
containerRuntime.js 263.43 KB 263.45 KB +14 Bytes
fluidFramework.js 428.84 KB 428.92 KB +87 Bytes
loader.js 134.18 KB 134.19 KB +14 Bytes
map.js 42.71 KB 42.71 KB +7 Bytes
matrix.js 150.15 KB 150.16 KB +7 Bytes
odspClient.js 529.85 KB 529.89 KB +49 Bytes
odspDriver.js 97.88 KB 97.9 KB +21 Bytes
odspPrefetchSnapshot.js 42.81 KB 42.83 KB +14 Bytes
sharedString.js 166.23 KB 166.24 KB +7 Bytes
sharedTree.js 419.3 KB 419.37 KB +80 Bytes
Total Size 3.38 MB 3.38 MB +391 Bytes

Baseline commit: f1c1c31

Generated by 🚫 dangerJS against 00b714e

.changeset/calm-horses-feel.md Outdated Show resolved Hide resolved
.changeset/calm-horses-feel.md Outdated Show resolved Hide resolved
.changeset/calm-horses-feel.md Outdated Show resolved Hide resolved

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot reviewed 30 out of 43 changed files in this pull request and generated no suggestions.

Files not reviewed (13)
  • packages/common/core-interfaces/api-report/core-interfaces.legacy.public.api.md: Evaluated as low risk
  • packages/common/core-interfaces/src/events/emitter.ts: Evaluated as low risk
  • packages/common/core-interfaces/src/events.ts: Evaluated as low risk
  • packages/common/core-interfaces/src/events/README.md: Evaluated as low risk
  • packages/common/core-interfaces/src/index.ts: Evaluated as low risk
  • packages/dds/tree/api-report/tree.legacy.alpha.api.md: Evaluated as low risk
  • packages/dds/tree/api-report/tree.beta.api.md: Evaluated as low risk
  • packages/dds/tree/api-report/tree.alpha.api.md: Evaluated as low risk
  • packages/common/client-utils/src/indexBrowser.ts: Evaluated as low risk
  • packages/common/client-utils/src/indexNode.ts: Evaluated as low risk
  • packages/common/client-utils/src/events/emitter.ts: Evaluated as low risk
  • packages/common/core-interfaces/src/events/index.ts: Evaluated as low risk
  • packages/common/core-interfaces/api-report/core-interfaces.public.api.md: Evaluated as low risk

Tip: If you use Visual Studio Code, you can request a review from Copilot before you push from the "Source Control" tab. Learn more

* A class can delegate handling {@link Listenable} to the returned value while using it to emit the events.
* See also {@link EventEmitter} which be used as a base class to implement {@link Listenable} via extension.
* A class can delegate handling {@link @fluidframework/core-interfaces#Listenable} to the returned value while using it to emit the events.
* See also CustomEventEmitter which be used as a base class to implement {@link @fluidframework/core-interfaces#Listenable} via extension.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit

Suggested change
* See also CustomEventEmitter which be used as a base class to implement {@link @fluidframework/core-interfaces#Listenable} via extension.
* @see {@link CustomEventEmitter}, which be used as a base class to implement {@link @fluidframework/core-interfaces#Listenable} via extension.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This causes build failures, possibly because it isn't exported from the other index.ts. However, the @link tag works fine for tests.

Copy link
Contributor

@ChumpChief ChumpChief left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some small suggestions and I would like to know the longer-term plan for the exports from the tree package, but overall looks good!

packages/common/client-utils/src/events/emitter.ts Outdated Show resolved Hide resolved
): ReturnType<TListeners[K]>[];
interface MapGetSet<K, V> {
get(key: K): V | undefined;
set(key: K, value: V): void;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe more of a question for the tree folks (and not something that should change in this PR), but I'm wondering why not just use something like:

export type MapGetSet<K, V> = Pick<Map<K, V>, "get" | "set">

I see that set has a void return instead of this but not sure if that is intentional and/or necessary here?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good question. I'm not sure how conscious of a decision it was originally, but having the return type of set be looser means it's a wee bit easier to have an object satisfy MapGetSet. I think the Tree package has some objects which are not JS maps, but which satisfy MapGetSet, and can therefore be used with e.g. getOrCreate. At best it'd be annoying to have to change their set method return this in order to satisfy the interface, and at worst it would be prohibitive because the return value is already being used for something else. I think it's a good call considering that I rarely (have I ever?) seen use of the fluent-style code that would leverage the returned this - e.g. map.set(...).size or something like that - so nothing is really lost.

You made me wonder if we could still make it more closely derived:

interface MapGetSet<K, V> extends Pick<Map<K, V>, "get"> {
    set(...args: Parameters<Map<K,V>["set"]>): void
}

The "typescript enjoyer and purist" part of me thinks that is cool and good, whereas the rational part of me thinks that it is less readable and will bother subsequent readers more than help them :)

@@ -305,6 +308,17 @@ export interface ITelemetryBaseProperties {
[index: string]: TelemetryBaseEventPropertyType | Tagged<TelemetryBaseEventPropertyType>;
}

// @public @sealed
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should other interfaces be marked as @sealed too?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we want to prevent further extensions of this interface to ensure a fixed structure?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, I see that this is the only @public interface - I was looking at the @internal ones too (e.g. IEmitter) which I think would be nice to declare @sealed but probably matters a lot less if they're not available to customers.

packages/dds/tree/src/core/forest/forest.ts Show resolved Hide resolved
type Listenable,
type Off,
} from "./events/index.js";
export type {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Long-term, we shouldn't re-export from here (folks should import directly from the appropriate package). Is this just to avoid a breaking change for the time being? Would be good to have a plan in place to deprecate/remove these exports from this package.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, it is just to avoid breaking changes. I'll open a follow-up work item to remove them

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removing these will be a breaking change on public API surface so it'll have to wait until 3.0, I think (?) but we'll have to deprecate them somehow before that, no? Should we do something like importing them as Listeners_base or similar in this package, and exporting them from here as a new type with its own docs and deprecation notice? I.e. something like (double check it, not sure it works as written):

import { Listeners as Listeners_base } from "@fluidframework/core-interfaces";

/**
 * @inheritDoc <something here, I don't recall the syntax>
 * @ deprecated This type has moved to `@fluidframework/core-interfaces` and will be removed from here in a future release.
 * If you need to reference it directly, do it from `@fluidframework/core-interfaces`.
 */
export type Listeners = Listeners_base;

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe this is not considered breaking since it's re-exported from here as well, and there are no typetest breaks in tree.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right, it's not breaking now, but when we remove them from here it will be breaking, and before we can do that they should be marked as deprecated here. So I'm suggesting we deprecate them here now (while keeping them not-deprecated in core-interfaces).

Copy link
Contributor Author

@sonalideshpandemsft sonalideshpandemsft Nov 22, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ADO: https://dev.azure.com/fluidframework/internal/_workitems/edit/25440

Another concern could be aliasing in core-interfaces: sonalideshpandemsft#41.

Would that be a problem? Is it okay for aliasing to happen in tree? but that will cause typetest breaks.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wrong link about the aliasing bit? Not sure what the concern is there.

Copy link
Contributor Author

@sonalideshpandemsft sonalideshpandemsft Nov 22, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Aliasing in core-interfaces: 04274d8

EDIT:

Aliasing is not required. Types can be exported from core-interfaces by adding eslint suppression. 4d0a841

When importing types from tree, VSCode displays the usual strikethrough. However, the TSDoc shown is from core-interfaces rather than the deprecation warning from tree. I guess that's OK?
@Josmithr, is there anyway to add the deprecation docs too?

export type {
	/**
	 * Moved to the `@fluidframework/core-interfaces` package.
	 * @deprecated Moved to the `@fluidframework/core-interfaces` package.
	 */
	Listeners,
	/**
	 * @deprecated Moved to the `@fluidframework/core-interfaces` package.
	 */
	IsListener,
	/**
	 * @deprecated Moved to the `@fluidframework/core-interfaces` package.
	 */
	Listenable,
	/**
	 * Moved to the `@fluidframework/core-interfaces` package.
	 * @deprecated Moved to the `@fluidframework/core-interfaces` package.
	 */
	Off,
} from "@fluidframework/core-interfaces";

Similar example: https://github.com/microsoft/FluidFramework/blame/main/packages/common/container-definitions/src/index.ts#L70

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm actually not sure why Intellisense picks up on the deprecation notice and nothing else. For what it's worth, our API docs will not understand this. Unfortunately, I think you would need to do what @alexvy86 suggested to make everything work out correctly. E.g.

import { Foo as FooBase } from "a";

/**
 * Foo description.
 * @deprecated ...
 */
export type Foo = FooBase;

I don't believe you can use {@inheritDoc} in this case, unfortunately, since we're introducing local documentation (the deprecated tag).

Are all of these re-exports type-only? Or are any of them classes or anything? Making the re-export of a class would require subclassing to remain compatible.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

They are all type-only.

Copy link
Contributor

@Josmithr Josmithr left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Left some documentation nitpicks, but otherwise looks good to me!

.changeset/new-hats-learn.md Outdated Show resolved Hide resolved
type Listenable,
type Off,
} from "./events/index.js";
export type {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removing these will be a breaking change on public API surface so it'll have to wait until 3.0, I think (?) but we'll have to deprecate them somehow before that, no? Should we do something like importing them as Listeners_base or similar in this package, and exporting them from here as a new type with its own docs and deprecation notice? I.e. something like (double check it, not sure it works as written):

import { Listeners as Listeners_base } from "@fluidframework/core-interfaces";

/**
 * @inheritDoc <something here, I don't recall the syntax>
 * @ deprecated This type has moved to `@fluidframework/core-interfaces` and will be removed from here in a future release.
 * If you need to reference it directly, do it from `@fluidframework/core-interfaces`.
 */
export type Listeners = Listeners_base;

Copy link
Contributor

🔗 No broken links found! ✅

Your attention to detail is admirable.

linkcheck output


> [email protected] ci:check-links /home/runner/work/FluidFramework/FluidFramework/docs
> start-server-and-test "npm run serve -- --no-open" 3000 check-links

1: starting server using command "npm run serve -- --no-open"
and when url "[ 'http://127.0.0.1:3000' ]" is responding with HTTP status code 200
running tests using command "npm run check-links"


> [email protected] serve
> docusaurus serve --no-open

[SUCCESS] Serving "build" directory at: http://localhost:3000/

> [email protected] check-links
> linkcheck http://localhost:3000 --skip-file skipped-urls.txt

Crawling...

Stats:
  170005 links
    1595 destination URLs
    1825 URLs ignored
       0 warnings
       0 errors


@sonalideshpandemsft sonalideshpandemsft merged commit cae07b5 into microsoft:main Nov 22, 2024
31 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area: dds: tree area: dds Issues related to distributed data structures base: main PRs targeted against main branch changeset-present public api change Changes to a public API
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants