Skip to content

example: add cross-package SharedTree schema consumption example #26522

Open
WillieHabi wants to merge 23 commits intomicrosoft:mainfrom
WillieHabi:cross-package-schema
Open

example: add cross-package SharedTree schema consumption example #26522
WillieHabi wants to merge 23 commits intomicrosoft:mainfrom
WillieHabi:cross-package-schema

Conversation

@WillieHabi
Copy link
Contributor

@WillieHabi WillieHabi commented Feb 23, 2026

Description

Adds a minimal two-package example (schema-provider + schema-consumer) demonstrating cross-package consumption of SharedTree schemas defined with objectAlpha().

Also merges the tree entrypoint fix from jason-ha@4c04950, which restructures @fluidframework/tree's package.json exports so each API tier (., ./alpha, ./beta, etc.) has its own JS entrypoint.

With this fix, the example consumer imports schemas through standard imports with no workarounds needed.

Copilot AI review requested due to automatic review settings February 23, 2026 22:17
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Adds a new examples/utils/cross-package-schema two-package example intended to demonstrate consuming SharedTree objectAlpha() schemas across package boundaries by using TypeScript customConditions: ["source"] and a "source" export condition to bypass problematic .d.ts path normalization under TS 5.9 + moduleResolution: "bundler".

Changes:

  • Add a new schema-provider package exporting SharedTree schema classes with a "source" export condition and a TS 5.9 “bundler” build mode to reproduce the .d.ts issue.
  • Add a new schema-consumer package that imports the provider’s schemas and demonstrates success/failure with and without customConditions: ["source"].
  • Add documentation and lockfile updates to wire the new example packages into the repo.

Reviewed changes

Copilot reviewed 13 out of 14 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
pnpm-lock.yaml Adds new workspace importers for the provider/consumer example packages and updates a dependency resolution entry.
examples/utils/cross-package-schema/README.md Documents the problem, the "source"-condition workaround, and verification steps.
examples/utils/cross-package-schema/schema-provider/package.json Defines the provider package exports (including "source"), build scripts, and dependencies.
examples/utils/cross-package-schema/schema-provider/tsconfig.json Provider baseline TS config for Node16 resolution output to lib.
examples/utils/cross-package-schema/schema-provider/tsconfig.bundler.json Provider TS 5.9+ bundler-resolution config to reproduce .d.ts normalization.
examples/utils/cross-package-schema/schema-provider/src/schema.ts Declares a small set of objectAlpha()-based schema classes to export.
examples/utils/cross-package-schema/schema-provider/src/index.ts Re-exports the provider schema classes as the public entrypoint.
examples/utils/cross-package-schema/schema-provider/eslint.config.mts Adds local ESLint flat-config wiring consistent with other examples.
examples/utils/cross-package-schema/schema-consumer/package.json Defines the consumer package scripts for the “with source condition” pass and “without source condition” failure demonstration.
examples/utils/cross-package-schema/schema-consumer/tsconfig.json Enables customConditions: ["source"] for the success-path typecheck.
examples/utils/cross-package-schema/schema-consumer/tsconfig.no-source.json Consumer TS config variant that omits customConditions to reproduce the failure.
examples/utils/cross-package-schema/schema-consumer/src/consume.ts Imports provider schemas and constructs a TreeViewConfiguration to validate compatibility.
examples/utils/cross-package-schema/schema-consumer/src/index.ts Re-exports the consumer example entrypoint/types.
examples/utils/cross-package-schema/schema-consumer/eslint.config.mts Adds local ESLint flat-config wiring consistent with other examples.
Files not reviewed (1)
  • pnpm-lock.yaml: Language not supported

WillieHabi and others added 10 commits February 23, 2026 16:40
relying on tree exports being setup for normal consumption patterns - no special setup to share schema across packages
Stage tree entrypoint files such that none reference index.js directly that may result in consumer packages generating .d.ts files with incorrect tree imports.

tree entrypoints are no longer generated during build. Changes for exposed API surface require updating files under src/entrypoints, which may use ` generate:entrypoint-sources` script.

Update entrypoint linting to use new sources, but keep them from being formatted or linted.

