Skip to content

feat: project detection support added#1476

Open
KartikJha wants to merge 55 commits intomainfrom
DXCDT-1555/tool-detection-module
Open

feat: project detection support added#1476
KartikJha wants to merge 55 commits intomainfrom
DXCDT-1555/tool-detection-module

Conversation

@KartikJha
Copy link
Copy Markdown

Changes

internal/cli/quickstart_detect.go (new file)

  • Added DetectProject(dir string) DetectionResult — scans the working directory for framework signal files and returns a structured result with Framework, Type, BuildTool, Port, AppName, Detected, and AmbiguousCandidates
  • Implements 14 detection priority levels covering: Angular, Flutter (web/native), Vite+React/Vue/Svelte/Vanilla, Next.js, Nuxt, SvelteKit, Expo, ASP.NET (.csproj), Java (Spring Boot / Java EE / Vanilla via pom.xml or build.gradle), PHP/Laravel (composer.json), Go (go.mod), Ruby on Rails (Gemfile), Python/Flask (requirements.txt / pyproject.toml), and package.json dep scanning for Express/Fastify/Hono/Ionic/React Native
  • Config-file signals (e.g. angular.json, vite.config.ts) take priority over generic dep scanning to avoid false positives
  • When multiple package.json deps match, AmbiguousCandidates is populated so the caller can prompt for disambiguation

internal/cli/quickstarts.go

New setup-experimental command flow:

  • Added SetupInputs named struct replacing 3x repeated anonymous structs
  • Added resolveRequestParams() — resolves DetectionSub placeholders in RequestParams (callbacks, logout URLs, web origins, name) using actual app name and port at runtime
  • Integrated DetectProject() into RunE: on an existing project the detected framework/type/build-tool/port/name are shown as a summary and the user is asked to confirm; accepted values pre-fill SetupInputs so downstream prompts are skipped
  • Ambiguous detection (multiple package.json deps) triggers a framework disambiguation prompt
  • No-detection fallback (empty directory) prompts for all inputs: type -> framework (filtered by type) -> build tool -> port -> name
  • getQuickstartConfigKey skips any field already populated (by flags or detection) and only asks for what is missing
  • API creation now uses management.ResourceServer + cli.api.ResourceServer.Create() instead of management.Client
  • API name defaults to <app-name>-API; API identifier defaults to https://<app-name-slug>
  • API-only flow prompts the user to select an existing Auth0 application to associate with
  • Registered all spec flags: --app, --api, --name, --type, --framework, --build-tool, --port, --callback-url, --logout-url, --web-origin-url, --identifier, --audience, --signing-alg, --scopes, --token-lifetime, --offline-access

Other fixes applied during review:

  • Removed hardcoded RS256 overwrite on API signing algorithm
  • Secret fields (e.g. AUTH0_SECRET, SESSION_SECRET) now use generateState(32) instead of a static placeholder
  • Map iteration over EnvValues is now sorted for deterministic config file output
  • Spring Boot YAML config uses gopkg.in/yaml.v2 with buildNestedMap() to correctly produce nested YAML from dot-delimited keys (e.g. okta.oauth2.issuer)
  • All detection-related string literals replaced with the auth0.DetectionSub constant
  • Output switched from fmt.Printf to cli.renderer.Infof for consistency
  • m2m removed from the application type selection list
  • Fixed "::none" error when only --api was selected (config key lookup now correctly skipped for API-only flows)
  • Trailing periods removed from section comment dividers in internal/auth0/quickstart.go

References

  • DXCDT-1554 — review comment fixes for setup-experimental
  • DXCDT-1555 — tool detection module and CLI flow refinement

Testing

Manual — existing project:

cd /path/to/react-vite-project
auth0 quickstarts setup-experimental
# Expected: detects react/spa/vite/5173, shows summary, confirms, skips re-prompting those fields

Manual — empty directory:

mkdir empty-test && cd empty-test
auth0 quickstarts setup-experimental
# Expected: no detection panel, prompts for type -> framework -> build tool -> port -> name

Manual — API-only:

auth0 quickstarts setup-experimental --api --identifier https://my-api
# Expected: prompts to select an existing app, creates ResourceServer, no app client created

Manual — App + API:

