From 5b6c8cce0f9ad6f44b03c0979976746db15f75e5 Mon Sep 17 00:00:00 2001 From: Douglas Galdino Date: Thu, 24 Jul 2025 19:11:36 -0300 Subject: [PATCH 1/3] add changes --- apps/test-app/App.tsx | 17 +- apps/test-app/babel.config.js | 4 +- apps/test-app/react-native.config.js | 3 +- biome.json | 38 + eslint.config.js | 49 - package-lock.json | 1047 +++-------------- package.json | 10 +- packages/cmake-rn/src/cli.ts | 71 +- packages/cmake-rn/src/headers.ts | 12 +- packages/cmake-rn/src/platforms.test.ts | 7 +- packages/cmake-rn/src/platforms.ts | 6 +- packages/cmake-rn/src/platforms/android.ts | 33 +- packages/cmake-rn/src/platforms/apple.ts | 28 +- packages/cmake-rn/src/platforms/types.ts | 10 +- packages/cmake-rn/src/run.ts | 1 + packages/cmake-rn/src/weak-node-api.ts | 15 +- packages/ferric/src/banner.ts | 2 +- packages/ferric/src/build.ts | 96 +- packages/ferric/src/cargo.ts | 36 +- packages/ferric/src/errors.ts | 4 +- packages/ferric/src/napi-rs.ts | 8 +- packages/ferric/src/rustup.ts | 6 +- packages/ferric/src/targets.ts | 12 +- packages/gyp-to-cmake/src/cli.ts | 11 +- packages/gyp-to-cmake/src/gyp.test.ts | 4 +- packages/gyp-to-cmake/src/gyp.ts | 14 +- packages/gyp-to-cmake/src/run.ts | 1 + packages/gyp-to-cmake/src/transformer.test.ts | 8 +- packages/gyp-to-cmake/src/transformer.ts | 4 +- .../generate-weak-node-api-injector.ts | 6 +- .../host/scripts/generate-weak-node-api.ts | 6 +- packages/host/scripts/node-api-functions.ts | 22 +- .../host/src/node/babel-plugin/plugin.test.ts | 17 +- packages/host/src/node/babel-plugin/plugin.ts | 18 +- packages/host/src/node/cli/android.ts | 4 +- packages/host/src/node/cli/apple.ts | 31 +- packages/host/src/node/cli/hermes.ts | 22 +- packages/host/src/node/cli/link-modules.ts | 28 +- packages/host/src/node/cli/options.ts | 2 +- packages/host/src/node/cli/program.ts | 47 +- packages/host/src/node/cli/run.ts | 1 + packages/host/src/node/index.ts | 29 +- packages/host/src/node/path-utils.test.ts | 54 +- packages/host/src/node/path-utils.ts | 76 +- packages/host/src/node/prebuilds/android.ts | 7 +- packages/host/src/node/prebuilds/apple.ts | 21 +- packages/host/src/node/prebuilds/triplets.ts | 6 +- packages/host/src/node/test-utils.ts | 6 +- packages/host/src/node/weak-node-api.ts | 2 +- .../scripts/build-examples.mts | 2 +- .../scripts/copy-examples.mts | 8 +- .../scripts/verify-prebuilds.mts | 20 +- packages/node-addon-examples/src/index.ts | 27 +- .../node-addon-examples/tests/async/addon.js | 4 +- .../tests/buffers/addon.js | 7 +- 55 files changed, 667 insertions(+), 1363 deletions(-) create mode 100644 biome.json delete mode 100644 eslint.config.js diff --git a/apps/test-app/App.tsx b/apps/test-app/App.tsx index 27fca38e..497f735b 100644 --- a/apps/test-app/App.tsx +++ b/apps/test-app/App.tsx @@ -1,19 +1,18 @@ -import React from "react"; -import { StyleSheet, View, SafeAreaView } from "react-native"; - +import { suites as nodeAddonExamplesSuites } from "@react-native-node-api/node-addon-examples"; import { - MochaRemoteProvider, ConnectionText, + MochaRemoteProvider, StatusEmoji, StatusText, } from "mocha-remote-react-native"; - -import { suites as nodeAddonExamplesSuites } from "@react-native-node-api/node-addon-examples"; +// biome-ignore lint/correctness/noUnusedImports: Keep React +import React from "react"; +import { SafeAreaView, StyleSheet, View } from "react-native"; function describeIf( condition: boolean, title: string, - fn: (this: Mocha.Suite) => void + fn: (this: Mocha.Suite) => void, ) { return condition ? describe(title, fn) : describe.skip(title, fn); } @@ -31,7 +30,7 @@ function loadTests({ }: Context) { describeIf(nodeAddonExamples, "Node Addon Examples", () => { for (const [suiteName, examples] of Object.entries( - nodeAddonExamplesSuites + nodeAddonExamplesSuites, )) { describe(suiteName, () => { for (const [exampleName, requireExample] of Object.entries(examples)) { @@ -48,7 +47,7 @@ function loadTests({ describeIf(ferricExample, "ferric-example", () => { it("exports a callable sum function", () => { - /* eslint-disable-next-line @typescript-eslint/no-require-imports -- TODO: Determine why a dynamic import doesn't work on Android */ + // TODO: Determine why a dynamic import doesn't work on Android */ const exampleAddon = require("ferric-example"); const result = exampleAddon.sum(1, 3); if (result !== 4) { diff --git a/apps/test-app/babel.config.js b/apps/test-app/babel.config.js index 175e8359..8ea846e2 100644 --- a/apps/test-app/babel.config.js +++ b/apps/test-app/babel.config.js @@ -1,5 +1,5 @@ module.exports = { - presets: ['module:@react-native/babel-preset'], + presets: ["module:@react-native/babel-preset"], // plugins: [['module:react-native-node-api/babel-plugin', { stripPathSuffix: true }]], - plugins: ['module:react-native-node-api/babel-plugin'], + plugins: ["module:react-native-node-api/babel-plugin"], }; diff --git a/apps/test-app/react-native.config.js b/apps/test-app/react-native.config.js index e15e25b5..dab1d107 100644 --- a/apps/test-app/react-native.config.js +++ b/apps/test-app/react-native.config.js @@ -1,4 +1,3 @@ - const project = (() => { try { const { configureProjects } = require("react-native-test-app"); @@ -25,4 +24,4 @@ const project = (() => { module.exports = { ...(project ? { project } : undefined), -}; \ No newline at end of file +}; diff --git a/biome.json b/biome.json new file mode 100644 index 00000000..8e3f3c2c --- /dev/null +++ b/biome.json @@ -0,0 +1,38 @@ +{ + "$schema": "https://biomejs.dev/schemas/2.1.2/schema.json", + "assist": { + "actions": { + "source": { + "organizeImports": "on" + } + }, + "enabled": true + }, + "files": { + "ignoreUnknown": false, + "includes": [ + "**", + "!node_modules", + "!.nx/**", + "!**/dist/**", + "!apps/test-app/ios/**", + "!packages/host/hermes/**", + "!packages/node-addon-examples/examples/**" + ] + }, + "formatter": { + "enabled": true, + "indentStyle": "space" + }, + "linter": { + "enabled": true, + "rules": { + "recommended": true + } + }, + "vcs": { + "clientKind": "git", + "enabled": false, + "useIgnoreFile": false + } +} diff --git a/eslint.config.js b/eslint.config.js deleted file mode 100644 index 360cbeaf..00000000 --- a/eslint.config.js +++ /dev/null @@ -1,49 +0,0 @@ -// @ts-check - -import { globalIgnores } from "eslint/config"; -import globals from "globals"; -import eslint from '@eslint/js'; -import tseslint from 'typescript-eslint'; - -export default tseslint.config( - globalIgnores([".nx/**"]), - globalIgnores(["**/dist/**"]), - globalIgnores(["apps/test-app/ios/**"]), - globalIgnores(["packages/host/hermes/**"]), - globalIgnores(["packages/node-addon-examples/examples/**"]), - globalIgnores(["packages/ferric-example/ferric_example.d.ts"]), - eslint.configs.recommended, - tseslint.configs.recommended, - { - files: [ - "apps/test-app/*.js", - "packages/node-addon-examples/*.js", - "packages/host/babel-plugin.js", - "packages/host/react-native.config.js" - ], - languageOptions: { - parserOptions: { - sourceType: "commonjs", - }, - globals: { - ...globals.commonjs, - }, - }, - rules: { - // We're using CommonJS here for Node.js backwards compatibility - "@typescript-eslint/no-require-imports": "off", - }, - }, - { - files: [ - "packages/gyp-to-cmake/bin/*.js", - "packages/host/bin/*.mjs", - "packages/host/scripts/*.mjs" - ], - languageOptions: { - globals: { - ...globals.node, - }, - }, - }, -); diff --git a/package-lock.json b/package-lock.json index 5758c0f0..b6d07e3c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -16,18 +16,16 @@ "packages/ferric-example" ], "devDependencies": { + "@biomejs/biome": "^2.1.2", "@changesets/cli": "^2.29.5", - "@eslint/js": "^9.19.0", "@reporters/github": "^1.7.2", "@tsconfig/node22": "^22.0.0", "@tsconfig/react-native": "3.0.5", "@types/node": "^22.13.0", - "eslint": "^9.19.0", "globals": "^16.0.0", "react-native": "0.79.5", "tsx": "^4.19.3", - "typescript": "^5.7.3", - "typescript-eslint": "^8.22.0" + "typescript": "^5.7.3" } }, "apps/test-app": { @@ -2080,6 +2078,169 @@ "node": ">=6.9.0" } }, + "node_modules/@biomejs/biome": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@biomejs/biome/-/biome-2.1.2.tgz", + "integrity": "sha512-yq8ZZuKuBVDgAS76LWCfFKHSYIAgqkxVB3mGVVpOe2vSkUTs7xG46zXZeNPRNVjiJuw0SZ3+J2rXiYx0RUpfGg==", + "dev": true, + "license": "MIT OR Apache-2.0", + "bin": { + "biome": "bin/biome" + }, + "engines": { + "node": ">=14.21.3" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/biome" + }, + "optionalDependencies": { + "@biomejs/cli-darwin-arm64": "2.1.2", + "@biomejs/cli-darwin-x64": "2.1.2", + "@biomejs/cli-linux-arm64": "2.1.2", + "@biomejs/cli-linux-arm64-musl": "2.1.2", + "@biomejs/cli-linux-x64": "2.1.2", + "@biomejs/cli-linux-x64-musl": "2.1.2", + "@biomejs/cli-win32-arm64": "2.1.2", + "@biomejs/cli-win32-x64": "2.1.2" + } + }, + "node_modules/@biomejs/cli-darwin-arm64": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@biomejs/cli-darwin-arm64/-/cli-darwin-arm64-2.1.2.tgz", + "integrity": "sha512-leFAks64PEIjc7MY/cLjE8u5OcfBKkcDB0szxsWUB4aDfemBep1WVKt0qrEyqZBOW8LPHzrFMyDl3FhuuA0E7g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT OR Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=14.21.3" + } + }, + "node_modules/@biomejs/cli-darwin-x64": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@biomejs/cli-darwin-x64/-/cli-darwin-x64-2.1.2.tgz", + "integrity": "sha512-Nmmv7wRX5Nj7lGmz0FjnWdflJg4zii8Ivruas6PBKzw5SJX/q+Zh2RfnO+bBnuKLXpj8kiI2x2X12otpH6a32A==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT OR Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=14.21.3" + } + }, + "node_modules/@biomejs/cli-linux-arm64": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-arm64/-/cli-linux-arm64-2.1.2.tgz", + "integrity": "sha512-NWNy2Diocav61HZiv2enTQykbPP/KrA/baS7JsLSojC7Xxh2nl9IczuvE5UID7+ksRy2e7yH7klm/WkA72G1dw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT OR Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.21.3" + } + }, + "node_modules/@biomejs/cli-linux-arm64-musl": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-arm64-musl/-/cli-linux-arm64-musl-2.1.2.tgz", + "integrity": "sha512-qgHvafhjH7Oca114FdOScmIKf1DlXT1LqbOrrbR30kQDLFPEOpBG0uzx6MhmsrmhGiCFCr2obDamu+czk+X0HQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT OR Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.21.3" + } + }, + "node_modules/@biomejs/cli-linux-x64": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-x64/-/cli-linux-x64-2.1.2.tgz", + "integrity": "sha512-Km/UYeVowygTjpX6sGBzlizjakLoMQkxWbruVZSNE6osuSI63i4uCeIL+6q2AJlD3dxoiBJX70dn1enjQnQqwA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT OR Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.21.3" + } + }, + "node_modules/@biomejs/cli-linux-x64-musl": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-x64-musl/-/cli-linux-x64-musl-2.1.2.tgz", + "integrity": "sha512-xlB3mU14ZUa3wzLtXfmk2IMOGL+S0aHFhSix/nssWS/2XlD27q+S6f0dlQ8WOCbYoXcuz8BCM7rCn2lxdTrlQA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT OR Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.21.3" + } + }, + "node_modules/@biomejs/cli-win32-arm64": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@biomejs/cli-win32-arm64/-/cli-win32-arm64-2.1.2.tgz", + "integrity": "sha512-G8KWZli5ASOXA3yUQgx+M4pZRv3ND16h77UsdunUL17uYpcL/UC7RkWTdkfvMQvogVsAuz5JUcBDjgZHXxlKoA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT OR Apache-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=14.21.3" + } + }, + "node_modules/@biomejs/cli-win32-x64": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@biomejs/cli-win32-x64/-/cli-win32-x64-2.1.2.tgz", + "integrity": "sha512-9zajnk59PMpjBkty3bK2IrjUsUHvqe9HWwyAWQBjGLE7MIBjbX2vwv1XPEhmO2RRuGoTkVx3WCanHrjAytICLA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT OR Apache-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=14.21.3" + } + }, "node_modules/@changesets/apply-release-plan": { "version": "7.0.12", "resolved": "https://registry.npmjs.org/@changesets/apply-release-plan/-/apply-release-plan-7.0.12.tgz", @@ -2929,157 +3090,6 @@ "node": ">=18" } }, - "node_modules/@eslint-community/eslint-utils": { - "version": "4.6.1", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.6.1.tgz", - "integrity": "sha512-KTsJMmobmbrFLe3LDh0PC2FXpcSYJt/MLjlkh/9LEnmKYLSYmT/0EW9JWANjeoemiuZrmogti0tW5Ch+qNUYDw==", - "dev": true, - "license": "MIT", - "dependencies": { - "eslint-visitor-keys": "^3.4.3" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - }, - "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" - } - }, - "node_modules/@eslint-community/eslint-utils/node_modules/eslint-visitor-keys": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", - "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/@eslint-community/regexpp": { - "version": "4.12.1", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz", - "integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^12.0.0 || ^14.0.0 || >=16.0.0" - } - }, - "node_modules/@eslint/config-array": { - "version": "0.20.0", - "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.20.0.tgz", - "integrity": "sha512-fxlS1kkIjx8+vy2SjuCB94q3htSNrufYTXubwiBFeaQHbH6Ipi43gFJq2zCMt6PHhImH3Xmr0NksKDvchWlpQQ==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@eslint/object-schema": "^2.1.6", - "debug": "^4.3.1", - "minimatch": "^3.1.2" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - } - }, - "node_modules/@eslint/config-helpers": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.2.1.tgz", - "integrity": "sha512-RI17tsD2frtDu/3dmI7QRrD4bedNKPM08ziRYaC5AhkGrzIAJelm9kJU1TznK+apx6V+cqRz8tfpEeG3oIyjxw==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - } - }, - "node_modules/@eslint/core": { - "version": "0.13.0", - "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.13.0.tgz", - "integrity": "sha512-yfkgDw1KR66rkT5A8ci4irzDysN7FRpq3ttJolR88OqQikAWqwA8j5VZyas+vjyBNFIJ7MfybJ9plMILI2UrCw==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@types/json-schema": "^7.0.15" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - } - }, - "node_modules/@eslint/eslintrc": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.1.tgz", - "integrity": "sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ajv": "^6.12.4", - "debug": "^4.3.2", - "espree": "^10.0.1", - "globals": "^14.0.0", - "ignore": "^5.2.0", - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", - "minimatch": "^3.1.2", - "strip-json-comments": "^3.1.1" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/@eslint/eslintrc/node_modules/globals": { - "version": "14.0.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", - "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@eslint/js": { - "version": "9.25.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.25.0.tgz", - "integrity": "sha512-iWhsUS8Wgxz9AXNfvfOPFSW4VfMXdVhp1hjkZVhXCrpgh/aLcc45rX6MPu+tIVUWDw0HfNwth7O28M1xDxNf9w==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - } - }, - "node_modules/@eslint/object-schema": { - "version": "2.1.6", - "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.6.tgz", - "integrity": "sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - } - }, - "node_modules/@eslint/plugin-kit": { - "version": "0.2.8", - "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.8.tgz", - "integrity": "sha512-ZAoA40rNMPwSm+AeHpCq8STiNAwzWLJuP8Xv4CHIc9wv/PSuExjMrmjfYNj682vW0OOiZ1HKxzvjQr9XZIisQA==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@eslint/core": "^0.13.0", - "levn": "^0.4.1" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - } - }, "node_modules/@fastify/busboy": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-2.1.1.tgz", @@ -3105,72 +3115,6 @@ "@hapi/hoek": "^9.0.0" } }, - "node_modules/@humanfs/core": { - "version": "0.19.1", - "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz", - "integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">=18.18.0" - } - }, - "node_modules/@humanfs/node": { - "version": "0.16.6", - "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.6.tgz", - "integrity": "sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@humanfs/core": "^0.19.1", - "@humanwhocodes/retry": "^0.3.0" - }, - "engines": { - "node": ">=18.18.0" - } - }, - "node_modules/@humanfs/node/node_modules/@humanwhocodes/retry": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.1.tgz", - "integrity": "sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">=18.18" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/nzakas" - } - }, - "node_modules/@humanwhocodes/module-importer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", - "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">=12.22" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/nzakas" - } - }, - "node_modules/@humanwhocodes/retry": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.3.tgz", - "integrity": "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">=18.18" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/nzakas" - } - }, "node_modules/@inquirer/checkbox": { "version": "4.1.7", "resolved": "https://registry.npmjs.org/@inquirer/checkbox/-/checkbox-4.1.7.tgz", @@ -5998,13 +5942,6 @@ "@babel/types": "^7.20.7" } }, - "node_modules/@types/estree": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.7.tgz", - "integrity": "sha512-w28IoSUCJpidD/TGviZwwMJckNESJZXFu7NBZ5YJ4mEUnNraUn9Pm8HSZm/jDF1pDWYKspWE7oVphigUPRakIQ==", - "dev": true, - "license": "MIT" - }, "node_modules/@types/graceful-fs": { "version": "4.1.9", "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.9.tgz", @@ -6038,13 +5975,6 @@ "@types/istanbul-lib-report": "*" } }, - "node_modules/@types/json-schema": { - "version": "7.0.15", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", - "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", - "dev": true, - "license": "MIT" - }, "node_modules/@types/mocha": { "version": "10.0.10", "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-10.0.10.tgz", @@ -6069,239 +5999,33 @@ "node_modules/@types/react": { "version": "19.1.2", "resolved": "https://registry.npmjs.org/@types/react/-/react-19.1.2.tgz", - "integrity": "sha512-oxLPMytKchWGbnQM9O7D67uPa9paTNxO7jVoNMXgkkErULBPhPARCfkKL9ytcIJJRGjbsVwW4ugJzyFFvm/Tiw==", - "license": "MIT", - "dependencies": { - "csstype": "^3.0.2" - } - }, - "node_modules/@types/stack-utils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz", - "integrity": "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==", - "license": "MIT" - }, - "node_modules/@types/yargs": { - "version": "17.0.33", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.33.tgz", - "integrity": "sha512-WpxBCKWPLr4xSsHgz511rFJAM+wS28w2zEO1QDNY5zM/S8ok70NNfztH0xwhqKyaK0OHCbN98LDAZuy1ctxDkA==", - "license": "MIT", - "dependencies": { - "@types/yargs-parser": "*" - } - }, - "node_modules/@types/yargs-parser": { - "version": "21.0.3", - "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz", - "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==", - "license": "MIT" - }, - "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.30.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.30.1.tgz", - "integrity": "sha512-v+VWphxMjn+1t48/jO4t950D6KR8JaJuNXzi33Ve6P8sEmPr5k6CEXjdGwT6+LodVnEa91EQCtwjWNUCPweo+Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "8.30.1", - "@typescript-eslint/type-utils": "8.30.1", - "@typescript-eslint/utils": "8.30.1", - "@typescript-eslint/visitor-keys": "8.30.1", - "graphemer": "^1.4.0", - "ignore": "^5.3.1", - "natural-compare": "^1.4.0", - "ts-api-utils": "^2.0.1" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "@typescript-eslint/parser": "^8.0.0 || ^8.0.0-alpha.0", - "eslint": "^8.57.0 || ^9.0.0", - "typescript": ">=4.8.4 <5.9.0" - } - }, - "node_modules/@typescript-eslint/parser": { - "version": "8.30.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.30.1.tgz", - "integrity": "sha512-H+vqmWwT5xoNrXqWs/fesmssOW70gxFlgcMlYcBaWNPIEWDgLa4W9nkSPmhuOgLnXq9QYgkZ31fhDyLhleCsAg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/scope-manager": "8.30.1", - "@typescript-eslint/types": "8.30.1", - "@typescript-eslint/typescript-estree": "8.30.1", - "@typescript-eslint/visitor-keys": "8.30.1", - "debug": "^4.3.4" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0", - "typescript": ">=4.8.4 <5.9.0" - } - }, - "node_modules/@typescript-eslint/scope-manager": { - "version": "8.30.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.30.1.tgz", - "integrity": "sha512-+C0B6ChFXZkuaNDl73FJxRYT0G7ufVPOSQkqkpM/U198wUwUFOtgo1k/QzFh1KjpBitaK7R1tgjVz6o9HmsRPg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/types": "8.30.1", - "@typescript-eslint/visitor-keys": "8.30.1" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/type-utils": { - "version": "8.30.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.30.1.tgz", - "integrity": "sha512-64uBF76bfQiJyHgZISC7vcNz3adqQKIccVoKubyQcOnNcdJBvYOILV1v22Qhsw3tw3VQu5ll8ND6hycgAR5fEA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/typescript-estree": "8.30.1", - "@typescript-eslint/utils": "8.30.1", - "debug": "^4.3.4", - "ts-api-utils": "^2.0.1" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0", - "typescript": ">=4.8.4 <5.9.0" - } - }, - "node_modules/@typescript-eslint/types": { - "version": "8.30.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.30.1.tgz", - "integrity": "sha512-81KawPfkuulyWo5QdyG/LOKbspyyiW+p4vpn4bYO7DM/hZImlVnFwrpCTnmNMOt8CvLRr5ojI9nU1Ekpw4RcEw==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.30.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.30.1.tgz", - "integrity": "sha512-kQQnxymiUy9tTb1F2uep9W6aBiYODgq5EMSk6Nxh4Z+BDUoYUSa029ISs5zTzKBFnexQEh71KqwjKnRz58lusQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/types": "8.30.1", - "@typescript-eslint/visitor-keys": "8.30.1", - "debug": "^4.3.4", - "fast-glob": "^3.3.2", - "is-glob": "^4.0.3", - "minimatch": "^9.0.4", - "semver": "^7.6.0", - "ts-api-utils": "^2.0.1" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "typescript": ">=4.8.4 <5.9.0" - } - }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", - "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/@typescript-eslint/utils": { - "version": "8.30.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.30.1.tgz", - "integrity": "sha512-T/8q4R9En2tcEsWPQgB5BQ0XJVOtfARcUvOa8yJP3fh9M/mXraLxZrkCfGb6ChrO/V3W+Xbd04RacUEqk1CFEQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "8.30.1", - "@typescript-eslint/types": "8.30.1", - "@typescript-eslint/typescript-estree": "8.30.1" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0", - "typescript": ">=4.8.4 <5.9.0" + "integrity": "sha512-oxLPMytKchWGbnQM9O7D67uPa9paTNxO7jVoNMXgkkErULBPhPARCfkKL9ytcIJJRGjbsVwW4ugJzyFFvm/Tiw==", + "license": "MIT", + "dependencies": { + "csstype": "^3.0.2" } }, - "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.30.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.30.1.tgz", - "integrity": "sha512-aEhgas7aJ6vZnNFC7K4/vMGDGyOiqWcYZPpIWrTKuTAlsvDNKy2GFDqh9smL+iq069ZvR0YzEeq0B8NJlLzjFA==", - "dev": true, + "node_modules/@types/stack-utils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz", + "integrity": "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==", + "license": "MIT" + }, + "node_modules/@types/yargs": { + "version": "17.0.33", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.33.tgz", + "integrity": "sha512-WpxBCKWPLr4xSsHgz511rFJAM+wS28w2zEO1QDNY5zM/S8ok70NNfztH0xwhqKyaK0OHCbN98LDAZuy1ctxDkA==", "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.30.1", - "eslint-visitor-keys": "^4.2.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "@types/yargs-parser": "*" } }, + "node_modules/@types/yargs-parser": { + "version": "21.0.3", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz", + "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==", + "license": "MIT" + }, "node_modules/@vscode/sudo-prompt": { "version": "9.3.1", "resolved": "https://registry.npmjs.org/@vscode/sudo-prompt/-/sudo-prompt-9.3.1.tgz", @@ -6345,33 +6069,6 @@ "node": ">=0.4.0" } }, - "node_modules/acorn-jsx": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", - "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", - "dev": true, - "license": "MIT", - "peerDependencies": { - "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" - } - }, - "node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "license": "MIT", - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, "node_modules/anser": { "version": "1.4.10", "resolved": "https://registry.npmjs.org/anser/-/anser-1.4.10.tgz", @@ -7688,13 +7385,6 @@ "node": ">=4.0.0" } }, - "node_modules/deep-is": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", - "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", - "dev": true, - "license": "MIT" - }, "node_modules/deepmerge": { "version": "4.3.1", "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", @@ -8056,115 +7746,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/eslint": { - "version": "9.25.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.25.0.tgz", - "integrity": "sha512-MsBdObhM4cEwkzCiraDv7A6txFXEqtNXOb877TsSp2FCkBNl8JfVQrmiuDqC1IkejT6JLPzYBXx/xAiYhyzgGA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.12.1", - "@eslint/config-array": "^0.20.0", - "@eslint/config-helpers": "^0.2.1", - "@eslint/core": "^0.13.0", - "@eslint/eslintrc": "^3.3.1", - "@eslint/js": "9.25.0", - "@eslint/plugin-kit": "^0.2.8", - "@humanfs/node": "^0.16.6", - "@humanwhocodes/module-importer": "^1.0.1", - "@humanwhocodes/retry": "^0.4.2", - "@types/estree": "^1.0.6", - "@types/json-schema": "^7.0.15", - "ajv": "^6.12.4", - "chalk": "^4.0.0", - "cross-spawn": "^7.0.6", - "debug": "^4.3.2", - "escape-string-regexp": "^4.0.0", - "eslint-scope": "^8.3.0", - "eslint-visitor-keys": "^4.2.0", - "espree": "^10.3.0", - "esquery": "^1.5.0", - "esutils": "^2.0.2", - "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^8.0.0", - "find-up": "^5.0.0", - "glob-parent": "^6.0.2", - "ignore": "^5.2.0", - "imurmurhash": "^0.1.4", - "is-glob": "^4.0.0", - "json-stable-stringify-without-jsonify": "^1.0.1", - "lodash.merge": "^4.6.2", - "minimatch": "^3.1.2", - "natural-compare": "^1.4.0", - "optionator": "^0.9.3" - }, - "bin": { - "eslint": "bin/eslint.js" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://eslint.org/donate" - }, - "peerDependencies": { - "jiti": "*" - }, - "peerDependenciesMeta": { - "jiti": { - "optional": true - } - } - }, - "node_modules/eslint-scope": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.3.0.tgz", - "integrity": "sha512-pUNxi75F8MJ/GdeKtVLSbYg4ZI34J6C0C7sbL4YOp2exGwen7ZsuBqKzUhXd0qMQ362yET3z+uPwKeg/0C2XCQ==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint-visitor-keys": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", - "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/espree": { - "version": "10.3.0", - "resolved": "https://registry.npmjs.org/espree/-/espree-10.3.0.tgz", - "integrity": "sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "acorn": "^8.14.0", - "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^4.2.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, "node_modules/esprima": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", @@ -8178,42 +7759,6 @@ "node": ">=4" } }, - "node_modules/esquery": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", - "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "estraverse": "^5.1.0" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/esrecurse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "estraverse": "^5.2.0" - }, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, - "license": "BSD-2-Clause", - "engines": { - "node": ">=4.0" - } - }, "node_modules/esutils": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", @@ -8356,13 +7901,6 @@ "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", "license": "MIT" }, - "node_modules/fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", - "dev": true, - "license": "MIT" - }, "node_modules/fast-uri": { "version": "3.0.6", "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.6.tgz", @@ -8423,19 +7961,6 @@ "resolved": "packages/ferric-example", "link": true }, - "node_modules/file-entry-cache": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", - "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "flat-cache": "^4.0.0" - }, - "engines": { - "node": ">=16.0.0" - } - }, "node_modules/fill-range": { "version": "7.1.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", @@ -8518,20 +8043,6 @@ "flat": "cli.js" } }, - "node_modules/flat-cache": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", - "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", - "dev": true, - "license": "MIT", - "dependencies": { - "flatted": "^3.2.9", - "keyv": "^4.5.4" - }, - "engines": { - "node": ">=16" - } - }, "node_modules/flatted": { "version": "3.3.3", "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz", @@ -8856,19 +8367,6 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/glob-parent": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", - "dev": true, - "license": "ISC", - "dependencies": { - "is-glob": "^4.0.3" - }, - "engines": { - "node": ">=10.13.0" - } - }, "node_modules/globals": { "version": "16.3.0", "resolved": "https://registry.npmjs.org/globals/-/globals-16.3.0.tgz", @@ -8921,13 +8419,6 @@ "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", "license": "ISC" }, - "node_modules/graphemer": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", - "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", - "dev": true, - "license": "MIT" - }, "node_modules/gyp-parser": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/gyp-parser/-/gyp-parser-1.0.4.tgz", @@ -9746,13 +9237,6 @@ "node": ">=6" } }, - "node_modules/json-buffer": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", - "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", - "dev": true, - "license": "MIT" - }, "node_modules/json-parse-better-errors": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", @@ -9765,20 +9249,6 @@ "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", "license": "MIT" }, - "node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true, - "license": "MIT" - }, - "node_modules/json-stable-stringify-without-jsonify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", - "dev": true, - "license": "MIT" - }, "node_modules/json5": { "version": "2.2.3", "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", @@ -9800,16 +9270,6 @@ "graceful-fs": "^4.1.6" } }, - "node_modules/keyv": { - "version": "4.5.4", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", - "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", - "dev": true, - "license": "MIT", - "dependencies": { - "json-buffer": "3.0.1" - } - }, "node_modules/kleur": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", @@ -9838,20 +9298,6 @@ "node": ">=6" } }, - "node_modules/levn": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", - "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" - }, - "engines": { - "node": ">= 0.8.0" - } - }, "node_modules/lighthouse-logger": { "version": "1.4.2", "resolved": "https://registry.npmjs.org/lighthouse-logger/-/lighthouse-logger-1.4.2.tgz", @@ -9916,13 +9362,6 @@ "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==", "license": "MIT" }, - "node_modules/lodash.merge": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", - "dev": true, - "license": "MIT" - }, "node_modules/lodash.startcase": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/lodash.startcase/-/lodash.startcase-4.4.0.tgz", @@ -10848,13 +10287,6 @@ "node": "^18.17.0 || >=20.5.0" } }, - "node_modules/natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", - "dev": true, - "license": "MIT" - }, "node_modules/negotiator": { "version": "0.6.3", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", @@ -11126,24 +10558,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/optionator": { - "version": "0.9.4", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", - "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", - "dev": true, - "license": "MIT", - "dependencies": { - "deep-is": "^0.1.3", - "fast-levenshtein": "^2.0.6", - "levn": "^0.4.1", - "prelude-ls": "^1.2.1", - "type-check": "^0.4.0", - "word-wrap": "^1.2.5" - }, - "engines": { - "node": ">= 0.8.0" - } - }, "node_modules/ora": { "version": "5.4.1", "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz", @@ -11421,16 +10835,6 @@ "node": ">= 0.4" } }, - "node_modules/prelude-ls": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.8.0" - } - }, "node_modules/prettier": { "version": "2.8.8", "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz", @@ -11501,16 +10905,6 @@ "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", "license": "MIT" }, - "node_modules/punycode": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", - "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, "node_modules/qs": { "version": "6.13.0", "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", @@ -12867,19 +12261,6 @@ "tree-kill": "cli.js" } }, - "node_modules/ts-api-utils": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.1.0.tgz", - "integrity": "sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18.12" - }, - "peerDependencies": { - "typescript": ">=4.8.4" - } - }, "node_modules/tslib": { "version": "2.8.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", @@ -12925,19 +12306,6 @@ "website" ] }, - "node_modules/type-check": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", - "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", - "dev": true, - "license": "MIT", - "dependencies": { - "prelude-ls": "^1.2.1" - }, - "engines": { - "node": ">= 0.8.0" - } - }, "node_modules/type-detect": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", @@ -12983,29 +12351,6 @@ "node": ">=14.17" } }, - "node_modules/typescript-eslint": { - "version": "8.30.1", - "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.30.1.tgz", - "integrity": "sha512-D7lC0kcehVH7Mb26MRQi64LMyRJsj3dToJxM1+JVTl53DQSV5/7oUGWQLcKl1C1KnoVHxMMU2FNQMffr7F3Row==", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/eslint-plugin": "8.30.1", - "@typescript-eslint/parser": "8.30.1", - "@typescript-eslint/utils": "8.30.1" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0", - "typescript": ">=4.8.4 <5.9.0" - } - }, "node_modules/undici": { "version": "5.29.0", "resolved": "https://registry.npmjs.org/undici/-/undici-5.29.0.tgz", @@ -13131,16 +12476,6 @@ "browserslist": ">= 4.21.0" } }, - "node_modules/uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "punycode": "^2.1.0" - } - }, "node_modules/url-join": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/url-join/-/url-join-4.0.1.tgz", @@ -13294,16 +12629,6 @@ "string-width": "^1.0.2 || 2 || 3 || 4" } }, - "node_modules/word-wrap": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", - "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/workerpool": { "version": "9.3.2", "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-9.3.2.tgz", diff --git a/package.json b/package.json index 1216fa69..1c735e95 100644 --- a/package.json +++ b/package.json @@ -17,7 +17,7 @@ "build": "tsc --build", "clean": "tsc --build --clean", "dev": "tsc --build --watch", - "lint": "eslint .", + "lint": "biome check --write", "test": "npm run test --workspace react-native-node-api --workspace cmake-rn --workspace gyp-to-cmake --workspace node-addon-examples", "bootstrap": "npm run build && npm run bootstrap --workspaces --if-present", "prerelease": "npm run build && npm run prerelease --workspaces --if-present", @@ -39,17 +39,15 @@ ], "license": "MIT", "devDependencies": { + "@biomejs/biome": "^2.1.2", "@changesets/cli": "^2.29.5", - "@eslint/js": "^9.19.0", "@reporters/github": "^1.7.2", "@tsconfig/node22": "^22.0.0", "@tsconfig/react-native": "3.0.5", "@types/node": "^22.13.0", - "eslint": "^9.19.0", "globals": "^16.0.0", "react-native": "0.79.5", - "typescript": "^5.7.3", - "typescript-eslint": "^8.22.0", - "tsx": "^4.19.3" + "tsx": "^4.19.3", + "typescript": "^5.7.3" } } diff --git a/packages/cmake-rn/src/cli.ts b/packages/cmake-rn/src/cli.ts index 56c8dac9..307d90d4 100644 --- a/packages/cmake-rn/src/cli.ts +++ b/packages/cmake-rn/src/cli.ts @@ -1,22 +1,21 @@ import assert from "node:assert/strict"; -import path from "node:path"; -import fs from "node:fs"; import { EventEmitter } from "node:events"; +import fs from "node:fs"; +import path from "node:path"; import { Command, Option } from "@commander-js/extra-typings"; -import { spawn, SpawnFailure } from "bufout"; -import { oraPromise } from "ora"; +import { SpawnFailure, spawn } from "bufout"; import chalk from "chalk"; - -import { getWeakNodeApiVariables } from "./weak-node-api.js"; +import { oraPromise } from "ora"; +import { isSupportedTriplet } from "react-native-node-api"; +import type { BaseOpts, Platform, TargetContext } from "./platforms/types.js"; import { - platforms, allTargets, findPlatformForTarget, platformHasTarget, + platforms, } from "./platforms.js"; -import { BaseOpts, TargetContext, Platform } from "./platforms/types.js"; -import { isSupportedTriplet } from "react-native-node-api"; +import { getWeakNodeApiVariables } from "./weak-node-api.js"; // We're attaching a lot of listeners when spawning in parallel EventEmitter.defaultMaxListeners = 100; @@ -25,12 +24,12 @@ EventEmitter.defaultMaxListeners = 100; const verboseOption = new Option( "--verbose", - "Print more output during the build" + "Print more output during the build", ).default(process.env.CI === "true"); const sourcePathOption = new Option( "--source ", - "Specify the source directory containing a CMakeLists.txt file" + "Specify the source directory containing a CMakeLists.txt file", ).default(process.cwd()); // TODO: Add "MinSizeRel" and "RelWithDebInfo" @@ -48,7 +47,7 @@ const defaultTargets = CMAKE_RN_TARGETS ? CMAKE_RN_TARGETS.split(",") : []; for (const target of defaultTargets) { assert( (allTargets as string[]).includes(target), - `Unexpected target in CMAKE_RN_TARGETS: ${target}` + `Unexpected target in CMAKE_RN_TARGETS: ${target}`, ); } @@ -56,32 +55,32 @@ const targetOption = new Option("--target ", "Targets to build for") .choices(allTargets) .default( defaultTargets, - "CMAKE_RN_TARGETS environment variable split by ','" + "CMAKE_RN_TARGETS environment variable split by ','", ); const buildPathOption = new Option( "--build ", - "Specify the build directory to store the configured CMake project" + "Specify the build directory to store the configured CMake project", ); const cleanOption = new Option( "--clean", - "Delete the build directory before configuring the project" + "Delete the build directory before configuring the project", ); const outPathOption = new Option( "--out ", - "Specify the output directory to store the final build artifacts" + "Specify the output directory to store the final build artifacts", ).default(false, "./{build}/{configuration}"); const noAutoLinkOption = new Option( "--no-auto-link", - "Don't mark the output as auto-linkable by react-native-node-api" + "Don't mark the output as auto-linkable by react-native-node-api", ); const noWeakNodeApiLinkageOption = new Option( "--no-weak-node-api-linkage", - "Don't pass the path of the weak-node-api library from react-native-node-api" + "Don't pass the path of the weak-node-api library from react-native-node-api", ); let program = new Command("cmake-rn") @@ -99,7 +98,7 @@ let program = new Command("cmake-rn") for (const platform of platforms) { const allOption = new Option( `--${platform.id}`, - `Enable all ${platform.name} triplets` + `Enable all ${platform.name} triplets`, ); program = program.addOption(allOption); program = platform.amendCommand(program); @@ -133,13 +132,13 @@ program = program.action( } if (targets.size === 0) { throw new Error( - "Found no default targets: Install some platform specific build tools" + "Found no default targets: Install some platform specific build tools", ); } else { console.error( chalk.yellowBright("ℹ"), "Using default targets", - chalk.dim("(" + [...targets].join(", ") + ")") + chalk.dim(`(${[...targets].join(", ")})`), ); } } @@ -162,20 +161,20 @@ program = program.action( // Configure every triplet project const targetsSummary = chalk.dim( - `(${getTargetsSummary(targetContexts)})` + `(${getTargetsSummary(targetContexts)})`, ); await oraPromise( Promise.all( targetContexts.map(({ platform, ...context }) => - configureProject(platform, context, baseOptions) - ) + configureProject(platform, context, baseOptions), + ), ), { text: `Configuring projects ${targetsSummary}`, isSilent: baseOptions.verbose, successText: `Configured projects ${targetsSummary}`, failText: ({ message }) => `Failed to configure projects: ${message}`, - } + }, ); // Build every triplet project @@ -189,22 +188,22 @@ program = program.action( force: true, }); await buildProject(platform, context, baseOptions); - }) + }), ), { text: "Building projects", isSilent: baseOptions.verbose, successText: "Built projects", failText: ({ message }) => `Failed to build projects: ${message}`, - } + }, ); // Perform post-build steps for each platform in sequence for (const platform of platforms) { const relevantTargets = targetContexts.filter(({ target }) => - platformHasTarget(platform, target) + platformHasTarget(platform, target), ); - if (relevantTargets.length == 0) { + if (relevantTargets.length === 0) { continue; } await platform.postBuild( @@ -212,7 +211,7 @@ program = program.action( outputPath: baseOptions.out || baseOptions.source, targets: relevantTargets, }, - baseOptions + baseOptions, ); } } catch (error) { @@ -221,11 +220,11 @@ program = program.action( } throw error; } - } + }, ); function getTargetsSummary( - targetContexts: { target: string; platform: Platform }[] + targetContexts: { target: string; platform: Platform }[], ) { const targetsPerPlatform: Record = {}; for (const { target, platform } of targetContexts) { @@ -257,7 +256,7 @@ function getTargetBuildPath(buildPath: string, target: unknown) { async function configureProject( platform: Platform>, context: TargetContext, - options: BaseOpts + options: BaseOpts, ) { const { target, buildPath, outputPath } = context; const { verbose, source, weakNodeApiLinkage } = options; @@ -286,14 +285,14 @@ async function configureProject( { outputMode: verbose ? "inherit" : "buffered", outputPrefix: verbose ? chalk.dim(`[${target}] `) : undefined, - } + }, ); } async function buildProject( platform: Platform>, context: TargetContext, - options: BaseOpts + options: BaseOpts, ) { const { target, buildPath } = context; const { verbose, configuration } = options; @@ -310,7 +309,7 @@ async function buildProject( { outputMode: verbose ? "inherit" : "buffered", outputPrefix: verbose ? chalk.dim(`[${target}] `) : undefined, - } + }, ); } diff --git a/packages/cmake-rn/src/headers.ts b/packages/cmake-rn/src/headers.ts index 61510846..aefd1464 100644 --- a/packages/cmake-rn/src/headers.ts +++ b/packages/cmake-rn/src/headers.ts @@ -1,7 +1,7 @@ +import assert from "node:assert/strict"; +import fs from "node:fs"; import { createRequire } from "node:module"; import path from "node:path"; -import fs from "node:fs"; -import assert from "node:assert/strict"; const require = createRequire(import.meta.url); @@ -11,7 +11,7 @@ const require = createRequire(import.meta.url); export function getNodeApiHeadersPath(): string { try { const packagePath = path.dirname( - require.resolve("node-api-headers/package.json") + require.resolve("node-api-headers/package.json"), ); const result = path.join(packagePath, "include"); const stat = fs.statSync(packagePath); @@ -22,7 +22,7 @@ export function getNodeApiHeadersPath(): string { `Failed resolve Node-API headers: Did you install the 'node-api-headers' package?`, { cause: error, - } + }, ); } } @@ -33,7 +33,7 @@ export function getNodeApiHeadersPath(): string { export function getNodeAddonHeadersPath(): string { try { const packagePath = path.dirname( - require.resolve("node-addon-api/package.json") + require.resolve("node-addon-api/package.json"), ); return packagePath; } catch (error) { @@ -41,7 +41,7 @@ export function getNodeAddonHeadersPath(): string { `Failed resolve Node-API addon headers: Did you install the 'node-addon-api' package?`, { cause: error, - } + }, ); } } diff --git a/packages/cmake-rn/src/platforms.test.ts b/packages/cmake-rn/src/platforms.test.ts index 2f8c95f7..77dee711 100644 --- a/packages/cmake-rn/src/platforms.test.ts +++ b/packages/cmake-rn/src/platforms.test.ts @@ -1,12 +1,11 @@ import assert from "node:assert/strict"; import { describe, it } from "node:test"; - +import type { Platform } from "./platforms/types.js"; import { - platforms, - platformHasTarget, findPlatformForTarget, + platformHasTarget, + platforms, } from "./platforms.js"; -import { Platform } from "./platforms/types.js"; const mockPlatform = { targets: ["target1", "target2"] } as unknown as Platform; diff --git a/packages/cmake-rn/src/platforms.ts b/packages/cmake-rn/src/platforms.ts index 0692a3a4..2a298328 100644 --- a/packages/cmake-rn/src/platforms.ts +++ b/packages/cmake-rn/src/platforms.ts @@ -2,21 +2,21 @@ import assert from "node:assert/strict"; import { platform as android } from "./platforms/android.js"; import { platform as apple } from "./platforms/apple.js"; -import { Platform } from "./platforms/types.js"; +import type { Platform } from "./platforms/types.js"; export const platforms: Platform[] = [android, apple] as const; export const allTargets = [...android.targets, ...apple.targets] as const; export function platformHasTarget

