Skip to content

chore: migrated to package manager to pnpm #204

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 25 commits into
base: main
Choose a base branch
from

Conversation

dougg0k
Copy link
Contributor

@dougg0k dougg0k commented Jul 25, 2025

Before I had trouble using npm i in the root, ferric-cli were not running, it wasnt finding the js.

Even if it were recognized in the package-lock as workspace installed.

It only worked after I did a pnpm i straight in the ferric folder, then I was able to run the command standalone. That's the experience I had.

This led to this PR. Which in fact work now just after a pnpm install in the root folder.

pnpm are faster, in my experience, there is no reason to not migrate to it, even more if from npm.

https://pnpm.io/pnpm-vs-npm

https://refine.dev/blog/pnpm-vs-npm-and-yarn/ - Faster CI installs and more

Copy link

changeset-bot bot commented Jul 25, 2025

🦋 Changeset detected

Latest commit: 51df6e3

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 5 packages
Name Type
@react-native-node-api/ferric-example Patch
cmake-rn Patch
ferric-cli Patch
@react-native-node-api/test-app Patch
react-native-node-api Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@dougg0k
Copy link
Contributor Author

dougg0k commented Jul 25, 2025

This is even showing errors that does not show with npm.

❯ pnpm bootstrap                                                                                                                                                                                                                                                                                                                                                                     23:42:00

> @react-native-node-api/root@ bootstrap /react-native-node-api
> pnpm build && pnpm bootstrap --workspaces --if-present


> @react-native-node-api/root@ build /react-native-node-api
> tsc --build

