commit 74396f8426644b7ab4a28958914c4d10101e1648 Author: tdzl2003 Date: Sun Feb 14 00:04:42 2016 +0800 working diff --git a/index.js b/index.js new file mode 100644 index 0000000..2786548 --- /dev/null +++ b/index.js @@ -0,0 +1,11 @@ +/** + * Created by tdzl2003 on 2/6/16. + */ + +if (__DEV__){ + if (global.__fbBatchedBridge) { + require('fbjs/lib/warning')('Should require pushy before react-native to do hook stuff!'); + } +} + +require('./lib/hooks'); diff --git a/lib/hooks.js b/lib/hooks.js new file mode 100644 index 0000000..269cec0 --- /dev/null +++ b/lib/hooks.js @@ -0,0 +1,8 @@ +/** + * Created by tdzl2003 on 2/6/16. + */ + +// Hook resolvedAssetSource +__d('resolveAssetSource', function(_1, _2, module, _3) { + module.exports = require('./resolveAssetSource'); +}); diff --git a/lib/resolveAssetSource.js b/lib/resolveAssetSource.js new file mode 100644 index 0000000..f308228 --- /dev/null +++ b/lib/resolveAssetSource.js @@ -0,0 +1,146 @@ +/** + * Copyright (c) 2015-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + * @providesModule resolveAssetSource + * @flow + * + * Resolves an asset into a `source` for `Image`. + * + * Hooked by @tdzl2003 for react-native-pushy + */ +'use strict'; + +var AssetRegistry = require('react-native/Libraries/Image/AssetRegistry'); +var PixelRatio = require('react-native/Libraries/Utilities/PixelRatio'); +var Platform = require('react-native/Libraries/Utilities/Platform'); +var NativeModules = require('react-native/Libraries/BatchedBridge/BatchedBridgedModules/NativeModules.js'); +var SourceCode = NativeModules.SourceCode; + +var _serverURL, _offlinePath; + +function getDevServerURL() { + if (_serverURL === undefined) { + var scriptURL = SourceCode.scriptURL; + var match = scriptURL && scriptURL.match(/^https?:\/\/.*?\//); + if (match) { + // Bundle was loaded from network + _serverURL = match[0]; + } else { + // Bundle was loaded from file + _serverURL = null; + } + } + + return _serverURL; +} + +function getOfflinePath() { + if (_offlinePath === undefined) { + var scriptURL = SourceCode.scriptURL; + var match = scriptURL && scriptURL.match(/^file:\/\/(\/.*\/)/); + if (match) { + _offlinePath = match[1]; + } else { + _offlinePath = ''; + } + } + + return _offlinePath; +} + +/** + * Returns the path at which the asset can be found in the archive + */ +function getPathInArchive(asset) { + if (Platform.OS === 'android') { + var assetDir = getBasePath(asset); + // E.g. 'assets_awesomemodule_icon' + // The Android resource system picks the correct scale. + return (assetDir + '/' + asset.name) + .toLowerCase() + .replace(/\//g, '_') // Encode folder structure in file name + .replace(/([^a-z0-9_])/g, '') // Remove illegal chars + .replace(/^assets_/, ''); // Remove "assets_" prefix + } else { + // E.g. 'assets/AwesomeModule/icon@2x.png' + return getOfflinePath() + getScaledAssetPath(asset); + } +} + +/** + * Returns an absolute URL which can be used to fetch the asset + * from the devserver + */ +function getPathOnDevserver(devServerUrl, asset) { + return devServerUrl + getScaledAssetPath(asset) + '?platform=' + Platform.OS + + '&hash=' + asset.hash; +} + +/** + * Returns a path like 'assets/AwesomeModule' + */ +function getBasePath(asset) { + // TODO(frantic): currently httpServerLocation is used both as + // path in http URL and path within IPA. Should we have zipArchiveLocation? + var path = asset.httpServerLocation; + if (path[0] === '/') { + path = path.substr(1); + } + return path; +} + +/** + * Returns a path like 'assets/AwesomeModule/icon@2x.png' + */ +function getScaledAssetPath(asset) { + var scale = pickScale(asset.scales, PixelRatio.get()); + var scaleSuffix = scale === 1 ? '' : '@' + scale + 'x'; + var assetDir = getBasePath(asset); + return assetDir + '/' + asset.name + scaleSuffix + '.' + asset.type; +} + +function pickScale(scales, deviceScale) { + // Packager guarantees that `scales` array is sorted + for (var i = 0; i < scales.length; i++) { + if (scales[i] >= deviceScale) { + return scales[i]; + } + } + + // If nothing matches, device scale is larger than any available + // scales, so we return the biggest one. Unless the array is empty, + // in which case we default to 1 + return scales[scales.length - 1] || 1; +} + +function resolveAssetSource(source){ + if (typeof source === 'object') { + return source; + } + + var asset = AssetRegistry.getAssetByID(source); + if (asset) { + return assetToImageSource(asset); + } + + return null; +} + +function assetToImageSource(asset){ + var devServerURL = getDevServerURL(); + return { + __packager_asset: true, + width: asset.width, + height: asset.height, + uri: devServerURL ? getPathOnDevserver(devServerURL, asset) : getPathInArchive(asset), + scale: pickScale(asset.scales, PixelRatio.get()), + }; +} + +module.exports = resolveAssetSource; +module.exports.pickScale = pickScale; diff --git a/local-cli/api.js b/local-cli/api.js new file mode 100644 index 0000000..589c8f1 --- /dev/null +++ b/local-cli/api.js @@ -0,0 +1,55 @@ +/** + * Created by tdzl2003 on 2/13/16. + */ + +const fetch = require('isomorphic-fetch'); +const host = process.env.PUSHY_REGISTRY || 'http://pushy.reactnative.cn'; +const fs = require('fs-promise'); + +let session = undefined; +let fileSession = undefined; + +exports.loadSession = async function() { + if (await fs.exists('.pushy')) { + try { + session = JSON.parse(await fs.readFile('.pushy', 'utf8')); + } catch (e) { + console.error('Failed to parse file `.pushy`. Try to remove it manually.'); + throw e; + } + } +} + +exports.getSession = function(){ + return session; +} + +exports.replaceSession = function(newSession) { + session = newSession; +} + +exports.saveSession = async function(){ + // Only save on change. + if (session != fileSession) { + const current = session; + const data = JSON.stringify(current, null, 4); + await fs.writeFile('.pushy', data, 'utf8'); + fileSession = current; + } +} + +function queryWithBody(method){ + return async function(api, body) { + const resp = await fetch(host + api, { + method: 'post', + headers: { + 'Content-Type': 'application/json', + 'X-AccessToken': session ? session.token : '', + }, + body: JSON.stringify(body), + }); + } +} + +exports.post = queryWithBody('POST'); +exports.put = queryWithBody('PUT'); diff --git a/local-cli/cli.json b/local-cli/cli.json new file mode 100644 index 0000000..97e849e --- /dev/null +++ b/local-cli/cli.json @@ -0,0 +1,18 @@ +{ + "useCommand": true, + "defaultCommand": "help", + "commands": { + "login":{ + "options": { + "username": { + + } + } + }, + "help": { + + } + }, + "globalOptions":{ + } +} \ No newline at end of file diff --git a/local-cli/index.js b/local-cli/index.js new file mode 100644 index 0000000..af06da3 --- /dev/null +++ b/local-cli/index.js @@ -0,0 +1,24 @@ +/** + * Created by tdzl2003 on 2/13/16. + */ + +const userCommands = require('./user').commands; + +function printUsage({args}) { + // const commandName = args[0]; + // TODO: print usage of commandName, or print global usage. + + console.log('Usage is under development now.') + console.log('Visit `https://github.com/reactnativecn/react-native-pushy` for early document.'); + process.exit(1); +} + +const commands = { + ...userCommands, + help: printUsage, +}; + +exports.run = function () { + const argv = require('cli-arguments').parse(require('./cli.json')); + commands[argv.command](argv).catch(err=>console.error(err.stack)); +}; diff --git a/local-cli/user.js b/local-cli/user.js new file mode 100644 index 0000000..ba8cd74 --- /dev/null +++ b/local-cli/user.js @@ -0,0 +1,13 @@ +/** + * Created by tdzl2003 on 2/13/16. + */ + +const {question} = require('./utils'); + +exports.commands = { + login: async function ({args}){ + const username = args[0] || await question('user:'); + const password = args[1] || await question('password:', true); + + } +} \ No newline at end of file diff --git a/local-cli/utils.js b/local-cli/utils.js new file mode 100644 index 0000000..3992247 --- /dev/null +++ b/local-cli/utils.js @@ -0,0 +1,13 @@ +/** + * Created by tdzl2003 on 2/13/16. + */ + +var read = require('read'); + +exports.question = function(query, password) { + return new Promise((resolve, reject)=>read({ + prompt: query, + silent: password, + replace: password ? '*' : undefined, + }, (err, result)=> err ? reject(err) : resolve(result))); +} \ No newline at end of file diff --git a/react-native-pushy-cli/cli.js b/react-native-pushy-cli/cli.js new file mode 100755 index 0000000..365dbad --- /dev/null +++ b/react-native-pushy-cli/cli.js @@ -0,0 +1,63 @@ +#!/usr/bin/env node +/** + * Created by tdzl2003 on 2/13/16. + */ + +var path = require('path'); +var fs = require('fs'); + + +var CLI_MODULE_PATH = function() { + return path.resolve( + process.cwd(), + 'node_modules', + 'react-native-pushy', + 'local-cli' + ); +}; + +var PACKAGE_JSON_PATH = function() { + return path.resolve( + process.cwd(), + 'node_modules', + 'react-native-pushy', + 'package.json' + ); +}; + +checkForVersionCommand(); + +require('babel-register')({ + 'plugins': [ + 'transform-async-to-generator', + 'transform-strict-mode', + 'transform-object-rest-spread', + 'transform-es2015-parameters', + 'transform-es2015-destructuring', + ], +}); + +var cli; +var cliPath = CLI_MODULE_PATH(); +if (fs.existsSync(cliPath)) { + cli = require(cliPath); +} + +if (cli) { + cli.run(); +} else { + console.error('`pushy install` is under development, please run `npm install react-native-pushy` to install pushy manually.'); + process.exit(1); +} + +function checkForVersionCommand() { + if (process.argv.indexOf('-v') >= 0 || process.argv[2] === 'version') { + console.log('react-native-pushy-cli: ' + require('./package.json').version); + try { + console.log('react-native-pushy: ' + require(PACKAGE_JSON_PATH()).version); + } catch (e) { + console.log('react-native-pushy: n/a - not inside a React Native project directory') + } + process.exit(); + } +} diff --git a/react-native-pushy-cli/package.json b/react-native-pushy-cli/package.json new file mode 100644 index 0000000..be831ba --- /dev/null +++ b/react-native-pushy-cli/package.json @@ -0,0 +1,31 @@ +{ + "name": "react-native-pushy-cli", + "version": "0.1.0", + "description": "Command tools for javaScript updater with `pushy` service for react native apps.", + "main": "index.js", + "bin": { + "pushy": "cli.js" + }, + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/reactnativecn/react-native-pushy.git" + }, + "keywords": [ + "react-native", + "ios", + "android", + "update" + ], + "author": "reactnativecn", + "license": "BSD-3-Clause", + "bugs": { + "url": "https://github.com/reactnativecn/react-native-pushy/issues" + }, + "homepage": "https://github.com/reactnativecn/react-native-pushy/tree/master/react-native-pushy-cli", + "dependencies": { + "babel-register": "^6.5.2" + } +}