Skip to content

Commit 9097e85

Browse files
committed
Merge main
2 parents f94ff87 + 6aaac7e commit 9097e85

File tree

593 files changed

+7736
-3555
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

593 files changed

+7736
-3555
lines changed

.changeset/mighty-bugs-yell.md

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
---
2+
"fluid-framework": minor
3+
"@fluidframework/tree": minor
4+
"__section": feature
5+
---
6+
Add push as alias for insertAtEnd on TreeArrayNode
7+
8+
#### Why this change
9+
10+
Adding push as an alias makes the API more intuitive and reduces friction for both `LLM` generated code and developers familiar with JavaScript array semantics.
11+
12+
#### Usage
13+
14+
```typescript
15+
import { TreeArrayNode } from "@fluidframework/tree";
16+
17+
// `inventory` is a TreeArrayNode from your schema.
18+
inventory.push({ name: "Apples", quantity: 3 });
19+
20+
// Insert multiple items in one call.
21+
inventory.push(
22+
TreeArrayNode.spread([
23+
{ name: "Oranges", quantity: 2 },
24+
{ name: "Bananas", quantity: 5 },
25+
]),
26+
);
27+
```

.changeset/yummy-oranges-attack.md

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
---
2+
"fluid-framework": minor
3+
"@fluidframework/tree": minor
4+
"__section": feature
5+
---
6+
Adds optional `label` parameter to `runTransaction` for grouping changes.
7+
8+
Transaction labels can be used to group multiple changes for undo/redo, where groups of changes with the same label can be undone together. When multiple labels are used in nested transactions, only the outermost label will be used.
9+
10+
The following example demonstrates how to implement label-based undo/redo grouping. It listens to the `changed` event on the checkout to collect all commits with the same label into a group. When `undoLatestGroup()` is called, all transactions in that group are reverted together with a single operation.
11+
12+
```typescript
13+
interface LabeledGroup {
14+
label: unknown;
15+
revertibles: { revert(): void }[];
16+
}
17+
18+
const undoGroups: LabeledGroup[] = [];
19+
20+
// The callback on the "changed" event can be used to group the commits.
21+
view.checkout.events.on("changed", (meta, getRevertible) => {
22+
// Only process local edits, not remote changes or Undo/Redo operations
23+
if (getRevertible !== undefined && meta.kind === CommitKind.Default) {
24+
const label = meta.label;
25+
const revertible = getRevertible();
26+
27+
// Check if the latest group contains the same label.
28+
const latestGroup = undoGroups[undoGroups.length - 1];
29+
if (
30+
label !== undefined &&
31+
latestGroup !== undefined &&
32+
label === latestGroup.label
33+
) {
34+
latestGroup.revertibles.push(revertible);
35+
} else {
36+
undoGroups.push({ label, revertibles: [revertible] });
37+
}
38+
}
39+
});
40+
41+
const undoLatestGroup = () => {
42+
const latestGroup = undoGroups.pop() ?? fail("There are currently no undo groups.");
43+
for (const revertible of latestGroup.revertibles.reverse()) {
44+
revertible.revert();
45+
}
46+
};
47+
48+
// Group multiple transactions with the same label
49+
view.runTransaction(() => { view.root.content = 1; }, { label: "EditGroup" });
50+
view.runTransaction(() => { view.root.content = 2; }, { label: "EditGroup" });
51+
view.runTransaction(() => { view.root.content = 3; }, { label: "EditGroup" });
52+
53+
// This would undo all three transactions together.
54+
undoLatestGroup();
55+
// view.root.content is now back to 0 (the initial state).
56+
```

.github/CODEOWNERS

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
# ORDER MATTERS! The last matching pattern has the most precedence.
1717
# Be careful not to break existing ownership patterns.
1818
#
19-
# Do not assign ownership to indviduals. Use a Team: https://github.com/orgs/microsoft/teams/fluid-cr/teams .
19+
# Do not assign ownership to individuals. Use a Team: https://github.com/orgs/microsoft/teams/fluid-cr/teams .
2020
# Using individuals can break processing of this file if they are not contributors, or lose contributors status
2121
# which can and does happen. Use "function/area-based" teams rather than "organization-based" teams and add
2222
# individuals to each one; we use fluid-cr and its child teams (by convention named fluid-cr-<some-specifier>)
@@ -52,6 +52,9 @@
5252
/packages/dds/tree/src @microsoft/fluid-cr-tree
5353
/experimental/dds/tree/src @microsoft/fluid-cr-tree
5454

