Skip to content
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
7745727
Phase 3: Prepare core package for workspace structure
AbanoubGhadban Sep 26, 2025
ce91f23
Fix CI failures: Update Knip config and test imports for workspace st…
AbanoubGhadban Sep 26, 2025
0182224
Fix package.json workspace configuration for publishing
AbanoubGhadban Sep 26, 2025
6f08b49
Fix workspace configuration for publishing and CI
AbanoubGhadban Sep 26, 2025
385df7f
Fix Knip configuration to ignore build output directories
AbanoubGhadban Sep 28, 2025
4417277
Fix ESLint configuration for workspace package imports
AbanoubGhadban Sep 28, 2025
3b34f34
Fix Jest configuration for workspace and testing library setup
AbanoubGhadban Sep 28, 2025
5fd223e
Fix Jest setupFilesAfterEnv path resolution for CI
AbanoubGhadban Sep 28, 2025
ef7c6e6
Update Gemfile.lock and package.json for path corrections
AbanoubGhadban Sep 28, 2025
4b94aba
Update script/convert for workspace structure
AbanoubGhadban Sep 28, 2025
8cf9138
Remove setupFilesAfterEnv from Jest configuration and clean up conver…
AbanoubGhadban Sep 28, 2025
ee4487a
Update CircleCI configuration to enhance caching strategy for node_mo…
AbanoubGhadban Sep 28, 2025
5eb784f
Update package.json to simplify link-source script by removing redund…
AbanoubGhadban Sep 28, 2025
a9e1e01
Update link-source script in package.json to target the correct direc…
AbanoubGhadban Sep 28, 2025
3250a03
Update build output path to workspace package directory
AbanoubGhadban Sep 28, 2025
660cab3
Complete workspace migration: move tests, scripts, and babel config
AbanoubGhadban Sep 28, 2025
eab8e2a
Refactor package.json scripts to utilize workspaces for improved comm…
AbanoubGhadban Sep 28, 2025
c1c6b45
Enhance package.json scripts for improved workspace management
AbanoubGhadban Sep 28, 2025
b34e161
Rename package to react-on-rails-workspace and streamline scripts in …
AbanoubGhadban Sep 28, 2025
946698d
Update CircleCI configuration to streamline caching for node_modules …
AbanoubGhadban Sep 28, 2025
a784eb6
Update Knip configuration and package.json scripts for improved path …
AbanoubGhadban Sep 28, 2025
87fe9cc
Revert unnecessary file extension changes
AbanoubGhadban Sep 29, 2025
3e992bc
Add global Jest configuration and refactor Knip settings
AbanoubGhadban Sep 29, 2025
20f2f0b
Update ESLint configuration to reflect new package structure
AbanoubGhadban Sep 29, 2025
dfc1275
Update configuration files to reflect package structure changes
AbanoubGhadban Sep 29, 2025
caf8d34
Update MONOREPO_MERGER_PLAN.md to reflect co-located test structure
AbanoubGhadban Sep 29, 2025
325e4e8
Update documentation and references to reflect new package structure
AbanoubGhadban Sep 29, 2025
e0d1365
Update test command in convert script for improved execution
AbanoubGhadban Sep 29, 2025
fd728b3
Update Knip configuration and package.json scripts for improved execu…
AbanoubGhadban Sep 29, 2025
0a97c1e
Update test command in package.json for improved execution
AbanoubGhadban Sep 29, 2025
86e0ab6
Update DIRECTORY_LICENSING.md to reflect new directory structure
AbanoubGhadban Sep 29, 2025
ceb15a6
Update DIRECTORY_LICENSING.md to reflect new directory structure and …
AbanoubGhadban Sep 29, 2025
4331ea1
Update CONTRIBUTING.md to correct link formatting
AbanoubGhadban Sep 29, 2025
40ccdb2
Update MONOREPO_MERGER_PLAN.md to specify new build output locations …
AbanoubGhadban Sep 29, 2025
c9c406f
Update MONOREPO_MERGER_PLAN.md and MONOREPO_MERGER_PLAN_REF.md to ref…
AbanoubGhadban Sep 29, 2025
804a88d
Update MONOREPO_MERGER_PLAN.md and MONOREPO_MERGER_PLAN_REF.md to ref…
AbanoubGhadban Sep 29, 2025
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
8 changes: 4 additions & 4 deletions .github/workflows/lint-js-and-ruby.yml
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ jobs:
yarn install --no-progress --no-emoji --frozen-lockfile
sudo yarn global add yalc
- name: yalc publish for react-on-rails
run: yalc publish
run: cd packages/react-on-rails && yalc publish
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Build before yalc publish to ensure lib exists

The workflow publishes via yalc without building first. Insert a build step before publishing.

-      - name: yalc publish for react-on-rails
-        run: cd packages/react-on-rails && yalc publish
+      - name: Build package
+        run: yarn workspace react-on-rails build
+      - name: yalc publish for react-on-rails
+        run: cd packages/react-on-rails && yalc publish
πŸ“ 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
run: cd packages/react-on-rails && yalc publish
- name: Build package
run: yarn workspace react-on-rails build
- name: yalc publish for react-on-rails
run: cd packages/react-on-rails && yalc publish
πŸ€– Prompt for AI Agents
.github/workflows/lint-js-and-ruby.yml around line 48: the workflow calls "cd
packages/react-on-rails && yalc publish" without building the package first;
update the job to run the package's build script before publishing (e.g., "cd
packages/react-on-rails && yarn install && yarn build" or the equivalent
npm/pnpm commands), ensuring the lib/dist output exists before invoking "yalc
publish".

- name: yalc add react-on-rails
run: cd spec/dummy && yalc add react-on-rails
- name: Install Node modules with Yarn for dummy app
Expand Down Expand Up @@ -81,12 +81,12 @@ jobs:
- name: Type-check TypeScript
run: yarn run type-check
- name: Pack for attw and publint
run: yarn pack -f react-on-rails.tgz
run: cd packages/react-on-rails && yarn pack -f react-on-rails.tgz
- name: Lint package types
# our package is ESM-only
run: yarn run attw react-on-rails.tgz --profile esm-only
run: yarn run attw packages/react-on-rails/react-on-rails.tgz --profile esm-only
- name: Lint package publishing
run: yarn run publint --strict react-on-rails.tgz
run: yarn run publint --strict packages/react-on-rails/react-on-rails.tgz
# We only download and run Actionlint if there is any difference in GitHub Action workflows
# https://github.com/rhysd/actionlint/blob/main/docs/usage.md#on-github-actions
- name: Check GitHub Action changes
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ jobs:
yarn install --no-progress --no-emoji ${{ matrix.dependency-level == 'latest' && '--frozen-lockfile' || '' }}
sudo yarn global add yalc
- name: yalc publish for react-on-rails
run: yalc publish
run: cd packages/react-on-rails && yalc publish
- name: yalc add react-on-rails
run: cd spec/dummy && yalc add react-on-rails
- name: Install Node modules with Yarn for dummy app
Expand Down Expand Up @@ -159,7 +159,7 @@ jobs:
yarn install --no-progress --no-emoji ${{ matrix.dependency-level == 'latest' && '--frozen-lockfile' || '' }}
sudo yarn global add yalc
- name: yalc publish for react-on-rails
run: yalc publish
run: cd packages/react-on-rails && yalc publish
- name: yalc add react-on-rails
run: cd spec/dummy && yalc add react-on-rails
- name: Install Node modules with Yarn for dummy app
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ tmp/
node_modules