( platform: P, - target: unknown + target: unknown, ): target is P["targets"][number] { return (platform.targets as unknown[]).includes(target); } export function findPlatformForTarget(target: unknown) { const platform = Object.values(platforms).find((platform) => - platformHasTarget(platform, target) + platformHasTarget(platform, target), ); assert(platform, `Unable to determine platform from target: ${target}`); return platform; diff --git a/packages/cmake-rn/src/platforms/android.ts b/packages/cmake-rn/src/platforms/android.ts index 51e2ab76..d61d3e8d 100644 --- a/packages/cmake-rn/src/platforms/android.ts +++ b/packages/cmake-rn/src/platforms/android.ts @@ -3,15 +3,14 @@ import fs from "node:fs"; import path from "node:path"; import { Option } from "@commander-js/extra-typings"; +import chalk from "chalk"; +import { oraPromise } from "ora"; import { createAndroidLibsDirectory, determineAndroidLibsFilename, - AndroidTriplet as Target, + type AndroidTriplet as Target, } from "react-native-node-api"; - import type { Platform } from "./types.js"; -import { oraPromise } from "ora"; -import chalk from "chalk"; // This should match https://github.com/react-native-community/template/blob/main/template/android/build.gradle#L7 const DEFAULT_NDK_VERSION = "27.1.12297006"; @@ -28,12 +27,12 @@ export const ANDROID_ARCHITECTURES = { const ndkVersionOption = new Option( "--ndk-version ", - "The NDK version to use for Android builds" + "The NDK version to use for Android builds", ).default(DEFAULT_NDK_VERSION); const androidSdkVersionOption = new Option( "--android-sdk-version ", - "The Android SDK version to use for Android builds" + "The Android SDK version to use for Android builds", ).default(DEFAULT_ANDROID_SDK_VERSION); type AndroidOpts = { ndkVersion: string; androidSdkVersion: string }; @@ -65,22 +64,22 @@ export const platform: Platform = { const { ANDROID_HOME } = process.env; assert( typeof ANDROID_HOME === "string", - "Missing env variable ANDROID_HOME" + "Missing env variable ANDROID_HOME", ); assert( fs.existsSync(ANDROID_HOME), - `Expected the Android SDK at ${ANDROID_HOME}` + `Expected the Android SDK at ${ANDROID_HOME}`, ); const installNdkCommand = `sdkmanager --install "ndk;${ndkVersion}"`; const ndkPath = path.resolve(ANDROID_HOME, "ndk", ndkVersion); assert( fs.existsSync(ndkPath), - `Missing Android NDK v${ndkVersion} (at ${ndkPath}) - run: ${installNdkCommand}` + `Missing Android NDK v${ndkVersion} (at ${ndkPath}) - run: ${installNdkCommand}`, ); const toolchainPath = path.join( ndkPath, - "build/cmake/android.toolchain.cmake" + "build/cmake/android.toolchain.cmake", ); const architecture = ANDROID_ARCHITECTURES[target]; @@ -130,7 +129,7 @@ export const platform: Platform = { targets.map(async ({ target, outputPath }) => { assert( fs.existsSync(outputPath), - `Expected a directory at ${outputPath}` + `Expected a directory at ${outputPath}`, ); // Expect binary file(s), either .node or .so const dirents = await fs.promises.readdir(outputPath, { @@ -140,16 +139,16 @@ export const platform: Platform = { .filter( (dirent) => dirent.isFile() && - (dirent.name.endsWith(".so") || dirent.name.endsWith(".node")) + (dirent.name.endsWith(".so") || dirent.name.endsWith(".node")), ) .map((dirent) => path.join(dirent.parentPath, dirent.name)); assert.equal(result.length, 1, "Expected exactly one library file"); return [target, result[0]] as const; - }) - ) + }), + ), ) as Record; const androidLibsFilename = determineAndroidLibsFilename( - Object.values(libraryPathByTriplet) + Object.values(libraryPathByTriplet), ); const androidLibsOutputPath = path.resolve(outputPath, androidLibsFilename); @@ -162,11 +161,11 @@ export const platform: Platform = { { text: "Assembling Android libs directory", successText: `Android libs directory assembled into ${chalk.dim( - path.relative(process.cwd(), androidLibsOutputPath) + path.relative(process.cwd(), androidLibsOutputPath), )}`, failText: ({ message }) => `Failed to assemble Android libs directory: ${message}`, - } + }, ); }, }; diff --git a/packages/cmake-rn/src/platforms/apple.ts b/packages/cmake-rn/src/platforms/apple.ts index b5ad0b1c..b65a0fed 100644 --- a/packages/cmake-rn/src/platforms/apple.ts +++ b/packages/cmake-rn/src/platforms/apple.ts @@ -1,18 +1,17 @@ import assert from "node:assert/strict"; -import path from "node:path"; import fs from "node:fs"; +import path from "node:path"; import { Option } from "@commander-js/extra-typings"; +import chalk from "chalk"; import { oraPromise } from "ora"; import { - AppleTriplet as Target, createAppleFramework, createXCframework, determineXCFrameworkFilename, + type AppleTriplet as Target, } from "react-native-node-api"; - import type { Platform } from "./types.js"; -import chalk from "chalk"; type XcodeSDKName = | "iphoneos" @@ -89,7 +88,7 @@ export function getAppleBuildArgs() { const xcframeworkExtensionOption = new Option( "--xcframework-extension", - "Don't rename the xcframework to .apple.node" + "Don't rename the xcframework to .apple.node", ).default(false); type AppleOpts = { @@ -130,19 +129,18 @@ export const platform: Platform = { // We expect the final application to sign these binaries return ["CODE_SIGNING_ALLOWED=NO"]; }, - isSupportedByHost: function (): boolean | Promise { - return process.platform === "darwin"; - }, + isSupportedByHost: (): boolean | Promise => + process.platform === "darwin", async postBuild( { outputPath, targets }, - { configuration, autoLink, xcframeworkExtension } + { configuration, autoLink, xcframeworkExtension }, ) { const libraryPaths = await Promise.all( targets.map(async ({ outputPath }) => { const configSpecificPath = path.join(outputPath, configuration); assert( fs.existsSync(configSpecificPath), - `Expected a directory at ${configSpecificPath}` + `Expected a directory at ${configSpecificPath}`, ); // Expect binary file(s), either .node or .dylib const files = await fs.promises.readdir(configSpecificPath); @@ -157,18 +155,18 @@ export const platform: Platform = { return newFilePath; } else { throw new Error( - `Expected a .node or .dylib file, but found ${file}` + `Expected a .node or .dylib file, but found ${file}`, ); } }); assert.equal(result.length, 1, "Expected exactly one library file"); return await result[0]; - }) + }), ); const frameworkPaths = libraryPaths.map(createAppleFramework); const xcframeworkFilename = determineXCFrameworkFilename( frameworkPaths, - xcframeworkExtension ? ".xcframework" : ".apple.node" + xcframeworkExtension ? ".xcframework" : ".apple.node", ); // Create the xcframework @@ -183,10 +181,10 @@ export const platform: Platform = { { text: "Assembling XCFramework", successText: `XCFramework assembled into ${chalk.dim( - path.relative(process.cwd(), xcframeworkOutputPath) + path.relative(process.cwd(), xcframeworkOutputPath), )}`, failText: ({ message }) => `Failed to assemble XCFramework: ${message}`, - } + }, ); }, }; diff --git a/packages/cmake-rn/src/platforms/types.ts b/packages/cmake-rn/src/platforms/types.ts index 5406cc48..f191408e 100644 --- a/packages/cmake-rn/src/platforms/types.ts +++ b/packages/cmake-rn/src/platforms/types.ts @@ -1,4 +1,4 @@ -import * as commander from "@commander-js/extra-typings"; +import type * as commander from "@commander-js/extra-typings"; import type { program } from "../cli.js"; type InferOptionValues = ReturnType< @@ -23,7 +23,7 @@ export type TargetContext = { export type Platform< Targets extends string[] = string[], Opts extends commander.OptionValues = Record, - Command = ExtendedCommand + Command = ExtendedCommand, > = { /** * Used to identify the platform in the CLI. @@ -54,14 +54,14 @@ export type Platform< */ configureArgs( context: TargetContext, - options: BaseOpts & Opts + options: BaseOpts & Opts, ): string[]; /** * Platform specific arguments passed to CMake to build a target project. */ buildArgs( context: TargetContext, - options: BaseOpts & Opts + options: BaseOpts & Opts, ): string[]; /** * Called to combine multiple targets into a single prebuilt artefact. @@ -74,6 +74,6 @@ export type Platform< outputPath: string; targets: TargetContext[]; }, - options: BaseOpts & Opts + options: BaseOpts & Opts, ): Promise; }; diff --git a/packages/cmake-rn/src/run.ts b/packages/cmake-rn/src/run.ts index c64a70b0..f4f89314 100644 --- a/packages/cmake-rn/src/run.ts +++ b/packages/cmake-rn/src/run.ts @@ -1,2 +1,3 @@ import { program } from "./cli.js"; + program.parse(process.argv); diff --git a/packages/cmake-rn/src/weak-node-api.ts b/packages/cmake-rn/src/weak-node-api.ts index 4db8d667..a7c3071d 100644 --- a/packages/cmake-rn/src/weak-node-api.ts +++ b/packages/cmake-rn/src/weak-node-api.ts @@ -1,16 +1,15 @@ -import fs from "node:fs"; import assert from "node:assert/strict"; +import fs from "node:fs"; import path from "node:path"; import { isAndroidTriplet, isAppleTriplet, - SupportedTriplet, + type SupportedTriplet, weakNodeApiPath, } from "react-native-node-api"; - -import { ANDROID_ARCHITECTURES } from "./platforms/android.js"; import { getNodeAddonHeadersPath, getNodeApiHeadersPath } from "./headers.js"; +import { ANDROID_ARCHITECTURES } from "./platforms/android.js"; export function toCmakePath(input: string) { return input.split(path.win32.sep).join(path.posix.sep); @@ -20,11 +19,11 @@ export function getWeakNodeApiPath(triplet: SupportedTriplet): string { if (isAppleTriplet(triplet)) { const xcframeworkPath = path.join( weakNodeApiPath, - "weak-node-api.xcframework" + "weak-node-api.xcframework", ); assert( fs.existsSync(xcframeworkPath), - `Expected an XCFramework at ${xcframeworkPath}` + `Expected an XCFramework at ${xcframeworkPath}`, ); return xcframeworkPath; } else if (isAndroidTriplet(triplet)) { @@ -32,7 +31,7 @@ export function getWeakNodeApiPath(triplet: SupportedTriplet): string { weakNodeApiPath, "weak-node-api.android.node", ANDROID_ARCHITECTURES[triplet], - "libweak-node-api.so" + "libweak-node-api.so", ); assert(fs.existsSync(libraryPath), `Expected library at ${libraryPath}`); return libraryPath; @@ -46,7 +45,7 @@ export function getWeakNodeApiVariables(triplet: SupportedTriplet) { for (const includePath of includePaths) { assert( !includePath.includes(";"), - `Include path with a ';' is not supported: ${includePath}` + `Include path with a ';' is not supported: ${includePath}`, ); } return { diff --git a/packages/ferric/src/banner.ts b/packages/ferric/src/banner.ts index c9c136f3..820b681d 100644 --- a/packages/ferric/src/banner.ts +++ b/packages/ferric/src/banner.ts @@ -25,6 +25,6 @@ export function printBanner() { LINES.map((line, lineNumber, lines) => { const ratio = lineNumber / lines.length; return chalk.rgb(Math.round(250 - 100 * ratio), 0, 0)(line); - }).join("\n") + }).join("\n"), ); } diff --git a/packages/ferric/src/build.ts b/packages/ferric/src/build.ts index 48c10d8b..109a13a7 100644 --- a/packages/ferric/src/build.ts +++ b/packages/ferric/src/build.ts @@ -1,36 +1,35 @@ -import path from "node:path"; import fs from "node:fs"; +import path from "node:path"; import { Command, Option } from "@commander-js/extra-typings"; -import chalk from "chalk"; import { SpawnFailure } from "bufout"; +import chalk from "chalk"; import { oraPromise } from "ora"; import { - determineAndroidLibsFilename, + type AndroidTriplet, createAndroidLibsDirectory, - AndroidTriplet, createAppleFramework, - determineXCFrameworkFilename, - createXCframework, createUniversalAppleLibrary, + createXCframework, + determineAndroidLibsFilename, determineLibraryBasename, + determineXCFrameworkFilename, prettyPath, } from "react-native-node-api"; - -import { UsageError, assertFixable } from "./errors.js"; -import { ensureCargo, build } from "./cargo.js"; +import { getBlockComment } from "./banner.js"; +import { build, ensureCargo } from "./cargo.js"; +import { assertFixable, UsageError } from "./errors.js"; +import { generateTypeScriptDeclarations } from "./napi-rs.js"; import { ALL_TARGETS, ANDROID_TARGETS, - AndroidTargetName, + type AndroidTargetName, APPLE_TARGETS, - AppleTargetName, + type AppleTargetName, ensureInstalledTargets, filterTargetsByPlatform, } from "./targets.js"; -import { generateTypeScriptDeclarations } from "./napi-rs.js"; -import { getBlockComment } from "./banner.js"; type EntrypointOptions = { outputPath: string; @@ -42,12 +41,11 @@ async function generateEntrypoint({ }: EntrypointOptions) { await fs.promises.writeFile( outputPath, - [ - "/* eslint-disable */", + `${[ getBlockComment(), `module.exports = require('./${libraryName}.node');`, - ].join("\n\n") + "\n", - "utf8" + ].join("\n\n")}\n`, + "utf8", ); } @@ -73,7 +71,7 @@ function getDefaultTargets() { { instructions: "Pass only valid targets via FERRIC_TARGETS (or remove them)", - } + }, ); } return result as (typeof ALL_TARGETS)[number][]; @@ -86,20 +84,20 @@ const appleTarget = new Option("--apple", "Use all Apple targets"); const androidTarget = new Option("--android", "Use all Android targets"); const ndkVersionOption = new Option( "--ndk-version ", - "The NDK version to use for Android builds" + "The NDK version to use for Android builds", ).default(DEFAULT_NDK_VERSION); const xcframeworkExtensionOption = new Option( "--xcframework-extension", - "Don't rename the xcframework to .apple.node" + "Don't rename the xcframework to .apple.node", ).default(false); const outputPathOption = new Option( "--output ", - "Writing outputs to this directory" + "Writing outputs to this directory", ).default(process.cwd()); const configurationOption = new Option( "--configuration ", - "Build configuration" + "Build configuration", ) .choices(["debug", "release"]) .default("debug"); @@ -153,11 +151,11 @@ export const buildCommand = new Command("build") chalk.yellowBright("ℹ"), chalk.dim( `Using default targets, pass ${chalk.italic( - "--android" + "--android", )}, ${chalk.italic("--apple")} or individual ${chalk.italic( - "--target" - )} options, to avoid this.` - ) + "--target", + )} options, to avoid this.`, + ), ); } ensureCargo(); @@ -169,14 +167,14 @@ export const buildCommand = new Command("build") const targetsDescription = targets.size + (targets.size === 1 ? " target" : " targets") + - chalk.dim(" (" + [...targets].join(", ") + ")"); + chalk.dim(` (${[...targets].join(", ")})`); const [appleLibraries, androidLibraries] = await oraPromise( Promise.all([ Promise.all( appleTargets.map( async (target) => - [target, await build({ configuration, target })] as const - ) + [target, await build({ configuration, target })] as const, + ), ), Promise.all( androidTargets.map( @@ -189,15 +187,15 @@ export const buildCommand = new Command("build") ndkVersion, androidApiLevel: ANDROID_API_LEVEL, }), - ] as const - ) + ] as const, + ), ), ]), { text: `Building ${targetsDescription}`, successText: `Built ${targetsDescription}`, failText: (error: Error) => `Failed to build: ${error.message}`, - } + }, ); if (androidLibraries.length > 0) { @@ -205,15 +203,15 @@ export const buildCommand = new Command("build") androidLibraries.map(([target, outputPath]) => [ ANDROID_TRIPLET_PER_TARGET[target], outputPath, - ]) + ]), ) as Record; const androidLibsFilename = determineAndroidLibsFilename( - Object.values(libraryPathByTriplet) + Object.values(libraryPathByTriplet), ); const androidLibsOutputPath = path.resolve( outputPath, - androidLibsFilename + androidLibsFilename, ); await oraPromise( @@ -225,11 +223,11 @@ export const buildCommand = new Command("build") { text: "Assembling Android libs directory", successText: `Android libs directory assembled into ${prettyPath( - androidLibsOutputPath + androidLibsOutputPath, )}`, failText: ({ message }) => `Failed to assemble Android libs directory: ${message}`, - } + }, ); } @@ -238,13 +236,13 @@ export const buildCommand = new Command("build") const frameworkPaths = libraryPaths.map(createAppleFramework); const xcframeworkFilename = determineXCFrameworkFilename( frameworkPaths, - xcframeworkExtension ? ".xcframework" : ".apple.node" + xcframeworkExtension ? ".xcframework" : ".apple.node", ); // Create the xcframework const xcframeworkOutputPath = path.resolve( outputPath, - xcframeworkFilename + xcframeworkFilename, ); await oraPromise( @@ -256,11 +254,11 @@ export const buildCommand = new Command("build") { text: "Assembling XCFramework", successText: `XCFramework assembled into ${chalk.dim( - path.relative(process.cwd(), xcframeworkOutputPath) + path.relative(process.cwd(), xcframeworkOutputPath), )}`, failText: ({ message }) => `Failed to assemble XCFramework: ${message}`, - } + }, ); } @@ -280,11 +278,11 @@ export const buildCommand = new Command("build") { text: "Generating TypeScript declarations", successText: `Generated TypeScript declarations ${prettyPath( - declarationsPath + declarationsPath, )}`, failText: (error) => `Failed to generate TypeScript declarations: ${error.message}`, - } + }, ); const entrypointPath = path.join(outputPath, `${libraryName}.js`); @@ -297,11 +295,11 @@ export const buildCommand = new Command("build") { text: `Generating entrypoint`, successText: `Generated entrypoint into ${prettyPath( - entrypointPath + entrypointPath, )}`, failText: (error) => `Failed to generate entrypoint: ${error.message}`, - } + }, ); } catch (error) { process.exitCode = 1; @@ -318,18 +316,18 @@ export const buildCommand = new Command("build") chalk.green("FIX"), error.fix.command ? chalk.dim("Run: ") + error.fix.command - : error.fix.instructions + : error.fix.instructions, ); } } else { throw error; } } - } + }, ); async function combineLibraries( - libraries: Readonly<[AppleTargetName, string]>[] + libraries: Readonly<[AppleTargetName, string]>[], ): Promise { const result = []; const darwinLibraries = []; @@ -352,7 +350,7 @@ async function combineLibraries( successText: "Combined Darwin libraries into a universal library", failText: (error) => `Failed to combine Darwin libraries: ${error.message}`, - } + }, ); return [...result, universalPath]; } diff --git a/packages/ferric/src/cargo.ts b/packages/ferric/src/cargo.ts index 16d2f38e..4e9e04b9 100644 --- a/packages/ferric/src/cargo.ts +++ b/packages/ferric/src/cargo.ts @@ -5,17 +5,15 @@ import path from "node:path"; import { spawn } from "bufout"; import chalk from "chalk"; - +import { weakNodeApiPath } from "react-native-node-api"; import { assertFixable, UsageError } from "./errors.js"; import { - AndroidTargetName, - AppleTargetName, + type AndroidTargetName, + type AppleTargetName, isAndroidTarget, isAppleTarget, } from "./targets.js"; -import { weakNodeApiPath } from "react-native-node-api"; - const APPLE_XCFRAMEWORK_CHILDS_PER_TARGET: Record = { "aarch64-apple-darwin": "macos-arm64_x86_64", // Universal "x86_64-apple-darwin": "macos-arm64_x86_64", // Universal @@ -54,7 +52,7 @@ export function ensureCargo() { } catch (error) { throw new UsageError( "You need a Rust toolchain: https://doc.rust-lang.org/cargo/getting-started/installation.html#install-rust-and-cargo", - { cause: error } + { cause: error }, ); } } @@ -87,14 +85,14 @@ export async function build(options: BuildOptions) { process.cwd(), "target", target, - configuration + configuration, ); const dynamicLibraryFile = fs .readdirSync(targetOutputPath) .filter((file) => file.endsWith(".so") || file.endsWith(".dylib")); assert( dynamicLibraryFile.length === 1, - `Expected a single shared object file in ${targetOutputPath}` + `Expected a single shared object file in ${targetOutputPath}`, ); return joinPathAndAssertExistence(targetOutputPath, dynamicLibraryFile[0]); } @@ -126,7 +124,7 @@ export function getWeakNodeApiFrameworkPath(target: AppleTargetName) { return joinPathAndAssertExistence( weakNodeApiPath, "weak-node-api.xcframework", - APPLE_XCFRAMEWORK_CHILDS_PER_TARGET[target] + APPLE_XCFRAMEWORK_CHILDS_PER_TARGET[target], ); } @@ -134,7 +132,7 @@ export function getWeakNodeApiAndroidLibraryPath(target: AndroidTargetName) { return joinPathAndAssertExistence( weakNodeApiPath, "weak-node-api.android.node", - ANDROID_ARCH_PR_TARGET[target] + ANDROID_ARCH_PR_TARGET[target], ); } @@ -152,7 +150,7 @@ export function getTargetEnvironmentVariables({ `Missing ANDROID_HOME environment variable`, { instructions: "Set ANDROID_HOME to the Android SDK directory", - } + }, ); const ndkPath = path.join(ANDROID_HOME, "ndk", ndkVersion); assertFixable(fs.existsSync(ndkPath), `Expected NDK at ${ndkPath}`, { @@ -175,35 +173,35 @@ export function getTargetEnvironmentVariables({ ].join(String.fromCharCode(0x1f)), CARGO_TARGET_AARCH64_LINUX_ANDROID_LINKER: joinPathAndAssertExistence( toolchainBinPath, - `aarch64-linux-android${androidApiLevel}-clang${cmdMaybe}` + `aarch64-linux-android${androidApiLevel}-clang${cmdMaybe}`, ), CARGO_TARGET_ARMV7_LINUX_ANDROIDEABI_LINKER: joinPathAndAssertExistence( toolchainBinPath, - `armv7a-linux-androideabi${androidApiLevel}-clang${cmdMaybe}` + `armv7a-linux-androideabi${androidApiLevel}-clang${cmdMaybe}`, ), CARGO_TARGET_X86_64_LINUX_ANDROID_LINKER: joinPathAndAssertExistence( toolchainBinPath, - `x86_64-linux-android${androidApiLevel}-clang${cmdMaybe}` + `x86_64-linux-android${androidApiLevel}-clang${cmdMaybe}`, ), CARGO_TARGET_I686_LINUX_ANDROID_LINKER: joinPathAndAssertExistence( toolchainBinPath, - `i686-linux-android${androidApiLevel}-clang${cmdMaybe}` + `i686-linux-android${androidApiLevel}-clang${cmdMaybe}`, ), TARGET_CC: joinPathAndAssertExistence( toolchainBinPath, - `${targetArch}-linux-${targetPlatform}-clang${cmdMaybe}` + `${targetArch}-linux-${targetPlatform}-clang${cmdMaybe}`, ), TARGET_CXX: joinPathAndAssertExistence( toolchainBinPath, - `${targetArch}-linux-${targetPlatform}-clang++${cmdMaybe}` + `${targetArch}-linux-${targetPlatform}-clang++${cmdMaybe}`, ), TARGET_AR: joinPathAndAssertExistence( toolchainBinPath, - `llvm-ar${exeMaybe}` + `llvm-ar${exeMaybe}`, ), TARGET_RANLIB: joinPathAndAssertExistence( toolchainBinPath, - `llvm-ranlib${exeMaybe}` + `llvm-ranlib${exeMaybe}`, ), ANDROID_NDK: ndkPath, PATH: `${toolchainBinPath}:${process.env.PATH}`, diff --git a/packages/ferric/src/errors.ts b/packages/ferric/src/errors.ts index b27489b9..fbdc8480 100644 --- a/packages/ferric/src/errors.ts +++ b/packages/ferric/src/errors.ts @@ -15,7 +15,7 @@ export class UsageError extends Error { constructor( message: string, - { fix, cause }: { cause?: unknown; fix?: Fix } = {} + { fix, cause }: { cause?: unknown; fix?: Fix } = {}, ) { super(message, { cause }); this.fix = fix; @@ -25,7 +25,7 @@ export class UsageError extends Error { export function assertFixable( value: unknown, message: string, - fix: Fix + fix: Fix, ): asserts value { try { assert(value, message); diff --git a/packages/ferric/src/napi-rs.ts b/packages/ferric/src/napi-rs.ts index 95330b39..fbba24e3 100644 --- a/packages/ferric/src/napi-rs.ts +++ b/packages/ferric/src/napi-rs.ts @@ -32,7 +32,7 @@ export async function generateTypeScriptDeclarations({ }: TypeScriptDeclarationsOptions) { // Using a temporary directory to avoid polluting crate with any other side-effects for generating TypeScript declarations const tempPath = fs.realpathSync( - fs.mkdtempSync(path.join(PACKAGE_ROOT, "dts-tmp-")) + fs.mkdtempSync(path.join(PACKAGE_ROOT, "dts-tmp-")), ); const finalOutputPath = path.join(outputPath, outputFilename); try { @@ -40,7 +40,7 @@ export async function generateTypeScriptDeclarations({ await fs.promises.writeFile( path.join(tempPath, "package.json"), "{}", - "utf8" + "utf8", ); const tempOutputPath = path.join(tempPath, outputFilename); // Call into napi.rs to generate TypeScript declarations @@ -55,12 +55,12 @@ export async function generateTypeScriptDeclarations({ // Override the banner assert( fs.existsSync(tempOutputPath), - `Expected napi.rs to emit ${tempOutputPath}` + `Expected napi.rs to emit ${tempOutputPath}`, ); const contents = await fs.promises.readFile(tempOutputPath, "utf8"); const patchedContents = contents.replace( "/* auto-generated by NAPI-RS */", - getBlockComment() + getBlockComment(), ); // Copy out the generated TypeScript declarations await fs.promises.writeFile(finalOutputPath, patchedContents, { diff --git a/packages/ferric/src/rustup.ts b/packages/ferric/src/rustup.ts index c4b101a6..36d11159 100644 --- a/packages/ferric/src/rustup.ts +++ b/packages/ferric/src/rustup.ts @@ -1,4 +1,4 @@ -import cp from "child_process"; +import cp from "node:child_process"; import { UsageError } from "./errors.js"; @@ -9,12 +9,12 @@ export function getInstalledTargets() { .execFileSync("rustup", ["target", "list", "--installed"], { encoding: "utf-8", }) - .split("\n") + .split("\n"), ); } catch (error) { throw new UsageError( "You need a Rust toolchain: https://doc.rust-lang.org/cargo/getting-started/installation.html#install-rust-and-cargo", - { cause: error } + { cause: error }, ); } } diff --git a/packages/ferric/src/targets.ts b/packages/ferric/src/targets.ts index 0ad090a4..c1990d16 100644 --- a/packages/ferric/src/targets.ts +++ b/packages/ferric/src/targets.ts @@ -66,14 +66,14 @@ export function ensureInstalledTargets(expectedTargets: Set) { `You're missing ${ missingTargets.size } targets - to fix this, run:\n\n${chalk.italic( - `rustup target add ${[...missingTargets].join(" ")}` - )}` + `rustup target add ${[...missingTargets].join(" ")}`, + )}`, ); } } export function isAndroidTarget( - target: TargetName + target: TargetName, ): target is AndroidTargetName { return ANDROID_TARGETS.includes(target as (typeof ANDROID_TARGETS)[number]); } @@ -84,15 +84,15 @@ export function isAppleTarget(target: TargetName): target is AppleTargetName { export function filterTargetsByPlatform( targets: Set, - platform: "android" + platform: "android", ): AndroidTargetName[]; export function filterTargetsByPlatform( targets: Set, - platform: "apple" + platform: "apple", ): AppleTargetName[]; export function filterTargetsByPlatform( targets: Set, - platform: "apple" | "android" + platform: "apple" | "android", ) { if (platform === "android") { return [...targets].filter(isAndroidTarget); diff --git a/packages/gyp-to-cmake/src/cli.ts b/packages/gyp-to-cmake/src/cli.ts index 77a4f92d..91b64b9c 100644 --- a/packages/gyp-to-cmake/src/cli.ts +++ b/packages/gyp-to-cmake/src/cli.ts @@ -26,7 +26,7 @@ export function transformBindingGypFile( disallowUnknownProperties, projectName = generateProjectName(gypPath), ...restOfOptions - }: TransformOptions + }: TransformOptions, ) { console.log("Transforming", gypPath); const gyp = readBindingFile(gypPath, disallowUnknownProperties); @@ -42,7 +42,7 @@ export function transformBindingGypFile( export function transformBindingGypsRecursively( directoryPath: string, - options: TransformOptions + options: TransformOptions, ) { const entries = fs.readdirSync(directoryPath, { withFileTypes: true }); for (const entry of entries) { @@ -57,11 +57,14 @@ export function transformBindingGypsRecursively( export const program = new Command("gyp-to-cmake") .description("Transform binding.gyp to CMakeLists.txt") - .option("--no-path-transforms", "Don't transform output from command expansions (replacing '\\' with '/')") + .option( + "--no-path-transforms", + "Don't transform output from command expansions (replacing '\\' with '/')", + ) .argument( "[path]", "Path to the binding.gyp file or directory to traverse recursively", - process.cwd() + process.cwd(), ) .action((targetPath: string, { pathTransforms }) => { const options: TransformOptions = { diff --git a/packages/gyp-to-cmake/src/gyp.test.ts b/packages/gyp-to-cmake/src/gyp.test.ts index 5528bff8..7c4e7b47 100644 --- a/packages/gyp-to-cmake/src/gyp.test.ts +++ b/packages/gyp-to-cmake/src/gyp.test.ts @@ -1,5 +1,5 @@ -import { describe, it } from "node:test"; import assert from "node:assert/strict"; +import { describe, it } from "node:test"; import { assertBinding } from "./gyp.js"; @@ -28,7 +28,7 @@ describe("gyp.assertRoot", () => { { targets: [{ target_name: "", sources: [], extra: "not allowed" }], }, - true + true, ); }, /Unexpected property: extra/); }); diff --git a/packages/gyp-to-cmake/src/gyp.ts b/packages/gyp-to-cmake/src/gyp.ts index fdd209ef..c1d17341 100644 --- a/packages/gyp-to-cmake/src/gyp.ts +++ b/packages/gyp-to-cmake/src/gyp.ts @@ -16,7 +16,7 @@ export type GypBinding = { function assertNoExtraProperties( input: T, - expectedKeys: string[] + expectedKeys: string[], ) { for (const key of Object.keys(input)) { if (!expectedKeys.includes(key)) { @@ -27,7 +27,7 @@ function assertNoExtraProperties( export function assertTarget( target: unknown, - disallowUnknownProperties = false + disallowUnknownProperties = false, ): asserts target is GypTarget { assert(typeof target === "object" && target !== null, "Expected an object"); assert("target_name" in target, "Expected a 'target_name' property"); @@ -36,17 +36,17 @@ export function assertTarget( assert(Array.isArray(sources), "Expected a 'sources' array"); assert( sources.every((source) => typeof source === "string"), - "Expected all sources to be strings" + "Expected all sources to be strings", ); if ("include_dirs" in target) { const { include_dirs } = target; assert( Array.isArray(include_dirs), - "Expected 'include_dirs' to be an array" + "Expected 'include_dirs' to be an array", ); assert( include_dirs.every((dir) => typeof dir === "string"), - "Expected all include_dirs to be strings" + "Expected all include_dirs to be strings", ); } if (disallowUnknownProperties) { @@ -56,7 +56,7 @@ export function assertTarget( export function assertBinding( json: unknown, - disallowUnknownProperties = false + disallowUnknownProperties = false, ): asserts json is GypBinding { assert(typeof json === "object" && json !== null, "Expected an object"); assert("targets" in json, "Expected a 'targets' property"); @@ -72,7 +72,7 @@ export function assertBinding( export function readBindingFile( path: string, - disallowUnknownProperties = false + disallowUnknownProperties = false, ): GypBinding { try { const contents = fs.readFileSync(path, "utf-8"); diff --git a/packages/gyp-to-cmake/src/run.ts b/packages/gyp-to-cmake/src/run.ts index c64a70b0..f4f89314 100644 --- a/packages/gyp-to-cmake/src/run.ts +++ b/packages/gyp-to-cmake/src/run.ts @@ -1,2 +1,3 @@ import { program } from "./cli.js"; + program.parse(process.argv); diff --git a/packages/gyp-to-cmake/src/transformer.test.ts b/packages/gyp-to-cmake/src/transformer.test.ts index cfea9e14..06d62f8f 100644 --- a/packages/gyp-to-cmake/src/transformer.test.ts +++ b/packages/gyp-to-cmake/src/transformer.test.ts @@ -46,7 +46,9 @@ describe("bindingGypToCmakeLists", () => { }, }); - assert(output.includes("add_library(foo SHARED file/with/win32/separator.cc")); + assert( + output.includes("add_library(foo SHARED file/with/win32/separator.cc"), + ); }); it("escapes spaces in source filenames", () => { @@ -117,9 +119,9 @@ describe("bindingGypToCmakeLists", () => { assert( output.includes( - "target_compile_definitions(foo PRIVATE FOO BAR=value)" + "target_compile_definitions(foo PRIVATE FOO BAR=value)", ), - `Expected output to include target_compile_definitions:\n${output}` + `Expected output to include target_compile_definitions:\n${output}`, ); }); }); diff --git a/packages/gyp-to-cmake/src/transformer.ts b/packages/gyp-to-cmake/src/transformer.ts index d6fbeb65..01096501 100644 --- a/packages/gyp-to-cmake/src/transformer.ts +++ b/packages/gyp-to-cmake/src/transformer.ts @@ -105,7 +105,7 @@ export function bindingGypToCmakeLists({ ? [ `target_compile_definitions(${targetName} PRIVATE ${escapedJoinedDefines})`, ] - : []) + : []), // or // `set_target_properties(${targetName} PROPERTIES CXX_STANDARD 11 CXX_STANDARD_REQUIRED YES CXX_EXTENSIONS NO)`, ); @@ -117,7 +117,7 @@ export function bindingGypToCmakeLists({ "if(MSVC AND CMAKE_JS_NODELIB_DEF AND CMAKE_JS_NODELIB_TARGET)", " # Generate node.lib", " execute_process(COMMAND ${CMAKE_AR} /def:${CMAKE_JS_NODELIB_DEF} /out:${CMAKE_JS_NODELIB_TARGET} ${CMAKE_STATIC_LINKER_FLAGS})", - "endif()" + "endif()", ); return lines.join("\n"); diff --git a/packages/host/scripts/generate-weak-node-api-injector.ts b/packages/host/scripts/generate-weak-node-api-injector.ts index 010288a0..7eaa4419 100644 --- a/packages/host/scripts/generate-weak-node-api-injector.ts +++ b/packages/host/scripts/generate-weak-node-api-injector.ts @@ -1,8 +1,8 @@ +import cp from "node:child_process"; import fs from "node:fs"; import path from "node:path"; -import cp from "node:child_process"; -import { FunctionDecl, getNodeApiFunctions } from "./node-api-functions"; +import { type FunctionDecl, getNodeApiFunctions } from "./node-api-functions"; export const CPP_SOURCE_PATH = path.join(__dirname, "../cpp"); @@ -63,7 +63,7 @@ export function generateSource(functions: FunctionDecl[]) { ${functions .filter( ({ kind, name }) => - kind === "engine" || IMPLEMENTED_RUNTIME_FUNCTIONS.includes(name) + kind === "engine" || IMPLEMENTED_RUNTIME_FUNCTIONS.includes(name), ) .flatMap(({ name }) => `.${name} = ${name},`) .join("\n")} diff --git a/packages/host/scripts/generate-weak-node-api.ts b/packages/host/scripts/generate-weak-node-api.ts index 23a3c89d..8177cb18 100644 --- a/packages/host/scripts/generate-weak-node-api.ts +++ b/packages/host/scripts/generate-weak-node-api.ts @@ -1,8 +1,8 @@ +import cp from "node:child_process"; import fs from "node:fs"; import path from "node:path"; -import cp from "node:child_process"; -import { FunctionDecl, getNodeApiFunctions } from "./node-api-functions"; +import { type FunctionDecl, getNodeApiFunctions } from "./node-api-functions"; export const WEAK_NODE_API_PATH = path.join(__dirname, "../weak-node-api"); @@ -21,7 +21,7 @@ export function generateHeader(functions: FunctionDecl[]) { ({ returnType, noReturn, name, argumentTypes }) => `${returnType} ${ noReturn ? " __attribute__((noreturn))" : "" - }(*${name})(${argumentTypes.join(", ")});` + }(*${name})(${argumentTypes.join(", ")});`, ), "};", "typedef void(*InjectHostFunction)(const WeakNodeApiHost&);", diff --git a/packages/host/scripts/node-api-functions.ts b/packages/host/scripts/node-api-functions.ts index ad532ae1..c2f2ee90 100644 --- a/packages/host/scripts/node-api-functions.ts +++ b/packages/host/scripts/node-api-functions.ts @@ -1,11 +1,11 @@ import assert from "node:assert/strict"; -import path from "node:path"; import cp from "node:child_process"; +import path from "node:path"; import { type NodeApiVersion, - symbols, include_dir as nodeApiIncludePath, + symbols, } from "node-api-headers"; import { z } from "zod"; @@ -20,7 +20,7 @@ const clangAstDump = z.object({ qualType: z.string(), }) .optional(), - }) + }), ), }); @@ -49,7 +49,7 @@ export function getNodeApiHeaderAST(version: NodeApiVersion) { encoding: "utf-8", // Emitting the AST can produce a lot of output maxBuffer: 1024 * 1024 * 10, - } + }, ); const parsed = JSON.parse(output); return clangAstDump.parse(parsed); @@ -86,24 +86,24 @@ export function getNodeApiFunctions(version: NodeApiVersion = "v8") { assert(node.type, `Expected type for ${node.name}`); const match = node.type.qualType.match( - /^(?[^(]+) \((?[^)]+)\)/ + /^(?[^(]+) \((?[^)]+)\)/, ); assert( - match && match.groups, - `Failed to parse function type: ${node.type.qualType}` + match?.groups, + `Failed to parse function type: ${node.type.qualType}`, ); const { returnType, argumentTypes } = match.groups; assert( returnType, - `Failed to get return type from ${node.type.qualType}` + `Failed to get return type from ${node.type.qualType}`, ); assert( argumentTypes, - `Failed to get argument types from ${argumentTypes}` + `Failed to get argument types from ${argumentTypes}`, ); assert( returnType === "napi_status" || returnType === "void", - `Expected return type to be napi_status, got ${returnType}` + `Expected return type to be napi_status, got ${returnType}`, ); nodeApiFunctions.push({ @@ -128,7 +128,7 @@ export function getNodeApiFunctions(version: NodeApiVersion = "v8") { for (const knownSymbol of allSymbols) { if (!foundSymbols.has(knownSymbol)) { throw new Error( - `Missing symbol '${knownSymbol}' in the AST for Node API ${version}` + `Missing symbol '${knownSymbol}' in the AST for Node API ${version}`, ); } } diff --git a/packages/host/src/node/babel-plugin/plugin.test.ts b/packages/host/src/node/babel-plugin/plugin.test.ts index 349864b9..a40fe195 100644 --- a/packages/host/src/node/babel-plugin/plugin.test.ts +++ b/packages/host/src/node/babel-plugin/plugin.test.ts @@ -1,11 +1,10 @@ import assert from "node:assert/strict"; -import { describe, it, TestContext } from "node:test"; import path from "node:path"; +import { describe, it, type TestContext } from "node:test"; import { transformFileSync } from "@babel/core"; - -import { plugin, PluginOptions } from "./plugin.js"; import { setupTempDirectory } from "../test-utils.js"; +import { type PluginOptions, plugin } from "./plugin.js"; type TestTransformationOptions = { files: Record; @@ -16,13 +15,13 @@ type TestTransformationOptions = { function itTransforms( title: string, - { files, inputFilePath, assertion, options = {} }: TestTransformationOptions + { files, inputFilePath, assertion, options = {} }: TestTransformationOptions, ) { it(`transforms ${title}`, (context: TestContext) => { const tempDirectoryPath = setupTempDirectory(context, files); const result = transformFileSync( path.join(tempDirectoryPath, inputFilePath), - { plugins: [[plugin, options]] } + { plugins: [[plugin, options]] }, ); assert(result, "Expected transformation to produce a result"); const { code } = result; @@ -36,12 +35,12 @@ function assertIncludes(needle: string, { reverse = false } = {}) { if (reverse) { assert( !code.includes(needle), - `Expected code to not include: ${needle}, got ${code}` + `Expected code to not include: ${needle}, got ${code}`, ); } else { assert( code.includes(needle), - `Expected code to include: ${needle}, got ${code}` + `Expected code to include: ${needle}, got ${code}`, ); } }; @@ -91,7 +90,7 @@ describe("plugin", () => { inputFilePath: "index.js", options: { pathSuffix: "keep" }, assertion: assertIncludes( - `requireNodeAddon("my-package--sub-dir-my-addon")` + `requireNodeAddon("my-package--sub-dir-my-addon")`, ), }); @@ -170,7 +169,7 @@ describe("plugin", () => { inputFilePath: "index.js", options: { pathSuffix: "keep" }, assertion: assertIncludes( - `requireNodeAddon("my-package--build-Release-my-addon")` + `requireNodeAddon("my-package--build-Release-my-addon")`, ), }); diff --git a/packages/host/src/node/babel-plugin/plugin.ts b/packages/host/src/node/babel-plugin/plugin.ts index 92792910..5db5eb3d 100644 --- a/packages/host/src/node/babel-plugin/plugin.ts +++ b/packages/host/src/node/babel-plugin/plugin.ts @@ -1,16 +1,16 @@ import assert from "node:assert/strict"; import path from "node:path"; -import type { PluginObj, NodePath } from "@babel/core"; +import type { NodePath, PluginObj } from "@babel/core"; import * as t from "@babel/types"; import { + assertPathSuffix, + findNodeAddonForBindings, getLibraryName, isNodeApiModule, - findNodeAddonForBindings, - NamingStrategy, - PathSuffixChoice, - assertPathSuffix, + type NamingStrategy, + type PathSuffixChoice, } from "../path-utils"; export type PluginOptions = { @@ -36,7 +36,7 @@ function assertOptions(opts: unknown): asserts opts is PluginOptions { export function replaceWithRequireNodeAddon( p: NodePath, modulePath: string, - naming: NamingStrategy + naming: NamingStrategy, ) { const requireCallArgument = getLibraryName(modulePath, naming); p.replaceWith( @@ -45,10 +45,10 @@ export function replaceWithRequireNodeAddon( t.callExpression(t.identifier("require"), [ t.stringLiteral("react-native-node-api"), ]), - t.identifier("requireNodeAddon") + t.identifier("requireNodeAddon"), ), - [t.stringLiteral(requireCallArgument)] - ) + [t.stringLiteral(requireCallArgument)], + ), ); } diff --git a/packages/host/src/node/cli/android.ts b/packages/host/src/node/cli/android.ts index 4acae601..a48cc36e 100644 --- a/packages/host/src/node/cli/android.ts +++ b/packages/host/src/node/cli/android.ts @@ -5,8 +5,8 @@ import path from "node:path"; import { getLatestMtime, getLibraryName, MAGIC_FILENAME } from "../path-utils"; import { getLinkedModuleOutputPath, - LinkModuleResult, type LinkModuleOptions, + type LinkModuleResult, } from "./link-modules"; const ANDROID_ARCHITECTURES = [ @@ -55,7 +55,7 @@ export async function linkAndroidDir({ const libraryPath = path.join(libraryDirent.parentPath, libraryDirent.name); await fs.promises.rename( libraryPath, - path.join(archPath, `lib${libraryName}.so`) + path.join(archPath, `lib${libraryName}.so`), ); } await fs.promises.rm(path.join(outputPath, MAGIC_FILENAME), { diff --git a/packages/host/src/node/cli/apple.ts b/packages/host/src/node/cli/apple.ts index 47be74d1..fb344caf 100644 --- a/packages/host/src/node/cli/apple.ts +++ b/packages/host/src/node/cli/apple.ts @@ -1,15 +1,15 @@ import assert from "node:assert/strict"; -import path from "node:path"; import fs from "node:fs"; import os from "node:os"; +import path from "node:path"; import { spawn } from "bufout"; import { getLatestMtime, getLibraryName } from "../path-utils.js"; import { getLinkedModuleOutputPath, - LinkModuleOptions, - LinkModuleResult, + type LinkModuleOptions, + type LinkModuleResult, } from "./link-modules.js"; type UpdateInfoPlistOptions = { @@ -30,7 +30,7 @@ export async function updateInfoPlist({ // TODO: Use a proper plist parser const updatedContents = infoPlistContents.replaceAll( oldLibraryName, - newLibraryName + newLibraryName, ); await fs.promises.writeFile(filePath, updatedContents, "utf-8"); } @@ -45,7 +45,7 @@ export async function linkXcframework({ const newLibraryName = getLibraryName(modulePath, naming); const outputPath = getLinkedModuleOutputPath(platform, modulePath, naming); const tempPath = await fs.promises.mkdtemp( - path.join(os.tmpdir(), `react-native-node-api-${newLibraryName}-`) + path.join(os.tmpdir(), `react-native-node-api-${newLibraryName}-`), ); try { if (incremental && fs.existsSync(outputPath)) { @@ -67,7 +67,7 @@ export async function linkXcframework({ // Following extracted function mimics `glob("*/*.framework/")` function globFrameworkDirs( startPath: string, - fn: (parentPath: string, name: string) => Promise + fn: (parentPath: string, name: string) => Promise, ) { return fs .readdirSync(startPath, { withFileTypes: true }) @@ -79,10 +79,11 @@ export async function linkXcframework({ .filter( (frameworkEntry) => frameworkEntry.isDirectory() && - path.extname(frameworkEntry.name) === ".framework" + path.extname(frameworkEntry.name) === ".framework", ) - .flatMap(async (frameworkEntry) => - await fn(tripletPath, frameworkEntry.name) + .flatMap( + async (frameworkEntry) => + await fn(tripletPath, frameworkEntry.name), ); }); } @@ -94,18 +95,18 @@ export async function linkXcframework({ const oldLibraryPath = path.join(frameworkPath, oldLibraryName); const newFrameworkPath = path.join( tripletPath, - `${newLibraryName}.framework` + `${newLibraryName}.framework`, ); const newLibraryPath = path.join(newFrameworkPath, newLibraryName); assert( fs.existsSync(oldLibraryPath), - `Expected a library at '${oldLibraryPath}'` + `Expected a library at '${oldLibraryPath}'`, ); // Rename the library await fs.promises.rename( oldLibraryPath, // Cannot use newLibraryPath here, because the framework isn't renamed yet - path.join(frameworkPath, newLibraryName) + path.join(frameworkPath, newLibraryName), ); // Rename the framework await fs.promises.rename(frameworkPath, newFrameworkPath); @@ -121,7 +122,7 @@ export async function linkXcframework({ ], { outputMode: "buffered", - } + }, ); // Update the Info.plist file for the framework await updateInfoPlist({ @@ -130,7 +131,7 @@ export async function linkXcframework({ newLibraryName, }); return newFrameworkPath; - }) + }), ); // Create a new xcframework from the renamed frameworks @@ -147,7 +148,7 @@ export async function linkXcframework({ ], { outputMode: "buffered", - } + }, ); return { diff --git a/packages/host/src/node/cli/hermes.ts b/packages/host/src/node/cli/hermes.ts index a7c875a5..d37872ad 100644 --- a/packages/host/src/node/cli/hermes.ts +++ b/packages/host/src/node/cli/hermes.ts @@ -3,7 +3,7 @@ import fs from "node:fs"; import path from "node:path"; import { Command } from "@commander-js/extra-typings"; -import { spawn, SpawnFailure } from "bufout"; +import { SpawnFailure, spawn } from "bufout"; import { oraPromise } from "ora"; import { packageDirectorySync } from "pkg-dir"; @@ -19,7 +19,7 @@ export const command = new Command("vendor-hermes") .option( "--force", "Don't check timestamps of input files to skip unnecessary rebuilds", - false + false, ) .action(async (from, { force, silent }) => { try { @@ -29,12 +29,12 @@ export const command = new Command("vendor-hermes") require.resolve("react-native/package.json", { // Ensures we'll be patching the React Native package actually used by the app paths: [appPackageRoot], - }) + }), ); const hermesVersionPath = path.join( reactNativePath, "sdks", - ".hermesversion" + ".hermesversion", ); const hermesVersion = fs.readFileSync(hermesVersionPath, "utf8").trim(); if (!silent) { @@ -43,7 +43,7 @@ export const command = new Command("vendor-hermes") const reactNativeJsiPath = path.join( reactNativePath, - "ReactCommon/jsi/jsi/" + "ReactCommon/jsi/jsi/", ); const hermesPath = path.join(HOST_PACKAGE_ROOT, "hermes"); @@ -56,7 +56,7 @@ export const command = new Command("vendor-hermes") failText: (error) => `Failed to remove existing Hermes clone: ${error.message}`, isEnabled: !silent, - } + }, ); } if (!fs.existsSync(hermesPath)) { @@ -77,7 +77,7 @@ export const command = new Command("vendor-hermes") ], { outputMode: "buffered", - } + }, ), { text: `Cloning custom Hermes into ${prettyPath(hermesPath)}`, @@ -85,14 +85,14 @@ export const command = new Command("vendor-hermes") failText: (err) => `Failed to clone custom Hermes: ${err.message}`, isEnabled: !silent, - } + }, ); } catch (error) { if (error instanceof SpawnFailure) { error.flushOutput("both"); console.error( `\n🛑 React Native uses the ${hermesVersion} tag and cloning our fork failed.`, - `Please see the Node-API package's peer dependency on "react-native" for supported versions.` + `Please see the Node-API package's peer dependency on "react-native" for supported versions.`, ); process.exitCode = 1; return; @@ -105,7 +105,7 @@ export const command = new Command("vendor-hermes") assert( fs.existsSync(hermesJsiPath), - `Hermes JSI path does not exist: ${hermesJsiPath}` + `Hermes JSI path does not exist: ${hermesJsiPath}`, ); await oraPromise( @@ -118,7 +118,7 @@ export const command = new Command("vendor-hermes") failText: (err) => `Failed to copy JSI from Hermes to React Native: ${err.message}`, isEnabled: !silent, - } + }, ); console.log(hermesPath); } catch (error) { diff --git a/packages/host/src/node/cli/link-modules.ts b/packages/host/src/node/cli/link-modules.ts index 5bb18d80..d6caeca1 100644 --- a/packages/host/src/node/cli/link-modules.ts +++ b/packages/host/src/node/cli/link-modules.ts @@ -1,20 +1,20 @@ -import path from "node:path"; import fs from "node:fs"; +import path from "node:path"; import { SpawnFailure } from "bufout"; +import chalk from "chalk"; import { findNodeApiModulePathsByDependency, getAutolinkPath, getLibraryName, logModulePaths, - NamingStrategy, - PlatformName, + type NamingStrategy, + type PlatformName, prettyPath, } from "../path-utils"; -import chalk from "chalk"; export type ModuleLinker = ( - options: LinkModuleOptions + options: LinkModuleOptions, ) => Promise; export type LinkModulesOptions = { @@ -71,8 +71,8 @@ export async function linkModules({ const absoluteModulePaths = Object.values(dependenciesByName).flatMap( (dependency) => dependency.modulePaths.map((modulePath) => - path.join(dependency.path, modulePath) - ) + path.join(dependency.path, modulePath), + ), ); if (hasDuplicateLibraryNames(absoluteModulePaths, naming)) { @@ -100,13 +100,13 @@ export async function linkModules({ throw error; } } - }) + }), ); } export async function pruneLinkedModules( platform: PlatformName, - linkedModules: ModuleOutput[] + linkedModules: ModuleOutput[], ) { if (linkedModules.some(({ failure }) => failure)) { // Don't prune if any of the modules failed to copy @@ -122,17 +122,17 @@ export async function pruneLinkedModules( console.log( "🧹Deleting", prettyPath(candidatePath), - chalk.dim("(no longer linked)") + chalk.dim("(no longer linked)"), ); await fs.promises.rm(candidatePath, { recursive: true, force: true }); } - }) + }), ); } export function hasDuplicateLibraryNames( modulePaths: string[], - naming: NamingStrategy + naming: NamingStrategy, ): boolean { const libraryNames = modulePaths.map((modulePath) => { return getLibraryName(modulePath, naming); @@ -144,13 +144,13 @@ export function hasDuplicateLibraryNames( export function getLinkedModuleOutputPath( platform: PlatformName, modulePath: string, - naming: NamingStrategy + naming: NamingStrategy, ): string { const libraryName = getLibraryName(modulePath, naming); if (platform === "android") { return path.join(getAutolinkPath(platform), libraryName); } else if (platform === "apple") { - return path.join(getAutolinkPath(platform), libraryName + ".xcframework"); + return path.join(getAutolinkPath(platform), `${libraryName}.xcframework`); } else { throw new Error(`Unsupported platform: ${platform}`); } diff --git a/packages/host/src/node/cli/options.ts b/packages/host/src/node/cli/options.ts index 3e8b512b..1f81f306 100644 --- a/packages/host/src/node/cli/options.ts +++ b/packages/host/src/node/cli/options.ts @@ -9,7 +9,7 @@ if (typeof NODE_API_PATH_SUFFIX === "string") { export const pathSuffixOption = new Option( "--path-suffix ", - "Controls how the path of the addon inside a package is transformed into a library name" + "Controls how the path of the addon inside a package is transformed into a library name", ) .choices(PATH_SUFFIX_CHOICES) .default(NODE_API_PATH_SUFFIX || "strip"); diff --git a/packages/host/src/node/cli/program.ts b/packages/host/src/node/cli/program.ts index 0b629245..11ace89a 100644 --- a/packages/host/src/node/cli/program.ts +++ b/packages/host/src/node/cli/program.ts @@ -14,22 +14,25 @@ import { getLibraryName, logModulePaths, normalizeModulePath, - PlatformName, PLATFORMS, + type PlatformName, prettyPath, } from "../path-utils"; - +import { linkAndroidDir } from "./android"; +import { linkXcframework } from "./apple"; import { command as vendorHermes } from "./hermes"; +import { + linkModules, + type ModuleLinker, + pruneLinkedModules, +} from "./link-modules"; import { pathSuffixOption } from "./options"; -import { linkModules, pruneLinkedModules, ModuleLinker } from "./link-modules"; -import { linkXcframework } from "./apple"; -import { linkAndroidDir } from "./android"; // We're attaching a lot of listeners when spawning in parallel EventEmitter.defaultMaxListeners = 100; export const program = new Command("react-native-node-api").addCommand( - vendorHermes + vendorHermes, ); function getLinker(platform: PlatformName): ModuleLinker { @@ -58,12 +61,12 @@ program .option( "--force", "Don't check timestamps of input files to skip unnecessary rebuilds", - false + false, ) .option( "--prune", "Delete vendored modules that are no longer auto-linked", - true + true, ) .option("--android", "Link Android modules") .option("--apple", "Link Apple modules") @@ -81,7 +84,7 @@ program if (platforms.length === 0) { console.error( `No platform specified, pass one or more of:`, - ...PLATFORMS.map((platform) => chalk.bold(`\n --${platform}`)) + ...PLATFORMS.map((platform) => chalk.bold(`\n --${platform}`)), ); process.exitCode = 1; return; @@ -101,16 +104,16 @@ program }), { text: `Linking ${platformDisplayName} Node-API modules into ${prettyPath( - platformOutputPath + platformOutputPath, )}`, successText: `Linked ${platformDisplayName} Node-API modules into ${prettyPath( - platformOutputPath + platformOutputPath, )}`, failText: (error) => `Failed to link ${platformDisplayName} Node-API modules into ${prettyPath( - platformOutputPath + platformOutputPath, )}: ${error.message}`, - } + }, ); if (modules.length === 0) { @@ -122,7 +125,7 @@ program for (const { originalPath, outputPath, skipped } of linked) { const prettyOutputPath = outputPath - ? "→ " + prettyPath(path.basename(outputPath)) + ? `→ ${prettyPath(path.basename(outputPath))}` : ""; if (skipped) { console.log( @@ -130,14 +133,14 @@ program "Skipped", prettyPath(originalPath), prettyOutputPath, - "(up to date)" + "(up to date)", ); } else { console.log( chalk.greenBright("⚭"), "Linked", prettyPath(originalPath), - prettyOutputPath + prettyOutputPath, ); } } @@ -148,7 +151,7 @@ program "\n", chalk.redBright("✖"), "Failed to copy", - prettyPath(originalPath) + prettyPath(originalPath), ); console.error(failure.message); failure.flushOutput("both"); @@ -181,7 +184,7 @@ program const dependencyCount = Object.keys(dependencies).length; const xframeworkCount = Object.values(dependencies).reduce( (acc, { modulePaths }) => acc + modulePaths.length, - 0 + 0, ); console.log( "Found", @@ -190,17 +193,17 @@ program chalk.greenBright(dependencyCount), dependencyCount === 1 ? "package" : "packages", "from", - prettyPath(rootPath) + prettyPath(rootPath), ); for (const [dependencyName, dependency] of Object.entries(dependencies)) { console.log( chalk.blueBright(dependencyName), "→", - prettyPath(dependency.path) + prettyPath(dependency.path), ); logModulePaths( dependency.modulePaths.map((p) => path.join(dependency.path, p)), - { pathSuffix } + { pathSuffix }, ); } } @@ -209,7 +212,7 @@ program program .command("info ") .description( - "Utility to print, module path, the hash of a single Android library" + "Utility to print, module path, the hash of a single Android library", ) .addOption(pathSuffixOption) .action((pathInput, { pathSuffix }) => { diff --git a/packages/host/src/node/cli/run.ts b/packages/host/src/node/cli/run.ts index ee4c5620..da5566fe 100644 --- a/packages/host/src/node/cli/run.ts +++ b/packages/host/src/node/cli/run.ts @@ -1,2 +1,3 @@ import { program } from "./program"; + program.parseAsync(process.argv).catch(console.error); diff --git a/packages/host/src/node/index.ts b/packages/host/src/node/index.ts index 878eeb01..bd2320a2 100644 --- a/packages/host/src/node/index.ts +++ b/packages/host/src/node/index.ts @@ -1,27 +1,26 @@ -export { - SUPPORTED_TRIPLETS, - ANDROID_TRIPLETS, - APPLE_TRIPLETS, - type SupportedTriplet, - type AndroidTriplet, - type AppleTriplet, - isSupportedTriplet, - isAppleTriplet, - isAndroidTriplet, -} from "./prebuilds/triplets.js"; +export { determineLibraryBasename, prettyPath } from "./path-utils.js"; export { - determineAndroidLibsFilename, createAndroidLibsDirectory, + determineAndroidLibsFilename, } from "./prebuilds/android.js"; export { createAppleFramework, - createXCframework, createUniversalAppleLibrary, + createXCframework, determineXCFrameworkFilename, } from "./prebuilds/apple.js"; - -export { determineLibraryBasename, prettyPath } from "./path-utils.js"; +export { + ANDROID_TRIPLETS, + type AndroidTriplet, + APPLE_TRIPLETS, + type AppleTriplet, + isAndroidTriplet, + isAppleTriplet, + isSupportedTriplet, + SUPPORTED_TRIPLETS, + type SupportedTriplet, +} from "./prebuilds/triplets.js"; export { weakNodeApiPath } from "./weak-node-api.js"; diff --git a/packages/host/src/node/path-utils.test.ts b/packages/host/src/node/path-utils.test.ts index 3b1fafba..f7cde5d3 100644 --- a/packages/host/src/node/path-utils.test.ts +++ b/packages/host/src/node/path-utils.test.ts @@ -1,18 +1,18 @@ import assert from "node:assert/strict"; -import { describe, it } from "node:test"; -import path from "node:path"; import fs from "node:fs"; +import path from "node:path"; +import { describe, it } from "node:test"; import fswin from "fswin"; import { determineModuleContext, - findNodeApiModulePaths, findNodeAddonForBindings, + findNodeApiModulePaths, + findNodeApiModulePathsByDependency, findPackageDependencyPaths, getLibraryName, isNodeApiModule, stripExtension, - findNodeApiModulePathsByDependency, } from "./path-utils.js"; import { setupTempDirectory } from "./test-utils.js"; @@ -75,12 +75,12 @@ describe("isNodeApiModule", () => { try { assert.equal( isNodeApiModule(path.join(tempDirectoryPath, "addon")), - false + false, ); } finally { restoreReadPermissions(tempDirectoryPath); } - } + }, ); it("throws when module file exists but is not readable", (context) => { @@ -92,7 +92,7 @@ describe("isNodeApiModule", () => { try { assert.throws( () => isNodeApiModule(path.join(tempDirectoryPath, "addon")), - /Found an unreadable module addon\.android\.node/ + /Found an unreadable module addon\.android\.node/, ); } finally { restoreReadPermissions(candidate); @@ -112,7 +112,7 @@ describe("isNodeApiModule", () => { assert.equal(isNodeApiModule(path.join(tempDirectoryPath, "addon")), true); assert.equal( isNodeApiModule(path.join(tempDirectoryPath, "addon.node")), - true + true, ); assert.equal(isNodeApiModule(path.join(tempDirectoryPath, "nope")), false); }); @@ -127,7 +127,7 @@ describe("isNodeApiModule", () => { removeReadPermissions(unreadable); assert.throws( () => isNodeApiModule(path.join(tempDirectoryPath, "addon")), - /Found an unreadable module addon\.android\.node/ + /Found an unreadable module addon\.android\.node/, ); restoreReadPermissions(unreadable); }); @@ -151,7 +151,7 @@ describe("determineModuleContext", () => { { const { packageName, relativePath } = determineModuleContext( - path.join(tempDirectoryPath, "some-dir/some-file.node") + path.join(tempDirectoryPath, "some-dir/some-file.node"), ); assert.equal(packageName, "my-package"); assert.equal(relativePath, "some-dir/some-file"); @@ -165,7 +165,7 @@ describe("determineModuleContext", () => { { const { packageName, relativePath } = determineModuleContext( - path.join(tempDirectoryPath, "some-dir/libsome-file.node") + path.join(tempDirectoryPath, "some-dir/libsome-file.node"), ); assert.equal(packageName, "my-package"); assert.equal(relativePath, "some-dir/some-file"); @@ -182,7 +182,7 @@ describe("determineModuleContext", () => { { const { packageName, relativePath } = determineModuleContext( - path.join(tempDirectoryPath, "sub-package-a/some-file.node") + path.join(tempDirectoryPath, "sub-package-a/some-file.node"), ); assert.equal(packageName, "my-sub-package-a"); assert.equal(relativePath, "some-file"); @@ -190,7 +190,7 @@ describe("determineModuleContext", () => { { const { packageName, relativePath } = determineModuleContext( - path.join(tempDirectoryPath, "sub-package-b/some-file.node") + path.join(tempDirectoryPath, "sub-package-b/some-file.node"), ); assert.equal(packageName, "my-sub-package-b"); assert.equal(relativePath, "some-file"); @@ -210,14 +210,14 @@ describe("getLibraryName", () => { getLibraryName(path.join(tempDirectoryPath, "addon"), { pathSuffix: "keep", }), - "my-package--addon" + "my-package--addon", ); assert.equal( getLibraryName(path.join(tempDirectoryPath, "sub-directory/addon"), { pathSuffix: "keep", }), - "my-package--sub-directory-addon" + "my-package--sub-directory-addon", ); }); @@ -232,14 +232,14 @@ describe("getLibraryName", () => { getLibraryName(path.join(tempDirectoryPath, "addon"), { pathSuffix: "strip", }), - "my-package--addon" + "my-package--addon", ); assert.equal( getLibraryName(path.join(tempDirectoryPath, "sub-directory", "addon"), { pathSuffix: "strip", }), - "my-package--addon" + "my-package--addon", ); }); @@ -254,14 +254,14 @@ describe("getLibraryName", () => { getLibraryName(path.join(tempDirectoryPath, "addon"), { pathSuffix: "omit", }), - "my-package" + "my-package", ); assert.equal( getLibraryName(path.join(tempDirectoryPath, "sub-directory", "addon"), { pathSuffix: "omit", }), - "my-package" + "my-package", ); }); }); @@ -296,7 +296,7 @@ describe("findPackageDependencyPaths", () => { }); const result = findPackageDependencyPaths( - path.join(tempDir, "test-package/src/index.js") + path.join(tempDir, "test-package/src/index.js"), ); assert.deepEqual(result, { @@ -394,7 +394,7 @@ describe("findNodeApiModulePaths", () => { } finally { restoreReadPermissions(tempDir); } - } + }, ); }); @@ -405,7 +405,7 @@ describe("findNodeApiModulePathsByDependency", () => { "app/package.json": JSON.stringify({ name: "app", dependencies: Object.fromEntries( - packagesNames.map((packageName) => [packageName, "^1.0.0"]) + packagesNames.map((packageName) => [packageName, "^1.0.0"]), ), }), ...Object.fromEntries( @@ -419,7 +419,7 @@ describe("findNodeApiModulePathsByDependency", () => { "index.js": "", "addon.apple.node/react-native-node-api-module": "", }, - ]) + ]), ), }); @@ -461,14 +461,14 @@ describe("determineModuleContext", () => { readCount++; } return orig(...args); - } + }, ); const ctx1 = determineModuleContext( - path.join(tempDir, "subdir1/file1.node") + path.join(tempDir, "subdir1/file1.node"), ); const ctx2 = determineModuleContext( - path.join(tempDir, "subdir2/file2.node") + path.join(tempDir, "subdir2/file2.node"), ); assert.equal(ctx1.packageName, "cached-pkg"); assert.equal(ctx2.packageName, "cached-pkg"); @@ -497,7 +497,7 @@ describe("findNodeAddonForBindings()", () => { // Act const actualPath = await findNodeAddonForBindings( name, - tempDirectoryPath + tempDirectoryPath, ); // Assert const expectedAbsPath = path.join(tempDirectoryPath, relPath); diff --git a/packages/host/src/node/path-utils.ts b/packages/host/src/node/path-utils.ts index c92115cc..60a06a4d 100644 --- a/packages/host/src/node/path-utils.ts +++ b/packages/host/src/node/path-utils.ts @@ -1,11 +1,11 @@ import assert from "node:assert/strict"; -import path from "node:path"; import fs from "node:fs"; -import { findDuplicates } from "./duplicates"; +import { createRequire } from "node:module"; +import path from "node:path"; import chalk from "chalk"; import { packageDirectorySync } from "pkg-dir"; import { readPackageSync } from "read-pkg"; -import { createRequire } from "node:module"; +import { findDuplicates } from "./duplicates"; // TODO: Change to .apple.node export const PLATFORMS = ["android", "apple"] as const; @@ -22,15 +22,15 @@ export const PATH_SUFFIX_CHOICES = ["strip", "keep", "omit"] as const; export type PathSuffixChoice = (typeof PATH_SUFFIX_CHOICES)[number]; export function assertPathSuffix( - value: unknown + value: unknown, ): asserts value is PathSuffixChoice { assert( typeof value === "string", - `Expected a string, got ${typeof value} (${value})` + `Expected a string, got ${typeof value} (${value})`, ); assert( (PATH_SUFFIX_CHOICES as readonly string[]).includes(value), - `Expected one of ${PATH_SUFFIX_CHOICES.join(", ")}` + `Expected one of ${PATH_SUFFIX_CHOICES.join(", ")}`, ); } @@ -57,16 +57,14 @@ const packageNameCache = new Map(); * TODO: Consider checking for a specific platform extension. */ export function isNodeApiModule(modulePath: string): boolean { - { - // HACK: Take a shortcut (if applicable): existing `.node` files are addons - try { - fs.accessSync( - modulePath.endsWith(".node") ? modulePath : `${modulePath}.node` - ); - return true; - } catch { - // intentionally left empty - } + // HACK: Take a shortcut (if applicable): existing `.node` files are addons + try { + fs.accessSync( + modulePath.endsWith(".node") ? modulePath : `${modulePath}.node`, + ); + return true; + } catch { + // intentionally left empty } const dir = path.dirname(modulePath); const baseName = path.basename(modulePath, ".node"); @@ -131,7 +129,7 @@ export function stripExtension(modulePath: string) { return modulePath; } }, - modulePath + modulePath, ); } @@ -145,7 +143,7 @@ export type ModuleContext = { */ export function determineModuleContext( modulePath: string, - originalPath = modulePath + originalPath = modulePath, ): ModuleContext { // Locate nearest package directory const pkgDir = packageDirectorySync({ cwd: modulePath }); @@ -158,7 +156,7 @@ export function determineModuleContext( const pkg = readPackageSync({ cwd: pkgDir }); assert( typeof pkg.name === "string", - "Expected package.json to have a name" + "Expected package.json to have a name", ); pkgName = pkg.name; packageNameCache.set(pkgDir, pkgName); @@ -191,19 +189,19 @@ export function getLibraryName(modulePath: string, naming: NamingStrategy) { : `${escapedPackageName}--${escapePath( naming.pathSuffix === "strip" ? path.basename(relativePath) - : relativePath + : relativePath, )}`; } export function prettyPath(p: string) { return chalk.dim( - path.relative(process.cwd(), p) || chalk.italic("current directory") + path.relative(process.cwd(), p) || chalk.italic("current directory"), ); } export function resolvePackageRoot( requireFromPackageRoot: NodeJS.Require, - packageName: string + packageName: string, ): string | undefined { try { const resolvedPath = requireFromPackageRoot.resolve(packageName); @@ -217,7 +215,7 @@ export function resolvePackageRoot( export function logModulePaths( modulePaths: string[], // TODO: Default to iterating and printing for all supported naming strategies - naming: NamingStrategy + naming: NamingStrategy, ) { const pathsPerName = new Map(); for (const modulePath of modulePaths) { @@ -237,7 +235,7 @@ export function logModulePaths( ? chalk.redBright(prettyPath(modulePath)) : prettyPath(modulePath); return `\n ↳ ${line}`; - }) + }), ); } } @@ -247,13 +245,13 @@ export function logModulePaths( * return a record mapping from each dependencies of that package to their path on disk. */ export function findPackageDependencyPaths( - fromPath: string + fromPath: string, ): Record { const packageRoot = packageDirectorySync({ cwd: fromPath }); assert(packageRoot, `Could not find package root from ${fromPath}`); const requireFromPackageRoot = createRequire( - path.join(packageRoot, "noop.js") + path.join(packageRoot, "noop.js"), ); const { dependencies = {} } = readPackageSync({ cwd: packageRoot }); @@ -263,13 +261,13 @@ export function findPackageDependencyPaths( .map((dependencyName) => { const resolvedDependencyRoot = resolvePackageRoot( requireFromPackageRoot, - dependencyName + dependencyName, ); return resolvedDependencyRoot ? [dependencyName, resolvedDependencyRoot] : undefined; }) - .filter((item) => typeof item !== "undefined") + .filter((item) => typeof item !== "undefined"), ); } @@ -285,7 +283,7 @@ export const DEFAULT_EXCLUDE_PATTERNS = [ export function hasPlatformExtension( platform: PlatformName | Readonly, - fileName: string + fileName: string, ): boolean { if (typeof platform === "string") { return fileName.endsWith(PLATFORM_EXTENSIONS[platform]); @@ -305,7 +303,7 @@ export type FindNodeApiModuleOptions = { */ export async function findNodeApiModulePaths( options: FindNodeApiModuleOptions, - suffix = "" + suffix = "", ): Promise { const { fromPath, @@ -338,7 +336,7 @@ export async function findNodeApiModulePaths( // Traverse into the child directory // Pushing result into a list instead of awaiting immediately to parallelize the search pendingResults.push( - findNodeApiModulePaths(options, path.join(suffix, dirent.name)) + findNodeApiModulePaths(options, path.join(suffix, dirent.name)), ); } } @@ -354,7 +352,7 @@ export async function findNodeApiModulePaths( throw error; } const childResults = await Promise.all(pendingResults); - result.push(...childResults.flatMap((filePath) => filePath)); + result.push(...childResults.flat()); return result; } @@ -402,16 +400,16 @@ export async function findNodeApiModulePathsByDependency({ { path: dependencyPath, modulePaths: absoluteModulePaths.map((p) => - path.relative(dependencyPath, p) + path.relative(dependencyPath, p), ), }, ] as const; - }) + }), ); // Return an object by dependency name return Object.fromEntries( // Remove any dependencies without Node-API module paths - resultEntries.filter(([, { modulePaths }]) => modulePaths.length > 0) + resultEntries.filter(([, { modulePaths }]) => modulePaths.length > 0), ); } @@ -422,16 +420,18 @@ export async function findNodeApiModulePathsByDependency({ export function determineLibraryBasename(libraryPaths: string[]) { assert( libraryPaths.length > 0, - "Expected at least one library path to determine its basename" + "Expected at least one library path to determine its basename", ); const libraryNames = libraryPaths.map((p) => // Strip the "lib" prefix and any file extension - path.basename(p, path.extname(p)).replace(/^lib/, "") + path + .basename(p, path.extname(p)) + .replace(/^lib/, ""), ); const candidates = new Set(libraryNames); assert( candidates.size === 1, - `Expected all libraries to share name, got: ${[...candidates].join(", ")}` + `Expected all libraries to share name, got: ${[...candidates].join(", ")}`, ); const [name] = candidates; return name; diff --git a/packages/host/src/node/prebuilds/android.ts b/packages/host/src/node/prebuilds/android.ts index b999d8e3..9c750059 100644 --- a/packages/host/src/node/prebuilds/android.ts +++ b/packages/host/src/node/prebuilds/android.ts @@ -1,9 +1,8 @@ import assert from "node:assert/strict"; import fs from "node:fs"; import path from "node:path"; - -import { AndroidTriplet } from "./triplets.js"; import { determineLibraryBasename } from "../path-utils.js"; +import type { AndroidTriplet } from "./triplets.js"; export const DEFAULT_ANDROID_TRIPLETS = [ "aarch64-linux-android", @@ -47,7 +46,7 @@ export async function createAndroidLibsDirectory({ for (const [triplet, libraryPath] of Object.entries(libraryPathByTriplet)) { assert( fs.existsSync(libraryPath), - `Library not found: ${libraryPath} for triplet ${triplet}` + `Library not found: ${libraryPath} for triplet ${triplet}`, ); const arch = ANDROID_ARCHITECTURES[triplet as AndroidTriplet]; const archOutputPath = path.join(outputPath, arch); @@ -68,7 +67,7 @@ export async function createAndroidLibsDirectory({ await fs.promises.writeFile( path.join(outputPath, "react-native-node-api-module"), "", - "utf8" + "utf8", ); } return outputPath; diff --git a/packages/host/src/node/prebuilds/apple.ts b/packages/host/src/node/prebuilds/apple.ts index 769f7857..e727ec27 100644 --- a/packages/host/src/node/prebuilds/apple.ts +++ b/packages/host/src/node/prebuilds/apple.ts @@ -1,13 +1,12 @@ import assert from "node:assert/strict"; +import cp from "node:child_process"; import fs from "node:fs"; -import path from "node:path"; import os from "node:os"; -import cp from "node:child_process"; +import path from "node:path"; import { spawn } from "bufout"; - -import { AppleTriplet } from "./triplets.js"; import { determineLibraryBasename } from "../path-utils.js"; +import type { AppleTriplet } from "./triplets.js"; type AppleArchitecture = "arm64" | "x86_64" | "arm64;x86_64"; @@ -51,7 +50,7 @@ export function createAppleFramework(libraryPath: string) { const libraryName = path.basename(libraryPath, path.extname(libraryPath)); const frameworkPath = path.join( path.dirname(libraryPath), - `${libraryName}.framework` + `${libraryName}.framework`, ); // Create the framework from scratch fs.rmSync(frameworkPath, { recursive: true, force: true }); @@ -71,7 +70,7 @@ export function createAppleFramework(libraryPath: string) { CFBundleVersion: "1", NSPrincipalClass: "", }), - "utf8" + "utf8", ); const newLibraryPath = path.join(frameworkPath, libraryName); // TODO: Consider copying the library instead of renaming it @@ -111,7 +110,7 @@ export async function createXCframework({ ], { outputMode: "buffered", - } + }, ); if (xcodeOutputPath !== outputPath) { // Rename the xcframework to the original output path @@ -123,7 +122,7 @@ export async function createXCframework({ fs.writeFileSync( path.join(outputPath, "react-native-node-api-module"), "", - "utf8" + "utf8", ); } } @@ -134,7 +133,7 @@ export async function createXCframework({ */ export function determineXCFrameworkFilename( frameworkPaths: string[], - extension: ".xcframework" | ".apple.node" = ".xcframework" + extension: ".xcframework" | ".apple.node" = ".xcframework", ) { const name = determineLibraryBasename(frameworkPaths); return `${name}${extension}`; @@ -145,11 +144,11 @@ export async function createUniversalAppleLibrary(libraryPaths: string[]) { const filenames = new Set(libraryPaths.map((p) => path.basename(p))); assert( filenames.size === 1, - "Expected all darwin libraries to have the same name" + "Expected all darwin libraries to have the same name", ); const [filename] = filenames; const lipoParentPath = fs.realpathSync( - fs.mkdtempSync(path.join(os.tmpdir(), "ferric-lipo-output-")) + fs.mkdtempSync(path.join(os.tmpdir(), "ferric-lipo-output-")), ); const outputPath = path.join(lipoParentPath, filename); await spawn("lipo", ["-create", "-output", outputPath, ...libraryPaths], { diff --git a/packages/host/src/node/prebuilds/triplets.ts b/packages/host/src/node/prebuilds/triplets.ts index 60bff46f..7471b15b 100644 --- a/packages/host/src/node/prebuilds/triplets.ts +++ b/packages/host/src/node/prebuilds/triplets.ts @@ -33,19 +33,19 @@ export const SUPPORTED_TRIPLETS = [ export type SupportedTriplet = (typeof SUPPORTED_TRIPLETS)[number]; export function isSupportedTriplet( - triplet: unknown + triplet: unknown, ): triplet is SupportedTriplet { return (SUPPORTED_TRIPLETS as readonly unknown[]).includes(triplet); } export function isAndroidTriplet( - triplet: SupportedTriplet + triplet: SupportedTriplet, ): triplet is AndroidTriplet { return (ANDROID_TRIPLETS as readonly unknown[]).includes(triplet); } export function isAppleTriplet( - triplet: SupportedTriplet + triplet: SupportedTriplet, ): triplet is AppleTriplet { return (APPLE_TRIPLETS as readonly unknown[]).includes(triplet); } diff --git a/packages/host/src/node/test-utils.ts b/packages/host/src/node/test-utils.ts index 3fd67386..a1791502 100644 --- a/packages/host/src/node/test-utils.ts +++ b/packages/host/src/node/test-utils.ts @@ -1,7 +1,7 @@ -import { TestContext } from "node:test"; -import os from "node:os"; import fs from "node:fs"; +import os from "node:os"; import path from "node:path"; +import type { TestContext } from "node:test"; export interface FileMap { [key: string]: string | FileMap; @@ -21,7 +21,7 @@ function writeFiles(fromPath: string, files: FileMap) { export function setupTempDirectory(context: TestContext, files: FileMap) { const tempDirectoryPath = fs.realpathSync( - fs.mkdtempSync(path.join(os.tmpdir(), "react-native-node-api-test-")) + fs.mkdtempSync(path.join(os.tmpdir(), "react-native-node-api-test-")), ); context.after(() => { diff --git a/packages/host/src/node/weak-node-api.ts b/packages/host/src/node/weak-node-api.ts index df29834f..02e3befe 100644 --- a/packages/host/src/node/weak-node-api.ts +++ b/packages/host/src/node/weak-node-api.ts @@ -6,5 +6,5 @@ export const weakNodeApiPath = path.resolve(__dirname, "../../weak-node-api"); assert( fs.existsSync(weakNodeApiPath), - `Expected Weak Node API path to exist: ${weakNodeApiPath}` + `Expected Weak Node API path to exist: ${weakNodeApiPath}`, ); diff --git a/packages/node-addon-examples/scripts/build-examples.mts b/packages/node-addon-examples/scripts/build-examples.mts index a8d587e9..fd590eb6 100644 --- a/packages/node-addon-examples/scripts/build-examples.mts +++ b/packages/node-addon-examples/scripts/build-examples.mts @@ -13,7 +13,7 @@ for (const projectDirectory of projectDirectories) { { cwd: projectDirectory, stdio: "inherit", - } + }, ); console.log(); } diff --git a/packages/node-addon-examples/scripts/copy-examples.mts b/packages/node-addon-examples/scripts/copy-examples.mts index 426f07dd..1c8eb845 100644 --- a/packages/node-addon-examples/scripts/copy-examples.mts +++ b/packages/node-addon-examples/scripts/copy-examples.mts @@ -1,5 +1,5 @@ -import { createRequire } from "node:module"; import fs from "node:fs"; +import { createRequire } from "node:module"; import path from "node:path"; import { readPackageSync } from "read-pkg"; @@ -58,7 +58,7 @@ console.log("Copying files to", EXAMPLES_DIR); const require = createRequire(import.meta.url); const EXAMPLES_PACKAGE_PATH = require.resolve( - "node-addon-examples/package.json" + "node-addon-examples/package.json", ); const SRC_DIR = path.join(path.dirname(EXAMPLES_PACKAGE_PATH), "src"); console.log("Copying files from", SRC_DIR); @@ -73,7 +73,7 @@ for (const src of ALLOW_LIST) { if (fs.existsSync(destPath)) { console.warn( - `Destination path ${destPath} already exists - skipping copy of ${src}.` + `Destination path ${destPath} already exists - skipping copy of ${src}.`, ); continue; } @@ -93,7 +93,7 @@ for (const src of ALLOW_LIST) { fs.writeFileSync( path.join(entry.parentPath, entry.name), JSON.stringify(packageJson, null, 2), - "utf-8" + "utf-8", ); } } diff --git a/packages/node-addon-examples/scripts/verify-prebuilds.mts b/packages/node-addon-examples/scripts/verify-prebuilds.mts index 666eeba3..498b9e73 100644 --- a/packages/node-addon-examples/scripts/verify-prebuilds.mts +++ b/packages/node-addon-examples/scripts/verify-prebuilds.mts @@ -1,5 +1,5 @@ -import fs from "node:fs"; import assert from "node:assert/strict"; +import fs from "node:fs"; import path from "node:path"; import { EXAMPLES_DIR } from "./cmake-projects.mjs"; @@ -21,7 +21,7 @@ async function verifyAndroidPrebuild(dirent: fs.Dirent) { "Verifying Android prebuild", dirent.name, "in", - dirent.parentPath + dirent.parentPath, ); for (const arch of EXPECTED_ANDROID_ARCHS) { const archDir = path.join(dirent.parentPath, dirent.name, arch); @@ -31,7 +31,7 @@ async function verifyAndroidPrebuild(dirent: fs.Dirent) { assert(file.isFile()); assert( !file.name.endsWith(".node"), - `Unexpected .node file: ${path.join(file.parentPath, file.name)}` + `Unexpected .node file: ${path.join(file.parentPath, file.name)}`, ); } } @@ -46,7 +46,7 @@ async function verifyApplePrebuild(dirent: fs.Dirent) { })) { assert( file.isDirectory(), - "Expected only directories in xcframework arch directory" + "Expected only directories in xcframework arch directory", ); assert(file.name.endsWith(".framework"), "Expected framework directory"); const frameworkDir = path.join(file.parentPath, file.name); @@ -57,23 +57,21 @@ async function verifyApplePrebuild(dirent: fs.Dirent) { assert.equal( file.name, "Headers", - "Unexpected directory in xcframework" + "Unexpected directory in xcframework", ); } else { assert( file.isFile(), - "Expected only directory and files in framework" + "Expected only directory and files in framework", ); if (file.name === "Info.plist") { - // TODO: Verify the contents of the Info.plist file - continue; } else { assert( !file.name.endsWith(".node"), `Didn't expected a .node file in xcframework: ${path.join( frameworkDir, - file.name - )}` + file.name, + )}`, ); } } @@ -92,7 +90,7 @@ for await (const dirent of fs.promises.glob("**/*.*.node", { await verifyApplePrebuild(dirent); } else { throw new Error( - `Unexpected prebuild file: ${dirent.name} in ${dirent.parentPath}` + `Unexpected prebuild file: ${dirent.name} in ${dirent.parentPath}`, ); } } diff --git a/packages/node-addon-examples/src/index.ts b/packages/node-addon-examples/src/index.ts index d2228f84..196810a1 100644 --- a/packages/node-addon-examples/src/index.ts +++ b/packages/node-addon-examples/src/index.ts @@ -1,5 +1,3 @@ -/* eslint-disable @typescript-eslint/no-require-imports */ - function assertLogs(cb: () => void, expectedMessages: string[]) { const errors: Error[] = []; // Spying on the console.log function, as the examples don't assert anything themselves @@ -15,7 +13,9 @@ function assertLogs(cb: () => void, expectedMessages: string[]) { cb(); if (expectedMessages.length > 0) { errors.push( - new Error(`Missing expected message(s): ${expectedMessages.join(", ")}`) + new Error( + `Missing expected message(s): ${expectedMessages.join(", ")}`, + ), ); } } finally { @@ -30,6 +30,7 @@ function assertLogs(cb: () => void, expectedMessages: string[]) { export const suites: Record< string, + // biome-ignore lint/suspicious/noConfusingVoidType: Unknown Record void | (() => void)> > = { "1-getting-started": { @@ -37,61 +38,61 @@ export const suites: Record< assertLogs( () => require("../examples/1-getting-started/1_hello_world/napi/hello.js"), - ["world"] + ["world"], ), "1_hello_world/node-addon-api": () => assertLogs( () => require("../examples/1-getting-started/1_hello_world/node-addon-api/hello.js"), - ["world"] + ["world"], ), "1_hello_world/node-addon-api-addon-class": () => assertLogs( () => require("../examples/1-getting-started/1_hello_world/node-addon-api-addon-class/hello.js"), - ["world"] + ["world"], ), "2_function_arguments/napi": () => assertLogs( () => require("../examples/1-getting-started/2_function_arguments/napi/addon.js"), - ["This should be eight: 8"] + ["This should be eight: 8"], ), "2_function_arguments/node-addon-api": () => assertLogs( () => require("../examples/1-getting-started/2_function_arguments/node-addon-api/addon.js"), - ["This should be eight: 8"] + ["This should be eight: 8"], ), "3_callbacks/napi": () => assertLogs( () => require("../examples/1-getting-started/3_callbacks/napi/addon.js"), - ["hello world"] + ["hello world"], ), "3_callbacks/node-addon-api": () => assertLogs( () => require("../examples/1-getting-started/3_callbacks/node-addon-api/addon.js"), - ["hello world"] + ["hello world"], ), "4_object_factory/napi": () => assertLogs( () => require("../examples/1-getting-started/4_object_factory/napi/addon.js"), - ["hello world"] + ["hello world"], ), "4_object_factory/node-addon-api": () => assertLogs( () => require("../examples/1-getting-started/4_object_factory/node-addon-api/addon.js"), - ["hello world"] + ["hello world"], ), "5_function_factory": () => assertLogs( () => require("../examples/1-getting-started/5_function_factory/napi/addon.js"), - ["hello world"] + ["hello world"], ), }, "5-async-work": { diff --git a/packages/node-addon-examples/tests/async/addon.js b/packages/node-addon-examples/tests/async/addon.js index f30d87d2..10fad839 100644 --- a/packages/node-addon-examples/tests/async/addon.js +++ b/packages/node-addon-examples/tests/async/addon.js @@ -1,6 +1,4 @@ -/* eslint-disable @typescript-eslint/no-require-imports */ -/* eslint-disable no-undef */ -const assert = require("assert"); +const assert = require("node:assert"); const test_async = require("bindings")("addon.node"); const test = () => diff --git a/packages/node-addon-examples/tests/buffers/addon.js b/packages/node-addon-examples/tests/buffers/addon.js index a5ccd75f..3e9919f8 100644 --- a/packages/node-addon-examples/tests/buffers/addon.js +++ b/packages/node-addon-examples/tests/buffers/addon.js @@ -1,8 +1,7 @@ -/* eslint-disable @typescript-eslint/no-require-imports */ -/* eslint-disable no-undef */ -const assert = require("assert"); +const assert = require("node:assert"); const addon = require("bindings")("addon.node"); +// biome-ignore lint/suspicious/noShadowRestrictedNames: Unknown const toLocaleString = (text) => { return text .toString() @@ -15,7 +14,7 @@ module.exports = () => { assert.strictEqual(toLocaleString(addon.newBuffer()), addon.theText); assert.strictEqual(toLocaleString(addon.newExternalBuffer()), addon.theText); assert.strictEqual(toLocaleString(addon.copyBuffer()), addon.theText); - let buffer = addon.staticBuffer(); + const buffer = addon.staticBuffer(); assert.strictEqual(addon.bufferHasInstance(buffer), true); assert.strictEqual(addon.bufferInfo(buffer), true); addon.invalidObjectAsBuffer({}); From 3a1ac34d68744647bed509bb99f72882435804f2 Mon Sep 17 00:00:00 2001 From: Douglas Galdino Date: Thu, 24 Jul 2025 19:16:09 -0300 Subject: [PATCH 2/3] added changeset --- .changeset/brown-chefs-fetch.md | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 .changeset/brown-chefs-fetch.md diff --git a/.changeset/brown-chefs-fetch.md b/.changeset/brown-chefs-fetch.md new file mode 100644 index 00000000..dfb51c6e --- /dev/null +++ b/.changeset/brown-chefs-fetch.md @@ -0,0 +1,9 @@ +--- +"gyp-to-cmake": patch +"cmake-rn": patch +"ferric-cli": patch +"@react-native-node-api/test-app": patch +"react-native-node-api": patch +--- + +Replaced ESLint with Biome as Linter, Formatter and Sort Organizer From 234c927299a5ae6fef743ebd095225f0332724c8 Mon Sep 17 00:00:00 2001 From: Douglas Galdino Date: Thu, 24 Jul 2025 21:05:47 -0300 Subject: [PATCH 3/3] removed trailing comma from linter --- apps/test-app/App.tsx | 20 +-- apps/test-app/babel.config.js | 2 +- apps/test-app/metro.config.js | 8 +- apps/test-app/react-native.config.js | 10 +- biome.json | 5 + packages/cmake-rn/src/cli.ts | 76 ++++----- packages/cmake-rn/src/headers.ts | 12 +- packages/cmake-rn/src/platforms.test.ts | 2 +- packages/cmake-rn/src/platforms.ts | 4 +- packages/cmake-rn/src/platforms/android.ts | 42 ++--- packages/cmake-rn/src/platforms/apple.ts | 38 ++--- packages/cmake-rn/src/platforms/types.ts | 8 +- packages/cmake-rn/src/weak-node-api.ts | 12 +- packages/ferric/src/banner.ts | 4 +- packages/ferric/src/build.ts | 108 ++++++------ packages/ferric/src/cargo.ts | 54 +++--- packages/ferric/src/errors.ts | 4 +- packages/ferric/src/napi-rs.ts | 14 +- packages/ferric/src/rustup.ts | 6 +- packages/ferric/src/targets.ts | 18 +- packages/gyp-to-cmake/src/cli.ts | 14 +- packages/gyp-to-cmake/src/gyp.test.ts | 4 +- packages/gyp-to-cmake/src/gyp.ts | 14 +- packages/gyp-to-cmake/src/transformer.test.ts | 58 +++---- packages/gyp-to-cmake/src/transformer.ts | 10 +- packages/host/react-native.config.js | 6 +- .../generate-weak-node-api-injector.ts | 4 +- .../host/scripts/generate-weak-node-api.ts | 8 +- packages/host/scripts/node-api-functions.ts | 30 ++-- .../host/src/node/babel-plugin/plugin.test.ts | 52 +++--- packages/host/src/node/babel-plugin/plugin.ts | 18 +- packages/host/src/node/cli/android.ts | 16 +- packages/host/src/node/cli/apple.ts | 44 ++--- packages/host/src/node/cli/hermes.ts | 34 ++-- packages/host/src/node/cli/link-modules.ts | 28 ++-- packages/host/src/node/cli/options.ts | 2 +- packages/host/src/node/cli/program.ts | 46 +++--- packages/host/src/node/index.ts | 6 +- packages/host/src/node/path-utils.test.ts | 156 +++++++++--------- packages/host/src/node/path-utils.ts | 68 ++++---- packages/host/src/node/prebuilds/android.ts | 10 +- packages/host/src/node/prebuilds/apple.ts | 32 ++-- packages/host/src/node/prebuilds/triplets.ts | 12 +- packages/host/src/node/test-utils.ts | 2 +- packages/host/src/node/weak-node-api.ts | 2 +- .../scripts/build-examples.mts | 4 +- .../scripts/copy-examples.mts | 10 +- .../scripts/verify-prebuilds.mts | 26 +-- packages/node-addon-examples/src/index.ts | 30 ++-- 49 files changed, 598 insertions(+), 595 deletions(-) diff --git a/apps/test-app/App.tsx b/apps/test-app/App.tsx index 497f735b..ddf4098c 100644 --- a/apps/test-app/App.tsx +++ b/apps/test-app/App.tsx @@ -3,7 +3,7 @@ import { ConnectionText, MochaRemoteProvider, StatusEmoji, - StatusText, + StatusText } from "mocha-remote-react-native"; // biome-ignore lint/correctness/noUnusedImports: Keep React import React from "react"; @@ -12,7 +12,7 @@ import { SafeAreaView, StyleSheet, View } from "react-native"; function describeIf( condition: boolean, title: string, - fn: (this: Mocha.Suite) => void, + fn: (this: Mocha.Suite) => void ) { return condition ? describe(title, fn) : describe.skip(title, fn); } @@ -26,11 +26,11 @@ type Context = { function loadTests({ allTests = false, nodeAddonExamples = allTests, - ferricExample = allTests, + ferricExample = allTests }: Context) { describeIf(nodeAddonExamples, "Node Addon Examples", () => { for (const [suiteName, examples] of Object.entries( - nodeAddonExamplesSuites, + nodeAddonExamplesSuites )) { describe(suiteName, () => { for (const [exampleName, requireExample] of Object.entries(examples)) { @@ -74,24 +74,24 @@ export default function App() { const styles = StyleSheet.create({ container: { flex: 1, - backgroundColor: "#fff", + backgroundColor: "#fff" }, statusContainer: { flex: 1, alignItems: "center", - justifyContent: "center", + justifyContent: "center" }, statusEmoji: { fontSize: 30, margin: 30, - textAlign: "center", + textAlign: "center" }, statusText: { fontSize: 20, margin: 20, - textAlign: "center", + textAlign: "center" }, connectionText: { - textAlign: "center", - }, + textAlign: "center" + } }); diff --git a/apps/test-app/babel.config.js b/apps/test-app/babel.config.js index 8ea846e2..0f386812 100644 --- a/apps/test-app/babel.config.js +++ b/apps/test-app/babel.config.js @@ -1,5 +1,5 @@ module.exports = { presets: ["module:@react-native/babel-preset"], // plugins: [['module:react-native-node-api/babel-plugin', { stripPathSuffix: true }]], - plugins: ["module:react-native-node-api/babel-plugin"], + plugins: ["module:react-native-node-api/babel-plugin"] }; diff --git a/apps/test-app/metro.config.js b/apps/test-app/metro.config.js index 2c321b49..c2c455c4 100644 --- a/apps/test-app/metro.config.js +++ b/apps/test-app/metro.config.js @@ -4,8 +4,8 @@ module.exports = makeMetroConfig({ getTransformOptions: async () => ({ transform: { experimentalImportSupport: false, - inlineRequires: false, - }, - }), - }, + inlineRequires: false + } + }) + } }); diff --git a/apps/test-app/react-native.config.js b/apps/test-app/react-native.config.js index dab1d107..35556659 100644 --- a/apps/test-app/react-native.config.js +++ b/apps/test-app/react-native.config.js @@ -3,19 +3,19 @@ const project = (() => { const { configureProjects } = require("react-native-test-app"); const project = configureProjects({ android: { - sourceDir: "android", + sourceDir: "android" }, ios: { sourceDir: "ios", - automaticPodsInstallation: false, - }, + automaticPodsInstallation: false + } // windows: { // sourceDir: "windows", // solutionFile: "windows/react-native-node-api-example.sln", // }, }); return { - ...project, + ...project }; } catch { return undefined; @@ -23,5 +23,5 @@ const project = (() => { })(); module.exports = { - ...(project ? { project } : undefined), + ...(project ? { project } : undefined) }; diff --git a/biome.json b/biome.json index 8e3f3c2c..1bf39833 100644 --- a/biome.json +++ b/biome.json @@ -24,6 +24,11 @@ "enabled": true, "indentStyle": "space" }, + "javascript": { + "formatter": { + "trailingCommas": "none" + } + }, "linter": { "enabled": true, "rules": { diff --git a/packages/cmake-rn/src/cli.ts b/packages/cmake-rn/src/cli.ts index 307d90d4..94f5dfb2 100644 --- a/packages/cmake-rn/src/cli.ts +++ b/packages/cmake-rn/src/cli.ts @@ -13,7 +13,7 @@ import { allTargets, findPlatformForTarget, platformHasTarget, - platforms, + platforms } from "./platforms.js"; import { getWeakNodeApiVariables } from "./weak-node-api.js"; @@ -24,12 +24,12 @@ EventEmitter.defaultMaxListeners = 100; const verboseOption = new Option( "--verbose", - "Print more output during the build", + "Print more output during the build" ).default(process.env.CI === "true"); const sourcePathOption = new Option( "--source ", - "Specify the source directory containing a CMakeLists.txt file", + "Specify the source directory containing a CMakeLists.txt file" ).default(process.cwd()); // TODO: Add "MinSizeRel" and "RelWithDebInfo" @@ -47,7 +47,7 @@ const defaultTargets = CMAKE_RN_TARGETS ? CMAKE_RN_TARGETS.split(",") : []; for (const target of defaultTargets) { assert( (allTargets as string[]).includes(target), - `Unexpected target in CMAKE_RN_TARGETS: ${target}`, + `Unexpected target in CMAKE_RN_TARGETS: ${target}` ); } @@ -55,32 +55,32 @@ const targetOption = new Option("--target ", "Targets to build for") .choices(allTargets) .default( defaultTargets, - "CMAKE_RN_TARGETS environment variable split by ','", + "CMAKE_RN_TARGETS environment variable split by ','" ); const buildPathOption = new Option( "--build ", - "Specify the build directory to store the configured CMake project", + "Specify the build directory to store the configured CMake project" ); const cleanOption = new Option( "--clean", - "Delete the build directory before configuring the project", + "Delete the build directory before configuring the project" ); const outPathOption = new Option( "--out ", - "Specify the output directory to store the final build artifacts", + "Specify the output directory to store the final build artifacts" ).default(false, "./{build}/{configuration}"); const noAutoLinkOption = new Option( "--no-auto-link", - "Don't mark the output as auto-linkable by react-native-node-api", + "Don't mark the output as auto-linkable by react-native-node-api" ); const noWeakNodeApiLinkageOption = new Option( "--no-weak-node-api-linkage", - "Don't pass the path of the weak-node-api library from react-native-node-api", + "Don't pass the path of the weak-node-api library from react-native-node-api" ); let program = new Command("cmake-rn") @@ -98,7 +98,7 @@ let program = new Command("cmake-rn") for (const platform of platforms) { const allOption = new Option( `--${platform.id}`, - `Enable all ${platform.name} triplets`, + `Enable all ${platform.name} triplets` ); program = program.addOption(allOption); program = platform.amendCommand(program); @@ -132,13 +132,13 @@ program = program.action( } if (targets.size === 0) { throw new Error( - "Found no default targets: Install some platform specific build tools", + "Found no default targets: Install some platform specific build tools" ); } else { console.error( chalk.yellowBright("ℹ"), "Using default targets", - chalk.dim(`(${[...targets].join(", ")})`), + chalk.dim(`(${[...targets].join(", ")})`) ); } } @@ -155,26 +155,26 @@ program = program.action( platform, buildPath: targetBuildPath, outputPath: path.join(targetBuildPath, "out"), - options: baseOptions, + options: baseOptions }; }); // Configure every triplet project const targetsSummary = chalk.dim( - `(${getTargetsSummary(targetContexts)})`, + `(${getTargetsSummary(targetContexts)})` ); await oraPromise( Promise.all( targetContexts.map(({ platform, ...context }) => - configureProject(platform, context, baseOptions), - ), + configureProject(platform, context, baseOptions) + ) ), { text: `Configuring projects ${targetsSummary}`, isSilent: baseOptions.verbose, successText: `Configured projects ${targetsSummary}`, - failText: ({ message }) => `Failed to configure projects: ${message}`, - }, + failText: ({ message }) => `Failed to configure projects: ${message}` + } ); // Build every triplet project @@ -185,23 +185,23 @@ program = program.action( // This is important, since we might rename the output files await fs.promises.rm(context.outputPath, { recursive: true, - force: true, + force: true }); await buildProject(platform, context, baseOptions); - }), + }) ), { text: "Building projects", isSilent: baseOptions.verbose, successText: "Built projects", - failText: ({ message }) => `Failed to build projects: ${message}`, - }, + failText: ({ message }) => `Failed to build projects: ${message}` + } ); // Perform post-build steps for each platform in sequence for (const platform of platforms) { const relevantTargets = targetContexts.filter(({ target }) => - platformHasTarget(platform, target), + platformHasTarget(platform, target) ); if (relevantTargets.length === 0) { continue; @@ -209,9 +209,9 @@ program = program.action( await platform.postBuild( { outputPath: baseOptions.out || baseOptions.source, - targets: relevantTargets, + targets: relevantTargets }, - baseOptions, + baseOptions ); } } catch (error) { @@ -220,11 +220,11 @@ program = program.action( } throw error; } - }, + } ); function getTargetsSummary( - targetContexts: { target: string; platform: Platform }[], + targetContexts: { target: string; platform: Platform }[] ) { const targetsPerPlatform: Record = {}; for (const { target, platform } of targetContexts) { @@ -256,7 +256,7 @@ function getTargetBuildPath(buildPath: string, target: unknown) { async function configureProject( platform: Platform>, context: TargetContext, - options: BaseOpts, + options: BaseOpts ) { const { target, buildPath, outputPath } = context; const { verbose, source, weakNodeApiLinkage } = options; @@ -269,7 +269,7 @@ async function configureProject( const declarations = { ...nodeApiVariables, - CMAKE_LIBRARY_OUTPUT_DIRECTORY: outputPath, + CMAKE_LIBRARY_OUTPUT_DIRECTORY: outputPath }; await spawn( @@ -280,19 +280,19 @@ async function configureProject( "-B", buildPath, ...platform.configureArgs(context, options), - ...toDeclarationArguments(declarations), + ...toDeclarationArguments(declarations) ], { outputMode: verbose ? "inherit" : "buffered", - outputPrefix: verbose ? chalk.dim(`[${target}] `) : undefined, - }, + outputPrefix: verbose ? chalk.dim(`[${target}] `) : undefined + } ); } async function buildProject( platform: Platform>, context: TargetContext, - options: BaseOpts, + options: BaseOpts ) { const { target, buildPath } = context; const { verbose, configuration } = options; @@ -304,19 +304,19 @@ async function buildProject( "--config", configuration, "--", - ...platform.buildArgs(context, options), + ...platform.buildArgs(context, options) ], { outputMode: verbose ? "inherit" : "buffered", - outputPrefix: verbose ? chalk.dim(`[${target}] `) : undefined, - }, + outputPrefix: verbose ? chalk.dim(`[${target}] `) : undefined + } ); } function toDeclarationArguments(declarations: Record) { return Object.entries(declarations).flatMap(([key, value]) => [ "-D", - `${key}=${value}`, + `${key}=${value}` ]); } diff --git a/packages/cmake-rn/src/headers.ts b/packages/cmake-rn/src/headers.ts index aefd1464..87352b0c 100644 --- a/packages/cmake-rn/src/headers.ts +++ b/packages/cmake-rn/src/headers.ts @@ -11,7 +11,7 @@ const require = createRequire(import.meta.url); export function getNodeApiHeadersPath(): string { try { const packagePath = path.dirname( - require.resolve("node-api-headers/package.json"), + require.resolve("node-api-headers/package.json") ); const result = path.join(packagePath, "include"); const stat = fs.statSync(packagePath); @@ -21,8 +21,8 @@ export function getNodeApiHeadersPath(): string { throw new Error( `Failed resolve Node-API headers: Did you install the 'node-api-headers' package?`, { - cause: error, - }, + cause: error + } ); } } @@ -33,15 +33,15 @@ export function getNodeApiHeadersPath(): string { export function getNodeAddonHeadersPath(): string { try { const packagePath = path.dirname( - require.resolve("node-addon-api/package.json"), + require.resolve("node-addon-api/package.json") ); return packagePath; } catch (error) { throw new Error( `Failed resolve Node-API addon headers: Did you install the 'node-addon-api' package?`, { - cause: error, - }, + cause: error + } ); } } diff --git a/packages/cmake-rn/src/platforms.test.ts b/packages/cmake-rn/src/platforms.test.ts index 77dee711..c0440421 100644 --- a/packages/cmake-rn/src/platforms.test.ts +++ b/packages/cmake-rn/src/platforms.test.ts @@ -4,7 +4,7 @@ import type { Platform } from "./platforms/types.js"; import { findPlatformForTarget, platformHasTarget, - platforms, + platforms } from "./platforms.js"; const mockPlatform = { targets: ["target1", "target2"] } as unknown as Platform; diff --git a/packages/cmake-rn/src/platforms.ts b/packages/cmake-rn/src/platforms.ts index 2a298328..7aedc0b3 100644 --- a/packages/cmake-rn/src/platforms.ts +++ b/packages/cmake-rn/src/platforms.ts @@ -9,14 +9,14 @@ export const allTargets = [...android.targets, ...apple.targets] as const; export function platformHasTarget

( platform: P, - target: unknown, + target: unknown ): target is P["targets"][number] { return (platform.targets as unknown[]).includes(target); } export function findPlatformForTarget(target: unknown) { const platform = Object.values(platforms).find((platform) => - platformHasTarget(platform, target), + platformHasTarget(platform, target) ); assert(platform, `Unable to determine platform from target: ${target}`); return platform; diff --git a/packages/cmake-rn/src/platforms/android.ts b/packages/cmake-rn/src/platforms/android.ts index d61d3e8d..cb36dffd 100644 --- a/packages/cmake-rn/src/platforms/android.ts +++ b/packages/cmake-rn/src/platforms/android.ts @@ -8,7 +8,7 @@ import { oraPromise } from "ora"; import { createAndroidLibsDirectory, determineAndroidLibsFilename, - type AndroidTriplet as Target, + type AndroidTriplet as Target } from "react-native-node-api"; import type { Platform } from "./types.js"; @@ -22,17 +22,17 @@ export const ANDROID_ARCHITECTURES = { "armv7a-linux-androideabi": "armeabi-v7a", "aarch64-linux-android": "arm64-v8a", "i686-linux-android": "x86", - "x86_64-linux-android": "x86_64", + "x86_64-linux-android": "x86_64" } satisfies Record; const ndkVersionOption = new Option( "--ndk-version ", - "The NDK version to use for Android builds", + "The NDK version to use for Android builds" ).default(DEFAULT_NDK_VERSION); const androidSdkVersionOption = new Option( "--android-sdk-version ", - "The Android SDK version to use for Android builds", + "The Android SDK version to use for Android builds" ).default(DEFAULT_ANDROID_SDK_VERSION); type AndroidOpts = { ndkVersion: string; androidSdkVersion: string }; @@ -44,7 +44,7 @@ export const platform: Platform = { "aarch64-linux-android", "armv7a-linux-androideabi", "i686-linux-android", - "x86_64-linux-android", + "x86_64-linux-android" ], defaultTargets() { if (process.arch === "arm64") { @@ -64,22 +64,22 @@ export const platform: Platform = { const { ANDROID_HOME } = process.env; assert( typeof ANDROID_HOME === "string", - "Missing env variable ANDROID_HOME", + "Missing env variable ANDROID_HOME" ); assert( fs.existsSync(ANDROID_HOME), - `Expected the Android SDK at ${ANDROID_HOME}`, + `Expected the Android SDK at ${ANDROID_HOME}` ); const installNdkCommand = `sdkmanager --install "ndk;${ndkVersion}"`; const ndkPath = path.resolve(ANDROID_HOME, "ndk", ndkVersion); assert( fs.existsSync(ndkPath), - `Missing Android NDK v${ndkVersion} (at ${ndkPath}) - run: ${installNdkCommand}`, + `Missing Android NDK v${ndkVersion} (at ${ndkPath}) - run: ${installNdkCommand}` ); const toolchainPath = path.join( ndkPath, - "build/cmake/android.toolchain.cmake", + "build/cmake/android.toolchain.cmake" ); const architecture = ANDROID_ARCHITECTURES[target]; @@ -112,7 +112,7 @@ export const platform: Platform = { `ANDROID_PLATFORM=${androidSdkVersion}`, "-D", // TODO: Make this configurable - "ANDROID_STL=c++_shared", + "ANDROID_STL=c++_shared" ]; }, buildArgs() { @@ -129,26 +129,26 @@ export const platform: Platform = { targets.map(async ({ target, outputPath }) => { assert( fs.existsSync(outputPath), - `Expected a directory at ${outputPath}`, + `Expected a directory at ${outputPath}` ); // Expect binary file(s), either .node or .so const dirents = await fs.promises.readdir(outputPath, { - withFileTypes: true, + withFileTypes: true }); const result = dirents .filter( (dirent) => dirent.isFile() && - (dirent.name.endsWith(".so") || dirent.name.endsWith(".node")), + (dirent.name.endsWith(".so") || dirent.name.endsWith(".node")) ) .map((dirent) => path.join(dirent.parentPath, dirent.name)); assert.equal(result.length, 1, "Expected exactly one library file"); return [target, result[0]] as const; - }), - ), + }) + ) ) as Record; const androidLibsFilename = determineAndroidLibsFilename( - Object.values(libraryPathByTriplet), + Object.values(libraryPathByTriplet) ); const androidLibsOutputPath = path.resolve(outputPath, androidLibsFilename); @@ -156,16 +156,16 @@ export const platform: Platform = { createAndroidLibsDirectory({ outputPath: androidLibsOutputPath, libraryPathByTriplet, - autoLink, + autoLink }), { text: "Assembling Android libs directory", successText: `Android libs directory assembled into ${chalk.dim( - path.relative(process.cwd(), androidLibsOutputPath), + path.relative(process.cwd(), androidLibsOutputPath) )}`, failText: ({ message }) => - `Failed to assemble Android libs directory: ${message}`, - }, + `Failed to assemble Android libs directory: ${message}` + } ); - }, + } }; diff --git a/packages/cmake-rn/src/platforms/apple.ts b/packages/cmake-rn/src/platforms/apple.ts index b65a0fed..d40b00e7 100644 --- a/packages/cmake-rn/src/platforms/apple.ts +++ b/packages/cmake-rn/src/platforms/apple.ts @@ -9,7 +9,7 @@ import { createAppleFramework, createXCframework, determineXCFrameworkFilename, - type AppleTriplet as Target, + type AppleTriplet as Target } from "react-native-node-api"; import type { Platform } from "./types.js"; @@ -33,7 +33,7 @@ const XCODE_SDK_NAMES = { // "x86_64-apple-tvos": "appletvos", "arm64-apple-tvos-sim": "appletvsimulator", "arm64-apple-visionos": "xros", - "arm64-apple-visionos-sim": "xrsimulator", + "arm64-apple-visionos-sim": "xrsimulator" } satisfies Record; type CMakeSystemName = "Darwin" | "iOS" | "tvOS" | "watchOS" | "visionOS"; @@ -48,7 +48,7 @@ const CMAKE_SYSTEM_NAMES = { // "x86_64-apple-tvos": "appletvos", "arm64-apple-tvos-sim": "tvOS", "arm64-apple-visionos": "visionOS", - "arm64-apple-visionos-sim": "visionOS", + "arm64-apple-visionos-sim": "visionOS" } satisfies Record; type AppleArchitecture = "arm64" | "x86_64" | "arm64;x86_64"; @@ -63,7 +63,7 @@ export const APPLE_ARCHITECTURES = { // "x86_64-apple-tvos": "x86_64", "arm64-apple-tvos-sim": "arm64", "arm64-apple-visionos": "arm64", - "arm64-apple-visionos-sim": "arm64", + "arm64-apple-visionos-sim": "arm64" } satisfies Record; export function createPlistContent(values: Record) { @@ -74,10 +74,10 @@ export function createPlistContent(values: Record) { "", ...Object.entries(values).flatMap(([key, value]) => [ `${key}`, - `${value}`, + `${value}` ]), "", - "", + "" ].join("\n"); } @@ -88,7 +88,7 @@ export function getAppleBuildArgs() { const xcframeworkExtensionOption = new Option( "--xcframework-extension", - "Don't rename the xcframework to .apple.node", + "Don't rename the xcframework to .apple.node" ).default(false); type AppleOpts = { @@ -105,7 +105,7 @@ export const platform: Platform = { "arm64-apple-tvos", "arm64-apple-tvos-sim", "arm64-apple-visionos", - "arm64-apple-visionos-sim", + "arm64-apple-visionos-sim" ], defaultTargets() { return process.arch === "arm64" ? ["arm64-apple-ios-sim"] : []; @@ -122,7 +122,7 @@ export const platform: Platform = { "-D", `CMAKE_OSX_SYSROOT=${XCODE_SDK_NAMES[target]}`, "-D", - `CMAKE_OSX_ARCHITECTURES=${APPLE_ARCHITECTURES[target]}`, + `CMAKE_OSX_ARCHITECTURES=${APPLE_ARCHITECTURES[target]}` ]; }, buildArgs() { @@ -133,14 +133,14 @@ export const platform: Platform = { process.platform === "darwin", async postBuild( { outputPath, targets }, - { configuration, autoLink, xcframeworkExtension }, + { configuration, autoLink, xcframeworkExtension } ) { const libraryPaths = await Promise.all( targets.map(async ({ outputPath }) => { const configSpecificPath = path.join(outputPath, configuration); assert( fs.existsSync(configSpecificPath), - `Expected a directory at ${configSpecificPath}`, + `Expected a directory at ${configSpecificPath}` ); // Expect binary file(s), either .node or .dylib const files = await fs.promises.readdir(configSpecificPath); @@ -155,18 +155,18 @@ export const platform: Platform = { return newFilePath; } else { throw new Error( - `Expected a .node or .dylib file, but found ${file}`, + `Expected a .node or .dylib file, but found ${file}` ); } }); assert.equal(result.length, 1, "Expected exactly one library file"); return await result[0]; - }), + }) ); const frameworkPaths = libraryPaths.map(createAppleFramework); const xcframeworkFilename = determineXCFrameworkFilename( frameworkPaths, - xcframeworkExtension ? ".xcframework" : ".apple.node", + xcframeworkExtension ? ".xcframework" : ".apple.node" ); // Create the xcframework @@ -176,15 +176,15 @@ export const platform: Platform = { createXCframework({ outputPath: xcframeworkOutputPath, frameworkPaths, - autoLink, + autoLink }), { text: "Assembling XCFramework", successText: `XCFramework assembled into ${chalk.dim( - path.relative(process.cwd(), xcframeworkOutputPath), + path.relative(process.cwd(), xcframeworkOutputPath) )}`, - failText: ({ message }) => `Failed to assemble XCFramework: ${message}`, - }, + failText: ({ message }) => `Failed to assemble XCFramework: ${message}` + } ); - }, + } }; diff --git a/packages/cmake-rn/src/platforms/types.ts b/packages/cmake-rn/src/platforms/types.ts index f191408e..4d4b22d8 100644 --- a/packages/cmake-rn/src/platforms/types.ts +++ b/packages/cmake-rn/src/platforms/types.ts @@ -23,7 +23,7 @@ export type TargetContext = { export type Platform< Targets extends string[] = string[], Opts extends commander.OptionValues = Record, - Command = ExtendedCommand, + Command = ExtendedCommand > = { /** * Used to identify the platform in the CLI. @@ -54,14 +54,14 @@ export type Platform< */ configureArgs( context: TargetContext, - options: BaseOpts & Opts, + options: BaseOpts & Opts ): string[]; /** * Platform specific arguments passed to CMake to build a target project. */ buildArgs( context: TargetContext, - options: BaseOpts & Opts, + options: BaseOpts & Opts ): string[]; /** * Called to combine multiple targets into a single prebuilt artefact. @@ -74,6 +74,6 @@ export type Platform< outputPath: string; targets: TargetContext[]; }, - options: BaseOpts & Opts, + options: BaseOpts & Opts ): Promise; }; diff --git a/packages/cmake-rn/src/weak-node-api.ts b/packages/cmake-rn/src/weak-node-api.ts index a7c3071d..0d7ddfd4 100644 --- a/packages/cmake-rn/src/weak-node-api.ts +++ b/packages/cmake-rn/src/weak-node-api.ts @@ -6,7 +6,7 @@ import { isAndroidTriplet, isAppleTriplet, type SupportedTriplet, - weakNodeApiPath, + weakNodeApiPath } from "react-native-node-api"; import { getNodeAddonHeadersPath, getNodeApiHeadersPath } from "./headers.js"; import { ANDROID_ARCHITECTURES } from "./platforms/android.js"; @@ -19,11 +19,11 @@ export function getWeakNodeApiPath(triplet: SupportedTriplet): string { if (isAppleTriplet(triplet)) { const xcframeworkPath = path.join( weakNodeApiPath, - "weak-node-api.xcframework", + "weak-node-api.xcframework" ); assert( fs.existsSync(xcframeworkPath), - `Expected an XCFramework at ${xcframeworkPath}`, + `Expected an XCFramework at ${xcframeworkPath}` ); return xcframeworkPath; } else if (isAndroidTriplet(triplet)) { @@ -31,7 +31,7 @@ export function getWeakNodeApiPath(triplet: SupportedTriplet): string { weakNodeApiPath, "weak-node-api.android.node", ANDROID_ARCHITECTURES[triplet], - "libweak-node-api.so", + "libweak-node-api.so" ); assert(fs.existsSync(libraryPath), `Expected library at ${libraryPath}`); return libraryPath; @@ -45,11 +45,11 @@ export function getWeakNodeApiVariables(triplet: SupportedTriplet) { for (const includePath of includePaths) { assert( !includePath.includes(";"), - `Include path with a ';' is not supported: ${includePath}`, + `Include path with a ';' is not supported: ${includePath}` ); } return { CMAKE_JS_INC: includePaths.join(";"), - CMAKE_JS_LIB: getWeakNodeApiPath(triplet), + CMAKE_JS_LIB: getWeakNodeApiPath(triplet) }; } diff --git a/packages/ferric/src/banner.ts b/packages/ferric/src/banner.ts index 820b681d..f72c3c88 100644 --- a/packages/ferric/src/banner.ts +++ b/packages/ferric/src/banner.ts @@ -7,7 +7,7 @@ const LINES = [ "│░█▀▀░█▀▀░█▀▄░█▀▄░▀█▀░█▀▀░│", "│░█▀▀░█▀▀░█▀▄░█▀▄░░█░░█░░░│", "│░▀░░░▀▀▀░▀░▀░▀░▀░▀▀▀░▀▀▀░│", - "╰─────────────────────────╯", + "╰─────────────────────────╯" ]; export function getBlockComment() { @@ -25,6 +25,6 @@ export function printBanner() { LINES.map((line, lineNumber, lines) => { const ratio = lineNumber / lines.length; return chalk.rgb(Math.round(250 - 100 * ratio), 0, 0)(line); - }).join("\n"), + }).join("\n") ); } diff --git a/packages/ferric/src/build.ts b/packages/ferric/src/build.ts index 109a13a7..a6d58bdf 100644 --- a/packages/ferric/src/build.ts +++ b/packages/ferric/src/build.ts @@ -15,7 +15,7 @@ import { determineAndroidLibsFilename, determineLibraryBasename, determineXCFrameworkFilename, - prettyPath, + prettyPath } from "react-native-node-api"; import { getBlockComment } from "./banner.js"; import { build, ensureCargo } from "./cargo.js"; @@ -28,7 +28,7 @@ import { APPLE_TARGETS, type AppleTargetName, ensureInstalledTargets, - filterTargetsByPlatform, + filterTargetsByPlatform } from "./targets.js"; type EntrypointOptions = { @@ -37,15 +37,15 @@ type EntrypointOptions = { }; async function generateEntrypoint({ outputPath, - libraryName, + libraryName }: EntrypointOptions) { await fs.promises.writeFile( outputPath, `${[ getBlockComment(), - `module.exports = require('./${libraryName}.node');`, + `module.exports = require('./${libraryName}.node');` ].join("\n\n")}\n`, - "utf8", + "utf8" ); } @@ -53,7 +53,7 @@ const ANDROID_TRIPLET_PER_TARGET: Record = { "aarch64-linux-android": "aarch64-linux-android", "armv7-linux-androideabi": "armv7a-linux-androideabi", "i686-linux-android": "i686-linux-android", - "x86_64-linux-android": "x86_64-linux-android", + "x86_64-linux-android": "x86_64-linux-android" }; // This should match https://github.com/react-native-community/template/blob/main/template/android/build.gradle#L7 @@ -70,8 +70,8 @@ function getDefaultTargets() { `Unexpected target in FERRIC_TARGETS: ${target}`, { instructions: - "Pass only valid targets via FERRIC_TARGETS (or remove them)", - }, + "Pass only valid targets via FERRIC_TARGETS (or remove them)" + } ); } return result as (typeof ALL_TARGETS)[number][]; @@ -84,20 +84,20 @@ const appleTarget = new Option("--apple", "Use all Apple targets"); const androidTarget = new Option("--android", "Use all Android targets"); const ndkVersionOption = new Option( "--ndk-version ", - "The NDK version to use for Android builds", + "The NDK version to use for Android builds" ).default(DEFAULT_NDK_VERSION); const xcframeworkExtensionOption = new Option( "--xcframework-extension", - "Don't rename the xcframework to .apple.node", + "Don't rename the xcframework to .apple.node" ).default(false); const outputPathOption = new Option( "--output ", - "Writing outputs to this directory", + "Writing outputs to this directory" ).default(process.cwd()); const configurationOption = new Option( "--configuration ", - "Build configuration", + "Build configuration" ) .choices(["debug", "release"]) .default("debug"); @@ -119,7 +119,7 @@ export const buildCommand = new Command("build") ndkVersion, output: outputPath, configuration, - xcframeworkExtension, + xcframeworkExtension }) => { try { const targets = new Set([...targetArg]); @@ -151,11 +151,11 @@ export const buildCommand = new Command("build") chalk.yellowBright("ℹ"), chalk.dim( `Using default targets, pass ${chalk.italic( - "--android", + "--android" )}, ${chalk.italic("--apple")} or individual ${chalk.italic( - "--target", - )} options, to avoid this.`, - ), + "--target" + )} options, to avoid this.` + ) ); } ensureCargo(); @@ -173,8 +173,8 @@ export const buildCommand = new Command("build") Promise.all( appleTargets.map( async (target) => - [target, await build({ configuration, target })] as const, - ), + [target, await build({ configuration, target })] as const + ) ), Promise.all( androidTargets.map( @@ -185,49 +185,49 @@ export const buildCommand = new Command("build") configuration, target, ndkVersion, - androidApiLevel: ANDROID_API_LEVEL, - }), - ] as const, - ), - ), + androidApiLevel: ANDROID_API_LEVEL + }) + ] as const + ) + ) ]), { text: `Building ${targetsDescription}`, successText: `Built ${targetsDescription}`, - failText: (error: Error) => `Failed to build: ${error.message}`, - }, + failText: (error: Error) => `Failed to build: ${error.message}` + } ); if (androidLibraries.length > 0) { const libraryPathByTriplet = Object.fromEntries( androidLibraries.map(([target, outputPath]) => [ ANDROID_TRIPLET_PER_TARGET[target], - outputPath, - ]), + outputPath + ]) ) as Record; const androidLibsFilename = determineAndroidLibsFilename( - Object.values(libraryPathByTriplet), + Object.values(libraryPathByTriplet) ); const androidLibsOutputPath = path.resolve( outputPath, - androidLibsFilename, + androidLibsFilename ); await oraPromise( createAndroidLibsDirectory({ outputPath: androidLibsOutputPath, libraryPathByTriplet, - autoLink: true, + autoLink: true }), { text: "Assembling Android libs directory", successText: `Android libs directory assembled into ${prettyPath( - androidLibsOutputPath, + androidLibsOutputPath )}`, failText: ({ message }) => - `Failed to assemble Android libs directory: ${message}`, - }, + `Failed to assemble Android libs directory: ${message}` + } ); } @@ -236,35 +236,35 @@ export const buildCommand = new Command("build") const frameworkPaths = libraryPaths.map(createAppleFramework); const xcframeworkFilename = determineXCFrameworkFilename( frameworkPaths, - xcframeworkExtension ? ".xcframework" : ".apple.node", + xcframeworkExtension ? ".xcframework" : ".apple.node" ); // Create the xcframework const xcframeworkOutputPath = path.resolve( outputPath, - xcframeworkFilename, + xcframeworkFilename ); await oraPromise( createXCframework({ outputPath: xcframeworkOutputPath, frameworkPaths, - autoLink: true, + autoLink: true }), { text: "Assembling XCFramework", successText: `XCFramework assembled into ${chalk.dim( - path.relative(process.cwd(), xcframeworkOutputPath), + path.relative(process.cwd(), xcframeworkOutputPath) )}`, failText: ({ message }) => - `Failed to assemble XCFramework: ${message}`, - }, + `Failed to assemble XCFramework: ${message}` + } ); } const libraryName = determineLibraryBasename([ ...androidLibraries.map(([, outputPath]) => outputPath), - ...appleLibraries.map(([, outputPath]) => outputPath), + ...appleLibraries.map(([, outputPath]) => outputPath) ]); const declarationsFilename = `${libraryName}.d.ts`; @@ -273,16 +273,16 @@ export const buildCommand = new Command("build") generateTypeScriptDeclarations({ outputFilename: declarationsFilename, createPath: process.cwd(), - outputPath, + outputPath }), { text: "Generating TypeScript declarations", successText: `Generated TypeScript declarations ${prettyPath( - declarationsPath, + declarationsPath )}`, failText: (error) => - `Failed to generate TypeScript declarations: ${error.message}`, - }, + `Failed to generate TypeScript declarations: ${error.message}` + } ); const entrypointPath = path.join(outputPath, `${libraryName}.js`); @@ -290,16 +290,16 @@ export const buildCommand = new Command("build") await oraPromise( generateEntrypoint({ libraryName, - outputPath: entrypointPath, + outputPath: entrypointPath }), { text: `Generating entrypoint`, successText: `Generated entrypoint into ${prettyPath( - entrypointPath, + entrypointPath )}`, failText: (error) => - `Failed to generate entrypoint: ${error.message}`, - }, + `Failed to generate entrypoint: ${error.message}` + } ); } catch (error) { process.exitCode = 1; @@ -316,18 +316,18 @@ export const buildCommand = new Command("build") chalk.green("FIX"), error.fix.command ? chalk.dim("Run: ") + error.fix.command - : error.fix.instructions, + : error.fix.instructions ); } } else { throw error; } } - }, + } ); async function combineLibraries( - libraries: Readonly<[AppleTargetName, string]>[], + libraries: Readonly<[AppleTargetName, string]>[] ): Promise { const result = []; const darwinLibraries = []; @@ -349,8 +349,8 @@ async function combineLibraries( text: "Combining Darwin libraries into a universal library", successText: "Combined Darwin libraries into a universal library", failText: (error) => - `Failed to combine Darwin libraries: ${error.message}`, - }, + `Failed to combine Darwin libraries: ${error.message}` + } ); return [...result, universalPath]; } diff --git a/packages/ferric/src/cargo.ts b/packages/ferric/src/cargo.ts index 4e9e04b9..d2d1cccb 100644 --- a/packages/ferric/src/cargo.ts +++ b/packages/ferric/src/cargo.ts @@ -11,14 +11,14 @@ import { type AndroidTargetName, type AppleTargetName, isAndroidTarget, - isAppleTarget, + isAppleTarget } from "./targets.js"; const APPLE_XCFRAMEWORK_CHILDS_PER_TARGET: Record = { "aarch64-apple-darwin": "macos-arm64_x86_64", // Universal "x86_64-apple-darwin": "macos-arm64_x86_64", // Universal "aarch64-apple-ios": "ios-arm64", - "aarch64-apple-ios-sim": "ios-arm64-simulator", + "aarch64-apple-ios-sim": "ios-arm64-simulator" // "aarch64-apple-ios-macabi": "", // Catalyst // "x86_64-apple-ios": "ios-x86_64", // "x86_64-apple-ios-macabi": "ios-x86_64-simulator", @@ -32,7 +32,7 @@ const ANDROID_ARCH_PR_TARGET: Record = { "aarch64-linux-android": "arm64-v8a", "armv7-linux-androideabi": "armeabi-v7a", "i686-linux-android": "x86", - "x86_64-linux-android": "x86_64", + "x86_64-linux-android": "x86_64" }; export function joinPathAndAssertExistence(...pathSegments: string[]) { @@ -45,14 +45,14 @@ export function ensureCargo() { try { const cargoVersion = cp .execFileSync("cargo", ["--version"], { - encoding: "utf-8", + encoding: "utf-8" }) .trim(); console.log(chalk.dim(`Using ${cargoVersion}`)); } catch (error) { throw new UsageError( "You need a Rust toolchain: https://doc.rust-lang.org/cargo/getting-started/installation.html#install-rust-and-cargo", - { cause: error }, + { cause: error } ); } } @@ -78,21 +78,21 @@ export async function build(options: BuildOptions) { outputMode: "buffered", env: { ...process.env, - ...getTargetEnvironmentVariables(options), - }, + ...getTargetEnvironmentVariables(options) + } }); const targetOutputPath = joinPathAndAssertExistence( process.cwd(), "target", target, - configuration, + configuration ); const dynamicLibraryFile = fs .readdirSync(targetOutputPath) .filter((file) => file.endsWith(".so") || file.endsWith(".dylib")); assert( dynamicLibraryFile.length === 1, - `Expected a single shared object file in ${targetOutputPath}`, + `Expected a single shared object file in ${targetOutputPath}` ); return joinPathAndAssertExistence(targetOutputPath, dynamicLibraryFile[0]); } @@ -124,7 +124,7 @@ export function getWeakNodeApiFrameworkPath(target: AppleTargetName) { return joinPathAndAssertExistence( weakNodeApiPath, "weak-node-api.xcframework", - APPLE_XCFRAMEWORK_CHILDS_PER_TARGET[target], + APPLE_XCFRAMEWORK_CHILDS_PER_TARGET[target] ); } @@ -132,14 +132,14 @@ export function getWeakNodeApiAndroidLibraryPath(target: AndroidTargetName) { return joinPathAndAssertExistence( weakNodeApiPath, "weak-node-api.android.node", - ANDROID_ARCH_PR_TARGET[target], + ANDROID_ARCH_PR_TARGET[target] ); } export function getTargetEnvironmentVariables({ target, ndkVersion, - androidApiLevel, + androidApiLevel }: BuildOptions): Record { if (isAndroidTarget(target)) { assert(ndkVersion, "Expected ndkVersion to be set for Android targets"); @@ -149,12 +149,12 @@ export function getTargetEnvironmentVariables({ ANDROID_HOME && fs.existsSync(ANDROID_HOME), `Missing ANDROID_HOME environment variable`, { - instructions: "Set ANDROID_HOME to the Android SDK directory", - }, + instructions: "Set ANDROID_HOME to the Android SDK directory" + } ); const ndkPath = path.join(ANDROID_HOME, "ndk", ndkVersion); assertFixable(fs.existsSync(ndkPath), `Expected NDK at ${ndkPath}`, { - command: `sdkmanager --install "ndk;${ndkVersion}"`, + command: `sdkmanager --install "ndk;${ndkVersion}"` }); const toolchainBinPath = getLLVMToolchainBinPath(ndkPath); @@ -169,42 +169,42 @@ export function getTargetEnvironmentVariables({ "-L", weakNodeApiPath, "-l", - "weak-node-api", + "weak-node-api" ].join(String.fromCharCode(0x1f)), CARGO_TARGET_AARCH64_LINUX_ANDROID_LINKER: joinPathAndAssertExistence( toolchainBinPath, - `aarch64-linux-android${androidApiLevel}-clang${cmdMaybe}`, + `aarch64-linux-android${androidApiLevel}-clang${cmdMaybe}` ), CARGO_TARGET_ARMV7_LINUX_ANDROIDEABI_LINKER: joinPathAndAssertExistence( toolchainBinPath, - `armv7a-linux-androideabi${androidApiLevel}-clang${cmdMaybe}`, + `armv7a-linux-androideabi${androidApiLevel}-clang${cmdMaybe}` ), CARGO_TARGET_X86_64_LINUX_ANDROID_LINKER: joinPathAndAssertExistence( toolchainBinPath, - `x86_64-linux-android${androidApiLevel}-clang${cmdMaybe}`, + `x86_64-linux-android${androidApiLevel}-clang${cmdMaybe}` ), CARGO_TARGET_I686_LINUX_ANDROID_LINKER: joinPathAndAssertExistence( toolchainBinPath, - `i686-linux-android${androidApiLevel}-clang${cmdMaybe}`, + `i686-linux-android${androidApiLevel}-clang${cmdMaybe}` ), TARGET_CC: joinPathAndAssertExistence( toolchainBinPath, - `${targetArch}-linux-${targetPlatform}-clang${cmdMaybe}`, + `${targetArch}-linux-${targetPlatform}-clang${cmdMaybe}` ), TARGET_CXX: joinPathAndAssertExistence( toolchainBinPath, - `${targetArch}-linux-${targetPlatform}-clang++${cmdMaybe}`, + `${targetArch}-linux-${targetPlatform}-clang++${cmdMaybe}` ), TARGET_AR: joinPathAndAssertExistence( toolchainBinPath, - `llvm-ar${exeMaybe}`, + `llvm-ar${exeMaybe}` ), TARGET_RANLIB: joinPathAndAssertExistence( toolchainBinPath, - `llvm-ranlib${exeMaybe}`, + `llvm-ranlib${exeMaybe}` ), ANDROID_NDK: ndkPath, - PATH: `${toolchainBinPath}:${process.env.PATH}`, + PATH: `${toolchainBinPath}:${process.env.PATH}` }; } else if (isAppleTarget(target)) { const weakNodeApiFrameworkPath = getWeakNodeApiFrameworkPath(target); @@ -213,8 +213,8 @@ export function getTargetEnvironmentVariables({ "-L", `framework=${weakNodeApiFrameworkPath}`, "-l", - "framework=weak-node-api", - ].join(String.fromCharCode(0x1f)), + "framework=weak-node-api" + ].join(String.fromCharCode(0x1f)) }; } else { throw new Error(`Unexpected target: ${target}`); diff --git a/packages/ferric/src/errors.ts b/packages/ferric/src/errors.ts index fbdc8480..b27489b9 100644 --- a/packages/ferric/src/errors.ts +++ b/packages/ferric/src/errors.ts @@ -15,7 +15,7 @@ export class UsageError extends Error { constructor( message: string, - { fix, cause }: { cause?: unknown; fix?: Fix } = {}, + { fix, cause }: { cause?: unknown; fix?: Fix } = {} ) { super(message, { cause }); this.fix = fix; @@ -25,7 +25,7 @@ export class UsageError extends Error { export function assertFixable( value: unknown, message: string, - fix: Fix, + fix: Fix ): asserts value { try { assert(value, message); diff --git a/packages/ferric/src/napi-rs.ts b/packages/ferric/src/napi-rs.ts index fbba24e3..77ee8180 100644 --- a/packages/ferric/src/napi-rs.ts +++ b/packages/ferric/src/napi-rs.ts @@ -28,11 +28,11 @@ type TypeScriptDeclarationsOptions = { export async function generateTypeScriptDeclarations({ createPath, outputPath, - outputFilename, + outputFilename }: TypeScriptDeclarationsOptions) { // Using a temporary directory to avoid polluting crate with any other side-effects for generating TypeScript declarations const tempPath = fs.realpathSync( - fs.mkdtempSync(path.join(PACKAGE_ROOT, "dts-tmp-")), + fs.mkdtempSync(path.join(PACKAGE_ROOT, "dts-tmp-")) ); const finalOutputPath = path.join(outputPath, outputFilename); try { @@ -40,7 +40,7 @@ export async function generateTypeScriptDeclarations({ await fs.promises.writeFile( path.join(tempPath, "package.json"), "{}", - "utf8", + "utf8" ); const tempOutputPath = path.join(tempPath, outputFilename); // Call into napi.rs to generate TypeScript declarations @@ -49,22 +49,22 @@ export async function generateTypeScriptDeclarations({ dts: outputFilename, outputDir: tempPath, cwd: createPath, - cargoOptions: ["--quiet"], + cargoOptions: ["--quiet"] }); await task; // Override the banner assert( fs.existsSync(tempOutputPath), - `Expected napi.rs to emit ${tempOutputPath}`, + `Expected napi.rs to emit ${tempOutputPath}` ); const contents = await fs.promises.readFile(tempOutputPath, "utf8"); const patchedContents = contents.replace( "/* auto-generated by NAPI-RS */", - getBlockComment(), + getBlockComment() ); // Copy out the generated TypeScript declarations await fs.promises.writeFile(finalOutputPath, patchedContents, { - encoding: "utf8", + encoding: "utf8" }); return finalOutputPath; } finally { diff --git a/packages/ferric/src/rustup.ts b/packages/ferric/src/rustup.ts index 36d11159..de93be8e 100644 --- a/packages/ferric/src/rustup.ts +++ b/packages/ferric/src/rustup.ts @@ -7,14 +7,14 @@ export function getInstalledTargets() { return new Set( cp .execFileSync("rustup", ["target", "list", "--installed"], { - encoding: "utf-8", + encoding: "utf-8" }) - .split("\n"), + .split("\n") ); } catch (error) { throw new UsageError( "You need a Rust toolchain: https://doc.rust-lang.org/cargo/getting-started/installation.html#install-rust-and-cargo", - { cause: error }, + { cause: error } ); } } diff --git a/packages/ferric/src/targets.ts b/packages/ferric/src/targets.ts index c1990d16..b21f5830 100644 --- a/packages/ferric/src/targets.ts +++ b/packages/ferric/src/targets.ts @@ -7,7 +7,7 @@ export const ANDROID_TARGETS = [ "aarch64-linux-android", "armv7-linux-androideabi", "i686-linux-android", - "x86_64-linux-android", + "x86_64-linux-android" // "arm-linux-androideabi", // "thumbv7neon-linux-androideabi", ] as const; @@ -19,7 +19,7 @@ export const APPLE_TARGETS = [ "aarch64-apple-darwin", "x86_64-apple-darwin", "aarch64-apple-ios", - "aarch64-apple-ios-sim", + "aarch64-apple-ios-sim" // "aarch64-apple-ios-macabi", // Catalyst // "x86_64-apple-ios", // "x86_64-apple-ios-macabi", // Catalyst @@ -58,7 +58,7 @@ export type TargetName = (typeof ALL_TARGETS)[number]; export function ensureInstalledTargets(expectedTargets: Set) { const installedTargets = getInstalledTargets(); const missingTargets = new Set([ - ...[...expectedTargets].filter((target) => !installedTargets.has(target)), + ...[...expectedTargets].filter((target) => !installedTargets.has(target)) ]); if (missingTargets.size > 0) { // TODO: Ask the user if they want to run this @@ -66,14 +66,14 @@ export function ensureInstalledTargets(expectedTargets: Set) { `You're missing ${ missingTargets.size } targets - to fix this, run:\n\n${chalk.italic( - `rustup target add ${[...missingTargets].join(" ")}`, - )}`, + `rustup target add ${[...missingTargets].join(" ")}` + )}` ); } } export function isAndroidTarget( - target: TargetName, + target: TargetName ): target is AndroidTargetName { return ANDROID_TARGETS.includes(target as (typeof ANDROID_TARGETS)[number]); } @@ -84,15 +84,15 @@ export function isAppleTarget(target: TargetName): target is AppleTargetName { export function filterTargetsByPlatform( targets: Set, - platform: "android", + platform: "android" ): AndroidTargetName[]; export function filterTargetsByPlatform( targets: Set, - platform: "apple", + platform: "apple" ): AppleTargetName[]; export function filterTargetsByPlatform( targets: Set, - platform: "apple" | "android", + platform: "apple" | "android" ) { if (platform === "android") { return [...targets].filter(isAndroidTarget); diff --git a/packages/gyp-to-cmake/src/cli.ts b/packages/gyp-to-cmake/src/cli.ts index 91b64b9c..81dfe83e 100644 --- a/packages/gyp-to-cmake/src/cli.ts +++ b/packages/gyp-to-cmake/src/cli.ts @@ -5,7 +5,7 @@ import { Command } from "@commander-js/extra-typings"; import { readBindingFile } from "./gyp.js"; import { bindingGypToCmakeLists, - type GypToCmakeListsOptions, + type GypToCmakeListsOptions } from "./transformer.js"; export type TransformOptions = Omit< @@ -26,7 +26,7 @@ export function transformBindingGypFile( disallowUnknownProperties, projectName = generateProjectName(gypPath), ...restOfOptions - }: TransformOptions, + }: TransformOptions ) { console.log("Transforming", gypPath); const gyp = readBindingFile(gypPath, disallowUnknownProperties); @@ -34,7 +34,7 @@ export function transformBindingGypFile( const result = bindingGypToCmakeLists({ gyp, projectName, - ...restOfOptions, + ...restOfOptions }); const cmakeListsPath = path.join(parentPath, "CMakeLists.txt"); fs.writeFileSync(cmakeListsPath, result, "utf-8"); @@ -42,7 +42,7 @@ export function transformBindingGypFile( export function transformBindingGypsRecursively( directoryPath: string, - options: TransformOptions, + options: TransformOptions ) { const entries = fs.readdirSync(directoryPath, { withFileTypes: true }); for (const entry of entries) { @@ -59,18 +59,18 @@ export const program = new Command("gyp-to-cmake") .description("Transform binding.gyp to CMakeLists.txt") .option( "--no-path-transforms", - "Don't transform output from command expansions (replacing '\\' with '/')", + "Don't transform output from command expansions (replacing '\\' with '/')" ) .argument( "[path]", "Path to the binding.gyp file or directory to traverse recursively", - process.cwd(), + process.cwd() ) .action((targetPath: string, { pathTransforms }) => { const options: TransformOptions = { unsupportedBehaviour: "throw", disallowUnknownProperties: false, - transformWinPathsToPosix: pathTransforms, + transformWinPathsToPosix: pathTransforms }; const stat = fs.statSync(targetPath); if (stat.isFile()) { diff --git a/packages/gyp-to-cmake/src/gyp.test.ts b/packages/gyp-to-cmake/src/gyp.test.ts index 7c4e7b47..bed95431 100644 --- a/packages/gyp-to-cmake/src/gyp.test.ts +++ b/packages/gyp-to-cmake/src/gyp.test.ts @@ -26,9 +26,9 @@ describe("gyp.assertRoot", () => { assert.throws(() => { assertBinding( { - targets: [{ target_name: "", sources: [], extra: "not allowed" }], + targets: [{ target_name: "", sources: [], extra: "not allowed" }] }, - true, + true ); }, /Unexpected property: extra/); }); diff --git a/packages/gyp-to-cmake/src/gyp.ts b/packages/gyp-to-cmake/src/gyp.ts index c1d17341..fdd209ef 100644 --- a/packages/gyp-to-cmake/src/gyp.ts +++ b/packages/gyp-to-cmake/src/gyp.ts @@ -16,7 +16,7 @@ export type GypBinding = { function assertNoExtraProperties( input: T, - expectedKeys: string[], + expectedKeys: string[] ) { for (const key of Object.keys(input)) { if (!expectedKeys.includes(key)) { @@ -27,7 +27,7 @@ function assertNoExtraProperties( export function assertTarget( target: unknown, - disallowUnknownProperties = false, + disallowUnknownProperties = false ): asserts target is GypTarget { assert(typeof target === "object" && target !== null, "Expected an object"); assert("target_name" in target, "Expected a 'target_name' property"); @@ -36,17 +36,17 @@ export function assertTarget( assert(Array.isArray(sources), "Expected a 'sources' array"); assert( sources.every((source) => typeof source === "string"), - "Expected all sources to be strings", + "Expected all sources to be strings" ); if ("include_dirs" in target) { const { include_dirs } = target; assert( Array.isArray(include_dirs), - "Expected 'include_dirs' to be an array", + "Expected 'include_dirs' to be an array" ); assert( include_dirs.every((dir) => typeof dir === "string"), - "Expected all include_dirs to be strings", + "Expected all include_dirs to be strings" ); } if (disallowUnknownProperties) { @@ -56,7 +56,7 @@ export function assertTarget( export function assertBinding( json: unknown, - disallowUnknownProperties = false, + disallowUnknownProperties = false ): asserts json is GypBinding { assert(typeof json === "object" && json !== null, "Expected an object"); assert("targets" in json, "Expected a 'targets' property"); @@ -72,7 +72,7 @@ export function assertBinding( export function readBindingFile( path: string, - disallowUnknownProperties = false, + disallowUnknownProperties = false ): GypBinding { try { const contents = fs.readFileSync(path, "utf-8"); diff --git a/packages/gyp-to-cmake/src/transformer.test.ts b/packages/gyp-to-cmake/src/transformer.test.ts index 06d62f8f..d08b4673 100644 --- a/packages/gyp-to-cmake/src/transformer.test.ts +++ b/packages/gyp-to-cmake/src/transformer.test.ts @@ -7,7 +7,7 @@ describe("bindingGypToCmakeLists", () => { it("should declare a project name", () => { const output = bindingGypToCmakeLists({ projectName: "some-project", - gyp: { targets: [] }, + gyp: { targets: [] } }); assert(output.includes("project(some-project)")); }); @@ -19,14 +19,14 @@ describe("bindingGypToCmakeLists", () => { targets: [ { target_name: "foo", - sources: ["foo.cc"], + sources: ["foo.cc"] }, { target_name: "bar", - sources: ["bar.cc"], - }, - ], - }, + sources: ["bar.cc"] + } + ] + } }); assert(output.includes("add_library(foo SHARED foo.cc")); @@ -40,14 +40,14 @@ describe("bindingGypToCmakeLists", () => { targets: [ { target_name: "foo", - sources: ["file\\with\\win32\\separator.cc"], - }, - ], - }, + sources: ["file\\with\\win32\\separator.cc"] + } + ] + } }); assert( - output.includes("add_library(foo SHARED file/with/win32/separator.cc"), + output.includes("add_library(foo SHARED file/with/win32/separator.cc") ); }); @@ -58,10 +58,10 @@ describe("bindingGypToCmakeLists", () => { targets: [ { target_name: "foo", - sources: ["file with spaces.cc"], - }, - ], - }, + sources: ["file with spaces.cc"] + } + ] + } }); assert(output.includes("add_library(foo SHARED file\\ with\\ spaces.cc")); @@ -75,10 +75,10 @@ describe("bindingGypToCmakeLists", () => { targets: [ { target_name: "foo", - sources: [" { targets: [ { target_name: "foo", - sources: [" { { target_name: "foo", sources: ["foo.cc"], - defines: ["FOO", "BAR=value"], - }, - ], - }, + defines: ["FOO", "BAR=value"] + } + ] + } }); assert( output.includes( - "target_compile_definitions(foo PRIVATE FOO BAR=value)", + "target_compile_definitions(foo PRIVATE FOO BAR=value)" ), - `Expected output to include target_compile_definitions:\n${output}`, + `Expected output to include target_compile_definitions:\n${output}` ); }); }); diff --git a/packages/gyp-to-cmake/src/transformer.ts b/packages/gyp-to-cmake/src/transformer.ts index 01096501..a0d2d58d 100644 --- a/packages/gyp-to-cmake/src/transformer.ts +++ b/packages/gyp-to-cmake/src/transformer.ts @@ -33,7 +33,7 @@ export function bindingGypToCmakeLists({ napiVersion = DEFAULT_NAPI_VERSION, executeCmdExpansions = true, unsupportedBehaviour = "skip", - transformWinPathsToPosix = true, + transformWinPathsToPosix = true }: GypToCmakeListsOptions): string { function mapExpansion(value: string): string[] { if (!isCmdExpansion(value)) { @@ -66,7 +66,7 @@ export function bindingGypToCmakeLists({ `project(${projectName})`, "", // Declaring a project-wide NAPI_VERSION as a fallback for targets that don't explicitly set it - `add_compile_definitions(NAPI_VERSION=${napiVersion})`, + `add_compile_definitions(NAPI_VERSION=${napiVersion})` ]; for (const target of gyp.targets) { @@ -103,9 +103,9 @@ export function bindingGypToCmakeLists({ `target_compile_features(${targetName} PRIVATE cxx_std_17)`, ...(escapedJoinedDefines ? [ - `target_compile_definitions(${targetName} PRIVATE ${escapedJoinedDefines})`, + `target_compile_definitions(${targetName} PRIVATE ${escapedJoinedDefines})` ] - : []), + : []) // or // `set_target_properties(${targetName} PROPERTIES CXX_STANDARD 11 CXX_STANDARD_REQUIRED YES CXX_EXTENSIONS NO)`, ); @@ -117,7 +117,7 @@ export function bindingGypToCmakeLists({ "if(MSVC AND CMAKE_JS_NODELIB_DEF AND CMAKE_JS_NODELIB_TARGET)", " # Generate node.lib", " execute_process(COMMAND ${CMAKE_AR} /def:${CMAKE_JS_NODELIB_DEF} /out:${CMAKE_JS_NODELIB_TARGET} ${CMAKE_STATIC_LINKER_FLAGS})", - "endif()", + "endif()" ); return lines.join("\n"); diff --git a/packages/host/react-native.config.js b/packages/host/react-native.config.js index f5e3cd40..0b14ee50 100644 --- a/packages/host/react-native.config.js +++ b/packages/host/react-native.config.js @@ -1,7 +1,7 @@ module.exports = { dependency: { platforms: { - android: {}, - }, - }, + android: {} + } + } }; diff --git a/packages/host/scripts/generate-weak-node-api-injector.ts b/packages/host/scripts/generate-weak-node-api-injector.ts index 7eaa4419..c7860cf8 100644 --- a/packages/host/scripts/generate-weak-node-api-injector.ts +++ b/packages/host/scripts/generate-weak-node-api-injector.ts @@ -19,7 +19,7 @@ const IMPLEMENTED_RUNTIME_FUNCTIONS = [ "napi_cancel_async_work", "napi_fatal_error", "napi_get_node_version", - "napi_get_version", + "napi_get_version" ]; /** @@ -63,7 +63,7 @@ export function generateSource(functions: FunctionDecl[]) { ${functions .filter( ({ kind, name }) => - kind === "engine" || IMPLEMENTED_RUNTIME_FUNCTIONS.includes(name), + kind === "engine" || IMPLEMENTED_RUNTIME_FUNCTIONS.includes(name) ) .flatMap(({ name }) => `.${name} = ${name},`) .join("\n")} diff --git a/packages/host/scripts/generate-weak-node-api.ts b/packages/host/scripts/generate-weak-node-api.ts index 8177cb18..852d9867 100644 --- a/packages/host/scripts/generate-weak-node-api.ts +++ b/packages/host/scripts/generate-weak-node-api.ts @@ -21,11 +21,11 @@ export function generateHeader(functions: FunctionDecl[]) { ({ returnType, noReturn, name, argumentTypes }) => `${returnType} ${ noReturn ? " __attribute__((noreturn))" : "" - }(*${name})(${argumentTypes.join(", ")});`, + }(*${name})(${argumentTypes.join(", ")});` ), "};", "typedef void(*InjectHostFunction)(const WeakNodeApiHost&);", - `extern "C" void inject_weak_node_api_host(const WeakNodeApiHost& host);`, + `extern "C" void inject_weak_node_api_host(const WeakNodeApiHost& host);` ].join("\n"); } @@ -60,9 +60,9 @@ export function generateSource(functions: FunctionDecl[]) { "(" + argumentTypes.map((_, index) => `arg${index}`).join(", ") + ");", - "};", + "};" ]; - }), + }) ].join("\n"); } diff --git a/packages/host/scripts/node-api-functions.ts b/packages/host/scripts/node-api-functions.ts index c2f2ee90..92f0efc0 100644 --- a/packages/host/scripts/node-api-functions.ts +++ b/packages/host/scripts/node-api-functions.ts @@ -5,7 +5,7 @@ import path from "node:path"; import { type NodeApiVersion, include_dir as nodeApiIncludePath, - symbols, + symbols } from "node-api-headers"; import { z } from "zod"; @@ -17,11 +17,11 @@ const clangAstDump = z.object({ name: z.string().optional(), type: z .object({ - qualType: z.string(), + qualType: z.string() }) - .optional(), - }), - ), + .optional() + }) + ) }); /** @@ -43,13 +43,13 @@ export function getNodeApiHeaderAST(version: NodeApiVersion) { "-fsyntax-only", // Include from the node-api-headers package `-I${nodeApiIncludePath}`, - path.join(nodeApiIncludePath, "node_api.h"), + path.join(nodeApiIncludePath, "node_api.h") ], { encoding: "utf-8", // Emitting the AST can produce a lot of output - maxBuffer: 1024 * 1024 * 10, - }, + maxBuffer: 1024 * 1024 * 10 + } ); const parsed = JSON.parse(output); return clangAstDump.parse(parsed); @@ -86,24 +86,24 @@ export function getNodeApiFunctions(version: NodeApiVersion = "v8") { assert(node.type, `Expected type for ${node.name}`); const match = node.type.qualType.match( - /^(?[^(]+) \((?[^)]+)\)/, + /^(?[^(]+) \((?[^)]+)\)/ ); assert( match?.groups, - `Failed to parse function type: ${node.type.qualType}`, + `Failed to parse function type: ${node.type.qualType}` ); const { returnType, argumentTypes } = match.groups; assert( returnType, - `Failed to get return type from ${node.type.qualType}`, + `Failed to get return type from ${node.type.qualType}` ); assert( argumentTypes, - `Failed to get argument types from ${argumentTypes}`, + `Failed to get argument types from ${argumentTypes}` ); assert( returnType === "napi_status" || returnType === "void", - `Expected return type to be napi_status, got ${returnType}`, + `Expected return type to be napi_status, got ${returnType}` ); nodeApiFunctions.push({ @@ -121,14 +121,14 @@ export function getNodeApiFunctions(version: NodeApiVersion = "v8") { fallbackReturnStatement: returnType === "void" ? "abort();" - : "return napi_status::napi_generic_failure;", + : "return napi_status::napi_generic_failure;" }); } } for (const knownSymbol of allSymbols) { if (!foundSymbols.has(knownSymbol)) { throw new Error( - `Missing symbol '${knownSymbol}' in the AST for Node API ${version}`, + `Missing symbol '${knownSymbol}' in the AST for Node API ${version}` ); } } diff --git a/packages/host/src/node/babel-plugin/plugin.test.ts b/packages/host/src/node/babel-plugin/plugin.test.ts index a40fe195..e04da6f6 100644 --- a/packages/host/src/node/babel-plugin/plugin.test.ts +++ b/packages/host/src/node/babel-plugin/plugin.test.ts @@ -15,13 +15,13 @@ type TestTransformationOptions = { function itTransforms( title: string, - { files, inputFilePath, assertion, options = {} }: TestTransformationOptions, + { files, inputFilePath, assertion, options = {} }: TestTransformationOptions ) { it(`transforms ${title}`, (context: TestContext) => { const tempDirectoryPath = setupTempDirectory(context, files); const result = transformFileSync( path.join(tempDirectoryPath, inputFilePath), - { plugins: [[plugin, options]] }, + { plugins: [[plugin, options]] } ); assert(result, "Expected transformation to produce a result"); const { code } = result; @@ -35,12 +35,12 @@ function assertIncludes(needle: string, { reverse = false } = {}) { if (reverse) { assert( !code.includes(needle), - `Expected code to not include: ${needle}, got ${code}`, + `Expected code to not include: ${needle}, got ${code}` ); } else { assert( code.includes(needle), - `Expected code to include: ${needle}, got ${code}`, + `Expected code to include: ${needle}, got ${code}` ); } }; @@ -56,10 +56,10 @@ describe("plugin", () => { "index.js": ` const addon = require('./my-addon.node'); console.log(addon); - `, + ` }, inputFilePath: "index.js", - assertion: assertIncludes(`requireNodeAddon("my-package--my-addon")`), + assertion: assertIncludes(`requireNodeAddon("my-package--my-addon")`) }); itTransforms("from sub-directory", { @@ -70,10 +70,10 @@ describe("plugin", () => { "sub-dir/index.js": ` const addon = require('../my-addon.node'); console.log(addon); - `, + ` }, inputFilePath: "sub-dir/index.js", - assertion: assertIncludes(`requireNodeAddon("my-package--my-addon")`), + assertion: assertIncludes(`requireNodeAddon("my-package--my-addon")`) }); describe("in 'sub-dir'", () => { @@ -85,13 +85,13 @@ describe("plugin", () => { "index.js": ` const addon = require('./sub-dir/my-addon.node'); console.log(addon); - `, + ` }, inputFilePath: "index.js", options: { pathSuffix: "keep" }, assertion: assertIncludes( - `requireNodeAddon("my-package--sub-dir-my-addon")`, - ), + `requireNodeAddon("my-package--sub-dir-my-addon")` + ) }); itTransforms("a nested addon (stripping suffix)", { @@ -102,11 +102,11 @@ describe("plugin", () => { "index.js": ` const addon = require('./sub-dir/my-addon.node'); console.log(addon); - `, + ` }, inputFilePath: "index.js", options: { pathSuffix: "strip" }, - assertion: assertIncludes(`requireNodeAddon("my-package--my-addon")`), + assertion: assertIncludes(`requireNodeAddon("my-package--my-addon")`) }); itTransforms("a nested addon (omitting suffix)", { @@ -117,11 +117,11 @@ describe("plugin", () => { "index.js": ` const addon = require('./sub-dir/my-addon.node'); console.log(addon); - `, + ` }, inputFilePath: "index.js", options: { pathSuffix: "omit" }, - assertion: assertIncludes(`requireNodeAddon("my-package")`), + assertion: assertIncludes(`requireNodeAddon("my-package")`) }); }); @@ -133,10 +133,10 @@ describe("plugin", () => { "index.js": ` const addon = require('./my-addon'); console.log(addon); - `, + ` }, inputFilePath: "index.js", - assertion: assertIncludes("requireNodeAddon", { reverse: true }), + assertion: assertIncludes("requireNodeAddon", { reverse: true }) }); }); @@ -149,10 +149,10 @@ describe("plugin", () => { "index.js": ` const addon = require('bindings')('my-addon'); console.log(addon); - `, + ` }, inputFilePath: "index.js", - assertion: assertIncludes(`requireNodeAddon("my-package--my-addon")`), + assertion: assertIncludes(`requireNodeAddon("my-package--my-addon")`) }); describe("in 'build/Release'", () => { @@ -164,13 +164,13 @@ describe("plugin", () => { "index.js": ` const addon = require('bindings')('my-addon'); console.log(addon); - `, + ` }, inputFilePath: "index.js", options: { pathSuffix: "keep" }, assertion: assertIncludes( - `requireNodeAddon("my-package--build-Release-my-addon")`, - ), + `requireNodeAddon("my-package--build-Release-my-addon")` + ) }); itTransforms("a nested addon (stripping suffix)", { @@ -181,11 +181,11 @@ describe("plugin", () => { "index.js": ` const addon = require('bindings')('my-addon'); console.log(addon); - `, + ` }, inputFilePath: "index.js", options: { pathSuffix: "strip" }, - assertion: assertIncludes(`requireNodeAddon("my-package--my-addon")`), + assertion: assertIncludes(`requireNodeAddon("my-package--my-addon")`) }); itTransforms("a nested addon (omitting suffix)", { @@ -196,11 +196,11 @@ describe("plugin", () => { "index.js": ` const addon = require('bindings')('my-addon'); console.log(addon); - `, + ` }, inputFilePath: "index.js", options: { pathSuffix: "omit" }, - assertion: assertIncludes(`requireNodeAddon("my-package")`), + assertion: assertIncludes(`requireNodeAddon("my-package")`) }); }); }); diff --git a/packages/host/src/node/babel-plugin/plugin.ts b/packages/host/src/node/babel-plugin/plugin.ts index 5db5eb3d..07a2c886 100644 --- a/packages/host/src/node/babel-plugin/plugin.ts +++ b/packages/host/src/node/babel-plugin/plugin.ts @@ -10,7 +10,7 @@ import { getLibraryName, isNodeApiModule, type NamingStrategy, - type PathSuffixChoice, + type PathSuffixChoice } from "../path-utils"; export type PluginOptions = { @@ -36,19 +36,19 @@ function assertOptions(opts: unknown): asserts opts is PluginOptions { export function replaceWithRequireNodeAddon( p: NodePath, modulePath: string, - naming: NamingStrategy, + naming: NamingStrategy ) { const requireCallArgument = getLibraryName(modulePath, naming); p.replaceWith( t.callExpression( t.memberExpression( t.callExpression(t.identifier("require"), [ - t.stringLiteral("react-native-node-api"), + t.stringLiteral("react-native-node-api") ]), - t.identifier("requireNodeAddon"), + t.identifier("requireNodeAddon") ), - [t.stringLiteral(requireCallArgument)], - ), + [t.stringLiteral(requireCallArgument)] + ) ); } @@ -80,7 +80,7 @@ export function plugin(): PluginObj { const resolvedPath = findNodeAddonForBindings(id, from); if (typeof resolvedPath === "string") { replaceWithRequireNodeAddon(p.parentPath, resolvedPath, { - pathSuffix, + pathSuffix }); } } @@ -92,7 +92,7 @@ export function plugin(): PluginObj { replaceWithRequireNodeAddon(p, relativePath, { pathSuffix }); } } - }, - }, + } + } }; } diff --git a/packages/host/src/node/cli/android.ts b/packages/host/src/node/cli/android.ts index a48cc36e..4df25abd 100644 --- a/packages/host/src/node/cli/android.ts +++ b/packages/host/src/node/cli/android.ts @@ -6,21 +6,21 @@ import { getLatestMtime, getLibraryName, MAGIC_FILENAME } from "../path-utils"; import { getLinkedModuleOutputPath, type LinkModuleOptions, - type LinkModuleResult, + type LinkModuleResult } from "./link-modules"; const ANDROID_ARCHITECTURES = [ "arm64-v8a", "armeabi-v7a", "x86_64", - "x86", + "x86" ] as const; export async function linkAndroidDir({ incremental, modulePath, naming, - platform, + platform }: LinkModuleOptions): Promise { const libraryName = getLibraryName(modulePath, naming); const outputPath = getLinkedModuleOutputPath(platform, modulePath, naming); @@ -33,7 +33,7 @@ export async function linkAndroidDir({ originalPath: modulePath, libraryName, outputPath, - skipped: true, + skipped: true }; } } @@ -47,7 +47,7 @@ export async function linkAndroidDir({ continue; } const libraryDirents = await fs.promises.readdir(archPath, { - withFileTypes: true, + withFileTypes: true }); assert(libraryDirents.length === 1, "Expected exactly one library file"); const [libraryDirent] = libraryDirents; @@ -55,11 +55,11 @@ export async function linkAndroidDir({ const libraryPath = path.join(libraryDirent.parentPath, libraryDirent.name); await fs.promises.rename( libraryPath, - path.join(archPath, `lib${libraryName}.so`), + path.join(archPath, `lib${libraryName}.so`) ); } await fs.promises.rm(path.join(outputPath, MAGIC_FILENAME), { - recursive: true, + recursive: true }); // TODO: Update the DT_NEEDED entry in the .so files @@ -68,6 +68,6 @@ export async function linkAndroidDir({ originalPath: modulePath, outputPath, libraryName, - skipped: false, + skipped: false }; } diff --git a/packages/host/src/node/cli/apple.ts b/packages/host/src/node/cli/apple.ts index fb344caf..9bd378cb 100644 --- a/packages/host/src/node/cli/apple.ts +++ b/packages/host/src/node/cli/apple.ts @@ -9,7 +9,7 @@ import { getLatestMtime, getLibraryName } from "../path-utils.js"; import { getLinkedModuleOutputPath, type LinkModuleOptions, - type LinkModuleResult, + type LinkModuleResult } from "./link-modules.js"; type UpdateInfoPlistOptions = { @@ -24,13 +24,13 @@ type UpdateInfoPlistOptions = { export async function updateInfoPlist({ filePath, oldLibraryName, - newLibraryName, + newLibraryName }: UpdateInfoPlistOptions) { const infoPlistContents = await fs.promises.readFile(filePath, "utf-8"); // TODO: Use a proper plist parser const updatedContents = infoPlistContents.replaceAll( oldLibraryName, - newLibraryName, + newLibraryName ); await fs.promises.writeFile(filePath, updatedContents, "utf-8"); } @@ -39,13 +39,13 @@ export async function linkXcframework({ platform, modulePath, incremental, - naming, + naming }: LinkModuleOptions): Promise { // Copy the xcframework to the output directory and rename the framework and binary const newLibraryName = getLibraryName(modulePath, naming); const outputPath = getLinkedModuleOutputPath(platform, modulePath, naming); const tempPath = await fs.promises.mkdtemp( - path.join(os.tmpdir(), `react-native-node-api-${newLibraryName}-`), + path.join(os.tmpdir(), `react-native-node-api-${newLibraryName}-`) ); try { if (incremental && fs.existsSync(outputPath)) { @@ -56,7 +56,7 @@ export async function linkXcframework({ originalPath: modulePath, libraryName: newLibraryName, outputPath, - skipped: true, + skipped: true }; } } @@ -67,7 +67,7 @@ export async function linkXcframework({ // Following extracted function mimics `glob("*/*.framework/")` function globFrameworkDirs( startPath: string, - fn: (parentPath: string, name: string) => Promise, + fn: (parentPath: string, name: string) => Promise ) { return fs .readdirSync(startPath, { withFileTypes: true }) @@ -79,11 +79,11 @@ export async function linkXcframework({ .filter( (frameworkEntry) => frameworkEntry.isDirectory() && - path.extname(frameworkEntry.name) === ".framework", + path.extname(frameworkEntry.name) === ".framework" ) .flatMap( async (frameworkEntry) => - await fn(tripletPath, frameworkEntry.name), + await fn(tripletPath, frameworkEntry.name) ); }); } @@ -95,18 +95,18 @@ export async function linkXcframework({ const oldLibraryPath = path.join(frameworkPath, oldLibraryName); const newFrameworkPath = path.join( tripletPath, - `${newLibraryName}.framework`, + `${newLibraryName}.framework` ); const newLibraryPath = path.join(newFrameworkPath, newLibraryName); assert( fs.existsSync(oldLibraryPath), - `Expected a library at '${oldLibraryPath}'`, + `Expected a library at '${oldLibraryPath}'` ); // Rename the library await fs.promises.rename( oldLibraryPath, // Cannot use newLibraryPath here, because the framework isn't renamed yet - path.join(frameworkPath, newLibraryName), + path.join(frameworkPath, newLibraryName) ); // Rename the framework await fs.promises.rename(frameworkPath, newFrameworkPath); @@ -118,20 +118,20 @@ export async function linkXcframework({ [ "-id", `@rpath/${newLibraryName}.framework/${newLibraryName}`, - newLibraryPath, + newLibraryPath ], { - outputMode: "buffered", - }, + outputMode: "buffered" + } ); // Update the Info.plist file for the framework await updateInfoPlist({ filePath: path.join(newFrameworkPath, "Info.plist"), oldLibraryName, - newLibraryName, + newLibraryName }); return newFrameworkPath; - }), + }) ); // Create a new xcframework from the renamed frameworks @@ -141,21 +141,21 @@ export async function linkXcframework({ "-create-xcframework", ...frameworkPaths.flatMap((frameworkPath) => [ "-framework", - frameworkPath, + frameworkPath ]), "-output", - outputPath, + outputPath ], { - outputMode: "buffered", - }, + outputMode: "buffered" + } ); return { originalPath: modulePath, libraryName: newLibraryName, outputPath, - skipped: false, + skipped: false }; } finally { await fs.promises.rm(tempPath, { recursive: true, force: true }); diff --git a/packages/host/src/node/cli/hermes.ts b/packages/host/src/node/cli/hermes.ts index d37872ad..18e3a79b 100644 --- a/packages/host/src/node/cli/hermes.ts +++ b/packages/host/src/node/cli/hermes.ts @@ -19,7 +19,7 @@ export const command = new Command("vendor-hermes") .option( "--force", "Don't check timestamps of input files to skip unnecessary rebuilds", - false, + false ) .action(async (from, { force, silent }) => { try { @@ -28,13 +28,13 @@ export const command = new Command("vendor-hermes") const reactNativePath = path.dirname( require.resolve("react-native/package.json", { // Ensures we'll be patching the React Native package actually used by the app - paths: [appPackageRoot], - }), + paths: [appPackageRoot] + }) ); const hermesVersionPath = path.join( reactNativePath, "sdks", - ".hermesversion", + ".hermesversion" ); const hermesVersion = fs.readFileSync(hermesVersionPath, "utf8").trim(); if (!silent) { @@ -43,7 +43,7 @@ export const command = new Command("vendor-hermes") const reactNativeJsiPath = path.join( reactNativePath, - "ReactCommon/jsi/jsi/", + "ReactCommon/jsi/jsi/" ); const hermesPath = path.join(HOST_PACKAGE_ROOT, "hermes"); @@ -55,8 +55,8 @@ export const command = new Command("vendor-hermes") successText: "Removed existing Hermes clone", failText: (error) => `Failed to remove existing Hermes clone: ${error.message}`, - isEnabled: !silent, - }, + isEnabled: !silent + } ); } if (!fs.existsSync(hermesPath)) { @@ -73,26 +73,26 @@ export const command = new Command("vendor-hermes") "--branch", patchedTag, HERMES_GIT_URL, - hermesPath, + hermesPath ], { - outputMode: "buffered", - }, + outputMode: "buffered" + } ), { text: `Cloning custom Hermes into ${prettyPath(hermesPath)}`, successText: "Cloned custom Hermes", failText: (err) => `Failed to clone custom Hermes: ${err.message}`, - isEnabled: !silent, - }, + isEnabled: !silent + } ); } catch (error) { if (error instanceof SpawnFailure) { error.flushOutput("both"); console.error( `\n🛑 React Native uses the ${hermesVersion} tag and cloning our fork failed.`, - `Please see the Node-API package's peer dependency on "react-native" for supported versions.`, + `Please see the Node-API package's peer dependency on "react-native" for supported versions.` ); process.exitCode = 1; return; @@ -105,20 +105,20 @@ export const command = new Command("vendor-hermes") assert( fs.existsSync(hermesJsiPath), - `Hermes JSI path does not exist: ${hermesJsiPath}`, + `Hermes JSI path does not exist: ${hermesJsiPath}` ); await oraPromise( fs.promises.cp(hermesJsiPath, reactNativeJsiPath, { - recursive: true, + recursive: true }), { text: `Copying JSI from patched Hermes to React Native`, successText: "Copied JSI from patched Hermes to React Native", failText: (err) => `Failed to copy JSI from Hermes to React Native: ${err.message}`, - isEnabled: !silent, - }, + isEnabled: !silent + } ); console.log(hermesPath); } catch (error) { diff --git a/packages/host/src/node/cli/link-modules.ts b/packages/host/src/node/cli/link-modules.ts index d6caeca1..5dabd733 100644 --- a/packages/host/src/node/cli/link-modules.ts +++ b/packages/host/src/node/cli/link-modules.ts @@ -10,11 +10,11 @@ import { logModulePaths, type NamingStrategy, type PlatformName, - prettyPath, + prettyPath } from "../path-utils"; export type ModuleLinker = ( - options: LinkModuleOptions, + options: LinkModuleOptions ) => Promise; export type LinkModulesOptions = { @@ -58,21 +58,21 @@ export async function linkModules({ incremental, naming, platform, - linker, + linker }: LinkModulesOptions): Promise { // Find all their xcframeworks const dependenciesByName = await findNodeApiModulePathsByDependency({ fromPath, platform, - includeSelf: true, + includeSelf: true }); // Find absolute paths to xcframeworks const absoluteModulePaths = Object.values(dependenciesByName).flatMap( (dependency) => dependency.modulePaths.map((modulePath) => - path.join(dependency.path, modulePath), - ), + path.join(dependency.path, modulePath) + ) ); if (hasDuplicateLibraryNames(absoluteModulePaths, naming)) { @@ -87,26 +87,26 @@ export async function linkModules({ modulePath: originalPath, incremental, naming, - platform, + platform }); } catch (error) { if (error instanceof SpawnFailure) { return { originalPath, skipped: false, - failure: error, + failure: error }; } else { throw error; } } - }), + }) ); } export async function pruneLinkedModules( platform: PlatformName, - linkedModules: ModuleOutput[], + linkedModules: ModuleOutput[] ) { if (linkedModules.some(({ failure }) => failure)) { // Don't prune if any of the modules failed to copy @@ -122,17 +122,17 @@ export async function pruneLinkedModules( console.log( "🧹Deleting", prettyPath(candidatePath), - chalk.dim("(no longer linked)"), + chalk.dim("(no longer linked)") ); await fs.promises.rm(candidatePath, { recursive: true, force: true }); } - }), + }) ); } export function hasDuplicateLibraryNames( modulePaths: string[], - naming: NamingStrategy, + naming: NamingStrategy ): boolean { const libraryNames = modulePaths.map((modulePath) => { return getLibraryName(modulePath, naming); @@ -144,7 +144,7 @@ export function hasDuplicateLibraryNames( export function getLinkedModuleOutputPath( platform: PlatformName, modulePath: string, - naming: NamingStrategy, + naming: NamingStrategy ): string { const libraryName = getLibraryName(modulePath, naming); if (platform === "android") { diff --git a/packages/host/src/node/cli/options.ts b/packages/host/src/node/cli/options.ts index 1f81f306..3e8b512b 100644 --- a/packages/host/src/node/cli/options.ts +++ b/packages/host/src/node/cli/options.ts @@ -9,7 +9,7 @@ if (typeof NODE_API_PATH_SUFFIX === "string") { export const pathSuffixOption = new Option( "--path-suffix ", - "Controls how the path of the addon inside a package is transformed into a library name", + "Controls how the path of the addon inside a package is transformed into a library name" ) .choices(PATH_SUFFIX_CHOICES) .default(NODE_API_PATH_SUFFIX || "strip"); diff --git a/packages/host/src/node/cli/program.ts b/packages/host/src/node/cli/program.ts index 11ace89a..df9482c3 100644 --- a/packages/host/src/node/cli/program.ts +++ b/packages/host/src/node/cli/program.ts @@ -16,7 +16,7 @@ import { normalizeModulePath, PLATFORMS, type PlatformName, - prettyPath, + prettyPath } from "../path-utils"; import { linkAndroidDir } from "./android"; import { linkXcframework } from "./apple"; @@ -24,7 +24,7 @@ import { command as vendorHermes } from "./hermes"; import { linkModules, type ModuleLinker, - pruneLinkedModules, + pruneLinkedModules } from "./link-modules"; import { pathSuffixOption } from "./options"; @@ -32,7 +32,7 @@ import { pathSuffixOption } from "./options"; EventEmitter.defaultMaxListeners = 100; export const program = new Command("react-native-node-api").addCommand( - vendorHermes, + vendorHermes ); function getLinker(platform: PlatformName): ModuleLinker { @@ -61,12 +61,12 @@ program .option( "--force", "Don't check timestamps of input files to skip unnecessary rebuilds", - false, + false ) .option( "--prune", "Delete vendored modules that are no longer auto-linked", - true, + true ) .option("--android", "Link Android modules") .option("--apple", "Link Apple modules") @@ -84,7 +84,7 @@ program if (platforms.length === 0) { console.error( `No platform specified, pass one or more of:`, - ...PLATFORMS.map((platform) => chalk.bold(`\n --${platform}`)), + ...PLATFORMS.map((platform) => chalk.bold(`\n --${platform}`)) ); process.exitCode = 1; return; @@ -100,20 +100,20 @@ program fromPath: path.resolve(pathArg), incremental: !force, naming: { pathSuffix }, - linker: getLinker(platform), + linker: getLinker(platform) }), { text: `Linking ${platformDisplayName} Node-API modules into ${prettyPath( - platformOutputPath, + platformOutputPath )}`, successText: `Linked ${platformDisplayName} Node-API modules into ${prettyPath( - platformOutputPath, + platformOutputPath )}`, failText: (error) => `Failed to link ${platformDisplayName} Node-API modules into ${prettyPath( - platformOutputPath, - )}: ${error.message}`, - }, + platformOutputPath + )}: ${error.message}` + } ); if (modules.length === 0) { @@ -133,14 +133,14 @@ program "Skipped", prettyPath(originalPath), prettyOutputPath, - "(up to date)", + "(up to date)" ); } else { console.log( chalk.greenBright("⚭"), "Linked", prettyPath(originalPath), - prettyOutputPath, + prettyOutputPath ); } } @@ -151,7 +151,7 @@ program "\n", chalk.redBright("✖"), "Failed to copy", - prettyPath(originalPath), + prettyPath(originalPath) ); console.error(failure.message); failure.flushOutput("both"); @@ -175,7 +175,7 @@ program const dependencies = await findNodeApiModulePathsByDependency({ fromPath: rootPath, platform: PLATFORMS, - includeSelf: true, + includeSelf: true }); if (json) { @@ -184,7 +184,7 @@ program const dependencyCount = Object.keys(dependencies).length; const xframeworkCount = Object.values(dependencies).reduce( (acc, { modulePaths }) => acc + modulePaths.length, - 0, + 0 ); console.log( "Found", @@ -193,17 +193,17 @@ program chalk.greenBright(dependencyCount), dependencyCount === 1 ? "package" : "packages", "from", - prettyPath(rootPath), + prettyPath(rootPath) ); for (const [dependencyName, dependency] of Object.entries(dependencies)) { console.log( chalk.blueBright(dependencyName), "→", - prettyPath(dependency.path), + prettyPath(dependency.path) ); logModulePaths( dependency.modulePaths.map((p) => path.join(dependency.path, p)), - { pathSuffix }, + { pathSuffix } ); } } @@ -212,7 +212,7 @@ program program .command("info ") .description( - "Utility to print, module path, the hash of a single Android library", + "Utility to print, module path, the hash of a single Android library" ) .addOption(pathSuffixOption) .action((pathInput, { pathSuffix }) => { @@ -221,13 +221,13 @@ program const { packageName, relativePath } = determineModuleContext(resolvedModulePath); const libraryName = getLibraryName(resolvedModulePath, { - pathSuffix, + pathSuffix }); console.log({ resolvedModulePath, normalizedModulePath, packageName, relativePath, - libraryName, + libraryName }); }); diff --git a/packages/host/src/node/index.ts b/packages/host/src/node/index.ts index bd2320a2..4d6157f1 100644 --- a/packages/host/src/node/index.ts +++ b/packages/host/src/node/index.ts @@ -2,14 +2,14 @@ export { determineLibraryBasename, prettyPath } from "./path-utils.js"; export { createAndroidLibsDirectory, - determineAndroidLibsFilename, + determineAndroidLibsFilename } from "./prebuilds/android.js"; export { createAppleFramework, createUniversalAppleLibrary, createXCframework, - determineXCFrameworkFilename, + determineXCFrameworkFilename } from "./prebuilds/apple.js"; export { ANDROID_TRIPLETS, @@ -20,7 +20,7 @@ export { isAppleTriplet, isSupportedTriplet, SUPPORTED_TRIPLETS, - type SupportedTriplet, + type SupportedTriplet } from "./prebuilds/triplets.js"; export { weakNodeApiPath } from "./weak-node-api.js"; diff --git a/packages/host/src/node/path-utils.test.ts b/packages/host/src/node/path-utils.test.ts index f7cde5d3..5ffae02a 100644 --- a/packages/host/src/node/path-utils.test.ts +++ b/packages/host/src/node/path-utils.test.ts @@ -12,7 +12,7 @@ import { findPackageDependencyPaths, getLibraryName, isNodeApiModule, - stripExtension, + stripExtension } from "./path-utils.js"; import { setupTempDirectory } from "./test-utils.js"; @@ -27,7 +27,7 @@ function removeReadPermissions(p: string) { const attributes = { IS_READ_ONLY: true, IS_OFFLINE: true, - IS_TEMPORARY: true, + IS_TEMPORARY: true }; const result = fswin.setAttributesSync(p, attributes); @@ -45,7 +45,7 @@ function restoreReadPermissions(p: string) { const attributes = { IS_READ_ONLY: false, IS_OFFLINE: false, - IS_TEMPORARY: false, + IS_TEMPORARY: false }; const result = fswin.setAttributesSync(p, attributes); @@ -56,7 +56,7 @@ function restoreReadPermissions(p: string) { describe("isNodeApiModule", () => { it("returns true for .node", (context) => { const tempDirectoryPath = setupTempDirectory(context, { - "addon.apple.node/addon.node": "// This is supposted to be a binary file", + "addon.apple.node/addon.node": "// This is supposted to be a binary file" }); assert(isNodeApiModule(path.join(tempDirectoryPath, "addon"))); @@ -69,30 +69,30 @@ describe("isNodeApiModule", () => { { skip: process.platform === "win32" }, (context) => { const tempDirectoryPath = setupTempDirectory(context, { - "addon.android.node": "", + "addon.android.node": "" }); removeReadPermissions(tempDirectoryPath); try { assert.equal( isNodeApiModule(path.join(tempDirectoryPath, "addon")), - false, + false ); } finally { restoreReadPermissions(tempDirectoryPath); } - }, + } ); it("throws when module file exists but is not readable", (context) => { const tempDirectoryPath = setupTempDirectory(context, { - "addon.android.node": "", + "addon.android.node": "" }); const candidate = path.join(tempDirectoryPath, "addon.android.node"); removeReadPermissions(candidate); try { assert.throws( () => isNodeApiModule(path.join(tempDirectoryPath, "addon")), - /Found an unreadable module addon\.android\.node/, + /Found an unreadable module addon\.android\.node/ ); } finally { restoreReadPermissions(candidate); @@ -107,12 +107,12 @@ describe("isNodeApiModule", () => { it("recognize .apple.node directories", (context) => { const tempDirectoryPath = setupTempDirectory(context, { - "addon.apple.node/addon.node": "// This is supposed to be a binary file", + "addon.apple.node/addon.node": "// This is supposed to be a binary file" }); assert.equal(isNodeApiModule(path.join(tempDirectoryPath, "addon")), true); assert.equal( isNodeApiModule(path.join(tempDirectoryPath, "addon.node")), - true, + true ); assert.equal(isNodeApiModule(path.join(tempDirectoryPath, "nope")), false); }); @@ -120,14 +120,14 @@ describe("isNodeApiModule", () => { it("throws when one module unreadable but another readable", (context) => { const tempDirectoryPath = setupTempDirectory(context, { "addon.android.node": "", - "addon.apple.node": "", + "addon.apple.node": "" }); const unreadable = path.join(tempDirectoryPath, "addon.android.node"); // only android module is unreadable removeReadPermissions(unreadable); assert.throws( () => isNodeApiModule(path.join(tempDirectoryPath, "addon")), - /Found an unreadable module addon\.android\.node/, + /Found an unreadable module addon\.android\.node/ ); restoreReadPermissions(unreadable); }); @@ -146,12 +146,12 @@ describe("stripExtension", () => { describe("determineModuleContext", () => { it("strips the file extension", (context) => { const tempDirectoryPath = setupTempDirectory(context, { - "package.json": `{ "name": "my-package" }`, + "package.json": `{ "name": "my-package" }` }); { const { packageName, relativePath } = determineModuleContext( - path.join(tempDirectoryPath, "some-dir/some-file.node"), + path.join(tempDirectoryPath, "some-dir/some-file.node") ); assert.equal(packageName, "my-package"); assert.equal(relativePath, "some-dir/some-file"); @@ -160,12 +160,12 @@ describe("determineModuleContext", () => { it("strips a lib prefix", (context) => { const tempDirectoryPath = setupTempDirectory(context, { - "package.json": `{ "name": "my-package" }`, + "package.json": `{ "name": "my-package" }` }); { const { packageName, relativePath } = determineModuleContext( - path.join(tempDirectoryPath, "some-dir/libsome-file.node"), + path.join(tempDirectoryPath, "some-dir/libsome-file.node") ); assert.equal(packageName, "my-package"); assert.equal(relativePath, "some-dir/some-file"); @@ -177,12 +177,12 @@ describe("determineModuleContext", () => { "package.json": `{ "name": "root-package" }`, // Two sub-packages with the same name "sub-package-a/package.json": `{ "name": "my-sub-package-a" }`, - "sub-package-b/package.json": `{ "name": "my-sub-package-b" }`, + "sub-package-b/package.json": `{ "name": "my-sub-package-b" }` }); { const { packageName, relativePath } = determineModuleContext( - path.join(tempDirectoryPath, "sub-package-a/some-file.node"), + path.join(tempDirectoryPath, "sub-package-a/some-file.node") ); assert.equal(packageName, "my-sub-package-a"); assert.equal(relativePath, "some-file"); @@ -190,7 +190,7 @@ describe("determineModuleContext", () => { { const { packageName, relativePath } = determineModuleContext( - path.join(tempDirectoryPath, "sub-package-b/some-file.node"), + path.join(tempDirectoryPath, "sub-package-b/some-file.node") ); assert.equal(packageName, "my-sub-package-b"); assert.equal(relativePath, "some-file"); @@ -204,20 +204,20 @@ describe("getLibraryName", () => { "package.json": `{ "name": "my-package" }`, "addon.apple.node/addon.node": "// This is supposed to be a binary file", "sub-directory/addon.apple.node/addon.node": - "// This is supposed to be a binary file", + "// This is supposed to be a binary file" }); assert.equal( getLibraryName(path.join(tempDirectoryPath, "addon"), { - pathSuffix: "keep", + pathSuffix: "keep" }), - "my-package--addon", + "my-package--addon" ); assert.equal( getLibraryName(path.join(tempDirectoryPath, "sub-directory/addon"), { - pathSuffix: "keep", + pathSuffix: "keep" }), - "my-package--sub-directory-addon", + "my-package--sub-directory-addon" ); }); @@ -226,20 +226,20 @@ describe("getLibraryName", () => { "package.json": `{ "name": "my-package" }`, "addon.apple.node/addon.node": "// This is supposed to be a binary file", "sub-directory/addon.apple.node/addon.node": - "// This is supposed to be a binary file", + "// This is supposed to be a binary file" }); assert.equal( getLibraryName(path.join(tempDirectoryPath, "addon"), { - pathSuffix: "strip", + pathSuffix: "strip" }), - "my-package--addon", + "my-package--addon" ); assert.equal( getLibraryName(path.join(tempDirectoryPath, "sub-directory", "addon"), { - pathSuffix: "strip", + pathSuffix: "strip" }), - "my-package--addon", + "my-package--addon" ); }); @@ -248,20 +248,20 @@ describe("getLibraryName", () => { "package.json": `{ "name": "my-package" }`, "addon.apple.node/addon.node": "// This is supposed to be a binary file", "sub-directory/addon.apple.node/addon.node": - "// This is supposed to be a binary file", + "// This is supposed to be a binary file" }); assert.equal( getLibraryName(path.join(tempDirectoryPath, "addon"), { - pathSuffix: "omit", + pathSuffix: "omit" }), - "my-package", + "my-package" ); assert.equal( getLibraryName(path.join(tempDirectoryPath, "sub-directory", "addon"), { - pathSuffix: "omit", + pathSuffix: "omit" }), - "my-package", + "my-package" ); }); }); @@ -272,36 +272,36 @@ describe("findPackageDependencyPaths", () => { "node_modules/lib-a": { "package.json": JSON.stringify({ name: "lib-a", - main: "index.js", + main: "index.js" }), - "index.js": "", + "index.js": "" }, "test-package": { "package.json": JSON.stringify({ name: "test-package", dependencies: { "lib-a": "^1.0.0", - "lib-b": "^1.0.0", - }, + "lib-b": "^1.0.0" + } }), "src/index.js": "console.log('Hello, world!')", "node_modules/lib-b": { "package.json": JSON.stringify({ name: "lib-b", - main: "index.js", + main: "index.js" }), - "index.js": "", - }, - }, + "index.js": "" + } + } }); const result = findPackageDependencyPaths( - path.join(tempDir, "test-package/src/index.js"), + path.join(tempDir, "test-package/src/index.js") ); assert.deepEqual(result, { "lib-a": path.join(tempDir, "node_modules/lib-a"), - "lib-b": path.join(tempDir, "test-package/node_modules/lib-b"), + "lib-b": path.join(tempDir, "test-package/node_modules/lib-b") }); }); }); @@ -311,16 +311,16 @@ describe("findNodeApiModulePaths", () => { const tempDir = setupTempDirectory(context, { "root.apple.node/react-native-node-api-module": "", "sub-directory/lib-a.apple.node/react-native-node-api-module": "", - "sub-directory/lib-b.apple.node/react-native-node-api-module": "", + "sub-directory/lib-b.apple.node/react-native-node-api-module": "" }); const result = await findNodeApiModulePaths({ fromPath: tempDir, - platform: "apple", + platform: "apple" }); assert.deepEqual(result.sort(), [ path.join(tempDir, "root.apple.node"), path.join(tempDir, "sub-directory/lib-a.apple.node"), - path.join(tempDir, "sub-directory/lib-b.apple.node"), + path.join(tempDir, "sub-directory/lib-b.apple.node") ]); }); @@ -330,15 +330,15 @@ describe("findNodeApiModulePaths", () => { "node_modules/dependency/lib.apple.node/react-native-node-api-module": "", "child-dir/dependency/lib.apple.node/react-native-node-api-module": "", "child-dir/node_modules/dependency/lib.apple.node/react-native-node-api-module": - "", + "" }); const result = await findNodeApiModulePaths({ fromPath: tempDir, - platform: "apple", + platform: "apple" }); assert.deepEqual(result.sort(), [ path.join(tempDir, "child-dir/dependency/lib.apple.node"), - path.join(tempDir, "root.apple.node"), + path.join(tempDir, "root.apple.node") ]); }); @@ -347,16 +347,16 @@ describe("findNodeApiModulePaths", () => { "root.apple.node/react-native-node-api-module": "", "child-dir/dependency/lib.apple.node/react-native-node-api-module": "", "child-dir/node_modules/dependency/lib.apple.node/react-native-node-api-module": - "", + "" }); const result = await findNodeApiModulePaths({ fromPath: tempDir, platform: "apple", - excludePatterns: [/root/], + excludePatterns: [/root/] }); assert.deepEqual(result.sort(), [ path.join(tempDir, "child-dir/dependency/lib.apple.node"), - path.join(tempDir, "child-dir/node_modules/dependency/lib.apple.node"), + path.join(tempDir, "child-dir/node_modules/dependency/lib.apple.node") ]); }); @@ -364,14 +364,14 @@ describe("findNodeApiModulePaths", () => { const tempDir = setupTempDirectory(context, { "node_modules/root.apple.node/react-native-node-api-module": "", "node_modules/child-dir/node_modules/dependency/lib.apple.node/react-native-node-api-module": - "", + "" }); const result = await findNodeApiModulePaths({ fromPath: path.join(tempDir, "node_modules"), - platform: "apple", + platform: "apple" }); assert.deepEqual(result, [ - path.join(tempDir, "node_modules/root.apple.node"), + path.join(tempDir, "node_modules/root.apple.node") ]); }); @@ -381,20 +381,20 @@ describe("findNodeApiModulePaths", () => { { skip: process.platform === "win32" }, async (context) => { const tempDir = setupTempDirectory(context, { - "addon.apple.node/react-native-node-api-module": "", + "addon.apple.node/react-native-node-api-module": "" }); removeReadPermissions(tempDir); try { const result = findNodeApiModulePaths({ fromPath: tempDir, - platform: "apple", + platform: "apple" }); assert.deepEqual(await result, []); } finally { restoreReadPermissions(tempDir); } - }, + } ); }); @@ -405,8 +405,8 @@ describe("findNodeApiModulePathsByDependency", () => { "app/package.json": JSON.stringify({ name: "app", dependencies: Object.fromEntries( - packagesNames.map((packageName) => [packageName, "^1.0.0"]), - ), + packagesNames.map((packageName) => [packageName, "^1.0.0"]) + ) }), ...Object.fromEntries( packagesNames.map((packageName) => [ @@ -414,30 +414,30 @@ describe("findNodeApiModulePathsByDependency", () => { { "package.json": JSON.stringify({ name: packageName, - main: "index.js", + main: "index.js" }), "index.js": "", - "addon.apple.node/react-native-node-api-module": "", - }, - ]), - ), + "addon.apple.node/react-native-node-api-module": "" + } + ]) + ) }); const result = await findNodeApiModulePathsByDependency({ fromPath: path.join(tempDir, "app"), platform: "apple", includeSelf: false, - excludePackages: ["lib-a"], + excludePackages: ["lib-a"] }); assert.deepEqual(result, { "lib-b": { path: path.join(tempDir, "app/node_modules/lib-b"), - modulePaths: ["addon.apple.node"], + modulePaths: ["addon.apple.node"] }, "lib-c": { path: path.join(tempDir, "app/node_modules/lib-c"), - modulePaths: ["addon.apple.node"], - }, + modulePaths: ["addon.apple.node"] + } }); }); }); @@ -448,7 +448,7 @@ describe("determineModuleContext", () => { "package.json": `{ "name": "cached-pkg" }`, "subdir1/file1.node": "", "subdir2/file2.node": "", - "subdir1/file1.apple.node": "", + "subdir1/file1.apple.node": "" }); let readCount = 0; const orig = fs.readFileSync; @@ -461,14 +461,14 @@ describe("determineModuleContext", () => { readCount++; } return orig(...args); - }, + } ); const ctx1 = determineModuleContext( - path.join(tempDir, "subdir1/file1.node"), + path.join(tempDir, "subdir1/file1.node") ); const ctx2 = determineModuleContext( - path.join(tempDir, "subdir2/file2.node"), + path.join(tempDir, "subdir2/file2.node") ); assert.equal(ctx1.packageName, "cached-pkg"); assert.equal(ctx2.packageName, "cached-pkg"); @@ -485,19 +485,19 @@ describe("findNodeAddonForBindings()", () => { addon_5: "out/Release/addon_5.node", addon_6: "out/Debug/addon_6.node", addon_7: "Release/addon_7.node", - addon_8: "Debug/addon_8.node", + addon_8: "Debug/addon_8.node" }; for (const [name, relPath] of Object.entries(expectedPaths)) { it(`should look for addons in common paths (${name} in "${relPath}")`, async (context) => { // Arrange const tempDirectoryPath = setupTempDirectory(context, { - [relPath]: "// This is supposed to be a binary file", + [relPath]: "// This is supposed to be a binary file" }); // Act const actualPath = await findNodeAddonForBindings( name, - tempDirectoryPath, + tempDirectoryPath ); // Assert const expectedAbsPath = path.join(tempDirectoryPath, relPath); diff --git a/packages/host/src/node/path-utils.ts b/packages/host/src/node/path-utils.ts index 60a06a4d..ac297641 100644 --- a/packages/host/src/node/path-utils.ts +++ b/packages/host/src/node/path-utils.ts @@ -13,7 +13,7 @@ export type PlatformName = "android" | "apple"; export const PLATFORM_EXTENSIONS = { android: ".android.node", - apple: ".apple.node", + apple: ".apple.node" } as const satisfies Record; export type PlatformExtentions = (typeof PLATFORM_EXTENSIONS)[PlatformName]; @@ -22,15 +22,15 @@ export const PATH_SUFFIX_CHOICES = ["strip", "keep", "omit"] as const; export type PathSuffixChoice = (typeof PATH_SUFFIX_CHOICES)[number]; export function assertPathSuffix( - value: unknown, + value: unknown ): asserts value is PathSuffixChoice { assert( typeof value === "string", - `Expected a string, got ${typeof value} (${value})`, + `Expected a string, got ${typeof value} (${value})` ); assert( (PATH_SUFFIX_CHOICES as readonly string[]).includes(value), - `Expected one of ${PATH_SUFFIX_CHOICES.join(", ")}`, + `Expected one of ${PATH_SUFFIX_CHOICES.join(", ")}` ); } @@ -60,7 +60,7 @@ export function isNodeApiModule(modulePath: string): boolean { // HACK: Take a shortcut (if applicable): existing `.node` files are addons try { fs.accessSync( - modulePath.endsWith(".node") ? modulePath : `${modulePath}.node`, + modulePath.endsWith(".node") ? modulePath : `${modulePath}.node` ); return true; } catch { @@ -129,7 +129,7 @@ export function stripExtension(modulePath: string) { return modulePath; } }, - modulePath, + modulePath ); } @@ -143,7 +143,7 @@ export type ModuleContext = { */ export function determineModuleContext( modulePath: string, - originalPath = modulePath, + originalPath = modulePath ): ModuleContext { // Locate nearest package directory const pkgDir = packageDirectorySync({ cwd: modulePath }); @@ -156,7 +156,7 @@ export function determineModuleContext( const pkg = readPackageSync({ cwd: pkgDir }); assert( typeof pkg.name === "string", - "Expected package.json to have a name", + "Expected package.json to have a name" ); pkgName = pkg.name; packageNameCache.set(pkgDir, pkgName); @@ -189,19 +189,19 @@ export function getLibraryName(modulePath: string, naming: NamingStrategy) { : `${escapedPackageName}--${escapePath( naming.pathSuffix === "strip" ? path.basename(relativePath) - : relativePath, + : relativePath )}`; } export function prettyPath(p: string) { return chalk.dim( - path.relative(process.cwd(), p) || chalk.italic("current directory"), + path.relative(process.cwd(), p) || chalk.italic("current directory") ); } export function resolvePackageRoot( requireFromPackageRoot: NodeJS.Require, - packageName: string, + packageName: string ): string | undefined { try { const resolvedPath = requireFromPackageRoot.resolve(packageName); @@ -215,7 +215,7 @@ export function resolvePackageRoot( export function logModulePaths( modulePaths: string[], // TODO: Default to iterating and printing for all supported naming strategies - naming: NamingStrategy, + naming: NamingStrategy ) { const pathsPerName = new Map(); for (const modulePath of modulePaths) { @@ -235,7 +235,7 @@ export function logModulePaths( ? chalk.redBright(prettyPath(modulePath)) : prettyPath(modulePath); return `\n ↳ ${line}`; - }), + }) ); } } @@ -245,13 +245,13 @@ export function logModulePaths( * return a record mapping from each dependencies of that package to their path on disk. */ export function findPackageDependencyPaths( - fromPath: string, + fromPath: string ): Record { const packageRoot = packageDirectorySync({ cwd: fromPath }); assert(packageRoot, `Could not find package root from ${fromPath}`); const requireFromPackageRoot = createRequire( - path.join(packageRoot, "noop.js"), + path.join(packageRoot, "noop.js") ); const { dependencies = {} } = readPackageSync({ cwd: packageRoot }); @@ -261,13 +261,13 @@ export function findPackageDependencyPaths( .map((dependencyName) => { const resolvedDependencyRoot = resolvePackageRoot( requireFromPackageRoot, - dependencyName, + dependencyName ); return resolvedDependencyRoot ? [dependencyName, resolvedDependencyRoot] : undefined; }) - .filter((item) => typeof item !== "undefined"), + .filter((item) => typeof item !== "undefined") ); } @@ -278,12 +278,12 @@ export const MAGIC_FILENAME = "react-native-node-api-module"; */ export const DEFAULT_EXCLUDE_PATTERNS = [ /(^|\/)node_modules\//, - /(^|\/).git\//, + /(^|\/).git\// ]; export function hasPlatformExtension( platform: PlatformName | Readonly, - fileName: string, + fileName: string ): boolean { if (typeof platform === "string") { return fileName.endsWith(PLATFORM_EXTENSIONS[platform]); @@ -303,12 +303,12 @@ export type FindNodeApiModuleOptions = { */ export async function findNodeApiModulePaths( options: FindNodeApiModuleOptions, - suffix = "", + suffix = "" ): Promise { const { fromPath, platform, - excludePatterns = DEFAULT_EXCLUDE_PATTERNS, + excludePatterns = DEFAULT_EXCLUDE_PATTERNS } = options; if (excludePatterns.some((pattern) => pattern.test(suffix))) { return []; @@ -336,7 +336,7 @@ export async function findNodeApiModulePaths( // Traverse into the child directory // Pushing result into a list instead of awaiting immediately to parallelize the search pendingResults.push( - findNodeApiModulePaths(options, path.join(suffix, dirent.name)), + findNodeApiModulePaths(options, path.join(suffix, dirent.name)) ); } } @@ -361,7 +361,7 @@ export async function findNodeApiModulePaths( */ export const DEFAULT_EXCLUDE_PACKAGES = [ "react-native-node-api", // The host package itself - "react-native", // React Native core + "react-native" // React Native core ]; /** @@ -393,23 +393,23 @@ export async function findNodeApiModulePathsByDependency({ // Make all the xcframeworks relative to the dependency path const absoluteModulePaths = await findNodeApiModulePaths({ fromPath: dependencyPath, - ...options, + ...options }); return [ dependencyName, { path: dependencyPath, modulePaths: absoluteModulePaths.map((p) => - path.relative(dependencyPath, p), - ), - }, + path.relative(dependencyPath, p) + ) + } ] as const; - }), + }) ); // Return an object by dependency name return Object.fromEntries( // Remove any dependencies without Node-API module paths - resultEntries.filter(([, { modulePaths }]) => modulePaths.length > 0), + resultEntries.filter(([, { modulePaths }]) => modulePaths.length > 0) ); } @@ -420,18 +420,18 @@ export async function findNodeApiModulePathsByDependency({ export function determineLibraryBasename(libraryPaths: string[]) { assert( libraryPaths.length > 0, - "Expected at least one library path to determine its basename", + "Expected at least one library path to determine its basename" ); const libraryNames = libraryPaths.map((p) => // Strip the "lib" prefix and any file extension path .basename(p, path.extname(p)) - .replace(/^lib/, ""), + .replace(/^lib/, "") ); const candidates = new Set(libraryNames); assert( candidates.size === 1, - `Expected all libraries to share name, got: ${[...candidates].join(", ")}`, + `Expected all libraries to share name, got: ${[...candidates].join(", ")}` ); const [name] = candidates; return name; @@ -449,7 +449,7 @@ export function getAutolinkPath(platform: PlatformName) { export function getLatestMtime(fromPath: string): number { const entries = fs.readdirSync(fromPath, { withFileTypes: true, - recursive: true, + recursive: true }); let latest = 0; @@ -477,7 +477,7 @@ const nodeBindingsSubdirs = [ "./out/Release", "./out/Debug", "./Release", - "./Debug", + "./Debug" ]; export function findNodeAddonForBindings(id: string, fromDir: string) { diff --git a/packages/host/src/node/prebuilds/android.ts b/packages/host/src/node/prebuilds/android.ts index 9c750059..792b7198 100644 --- a/packages/host/src/node/prebuilds/android.ts +++ b/packages/host/src/node/prebuilds/android.ts @@ -8,7 +8,7 @@ export const DEFAULT_ANDROID_TRIPLETS = [ "aarch64-linux-android", "armv7a-linux-androideabi", "i686-linux-android", - "x86_64-linux-android", + "x86_64-linux-android" ] as const satisfies AndroidTriplet[]; type AndroidArchitecture = "armeabi-v7a" | "arm64-v8a" | "x86" | "x86_64"; @@ -17,7 +17,7 @@ export const ANDROID_ARCHITECTURES = { "armv7a-linux-androideabi": "armeabi-v7a", "aarch64-linux-android": "arm64-v8a", "i686-linux-android": "x86", - "x86_64-linux-android": "x86_64", + "x86_64-linux-android": "x86_64" } satisfies Record; /** @@ -38,7 +38,7 @@ type AndroidLibsDirectoryOptions = { export async function createAndroidLibsDirectory({ outputPath, libraryPathByTriplet, - autoLink, + autoLink }: AndroidLibsDirectoryOptions) { // Delete and recreate any existing output directory await fs.promises.rm(outputPath, { recursive: true, force: true }); @@ -46,7 +46,7 @@ export async function createAndroidLibsDirectory({ for (const [triplet, libraryPath] of Object.entries(libraryPathByTriplet)) { assert( fs.existsSync(libraryPath), - `Library not found: ${libraryPath} for triplet ${triplet}`, + `Library not found: ${libraryPath} for triplet ${triplet}` ); const arch = ANDROID_ARCHITECTURES[triplet as AndroidTriplet]; const archOutputPath = path.join(outputPath, arch); @@ -67,7 +67,7 @@ export async function createAndroidLibsDirectory({ await fs.promises.writeFile( path.join(outputPath, "react-native-node-api-module"), "", - "utf8", + "utf8" ); } return outputPath; diff --git a/packages/host/src/node/prebuilds/apple.ts b/packages/host/src/node/prebuilds/apple.ts index e727ec27..a30d4cd8 100644 --- a/packages/host/src/node/prebuilds/apple.ts +++ b/packages/host/src/node/prebuilds/apple.ts @@ -20,7 +20,7 @@ export const APPLE_ARCHITECTURES = { // "x86_64-apple-tvos": "x86_64", "arm64-apple-tvos-sim": "arm64", "arm64-apple-visionos": "arm64", - "arm64-apple-visionos-sim": "arm64", + "arm64-apple-visionos-sim": "arm64" } satisfies Record; export function createPlistContent(values: Record) { @@ -31,10 +31,10 @@ export function createPlistContent(values: Record) { " ", ...Object.entries(values).flatMap(([key, value]) => [ ` ${key}`, - ` ${value}`, + ` ${value}` ]), " ", - "", + "" ].join("\n"); } @@ -50,7 +50,7 @@ export function createAppleFramework(libraryPath: string) { const libraryName = path.basename(libraryPath, path.extname(libraryPath)); const frameworkPath = path.join( path.dirname(libraryPath), - `${libraryName}.framework`, + `${libraryName}.framework` ); // Create the framework from scratch fs.rmSync(frameworkPath, { recursive: true, force: true }); @@ -68,9 +68,9 @@ export function createAppleFramework(libraryPath: string) { CFBundlePackageType: "FMWK", CFBundleShortVersionString: "1.0", CFBundleVersion: "1", - NSPrincipalClass: "", + NSPrincipalClass: "" }), - "utf8", + "utf8" ); const newLibraryPath = path.join(frameworkPath, libraryName); // TODO: Consider copying the library instead of renaming it @@ -79,7 +79,7 @@ export function createAppleFramework(libraryPath: string) { cp.spawnSync("install_name_tool", [ "-id", `@rpath/${libraryName}.framework/${libraryName}`, - newLibraryPath, + newLibraryPath ]); return frameworkPath; } @@ -87,7 +87,7 @@ export function createAppleFramework(libraryPath: string) { export async function createXCframework({ frameworkPaths, outputPath, - autoLink, + autoLink }: XCframeworkOptions) { // Delete any existing xcframework to prevent the error: // - A library with the identifier 'macos-arm64' already exists. @@ -106,11 +106,11 @@ export async function createXCframework({ "-create-xcframework", ...frameworkPaths.flatMap((p) => ["-framework", p]), "-output", - xcodeOutputPath, + xcodeOutputPath ], { - outputMode: "buffered", - }, + outputMode: "buffered" + } ); if (xcodeOutputPath !== outputPath) { // Rename the xcframework to the original output path @@ -122,7 +122,7 @@ export async function createXCframework({ fs.writeFileSync( path.join(outputPath, "react-native-node-api-module"), "", - "utf8", + "utf8" ); } } @@ -133,7 +133,7 @@ export async function createXCframework({ */ export function determineXCFrameworkFilename( frameworkPaths: string[], - extension: ".xcframework" | ".apple.node" = ".xcframework", + extension: ".xcframework" | ".apple.node" = ".xcframework" ) { const name = determineLibraryBasename(frameworkPaths); return `${name}${extension}`; @@ -144,15 +144,15 @@ export async function createUniversalAppleLibrary(libraryPaths: string[]) { const filenames = new Set(libraryPaths.map((p) => path.basename(p))); assert( filenames.size === 1, - "Expected all darwin libraries to have the same name", + "Expected all darwin libraries to have the same name" ); const [filename] = filenames; const lipoParentPath = fs.realpathSync( - fs.mkdtempSync(path.join(os.tmpdir(), "ferric-lipo-output-")), + fs.mkdtempSync(path.join(os.tmpdir(), "ferric-lipo-output-")) ); const outputPath = path.join(lipoParentPath, filename); await spawn("lipo", ["-create", "-output", outputPath, ...libraryPaths], { - outputMode: "buffered", + outputMode: "buffered" }); assert(fs.existsSync(outputPath), "Expected lipo output path to exist"); return outputPath; diff --git a/packages/host/src/node/prebuilds/triplets.ts b/packages/host/src/node/prebuilds/triplets.ts index 7471b15b..fe0ed96b 100644 --- a/packages/host/src/node/prebuilds/triplets.ts +++ b/packages/host/src/node/prebuilds/triplets.ts @@ -5,7 +5,7 @@ export const ANDROID_TRIPLETS = [ "aarch64-linux-android", "armv7a-linux-androideabi", "i686-linux-android", - "x86_64-linux-android", + "x86_64-linux-android" ] as const; export type AndroidTriplet = (typeof ANDROID_TRIPLETS)[number]; @@ -20,32 +20,32 @@ export const APPLE_TRIPLETS = [ "arm64-apple-tvos-sim", // "x86_64-apple-tvos", "arm64-apple-visionos", - "arm64-apple-visionos-sim", + "arm64-apple-visionos-sim" ] as const; export type AppleTriplet = (typeof APPLE_TRIPLETS)[number]; export const SUPPORTED_TRIPLETS = [ ...APPLE_TRIPLETS, - ...ANDROID_TRIPLETS, + ...ANDROID_TRIPLETS ] as const; export type SupportedTriplet = (typeof SUPPORTED_TRIPLETS)[number]; export function isSupportedTriplet( - triplet: unknown, + triplet: unknown ): triplet is SupportedTriplet { return (SUPPORTED_TRIPLETS as readonly unknown[]).includes(triplet); } export function isAndroidTriplet( - triplet: SupportedTriplet, + triplet: SupportedTriplet ): triplet is AndroidTriplet { return (ANDROID_TRIPLETS as readonly unknown[]).includes(triplet); } export function isAppleTriplet( - triplet: SupportedTriplet, + triplet: SupportedTriplet ): triplet is AppleTriplet { return (APPLE_TRIPLETS as readonly unknown[]).includes(triplet); } diff --git a/packages/host/src/node/test-utils.ts b/packages/host/src/node/test-utils.ts index a1791502..20fc1a04 100644 --- a/packages/host/src/node/test-utils.ts +++ b/packages/host/src/node/test-utils.ts @@ -21,7 +21,7 @@ function writeFiles(fromPath: string, files: FileMap) { export function setupTempDirectory(context: TestContext, files: FileMap) { const tempDirectoryPath = fs.realpathSync( - fs.mkdtempSync(path.join(os.tmpdir(), "react-native-node-api-test-")), + fs.mkdtempSync(path.join(os.tmpdir(), "react-native-node-api-test-")) ); context.after(() => { diff --git a/packages/host/src/node/weak-node-api.ts b/packages/host/src/node/weak-node-api.ts index 02e3befe..df29834f 100644 --- a/packages/host/src/node/weak-node-api.ts +++ b/packages/host/src/node/weak-node-api.ts @@ -6,5 +6,5 @@ export const weakNodeApiPath = path.resolve(__dirname, "../../weak-node-api"); assert( fs.existsSync(weakNodeApiPath), - `Expected Weak Node API path to exist: ${weakNodeApiPath}`, + `Expected Weak Node API path to exist: ${weakNodeApiPath}` ); diff --git a/packages/node-addon-examples/scripts/build-examples.mts b/packages/node-addon-examples/scripts/build-examples.mts index fd590eb6..24d702b2 100644 --- a/packages/node-addon-examples/scripts/build-examples.mts +++ b/packages/node-addon-examples/scripts/build-examples.mts @@ -12,8 +12,8 @@ for (const projectDirectory of projectDirectories) { // "cmake-rn --triplet aarch64-linux-android --triplet arm64-apple-ios-sim", { cwd: projectDirectory, - stdio: "inherit", - }, + stdio: "inherit" + } ); console.log(); } diff --git a/packages/node-addon-examples/scripts/copy-examples.mts b/packages/node-addon-examples/scripts/copy-examples.mts index 1c8eb845..37a5eb82 100644 --- a/packages/node-addon-examples/scripts/copy-examples.mts +++ b/packages/node-addon-examples/scripts/copy-examples.mts @@ -32,7 +32,7 @@ const ALLOW_LIST = [ // "5-async-work/async_pi_estimate/node-addon-api/" // Disabled, as it's using process.argv // "5-async-work/async_work_promise/napi/" // Disabled, as it's using process.argv // "5-async-work/async_work_promise/node-addon-api/" // Disabled, as it's using process.argv - "5-async-work/async_work_thread_safe_function/napi/", + "5-async-work/async_work_thread_safe_function/napi/" // "5-async-work/async-iterator/node-addon-api/" // Brings its own CMake project 👀 // "5-async-work/call-js-from-async-worker-execute/node-addon-api/" // Disabled, as it's using "node:events" // TODO: Perhaps we should make sure gyp-to-cmake produce projects which match the output directory of gyp, to fix 👇 @@ -58,7 +58,7 @@ console.log("Copying files to", EXAMPLES_DIR); const require = createRequire(import.meta.url); const EXAMPLES_PACKAGE_PATH = require.resolve( - "node-addon-examples/package.json", + "node-addon-examples/package.json" ); const SRC_DIR = path.join(path.dirname(EXAMPLES_PACKAGE_PATH), "src"); console.log("Copying files from", SRC_DIR); @@ -73,7 +73,7 @@ for (const src of ALLOW_LIST) { if (fs.existsSync(destPath)) { console.warn( - `Destination path ${destPath} already exists - skipping copy of ${src}.`, + `Destination path ${destPath} already exists - skipping copy of ${src}.` ); continue; } @@ -84,7 +84,7 @@ for (const src of ALLOW_LIST) { // as they have duplicate names, causing collisions when vendored into the host package. for (const entry of fs.readdirSync(destPath, { withFileTypes: true, - recursive: true, + recursive: true })) { if (entry.name === "package.json") { const packageJson = readPackageSync({ cwd: entry.parentPath }); @@ -93,7 +93,7 @@ for (const src of ALLOW_LIST) { fs.writeFileSync( path.join(entry.parentPath, entry.name), JSON.stringify(packageJson, null, 2), - "utf-8", + "utf-8" ); } } diff --git a/packages/node-addon-examples/scripts/verify-prebuilds.mts b/packages/node-addon-examples/scripts/verify-prebuilds.mts index 498b9e73..81b4c4e8 100644 --- a/packages/node-addon-examples/scripts/verify-prebuilds.mts +++ b/packages/node-addon-examples/scripts/verify-prebuilds.mts @@ -13,7 +13,7 @@ const EXPECTED_XCFRAMEWORK_PLATFORMS = [ "tvos-arm64", "tvos-arm64-simulator", "xros-arm64", - "xros-arm64-simulator", + "xros-arm64-simulator" ]; async function verifyAndroidPrebuild(dirent: fs.Dirent) { @@ -21,17 +21,17 @@ async function verifyAndroidPrebuild(dirent: fs.Dirent) { "Verifying Android prebuild", dirent.name, "in", - dirent.parentPath, + dirent.parentPath ); for (const arch of EXPECTED_ANDROID_ARCHS) { const archDir = path.join(dirent.parentPath, dirent.name, arch); for (const file of await fs.promises.readdir(archDir, { - withFileTypes: true, + withFileTypes: true })) { assert(file.isFile()); assert( !file.name.endsWith(".node"), - `Unexpected .node file: ${path.join(file.parentPath, file.name)}`, + `Unexpected .node file: ${path.join(file.parentPath, file.name)}` ); } } @@ -42,27 +42,27 @@ async function verifyApplePrebuild(dirent: fs.Dirent) { for (const arch of EXPECTED_XCFRAMEWORK_PLATFORMS) { const archDir = path.join(dirent.parentPath, dirent.name, arch); for (const file of await fs.promises.readdir(archDir, { - withFileTypes: true, + withFileTypes: true })) { assert( file.isDirectory(), - "Expected only directories in xcframework arch directory", + "Expected only directories in xcframework arch directory" ); assert(file.name.endsWith(".framework"), "Expected framework directory"); const frameworkDir = path.join(file.parentPath, file.name); for (const file of await fs.promises.readdir(frameworkDir, { - withFileTypes: true, + withFileTypes: true })) { if (file.isDirectory()) { assert.equal( file.name, "Headers", - "Unexpected directory in xcframework", + "Unexpected directory in xcframework" ); } else { assert( file.isFile(), - "Expected only directory and files in framework", + "Expected only directory and files in framework" ); if (file.name === "Info.plist") { } else { @@ -70,8 +70,8 @@ async function verifyApplePrebuild(dirent: fs.Dirent) { !file.name.endsWith(".node"), `Didn't expected a .node file in xcframework: ${path.join( frameworkDir, - file.name, - )}`, + file.name + )}` ); } } @@ -82,7 +82,7 @@ async function verifyApplePrebuild(dirent: fs.Dirent) { for await (const dirent of fs.promises.glob("**/*.*.node", { cwd: EXAMPLES_DIR, - withFileTypes: true, + withFileTypes: true })) { if (dirent.name.endsWith(".android.node")) { await verifyAndroidPrebuild(dirent); @@ -90,7 +90,7 @@ for await (const dirent of fs.promises.glob("**/*.*.node", { await verifyApplePrebuild(dirent); } else { throw new Error( - `Unexpected prebuild file: ${dirent.name} in ${dirent.parentPath}`, + `Unexpected prebuild file: ${dirent.name} in ${dirent.parentPath}` ); } } diff --git a/packages/node-addon-examples/src/index.ts b/packages/node-addon-examples/src/index.ts index 196810a1..9ebaf93d 100644 --- a/packages/node-addon-examples/src/index.ts +++ b/packages/node-addon-examples/src/index.ts @@ -13,9 +13,7 @@ function assertLogs(cb: () => void, expectedMessages: string[]) { cb(); if (expectedMessages.length > 0) { errors.push( - new Error( - `Missing expected message(s): ${expectedMessages.join(", ")}`, - ), + new Error(`Missing expected message(s): ${expectedMessages.join(", ")}`) ); } } finally { @@ -38,62 +36,62 @@ export const suites: Record< assertLogs( () => require("../examples/1-getting-started/1_hello_world/napi/hello.js"), - ["world"], + ["world"] ), "1_hello_world/node-addon-api": () => assertLogs( () => require("../examples/1-getting-started/1_hello_world/node-addon-api/hello.js"), - ["world"], + ["world"] ), "1_hello_world/node-addon-api-addon-class": () => assertLogs( () => require("../examples/1-getting-started/1_hello_world/node-addon-api-addon-class/hello.js"), - ["world"], + ["world"] ), "2_function_arguments/napi": () => assertLogs( () => require("../examples/1-getting-started/2_function_arguments/napi/addon.js"), - ["This should be eight: 8"], + ["This should be eight: 8"] ), "2_function_arguments/node-addon-api": () => assertLogs( () => require("../examples/1-getting-started/2_function_arguments/node-addon-api/addon.js"), - ["This should be eight: 8"], + ["This should be eight: 8"] ), "3_callbacks/napi": () => assertLogs( () => require("../examples/1-getting-started/3_callbacks/napi/addon.js"), - ["hello world"], + ["hello world"] ), "3_callbacks/node-addon-api": () => assertLogs( () => require("../examples/1-getting-started/3_callbacks/node-addon-api/addon.js"), - ["hello world"], + ["hello world"] ), "4_object_factory/napi": () => assertLogs( () => require("../examples/1-getting-started/4_object_factory/napi/addon.js"), - ["hello world"], + ["hello world"] ), "4_object_factory/node-addon-api": () => assertLogs( () => require("../examples/1-getting-started/4_object_factory/node-addon-api/addon.js"), - ["hello world"], + ["hello world"] ), "5_function_factory": () => assertLogs( () => require("../examples/1-getting-started/5_function_factory/napi/addon.js"), - ["hello world"], - ), + ["hello world"] + ) }, "5-async-work": { // TODO: This crashes (SIGABRT) @@ -101,6 +99,6 @@ export const suites: Record< }, tests: { buffers: () => require("../tests/buffers/addon.js"), - async: () => require("../tests/async/addon.js"), - }, + async: () => require("../tests/async/addon.js") + } };