npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

react-native-safe-module

v1.2.0

Published

A safe way to consume React Native NativeModules

Downloads

10,472

Readme

react-native-safe-module

A safe way to consume React Native NativeModules

npm Version License Build Status

Motivation

React Native enables a new aspect of mobile development: "Code Push". Code Push provides developers a way to push updates to their JS code base to mobile clients without going through the app store.

Since you can code push to older versions of the native client app, this type of deployment creates a new point of failure though: JavaScript code that is incompatible with the native version of the app it's running on.

React Native JS interacts with the Native code entirely through "Native Modules", which are injected at run-time onto the ReactNative.NativeModules namespace. As a result, having code that interacts with these modules directly can result in run-time errors. This library allows you to more safely interact with native modules, and provide version-specific overrides for the module, as well as mocks to use in the case that the method or module is entirely absent. The result is more robust code that can be code pushed to more users, as well as code that can be tested in an environment without a host app (e.g, Node).

Installation

npm i --save react-native-safe-module

Usage

Importing SafeModule is as simple as:

import SafeModule from 'react-native-safe-module';

Basic Usage

If you were using a Native Module before, such as NativeModules.FooModule like this:

import { NativeModules } from 'react-native';
const { FooModule } = NativeModules;

// ...

FooModule.doSomething().then(...)

You can instead do:

import SafeModule from 'react-native-safe-module';
const FooModule = SafeModule.create({
  moduleName: 'FooModule',
  mock: {
    doSomething: () => Promise.resolve(...),
  },
});

// ...

FooModule.doSomething().then(...)

Version-Specific Overrides

By default, SafeModule assumes that you are exporting a constant VERSION with each Native Module that can be used to identify which version of the native module it is. If you would like to specify the version a different way, you are able to add a getVersion option to the SafeModule configuration which is a function expected to return the correct version of the module.

Often times you may need to make a breaking change to the API of your Native Module, but it can be made backwards compatible with SafeModule very easily.

For example, imagine we have a Scrolling module with a scrollTo(...) method.

In version "7" of the module, the method signature of scrollTo looked something like scrollTo(x: number, y: number, animated: true).

In the latest version of the module, we have changed the method signature to look something like: scrollTo(options: {x: number, y: number, animated: true}).

This is a breaking change, but we can make it backwards compatible with SafeModule:

// Scrolling.js
import SafeModule from 'react-native-safe-module';

module.exports = SafeModule.create({
  moduleName: 'MyCustomScrollingModule',
  mock: {
    scrollTo: () => { /* do nothing */},
  },
  overrides: {
    7: {
      // overrides are defined as higher-order functions which are first
      // called with the real module's method, and are expected to return
      // a new function with the current API.
      scrollTo: oldScrollTo => options => {
        return oldScrollTo(options.x, options.y, !!options.animated);
      },
    },
  },
});

Module Name Changes

Sometimes we want to change the name of a Native Module. In this case, we need to support both versions of the name. SafeModule allows you to specify moduleName as an array of names. It will use the first name it finds.

For example, consider the case where we have a module named FooExperimentalModule, and we want to change the name of it to be just FooModule.

// FooModule.js
import SafeModule from 'react-native-safe-module';

module.exports = SafeModule.create({
  moduleName: ['FooModule', 'FooExperimentalModule'],
  mock: {
    ...
  },
});

In this case, SafeModule will look for FooModule first, and then FooExperimentalModule if it is not found. Finally, it will fall back to the mock implementation if none is found.

API

SafeModule.create(options)

Parameters:

  • options.moduleName: (required, string | Array<string>) the name, or array of names, to look for the module at on the NativeModules namespace.
  • options.mock: (required, mixed) The mock implementation of the native module.
  • options.getVersion: ((module) => string|number) Optional. A function that returns the version of the native module. Only needed if you are specifying overrides and not exporting a VERSION property on your native module. Defaults to x => x.VERSION.
  • options.overrides: ({[version: string]: mixed) Optional. A map of version numbers to overridden implementations of the corresponding property/method. If an overridden property or method is a function, it will be called during SafeModule.create(...) with two arguments, the original value of that property on the original module, and the original module itself. The return value of this function will be put on the return value of SafeModule.create(...).
  • options.isEventEmitter: (bool) Optional. A flag indicating that the native module is expected to be an EventEmitter. Puts the EventEmitter instance on the emitter property of the resulting module. Defaults to false.

TODO

  • [ ] Implement onInit lifecycle method
  • [ ] Implement onNoModuleFound lifecycle method
  • [ ] Implement onVersionFound lifecycle method
  • [ ] Implement onOverrideUsed lifecycle method
  • [ ] Implement onOverrideCalled lifecycle method