Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (2)
🚧 Files skipped from review as they are similar to previous changes (1)
📝 WalkthroughWalkthroughAdds strict typed config authoring and a renderer in packages/stack-shared; switches CLI and init to use the renderer; updates backend local-emulator to use renderer and export new constants/functions; strengthens tests and CLI to expect typed Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
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. Comment |
Greptile SummaryThis PR introduces a type-safe config authoring API for Stack Auth by adding Key changes:
Confidence Score: 3/5
Important Files Changed
Flowchart%%{init: {'theme': 'neutral'}}%%
flowchart TD
A["CLI: config pull"] --> B["project.getConfigOverride('branch')"]
B --> C["renderConfigFileContent(config)"]
C --> D{isValidConfig?}
D -- No --> E["throw Error (plain, not CliError)"]
D -- Yes --> F["normalize(config)"]
F --> G{droppedKeys?}
G -- Yes --> H["throw Error (plain, not CliError)"]
G -- No --> I["emit TS-flavoured file\n(always, even for .js)"]
I --> J["fs.writeFileSync(filePath, content)"]
K["Local Emulator API\nPATCH /branch"] --> L["writeConfigToFile(filePath, config)"]
L --> C
H -- uncaught --> M["HTTP 500 (should be 400)"]
E -- uncaught in emulator path --> M
N["defineStackConfig(config)"] --> O["Type-check:\nStrictConfigShape<T, StackConfig>"]
O -- extra/dot keys --> P["TypeScript error (compile time)"]
O -- valid --> Q["return config unchanged (identity)"]
Reviews (4): Last reviewed commit: "Update local emulator tests to use inlin..." | Re-trigger Greptile |
There was a problem hiding this comment.
Pull request overview
Introduces a typed config authoring entrypoint (defineStackConfig) in @stackframe/stack-shared and updates Stack CLI + local emulator to generate config files that import and wrap the exported config in defineStackConfig(...), with e2e/tests updated accordingly.
Changes:
- Add
defineStackConfighelper + type-level strictness to reject unknown keys (including dot-notation keys) in typed config files. - Update CLI (
init,config pull) and backend local emulator to render normalized, typed config files (and add--overwriteforconfig pull). - Update e2e tests to assert the new typed-config file format.
Reviewed changes
Copilot reviewed 10 out of 10 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| packages/stack-shared/src/config-authoring.ts | Adds defineStackConfig and strict shape typing for config authoring. |
| packages/stack-shared/src/config-authoring.test.ts | Type-level tests ensuring invalid keys/values are rejected. |
| packages/stack-shared/package.json | Exposes new ./config entrypoint and includes authoring source in package files. |
| packages/stack-cli/src/lib/stack-config-file.ts | Centralizes config file rendering with normalization + typed wrapper. |
| packages/stack-cli/src/commands/init.ts | Uses renderConfigFile when generating stack.config.ts. |
| packages/stack-cli/src/commands/config-file.ts | Adds --overwrite, uses renderConfigFile, and standardizes loading via jiti. |
| apps/e2e/tests/general/cli.test.ts | Updates CLI tests for new generated config file structure and overwrite behavior. |
| apps/e2e/tests/backend/endpoints/api/v1/internal/local-emulator-project.test.ts | Updates assertions for typed config output. |
| apps/e2e/tests/backend/endpoints/api/v1/internal/config-local-emulator.test.ts | Updates test to validate typed config output after branch override updates. |
| apps/backend/src/lib/local-emulator.ts | Writes typed config files and normalizes config before serialization. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
You can also share your feedback on Copilot code review. Take the survey.
apps/e2e/tests/backend/endpoints/api/v1/internal/config-local-emulator.test.ts
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
🧹 Nitpick comments (2)
apps/backend/src/lib/local-emulator.ts (1)
73-84: Consider consolidating with CLI'srenderConfigFile.This implementation is nearly identical to
packages/stack-cli/src/lib/stack-config-file.ts. Both validate, normalize with the same options, and produce the same output format. The only differences are the error types (StatusErrorvsCliError) and messages.Consider extracting the core rendering logic to
@stackframe/stack-sharedand having both CLI and backend wrap it with their respective error handling. This would prevent the implementations from drifting apart.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/backend/src/lib/local-emulator.ts` around lines 73 - 84, Extract the shared rendering logic into `@stackframe/stack-shared` as a single function (e.g., formatConfigExport or renderConfigCore) that accepts the raw config, runs isValidConfig + normalize with the same options (onDotIntoNonObject: "ignore", onDotIntoNull: "empty-object") and returns the export string (import + export const config = defineStackConfig(...)); then update apps/backend/src/lib/local-emulator.ts's renderConfigFile to call that shared function and translate any thrown error into a StatusError with the existing message, and similarly update packages/stack-cli/src/lib/stack-config-file.ts to call the shared function and wrap errors in a CliError so both callers use the identical core logic while preserving their specific error types.packages/stack-shared/src/config-authoring.test.ts (1)
34-43: Make the enum-negative test fail for only the enum reason.Line 38 uses
@ts-expect-error, but the object is partial; that can let the test pass for a different type error. Include the same valid sibling fields and change onlycustomerTypeto keep this assertion precise.♻️ Suggested tightening
defineStackConfig({ payments: { items: { todos: { + displayName: "Todo Slots", // `@ts-expect-error` Invalid enum values should fail type-checking. customerType: "workspace", }, }, }, });🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/stack-shared/src/config-authoring.test.ts` around lines 34 - 43, The test using defineStackConfig currently marks customerType with // `@ts-expect-error` but the surrounding object is partial which may allow other type errors to satisfy the directive; update the test so the todos object includes the same valid sibling fields (the required fields present in a normal todos config) and change only payments.items.todos.customerType to the invalid enum value ("workspace") so the `@ts-expect-error` fails solely for the enum mismatch; locate the defineStackConfig call and adjust the payments.items.todos object to be otherwise valid except for customerType.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@apps/backend/src/lib/local-emulator.ts`:
- Around line 73-84: Extract the shared rendering logic into
`@stackframe/stack-shared` as a single function (e.g., formatConfigExport or
renderConfigCore) that accepts the raw config, runs isValidConfig + normalize
with the same options (onDotIntoNonObject: "ignore", onDotIntoNull:
"empty-object") and returns the export string (import + export const config =
defineStackConfig(...)); then update apps/backend/src/lib/local-emulator.ts's
renderConfigFile to call that shared function and translate any thrown error
into a StatusError with the existing message, and similarly update
packages/stack-cli/src/lib/stack-config-file.ts to call the shared function and
wrap errors in a CliError so both callers use the identical core logic while
preserving their specific error types.
In `@packages/stack-shared/src/config-authoring.test.ts`:
- Around line 34-43: The test using defineStackConfig currently marks
customerType with // `@ts-expect-error` but the surrounding object is partial
which may allow other type errors to satisfy the directive; update the test so
the todos object includes the same valid sibling fields (the required fields
present in a normal todos config) and change only
payments.items.todos.customerType to the invalid enum value ("workspace") so the
`@ts-expect-error` fails solely for the enum mismatch; locate the
defineStackConfig call and adjust the payments.items.todos object to be
otherwise valid except for customerType.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: d773932d-7108-4560-af7b-77ecbddf271a
📒 Files selected for processing (10)
apps/backend/src/lib/local-emulator.tsapps/e2e/tests/backend/endpoints/api/v1/internal/config-local-emulator.test.tsapps/e2e/tests/backend/endpoints/api/v1/internal/local-emulator-project.test.tsapps/e2e/tests/general/cli.test.tspackages/stack-cli/src/commands/config-file.tspackages/stack-cli/src/commands/init.tspackages/stack-cli/src/lib/stack-config-file.tspackages/stack-shared/package.jsonpackages/stack-shared/src/config-authoring.test.tspackages/stack-shared/src/config-authoring.ts
- Introduced `renderConfigFileContent` function to handle config rendering and validation, replacing the previous `renderConfigFile` function. - Updated `writeConfigToFile` to use the new rendering function. - Added a test case to ensure that array config exports are rejected. - Adjusted package.json to point to the correct type definitions for config authoring. - Removed deprecated code related to config normalization and validation.
- Updated the `registerConfigCommand` function to explicitly define the type of `configModule` when importing the configuration file. - Simplified the `renderConfigFile` function by removing error handling, as it now directly returns the result of `renderConfigFileContent` without additional validation.
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
packages/stack-shared/src/config-rendering.ts (1)
17-37: Consider adding a test for conflicting keys.The tests cover normalization and invalid input rejection, but don't cover the scenario where keys conflict (e.g.,
{"a.b": "string", "a.b.c": "nested"}). Adding such a test would clarify the expected behavior.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/stack-shared/src/config-rendering.ts` around lines 17 - 37, Add a unit test for renderConfigFileContent that asserts behavior when the input has conflicting dotted keys (e.g., "a.b" vs "a.b.c"); locate renderConfigFileContent in the test file and add a test case that either expects a thrown error (toDocument the rejection) or expects a deterministic resolution (specify which value wins), using expect(() => renderConfigFileContent(conflictingInput)).toThrow... or expect(...).toContain... depending on the intended behavior; ensure the new test name clearly describes "conflicting keys" so it complements the existing normalization and invalid-input tests.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@packages/stack-shared/src/config-rendering.ts`:
- Around line 10-13: The normalize call currently uses onDotIntoNonObject:
"ignore", which silently drops conflicting keys; change this to
onDotIntoNonObject: "throw" in the normalize invocation (the call that produces
normalizedConfig in config-rendering.ts) so path conflicts raise an error, or
alternatively pass a droppedKeys array into normalize and if droppedKeys is
non-empty throw or log an error that includes droppedKeys; ensure the thrown
error or logged message references the droppedKeys and occurs before returning
normalizedConfig.
---
Nitpick comments:
In `@packages/stack-shared/src/config-rendering.ts`:
- Around line 17-37: Add a unit test for renderConfigFileContent that asserts
behavior when the input has conflicting dotted keys (e.g., "a.b" vs "a.b.c");
locate renderConfigFileContent in the test file and add a test case that either
expects a thrown error (toDocument the rejection) or expects a deterministic
resolution (specify which value wins), using expect(() =>
renderConfigFileContent(conflictingInput)).toThrow... or
expect(...).toContain... depending on the intended behavior; ensure the new test
name clearly describes "conflicting keys" so it complements the existing
normalization and invalid-input tests.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 4af8efa5-e487-4d7c-b022-a6ca80c2c9f8
📒 Files selected for processing (6)
apps/backend/src/lib/local-emulator.tsapps/e2e/tests/general/cli.test.tspackages/stack-cli/src/lib/stack-config-file.tspackages/stack-shared/package.jsonpackages/stack-shared/src/config-authoring.test.tspackages/stack-shared/src/config-rendering.ts
🚧 Files skipped from review as they are similar to previous changes (2)
- apps/e2e/tests/general/cli.test.ts
- packages/stack-shared/src/config-authoring.test.ts
- Introduced `createRequire` to support module aliasing in `local-emulator.ts` and `config-file.ts`, allowing for more flexible configuration imports. - Updated the `createJiti` function to include an alias for `@stackframe/stack-shared/config`, improving module resolution. - Added a test case in `config-authoring.test.ts` to verify that `defineStackConfig` returns its input unchanged, ensuring expected behavior in config authoring.
- Replaced `defineStackConfig` with type imports for `StackConfig` in multiple files, enhancing type safety. - Updated the `renderConfigFile` function to `renderConfigFileContent`, streamlining the rendering process. - Adjusted tests to reflect changes in config import statements and ensure compatibility with the new type definitions. - Removed deprecated `stack-config-file.ts` as part of the refactor.
|
@greptile-ai review and re-score |
There was a problem hiding this comment.
🧹 Nitpick comments (1)
apps/e2e/tests/backend/endpoints/api/v1/internal/config-local-emulator.test.ts (1)
114-117: Brittle whitespace-dependent assertion.The string match
'"teams": {\n "allowClientTeamCreation": true\n }'is sensitive to exact formatting (newlines, indentation). IfrenderConfigFileContentchanges its output style, this test will break even if the content is semantically correct.Consider parsing the config object from the file and asserting on the parsed structure, similar to how
cli.test.tsusesextractConfigObjectString+JSON.parse.♻️ Suggested approach
const fileContent = await fs.readFile(filePath, "utf-8"); expect(fileContent).toContain('import type { StackConfig } from "@stackframe/stack-shared/config";'); - expect(fileContent).toContain('"teams": {\n "allowClientTeamCreation": true\n }'); + // Extract and parse the config object for a more robust assertion + const configMatch = fileContent.match(/export const config:\s*StackConfig\s*=\s*(.+);\s*$/s); + expect(configMatch).not.toBeNull(); + const parsedConfig = JSON.parse(configMatch![1]); + expect(parsedConfig.teams).toEqual({ allowClientTeamCreation: true });🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/e2e/tests/backend/endpoints/api/v1/internal/config-local-emulator.test.ts` around lines 114 - 117, The assertion is brittle because it depends on exact whitespace in fileContent; instead extract the config object string from fileContent (reuse the existing extractConfigObjectString helper used in cli.test.ts), JSON.parse that string into an object, and assert on the parsed shape (e.g., parsedConfig.teams.allowClientTeamCreation === true). Keep the existing import line assertion but replace the raw string match with parsing via extractConfigObjectString(fileContent) -> JSON.parse(...) and then use the parsed object in assertions.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In
`@apps/e2e/tests/backend/endpoints/api/v1/internal/config-local-emulator.test.ts`:
- Around line 114-117: The assertion is brittle because it depends on exact
whitespace in fileContent; instead extract the config object string from
fileContent (reuse the existing extractConfigObjectString helper used in
cli.test.ts), JSON.parse that string into an object, and assert on the parsed
shape (e.g., parsedConfig.teams.allowClientTeamCreation === true). Keep the
existing import line assertion but replace the raw string match with parsing via
extractConfigObjectString(fileContent) -> JSON.parse(...) and then use the
parsed object in assertions.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 50d7b0d3-cd61-4da7-9a7e-d7000f74c952
📒 Files selected for processing (7)
apps/e2e/tests/backend/endpoints/api/v1/internal/config-local-emulator.test.tsapps/e2e/tests/backend/endpoints/api/v1/internal/local-emulator-project.test.tsapps/e2e/tests/general/cli.test.tspackages/stack-cli/src/commands/config-file.tspackages/stack-cli/src/commands/init.tspackages/stack-shared/src/config-authoring.test.tspackages/stack-shared/src/config-rendering.ts
🚧 Files skipped from review as they are similar to previous changes (3)
- packages/stack-cli/src/commands/config-file.ts
- packages/stack-shared/src/config-authoring.test.ts
- packages/stack-shared/src/config-rendering.ts
…st files and CLI commands - Changed import statements in various test files and the CLI command to reference the new StackConfig path. - Updated error messages in the config-file command to reflect the new import structure. - Adjusted the config rendering logic to align with the updated import path for StackConfig.
|
@greptile-ai review |
There was a problem hiding this comment.
🧹 Nitpick comments (2)
apps/e2e/tests/backend/endpoints/api/v1/internal/config-local-emulator.test.ts (1)
115-117: Prefer inline snapshots over brittle multilinetoContainchecks.These assertions are sensitive to whitespace/formatting. A single inline snapshot is usually clearer and more stable for generated-file output checks.
♻️ Suggested refactor
- const fileContent = await fs.readFile(filePath, "utf-8"); - expect(fileContent).toContain('import type { StackConfig } from "@stackframe/js";'); - expect(fileContent).toContain('"teams": {\n "allowClientTeamCreation": true\n }'); + const fileContent = await fs.readFile(filePath, "utf-8"); + expect(fileContent).toMatchInlineSnapshot(` +"import type { StackConfig } from \\"@stackframe/js\\"; + +export const config: StackConfig = { + \\"teams\\": { + \\"allowClientTeamCreation\\": true + } +}; +" +`);Based on learnings: "When writing tests, prefer .toMatchInlineSnapshot over other selectors, if possible."
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/e2e/tests/backend/endpoints/api/v1/internal/config-local-emulator.test.ts` around lines 115 - 117, Replace the brittle multiline toContain checks on the generated file string with a single inline snapshot assertion: capture the value returned by await fs.readFile(filePath, "utf-8") (variable fileContent) and use expect(fileContent).toMatchInlineSnapshot(`...`) containing the exact expected file output; update the test in config-local-emulator.test.ts to remove the two expect(...).toContain(...) lines and instead assert a single inline snapshot for fileContent so formatting/whitespace changes are versioned in the snapshot.apps/e2e/tests/backend/endpoints/api/v1/internal/local-emulator-project.test.ts (1)
88-89: Good assertion target; consider snapshotting this generated snippet.This is a solid check for typed output, but
toMatchInlineSnapshotwill usually be easier to maintain than multipletoContainassertions.♻️ Suggested refactor
- expect(fileContent).toContain('import type { StackConfig } from "@stackframe/js";'); - expect(fileContent).toContain("export const config: StackConfig ="); + expect(fileContent).toMatchInlineSnapshot(` +"import type { StackConfig } from \\"@stackframe/js\\"; + +export const config: StackConfig = { + ... +}; +" +`);Based on learnings: "When writing tests, prefer .toMatchInlineSnapshot over other selectors, if possible."
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/e2e/tests/backend/endpoints/api/v1/internal/local-emulator-project.test.ts` around lines 88 - 89, Replace the two .toContain assertions on fileContent with a single .toMatchInlineSnapshot assertion: locate the test that calls expect(fileContent).toContain('import type { StackConfig } ...') and expect(fileContent).toContain("export const config: StackConfig ="), remove those two expects and replace with expect(fileContent).toMatchInlineSnapshot(`...`) containing the exact generated snippet (the import line and the export const config block) so the generated code is snapshot-tested as a single, maintainable inline snapshot.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In
`@apps/e2e/tests/backend/endpoints/api/v1/internal/config-local-emulator.test.ts`:
- Around line 115-117: Replace the brittle multiline toContain checks on the
generated file string with a single inline snapshot assertion: capture the value
returned by await fs.readFile(filePath, "utf-8") (variable fileContent) and use
expect(fileContent).toMatchInlineSnapshot(`...`) containing the exact expected
file output; update the test in config-local-emulator.test.ts to remove the two
expect(...).toContain(...) lines and instead assert a single inline snapshot for
fileContent so formatting/whitespace changes are versioned in the snapshot.
In
`@apps/e2e/tests/backend/endpoints/api/v1/internal/local-emulator-project.test.ts`:
- Around line 88-89: Replace the two .toContain assertions on fileContent with a
single .toMatchInlineSnapshot assertion: locate the test that calls
expect(fileContent).toContain('import type { StackConfig } ...') and
expect(fileContent).toContain("export const config: StackConfig ="), remove
those two expects and replace with
expect(fileContent).toMatchInlineSnapshot(`...`) containing the exact generated
snippet (the import line and the export const config block) so the generated
code is snapshot-tested as a single, maintainable inline snapshot.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: c25255b7-119f-4525-8ac8-ba336be27d83
📒 Files selected for processing (6)
apps/e2e/tests/backend/endpoints/api/v1/internal/config-local-emulator.test.tsapps/e2e/tests/backend/endpoints/api/v1/internal/local-emulator-project.test.tsapps/e2e/tests/general/cli.test.tspackages/stack-cli/src/commands/config-file.tspackages/stack-shared/src/config-rendering.tspackages/template/src/index.ts
✅ Files skipped from review due to trivial changes (2)
- packages/template/src/index.ts
- apps/e2e/tests/general/cli.test.ts
🚧 Files skipped from review as they are similar to previous changes (2)
- packages/stack-cli/src/commands/config-file.ts
- packages/stack-shared/src/config-rendering.ts
…alidation - Replaced direct string containment checks with inline snapshots for file content validation in `config-local-emulator.test.ts` and `local-emulator-project.test.ts`. - Ensured that the tests accurately reflect the expected structure of the StackConfig imports and configurations.
|
@greptile-ai review |
Summary
defineStackConfighelper andStackConfigtype for nested config authoringstack.configformatTesting
Summary by CodeRabbit
New Features
Improvements
Tests