Giter VIP home page Giter VIP logo

re-natal's Introduction

Re-Natal

A utility for building ClojureScript-based React Native apps

Artur Girenko @drapanjanas


Re-Natal is a simple command-line utility that automates most of the process of setting up a React Native app running on ClojureScript with Reagent + re-frame, Om.Next or Rum.

This project is a fork of dmotz/natal by Dan Motzenbecker.

Figwheel support is based on the brilliant solution developed by Will Decker decker405/figwheel-react-native, which works on both platforms.

For more ClojureScript React Native resources visit cljsrn.org.

Contributions are very welcome.

Status

  • Uses React Native v0.59.5
  • Reusable codebase between iOS and Android
  • Figwheel used for REPL and live coding
    • Works in iOS (real device and simulator)
    • Works in Android (real device and simulators, specifically AVD and Genymotion)
    • Figwheel REPL can be started from within nREPL
    • Simultaneous development of iOS and Android apps
    • Manual reload and automatic hot reload
    • Custom react-native components supported
    • Source maps available
  • Supported React wrappers: Reagent, Om.Next, and Rum
  • Support of windows (UWP and WPF) apps
  • Unified way of using static images of React Native 0.14+ supported

Compatibility with RN versions

Current version of re-natal might not work correctly with older versions of React Native

  • use current version of re-natal with React Native >= v0.46
  • use re-natal < v0.5.0 with React Native < v0.46

Dependencies

As Re-Natal is an orchestration of many individual tools, there are quite a few dependencies. If you've previously done React Native or Clojure development, you should hopefully have most installed already. Platform dependencies are listed under their respective tools.

For iOS development:

  • Xcode (+ Command Line Tools) >=6.3

Creating a new project

Before getting started, make sure you have the required dependencies installed.

Then, install the CLI using npm:

$ npm install -g re-natal

To generate a new app, run re-natal init with your app's name as an argument:

$ re-natal init FutureApp

This will generate a project which uses Reagent v0.6.
You may specify the -i option to choose a specific React wrapper: Om.Next, Reagent v0.6 or Rum:

$ re-natal init FutureApp -i [om-next | reagent6 | rum]

If your app's name is more than a single word, be sure to type it in CamelCase. A corresponding hyphenated Clojure namespace will be created.

The init process will take a few minutes — coffee break! If all goes well you should see basic instructions on how to run in iOS simulator.

Development with Figwheel

Initially the index.*.js files are generated with the production profile, ready for deployment.
However, during development it is better to use the development profile and integrate with Figwheel. Switch to the development profile with:

$ re-natal use-figwheel

This command needs to be run every time you switch to the development profile or specify a development environment (with use-ios-device or use-android-device).

NOTE: You might need to restart React Native Packager and reload your app.

Starting a standalone Figwheel REPL

Start a Figwheel REPL from the command line with:

$ lein figwheel [ios | android]

If all went well you should see the REPL prompt and changes in source files should be hot-loaded by Figwheel.

Starting Figwheel REPL from nREPL

You can also start Figwheel from within an existing nREPL session. Start a REPL with lein repl or, if using emacs and CIDER for editor integration, cider-jack-in (C-c M-j). Then in the REPL prompt type:

user=> (start-figwheel "ios")

Or, for Android build type:

user=> (start-figwheel "android")

Or, for both type:

user=> (start-figwheel "ios" "android")

Changing the default Figwheel port

In case you have a conflict with the default Figwheel port you can change it as follows:

  1. Change the port in project.clj (as per Figwheel docs)
  2. Run re-natal set-figwheel-port <port>
  3. Run re-natal use-figwheel

Running the app

Note for Linux users

On Linux, the React Native Packager has to be started manually with

react-native start

See here for more details.

iOS

Using iOS simulator

re-natal use-ios-device simulator
react-native run-ios

Using real iOS device

re-natal use-ios-device real

If this doesn't correctly detect your computer's IP you can pass your IP address explicitly: re-natal use-ios-device <IP address>.
And then run

react-native run-ios

Switching between iOS devices

Run use-ios-device to configure device type you want to use in development:

$ re-natal use-ios-device <real|simulator>
$ re-natal use-figwheel
$ lein figwheel ios

Android

Using Android Virtual Device (AVD)

Set up a virtual device in AVD. Start the virtual device then run

$ re-natal use-android-device avd
$ re-natal use-figwheel
$ lein figwheel android
$ react-native run-android

Using Genymotion simulator

Set up and start the Genymotion simulator then run

$ re-natal use-android-device genymotion
$ re-natal use-figwheel
$ lein figwheel android
$ react-native run-android

Using real Android device

To run figwheel with real Android device please read Running on Device.
To make it work on a USB connected device I also had to run:

$ adb reverse tcp:8081 tcp:8081
$ adb reverse tcp:3449 tcp:3449

Then:

$ re-natal use-android-device real
$ re-natal use-figwheel
$ lein figwheel android
$ react-native run-android

Switching between Android devices

Run use-android-device to configure device type you want to use in development:

$ re-natal use-android-device <real|genymotion|avd>
$ re-natal use-figwheel
$ lein figwheel android

Developing iOS and Android apps simultaneously

$ re-natal use-figwheel
$ lein figwheel ios android

Using external React Native Components

Lets say you have installed an external library from npm like this:

$ npm i some-library --save

And you want to use a component called 'some-library/Component':

(def Component (js/require "some-library/Component"))

This works fine when you do lein prod-build and run your app.

The React Native packager statically scans for all calls to require and prepares the required code to be available at runtime. But, dynamically loaded (by Figwheel) code bypasses this scan and therefore requiring the custom component fails.

In re-natal this is solved by adding all dependencies in index.*.js file which is scanned by React Native packager.

Using auto-require

To enable auto-require feature you have to run command:

$ re-natal enable-auto-require

From now on, command use-figwheel will scan for all required modules and generate index.*.js with all required dependencies. You will have to re-run use-figwheel command every time you use new modules via (js/require "...")

This feature is available since [email protected]

Manually registering dependencies with use-component command

You can register a single dependency manually by running require command:

