Skip to content

feat(config): introduce app config file#63

Open
luanvdw wants to merge 4 commits into
mainfrom
feat/config-app-config-file
Open

feat(config): introduce app config file#63
luanvdw wants to merge 4 commits into
mainfrom
feat/config-app-config-file

Conversation

@luanvdw
Copy link
Copy Markdown
Member

@luanvdw luanvdw commented Jun 3, 2026

Summary

  • Add prisma.app.json as a repo-owned app build settings file for config-backed deploys.
  • Generate the file from inferred defaults on first deploy, then honor existing buildCommand and outputDirectory values without overwriting them.
  • Wire the resolved settings through deploy output, provider build execution, and Next.js/TanStack staging while keeping target identity in .prisma/local.json.
  • Update product docs for the new build-settings config boundary.

Validation

  • pnpm --filter @prisma/cli exec vitest run tests/app-build.test.ts tests/app-controller.test.ts tests/app-bun-compat.test.ts passed.
  • git diff --check passed.
  • Thermonuclear review file-size gate passed: preview-build.ts is 780 lines; new settings module is 488 lines.
  • pnpm --filter @prisma/cli exec tsc --noEmit reports existing unrelated baseline failures in tests/helpers.ts, tests/project-real-mode.test.ts, tests/publish-prep.test.ts, and tests/resolve-cli-version.test.ts. No touched app config/build files are in the TypeScript failure set.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Jun 3, 2026

Review Change Stack

Warning

Review limit reached

@luanvdw, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 8 minutes and 33 seconds. Learn how PR review limits work.

Your organization has run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: a52f14de-7527-436c-a312-ebd7237bd09e

📥 Commits

Reviewing files that changed from the base of the PR and between eb71701 and 007ce5a.

📒 Files selected for processing (2)
  • packages/cli/src/lib/app/preview-build-settings.ts
  • packages/cli/tests/app-build.test.ts

Walkthrough

This PR adds prisma.app.json configuration support to manage preview app build settings (build command and output directory). The implementation includes build settings resolution with framework-specific defaults, file validation, package manager detection, build execution, CLI output rendering, and integration into preview build strategies and deploy flow.

Changes

Build Settings Configuration for Preview Deploys

Layer / File(s) Summary
Documentation and error conventions
docs/product/command-spec.md, docs/product/error-conventions.md, docs/product/output-conventions.md, docs/product/resource-model.md
Documentation establishes prisma.app.json as a committed app build-settings file distinct from runtime/resolution state. Adds APP_CONFIG_INVALID error code and requires the CLI to indicate whether prisma.app.json was created or reused, along with build command source and literal output directory in deployment output.
Package metadata extension
packages/cli/src/lib/app/bun-project.ts
BunPackageJsonLike interface extended with optional packageManager field for package manager detection logic.
Build settings resolution and validation
packages/cli/src/lib/app/preview-build-settings.ts
Core module implementing prisma.app.json lifecycle: exclusive-write creation pattern, framework-specific build command/output directory resolution (Next.js reads next.config.* for distDir and output), JSON validation and path sanitization, package manager detection from package.json or lockfiles, and build command execution with process/buffer management and abort signal support.
Build strategy integration
packages/cli/src/lib/app/preview-build.ts
Extends PreviewBuildStrategy to accept resolved buildSettings, refactors Next.js/TanStack/Bun implementations to run resolved build commands and stage output locally, and adds helpers to discover standalone entrypoints and copy static assets into artifact directories.
Provider and controller integration
packages/cli/src/controllers/app.ts, packages/cli/src/lib/app/preview-provider.ts
app.deploy controller resolves/creates prisma.app.json, renders build settings via maybeRenderDeployBuildSettings, and passes resolved settings to PreviewAppProvider.deployApp, which forwards them into build strategies. Type definitions updated to use PreviewBuildSettingsBuildType and extend resolveProjectContext options.
Build settings unit tests
packages/cli/tests/app-build.test.ts
Test coverage for config creation with inferred framework settings, default configs per framework type, preserving existing configs without overwriting, rejecting invalid JSON and schema violations, resolving build scripts from package.json, detecting package manager from lockfiles, executing builds and staging output, and handling null build commands.
Deployment integration tests
packages/cli/tests/app-controller.test.ts
Updated test helpers for variable dependency specs and new readPrismaAppConfig helper. First-deploy test verifies buildSettings are passed to provider with correct source metadata; new test confirms existing prisma.app.json is reused with source fields set to null.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title 'feat(config): introduce app config file' directly and concisely describes the main change: introduction of a new app config file (prisma.app.json) for build settings.
Description check ✅ Passed The description is comprehensive and directly related to the changeset, covering the addition of prisma.app.json, its generation and usage behavior, integration with deploy systems, documentation updates, and validation results.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/config-app-config-file
✨ Simplify code
  • Create PR with simplified code
  • Commit simplified code in branch feat/config-app-config-file

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@luanvdw luanvdw marked this pull request as ready for review June 3, 2026 01:56
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 4

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
docs/product/error-conventions.md (1)

