-
-
Notifications
You must be signed in to change notification settings - Fork 0
feat: add config package to normalize tsdown options #57
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: dev
Are you sure you want to change the base?
Conversation
…error handling Signed-off-by: GitHub <noreply@github.com>
Signed-off-by: GitHub <noreply@github.com>
Signed-off-by: GitHub <noreply@github.com>
Signed-off-by: GitHub <noreply@github.com>
|
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #57 +/- ##
==========================================
+ Coverage 93.80% 97.31% +3.50%
==========================================
Files 19 21 +2
Lines 872 1080 +208
Branches 215 265 +50
==========================================
+ Hits 818 1051 +233
+ Misses 54 29 -25 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Summary of Changes
Hello @mcansh, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!
This pull request primarily focuses on improving the developer experience and consistency within the monorepo by introducing a new shared configuration package for tsdown
, a build tool. This centralization streamlines build setups across various packages. Concurrently, the vitest-response-matchers
package has undergone a substantial refactoring to enhance its reliability, type safety, and testing capabilities. Minor tooling updates and code formatting adjustments are also included to maintain overall code quality.
Highlights
- Centralized
tsdown
Configuration: Introduced a new@mcansh/config
package that provides adefaultBuildConfig
and amergeBuildConfig
utility. This allows other packages in the monorepo to easily adopt and extend a standardizedtsdown
build configuration, reducing boilerplate and ensuring consistency. tsdown
Integration: Updatedtsdown.config.ts
files inhttp-helmet
,url
, andvitest-response-matchers
packages to leverage the new@mcansh/config
package, simplifying their build configurations.- Enhanced Vitest Response Matchers: Significantly refactored the
vitest-response-matchers
package. This includes introducing a newutils.ts
file for common helpers, updating matcher type definitions to correctly handle asynchronous operations (e.g.,toHaveJsonBody
,toHaveTextBody
,toThrowResponse
) by returningPromise<MatcherResult>
, improving the robustness of existing matchers with better error handling and more comprehensive test cases, and extendingtoMatchResponse
to support header matching. - Tooling and Dependency Updates: Updated various monorepo-level configurations and dependencies, including adding
tsgo
for type checking, integratingprettier-plugin-jsdoc
for improved JSDoc formatting, and removing custompublish.js
andversion.js
scripts (implying reliance on standardchangeset
orpnpm
commands).
Using Gemini Code Assist
The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.
Invoking Gemini
You can request assistance from Gemini at any point in your pull request via creating an issue comment (i.e. comment on the pull request page) using either /gemini <command>
or @gemini-code-assist <command>
. Below is a summary of the supported commands.
Feature | Command | Description |
---|---|---|
Code Review | /gemini review |
Performs a code review for the current pull request in its current state. |
Pull Request Summary | /gemini summary |
Provides a summary of the current pull request in its current state. |
Comment | @gemini-code-assist | Responds in comments when explicitly tagged, both in issue comments and review comments. |
Help | /gemini help |
Displays a list of available commands. |
Customization
To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/
folder in the base of the repository. Detailed instructions can be found here.
Limitations & Feedback
Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments or fill out our survey to provide feedback.
You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.
Footnotes
-
Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution. ↩
commit: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Code Review
This pull request introduces a new @mcansh/config
package to centralize tsdown
build configurations, which is a great step towards improving maintainability and consistency across the monorepo. The refactoring of other packages to use this new config package is well-executed and demonstrates its value.
Additionally, there are significant improvements to the @mcansh/vitest-response-matchers
package, including making several matchers asynchronous for correctness and enhancing their APIs. The move to changesets
for versioning and publishing by removing custom scripts is also a welcome modernization of the project's tooling.
I've identified a few areas for improvement, including a critical bug in header matching logic and a couple of high-severity issues related to package metadata and a logic regression. Addressing these will further strengthen the quality of the codebase.
if (expected.headers) { | ||
for (const [name, value] of Object.entries(expected.headers)) { | ||
if (response.headers.get(name) !== value) { | ||
return { | ||
pass: false, | ||
actual: { | ||
status: response.status, | ||
statusText: response.statusText, | ||
headers: formatHeaders(response.headers), | ||
}, | ||
expected: { | ||
status: expected.status, | ||
statusText: expected.statusText, | ||
headers: formatHeaders(expected.headers), | ||
}, | ||
message() { | ||
return `Expected response to have (status: ${expected.status}, statusText: "${expected.statusText}"), but received (status: ${response.status}, statusText: "${response.statusText}")`; | ||
}, | ||
}; | ||
} | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The current implementation for checking headers is incorrect. Object.entries(expected.headers)
will not work as intended for Headers
objects or string[][]
arrays, which are valid HeadersInit
types. This will cause the matcher to fail to check headers correctly in those cases.
To fix this, you should normalize expected.headers
into a Headers
object before iterating over it. This ensures all HeadersInit
types are handled correctly. I've also improved the failure message to be more specific about which header failed.
if (expected.headers) {
const expectedHeaders = new Headers(expected.headers);
for (const [name, value] of expectedHeaders.entries()) {
if (response.headers.get(name) !== value) {
return {
pass: false,
actual: {
status: response.status,
statusText: response.statusText,
headers: formatHeaders(response.headers),
},
expected: {
status: expected.status,
statusText: expected.statusText,
headers: formatHeaders(expected.headers),
},
message() {
return `Expected header "${name}" to be "${value}", but got "${response.headers.get(
name,
)}"`;
},
};
}
}
}
"repository": { | ||
"type": "git", | ||
"url": "git+https://github.com/mcansh/packages.git", | ||
"directory": "./packages/vitest-response-matchers" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The repository.directory
field appears to have an incorrect value. It should point to this package's directory, ./packages/config
, instead of ./packages/vitest-response-matchers
. This could cause issues for tools that rely on this metadata for package discovery and linking.
"directory": "./packages/config"
if (!isResponse(error)) { | ||
return expectedResponseError(error); | ||
} | ||
|
||
if (expected.status && expected.statusText) { | ||
return { | ||
message: () => `Did not throw a Response`, | ||
pass: false, | ||
actual: error, | ||
expected: `[Response]`, | ||
pass: | ||
error.status === expected.status && | ||
error.statusText === expected.statusText, | ||
actual: { status: error.status, statusText: error.statusText }, | ||
expected: { status: expected.status, statusText: expected.statusText }, | ||
message: () => `Expected to throw a Response`, | ||
}; | ||
} | ||
|
||
let expectedResponse = | ||
expected instanceof Response ? expected : new Response(null, expected); | ||
|
||
return { | ||
pass: error.status === expected.status, | ||
actual: { status: error.status }, | ||
expected: { status: expected.status }, | ||
message: () => `Expected to throw a Response`, | ||
pass: | ||
error instanceof Response && | ||
error.status === expectedResponse.status && | ||
error.statusText === expectedResponse.statusText, | ||
actual: { status: error.status, statusText: error.statusText }, | ||
expected: { status: expected.status, statusText: expected.statusText }, | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This refactoring introduces a regression. The previous implementation correctly handled expected
as a Response
object by checking both status
and statusText
. The new logic may only check the status
if expected.statusText
is an empty string (which is the default for many status codes), because if (expected.status && expected.statusText)
will evaluate to false.
To restore the correct behavior, you can normalize the expected
value into a Response
object before performing the comparison, similar to the original implementation.
if (!isResponse(error)) {
return expectedResponseError(error);
}
const expectedResponse =
expected instanceof Response ? expected : new Response(null, expected);
return {
pass:
error.status === expectedResponse.status &&
error.statusText === expectedResponse.statusText,
actual: { status: error.status, statusText: error.statusText },
expected: {
status: expectedResponse.status,
statusText: expectedResponse.statusText,
},
message: () => `Expected to throw a Response`,
};
let config = mergeBuildConfig((config) => { | ||
config.dts = false; | ||
return {}; | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This test case is a bit confusing because it relies on mutating the defaultBuildConfig
object. While it currently passes, this approach can be brittle and hard to reason about.
A clearer way to write this test would be to have the function return the desired configuration overrides without modifying the input object. This avoids side effects and makes the test's intent more explicit.
let config = mergeBuildConfig(() => ({
dts: false,
}));
Deploying with
|
Status | Name | Latest Commit | Preview URL | Updated (UTC) |
---|---|---|---|---|
✅ Deployment successful! View logs |
packages | b60c084 | Commit Preview URL Branch Preview URL |
Jul 31 2025, 06:55 PM |
Signed-off-by: GitHub noreply@github.com