$ re-natal require some-library/Component

or for a platform-specific component use the optional platform parameter:

$ re-natal require some-library/ComponentIOS ios

Then, regenerate index.*.js files:

$ re-natal use-figwheel

Lastly, you will have to restart the packager and reload your app.

NOTE: If you mistyped something, or no longer use the component and would like to remove it, manually open .re-natal and fix it there (it's just a list of names in JSON format, so the process should be straight forward).

Scanning for dependencies with require-all command

If you have used new modules in your code you can run:

$ re-natal require-all

This will scan your code for (js/require ...) calls and add new required modules automatically. After this, you still need to run use-figwheel command to regenerate index.*.js files.

REPL

You have to reload your app, and should see the REPL coming up with the prompt.

At the REPL prompt, try loading your app's namespace:

(in-ns 'future-app.ios.core)

Changes you make via the REPL or by changing your .cljs files should appear live in the simulator.

Try this command as an example:

(dispatch [:set-greeting "Hello Native World!"])

Running on Linux

In addition to the instructions above on Linux you might need to start React Native packager manually with command react-native start. This was reported in #3

See this tutorial on how to set up and run re-natal on a clean install of Ubuntu.

Support of UWP and WPF apps (using react-native-windows)

To start new project with UWP app:

$ re-natal init FutureApp -u

To start new project with WPF app:

$ re-natal init FutureApp -w

Existing projects can also add windows platforms any time using commands:

$ re-natal add-platform windows

or

$ re-natal add-platform wpf

Note: for projects generated with re-natal version prior to 0.4.0 additional windows builds will not be added automatically to project.clj. Workaround is to generate fresh windows project and copy-paste additional builds manually.

Production build

Do this with command:

$ lein prod-build

Follow the React Native documentation to proceed with the release.

Advanced CLJS compilation

$ lein advanced-build

The ReactNative externs are provided by react-native-externs Other library externs needs to be added manually to advanced profile in project.clj

Static Images

Since version 0.14 React Native supports a unified way of referencing static images

In Re-Natal skeleton images are stored in "images" directory. Place your images there and reference them from cljs code:

(def my-img (js/require "./images/my-img.png"))

Adding an image during development

When you have dropped a new image to "images" dir, you need to restart React Native packager and re-run command:

$ re-natal use-figwheel

This is needed to regenerate index.*.js files which includes require calls to all local images. After this you can use a new image in your cljs code.

If your images aren't able to be required after running re-natal use-figwheel, you may need to also run react-native run-android.

Upgrading existing Re-Natal project

Upgrading React Native version

To upgrade React Native to newer version please follow the official Upgrading guide of React Native. Re-Natal makes almost no changes to the files generated by react-native so the official guide should be valid.

Upgrading Re-Natal CLI version

Do this if you want to use newer version of re-natal.

Commit or backup your current project, so that you can restore it in case of any problem ;)

Upgrade re-natal npm package

$ npm upgrade -g re-natal

In root directory of your project run

$ re-natal upgrade

This will overwrite only some files which usually contain fixes in newer versions of re-natal, and are unlikely to be changed by the user. No checks are done, these files are just overwritten:

  • files in /env directory
  • figwheel-bridge.js

Then to continue development using figwheel

$ re-natal use-figwheel

Example Apps

Tips

  • Having rlwrap installed is optional but highly recommended since it makes the REPL a much nicer experience with arrow keys.

  • Running multiple React Native apps at once can cause problems with the React Packager so try to avoid doing so.

  • You can launch your app on the simulator without opening Xcode by running react-native run-ios in your app's root directory (since RN 0.19.0).

  • To change advanced settings run re-natal xcode to quickly open the Xcode project. (A workspace will be opened in preference to a project if present.)

  • If you have customized project layout and re-natal upgrade does not fit you well, then these commands might be useful for you: * re-natal copy-figwheel-bridge - just copies figwheel-bridge.js from current re-natal

Local Development of Re-Natal

If you would like to run any of this on your local environment first clone the code to an appropriate place on your machine and install dependencies

$ git clone https://github.com/drapanjanas/re-natal.git
$ cd re-natal
$ npm install

To test any changes made to re-natal, cd to an already existing project or a brand new dummy project:

$ cd ../already-existing

and run the re-natal command line like so

$ node ../re-natal/index.js

  Usage: re-natal [options] [command]


  Commands:

    init [options] <name>              create a new ClojureScript React Native project
    upgrade                            upgrades project files to current installed version of re-natal (the upgrade of re-natal itself is done via npm)
    add-platform <platform>            adds additional app platform: 'windows' - UWP app, 'wpf' - WPF app
    xcode                              open Xcode project (or workspace if present)
    deps                               install all dependencies for the project
    use-figwheel                       generate index.*.js for development with figwheel
    use-android-device <type>          sets up the host for android device type: 'real' - localhost, 'avd' - 10.0.2.2, 'genymotion' - 10.0.3.2, IP
    use-ios-device <type>              sets up the host for ios device type: 'simulator' - localhost, 'real' - auto detect IP on eth0, IP
    use-component <name> [<platform>]  configures a custom component to work with figwheel. name is the value you pass to (js/require) function.
    enable-source-maps                 patches RN packager to server *.map files from filesystem, so that chrome can download them.
    copy-figwheel-bridge               copy figwheel-bridge.js into project

  Options:

    -h, --help     output usage information
    -V, --version  output the version number

You can then run any of the commands manually.

re-natal's People

Contributors

areina avatar at-tran avatar carocad avatar cascadian avatar cldwalker avatar daiyi avatar daveliepmann avatar dmotz avatar drapanjanas avatar ducky427 avatar dvcrn avatar erubi avatar gadfly361 avatar livtanong avatar maacl avatar madvas avatar marxama avatar mfikes avatar mlakewood avatar neutrous avatar nrakochy avatar paulbutcher avatar prertik avatar puppybits avatar pvinis avatar stask avatar tmclane avatar vikeri avatar wnr avatar zetagon avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

re-natal's Issues

Automatically write dev env ip in `(start-figwheel)` for `env.main` to use (fix included)

Hey!

Thanks for this great project. I adapted the code to use in https://exponentjs.com/ (allows you to publish react-native apps for browsing on both ios and android). Everything works: code reload, repl, cider integration with autocomplete, docs. The use case was a little different (ios and android have common code) so I just adapted the code. Here's a gif: https://twitter.com/snikhilesh/status/722743659674804224

I made it automatically write the development environment ip to a javascript module 'dev-env' that goes in target/ so that env.main can read that to pass to figwheel/watch-and-reload. You may want to adapt your code to do this too. Here is the relevant change:
expo/exp-cljstest@e762b4d

I would've done a pull request but I only wrote the case for reagent and my directory structure is a bit different because I don't have separate ios and android code.

We may be able to do it without writing a .js file and instead a .cljs file that writes to a new dev.config namespace or something (will figwheel automatically load a new .cljs file added under target/?). Let me know if you go down that route, I'd like to see what you come up with!

We could also just use closure defines in project.clj to inject constants into the resultant JS--haven't explored that route yet.

Reduce logging output or maybe create logging levels?

Right now re-natal logs a lot of info to the console. It's easy to get lost in the sea of cljs packages that are loaded and evaled (two separate messages per file). Maybe removing some of the logging would help users see more signal than noise? Here's what my console looks like after I disabled some of the info logs:

screen shot 2016-03-20 at 2 55 04 pm

Beautiful! :)

