Assess, plan, evolve.
Reusable compiler-aware skills that help coding agents understand, plan, and safely evolve your codebase.
39 packages
## Example This codemod turns X into Y. It also does Z. Note: this is a contrived example. Please modify it. ### Before ```ts // convert vue2 script component into vue 3 setup export default { data: () => ({ message: 'Hello' }), }; ``` ### After ```ts const message = ref('Hello'); export default {}; ``` ,This codemod turns X into Y. It also does Z. Note: this is a contrived example. Please modify it. ### Before ```ts // convert vue2 script component into vue 3 setup export default { data: () => ({ isActive: true }), }; ``` ### After ```ts const isActive = ref(true); export default {}; ``` ,This codemod turns X into Y. It also does Z. Note: this is a contrived example. Please modify it. ### Before ```ts // convert vue2 script component into vue 3 setup export default { data: () => ({ items: [1, 2, 3] }), }; ``` ### After ```ts const items = ref([1, 2, 3]); export default {}; ``` ,This codemod turns X into Y. It also does Z. Note: this is a contrived example. Please modify it. ### Before ```ts // convert vue2 script component into vue 3 setup export default { data: () => ({ count: 0, message: 'Hello', isActive: true, items: [1, 2, 3], }), }; ``` ### After ```ts const items = ref([1, 2, 3]); const isActive = ref(true); const message = ref('Hello'); const count = ref(0); export default {}; ``` ,This codemod turns X into Y. It also does Z. Note: this is a contrived example. Please modify it. ### Before ```ts // convert vue2 script component into vue 3 setup export default { methods: { displayCoucou: function() { // the content isn't relevant console.log('coucou'); }, }, }; ``` ### After ```ts export default { methods: { displayCoucou: function() { // the content isn't relevant console.log('coucou'); }, }, }; ``` ,This codemod turns X into Y. It also does Z. Note: this is a contrived example. Please modify it. ### Before ```ts // convert vue2 script component into vue 3 setup export default { methods: { fetchApi: async function() { const request = await fetch('/request/info'); }, }, }; ``` ### After ```ts // convert vue2 script component into vue 3 setup export default { methods: { fetchApi: async function() { const request = await fetch('/request/info'); }, }, }; ``` ,This codemod turns X into Y. It also does Z. Note: this is a contrived example. Please modify it. ### Before ```ts export default { data: () => ({ count: 0 }), methods: { increment: function() { this.count += 1; }, }, }; ``` ### After ```ts const count = ref(0); export default { methods: { increment: function() { this.count += 1; }, }, }; ``` ,This codemod turns X into Y. It also does Z. Note: this is a contrived example. Please modify it. ### Before ```ts export default { data: () => ({ count: 0 }), methods: { increment: async function() { this.count = await (await fetch('/request')).json(); }, }, }; ``` ### After ```ts import { ref } from 'vue'; const count = ref(0); export default { data: () => ({ count: 0 }), methods: { increment: async function() { this.count = await (await fetch('/request')).json(); }, }, }; ```
- vue
- 3
- +1
Identify cases where an arrow function is mistakenly used instead of a comparison operator (e.g., x => 0 instead of x >= 0) and convert the arrow function expressions to proper comparison operations. ### Before ```ts // Arrow Function Misused as a Comparison const x = 5; if ((x) => 0) { //some awesome code } ``` ### After ```ts const x = 5; if (x >= 0) { //some awesome code } ```
- TypeScript
- best-practices
This recipe provides a collection of codemods to help you migrate your codebase to [Preact X](https://preactjs.com/guide/v10/upgrade-guide). These codemods are designed to streamline the transition process by automating common code transformations. ## Codemods Included The following codemods are included in this recipe: 1. **Replace `this.state` with `prevState`** Converts instances of `this.state` to use `prevState` to align with Preact X best practices. 2. **Convert `props.children` to `childArray`** Transforms `props.children` into a child array, which is the recommended structure in Preact X. 3. **Update Preact Import Source** Updates import paths to the new Preact X syntax, ensuring that your imports align with the latest version. 4. **Convert Default Import to Namespace Import** Replaces default imports with namespace imports (`import * as Preact from 'preact';`) to prevent potential issues and improve compatibility with Preact X.
- migration
- preact
Since Next.js 13.4, you can mark the files that contain only client-side code with the `use client` directive at the top. The codemod will look for identifiers and string literals common for files that contain client-side code, such as React hooks or event handlers. On the other hand, it will not upsert any directive should it spot elements indicating server-side code. The codemod will not remove the existing `use client` directive even if it would suggest otherwise due to the code in question. ## Example ### Before ```jsx import { useState } from "react"; export default function Page() { const [x, setX] = useState(""); return x; } ``` ### After ```jsx "use client"; import { useState } from "react"; export default function Page() { const [x, setX] = useState(""); return x; } ```
- next.js
- migration
# Feature Documentation: Updating `null` Comparisons to `undefined` ## Overview Default `data` and `error` values in `useAsyncData` and `useFetch` ### What Changed The `data` and `error` objects returned from `useAsyncData` and `useFetch` will now default to `undefined`. ## Before and After Examples ### Before ```javascript const { data, error } = useAsyncData( () => client.value.v1.lists.$select(list.value).fetch(), { default: () => shallowRef(), }, ); if (data.value === null) { // Handle case where data is null } let x = data.value === null ? "No Data" : error.value === null ? "Error" : "Data Available"; ``` ### After ```javascript const { data, error } = useAsyncData( () => client.value.v1.lists.$select(list.value).fetch(), { default: () => shallowRef(), }, ); if (data.value === undefined) { // Handle case where data is undefined } let x = data.value === undefined ? "No Data" : error.value === undefined ? "Error" : "Data Available"; ```
- nuxt
- 4
- +1
Migrate Mocha 8.x tests to Node.js (22.x, 24.x) test runner
- transformation
- migration
- +2
To send a response from MSW handler, one would previously use something like `res(ctx.text("Hello world"))`. In msw v2, this is achieved by returning a native WebAPI Response object. msw v2 conveniently exposes a `HttpResponse` function that has useful methods for creating just that object with a desired body. This codemod replaces the old `res` calls with the new `HttpResponse` function calls and a bunch of ctx utilities that usually go with it. See examples below. This codemod does not remove unused properties on the callback signature due to the fact that there are more changes in other codemods included in the `upgrade-recipe` that rely on it. To apply these changes, you will have to run the recipe or run a `callback-signature` codemod that will do only that and replace all the references of old signature arguments. ## Before ```ts import { rest } from "msw"; rest.get("/user", (req, res, ctx) => { return res( ctx.json({ id: "abc-123" }), ctx.cookie("roses", "red"), ctx.cookie("violets", "blue"), ctx.set("X-Custom", "value"), ); }); ``` ## After ```ts import { rest } from "msw"; rest.get("/user", (req, res, ctx) => { return HttpResponse.json( { id: "abc-123" }, { headers: { "X-Custom": "value", "Set-Cookie": "roses=red;violets=blue;", }, }, ); }); ``` ## Before ```ts import { rest } from "msw"; rest.get("/user", (req, res, ctx) => { return res(ctx.text("Hello world!"), ctx.delay(500), ctx.status(401)); }); ``` ## After ```ts import { rest, delay } from "msw"; rest.get("/user", (req, res, ctx) => { await delay(500); return HttpResponse.text("Hello world", { status: 401, }); }); ``` ## Before ```ts import { rest } from "msw"; rest.get("/user", (req, res, ctx) => { return res(ctx.body("Hello world!"), ctx.set("Content-Type", "text/plain")); }); ``` ## After ```ts import { delay, rest } from "msw"; rest.get("/user", (req, res, ctx) => { return HttpResponse.text("Hello world"); }); ``` ## Before ```ts import { rest } from "msw"; rest.get("/user", (req, res, ctx) => { return res(ctx.text("Hello world!")); }); ``` ## After ```ts import { rest } from "msw"; rest.get("/user", (req, res, ctx) => { return HttpResponse.text("Hello world"); }); ``` ## Before ```ts graphql.query("GetUser", (req, res, ctx) => { return res( ctx.data({ user: { firstName: "John" }, }), ctx.errors([ { message: `Failed to login: user "${username}" does not exist` }, ]), ctx.extensions({ requestId: "abc-123", }), ); }); ``` ## After ```ts graphql.query('GetUser', (req, res, ctx) => { return HttpResponse.json( data: { user: { firstName: 'John' }, }, errors: [ { message: `Failed to login: user "${username}" does not exist` }, ], extensions: { requestId: 'abc-123', }, ) }) ```
- msw
- v2
## Example This codemod turns X into Y. It also does Z. Note: this is a contrived example. Please modify it. ### Before ```ts import React from 'react'; import PropTypes from 'prop-types'; import { makeStyles, useTheme } from '@material-ui/styles'; import classNames from 'classnames'; import Button from '../../../../components/controls/Button'; import ButtonLoader from '../../../../components/loaders/ButtonLoader'; import makeStateElementName from '../../../../theme-editor/utils/makeStateElementName'; const useStyles = makeStyles((theme) => ({ stakeButton: ({ editorId }) => ({ width: '100%', height: 40, fontWeight: 600, ...theme[editorId], }), stakeButtonDisabled: ({ editorId }) => ({ ...theme[`${makeStateElementName(editorId, 'disabled')}`], }), '@media (hover: hover)': { stakeButtonDisabled: ({ editorId }) => ({ '&:hover': { ...theme[`${makeStateElementName(editorId, 'disabled')}`], }, }), }, loaderContainer: { width: '100%', height: '100%', display: 'flex', alignItems: 'center', justifyContent: 'center', }, })); const StakeInputButton = ({ onClick, isDisabled, children, className, isLoading, dataEditorId, }) => { const classes = useStyles({ editorId: dataEditorId }); const theme = useTheme(); return ( < Button elementClasses = { { default: classNames(classes.stakeButton, className), disabled: classes.stakeButtonDisabled, } } disabled = { isDisabled } onClick = { onClick } style = { { padding: 0, } } dataEditorId = { dataEditorId } > { isLoading ? ( < div className = { classes.loaderContainer } > < ButtonLoader color = { theme.brandButton.color } /> < /div> ) : ( children ) } < /Button> ); }; StakeInputButton.propTypes = { dataEditorId: PropTypes.string, }; StakeInputButton.defaultProps = { dataEditorId: 'betslipPlaceBetButton', }; export default StakeInputButton; ``` ### After ```ts import React from 'react'; import PropTypes from 'prop-types'; import { makeStyles, useTheme } from '@material-ui/styles'; import classNames from 'classnames'; import Button from '../../../../components/controls/Button'; import ButtonLoader from '../../../../components/loaders/ButtonLoader'; import makeStateElementName from '../../../../theme-editor/utils/makeStateElementName'; const useStyles = makeStyles((theme) => ({ stakeButton: ({ editorId }) => ({ width: '100%', height: 40, fontWeight: 600, ...theme[editorId], }), stakeButtonDisabled: ({ editorId }) => ({ ...theme[`${makeStateElementName(editorId, 'disabled')}`], }), '@media (hover: hover)': { stakeButtonDisabled: ({ editorId }) => ({ '&:hover': { ...theme[`${makeStateElementName(editorId, 'disabled')}`], }, }), }, loaderContainer: { width: '100%', height: '100%', display: 'flex', alignItems: 'center', justifyContent: 'center', }, })); const StakeInputButton = ({ onClick, isDisabled, children, className, isLoading, dataEditorId = 'betslipPlaceBetButton', }) => { const classes = useStyles({ editorId: dataEditorId }); const theme = useTheme(); return ( < Button elementClasses = { { default: classNames(classes.stakeButton, className), disabled: classes.stakeButtonDisabled, } } disabled = { isDisabled } onClick = { onClick } style = { { padding: 0, } } dataEditorId = { dataEditorId } > { isLoading ? ( < div className = { classes.loaderContainer } > < ButtonLoader color = { theme.brandButton.color } /> < /div> ) : ( children ) } < /Button> ); }; StakeInputButton.propTypes = { dataEditorId: PropTypes.string, }; export default StakeInputButton; ``` ,This codemod turns X into Y. It also does Z. Note: this is a contrived example. Please modify it. ### Before ```ts // In react 19 default props should be replaced with js default function parameters import React from 'react'; import PropTypes from 'prop-types'; import { useSelector } from 'react-redux'; import { useTranslation } from 'react-i18next'; import { makeStyles } from '@material-ui/styles'; import classNames from 'classnames'; import Button from '../../../components/controls/Button'; import { selectors as betsSelectors } from '../../../redux/ducks/bets'; import useOfflineBooking from '../hooks/useOfflineBooking'; const useStyles = makeStyles({ bookingButton: { width: '100%', fontWeight: 600, }, }); const BookingCodeBookButton = ({ className, dataEditorId }) => { const { makeBooking } = useOfflineBooking(); const { t } = useTranslation(); const classes = useStyles(); const selectionsValid = useSelector(betsSelectors.selectSelectionsValid); return ( < Button className = { classNames(classes.bookingButton, className) } disabled = {!selectionsValid } onClick = { () => (selectionsValid ? makeBooking() : null) } dataEditorId = { dataEditorId } > { t('Book') } < /Button> ); }; BookingCodeBookButton.propTypes = { className: PropTypes.string, dataEditorId: PropTypes.string, }; BookingCodeBookButton.defaultProps = { className: null, dataEditorId: 'betslipShareButton', }; export default BookingCodeBookButton; ``` ### After ```ts import React from 'react'; import PropTypes from 'prop-types'; import { useSelector } from 'react-redux'; import { useTranslation } from 'react-i18next'; import { makeStyles } from '@material-ui/styles'; import classNames from 'classnames'; import Button from '../../../components/controls/Button'; import { selectors as betsSelectors } from '../../../redux/ducks/bets'; import useOfflineBooking from '../hooks/useOfflineBooking'; const useStyles = makeStyles({ bookingButton: { width: '100%', fontWeight: 600, }, }); const BookingCodeBookButton = ({ className = null, dataEditorId = 'betslipShareButton', }) => { const { makeBooking } = useOfflineBooking(); const { t } = useTranslation(); const classes = useStyles(); const selectionsValid = useSelector(betsSelectors.selectSelectionsValid); return ( < Button className = { classNames(classes.bookingButton, className) } disabled = {!selectionsValid } onClick = { () => (selectionsValid ? makeBooking() : null) } dataEditorId = { dataEditorId } > { t('Book') } < /Button> ); }; BookingCodeBookButton.propTypes = { className: PropTypes.string, dataEditorId: PropTypes.string, }; export default BookingCodeBookButton; ``` ,This codemod turns X into Y. It also does Z. Note: this is a contrived example. Please modify it. ### Before ```ts // do not add new parameter if default props exist but is not defined in function parameters import React from 'react'; import PropTypes from 'prop-types'; import { useTranslation } from 'react-i18next'; import { makeStyles, useTheme } from '@material-ui/styles'; import ButtonArrow from '../../../../components/controls/ButtonArrow'; import SliderPoints from '../../../../components/controls/SliderPoints'; import BetSlipBonusesSlider from '../../BetSlipBonusesSlider'; import BetSlipEmptyBlock from '../../BetSlipTable/BetSlipEmptyBlock'; const useStyles = makeStyles((theme) => ({ bonusesListContainer: { background: theme.bonusPopup.background, color: theme.bonusPopup.color, paddingBottom: 20, overflowY: 'auto', boxSizing: 'border-box', }, points: { maxWidth: 200, margin: '0 auto', }, topLine: { marginBottom: 8, padding: '8px 16px', }, betSlipEmptyBlock: { minHeight: 275, }, })); const BetSlipBonusesListBase = ({ slides, currentSlide, setCurrentSlide, onCloseButtonClick, className, maxHeight, }) => { const theme = useTheme(); const classes = useStyles(); const { t } = useTranslation(); const arrowButtonBackground = theme.bonusPopup.background; return ( < div className = { `${classes.bonusesListContainer} ${className}` } style = { { maxHeight } } > < div className = { classes.topLine } > < ButtonArrow backgroundColor = { arrowButtonBackground } label = { t('Back') } onClick = { onCloseButtonClick } size = { 32 } direction = 'left' / > < /div> { slides.length > 0 ? ( < > < BetSlipBonusesSlider items = { slides } currentSlide = { currentSlide } setCurrentSlide = { setCurrentSlide } /> { !!slides.length && ( < div className = { classes.points } > < SliderPoints count = { slides.length } activeIndex = { currentSlide } color = { theme.bonusPopup.color } activeColor = { theme.bonusPopup.color } /> < /div> ) } < /> ) : ( < BetSlipEmptyBlock text = { t('No available Bonuses at this moment') } className = { classes.betSlipEmptyBlock } /> ) } < /div> ); }; BetSlipBonusesListBase.propTypes = { className: PropTypes.string, placeholder: PropTypes.string, // for widgets showBonusesForBet: PropTypes.string, toggleChooseBonusBlock: PropTypes.func.isRequired, onUseBonus: PropTypes.func.isRequired, onActivateBonus: PropTypes.func.isRequired, availableBonusesIds: PropTypes.arrayOf(PropTypes.string), bonuses: PropTypes.objectOf(PropTypes.shape({})).isRequired, }; BetSlipBonusesListBase.defaultProps = { placeholder: null, className: null, showBonusesForBet: null, availableBonusesIds: null, }; export default BetSlipBonusesListBase; ``` ### After ```ts import React from 'react'; import PropTypes from 'prop-types'; import { useTranslation } from 'react-i18next'; import { makeStyles, useTheme } from '@material-ui/styles'; import ButtonArrow from '../../../../components/controls/ButtonArrow'; import SliderPoints from '../../../../components/controls/SliderPoints'; import BetSlipBonusesSlider from '../../BetSlipBonusesSlider'; import BetSlipEmptyBlock from '../../BetSlipTable/BetSlipEmptyBlock'; const useStyles = makeStyles((theme) => ({ bonusesListContainer: { background: theme.bonusPopup.background, color: theme.bonusPopup.color, paddingBottom: 20, overflowY: 'auto', boxSizing: 'border-box', }, points: { maxWidth: 200, margin: '0 auto', }, topLine: { marginBottom: 8, padding: '8px 16px', }, betSlipEmptyBlock: { minHeight: 275, }, })); const BetSlipBonusesListBase = ({ slides, currentSlide, setCurrentSlide, onCloseButtonClick, className = null, maxHeight, }) => { const theme = useTheme(); const classes = useStyles(); const { t } = useTranslation(); const arrowButtonBackground = theme.bonusPopup.background; return ( < div className = { `${classes.bonusesListContainer} ${className}` } style = { { maxHeight } } > < div className = { classes.topLine } > < ButtonArrow backgroundColor = { arrowButtonBackground } label = { t('Back') } onClick = { onCloseButtonClick } size = { 32 } direction = 'left' / > < /div> { slides.length > 0 ? ( < > < BetSlipBonusesSlider items = { slides } currentSlide = { currentSlide } setCurrentSlide = { setCurrentSlide } /> { !!slides.length && ( < div className = { classes.points } > < SliderPoints count = { slides.length } activeIndex = { currentSlide } color = { theme.bonusPopup.color } activeColor = { theme.bonusPopup.color } /> < /div> ) } < /> ) : ( < BetSlipEmptyBlock text = { t('No available Bonuses at this moment') } className = { classes.betSlipEmptyBlock } /> ) } < /div> ); }; BetSlipBonusesListBase.propTypes = { className: PropTypes.string, placeholder: PropTypes.string, // for widgets showBonusesForBet: PropTypes.string, toggleChooseBonusBlock: PropTypes.func.isRequired, onUseBonus: PropTypes.func.isRequired, onActivateBonus: PropTypes.func.isRequired, availableBonusesIds: PropTypes.arrayOf(PropTypes.string), bonuses: PropTypes.objectOf(PropTypes.shape({})).isRequired, }; export default BetSlipBonusesListBase; ```
Short description Detailed description ## Example ### Before ```ts const toReplace = "hello"; ``` ### After ```ts const replacement = "hello"; ```
This codemod replaces feature flags with a static value provided by the user. Codemod replaces `useFlag` hook calls. The codemod accepts the following arguments: - `key`: The key of the feature flag to be replaced. - `value`: The value to replace the feature flag with. - `type`: The type to which the provided value should be cast. ## Example ### Before ```ts const theValue = useFlag("the-gate").value; if (theValue) { // Simple Case is true console.log("theValue is truthy"); } if (theValue === 3) { console.log("value var === 3"); } const x = theValue ? 1 : 0; ``` ### After ```ts // Simple Case is true console.log("theValue is truthy"); const x = 1; ```
- netlify
- feature-flag
In Vue 3.x, h is now globally imported instead of being automatically passed as an argument. This codemod migrates the render function API to be compatible with Vue 3.x. ## Before ```ts export default { render(h) { return h("div"); }, }; ``` ## After ```ts import { h } from "vue"; export default { render() { return h("div"); }, }; ```
- vue
Codemod to replace the deprecated Severity enum with the SeverityLevel type in Sentry from version 7.x to 8.x. ## Example ### Before ```ts import { Severity } from '@sentry/types'; ``` ### After ```ts import { SeverityLevel } from '@sentry/types'; ``` , ### Before ```ts const level = Severity.error; ``` ### After ```ts const level: SeverityLevel = 'error'; ``` , ### Before ```ts const warningLevel = Severity.warning; const infoLevel = Severity.info; ``` ### After ```ts const warningLevel: SeverityLevel = 'warning'; const infoLevel: SeverityLevel = 'info'; ``` , ### Before ```ts let currentLevel = Severity.fatal; ``` ### After ```ts let currentLevel: SeverityLevel = 'fatal'; ``` , ### Before ```ts function getSeverity() { return Severity.debug; } ``` ### After ```ts function getSeverity(): SeverityLevel { return 'debug'; } ```
- sentry
- migration
- +1
Ready to evolve your codebase?
Build tailored, compiler-aware skills to assess, plan, and automate complex codebase changes.