### Install iOS Dependencies Source: https://github.com/mrousavy/nitro/blob/main/docs/docs/resources/contributing.md If you are working on the iOS version of the example app, navigate to the example directory, install Ruby dependencies using Bundler, and then install the CocoaPods using Bun. ```sh cd example bundle install bun pods ``` -------------------------------- ### Install Dependencies and Build Nitro Source: https://github.com/mrousavy/nitro/blob/main/docs/docs/resources/contributing.md Use Bun to install all project dependencies and build the Nitro project. This is a prerequisite for running the example app. ```sh bun install bun run build ``` -------------------------------- ### Navigate to Docs and Install Dependencies Source: https://github.com/mrousavy/nitro/blob/main/docs/docs/resources/contributing.md Change directory to the 'docs/' folder and install all project dependencies using Bun. ```sh cd docs bun install ``` -------------------------------- ### Install Dependencies Source: https://github.com/mrousavy/nitro/blob/main/docs/README.md Run this command to install all required project dependencies. ```bash $ yarn ``` -------------------------------- ### Installing Nitro Modules without a Dispatcher Source: https://github.com/mrousavy/nitro/blob/main/docs/docs/guides/entry-point.md Shows the installation process for environments where a Dispatcher is not required. Note that asynchronous methods and promises will throw errors if a Dispatcher is not provided. ```cpp #include #include jsi::Runtime& runtime = ... margelo::nitro::install(runtime); ``` -------------------------------- ### Synchronous MMKV Get Example (TypeScript) Source: https://github.com/mrousavy/nitro/blob/main/docs/docs/guides/sync-vs-async.md Demonstrates how to synchronously retrieve a string value from MMKV storage. This is suitable for small, quick operations where immediate return is desired and blocking the JS thread is acceptable. It shows a direct call to `mmkv.getString()`. ```typescript function App() { const mmkv = new MMKV() const name = mmkv.getString('username') // --> Marc } ``` -------------------------------- ### Start Local Development Server Source: https://github.com/mrousavy/nitro/blob/main/docs/README.md Launches a local development server with live reloading enabled. ```bash $ yarn start ``` -------------------------------- ### Manually Registering Nitro Modules with Dispatcher Source: https://github.com/mrousavy/nitro/blob/main/docs/docs/guides/entry-point.md Demonstrates how to manually install Nitro in a custom JSI environment by providing a jsi::Runtime and a Dispatcher. The Dispatcher is required to handle asynchronous calls and callbacks safely. ```cpp #include #include #include jsi::Runtime& runtime = ... std::shared_ptr dispatcher = ... margelo::nitro::install(runtime, dispatcher); ``` -------------------------------- ### Asynchronous MMKV Get Example (TypeScript) Source: https://github.com/mrousavy/nitro/blob/main/docs/docs/guides/sync-vs-async.md Illustrates the asynchronous retrieval of a string value from MMKV storage using `async/await`. This pattern is necessary when the operation might take longer and blocking the JS thread is undesirable. It shows fetching the value within a `useEffect` hook and updating state. ```typescript function App() { const mmkv = new MMKV() const [name, setName] = useState(undefined) useEffect(() => { (async () => { const n = await mmkv.getString('username') // --> Marc setName(n) })() }, []) } ``` -------------------------------- ### Run Nitro Docs Development Server Source: https://github.com/mrousavy/nitro/blob/main/docs/docs/resources/contributing.md Start the Docusaurus development server for the Nitro documentation site. ```sh bun start ``` -------------------------------- ### Verify Local Changes Source: https://github.com/mrousavy/nitro/blob/main/CONTRIBUTING.md Run these commands to ensure all packages build, type checking passes, linting is clean, and the example app functions correctly. ```sh bun run build ``` ```sh bun typecheck ``` ```sh bun lint-all ``` -------------------------------- ### Install react-native-nitro-modules Source: https://github.com/mrousavy/nitro/blob/main/README.md Installs the react-native-nitro-modules package using npm and runs pod install for iOS dependencies. Ensure you are in your project's root directory. ```sh npm i react-native-nitro-modules cd ios && pod install ``` -------------------------------- ### Implement Lifecycle Methods in Swift Source: https://github.com/mrousavy/nitro/blob/main/docs/docs/guides/view-components.md Example of implementing beforeUpdate() and afterUpdate() lifecycle methods for a HybridCameraView in Swift. These methods can be used for batching prop changes. ```swift class HybridCameraView: HybridCameraViewSpec { // View var view: UIView = UIView() func beforeUpdate() { } func afterUpdate() { } } ``` -------------------------------- ### Implement Lifecycle Methods in Kotlin Source: https://github.com/mrousavy/nitro/blob/main/docs/docs/guides/view-components.md Example of implementing beforeUpdate() and afterUpdate() lifecycle methods for a HybridCameraView in Kotlin. These methods can be used for batching prop changes. ```kotlin class HybridCameraView(context: ThemedReactContext): HybridCameraViewSpec() { // View override val view: View = View(context) override fun beforeUpdate() { } override fun afterUpdate() { } } ``` -------------------------------- ### Use Custom ImageView Component Source: https://github.com/mrousavy/nitro/blob/main/docs/docs/guides/view-components.md Example of how to use the custom ImageView component in an App, loading an image and passing it as a prop. ```jsx function App() { const image = await loadImage('https://...') return } ``` -------------------------------- ### Install Nitro and Nitrogen Dependencies Source: https://github.com/mrousavy/nitro/blob/main/docs/docs/getting-started/how-to-build-a-nitro-module.md Installs react-native-nitro-modules and nitrogen as development dependencies in an existing React Native library. ```sh npm install react-native-nitro-modules --save-dev npm install nitrogen --save-dev ``` -------------------------------- ### Run Nitrogen CLI for Spec Generation Source: https://github.com/mrousavy/nitro/blob/main/docs/docs/getting-started/how-to-build-a-nitro-module.md Executes the Nitrogen CLI to generate autolinking setup files after a `nitro.json` configuration file has been created. ```sh npx nitrogen ``` -------------------------------- ### Install Nitrogen with bun Source: https://github.com/mrousavy/nitro/blob/main/docs/docs/concepts/nitrogen.md Installs Nitrogen as a development dependency using bun. This command should be run in the root directory of a Nitro Module. ```sh bun i nitrogen -d ``` -------------------------------- ### Calling a Method on a HybridView Component Source: https://github.com/mrousavy/nitro/blob/main/docs/docs/guides/view-components.md Demonstrates how to get a reference to a HybridView component's HybridObject using `hybridRef` and then call its methods, such as `takePhoto`. ```jsx function App() { return ( { const image = ref.takePhoto() })} /> ) } ``` -------------------------------- ### Nitrogen Generation Output Example Source: https://github.com/mrousavy/nitro/blob/main/docs/docs/concepts/nitrogen.md Example output from the Nitrogen CLI after successfully generating native specs. It indicates the files processed, specs generated, and the location of the generated files. ```sh 🔧 Loading nitro.json config... 🚀 Nitrogen runs at ~/Projects/nitro/example/dummy 🔍 Nitrogen found 1 spec in ~/Projects/nitro/example/dummy ⏳ Parsing Math.nitro.ts... ⚙️ Generating specs for HybridObject "Math"... shared: Generating C++ code... ⛓️ Setting up build configs for autolinking... 🎉 Generated 1/1 HybridObject in 0.6s! 💡 Your code is in ./nitrogen/generated ‼️ Added 8 files - you need to run `pod install`/sync gradle to update files! ``` -------------------------------- ### Install Nitrogen with pnpm Source: https://github.com/mrousavy/nitro/blob/main/docs/docs/concepts/nitrogen.md Installs Nitrogen as a development dependency using pnpm. This command should be run in the root directory of a Nitro Module. ```sh pnpm add nitrogen -D ``` -------------------------------- ### Get Host Component for Camera View Source: https://github.com/mrousavy/nitro/blob/main/docs/docs/guides/view-components.md In JavaScript, use `getHostComponent` to get a reference to your Nitro View, providing its name and configuration. This allows you to use the view in your React Native components. ```typescript import { getHostComponent } from 'react-native-nitro-modules' import CameraViewConfig from '../nitrogen/generated/shared/json/CameraViewConfig.json' export const Camera = getHostComponent( 'Camera', () => CameraViewConfig ) ``` -------------------------------- ### Implement Hybrid Object (C++) Source: https://github.com/mrousavy/nitro/blob/main/README.md Provides a C++ implementation for a hybrid object, fulfilling the interface defined in TypeScript. This example shows the 'add' method implementation. ```cpp class HybridMath: public HybridMathSpec { public: HybridMath(): HybridObject(TAG) {} double add(double a, double b) override { return a + b; } } ``` -------------------------------- ### Implement and Install a Custom Dispatcher Source: https://github.com/mrousavy/nitro/blob/main/docs/docs/guides/worklets.md Defines a custom Dispatcher class in C++ to handle asynchronous callbacks for custom JSI runtimes and registers it globally with the Nitro runtime. ```cpp #include using namespace margelo::nitro; class MyRuntimeDispatcher: public Dispatcher { public: void runSync(std::function&& function) override; void runAsync(std::function&& function) override; }; ``` ```cpp auto myDispatcher = std::make_shared(); Dispatcher::installRuntimeGlobalDispatcher(myRuntime, myDispatcher); ``` -------------------------------- ### Get Renderable Hybrid View (TypeScript) Source: https://github.com/mrousavy/nitro/blob/main/docs/docs/concepts/hybrid-views.md Demonstrates how to obtain a renderable version of a Hybrid View using the getHostComponent function in TypeScript. This function takes the component name and a configuration loader. ```typescript export const Camera = getHostComponent( 'Camera', () => CameraViewConfig ) ``` -------------------------------- ### Return `null` from Nitro Functions Source: https://github.com/mrousavy/nitro/blob/main/docs/docs/types/nulls.md Illustrates how to return a `null` value from functions in Nitro, utilizing the `NullType` singleton. Examples are provided for Swift, Kotlin, and C++, showing the specific syntax for returning `null`. ```swift func getNull() -> NullType { return .null } ``` ```kotlin fun getNull(): NullType { return NullType.NULL } ``` ```cpp NullType getNull() { return nitro::null; } ``` -------------------------------- ### Expo Module Definition (Swift) Source: https://github.com/mrousavy/nitro/blob/main/docs/docs/resources/comparison.md Illustrates how to define a native module in Swift using Expo Modules' declarative syntax. This example shows the definition of an 'add' function within the module. ```swift public class MathModule: Module { public func definition() -> ModuleDefinition { Name("Math") Function("add") { (a: Double, b: Double) -> Double in return a + b } } } ``` -------------------------------- ### JavaScript Buffer Operations Source: https://github.com/mrousavy/nitro/blob/main/docs/docs/types/array-buffers.md Examples of creating standard JS ArrayBuffers and utilizing Nitro's helper to create owning native buffers directly from JavaScript. ```ts const arrayBuffer = new ArrayBuffer(4096) const view = new Uint8Array(arrayBuffer) view[0] = 64 view[1] = 128 view[2] = 255 // Create an owning native buffer const nativeBuffer = NitroModules.createNativeArrayBuffer(4096) ``` -------------------------------- ### Define TypeScript Types for Turbo Modules Source: https://github.com/mrousavy/nitro/blob/main/docs/docs/resources/comparison.md Examples of unsupported types in Turbo Modules, specifically tuples and callbacks with return values. ```typescript type SomeTuple = [number, number] type SomeCallback = () => number ``` -------------------------------- ### Asynchronous Function Implementation (Kotlin) Source: https://github.com/mrousavy/nitro/blob/main/docs/docs/resources/comparison.md Compares the implementation of an asynchronous function using Kotlin coroutines in Nitro's HybridMath and Expo Modules. Both examples demonstrate a delay before returning a result. ```kotlin class HybridMath: HybridMathSpec { override fun doSomeWork(): Promise { return Promise.async { delay(5000) return@async "done!" } } } ``` ```kotlin class MathModule: Module { override fun definition() = ModuleDefinition { Name("Math") AsyncFunction("doSomeWork") Coroutine { delay(5000) return@Coroutine "done!" } } } ``` -------------------------------- ### Implement Hybrid Objects for Lazy Data Access Source: https://github.com/mrousavy/nitro/blob/main/docs/docs/guides/performance-tips.md Use Hybrid Objects to avoid converting large datasets to JS when only a subset is needed. The 'Good' example demonstrates lazy retrieval via native methods. ```ts interface AllData { rows: DataRow[] } interface BadDatabase extends HybridObject<{ … }> { getAllData(): AllData } const database = // ... const data = database.getAllData() const row = data.rows .find((r) => r.name === "Marc") ``` ```ts interface AllData extends HybridObject<{ … }> { findRowWithName(name: string): DataRow } interface GoodDatabase extends HybridObject<{ … }> { getAllData(): AllData } const database = // ... const data = database.getAllData() const row = data.findRowWithName("Marc") ``` -------------------------------- ### Install Nitro Modules core package Source: https://github.com/mrousavy/nitro/blob/main/docs/docs/resources/for-library-users.md Installs the Nitro Modules core dependency and updates iOS CocoaPods. This is required for any project utilizing libraries built with Nitro. ```npm npm i react-native-nitro-modules cd ios && pod install ``` ```yarn yarn add react-native-nitro-modules cd ios && pod install ``` ```pnpm pnpm add react-native-nitro-modules cd ios && pod install ``` ```bun bun i react-native-nitro-modules cd ios && pod install ``` -------------------------------- ### Run Nitrogen Specs Source: https://github.com/mrousavy/nitro/blob/main/docs/docs/resources/contributing.md Execute Nitrogen specs from the repository root to generate files. Commit these generated files. ```sh bun specs ``` -------------------------------- ### Build Static Content Source: https://github.com/mrousavy/nitro/blob/main/docs/README.md Generates the production-ready static files in the build directory. ```bash $ yarn build ``` -------------------------------- ### Install Nitrogen with yarn Source: https://github.com/mrousavy/nitro/blob/main/docs/docs/concepts/nitrogen.md Installs Nitrogen as a development dependency using yarn. This command should be run in the root directory of a Nitro Module. ```sh yarn add nitrogen -D ``` -------------------------------- ### Manually Implement Hybrid Object in C++ Source: https://github.com/mrousavy/nitro/blob/main/docs/docs/getting-started/how-to-build-a-nitro-module.md Demonstrates how to manually create a Hybrid Object by inheriting from the base class, calling the constructor, and registering methods via loadHybridMethods. ```cpp #pragma once #include namespace margelo::nitro::math { class HybridMath : public HybridObject { public: HybridMath(): HybridObject("Math") { } double add(double a, double b) { return a + b; } void loadHybridMethods() override { HybridObject::loadHybridMethods(); registerHybrids(this, [](Prototype& proto) { // Registration logic here }); } }; } ``` -------------------------------- ### Install Nitrogen with npm Source: https://github.com/mrousavy/nitro/blob/main/docs/docs/concepts/nitrogen.md Installs Nitrogen as a development dependency using npm. This command should be run in the root directory of a Nitro Module. ```sh npm i nitrogen --save-dev ``` -------------------------------- ### Custom Alias Names for Variants in TypeScript Source: https://github.com/mrousavy/nitro/blob/main/docs/docs/types/variants.md Shows the recommended approach for declaring variants using custom type aliases to improve readability in generated code. The 'Bad' example uses a generated, less readable variant name, while the 'Good' example uses a clear type alias. ```typescript interface Math extends HybridObject<{ … }> { calculate(): string | number } ``` ```typescript type MathOutput = string | number interface Math extends HybridObject<{ … }> { calculate(): MathOutput } ``` -------------------------------- ### Deploy to GitHub Pages Source: https://github.com/mrousavy/nitro/blob/main/docs/README.md Commands to deploy the website to the gh-pages branch, supporting both SSH and HTTPS authentication methods. ```bash $ USE_SSH=true yarn deploy ``` ```bash $ GIT_USER= yarn deploy ``` -------------------------------- ### Typed Maps Example: Record Source: https://github.com/mrousavy/nitro/blob/main/docs/docs/types/typed-maps.md Demonstrates how to define and use typed maps (Record) in various programming languages. This example shows a function returning a map of user IDs to ages. Nitro cannot fully optimize these due to unknown keys. ```TypeScript interface Database extends HybridObject<{ … }> { getAllUsers(): Record } ``` ```Swift class HybridDatabase: HybridDatabaseSpec { func getAllUsers() -> Dictionary } ``` ```Kotlin class HybridDatabase: HybridDatabaseSpec() { fun getAllUsers(): Map } ``` ```C++ class HybridDatabase: public HybridDatabaseSpec { std::unordered_map getAllUsers(); } ``` -------------------------------- ### Bootstrap Nitro Module with Nitrogen CLI Source: https://github.com/mrousavy/nitro/blob/main/docs/docs/getting-started/how-to-build-a-nitro-module.md Initializes a new Nitro Module project using the Nitrogen CLI. This command bootstraps a template for creating a new module. ```sh npx nitrogen@latest init ``` -------------------------------- ### Run Nitrogen for Code Generation Source: https://github.com/mrousavy/nitro/blob/main/docs/docs/guides/view-components.md Execute the `nitrogen` command to generate the necessary C++ ShadowNode, native interfaces (iOS/Android), and view configuration files. This command is essential after declaring your view. ```sh npx nitrogen ``` ```sh yarn nitrogen ``` ```sh pnpm nitrogen ``` ```sh bun nitrogen ``` -------------------------------- ### Bootstrap Nitro Module with create-nitro-module CLI Source: https://github.com/mrousavy/nitro/blob/main/docs/docs/getting-started/how-to-build-a-nitro-module.md Initializes a new Nitro Module project using the create-nitro-module CLI. This is a dedicated tool for bootstrapping Nitro modules. ```sh npx create-nitro-module@latest ``` -------------------------------- ### Implement RecyclableView Protocol in Swift Source: https://github.com/mrousavy/nitro/blob/main/docs/docs/guides/view-components.md Shows how to implement the RecyclableView protocol in Swift for a HybridMyView. The prepareForRecycle() method should be implemented to reset internal state. ```swift import NitroModules class HybridMyView: HybridMyViewSpec, RecyclableView { // ... func prepareForRecycle() {} } ``` -------------------------------- ### Implement Generated Native Specs Source: https://github.com/mrousavy/nitro/blob/main/docs/docs/getting-started/how-to-build-a-nitro-module.md Provides the native implementation for the generated Hybrid Object specs in Swift, Kotlin, or C++. ```swift import Foundation import NitroModules class HybridMath : HybridMathSpec { func add(a: Double, b: Double) throws -> Double { return a + b } } ``` ```kotlin package com.margelo.nitro.math import com.margelo.nitro.core.* class HybridMath : HybridMathSpec() { override fun add(a: Double, b: Double): Double { return a + b } } ``` ```cpp // HybridMath.hpp #include "HybridMathSpec.hpp" namespace margelo::nitro::math { class HybridMath: public HybridMathSpec { public: HybridMath(): HybridObject(TAG) {} double add(double a, double b) override; }; } // HybridMath.cpp #include "HybridMath.hpp" namespace margelo::nitro::math { double HybridMath::add(double a, double b) { return a + b; } } ``` -------------------------------- ### Implement RecyclableView Interface in Kotlin Source: https://github.com/mrousavy/nitro/blob/main/docs/docs/guides/view-components.md Shows how to implement the RecyclableView interface in Kotlin for a HybridMyView. The prepareForRecycle() method should be implemented to reset internal state. ```kotlin import com.margelo.nitro.views.RecyclableView class HybridMyView: HybridMyViewSpec(), RecyclableView { // ... override fun prepareForRecycle() {} } ``` -------------------------------- ### Consume Hybrid Objects in TypeScript Source: https://github.com/mrousavy/nitro/blob/main/docs/docs/getting-started/how-to-build-a-nitro-module.md Demonstrates how to import and instantiate a registered Hybrid Object in a TypeScript environment. The object methods are then accessible directly via the created instance. ```typescript import { type HybridObject, NitroModules } from 'react-native-nitro-modules' interface Math extends HybridObject<{ … }> { add(a: number, b: number): number } const math = NitroModules.createHybridObject("Math") const result = math.add(5, 7) // --> 12 ``` -------------------------------- ### Bootstrap Nitro Module with create-react-native-library Source: https://github.com/mrousavy/nitro/blob/main/docs/docs/getting-started/how-to-build-a-nitro-module.md Initializes a new React Native library project using the create-react-native-library CLI. This can be used as a base for a Nitro Module. ```sh npx create-react-native-library@latest ``` -------------------------------- ### Implement Hybrid Image Cropping in Nitro vs Turbo Modules Source: https://github.com/mrousavy/nitro/blob/main/docs/docs/resources/comparison.md Demonstrates the difference between passing native objects directly in Nitro versus the workaround of file-based serialization required by Turbo Modules. ```swift class HybridImageEditor: HybridImageEditorSpec { func crop(image: HybridImage, size: Size) -> HybridImage { let original = image.cgImage let cropped = original.cropping(to: size) return HybridImage(cgImage: cropped) } } ``` ```objective-c @implementation ImageEditor - (NSString*)crop:(NSString*)imageUri size:(CGRect)size { UIImage* image = [UIImage imageWithContentsOfFile:imageUri]; CGImageRef cropped = CGImageCreateWithImageInRect([image CGImage], size); UIImage* croppedImage = [UIImage imageWithCGImage:cropped]; CGImageRelease(cropped); NSString* fileName = [NSString stringWithFormat:@"%@.png", [[NSUUID UUID] UUIDString]]; NSString* filePath = [NSTemporaryDirectory() stringByAppendingPathComponent:fileName]; NSData* pngData = UIImagePNGRepresentation(croppedImage); [pngData writeToFile:tempPath atomically:YES]; return tempPath; } ``` -------------------------------- ### Register Hybrid Objects Source: https://github.com/mrousavy/nitro/blob/main/packages/react-native-nitro-modules/README.md Shows how to register a Hybrid Object constructor in the global registry to make it available for instantiation at app startup. ```cpp #include void load() { HybridObjectRegistry::registerHybridObjectConstructor( "MyHybrid", []() -> std::shared_ptr { return std::make_shared(); } ); } ``` -------------------------------- ### Implement Native Camera View in Swift Source: https://github.com/mrousavy/nitro/blob/main/docs/docs/guides/view-components.md Implement the `HybridCameraViewSpec` in Swift, providing the actual logic for props like `enableFlash` and the `view` accessor. ```swift class HybridCameraView : HybridCameraViewSpec { // Props var enableFlash: Bool = false // View var view: UIView = UIView() } ``` -------------------------------- ### Implement Hybrid Object (Swift) Source: https://github.com/mrousavy/nitro/blob/main/docs/docs/concepts/hybrid-objects.md Provides a Swift implementation for a Hybrid Object, adhering to the defined interface. This example shows how to expose properties and methods to JavaScript. ```swift class HybridMath : HybridMathSpec { var pi: Double { return Double.pi } func add(a: Double, b: Double) -> Double { return a + b } } ``` -------------------------------- ### Reset Image View State for Recycling in Swift Source: https://github.com/mrousavy/nitro/blob/main/docs/docs/guides/view-components.md Example of resetting an ImageView's state by setting its image to nil within the prepareForRecycle() method, ensuring it doesn't display old content when recycled. ```swift class HybridImageView: HybridImageViewSpec, RecyclableView { var view: UIView { imageView } private var imageView = UIImageView() func prepareForRecycle() { // highlight-next-line imageView.image = nil } } ``` -------------------------------- ### Implement Event Listeners Source: https://github.com/mrousavy/nitro/blob/main/docs/docs/types/callbacks.md Shows how to store and trigger multiple callbacks to simulate event-based behavior. This pattern allows native code to maintain a list of listeners and invoke them when specific events occur. ```ts type Orientation = "portrait" | "landscape" interface DeviceInfo extends HybridObject<{ … }> { listenToOrientation(onChanged: (o: Orientation) => void): void } deviceInfo.listenToOrientation((o) => { console.log(`Orientation changed to ${o}!`) }) ``` ```swift func listenToOrientation(onChanged: (Orientation) -> Void) { self.listeners.append(onChanged) } func onRotate() { for listener in self.listeners { listener(newOrientation) } } ``` ```kotlin fun listenToOrientation(onChanged: (Orientation) -> Unit) { this.listeners.add(onChanged) } fun onRotate() { for (listener in this.listeners) { listener(newOrientation) } } ``` ```cpp void listenToOrientation(std::function onChanged) { this->listeners.push_back(onChanged); } void onRotate() { for (const auto& listener: this->listeners) { listener(newOrientation); } } ``` -------------------------------- ### Implement Native Camera View in Kotlin Source: https://github.com/mrousavy/nitro/blob/main/docs/docs/guides/view-components.md Implement the `HybridCameraViewSpec` in Kotlin, providing the actual logic for props like `enableFlash` and the `view` accessor. ```kotlin class HybridCameraView(val context: ThemedReactContext) : HybridCameraViewSpec() { // Props override var enableFlash: Boolean = false // View override val view: View = View(context) } ``` -------------------------------- ### Implementing Async Method with Promise.async (Kotlin) Source: https://github.com/mrousavy/nitro/blob/main/docs/docs/guides/sync-vs-async.md Demonstrates the Kotlin implementation for an asynchronous Nitro method. Similar to Swift, it allows for initial synchronous operations before deferring the main computation to a background thread using `Promise.async`, returning a `Promise`. ```kotlin override fun mineOneBitcoin(): Promise { // 1. synchronous in here, JS Thread is still blocked // useful e.g. for argument checking before starting async Thread return Promise.async { // 2. asynchronous in here, JS Thread is now free return computeBitcoin() } } ``` -------------------------------- ### Nitrogen Configuration File Source: https://github.com/mrousavy/nitro/blob/main/docs/docs/concepts/nitrogen.md Example `nitro.json` configuration file for a Nitro Module. This file specifies settings for code generation, including C++ namespaces and module names for iOS and Android. ```json { "$schema": "https://nitro.margelo.com/nitro.schema.json", "cxxNamespace": ["math"], "ios": { "iosModuleName": "NitroMath" }, "android": { "androidNamespace": ["math"], "androidCxxLibName": "NitroMath" }, "autolinking": {} } ``` -------------------------------- ### Catch Native Errors in JavaScript Source: https://github.com/mrousavy/nitro/blob/main/docs/docs/guides/errors.md Shows how to catch errors propagated from native Nitro methods in JavaScript. This example uses an async/await with a try/catch block to handle potential rejections from asynchronous operations like `math.add`. ```ts const math = // ... try { await math.add(-5, -1) } catch (error) { console.log(error) } ``` -------------------------------- ### Wrap Callbacks with Nitro's callback() Source: https://github.com/mrousavy/nitro/blob/main/docs/docs/guides/view-components.md Demonstrates how to wrap JavaScript callback functions using Nitro's `callback(...)` utility to bypass React Native's conversion limitations when passing functions to Nitro Views. ```tsx export interface CameraProps extends HybridViewProps { onCaptured: (image: Image) => void } export type CameraView = HybridView function App() { // diff-remove return console.log(i)} /> // diff-add return console.log(i))} /> } ``` -------------------------------- ### Enforce Promise Return Types in Swift Source: https://github.com/mrousavy/nitro/blob/main/docs/docs/types/promises.md An example showing how Nitro statically enforces that functions returning a Promise must properly return a Promise object, preventing common errors like returning void. ```swift func saveToFile(image: HybridImage) -> Promise { guard let data = image.data else { return } // code-error ^ // Error: Cannot return void! return Promise.async { try await data.writeToFile("file://tmp/img.png") } } ``` -------------------------------- ### Implement View Recycling Source: https://github.com/mrousavy/nitro/blob/main/docs/docs/guides/performance-tips.md Enable view recycling by implementing the RecyclableView interface and overriding the prepareForRecycle method to reset internal state. ```swift import NitroModules class HybridMyView: HybridMyViewSpec, RecyclableView { // ... func prepareForRecycle() {} } ``` ```kotlin import com.margelo.nitro.views.RecyclableView class HybridMyView: HybridMyViewSpec(), RecyclableView { // ... override fun prepareForRecycle() {} } ``` -------------------------------- ### Create and Use Hybrid Object from JavaScript Source: https://github.com/mrousavy/nitro/blob/main/docs/docs/concepts/hybrid-objects.md Demonstrates how to create and interact with Hybrid Objects from JavaScript using helper functions like `createHybridObject` and `getHybridObjectConstructor`. This allows for dynamic instantiation and type checking. ```javascript const math = NitroModules.createHybridObject("Math") const result = math.add(5, 7) ``` ```javascript const HybridMath = getHybridObjectConstructor("Math") const math = new HybridMath() const isMath = math instanceof HybridMath ``` -------------------------------- ### Bun Tooling Commands Source: https://github.com/mrousavy/nitro/blob/main/CONTRIBUTING.md Common commands for managing the Nitro monorepo using Bun. Ensure Bun is used as the package manager and task runner. ```sh bun install # install all workspaces bun run build # build nitro, nitrogen, and the test modules bun specs # regenerate nitrogen output for react-native-nitro-test bun lint-all # run all linters (JS/TS, C++, Swift, Kotlin) ``` -------------------------------- ### Get All Users - Standard Array Implementations Source: https://github.com/mrousavy/nitro/blob/main/docs/docs/types/arrays.md Demonstrates the implementation of a `getAllUsers` function across different programming languages (TypeScript, Swift, Kotlin, C++) to retrieve an array of User objects. Each language uses its idiomatic array type. ```typescript interface Contacts extends HybridObject<{ … }> { getAllUsers(): User[] } ``` ```swift class HybridContacts: HybridContactsSpec { fun getAllUsers() -> Array } ``` ```kotlin class HybridContacts: HybridContactsSpec() { fun getAllUsers(): Array } ``` ```cpp class HybridContacts : public HybridContactsSpec { std::vector getAllUsers(); } ``` -------------------------------- ### Compare Codegen Implementations Source: https://github.com/mrousavy/nitro/blob/main/docs/docs/resources/comparison.md Compares the syntax for creating modules using Nitro's HybridObject versus Turbo Module's Registry. ```typescript // Nitrogen interface Math extends HybridObject<{ … }> { add(a: number, b: number): Promise } export const Math = NitroModules.createHybridObject('Math') // Codegen export interface Spec extends TurboModule { add(a: number, b: number): Promise; } export const Math = TurboModuleRegistry.get('RTNMath') as Spec | null; ``` -------------------------------- ### JS to C++ Type Conversion Example (TypeScript) Source: https://github.com/mrousavy/nitro/blob/main/docs/docs/types/typing-system.md Demonstrates how a JavaScript 'number' type is statically defined as a 'double' in C++ using Nitro's typing system. This ensures type safety and null safety at compile time. ```typescript interface Math extends HybridObject<{ ios: 'c++' }> { add(a: number, b: number): number } ``` ```cpp class HybridMath : public HybridMathSpec { public: double add(double a, double b) override; } ``` -------------------------------- ### Use Hybrid Object in TypeScript Source: https://github.com/mrousavy/nitro/blob/main/README.md Demonstrates how to create and use a hybrid object from TypeScript. Import NitroModules, create an instance of your hybrid object, and call its methods. ```typescript import { NitroModules } from 'react-native-nitro-modules' const math = NitroModules.createHybridObject('Math') const result = math.add(5, 3) ``` -------------------------------- ### Legacy React Native Callback Limitation Example Source: https://github.com/mrousavy/nitro/blob/main/docs/docs/types/callbacks.md Illustrates the limitation in legacy React Native Native Modules where a native method cannot accept multiple callbacks beyond the standard success/failure, as demonstrated by an interface attempting to define multiple callbacks for recording events. ```typescript interface Camera { startRecording(onStatusUpdate: () => void, onRecordingFailed: () => void, onRecordingFinished: () => void): Promise } ``` -------------------------------- ### Implement Event Listeners in Nitro vs Turbo Modules Source: https://github.com/mrousavy/nitro/blob/main/docs/docs/resources/comparison.md Shows how Nitro uses first-class function listeners compared to the string-based event system in Turbo Modules. ```swift class Math: MathSpec { var listeners: [(String) -> Void] = [] func addListener(listener: (String) -> Void) { listeners.add(listener) } func onSomethingChanged() { for listener in listeners { listener("something changed!") } } } ``` ```objective-c @implementation RTNMath RCT_EXPORT_MODULE(); - (NSArray *)supportedEvents { return @[@"onSomethingChanged"]; } - (void)onSomethingChanged { NSString* message = @"something changed!"; [self sendEventWithName:@"onSomethingChanged" body:@{@"msg": message}]; } ``` -------------------------------- ### TypeScript and Swift Type Mismatch Example Source: https://github.com/mrousavy/nitro/blob/main/docs/docs/resources/comparison.md Shows a type mismatch scenario between TypeScript on the JS side and Swift on the native side for an 'add' function. This highlights potential runtime errors in Expo Modules due to the lack of a code-generator and potential user errors in maintaining type synchronization. ```typescript interface Math { add(a: number, b: number | undefined): number // b can be undefined here: ^ } const math = ... math.add(5, undefined) // code-error // ^ will throw at runtime! ``` ```swift public class MathModule: Module { public func definition() -> ModuleDefinition { Name("Math") Function("add") { (a: Double, b: Double) -> Double in // b CANNOT be undefined here: ^ return a + b } } } ``` -------------------------------- ### Implement a C++ Hybrid Object Source: https://github.com/mrousavy/nitro/blob/main/packages/react-native-nitro-modules/README.md Demonstrates how to create a custom Hybrid Object by inheriting from the HybridObject class. It includes defining properties, methods, and registering them within the loadHybridMethods override. ```cpp #include using namespace margelo::nitro; class MyHybridObject: public HybridObject { public: explicit MyHybridObject(): HybridObject(TAG) {} public: double getNumber() { return 13; } void setNumber(double value) { } double add(double left, double right) { return left + right; } public: void loadHybridMethods() override { HybridObject::loadHybridMethods(); registerHybrids(this, [](Prototype& prototype) { prototype.registerHybridGetter("number", &MyHybridObject::getNumber); prototype.registerHybridSetter("number", &MyHybridObject::setNumber); prototype.registerHybridMethod("add", &MyHybridObject::add); }); } private: static constexpr auto TAG = "MyHybrid"; }; ``` -------------------------------- ### Manage Native ArrayBuffers Source: https://github.com/mrousavy/nitro/blob/main/docs/docs/types/array-buffers.md Demonstrates how to wrap existing memory, copy data, or allocate new buffers on the native side. These operations allow for efficient memory management across Swift, Kotlin, and C++. ```swift let myData = UnsafeMutablePointer.allocate(capacity: 4096) // wrap (no copy) let wrappingArrayBuffer = ArrayBuffer.wrap(dataWithoutCopy: myData, size: 4096, onDelete: { myData.deallocate() }) // copy let copiedArrayBuffer = ArrayBuffer.copy(of: wrappingArrayBuffer) // new blank buffer let newArrayBuffer = ArrayBuffer.allocate(size: 4096) ``` ```kotlin val myData = ByteBuffer.allocateDirect(4096) // wrap (no copy) val wrappingArrayBuffer = ArrayBuffer.wrap(myData) // copy val copiedArrayBuffer = ArrayBuffer.copy(myData) // new blank buffer val newArrayBuffer = ArrayBuffer.allocate(4096) ``` ```cpp auto myData = new uint8_t[4096]; // wrap (no copy) auto wrappingArrayBuffer = ArrayBuffer::wrap(myData, 4096, [=]() { delete[] myData; }); // copy auto copiedArrayBuffer = ArrayBuffer::copy(myData, 4096); // new blank buffer auto newArrayBuffer = ArrayBuffer::allocate(4096); ``` -------------------------------- ### Initialize Android C++ Native Modules Source: https://github.com/mrousavy/nitro/blob/main/docs/docs/concepts/nitrogen.md Manual initialization of C++ native modules using JNI and React Package integration. ```cpp JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void*) { return facebook::jni::initialize(vm, []() { margelo::nitro::math::registerAllNatives(); }); } ``` ```kotlin public class NitroMathPackage: BaseReactPackage() { companion object { init { NitroMathOnLoad.initializeNative(); } } } ``` -------------------------------- ### Handle Non-Owning ArrayBuffers in Swift Source: https://github.com/mrousavy/nitro/blob/main/docs/docs/types/array-buffers.md Shows how to safely handle non-owning ArrayBuffers received from JavaScript. It highlights the danger of accessing them asynchronously and demonstrates how to create an owning copy. ```swift func doSomething(buffer: ArrayBuffer) { let copy = buffer.isOwner ? buffer : ArrayBuffer.copy(of: buffer) let data = copy.data // <-- safe now because we have an owning copy DispatchQueue.global().async { let data = copy.data // <-- still safe now because we have an owning copy } } ``` -------------------------------- ### Event Handling in Native Modules (Swift) Source: https://github.com/mrousavy/nitro/blob/main/docs/docs/resources/comparison.md Demonstrates how to handle events in native modules using Swift for both Nitro and Expo Modules. Nitro uses a listener callback, while Expo Modules uses a dedicated `Events` declaration and `sendEvent` method. ```swift class Math: MathSpec { var listeners: [(String) -> Void] = [] func addListener(listener: (String) -> Void) { listeners.add(listener) } func onSomethingChanged() { for listener in listeners { listener("something changed!") } } } ``` ```swift let SOMETHING_CHANGED = "onSomethingChanged" public class MathModule: Module { public func definition() -> ModuleDefinition { Name("Math") Events(SOMETHING_CHANGED) } private func onSomethingChanged() { sendEvent(SOMETHING_CHANGED, [ "message": "something changed!" ]) } } ``` -------------------------------- ### Declare Camera View Props and Methods Source: https://github.com/mrousavy/nitro/blob/main/docs/docs/guides/view-components.md Define the properties and methods for your custom view using `HybridViewProps` and `HybridViewMethods`. This TypeScript file serves as the declaration for your Nitro View. ```typescript import type { HybridView, HybridViewProps, HybridViewMethods } from 'react-react-native-nitro-modules' export interface CameraProps extends HybridViewProps { enableFlash: boolean } export interface CameraMethods extends HybridViewMethods {} // highlight-next-line export type CameraView = HybridView ```