Use same approach for requiring static images as for external components

Currently there is a macro env.require-img/require-img which expands to {:uri "http://localhost:8081/path/to/image.png"} during development and to (js/require "./path/to/image.png) during prod build.
This was more like a workaround just to support Static Image Resources in re-natal.
Now this macro can be deprecated/removed in favour of using similar approach like was implemented for #5

Implementation could be smth like:

  • in use-figwheel scan images directory and statically include them same as with use-component
  • add CLI command to include other directories with images

Pros

  • normal js/require can be used to require a static image

Cons

  • when new image is added, need to call use-figwheel again and reload app via "Reload JS"

Slow Rendering + Glitches on iOS 9.1

I just got back to working on #37 and started noticing some weird rendering issues and glitches. Specifically:

  • rendering refreshes very slowly, and
  • the alert OK button isn't clickable

I was able to localize it to the iOS 9.1 simulator on my machine. 8.1 works no problem. I've not tried a physical device.

I've include a screen capture of what I am seeing. Am I the only one? I doubt it's re-natal specific. Thanks for the sanity check.

screen recording 2016-04-25 at 10 03 pm

figwheel-bridge.js only logs first argument to log

Did:

  • Called apply js/console.log with many arguments.

Expected:

  • To see all arguments logged in my console.

Happened:

  • Saw only the first argument being logged.

Suggested solution:
Call log with apply with all arguments:

// figwheel-bridge.js

    window.console.log = function (msg) {
        if (compileWarningRx.test(msg)) {
            console.warn(msg);
        } else {
            log.apply(window.console, arguments);
        }
    };

Currently version:

// figwheel-bridge.js

    window.console.log = function (msg) {
        if (compileWarningRx.test(msg)) {
            console.warn(msg);
        } else {
            log.call(window.console, msg);
        }
    };

Command for copyFigwheelBridge

Hi. Would you take a PR for a command that just calls copyFigwheelBridge() with name from the config? We'd like to pull in the great upstream work you're doing on figwheel-bridge.js. doUpgrade() doesn't work for us because we have a different project layout than env/ and "src/#{projNameUs}/ios/core.cljs" and we're not looking to use the other changes e.g. patch react-native. Cheers

Switch schema out for cljs.spec

Would you be interested in a PR to change schema in cljs-reagent6 for cljs.spec? This will require upgrading the template to use latest clojurescript and a clojure 1.8.0-alpha version. I've been using cljs.spec in deployed ios + android re-natal apps and it's been working great :)

Use reagent 0.6.0-alpha with latest re-natal

react-native version 0.18.x is dependent on react 0.14.x while reagent 0.5.x is dependent on react 0.13.x.

These are the breaking changes for react 0.14.0

Not sure if this is really an issue but its worth highlighting.

Support Rum

I am interested in supporting Rum https://github.com/tonsky/rum for react-native development through re-natal.

Rum is a minimal Clojure wrapper around React that is opinion-less.

I took an initial stab at getting it to work but I was having trouble with sablono https://github.com/r0man/sablono (it seems tightly coupled with browser DOM stuff).

Shimming a couple things and writing some custom Rum macros and mixins to not use sablono should be all that it takes.

Putting this out there if anyone else is interested as well and/or has insights.

lein figwheel android hands for ever

I could run the following command successfully, but "lein figwheel android" runs forever, the last message is "Prompt will show when Figwheel connects to your application". What's wrong?

oracle@SomeHost /data/node-v4.4.3/bin/future-app $ re-natal use-android-device avd
Using host '10.0.2.2' for android device type 'avd'

oracle@SomeHost /data/node-v4.4.3/bin/future-app $ re-natal use-figwheel
Cleaning...
index.ios.js was regenerated
index.android.js was regenerated
AppDelegate.m was updated
Dev server host for iOS: localhost
Dev server host for Android: 10.0.2.2

oracle@SomeHost /data/node-v4.4.3/bin/future-app $ adb devices
List of devices attached
R32D100AT3K device