Until 0.64 build-tools are used, legacy.d.ts Node10 file won't be generated and is temporarily checked in.
Stage tree entrypoint files such that none reference index.js directly that may result in consumer packages generating .d.ts files with incorrect tree imports.

tree entrypoints are no longer generated during build. Changes for exposed API surface require updating files under src/entrypoints, which may use ` generate:entrypoint-sources` script.

Update entrypoint linting to use new sources, but keep them from being formatted or linted.

Until 0.64 build-tools are used, legacy.d.ts Node10 file won't be generated and is temporarily checked in.
@WillieHabi WillieHabi requested a review from a team as a code owner March 2, 2026 17:44
@WillieHabi WillieHabi force-pushed the cross-package-schema branch from cb3ee9f to 703cb3f Compare March 2, 2026 18:18
@WillieHabi WillieHabi requested a review from jason-ha March 2, 2026 18:21
WillieHabi and others added 6 commits March 2, 2026 10:54
Tree's generate:entrypoint-sources script produces files that overlap
with tsc output, causing policy check failures.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
into a bash script that policy checker doesn't understand.
Copy link
Contributor

@jason-ha jason-ha left a comment

Choose a reason for hiding this comment

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

Looks pretty good - you'll obviously need another review since I have decent contributions in here.
Do update the PR title and description.
Apologies if this posts with seemingly irrelevant comments. I apparently never submitted notes I had from last week. I tried to cleanup things that I could see to be accurate.

Comment on lines +24 to +25
"types": "./src/index.ts",
"default": "./lib/index.js"
Copy link
Contributor

Choose a reason for hiding this comment

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

Should only support "import" condition - like is used in ".".