157-213: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Add APP_CONFIG_INVALID to the stable MVP list, not just the meanings section.

Line 213 introduces a new public code, but the authoritative MVP list in Lines 161-200 still omits it. That makes the error contract internally inconsistent for agents and CI that treat the stable-set list as the source of truth.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/product/error-conventions.md` around lines 157 - 213, The MVP list omits
the `APP_CONFIG_INVALID` code while it appears in the meanings section; update
the stable MVP codes list (the bullet list under "These codes are the minimum
stable set for the MVP") to include `APP_CONFIG_INVALID` so the authoritative
list matches the meanings section (add the exact token `APP_CONFIG_INVALID` to
the list of codes).
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/cli/src/lib/app/preview-build-settings.ts`:
- Around line 297-346: The code currently defaults an unknown package manager to
"bun", which can write a Bun-specific build command incorrectly; change
resolvePackageManager to return Promise<PackageManager | undefined> (remove the
final return "bun") so it yields undefined when no package manager is inferred
(keep using packageManagerFromPackageJson and the lockfile checks), then update
the caller that uses resolvePackageManager (the if branch that builds command
when hasBuildScript(...) is true) to check for a truthy packageManager and only
return { command: `${packageManager} run build`, source: "package.json
scripts.build" } when packageManager is present; otherwise fall back to
returning the provided fallback.command and fallback.source. Ensure function
signatures/types are updated accordingly.
- Around line 440-457: The current regex-based readStaticDistDir incorrectly
captures distDir from comments/strings/unrelated objects in raw next.config.*;
update readStaticDistDir (and the readNextConfig → resolveNextOutputRoot flow)
to parse the source AST and extract distDir only from the exported Next config
object with high confidence: use a JS/TS parser (e.g., `@babel/parser` or
ts-morph) to find the module.exports/export default object, read a direct string
Literal value for distDir (reject computed/concatenated values), validate it is
a simple relative path (no absolute, "..", or path traversal) and only then
return the normalized posix path for outputDirectory/prisma.app.json; otherwise
return undefined so mistaken/commented values cannot persist.
- Around line 103-116: The code unconditionally writes a standalone path for
Next.js (`joinPosix(outputRoot, "standalone")`) even when next.config may not
enable output:"standalone", causing stale persisted settings; update
resolvePreviewBuildSettings to detect the actual Next.js output mode (use or
extend resolveNextOutputRoot to return the resolved outputRoot plus the output
mode or call a helper that inspects next.config for
output:"standalone"|"export") and only set outputDirectory to
joinPosix(outputRoot, "standalone") and set outputDirectorySource to "Next.js
output" when the detected mode is "standalone"; for other modes (e.g., "export"
or default) either set outputDirectory to the plain outputRoot or leave it unset
and ensure resolveOrCreatePreviewBuildSettings does not persist an inferred
standalone path before the build runs (persist only when outputDirectorySource
confirms standalone or after a successful build).

In `@packages/cli/src/lib/app/preview-build.ts`:
- Around line 363-369: The NEXT_CONFIG_FILENAMES array in preview-build.ts
should not include "next.config.cjs" because Next.js doesn't support that root
filename; remove "next.config.cjs" from that constant and update the other
in-repo Next.js candidate lists to match (remove "next.config.cjs" wherever Next
config filename lists are defined), specifically in the detectNextConfig() logic
in packages/cli/src/controllers/app.ts and the filename arrays in local-dev.ts
and preview-build-settings.ts so all detections use only supported names (e.g.,
next.config.js, .mjs, .ts, .mts) and stay consistent across functions.

---

Outside diff comments:
In `@docs/product/error-conventions.md`:
- Around line 157-213: The MVP list omits the `APP_CONFIG_INVALID` code while it
appears in the meanings section; update the stable MVP codes list (the bullet
list under "These codes are the minimum stable set for the MVP") to include
`APP_CONFIG_INVALID` so the authoritative list matches the meanings section (add
the exact token `APP_CONFIG_INVALID` to the list of codes).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 320e6bca-e80f-4a78-91d1-b0d8d81d1849

📥 Commits

Reviewing files that changed from the base of the PR and between 8930881 and 5bc6e5a.

