microsoft / microsoft/FluidFramework

Duplicate Code: duplicated only-pnpm preinstall script across packages

Open
#26,946 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

bug
Dominant language
TypeScript
Stars
4.9k
Forks
586
Avg merge
1d 15h
Merged PRs (30d)
146

Description

Analysis of commit 258aa332a9ab237e8a72b6747968669be9d4db20

Assignee: @copilot

Summary

The same only-pnpm.cjs preinstall guard script is duplicated verbatim in multiple package subtrees. This creates unnecessary maintenance overhead and risk of divergence if the message/logic ever needs to change.

Duplication Details

Pattern: Identical only-pnpm.cjs preinstall guard script
  • Severity: Medium

  • Occurrences: 4 identical copies

  • Locations (entire file is duplicated):

    • scripts/only-pnpm.cjs (lines 1–30)
    • server/gitrest/scripts/only-pnpm.cjs (lines 1–30)
    • server/routerlicious/scripts/only-pnpm.cjs (lines 1–30)
    • server/historian/scripts/only-pnpm.cjs (lines 1–30)
  • Code Sample (representative excerpt, identical in all 4 files):

    const message = `
    ╔══════════════════════════════════════════════════════════════════╗
    ║                                                                  ║
    ║   Use "pnpm install" for installation in this project.           ║
    ║                                                                  ║
    ║   If you don't have pnpm, enable corepack via "corepack enable". ║
    ║   Then run "pnpm install" to install dependencies.               ║
    ║                                                                  ║
    ║   For more details, see the README.                              ║
    ║                                                                  ║
    ╚══════════════════════════════════════════════════════════════════╝
    `;
    
    const used_pnpm = process.env.npm_config_user_agent.startsWith(`pnpm`);
    
    if (!used_pnpm) {
    	console.error(message);
    	process.exit(1);
    }
    

Impact Analysis

  • Maintainability: Any future change (wording, behavior, guard conditions) must be repeated in 4 places.
  • Bug Risk: Copies can drift, leading to inconsistent developer experience across packages.
  • Code Bloat: Small but pure duplication (~30 LOC × 4).

Refactoring Recommendations

  1. Use a single canonical implementation

    • Keep scripts/only-pnpm.cjs as the source of truth.
    • Replace the 3 server copies with tiny wrappers that just delegate, e.g.:
      • server/*/scripts/only-pnpm.cjsrequire("../../../scripts/only-pnpm.cjs");
    • Benefits: preserves per-package entrypoint paths while centralizing logic.
  2. (Alternative) Point package.json preinstall directly at the root script

    • Update server/*/package.json preinstall scripts to reference ../../scripts/only-pnpm.cjs (or equivalent).
    • Note: only viable if these packages are never installed outside the monorepo context.

Implementation Checklist

  • Confirm whether server/* packages must support standalone installs outside the monorepo
  • Choose wrapper vs direct-reference approach
  • Update references and remove redundant copies (or keep wrappers)
  • Validate preinstall still fails correctly under non-pnpm installers

Analysis Metadata

  • Analyzed Files: 4 (CJS)
  • Detection Method: Serena semantic/pattern analysis + manual verification
  • Commit: 258aa332a9ab237e8a72b6747968669be9d4db20
  • Analysis Date: 2026-04-06T21:49:32.084Z

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.

Research direction

Read scripts/only-pnpm.cjs and the copies under server/gitrest, server/routerlicious, and server/historian, then inspect the related package.json preinstall entries. Determine whether the server packages must support standalone installs before choosing wrappers or direct references. Done means one canonical guard remains, all preinstall paths work, and non-pnpm installation still fails correctly.

Written by the indexing model from the issue text.

Assessment

Tech stack
javascript
Domain
tooling
Issue type
Refactor
Difficulty
3/5
Estimated time
1-2 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
57/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.