"compilerOptions": {
"rootDir": "./src",
"outDir": "./lib",
"exactOptionalPropertyTypes": false,
Copy link
Contributor

Choose a reason for hiding this comment

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

Do you need this? We prefer to not have this setting when possible.
I think you do - should comment on the need.

## The Problem

When SharedTree schema classes are defined using `objectAlpha()` and compiled with
TypeScript 5.9+ using `moduleResolution: "bundler"`, the `.d.ts` emitter normalizes import
Copy link
Contributor

Choose a reason for hiding this comment

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

Is using bundler resolution a part of the problem? I didn't think that was part of the issue. The only issue as I understood it was working with generated .d.ts files.

Copy link
Contributor

Choose a reason for hiding this comment

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

Whoa. I'm reading step 1 below. That suggests bundler is part of the problem. So, the solution is maybe is don't use bundler resolution for your schema package? (office-bohemia doesn't require bundler resolution. It is largely used because it has relaxed rules. But should be easy to build schema package with node16 resolution.)

Comment on lines +27 to +28
},
"scripts": {
Copy link
Contributor

Choose a reason for hiding this comment

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

For completeness, there should be a "files" block in here. "files" says what files are actually part of a published package. See presence package for an example. In this case, we want to call out src explicitly as some or all of it is needed. (Even if there aren't test files, I would exclude those paths to set a good example.)

The above is an old comment that was never apparently published. It matters more and less now that we don't need to publish src. More because a proper package wouldn't have to publish them. Less because this is super simple now.

biome.jsonc Outdated
"!**/src/**/test/types/**/*.generated.ts",
"!**/src/packageVersion.ts",
"!**/src/layerGenerationState.ts",
"!**/src/entrypoints/*.ts",
Copy link
Contributor

Choose a reason for hiding this comment

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

We do not want a broad disable of src/entrypoints from biome. The disable in tree should be temporary. If the package level biome config is a problem, then make this "absolute" just for tree with a comment.

Comment on lines -30428 to +30499
minimatch: 10.1.1
minimatch: 10.2.1
Copy link
Contributor

Choose a reason for hiding this comment

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

okay, I think, but rogue unrelated change

Comment on lines +7 to +8
// Need to skip lib check since some .d.ts from provider are invalid.
"skipLibCheck": true,
Copy link
Contributor

Choose a reason for hiding this comment

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

No longer the case. All builds should be good.

@jason-ha
Copy link
Contributor

jason-ha commented Mar 3, 2026

Do update the PR title and description.

Do borrow liberally from jason-ha@4c04950 description. I am not planning on submitting those separately as we want to have tests in place. You get the credit. :)

@CraigMacomber
Copy link
Contributor

CraigMacomber commented Mar 3, 2026

If possible, do testing of stuff like this in the import-testing package, which exists for the purpose of testing the exporting of content using fluid types then importing of them.

Realistically I believe what you want to test is d.ts generation and consumption, which can be done with two ts projects in a single package, which is how import-testing is setup. This approach should be able to test what we need, as well as serve as examples of how to do it, while not requiring extra packages.

Note that this package already has tests/example for a lot of schema related APIs.

*/

/*
* THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
Copy link
Contributor

Choose a reason for hiding this comment

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

I'd prefer we don't commit auto generated files, and instead have them produces as part of the build, unless it is intended for human auditing like API reports. As we already have an API report for these, I don't think we want this as well for the same purpose.

Copy link
Contributor

Choose a reason for hiding this comment

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

This is exactly the plan. The API report files give us one thing, but they don't tell us what is exactly happening and we can miss things.
InternalTypes is an example of that. Our current "generate entrypoints" actually emits and error for InternalTypes but you don't see it when run as part of the task infrastructure - run it on its own to see. You can also look at the current lib/public.d.ts to see the funkiness.
In the future (see AB#14504), we'll be able to review API surface changes more easily (easier to understand) than with API reports. (Though we'll likely keep one API report to keep track of documented/undocumented and tags.)
In some cases, we may want to temporarily or permanently handcraft parts of the entrypoint files.

This result is not exactly what we want, but it is sufficient.

@jason-ha
Copy link
Contributor

jason-ha commented Mar 3, 2026

If possible, do testing of stuff like this in the import-testing package, which exists for the purpose of testing the exporting of content using fluid types then importing of them.

Realistically I believe what you want to test is d.ts generation and consumption, which can be done with two ts projects in a single package, which is how import-testing is setup. This approach should be able to test what we need, as well as serve as examples of how to do it, while not requiring extra packages.

Note that this package already has tests/example for a lot of schema related APIs.

I think testing can be relocated. I don't know that need (see below) to bother with two ts projects, though I know you can test that way as one form of setup in my personal iterations had observed that.

I do know that these cases need to be isolated. I observed too many things that would avoid recreating the issue. Maybe separate project is the best to help ensure that.

I don't think it is bad to have a clear example of practical use. Multiple ts projects does complicate the build a bit and is a lot less obvious.

I'm okay with this or rolled into import-testing.

@jason-ha
Copy link
Contributor

jason-ha commented Mar 3, 2026

@WillieHabi, to fix the build break probably should apply this diff to fluidBuild.config.cjs:

-		"build:api-reports:current": ["api-extractor:esnext"],
-		"build:api-reports:legacy": ["api-extractor:esnext"],
-		"ci:build:api-reports:current": ["api-extractor:esnext"],
-		"ci:build:api-reports:legacy": ["api-extractor:esnext"],
+		// Depend on "build:esnext" in case there is no "api-extractor:esnext".
+		"build:api-reports:current": ["api-extractor:esnext", "build:esnext"],
+		"build:api-reports:legacy": ["api-extractor:esnext", "build:esnext"],
+		"ci:build:api-reports:current": ["api-extractor:esnext", "build:esnext"],
+		"ci:build:api-reports:legacy": ["api-extractor:esnext", "build:esnext"],

@github-actions
Copy link
Contributor

github-actions bot commented Mar 3, 2026

🔗 No broken links found! ✅

Your attention to detail is admirable.

linkcheck output


> fluid-framework-docs-site@0.0.0 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"


> fluid-framework-docs-site@0.0.0 serve
> docusaurus serve --no-open

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

> fluid-framework-docs-site@0.0.0 check-links
> linkcheck http://localhost:3000 --skip-file skipped-urls.txt

Crawling...

Stats:
  257792 links
    1822 destination URLs
    2063 URLs ignored
       0 warnings
       0 errors


Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants