@rejaul/react-native-rust 1.0.2 → 1.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +76 -2
- package/dist/app.js +271 -0
- package/dist/codegen/constants.js +168 -0
- package/dist/codegen/index.js +34 -0
- package/dist/codegen/project.js +201 -0
- package/{bin → dist}/codegen/renderers.js +201 -84
- package/dist/codegen/spec.js +158 -0
- package/dist/codegen/types.js +16 -0
- package/dist/codegen.js +22 -0
- package/dist/react-native-rust-lib.js +388 -0
- package/dist/react-native-rust.js +116 -0
- package/dist/types.js +16 -0
- package/package.json +28 -4
- package/bin/codegen/constants.js +0 -39
- package/bin/codegen/index.js +0 -9
- package/bin/codegen/project.js +0 -168
- package/bin/codegen/spec.js +0 -156
- package/bin/codegen.js +0 -1
- package/bin/react-native-rust-lib.js +0 -302
- package/bin/react-native-rust.js +0 -82
package/README.md
CHANGED
|
@@ -4,11 +4,21 @@ Generate Rust functions and native bindings from a React Native TurboModule Type
|
|
|
4
4
|
|
|
5
5
|
The CLI currently targets the **C++ TurboModule** template created by [`create-react-native-library`](https://www.npmjs.com/package/create-react-native-library).
|
|
6
6
|
|
|
7
|
+
## Screenshots
|
|
8
|
+
|
|
9
|
+
The generated [`react-native-awesome-library-example`](react-native-awesome-library-example) app calling every generated method and rendering its live Rust result, on all three platforms:
|
|
10
|
+
|
|
11
|
+
| Android | iOS | Web |
|
|
12
|
+
| --- | --- | --- |
|
|
13
|
+
|  |  |  |
|
|
14
|
+
|
|
7
15
|
## Contents
|
|
8
16
|
|
|
17
|
+
- [Screenshots](#screenshots)
|
|
9
18
|
- [Requirements](#requirements)
|
|
10
19
|
- [Create a library](#create-a-library)
|
|
11
20
|
- [Add Rust functions](#add-rust-functions)
|
|
21
|
+
- [Use Rust in an app](#use-rust-in-an-app)
|
|
12
22
|
- [Build and run](#build-and-run)
|
|
13
23
|
- [Supported types](#supported-types)
|
|
14
24
|
- [Publish](#publish)
|
|
@@ -24,6 +34,7 @@ The CLI currently targets the **C++ TurboModule** template created by [`create-r
|
|
|
24
34
|
- Rust stable (`rustup`, `cargo`).
|
|
25
35
|
- Android builds: Android SDK/NDK and `cargo-ndk`.
|
|
26
36
|
- iOS builds: macOS, Xcode command-line tools, and the Rust Apple targets.
|
|
37
|
+
- Web builds (`react-native-web`): [`wasm-pack`](https://rustwasm.github.io/wasm-pack/) and the `wasm32-unknown-unknown` Rust target (`rustup target add wasm32-unknown-unknown`).
|
|
27
38
|
|
|
28
39
|
## Create a library
|
|
29
40
|
|
|
@@ -42,10 +53,10 @@ cd react-native-awesome-library
|
|
|
42
53
|
yarn install
|
|
43
54
|
```
|
|
44
55
|
|
|
45
|
-
To run the CLI from its source checkout before publishing,
|
|
56
|
+
To run the CLI from its source checkout before publishing, build it once (`npm run build` from the checkout root), then invoke the compiled output by path from the desired parent folder:
|
|
46
57
|
|
|
47
58
|
```sh
|
|
48
|
-
node /path/to/rust_to_cpp/
|
|
59
|
+
node /path/to/rust_to_cpp/dist/react-native-rust.js create react-native-awesome-library
|
|
49
60
|
```
|
|
50
61
|
|
|
51
62
|
To add Rust support to an existing C++ TurboModule library, install the CLI and initialize it from that library's root:
|
|
@@ -89,6 +100,40 @@ Run Rust tests with:
|
|
|
89
100
|
yarn rust:test
|
|
90
101
|
```
|
|
91
102
|
|
|
103
|
+
## Use Rust in an app
|
|
104
|
+
|
|
105
|
+
For app-specific Rust code, run the CLI from the root of an existing React Native Community CLI app that has both `android/` and `ios/` folders:
|
|
106
|
+
|
|
107
|
+
```sh
|
|
108
|
+
npx react-native-rust init --app
|
|
109
|
+
npm install
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
The command creates a private local TurboModule package in `native/rust-module/`, adds it to the app as a local dependency, and generates its C++ bridge and Rust crate. It does not publish a separate library. App-local mode currently supports C++ TurboModule apps with both Android and iOS projects.
|
|
113
|
+
|
|
114
|
+
Edit `native/rust-module/src/NativeRustApp.ts` to declare methods, then implement their generated handlers under `native/rust-module/rust/src/api/`. From the app root, regenerate the bindings and React Native Codegen output with:
|
|
115
|
+
|
|
116
|
+
```sh
|
|
117
|
+
npm run rust:generate
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
Build the Rust archive for the target platform, then build and launch the React Native app:
|
|
121
|
+
|
|
122
|
+
```sh
|
|
123
|
+
npm run rust:build:android
|
|
124
|
+
npx react-native run-android
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
For iOS, build the XCFramework, install Pods, then launch the app:
|
|
128
|
+
|
|
129
|
+
```sh
|
|
130
|
+
npm run rust:build:ios
|
|
131
|
+
cd ios && pod install && cd ..
|
|
132
|
+
npx react-native run-ios
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
The generated module is app-local and can be used from the app's JavaScript imports. The root `example/` project in this repository exercises this workflow.
|
|
136
|
+
|
|
92
137
|
## Build and run
|
|
93
138
|
|
|
94
139
|
Run these commands from the library root. Generate TurboModule Codegen output with `yarn prepare` before building the host app.
|
|
@@ -150,6 +195,30 @@ Rust outputs are written under `rust/build/` and included in the generated libra
|
|
|
150
195
|
|
|
151
196
|
The example screen in `example/src/App.tsx` exercises the supported scalar, JSON, Promise, and callback signatures.
|
|
152
197
|
|
|
198
|
+
### Web
|
|
199
|
+
|
|
200
|
+
Install `wasm-pack` and the `wasm32-unknown-unknown` target once:
|
|
201
|
+
|
|
202
|
+
```sh
|
|
203
|
+
cargo install wasm-pack
|
|
204
|
+
rustup target add wasm32-unknown-unknown
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
Build the WebAssembly package:
|
|
208
|
+
|
|
209
|
+
```sh
|
|
210
|
+
yarn rust:build:web
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
This compiles `rust/` to `rust/build/web/pkg/` with `wasm-pack build --target web`, reusing the same `rust/src/api/<method>.rs` handlers as native — no separate implementation is needed. It replaces the generated `src/rust-generated.tsx` module (used by web bundlers that don't understand Metro's `.native.` file convention, such as Vite or webpack) with a real, WASM-backed implementation instead of the "not supported on native platforms" stub used before this module exists. Call and await its exported `initRustWeb()` once before using any generated function on web, since loading a `.wasm` file is asynchronous:
|
|
214
|
+
|
|
215
|
+
```ts
|
|
216
|
+
import { initRustWeb, multiply } from 'react-native-awesome-library';
|
|
217
|
+
|
|
218
|
+
await initRustWeb();
|
|
219
|
+
multiply(3, 7); // 21
|
|
220
|
+
```
|
|
221
|
+
|
|
153
222
|
## Supported types
|
|
154
223
|
|
|
155
224
|
The generator supports these TypeScript-to-Rust/C++ mappings:
|
|
@@ -169,6 +238,8 @@ Arrays and `UnsafeObject` values cross the native boundary as JSON, so their con
|
|
|
169
238
|
|
|
170
239
|
Typed object structs, optional or rest parameters, destructured parameters, generic methods, and overloads are not supported. Unsupported signatures fail before generated files are changed.
|
|
171
240
|
|
|
241
|
+
The same mappings apply on `react-native-web`: values cross as JSON strings via `wasm-bindgen` instead of the JSI C++ bridge, and callback parameters are passed as a JS function. See [Web](#web) for the build step and the async `initRustWeb()` call it requires.
|
|
242
|
+
|
|
172
243
|
## Publish
|
|
173
244
|
|
|
174
245
|
Before publishing a generated React Native library, generate its TypeScript/native outputs and build the Rust artifacts for the platforms you intend to ship:
|
|
@@ -177,6 +248,7 @@ Before publishing a generated React Native library, generate its TypeScript/nati
|
|
|
177
248
|
yarn prepare
|
|
178
249
|
yarn rust:build:ios
|
|
179
250
|
yarn rust:build:android
|
|
251
|
+
yarn rust:build:web
|
|
180
252
|
npm pack --dry-run
|
|
181
253
|
```
|
|
182
254
|
|
|
@@ -196,6 +268,8 @@ Pushing a version tag such as `v1.0.2` runs [`.github/workflows/publish.yml`](.g
|
|
|
196
268
|
- Android CMake cannot find `android/generated/jni`: run `yarn prepare` from the library root.
|
|
197
269
|
- Android CMake cannot find a Rust `.a` archive: run `yarn rust:build:android` before launching the example.
|
|
198
270
|
- iOS reports a missing Rust XCFramework: run `yarn rust:build:ios`, then `pod install` in `example/ios`.
|
|
271
|
+
- `wasm-pack: command not found`: install it with `cargo install wasm-pack`, or run `react-native-rust doctor web` to check both prerequisites.
|
|
272
|
+
- The web app throws "Call and await initRustWeb()...": await `initRustWeb()` once before calling any other generated function; loading the `.wasm` file is asynchronous even though the generated calls are not.
|
|
199
273
|
- A React Native type is reported as unsupported: check the mappings and signature restrictions in [Supported types](#supported-types).
|
|
200
274
|
|
|
201
275
|
## Contributing
|
package/dist/app.js
ADDED
|
@@ -0,0 +1,271 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
+
var app_exports = {};
|
|
30
|
+
__export(app_exports, {
|
|
31
|
+
appModuleRoot: () => appModuleRoot,
|
|
32
|
+
inDirectory: () => inDirectory,
|
|
33
|
+
initApp: () => initApp,
|
|
34
|
+
runCodegen: () => runCodegen
|
|
35
|
+
});
|
|
36
|
+
module.exports = __toCommonJS(app_exports);
|
|
37
|
+
var import_node_fs = __toESM(require("node:fs"));
|
|
38
|
+
var import_node_path = __toESM(require("node:path"));
|
|
39
|
+
var import_node_child_process = require("node:child_process");
|
|
40
|
+
var import_react_native_rust_lib = require("./react-native-rust-lib");
|
|
41
|
+
const moduleDirectory = import_node_path.default.join("native", "rust-module");
|
|
42
|
+
const moduleName = "RustApp";
|
|
43
|
+
const packageName = "rust-app-native-module";
|
|
44
|
+
function writeFiles(root, files) {
|
|
45
|
+
for (const [relativePath, contents] of Object.entries(files)) {
|
|
46
|
+
const outputPath = import_node_path.default.join(root, relativePath);
|
|
47
|
+
import_node_fs.default.mkdirSync(import_node_path.default.dirname(outputPath), { recursive: true });
|
|
48
|
+
import_node_fs.default.writeFileSync(outputPath, contents);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
function scaffoldFiles(appName) {
|
|
52
|
+
const javaPackageName = appName.replace(/([a-z0-9])([A-Z])/g, "$1.$2").replace(/[^a-zA-Z0-9]+/g, ".").replace(/^\.+|\.+$/g, "").toLowerCase() || "com.rustapp";
|
|
53
|
+
return {
|
|
54
|
+
"package.json": `${JSON.stringify({
|
|
55
|
+
name: packageName,
|
|
56
|
+
version: "0.0.1",
|
|
57
|
+
description: "App-local Rust TurboModule",
|
|
58
|
+
main: "src/index.tsx",
|
|
59
|
+
"react-native": "src/index.tsx",
|
|
60
|
+
types: "src/index.tsx",
|
|
61
|
+
files: ["src/", "cpp/", "android/", "ios/", "*.podspec", "react-native.config.js", "rust/"],
|
|
62
|
+
peerDependencies: { react: "*", "react-native": ">=0.76" },
|
|
63
|
+
codegenConfig: {
|
|
64
|
+
name: `${moduleName}Spec`,
|
|
65
|
+
type: "modules",
|
|
66
|
+
jsSrcsDir: "src",
|
|
67
|
+
outputDir: { ios: "ios/generated", android: "android/generated" },
|
|
68
|
+
android: { javaPackageName },
|
|
69
|
+
includesGeneratedCode: true
|
|
70
|
+
}
|
|
71
|
+
}, null, 2)}
|
|
72
|
+
`,
|
|
73
|
+
"react-native.config.js": `module.exports = {
|
|
74
|
+
dependency: {
|
|
75
|
+
platforms: {
|
|
76
|
+
android: {
|
|
77
|
+
cmakeListsPath: 'generated/jni/CMakeLists.txt',
|
|
78
|
+
cxxModuleCMakeListsModuleName: '${packageName}',
|
|
79
|
+
cxxModuleCMakeListsPath: 'CMakeLists.txt',
|
|
80
|
+
cxxModuleHeaderName: '${moduleName}Impl',
|
|
81
|
+
},
|
|
82
|
+
},
|
|
83
|
+
},
|
|
84
|
+
};
|
|
85
|
+
`,
|
|
86
|
+
[`${moduleName}.podspec`]: `Pod::Spec.new do |s|
|
|
87
|
+
s.name = "${moduleName}"
|
|
88
|
+
s.version = "0.0.1"
|
|
89
|
+
s.summary = "App-local Rust TurboModule"
|
|
90
|
+
s.homepage = "https://example.invalid"
|
|
91
|
+
s.license = "MIT"
|
|
92
|
+
s.author = "Local app"
|
|
93
|
+
s.source = { :git => "https://example.invalid" }
|
|
94
|
+
s.platforms = { :ios => min_ios_version_supported }
|
|
95
|
+
s.source_files = "cpp/**/*.{hpp,cpp,c,h}", "ios/**/*.{h,m,mm}", "ios/generated/*.{h,cpp,mm}"
|
|
96
|
+
s.vendored_frameworks = "rust/build/ios/${moduleName}Rust.xcframework"
|
|
97
|
+
install_modules_dependencies(s)
|
|
98
|
+
end
|
|
99
|
+
`,
|
|
100
|
+
".gitignore": "node_modules/\nrust/target/\nrust/build/\n",
|
|
101
|
+
"src/NativeRustApp.ts": `import { TurboModuleRegistry, type TurboModule } from 'react-native';
|
|
102
|
+
|
|
103
|
+
export interface Spec extends TurboModule {
|
|
104
|
+
multiply(a: number, b: number): number;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
export default TurboModuleRegistry.getEnforcing<Spec>('${moduleName}');
|
|
108
|
+
`,
|
|
109
|
+
"src/index.tsx": "export * from './rust-generated';\n",
|
|
110
|
+
"cpp/RustAppImpl.h": `#pragma once
|
|
111
|
+
|
|
112
|
+
#include <${moduleName}SpecJSI.h>
|
|
113
|
+
|
|
114
|
+
#include <memory>
|
|
115
|
+
|
|
116
|
+
namespace facebook::react {
|
|
117
|
+
|
|
118
|
+
class ${moduleName}Impl : public Native${moduleName}CxxSpec<${moduleName}Impl> {
|
|
119
|
+
public:
|
|
120
|
+
${moduleName}Impl(std::shared_ptr<CallInvoker> jsInvoker);
|
|
121
|
+
double multiply(jsi::Runtime& rt, double a, double b);
|
|
122
|
+
};
|
|
123
|
+
|
|
124
|
+
}
|
|
125
|
+
`,
|
|
126
|
+
"cpp/RustAppImpl.cpp": `#include "RustAppImpl.h"
|
|
127
|
+
|
|
128
|
+
namespace facebook::react {
|
|
129
|
+
|
|
130
|
+
${moduleName}Impl::${moduleName}Impl(std::shared_ptr<CallInvoker> jsInvoker)
|
|
131
|
+
: Native${moduleName}CxxSpec(std::move(jsInvoker)) {}
|
|
132
|
+
|
|
133
|
+
double ${moduleName}Impl::multiply(jsi::Runtime&, double a, double b) {
|
|
134
|
+
return a * b;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
}
|
|
138
|
+
`,
|
|
139
|
+
"android/CMakeLists.txt": `cmake_minimum_required(VERSION 3.13)
|
|
140
|
+
set(CMAKE_VERBOSE_MAKEFILE ON)
|
|
141
|
+
|
|
142
|
+
add_library(
|
|
143
|
+
${packageName}
|
|
144
|
+
STATIC
|
|
145
|
+
../cpp/${moduleName}Impl.cpp
|
|
146
|
+
)
|
|
147
|
+
|
|
148
|
+
set_target_properties(
|
|
149
|
+
${packageName} PROPERTIES
|
|
150
|
+
CXX_STANDARD 20
|
|
151
|
+
CXX_STANDARD_REQUIRED ON
|
|
152
|
+
CXX_EXTENSIONS OFF
|
|
153
|
+
)
|
|
154
|
+
|
|
155
|
+
target_include_directories(${packageName} PUBLIC ../cpp)
|
|
156
|
+
|
|
157
|
+
target_link_libraries(
|
|
158
|
+
${packageName}
|
|
159
|
+
jsi
|
|
160
|
+
reactnative
|
|
161
|
+
react_codegen_${moduleName}Spec
|
|
162
|
+
)
|
|
163
|
+
`,
|
|
164
|
+
"ios/OnLoad.mm": `#import <Foundation/Foundation.h>
|
|
165
|
+
#import "${moduleName}Impl.h"
|
|
166
|
+
#import <ReactCommon/CxxTurboModuleUtils.h>
|
|
167
|
+
|
|
168
|
+
@interface ${moduleName}OnLoad : NSObject
|
|
169
|
+
@end
|
|
170
|
+
|
|
171
|
+
@implementation ${moduleName}OnLoad
|
|
172
|
+
|
|
173
|
+
using namespace facebook::react;
|
|
174
|
+
|
|
175
|
+
+ (void)load
|
|
176
|
+
{
|
|
177
|
+
registerCxxModuleToGlobalModuleMap(
|
|
178
|
+
std::string(${moduleName}Impl::kModuleName),
|
|
179
|
+
[](std::shared_ptr<CallInvoker> jsInvoker) {
|
|
180
|
+
return std::make_shared<${moduleName}Impl>(jsInvoker);
|
|
181
|
+
}
|
|
182
|
+
);
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
@end
|
|
186
|
+
`
|
|
187
|
+
};
|
|
188
|
+
}
|
|
189
|
+
function appModuleRoot(appRoot = process.cwd()) {
|
|
190
|
+
const moduleRoot = import_node_path.default.join(appRoot, moduleDirectory);
|
|
191
|
+
return import_node_fs.default.existsSync(import_node_path.default.join(moduleRoot, "rust", "Cargo.toml")) ? moduleRoot : null;
|
|
192
|
+
}
|
|
193
|
+
function inDirectory(directory, callback) {
|
|
194
|
+
const previousDirectory = process.cwd();
|
|
195
|
+
process.chdir(directory);
|
|
196
|
+
try {
|
|
197
|
+
return callback();
|
|
198
|
+
} finally {
|
|
199
|
+
process.chdir(previousDirectory);
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
function runCodegen(appRoot, moduleRoot) {
|
|
203
|
+
const script = import_node_path.default.join(appRoot, "node_modules", "react-native", "scripts", "generate-codegen-artifacts.js");
|
|
204
|
+
if (!import_node_fs.default.existsSync(script)) {
|
|
205
|
+
throw new Error("React Native dependencies are missing. Install the app dependencies, then run `react-native-rust generate`.");
|
|
206
|
+
}
|
|
207
|
+
const result = (0, import_node_child_process.spawnSync)(process.execPath, [script, "-p", moduleRoot, "-t", "all", "-s", "library"], {
|
|
208
|
+
cwd: appRoot,
|
|
209
|
+
encoding: "utf8",
|
|
210
|
+
stdio: "pipe"
|
|
211
|
+
});
|
|
212
|
+
if (result.error || result.status !== 0) {
|
|
213
|
+
throw new Error(`React Native Codegen failed: ${(result.stderr || result.stdout || result.error?.message || "").trim()}`);
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
function initApp() {
|
|
217
|
+
const appRoot = process.cwd();
|
|
218
|
+
const appManifestPath = import_node_path.default.join(appRoot, "package.json");
|
|
219
|
+
if (!import_node_fs.default.existsSync(appManifestPath)) throw new Error("Run `react-native-rust init --app` from a React Native app root.");
|
|
220
|
+
const appManifest = (0, import_react_native_rust_lib.readJson)(appManifestPath);
|
|
221
|
+
if (!(appManifest.dependencies || {})["react-native"]) throw new Error("This project does not declare react-native as a dependency.");
|
|
222
|
+
if (!import_node_fs.default.existsSync(import_node_path.default.join(appRoot, "android")) || !import_node_fs.default.existsSync(import_node_path.default.join(appRoot, "ios"))) {
|
|
223
|
+
throw new Error("App-local Rust currently requires both Android and iOS native project folders.");
|
|
224
|
+
}
|
|
225
|
+
const moduleRoot = import_node_path.default.join(appRoot, moduleDirectory);
|
|
226
|
+
if (import_node_fs.default.existsSync(moduleRoot)) throw new Error(`${moduleDirectory} already exists; no files were changed.`);
|
|
227
|
+
import_node_fs.default.mkdirSync(moduleRoot, { recursive: true });
|
|
228
|
+
try {
|
|
229
|
+
writeFiles(moduleRoot, scaffoldFiles(appManifest.name || "rust-app"));
|
|
230
|
+
inDirectory(moduleRoot, import_react_native_rust_lib.init);
|
|
231
|
+
const cliManifest = (0, import_react_native_rust_lib.readJson)(import_node_path.default.join(__dirname, "..", "package.json"));
|
|
232
|
+
const cliRoot = import_node_path.default.resolve(__dirname, "..");
|
|
233
|
+
const cliIsInstalled = cliRoot.split(import_node_path.default.sep).includes("node_modules");
|
|
234
|
+
const cliDependency = cliIsInstalled ? `^${cliManifest.version}` : `file:${import_node_path.default.relative(appRoot, cliRoot).split(import_node_path.default.sep).join("/") || "."}`;
|
|
235
|
+
const moduleManifestPath = import_node_path.default.join(moduleRoot, "package.json");
|
|
236
|
+
const moduleManifest = (0, import_react_native_rust_lib.readJson)(moduleManifestPath);
|
|
237
|
+
delete moduleManifest.devDependencies?.[cliManifest.name];
|
|
238
|
+
import_node_fs.default.writeFileSync(moduleManifestPath, `${JSON.stringify(moduleManifest, null, 2)}
|
|
239
|
+
`);
|
|
240
|
+
appManifest.dependencies = {
|
|
241
|
+
...appManifest.dependencies,
|
|
242
|
+
[packageName]: `file:./${moduleDirectory.split(import_node_path.default.sep).join("/")}`
|
|
243
|
+
};
|
|
244
|
+
appManifest.devDependencies = {
|
|
245
|
+
...appManifest.devDependencies,
|
|
246
|
+
[cliManifest.name]: appManifest.devDependencies?.[cliManifest.name] || cliDependency
|
|
247
|
+
};
|
|
248
|
+
appManifest.scripts = {
|
|
249
|
+
...appManifest.scripts,
|
|
250
|
+
"rust:generate": "react-native-rust generate",
|
|
251
|
+
"rust:build:ios": "react-native-rust build ios",
|
|
252
|
+
"rust:build:android": "react-native-rust build android",
|
|
253
|
+
"rust:test": `cargo test --manifest-path ${moduleDirectory.split(import_node_path.default.sep).join("/")}/rust/Cargo.toml`
|
|
254
|
+
};
|
|
255
|
+
runCodegen(appRoot, moduleRoot);
|
|
256
|
+
import_node_fs.default.writeFileSync(appManifestPath, `${JSON.stringify(appManifest, null, 2)}
|
|
257
|
+
`);
|
|
258
|
+
} catch (error) {
|
|
259
|
+
import_node_fs.default.rmSync(moduleRoot, { recursive: true, force: true });
|
|
260
|
+
throw error;
|
|
261
|
+
}
|
|
262
|
+
console.log(`Created app-local Rust TurboModule in ${import_node_path.default.relative(appRoot, moduleRoot)}.`);
|
|
263
|
+
console.log("Install app dependencies, then run `npm run rust:build:android` or `npm run rust:build:ios`.");
|
|
264
|
+
}
|
|
265
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
266
|
+
0 && (module.exports = {
|
|
267
|
+
appModuleRoot,
|
|
268
|
+
inDirectory,
|
|
269
|
+
initApp,
|
|
270
|
+
runCodegen
|
|
271
|
+
});
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
+
var constants_exports = {};
|
|
30
|
+
__export(constants_exports, {
|
|
31
|
+
HEADER_END: () => HEADER_END,
|
|
32
|
+
HEADER_START: () => HEADER_START,
|
|
33
|
+
SOURCE_END: () => SOURCE_END,
|
|
34
|
+
SOURCE_START: () => SOURCE_START,
|
|
35
|
+
cppKeywords: () => cppKeywords,
|
|
36
|
+
rustKeywords: () => rustKeywords,
|
|
37
|
+
supportedTypes: () => supportedTypes,
|
|
38
|
+
ts: () => import_typescript.default
|
|
39
|
+
});
|
|
40
|
+
module.exports = __toCommonJS(constants_exports);
|
|
41
|
+
var import_typescript = __toESM(require("typescript"));
|
|
42
|
+
const HEADER_START = "// react-native-rust:generated-methods:start";
|
|
43
|
+
const HEADER_END = "// react-native-rust:generated-methods:end";
|
|
44
|
+
const SOURCE_START = "// react-native-rust:generated-methods:start";
|
|
45
|
+
const SOURCE_END = "// react-native-rust:generated-methods:end";
|
|
46
|
+
const rustKeywords = /* @__PURE__ */ new Set([
|
|
47
|
+
"as",
|
|
48
|
+
"async",
|
|
49
|
+
"await",
|
|
50
|
+
"break",
|
|
51
|
+
"const",
|
|
52
|
+
"continue",
|
|
53
|
+
"crate",
|
|
54
|
+
"dyn",
|
|
55
|
+
"else",
|
|
56
|
+
"enum",
|
|
57
|
+
"extern",
|
|
58
|
+
"false",
|
|
59
|
+
"fn",
|
|
60
|
+
"for",
|
|
61
|
+
"if",
|
|
62
|
+
"impl",
|
|
63
|
+
"in",
|
|
64
|
+
"let",
|
|
65
|
+
"loop",
|
|
66
|
+
"match",
|
|
67
|
+
"mod",
|
|
68
|
+
"move",
|
|
69
|
+
"mut",
|
|
70
|
+
"pub",
|
|
71
|
+
"ref",
|
|
72
|
+
"return",
|
|
73
|
+
"self",
|
|
74
|
+
"Self",
|
|
75
|
+
"static",
|
|
76
|
+
"struct",
|
|
77
|
+
"super",
|
|
78
|
+
"trait",
|
|
79
|
+
"true",
|
|
80
|
+
"type",
|
|
81
|
+
"unsafe",
|
|
82
|
+
"use",
|
|
83
|
+
"where",
|
|
84
|
+
"while"
|
|
85
|
+
]);
|
|
86
|
+
const cppKeywords = /* @__PURE__ */ new Set([
|
|
87
|
+
"alignas",
|
|
88
|
+
"alignof",
|
|
89
|
+
"and",
|
|
90
|
+
"asm",
|
|
91
|
+
"auto",
|
|
92
|
+
"bool",
|
|
93
|
+
"break",
|
|
94
|
+
"case",
|
|
95
|
+
"catch",
|
|
96
|
+
"char",
|
|
97
|
+
"class",
|
|
98
|
+
"const",
|
|
99
|
+
"continue",
|
|
100
|
+
"default",
|
|
101
|
+
"delete",
|
|
102
|
+
"do",
|
|
103
|
+
"double",
|
|
104
|
+
"else",
|
|
105
|
+
"enum",
|
|
106
|
+
"explicit",
|
|
107
|
+
"export",
|
|
108
|
+
"extern",
|
|
109
|
+
"false",
|
|
110
|
+
"float",
|
|
111
|
+
"for",
|
|
112
|
+
"friend",
|
|
113
|
+
"goto",
|
|
114
|
+
"if",
|
|
115
|
+
"inline",
|
|
116
|
+
"int",
|
|
117
|
+
"long",
|
|
118
|
+
"namespace",
|
|
119
|
+
"new",
|
|
120
|
+
"noexcept",
|
|
121
|
+
"not",
|
|
122
|
+
"nullptr",
|
|
123
|
+
"operator",
|
|
124
|
+
"or",
|
|
125
|
+
"private",
|
|
126
|
+
"protected",
|
|
127
|
+
"public",
|
|
128
|
+
"register",
|
|
129
|
+
"return",
|
|
130
|
+
"short",
|
|
131
|
+
"signed",
|
|
132
|
+
"sizeof",
|
|
133
|
+
"static",
|
|
134
|
+
"struct",
|
|
135
|
+
"switch",
|
|
136
|
+
"template",
|
|
137
|
+
"this",
|
|
138
|
+
"throw",
|
|
139
|
+
"true",
|
|
140
|
+
"try",
|
|
141
|
+
"typedef",
|
|
142
|
+
"typename",
|
|
143
|
+
"union",
|
|
144
|
+
"unsigned",
|
|
145
|
+
"using",
|
|
146
|
+
"virtual",
|
|
147
|
+
"void",
|
|
148
|
+
"volatile",
|
|
149
|
+
"while",
|
|
150
|
+
"xor"
|
|
151
|
+
]);
|
|
152
|
+
const supportedTypes = /* @__PURE__ */ new Map([
|
|
153
|
+
[import_typescript.default.SyntaxKind.NumberKeyword, { kind: "number", typescript: "number", rust: "f64", cpp: "double", defaultValue: "0.0" }],
|
|
154
|
+
[import_typescript.default.SyntaxKind.BooleanKeyword, { kind: "boolean", typescript: "boolean", rust: "bool", cpp: "bool", defaultValue: "false" }],
|
|
155
|
+
[import_typescript.default.SyntaxKind.StringKeyword, { kind: "json", typescript: "string", rust: "String", cpp: "jsi::String", defaultValue: "String::new()" }],
|
|
156
|
+
[import_typescript.default.SyntaxKind.VoidKeyword, { kind: "void", typescript: "void", rust: "()", cpp: "void", defaultValue: null }]
|
|
157
|
+
]);
|
|
158
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
159
|
+
0 && (module.exports = {
|
|
160
|
+
HEADER_END,
|
|
161
|
+
HEADER_START,
|
|
162
|
+
SOURCE_END,
|
|
163
|
+
SOURCE_START,
|
|
164
|
+
cppKeywords,
|
|
165
|
+
rustKeywords,
|
|
166
|
+
supportedTypes,
|
|
167
|
+
ts
|
|
168
|
+
});
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
var codegen_exports = {};
|
|
20
|
+
__export(codegen_exports, {
|
|
21
|
+
parseSpec: () => import_spec.parseSpec,
|
|
22
|
+
renderProjectBindings: () => import_project.renderProjectBindings,
|
|
23
|
+
renderRustFfiModule: () => import_renderers.renderRustFfiModule
|
|
24
|
+
});
|
|
25
|
+
module.exports = __toCommonJS(codegen_exports);
|
|
26
|
+
var import_spec = require("./spec");
|
|
27
|
+
var import_renderers = require("./renderers");
|
|
28
|
+
var import_project = require("./project");
|
|
29
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
30
|
+
0 && (module.exports = {
|
|
31
|
+
parseSpec,
|
|
32
|
+
renderProjectBindings,
|
|
33
|
+
renderRustFfiModule
|
|
34
|
+
});
|