📒 Files selected for processing (11)
  • docs/product/command-spec.md
  • docs/product/error-conventions.md
  • docs/product/output-conventions.md
  • docs/product/resource-model.md
  • packages/cli/src/controllers/app.ts
  • packages/cli/src/lib/app/bun-project.ts
  • packages/cli/src/lib/app/preview-build-settings.ts
  • packages/cli/src/lib/app/preview-build.ts
  • packages/cli/src/lib/app/preview-provider.ts
  • packages/cli/tests/app-build.test.ts
  • packages/cli/tests/app-controller.test.ts

Comment thread packages/cli/src/lib/app/preview-build-settings.ts
Comment thread packages/cli/src/lib/app/preview-build-settings.ts Outdated
Comment thread packages/cli/src/lib/app/preview-build-settings.ts Outdated
Comment on lines +363 to +369
const NEXT_CONFIG_FILENAMES = [
"next.config.js",
"next.config.mjs",
"next.config.cjs",
"next.config.ts",
"next.config.mts",
] as const;
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Locate NEXT_CONFIG_FILENAMES usage/definition
rg -n "NEXT_CONFIG_FILENAMES|detectNextConfig|next\.config\.cjs" packages/cli/src -S

Repository: prisma/prisma-cli

Length of output: 1131


🌐 Web query:

Next.js supported next.config filenames next.config.cjs next.config.mjs next.config.ts

💡 Result:

Next.js supports multiple file formats for its configuration file, allowing you to use JavaScript or TypeScript with either CommonJS (CJS) or ECMAScript Module (ESM) syntax [1][2]. The officially supported configuration filenames are: - next.config.js: The standard configuration file using CommonJS syntax (module.exports) [3][4]. - next.config.mjs: Used for configurations requiring ECMAScript Module (ESM) syntax (export default) [3][4]. - next.config.ts: Supported since Next.js 15.0.0, this allows you to write your configuration in TypeScript [2][5]. Regarding the filenames mentioned in your query: - next.config.cjs: While often used in Node.js environments to explicitly denote CommonJS files, official Next.js documentation has historically noted that .cjs (and .cts) extensions are not explicitly supported for the main configuration file [3]. - next.config.ts: This is a fully supported configuration format [2][5]. When using next.config.ts, your configuration is processed by Next.js using a built-in resolver [6]. In environments with modern Node.js versions (v22.10.0+), Next.js can leverage native TypeScript resolution, which allows for native ESM syntax (such as top-level await) [2][6]. For projects where you wish to explicitly signal ESM usage while using TypeScript, next.config.mts is also utilized as a compatible approach [2].

Citations:


🌐 Web query:

site:nextjs.org "next.config.cjs" "next-config-js" supported

💡 Result:

As of June 3, 2026, Next.js does not support configuration files with the.cjs or.cts extensions [1][2]. According to official Next.js documentation, the supported configuration file formats are: - next.config.js: The standard configuration file [1][2]. - next.config.mjs: Used when ECMAScript modules are required [1][2]. - next.config.ts: Used for TypeScript configuration (introduced in v15.0.0) [3][4]. While Next.js projects may use.cjs or.cts files elsewhere for other purposes (such as when forced by a "type": "module" setting in package.json), these specific extensions are explicitly unsupported for the main Next.js configuration file [1][2][4].

Citations:


🌐 Web query:

next-config-js supported filenames next.config.cjs next.config.cts

💡 Result:

As of June 3, 2026, the Next.js configuration files next.config.cjs and next.config.cts are not supported [1][2][3]. Next.js explicitly states in its official documentation that configuration files with the .cjs or .cts extensions are not supported [1][2]. Attempting to use these extensions may result in them being ignored or cause the framework to throw an error [3][4]. The officially supported configuration filenames are: - next.config.js: The standard configuration file [1][2]. - next.config.mjs: Used for projects requiring ECMAScript modules (ESM) [1][5]. - next.config.ts: Used for TypeScript-based configurations [1][6]. While there has been development activity regarding different extensions, the framework currently maintains a restricted list of supported filenames for the configuration root to ensure stability and predictable behavior [3][4][7].

Citations:


Remove next.config.cjs from Next.js config filename detection

