├── .eslintrc.js ├── .gitignore ├── LICENSE ├── browser-browserify.json ├── browser.json ├── cmd.js ├── coreList.js ├── package.json ├── pkg-hacks.js ├── readme.md ├── shim.js ├── shims-browserify.js ├── shims.js └── test └── index.js /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | "env": { 3 | "es6": true, 4 | "node": true 5 | }, 6 | "globals": { 7 | // react native 8 | "window": true, 9 | "__DEV__": true, 10 | "localStorage": true 11 | }, 12 | "extends": "eslint:recommended", 13 | "parserOptions": { 14 | "sourceType": "module" 15 | }, 16 | "rules": { 17 | "accessor-pairs": "error", 18 | "array-bracket-spacing": "warn", 19 | "array-callback-return": "warn", 20 | "arrow-body-style": "warn", 21 | "arrow-parens": [ 22 | "error", 23 | "as-needed" 24 | ], 25 | "arrow-spacing": [ 26 | "error", 27 | { 28 | "after": true, 29 | "before": true 30 | } 31 | ], 32 | "block-scoped-var": "error", 33 | "block-spacing": "error", 34 | "brace-style": [ 35 | "error", 36 | "1tbs" 37 | ], 38 | "callback-return": "error", 39 | "camelcase": "warn", 40 | "capitalized-comments": "off", 41 | "class-methods-use-this": "error", 42 | "comma-dangle": "off", 43 | "comma-spacing": [ 44 | "error", 45 | { 46 | "after": true, 47 | "before": false 48 | } 49 | ], 50 | "comma-style": [ 51 | "error", 52 | "last" 53 | ], 54 | "complexity": "error", 55 | "computed-property-spacing": "error", 56 | "consistent-return": "warn", 57 | "consistent-this": "warn", 58 | "curly": "off", 59 | "default-case": "error", 60 | "dot-location": "off", 61 | "dot-notation": "warn", 62 | "eol-last": "warn", 63 | "eqeqeq": "warn", 64 | "func-call-spacing": "error", 65 | "func-name-matching": "error", 66 | "func-names": "warn", 67 | "func-style": "warn", 68 | "generator-star-spacing": "off", 69 | "global-require": "off", 70 | "guard-for-in": "warn", 71 | "handle-callback-err": "warn", 72 | "id-blacklist": "error", 73 | "id-length": "off", 74 | "id-match": "error", 75 | "indent": "off", 76 | "init-declarations": "off", 77 | "jsx-quotes": "error", 78 | "key-spacing": "error", 79 | "keyword-spacing": [ 80 | "error", 81 | { 82 | "after": true, 83 | "before": true 84 | } 85 | ], 86 | "line-comment-position": "warn", 87 | "linebreak-style": [ 88 | "error", 89 | "unix" 90 | ], 91 | "lines-around-comment": "warn", 92 | "lines-around-directive": "error", 93 | "max-depth": "error", 94 | "max-len": "off", 95 | "max-lines": "warn", 96 | "max-nested-callbacks": "error", 97 | "max-params": "warn", 98 | "max-statements": "off", 99 | "max-statements-per-line": "error", 100 | "multiline-ternary": "warn", 101 | "new-cap": "error", 102 | "new-parens": "error", 103 | "newline-after-var": "off", 104 | "newline-before-return": "off", 105 | "newline-per-chained-call": "warn", 106 | "no-alert": "error", 107 | "no-array-constructor": "error", 108 | "no-await-in-loop": "error", 109 | "no-bitwise": "error", 110 | "no-caller": "error", 111 | "no-case-declarations": "warn", 112 | "no-catch-shadow": "warn", 113 | "no-cond-assign": "warn", 114 | "no-confusing-arrow": "error", 115 | "no-console": "warn", 116 | "no-constant-condition": "warn", 117 | "no-continue": "warn", 118 | "no-div-regex": "error", 119 | "no-duplicate-imports": "error", 120 | "no-else-return": "error", 121 | "no-ex-assign": "off", 122 | "no-empty": [ 123 | "error", 124 | { 125 | "allowEmptyCatch": true 126 | } 127 | ], 128 | "no-empty-function": "off", 129 | "no-eq-null": "warn", 130 | "no-eval": "error", 131 | "no-extend-native": "error", 132 | "no-extra-bind": "error", 133 | "no-extra-label": "error", 134 | "no-extra-parens": "warn", 135 | "no-extra-semi": "warn", 136 | "no-floating-decimal": "error", 137 | "no-implicit-coercion": "warn", 138 | "no-implicit-globals": "error", 139 | "no-implied-eval": "error", 140 | "no-inline-comments": "off", 141 | "no-inner-declarations": "warn", 142 | "no-invalid-this": "warn", 143 | "no-iterator": "error", 144 | "no-label-var": "error", 145 | "no-labels": "error", 146 | "no-lone-blocks": "error", 147 | "no-lonely-if": "warn", 148 | "no-loop-func": "error", 149 | "no-magic-numbers": "off", 150 | "no-mixed-operators": "error", 151 | "no-mixed-requires": "error", 152 | "no-multi-assign": "warn", 153 | "no-multi-spaces": "error", 154 | "no-multi-str": "error", 155 | "no-multiple-empty-lines": "error", 156 | "no-native-reassign": "error", 157 | "no-negated-condition": "warn", 158 | "no-negated-in-lhs": "error", 159 | "no-nested-ternary": "error", 160 | "no-new": "error", 161 | "no-new-func": "error", 162 | "no-new-object": "error", 163 | "no-new-require": "error", 164 | "no-new-wrappers": "error", 165 | "no-octal-escape": "error", 166 | "no-param-reassign": "warn", 167 | "no-path-concat": "error", 168 | "no-process-env": "off", 169 | "no-process-exit": "off", 170 | "no-proto": "error", 171 | "no-prototype-builtins": "error", 172 | "no-restricted-globals": "error", 173 | "no-restricted-imports": "error", 174 | "no-restricted-modules": "error", 175 | "no-restricted-properties": "error", 176 | "no-restricted-syntax": "error", 177 | "no-return-assign": "warn", 178 | "no-return-await": "error", 179 | "no-script-url": "error", 180 | "no-self-compare": "error", 181 | "no-sequences": "error", 182 | "no-shadow": "warn", 183 | "no-shadow-restricted-names": "error", 184 | "no-spaced-func": "error", 185 | "no-sync": "off", 186 | "no-tabs": "error", 187 | "no-template-curly-in-string": "error", 188 | "no-ternary": "off", 189 | "no-throw-literal": "error", 190 | "no-trailing-spaces": "error", 191 | "no-undef-init": "warn", 192 | "no-undefined": "warn", 193 | "no-underscore-dangle": "warn", 194 | "no-unmodified-loop-condition": "error", 195 | "no-unneeded-ternary": "error", 196 | "no-unused-expressions": "error", 197 | "no-unused-vars": "warn", 198 | "no-use-before-define": "off", 199 | "no-useless-call": "error", 200 | "no-useless-computed-key": "error", 201 | "no-useless-concat": "error", 202 | "no-useless-constructor": "error", 203 | "no-useless-escape": "warn", 204 | "no-useless-rename": "error", 205 | "no-useless-return": "error", 206 | "no-var": "warn", 207 | "no-void": "error", 208 | "no-warning-comments": "warn", 209 | "no-whitespace-before-property": "error", 210 | "no-with": "error", 211 | "object-curly-newline": "off", 212 | "object-curly-spacing": [ 213 | "error", 214 | "always" 215 | ], 216 | "object-property-newline": [ 217 | "error", 218 | { 219 | "allowMultiplePropertiesPerLine": true 220 | } 221 | ], 222 | "object-shorthand": "warn", 223 | "one-var": "off", 224 | "one-var-declaration-per-line": "error", 225 | "operator-assignment": "error", 226 | "operator-linebreak": "error", 227 | "padded-blocks": "off", 228 | "prefer-const": "warn", 229 | "prefer-destructuring": "warn", 230 | "prefer-numeric-literals": "error", 231 | "prefer-promise-reject-errors": "error", 232 | "prefer-reflect": "warn", 233 | "prefer-rest-params": "warn", 234 | "prefer-spread": "warn", 235 | "prefer-template": "off", 236 | "quote-props": "off", 237 | "quotes": "off", 238 | "radix": "error", 239 | "require-await": "error", 240 | "require-jsdoc": "off", 241 | "require-yield": "off", 242 | "rest-spread-spacing": [ 243 | "error", 244 | "never" 245 | ], 246 | "semi": "off", 247 | "semi-spacing": "error", 248 | "sort-imports": "error", 249 | "sort-keys": "off", 250 | "sort-vars": "error", 251 | "space-before-blocks": "error", 252 | "space-before-function-paren": "error", 253 | "space-in-parens": [ 254 | "error", 255 | "never" 256 | ], 257 | "space-infix-ops": "off", 258 | "space-unary-ops": "error", 259 | "spaced-comment": [ 260 | "error", 261 | "always" 262 | ], 263 | "strict": "error", 264 | "symbol-description": "error", 265 | "template-curly-spacing": [ 266 | "error", 267 | "never" 268 | ], 269 | "unicode-bom": [ 270 | "error", 271 | "never" 272 | ], 273 | "valid-jsdoc": "warn", 274 | "vars-on-top": "off", 275 | "wrap-iife": "error", 276 | "wrap-regex": "warn", 277 | "yield-star-spacing": "error", 278 | "yoda": [ 279 | "error", 280 | "never" 281 | ] 282 | } 283 | }; 284 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Tradle 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /browser-browserify.json: -------------------------------------------------------------------------------- 1 | { 2 | "zlib": "browserify-zlib", 3 | "console": "console-browserify", 4 | "constants": "constants-browserify", 5 | "crypto": "crypto-browserify", 6 | "dns": "dns.js", 7 | "net": "react-native-tcp", 8 | "domain": "domain-browser", 9 | "http": "stream-http", 10 | "https": "https-browserify", 11 | "os": "os-browserify", 12 | "path": "path-browserify", 13 | "querystring": "querystring-es3", 14 | "fs": "react-native-level-fs", 15 | "_stream_transform": "readable-stream/transform", 16 | "_stream_readable": "readable-stream/readable", 17 | "_stream_writable": "readable-stream/writable", 18 | "_stream_duplex": "readable-stream/duplex", 19 | "_stream_passthrough": "readable-stream/passthrough", 20 | "dgram": "react-native-udp", 21 | "stream": "stream-browserify", 22 | "timers": "timers-browserify", 23 | "tty": "tty-browserify", 24 | "vm": "vm-browserify" 25 | } 26 | -------------------------------------------------------------------------------- /browser.json: -------------------------------------------------------------------------------- 1 | { 2 | "zlib": "browserify-zlib", 3 | "console": "console-browserify", 4 | "constants": "constants-browserify", 5 | "crypto": "react-native-crypto", 6 | "dns": "dns.js", 7 | "net": "react-native-tcp", 8 | "domain": "domain-browser", 9 | "http": "@tradle/react-native-http", 10 | "https": "https-browserify", 11 | "os": "react-native-os", 12 | "path": "path-browserify", 13 | "querystring": "querystring-es3", 14 | "fs": "react-native-level-fs", 15 | "_stream_transform": "readable-stream/transform", 16 | "_stream_readable": "readable-stream/readable", 17 | "_stream_writable": "readable-stream/writable", 18 | "_stream_duplex": "readable-stream/duplex", 19 | "_stream_passthrough": "readable-stream/passthrough", 20 | "dgram": "react-native-udp", 21 | "stream": "stream-browserify", 22 | "timers": "timers-browserify", 23 | "tty": "tty-browserify", 24 | "vm": "vm-browserify", 25 | "tls": false 26 | } 27 | -------------------------------------------------------------------------------- /cmd.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | var fs = require('fs') 4 | var path = require('path') 5 | var semver = require('semver') 6 | var proc = require('child_process') 7 | var pick = require('object.pick') 8 | var extend = require('xtend/mutable') 9 | var deepEqual = require('deep-equal') 10 | var find = require('findit') 11 | var minimist = require('minimist') 12 | var parallel = require('run-parallel') 13 | var yarnlock = require('@yarnpkg/lockfile') 14 | var allShims = require('./shims') 15 | var coreList = require('./coreList') 16 | var browser = require('./browser') 17 | var pkgPath = path.join(process.cwd(), 'package.json') 18 | var pkg = require(pkgPath) 19 | var hackFiles = require('./pkg-hacks') 20 | var argv = minimist(process.argv.slice(2), { 21 | alias: { 22 | h: 'help', 23 | i: 'install', 24 | e: 'hack', 25 | o: 'overwrite', 26 | y: 'yarn' 27 | } 28 | }) 29 | 30 | var BASE_INSTALL_LINE = argv.yarn ? 'yarn add' : 'npm install --save' 31 | 32 | if (argv.help) { 33 | runHelp() 34 | process.exit(0) 35 | } else { 36 | run() 37 | } 38 | 39 | function run () { 40 | var toShim 41 | if (argv.install) { 42 | if (argv.install === true) { 43 | toShim = coreList 44 | } else { 45 | toShim = argv.install.split(',') 46 | .map(function (name) { 47 | return name.trim() 48 | }) 49 | } 50 | } else { 51 | toShim = coreList 52 | } 53 | 54 | if (toShim.indexOf('stream') !== -1) { 55 | toShim.push( 56 | '_stream_transform', 57 | '_stream_readable', 58 | '_stream_writable', 59 | '_stream_duplex', 60 | '_stream_passthrough', 61 | 'readable-stream' 62 | ) 63 | } 64 | 65 | if (toShim.indexOf('crypto') !== -1) { 66 | toShim.push('react-native-randombytes') 67 | } 68 | 69 | if (argv.install) { 70 | installShims({ 71 | modules: toShim, 72 | overwrite: argv.overwrite 73 | }, function (err) { 74 | if (err) throw err 75 | 76 | runHacks() 77 | }) 78 | } else { 79 | runHacks() 80 | } 81 | 82 | function runHacks () { 83 | hackPackageJSONs(toShim, function (err) { 84 | if (err) throw err 85 | 86 | if (argv.hack) { 87 | if (argv.hack === true) hackFiles() 88 | else hackFiles([].concat(argv.hack)) 89 | } 90 | }) 91 | } 92 | } 93 | 94 | function installShims ({ modules, overwrite }, done) { 95 | if (!overwrite) { 96 | modules = modules.filter(name => { 97 | const shimPackageName = browser[name] || name 98 | if (pkg.dependencies[shimPackageName]) { 99 | log(`not overwriting "${shimPackageName}"`) 100 | return false 101 | } 102 | 103 | return true 104 | }) 105 | } 106 | 107 | var shimPkgNames = modules 108 | .map(function (m) { 109 | return browser[m] || m 110 | }) 111 | .filter(function (shim) { 112 | return !/^_/.test(shim) && (shim[0] === '@' || shim.indexOf('/') === -1) 113 | }) 114 | 115 | if (!shimPkgNames.length) { 116 | return finish() 117 | } 118 | 119 | // Load the exact package versions from the lockfile 120 | var lockfile 121 | if (argv.yarn) { 122 | if (fs.existsSync('yarn.lock')) { 123 | let result = yarnlock.parse(fs.readFileSync('yarn.lock', 'utf8')) 124 | if (result.type == 'success') { 125 | lockfile = result.object 126 | } 127 | } 128 | } else { 129 | var lockpath = path.join(process.cwd(), 'package-lock.json') 130 | if (fs.existsSync(lockpath)) { 131 | let result = require(lockpath) 132 | if (result && result.dependencies) { 133 | lockfile = result.dependencies 134 | } 135 | } 136 | } 137 | 138 | parallel(shimPkgNames.map(function (name) { 139 | var modPath = path.resolve('./node_modules/' + name) 140 | return function (cb) { 141 | fs.exists(modPath, function (exists) { 142 | if (!exists) return cb() 143 | 144 | var install = true 145 | if (lockfile) { 146 | // Use the lockfile to resolve installed version of package 147 | if (argv.yarn) { 148 | if (`${name}@${allShims[name]}` in lockfile) { 149 | install = false 150 | } 151 | } else { 152 | var lockfileVer = (lockfile[name] || {}).version 153 | var targetVer = allShims[name] 154 | if (semver.valid(lockfileVer)) { 155 | if (semver.satisfies(lockfileVer, targetVer)) { 156 | install = false 157 | } 158 | } else if (lockfileVer) { 159 | // To be considered up-to-date, we need an exact match, 160 | // after doing some normalization of github url's 161 | if (lockfileVer.startsWith('github:')) { 162 | lockfileVer = lockfileVer.slice(7) 163 | } 164 | if (lockfileVer.indexOf(targetVer) == 0) { 165 | install = false 166 | } 167 | } 168 | } 169 | } else { 170 | // Fallback to using the version from the dependency's package.json 171 | var pkgJson = require(modPath + '/package.json') 172 | if (/^git\:\/\//.test(pkgJson._resolved)) { 173 | var hash = allShims[name].split('#')[1] 174 | if (hash && pkgJson.gitHead.indexOf(hash) === 0) { 175 | install = false 176 | } 177 | } else { 178 | var existingVerNpm5 = (/\-([^\-]+)\.tgz/.exec(pkgJson.version) || [null, null])[1] 179 | var existingVer = existingVerNpm5 || pkgJson.version 180 | if (semver.satisfies(existingVer, allShims[name])) { 181 | install = false 182 | } 183 | } 184 | } 185 | 186 | if (!install) { 187 | log('not reinstalling ' + name) 188 | shimPkgNames.splice(shimPkgNames.indexOf(name), 1) 189 | } 190 | 191 | cb() 192 | }) 193 | } 194 | }), function (err) { 195 | if (err) throw err 196 | 197 | if (!shimPkgNames.length) { 198 | return finish() 199 | } 200 | 201 | var installLine = BASE_INSTALL_LINE + ' ' 202 | shimPkgNames.forEach(function (name) { 203 | let version = allShims[name] 204 | if (!version) return 205 | if (version.indexOf('/') === -1) { 206 | if (argv.yarn) { 207 | log('installing from yarn', name) 208 | } else { 209 | log('installing from npm', name) 210 | } 211 | installLine += name + '@' + version 212 | } else { 213 | // github url 214 | log('installing from github', name) 215 | installLine += version.match(/([^\/]+\/[^\/]+)$/)[1] 216 | } 217 | 218 | pkg.dependencies[name] = version 219 | installLine += ' ' 220 | }) 221 | 222 | fs.writeFile(pkgPath, prettify(pkg), function (err) { 223 | if (err) throw err 224 | 225 | if (installLine.trim() === BASE_INSTALL_LINE) { 226 | return finish() 227 | } 228 | 229 | log('installing:', installLine) 230 | proc.execSync(installLine, { 231 | cwd: process.cwd(), 232 | env: process.env, 233 | stdio: 'inherit' 234 | }) 235 | 236 | finish() 237 | }) 238 | }) 239 | 240 | function finish () { 241 | copyShim(done) 242 | } 243 | } 244 | 245 | function copyShim (cb) { 246 | fs.exists('./shim.js', function (exists) { 247 | if (exists) { 248 | log('not overwriting shim.js. For the latest version, see rn-nodeify/shim.js') 249 | return cb() 250 | } 251 | 252 | fs.readFile(path.join(__dirname, 'shim.js'), { encoding: 'utf8' }, function (err, contents) { 253 | if (err) return cb(err) 254 | 255 | fs.writeFile('./shim.js', contents, cb) 256 | }) 257 | }) 258 | } 259 | 260 | function hackPackageJSONs (modules, done) { 261 | fixPackageJSON(modules, './package.json', true) 262 | 263 | var finder = find('./node_modules') 264 | 265 | finder.on('file', function (file) { 266 | if (path.basename(file) !== 'package.json') return 267 | 268 | fixPackageJSON(modules, file, true) 269 | }) 270 | 271 | finder.once('end', done) 272 | } 273 | 274 | function fixPackageJSON (modules, file, overwrite) { 275 | if (file.split(path.sep).indexOf('react-native') >= 0) return 276 | 277 | var contents = fs.readFileSync(path.resolve(file), { encoding: 'utf8' }) 278 | 279 | // var browser = pick(baseBrowser, modules) 280 | var pkgJson 281 | try { 282 | pkgJson = JSON.parse(contents) 283 | } catch (err) { 284 | console.warn('failed to parse', file) 285 | return 286 | } 287 | 288 | // if (shims[pkgJson.name]) { 289 | // log('skipping', pkgJson.name) 290 | // return 291 | // } 292 | 293 | // if (pkgJson.name === 'readable-stream') debugger 294 | 295 | var orgBrowser = pkgJson['react-native'] || pkgJson.browser || pkgJson.browserify || {} 296 | if (typeof orgBrowser === 'string') { 297 | orgBrowser = {} 298 | orgBrowser[pkgJson.main || 'index.js'] = pkgJson['react-native'] || pkgJson.browser || pkgJson.browserify 299 | } 300 | 301 | var depBrowser = extend({}, orgBrowser) 302 | for (var p in browser) { 303 | if (modules.indexOf(p) === -1) continue 304 | 305 | if (!(p in orgBrowser)) { 306 | depBrowser[p] = browser[p] 307 | } else { 308 | if (!overwrite && orgBrowser[p] !== browser[p]) { 309 | log('not overwriting mapping', p, orgBrowser[p]) 310 | } else { 311 | depBrowser[p] = browser[p] 312 | } 313 | } 314 | } 315 | 316 | modules.forEach(function (p) { 317 | if (depBrowser[p] === false && browser[p] !== false) { 318 | log('removing browser exclude', file, p) 319 | delete depBrowser[p] 320 | } 321 | }) 322 | 323 | 324 | const { main } = pkgJson 325 | if (typeof main === 'string') { 326 | const alt = main.startsWith('./') ? main.slice(2) : './' + main 327 | if (depBrowser[alt]) { 328 | depBrowser[main] = depBrowser[alt] 329 | log(`normalized "main" browser mapping in ${pkgJson.name}, fixed here: https://github.com/facebook/metro-bundler/pull/3`) 330 | delete depBrowser[alt] 331 | } 332 | } 333 | 334 | if (pkgJson.name === 'constants-browserify') { 335 | // otherwise react-native packager chokes for some reason 336 | delete depBrowser.constants 337 | } 338 | 339 | if (!deepEqual(orgBrowser, depBrowser)) { 340 | pkgJson.browser = pkgJson['react-native'] = depBrowser 341 | delete pkgJson.browserify 342 | fs.writeFileSync(file, prettify(pkgJson)) 343 | } 344 | } 345 | 346 | function runHelp () { 347 | log(function () { 348 | /* 349 | Usage: 350 | rn-nodeify --install dns,stream,http,https 351 | rn-nodeify --install # installs all core shims 352 | rn-nodeify --hack # run all package-specific hacks 353 | rn-nodeify --hack rusha,fssync # run some package-specific hacks 354 | Options: 355 | -h --help show usage 356 | -e, --hack run package-specific hacks (list or leave blank to run all) 357 | -i, --install install shims (list or leave blank to install all) 358 | -o, --overwrite updates installed packages if a newer version is available 359 | -y, --yarn use yarn to install packages instead of npm (experimental) 360 | 361 | Please report bugs! https://github.com/mvayngrib/rn-nodeify/issues 362 | */ 363 | }.toString().split(/\n/).slice(2, -2).join('\n')) 364 | process.exit(0) 365 | } 366 | 367 | function log () { 368 | console.log.apply(console, arguments) 369 | } 370 | 371 | function prettify (json) { 372 | return JSON.stringify(json, null, 2) + '\n' 373 | } 374 | -------------------------------------------------------------------------------- /coreList.js: -------------------------------------------------------------------------------- 1 | module.exports = [ 2 | "assert", 3 | "zlib", 4 | "buffer", 5 | "inherits", 6 | "console", 7 | "constants", 8 | "crypto", 9 | "dns", 10 | "domain", 11 | "events", 12 | "http", 13 | "https", 14 | "os", 15 | "path", 16 | "process", 17 | "punycode", 18 | "querystring", 19 | "fs", 20 | "dgram", 21 | // "readable-stream", 22 | "stream", 23 | "string_decoder", 24 | "timers", 25 | "tty", 26 | "url", 27 | "util", 28 | "net", 29 | "vm", 30 | // note: tls doesn't have a shim 31 | "tls" 32 | ] 33 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "rn-nodeify", 3 | "repository": { 4 | "type": "git", 5 | "url": "https://github.com/tradle/rn-nodeify.git" 6 | }, 7 | "version": "10.3.0", 8 | "preferGlobal": true, 9 | "bin": "./cmd.js", 10 | "license": "MIT", 11 | "dependencies": { 12 | "@yarnpkg/lockfile": "^1.0.0", 13 | "deep-equal": "^1.0.0", 14 | "findit": "^2.0.0", 15 | "fs-extra": "^0.22.1", 16 | "minimist": "^1.1.2", 17 | "object.pick": "^1.1.1", 18 | "run-parallel": "^1.1.2", 19 | "semver": "^5.0.1", 20 | "xtend": "^4.0.0" 21 | }, 22 | "scripts": { 23 | "lint": "eslint --quiet --ignore-path .gitignore .", 24 | "precommit": "npm run lint" 25 | }, 26 | "devDependencies": { 27 | "husky": "^0.14.3" 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /pkg-hacks.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | // shelljs.exec('force-dedupe-git-modules') 4 | var proc = require('child_process') 5 | var fs = require('fs-extra') 6 | var find = require('findit') 7 | var path = require('path') 8 | // var thisPkg = require('./package.json') 9 | 10 | // function loadDeps() { 11 | // var pkgs = [] 12 | // loadPkg('./package.json') 13 | 14 | // function loadPkg(pkgPath) { 15 | // var pkg = require(pkgPath) 16 | // for (var dep in pkg.dependencies) { 17 | // if (!allDeps[dep]) { 18 | // allDeps[dep] = true 19 | // pkgs.push.apply(pkgs, Object.keys(pkg.dependencies).map(function(name) { 20 | // return path.join(pkgPath, 'node_modules/' + name) 21 | // })) 22 | // } 23 | // } 24 | // } 25 | // } 26 | 27 | module.exports = function hackFiles (hacks) { 28 | var finder = find('./node_modules') 29 | hacks = hacks || hackers.map(h => h.name) 30 | 31 | finder.on('file', function (file) { 32 | if (!/\.(js|json)$/.test(file) || 33 | /\/tests?\//.test(file)) { 34 | return 35 | } 36 | 37 | file = file.replace(/\\/g, path.posix.sep); 38 | 39 | var matchingHackers = hackers.filter(function (hacker) { 40 | return hacks.indexOf(hacker.name) !== -1 && hacker.regex.some(function (regex) { 41 | return regex.test(file) 42 | }) 43 | }) 44 | 45 | if (!matchingHackers.length) return 46 | 47 | file = path.resolve(file) 48 | fs.readFile(file, { encoding: 'utf8' }, onread) 49 | 50 | function onread (err, str) { 51 | if (err) throw err 52 | 53 | var hacked = matchingHackers.reduce(function (hacked, hacker) { 54 | return hacker.hack(file, hacked || str) || hacked 55 | }, str) 56 | 57 | if (hacked && hacked !== str) { 58 | console.log('hacking', file) 59 | fs.writeFile(file, hacked) 60 | } 61 | } 62 | }) 63 | } 64 | 65 | // loadDeps(hackFiles) 66 | 67 | var hackers = [ 68 | // don't need this as soon as react native 69 | // stops ignoring webtorrent/package.json "browser": "./lib/fs-storage.js": false 70 | { 71 | name: 'bluebird', 72 | regex: [ 73 | /bluebird\/js\/main\/captured_trace\.js$/ 74 | ], 75 | hack: function (file, contents) { 76 | var fixed = contents.replace( 77 | /fireGlobalEvent \= \(function\(\) \{\s{1}/, 78 | 'fireGlobalEvent = (function() {var self = global;' 79 | ) 80 | 81 | return contents === fixed ? null : fixed 82 | } 83 | }, 84 | { 85 | name: 'stream-browserify', 86 | regex: [ 87 | /stream-browserify\/index\.js$/ 88 | ], 89 | hack: function (file, contents) { 90 | var fixed = contents.replace( 91 | 'module.exports = Stream;', 92 | 'module.exports = global.StreamModule = Stream' 93 | ) 94 | 95 | return contents === fixed ? null : fixed 96 | } 97 | }, 98 | { 99 | name: 'readable-stream', 100 | regex: [ 101 | /readable-stream\/lib\/_stream_(readable|writable)\.js$/, 102 | /readable-stream\/readable\.js$/ 103 | ], 104 | hack: function (file, contents) { 105 | var fixed = contents.replace( 106 | "var Stream = require('stream');", 107 | "var Stream = global.StreamModule || require('stream')" 108 | ) 109 | 110 | return contents === fixed ? null : fixed 111 | } 112 | }, 113 | { 114 | name: 'has-cors', 115 | regex: [ 116 | /has-cors\/index\.js/, 117 | /socket\.io\.js/, 118 | /engine\.io\.js/ 119 | ], 120 | hack: function (file, contents) { 121 | var fixed = contents.replace("'withCredentials' in new XMLHttpRequest()", 'true') 122 | return contents === fixed ? null : fixed 123 | } 124 | }, 125 | { 126 | name: 'debug', 127 | regex: [ 128 | /debug\/browser\.js/ 129 | ], 130 | hack: function (file, contents) { 131 | var fixed = contents.replace("('WebkitAppearance' in document.documentElement.style)", 'true') 132 | return contents === fixed ? null : fixed 133 | } 134 | }, 135 | { 136 | name: 'rn-bundler', 137 | regex: [ 138 | /react\-(?:native\/)?packager\/src\/bundler\/bundle\.js/i, 139 | /react\-(?:native\/)?packager\/src\/JSTransformer\/worker\/minify\.js/i, 140 | ], 141 | hack: function (file, contents) { 142 | if (contents.indexOf('mangle:false') !== -1) return 143 | 144 | var fixed = contents.replace(/(\s+)(fromString: true,)/, '$1$2$1mangle:false,') 145 | return contents === fixed ? null : fixed 146 | } 147 | }, 148 | { 149 | name: 'pseudomap', 150 | regex: [ 151 | /pseudomap\/map\.js/ 152 | ], 153 | hack: function (file, contents) { 154 | var bad = /(module\.exports\s+\=\s+Map[^r]+return[^}]+\})/ 155 | var match = contents.match(bad) 156 | if (!match) return 157 | 158 | return contents.replace(match[0], 'module.exports=Map}else{') + '}' 159 | } 160 | }, 161 | { 162 | name: 'fssync', 163 | regex: [ 164 | /webtorrent\/lib\/fs-storage\.js/ 165 | ], 166 | hack: function (file, contents) { 167 | if (isInReactNative(file)) return 168 | 169 | var fixed = contents.replace(/fs\.existsSync\([^\)]*\)/g, 'false') 170 | return contents === fixed ? null : fixed 171 | } 172 | }, 173 | { 174 | name: 'rusha', 175 | regex: [ 176 | /\/rusha\/rusha\.js/ 177 | ], 178 | hack: function (file, contents) { 179 | var fixed = contents.replace(/typeof\ FileReaderSync \!\=\= \'undefined\'/, 'false') 180 | return contents === fixed ? null : fixed 181 | } 182 | }, 183 | { 184 | name: 'bufferequal', 185 | regex: [/rudp\/lib\/bufferEqual\.js/], 186 | hack: function (file, contents) { 187 | if (isInReactNative(file)) return 188 | 189 | var hacked = "module.exports = require('buffer-equal')" 190 | if (contents !== hacked) return hacked 191 | } 192 | }, 193 | // { 194 | // name: 'levelup', 195 | // regex: [ 196 | // /levelup\/lib\/util\.js$/ 197 | // ], 198 | // hack: function(file, contents) { 199 | // var bad = 'require(\'../package.json\')' 200 | // contents = contents.toString() 201 | // if (contents.indexOf(bad) !== -1) { 202 | // debugger 203 | // var pkg = require(path.resolve(file, '../../package.json')) 204 | // var fixed = contents.replace(bad, JSON.stringify(pkg)) 205 | // return contents === fixed ? null : fixed 206 | // } 207 | // } 208 | // }, 209 | { 210 | name: 'webworkerthreads', 211 | regex: [ 212 | /otr\/lib\/(dsa|otr)\.js/ 213 | ], 214 | hack: function (file, contents) { 215 | if (isInReactNative(file)) return 216 | 217 | var fixed = contents 218 | fixed = fixed.replace("require('webworker-threads').Worker", "null") 219 | return contents === fixed ? null : fixed 220 | } 221 | }, 222 | { 223 | name: 'levelup', 224 | regex: [ 225 | /levelup\/lib\/util\.js$/ 226 | ], 227 | hack: function (file, contents) { 228 | if (isInReactNative(file)) return 229 | 230 | var fixed = contents 231 | fixed = fixed.replace("require('../package.json').devDependencies.leveldown", "'1.0.0'") 232 | fixed = fixed.replace("require('leveldown/package').version", "'1.0.0'") 233 | fixed = fixed.replace("require('leveldown/package.json').version", "'1.0.0'") 234 | fixed = fixed.replace("require('leveldown')", "null") 235 | 236 | // var bad = '\'leveldown' 237 | // var fixed = contents.replace(/\'leveldown/g, '\'asyncstorage-down') 238 | // bad = 'require(\'../package.json\')' 239 | // if (fixed.indexOf(bad) !== -1) { 240 | // var pkg = require(path.resolve(file, '../../package.json')) 241 | // fixed = fixed.replace(bad, JSON.stringify(pkg)) 242 | // } 243 | 244 | // bad = "require('asyncstorage-down/package')" 245 | // if (fixed.indexOf(bad) !== -1) { 246 | // console.log(path.dirname(file)) 247 | // console.log(resolve.sync('asyncstorage-down'), { basedir: path.dirname(file) }) 248 | // var pkg = require(path.resolve(file, '../../node_modules/asyncstorage-down/package.json')) 249 | // fixed = fixed.replace(bad, JSON.stringify(pkg)) 250 | // } 251 | 252 | return contents === fixed ? null : fixed 253 | } 254 | }, 255 | { 256 | name: 'non-browser', 257 | regex: [ 258 | /level-jobs\/package\.json$/ 259 | ], 260 | hack: function (file, contents) { 261 | if (isInReactNative(file)) return 262 | 263 | var pkg 264 | try { 265 | pkg = JSON.parse(contents) 266 | } catch (err) { 267 | console.log('failed to parse:', file) 268 | return 269 | } 270 | 271 | if (pkg.browser) { 272 | delete pkg.browser 273 | return prettify(pkg) 274 | } 275 | } 276 | }, 277 | { 278 | name: 'simple-get', 279 | regex: [ 280 | /simple\-get\/package\.json$/ 281 | ], 282 | hack: function (file, contents) { 283 | if (isInReactNative(file)) return 284 | 285 | var pkg = JSON.parse(contents) 286 | if (pkg.browser['unzip-response'] === false) { 287 | delete pkg.browser['unzip-response'] 288 | return prettify(pkg) 289 | } 290 | } 291 | }, 292 | { 293 | name: 'browser_field', 294 | regex: [ 295 | /package\.json$/ 296 | ], 297 | hack: function (file, contents) { 298 | if (isInReactNative(file)) return 299 | 300 | var pkg 301 | try { 302 | pkg = JSON.parse(contents) 303 | } catch (err) { 304 | console.log('failed to parse:', file) 305 | return 306 | } 307 | 308 | if (pkg.browser && typeof pkg.browser === 'object') { 309 | var fixed 310 | for (var left in pkg.browser) { 311 | if (left[0] === '.' && !/\.[a-z]{0,4}$/i.test(left)) { 312 | fixed = true 313 | pkg.browser[left + '.js'] = pkg.browser[left] 314 | delete pkg.browser[left] 315 | } 316 | } 317 | 318 | if (fixed) return prettify(pkg) 319 | } 320 | } 321 | }, 322 | { 323 | name: 'webtorrentstuff', 324 | regex: [ 325 | /\/torrent\-discovery\/package.json$/, 326 | /\/webtorrent\/package.json$/, 327 | /\/load-ip-set\/package.json$/, 328 | ], 329 | hack: function (file, contents) { 330 | if (isInReactNative(file)) return 331 | 332 | var pkg = JSON.parse(contents) 333 | var browser = pkg.browser 334 | var save 335 | var toDel = [ 336 | 'bittorrent-dht', 337 | 'bittorrent-dht/client', 338 | 'bittorrent-tracker', 339 | 'bittorrent-tracker/client', 340 | 'bittorrent-swarm' 341 | ] 342 | 343 | for (var p in browser) { 344 | if (browser[p] === false) { 345 | toDel.push(p) 346 | } 347 | } 348 | 349 | toDel.forEach(function (p) { 350 | if (p in browser) { 351 | delete browser[p] 352 | save = true 353 | } 354 | }) 355 | 356 | if (save) return prettify(pkg) 357 | } 358 | }, 359 | { 360 | name: 'depgraph (rn 0.6)', 361 | regex: [ 362 | /react\-packager\/.*\/DependencyGraph\/index\.js/ 363 | ], 364 | hack: function (file, contents) { 365 | if (isInReactNative(file)) return 366 | 367 | var evil = 'var id = sansExtJs(name);' 368 | if (contents.indexOf(evil) !== -1) { 369 | return contents.replace(evil, 'var id = name;') 370 | } 371 | } 372 | }, 373 | { 374 | name: 'ecurve', 375 | regex: [ 376 | /ecurve\/lib\/names\.js/ 377 | ], 378 | hack: function (file, contents) { 379 | if (isInReactNative(file)) return 380 | 381 | var evil = 'var curves = require(\'./curves\')' 382 | if (contents.indexOf(evil) !== -1) { 383 | return contents.replace(evil, 'var curves = require(\'./curves.json\')') 384 | } 385 | } 386 | }, 387 | { 388 | name: 'assert', 389 | regex: [ 390 | /assert\/assert.js$/ 391 | ], 392 | hack: function (file, contents) { 393 | if (isInReactNative(file)) return 394 | 395 | var evil = 'var util = require(\'util/\');' 396 | if (contents.indexOf(evil) !== -1) { 397 | return contents.replace(evil, 'var util = require(\'util\');') 398 | } 399 | } 400 | }, 401 | // { 402 | // name: 'net', 403 | // regex: [ 404 | // /bittorrent-swarm\/package\.json$/, 405 | // /portfinder\/package\.json$/ 406 | // ], 407 | // hack: function (file, contents) { 408 | // var pkg 409 | // try { 410 | // pkg = JSON.parse(contents) 411 | // } catch (err) { 412 | // console.log('failed to parse:', file) 413 | // return 414 | // } 415 | 416 | // rewireMain(pkg) 417 | // if (pkg.browser.net !== 'utp') { 418 | // pkg.browser.net = 'utp' 419 | // return prettify(pkg) 420 | // } 421 | // } 422 | // }, 423 | { 424 | name: 'bytewise', 425 | regex: [ 426 | /bytewise\/bytewise\.js$/ 427 | ], 428 | hack: function (file, contents) { 429 | if (isInReactNative(file)) return 430 | 431 | var fixed = contents 432 | fixed = fixed.replace("require('typewise')", "null") 433 | return contents === fixed ? null : fixed 434 | } 435 | }, 436 | { 437 | name: 'unzip-response', 438 | regex: [ 439 | /unzip\-response\/index\.js$/ 440 | ], 441 | hack: function (file, contents) { 442 | if (isInReactNative(file)) return 443 | 444 | var hack = ';res.headers = res.headers || {};' 445 | if (contents.indexOf(hack) !== -1) return 446 | 447 | var orig = "if (['gzip', 'deflate'].indexOf(res.headers['content-encoding']) !== -1) {" 448 | return contents.replace( 449 | orig, 450 | hack + orig 451 | ) 452 | } 453 | }, 454 | { 455 | name: 'rn-packager', 456 | regex: [ 457 | /DependencyResolver\/Package\.js/ 458 | ], 459 | hack: function (file, contents) { 460 | // var hack = body(function () { 461 | /* 462 | if (!browser[name]) return name 463 | 464 | // HACK! 465 | name = browser[name] 466 | if (name[0] === '.') { 467 | return '.' + name 468 | } 469 | 470 | return name 471 | */ 472 | // }) 473 | 474 | var fixed = contents 475 | // fixed = fixed.replace('return browser[name] || name', hack) 476 | // fixed = fixed.replace("this._cache.get(this.path, 'haste'", "this._cache.get(this.path, 'package-haste'") 477 | fixed = fixed.replace("this._cache.get(this.path, 'name'", "this._cache.get(this.path, 'package-name'") 478 | return fixed === contents ? null : fixed 479 | } 480 | }, 481 | { 482 | name: 'crypto-browserify', 483 | regex: [ 484 | /\/crypto-browserify\/rng\.js$/ 485 | ], 486 | hack: function (file, contents) { 487 | // var hack = body(function () { 488 | 489 | // // react-native-hack 490 | // var _crypto = { 491 | // randomBytes: function (size) { 492 | // console.warn('WARNING: using insecure random number') 493 | // return Math.random() * size 494 | // } 495 | // } 496 | 497 | // }) 498 | 499 | var hack = body(function () { 500 | /* 501 | // react-native-hack 502 | try { 503 | var _crypto = ( 504 | g.crypto || g.msCrypto || require('crypto') 505 | ) 506 | } catch (err) { 507 | _crypto = {} 508 | } 509 | */ 510 | }) 511 | 512 | if (contents.indexOf('react-native-hack') !== -1) return 513 | 514 | return contents.replace(/_crypto\s+=\s+\(\s+g\.crypto\s+\|\|\s+g.msCrypto\s+\|\|\s+require\('crypto'\)\s+\)/, hack) 515 | } 516 | }, 517 | { 518 | name: 'version', 519 | regex: [/pbkdf2/], 520 | hack: function (file, contents) { 521 | if (isInReactNative(file)) return 522 | 523 | var fixed = contents 524 | .replace(/global\.process\.version/g, '"' + process.version + '"') 525 | .replace(/process\.version/g, '"' + process.version + '"') 526 | 527 | return contents === fixed ? null : fixed 528 | } 529 | }, 530 | ] 531 | 532 | function rewireMain (pkg) { 533 | if (typeof pkg.browser === 'string') { 534 | var main = pkg.browser || './index.js' 535 | pkg.browser = {} 536 | pkg.browser[pkg.main] = main 537 | } else if (typeof pkg.browser === 'undefined') { 538 | pkg.browser = {} 539 | } 540 | } 541 | 542 | function rethrow (err) { 543 | if (err) throw err 544 | } 545 | 546 | function body (fn) { 547 | return fn.toString().split(/\n/).slice(2, -2).join('\n').trim() 548 | } 549 | 550 | function prettify (json) { 551 | return JSON.stringify(json, null, 2) + '\n' 552 | } 553 | 554 | function isInReactNative (file) { 555 | return /\/react\-native\//.test(file) 556 | } 557 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # rn-nodeify 2 | 3 | Run after npm install and you can use node core modules and npm modules that use them in your React Native app. 4 | 5 | ## What is solves 6 | 7 | If your project has no non-React-Native dependencies, you don't need this module, and you should just check out ['./shims.js'](./shims.js) for the core node modules to use individually. 8 | 9 | However, with bigger projects that don't reimplement every wheel from scratch, somewhere in your dependency tree, something uses a core node module. I found myself building this because in my React Native app, I wanted to use [bitcoinjs-lib](https://github.com/bitcoinjs/bitcoinjs-lib), [levelup](https://github.com/Level/levelup), [bittorrent-dht](https://github.com/feross/bittorrent-dht), and lots of fun crypto. If that sounds like you, keep reading. 10 | 11 | ## What it does 12 | 13 | `rn-nodeify --install` 14 | installs shims for core node modules, see ['./shims.js'](./shims.js) for the current mappings. It recurses down `node_modules` and modifies all the `package.json`'s in there to add/update the `browser` and `react-native` fields. It sounds scary because it is. However, it does work. 15 | 16 | `rn-nodeify --hack` 17 | Now that you're scared, I should also mention that there are some package-specific hacks (see ['./pkg-hacks.js'](./pkg-hacks.js)), for when the React Native packager choked on something that Webpack and Browserify swallowed. 18 | 19 | If you're looking for a saner approach, check out [ReactNativify](https://github.com/philikon/ReactNativify). I haven't tested it myself, but I think [philikon](https://github.com/philikon) will be happy to help. 20 | 21 | ## Usage 22 | 23 | ```bash 24 | rn-nodeify 25 | ``` 26 | 27 | ## Options 28 | 29 | ``` 30 | --install install node core shims (default: install all), fix the "browser" 31 | and "react-native" fields in the package.json's of dependencies 32 | --hack hack individual packages that are known to make the React Native packager choke 33 | --yarn use yarn instead of npm 34 | ``` 35 | 36 | ### Examples 37 | 38 | ```bash 39 | # install all shims and run package-specific hacks 40 | rn-nodeify --install --hack 41 | ``` 42 | 43 | ```bash 44 | # install specific shims 45 | rn-nodeify --install "fs,dgram,process,path,console" 46 | ``` 47 | 48 | ```bash 49 | # install specific shims and hack 50 | rn-nodeify --install "fs,dgram,process,path,console" --hack 51 | ``` 52 | 53 | It is recommended to add this command to the "postinstall" script in your project's package.json 54 | 55 | ```json 56 | "scripts": { 57 | "start": "node node_modules/react-native/local-cli/cli.js start", 58 | "postinstall": "rn-nodeify --install fs,dgram,process,path,console --hack" 59 | } 60 | ``` 61 | 62 | rn-nodeify will create a `shim.js` file in your project root directory. The first line in index.ios.js / index.android.js should be to `import` it (NOT `require` it!) 63 | 64 | ```js 65 | import './shim' 66 | ``` 67 | 68 | If you are using the crypto shim, you will need to manually uncomment the line to `require('crypto')` in `shim.js`, this is because as of react-native 0.49, dynamically requiring a library is no longer allowed. 69 | 70 | Some shims may require linking libraries, be sure to run `react-native link` after installing new shims if you run into problems. 71 | 72 | ### Example Apps / Workflows 73 | 74 | * the [react-native-crypto](https://github.com/tradle/react-native-crypto) package has an example workflow for using crypto in a React Native app 75 | * this [example React Native app](https://github.com/mvayngrib/adexample) shows how you can use [levelup](https://github.com/Level/levelup) in React Native 76 | 77 | ### Example Workflow 78 | 79 | copied from [react-native-crypto](https://github.com/tradle/react-native-crypto) 80 | 81 | 1. Install and shim 82 | ```sh 83 | npm i --save react-native-crypto 84 | # install peer deps 85 | npm i --save react-native-randombytes 86 | react-native link react-native-randombytes 87 | # install latest rn-nodeify 88 | npm i --save-dev rn-nodeify@latest 89 | # install node core shims and recursively hack package.json files 90 | # in ./node_modules to add/update the "browser"/"react-native" field with relevant mappings 91 | ./node_modules/.bin/rn-nodeify --hack --install 92 | ``` 93 | 94 | 2. `rn-nodeify` will create a `shim.js` in the project root directory 95 | ```js 96 | // index.ios.js or index.android.js 97 | // make sure you use `import` and not `require`! 98 | import './shim.js' 99 | // ...the rest of your code 100 | import crypto from 'crypto' 101 | // use crypto 102 | console.log(crypto.randomBytes(32).toString('hex')) 103 | ``` 104 | 105 | ## Please note... 106 | 107 | - rn-nodeify won't work with modules that are added using `npm link`. 108 | - modules that contain a .babelrc will cause problems with the latest react-native version (0.20 at this time), remove them after installation (`rm node_modules/*/.babelrc`) 109 | - when installing a package from git, the postinstall hook isn't triggered, run it manually instead (`npm run postinstall`) 110 | - restart the react-native packager after installing a module! 111 | - removing the packager cache helps as well sometimes (`rm -fr $TMPDIR/react-*`) 112 | - use `npm@3`. `npm@5` has some issues that cause `node_modules` to disappear. See: 113 | - https://github.com/tradle/rn-nodeify/issues/42 114 | - https://github.com/infinitered/ignite/issues/1101 115 | - https://github.com/npm/npm/issues/16839 116 | -------------------------------------------------------------------------------- /shim.js: -------------------------------------------------------------------------------- 1 | if (typeof __dirname === 'undefined') global.__dirname = '/' 2 | if (typeof __filename === 'undefined') global.__filename = '' 3 | if (typeof process === 'undefined') { 4 | global.process = require('process') 5 | } else { 6 | const bProcess = require('process') 7 | for (var p in bProcess) { 8 | if (!(p in process)) { 9 | process[p] = bProcess[p] 10 | } 11 | } 12 | } 13 | 14 | process.browser = false 15 | if (typeof Buffer === 'undefined') global.Buffer = require('buffer').Buffer 16 | 17 | // global.location = global.location || { port: 80 } 18 | const isDev = typeof __DEV__ === 'boolean' && __DEV__ 19 | process.env['NODE_ENV'] = isDev ? 'development' : 'production' 20 | if (typeof localStorage !== 'undefined') { 21 | localStorage.debug = isDev ? '*' : '' 22 | } 23 | 24 | // If using the crypto shim, uncomment the following line to ensure 25 | // crypto is loaded first, so it can populate global.crypto 26 | // require('crypto') 27 | -------------------------------------------------------------------------------- /shims-browserify.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | "assert": "~1.3.0", 3 | "browserify-zlib": "~0.1.2", 4 | "buffer": "^3.0.0", 5 | "inherits": "~2.0.1", 6 | "console-browserify": "^1.1.0", 7 | "constants-browserify": "^1.0.0", 8 | "crypto-browserify": "~3.2.6", 9 | "dns.js": "^1.0.1", 10 | "domain-browser": "~1.1.0", 11 | "events": "~1.0.0", 12 | "stream-http": "^1.2.0", 13 | "https-browserify": "~0.0.0", 14 | "os-browserify": "~0.1.1", 15 | "path-browserify": "~0.0.0", 16 | "process": "~0.11.0", 17 | "punycode": "^1.3.2", 18 | "querystring-es3": "~0.2.0", 19 | "react-native-level-fs": "^3.0.0", 20 | "react-native-udp": "0.0.12", 21 | // "readable-stream": "~1.0.33-1", 22 | "readable-stream": "^2.0.2", 23 | "stream-browserify": "^2.0.0", 24 | "string_decoder": "~0.10.0", 25 | "timers-browserify": "^1.0.1", 26 | "tty-browserify": "~0.0.0", 27 | "url": "~0.10.1", 28 | "util": "~0.10.1", 29 | "utp": "0.0.8", 30 | "react-native-tcp": "^3.2.1", 31 | "vm-browserify": "~0.0.1" 32 | } 33 | -------------------------------------------------------------------------------- /shims.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | "assert": "^1.1.1", 3 | "browserify-zlib": "~0.1.4", 4 | "buffer": "^4.9.1", 5 | "inherits": "^2.0.1", 6 | "console-browserify": "^1.1.0", 7 | "constants-browserify": "^1.0.0", 8 | "react-native-crypto": "^2.1.0", 9 | "react-native-randombytes": "^3.0.0", 10 | "dns.js": "^1.0.1", 11 | "domain-browser": "^1.1.1", 12 | "events": "^1.0.0", 13 | "@tradle/react-native-http": "^2.0.0", 14 | "https-browserify": "~0.0.0", 15 | "react-native-os": "^1.0.1", 16 | "path-browserify": "0.0.0", 17 | "process": "^0.11.0", 18 | "punycode": "^1.2.4", 19 | "querystring-es3": "~0.2.0", 20 | "react-native-level-fs": "^3.0.0", 21 | "react-native-udp": "^2.1.0", 22 | "readable-stream": "1.0.33", 23 | // "stream-browserify": "substack/stream-browserify#fa56e68", 24 | "stream-browserify": "^1.0.0", 25 | "string_decoder": "~0.10.25", 26 | "timers-browserify": "^1.0.1", 27 | "tty-browserify": "0.0.0", 28 | "url": "~0.10.1", 29 | "util": "~0.10.3", 30 | "react-native-tcp": "^3.2.1", 31 | "vm-browserify": "0.0.4" 32 | } 33 | -------------------------------------------------------------------------------- /test/index.js: -------------------------------------------------------------------------------- 1 | var test = require('tape') 2 | 3 | test('dummy test', function (t) { 4 | t.end() 5 | }) --------------------------------------------------------------------------------