Skip to content

Conversation

@arnautov-anton
Copy link
Contributor

@arnautov-anton arnautov-anton commented Dec 15, 2025

🎫 Ticket: https://linear.app/stream/issue/REACT-690

💡 Overview

React tutorial sample application had troubles running on React v18 and lower for seemingly unknown reasons and errors that kept popping up weren't really telling anything useful either.

The issue was in the monorepo setup and Vite's inability to bundle only one (specified) version of React into the final application's bundle.

While exploring different approaches and solutions I decided to clean things up a bit and get rid of some annoying parts, here's the full list of changes.

  • adjusted tsconfig setup in the client, different files with different purposes
    • tsconfig.lib.json - for client types
    • tsconfig.test.json - for test files (excluding the source files)
    • tsconfig.node.json - for vite.config.ts
  • removed @self alias imports as a part of the investigation (tsc does not really resolve these when it's compiling declarations and that's why I had to use vite-plugin-dts which is still in beta), they require some extra setup and are generally not that useful
  • Vite does not externalize imports with different entrypoints other than ".", @stream-io/state-store is externalized while @stream-io/state-store/react-bindings is treated like a separate package and gets imported, added regular expressions to prevent subpaths from being bundled
  • ✨main course✨: upgraded Yarn to v4 to be able to use catalog protocol and cataloged react/react-dom (types too) versions across the monorepo to prevent Vite from bundling different React versions and breaking the dev setup, published SDK works well with React >=v17

Fixes: REACT-690

Summary by CodeRabbit

  • New Features

    • Broadened React support to include v17 and made file/image upload parameters optional for more flexible usage.
  • Build & Dependencies

    • Upgraded Yarn to 4.12.0 and updated workspace build/test scripts.
    • Reworked TypeScript project layout and build configs for improved library declaration output and Node builds.
  • Refactor

    • Internal module/type import and packaging config cleanup; bundling/export settings adjusted for consistent outputs.

✏️ Tip: You can customize this high-level summary in your review settings.

@arnautov-anton arnautov-anton force-pushed the fix/feeds-client/react-18 branch 2 times, most recently from 1312424 to 2408281 Compare December 15, 2025 17:46
Comment on lines 452 to 471
uploadFile = (
request: Omit<FileUploadRequest, 'file'> & { file: StreamFile },
request?: Omit<FileUploadRequest, 'file'> & { file?: StreamFile | string },
) => {
return super.uploadFile({
// @ts-expect-error API spec says file should be a string
file: request.file,
file: request?.file as string,
});
};

// @ts-expect-error API spec says file should be a string
uploadImage = (
request: Omit<ImageUploadRequest, 'file'> & { file: StreamFile },
request?: Omit<ImageUploadRequest, 'file'> & { file?: StreamFile | string },
) => {
return super.uploadImage({
// @ts-expect-error API spec says file should be a string
file: request.file,
// @ts-expect-error form data will only work if this is a string
upload_sizes: JSON.stringify(request.upload_sizes),
file: request?.file as string,
upload_sizes: JSON.stringify(
request?.upload_sizes,
) as unknown as ImageSize[],
});
};
Copy link
Contributor Author

Choose a reason for hiding this comment

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

We can extend the type request type but cannot change it as we're just extending the base class, I've adjusted this so that it matches but it'd be better if this could be changed in the base class (the spec.).

"import": "./dist/es/index.mjs",
"require": "./dist/cjs/index.js",
"default": "./dist/es/index.mjs"
"default": "./dist/cjs/index.js"
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I've changed these to default to CommonJS, it's safer.

@arnautov-anton arnautov-anton force-pushed the fix/feeds-client/react-18 branch 3 times, most recently from 81d870c to 5b98279 Compare December 15, 2025 18:32
Comment on lines 13 to 24
"build:all": "yarn workspaces foreach -Avp --topological-dev run build",
"build:libs": "yarn workspaces foreach -Avp --topological-dev --no-private run build",
"build:client": "yarn workspace @stream-io/feeds-client run build",
"build:react-native-sdk": "yarn workspace @stream-io/feeds-react-native-sdk run build",
"build:react-sdk": "yarn workspace @stream-io/feeds-react-sdk run build",
"build:react-tutorial": "yarn build:client && yarn build:react-sdk && yarn workspace stream-feeds-react-tutorial run build",
"clean:all": "yarn workspaces foreach -vt run clean",
"build:react-tutorial": "yarn workspaces foreach -Avpt --include '{packages/{feeds-client,react-sdk},sample-apps/react-tutorial}' run build",
"clean:all": "yarn workspaces foreach -Avp run clean",
"lint:all": "eslint --max-warnings=0 --cache '**/*.{ts,tsx}'",
"lint:all:fix": "eslint --max-warnings=0 '**/*.{ts,tsx}' --fix",
"test:ci:all": "yarn workspaces foreach -vt run test-ci",
"test:ci:libs": "yarn workspaces foreach -vt --no-private run test-ci",
"test:docs-snippets": "yarn workspaces foreach -vt --no-private run test-docs-snippets",
"test:ci:all": "yarn workspaces foreach -Avt run test-ci",
"test:ci:libs": "yarn workspaces foreach -Avt --no-private run test-ci",
"test:docs-snippets": "yarn workspaces foreach -Avt --no-private run test-docs-snippets",
Copy link
Contributor Author

Choose a reason for hiding this comment

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

New yarn now requires to specify extra option in foreach (A - all).

@arnautov-anton arnautov-anton force-pushed the fix/feeds-client/react-18 branch 2 times, most recently from ecc8989 to 668db1a Compare December 15, 2025 18:53
@arnautov-anton arnautov-anton force-pushed the fix/feeds-client/react-18 branch from c055e74 to ebfe54e Compare December 17, 2025 08:59
@arnautov-anton arnautov-anton marked this pull request as ready for review December 17, 2025 08:59
@coderabbitai
Copy link

coderabbitai bot commented Dec 17, 2025

Walkthrough

Migration and build overhaul: Yarn upgraded to 4.12.0, TypeScript configs moved to a composite project layout, many @self barrel imports replaced with explicit relative paths across the feeds-client and related packages, package exports and peer React ranges adjusted, and several build/Vite/npm scripts and configs updated.

Changes