packages/host/src/node/babel-plugin/plugin.ts:43:5 - error TS2769: No overload matches this call.
  Overload 1 of 2, '(replacementPath: Node | NodePath<Node>): [NodePath<Node>]', gave the following error.
    Argument of type 'CallExpression' is not assignable to parameter of type 'Node | NodePath<Node>'.
      Type 'import("/react-native-node-api/node_modules/.pnpm/@[email protected]/node_modules/@babel/types/lib/index").CallExpression' is not assignable to type 'babel.types.CallExpression'.
        Types of property 'callee' are incompatible.
          Type 'Expression | V8IntrinsicIdentifier' is not assignable to type 'V8IntrinsicIdentifier | Expression'.
            Type 'ArrayExpression' is not assignable to type 'V8IntrinsicIdentifier | Expression'.
              Type 'import("/react-native-node-api/node_modules/.pnpm/@[email protected]/node_modules/@babel/types/lib/index").ArrayExpression' is not assignable to type 'babel.types.ArrayExpression'.
                Types of property 'elements' are incompatible.
                  Type '(Expression | SpreadElement | null)[]' is not assignable to type '(SpreadElement | Expression | null)[]'.
                    Type 'Expression | SpreadElement | null' is not assignable to type 'SpreadElement | Expression | null'.
                      Type 'ArrayExpression' is not assignable to type 'SpreadElement | Expression | null'.
  Overload 2 of 2, '(replacementPath: NodePath<Node>): [NodePath<Node>]', gave the following error.
    Argument of type 'CallExpression' is not assignable to parameter of type 'NodePath<Node>'.
      Type 'CallExpression' is missing the following properties from type 'NodePath<Node>': parent, hub, data, context, and 721 more.

 43     t.callExpression(
        ~~~~~~~~~~~~~~~~~
 44       t.memberExpression(
    ~~~~~~~~~~~~~~~~~~~~~~~~~
...
 50       [t.stringLiteral(requireCallArgument)]
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 51     )
    ~~~~~



Found 1 error.
❯ npm run bootstrap

> bootstrap
> npm run build && npm run bootstrap --workspaces --if-present


> build
> tsc --build


> [email protected] bootstrap
> npm run copy-node-api-headers && npm run generate-weak-node-api-injector && npm run generate-weak-node-api && npm run build-weak-node-api

@shirakaba
Copy link
Collaborator

Before I had trouble using npm i, even if it were recognized in the package-lock as some package as installed, when running commands in a folder, it would not work, unless I specifically ran install (non-npm).

I didn't experience that when I cloned and installed the repo. Would it help if we just regenerated the package-lock.json?

What version of npm are you using? I'm using 10.9.2.

@dougg0k
Copy link
Contributor Author

dougg0k commented Jul 25, 2025

Already did.

Same version.


With pnpm another issue appeared through the CI, and were not showing before with npm.

Clearly pnpm are working properly where npm was not.


> pnpm --recursive --if-present build

Scope: 7 of 8 workspace projects
packages/gyp-to-cmake build$ tsc
packages/host build$ tsc --build
packages/node-addon-examples build$ tsx scripts/build-examples.mts
packages/node-addon-examples build: node:fs:1583
packages/node-addon-examples build:   const result = binding.readdir(
packages/node-addon-examples build:                          ^
packages/node-addon-examples build: Error: ENOENT: no such file or directory, scandir '/home/runner/work/react-native-node-api/react-native-node-api/packages/node-addon-examples/examples'
packages/node-addon-examples build:     at readdirSync (node:fs:1583:26)
packages/node-addon-examples build:     at findCMakeProjectsRecursively (/home/runner/work/react-native-node-api/react-native-node-api/packages/node-addon-examples/scripts/cmake-projects.mts:10:17)
packages/node-addon-examples build:     at Array.flatMap (<anonymous>)
packages/node-addon-examples build:     at findCMakeProjects (/home/runner/work/react-native-node-api/react-native-node-api/packages/node-addon-examples/scripts/cmake-projects.mts:25:15)
packages/node-addon-examples build:     at <anonymous> (/home/runner/work/react-native-node-api/react-native-node-api/packages/node-addon-examples/scripts/build-examples.mts:5:28)
packages/node-addon-examples build:     at ModuleJob.run (node:internal/modules/esm/module_job:329:25)
packages/node-addon-examples build:     at async onImport.tracePromise.__proto__ (node:internal/modules/esm/loader:644:26)
packages/node-addon-examples build:     at async asyncRunEntryPointWithESMLoader (node:internal/modules/run_main:117:5) {
packages/node-addon-examples build:   errno: -2,
packages/node-addon-examples build:   code: 'ENOENT',
packages/node-addon-examples build:   syscall: 'scandir',
packages/node-addon-examples build:   path: '/home/runner/work/react-native-node-api/react-native-node-api/packages/node-addon-examples/examples'
packages/node-addon-examples build: }
packages/node-addon-examples build: Node.js v22.17.1
packages/node-addon-examples build: Failed
/home/runner/work/react-native-node-api/react-native-node-api/packages/node-addon-examples:
 ERR_PNPM_RECURSIVE_RUN_FIRST_FAIL  @react-native-node-api/node-addon-examples@ build: `tsx scripts/build-examples.mts`
Exit status 1

@dougg0k
Copy link
Contributor Author

dougg0k commented Jul 25, 2025

And more.

ackages/node-addon-examples test: node:internal/fs/promises:955
packages/node-addon-examples test:   const result = await PromisePrototypeThen(
packages/node-addon-examples test:                  ^
packages/node-addon-examples test: Error: ENOENT: no such file or directory, scandir '/home/runner/work/react-native-node-api/react-native-node-api/packages/node-addon-examples/examples/5-async-work/async_work_thread_safe_function/napi/build/Release/binding.android.node/armeabi-v7a'
packages/node-addon-examples test:     at async Object.readdir (node:internal/fs/promises:955:18)
packages/node-addon-examples test:     at async verifyAndroidPrebuild (/home/runner/work/react-native-node-api/react-native-node-api/packages/node-addon-examples/scripts/verify-prebuilds.mts:28:24)
packages/node-addon-examples test:     at async <anonymous> (/home/runner/work/react-native-node-api/react-native-node-api/packages/node-addon-examples/scripts/verify-prebuilds.mts:90:5) {
packages/node-addon-examples test: node:internal/fs/promises:955
packages/node-addon-examples test:   const result = await PromisePrototypeThen(
packages/node-addon-examples test:                  ^
packages/node-addon-examples test: Error: ENOENT: no such file or directory, scandir '/Users/runner/work/react-native-node-api/react-native-node-api/packages/node-addon-examples/examples/5-async-work/async_work_thread_safe_function/napi/build/Release/binding.apple.node/ios-arm64'
packages/node-addon-examples test:     at async Object.readdir (node:internal/fs/promises:955:18)
packages/node-addon-examples test:     at async verifyApplePrebuild (/Users/runner/work/react-native-node-api/react-native-node-api/packages/node-addon-examples/scripts/verify-prebuilds.mts:47:24)
packages/node-addon-examples test:     at async <anonymous> (/Users/runner/work/react-native-node-api/react-native-node-api/packages/node-addon-examples/scripts/verify-prebuilds.mts:95:5) {

@dougg0k
Copy link
Contributor Author

dougg0k commented Jul 25, 2025

Can you review? In some fixes, you should consider the comments I made. It's related.

@dougg0k dougg0k mentioned this pull request Jul 25, 2025
2 tasks
@@ -88,6 +88,7 @@
"devDependencies": {
"@babel/core": "^7.26.10",
"@babel/types": "^7.27.0",
"@types/babel__core": "^7.20.5",
Copy link
Collaborator

Choose a reason for hiding this comment

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

What was this fixing?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Comment on lines +10 to +12
if (!existsSync(dir)) {
return results;
}
Copy link
Collaborator

Choose a reason for hiding this comment

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

This breaks an invariant and shouldn't fail silently.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Copy link
Contributor Author

Choose a reason for hiding this comment

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

What would you prefer to be done?

Comment on lines +28 to +30
if (!fs.existsSync(archDir)) {
return;
}
Copy link
Collaborator

Choose a reason for hiding this comment

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

This breaks an invariant and shouldn't fail silently.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Copy link
Contributor Author

Choose a reason for hiding this comment

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

What would you prefer to be done?

Comment on lines +47 to +49
if (!fs.existsSync(archDir)) {
return;
}
Copy link
Collaborator

Choose a reason for hiding this comment

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

This breaks an invariant and shouldn't fail silently.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Copy link
Contributor Author

Choose a reason for hiding this comment

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

What would you prefer to be done?

@kraenhansen
Copy link
Collaborator

I would like for you to create an issue for the NPM issue which prompted you to want to migrate to PNPM in the first place, I'm fairly certain we could fix that without migrating package manager.

Some of the issues you're seeing might come from:

  • the "build" scripts aren't designed to be ran in sequence across all workspaces, as some build native addon code while others build TS locally for that package. Right now, we use the "bootstrap" script as the script a package implements to prepare for development.
  • NPM runs scripts in order of entry in the workspaces array of the package.json, whereas PNPM runs them in topological order - and the scripts aren't necessarily designed for that.

@dougg0k
Copy link
Contributor Author

dougg0k commented Jul 25, 2025

https://pnpm.io/cli/recursive#--no-sort


Weird that you do not prefer better tooling.

As one can easily replace one for another, if ever needed.

I gave the reasons in the PR.

Not looking to resolve the issues in the current, but actual improve while resolving some that I mentioned.

pnpm are clearly more functional than npm.

@dougg0k dougg0k mentioned this pull request Jul 26, 2025
@kraenhansen
Copy link
Collaborator

Weird that you do not prefer better tooling.

Not weird at all - we're the ones maintaining this package in the long run and choosing technology / tools aren't soly about choosing the seemingly superior solution in my experience. To be clear, I'm not saying that NPM is flawless nor that we won't make a switch to a different package manager and I'm not looking to get more into that conversation right now.

I gave the reasons in the PR.

I disagree, as I'm unable to reproduce the issue: You're not providing specific commands and outputs from running those and therefore I'm unable to get a strong signal, giving me a compelling reason to accept your suggested change.

@dougg0k
Copy link
Contributor Author

dougg0k commented Jul 26, 2025

Of course.

I did provide, there should be plenty of commands explaining in the first post and then in the ones that was triggered in the CI.


I meant weird in a sense where it's a just a simple tool that seem to be doing a bit more than the current. As any can be easily replaced by another. Also in a sense where it's not a life decision where it could lead you to a path or another, due to having made the decision of changing a tool.

@dougg0k
Copy link
Contributor Author

dougg0k commented Jul 26, 2025

I added the --no-sort to the --recursive.

Now it should be the same.


I answered your reviews done in here.


I have updated the first description post, it should be more clear.

In my experience, pnpm (or yarn if not possible) and biome are minimum in a project.


If after all the information provided, it's stil not enough, it's a waste, but feel free to close the PR.

@dougg0k
Copy link
Contributor Author

dougg0k commented Jul 26, 2025

Another issue appeared here. Build from ferric were not being generated. I then removed node_modules and package-lock.json and reinstalled with npm.

But now the error are this one. And nothing to fix.

...
> cmake-rn --no-auto-link --no-weak-node-api-linkage --xcframework-extension --source ./weak-node-api --out ./weak-node-api

node:internal/modules/package_json_reader:256
  throw new ERR_MODULE_NOT_FOUND(packageName, fileURLToPath(base), null);
        ^

Error [ERR_MODULE_NOT_FOUND]: Cannot find package 'stdin-discarder' imported from /react-native-node-api/packages/cmake-rn/node_modules/ora/index.js
    at Object.getPackageJSONURL (node:internal/modules/package_json_reader:256:9)
    at packageResolve (node:internal/modules/esm/resolve:768:81)
    at moduleResolve (node:internal/modules/esm/resolve:854:18)
    at defaultResolve (node:internal/modules/esm/resolve:984:11)
    at ModuleLoader.defaultResolve (node:internal/modules/esm/loader:780:12)
    at #cachedDefaultResolve (node:internal/modules/esm/loader:704:25)
    at ModuleLoader.resolve (node:internal/modules/esm/loader:687:38)
    at ModuleLoader.getModuleJobForImport (node:internal/modules/esm/loader:305:38)
    at ModuleJob._link (node:internal/modules/esm/module_job:175:49) {
  code: 'ERR_MODULE_NOT_FOUND'
}
❯ npm i                                                                                                                                                                                                                                                                                                                                                                              

up to date, audited 1089 packages in 1s

162 packages are looking for funding
  run `npm fund` for details

found 0 vulnerabilities

Then again, I installed with pnpm.

It found the errors I mentioned in this PR with babel, where before with npm they dont even appear.

❯ pnpm bootstrap                                                                                                                                                                                                                                                                                                                                                                     

> @react-native-node-api/root@ bootstrap /react-native-node-api
> npm run build && npm run bootstrap --workspaces --if-present


> build
> tsc --build

packages/host/src/node/babel-plugin/plugin.ts:4:42 - error TS7016: Could not find a declaration file for module '@babel/core'. '/react-native-node-api/node_modules/.pnpm/@[email protected]/node_modules/@babel/core/lib/index.js' implicitly has an 'any' type.
  Try `npm i --save-dev @types/babel__core` if it exists or add a new declaration (.d.ts) file containing `declare module '@babel/core';`

4 import type { PluginObj, NodePath } from "@babel/core";
                                           ~~~~~~~~~~~~~

packages/host/src/node/babel-plugin/plugin.ts:58:22 - error TS7006: Parameter 'p' implicitly has an 'any' type.

58       CallExpression(p) {
                        ~

packages/host/src/node/babel-plugin/plugin.ts:59:28 - error TS2339: Property 'opts' does not exist on type '{ CallExpression(p: any): void; }'.

59         assertOptions(this.opts);
                              ~~~~

packages/host/src/node/babel-plugin/plugin.ts:60:47 - error TS2339: Property 'opts' does not exist on type '{ CallExpression(p: any): void; }'.

60         const { pathSuffix = "strip" } = this.opts;
                                                 ~~~~

packages/host/src/node/babel-plugin/plugin.ts:61:25 - error TS2339: Property 'filename' does not exist on type '{ CallExpression(p: any): void; }'.

61         if (typeof this.filename !== "string") {
                           ~~~~~~~~

packages/host/src/node/babel-plugin/plugin.ts:65:40 - error TS2339: Property 'filename' does not exist on type '{ CallExpression(p: any): void; }'.

65         const from = path.dirname(this.filename);
                                          ~~~~~~~~

packages/host/src/node/babel-plugin/plugin.test.ts:5:35 - error TS7016: Could not find a declaration file for module '@babel/core'. '/react-native-node-api/node_modules/.pnpm/@[email protected]/node_modules/@babel/core/lib/index.js' implicitly has an 'any' type.
  Try `npm i --save-dev @types/babel__core` if it exists or add a new declaration (.d.ts) file containing `declare module '@babel/core';`

5 import { transformFileSync } from "@babel/core";
                                    ~~~~~~~~~~~~~

packages/cmake-rn/src/cli.ts:19:10 - error TS2724: '"react-native-node-api"' has no exported member named 'isSupportedTriplet'. Did you mean 'SupportedTriplet'?

19 import { isSupportedTriplet } from "react-native-node-api";
            ~~~~~~~~~~~~~~~~~~

packages/cmake-rn/src/cli.ts:267:33 - error TS2345: Argument of type 'T' is not assignable to parameter of type '"aarch64-linux-android" | "armv7a-linux-androideabi" | "i686-linux-android" | "x86_64-linux-android" | "arm64;x86_64-apple-darwin" | "x86_64-apple-darwin" | "arm64-apple-darwin" | ... 5 more ... | "arm64-apple-visionos-sim"'.
  Type 'string' is not assignable to type '"aarch64-linux-android" | "armv7a-linux-androideabi" | "i686-linux-android" | "x86_64-linux-android" | "arm64;x86_64-apple-darwin" | "x86_64-apple-darwin" | "arm64-apple-darwin" | ... 5 more ... | "arm64-apple-visionos-sim"'.

267       ? getWeakNodeApiVariables(target)
                                    ~~~~~~

packages/cmake-rn/src/weak-node-api.ts:9:3 - error TS2305: Module '"react-native-node-api"' has no exported member 'weakNodeApiPath'.

9   weakNodeApiPath,
    ~~~~~~~~~~~~~~~

packages/ferric/src/cargo.ts:17:10 - error TS2305: Module '"react-native-node-api"' has no exported member 'weakNodeApiPath'.

17 import { weakNodeApiPath } from "react-native-node-api";
            ~~~~~~~~~~~~~~~


Found 11 errors.

Wow, and the build now works with pnpm.

@shirakaba
Copy link
Collaborator

shirakaba commented Jul 26, 2025

I then removed node_modules and package-lock.json and reinstalled with npm.

❯ npm i

up to date, audited 1089 packages in 1s

162 packages are looking for funding
run npm fund for details

found 0 vulnerabilities

Are you saying that regenerating the lockfile led to npm working for you?

@dougg0k
Copy link
Contributor Author

dougg0k commented Jul 26, 2025

No, with that, it made it worse, it resulted in the error mentioned.

Currently, I am using pnpm as workaround without commiting it, to be able to properly run the project.

@dougg0k dougg0k requested a review from kraenhansen July 28, 2025 15:23
@kraenhansen kraenhansen added Apple 🍎 Anything related to the Apple platform (iOS, macOS, Cocoapods, Xcode, XCFrameworks, etc.) Android 🤖 Anything related to the Android platform (Gradle, NDK, Android SDK) labels Aug 2, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Android 🤖 Anything related to the Android platform (Gradle, NDK, Android SDK) Apple 🍎 Anything related to the Apple platform (iOS, macOS, Cocoapods, Xcode, XCFrameworks, etc.)
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants