Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 2 additions & 4 deletions .eslintrc
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,7 @@
"node": true,
"jest": true
},
"globals": {
"sinon": true
},
"globals": {},
"rules": {
"semi": [2, "never"],
"no-use-before-define": ["error", { "functions": false }],
Expand All @@ -42,7 +40,7 @@
"react/no-multi-comp": [0],
"react/sort-comp": [0],
"react/jsx-filename-extension": [0],
"prettier/prettier": ["error", {"semi": false, "trailingComma": "es5", "singleQuote": true}],
"prettier/prettier": "error",
"react/destructuring-assignment": [0],
"react/jsx-curly-brace-presence": [0],
"react/no-unused-prop-types": [0],
Expand Down
3 changes: 2 additions & 1 deletion .prettierrc
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
semi: false
singleQuote: true
trailingComma: es5
trailingComma: es5
parser: babel
30 changes: 15 additions & 15 deletions .size-snapshot.json
Original file line number Diff line number Diff line change
@@ -1,25 +1,25 @@
{
"lib/packages/recompose/dist/Recompose.umd.js": {
"bundled": 56428,
"minified": 19441,
"gzipped": 5636
"Recompose.umd.js": {
"bundled": 49359,
"minified": 17069,
"gzipped": 5102
},
"lib/packages/recompose/dist/Recompose.min.js": {
"bundled": 48906,
"minified": 17887,
"gzipped": 5043
"Recompose.min.js": {
"bundled": 41591,
"minified": 15506,
"gzipped": 4511
},
"lib/packages/recompose/dist/Recompose.esm.js": {
"bundled": 32428,
"minified": 15083,
"gzipped": 3550,
"Recompose.esm.js": {
"bundled": 32330,
"minified": 15254,
"gzipped": 3644,
"treeshaked": {
"rollup": {
"code": 310,
"import_statements": 310
"code": 311,
"import_statements": 311
},
"webpack": {
"code": 1838
"code": 1874
}
}
}
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ The project is a fork of [Recompose](https://github.com/acdlite/recompose/) whic

[fbjs](https://github.com/facebook/fbjs) was one of the core dependencies for the last npm release of [Recompose](https://github.com/acdlite/recompose/) i.e [![npm version](https://img.shields.io/npm/v/recompose.svg?style=flat-square)](https://www.npmjs.com/package/recompose). The [Recompose](https://github.com/acdlite/recompose/) project was updated to remove the usage of [fbjs](https://github.com/facebook/fbjs), but it was never published to npm. The fork removes `fbjs` as dependency and updates `@babel/runtime`, `react-lifecycles-compat`, `symbol-observable` and `hoist-non-react-statics` packages to latest versions.

Use `"@shakacode/recompose": "^0.31.0"` for React 17-19, `"@shakacode/recompose": "^0.30.3"` for earlier React versions.

Recompose
-----
Expand Down
2 changes: 1 addition & 1 deletion babel.config.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
module.exports = {
plugins: [['@babel/proposal-class-properties', { loose: true }]],
plugins: [['@babel/transform-class-properties', { loose: true }]],
presets: [['@babel/env', { loose: true }], '@babel/react'],
}

Expand Down
12 changes: 8 additions & 4 deletions docs/API.md
Original file line number Diff line number Diff line change
Expand Up @@ -550,23 +550,27 @@ const Post = enhance(({ title, content, author }) =>
```ts
// TContext = the type of the provided child context
withContext<TContext>(
childContextTypes: PropTypes.ValidationMap<TContext>,
childContextTypes: Record<keyof TContext, unknown>,
getChildContext: (props: Object) => TContext
): HigherOrderComponent
```

Provides context to the component's children. `childContextTypes` is an object of React prop types. `getChildContext()` is a function that returns the child context. Use along with `getContext()`.
Provides context to the component's children. `childContextTypes` is an object whose keys define the context properties to provide. `getChildContext()` is a function that returns the child context values. Use along with `getContext()`.

Note: this uses `React.createContext` internally. The keys of `childContextTypes` are used to create or look up context objects; the values are ignored. This means prop-types validation is no longer performed on context values. Existing code passing `PropTypes.ValidationMap` objects will continue to work.

### `getContext()`

```ts
getContext(
contextTypes: Object
getContext<TContext>(
contextTypes: Record<keyof TContext, unknown>
): HigherOrderComponent
```

Gets values from context and passes them along as props. Use along with `withContext()`.

Note: like `withContext()`, the keys of `contextTypes` determine which context values to consume; the values are ignored.

### `lifecycle()`

```ts
Expand Down
64 changes: 30 additions & 34 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,15 @@
"url": "git://github.com/acdlite/recompose.git"
},
"license": "MIT",
"packageManager": "[email protected]",
"scripts": {
"lint": "eslint scripts src",
"build:recompose": "cross-env PACKAGE_NAME=recompose rollup --config scripts/rollup.config.js",
"test": "jest && flow check && cross-env SNAPSHOT=match npm run build:recompose",
"test:watch": "cross-env BABEL_ENV=cjs jest --watch",
"release": "node scripts/release.js",
"postinstall": "node scripts/installNestedPackageDeps.js",
"format": "prettier --semi false --trailing-comma es5 --single-quote --write 'scripts/*.js' 'src/packages/*/*.js' 'src/packages/*/!(node_modules)/**/*.js'",
"format": "prettier --write 'scripts/*.js' 'src/packages/*/*.js' 'src/packages/*/!(node_modules)/**/*.js'",
"precommit": "lint-staged",
"prepush": "yarn test"
},
Expand All @@ -26,71 +27,66 @@
"text-summary",
"lcov"
],
"setupTestFrameworkScriptFile": "<rootDir>/scripts/jest.setup.js"
"testTimeout": 20000,
"testEnvironment": "jsdom",
"restoreMocks": true
},
"lint-staged": {
"*.js": [
"prettier --semi false --trailing-comma es5 --single-quote --write",
"prettier --write",
"eslint --fix",
"git add"
]
},
"devDependencies": {
"@babel/cli": "^7.0.0",
"@babel/core": "^7.0.0",
"@babel/plugin-proposal-class-properties": "^7.0.0",
"@babel/plugin-transform-runtime": "^7.0.0",
"@babel/preset-env": "^7.0.0",
"@babel/preset-react": "^7.0.0",
"@babel/runtime": "^7.0.0",
"babel-core": "^7.0.0-bridge.0",
"@babel/cli": "^7.22.0",
"@babel/core": "^7.22.0",
"@babel/plugin-transform-class-properties": "^7.25.0",
"@babel/plugin-transform-runtime": "^7.22.0",
"@babel/preset-env": "^7.22.0",
"@babel/preset-react": "^7.22.0",
"@babel/runtime": "^7.22.0",
"@testing-library/dom": "^10.4.0",
"@testing-library/react": "^16.3.0",
"babel-eslint": "^9.0.0",
"babel-jest": "^22.4.3",
"babel-jest": "^29.7.0",
"baconjs": "^0.7.84",
"chalk": "^1.1.1",
"change-case": "^2.3.1",
"codecov": "^1.0.1",
"create-react-class": "^15.5.0",
"cross-env": "^4.0.0",
"enzyme": "^3.3.0",
"eslint": "^5.3.0",
"eslint-config-airbnb": "^17.0.0",
"eslint-config-prettier": "^2.9.0",
"eslint-plugin-import": "^2.13.0",
"eslint-plugin-jsx-a11y": "^6.1.1",
"eslint-plugin-prettier": "^2.0.1",
"eslint-plugin-prettier": "^3.4.0",
"eslint-plugin-react": "^7.10.0",
"flow-bin": "^0.72.0",
"flyd": "^0.2.4",
"husky": "^0.13.3",
"jest": "^22.4.3",
"jest": "^29.7.0",
"jest-environment-jsdom": "^29.7.0",
"kefir": "^3.2.3",
"lint-staged": "^3.4.0",
"most": "^1.0.2",
"prettier": "^1.2.2",
"prettier": "^1.19.1",
"prop-types": "^15.6.1",
"react": "^16.3.1",
"react-dom": "^16.3.1",
"react": "^19.0.0",
"react-dom": "^19.0.0",
Comment on lines +76 to +77
Copy link

@coderabbitai coderabbitai bot Feb 13, 2026

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

# First, locate and examine the package.json file to check peerDependencies
find . -name "package.json" -type f | head -5

Repository: shakacode/recompose

Length of output: 257


🏁 Script executed:

# Show the full package.json to see peerDependencies section
cat package.json | jq '{peerDependencies, devDependencies: .devDependencies | with_entries(select(.key == "react" or .key == "react-dom"))}'

Repository: shakacode/recompose

Length of output: 172


🏁 Script executed:

# Search for CI configuration files that might specify test matrix
find . -type f \( -name "*.yml" -o -name "*.yaml" \) | grep -E "(workflow|ci|github)" | head -10

Repository: shakacode/recompose

Length of output: 634


🏁 Script executed:

# Check full peerDependencies from root package.json
jq '.peerDependencies' package.json

Repository: shakacode/recompose

Length of output: 67


🏁 Script executed:

# Check the recompose package's own package.json for peerDependencies
cat src/packages/recompose/package.json | jq '{peerDependencies, devDependencies: .devDependencies | with_entries(select(.key == "react" or .key == "react-dom"))}'

Repository: shakacode/recompose

Length of output: 113


🏁 Script executed:

# Examine the CI workflow files to check for test matrix
cat .github/workflows/claude-code-review.yml | head -50

Repository: shakacode/recompose

Length of output: 1495


🏁 Script executed:

# Also check the other workflow
cat .github/workflows/claude.yml | head -50

Repository: shakacode/recompose

Length of output: 1948


🏁 Script executed:

# Check the recompose package's package.json directly
cat src/packages/recompose/package.json | head -40

Repository: shakacode/recompose

Length of output: 645


🏁 Script executed:

# Search for any peerDependencies mentions in the codebase
rg "peerDependencies" --type json

Repository: shakacode/recompose

Length of output: 188


🏁 Script executed:

# Check if there are any other test workflow files that might have a matrix
find . -path ./node_modules -prune -o -type f -name "*.yml" -o -name "*.yaml" | xargs grep -l "react\|matrix" 2>/dev/null | grep -v node_modules | head -10

Repository: shakacode/recompose

Length of output: 45


🏁 Script executed:

# Check what the root package.json test script does
cat package.json | jq '.scripts.test'

Repository: shakacode/recompose

Length of output: 135


🏁 Script executed:

# Look at the jest configuration to understand what's being tested
cat package.json | jq '.jest'

Repository: shakacode/recompose

Length of output: 272


🏁 Script executed:

# Check if there's a .github/workflows/test.yml or similar that runs the actual tests
find .github/workflows -name "*.yml" -o -name "*.yaml" | xargs cat 2>/dev/null | grep -A 20 "test\|jest" | head -50

Repository: shakacode/recompose

Length of output: 1387


🏁 Script executed:

# Check the structure - is there a monorepo setup?
ls -la src/packages/

Repository: shakacode/recompose

Length of output: 359


Tests only run against React 19, but the library claims React 17/18 support.

The recompose package declares "react": "^17.0.0 || ^18.0.0 || ^19.0.0" as a peer dependency, yet the root package.json pins react and react-dom devDependencies to ^19.0.0 only. The test suite will validate against React 19 exclusively. Consider adding a CI matrix or local verification step to run tests against React 17 and 18 to ensure compatibility claims are backed by actual validation.

🤖 Prompt for AI Agents
In `@package.json` around lines 76 - 77, Tests are only running against "react"
and "react-dom" pinned to ^19.0.0 while package peerDependencies declare
"react": "^17.0.0 || ^18.0.0 || ^19.0.0", so add CI jobs to validate those
claims: update your CI workflow to include a matrix over REACT_VERSION (17 18
19), install matching versions of "react" and "react-dom" for each matrix entry
before running the test script, or alternately adjust devDependencies to install
multiple versions via npm aliases in the CI run; ensure the CI uses the
peerDependency string "react": "^17.0.0 || ^18.0.0 || ^19.0.0" as the source of
truth and that the test command is executed for each matrix entry to verify
compatibility.

Copy link
Author

Choose a reason for hiding this comment

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

The APIs used are stable. Adding tests for older React versions is a potential improvement, but not worth the complexity.

Copy link

Choose a reason for hiding this comment

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

@alexeyr-ci2, understood. I've noted your preference for the future.

"readline-sync": "^1.2.21",
"rollup": "^0.65.0",
"rollup-plugin-babel": "^4.0.1",
"rollup-plugin-commonjs": "^9.1.6",
"rollup-plugin-node-resolve": "^3.3.0",
"rollup-plugin-replace": "^2.0.0",
"rollup-plugin-size-snapshot": "^0.6.1",
"rollup-plugin-uglify": "^4.0.0",
"@rollup/plugin-babel": "^6.0.0",
"@rollup/plugin-commonjs": "^28.0.0",
"@rollup/plugin-node-resolve": "^16.0.0",
"@rollup/plugin-replace": "^6.0.0",
"@rollup/plugin-terser": "^0.4.0",
"rollup": "^4.0.0",
"rollup-plugin-size-snapshot": "^0.12.0",
Copy link

@coderabbitai coderabbitai bot Feb 12, 2026

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

# First, check what Rollup version is in package.json
cat package.json | grep -A2 -B2 '"rollup"'

Repository: shakacode/recompose

Length of output: 231


🏁 Script executed:

# Check the package.json for rollup version
cat package.json | jq '.dependencies.rollup // .devDependencies.rollup // "not found"'

Repository: shakacode/recompose

Length of output: 71


🏁 Script executed:

# Query npm registry for rollup-plugin-size-snapshot package info
npm view rollup-plugin-size-snapshot versions --json 2>/dev/null | tail -5

Repository: shakacode/recompose

Length of output: 110


🏁 Script executed:

# Get recent releases and maintenance info
npm view rollup-plugin-size-snapshot --json 2>/dev/null | jq '{name, "dist-tags": .["dist-tags"], latest_version: .version, modified: .time.modified, maintainers: .maintainers}'

Repository: shakacode/recompose

Length of output: 283


🏁 Script executed:

# Check specifically for [email protected] details
npm view [email protected] --json 2>/dev/null | jq '{version, peerDependencies, dependencies}'

Repository: shakacode/recompose

Length of output: 405


Replace rollup-plugin-size-snapshot@^0.12.0 with a Rollup 4-compatible alternative.

[email protected] declares a peer dependency on rollup@^2.0.0, but your project uses rollup@^4.0.0. Additionally, the plugin has not been maintained since May 2022 and has no newer releases. This peer dependency mismatch can lead to runtime incompatibilities or unexpected behavior. Consider removing this plugin or migrating to a maintained alternative that supports Rollup 4.

🤖 Prompt for AI Agents
In `@package.json` at line 85, Replace the outdated dependency
"rollup-plugin-size-snapshot" in package.json with a Rollup 4–compatible
alternative (or remove it): remove the "rollup-plugin-size-snapshot": "^0.12.0"
entry, add a maintained plugin that supports rollup@^4 (for example
"rollup-plugin-filesize" or "rollup-plugin-visualizer"), run your package
manager to install, and update any references in your Rollup config (e.g.,
import/usage of the old plugin in rollup.config.js/rollup.config.mjs) to the new
plugin's import name and API.

Copy link
Author

Choose a reason for hiding this comment

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

It works fine for now.

Copy link

Choose a reason for hiding this comment

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

@alexeyr-ci2, understood! If you encounter any issues with the plugin in the future, feel free to revisit this.

"rx": "^4.1.0",
"rxjs": "^5.0.0",
"shelljs": "^0.6.0",
"sinon": "^1.17.1",
"webpack": "^2.4.1",
"xstream": "^5.0.5"
},
"devEngines": {
"node": "5.x",
"npm": "3.x"
},
"dependencies": {
"enzyme-adapter-react-16": "^1.1.1"
}
"dependencies": {}
}
7 changes: 0 additions & 7 deletions scripts/jest.setup.js

This file was deleted.

26 changes: 17 additions & 9 deletions scripts/rollup.config.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
import path from 'path'
import nodeResolve from 'rollup-plugin-node-resolve'
import babel from 'rollup-plugin-babel'
import replace from 'rollup-plugin-replace'
import commonjs from 'rollup-plugin-commonjs'
import { uglify } from 'rollup-plugin-uglify'
import { createRequire } from 'module'
import nodeResolve from '@rollup/plugin-node-resolve'
import babel from '@rollup/plugin-babel'
import replace from '@rollup/plugin-replace'
import commonjs from '@rollup/plugin-commonjs'
import terser from '@rollup/plugin-terser'
import { sizeSnapshot } from 'rollup-plugin-size-snapshot'
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

cat package.json | jq '.devDependencies, .dependencies' | grep -A 5 -B 5 "rollup"

Repository: shakacode/recompose

Length of output: 538


🌐 Web query:

rollup-plugin-size-snapshot Rollup 4 compatibility

💡 Result:

rollup-plugin-size-snapshot is not officially compatible with Rollup 4.

  • The latest release (0.12.0, May 2020) declares peerDependencies: { "rollup": "^2.0.0" }, so package managers will treat Rollup 3/4 as unsupported unless you force/override peer deps. [1]
  • The project also appears inactive (no releases in ~5 years), which makes Rollup 4 support unlikely without a fork/patch. [2]

If you must try it on Rollup 4, you’d be in “best-effort” territory: override peer deps and run your build/tests, but expect potential breakage. [1]

Sources: [1] [2]


rollup-plugin-size-snapshot is incompatible with Rollup 4.

Version 0.12.0 (the latest, from May 2020) declares peerDependencies: { "rollup": "^2.0.0" }, restricting it to Rollup 2 only. The project is unmaintained with no releases for ~5 years. Using it with Rollup 4 requires forcing peer dependencies, which is fragile and unsupported. Consider switching to an active alternative, maintaining a fork, or downgrading Rollup.

🤖 Prompt for AI Agents
In `@scripts/rollup.config.js` at line 8, The import of the unmaintained
rollup-plugin-size-snapshot (symbol sizeSnapshot in rollup.config.js) is
incompatible with Rollup 4; remove the sizeSnapshot import and any usage of the
sizeSnapshot plugin in the Rollup config and replace it with a maintained
alternative (e.g., rollup-plugin-filesize or rollup-plugin-visualizer): install
the chosen package, import its symbol in place of sizeSnapshot, and wire that
plugin into the plugins array where sizeSnapshot was used so you avoid forcing
peer dependencies on Rollup 2.

import { pascalCase } from 'change-case'

const require = createRequire(import.meta.url)
const { PACKAGES_SRC_DIR, PACKAGES_OUT_DIR } = require('./getPackageNames')

const packageName = process.env.PACKAGE_NAME
Expand All @@ -21,7 +23,7 @@ const isExternal = id => !id.startsWith('.') && !id.startsWith('/')

const getBabelOptions = ({ useESModules }) => ({
exclude: '**/node_modules/**',
runtimeHelpers: true,
babelHelpers: 'runtime',
plugins: [['@babel/transform-runtime', { useESModules }]],
})

Expand All @@ -43,7 +45,10 @@ export default [
nodeResolve(),
babel(getBabelOptions({ useESModules: true })),
commonjs(),
replace({ 'process.env.NODE_ENV': JSON.stringify('development') }),
replace({
preventAssignment: true,
'process.env.NODE_ENV': JSON.stringify('development'),
}),
sizeSnapshot({ matchSnapshot }),
],
},
Expand All @@ -63,9 +68,12 @@ export default [
nodeResolve(),
babel(getBabelOptions({ useESModules: true })),
commonjs(),
replace({ 'process.env.NODE_ENV': JSON.stringify('production') }),
replace({
preventAssignment: true,
'process.env.NODE_ENV': JSON.stringify('production'),
}),
sizeSnapshot({ matchSnapshot }),
uglify(),
terser(),
],
},

Expand Down
44 changes: 19 additions & 25 deletions src/packages/recompose/__tests__/branch-test.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import sinon from 'sinon'
import React from 'react'
import { mount } from 'enzyme'
import { render, fireEvent } from '@testing-library/react'
import { branch, compose, withState, withProps } from '../'

test('branch tests props and applies one of two HoCs, for true and false', () => {
Expand All @@ -11,29 +10,24 @@ test('branch tests props and applies one of two HoCs, for true and false', () =>
withProps({ name: 'Heisenberg' }),
withProps({ name: 'Walter' })
)
)(({ isBad, name, updateIsBad }) =>
)(({ isBad, name, updateIsBad }) => (
<div>
<div className="isBad">
{isBad ? 'true' : 'false'}
</div>
<div className="name">
{name}
</div>
<div className="isBad">{isBad ? 'true' : 'false'}</div>
<div className="name">{name}</div>
<button onClick={() => updateIsBad(b => !b)}>Toggle</button>
</div>
)
))

expect(SayMyName.displayName).toBe('withState(branch(Component))')

const wrapper = mount(<SayMyName />)
const getIsBad = () => wrapper.find('.isBad').text()
const getName = () => wrapper.find('.name').text()
const toggle = wrapper.find('button')
const { container } = render(<SayMyName />)
const getIsBad = () => container.querySelector('.isBad').textContent
const getName = () => container.querySelector('.name').textContent

expect(getIsBad()).toBe('false')
expect(getName()).toBe('Walter')

toggle.simulate('click')
fireEvent.click(container.querySelector('button'))

expect(getIsBad()).toBe('true')
expect(getName()).toBe('Heisenberg')
Expand All @@ -48,23 +42,23 @@ test('branch defaults third argument to identity function', () => {
() => props => <Left {...props} />
)(Right)

const wrapper = mount(<BranchedComponent />)
const right = wrapper.find('.right').text()
const { container } = render(<BranchedComponent />)
const right = container.querySelector('.right').textContent

expect(right).toBe('Right')
})

test('branch third argument should not cause console error', () => {
const error = sinon.stub(console, 'error')
jest.spyOn(console, 'error').mockImplementation(() => {})
const Component = () => <div className="right">Component</div>

const BranchedComponent = branch(() => false, v => v, v => v)(Component)

mount(<BranchedComponent />)
const BranchedComponent = branch(
() => false,
v => v,
v => v
)(Component)

expect(error.called).toBe(false)
render(<BranchedComponent />)

/* eslint-disable */
error.restore()
/* eslint-enable */
expect(console.error).not.toHaveBeenCalled()
})
Loading
Loading