Cohort / File(s) Change Summary
Yarn & workspace scripts
.yarnrc.yml, package.json
Upgraded yarnPath to [email protected]; added catalog entries for React packages; changed compression/cache keys; refactored workspace scripts to use -Avp, --topological-dev, --include, and related flags.
feeds-client package config & exports
packages/feeds-client/package.json, packages/feeds-client/vite.config.ts
Added types field; changed package export defaults from ESM .mjs to CJS .js; expanded React peer range to include ^17; removed vite-plugin-dts and @self alias, changed externalization to RegExp subpath matching, set emptyOutDir:false, added esbuild tsconfig override.
TypeScript project layout (feeds-client)
packages/feeds-client/tsconfig.json, packages/feeds-client/tsconfig.lib.json, packages/feeds-client/tsconfig.node.json, packages/feeds-client/tsconfig.test.json
Replaced monolithic tsconfig with project-reference composite setup and added specialized tsconfigs for lib (declaration-only), node, and tests.
API surface / runtime types (feeds-client)
packages/feeds-client/src/feeds-client/feeds-client.ts
Made uploadFile/uploadImage request optional and accept `StreamFile
Import refactor — bindings, hooks, wrappers (~40 files)
packages/feeds-client/src/... (contexts/, hooks/, wrappers/, common/, feed/, utils/)
Systematically replaced @self barrel imports with explicit relative paths for types and utilities across contexts, hooks, wrappers, event handlers, and utils; added/imported specific React helpers (e.g., useMemo, useCallback) and introduced a few type assertions (satisfies).
Activity-state safety tweak
packages/feeds-client/src/activity-with-state-updates/activity-with-state-updates.ts
Changed GetCommentsRequest import source and added optional chaining guard when updating feed state (this.feed?.state.partialNext(...)).
Build & packaging (react-sdk)
packages/react-sdk/package.json, packages/react-sdk/tsconfig.json, packages/react-sdk/README.md
Simplified build scripts (clean, build, prepublishOnly), removed legacy lifecycle scripts, expanded React peer range to include ^17, rewrote tsconfig to nodenext/composite settings, updated README React support string.
React Native SDK updates
packages/react-native-sdk/package.json, packages/react-native-sdk/tsconfig.json
Updated devDependency versions and moved React entries to catalog: format; updated project reference to feeds-client/tsconfig.lib.json.
Sample apps — dependency & import updates
sample-apps/*/package.json, sample-apps/react-tutorial/src/*
Replaced pinned React/react-dom and @types specifications with catalog: placeholders; removed file extensions in imports and adjusted some type import sources (moved types to feeds-react-sdk).

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

  • Focus review on:
    • packages/feeds-client/src/feeds-client/feeds-client.ts — optional upload params and union typing/serialization
    • packages/feeds-client/package.json exports change (ESM → CJS) and downstream consumer compatibility
    • packages/feeds-client/vite.config.ts — external RegExp matching and removed @self alias
    • New tsconfig files and project references for build correctness
    • Large-scale import path changes — ensure no broken or unresolved imports remain

Poem

🐰 I hopped through paths both new and old,
Replaced the barrels, trimmed the fold.
Yarn leapt forward, TS split its art,
Uploads softened, exports set apart.
A tiny rabbit cheers the grind — new builds, new paths, a tidy mind! 🎉

Pre-merge checks and finishing touches

❌ 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%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed Title accurately reflects the main objective: addressing stream-feeds-react-tutorial issues through TypeScript config adjustments, @self alias removal, Vite bundling fixes, and Yarn v4 upgrade with catalog protocol.
Description check ✅ Passed PR description includes ticket reference, clear overview of root cause, detailed implementation notes covering all major changes (tsconfig restructuring, @self removal, Vite regex externalization, Yarn v4 upgrade), and outcome statement.
Linked Issues check ✅ Passed The PR comprehensively addresses REACT-690 by identifying the root cause (Vite bundling multiple React versions), implementing fixes (Yarn v4 catalog protocol), and ensuring single React version in final bundle across React >=17.
Out of Scope Changes check ✅ Passed All changes directly support the primary objective of fixing React 18+ compatibility and Vite bundling issues. TypeScript config restructuring, import path changes, and dependency version management are all necessary for resolving the identified root cause.
✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix/feeds-client/react-18

📜 Recent review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 2556518 and 0fb7e97.

⛔ Files ignored due to path filters (1)
  • yarn.lock is excluded by !**/yarn.lock, !**/*.lock
📒 Files selected for processing (1)
  • .yarnrc.yml (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • .yarnrc.yml
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: lint-and-test (22.x)

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.

Copy link

@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: 5

Caution

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

⚠️ Outside diff range comments (4)
packages/feeds-client/src/bindings/react/hooks/feed-state-hooks/useFollowing.ts (1)

22-22: Fix type mismatch: should reference loadNextPageFollowing not loadNextPageFollowers.

The type definition incorrectly references Feed['loadNextPageFollowers'], but the implementation (lines 35-36) correctly uses loadNextPageFollowing. This mismatch breaks the type contract for the loadNextPage function returned by this hook.

Apply this diff:

   loadNextPage: (
-    ...options: Parameters<Feed['loadNextPageFollowers']>
+    ...options: Parameters<Feed['loadNextPageFollowing']>
   ) => Promise<void>;
packages/feeds-client/src/bindings/react/hooks/useCreateFeedsClient.ts (1)

22-24: Critical: Resource leak—initial client instance is never disconnected.

The client created in the useState initializer (line 23) is immediately replaced when the useEffect runs (line 50), but the initial instance's disconnectUser is never called. This leaks any resources (connections, listeners, timers) that FeedsClient acquires in its constructor.

Apply this diff to fix the leak:

-  const [client, setClient] = useState<FeedsClient | null>(
-    () => new FeedsClient(apiKey, options),
-  );
+  const [client, setClient] = useState<FeedsClient | null>(null);

The useEffect will create and connect the client on mount, and the cleanup will properly disconnect it. This also aligns better with React 18's StrictMode behavior, which remounts components in development.

Based on learnings, backwards compatibility and high test coverage are priorities in this SDK—consider adding a test that verifies client cleanup to prevent regressions.

packages/react-sdk/package.json (1)

6-10: Missing CommonJS export condition.

The package only exports ESM format, which will break CommonJS consumers. According to the coding guidelines and learnings, packages should work in both CommonJS and ES modules.

Apply this diff to add CommonJS support:

  "exports": {
    ".": {
      "types": "./dist/index.d.ts",
+     "require": "./dist/index.cjs",
      "import": "./dist/index.js"
    }
  }

You'll also need to update the build script to generate both formats (e.g., using tsup or a bundler that supports dual builds).

Based on learnings, packages should support both CommonJS and ES modules.

packages/react-native-sdk/package.json (1)

4-4: Update packageManager to Yarn 4.

The packageManager field still references Yarn 3.5.0, but the PR upgrades Yarn to 4.12.0. Update this field to match the new version or remove it if relying on root-level packageManager.

Apply this diff:

- "packageManager": "[email protected]",
+ "packageManager": "[email protected]",
🧹 Nitpick comments (1)
sample-apps/react-native/ExpoTikTokApp/package.json (1)

57-57: Verify @types/react catalog version compatibility.

The @types/react package now uses catalog resolution. Ensure the catalog version is compatible with both the React version and the TypeScript version (~5.9.2) specified in devDependencies.

Based on learnings: The SDK should support React 18+ and React Native 0.73+. Verify the catalog definitions provide compatible versions for this React Native 0.81.4 application.

📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 2226a1e and 2556518.

⛔ Files ignored due to path filters (6)
  • .yarn/plugins/@yarnpkg/plugin-interactive-tools.cjs is excluded by !**/.yarn/**
  • .yarn/plugins/@yarnpkg/plugin-typescript.cjs is excluded by !**/.yarn/**
  • .yarn/plugins/@yarnpkg/plugin-workspace-tools.cjs is excluded by !**/.yarn/**
  • .yarn/releases/yarn-3.5.0.cjs is excluded by !**/.yarn/**
  • .yarn/releases/yarn-4.12.0.cjs is excluded by !**/.yarn/**
  • yarn.lock is excluded by !**/yarn.lock, !**/*.lock
📒 Files selected for processing (50)
  • .yarnrc.yml (1 hunks)
  • package.json (1 hunks)
  • packages/feeds-client/package.json (4 hunks)
  • packages/feeds-client/src/activity-with-state-updates/activity-with-state-updates.ts (2 hunks)
  • packages/feeds-client/src/bindings/react/contexts/StreamFeedContext.tsx (1 hunks)
  • packages/feeds-client/src/bindings/react/contexts/StreamFeedsContext.tsx (1 hunks)
  • packages/feeds-client/src/bindings/react/contexts/StreamSearchContext.tsx (1 hunks)
  • packages/feeds-client/src/bindings/react/contexts/StreamSearchResultsContext.tsx (1 hunks)
  • packages/feeds-client/src/bindings/react/hooks/client-state-hooks/useClientConnectedUser.ts (1 hunks)
  • packages/feeds-client/src/bindings/react/hooks/client-state-hooks/useWsConnectionState.ts (1 hunks)
  • packages/feeds-client/src/bindings/react/hooks/feed-state-hooks/useActivityComments.ts (1 hunks)
  • packages/feeds-client/src/bindings/react/hooks/feed-state-hooks/useAggregatedActivities.ts (1 hunks)
  • packages/feeds-client/src/bindings/react/hooks/feed-state-hooks/useComments.ts (1 hunks)
  • packages/feeds-client/src/bindings/react/hooks/feed-state-hooks/useFeedActivities.ts (1 hunks)
  • packages/feeds-client/src/bindings/react/hooks/feed-state-hooks/useFeedMetadata.ts (1 hunks)
  • packages/feeds-client/src/bindings/react/hooks/feed-state-hooks/useFollowers.ts (1 hunks)
  • packages/feeds-client/src/bindings/react/hooks/feed-state-hooks/useFollowing.ts (1 hunks)
  • packages/feeds-client/src/bindings/react/hooks/feed-state-hooks/useIsAggregatedActivityRead.ts (1 hunks)
  • packages/feeds-client/src/bindings/react/hooks/feed-state-hooks/useIsAggregatedActivitySeen.ts (1 hunks)
  • packages/feeds-client/src/bindings/react/hooks/feed-state-hooks/useNotificationStatus.ts (1 hunks)
  • packages/feeds-client/src/bindings/react/hooks/feed-state-hooks/useOwnCapabilities.ts (1 hunks)
  • packages/feeds-client/src/bindings/react/hooks/feed-state-hooks/useOwnFollows.ts (1 hunks)
  • packages/feeds-client/src/bindings/react/hooks/search-state-hooks/useSearchQuery.ts (1 hunks)
  • packages/feeds-client/src/bindings/react/hooks/search-state-hooks/useSearchResult.ts (1 hunks)
  • packages/feeds-client/src/bindings/react/hooks/search-state-hooks/useSearchSources.ts (1 hunks)
  • packages/feeds-client/src/bindings/react/hooks/useCreateFeedsClient.ts (1 hunks)
  • packages/feeds-client/src/bindings/react/wrappers/StreamFeed.tsx (1 hunks)
  • packages/feeds-client/src/bindings/react/wrappers/StreamSearch.tsx (1 hunks)
  • packages/feeds-client/src/bindings/react/wrappers/StreamSearchResults.tsx (1 hunks)
  • packages/feeds-client/src/common/real-time/event-models.ts (1 hunks)
  • packages/feeds-client/src/feed/event-handlers/activity/handle-activity-feedback.ts (1 hunks)
  • packages/feeds-client/src/feed/event-handlers/comment/utils/update-comment-count.ts (1 hunks)
  • packages/feeds-client/src/feeds-client/feeds-client.ts (4 hunks)
  • packages/feeds-client/src/utils/throttling/throttled-get-batched-own-capabilities.ts (1 hunks)
  • packages/feeds-client/tsconfig.json (1 hunks)
  • packages/feeds-client/tsconfig.lib.json (1 hunks)
  • packages/feeds-client/tsconfig.node.json (1 hunks)
  • packages/feeds-client/tsconfig.test.json (1 hunks)
  • packages/feeds-client/vite.config.ts (2 hunks)
  • packages/react-native-sdk/package.json (1 hunks)
  • packages/react-native-sdk/tsconfig.json (1 hunks)
  • packages/react-sdk/README.md (1 hunks)
  • packages/react-sdk/package.json (1 hunks)
  • packages/react-sdk/tsconfig.json (1 hunks)
  • sample-apps/react-native/ExpoTikTokApp/package.json (2 hunks)
  • sample-apps/react-sample-app/package.json (1 hunks)
  • sample-apps/react-tutorial/package.json (1 hunks)
  • sample-apps/react-tutorial/src/main.tsx (1 hunks)
  • sample-apps/react-tutorial/src/own-feeds-context.tsx (1 hunks)
  • sample-apps/react-tutorial/src/pages/Profile.tsx (1 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Use TypeScript for all code in this repository

Files:

  • sample-apps/react-tutorial/src/main.tsx
  • packages/feeds-client/src/bindings/react/contexts/StreamSearchResultsContext.tsx
  • packages/feeds-client/src/bindings/react/hooks/feed-state-hooks/useFollowers.ts
  • packages/feeds-client/src/feed/event-handlers/activity/handle-activity-feedback.ts
  • packages/feeds-client/src/bindings/react/hooks/client-state-hooks/useClientConnectedUser.ts
  • packages/feeds-client/src/bindings/react/hooks/feed-state-hooks/useIsAggregatedActivitySeen.ts
  • packages/feeds-client/src/bindings/react/hooks/feed-state-hooks/useFollowing.ts
  • packages/feeds-client/src/bindings/react/hooks/feed-state-hooks/useOwnFollows.ts
  • packages/feeds-client/src/activity-with-state-updates/activity-with-state-updates.ts
  • packages/feeds-client/src/bindings/react/wrappers/StreamFeed.tsx
  • packages/feeds-client/src/bindings/react/hooks/feed-state-hooks/useFeedMetadata.ts
  • packages/feeds-client/src/feed/event-handlers/comment/utils/update-comment-count.ts
  • packages/feeds-client/src/utils/throttling/throttled-get-batched-own-capabilities.ts
  • packages/feeds-client/src/bindings/react/hooks/search-state-hooks/useSearchQuery.ts
  • packages/feeds-client/src/bindings/react/hooks/feed-state-hooks/useNotificationStatus.ts
  • packages/feeds-client/src/bindings/react/contexts/StreamFeedContext.tsx
  • packages/feeds-client/src/bindings/react/hooks/feed-state-hooks/useFeedActivities.ts
  • sample-apps/react-tutorial/src/pages/Profile.tsx
  • packages/feeds-client/src/common/real-time/event-models.ts
  • packages/feeds-client/src/bindings/react/contexts/StreamSearchContext.tsx
  • packages/feeds-client/src/bindings/react/hooks/search-state-hooks/useSearchResult.ts
  • packages/feeds-client/src/bindings/react/hooks/feed-state-hooks/useActivityComments.ts
  • packages/feeds-client/src/bindings/react/hooks/feed-state-hooks/useOwnCapabilities.ts
  • sample-apps/react-tutorial/src/own-feeds-context.tsx
  • packages/feeds-client/src/bindings/react/hooks/feed-state-hooks/useIsAggregatedActivityRead.ts
  • packages/feeds-client/src/bindings/react/hooks/feed-state-hooks/useComments.ts
  • packages/feeds-client/src/bindings/react/hooks/feed-state-hooks/useAggregatedActivities.ts
  • packages/feeds-client/src/bindings/react/hooks/search-state-hooks/useSearchSources.ts
  • packages/feeds-client/src/bindings/react/contexts/StreamFeedsContext.tsx
  • packages/feeds-client/src/bindings/react/hooks/client-state-hooks/useWsConnectionState.ts
  • packages/feeds-client/src/bindings/react/hooks/useCreateFeedsClient.ts
  • packages/feeds-client/src/feeds-client/feeds-client.ts
  • packages/feeds-client/src/bindings/react/wrappers/StreamSearchResults.tsx
  • packages/feeds-client/vite.config.ts
  • packages/feeds-client/src/bindings/react/wrappers/StreamSearch.tsx
**/package.json

📄 CodeRabbit inference engine (AGENTS.md)

Ensure packages work in both CommonJS and ES modules; validate yarn workspaces integration

Files:

  • sample-apps/react-native/ExpoTikTokApp/package.json
  • packages/react-sdk/package.json
  • packages/react-native-sdk/package.json
  • package.json
  • sample-apps/react-tutorial/package.json
  • sample-apps/react-sample-app/package.json
  • packages/feeds-client/package.json
🧠 Learnings (8)
📓 Common learnings
Learnt from: CR
Repo: GetStream/stream-feeds-js PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-17T11:01:52.844Z
Learning: Applies to packages/react-bindings/**/*.{ts,tsx} : Support React 18+ and React Native 0.73+ in respective SDKs (react-sdk/ and react-native-sdk/)
Learnt from: CR
Repo: GetStream/stream-feeds-js PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-17T11:01:52.844Z
Learning: Prioritize backwards compatibility, API stability, and high test coverage when changing code in this TypeScript Feeds SDK repository
Learnt from: CR
Repo: GetStream/stream-feeds-js PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-17T11:01:52.844Z
Learning: Applies to **/*.test.ts : Add and extend tests with .test.ts suffix, covering FeedsClient, Feed classes, event handlers, state management, React hooks, contexts, utility functions, generated API clients, and integration tests in __integration-tests__/ directories
Learnt from: CR
Repo: GetStream/stream-feeds-js PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-17T11:01:52.844Z
Learning: Applies to **/package.json : Ensure packages work in both CommonJS and ES modules; validate yarn workspaces integration
📚 Learning: 2025-12-17T11:01:52.844Z
Learnt from: CR
Repo: GetStream/stream-feeds-js PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-17T11:01:52.844Z
Learning: Applies to packages/react-bindings/**/*.{ts,tsx} : Support React 18+ and React Native 0.73+ in respective SDKs (react-sdk/ and react-native-sdk/)

Applied to files:

  • sample-apps/react-tutorial/src/main.tsx
  • packages/feeds-client/tsconfig.test.json
  • packages/feeds-client/src/bindings/react/contexts/StreamSearchResultsContext.tsx
  • packages/feeds-client/src/bindings/react/hooks/feed-state-hooks/useFollowers.ts
  • .yarnrc.yml
  • packages/feeds-client/src/bindings/react/hooks/feed-state-hooks/useIsAggregatedActivitySeen.ts
  • sample-apps/react-native/ExpoTikTokApp/package.json
  • packages/feeds-client/src/bindings/react/hooks/feed-state-hooks/useFollowing.ts
  • packages/feeds-client/src/bindings/react/hooks/feed-state-hooks/useOwnFollows.ts
  • packages/react-sdk/package.json
  • packages/react-sdk/tsconfig.json
  • packages/feeds-client/src/bindings/react/wrappers/StreamFeed.tsx
  • packages/feeds-client/src/bindings/react/hooks/feed-state-hooks/useFeedMetadata.ts
  • packages/react-native-sdk/package.json
  • packages/feeds-client/src/bindings/react/hooks/search-state-hooks/useSearchQuery.ts
  • packages/feeds-client/src/bindings/react/hooks/feed-state-hooks/useNotificationStatus.ts
  • packages/feeds-client/src/bindings/react/contexts/StreamFeedContext.tsx
  • packages/feeds-client/src/bindings/react/hooks/feed-state-hooks/useFeedActivities.ts
  • packages/react-sdk/README.md
  • sample-apps/react-tutorial/src/pages/Profile.tsx
  • package.json
  • packages/react-native-sdk/tsconfig.json
  • sample-apps/react-tutorial/package.json
  • packages/feeds-client/src/bindings/react/contexts/StreamSearchContext.tsx
  • packages/feeds-client/src/bindings/react/hooks/search-state-hooks/useSearchResult.ts
  • packages/feeds-client/src/bindings/react/hooks/feed-state-hooks/useOwnCapabilities.ts
  • sample-apps/react-tutorial/src/own-feeds-context.tsx
  • packages/feeds-client/src/bindings/react/hooks/feed-state-hooks/useIsAggregatedActivityRead.ts
  • packages/feeds-client/src/bindings/react/hooks/feed-state-hooks/useComments.ts
  • packages/feeds-client/src/bindings/react/hooks/feed-state-hooks/useAggregatedActivities.ts
  • packages/feeds-client/src/bindings/react/hooks/search-state-hooks/useSearchSources.ts
  • packages/feeds-client/src/bindings/react/contexts/StreamFeedsContext.tsx
  • packages/feeds-client/src/bindings/react/hooks/client-state-hooks/useWsConnectionState.ts
  • sample-apps/react-sample-app/package.json
  • packages/feeds-client/src/bindings/react/hooks/useCreateFeedsClient.ts
  • packages/feeds-client/src/bindings/react/wrappers/StreamSearchResults.tsx
  • packages/feeds-client/package.json
  • packages/feeds-client/src/bindings/react/wrappers/StreamSearch.tsx
📚 Learning: 2025-12-17T11:01:52.844Z
Learnt from: CR
Repo: GetStream/stream-feeds-js PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-17T11:01:52.844Z
Learning: Applies to packages/react-bindings/**/*.{ts,tsx} : Use React hooks and contexts from react-bindings for React SDK integrations

Applied to files:

  • sample-apps/react-tutorial/src/main.tsx
  • packages/feeds-client/src/bindings/react/contexts/StreamSearchResultsContext.tsx
  • packages/feeds-client/src/bindings/react/hooks/feed-state-hooks/useFollowers.ts
  • packages/feeds-client/src/bindings/react/hooks/client-state-hooks/useClientConnectedUser.ts
  • packages/feeds-client/src/bindings/react/hooks/feed-state-hooks/useIsAggregatedActivitySeen.ts
  • sample-apps/react-native/ExpoTikTokApp/package.json
  • packages/feeds-client/src/bindings/react/hooks/feed-state-hooks/useFollowing.ts
  • packages/feeds-client/src/bindings/react/hooks/feed-state-hooks/useOwnFollows.ts
  • packages/react-sdk/package.json
  • packages/react-sdk/tsconfig.json
  • packages/feeds-client/src/bindings/react/wrappers/StreamFeed.tsx
  • packages/feeds-client/src/bindings/react/hooks/feed-state-hooks/useFeedMetadata.ts
  • packages/react-native-sdk/package.json
  • packages/feeds-client/src/bindings/react/hooks/search-state-hooks/useSearchQuery.ts
  • packages/feeds-client/src/bindings/react/hooks/feed-state-hooks/useNotificationStatus.ts
  • packages/feeds-client/src/bindings/react/contexts/StreamFeedContext.tsx
  • packages/feeds-client/src/bindings/react/hooks/feed-state-hooks/useFeedActivities.ts
  • packages/react-sdk/README.md
  • sample-apps/react-tutorial/src/pages/Profile.tsx
  • packages/react-native-sdk/tsconfig.json
  • sample-apps/react-tutorial/package.json
  • packages/feeds-client/src/bindings/react/contexts/StreamSearchContext.tsx
  • packages/feeds-client/src/bindings/react/hooks/search-state-hooks/useSearchResult.ts
  • packages/feeds-client/src/bindings/react/hooks/feed-state-hooks/useActivityComments.ts
  • packages/feeds-client/src/bindings/react/hooks/feed-state-hooks/useOwnCapabilities.ts
  • sample-apps/react-tutorial/src/own-feeds-context.tsx
  • packages/feeds-client/src/bindings/react/hooks/feed-state-hooks/useIsAggregatedActivityRead.ts
  • packages/feeds-client/src/bindings/react/hooks/feed-state-hooks/useComments.ts
  • packages/feeds-client/src/bindings/react/hooks/feed-state-hooks/useAggregatedActivities.ts
  • packages/feeds-client/src/bindings/react/hooks/search-state-hooks/useSearchSources.ts
  • packages/feeds-client/src/bindings/react/contexts/StreamFeedsContext.tsx
  • packages/feeds-client/src/bindings/react/hooks/client-state-hooks/useWsConnectionState.ts
  • sample-apps/react-sample-app/package.json
  • packages/feeds-client/src/bindings/react/hooks/useCreateFeedsClient.ts
  • packages/feeds-client/src/bindings/react/wrappers/StreamSearchResults.tsx
  • packages/feeds-client/package.json
  • packages/feeds-client/src/bindings/react/wrappers/StreamSearch.tsx
📚 Learning: 2025-12-17T11:01:52.844Z
Learnt from: CR
Repo: GetStream/stream-feeds-js PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-17T11:01:52.844Z
Learning: Applies to **/*.test.ts : Add and extend tests with .test.ts suffix, covering FeedsClient, Feed classes, event handlers, state management, React hooks, contexts, utility functions, generated API clients, and integration tests in __integration-tests__/ directories

Applied to files:

  • sample-apps/react-tutorial/src/main.tsx
  • packages/feeds-client/tsconfig.test.json
  • packages/feeds-client/src/bindings/react/contexts/StreamSearchResultsContext.tsx
  • packages/feeds-client/src/bindings/react/hooks/feed-state-hooks/useFollowers.ts
  • packages/feeds-client/src/feed/event-handlers/activity/handle-activity-feedback.ts
  • packages/feeds-client/src/bindings/react/hooks/client-state-hooks/useClientConnectedUser.ts
  • packages/feeds-client/src/bindings/react/hooks/feed-state-hooks/useIsAggregatedActivitySeen.ts
  • packages/feeds-client/src/bindings/react/hooks/feed-state-hooks/useFollowing.ts
  • packages/feeds-client/src/bindings/react/hooks/feed-state-hooks/useOwnFollows.ts
  • packages/feeds-client/tsconfig.node.json
  • packages/react-sdk/tsconfig.json
  • packages/feeds-client/src/activity-with-state-updates/activity-with-state-updates.ts
  • packages/feeds-client/src/bindings/react/wrappers/StreamFeed.tsx
  • packages/feeds-client/src/bindings/react/hooks/feed-state-hooks/useFeedMetadata.ts
  • packages/feeds-client/tsconfig.json
  • packages/feeds-client/src/feed/event-handlers/comment/utils/update-comment-count.ts
  • packages/feeds-client/src/utils/throttling/throttled-get-batched-own-capabilities.ts
  • packages/feeds-client/src/bindings/react/hooks/feed-state-hooks/useNotificationStatus.ts
  • packages/feeds-client/src/bindings/react/contexts/StreamFeedContext.tsx
  • packages/feeds-client/src/bindings/react/hooks/feed-state-hooks/useFeedActivities.ts
  • sample-apps/react-tutorial/src/pages/Profile.tsx
  • packages/feeds-client/src/common/real-time/event-models.ts
  • packages/react-native-sdk/tsconfig.json
  • packages/feeds-client/src/bindings/react/contexts/StreamSearchContext.tsx
  • packages/feeds-client/src/bindings/react/hooks/search-state-hooks/useSearchResult.ts
  • packages/feeds-client/src/bindings/react/hooks/feed-state-hooks/useActivityComments.ts
  • packages/feeds-client/src/bindings/react/hooks/feed-state-hooks/useOwnCapabilities.ts
  • sample-apps/react-tutorial/src/own-feeds-context.tsx
  • packages/feeds-client/src/bindings/react/hooks/feed-state-hooks/useIsAggregatedActivityRead.ts
  • packages/feeds-client/src/bindings/react/hooks/feed-state-hooks/useComments.ts
  • packages/feeds-client/src/bindings/react/hooks/feed-state-hooks/useAggregatedActivities.ts
  • packages/feeds-client/src/bindings/react/contexts/StreamFeedsContext.tsx
  • packages/feeds-client/src/bindings/react/hooks/client-state-hooks/useWsConnectionState.ts
  • packages/feeds-client/tsconfig.lib.json
  • packages/feeds-client/src/bindings/react/hooks/useCreateFeedsClient.ts
  • packages/feeds-client/src/feeds-client/feeds-client.ts
  • packages/feeds-client/vite.config.ts
  • packages/feeds-client/package.json
📚 Learning: 2025-12-17T11:01:52.844Z
Learnt from: CR
Repo: GetStream/stream-feeds-js PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-17T11:01:52.844Z
Learning: Prioritize backwards compatibility, API stability, and high test coverage when changing code in this TypeScript Feeds SDK repository

Applied to files:

  • packages/feeds-client/tsconfig.test.json
  • packages/feeds-client/src/bindings/react/hooks/feed-state-hooks/useFollowers.ts
  • packages/feeds-client/src/feed/event-handlers/activity/handle-activity-feedback.ts
  • packages/feeds-client/src/bindings/react/hooks/feed-state-hooks/useOwnFollows.ts
  • packages/feeds-client/tsconfig.node.json
  • packages/feeds-client/src/activity-with-state-updates/activity-with-state-updates.ts
  • packages/feeds-client/src/bindings/react/wrappers/StreamFeed.tsx
  • packages/feeds-client/tsconfig.json
  • packages/feeds-client/src/feed/event-handlers/comment/utils/update-comment-count.ts
  • packages/feeds-client/src/utils/throttling/throttled-get-batched-own-capabilities.ts
  • packages/feeds-client/src/bindings/react/hooks/feed-state-hooks/useNotificationStatus.ts
  • packages/feeds-client/src/bindings/react/contexts/StreamFeedContext.tsx
  • packages/feeds-client/src/bindings/react/hooks/feed-state-hooks/useFeedActivities.ts
  • package.json
  • packages/react-native-sdk/tsconfig.json
  • sample-apps/react-tutorial/src/own-feeds-context.tsx
  • packages/feeds-client/src/bindings/react/hooks/feed-state-hooks/useComments.ts
  • packages/feeds-client/src/bindings/react/contexts/StreamFeedsContext.tsx
  • packages/feeds-client/tsconfig.lib.json
  • packages/feeds-client/src/bindings/react/hooks/useCreateFeedsClient.ts
  • packages/feeds-client/src/feeds-client/feeds-client.ts
  • packages/feeds-client/package.json
📚 Learning: 2025-12-17T11:01:52.844Z
Learnt from: CR
Repo: GetStream/stream-feeds-js PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-17T11:01:52.844Z
Learning: Applies to **/*.{ts,tsx} : Use TypeScript for all code in this repository

Applied to files:

  • packages/feeds-client/tsconfig.test.json
  • packages/feeds-client/tsconfig.node.json
  • packages/react-sdk/tsconfig.json
  • packages/feeds-client/tsconfig.json
  • packages/feeds-client/tsconfig.lib.json
📚 Learning: 2025-12-17T11:01:52.844Z
Learnt from: CR
Repo: GetStream/stream-feeds-js PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-17T11:01:52.844Z
Learning: Applies to **/package.json : Ensure packages work in both CommonJS and ES modules; validate yarn workspaces integration

Applied to files:

  • packages/feeds-client/tsconfig.test.json
  • .yarnrc.yml
  • sample-apps/react-native/ExpoTikTokApp/package.json
  • packages/react-sdk/package.json
  • packages/feeds-client/tsconfig.node.json
  • packages/react-sdk/tsconfig.json
  • packages/react-native-sdk/package.json
  • package.json
  • sample-apps/react-tutorial/package.json
  • sample-apps/react-sample-app/package.json
  • packages/feeds-client/package.json
📚 Learning: 2025-12-17T11:01:52.844Z
Learnt from: CR
Repo: GetStream/stream-feeds-js PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-17T11:01:52.844Z
Learning: Use Yarn with workspaces for package management; check individual package.json files for package-specific scripts before running commands

Applied to files:

  • .yarnrc.yml
  • package.json
🧬 Code graph analysis (1)
packages/feeds-client/src/feeds-client/feeds-client.ts (2)
packages/feeds-client/src/gen/models/index.ts (3)
  • FileUploadRequest (2946-2950)
  • ImageUploadRequest (3416-3422)
  • ImageSize (3406-3414)
packages/feeds-client/src/types.ts (1)
  • StreamFile (34-34)
🪛 ast-grep (0.40.0)
packages/feeds-client/vite.config.ts

[warning] 9-9: Regular expression constructed from variable input detected. This can lead to Regular Expression Denial of Service (ReDoS) attacks if the variable contains malicious patterns. Use libraries like 'recheck' to validate regex safety or use static patterns.
Context: new RegExp(^${dependency}(\\/[\\w-]+)?$)
Note: [CWE-1333] Inefficient Regular Expression Complexity [REFERENCES]
- https://owasp.org/www-community/attacks/Regular_expression_Denial_of_Service_-_ReDoS
- https://cwe.mitre.org/data/definitions/1333.html

(regexp-from-variable)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: lint-and-test (22.x)
🔇 Additional comments (65)
packages/feeds-client/src/feed/event-handlers/comment/utils/update-comment-count.ts (1)

3-4: LGTM—Import paths correctly updated.

The migration from @self barrel imports to explicit relative paths appears correct. Both Feed and the generated model types resolve to the expected module locations.

Verify that TypeScript compilation and existing tests pass to confirm the type resolution works as expected across the refactored codebase.

Based on learnings, prioritizing API stability and test coverage in this SDK.

packages/feeds-client/src/bindings/react/hooks/feed-state-hooks/useIsAggregatedActivityRead.ts (1)

1-6: LGTM! Import refactoring aligns with PR objectives.

The explicit useMemo import and replacement of barrel imports with relative paths are correct. This change maintains the hook's public API and behavior while addressing the TypeScript declaration compilation issues with @self aliases described in the PR objectives.

Based on PR objectives and learnings.

packages/feeds-client/src/bindings/react/hooks/feed-state-hooks/useFollowing.ts (1)

5-6: LGTM! Import refactor aligns with PR objectives.

The replacement of @self barrel imports with explicit relative paths is correct. The type modifier on line 6 is good practice for type-only imports, improving tree-shaking and declaration generation.

Based on the PR objectives, this change helps resolve TypeScript declaration compilation issues that arose when using @self aliases.

packages/feeds-client/src/common/real-time/event-models.ts (1)

1-2: Import path refactor is correct and aligns with PR objectives.

The migration from @self barrel imports to explicit relative paths is properly implemented. Both types are correctly exported from their target locations: ConnectedUser from packages/feeds-client/src/types.ts and StreamApiError from packages/feeds-client/src/common/types.ts. Using import type for type-only imports is TypeScript best practice and optimizes build output.

packages/feeds-client/src/bindings/react/hooks/feed-state-hooks/useFollowers.ts (1)

4-5: LGTM! Import paths correctly updated.

The migration from @self barrel imports to explicit relative paths aligns with the PR objective to fix TypeScript declaration compilation issues. The paths are correctly calculated (../../../../feed and ../../../../utils), and the type-only import syntax for Feed and FeedState is preserved.

packages/feeds-client/src/bindings/react/hooks/feed-state-hooks/useNotificationStatus.ts (2)

7-15: Good use of satisfies for type safety.

The satisfies NotificationStatusResponse assertion on line 15 ensures the selector's return type strictly conforms to the expected shape without type widening. This is a solid type safety improvement.


4-5: Import path is correct; no changes needed.

The import path '../../../../gen/models' is valid. The gen/models directory is located at packages/feeds-client/src/gen/models (under src/), making the 4-level relative path correct for resolving from packages/feeds-client/src/bindings/react/hooks/feed-state-hooks/useNotificationStatus.ts.

packages/feeds-client/src/feed/event-handlers/activity/handle-activity-feedback.ts (1)

1-5: Imports correctly refactored from @self aliases to explicit relative paths.

All type imports properly use the import type syntax, and relative paths are accurate for the project structure. The migration aligns with the PR objective and maintains backwards compatibility by preserving runtime logic.

packages/feeds-client/src/bindings/react/hooks/client-state-hooks/useWsConnectionState.ts (1)

2-4: Import refactoring aligns with PR objectives and path resolves correctly.

The formatting improvement (line 2) and the import path change from @self to the explicit relative path '../../../../feeds-client' (line 4) align with the PR's goal of removing path aliases to fix TypeScript declaration compilation issues. The relative path correctly resolves to the feeds-client module, where FeedsClientState is properly exported. The type-only import maintains backwards compatibility with no runtime impact.

packages/feeds-client/src/bindings/react/hooks/feed-state-hooks/useIsAggregatedActivitySeen.ts (1)

1-6: Import refactoring looks good.

The replacement of barrel imports with explicit relative paths correctly addresses the TypeScript declaration compilation issue. The explicit import of useMemo from 'react' and the type-only imports using relative paths are appropriate and follow best practices. Import paths have been verified to resolve correctly: Feed is exported from packages/feeds-client/src/feed/ and AggregatedActivityResponse is exported from packages/feeds-client/src/gen/models/.

packages/feeds-client/src/bindings/react/hooks/useCreateFeedsClient.ts (1)

2-6: LGTM! Import refactoring correctly addresses the PR objective.

The migration from @self barrel imports to explicit relative paths is accurate. The paths correctly resolve to the source modules and this change addresses the TypeScript declaration compilation issue mentioned in the PR objectives.

packages/feeds-client/src/bindings/react/hooks/feed-state-hooks/useComments.ts (1)

5-8: Import refactoring looks correct.

The migration from @self barrel imports to explicit relative paths aligns with the PR objective to fix TypeScript declaration compilation issues. The relative paths correctly navigate 4 directories up from the current location to reach the intended modules.

Run the following script to verify all imports resolve correctly:

#!/bin/bash
# Description: Verify that imported items exist at the specified relative paths

# Verify utils exports
ast-grep --pattern $'export { $$$, checkHasAnotherPage, $$$ }' packages/feeds-client/src/utils
ast-grep --pattern $'export { $$$, isCommentResponse, $$$ }' packages/feeds-client/src/utils

# Verify gen/models exports
ast-grep --pattern $'export type { $$$, ActivityResponse, $$$ }' packages/feeds-client/src/gen/models
ast-grep --pattern $'export type { $$$, CommentResponse, $$$ }' packages/feeds-client/src/gen/models

# Verify feed exports
ast-grep --pattern $'export type { $$$, Feed, $$$ }' packages/feeds-client/src/feed
ast-grep --pattern $'export type { $$$, FeedState, $$$ }' packages/feeds-client/src/feed

# Verify types exports
ast-grep --pattern $'export type { $$$, CommentParent, $$$ }' packages/feeds-client/src/types
packages/feeds-client/src/activity-with-state-updates/activity-with-state-updates.ts (1)

10-10: LGTM! Import path refactoring aligns with PR objectives.

The change from @self to relative imports is consistent with the PR's goal of removing @self aliases due to TypeScript declaration compilation issues.

packages/feeds-client/src/bindings/react/contexts/StreamSearchResultsContext.tsx (1)

3-3: LGTM!

The import path change from @self to a relative path is correct and aligns with the PR objective to remove barrel import aliases for better declaration compilation compatibility.

packages/feeds-client/src/bindings/react/hooks/client-state-hooks/useClientConnectedUser.ts (1)

4-4: LGTM!

The import path change from @self to a relative path correctly resolves to the feeds-client module and aligns with the PR's goal to remove barrel import aliases.

sample-apps/react-tutorial/src/own-feeds-context.tsx (1)

1-12: LGTM!

The import consolidation and use of type imports follow TypeScript best practices and improve code readability. This aligns well with the verbatimModuleSyntax compiler option used in the project.

sample-apps/react-tutorial/src/main.tsx (1)

4-5: LGTM!

Removing explicit file extensions from imports is standard practice with modern bundlers and makes imports more maintainable. Vite's module resolution will correctly resolve these to the .tsx files.

packages/react-sdk/README.md (1)

5-5: No action needed. The supported React versions string in README matches the peerDependencies declaration in package.json exactly ("^17 || ^18 || ^19").

packages/feeds-client/tsconfig.test.json (1)

14-14: The test file inclusion pattern is correct.

The include pattern ["**/*.test.ts", "**/test-utils/**/*.ts"] aligns with the project's convention of using the .test.ts suffix for all tests, regardless of whether the source files are .ts or .tsx. This pattern correctly covers test files and test utilities.

sample-apps/react-native/ExpoTikTokApp/package.json (1)

39-40: The catalog: protocol is properly defined in .yarnrc.yml with React 19.1.0 and react-dom 19.1.0, and the package correctly references these catalog entries. No action needed.

Likely an incorrect or invalid review comment.

sample-apps/react-tutorial/src/pages/Profile.tsx (1)

1-1: Verify type exports from @stream-io/feeds-react-sdk.

The types BookmarkResponse and FeedState are imported from @stream-io/feeds-react-sdk. Confirm these types are properly exported from the react-sdk package and available for use in the codebase.

sample-apps/react-tutorial/package.json (2)

15-16: Good use of catalog protocol for React version pinning.

Using catalog: for react and react-dom ensures consistent versions across the monorepo, directly addressing the root cause of the React 18/Vite bundling issue.


22-24: Type dependencies and plugin version look correct.

The catalog: protocol for type packages maintains consistency, and @vitejs/plugin-react ^5 is compatible with Vite 6.x.

packages/feeds-client/tsconfig.node.json (1)

1-24: Well-structured Node-targeted config for build tooling.

The configuration appropriately isolates vite.config.ts compilation with modern settings. The erasableSyntaxOnly and noUncheckedSideEffectImports options require TypeScript 5.8+ and 5.6+ respectively—the package.json shows typescript: ^5.9.3, so these are supported.

packages/feeds-client/src/bindings/react/hooks/feed-state-hooks/useActivityComments.ts (2)

3-9: Import refactoring correctly migrates from barrel to explicit paths.

The switch from @self barrel imports to explicit relative paths resolves the tsc declaration compilation issue mentioned in the PR. Type-only imports are properly annotated, and the paths align with the module structure.


11-18: Type guard implementation is sound.

The canLoadComments type guard correctly narrows the union type using in operator checks for the required methods.

packages/react-sdk/tsconfig.json (1)

1-22: Composite TypeScript configuration is well-structured for library builds.

The composite: true with declaration: true enables proper incremental builds and type generation. The module: "nodenext" setting is appropriate for a Node.js package and implicitly sets moduleResolution: "nodenext". The es2020 target maintains compatibility with React 17+ per the SDK requirements.

packages/feeds-client/package.json (5)

7-7: Good addition of top-level types field.

Adding the explicit types field at the package root ensures legacy tooling that doesn't support the exports map can still resolve type definitions correctly.


17-17: Default to CommonJS is a safe backwards-compatible choice.

Defaulting to CJS for the default condition ensures broader compatibility with tools and runtimes that don't fully support ESM resolution.

Also applies to: 27-27


33-34: Parallel builds improve developer experience.

Running Vite build and TypeScript declaration generation concurrently reduces build time while maintaining separate concerns.


70-70: React 17 peer dependency aligns with PR objectives.

Broadening to ^17 || ^18 || ^19 supports the stated goal of ensuring the SDK works with React >= 17. Based on learnings, this maintains backwards compatibility which is a priority for this repository.


66-66: Vite 7 is stable, with version 7.3.0 currently released. Vite 7 is described as a smooth update from Vite 6, and the Vite team tests new versions through the vite-ecosystem-ci project before release. The ^7 specifier is appropriate for production use.

packages/react-sdk/package.json (2)

13-15: LGTM! Good addition of prepublishOnly script.

The new clean script and prepublishOnly hook ensure a fresh build before publishing, which prevents stale artifacts.


20-23: LGTM! Correctly excludes build artifacts.

The addition of !dist/.tsbuildinfo prevents internal TypeScript build artifacts from being published.

packages/feeds-client/src/bindings/react/hooks/feed-state-hooks/useOwnCapabilities.ts (1)

1-8: LGTM! Import refactor correctly removes @self alias.

The transition from @self barrel imports to explicit relative paths is clean and aligns with the PR's goal of improving module resolution for Vite/tsc. The import paths are correct and the explicit useCallback import is proper.

sample-apps/react-sample-app/package.json (2)

17-18: LGTM! Catalog usage prevents React version conflicts.

Switching to catalog: for React dependencies ensures the sample app uses the same React version as the SDK packages, directly addressing the PR's objective of preventing Vite from bundling multiple React versions.


24-25: LGTM! Consistent catalog usage for type definitions.

Using catalog: for type definitions ensures TypeScript type compatibility across the monorepo.

packages/feeds-client/src/feeds-client/feeds-client.ts (3)

20-20: LGTM! Added necessary type import.

The ImageSize import is required for the updated uploadImage method signature.


217-217: LGTM! Explicit typing improves clarity.

The explicit ActivityResponse[] type annotation makes the code's intent clearer without changing behavior.


345-352: LGTM! Type assertion ensures correct return type.

The explicit as Feed[] cast documents the expected return type and helps TypeScript understand the filter/map result.

packages/feeds-client/src/bindings/react/contexts/StreamFeedsContext.tsx (1)

1-3: LGTM! Import refactor correctly removes @self alias.

The transition from @self to an explicit relative path is clean and aligns with the PR's module resolution improvements.

packages/feeds-client/src/utils/throttling/throttled-get-batched-own-capabilities.ts (1)

1-1: LGTM! Import refactor correctly removes @self alias.

The relative path correctly navigates to the feeds-client module, consistent with the PR's @self removal refactor.

packages/feeds-client/src/bindings/react/contexts/StreamFeedContext.tsx (1)

1-3: LGTM! Import refactor correctly removes @self alias.

The relative path correctly imports from the feed module, consistent with the PR's @self removal strategy.

packages/react-native-sdk/package.json (1)

47-67: Catalog usage correctly aligns React versions across dependencies.

The monorepo catalog resolves react: "catalog:" to version 19.1.0, which perfectly matches the pinned react-test-renderer: "19.1.0". React and react-test-renderer packages must have the same version, and this configuration ensures that compatibility. The use of catalog: for React and @types/react correctly leverages centralized version management to prevent multiple React versions from being bundled, with react-native 0.81.4 properly supporting the React 19.1.0 runtime.

packages/react-native-sdk/tsconfig.json (1)

28-28: LGTM! TypeScript project reference correctly updated.

The reference now points to the declaration-focused config (tsconfig.lib.json) introduced for feeds-client, which aligns with the composite project setup described in the PR objectives.

packages/feeds-client/src/bindings/react/hooks/search-state-hooks/useSearchResult.ts (1)

3-7: LGTM! Import paths correctly refactored from barrel to explicit relative paths.

The type imports have been updated to use explicit relative paths instead of @self, which aligns with the PR's goal of removing barrel imports that interfere with declaration compilation. The hook logic and behavior remain unchanged.

packages/feeds-client/src/bindings/react/hooks/feed-state-hooks/useOwnFollows.ts (1)

3-5: LGTM! Import paths correctly updated to explicit relative paths.

Type imports have been refactored from @self to explicit relative paths, consistent with the broader refactoring effort across the codebase. The hook implementation remains unchanged.

packages/feeds-client/src/bindings/react/hooks/search-state-hooks/useSearchSources.ts (1)

3-5: LGTM! Import paths refactored consistently with other search hooks.

Type imports have been updated to use explicit relative paths instead of @self, maintaining consistency with the broader refactoring effort. The hook logic remains unchanged.

packages/feeds-client/src/bindings/react/hooks/feed-state-hooks/useAggregatedActivities.ts (1)

1-6: LGTM! Imports correctly refactored with explicit React imports.

The type imports have been updated to use explicit relative paths, and useMemo is now explicitly imported from React, which improves clarity and aligns with the removal of barrel imports.

packages/feeds-client/src/bindings/react/contexts/StreamSearchContext.tsx (1)

2-3: LGTM! Import path correctly updated.

The SearchController type import has been refactored to use an explicit relative path instead of @self, consistent with the broader refactoring effort. The context implementation remains unchanged.

.yarnrc.yml (2)

9-11: LGTM! Yarn 4 configuration updates are appropriate.

The compressionLevel: mixed and enableGlobalCache: false settings are reasonable for a monorepo setup with Yarn 4.


17-17: LGTM! Yarn upgraded to 4.12.0.

The Yarn upgrade from 3.5.0 to 4.12.0 enables the catalog protocol feature used to ensure consistent React versions across the monorepo, which aligns with the PR's objectives.

packages/feeds-client/src/bindings/react/wrappers/StreamFeed.tsx (1)

2-4: LGTM! Import path correctly updated.

The Feed type import has been refactored to use an explicit relative path instead of @self, consistent with the broader refactoring effort across wrappers and hooks. The component implementation remains unchanged.

packages/feeds-client/src/bindings/react/hooks/feed-state-hooks/useFeedMetadata.ts (1)

3-4: LGTM!

The import path refactoring correctly replaces the @self barrel import with explicit relative paths. Type-only imports are properly marked, and the path depth is accurate for the file location.

packages/feeds-client/src/bindings/react/wrappers/StreamSearchResults.tsx (1)

2-4: LGTM!

The import reorganization correctly moves SearchSource from the @self barrel to an explicit relative path, and the added blank line improves readability.

packages/feeds-client/tsconfig.lib.json (1)

1-25: LGTM!

This declaration-focused TypeScript config is well-structured for a composite library build. The use of module: "preserve", moduleResolution: "bundler", and verbatimModuleSyntax: true aligns with modern TypeScript and bundler best practices. The emitDeclarationOnly option ensures this config is dedicated to type generation.

packages/feeds-client/src/bindings/react/hooks/search-state-hooks/useSearchQuery.ts (1)

3-7: LGTM!

The import path refactoring correctly relocates types from @self to explicit relative paths. The type-only import syntax is properly used, and paths are accurate.

packages/feeds-client/tsconfig.json (1)

1-8: LGTM!

This refactor to a project-reference style configuration is a standard and recommended pattern for TypeScript composite projects. The empty files array and three reference entries correctly delegate to specialized configs for different build contexts.

packages/feeds-client/src/bindings/react/hooks/feed-state-hooks/useFeedActivities.ts (1)

2-6: LGTM!

The import reorganization correctly moves type imports from @self to explicit relative paths while maintaining proper type-only import syntax. The reordering improves import organization.

packages/feeds-client/src/bindings/react/wrappers/StreamSearch.tsx (1)

2-4: LGTM!

The import path refactoring correctly relocates SearchController from @self to an explicit relative path, and the formatting improvement enhances readability.

packages/feeds-client/vite.config.ts (3)

5-10: Externalization pattern correctly addresses the bundling issue.

The RegExp mapping ensures Vite externalizes both main packages and their subpaths (e.g., @stream-io/state-store/react-bindings), which is essential to fixing the multiple React version bundling problem described in the PR objectives.

Regarding the static analysis ReDoS warning: The dependency names are sourced from package.json (maintainer-controlled, not user input), and the pattern ^${dependency}(\\/[\\w-]+)?$ is simple and bounded, so the practical ReDoS risk is negligible.


13-17: LGTM!

Pointing esbuildOptions.tsconfig to the new tsconfig.lib.json ensures esbuild's dependency pre-bundling aligns with the library's TypeScript configuration in the composite project setup.


27-29: Verify the emptyOutDir: false change.

Using the dynamic name from package.json is good practice and eliminates duplication.

However, changing emptyOutDir from true to false prevents Vite from clearing the dist/ directory before each build, which could leave stale artifacts if file names change. Please confirm this is intentional (e.g., for incremental builds or preserving separately generated type declarations).

package.json (2)

13-24: Script updates align with Yarn 4 requirements.

The addition of the -A (all) flag and the updated flag patterns (-Avp, -Avt) are consistent with Yarn 4's new foreach requirements. The flag combinations are logical:

  • Build scripts use -Avp (all+verbose+parallel) for faster builds
  • Test scripts use -Avt (all+verbose+topological) to respect dependency order
  • Public package scripts correctly add --no-private to exclude private packages

The script organization properly separates concerns (all vs libs, specific includes for react-tutorial).

Based on the past review comment confirming the -A flag requirement in Yarn 4.


5-5: The Yarn 4 upgrade and catalog protocol configuration are properly implemented. The .yarnrc.yml file correctly defines the catalog with pinned React versions (19.1.0), and workspace scripts use valid flag combinations that Yarn 4 supports (parallel execution can coexist with topological ordering). No additional verification needed.

Comment on lines 1 to 6
catalog:
"@types/react": ~19.1.0
"@types/react-dom": 19.1.0
react: 19.1.0
react-dom: 19.1.0

Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

# Find all package.json files and check for React peerDependencies
find . -name "package.json" -type f | head -20 | xargs -I {} sh -c 'echo "=== {} ===" && cat "{}" | jq -r "if .peerDependencies and .peerDependencies.react then \"\(.name): \(.peerDependencies.react)\" else empty end" 2>/dev/null'

Repository: GetStream/stream-feeds-js

Length of output: 524


🏁 Script executed:

# Check for CI configuration files
find .github -name "*.yml" -o -name "*.yaml" 2>/dev/null | head -10 | xargs -I {} sh -c 'echo "=== {} ===" && head -50 "{}"'

Repository: GetStream/stream-feeds-js

Length of output: 2860


🏁 Script executed:

# Also search for test configuration or matrix testing
find . -maxdepth 3 -name "*.yml" -o -name "*.yaml" | grep -E "(test|ci|workflow)" | head -10 | xargs -I {} sh -c 'echo "=== {} ===" && cat "{}" | grep -A 10 -B 2 -i "react\|matrix" | head -40'

Repository: GetStream/stream-feeds-js

Length of output: 2122


🏁 Script executed:

# Check test configuration files for React version matrix testing
find . -maxdepth 3 -name "vitest.config.*" -o -name "jest.config.*" -o -name "tsconfig*.json" | head -10 | xargs cat 2>/dev/null | grep -i "react\|version\|matrix" -A 2 -B 2 | head -50

Repository: GetStream/stream-feeds-js

Length of output: 558


🏁 Script executed:

# Check package.json test scripts for any multi-version testing
find ./packages -name "package.json" -exec grep -l "test" {} \; | xargs -I {} sh -c 'echo "=== {} ===" && cat {} | jq ".scripts | select(. != null)"' 2>/dev/null | head -100

Repository: GetStream/stream-feeds-js

Length of output: 1011


React version compatibility is not validated by CI testing.

The peerDependencies in package.json are correctly specified: ^17 || ^18 || ^19 for react-sdk and feeds-client, >=17.0.0 for react-native-sdk. However, the CI pipeline (.github/workflows/lint-test.yml) only tests with a single Node.js version (22.x) and does not include a test matrix for React versions. This means tests execute exclusively with React 19.1.0 from the catalog, potentially masking compatibility issues with React 17–18.

To fully validate the stated React version support, add a test matrix that runs tests against React 17, 18, and 19, or explicitly test with older React versions in CI.

🤖 Prompt for AI Agents
In .yarnrc.yml around lines 1 to 6 the catalog pins React to 19.1.0 which causes
CI to only exercise React 19; update CI to validate the library peerDependency
range by adding a test matrix that runs the test workflow against React 17, 18,
and 19 (or explicitly install and run tests with older React versions). Modify
the GitHub Actions workflow (.github/workflows/lint-test.yml) to include a
strategy.matrix entry for REACT_VERSION (e.g. 17.0.2, 18.x, 19.1.0) and in each
job install the corresponding React and react-dom from the matrix before running
yarn install and tests so the test suite runs against all supported React
versions.

this.feed = connectActivityToFeed.call(this.feedsClient, { fid });

this.feed.state.partialNext({
this.feed?.state.partialNext({
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:

#!/bin/bash

# Find the activity-with-state-updates.ts file
fd -t f "activity-with-state-updates.ts" 

# List files in packages/feeds-client/src to confirm directory structure
fd -t f -e ts "." "packages/feeds-client/src" | head -20

Repository: GetStream/stream-feeds-js

Length of output: 1799


🏁 Script executed:

#!/bin/bash

# Get the exact file path
find . -name "activity-with-state-updates.ts" -type f

# Read the file
if [ -f "packages/feeds-client/src/activity-with-state-updates/activity-with-state-updates.ts" ]; then
  cat -n "packages/feeds-client/src/activity-with-state-updates/activity-with-state-updates.ts"
fi

Repository: GetStream/stream-feeds-js

Length of output: 6941


🏁 Script executed:

#!/bin/bash
# Find and examine connectActivityToFeed implementation
fd -t f "active-activity.ts" "packages/feeds-client/src"

# Read the file
find . -name "active-activity.ts" -type f | xargs cat -n

Repository: GetStream/stream-feeds-js

Length of output: 1275


🏁 Script executed:

#!/bin/bash
# Check if empty feeds arrays are ever valid/expected
rg -n "feeds.*\[\]|feeds\.length.*===.*0" packages/feeds-client/src --type ts -A 2 -B 2

# Check how activityResponse.feeds is used elsewhere
rg -n "\.feeds\[0\]|\.feeds\?" packages/feeds-client/src --type ts -B 2 -A 2

# Check if there are tests that cover empty feeds scenarios
fd -t f "\.test\.ts$" packages/feeds-client/src | xargs grep -l "feeds.*\[\]|empty.*feeds" 2>/dev/null

# Search for activity response type definition
fd -t f "models.*\.(ts|d\.ts)$" packages/feeds-client/src | head -5

Repository: GetStream/stream-feeds-js

Length of output: 10974


🏁 Script executed:

#!/bin/bash
# Check the ActivityResponse type definition more carefully
grep -A 10 "export interface ActivityResponse" packages/feeds-client/src/gen/models/index.ts

# Check if there are any tests that validate the empty feeds scenario
grep -r "feeds.*\[\]" packages/feeds-client/src --include="*.test.ts" -B 3 -A 3

# Check if there's validation in getActivity or any API handlers
grep -n "feeds" packages/feeds-client/src/feeds-client/feeds-client.ts | head -20

Repository: GetStream/stream-feeds-js

Length of output: 5536


🏁 Script executed:

#!/bin/bash
# Check if there's any validation or error handling around the feeds array access
grep -B 5 -A 10 "feeds\[0\]" packages/feeds-client/src/activity-with-state-updates/activity-with-state-updates.ts

# Check test file to see if there are tests for empty feeds scenarios
cat packages/feeds-client/src/activity-with-state-updates/activity-with-state-updates.test.ts | head -100

Repository: GetStream/stream-feeds-js

Length of output: 3862


🏁 Script executed:

#!/bin/bash
# Let's check if there's any type safety that prevents undefined from being passed
grep -B 5 -A 10 "fid: string" packages/feeds-client/src/feeds-client/active-activity.ts

# Check if there's any validation in setFeed or error handling
grep -B 10 -A 15 "private setFeed" packages/feeds-client/src/activity-with-state-updates/activity-with-state-updates.ts

# Let's verify what happens when we split undefined
node -e "console.log(undefined.split(':'))" 2>&1 || echo "Error as expected"

# Check if there's any validation that ensures feeds is not empty
rg "feeds.length|feeds\?" packages/feeds-client/src/test-utils/response-generators.ts -A 2 -B 2

Repository: GetStream/stream-feeds-js

Length of output: 1494


Accessing feeds[0] without bounds checking can cause a runtime crash.

If activityResponse.feeds is empty, feeds[0] is undefined. Passing undefined as fid to connectActivityToFeed will crash when attempting to split it (line 12 in active-activity.ts calls fid.split(':')), not silently fail as the optional chaining might suggest.

Add validation to ensure activityResponse.feeds is non-empty before calling setFeed:

if (!activityResponse.feeds.length) {
  throw new Error('Activity must belong to at least one feed');
}

this.setFeed({
  fid: activityResponse.feeds[0],
  initialState: activityResponse,
});
🤖 Prompt for AI Agents
In
packages/feeds-client/src/activity-with-state-updates/activity-with-state-updates.ts
around line 167, the code calls this.setFeed using activityResponse.feeds[0]
without verifying feeds is non-empty which can pass undefined into
connectActivityToFeed and crash when split is called; add a guard that checks
activityResponse.feeds exists and has length > 0, and if not throw a clear
Error('Activity must belong to at least one feed') (or otherwise handle the
empty case), then call this.setFeed with fid: activityResponse.feeds[0] and
initialState: activityResponse; ensure the check satisfies TypeScript narrowing
so the first element is typed as string.

Comment on lines 454 to 460
uploadFile = (
request: Omit<FileUploadRequest, 'file'> & { file: StreamFile },
request?: Omit<FileUploadRequest, 'file'> & { file?: StreamFile | string },
) => {
return super.uploadFile({
// @ts-expect-error API spec says file should be a string
file: request.file,
file: request?.file as string,
});
};
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

Unsafe type cast - missing StreamFile conversion.

The method accepts StreamFile | string but casts directly to string without conversion logic. If a StreamFile object (e.g., { name, uri, type }) is passed, the cast will not convert it, causing the API call to fail with a type error.

You need to add conversion logic before the cast:

  uploadFile = (
    request?: Omit<FileUploadRequest, 'file'> & { file?: StreamFile | string },
  ) => {
+   const fileString = typeof request?.file === 'string' 
+     ? request.file 
+     : request?.file?.uri || '';
    return super.uploadFile({
-     file: request?.file as string,
+     file: fileString,
    });
  };
🤖 Prompt for AI Agents
In packages/feeds-client/src/feeds-client/feeds-client.ts around lines 454 to
460, the uploadFile method unsafely casts request.file to string; instead,
detect whether request?.file is already a string and pass it through, or if it
is a StreamFile object convert it to the expected string representation (for
example use its uri/path or serialize the StreamFile into the required upload
payload) before calling super.uploadFile; also handle undefined file gracefully
and preserve the original request typing (Omit<FileUploadRequest,'file'> & {
file?: ... }) so the call to super.uploadFile receives a properly converted file
string or undefined.

Comment on lines 462 to 471
uploadImage = (
request: Omit<ImageUploadRequest, 'file'> & { file: StreamFile },
request?: Omit<ImageUploadRequest, 'file'> & { file?: StreamFile | string },
) => {
return super.uploadImage({
// @ts-expect-error API spec says file should be a string
file: request.file,
// @ts-expect-error form data will only work if this is a string
upload_sizes: JSON.stringify(request.upload_sizes),
file: request?.file as string,
upload_sizes: JSON.stringify(
request?.upload_sizes,
) as unknown as ImageSize[],
});
};
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

Multiple unsafe type casts in uploadImage.

Two issues:

  1. Same StreamFile conversion problem as uploadFile
  2. Line 467-469: JSON.stringify() returns a string, not ImageSize[]. This cast is unsafe and will likely cause the API call to fail.

Apply this diff to fix both issues:

  uploadImage = (
    request?: Omit<ImageUploadRequest, 'file'> & { file?: StreamFile | string },
  ) => {
+   const fileString = typeof request?.file === 'string' 
+     ? request.file 
+     : request?.file?.uri || '';
    return super.uploadImage({
-     file: request?.file as string,
-     upload_sizes: JSON.stringify(
-       request?.upload_sizes,
-     ) as unknown as ImageSize[],
+     file: fileString,
+     upload_sizes: request?.upload_sizes,
    });
  };

The API should accept ImageSize[] directly. If it requires JSON string, the base class should handle serialization, not this override.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
uploadImage = (
request: Omit<ImageUploadRequest, 'file'> & { file: StreamFile },
request?: Omit<ImageUploadRequest, 'file'> & { file?: StreamFile | string },
) => {
return super.uploadImage({
// @ts-expect-error API spec says file should be a string
file: request.file,
// @ts-expect-error form data will only work if this is a string
upload_sizes: JSON.stringify(request.upload_sizes),
file: request?.file as string,
upload_sizes: JSON.stringify(
request?.upload_sizes,
) as unknown as ImageSize[],
});
};
uploadImage = (
request?: Omit<ImageUploadRequest, 'file'> & { file?: StreamFile | string },
) => {
const fileString = typeof request?.file === 'string'
? request.file
: request?.file?.uri || '';
return super.uploadImage({
file: fileString,
upload_sizes: request?.upload_sizes,
});
};
🤖 Prompt for AI Agents
In packages/feeds-client/src/feeds-client/feeds-client.ts around lines 462-471,
the uploadImage override uses unsafe casts: it force-casts request.file to
string (losing StreamFile support) and JSON.stringify(...) is incorrectly cast
to ImageSize[]; change the method to accept request?.file as StreamFile | string
and pass upload_sizes through as ImageSize[] (do not stringify), matching the
base class signature so the base class handles any serialization; remove the
unsafe casts and forward the values directly to super.uploadImage({ file:
request?.file, upload_sizes: request?.upload_sizes }).

},
"peerDependencies": {
"react": "^18 || ^19"
"react": "^17 || ^18 || ^19"
Copy link

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:

#!/bin/bash
# Search for React 17-specific configurations or tests

# Check if there are CI configurations testing React 17
find . -type f \( -name ".github" -o -name ".gitlab-ci.yml" -o -name "*.yml" -o -name "*.yaml" \) -path "*/\.*" 2>/dev/null | head -20

# Search for test configuration files
find . -type f \( -name "jest.config.*" -o -name "vitest.config.*" -o -name "cypress.config.*" \) 2>/dev/null

# Search for React version pinning in test setup
rg -l "react.*17|17.*react" --type=json --type=ts --type=tsx . 2>/dev/null | head -10

# Check package.json files for React versions
find . -name "package.json" -type f | xargs grep -l "react" 2>/dev/null | head -5

Repository: GetStream/stream-feeds-js

Length of output: 904


🏁 Script executed:

#!/bin/bash
# Check CI workflows for React version matrix testing
echo "=== Checking lint-test.yml ==="
cat .github/workflows/lint-test.yml | head -100

echo -e "\n=== Checking check-pr.yml ==="
cat .github/workflows/check-pr.yml | head -100

echo -e "\n=== Current packages/react-sdk/package.json ==="
cat ./packages/react-sdk/package.json

Repository: GetStream/stream-feeds-js

Length of output: 3064


🏁 Script executed:

#!/bin/bash
# Check if react-sdk code uses React 18+ specific features or APIs

echo "=== Searching for React 18+ specific hooks/APIs ==="
rg "useInsertionEffect|useDeferredValue|useId|useTransition|startTransition|createRoot|hydrateRoot" \
  packages/react-sdk/src --type=ts --type=tsx

echo -e "\n=== Checking react-sdk source structure ==="
find packages/react-sdk/src -type f -name "*.ts" -o -name "*.tsx" | head -20

echo -e "\n=== Checking if any React 17 incompatible patterns ==="
rg "Suspense|concurrent|useSyncExternalStore" packages/react-sdk/src --type=ts --type=tsx -A 2

Repository: GetStream/stream-feeds-js

Length of output: 326


🏁 Script executed:

#!/bin/bash
# Check react-sdk source files
echo "=== Listing react-sdk/src files ==="
find packages/react-sdk/src -type f

echo -e "\n=== Reading react-sdk/src/index.ts ==="
cat packages/react-sdk/src/index.ts

echo -e "\n=== Searching for React 18+ only features ==="
rg "useInsertionEffect|useDeferredValue|useId|useTransition|startTransition|createRoot|hydrateRoot" packages/react-sdk/src

echo -e "\n=== Checking for useSyncExternalStore usage ==="
rg "useSyncExternalStore" packages/react-sdk/src -A 3

Repository: GetStream/stream-feeds-js

Length of output: 369


🏁 Script executed:

#!/bin/bash
# Check the actual react-bindings that are being exported
echo "=== Listing feeds-client/react-bindings structure ==="
find packages/feeds-client/src/react-bindings -type f 2>/dev/null | head -20

echo -e "\n=== Checking if react-bindings exists ==="
ls -la packages/feeds-client/src/ 2>/dev/null

echo -e "\n=== Checking feeds-client package.json ==="
cat packages/feeds-client/package.json | head -50

echo -e "\n=== Searching for React version usage in feeds-client ==="
rg "useSyncExternalStore|createRoot|hydrateRoot|useInsertionEffect" packages/feeds-client/src --type=ts --type=js -A 2

Repository: GetStream/stream-feeds-js

Length of output: 2791


🏁 Script executed:

#!/bin/bash
# Check the bindings code
echo "=== Checking bindings structure ==="
find packages/feeds-client/src/bindings -type f | head -20

echo -e "\n=== Checking for React usage in bindings ==="
cat packages/feeds-client/src/bindings/react/index.ts 2>/dev/null || find packages/feeds-client/src/bindings -name "*.ts" | head -5 | xargs head -30

echo -e "\n=== Checking peerDependencies in feeds-client ==="
grep -A 5 "peerDependencies" packages/feeds-client/package.json

echo -e "\n=== Check if there's any React version detection/compatibility code ==="
rg "useSyncExternalStore|React\.version|react.*version" packages/feeds-client/src --type=ts

Repository: GetStream/stream-feeds-js

Length of output: 2672


🏁 Script executed:

#!/bin/bash
# Check a few hook implementations to see what React features they use
echo "=== Checking useCreateFeedsClient hook ==="
cat packages/feeds-client/src/bindings/react/hooks/useCreateFeedsClient.ts 2>/dev/null | head -50

echo -e "\n=== Checking state-store react-bindings peerDependencies ==="
grep -A 5 "peerDependencies" packages/state-store/package.json 2>/dev/null

echo -e "\n=== Checking if use-sync-external-store is used for React 17 compatibility ==="
rg "useSyncExternalStore" packages --type=ts

echo -e "\n=== Check one context implementation ==="
head -40 packages/feeds-client/src/bindings/react/contexts/StreamFeedsContext.tsx

Repository: GetStream/stream-feeds-js

Length of output: 2111


🏁 Script executed:

#!/bin/bash
# Check state-store package to understand the React bindings better
echo "=== Checking state-store package.json ==="
cat packages/state-store/package.json | head -80

echo -e "\n=== Check use-sync-external-store usage in state-store ==="
rg "useSyncExternalStore" packages/state-store/src --type=ts -B 2 -A 5 | head -40

Repository: GetStream/stream-feeds-js

Length of output: 318


🏁 Script executed:

#!/bin/bash
# Check what packages exist
echo "=== Available packages ==="
ls -la packages/

echo -e "\n=== Check feeds-client for use-sync-external-store usage ==="
rg "use-sync-external-store|useSyncExternalStore" packages/feeds-client --type=ts -B 2 -A 3

echo -e "\n=== Check if state-store is external dependency ==="
grep "@stream-io/state-store" packages/feeds-client/package.json

echo -e "\n=== Full feeds-client dependencies ==="
cat packages/feeds-client/package.json | grep -A 30 '"dependencies"'

Repository: GetStream/stream-feeds-js

Length of output: 1156


🏁 Script executed:

#!/bin/bash
# Check what @stream-io/state-store declares for React
echo "=== Searching npm/yarn for state-store React requirements ==="
grep -r "useSyncExternalStore" . --include="*.ts" --include="*.tsx" 2>/dev/null | head -5

echo -e "\n=== Check the original package.json to see if this is new ==="
git log --oneline -n 20 -- packages/react-sdk/package.json 2>/dev/null

echo -e "\n=== Check git diff for this specific line ==="
git diff HEAD~1 packages/react-sdk/package.json 2>/dev/null | head -40

Repository: GetStream/stream-feeds-js

Length of output: 411


🏁 Script executed:

#!/bin/bash
# Check the actual PR branch
echo "=== Check the PR branch details ==="
git log --all --oneline | grep -i "react" | head -10

echo -e "\n=== Check HEAD for the specific change ==="
git show HEAD:packages/react-sdk/package.json | grep -A 2 "peerDependencies"

echo -e "\n=== Check previous commit ==="
git show HEAD~1:packages/react-sdk/package.json 2>/dev/null | grep -A 2 "peerDependencies" || echo "Not found in HEAD~1"

echo -e "\n=== Get the actual diff for peerDependencies ==="
git log -p --follow -S '"react".*17' -- packages/react-sdk/package.json | head -60

Repository: GetStream/stream-feeds-js

Length of output: 1011


🏁 Script executed:

#!/bin/bash
# Check what branch we're on and what the previous version was
echo "=== Check current branch ==="
git status

echo -e "\n=== Check the merge base before this PR ==="
git show $(git merge-base HEAD main):packages/react-sdk/package.json 2>/dev/null | grep -A 2 "peerDependencies" || echo "Could not get merge base"

echo -e "\n=== Get full commit message for the merge ==="
git log -1 HEAD --format=%B

echo -e "\n=== Check if there's a specific PR/branch for this change ==="
git branch -r | head -10

echo -e "\n=== Look at the test directory to understand what's tested ==="
find packages/react-sdk -name "*.test.ts" -o -name "*.test.tsx" -o -name "*.spec.ts"

echo -e "\n=== Check if there are any version-specific tests ==="
rg "react.*17|React.*17" packages/feeds-client/src --type=ts

Repository: GetStream/stream-feeds-js

Length of output: 795


🏁 Script executed:

#!/bin/bash
# Let me trace the actual change by checking what was before
echo "=== Get detailed history of react-sdk/package.json changes ==="
git log --all --oneline -- packages/react-sdk/package.json | head -20

echo -e "\n=== Check the specific commit that changed React peer deps ==="
git log -p --all -- packages/react-sdk/package.json | grep -B 5 -A 5 '"react".*17' | head -40

echo -e "\n=== Verify current state vs main ==="
git show main:packages/react-sdk/package.json 2>/dev/null | grep -A 2 "peerDependencies"

echo -e "\n=== Check feeds-client main branch too ==="
git show main:packages/feeds-client/package.json 2>/dev/null | grep -A 2 "peerDependencies"

Repository: GetStream/stream-feeds-js

Length of output: 1766


🏁 Script executed:

#!/bin/bash
# Final verification - check if this is intentional
echo "=== Check the fix/feeds-client/react-18 branch for any documentation ==="
git show fix/feeds-client/react-18:packages/react-sdk/package.json 2>/dev/null | grep -A 5 "peerDependencies" || echo "Branch not available"

echo -e "\n=== Check if there are any comments in the branch about React 17 ==="
git log --all --grep="React 17" --oneline | head -10

echo -e "\n=== Check CHANGELOG or README for React 17 mention ==="
find packages/react-sdk -name "CHANGELOG*" -o -name "README*" | xargs grep -i "react.*17" 2>/dev/null

echo -e "\n=== Final check: does the SDK code have any React 18+ only features ==="
rg "createRoot|hydrateRoot|useInsertionEffect|useDeferredValue|startTransition" packages/feeds-client/src/bindings/react --type=ts

Repository: GetStream/stream-feeds-js

Length of output: 1534


Add React 17 testing to CI or clarify support scope.

Adding React 17 to peer dependencies expands support from ^18 || ^19 to ^17 || ^18 || ^19, but the CI workflow lacks a Node/React version matrix to test React 17 compatibility. React 17 has different behavior around batching and concurrent features compared to React 18, which removed support for deprecated APIs like ReactDOM.render. While the SDK code appears compatible (using basic hooks and useSyncExternalStore), this change should either include CI testing for React 17 or be reconsidered. Additionally, the learnings reference "Support React 18+" rather than React 17—verify this aligns with PR objectives.

🤖 Prompt for AI Agents
In packages/react-sdk/package.json around line 18, the peerDependency change to
include "react": "^17 || ^18 || ^19" expands claimed support but the CI lacks
tests for React 17; either add CI coverage for React 17 or revert/clarify the
peerDependency and docs. To fix, update the repo's CI workflow to include a
matrix entry that installs and runs tests against React 17 (and an appropriate
Node version) so compatibility is validated, or revert the package.json to only
advertise supported versions and update README/learnings text to consistently
state the supported React range.

@szuperaz szuperaz merged commit 83abe04 into main Dec 17, 2025
6 checks passed
@szuperaz szuperaz deleted the fix/feeds-client/react-18 branch December 17, 2025 14:36
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.

4 participants