Next.js does not support next.config.cjs (or next.config.cts) as the root config filename, so detecting it can misclassify Next.js projects and drive incorrect build-settings inference. Remove next.config.cjs from packages/cli/src/lib/app/preview-build.ts (NEXT_CONFIG_FILENAMES, lines 363-369) and also from the other in-repo Next.js config filename candidate lists: packages/cli/src/controllers/app.ts (detectNextConfig()), packages/cli/src/lib/app/local-dev.ts, and packages/cli/src/lib/app/preview-build-settings.ts. (nextjs.org)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/cli/src/lib/app/preview-build.ts` around lines 363 - 369, The
NEXT_CONFIG_FILENAMES array in preview-build.ts should not include
"next.config.cjs" because Next.js doesn't support that root filename; remove
"next.config.cjs" from that constant and update the other in-repo Next.js
candidate lists to match (remove "next.config.cjs" wherever Next config filename
lists are defined), specifically in the detectNextConfig() logic in
packages/cli/src/controllers/app.ts and the filename arrays in local-dev.ts and
preview-build-settings.ts so all detections use only supported names (e.g.,
next.config.js, .mjs, .ts, .mts) and stay consistent across functions.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

♻️ Duplicate comments (1)
packages/cli/src/lib/app/preview-build-settings.ts (1)

450-456: ⚠️ Potential issue | 🟠 Major | 🏗️ Heavy lift

The parsed Next.js output mode is still ignored.

These lines now read output, but resolvePreviewBuildSettings() still always persists ${outputRoot}/standalone for Next.js. For default-mode or output: "export" apps, that writes a stale prisma.app.json, and packages/cli/src/lib/app/preview-build.ts:229-244 later treats that persisted directory as mandatory standalone output. Only append /standalone when the parsed mode is actually standalone.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/cli/src/lib/app/preview-build-settings.ts` around lines 450 - 456,
The code reads the Next.js output mode into the local variable output (via
readStaticStringProperty) but resolvePreviewBuildSettings() and the persistence
logic still unconditionally append "/standalone"; update
resolvePreviewBuildSettings() and any persistence in preview-build.ts to only
append "/standalone" when output === "standalone" (use the parsed output
variable), otherwise persist the outputRoot as-is (or append nothing) so default
or "export" modes don't produce a stale standalone directory; look for symbols
readStaticStringProperty, output, resolvePreviewBuildSettings, and the
persistence logic in preview-build.ts and gate the "/standalone" suffix behind
output === "standalone".
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/cli/src/lib/app/preview-build-settings.ts`:
- Around line 297-301: The current branch returns the framework fallback when
packageManager is falsy, which silently replaces a declared package.json
scripts.build; change the logic so that if packageManager is falsy but
packageJson.scripts?.build exists you preserve and return that literal script
(set command to packageJson.scripts.build and source to something like
"package.json:scripts.build"); if neither packageManager nor
packageJson.scripts?.build exist then fail closed (throw or return an explicit
error/null) instead of returning fallback.command/fallback.source. Update the
code paths around packageManager, fallback, and the returned { command, source }
to implement this behavior.

In `@packages/cli/tests/app-build.test.ts`:
- Around line 357-379: The test currently includes Bun-specific signals (e.g.,
package.json.module and index.ts) so next.config.cjs isn’t isolated; update the
fixture so the only potential Next.js indicator is next.config.cjs by removing
Bun signals: write a minimal package.json (e.g., {} or with only benign fields,
no "module" or "type":"module"), remove or avoid creating index.ts that suggests
Bun, and keep only next.config.cjs in appPath; then call
resolvePreviewBuildStrategy({ appPath, buildType: "auto" }) and assert it
resolves to the non-Next fallback (the existing expectation of buildType: "bun")
to ensure next.config.cjs is not treated as a Next.js signal.

---

Duplicate comments:
In `@packages/cli/src/lib/app/preview-build-settings.ts`:
- Around line 450-456: The code reads the Next.js output mode into the local
variable output (via readStaticStringProperty) but resolvePreviewBuildSettings()
and the persistence logic still unconditionally append "/standalone"; update
resolvePreviewBuildSettings() and any persistence in preview-build.ts to only
append "/standalone" when output === "standalone" (use the parsed output
variable), otherwise persist the outputRoot as-is (or append nothing) so default
or "export" modes don't produce a stale standalone directory; look for symbols
readStaticStringProperty, output, resolvePreviewBuildSettings, and the
persistence logic in preview-build.ts and gate the "/standalone" suffix behind
output === "standalone".
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 342c5440-2b83-4498-bcce-a87223e93261

📥 Commits

Reviewing files that changed from the base of the PR and between 5bc6e5a and eb71701.

📒 Files selected for processing (5)
  • docs/product/error-conventions.md
  • packages/cli/src/controllers/app.ts
  • packages/cli/src/lib/app/preview-build-settings.ts
  • packages/cli/src/lib/app/preview-build.ts
  • packages/cli/tests/app-build.test.ts
💤 Files with no reviewable changes (2)
  • packages/cli/src/controllers/app.ts
  • packages/cli/src/lib/app/preview-build.ts

Comment thread packages/cli/src/lib/app/preview-build-settings.ts
Comment thread packages/cli/tests/app-build.test.ts
@luanvdw luanvdw self-assigned this Jun 4, 2026
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.

1 participant