oracle@SomeHost /data/node-v4.4.3/bin/future-app $ lein figwheel android
Figwheel: Starting server at http://localhost:3449
Port 3449 is already being used. Are you running another Figwheel instance? If you want to run two Figwheel instances add a new :server-port (i.e. :server-port 3450) to Figwheel's config options in your project.clj
Figwheel: Watching build - android
Compiling "target/android/not-used.js" from ["src" "env/dev"]...
Successfully compiled "target/android/not-used.js" in 2.637 seconds.
Launching ClojureScript REPL for build: android
Figwheel Controls:
(stop-autobuild) ;; stops Figwheel autobuilder
(start-autobuild [id ...]) ;; starts autobuilder focused on optional ids
(switch-to-build id ...) ;; switches autobuilder to different build
(reset-autobuild) ;; stops, cleans, and starts autobuilder
(reload-config) ;; reloads build config and resets autobuild
(build-once [id ...]) ;; builds source one time
(clean-builds [id ..]) ;; deletes compiled cljs target files
(print-config [id ...]) ;; prints out build configurations
(fig-status) ;; displays current state of system
Switch REPL build focus:
:cljs/quit ;; allows you to switch REPL to another build
Docs: (doc function-name-here)
Exit: Control+C or :cljs/quit
Results: Stored in vars *1, *2, *3, *e holds last exception object
Prompt will show when Figwheel connects to your application

Figwheel inferior to Hot Reloading?

I'm facing an annoying issue with WebViews.
When using figwheel, each time I save (and thus hot reload the app) all webviews in my app are "refreshed".
It's not the case when using JavaScript react native projects with Hot Reload enabled. The UI tree is updated, and WebViews are not reloading their pages.

re-natal + figwheel + save = web view is refreshing
vanilla react native + hot reload + save = web view is not refreshing

I played around with a google maps examples.
simulator screen shot 24 jun 2016 22 20 34

Slow bootup times on Android

Anyone experience slow bootup times on Android using this stack? Seems like a 1-2s lag before the JS part of the app kicks in.

Stop working during initialize new project

I am trying to initialize new project but it stops during Creating React Native skeleton.
I wait about one hour but it did not work.
I also tried using http_proxy

Is there anyway see the what is happening behind?
As I checked there is a --verbose option in natal but not in re-natal

Out Of Memory Errors on Android

Hey there! Thanks so much for such a cool project :) I've been looking to try out ClojureScript and Reagent/Re-frame on a fun project, and this seemed like a great way to try.

However, I noticed when the app runs in Dev mode (haven't tried production), it takes up a great deal of memory and after a few reloads causes the app in my Android emulator to crash. (Note: I tried both the default Android Emulator and Genymotion).

Not sure if anyone has ideas on the source of this problem or how easy it would be to fix up, but this looked like a bit of a show-stopper for a first time user. Thanks again for all the time and effort on this project!

Steps:

  1. Follow the instructions to get the app running on Android
  2. Reload the android app several times (opening the menu, "Reload JS")
  3. App will crash (adb log shows an Out Of Memory Trend)

Looking at the monitor, there's a ton of memory usage from the sample app. Here's a comparison of the default re-natal memory usage vs react-native memory usage:

Stock React Native Project: Memory Usage

The blips in the graph come from reloading. Notice it always stays around 3mb of memory usage.

screenshot 2016-01-10 13 45 42

## Stock Re-natal project

The increases come after every time I reload the project. Notice the memory continues to grow and grow:

screenshot 2016-01-10 13 49 41

Eventually resulting in this Out Of Memory Crash:

--------- beginning of crash
01-10 13:50:00.885 19749-21983/com.gol E/AndroidRuntime: FATAL EXCEPTION: OkHttp Dispatcher
                                                         Process: com.gol, PID: 19749
                                                         java.lang.OutOfMemoryError: OutOfMemoryError thrown while trying to throw OutOfMemoryError; no stack trace available
01-10 13:50:00.892 19749-19757/com.gol E/System: java.lang.OutOfMemoryError: OutOfMemoryError thrown while trying to throw OutOfMemoryError; no stack trace available

                                                 [ 01-10 13:50:00.895  1362: 1835 D/         ]
                                                 HostConnection::get() New Host Connection established 0xa07b7340, tid 1835
01-10 13:50:00.911 19749-19749/com.gol I/art: Clamp target GC heap from 67MB to 64MB

Cannot connect to figwheel

"adb reverse" - is not available for android version prior to 5.0. So, I cannot use to reverse-forward port 3449 from android localhost to my Dev machine.
Need a way to specify IP to use by figwheel

How to "Reload the app to see the REPL prompt" ?

In the README documentation, it is mentionned that
You have to reload your app, and should see the REPL coming up with the prompt.

Does this mean to reload the entire application ? On a real Android device, the only way I've managed to have a REPL prompt was to go to "debug js" to launch a chrome instance on the computer, but I'm not sure it's the proper way to do it.

Thanks ;)

Why two core.cljs files ?

In the future-app sample application, how come there are two core.cljs files (for both android and ios) ? Shouldn't there be only one base code for all platforms ?

Thanks ;)

Example of creating a component?

Hi, I'm trying to get started with re-natal. I have the sample project running, and I'm about to make my first component / sub-view. The generated project doesn't have an example sub-component, and when I try to make one according to the reagent docs, it fails.

If I try to move the press-me button into a component:

(defn press-me-label [name]
  [text {:style {:color "white" :text-align "center" :font-weight "bold"}} (str "press me: " name)])

Then I can call it as a function as follows:

       ...
       [touchable-highlight {:style {:background-color "#999" :padding 10 :border-radius 5}
                             :on-press #(alert "HELLO!")}
        (press-me-label "bob")]])))

But the reagent docs specifically say you're supposed to call it as a vector:

       ...
       [touchable-highlight {:style {:background-color "#999" :padding 10 :border-radius 5}
                             :on-press #(alert "HELLO!")}
        [press-me-label "bob"]]])))

However, when I do that I get the following error:

error

Am I doing something wrong? If creating components differs from reagent, can you specify in the documentation how to do so? I've trying using a Form-2 component and it still doesn't work. Am I supposed to use the function syntax? why? What if I need a component that requires setup?

external library does not work in Android

Hi,

Thanks for create such a convenient library for mobile app developing!

I just import the react-native-vector-icons/FontAwesome today, and I tried it in iOS, it works perfectly, after I tried it in Android, it did not work, said the import is nil, the iOS and Android platform share almost the same code, and they have not met such problem before. I followed carefully the import guide, so I guess it is the import question here.

I have write it into .re-natal and the import code is like

       (def icons (r/adapt-react-class (js/require "react-native-vector-icons/FontAwesome")))