/node_package/lib
/packages/*/lib

yarn-debug.*
yarn-error.*
Expand Down
4 changes: 2 additions & 2 deletions LICENSE.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ This repository contains code under two different licenses:
The following directories and all their contents are licensed under the **MIT License** (see full text below):

- `lib/react_on_rails/` (excluding `lib/react_on_rails/pro/`)
- `node_package/src/` (excluding `node_package/src/pro/`)
- `packages/react-on-rails/` (excluding `packages/react-on-rails/src/pro/`)
- `node_package/lib/` (excluding `node_package/lib/pro/`)
- All other directories in this repository not explicitly listed as Pro-licensed

Expand All @@ -21,7 +21,7 @@ The following directories and all their contents are licensed under the **MIT Li
The following directories and all their contents are licensed under the **React on Rails Pro License**:

- `lib/react_on_rails/pro/`
- `node_package/src/pro/`
- `packages/react-on-rails/src/pro/`
- `node_package/lib/pro/`
- `react_on_rails_pro/` (entire directory)

Expand Down
6 changes: 6 additions & 0 deletions eslint.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,12 @@ const config = tsEslint.config([
'import/extensions': ['error', 'ignorePackages'],
},
},
{
files: ['packages/react-on-rails/src/**/*'],
rules: {
'import/extensions': ['error', 'ignorePackages'],
},
},
{
files: ['lib/generators/react_on_rails/templates/**/*'],
rules: {
Expand Down
1 change: 1 addition & 0 deletions jest.config.js β†’ jest.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ export default {
}),
testEnvironment: 'jsdom',
setupFiles: ['<rootDir>/node_package/tests/jest.setup.js'],
setupFilesAfterEnv: ['@testing-library/jest-dom'],
// React Server Components tests require React 19 and only run with Node version 18 (`newest` in our CI matrix)
moduleNameMapper:
nodeVersion < 18
Expand Down
40 changes: 22 additions & 18 deletions knip.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,36 +5,40 @@ const config: KnipConfig = {
workspaces: {
'.': {
entry: [
'node_package/src/ReactOnRails.node.ts!',
'node_package/src/pro/ReactOnRailsRSC.ts!',
'node_package/src/pro/registerServerComponent/client.tsx!',
'node_package/src/pro/registerServerComponent/server.tsx!',
'node_package/src/pro/registerServerComponent/server.rsc.ts!',
'node_package/src/pro/wrapServerComponentRenderer/server.tsx!',
'node_package/src/pro/wrapServerComponentRenderer/server.rsc.tsx!',
'node_package/src/pro/RSCRoute.tsx!',
'node_package/src/pro/ServerComponentFetchError.ts!',
'node_package/src/pro/getReactServerComponent.server.ts!',
'node_package/src/pro/transformRSCNodeStream.ts!',
'node_package/src/loadJsonFile.ts!',
'packages/react-on-rails/src/ReactOnRails.node.ts!',
'packages/react-on-rails/src/pro/ReactOnRailsRSC.ts!',
'packages/react-on-rails/src/pro/registerServerComponent/client.tsx!',
'packages/react-on-rails/src/pro/registerServerComponent/server.tsx!',
'packages/react-on-rails/src/pro/registerServerComponent/server.rsc.ts!',
'packages/react-on-rails/src/pro/wrapServerComponentRenderer/server.tsx!',
'packages/react-on-rails/src/pro/wrapServerComponentRenderer/server.rsc.tsx!',
'packages/react-on-rails/src/pro/RSCRoute.tsx!',
'packages/react-on-rails/src/pro/ServerComponentFetchError.ts!',
'packages/react-on-rails/src/pro/getReactServerComponent.server.ts!',
'packages/react-on-rails/src/pro/transformRSCNodeStream.ts!',
'packages/react-on-rails/src/loadJsonFile.ts!',
'eslint.config.ts',
],
project: [
'node_package/src/**/*.[jt]s{x,}!',
'packages/react-on-rails/src/**/*.[jt]s{x,}!',
'node_package/tests/**/*.[jt]s{x,}',
'!react_on_rails_pro/**',
'!packages/react-on-rails/lib/**',
],
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Restore ignoring of node_package/lib/**.

We still compile TypeScript into node_package/lib/ for backward compatibility (per PR summary). Dropping the ignore causes Knip to traverse the generated artifacts, which will surface false positives and waste analysis time. Keep excluding the legacy output alongside the new workspace lib directory.

       project: [
         'packages/react-on-rails/src/**/*.[jt]s{x,}!',
         'node_package/tests/**/*.[jt]s{x,}',
         '!react_on_rails_pro/**',
+        '!node_package/lib/**',
         '!packages/react-on-rails/lib/**',
       ],
       ignore: [
         'node_package/tests/emptyForTesting.js',
         // Build output directories that should be ignored
+        'node_package/lib/**',
         'packages/react-on-rails/lib/**',

Also applies to: 34-35

πŸ€– Prompt for AI Agents
In knip.ts around lines 24-27 (and also apply the same fix at lines 34-35), the
glob ignore for the legacy compiled TypeScript output node_package/lib/** was
removed causing Knip to traverse generated artifacts; restore the ignore pattern
'!node_package/lib/**' (add it to the ignore arrays) so Knip excludes the legacy
output alongside the existing workspace lib excludes to avoid false positives
and wasted analysis time.

babel: {
config: ['node_package/babel.config.js'],
},
ignore: [
'node_package/tests/emptyForTesting.js',
// Build output directories that should be ignored
'packages/react-on-rails/lib/**',
'node_package/lib/**',
// Pro features exported for external consumption
'node_package/src/pro/streamServerRenderedReactComponent.ts:transformRenderStreamChunksToResultObject',
'node_package/src/pro/streamServerRenderedReactComponent.ts:streamServerRenderedComponent',
'node_package/src/pro/ServerComponentFetchError.ts:isServerComponentFetchError',
'node_package/src/pro/RSCRoute.tsx:RSCRouteProps',
'node_package/src/pro/streamServerRenderedReactComponent.ts:StreamingTrackers',
'packages/react-on-rails/src/pro/streamServerRenderedReactComponent.ts:transformRenderStreamChunksToResultObject',
'packages/react-on-rails/src/pro/streamServerRenderedReactComponent.ts:streamServerRenderedComponent',
'packages/react-on-rails/src/pro/ServerComponentFetchError.ts:isServerComponentFetchError',
'packages/react-on-rails/src/pro/RSCRoute.tsx:RSCRouteProps',
'packages/react-on-rails/src/pro/streamServerRenderedReactComponent.ts:StreamingTrackers',
// Exclude entire pro directory - it has its own package.json with dependencies
'react_on_rails_pro/**',
],
Expand Down
2 changes: 1 addition & 1 deletion node_package/tests/Authenticity.test.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import ReactOnRails from '../src/ReactOnRails.client.ts';
import ReactOnRails from '../../packages/react-on-rails/src/ReactOnRails.client.ts';

const testToken = 'TEST_CSRF_TOKEN';

Expand Down
6 changes: 3 additions & 3 deletions node_package/tests/ComponentRegistry.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@
import * as React from 'react';
import * as createReactClass from 'create-react-class';

import * as ComponentRegistry from '../src/pro/ComponentRegistry.ts';
import * as ComponentRegistry from '../../packages/react-on-rails/src/pro/ComponentRegistry.ts';

const onPageLoadedCallbacks = [];
const onPageUnloadedCallbacks = [];

jest.mock('../src/pageLifecycle.ts', () => ({
jest.mock('../../packages/react-on-rails/src/pageLifecycle.ts', () => ({
onPageLoaded: jest.fn((cb) => {
onPageLoadedCallbacks.push(cb);
cb();
Expand All @@ -22,7 +22,7 @@ jest.mock('../src/pageLifecycle.ts', () => ({
}),
}));

jest.mock('../src/context.ts', () => ({
jest.mock('../../packages/react-on-rails/src/context.ts', () => ({
getRailsContext: () => ({ componentRegistryTimeout: 100 }),
}));

Expand Down
2 changes: 1 addition & 1 deletion node_package/tests/ReactOnRails.test.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import { createStore } from 'redux';
import * as React from 'react';
import * as createReactClass from 'create-react-class';
import ReactOnRails from '../src/ReactOnRails.client.ts';
import ReactOnRails from '../../packages/react-on-rails/src/ReactOnRails.client.ts';
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Fix ESLint violation from cross-package relative import

import/no-relative-packages rejects ../../packages/.... Lint will fail until we switch to the package alias. Please update (and ensure other occurrences follow suit):

-import ReactOnRails from '../../packages/react-on-rails/src/ReactOnRails.client.ts';
+import ReactOnRails from 'react-on-rails/src/ReactOnRails.client.ts';
πŸ“ 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
import ReactOnRails from '../../packages/react-on-rails/src/ReactOnRails.client.ts';
import ReactOnRails from 'react-on-rails/src/ReactOnRails.client.ts';
🧰 Tools
πŸͺ› ESLint

[error] 7-7: Relative import from another package is not allowed. Use react-on-rails/src/ReactOnRails.client.ts instead of ../../packages/react-on-rails/src/ReactOnRails.client.ts

(import/no-relative-packages)

πŸ€– Prompt for AI Agents
In node_package/tests/ReactOnRails.test.jsx around line 7, replace the
cross-package relative import
"../../packages/react-on-rails/src/ReactOnRails.client.ts" with the published
package alias (e.g. import ReactOnRails from 'react-on-rails') to satisfy
import/no-relative-packages; update any other files using
../../packages/react-on-rails/... to the same package alias and run ESLint to
verify the violation is resolved.


describe('ReactOnRails', () => {
it('render returns a virtual DOM element for component', () => {
Expand Down
2 changes: 1 addition & 1 deletion node_package/tests/StoreRegistry.test.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { createStore } from 'redux';

import * as StoreRegistry from '../src/pro/StoreRegistry.ts';
import * as StoreRegistry from '../../packages/react-on-rails/src/pro/StoreRegistry.ts';

function reducer() {
return {};
Expand Down
2 changes: 1 addition & 1 deletion node_package/tests/buildConsoleReplay.test.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import buildConsoleReplay, { consoleReplay } from '../src/buildConsoleReplay.ts';
import buildConsoleReplay, { consoleReplay } from '../../packages/react-on-rails/src/buildConsoleReplay.ts';

describe('consoleReplay', () => {
it('does not throw an exception if no console.history object', () => {
Expand Down
6 changes: 3 additions & 3 deletions node_package/tests/injectRSCPayload.test.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Readable, PassThrough } from 'stream';
import { RailsContextWithServerStreamingCapabilities } from '../src/types/index.ts';
import injectRSCPayload from '../src/pro/injectRSCPayload.ts';
import RSCRequestTracker from '../src/pro/RSCRequestTracker.ts';
import { RailsContextWithServerStreamingCapabilities } from '../../packages/react-on-rails/src/types/index.ts';
import injectRSCPayload from '../../packages/react-on-rails/src/pro/injectRSCPayload.ts';
import RSCRequestTracker from '../../packages/react-on-rails/src/pro/RSCRequestTracker.ts';
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Switch injectRSCPayload test imports to the package alias

The new relative paths break the lint rule banning cross-package relatives. Update them to the published workspace name:

-import { RailsContextWithServerStreamingCapabilities } from '../../packages/react-on-rails/src/types/index.ts';
-import injectRSCPayload from '../../packages/react-on-rails/src/pro/injectRSCPayload.ts';
-import RSCRequestTracker from '../../packages/react-on-rails/src/pro/RSCRequestTracker.ts';
+import { RailsContextWithServerStreamingCapabilities } from 'react-on-rails/src/types/index.ts';
+import injectRSCPayload from 'react-on-rails/src/pro/injectRSCPayload.ts';
+import RSCRequestTracker from 'react-on-rails/src/pro/RSCRequestTracker.ts';

Lint will pass once these aliases are in place.

πŸ“ 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
import { RailsContextWithServerStreamingCapabilities } from '../../packages/react-on-rails/src/types/index.ts';
import injectRSCPayload from '../../packages/react-on-rails/src/pro/injectRSCPayload.ts';
import RSCRequestTracker from '../../packages/react-on-rails/src/pro/RSCRequestTracker.ts';
// node_package/tests/injectRSCPayload.test.ts
-import { RailsContextWithServerStreamingCapabilities } from '../../packages/react-on-rails/src/types/index.ts';
-import injectRSCPayload from '../../packages/react-on-rails/src/pro/injectRSCPayload.ts';
import { RailsContextWithServerStreamingCapabilities } from 'react-on-rails/src/types/index.ts';
import injectRSCPayload from 'react-on-rails/src/pro/injectRSCPayload.ts';
import RSCRequestTracker from 'react-on-rails/src/pro/RSCRequestTracker.ts';
🧰 Tools
πŸͺ› ESLint

[error] 2-2: Relative import from another package is not allowed. Use react-on-rails/src/types/index.ts instead of ../../packages/react-on-rails/src/types/index.ts

(import/no-relative-packages)


[error] 3-3: Relative import from another package is not allowed. Use react-on-rails/src/pro/injectRSCPayload.ts instead of ../../packages/react-on-rails/src/pro/injectRSCPayload.ts

(import/no-relative-packages)


[error] 4-4: Relative import from another package is not allowed. Use react-on-rails/src/pro/RSCRequestTracker.ts instead of ../../packages/react-on-rails/src/pro/RSCRequestTracker.ts

(import/no-relative-packages)

πŸ€– Prompt for AI Agents
In node_package/tests/injectRSCPayload.test.ts lines 2-4, the test currently
imports three modules via cross-package relative paths which violate the lint
rule; replace the three relative imports with the package's published workspace
alias (the react-on-rails package entry points) so the imports read from the
package name (e.g., react-on-rails or its scoped workspace name) instead of
'../../packages/react-on-rails/src/...', updating all three imports to use the
package alias.


// Shared utilities
const createMockStream = (chunks: (string | Buffer)[] | { [key: number]: string | string[] }) => {
Expand Down
6 changes: 3 additions & 3 deletions node_package/tests/jest.setup.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,11 @@ if (typeof window !== 'undefined') {
// Node's fetch and polyfills like jest-fetch-mock return Node's Readable stream,
// so we convert it to a web-standard ReadableStream for consistency
// Note: Node's Readable stream exists in node 'stream' built-in module, can be imported as `import { Readable } from 'stream'`
jest.mock('../src/utils', () => ({
...jest.requireActual('../src/utils'),
jest.mock('../../packages/react-on-rails/src/utils', () => ({
...jest.requireActual('../../packages/react-on-rails/src/utils'),
fetch: (...args) =>
jest
.requireActual('../src/utils')
.requireActual('../../packages/react-on-rails/src/utils')
.fetch(...args)
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Align jest utils mock with package alias

The mock/require paths still use the forbidden ../../packages/... form, so ESLint will fail. Update them as follows:

-jest.mock('../../packages/react-on-rails/src/utils', () => ({
-  ...jest.requireActual('../../packages/react-on-rails/src/utils'),
+jest.mock('react-on-rails/src/utils', () => ({
+  ...jest.requireActual('react-on-rails/src/utils'),
   fetch: (...args) =>
-    jest
-      .requireActual('../../packages/react-on-rails/src/utils')
+    jest
+      .requireActual('react-on-rails/src/utils')
       .fetch(...args)

Apply the same alias elsewhere if needed so lint passes.

πŸ“ 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
jest.mock('../../packages/react-on-rails/src/utils', () => ({
...jest.requireActual('../../packages/react-on-rails/src/utils'),
fetch: (...args) =>
jest
.requireActual('../src/utils')
.requireActual('../../packages/react-on-rails/src/utils')
.fetch(...args)
jest.mock('react-on-rails/src/utils', () => ({
...jest.requireActual('react-on-rails/src/utils'),
fetch: (...args) =>
jest
.requireActual('react-on-rails/src/utils')
.fetch(...args)
πŸ€– Prompt for AI Agents
In node_package/tests/jest.setup.js around lines 26-31, the jest.mock and
jest.requireActual calls use forbidden relative paths like
'../../packages/react-on-rails/src/utils'; update those paths to use the
repository's configured package alias (the package import name used in
tsconfig/webpack/jest moduleNameMapper, e.g. 'react-on-rails/src/utils' or the
exact alias your project uses) for both jest.mock and jest.requireActual calls,
and scan other test files for any remaining '../../packages/...' usages and
replace them with the same alias so ESLint passes.

.then((res) => {
const originalBody = res.body;
Expand Down
16 changes: 8 additions & 8 deletions node_package/tests/pageLifecycle.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
*/

// Mock the turbolinksUtils module before importing pageLifecycle
jest.mock('../src/turbolinksUtils.ts', () => ({
jest.mock('../../packages/react-on-rails/src/turbolinksUtils.ts', () => ({
debugTurbolinks: jest.fn(),
turbolinksInstalled: jest.fn(() => false),
turbolinksSupported: jest.fn(() => false),
Expand All @@ -29,7 +29,7 @@ describe('pageLifecycle', () => {
// We use require here instead of a global import at the top because we need to dynamically reload the module in each test.
// This allows us to reset the module state between tests using jest.resetModules(), ensuring test isolation and preventing state leakage.
// eslint-disable-next-line global-require
const importPageLifecycle = () => require('../src/pageLifecycle.ts');
const importPageLifecycle = () => require('../../packages/react-on-rails/src/pageLifecycle.ts');

// Helper function to create navigation library mock
const createNavigationMock = (overrides = {}) => ({
Expand Down Expand Up @@ -109,15 +109,15 @@ describe('pageLifecycle', () => {

describe('with Turbo navigation library', () => {
beforeEach(() => {
jest.doMock('../src/turbolinksUtils.ts', () =>
jest.doMock('../../packages/react-on-rails/src/turbolinksUtils.ts', () =>
createNavigationMock({
turboInstalled: jest.fn(() => true),
}),
);
});

afterEach(() => {
jest.dontMock('../src/turbolinksUtils.ts');
jest.dontMock('../../packages/react-on-rails/src/turbolinksUtils.ts');
});

it('should set up Turbo event listeners when Turbo is installed', () => {
Expand All @@ -137,7 +137,7 @@ describe('pageLifecycle', () => {

describe('with Turbolinks 5 navigation library', () => {
beforeEach(() => {
jest.doMock('../src/turbolinksUtils.ts', () =>
jest.doMock('../../packages/react-on-rails/src/turbolinksUtils.ts', () =>
createNavigationMock({
turbolinksInstalled: jest.fn(() => true),
turbolinksSupported: jest.fn(() => true),
Expand All @@ -147,7 +147,7 @@ describe('pageLifecycle', () => {
});

afterEach(() => {
jest.dontMock('../src/turbolinksUtils.ts');
jest.dontMock('../../packages/react-on-rails/src/turbolinksUtils.ts');
});

it('should set up Turbolinks 5 event listeners when Turbolinks 5 is installed', () => {
Expand All @@ -167,7 +167,7 @@ describe('pageLifecycle', () => {

describe('with Turbolinks 2 navigation library', () => {
beforeEach(() => {
jest.doMock('../src/turbolinksUtils.ts', () =>
jest.doMock('../../packages/react-on-rails/src/turbolinksUtils.ts', () =>
createNavigationMock({
turbolinksInstalled: jest.fn(() => true),
turbolinksSupported: jest.fn(() => true),
Expand All @@ -176,7 +176,7 @@ describe('pageLifecycle', () => {
});

afterEach(() => {
jest.dontMock('../src/turbolinksUtils.ts');
jest.dontMock('../../packages/react-on-rails/src/turbolinksUtils.ts');
});

it('should set up Turbolinks 2 event listeners when Turbolinks 2 is installed', () => {
Expand Down
8 changes: 4 additions & 4 deletions node_package/tests/registerServerComponent.client.test.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@ import '@testing-library/jest-dom';
import * as path from 'path';
import * as fs from 'fs';
import { createNodeReadableStream, getNodeVersion } from './testUtils.js';
import ReactOnRails from '../src/ReactOnRails.client.ts';
import registerServerComponent from '../src/pro/registerServerComponent/client.tsx';
import { clear as clearComponentRegistry } from '../src/pro/ComponentRegistry.ts';
import ReactOnRails from '../../packages/react-on-rails/src/ReactOnRails.client.ts';
import registerServerComponent from '../../packages/react-on-rails/src/pro/registerServerComponent/client.tsx';
import { clear as clearComponentRegistry } from '../../packages/react-on-rails/src/pro/ComponentRegistry.ts';

enableFetchMocks();

Expand Down Expand Up @@ -44,7 +44,7 @@ enableFetchMocks();

expect(() => {
// Re-import to trigger the check
jest.requireActual('../src/pro/wrapServerComponentRenderer/client.tsx');
jest.requireActual('../../packages/react-on-rails/src/pro/wrapServerComponentRenderer/client.tsx');
}).toThrow('React.use is not defined');
});

Expand Down
2 changes: 1 addition & 1 deletion node_package/tests/renderFunction.test.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import * as React from 'react';
import * as createReactClass from 'create-react-class';

import isRenderFunction from '../src/isRenderFunction.ts';
import isRenderFunction from '../../packages/react-on-rails/src/isRenderFunction.ts';
Copy link
Contributor

Choose a reason for hiding this comment

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

πŸ› οΈ Refactor suggestion | 🟠 Major

🧩 Analysis chain

Fix ESLint error: disallowed relative import from another package.

Use the package import.

Apply:

-import isRenderFunction from '../../packages/react-on-rails/src/isRenderFunction.ts';
+import isRenderFunction from 'react-on-rails/src/isRenderFunction.ts';

🏁 Script executed:

#!/bin/bash
set -e
# Locate package.json for react-on-rails
react_pkg=$(find packages -type f -path "*/react-on-rails/package.json" | head -n1)
echo "Found package.json at $react_pkg"
# Extract the package name
pkg_name=$(sed -n 's/.*"name"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/p' "$react_pkg")
echo "Package name: $pkg_name"

Length of output: 87


🏁 Script executed:

#!/bin/bash
set -e
echo "=== package.json exports field ==="
rg -C3 '"exports"' packages/react-on-rails/package.json || echo "No exports field found"

echo -e "\n=== Preview of isRenderFunction.ts ==="
sed -n '1,50p' packages/react-on-rails/src/isRenderFunction.ts

echo -e "\n=== Check index.ts for isRenderFunction export ==="
rg -nP '\bexport\s+{[^}]*\bisRenderFunction\b' -g '*.ts' packages/react-on-rails/src/index.ts || echo "isRenderFunction not exported from index.ts"

Length of output: 1579


Re-export isRenderFunction in react-on-rails and update import

  • In packages/react-on-rails/src/index.ts, add:
    export { default as isRenderFunction } from './isRenderFunction';
  • In node_package/tests/renderFunction.test.jsx, replace the relative import with:
    import { isRenderFunction } from 'react-on-rails';
🧰 Tools
πŸͺ› ESLint

[error] 8-8: Relative import from another package is not allowed. Use react-on-rails/src/isRenderFunction.ts instead of ../../packages/react-on-rails/src/isRenderFunction.ts

(import/no-relative-packages)

πŸ€– Prompt for AI Agents
In node_package/tests/renderFunction.test.jsx around line 8, the test imports
isRenderFunction via a relative path; re-export isRenderFunction from
packages/react-on-rails/src/index.ts and then update this test to import it from
the package entry. Specifically, in packages/react-on-rails/src/index.ts add an
export statement re-exporting the default from isRenderFunction, and in
node_package/tests/renderFunction.test.jsx replace the relative import with a
named import from 'react-on-rails' (import { isRenderFunction } from
'react-on-rails';) so the test consumes the re-exported symbol.


describe('isRenderFunction', () => {
it('returns false for a ES5 React Component', () => {
Expand Down
2 changes: 1 addition & 1 deletion node_package/tests/scriptSanitizedVal.test.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import scriptSanitizedVal from '../src/scriptSanitizedVal.ts';
import scriptSanitizedVal from '../../packages/react-on-rails/src/scriptSanitizedVal.ts';

describe('scriptSanitizedVal', () => {
it('returns no </script if spaces, uppercase 1', () => {
Expand Down
6 changes: 3 additions & 3 deletions node_package/tests/serverRenderReactComponent.test.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import * as React from 'react';
import serverRenderReactComponent from '../src/serverRenderReactComponent.ts';
import * as ComponentRegistry from '../src/pro/ComponentRegistry.ts';
import serverRenderReactComponent from '../../packages/react-on-rails/src/serverRenderReactComponent.ts';
import * as ComponentRegistry from '../../packages/react-on-rails/src/pro/ComponentRegistry.ts';
Copy link
Contributor

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

Fix ESLint errors: disallowed relative imports from another package.

Replace with workspace package imports.

Apply:

-import serverRenderReactComponent from '../../packages/react-on-rails/src/serverRenderReactComponent.ts';
-import * as ComponentRegistry from '../../packages/react-on-rails/src/pro/ComponentRegistry.ts';
+import serverRenderReactComponent from 'react-on-rails/src/serverRenderReactComponent.ts';
+import * as ComponentRegistry from 'react-on-rails/src/pro/ComponentRegistry.ts';
@@
-} from '../../packages/react-on-rails/src/types/index.ts';
+} from 'react-on-rails/src/types/index.ts';

If deep imports are restricted via package.exports, add a Jest alias mapping for react-on-rails/src/* to packages/react-on-rails/src/*.

Also applies to: 10-10


🏁 Script executed:

#!/bin/bash
set -e

echo "===== Root package.json workspaces and name ====="
jq '{ name, workspaces }' package.json || cat package.json

echo "===== packages/react-on-rails package.json ====="
jq '{ name, version, exports }' packages/react-on-rails/package.json || cat packages/react-on-rails/package.json

echo "===== node_package/package.json ====="
jq '{ name, dependencies, devDependencies, jest }' node_package/package.json || cat node_package/package.json

echo "===== Jest config in node_package ====="
for f in node_package/jest.config.js node_package/jest.config.ts; do
  if [ -f "$f" ]; then
    echo "===== $f ====="
    sed -n '1,200p' "$f"
  fi
done

echo "===== Root ESLint config files ====="
ls -1 .eslintrc* 2>/dev/null || echo "No ESLint config files"
for f in .eslintrc.js .eslintrc.json .eslintrc.yaml; do
  if [ -f "$f" ]; then
    echo "===== $f ====="
    sed -n '1,200p' "$f"
  fi
done

echo "===== import/no-internal-modules rule ====="
rg -n "import/no-internal-modules" -g ".eslintrc*"

echo "===== no-restricted-imports rule ====="
rg -n "no-restricted-imports" -g ".eslintrc*"

echo "===== Deep relative imports in tests ====="
rg -n "import .* from '\.\./\.\./packages'" -g "node_package/tests/**/*.ts"

echo "===== serverRenderReactComponent.test.ts imports ====="
sed -n '1,15p' node_package/tests/serverRenderReactComponent.test.ts

Length of output: 1608


🏁 Script executed:

#!/bin/bash
# Do not exit on error
echo "===== [1] Root package.json: scripts & jest ====="
jq '{ scripts, jest }' package.json || true

echo "===== [2] Finding jest.config files ====="
find . -maxdepth 3 -type f \( -name "jest.config.js" -o -name "jest.config.ts" \) || echo "none"

echo "===== [3] Inspecting jest configs for moduleNameMapper ====="
grep -R "moduleNameMapper" -n . || echo "none"

echo "===== [4] Listing node_package directory contents ====="
if [ -d "node_package" ]; then
  find node_package -maxdepth 2 -type f
else
  echo "node_package directory not found"
fi

echo "===== [5] Previewing serverRenderReactComponent test file ====="
if [ -f "node_package/tests/serverRenderReactComponent.test.ts" ]; then
  sed -n '1,20p' node_package/tests/serverRenderReactComponent.test.ts
else
  echo "Test file not found at node_package/tests/serverRenderReactComponent.test.ts"
fi

echo "===== [6] ESLint config files ====="
find . -maxdepth 4 -type f -name ".eslintrc*" || echo "none"

echo "===== [7] ESLint rules import/no-internal-modules & no-restricted-imports ====="
grep -R "import/no-internal-modules" -n . || echo "none"
grep -R "no-restricted-imports" -n . || echo "none"

Length of output: 18925


🏁 Script executed:

#!/bin/bash
set -e

echo "===== [1] ESLint config (react_on_rails_pro/eslint.config.mjs 150-230) ====="
sed -n '150,230p' react_on_rails_pro/eslint.config.mjs || echo "react_on_rails_pro/eslint.config.mjs not found"

echo "===== [2] Jest config (jest.config.js 1-100) ====="
sed -n '1,100p' jest.config.js || echo "jest.config.js not found"

Length of output: 2585


Replace deep relative imports in tests and update Jest config

  • In node_package/tests/**/*.test.ts, change all imports from ../../packages/react-on-rails/src/... to react-on-rails/src/... (apply original diff).
  • In jest.config.js’s moduleNameMapper, add:
    '^react-on-rails/src/(.*)$': '<rootDir>/packages/react-on-rails/src/$1'
    so deep imports resolve despite package.exports.
🧰 Tools
πŸͺ› ESLint

[error] 2-2: Relative import from another package is not allowed. Use react-on-rails/src/serverRenderReactComponent.ts instead of ../../packages/react-on-rails/src/serverRenderReactComponent.ts

(import/no-relative-packages)


[error] 3-3: Relative import from another package is not allowed. Use react-on-rails/src/pro/ComponentRegistry.ts instead of ../../packages/react-on-rails/src/pro/ComponentRegistry.ts

(import/no-relative-packages)

πŸ€– Prompt for AI Agents
In node_package/tests/serverRenderReactComponent.test.ts around lines 2 to 3 and
all files under node_package/tests/**/*.test.ts, replace deep relative imports
like '../../packages/react-on-rails/src/...' with 'react-on-rails/src/...' so
tests import via the package name; then update the project's jest.config.js
moduleNameMapper to add the mapping '^react-on-rails/src/(.*)$':
'<rootDir>/packages/react-on-rails/src/$1' so those deep imports resolve at test
time despite package.exports.

import type {
RenderParams,
RenderResult,
RailsContext,
RenderFunction,
RenderFunctionResult,
} from '../src/types/index.ts';
} from '../../packages/react-on-rails/src/types/index.ts';

const assertIsString: (value: unknown) => asserts value is string = (value: unknown) => {
if (typeof value !== 'string') {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@

import * as React from 'react';
import * as PropTypes from 'prop-types';
import streamServerRenderedReactComponent from '../src/pro/streamServerRenderedReactComponent.ts';
import * as ComponentRegistry from '../src/pro/ComponentRegistry.ts';
import ReactOnRails from '../src/ReactOnRails.node.ts';
import streamServerRenderedReactComponent from '../../packages/react-on-rails/src/pro/streamServerRenderedReactComponent.ts';
import * as ComponentRegistry from '../../packages/react-on-rails/src/pro/ComponentRegistry.ts';
import ReactOnRails from '../../packages/react-on-rails/src/ReactOnRails.node.ts';
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Adopt workspace alias for streaming component imports

These relative imports still violate import/no-relative-packages. Please point them at the workspace package:

-import streamServerRenderedReactComponent from '../../packages/react-on-rails/src/pro/streamServerRenderedReactComponent.ts';
-import * as ComponentRegistry from '../../packages/react-on-rails/src/pro/ComponentRegistry.ts';
-import ReactOnRails from '../../packages/react-on-rails/src/ReactOnRails.node.ts';
+import streamServerRenderedReactComponent from 'react-on-rails/src/pro/streamServerRenderedReactComponent.ts';
+import * as ComponentRegistry from 'react-on-rails/src/pro/ComponentRegistry.ts';
+import ReactOnRails from 'react-on-rails/src/ReactOnRails.node.ts';

This resolves the lint errors blocking the PR.

πŸ“ 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
import streamServerRenderedReactComponent from '../../packages/react-on-rails/src/pro/streamServerRenderedReactComponent.ts';
import * as ComponentRegistry from '../../packages/react-on-rails/src/pro/ComponentRegistry.ts';
import ReactOnRails from '../../packages/react-on-rails/src/ReactOnRails.node.ts';
import streamServerRenderedReactComponent from 'react-on-rails/src/pro/streamServerRenderedReactComponent.ts';
import * as ComponentRegistry from 'react-on-rails/src/pro/ComponentRegistry.ts';
import ReactOnRails from 'react-on-rails/src/ReactOnRails.node.ts';
🧰 Tools
πŸͺ› ESLint

[error] 7-7: Relative import from another package is not allowed. Use react-on-rails/src/pro/streamServerRenderedReactComponent.ts instead of ../../packages/react-on-rails/src/pro/streamServerRenderedReactComponent.ts

(import/no-relative-packages)


[error] 8-8: Relative import from another package is not allowed. Use react-on-rails/src/pro/ComponentRegistry.ts instead of ../../packages/react-on-rails/src/pro/ComponentRegistry.ts

(import/no-relative-packages)


[error] 9-9: Relative import from another package is not allowed. Use react-on-rails/src/ReactOnRails.node.ts instead of ../../packages/react-on-rails/src/ReactOnRails.node.ts

(import/no-relative-packages)

πŸ€– Prompt for AI Agents
In node_package/tests/streamServerRenderedReactComponent.test.jsx around lines
7-9, the test imports use relative paths into packages which triggers
import/no-relative-packages; update each import to reference the workspace
package entrypoint instead (use the package name defined in that package's
package.json), e.g. replace the three relative imports with imports from the
workspace package name (pointing to the pro entry points exported by the
package) so tests import via the package alias rather than ../../packages/...,
and save the file.


const AsyncContent = async ({ throwAsyncError }) => {
await new Promise((resolve) => {
Expand Down
2 changes: 1 addition & 1 deletion node_package/tests/utils.test.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { enableFetchMocks } from 'jest-fetch-mock';

import { fetch } from '../src/utils.ts';
import { fetch } from '../../packages/react-on-rails/src/utils.ts';
import { createNodeReadableStream, getNodeVersion } from './testUtils.js';

enableFetchMocks();
Expand Down
Loading
Loading