fix: unbreak non-JS integration install flow (Django, .NET, Kotlin + others)#125
Merged
fix: unbreak non-JS integration install flow (Django, .NET, Kotlin + others)#125
Conversation
Previously `workos install` crashed with "Could not find package.json" in any project without a package.json: JS integration detection calls getPackageDotJson() which exits the process on missing file, killing the installer before non-JS integrations (Python/Django) got a turn. - Skip JS integration detection when package.json is missing - Widen Python detection: match manage.py or requirements.txt with django, not just pyproject.toml (via a new optional detect() override on FrameworkMetadata, wired to the existing isDjangoProject helper) - Write credentials to .env (not .env.local) and skip cookie password generation for non-JS projects in unclaimed env provisioning - Gate state-machine configureEnvironment actor on JS-only to prevent a second .env.local leak post-detection - Add Django port/callback defaults (8000, /auth/callback/) so detectPort returns the right values for Python Tests: +8 net covering detection matrix (no-package.json skip, pyproject.toml, manage.py alone, requirements.txt+django, non-Django python), python port defaults, and .env vs .env.local selection in unclaimed provisioning.
…languages Beyond the Django fixes in the previous commit, several other non-JS integrations had parallel problems that would bite the next user with a .NET, Kotlin, or non-trivial project layout. - .NET detection was completely broken: manifestFile '*.csproj' went through existsSync() which does literal-filename matching, so it never matched. Now uses globExists() from language-detection.ts (which has the right logic but wasn't wired up anywhere). - Kotlin detection only matched build.gradle.kts (Kotlin DSL). Now also matches build.gradle (Groovy DSL) and pom.xml (Maven) via the existing detectKotlin() helper, which already had Gradle Groovy support. Extended it to cover Maven too. - Port defaults added for ruby (3000), php (8000), php-laravel (8000), go (8080), dotnet (5000), elixir (4000), kotlin (8080). Previously all fell back to DEFAULT_PORT=3000, which is wrong for every one of them. - ensureGitignore() now also writes .env to .gitignore for non-JS projects (previously only handled .env.local for JS). Exported globExists() and detectKotlin() from language-detection.ts so the integrations can share them. detectLanguage() itself still isn't called anywhere in the install path — that's a larger cleanup for later.
…t, Rails
Follow-up to the hardcoded ecosystem defaults. These four languages have a
canonical config file where the dev server port lives; parse it so we don't
misconfigure redirect URIs when the user has customized the port.
- .NET: Properties/launchSettings.json → profiles[*].applicationUrl
- Phoenix: config/dev.exs or config/runtime.exs → port: NNNN
- Spring Boot: src/main/resources/application.{properties,yml} → server.port
- Rails: config/puma.rb → port ENV.fetch("PORT") { N } or literal port N
Falls back to the ecosystem default when the file is missing or malformed.
Python (Django), Go, plain PHP, and Laravel are unchanged — none has a
canonical config file; ports are CLI args or hardcoded in source.
detectLanguage() and its LANGUAGE_DETECTORS table were never called from the install path. globExists() and detectKotlin() were the only pieces still used after wiring up the dotnet/kotlin detect() overrides — both are caller-specific enough to inline: - dotnet/index.ts gets hasCsproj() (6 lines, readdirSync + endsWith) - kotlin/index.ts gets isKotlinProject() (handles kts, gradle, pom.xml) - The Language type moves into framework-config.ts where it is consumed Net: one fewer module, no lost functionality.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes:
workos installcrashed with "Could not find package.json" in Django projects — and audits the rest of the non-JS integrations for similar narrowness. Several were quietly broken:.NETdetection was 100% broken (a glob pattern passed to a literal-filename check).build.gradle.kts, missing Groovy DSL and Maven projects..env.localpolluted with JS-flavored vars alongside their real.env.3000for every non-JS integration — wrong for every one of them, and no per-project detection existed even when the port was sitting in a canonical config file.Root cause (Django crash)
JS integration detection calls
getPackageDotJson(), which callsprocess.exit(1)when nopackage.jsonexists. Next.js is the highest-priority integration (100), so detection always tried it first and killed the installer before non-JS integrations got a turn.Changes
Crash fix + Django detection
package.jsonis missing.manage.pyorrequirements.txtwithdjango, not justpyproject.toml. Added via a new optionaldetect()override onFrameworkMetadata, wired to the existingisDjangoProjecthelper.Broader non-JS audit
manifestFile: '*.csproj'went throughexistsSync()(literal-filename matching) so it never matched. Now uses a properreaddirSyncscan for.csproj.build.gradle(Groovy DSL) andpom.xml(Maven).Gemfile), PHP (composer.json), Go (go.mod), Elixir (mix.exs) — these manifests are universal in their ecosystems.Env file handling for non-JS
writeCredentialsEnv()picks.envinstead of.env.localwhen nopackage.jsonis present, and skipsWORKOS_COOKIE_PASSWORDgeneration (non-JS SDKs don't use it). Used by unclaimed env provisioning.configureEnvironmentactor on JS-only so it doesn't overwrite non-JS env files with JS defaults.ensureGitignore()now parameterized on filename — writes.envfor non-JS,.env.localfor JS.Port defaults
Added ecosystem defaults for every non-JS integration in
cli.config.tsand mapped them inport-detection.ts:Port detection (not just defaults)
For languages with a canonical config file, parse the actual configured port before falling back to the default. Mirrors the existing parsers for Next.js / Vite / TanStack Start.
Properties/launchSettings.json→profiles[*].applicationUrlconfig/dev.exsorconfig/runtime.exs→port: NNNNsrc/main/resources/application.propertiesor.yml→server.portconfig/puma.rb→port ENV.fetch("PORT") { N }or literalPython (Django), Go, plain PHP, and Laravel stay on defaults — none has a canonical config file; ports are CLI args or hardcoded in source.
Cleanup
Deleted
src/lib/language-detection.ts. ThedetectLanguage()function +LANGUAGE_DETECTORStable were never called from the install path. The only still-used pieces (globExists,detectKotlin) were inlined into the dotnet and kotlin integrations as caller-specific helpers. TheLanguagetype moved intoframework-config.tswhere it's consumed.