I also following the steps to import font to Android and iOS, due to the assert failed error hint, I believe I did the right so I come to re-natal here.

Hanwen

Do not regenerate env/dev/ files on re-natal use-figwheel

Currently there is Reagent specific code in env/dev/*/main.cljs. Regenerating these files makes it impossible to use om-next.
To support Android simulators, re-natal might just update fighweel url to set simulator specific IP address instead of regenerating whole file.
Actually, there is no need to change host for iOS at all. Only for android host might be localhost, 10.0.2.2 or 10.0.3.2.
Probably need to create dedicated command for changing host only for android and remove this concern from use-figwheel.

Clojure 1.9.0-alpha11 breaks `lein prod-build`

This is my first time posting an issue on Github, so hope I don't screw this up haha!

Just tried updating both my Clojure and ClojureScript dependencies in the project.clj of my new app project. Upgrading to the latest CLJS version 1.9.227 worked fine. When trying to go up from Clojure 1.9.0-alpha10 to 1.9.0-alpha11, I get the following massive error message:

Exception in thread "main" java.lang.IllegalArgumentException: Call to clojure.core/ns did not conform to spec:
In: [3 0] val: import fails spec: :clojure.core.specs/ns-refer-clojure at: [:args :clauses :refer-clojure :clause] predicate: #{:refer-clojure}
In: [3 0] val: import fails spec: :clojure.core.specs/ns-require at: [:args :clauses :require :clause] predicate: #{:require}
In: [3 0] val: import fails spec: :clojure.core.specs/ns-import at: [:args :clauses :import :clause] predicate: #{:import}
In: [3 0] val: import fails spec: :clojure.core.specs/ns-use at: [:args :clauses :use :clause] predicate: #{:use}
In: [3 0] val: import fails spec: :clojure.core.specs/ns-refer at: [:args :clauses :refer :clause] predicate: #{:refer}
In: [3 0] val: import fails spec: :clojure.core.specs/ns-load at: [:args :clauses :load :clause] predicate: #{:load}
In: [3 0] val: import fails spec: :clojure.core.specs/ns-gen-class at: [:args :clauses :gen-class :clause] predicate: #{:gen-class}
:clojure.spec/args  (cljsbuild.crossover (:use [clojure.java.io :only [as-url resource]]) (:require [cljsbuild.util :as util] [clojure.string :as string] [fs.core :as fs]) (import java.io.File java.net.URLDecoder))
, compiling:(cljsbuild/crossover.clj:1:1)
    at clojure.lang.Compiler.macroexpand1(Compiler.java:6795)
    at clojure.lang.Compiler.macroexpand(Compiler.java:6861)
    at clojure.lang.Compiler.eval(Compiler.java:6935)
    at clojure.lang.Compiler.load(Compiler.java:7403)
    at clojure.lang.RT.loadResourceScript(RT.java:374)
    at clojure.lang.RT.loadResourceScript(RT.java:365)
    at clojure.lang.RT.load(RT.java:455)
    at clojure.lang.RT.load(RT.java:421)
    at clojure.core$load$fn__7645.invoke(core.clj:6008)
    at clojure.core$load.invokeStatic(core.clj:6007)
    at clojure.core$load.doInvoke(core.clj:5991)
    at clojure.lang.RestFn.invoke(RestFn.java:408)
    at clojure.core$load_one.invokeStatic(core.clj:5812)
    at clojure.core$load_one.invoke(core.clj:5807)
    at clojure.core$load_lib$fn__7590.invoke(core.clj:5852)
    at clojure.core$load_lib.invokeStatic(core.clj:5851)
    at clojure.core$load_lib.doInvoke(core.clj:5832)
    at clojure.lang.RestFn.applyTo(RestFn.java:142)
    at clojure.core$apply.invokeStatic(core.clj:659)
    at clojure.core$load_libs.invokeStatic(core.clj:5889)
    at clojure.core$load_libs.doInvoke(core.clj:5873)
    at clojure.lang.RestFn.applyTo(RestFn.java:137)
    at clojure.core$apply.invokeStatic(core.clj:659)
    at clojure.core$require.invokeStatic(core.clj:5911)
    at clojure.core$require.doInvoke(core.clj:5911)
    at clojure.lang.RestFn.invoke(RestFn.java:436)
    at user$eval15.invokeStatic(form-init2469899088480641630.clj:1)
    at user$eval15.invoke(form-init2469899088480641630.clj:1)
    at clojure.lang.Compiler.eval(Compiler.java:6951)
    at clojure.lang.Compiler.eval(Compiler.java:6940)
    at clojure.lang.Compiler.load(Compiler.java:7403)
    at clojure.lang.Compiler.loadFile(Compiler.java:7341)
    at clojure.main$load_script.invokeStatic(main.clj:276)
    at clojure.main$init_opt.invokeStatic(main.clj:278)
    at clojure.main$init_opt.invoke(main.clj:278)
    at clojure.main$initialize.invokeStatic(main.clj:309)
    at clojure.main$null_opt.invokeStatic(main.clj:343)
    at clojure.main$null_opt.invoke(main.clj:340)
    at clojure.main$main.invokeStatic(main.clj:422)
    at clojure.main$main.doInvoke(main.clj:385)
    at clojure.lang.RestFn.applyTo(RestFn.java:137)
    at clojure.lang.Var.applyTo(Var.java:700)
    at clojure.main.main(main.java:37)
Caused by: java.lang.IllegalArgumentException: Call to clojure.core/ns did not conform to spec:
In: [3 0] val: import fails spec: :clojure.core.specs/ns-refer-clojure at: [:args :clauses :refer-clojure :clause] predicate: #{:refer-clojure}
In: [3 0] val: import fails spec: :clojure.core.specs/ns-require at: [:args :clauses :require :clause] predicate: #{:require}
In: [3 0] val: import fails spec: :clojure.core.specs/ns-import at: [:args :clauses :import :clause] predicate: #{:import}
In: [3 0] val: import fails spec: :clojure.core.specs/ns-use at: [:args :clauses :use :clause] predicate: #{:use}
In: [3 0] val: import fails spec: :clojure.core.specs/ns-refer at: [:args :clauses :refer :clause] predicate: #{:refer}
In: [3 0] val: import fails spec: :clojure.core.specs/ns-load at: [:args :clauses :load :clause] predicate: #{:load}
In: [3 0] val: import fails spec: :clojure.core.specs/ns-gen-class at: [:args :clauses :gen-class :clause] predicate: #{:gen-class}
:clojure.spec/args  (cljsbuild.crossover (:use [clojure.java.io :only [as-url resource]]) (:require [cljsbuild.util :as util] [clojure.string :as string] [fs.core :as fs]) (import java.io.File java.net.URLDecoder))

    at clojure.spec$macroexpand_check.invokeStatic(spec.clj:627)
    at clojure.spec$macroexpand_check.invoke(spec.clj:616)
    at clojure.lang.AFn.applyToHelper(AFn.java:156)
    at clojure.lang.AFn.applyTo(AFn.java:144)
    at clojure.lang.Var.applyTo(Var.java:700)
    at clojure.lang.Compiler.macroexpand1(Compiler.java:6789)
    ... 42 more
Error encountered performing task 'cljsbuild' with profile(s): 'prod'
Subprocess failed

Obviously a lot being worked on and changed with Clojure.spec. Does anyone know specifically what change between alpha10 and alpha11 might be causing this?

Thanks!

Some issues are not shown

reagent6, iOS, Mac

TLDR: Some RN errors are not reported anywhere

All of a sudden the hot code reload fails and no more changes are pushed. That usually means that I screwed something up. If I reload the emulator I just get Waiting for Figwheel to load files. The figwheel REPL shows nothing and a (reset-autobuild) successfully recompiles the project.

It is like these issues fall between compile issues shown by figwheel and the red screen of RN. I have not got around to make an MWE but an example issue is when I accidentally ran the function r/adapt-react-class twice on an object.

Not sure if this issue is related to re-natal but I never experienced them in React Web.

unknown command use-android-device on Arch Linux

I'm trying to use an android emulator with re-natal, but the command
re-natal use-android-device avd

raised the following error in the console :
unknown command use-android-device. See re-natal --help for valid commands

Using re-natal 0.2.18 on Arch Linux.

Is this command supported on Linux ?

Requiring unkown module problem

Hi
I've been trying to use react-native-vector-icons in my re-natal generated project. But for some reason I keep on ending up with the requiring unknown module error.
2016 01 03 15 50 41 Genymotion for personal use
I've tried requiring the module using the following different paths below:
(def icon (js/require "react-native-vector-icons/FontAwesome.js"))
(def icon (js/require "react-native-vector-icons/FontAwesome"))
(def icon (js/require "FontAwesome.js"))
It seems to happen with other custom react native components as well. So it seems maybe I'm doing something wrong

how to disable fig-wheel

Hi, thanks for the great framework,

I read all the document and start to use it with figwheel, but there is some problem and now I want to have a try with the original hot-Reloading Module. But after use re-natal use-figwheel, how to disable it to the init state? It will be nice if you can include this in the README.

Work on Android only

I would like to ask whether it would be possible to work on Android (no XCode installed) and Linux.

If no, which I can already see when I do re-natal init myApp, what could be done to contribute this feature? Is it a lot of work?

Thanks and very good job!

compileWarningsToYellowBox assumes msg is a string

I think figwheel-bridge.js has a regression:

function compileWarningsToYellowBox() {
    var log = window.console.log;
    var compileWarningRx = /Figwheel: Compile Warning/;
    window.console.log = function (msg) {
        if (msg.match(compileWarningRx) != null) {
            console.warn(msg);
        } else {
            log.call(window.console, msg);
        }
    };
}

This function assumes that msg is a string (it can also be a javascript/cljs object) and silently fails when match is called and it's not a string. Below is a fix. Also, I recommend just matching on "Figwheel Compile" as there are also "Figwheel Compile Exception"s.

function compileWarningsToYellowBox() {
    var log = window.console.log;
    var compileWarningRx = /Figwheel: Compile/;
    window.console.log = function (msg) {
        if (typeof msg.match === 'function' && msg.match(compileWarningRx) != null) {
            console.warn(msg);
        } else {
            log.call(window.console, msg);
        }
    };
}

So, I tried forking your repo and doing a pull request, but the forked repo was "natal". Now I'm certainly no github genius, but I think this is problematic.

Also, great work on the rewrite! Firebase is working out of the box now. :)

Show CLJS compilation errors and other warnings on screen

Currently, when using figwheel CLJS compilation erros are almost invisible. Same as other errors like if you mistyped some property name: instead of :font-weight you accidently typed :font-weihgt such error stays not visible.
If you use React Native without CLJS and figwheel you would see warnings in yellow box at the bottom of simulator screen.

re-natal init fails on W7

Hi,

I tried to run re-natal init SomeApp on W7 and it fails with:

Leiningen is required (http://leiningen.org)

As you suggested in slack the problem is that type does not exist on windows.

Any app (incl. default example) crashes with "Can't find variable: React" when launched from a JS bundle on an iOS device

...but works just fine when the JS is compiled+delivered via Figwheel/React Native packager.

Screenshot:
img_0003

...and Xcode console log:

2016-03-27 01:37:02.578 [error][tid:com.facebook.React.JavaScript] Can't find variable: React
2016-03-27 01:37:02.587 [fatal][tid:com.facebook.React.RCTExceptionsManagerQueue] Unhandled JS Exception: Can't find variable: React
2016-03-27 01:37:02.813 [error][tid:com.facebook.React.JavaScript] Module AppRegistry is not a registered callable module.
2016-03-27 01:37:02.817 [fatal][tid:com.facebook.React.RCTExceptionsManagerQueue] Unhandled JS Exception: Module AppRegistry is not a registered callable module.
2016-03-27 01:37:03.840 [warn][tid:com.facebook.React.JavaScript] Unable to load source map: No source map URL found. May be running from bundled file.
2016-03-27 01:37:03.841 [warn][tid:com.facebook.React.JavaScript] Unable to load source map: No source map URL found. May be running from bundled file.

I'm attaching the main.jsbundle:
main.jsbundle.zip

A readable one can be created with:

node --max-old-space-size=4096 node_modules/react-native/local-cli/cli.js bundle --entry-file index.ios.js --platform ios --dev true --bundle-output "ios/main.jsbundle"

Steps to reproduce:

npm install -g re-natal
re-natal init CrashingApp
cd crashing-app
re-natal xcode
lein prod-build

Make sure the JS is delivered from a bundle by editing ios/CrashingApp/AppDelegate.m, commenting this line:

 // jsCodeLocation = [NSURL URLWithString:@"http://localhost:8081/index.ios.bundle?platform=ios&dev=true"];

and uncommenting this one:

   jsCodeLocation = [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"];

Connect device, select it as launch destination in Xcode and hit the run button (after the prod-build process in step 1 is complete).

Expected: app launches after a brief display of a "loading from bundle" status message.
Observed: App crashes with aforementioned exception.

The app works fine on a device and in the simulator when run with:

lein figwheel ios
npm start

(+ reverse step 2 above to disable the bundle).

re-natal version is 0.2.28.

This issue seems like it might be related:
este/este#752

My guess is that the JS compiled with ":optimizations :simple" (as in the default config of the prod-build profile) somehow trips up some optimization/transformation the react native packager does to the JS when creating a bundle.

I tried switching the prod-build leiningen profile to :optimizations :none (as in the working figwheel profile configuration), but then the bundle cannot be created at all, the process dying with the following message:

uncaught error Error: UnableToResolveError: Unable to resolve module env.ios.main from /Users/gnl/Documents/cljs-issue/testcases/test-four/index.ios.js: Unable to find this module in its module map or any of the node_modules directories under /Users/node_modules/env.ios.main and its parent directories

Either way, this should work with the default configuration, as it most definitely used to. I'm not quite sure when it stopped, since I was happily developing with Figwheel for more than a week until I tried creating a standalone package to deploy to a device and saw this happen.

Oddly enough, even when downgrading re-natal to 0.2.26 (which I'm pretty sure I used for my last successful packaging) and init-ing a new default project I observe the same behaviour, so not sure which part of the build chain is causing this exactly.

In the same environment, creating a standard RN project with react-native init DemoApp and running on a device from a JS bundle works just fine.

Can anyone else reproduce this?

Thanks!

Update README dependencies

I tried creating a new project with re-natal 0.2.13 and was unable to start the app due to an "importScript not defined" error.

It was fixed by upgrading react-native-cli to the latest version, 1.9. Please add this as a dependency in the README to save other people time! :)

Google Closure defines not working with figwheel

Setting the compiler option in project.clj

:closure-defines {my.ns.var true}

does not work (due to the statement being compiled to not-used-js).

I also tried to set it in figwheel-bridge.js like this:

var CLOSURE_UNCOMPILED_DEFINES = {"my.ns.var":true};

But it didn't work either.

Any ideas on how to get it working?

When running figwheel on both platforms at once, reloads are doubled

I don't know if this is known, but:

  • start new project via re-natal init
  • re-natal use-android-device genymotion
  • re-natal use-figwheel
  • start figwheel as (start-figwheel "ios" "android")
  • start IOS simulator, genymotion

Now when u make file change, figwheel pushes new code twice. I mean twice into IOS, twice into android. If I hadn't start e.g. genymotion, IOS would be notified of file change just once - correctly.
As you can see in the picture, code is run twice on IOS after single file change.

snap 2016-05-14 at 16 02 27 416x297

The solution I came up with: Start running 2 figwheels on different ports, Android would connect to one, IOS to the other one. Everything works as expected. Code is pushed just once.

My user.clj looks like:

(ns user
  (:require [figwheel-sidecar.repl-api :as ra]
            [figwheel-sidecar.system :as fs]))
;; This namespace is loaded automatically by nREPL

;; read project.clj to get build configs
(def profiles (->> "project.clj"
                   slurp
                   read-string
                   (drop-while #(not= % :profiles))
                   (apply hash-map)
                   :profiles))

(def cljs-builds (get-in profiles [:dev :cljsbuild :builds]))

(defn start-figwheel
  ([build-id] (start-figwheel build-id false))
  ([build-id repl?]
   (let [port (if (= build-id :android) 6551 6552)
         start-fig (if repl? ra/start-figwheel! fs/start-figwheel!)]
     (start-fig
       {:figwheel-options {:server-port port}
        :build-ids        [build-id]
        :all-builds       cljs-builds}))
   (when repl?
     (ra/cljs-repl))))

(defn start-figwheels []
  (start-figwheel :android)
  (start-figwheel :ios true))

And we can't forget to change :websocket-url in env.android.main and env.ios.main to ports 6551 and 6552

Talk about React Native on Clojure/West 2016

Hi,

This is an awesome tool that you have here and currently on the list of suggested topics to the Clojure/West conference ClojureScript + ReactNative is wining, people are interested in this.

We should spread the news about ClojureScript and React Native. Currently there are not that much videos exists about this topics and I'm almost sure that many folks from JS community would be crazy to see REPL support (unique feature for ClojureScript) and macroses I'm sure would blow their mind! :)

'iosHost' config option to allow changing figwheel websocket host

Currently there is no easy to set the figwheel websocket url to anything other than 'ws://localhost:3449' which would be very helpful for live code reloading on an iOS device.

I tried changing the :websocket-url in env/dev/env/ios/main.cljs, but the localhost URL still ends up in:

ios/figwheel/connect.cljs
target/ios/figwheel/connect.cljs

I'm not familiar enough with the code base/figwheel/compilation process and wasn't able to find a quick solution. Help! :)

P.S. Awesome project!

How do I restart react native packager?

The README keeps telling us that we might need to restart the packager for the REPL to connect. How do we do that? It would be cool to include that in the README as well.

My REPL won't connect to my app, and I want to try this step but don't know how to proceed.

re-natal init, figwheel filenotfound error

I got re-natal, and ran re-natal init:

$ re-natal init FutureApp
Creating FutureApp

Creating Leiningen project
Updating Leiningen project
Creating React Native skeleton. Relax, this takes a while...
Creating Re-Natal config
Compiling ClojureScript

To get started with your new app, first cd into its directory:
cd future-app

Open iOS app in xcode and run it:
re-natal xcode

To use figwheel start "Debug in Chrome" in simulator and type:
re-natal use-figwheel
lein figwheel ios

Reload the app in simulator

At the REPL prompt type this:
(in-ns 'future-app.ios.core)

Changes you make via the REPL or by changing your .cljs files should appear live.

Try this command as an example:
(dispatch [:set-greeting "Hello Native World!"])

✔ Done

I then ran re-natal xcode and re-natal use-figwheel, and got an error on the third step

$ lein figwheel ios
clojure.lang.Compiler$CompilerException: java.io.FileNotFoundException: Could not locate cljs/analyzer__init.class or cljs/analyzer.clj on classpath: , compiling:(figwheel_sidecar/utils.clj:1:1)
 at clojure.lang.Compiler.load (Compiler.java:7142)
    clojure.lang.RT.loadResourceScript (RT.java:370)
    clojure.lang.RT.loadResourceScript (RT.java:361)
    clojure.lang.RT.load (RT.java:440)
    clojure.lang.RT.load (RT.java:411)
    clojure.core$load$fn__5066.invoke (core.clj:5641)
    clojure.core$load.doInvoke (core.clj:5640)
    clojure.lang.RestFn.invoke (RestFn.java:408)
    clojure.core$load_one.invoke (core.clj:5446)
    clojure.core$load_lib$fn__5015.invoke (core.clj:5486)
    clojure.core$load_lib.doInvoke (core.clj:5485)
    clojure.lang.RestFn.applyTo (RestFn.java:142)
    clojure.core$apply.invoke (core.clj:626)
    clojure.core$load_libs.doInvoke (core.clj:5524)
    clojure.lang.RestFn.applyTo (RestFn.java:137)
    clojure.core$apply.invoke (core.clj:626)
    clojure.core$require.doInvoke (core.clj:5607)
    clojure.lang.RestFn.invoke (RestFn.java:551)
    figwheel_sidecar.config$eval2752$loading__4958__auto____2753.invoke (config.clj:1)

re-natal breaks with React 0.15.0

React 0.15 came out today, and removes cloneWithProps (which is still used by react-native 0.22.2).

re-natal pulls in React 0.15, but produces an error about cloneWithProps.

[email protected] still requires react@^0.14.5 to run (probably because of the breaking changes):

npm WARN [email protected] requires a peer of react@^0.14.5 but none was installed.

I tried downgrading to [email protected], but re-natal does not allow anything below [email protected], when you run re-natal use-figwheel.

Not sure what the workaround is, until React Native fixes the breaking change in React 0.15 and upgrades.

Contribute to RN packager and remove hack for serving *.map files

As noted in readme to support source maps, RN packagers is patched in local node_module. Which is a small but dirty hack. It should be totally harmless, but still, soap and water can not wash off the dirt from my hands :)

So here's the plan:

  1. Implement an new option for packager to force serving files matching the provided pattern from the file system.
  2. Implement persistent configuration for being able to persist the packager options without need of supplying them in command line. Command line arguments should override those in config

re-natal upgrade fails with "Cannot read property 'length' of undefined"

Hi. While taking a look at luno-react-native I had the above error.

Steps to reproduce:

  1. git clone luno-react-native to alwx/luno-react-native@122d541
  2. re-natal upgrade

The failure seems to be coming from editing a non-existing file on older projects. This can be fixed by putting a file exists check before that line is invoked. Since that fn is called by multiple contexts, we may need to pass a boolean to patchReactNativePackager to check whether the file exists or not. Happy to submit a PR if you explain the approach you want.

For this particular case it would've been helpful if there was a stacktrace. Setting this event may help with that

Thanks for re-natal and look forward to using it more!

Support om-next

Similarily how it is done in original Natal init command.

Open points:

  1. Need to figure out suitable om-next architecture for crossplatform apps to reuse common code. Only UI part should be separate.
  2. What component wrappers to use for om-next? Reagent has function adapt-react-class, but in om-next examples usually use some wrapper library like natal-shell or ktoa has smth similar. Maybe better not to use any by default and let the developer decide?

This is a good excerse to learn om-next basics, so will it take some time. Any proposals on this topic are wellcome.

Configurable path to ios and android main.cljs

Problem

The path to android and ios main.cljs is currently hardcoded to env/{dev|prod}/env/{ios|android}/main.cljs
The command re-natal use-figwheel cannot be configured to match my project structure (see My use case).

Suggestion

It would be nice to have the path to {dev|prod}/env/{ios|android}/main.cljs configurable, i.e. having dir env configurable. To put something in .re-natal like:

{
...
  "envRoot": "env",
...
}

My use case

I have a lot of platforms and mains - server, web and mobile - and I'd like to have the same structure for all my mains. Here's part of my current structure:

env/client/dev/web/main.cljs
env/client/prod/web/main.cljs
env/client/dev/ios/main.cljs
env/client/prod/ios/main.cljs
env/client/dev/android/main.cljs
...
env/common/dev/utils.cljc
...
env/server/dev/server/main.clj
env/server/dev/server/repl.clj
...

In my case, I'd configure .re-natal: "envRoot": "env/client"

Discussion: Integrate boot to avoid fragmentation

As the essay of the lisp curse predicts we already have some fragmentation in the very young CLJS RN space: re-natal vs boot-react-native. re-natal is clearly the most popular one if you judge from number of stars and forks here on GitHub. I am pretty sure that as RN usage grows in the CLJS community people are going to want to use boot since it seems to be very popular for the web/node. While the fragmentation between boot and lein are reasonable since they represent different philosophies I do not feel the same is true for re-natal vs boot-react-native and therefore I'd like to raise the question if these projects could be merged or that re-natal would add boot to the roadmap.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.