auth0 quickstarts setup-experimental --app --api --name "My App"
# Expected: creates client, creates ResourceServer named "My App-API"

Unit tests for DetectProject covering each of the 14 signal rules: N/A (to be added in a follow-up — mocking os.ReadFile / os.Stat for the full matrix is tracked separately).


Checklist

  • All new/changed/fixed functionality is covered by tests (or N/A)
  • I have added documentation for all new/changed functionality (command --help text and flag descriptions updated inline)

@KartikJha KartikJha requested a review from a team as a code owner March 30, 2026 18:23
@KartikJha KartikJha force-pushed the DXCDT-1555/tool-detection-module branch from 2ee6d70 to 902aacd Compare March 31, 2026 16:44
@KartikJha KartikJha changed the base branch from DXCDT-1554/common-qs-fields-prefilling to main April 1, 2026 09:40
@KartikJha KartikJha force-pushed the DXCDT-1555/tool-detection-module branch 2 times, most recently from ace3263 to 336f8c1 Compare April 6, 2026 08:03
@codecov-commenter
Copy link
Copy Markdown

codecov-commenter commented Apr 8, 2026

Codecov Report

❌ Patch coverage is 57.97342% with 506 lines in your changes missing coverage. Please review.
✅ Project coverage is 58.95%. Comparing base (55b66e5) to head (cb9922c).
⚠️ Report is 16 commits behind head on main.

Files with missing lines Patch % Lines
internal/cli/quickstarts.go 42.07% 398 Missing and 15 partials ⚠️
internal/cli/quickstart_detect.go 84.86% 56 Missing and 15 partials ⚠️
internal/prompt/prompt.go 0.00% 11 Missing ⚠️
internal/cli/cli.go 0.00% 6 Missing ⚠️
internal/display/display.go 0.00% 5 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #1476      +/-   ##
==========================================
- Coverage   59.14%   58.95%   -0.19%     
==========================================
  Files         120      121       +1     
  Lines       21194    22585    +1391     
==========================================
+ Hits        12535    13316     +781     
- Misses       7841     8419     +578     
- Partials      818      850      +32     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@ramya18101
Copy link
Copy Markdown
Contributor

@KartikJha , Please fix the linters errors

@ramya18101
Copy link
Copy Markdown
Contributor

  • Colouring of newly created files/apps
  • Fix the Prompt to confirm with name
  • Port also should follow the name process
  • Format the output msg
  • Fix testcases for the main flow of each scenario which tests .env content and the requestparams Info
  • Refactor the consts and help functions into 1 package instead of depending on auth package

Comment on lines +47 to +49
--scopes string Comma-separated list of permission scopes for the API
--signing-alg string Token signing algorithm: RS256, PS256, or HS256 (leave blank to be prompted interactively)
--token-lifetime string Access token lifetime in seconds (default: 86400 = 24 hours) (default "86400")
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Highlight that these flags are for the API

Comment thread internal/auth0/quickstart.go Outdated
Comment on lines +208 to +210
Callbacks: []string{"http://localhost:5173/callback"},
AllowedLogoutURLs: []string{"http://localhost:5173"},
WebOrigins: []string{DetectionSub},
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

As discussed earlier, the port value should be prompted with default values like 5173 or 4200, as it varies depending on the configuration.

Comment thread internal/cli/quickstart_detect.go Outdated
if hasDep(earlyDeps, "@ionic/react") {
result.Framework = "ionic-react"
result.Type = "native"
result.BuildTool = "vite"
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Instead of static build tool, try to fetch the build tool details from other files like .vite.config.ts

@KartikJha KartikJha force-pushed the DXCDT-1555/tool-detection-module branch from 02bace3 to c37dcc3 Compare April 13, 2026 16:05
@KartikJha KartikJha requested a review from ramya18101 April 15, 2026 05:33
@KartikJha KartikJha force-pushed the DXCDT-1555/tool-detection-module branch 4 times, most recently from 2f95d6f to f5c678f Compare April 23, 2026 04:01
@KartikJha KartikJha force-pushed the DXCDT-1555/tool-detection-module branch from a02bac9 to b4c53bb Compare April 28, 2026 03:15
@KartikJha KartikJha force-pushed the DXCDT-1555/tool-detection-module branch from 26ae3bc to 34f57d1 Compare May 5, 2026 12:29
Comment thread internal/display/display.go Outdated
fmt.Fprintf(r.MessageWriter, format+"\n", a...)
}

