Skip to content

Port text-editor to shared example setup - #28259

Merged
Craig Macomber (Microsoft) (CraigMacomber) merged 5 commits into
microsoft:mainfrom
CraigMacomber:text-example
Sep 19, 2026
Merged

Craig Macomber (Microsoft) (CraigMacomber) merged 5 commits into
microsoft:mainfrom
CraigMacomber:text-example

Conversation

@CraigMacomber

@CraigMacomber Craig Macomber (Microsoft) (CraigMacomber) commented Sep 19, 2026

Copy link
Copy Markdown
Contributor

Description

Migrate text-editor to the shared ServiceClient and webpack setup used by inventory-app.
Devtools support required an extension to ServiceClient to support a logger which is included.

Add shared loading and error views with service-specific troubleshooting, and use them in both examples. Reuse the React root across startup transitions so guidance remains visible while connections retry.

Validation included interactive use of both examples suing this new pattern and checking dev tools work were working.

Reviewer Guidance

The review process is outlined in the pull request guidelines.

Copilot AI lite review requested due to automatic review settings September 19, 2026 01:28
@github-actions github-actions Bot added area: examples Changes that focus on our examples area: tools area: repo Repo related work dependencies Pull requests that update a dependency file area: website base: main PRs targeted against main branch labels Sep 19, 2026
@github-actions

github-actions Bot commented Sep 19, 2026

Copy link
Copy Markdown
Contributor

Hi! Thank you for opening this PR. Want me to review it?

Based on the diff (693 lines, 19 files), I've queued these reviewers:

  • Correctness — logic errors, race conditions, lifecycle issues
  • Security — vulnerabilities, secret exposure, injection
  • API Compatibility — breaking changes, release tags, type design
  • Performance — algorithmic regressions, memory leaks
  • Testing — coverage gaps, hollow tests

How this works

  • Adjust the reviewer set by ticking/unticking boxes above. Reviewer toggles alone don't trigger anything.

  • Tick Start review below to dispatch the review fleet.

  • After review finishes, tick Start review again to request another run — it auto-resets after each dispatch.

  • This comment updates as new commits land; your reviewer selections are preserved.

  • Start review

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot review overview

🟢 Approval recommended

The only remaining comment is a minor test-coverage nit, with no approval-blocking issues identified.

Review effort: Lite
Findings: None

What changed in this PR

Migrates the text editor to shared ServiceClient startup infrastructure and reusable loading/error views while preserving collaboration and Devtools behavior.

Changes:

  • Supports session, ephemeral, and Tinylicious services.
  • Reuses React roots across startup transitions.
  • Updates tests, documentation, webpack configuration, and dependencies.
File Description
pnpm-lock.yaml Updates workspace dependency links.
examples/​utils/​example-utils/​src/​test/​exampleApp.spec.ts Tests startup views and service selection.
examples/​utils/​example-utils/​src/​index.ts Exports shared startup views.
examples/​utils/​example-utils/​src/​exampleApp.ts Adds shared views and React root reuse.
examples/​data-objects/​text-editor/​webpack.config.cjs Uses shared webpack configuration.
examples/​data-objects/​text-editor/​tests/​textEditor.test.ts Adds multi-service collaboration coverage.
examples/​data-objects/​text-editor/​src/​test/​app.test.tsx Updates component test fixtures.
examples/​data-objects/​text-editor/​src/​app.tsx Migrates to ServiceClient and Devtools setup.
examples/​data-objects/​text-editor/​README.md Documents services and compatibility limitations.
examples/​data-objects/​text-editor/​package.json Updates scripts and dependencies.
examples/​data-objects/​inventory-app/​src/​index.ts Adds shared loading and error handling.
Files not reviewed (1)
  • pnpm-lock.yaml: Generated file

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

@github-actions github-actions Bot added area: framework Framework is a tag for issues involving the developer framework. Eg Aqueduct area: driver Driver related issues public api change Changes to a public API changeset-present labels Sep 19, 2026
@CraigMacomber Craig Macomber (Microsoft) (CraigMacomber) changed the title Port text-editor to shared example setup and startup views Port text-editor to shared example setup Sep 19, 2026
@github-actions

Copy link
Copy Markdown
Contributor

🔗 No broken links found! ✅

Your attention to detail is admirable.

linkcheck output

$ start-server-and-test "npm run serve -- --host 127.0.0.1 --no-open" http://127.0.0.1:3000 check-links
1: starting server using command "npm run serve -- --host 127.0.0.1 --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"


> fluid-framework-website@0.0.0 serve
> docusaurus serve --host 127.0.0.1 --no-open

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

> fluid-framework-website@0.0.0 check-links
> linkcheck http://127.0.0.1:3000 --skip-file skipped-urls.txt

Crawling...

Stats:
  658102 links
    3579 destination URLs
    3898 URLs ignored
       0 warnings
       0 errors


@github-actions

Copy link
Copy Markdown
Contributor

Bundle size comparison

Base commit: f469232c2bc8613a23c68e4edde1914da0d78f88
Head commit: 33590bb8d5a38d2e80644ddd479e2b18b1f8d245

Notable changes

No bundles changed by ≥ 500 bytes parsed.

Per-bundle deltas