55+
# presence source
56+
/packages/framework/presence/src @microsoft/fluid-cr-presence
57+
5558
# Fluid Devtools source
5659
/packages/tools/devtools/**/src @microsoft/fluid-cr-devtools
5760

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
---
2+
name: Beta Breaking Change Collection
3+
about: Track beta breaking changes for specific release
4+
title: "Client 2.#0 Beta | Legacy Breaking Changes [Open for additions]"
5+
labels: ""
6+
assignees: ""
7+
---
8+
9+
The attached sub-issues chronicle all of the major (breaking) changes to take place in client 2.#0 release for `/beta` and `/legacy` APIs (tagged `@beta`).
10+
11+
| | |
12+
| -------------------------- | ------------ |
13+
| List status | In development until 2026-mm-dd |
14+
| Estimated Release Date | 2026-mm-dd |

DEV.md

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,114 @@ The following dependencies are pinned to older major versions because newer vers
1616
- Impact: FluidFramework packages ship dual ESM/CJS builds. When consumers `require()` our packages, the CJS output would fail to `require('uuid')` since uuid v12+ is ESM-only.
1717
- Used in: Many packages across the repo (telemetry-utils, container-loader, odsp-driver, etc.)
1818

19+
## ESLint and typescript-eslint
20+
21+
### projectService vs explicit project arrays
22+
23+
The shared ESLint config uses `parserOptions.projectService: true` by default for TypeScript files. This is the recommended approach as of typescript-eslint v8. However, some packages require explicit `parserOptions.project` arrays due to non-standard tsconfig structures.
24+
25+
#### Why projectService is preferred
26+
27+
`projectService: true` uses TypeScript's Language Service API (the same API VS Code uses), which correctly handles advanced type features like `asserts this is` type narrowing. The explicit `project` array approach creates separate TypeScript Program instances that don't handle type narrowing across statements as well.
28+
29+
#### CLI vs VS Code discrepancies
30+
31+
If you see ESLint errors in the CLI that don't appear in VS Code (or vice versa), the cause is likely a mismatch in projectService settings:
32+
33+
- **VS Code's ESLint extension** may default to `projectService: true`
34+
- **CLI** uses whatever is configured in `eslint.config.mts`
35+
36+
When these differ, the same code can produce different type information, causing false positives or missed errors. For example, `asserts this is` type narrowing may work correctly with projectService but fail with explicit project arrays.
37+
38+
**To diagnose:**
39+
1. Check if the package's `eslint.config.mts` has `projectService: false` with an explicit `project` array
40+
2. If so, VS Code may be using projectService while CLI uses the explicit array
41+
3. Ensure VS Code's ESLint settings match the CLI configuration, or update the package to use projectService if possible
42+
43+
#### When projectService works
44+
45+
projectService works when all TypeScript files are covered by tsconfigs that are **discoverable**. A tsconfig is discoverable if:
46+
1. It is named `tsconfig.json` and exists in the directory ancestry of the source file, OR
47+
2. It is referenced (directly or transitively) via project references from a discoverable `tsconfig.json`
48+
49+
For example:
50+
- `./tsconfig.json` references `./tsconfig.main.json` → both are discoverable
51+
- `./tsconfig.json` references `./src/test/tsconfig.json` → test config is discoverable
52+
- `./tsconfig.jest.json` with no reference from any `tsconfig.json` → NOT discoverable
53+
54+
#### When explicit project arrays are required
55+
56+
Explicit `parserOptions.project` arrays are needed when files exist that are **not covered** by any discoverable tsconfig.
57+
58+
Common scenarios requiring explicit arrays:
59+
- **Standalone non-standard tsconfig naming** - e.g., `tsconfig.jest.json` or `tsconfig.cjs.lint.json` that is NOT referenced by any `tsconfig.json`
60+
- **Files intentionally excluded from the main tsconfig graph** - e.g., test files compiled separately to test different compiler options like `exactOptionalPropertyTypes`, where referencing them from the main tsconfig would cause double-compilation
61+
- **Test-only packages without root tsconfig.json** - no entry point for projectService to discover
62+
63+
These packages have comments in their `eslint.config.mts` explaining why explicit project arrays are needed.
64+
65+
#### Key limitation: projectService only recognizes `tsconfig.json`
66+
67+
The projectService **only looks for files named `tsconfig.json`**. It does not recognize `tsconfig.eslint.json`, `tsconfig.jest.json`, `tsconfig.test.json`, or any other naming convention. This is intentional - the typescript-eslint team made this choice to ensure consistency between editor type information and linting.
68+
69+
This means:
70+
- Non-standard tsconfig naming requires falling back to explicit `project` arrays
71+
- Files excluded from one `tsconfig.json` but needing a different tsconfig cannot use projectService
72+
73+
#### Why `allowDefaultProject` doesn't help
74+
75+
`allowDefaultProject` is designed for a **small number of out-of-project files** (like `eslint.config.js` or `vitest.config.ts`):
76+
- Default limit of 8 files
77+
- Cannot use `**` glob patterns
78+
- Significant performance overhead per file
79+
- Not suitable for test directories or large numbers of files
80+
81+
#### Potential restructuring to enable projectService
82+
83+
To maximize projectService usage, packages could be restructured to follow typescript-eslint's recommendations:
84+
85+
1. **Use `tsconfig.json` as the "lint" config** (what editors see)
86+
2. **Use `tsconfig.build.json` for build-specific settings** (inverts the common pattern of `tsconfig.eslint.json`)
87+
3. **Ensure every directory with TypeScript files has a `tsconfig.json`** that includes those files
88+
4. **Use project references** to connect all tsconfigs
89+
90+
For example, a test-only package without a root tsconfig could add one:
91+
92+
```json
93+
// root tsconfig.json
94+
{
95+
"files": [],
96+
"references": [
97+
{ "path": "./src/test" }
98+
]
99+
}
100+
```
101+
102+
However, some scenarios are fundamentally incompatible with projectService:
103+
- **Files that cannot be referenced from the main tsconfig graph** - For example, test files that need different compiler options (like `exactOptionalPropertyTypes: false`) and would cause double-compilation if referenced. These files are intentionally excluded from the main tsconfig and use a separate tsconfig that cannot be added as a project reference.
104+
- **Files needing different compiler settings than projectService would provide** - projectService uses the nearest discoverable `tsconfig.json`. If files need settings from a different tsconfig that isn't in their directory ancestry and can't be referenced, explicit arrays are required.
105+
106+
For these cases, use flat config overrides targeting specific file patterns:
107+
108+
```typescript
109+
{
110+
files: ['**/*.cjs.ts'],
111+
languageOptions: {
112+
parserOptions: {
113+
projectService: false,
114+
project: ['./tsconfig.cjs.lint.json'],
115+
},
116+
},
117+
}
118+
```
119+
120+
#### References
121+
122+
- [Typed Linting with Project Service](https://typescript-eslint.io/blog/project-service/) - Official blog post
123+
- [@typescript-eslint/parser documentation](https://typescript-eslint.io/packages/parser/) - Parser options reference
124+
- [Monorepo Configuration](https://typescript-eslint.io/troubleshooting/typed-linting/monorepos/) - Monorepo-specific guidance
125+
- [GitHub Issue #7383](https://github.com/typescript-eslint/typescript-eslint/issues/7383) - Custom tsconfig names (closed as not planned)
126+
19127
## pnpm Supply Chain Security Settings
20128

21129
All workspace `pnpm-workspace.yaml` files include security-hardening settings to protect against supply chain attacks. This section documents these settings and their rationale.

azure/packages/azure-local-service/biome.jsonc

Lines changed: 0 additions & 4 deletions
This file was deleted.

azure/packages/azure-local-service/eslint.config.mts

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,17 +6,6 @@
66
import type { Linter } from "eslint";
77
import { strict } from "../../../common/build/eslint-config-fluid/flat.mts";
88

9-
const config: Linter.Config[] = [
10-
...strict,
11-
{
12-
files: ["**/*.ts", "**/*.tsx", "**/*.mts", "**/*.cts"],
13-
languageOptions: {
14-
parserOptions: {
15-
projectService: false,
16-
project: ["./tsconfig.eslint.json"],
17-
},
18-
},
19-
},
20-
];
9+
const config: Linter.Config[] = [...strict];
2110

2211
export default config;

azure/packages/azure-service-utils/biome.jsonc

Lines changed: 0 additions & 4 deletions
This file was deleted.

0 commit comments

Comments
 (0)