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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 65 additions & 1 deletion docs/CLI.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,67 @@
# The `react-native-node-api` command-line interface (CLI)

<!-- TODO: Write detailed documentation of each command and their parameters -->
The `react-native-node-api` package installs a `react-native-node-api` binary, which app and library authors use to vendor Hermes, link Node-API modules into an app and inspect how the library-naming scheme resolves for a given module.

```bash
npx react-native-node-api <command> [options]
```

Run `npx react-native-node-api help` or `npx react-native-node-api help <command>` to see this same information from the CLI itself.

> [!NOTE]
> This document is hand-written from the [Commander](https://github.com/tj/commander.js) program definition in [`packages/host/src/node/cli/program.ts`](../packages/host/src/node/cli/program.ts) (with the `vendor-hermes` command defined in [`hermes.ts`](../packages/host/src/node/cli/hermes.ts)). It needs to be kept in sync by hand whenever a command or its options change.

## `vendor-hermes [from]`

Clones the pinned commit of Hermes' `static_h` branch (which carries Hermes' first-party Node-API implementation) into the `sdks/node-api-hermes` directory of the app's `react-native` package, so the native build can compile against it. Prints the path to the vendored checkout on success.

- `[from]` — Path to a file inside the app package. Defaults to the current working directory.
- `--react-native-package <package-name>` — The React Native package to vendor Hermes into. Defaults to `react-native`.
- `--silent` — Don't print anything except the final path. Defaults to `false`.
- `--force` — Don't check timestamps of input files to skip unnecessary rebuilds; removes and re-clones an existing checkout. Defaults to `false`.

## `link [path]`

Auto-links the Node-API modules found among the app's dependencies for one or more platforms, copying (and, on Apple, signing) them into place.

- `[path]` — Some path inside the app package. Defaults to the current working directory.
- `--android` — Link Android modules.
- `--apple` — Link Apple modules.
- `--prune` — Delete previously vendored modules that are no longer auto-linked. Defaults to `true`.
- `--package-name <strategy>` — Controls how a dependency's package name is transformed into a library name. One of `strip`, `keep` or `omit` (see [Library naming](#library-naming) below). Defaults to `strip`, or the `NODE_API_PACKAGE_NAME` environment variable if set.
- `--path-suffix <strategy>` — Controls how the path of the addon inside a package is transformed into a library name. One of `strip`, `keep` or `omit` (see [Library naming](#library-naming) below). Defaults to `strip`, or the `NODE_API_PATH_SUFFIX` environment variable if set.

At least one of `--android` / `--apple` must be passed, or the command exits with an error listing the supported platforms.

## `list [from-path]`

Lists the Node-API modules found among the dependencies of the package at (or above) a path, without linking them.

- `[from-path]` — Some path inside the app package. Defaults to the current working directory.
- `--json` — Output the result as JSON instead of a human-readable summary. Defaults to `false`.
- `--package-name <strategy>` — Same as for `link` (see [Library naming](#library-naming)).
- `--path-suffix <strategy>` — Same as for `link` (see [Library naming](#library-naming)).

## `info <path>`

Utility to print the resolved module path, package name and computed library name for a single Node-API module, given its path. Useful for debugging naming collisions.

- `<path>` — Path to a Node-API module (e.g. an `*.android.node` directory or `*.apple.node` framework).
- `--package-name <strategy>` — Same as for `link` (see [Library naming](#library-naming)).
- `--path-suffix <strategy>` — Same as for `link` (see [Library naming](#library-naming)).

## `patch-xcode-project [path]`

Patches the app's Xcode project to add a build phase which copies, renames and signs the Node-API frameworks (equivalent to running `link --apple` as part of the Xcode build). Only supported on macOS.

- `[path]` — Some path inside the app package. Defaults to the current working directory.

## Library naming

`--package-name` and `--path-suffix` both control how the [cross-platform library name](./PREBUILDS.md) (`package-name--path-component--addon-name`) is derived, and accept the same three strategies. Given a package `@my-org/my-pkg` with an addon at `build/Release/my-addon.node`:

| Strategy | `--package-name` effect | `--path-suffix` effect |
| -------- | ----------------------------------------- | --------------------------------------------------- |
| `strip` | Scope is dropped: `my-pkg--my-addon` | Path is reduced to its basename: `my-pkg--my-addon` |
| `keep` | Scope is kept: `my-org--my-pkg--my-addon` | Full path is kept: `my-pkg--build-Release-my-addon` |
| `omit` | Package name is dropped: `my-addon` | Path is dropped: `my-pkg` |
64 changes: 61 additions & 3 deletions docs/HOW-IT-WORKS.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,67 @@

This document will outline what happens throughout the various parts of the system, when the app calls the `add` method on the library introduced in the ["usage" document](./USAGE.md).

<!-- TODO: Add Clone this repo: ... -->
<!-- TODO: Add C++ code snippet -->
<!-- TODO: Add JS code snippet on requiring and calling it -->
If you want to follow along with the source code referenced throughout this document (such as `packages/host/cpp/HermesNapiHost.cpp`), clone this repo:

```bash
git clone https://github.com/callstackincubator/react-native-node-api.git
```

`calculator-lib`'s native code is a small Node-API addon written in C (see the ["usage" document](./USAGE.md#implement-native-code) for the full walkthrough of writing and building it):

```cpp
// addon.c

#include <assert.h>
#include <node_api.h>

static napi_value Add(napi_env env, napi_callback_info info) {
napi_status status;

size_t argc = 2;
napi_value args[2];
status = napi_get_cb_info(env, info, &argc, args, NULL, NULL);
assert(status == napi_ok);

double value0, value1;
status = napi_get_value_double(env, args[0], &value0);
assert(status == napi_ok);
status = napi_get_value_double(env, args[1], &value1);
assert(status == napi_ok);

napi_value sum;
status = napi_create_double(env, value0 + value1, &sum);
assert(status == napi_ok);

return sum;
}

#define DECLARE_NAPI_METHOD(name, func) \
{ name, 0, func, 0, 0, 0, napi_default, 0 }

NAPI_MODULE_INIT(/* napi_env env, napi_value exports */) {
napi_status status;

napi_property_descriptor addDescriptor = DECLARE_NAPI_METHOD("add", Add);
status = napi_define_properties(env, exports, 1, &addDescriptor);
assert(status == napi_ok);

return exports;
}
```

`calculator-lib`'s JavaScript entrypoint requires the prebuilt binary produced from that C code:

```javascript
module.exports = require("./prebuild.node");
```

And `my-app` imports and calls it:

```javascript
import { add } from "calculator-lib";
console.log("1 + 2 =", add(1, 2));
```

## `my-app` makes an `import`

Expand Down
Loading