utopia-php / utopia-php/detector

Framework detection can never return null for a repo with a package.json

Open
#16 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
PHP
Stars
3
Forks
0
Avg merge
11h 18m
Merged PRs (30d)
1

Description

Summary

Framework::detect() never returns null for any repository containing a package.json, even when no framework is present. It returns angular.

Cause

package.json is listed in getFiles() for every framework detection — Angular, React, NextJs, SvelteKit, Astro, Analog and the rest. So for a repo with a package.json and no framework dependencies, every detector scores exactly one path match.

detect() then filters to the joint-highest scorers, and since all fourteen tie at 1, falls through to the fewest-parents tie-break in src/Detector/Framework.php:

$bestFrameworks = \array_keys($frameworkMatches);
usort($bestFrameworks, fn ($a, $b) => $fameworkParents[$a] <=> $fameworkParents[$b]);
$bestFramework = $bestFrameworks[0];

Angular extends JS directly, so it has the fewest parents and wins. The count($frameworkMatches) <= 0 early return never fires, because the tie is at 1 rather than 0.

Reproduction

Against utopia-php/detector 0.2.6, with all fourteen detections registered as in Appwrite's detection endpoint:

$detector = new Framework('npm');
$detector->addInput('{"dependencies":{"lodash":"^4"}}', Framework::INPUT_PACKAGES);
$detector->addInput('package.json', Framework::INPUT_FILE);
// ... addOption() for all 14 detections

$detector->detect()->getName(); // => "angular"
Input Expected Actual
{"dependencies":{"lodash":"^4"}} null angular
{"devDependencies":{"turbo":"^2"}} null angular
{} null angular

Real repositories affected

Both are turborepo monorepos whose root package.json holds only tooling, with the apps under apps/*:

Consumers that map a detection to a build configuration will pick Angular's install/build commands and an output directory of ./dist/angular for these, which no build produces.

Note on the fix

This is a design call rather than an obvious patch, which is why this is an issue and not a PR. package.json cannot discriminate between frameworks, so the options I can see each have a blast radius across all fourteen detections:

  1. Drop package.json from getFiles() and rely on getPackages() for JS frameworks. Cleanest, but changes scores everywhere.
  2. Require at least one package match before a detection is eligible, keeping package.json as a tiebreak-only signal.
  3. Weight path matches so a universal file scores below a discriminating one.

Happy to send a PR for whichever direction you prefer.

Found while testing Appwrite's framework detection against open-source repositories.

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

Start in src/Detector/Framework.php, especially Framework::detect(), getFiles(), and getPackages(). Reproduce the fourteen-detector case with package.json and package inputs, then compare the proposed eligibility and scoring directions. Done means repositories with no framework dependencies return null while framework repositories still select the appropriate detection.

Written by the indexing model from the issue text.

Assessment

Tech stack
php
Domain
tooling
Issue type
Bug
Difficulty
5/5
Estimated time
Over a week
Activity status
Quiet
Clarity
Needs clarification
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.