@fluid-example/bundle-size-tests

  • fluidFrameworkAllAlpha.js: parsed 801533 → 801589 (+56), gzip 220527 → 220600 (+73)
  • azureClient.js: parsed 634336 → 634331 (-5), gzip 169989 → 170074 (+85)
  • odspClient.js: parsed 606600 → 606711 (+111), gzip 163052 → 163198 (+146)
  • aqueduct.js: parsed 533117 → 533128 (+11), gzip 143294 → 143338 (+44)
  • fluidFramework.js: parsed 415378 → 415411 (+33), gzip 117810 → 117845 (+35)
  • sharedTree.js: parsed 404757 → 404783 (+26), gzip 115252 → 115271 (+19)
  • containerRuntime.js: parsed 315027 → 315009 (-18), gzip 86438 → 86439 (+1)
  • sharedString.js: parsed 170105 → 170112 (+7), gzip 48455 → 48462 (+7)
  • experimentalSharedTree.js: parsed 161846 → 161846 (0), gzip 46722 → 46722 (0)
  • matrix.js: parsed 153720 → 153727 (+7), gzip 44381 → 44388 (+7)
  • loader.js: parsed 147328 → 147344 (+16), gzip 40038 → 40049 (+11)
  • odspDriver.js: parsed 106695 → 106753 (+58), gzip 33227 → 33294 (+67)
  • directory.js: parsed 65669 → 65676 (+7), gzip 18493 → 18502 (+9)
  • 578.js: parsed 58686 → 58686 (0), gzip 17657 → 17657 (0)
  • odspPrefetchSnapshot.js: parsed 46463 → 46444 (-19), gzip 15512 → 15522 (+10)
  • map.js: parsed 45820 → 45827 (+7), gzip 14120 → 14127 (+7)
  • 252.js: parsed 44384 → 44384 (0), gzip 13741 → 13741 (0)
  • summarizerDelayLoadedModule.js: parsed 31287 → 31287 (0), gzip 7929 → 7929 (0)
  • socketModule.js: parsed 27108 → 27078 (-30), gzip 8069 → 8103 (+34)
  • createNewModule.js: parsed 12464 → 12464 (0), gzip 4792 → 4805 (+13)
  • summaryModule.js: parsed 3888 → 3888 (0), gzip 1874 → 1874 (0)
  • connectionState.js: parsed 909 → 909 (0), gzip 500 → 500 (0)
  • sharedTreeAttributes.js: parsed 845 → 852 (+7), gzip 496 → 505 (+9)
  • debugAssert.js: parsed 429 → 429 (0), gzip 299 → 299 (0)
  • FluidFramework-HashFallback.js: parsed 419 → 419 (0), gzip 313 → 313 (0)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Left some suggestions, but overall looks good.

"fluid-framework": minor
"__section": feature
---

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Suggested change


Collect container telemetry through ServiceClient

The alpha `ServiceOptions` interface now accepts an optional `logger`.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Nit: API docs link (assuming they're available)?

// eslint-disable-next-line import-x/no-internal-modules -- TODO: migrate to `FormattedText` with explicit parameterization.
import { FormattedTextDefault } from "@fluidframework/tree/internal";
import type { IFluidContainer } from "fluid-framework";
import { configuredSharedTree, FormattedTextDefault } from "@fluidframework/tree/internal";

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Nit: do we need to import this from the internal entrypoint?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

And actually, since we're importing other things from fluid-framework, do we need to be importing anything from tree directly at all?

Comment on lines +90 to 104
const TextEditorDataStore = defineDataStore<TextEditorData, ITree>({
type: "text-editor",
registry: sharedObjectRegistryFromIterable([SharedTree]),
instantiateFirstTime: async (rootCreator, creator) =>
instantiateTreeFirstTime(rootCreator, creator, SharedTree, {
config: treeConfig,
initializer: () => createInitialRoot(),
}),
endpoint: getTinyliciousEndpoint(),
};
view: async (tree) => ({ tree, treeView: asAlpha(tree.viewWith(treeConfig)) }),
});

interface TextEditorData {
tree: ITree;
treeView: TreeViewAlpha<typeof TextEditorRoot>;
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Nit: docs (since this is an example)?

* Generates a fresh {@link UserId}.
*
* Random so simulated users stay unique in the document's audience even across page
* Random so simulated users stay unique across page

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Nit

Suggested change
* Random so simulated users stay unique across page
* @remarks
* This is random so simulated users stay unique across page

const { container, treeView } = await loadExistingContainer(client, containerId);
return { id, container, treeView };
}
type ConnectUser = (containerId: string) => Promise<UserView>;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Nit: docs (since this is an example)?

}
type ConnectUser = (containerId: string) => Promise<UserView>;

async function initFluid(): Promise<{

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Not necessarily for this PR, but we should probably rename this to "initializeFluid" or "initializeFluidContainer" or something to better follow our guidelines.

containerId: string;
devtoolsLogger: IDevtoolsLogger;
initialUsers: UserView[];
connectUser: ConnectUser;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Nit: param docs?

return { id: makeUserId(), container: loaded, treeView: loaded.data.treeView };
};
const rawContainerId = location.hash.slice(1);
if (rawContainerId.length > 0 && !/^[\dA-Za-z-]{3,64}$/.test(rawContainerId)) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Docs here would probably be useful. IMO regex_s should always be at least minimally documented.

@@ -3,67 +3,27 @@
* Licensed under the MIT License.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

So much simpler!!

@CraigMacomber

Copy link
Copy Markdown
Contributor Author

I'm going to merge this, and make a new PR addressing all of your excellent feedback.

@CraigMacomber
Craig Macomber (Microsoft) (CraigMacomber) merged commit 1126100 into microsoft:main Sep 19, 2026
38 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: driver Driver related issues area: examples Changes that focus on our examples area: framework Framework is a tag for issues involving the developer framework. Eg Aqueduct area: repo Repo related work area: tools area: website base: main PRs targeted against main branch changeset-present dependencies Pull requests that update a dependency file public api change Changes to a public API

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants