microsoft / microsoft/FluidFramework

Duplicate Code: repoPolicyCheck updatePackageJsonFile resolver boilerplate

Open
#26,922 0 comments 1 reaction 2 assignees View on GitHub

@Abe27342 is already working on this.

Since Apr 7, 2026.

  • #26961 by @copilot-swe-agent — closed without merging
Dominant language
TypeScript
Stars
4.9k
Forks
586
Avg merge
1d 15h
Merged PRs (30d)
146

Description

Analysis of commit 688c05dd39779ee023a5bb8fed97d59b64b4e6e2

Assignee: @copilot

Summary

Multiple repoPolicyCheck rules duplicate the same resolver boilerplate pattern: create a { resolved, message? } result, call updatePackageJsonFile(path.dirname(file), (json) => { ... }), sometimes mutate result on errors, then return result.

This repetition appears several times within npmPackages.ts and again in fluidBuildTasks.ts. It’s a maintainability smell: future adjustments to resolver behavior (error handling, logging, dry-run semantics, etc.) require updating many near-identical blocks.

Duplication Details

Pattern: “resolver wrapper around updatePackageJsonFile”
  • Severity: Medium
  • Occurrences: 7 (6 in npmPackages.ts, 1 in fluidBuildTasks.ts)
  • Locations:
    • build-tools/packages/build-cli/src/library/repoPolicyCheck/npmPackages.ts
      • lines 840–863 (simple updatePackageJsonFile(...) then return { resolved: true })
      • lines 1122–1160 (similar structure)
      • lines 1292–1303 (const result ... updatePackageJsonFile ... return result)
      • lines 1586–1604 (const result ... updatePackageJsonFile ... return result)
      • lines 1723–1737 (const result ... updatePackageJsonFile ... return result)
      • lines 1919–1965 (const result ... updatePackageJsonFile ... return result)
    • build-tools/packages/build-cli/src/library/repoPolicyCheck/fluidBuildTasks.ts
      • lines 904–939 (let result ... updatePackageJsonFile ... return result)
Code Sample (excerpt)

From npmPackages.ts (around 1722):

resolver: (file: string): { resolved: boolean; message?: string } => {
	const result: { resolved: boolean; message?: string } = { resolved: true };
	updatePackageJsonFile(path.dirname(file), (json) => {
		if (shouldCheckExportsField(json)) {
			try {
				const exportsField = generateExportsField(json);
				json.exports = exportsField;
			} catch (error: unknown) {
				result.resolved = false;
				result.message = (error as Error).message;
			}
		}
	});
	return result;
}

From fluidBuildTasks.ts (around 904):

resolver: (file: string, root: string): { resolved: boolean; message?: string } => {
	let result: { resolved: boolean; message?: string } = { resolved: true };
	updatePackageJsonFile(path.dirname(file), (json) => {
		// ...
		try {
			// compute/patch deps
		} catch (error: unknown) {
			result = { resolved: false, message: (error as Error).message };
			return;
		}
	});
	return result;
}

Impact Analysis

  • Maintainability: Resolver behavior is spread across many copies; refactors require repetitive edits and risk inconsistency.
  • Bug Risk: Small differences in copied patterns (e.g., whether errors are caught, whether result is reassigned vs mutated) can lead to inconsistent outcomes.
  • Code Bloat: The repeated scaffolding obscures the actual policy-specific logic.

Refactoring Recommendations

  1. Extract a shared resolver helper

    • Suggested location: build-tools/packages/build-cli/src/library/repoPolicyCheck/common.ts
    • Example shape:
      • makeUpdatePackageJsonResolver((packageJson, ctx) => void, { onError?: ... })
      • or runUpdatePackageJsonResolver(fileOrDir, (json) => { ... }) => { resolved, message? }
    • Benefits: centralizes result creation, consistent error handling, and optionally supports async variants.
  2. Normalize error handling semantics

    • Decide whether resolver callbacks should throw (and be caught centrally) or mutate a result object.
    • Benefits: fewer subtle differences, easier to test.

Implementation Checklist

  • Identify all updatePackageJsonFile(...) resolver call sites under repoPolicyCheck/
  • Add shared helper API in common.ts
  • Refactor the duplicated resolvers to use the helper
  • Ensure resolver return types and messages remain identical
  • Run existing policy-check tests/commands to validate behavior

Analysis Metadata

  • Analyzed Files: Top-churn + targeted cross-reference in build-tools/packages/build-cli/src/library/repoPolicyCheck/ and server/routerlicious/
  • Detection Method: Serena semantic symbol search + pattern search
  • Commit: 688c05dd39779ee023a5bb8fed97d59b64b4e6e2
  • Analysis Date: 2026-04-01T21:51:29.453Z

Generated by Duplicate Code Detector ·

To install this agentic workflow, run

gh aw add github/gh-aw/.github/workflows/duplicate-code-detector.md@94662b1dee8ce96c876ba9f33b3ab8be32de82a4

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.