func (r *Renderer) InfofNoSpace(format string, a ...interface{}) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

InfofNoSpace is not used at anywhere

Comment on lines +103 to +106
case dirExists(dir, "android") || dirExists(dir, "ios"):
result.Framework = "flutter"
result.Type = "native"
result.BundleID = readMobileBundleID(dir)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Can this case go along with the default case

Comment on lines +865 to +867
cli.renderer.InfofBullet("App name: %s", detection.AppName)
if detection.Port > 0 {
cli.renderer.InfofBullet("Port: %d", detection.Port)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

We don't need to display the app name and port as the detected values,
We can prompt the details by giving the default value

var mobileTFMRegex = regexp.MustCompile(`net\d+\.\d+-(?:android|ios)`)

// extractPortFromContent returns the first port number found in content, or 0 if none found.
func extractPortFromContent(content string) int {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

As discussed, we are not going to read the port values from the files,
Instead use the pre-defined default values shared in the Command Redesign Spec doc - v. 6
Remove these additional code

Comment on lines +352 to +368
func collectPackageJSONCandidates(deps map[string]bool) []detectionCandidate {
var candidates []detectionCandidate
// React-native without expo (expo check would have matched earlier in DetectProject).
if hasDep(deps, "react-native") {
candidates = append(candidates, detectionCandidate{framework: "react-native", qsType: "native"})
}
if hasDep(deps, "express") {
candidates = append(candidates, detectionCandidate{framework: "express", qsType: "regular", port: 3000})
}
if hasDep(deps, "hono") {
candidates = append(candidates, detectionCandidate{framework: "hono", qsType: "regular", port: 3000})
}
if hasDep(deps, "fastify") {
candidates = append(candidates, detectionCandidate{framework: "fastify", qsType: "regular", port: 3000})
}
return candidates
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

recheck

Comment on lines +1478 to +1481
if inputs.Port == 0 {
inputs.Port = defaultPortForFramework(inputs.Framework)
// Port stays 0 for native apps (react-native, expo, flutter) - no port needed.
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Isn't this handled again under - Step 3d: Prompt for port if not explicitly set --.

Comment on lines +1484 to +1487
// Config key is only meaningful when an app is being created.
if !inputs.App {
return "", inputs, false, nil
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Do we really need this check..?
As app check is already happened in the start!

}
}

// Resolve port from framework default before prompting (Bug 11).
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Why are we highlighting the bugs..?

Comment on lines +1508 to +1534
if len(candidates) > 0 {
// Sort by priority (vite > webpack > cra > others alphabetically) so modern
// build tools are preferred over legacy ones.
buildToolPriority := map[string]int{"vite": 0, "webpack": 1, "cra": 2}
sort.Slice(candidates, func(i, j int) bool {
pi, pj := len(buildToolPriority)+1, len(buildToolPriority)+1
if parts := strings.SplitN(candidates[i], ":", 3); len(parts) == 3 {
if p, ok := buildToolPriority[parts[2]]; ok {
pi = p
}
}
if parts := strings.SplitN(candidates[j], ":", 3); len(parts) == 3 {
if p, ok := buildToolPriority[parts[2]]; ok {
pj = p
}
}
if pi != pj {
return pi < pj
}
return candidates[i] < candidates[j]
})
configKey = candidates[0]
// Update inputs.BuildTool so the caller can notify the user of the auto-selection.
parts := strings.SplitN(configKey, ":", 3)
if len(parts) == 3 {
inputs.BuildTool = parts[2]
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Instead of this complicated logic, Can we enhance the frameworksForType logic to store the supported buildTools for each Framework!

// getQuickstartConfigKey resolves remaining missing prompts for App and API creation
// and returns the config map key for the selected framework.
// App/API selection and project detection are handled by the caller before this is invoked.
func getQuickstartConfigKey(inputs SetupInputs) (string, SetupInputs, bool, error) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Divide it into functions as fetchNecessaryInputs and GetQsConfigKey

and since both inputs was used in both input and output params of that func, Please wisely use reference(*)

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.

3 participants