Get new tree with state verified with current React Native on both platforms
This commit is contained in:
parent
8c93833942
commit
c5fd23b54f
|
@ -0,0 +1,23 @@
|
||||||
|
import React from 'react';
|
||||||
|
import { StyleSheet, Text, View } from 'react-native';
|
||||||
|
|
||||||
|
export default class App extends React.Component {
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<View style={styles.container}>
|
||||||
|
<Text>Open up App.js to start working on your app!</Text>
|
||||||
|
<Text>Changes you make will automatically reload.</Text>
|
||||||
|
<Text>Shake your phone to open the developer menu.</Text>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const styles = StyleSheet.create({
|
||||||
|
container: {
|
||||||
|
flex: 1,
|
||||||
|
backgroundColor: '#fff',
|
||||||
|
alignItems: 'center',
|
||||||
|
justifyContent: 'center',
|
||||||
|
},
|
||||||
|
});
|
|
@ -0,0 +1,9 @@
|
||||||
|
import React from 'react';
|
||||||
|
import App from './App';
|
||||||
|
|
||||||
|
import renderer from 'react-test-renderer';
|
||||||
|
|
||||||
|
it('renders without crashing', () => {
|
||||||
|
const rendered = renderer.create(<App />).toJSON();
|
||||||
|
expect(rendered).toBeTruthy();
|
||||||
|
});
|
|
@ -0,0 +1,220 @@
|
||||||
|
This project was bootstrapped with [Create React Native App](https://github.com/react-community/create-react-native-app).
|
||||||
|
|
||||||
|
Below you'll find information about performing common tasks. The most recent version of this guide is available [here](https://github.com/react-community/create-react-native-app/blob/master/react-native-scripts/template/README.md).
|
||||||
|
|
||||||
|
## Table of Contents
|
||||||
|
|
||||||
|
* [Updating to New Releases](#updating-to-new-releases)
|
||||||
|
* [Available Scripts](#available-scripts)
|
||||||
|
* [npm start](#npm-start)
|
||||||
|
* [npm test](#npm-test)
|
||||||
|
* [npm run ios](#npm-run-ios)
|
||||||
|
* [npm run android](#npm-run-android)
|
||||||
|
* [npm run eject](#npm-run-eject)
|
||||||
|
* [Writing and Running Tests](#writing-and-running-tests)
|
||||||
|
* [Environment Variables](#environment-variables)
|
||||||
|
* [Configuring Packager IP Address](#configuring-packager-ip-address)
|
||||||
|
* [Adding Flow](#adding-flow)
|
||||||
|
* [Customizing App Display Name and Icon](#customizing-app-display-name-and-icon)
|
||||||
|
* [Sharing and Deployment](#sharing-and-deployment)
|
||||||
|
* [Publishing to Expo's React Native Community](#publishing-to-expos-react-native-community)
|
||||||
|
* [Building an Expo "standalone" app](#building-an-expo-standalone-app)
|
||||||
|
* [Ejecting from Create React Native App](#ejecting-from-create-react-native-app)
|
||||||
|
* [Build Dependencies (Xcode & Android Studio)](#build-dependencies-xcode-android-studio)
|
||||||
|
* [Should I Use ExpoKit?](#should-i-use-expokit)
|
||||||
|
* [Troubleshooting](#troubleshooting)
|
||||||
|
* [Networking](#networking)
|
||||||
|
* [iOS Simulator won't open](#ios-simulator-wont-open)
|
||||||
|
* [QR Code does not scan](#qr-code-does-not-scan)
|
||||||
|
|
||||||
|
## Updating to New Releases
|
||||||
|
|
||||||
|
You should only need to update the global installation of `create-react-native-app` very rarely, ideally never.
|
||||||
|
|
||||||
|
Updating the `react-native-scripts` dependency of your app should be as simple as bumping the version number in `package.json` and reinstalling your project's dependencies.
|
||||||
|
|
||||||
|
Upgrading to a new version of React Native requires updating the `react-native`, `react`, and `expo` package versions, and setting the correct `sdkVersion` in `app.json`. See the [versioning guide](https://github.com/react-community/create-react-native-app/blob/master/VERSIONS.md) for up-to-date information about package version compatibility.
|
||||||
|
|
||||||
|
## Available Scripts
|
||||||
|
|
||||||
|
If Yarn was installed when the project was initialized, then dependencies will have been installed via Yarn, and you should probably use it to run these commands as well. Unlike dependency installation, command running syntax is identical for Yarn and NPM at the time of this writing.
|
||||||
|
|
||||||
|
### `npm start`
|
||||||
|
|
||||||
|
Runs your app in development mode.
|
||||||
|
|
||||||
|
Open it in the [Expo app](https://expo.io) on your phone to view it. It will reload if you save edits to your files, and you will see build errors and logs in the terminal.
|
||||||
|
|
||||||
|
Sometimes you may need to reset or clear the React Native packager's cache. To do so, you can pass the `--reset-cache` flag to the start script:
|
||||||
|
|
||||||
|
```
|
||||||
|
npm start -- --reset-cache
|
||||||
|
# or
|
||||||
|
yarn start -- --reset-cache
|
||||||
|
```
|
||||||
|
|
||||||
|
#### `npm test`
|
||||||
|
|
||||||
|
Runs the [jest](https://github.com/facebook/jest) test runner on your tests.
|
||||||
|
|
||||||
|
#### `npm run ios`
|
||||||
|
|
||||||
|
Like `npm start`, but also attempts to open your app in the iOS Simulator if you're on a Mac and have it installed.
|
||||||
|
|
||||||
|
#### `npm run android`
|
||||||
|
|
||||||
|
Like `npm start`, but also attempts to open your app on a connected Android device or emulator. Requires an installation of Android build tools (see [React Native docs](https://facebook.github.io/react-native/docs/getting-started.html) for detailed setup). We also recommend installing Genymotion as your Android emulator. Once you've finished setting up the native build environment, there are two options for making the right copy of `adb` available to Create React Native App:
|
||||||
|
|
||||||
|
##### Using Android Studio's `adb`
|
||||||
|
|
||||||
|
1. Make sure that you can run adb from your terminal.
|
||||||
|
2. Open Genymotion and navigate to `Settings -> ADB`. Select “Use custom Android SDK tools” and update with your [Android SDK directory](https://stackoverflow.com/questions/25176594/android-sdk-location).
|
||||||
|
|
||||||
|
##### Using Genymotion's `adb`
|
||||||
|
|
||||||
|
1. Find Genymotion’s copy of adb. On macOS for example, this is normally `/Applications/Genymotion.app/Contents/MacOS/tools/`.
|
||||||
|
2. Add the Genymotion tools directory to your path (instructions for [Mac](http://osxdaily.com/2014/08/14/add-new-path-to-path-command-line/), [Linux](http://www.computerhope.com/issues/ch001647.htm), and [Windows](https://www.howtogeek.com/118594/how-to-edit-your-system-path-for-easy-command-line-access/)).
|
||||||
|
3. Make sure that you can run adb from your terminal.
|
||||||
|
|
||||||
|
#### `npm run eject`
|
||||||
|
|
||||||
|
This will start the process of "ejecting" from Create React Native App's build scripts. You'll be asked a couple of questions about how you'd like to build your project.
|
||||||
|
|
||||||
|
**Warning:** Running eject is a permanent action (aside from whatever version control system you use). An ejected app will require you to have an [Xcode and/or Android Studio environment](https://facebook.github.io/react-native/docs/getting-started.html) set up.
|
||||||
|
|
||||||
|
## Customizing App Display Name and Icon
|
||||||
|
|
||||||
|
You can edit `app.json` to include [configuration keys](https://docs.expo.io/versions/latest/guides/configuration.html) under the `expo` key.
|
||||||
|
|
||||||
|
To change your app's display name, set the `expo.name` key in `app.json` to an appropriate string.
|
||||||
|
|
||||||
|
To set an app icon, set the `expo.icon` key in `app.json` to be either a local path or a URL. It's recommended that you use a 512x512 png file with transparency.
|
||||||
|
|
||||||
|
## Writing and Running Tests
|
||||||
|
|
||||||
|
This project is set up to use [jest](https://facebook.github.io/jest/) for tests. You can configure whatever testing strategy you like, but jest works out of the box. Create test files in directories called `__tests__` or with the `.test` extension to have the files loaded by jest. See the [the template project](https://github.com/react-community/create-react-native-app/blob/master/react-native-scripts/template/App.test.js) for an example test. The [jest documentation](https://facebook.github.io/jest/docs/en/getting-started.html) is also a wonderful resource, as is the [React Native testing tutorial](https://facebook.github.io/jest/docs/en/tutorial-react-native.html).
|
||||||
|
|
||||||
|
## Environment Variables
|
||||||
|
|
||||||
|
You can configure some of Create React Native App's behavior using environment variables.
|
||||||
|
|
||||||
|
### Configuring Packager IP Address
|
||||||
|
|
||||||
|
When starting your project, you'll see something like this for your project URL:
|
||||||
|
|
||||||
|
```
|
||||||
|
exp://192.168.0.2:19000
|
||||||
|
```
|
||||||
|
|
||||||
|
The "manifest" at that URL tells the Expo app how to retrieve and load your app's JavaScript bundle, so even if you load it in the app via a URL like `exp://localhost:19000`, the Expo client app will still try to retrieve your app at the IP address that the start script provides.
|
||||||
|
|
||||||
|
In some cases, this is less than ideal. This might be the case if you need to run your project inside of a virtual machine and you have to access the packager via a different IP address than the one which prints by default. In order to override the IP address or hostname that is detected by Create React Native App, you can specify your own hostname via the `REACT_NATIVE_PACKAGER_HOSTNAME` environment variable:
|
||||||
|
|
||||||
|
Mac and Linux:
|
||||||
|
|
||||||
|
```
|
||||||
|
REACT_NATIVE_PACKAGER_HOSTNAME='my-custom-ip-address-or-hostname' npm start
|
||||||
|
```
|
||||||
|
|
||||||
|
Windows:
|
||||||
|
```
|
||||||
|
set REACT_NATIVE_PACKAGER_HOSTNAME='my-custom-ip-address-or-hostname'
|
||||||
|
npm start
|
||||||
|
```
|
||||||
|
|
||||||
|
The above example would cause the development server to listen on `exp://my-custom-ip-address-or-hostname:19000`.
|
||||||
|
|
||||||
|
## Adding Flow
|
||||||
|
|
||||||
|
Flow is a static type checker that helps you write code with fewer bugs. Check out this [introduction to using static types in JavaScript](https://medium.com/@preethikasireddy/why-use-static-types-in-javascript-part-1-8382da1e0adb) if you are new to this concept.
|
||||||
|
|
||||||
|
React Native works with [Flow](http://flowtype.org/) out of the box, as long as your Flow version matches the one used in the version of React Native.
|
||||||
|
|
||||||
|
To add a local dependency to the correct Flow version to a Create React Native App project, follow these steps:
|
||||||
|
|
||||||
|
1. Find the Flow `[version]` at the bottom of the included [.flowconfig](.flowconfig)
|
||||||
|
2. Run `npm install --save-dev flow-bin@x.y.z` (or `yarn add --dev flow-bin@x.y.z`), where `x.y.z` is the .flowconfig version number.
|
||||||
|
3. Add `"flow": "flow"` to the `scripts` section of your `package.json`.
|
||||||
|
4. Add `// @flow` to any files you want to type check (for example, to `App.js`).
|
||||||
|
|
||||||
|
Now you can run `npm run flow` (or `yarn flow`) to check the files for type errors.
|
||||||
|
You can optionally use a [plugin for your IDE or editor](https://flow.org/en/docs/editors/) for a better integrated experience.
|
||||||
|
|
||||||
|
To learn more about Flow, check out [its documentation](https://flow.org/).
|
||||||
|
|
||||||
|
## Sharing and Deployment
|
||||||
|
|
||||||
|
Create React Native App does a lot of work to make app setup and development simple and straightforward, but it's very difficult to do the same for deploying to Apple's App Store or Google's Play Store without relying on a hosted service.
|
||||||
|
|
||||||
|
### Publishing to Expo's React Native Community
|
||||||
|
|
||||||
|
Expo provides free hosting for the JS-only apps created by CRNA, allowing you to share your app through the Expo client app. This requires registration for an Expo account.
|
||||||
|
|
||||||
|
Install the `exp` command-line tool, and run the publish command:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ npm i -g exp
|
||||||
|
$ exp publish
|
||||||
|
```
|
||||||
|
|
||||||
|
### Building an Expo "standalone" app
|
||||||
|
|
||||||
|
You can also use a service like [Expo's standalone builds](https://docs.expo.io/versions/latest/guides/building-standalone-apps.html) if you want to get an IPA/APK for distribution without having to build the native code yourself.
|
||||||
|
|
||||||
|
### Ejecting from Create React Native App
|
||||||
|
|
||||||
|
If you want to build and deploy your app yourself, you'll need to eject from CRNA and use Xcode and Android Studio.
|
||||||
|
|
||||||
|
This is usually as simple as running `npm run eject` in your project, which will walk you through the process. Make sure to install `react-native-cli` and follow the [native code getting started guide for React Native](https://facebook.github.io/react-native/docs/getting-started.html).
|
||||||
|
|
||||||
|
#### Should I Use ExpoKit?
|
||||||
|
|
||||||
|
If you have made use of Expo APIs while working on your project, then those API calls will stop working if you eject to a regular React Native project. If you want to continue using those APIs, you can eject to "React Native + ExpoKit" which will still allow you to build your own native code and continue using the Expo APIs. See the [ejecting guide](https://github.com/react-community/create-react-native-app/blob/master/EJECTING.md) for more details about this option.
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
### Networking
|
||||||
|
|
||||||
|
If you're unable to load your app on your phone due to a network timeout or a refused connection, a good first step is to verify that your phone and computer are on the same network and that they can reach each other. Create React Native App needs access to ports 19000 and 19001 so ensure that your network and firewall settings allow access from your device to your computer on both of these ports.
|
||||||
|
|
||||||
|
Try opening a web browser on your phone and opening the URL that the packager script prints, replacing `exp://` with `http://`. So, for example, if underneath the QR code in your terminal you see:
|
||||||
|
|
||||||
|
```
|
||||||
|
exp://192.168.0.1:19000
|
||||||
|
```
|
||||||
|
|
||||||
|
Try opening Safari or Chrome on your phone and loading
|
||||||
|
|
||||||
|
```
|
||||||
|
http://192.168.0.1:19000
|
||||||
|
```
|
||||||
|
|
||||||
|
and
|
||||||
|
|
||||||
|
```
|
||||||
|
http://192.168.0.1:19001
|
||||||
|
```
|
||||||
|
|
||||||
|
If this works, but you're still unable to load your app by scanning the QR code, please open an issue on the [Create React Native App repository](https://github.com/react-community/create-react-native-app) with details about these steps and any other error messages you may have received.
|
||||||
|
|
||||||
|
If you're not able to load the `http` URL in your phone's web browser, try using the tethering/mobile hotspot feature on your phone (beware of data usage, though), connecting your computer to that WiFi network, and restarting the packager.
|
||||||
|
|
||||||
|
### iOS Simulator won't open
|
||||||
|
|
||||||
|
If you're on a Mac, there are a few errors that users sometimes see when attempting to `npm run ios`:
|
||||||
|
|
||||||
|
* "non-zero exit code: 107"
|
||||||
|
* "You may need to install Xcode" but it is already installed
|
||||||
|
* and others
|
||||||
|
|
||||||
|
There are a few steps you may want to take to troubleshoot these kinds of errors:
|
||||||
|
|
||||||
|
1. Make sure Xcode is installed and open it to accept the license agreement if it prompts you. You can install it from the Mac App Store.
|
||||||
|
2. Open Xcode's Preferences, the Locations tab, and make sure that the `Command Line Tools` menu option is set to something. Sometimes when the CLI tools are first installed by Homebrew this option is left blank, which can prevent Apple utilities from finding the simulator. Make sure to re-run `npm/yarn run ios` after doing so.
|
||||||
|
3. If that doesn't work, open the Simulator, and under the app menu select `Reset Contents and Settings...`. After that has finished, quit the Simulator, and re-run `npm/yarn run ios`.
|
||||||
|
|
||||||
|
### QR Code does not scan
|
||||||
|
|
||||||
|
If you're not able to scan the QR code, make sure your phone's camera is focusing correctly, and also make sure that the contrast on the two colors in your terminal is high enough. For example, WebStorm's default themes may [not have enough contrast](https://github.com/react-community/create-react-native-app/issues/49) for terminal QR codes to be scannable with the system barcode scanners that the Expo app uses.
|
||||||
|
|
||||||
|
If this causes problems for you, you may want to try changing your terminal's color theme to have more contrast, or running Create React Native App from a different terminal. You can also manually enter the URL printed by the packager script in the Expo app's search bar to load it manually.
|
|
@ -0,0 +1,5 @@
|
||||||
|
{
|
||||||
|
"expo": {
|
||||||
|
"sdkVersion": "25.0.0"
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1 @@
|
||||||
|
../acorn/bin/acorn
|
|
@ -0,0 +1 @@
|
||||||
|
../analytics-node/bin/analytics
|
|
@ -0,0 +1 @@
|
||||||
|
../babylon/bin/babylon.js
|
|
@ -0,0 +1 @@
|
||||||
|
../@expo/bunyan/bin/bunyan
|
|
@ -0,0 +1 @@
|
||||||
|
../color-support/bin.js
|
|
@ -0,0 +1 @@
|
||||||
|
../decompress-zip/bin/decompress-zip
|
|
@ -0,0 +1 @@
|
||||||
|
../envinfo/src/cli.js
|
|
@ -0,0 +1 @@
|
||||||
|
../escodegen/bin/escodegen.js
|
|
@ -0,0 +1 @@
|
||||||
|
../escodegen/bin/esgenerate.js
|
|
@ -0,0 +1 @@
|
||||||
|
../esprima/bin/esparse.js
|
|
@ -0,0 +1 @@
|
||||||
|
../esprima/bin/esvalidate.js
|
|
@ -0,0 +1 @@
|
||||||
|
../react-native-vector-icons/bin/generate-icon.js
|
|
@ -0,0 +1 @@
|
||||||
|
../handlebars/bin/handlebars
|
|
@ -0,0 +1 @@
|
||||||
|
../image-size/bin/image-size.js
|
|
@ -0,0 +1 @@
|
||||||
|
../import-local/fixtures/cli.js
|
|
@ -0,0 +1 @@
|
||||||
|
../is-ci/bin.js
|
|
@ -0,0 +1 @@
|
||||||
|
../jest/bin/jest.js
|
|
@ -0,0 +1 @@
|
||||||
|
../jest-runtime/bin/jest-runtime.js
|
|
@ -0,0 +1 @@
|
||||||
|
../js-yaml/bin/js-yaml.js
|
|
@ -0,0 +1 @@
|
||||||
|
../jsesc/bin/jsesc
|
|
@ -0,0 +1 @@
|
||||||
|
../json5/lib/cli.js
|
|
@ -0,0 +1 @@
|
||||||
|
../logfmt/bin/logfmt
|
|
@ -0,0 +1 @@
|
||||||
|
../loose-envify/cli.js
|
|
@ -0,0 +1 @@
|
||||||
|
../md5-file/cli.js
|
|
@ -0,0 +1 @@
|
||||||
|
../metro/src/cli.js
|
|
@ -0,0 +1 @@
|
||||||
|
../mime/cli.js
|
|
@ -0,0 +1 @@
|
||||||
|
../mkdirp/bin/cmd.js
|
|
@ -0,0 +1 @@
|
||||||
|
../ncp/bin/ncp
|
|
@ -0,0 +1 @@
|
||||||
|
../@expo/ngrok/bin/ngrok
|
|
@ -0,0 +1 @@
|
||||||
|
../nopt/bin/nopt.js
|
|
@ -0,0 +1 @@
|
||||||
|
../pegjs/bin/pegjs
|
|
@ -0,0 +1 @@
|
||||||
|
../qrcode-terminal/bin/qrcode-terminal.js
|
|
@ -0,0 +1 @@
|
||||||
|
../raven/bin/raven
|
|
@ -0,0 +1 @@
|
||||||
|
../react-native/local-cli/wrong-react-native.js
|
|
@ -0,0 +1 @@
|
||||||
|
../react-native-scripts/build/bin/react-native-scripts.js
|
|
@ -0,0 +1 @@
|
||||||
|
../regjsparser/bin/parser
|
|
@ -0,0 +1 @@
|
||||||
|
../rimraf/bin.js
|
|
@ -0,0 +1 @@
|
||||||
|
../sane/src/cli.js
|
|
@ -0,0 +1 @@
|
||||||
|
../semver/bin/semver
|
|
@ -0,0 +1 @@
|
||||||
|
../sshpk/bin/sshpk-conv
|
|
@ -0,0 +1 @@
|
||||||
|
../sshpk/bin/sshpk-sign
|
|
@ -0,0 +1 @@
|
||||||
|
../sshpk/bin/sshpk-verify
|
|
@ -0,0 +1 @@
|
||||||
|
../tree-kill/cli.js
|
|
@ -0,0 +1 @@
|
||||||
|
../uglify-es/bin/uglifyjs
|
|
@ -0,0 +1 @@
|
||||||
|
../uuid/bin/uuid
|
|
@ -0,0 +1 @@
|
||||||
|
../watch/cli.js
|
|
@ -0,0 +1 @@
|
||||||
|
../which/bin/which
|
|
@ -0,0 +1,142 @@
|
||||||
|
# @babel/code-frame
|
||||||
|
|
||||||
|
> Generate errors that contain a code frame that point to source locations.
|
||||||
|
|
||||||
|
## Install
|
||||||
|
|
||||||
|
```sh
|
||||||
|
npm install --save-dev @babel/code-frame
|
||||||
|
```
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
```js
|
||||||
|
import { codeFrameColumns } from '@babel/code-frame';
|
||||||
|
|
||||||
|
const rawLines = `class Foo {
|
||||||
|
constructor()
|
||||||
|
}`;
|
||||||
|
const location = { start: { line: 2, column: 16 } };
|
||||||
|
|
||||||
|
const result = codeFrameColumns(rawLines, location, { /* options */ });
|
||||||
|
|
||||||
|
console.log(result);
|
||||||
|
```
|
||||||
|
|
||||||
|
```
|
||||||
|
1 | class Foo {
|
||||||
|
> 2 | constructor()
|
||||||
|
| ^
|
||||||
|
3 | }
|
||||||
|
```
|
||||||
|
|
||||||
|
If the column number is not known, you may omit it.
|
||||||
|
|
||||||
|
You can also pass an `end` hash in `location`.
|
||||||
|
|
||||||
|
```js
|
||||||
|
import { codeFrameColumns } from '@babel/code-frame';
|
||||||
|
|
||||||
|
const rawLines = `class Foo {
|
||||||
|
constructor() {
|
||||||
|
console.log("hello");
|
||||||
|
}
|
||||||
|
}`;
|
||||||
|
const location = { start: { line: 2, column: 17 }, end: { line: 4, column: 3 } };
|
||||||
|
|
||||||
|
const result = codeFrameColumns(rawLines, location, { /* options */ });
|
||||||
|
|
||||||
|
console.log(result);
|
||||||
|
```
|
||||||
|
|
||||||
|
```
|
||||||
|
1 | class Foo {
|
||||||
|
> 2 | constructor() {
|
||||||
|
| ^
|
||||||
|
> 3 | console.log("hello");
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
> 4 | }
|
||||||
|
| ^^^
|
||||||
|
5 | };
|
||||||
|
```
|
||||||
|
|
||||||
|
## Options
|
||||||
|
|
||||||
|
### `highlightCode`
|
||||||
|
|
||||||
|
`boolean`, defaults to `false`.
|
||||||
|
|
||||||
|
Toggles syntax highlighting the code as JavaScript for terminals.
|
||||||
|
|
||||||
|
|
||||||
|
### `linesAbove`
|
||||||
|
|
||||||
|
`number`, defaults to `2`.
|
||||||
|
|
||||||
|
Adjust the number of lines to show above the error.
|
||||||
|
|
||||||
|
### `linesBelow`
|
||||||
|
|
||||||
|
`number`, defaults to `3`.
|
||||||
|
|
||||||
|
Adjust the number of lines to show below the error.
|
||||||
|
|
||||||
|
### `forceColor`
|
||||||
|
|
||||||
|
`boolean`, defaults to `false`.
|
||||||
|
|
||||||
|
Enable this to forcibly syntax highlight the code as JavaScript (for non-terminals); overrides `highlightCode`.
|
||||||
|
|
||||||
|
### `message`
|
||||||
|
|
||||||
|
`string`, otherwise nothing
|
||||||
|
|
||||||
|
Pass in a string to be displayed inline (if possible) next to the highlighted
|
||||||
|
location in the code. If it can't be positioned inline, it will be placed above
|
||||||
|
the code frame.
|
||||||
|
|
||||||
|
```
|
||||||
|
1 | class Foo {
|
||||||
|
> 2 | constructor()
|
||||||
|
| ^ Missing {
|
||||||
|
3 | };
|
||||||
|
```
|
||||||
|
|
||||||
|
## Upgrading from prior versions
|
||||||
|
|
||||||
|
Prior to version 7, the only API exposed by this module was for a single line and optional column pointer. The old API will now log a deprecation warning.
|
||||||
|
|
||||||
|
The new API takes a `location` object, similar to what is available in an AST.
|
||||||
|
|
||||||
|
This is an example of the deprecated (but still available) API:
|
||||||
|
|
||||||
|
```js
|
||||||
|
import codeFrame from '@babel/code-frame';
|
||||||
|
|
||||||
|
const rawLines = `class Foo {
|
||||||
|
constructor()
|
||||||
|
}`;
|
||||||
|
const lineNumber = 2;
|
||||||
|
const colNumber = 16;
|
||||||
|
|
||||||
|
const result = codeFrame(rawLines, lineNumber, colNumber, { /* options */ });
|
||||||
|
|
||||||
|
console.log(result);
|
||||||
|
```
|
||||||
|
|
||||||
|
To get the same highlighting using the new API:
|
||||||
|
|
||||||
|
```js
|
||||||
|
import { codeFrameColumns } from '@babel/code-frame';
|
||||||
|
|
||||||
|
const rawLines = `class Foo {
|
||||||
|
constructor() {
|
||||||
|
console.log("hello");
|
||||||
|
}
|
||||||
|
}`;
|
||||||
|
const location = { start: { line: 2, column: 16 } };
|
||||||
|
|
||||||
|
const result = codeFrameColumns(rawLines, location, { /* options */ });
|
||||||
|
|
||||||
|
console.log(result);
|
||||||
|
```
|
|
@ -0,0 +1,244 @@
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
exports.__esModule = true;
|
||||||
|
exports.codeFrameColumns = codeFrameColumns;
|
||||||
|
exports.default = _default;
|
||||||
|
|
||||||
|
var _jsTokens = _interopRequireWildcard(require("js-tokens"));
|
||||||
|
|
||||||
|
var _esutils = _interopRequireDefault(require("esutils"));
|
||||||
|
|
||||||
|
var _chalk = _interopRequireDefault(require("chalk"));
|
||||||
|
|
||||||
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
||||||
|
|
||||||
|
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } }
|
||||||
|
|
||||||
|
var deprecationWarningShown = false;
|
||||||
|
|
||||||
|
function getDefs(chalk) {
|
||||||
|
return {
|
||||||
|
keyword: chalk.cyan,
|
||||||
|
capitalized: chalk.yellow,
|
||||||
|
jsx_tag: chalk.yellow,
|
||||||
|
punctuator: chalk.yellow,
|
||||||
|
number: chalk.magenta,
|
||||||
|
string: chalk.green,
|
||||||
|
regex: chalk.magenta,
|
||||||
|
comment: chalk.grey,
|
||||||
|
invalid: chalk.white.bgRed.bold,
|
||||||
|
gutter: chalk.grey,
|
||||||
|
marker: chalk.red.bold,
|
||||||
|
message: chalk.red.bold
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
var NEWLINE = /\r\n|[\n\r\u2028\u2029]/;
|
||||||
|
var JSX_TAG = /^[a-z][\w-]*$/i;
|
||||||
|
var BRACKET = /^[()[\]{}]$/;
|
||||||
|
|
||||||
|
function getTokenType(match) {
|
||||||
|
var _match$slice = match.slice(-2),
|
||||||
|
offset = _match$slice[0],
|
||||||
|
text = _match$slice[1];
|
||||||
|
|
||||||
|
var token = (0, _jsTokens.matchToToken)(match);
|
||||||
|
|
||||||
|
if (token.type === "name") {
|
||||||
|
if (_esutils.default.keyword.isReservedWordES6(token.value)) {
|
||||||
|
return "keyword";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (JSX_TAG.test(token.value) && (text[offset - 1] === "<" || text.substr(offset - 2, 2) == "</")) {
|
||||||
|
return "jsx_tag";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (token.value[0] !== token.value[0].toLowerCase()) {
|
||||||
|
return "capitalized";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (token.type === "punctuator" && BRACKET.test(token.value)) {
|
||||||
|
return "bracket";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (token.type === "invalid" && (token.value === "@" || token.value === "#")) {
|
||||||
|
return "punctuator";
|
||||||
|
}
|
||||||
|
|
||||||
|
return token.type;
|
||||||
|
}
|
||||||
|
|
||||||
|
function highlight(defs, text) {
|
||||||
|
return text.replace(_jsTokens.default, function () {
|
||||||
|
for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
|
||||||
|
args[_key] = arguments[_key];
|
||||||
|
}
|
||||||
|
|
||||||
|
var type = getTokenType(args);
|
||||||
|
var colorize = defs[type];
|
||||||
|
|
||||||
|
if (colorize) {
|
||||||
|
return args[0].split(NEWLINE).map(function (str) {
|
||||||
|
return colorize(str);
|
||||||
|
}).join("\n");
|
||||||
|
} else {
|
||||||
|
return args[0];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function getMarkerLines(loc, source, opts) {
|
||||||
|
var startLoc = Object.assign({}, {
|
||||||
|
column: 0,
|
||||||
|
line: -1
|
||||||
|
}, loc.start);
|
||||||
|
var endLoc = Object.assign({}, startLoc, loc.end);
|
||||||
|
var linesAbove = opts.linesAbove || 2;
|
||||||
|
var linesBelow = opts.linesBelow || 3;
|
||||||
|
var startLine = startLoc.line;
|
||||||
|
var startColumn = startLoc.column;
|
||||||
|
var endLine = endLoc.line;
|
||||||
|
var endColumn = endLoc.column;
|
||||||
|
var start = Math.max(startLine - (linesAbove + 1), 0);
|
||||||
|
var end = Math.min(source.length, endLine + linesBelow);
|
||||||
|
|
||||||
|
if (startLine === -1) {
|
||||||
|
start = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (endLine === -1) {
|
||||||
|
end = source.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
var lineDiff = endLine - startLine;
|
||||||
|
var markerLines = {};
|
||||||
|
|
||||||
|
if (lineDiff) {
|
||||||
|
for (var i = 0; i <= lineDiff; i++) {
|
||||||
|
var lineNumber = i + startLine;
|
||||||
|
|
||||||
|
if (!startColumn) {
|
||||||
|
markerLines[lineNumber] = true;
|
||||||
|
} else if (i === 0) {
|
||||||
|
var sourceLength = source[lineNumber - 1].length;
|
||||||
|
markerLines[lineNumber] = [startColumn, sourceLength - startColumn];
|
||||||
|
} else if (i === lineDiff) {
|
||||||
|
markerLines[lineNumber] = [0, endColumn];
|
||||||
|
} else {
|
||||||
|
var _sourceLength = source[lineNumber - i].length;
|
||||||
|
markerLines[lineNumber] = [0, _sourceLength];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (startColumn === endColumn) {
|
||||||
|
if (startColumn) {
|
||||||
|
markerLines[startLine] = [startColumn, 0];
|
||||||
|
} else {
|
||||||
|
markerLines[startLine] = true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
markerLines[startLine] = [startColumn, endColumn - startColumn];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
start: start,
|
||||||
|
end: end,
|
||||||
|
markerLines: markerLines
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function codeFrameColumns(rawLines, loc, opts) {
|
||||||
|
if (opts === void 0) {
|
||||||
|
opts = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
var highlighted = opts.highlightCode && _chalk.default.supportsColor || opts.forceColor;
|
||||||
|
var chalk = _chalk.default;
|
||||||
|
|
||||||
|
if (opts.forceColor) {
|
||||||
|
chalk = new _chalk.default.constructor({
|
||||||
|
enabled: true,
|
||||||
|
level: 1
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
var maybeHighlight = function maybeHighlight(chalkFn, string) {
|
||||||
|
return highlighted ? chalkFn(string) : string;
|
||||||
|
};
|
||||||
|
|
||||||
|
var defs = getDefs(chalk);
|
||||||
|
if (highlighted) rawLines = highlight(defs, rawLines);
|
||||||
|
var lines = rawLines.split(NEWLINE);
|
||||||
|
|
||||||
|
var _getMarkerLines = getMarkerLines(loc, lines, opts),
|
||||||
|
start = _getMarkerLines.start,
|
||||||
|
end = _getMarkerLines.end,
|
||||||
|
markerLines = _getMarkerLines.markerLines;
|
||||||
|
|
||||||
|
var hasColumns = loc.start && typeof loc.start.column === "number";
|
||||||
|
var numberMaxWidth = String(end).length;
|
||||||
|
var frame = lines.slice(start, end).map(function (line, index) {
|
||||||
|
var number = start + 1 + index;
|
||||||
|
var paddedNumber = (" " + number).slice(-numberMaxWidth);
|
||||||
|
var gutter = " " + paddedNumber + " | ";
|
||||||
|
var hasMarker = markerLines[number];
|
||||||
|
var lastMarkerLine = !markerLines[number + 1];
|
||||||
|
|
||||||
|
if (hasMarker) {
|
||||||
|
var markerLine = "";
|
||||||
|
|
||||||
|
if (Array.isArray(hasMarker)) {
|
||||||
|
var markerSpacing = line.slice(0, Math.max(hasMarker[0] - 1, 0)).replace(/[^\t]/g, " ");
|
||||||
|
var numberOfMarkers = hasMarker[1] || 1;
|
||||||
|
markerLine = ["\n ", maybeHighlight(defs.gutter, gutter.replace(/\d/g, " ")), markerSpacing, maybeHighlight(defs.marker, "^").repeat(numberOfMarkers)].join("");
|
||||||
|
|
||||||
|
if (lastMarkerLine && opts.message) {
|
||||||
|
markerLine += " " + maybeHighlight(defs.message, opts.message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return [maybeHighlight(defs.marker, ">"), maybeHighlight(defs.gutter, gutter), line, markerLine].join("");
|
||||||
|
} else {
|
||||||
|
return " " + maybeHighlight(defs.gutter, gutter) + line;
|
||||||
|
}
|
||||||
|
}).join("\n");
|
||||||
|
|
||||||
|
if (opts.message && !hasColumns) {
|
||||||
|
frame = "" + " ".repeat(numberMaxWidth + 1) + opts.message + "\n" + frame;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (highlighted) {
|
||||||
|
return chalk.reset(frame);
|
||||||
|
} else {
|
||||||
|
return frame;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function _default(rawLines, lineNumber, colNumber, opts) {
|
||||||
|
if (opts === void 0) {
|
||||||
|
opts = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!deprecationWarningShown) {
|
||||||
|
deprecationWarningShown = true;
|
||||||
|
var deprecationError = new Error("Passing lineNumber and colNumber is deprecated to @babel/code-frame. Please use `codeFrameColumns`.");
|
||||||
|
deprecationError.name = "DeprecationWarning";
|
||||||
|
|
||||||
|
if (process.emitWarning) {
|
||||||
|
process.emitWarning(deprecationError);
|
||||||
|
} else {
|
||||||
|
console.warn(deprecationError);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
colNumber = Math.max(colNumber, 0);
|
||||||
|
var location = {
|
||||||
|
start: {
|
||||||
|
column: colNumber,
|
||||||
|
line: lineNumber
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return codeFrameColumns(rawLines, location, opts);
|
||||||
|
}
|
|
@ -0,0 +1,105 @@
|
||||||
|
{
|
||||||
|
"_args": [
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"raw": "@babel/code-frame@^7.0.0-beta.35",
|
||||||
|
"scope": "@babel",
|
||||||
|
"escapedName": "@babel%2fcode-frame",
|
||||||
|
"name": "@babel/code-frame",
|
||||||
|
"rawSpec": "^7.0.0-beta.35",
|
||||||
|
"spec": ">=7.0.0-beta.35 <8.0.0",
|
||||||
|
"type": "range"
|
||||||
|
},
|
||||||
|
"/home/jdaugherty/work/GT2/GT2-Android/node_modules/jest-message-util"
|
||||||
|
]
|
||||||
|
],
|
||||||
|
"_from": "@babel/code-frame@>=7.0.0-beta.35 <8.0.0",
|
||||||
|
"_id": "@babel/code-frame@7.0.0-beta.39",
|
||||||
|
"_inCache": true,
|
||||||
|
"_location": "/@babel/code-frame",
|
||||||
|
"_nodeVersion": "8.9.1",
|
||||||
|
"_npmOperationalInternal": {
|
||||||
|
"host": "s3://npm-registry-packages",
|
||||||
|
"tmp": "tmp/code-frame-7.0.0-beta.39.tgz_1517344042108_0.45995172555558383"
|
||||||
|
},
|
||||||
|
"_npmUser": {
|
||||||
|
"name": "hzoo",
|
||||||
|
"email": "hi@henryzoo.com"
|
||||||
|
},
|
||||||
|
"_npmVersion": "5.6.0",
|
||||||
|
"_phantomChildren": {},
|
||||||
|
"_requested": {
|
||||||
|
"raw": "@babel/code-frame@^7.0.0-beta.35",
|
||||||
|
"scope": "@babel",
|
||||||
|
"escapedName": "@babel%2fcode-frame",
|
||||||
|
"name": "@babel/code-frame",
|
||||||
|
"rawSpec": "^7.0.0-beta.35",
|
||||||
|
"spec": ">=7.0.0-beta.35 <8.0.0",
|
||||||
|
"type": "range"
|
||||||
|
},
|
||||||
|
"_requiredBy": [
|
||||||
|
"/jest-message-util"
|
||||||
|
],
|
||||||
|
"_resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.0.0-beta.39.tgz",
|
||||||
|
"_shasum": "91c90bb65207fc5a55128cb54956ded39e850457",
|
||||||
|
"_shrinkwrap": null,
|
||||||
|
"_spec": "@babel/code-frame@^7.0.0-beta.35",
|
||||||
|
"_where": "/home/jdaugherty/work/GT2/GT2-Android/node_modules/jest-message-util",
|
||||||
|
"author": {
|
||||||
|
"name": "Sebastian McKenzie",
|
||||||
|
"email": "sebmck@gmail.com"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"chalk": "^2.0.0",
|
||||||
|
"esutils": "^2.0.2",
|
||||||
|
"js-tokens": "^3.0.0"
|
||||||
|
},
|
||||||
|
"description": "Generate errors that contain a code frame that point to source locations.",
|
||||||
|
"devDependencies": {
|
||||||
|
"strip-ansi": "^4.0.0"
|
||||||
|
},
|
||||||
|
"directories": {},
|
||||||
|
"dist": {
|
||||||
|
"integrity": "sha512-PConL+YIK9BgNUWWC2q4fbltj1g475TofpNVNivSypcAAKElfpSS1cv7MrpLYRG8TzZvwcVu9M30hLA/WAp1HQ==",
|
||||||
|
"shasum": "91c90bb65207fc5a55128cb54956ded39e850457",
|
||||||
|
"tarball": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.0.0-beta.39.tgz"
|
||||||
|
},
|
||||||
|
"homepage": "https://babeljs.io/",
|
||||||
|
"license": "MIT",
|
||||||
|
"main": "lib/index.js",
|
||||||
|
"maintainers": [
|
||||||
|
{
|
||||||
|
"name": "andarist",
|
||||||
|
"email": "mateuszburzynski@gmail.com"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "xtuc",
|
||||||
|
"email": "contact@xtuc.fr"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "existentialism",
|
||||||
|
"email": "bng412@gmail.com"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "danez",
|
||||||
|
"email": "daniel@tschinder.de"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "loganfsmyth",
|
||||||
|
"email": "loganfsmyth@gmail.com"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "hzoo",
|
||||||
|
"email": "hi@henryzoo.com"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "@babel/code-frame",
|
||||||
|
"optionalDependencies": {},
|
||||||
|
"readme": "# @babel/code-frame\n\n> Generate errors that contain a code frame that point to source locations.\n\n## Install\n\n```sh\nnpm install --save-dev @babel/code-frame\n```\n\n## Usage\n\n```js\nimport { codeFrameColumns } from '@babel/code-frame';\n\nconst rawLines = `class Foo {\n constructor()\n}`;\nconst location = { start: { line: 2, column: 16 } };\n\nconst result = codeFrameColumns(rawLines, location, { /* options */ });\n\nconsole.log(result);\n```\n\n```\n 1 | class Foo {\n> 2 | constructor()\n | ^\n 3 | }\n```\n\nIf the column number is not known, you may omit it.\n\nYou can also pass an `end` hash in `location`.\n\n```js\nimport { codeFrameColumns } from '@babel/code-frame';\n\nconst rawLines = `class Foo {\n constructor() {\n console.log(\"hello\");\n }\n}`;\nconst location = { start: { line: 2, column: 17 }, end: { line: 4, column: 3 } };\n\nconst result = codeFrameColumns(rawLines, location, { /* options */ });\n\nconsole.log(result);\n```\n\n```\n 1 | class Foo {\n> 2 | constructor() {\n | ^\n> 3 | console.log(\"hello\");\n | ^^^^^^^^^^^^^^^^^^^^^^^^^\n> 4 | }\n | ^^^\n 5 | };\n```\n\n## Options\n\n### `highlightCode`\n\n`boolean`, defaults to `false`.\n\nToggles syntax highlighting the code as JavaScript for terminals.\n\n\n### `linesAbove`\n\n`number`, defaults to `2`.\n\nAdjust the number of lines to show above the error.\n\n### `linesBelow`\n\n`number`, defaults to `3`.\n\nAdjust the number of lines to show below the error.\n\n### `forceColor`\n\n`boolean`, defaults to `false`.\n\nEnable this to forcibly syntax highlight the code as JavaScript (for non-terminals); overrides `highlightCode`.\n\n### `message`\n\n`string`, otherwise nothing\n\nPass in a string to be displayed inline (if possible) next to the highlighted\nlocation in the code. If it can't be positioned inline, it will be placed above\nthe code frame.\n\n```\n1 | class Foo {\n> 2 | constructor()\n | ^ Missing {\n3 | };\n```\n\n## Upgrading from prior versions\n\nPrior to version 7, the only API exposed by this module was for a single line and optional column pointer. The old API will now log a deprecation warning.\n\nThe new API takes a `location` object, similar to what is available in an AST.\n\nThis is an example of the deprecated (but still available) API:\n\n```js\nimport codeFrame from '@babel/code-frame';\n\nconst rawLines = `class Foo {\n constructor()\n}`;\nconst lineNumber = 2;\nconst colNumber = 16;\n\nconst result = codeFrame(rawLines, lineNumber, colNumber, { /* options */ });\n\nconsole.log(result);\n```\n\nTo get the same highlighting using the new API:\n\n```js\nimport { codeFrameColumns } from '@babel/code-frame';\n\nconst rawLines = `class Foo {\n constructor() {\n console.log(\"hello\");\n }\n}`;\nconst location = { start: { line: 2, column: 16 } };\n\nconst result = codeFrameColumns(rawLines, location, { /* options */ });\n\nconsole.log(result);\n```\n",
|
||||||
|
"readmeFilename": "README.md",
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/babel/babel/tree/master/packages/babel-code-frame"
|
||||||
|
},
|
||||||
|
"version": "7.0.0-beta.39"
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
/tmp
|
||||||
|
/node_modules
|
||||||
|
*.log
|
||||||
|
/examples
|
||||||
|
/test
|
||||||
|
/*.tgz
|
||||||
|
/tools
|
|
@ -0,0 +1,23 @@
|
||||||
|
language: node_js
|
||||||
|
|
||||||
|
os:
|
||||||
|
- linux
|
||||||
|
- osx
|
||||||
|
|
||||||
|
env:
|
||||||
|
- SKIP_DTRACE=1
|
||||||
|
|
||||||
|
node_js:
|
||||||
|
- '0.10'
|
||||||
|
- '0.12'
|
||||||
|
- '4'
|
||||||
|
- '5'
|
||||||
|
- '6'
|
||||||
|
- 'node'
|
||||||
|
|
||||||
|
|
||||||
|
# Gives us faster boot time, see https://docs.travis-ci.com/user/ci-environment/
|
||||||
|
sudo: false
|
||||||
|
|
||||||
|
script:
|
||||||
|
- npm test
|
|
@ -0,0 +1,42 @@
|
||||||
|
Trent Mick (http://trentm.com)
|
||||||
|
Mark Cavage (https://github.com/mcavage)
|
||||||
|
Dave Pacheco (https://github.com/davepacheco)
|
||||||
|
Michael Hart (https://github.com/mhart)
|
||||||
|
Isaac Schlueter (https://github.com/isaacs)
|
||||||
|
Rob Gulewich (https://github.com/rgulewich)
|
||||||
|
Bryan Cantrill (https://github.com/bcantrill)
|
||||||
|
Michael Hart (https://github.com/mhart)
|
||||||
|
Simon Wade (https://github.com/aexmachina)
|
||||||
|
https://github.com/glenn-murray-bse
|
||||||
|
Chakrit Wichian (https://github.com/chakrit)
|
||||||
|
Patrick Mooney (https://github.com/pfmooney)
|
||||||
|
Johan Nordberg (https://github.com/jnordberg)
|
||||||
|
https://github.com/timborodin
|
||||||
|
Ryan Graham (https://github.com/rmg)
|
||||||
|
Alex Kocharin (https://github.com/rlidwka)
|
||||||
|
Andrei Neculau (https://github.com/andreineculau)
|
||||||
|
Mihai Tomescu (https://github.com/matomesc)
|
||||||
|
Daniel Juhl (https://github.com/danieljuhl)
|
||||||
|
Chris Barber (https://github.com/cb1kenobi)
|
||||||
|
Manuel Schneider (https://github.com/manuelschneider)
|
||||||
|
Martin Gausby (https://github.com/gausby)
|
||||||
|
Stéphan Kochen (https://github.com/stephank)
|
||||||
|
Shakeel Mohamed (https://github.com/shakeelmohamed)
|
||||||
|
Denis Izmaylov (https://github.com/DenisIzmaylov)
|
||||||
|
Guillermo Grau Panea (https://github.com/guigrpa)
|
||||||
|
Mark LeMerise (https://github.com/MarkLeMerise)
|
||||||
|
https://github.com/sometimesalready
|
||||||
|
Charly Koza (https://github.com/Cactusbone)
|
||||||
|
Thomas Heymann (https://github.com/cyberthom)
|
||||||
|
David M. Lee (https://github.com/leedm777)
|
||||||
|
Marc Udoff (https://github.com/mlucool)
|
||||||
|
Mark Stosberg (https://github.com/markstos)
|
||||||
|
Alexander Ray (https://github.com/aray12)
|
||||||
|
Adam Lynch (https://github.com/adam-lynch)
|
||||||
|
Michael Nisi (https://github.com/michaelnisi)
|
||||||
|
Martijn Schrage (https://github.com/Oblosys)
|
||||||
|
Paul Milham (https://github.com/domrein)
|
||||||
|
Frankie O'Rourke (https://github.com/psfrankie)
|
||||||
|
Cody Mello (https://github.com/melloc)
|
||||||
|
Todd Whiteman (https://github.com/twhiteman)
|
||||||
|
Zach Bjornson (https://github.com/zbjornson)
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,205 @@
|
||||||
|
# Contributing to node-bunyan
|
||||||
|
|
||||||
|
Thanks for using node-bunyan and for considering contributing to it! Or perhaps
|
||||||
|
you are just here to get a sniff for what is going on with node-bunyan
|
||||||
|
development.
|
||||||
|
|
||||||
|
|
||||||
|
## How you can help
|
||||||
|
|
||||||
|
If you want to help me here, great! Thank you! Some ideas:
|
||||||
|
|
||||||
|
- Do you have experience with and/or recommendations for a good automated
|
||||||
|
testing service? Ideally I'd like support for Mac, Linux, SmartOS, and maybe
|
||||||
|
Windows. Also, support for node.js versions 0.10 up to whatever the current
|
||||||
|
latest is. Are those too tall an order? What's more, Bunyan is meant to work
|
||||||
|
(at least partially) in the browser. Is there a good service for that?
|
||||||
|
Please discuss on [issue #342](https://github.com/trentm/node-bunyan/issues/342).
|
||||||
|
|
||||||
|
- Fielding issues labelled with "[Type-Question][Type-Question]", if you are familiar
|
||||||
|
with Bunyan and know how to answer them, would be great.
|
||||||
|
|
||||||
|
- If you want to dive into code, but aren't *that* familiar with node-bunyan,
|
||||||
|
then [issues labelled with Experience-Easy][Experience-Easy] are a good
|
||||||
|
place to start.
|
||||||
|
|
||||||
|
- [Once I've made a once over
|
||||||
|
triaging](https://github.com/trentm/node-bunyan/issues/335) and consolodating
|
||||||
|
issues and PRs, volunteering for issues in a particular
|
||||||
|
[component](#component) with which you have familiarity would be great.
|
||||||
|
|
||||||
|
[Type-Question]: https://github.com/trentm/node-bunyan/issues?q=is%3Aopen+is%3Aissue+label%3AType-Question
|
||||||
|
|
||||||
|
|
||||||
|
## Trent's Biased Rules for Code
|
||||||
|
|
||||||
|
In the hope that it makes it easier to get PRs into Bunyan, here is my biased
|
||||||
|
list of what I typically want. Submitting a PR without all of these is
|
||||||
|
*totally fine*! The only side-effect is that it may take longer for me to
|
||||||
|
provide feedback on it and merge it. I'll politely request missing pieces.
|
||||||
|
|
||||||
|
|
||||||
|
- Please follow existing code style. Contributed code must pass `make check`.
|
||||||
|
(Note: I intended to [change to eslint
|
||||||
|
soon](https://github.com/trentm/node-bunyan/issues/341), so currently `make
|
||||||
|
check` might be a moving target.)
|
||||||
|
|
||||||
|
- Any user visible change in behaviour should almost certainly include an
|
||||||
|
update to the docs. Currently the "docs" is the README.md.
|
||||||
|
|
||||||
|
- Adding a test case for code changes is **stronly recommended**, else I
|
||||||
|
can't easily promise to not break your fix/feature later. If you don't
|
||||||
|
grok the test suite, please ask. We can use it to form the basis for a
|
||||||
|
"test/README.md".
|
||||||
|
|
||||||
|
- Typically a code change should have an associated issue or PR. This allows
|
||||||
|
addition of follow-up issues, discussion, test data, etc. to be associated
|
||||||
|
with the commit. Just using GitHub pull requests makes this easy.
|
||||||
|
|
||||||
|
- All but the most trivial code changes should have an addition to the
|
||||||
|
[changelog](./CHANGES.md). The audience for the changelog is *Bunyan users*.
|
||||||
|
However, because rebasing longer-lived PRs against master is a pain
|
||||||
|
with a change to CHANGES.md, please **do not include a CHANGES.md change
|
||||||
|
in your PR. Instead suggest a CHANGES.md addition in a comment on the
|
||||||
|
PR.**
|
||||||
|
|
||||||
|
- Good commit messages, please:
|
||||||
|
- The first line should be a succinct summary of the issue or fix. A
|
||||||
|
good candidate is to just cut 'n paste the issue title, if there is one.
|
||||||
|
- If the commit is for a particular issue/PR (see previous rule), please
|
||||||
|
list the issue number in the commit message. E.g. "Fixes #123" or "Related
|
||||||
|
to #234".
|
||||||
|
- The audience for commit messages is *Bunyan developers*.
|
||||||
|
|
||||||
|
|
||||||
|
## Pull Request Lifecycle
|
||||||
|
|
||||||
|
(Language adapted from
|
||||||
|
[terraform](https://github.com/hashicorp/terraform/blob/master/CONTRIBUTING.md).)
|
||||||
|
|
||||||
|
- You are welcome to submit your pull request for commentary or review before it
|
||||||
|
is fully completed. Please prefix the title of your pull request with "[WIP]"
|
||||||
|
to indicate this. It's also a good idea to include specific questions or items
|
||||||
|
you'd like feedback on.
|
||||||
|
|
||||||
|
- Once you believe your pull request is ready to be merged, you can remove any
|
||||||
|
"[WIP]" prefix from the title and a core team member will review. See
|
||||||
|
Trent's Biased Rules above to help ensure that your contribution will be
|
||||||
|
merged quickly.
|
||||||
|
|
||||||
|
- Trent or, if things go well, a node-bunyan maintainer will look over your
|
||||||
|
contribution and either provide comments letting you know if there is anything
|
||||||
|
left to do. Please be patient. Unfortunately, I'm not able to carve out
|
||||||
|
a *lot* of time for Bunyan development and maintenance.
|
||||||
|
|
||||||
|
- Once all outstanding comments and checklist items have been addressed, your
|
||||||
|
contribution will be merged. Merged PRs will be included in the next
|
||||||
|
node-bunyan release.
|
||||||
|
|
||||||
|
- In some cases, we might decide that a PR should be closed. We'll make sure to
|
||||||
|
provide clear reasoning when this happens.
|
||||||
|
|
||||||
|
|
||||||
|
## Issue labels
|
||||||
|
|
||||||
|
The point of issue labeling for node-bunyan is to help answer "what should be
|
||||||
|
worked on now? what can be left for later?" I don't want issue labelling to
|
||||||
|
become a burden for anyone, so (a) don't feel obliged to add them yourself and
|
||||||
|
(b) I'm happy to reevaluate their usage.
|
||||||
|
|
||||||
|
Bunyan shall have categories of [issue
|
||||||
|
labels](https://github.com/trentm/node-bunyan/labels) named "$category-$value".
|
||||||
|
An issue should have max *one* label from each set. Users of Google Code's
|
||||||
|
dearly departed issue tracker may remember this kind of thing. This is a
|
||||||
|
poorman's version of structured issue tracker metadata.
|
||||||
|
|
||||||
|
I'm inclined to *not* do priorities right now. *Possibly* we'll use GitHub
|
||||||
|
milestones to basically set targets for upcoming releases. But otherwise my
|
||||||
|
sense is that for smaller OSS projects, assigning prios will get in the way.
|
||||||
|
If people would think it helpful, I'd consider "Difficulty-" or "Experience-"
|
||||||
|
categories (a la Rust's "E-" labels) to mark easier and intermediate tasks
|
||||||
|
that someone interested but maybe not very familiar with Bunyan might want
|
||||||
|
to tackle.
|
||||||
|
|
||||||
|
For now, here are the various labels and their purpose:
|
||||||
|
|
||||||
|
### Meta
|
||||||
|
|
||||||
|
- needstriage: Temporary label to help me do a single triage pass through all
|
||||||
|
current open issues and PRs.
|
||||||
|
See [#335](https://github.com/trentm/node-bunyan/issues/335)
|
||||||
|
where I'm working through this.
|
||||||
|
|
||||||
|
### Type
|
||||||
|
|
||||||
|
Color: green
|
||||||
|
|
||||||
|
- Type-Unknown: If it is still unclear or undecided if an issue is an intended
|
||||||
|
feature (perhaps arguing for better docs or examples to avoid confusion) or a
|
||||||
|
bug, I will use this category.
|
||||||
|
- Type-Question: Asking a question on Bunyan usage, about the project, etc.
|
||||||
|
- Type-Bug: A bug in Bunyan's behaviour.
|
||||||
|
- Type-Improvement: A new feature or other improvement.
|
||||||
|
- Type-Doc: Issues with Bunyan's documentation.
|
||||||
|
- Type-Task: A project task to be done.
|
||||||
|
|
||||||
|
TODO: consider Type-Unknown for the "unclear if bug or feature" tickets.
|
||||||
|
|
||||||
|
### Component
|
||||||
|
|
||||||
|
Color: blue
|
||||||
|
|
||||||
|
- Component-Project: Project meta stuff like testing, linting, build, install,
|
||||||
|
etc.
|
||||||
|
- Component-CLI: The `bunyan` command-line tool.
|
||||||
|
- Component-Lib: catch-all for other library stuff
|
||||||
|
- Component-LibRotation: The bunyan library's log rotation support.
|
||||||
|
- Component-LibBrowser: Bunyan's handling/support for running in the browser.
|
||||||
|
- Component-LibFlush: A separate component for collecting the tickets related
|
||||||
|
to closing/flushing bunyan streams on process shutdown.
|
||||||
|
|
||||||
|
The point of components is to find like issues to help with reference, search
|
||||||
|
and resolving them. If no component fits an issue/PR, then don't add a label.
|
||||||
|
|
||||||
|
### Resolution
|
||||||
|
|
||||||
|
Color: red
|
||||||
|
|
||||||
|
- Resolution-WontFix
|
||||||
|
- Resolution-Duplicate
|
||||||
|
- Resolution-Fixed: Also used to indicate "doc written", "question answered",
|
||||||
|
"feature implemented".
|
||||||
|
- Resolution-CannotRepro: After some reasonable attempt by maintainers to
|
||||||
|
reproduce a bug report, I want it to be non-controversial to close it
|
||||||
|
and mark it with this. If given more info by someone able to repro, we
|
||||||
|
can happy re-open issues.
|
||||||
|
|
||||||
|
### Experience
|
||||||
|
|
||||||
|
Color: yellow
|
||||||
|
|
||||||
|
- Experience-Easy: Relatively little experience with node-bunyan should be
|
||||||
|
required to complete this issue.
|
||||||
|
- Experience-NeedsTest: Typically added to an issue or PR that needs a test
|
||||||
|
case. Someone familiar enough with node-bunyan's test suite could tackle this.
|
||||||
|
- Experience-Hard: At a guess, this is a thorny issue that requires known
|
||||||
|
node-bunyan well, knowing node.js well, requires design review or all of
|
||||||
|
these.
|
||||||
|
|
||||||
|
One of the "Experience-\*" labels can optionally be put on an issue or PR to
|
||||||
|
indicate what kind of experience a contributor would need with node-bunyan
|
||||||
|
(and/or node.js) to complete it. For example, if you're looking for somewhere to
|
||||||
|
start, check out the [Experience-Easy][Experience-Easy] tag. This category idea
|
||||||
|
is borrowed from [rust's E-\* labels][rust-issue-triage].
|
||||||
|
|
||||||
|
[Experience-Easy]: https://github.com/trentm/node-bunyan/issues?q=is%3Aopen+is%3Aissue+label%3AExperience-Easy
|
||||||
|
[rust-issue-triage]: https://github.com/rust-lang/rust/blob/master/CONTRIBUTING.md#issue-triage
|
||||||
|
|
||||||
|
|
||||||
|
## Acknowledgements
|
||||||
|
|
||||||
|
Anything good about this document is thanks to inspiration from
|
||||||
|
[rust](https://github.com/rust-lang/rust/blob/master/CONTRIBUTING.md) and, more
|
||||||
|
recently
|
||||||
|
[terraform](https://github.com/hashicorp/terraform/blob/master/CONTRIBUTING.md).
|
||||||
|
Anything bad about it, is my fault.
|
|
@ -0,0 +1,24 @@
|
||||||
|
# This is the MIT license
|
||||||
|
|
||||||
|
Copyright 2016 Trent Mick
|
||||||
|
Copyright 2016 Joyent Inc.
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
copy of this software and associated documentation files (the
|
||||||
|
"Software"), to deal in the Software without restriction, including
|
||||||
|
without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
|
permit persons to whom the Software is furnished to do so, subject to
|
||||||
|
the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included
|
||||||
|
in all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||||
|
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||||
|
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||||
|
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||||
|
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||||
|
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
|
@ -0,0 +1,149 @@
|
||||||
|
|
||||||
|
#---- Tools
|
||||||
|
|
||||||
|
NODEUNIT := ./node_modules/.bin/nodeunit
|
||||||
|
SUDO := sudo
|
||||||
|
ifeq ($(shell uname -s),SunOS)
|
||||||
|
# On SunOS (e.g. SmartOS) we expect to run the test suite as the
|
||||||
|
# root user -- necessary to run dtrace. Therefore `pfexec` isn't
|
||||||
|
# necessary.
|
||||||
|
SUDO :=
|
||||||
|
endif
|
||||||
|
DTRACE_UP_IN_HERE=
|
||||||
|
ifeq ($(shell uname -s),SunOS)
|
||||||
|
DTRACE_UP_IN_HERE=1
|
||||||
|
endif
|
||||||
|
ifeq ($(shell uname -s),Darwin)
|
||||||
|
DTRACE_UP_IN_HERE=1
|
||||||
|
endif
|
||||||
|
NODEOPT ?= $(HOME)/opt
|
||||||
|
|
||||||
|
|
||||||
|
#---- Files
|
||||||
|
|
||||||
|
JSSTYLE_FILES := $(shell find lib test tools examples -name "*.js") bin/bunyan
|
||||||
|
# All test files *except* dtrace.test.js.
|
||||||
|
NON_DTRACE_TEST_FILES := $(shell ls -1 test/*.test.js | grep -v dtrace | xargs)
|
||||||
|
|
||||||
|
|
||||||
|
#---- Targets
|
||||||
|
|
||||||
|
all $(NODEUNIT):
|
||||||
|
npm install $(NPM_INSTALL_FLAGS)
|
||||||
|
|
||||||
|
# Ensure all version-carrying files have the same version.
|
||||||
|
.PHONY: versioncheck
|
||||||
|
versioncheck:
|
||||||
|
@echo version is: $(shell cat package.json | json version)
|
||||||
|
[[ `cat package.json | json version` == `grep '^## ' CHANGES.md | head -2 | tail -1 | awk '{print $$2}'` ]]
|
||||||
|
[[ `cat package.json | json version` == `grep '^var VERSION' bin/bunyan | awk -F"'" '{print $$2}'` ]]
|
||||||
|
[[ `cat package.json | json version` == `grep '^var VERSION' lib/bunyan.js | awk -F"'" '{print $$2}'` ]]
|
||||||
|
@echo Version check ok.
|
||||||
|
|
||||||
|
.PHONY: cutarelease
|
||||||
|
cutarelease: check
|
||||||
|
[[ -z `git status --short` ]] # If this fails, the working dir is dirty.
|
||||||
|
@which json 2>/dev/null 1>/dev/null && \
|
||||||
|
ver=$(shell json -f package.json version) && \
|
||||||
|
name=$(shell json -f package.json name) && \
|
||||||
|
publishedVer=$(shell npm view -j $(shell json -f package.json name)@$(shell json -f package.json version) version 2>/dev/null) && \
|
||||||
|
if [[ -n "$$publishedVer" ]]; then \
|
||||||
|
echo "error: $$name@$$ver is already published to npm"; \
|
||||||
|
exit 1; \
|
||||||
|
fi && \
|
||||||
|
echo "** Are you sure you want to tag and publish $$name@$$ver to npm?" && \
|
||||||
|
echo "** Enter to continue, Ctrl+C to abort." && \
|
||||||
|
read
|
||||||
|
ver=$(shell cat package.json | json version) && \
|
||||||
|
date=$(shell date -u "+%Y-%m-%d") && \
|
||||||
|
git tag -a "$$ver" -m "version $$ver ($$date)" && \
|
||||||
|
git push --tags origin && \
|
||||||
|
npm publish
|
||||||
|
|
||||||
|
.PHONY: docs
|
||||||
|
docs: toc
|
||||||
|
@[[ `which ronn` ]] || (echo "No 'ronn' on your PATH. Install with 'gem install ronn'" && exit 2)
|
||||||
|
mkdir -p man/man1
|
||||||
|
ronn --style=toc --manual="bunyan manual" --date=$(shell git log -1 --pretty=format:%cd --date=short) --roff --html docs/bunyan.1.ronn
|
||||||
|
python -c 'import sys; h = open("docs/bunyan.1.html").read(); h = h.replace(".mp dt.flush {float:left;width:8ex}", ""); open("docs/bunyan.1.html", "w").write(h)'
|
||||||
|
python -c 'import sys; h = open("docs/bunyan.1.html").read(); h = h.replace("</body>", """<a href="https://github.com/trentm/node-bunyan"><img style="position: absolute; top: 0; right: 0; border: 0;" src="https://s3.amazonaws.com/github/ribbons/forkme_right_darkblue_121621.png" alt="Fork me on GitHub"></a></body>"""); open("docs/bunyan.1.html", "w").write(h)'
|
||||||
|
@echo "# test with 'man ./docs/bunyan.1' and 'open ./docs/bunyan.1.html'"
|
||||||
|
|
||||||
|
# Re-generate the README.md table of contents.
|
||||||
|
toc:
|
||||||
|
./node_modules/.bin/markdown-toc -i README.md
|
||||||
|
|
||||||
|
|
||||||
|
.PHONY: publish
|
||||||
|
publish:
|
||||||
|
mkdir -p tmp
|
||||||
|
[[ -d tmp/bunyan-gh-pages ]] || git clone git@github.com:trentm/node-bunyan.git tmp/bunyan-gh-pages
|
||||||
|
cd tmp/bunyan-gh-pages && git checkout gh-pages && git pull --rebase origin gh-pages
|
||||||
|
cp docs/index.html tmp/bunyan-gh-pages/index.html
|
||||||
|
cp docs/bunyan.1.html tmp/bunyan-gh-pages/bunyan.1.html
|
||||||
|
(cd tmp/bunyan-gh-pages \
|
||||||
|
&& git commit -a -m "publish latest docs" \
|
||||||
|
&& git push origin gh-pages || true)
|
||||||
|
|
||||||
|
.PHONY: distclean
|
||||||
|
distclean:
|
||||||
|
rm -rf node_modules
|
||||||
|
|
||||||
|
|
||||||
|
#---- test
|
||||||
|
|
||||||
|
.PHONY: test
|
||||||
|
test: $(NODEUNIT)
|
||||||
|
test -z "$(DTRACE_UP_IN_HERE)" || test -n "$(SKIP_DTRACE)" || \
|
||||||
|
(node -e 'require("dtrace-provider").createDTraceProvider("isthisthingon")' && \
|
||||||
|
echo "\nNote: Use 'SKIP_DTRACE=1 make test' to skip parts of the test suite that require root." && \
|
||||||
|
$(SUDO) $(NODEUNIT) test/dtrace.test.js)
|
||||||
|
$(NODEUNIT) $(NON_DTRACE_TEST_FILES)
|
||||||
|
|
||||||
|
# Test will all node supported versions (presumes install locations I use on
|
||||||
|
# my machine -- "~/opt/node-VER"):
|
||||||
|
# Note: 'test4' is last so (if all is well) I end up with a binary
|
||||||
|
# dtrace-provider build for my current default node version.
|
||||||
|
.PHONY: testall
|
||||||
|
testall: test7 test6 test012 test010 test4
|
||||||
|
|
||||||
|
.PHONY: test7
|
||||||
|
test7:
|
||||||
|
@echo "# Test node 7.x (with node `$(NODEOPT)/node-7/bin/node --version`)"
|
||||||
|
@$(NODEOPT)/node-7/bin/node --version | grep '^v7\.'
|
||||||
|
PATH="$(NODEOPT)/node-7/bin:$(PATH)" make distclean all test
|
||||||
|
.PHONY: test6
|
||||||
|
test6:
|
||||||
|
@echo "# Test node 6.x (with node `$(NODEOPT)/node-6/bin/node --version`)"
|
||||||
|
@$(NODEOPT)/node-6/bin/node --version | grep '^v6\.'
|
||||||
|
PATH="$(NODEOPT)/node-6/bin:$(PATH)" make distclean all test
|
||||||
|
.PHONY: test4
|
||||||
|
test4:
|
||||||
|
@echo "# Test node 4.x (with node `$(NODEOPT)/node-4/bin/node --version`)"
|
||||||
|
@$(NODEOPT)/node-4/bin/node --version | grep '^v4\.'
|
||||||
|
PATH="$(NODEOPT)/node-4/bin:$(PATH)" make distclean all test
|
||||||
|
.PHONY: test012
|
||||||
|
test012:
|
||||||
|
@echo "# Test node 0.12.x (with node `$(NODEOPT)/node-0.12/bin/node --version`)"
|
||||||
|
@$(NODEOPT)/node-0.12/bin/node --version | grep '^v0\.12\.'
|
||||||
|
PATH="$(NODEOPT)/node-0.12/bin:$(PATH)" make distclean all test
|
||||||
|
.PHONY: test010
|
||||||
|
test010:
|
||||||
|
@echo "# Test node 0.10.x (with node `$(NODEOPT)/node-0.10/bin/node --version`)"
|
||||||
|
@$(NODEOPT)/node-0.10/bin/node --version | grep '^v0\.10\.'
|
||||||
|
PATH="$(NODEOPT)/node-0.10/bin:$(PATH)" make distclean all test
|
||||||
|
|
||||||
|
|
||||||
|
#---- check
|
||||||
|
|
||||||
|
.PHONY: check-jsstyle
|
||||||
|
check-jsstyle: $(JSSTYLE_FILES)
|
||||||
|
./tools/jsstyle -o indent=4,doxygen,unparenthesized-return=0,blank-after-start-comment=0,leading-right-paren-ok=1 $(JSSTYLE_FILES)
|
||||||
|
|
||||||
|
.PHONY: check
|
||||||
|
check: check-jsstyle versioncheck
|
||||||
|
@echo "Check ok."
|
||||||
|
|
||||||
|
.PHONY: prepush
|
||||||
|
prepush: check testall
|
||||||
|
@echo "Okay to push."
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,137 @@
|
||||||
|
# higher prio
|
||||||
|
|
||||||
|
- `bunyan` (without redir) ^C should stop, doesn't since recent change
|
||||||
|
- man page for the bunyan CLI (refer to it in the readme)
|
||||||
|
- perhaps wait for a bunyan new version with deps, and use dashdash
|
||||||
|
with a (vapour) man page generator
|
||||||
|
|
||||||
|
# v2
|
||||||
|
|
||||||
|
- ^C fix
|
||||||
|
- node-exeunt
|
||||||
|
- `createLogger(<config-and-fields>, <fields>)` changes (#460)
|
||||||
|
- see section below
|
||||||
|
- the dtrace-provider thing (#487)
|
||||||
|
TODO: answer Cody email
|
||||||
|
- use package.json version for VERSION
|
||||||
|
- use deps
|
||||||
|
- dashdash
|
||||||
|
- assert-plus?
|
||||||
|
- verror?
|
||||||
|
- break out to multiple files
|
||||||
|
- want to work through PRs before that, so don't just break them all
|
||||||
|
- TODO: a quick pass through tickets and pulls for other things to include
|
||||||
|
- get ticket refs for the above, if any
|
||||||
|
- formatters: read up again on `glp master..1.x`
|
||||||
|
- support for customer formatters
|
||||||
|
- for the CLI as well? How? ~/.bunyanrc?
|
||||||
|
|
||||||
|
|
||||||
|
# changes to ctor and log.child to separate fields from config
|
||||||
|
|
||||||
|
<https://github.com/trentm/node-bunyan/issues/460>
|
||||||
|
|
||||||
|
Current:
|
||||||
|
|
||||||
|
createLogger(<config-and-fields>)
|
||||||
|
log.child(<config-and-fields>, <just-fields-bool>)
|
||||||
|
|
||||||
|
Could be:
|
||||||
|
|
||||||
|
createLogger(<config-and-fields>, <fields>)
|
||||||
|
log.child(<config-and-fields>, <fields>)
|
||||||
|
# Still support: log.child(<config-and-fields>, <just-fields-bool>)
|
||||||
|
|
||||||
|
Pros: Compat issues are minimal: a change is only required if there is a
|
||||||
|
collision with used field and a new config var name.
|
||||||
|
Cons: A *slight* con is that my guess is the common usage of child is
|
||||||
|
`log.child(<fields>)`, so the more future-proof common usage becomes:
|
||||||
|
|
||||||
|
log.child(null, <fields>)
|
||||||
|
|
||||||
|
That's not too bad. It is clearer at least than:
|
||||||
|
|
||||||
|
log.child(<fields>, true)
|
||||||
|
|
||||||
|
TODO:
|
||||||
|
|
||||||
|
- is there a ticket for this work already?
|
||||||
|
- make the change
|
||||||
|
- do a migration guide? i.e. provide the grep commands to find all
|
||||||
|
possible calls to inspect. E.g. if don't have `rg logUndefined` in your
|
||||||
|
code, then you are fine. And one time future-proofing via changing
|
||||||
|
to fields in the *second* arg.
|
||||||
|
- list of issues/pulls that wanted to add new config fields
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# docs
|
||||||
|
|
||||||
|
- document log.addStream() and log.addSerializers()
|
||||||
|
|
||||||
|
|
||||||
|
# someday/maybe
|
||||||
|
|
||||||
|
- 2.0 (?) with `v: 1` in log records. Fwd/bwd compat in `bunyan` CLI
|
||||||
|
- `tail -f`-like support
|
||||||
|
- full-on docs
|
||||||
|
- better examples/
|
||||||
|
- better coloring
|
||||||
|
- look at pino (bunyan style, perf benefits)
|
||||||
|
- would be exciting to have bunyan support in http://lnav.org/ if that
|
||||||
|
made sense
|
||||||
|
- "template" support for 'rotating-file' stream to get dated rolled files
|
||||||
|
- "all" or "off" levels? log4j? logging.py?
|
||||||
|
logging.py has NOTSET === 0. I think that is only needed/used for
|
||||||
|
multi-level hierarchical effective level.
|
||||||
|
- buffered writes to increase speed:
|
||||||
|
- I'd start with a tools/timeoutput.js for some numbers to compare
|
||||||
|
before/after. Sustained high output to a file.
|
||||||
|
- perhaps this would be a "buffered: true" option on the stream object
|
||||||
|
- then wrap the "stream" with a local class that handles the buffering
|
||||||
|
- to finish this, need the 'log.close' and `process.on('exit', ...)`
|
||||||
|
work that Trent has started.
|
||||||
|
- "canWrite" handling for full streams. Need to buffer a la log4js
|
||||||
|
- test file log with logadm rotation: does it handle that?
|
||||||
|
- test suite:
|
||||||
|
- test for a cloned logger double-`stream.end()` causing problems.
|
||||||
|
Perhaps the "closeOnExit" for existing streams should be false for
|
||||||
|
clones.
|
||||||
|
- test that a `log.clone(...)` adding a new field matching a serializer
|
||||||
|
works *and* that an existing field in the parent is not *re-serialized*.
|
||||||
|
- split out `bunyan` cli to a "bunyan" or "bunyan-reader" or "node-bunyan-reader"
|
||||||
|
as the basis for tools to consume bunyan logs. It can grow indep of node-bunyan
|
||||||
|
for generating the logs.
|
||||||
|
It would take a Bunyan log record object and be expected to emit it.
|
||||||
|
|
||||||
|
node-bunyan-reader
|
||||||
|
.createReadStream(path, [options]) ?
|
||||||
|
|
||||||
|
- coloring bug: in less the indented extra info lines only have the first
|
||||||
|
line colored. Do we need the ANSI char on *each* line? That'll be
|
||||||
|
slower.
|
||||||
|
- document "well-known" keys from bunyan CLI p.o.v.. Add "client_req".
|
||||||
|
- More `bunyan` output formats and filtering features.
|
||||||
|
- Think about a bunyan dashboard that supports organizing and viewing logs
|
||||||
|
from multiple hosts and services.
|
||||||
|
- doc the restify RequestCaptureStream usage of RingBuffer. Great example.
|
||||||
|
- A vim plugin (a la http://vim.cybermirror.org/runtime/autoload/zip.vim ?) to
|
||||||
|
allow browsing (read-only) a bunyan log in rendered form.
|
||||||
|
- Some speed comparisons with others to get a feel for Bunyan's speed.
|
||||||
|
- what about promoting 'latency' field and making that easier?
|
||||||
|
- `log.close` to close streams and shutdown and `this.closed`
|
||||||
|
process.on('exit', log.close)
|
||||||
|
-> 'end' for the name
|
||||||
|
- bunyan cli: more layouts (http://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/EnhancedPatternLayout.html)
|
||||||
|
Custom log formats (in config file? in '-f' arg) using printf or hogan.js
|
||||||
|
or whatever. Dap wants field width control for lining up. Hogan.js is
|
||||||
|
probably overkill for this.
|
||||||
|
- loggly example using raw streams, hook.io?, whatever.
|
||||||
|
- serializer support:
|
||||||
|
- restify-server.js example -> restifyReq ? or have `req` detect that.
|
||||||
|
That is nicer for the "use all standard ones". *Does* restify req
|
||||||
|
have anything special?
|
||||||
|
- differential HTTP *client* req/res with *server* req/res.
|
||||||
|
- statsd stream? http://codeascraft.etsy.com/2011/02/15/measure-anything-measure-everything/
|
||||||
|
Think about it.
|
||||||
|
- web ui. Ideas: http://googlecloudplatform.blogspot.ca/2014/04/a-new-logs-viewer-for-google-cloud.html
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,235 @@
|
||||||
|
.\" generated with Ronn/v0.7.3
|
||||||
|
.\" http://github.com/rtomayko/ronn/tree/0.7.3
|
||||||
|
.
|
||||||
|
.TH "BUNYAN" "1" "January 2015" "" "bunyan manual"
|
||||||
|
.
|
||||||
|
.SH "NAME"
|
||||||
|
\fBbunyan\fR \- filter and pretty\-print Bunyan log file content
|
||||||
|
.
|
||||||
|
.SH "SYNOPSIS"
|
||||||
|
\fBbunyan\fR [OPTIONS]
|
||||||
|
.
|
||||||
|
.P
|
||||||
|
\&\.\.\. | \fBbunyan\fR [OPTIONS]
|
||||||
|
.
|
||||||
|
.P
|
||||||
|
\fBbunyan\fR [OPTIONS] \-p PID
|
||||||
|
.
|
||||||
|
.SH "DESCRIPTION"
|
||||||
|
"Bunyan" is \fBa simple and fast a JSON logging library\fR for node\.js services, a one\-JSON\-object\-per\-line log format, and \fBa \fBbunyan\fR CLI tool\fR for nicely viewing those logs\. This man page describes the latter\.
|
||||||
|
.
|
||||||
|
.SS "Pretty\-printing"
|
||||||
|
A bunyan log file is a stream of JSON objects, optionally interspersed with non\-JSON log lines\. The primary usage of bunyan(1) is to pretty print, for example:
|
||||||
|
.
|
||||||
|
.IP "" 4
|
||||||
|
.
|
||||||
|
.nf
|
||||||
|
|
||||||
|
$ bunyan foo\.log # or `cat foo\.log | bunyan
|
||||||
|
[2012\-02\-08T22:56:52\.856Z] INFO: myservice/123 on example\.com: My message
|
||||||
|
extra: multi
|
||||||
|
line
|
||||||
|
[2012\-02\-08T22:56:54\.856Z] ERROR: myservice/123 on example\.com: My message
|
||||||
|
\.\.\.
|
||||||
|
.
|
||||||
|
.fi
|
||||||
|
.
|
||||||
|
.IP "" 0
|
||||||
|
.
|
||||||
|
.P
|
||||||
|
By default the "long" output format is used\. Use the \fB\-o FORMAT\fR option to emit other formats\. E\.g\.:
|
||||||
|
.
|
||||||
|
.IP "" 4
|
||||||
|
.
|
||||||
|
.nf
|
||||||
|
|
||||||
|
$ bunyan foo\.log \-o short
|
||||||
|
22:56:52\.856Z INFO myservice: My message
|
||||||
|
extra: multi
|
||||||
|
line
|
||||||
|
22:56:54\.856Z ERROR myservice: My message
|
||||||
|
\.\.\.
|
||||||
|
.
|
||||||
|
.fi
|
||||||
|
.
|
||||||
|
.IP "" 0
|
||||||
|
.
|
||||||
|
.P
|
||||||
|
These will color the output if supported in your terminal\. See "OUTPUT FORMATS" below\.
|
||||||
|
.
|
||||||
|
.SS "Filtering"
|
||||||
|
The \fBbunyan\fR CLI can also be used to filter a bunyan log\. Use \fB\-l LEVEL\fR to filter by level:
|
||||||
|
.
|
||||||
|
.IP "" 4
|
||||||
|
.
|
||||||
|
.nf
|
||||||
|
|
||||||
|
$ bunyan foo\.log \-l error # show only \'error\' level records
|
||||||
|
[2012\-02\-08T22:56:54\.856Z] ERROR: myservice/123 on example\.com: My message
|
||||||
|
.
|
||||||
|
.fi
|
||||||
|
.
|
||||||
|
.IP "" 0
|
||||||
|
.
|
||||||
|
.P
|
||||||
|
Use \fB\-c COND\fR to filter on a JavaScript expression returning true on the record data\. In the COND code, \fBthis\fR refers to the record object:
|
||||||
|
.
|
||||||
|
.IP "" 4
|
||||||
|
.
|
||||||
|
.nf
|
||||||
|
|
||||||
|
$ bunyan foo\.log \-c `this\.three` # show records with the \'extra\' field
|
||||||
|
[2012\-02\-08T22:56:52\.856Z] INFO: myservice/123 on example\.com: My message
|
||||||
|
extra: multi
|
||||||
|
line
|
||||||
|
.
|
||||||
|
.fi
|
||||||
|
.
|
||||||
|
.IP "" 0
|
||||||
|
.
|
||||||
|
.SH "OPTIONS"
|
||||||
|
.
|
||||||
|
.TP
|
||||||
|
\fB\-h\fR, \fB\-\-help\fR
|
||||||
|
Print this help info and exit\.
|
||||||
|
.
|
||||||
|
.TP
|
||||||
|
\fB\-\-version\fR
|
||||||
|
Print version of this command and exit\.
|
||||||
|
.
|
||||||
|
.TP
|
||||||
|
\fB\-q\fR, \fB\-\-quiet\fR
|
||||||
|
Don\'t warn if input isn\'t valid JSON\.
|
||||||
|
.
|
||||||
|
.P
|
||||||
|
Dtrace options (only on dtrace\-supporting platforms):
|
||||||
|
.
|
||||||
|
.TP
|
||||||
|
\fB\-p PID\fR, \fB\-p NAME\fR
|
||||||
|
Process bunyan:log\-* probes from the process with the given PID\. Can be used multiple times, or specify all processes with \'*\', or a set of processes whose command & args match a pattern with \'\-p NAME\'\.
|
||||||
|
.
|
||||||
|
.P
|
||||||
|
Filtering options:
|
||||||
|
.
|
||||||
|
.TP
|
||||||
|
\fB\-l\fR, \fB\-\-level LEVEL\fR
|
||||||
|
Only show messages at or above the specified level\. You can specify level \fInames\fR or numeric values\. (See \'Log Levels\' below\.)
|
||||||
|
.
|
||||||
|
.TP
|
||||||
|
\fB\-c COND\fR, \fB\-\-condition COND\fR
|
||||||
|
Run each log message through the condition and only show those that resolve to a truish value\. E\.g\. \fB\-c \'this\.pid == 123\'\fR\.
|
||||||
|
.
|
||||||
|
.TP
|
||||||
|
\fB\-\-strict\fR
|
||||||
|
Suppress all but legal Bunyan JSON log lines\. By default non\-JSON, and non\-Bunyan lines are passed through\.
|
||||||
|
.
|
||||||
|
.P
|
||||||
|
Output options:
|
||||||
|
.
|
||||||
|
.TP
|
||||||
|
\fB\-\-color\fR
|
||||||
|
Colorize output\. Defaults to try if output stream is a TTY\.
|
||||||
|
.
|
||||||
|
.TP
|
||||||
|
\fB\-\-no\-color\fR
|
||||||
|
Force no coloring (e\.g\. terminal doesn\'t support it)
|
||||||
|
.
|
||||||
|
.TP
|
||||||
|
\fB\-o FORMAT\fR, \fB\-\-output FORMAT\fR
|
||||||
|
Specify an output format\. One of \fBlong\fR (the default), \fBshort\fR, \fBjson\fR, \fBjson\-N\fR, \fBbunyan\fR (the native bunyan 0\-indent JSON output) or \fBinspect\fR\.
|
||||||
|
.
|
||||||
|
.TP
|
||||||
|
\fB\-j\fR
|
||||||
|
Shortcut for \fB\-o json\fR\.
|
||||||
|
.
|
||||||
|
.TP
|
||||||
|
\fB\-L\fR, \fB\-\-time local\fR
|
||||||
|
Display the time field in \fIlocal\fR time, rather than the default UTC time\.
|
||||||
|
.
|
||||||
|
.SH "LOG LEVELS"
|
||||||
|
In Bunyan log records, then \fBlevel\fR field is a number\. For the \fB\-l|\-\-level\fR argument the level \fBnames\fR are supported as shortcuts\. In \fB\-c|\-\-condition\fR scripts, uppercase symbols like "DEBUG" are defined for convenience\.
|
||||||
|
.
|
||||||
|
.IP "" 4
|
||||||
|
.
|
||||||
|
.nf
|
||||||
|
|
||||||
|
Level Name Level Number Symbol in COND Scripts
|
||||||
|
trace 10 TRACE
|
||||||
|
debug 20 DEBUG
|
||||||
|
info 30 INFO
|
||||||
|
warn 40 WARN
|
||||||
|
error 50 ERROR
|
||||||
|
fatal 60 FATAL
|
||||||
|
.
|
||||||
|
.fi
|
||||||
|
.
|
||||||
|
.IP "" 0
|
||||||
|
.
|
||||||
|
.SH "OUTPUT FORMATS"
|
||||||
|
.
|
||||||
|
.nf
|
||||||
|
|
||||||
|
FORMAT NAME DESCRIPTION
|
||||||
|
long (default) The default output\. Long form\. Colored and "pretty"\.
|
||||||
|
\'req\' and \'res\' and \'err\' fields are rendered specially
|
||||||
|
as an HTTP request, HTTP response and exception
|
||||||
|
stack trace, respectively\. For backward compat, the
|
||||||
|
name "paul" also works for this\.
|
||||||
|
short Like the default output, but more concise\. Some
|
||||||
|
typically redundant fields are ellided\.
|
||||||
|
json JSON output, 2\-space indentation\.
|
||||||
|
json\-N JSON output, N\-space indentation, e\.g\. "json\-4"
|
||||||
|
bunyan Alias for "json\-0", the Bunyan "native" format\.
|
||||||
|
inspect Node\.js `util\.inspect` output\.
|
||||||
|
.
|
||||||
|
.fi
|
||||||
|
.
|
||||||
|
.SH "DTRACE SUPPORT"
|
||||||
|
On systems that support DTrace (e\.g\., MacOS, FreeBSD, illumos derivatives like SmartOS and OmniOS), Bunyan will create a DTrace provider (\fBbunyan\fR) that makes available the following probes:
|
||||||
|
.
|
||||||
|
.IP "" 4
|
||||||
|
.
|
||||||
|
.nf
|
||||||
|
|
||||||
|
log\-trace
|
||||||
|
log\-debug
|
||||||
|
log\-info
|
||||||
|
log\-warn
|
||||||
|
log\-error
|
||||||
|
log\-fatal
|
||||||
|
.
|
||||||
|
.fi
|
||||||
|
.
|
||||||
|
.IP "" 0
|
||||||
|
.
|
||||||
|
.P
|
||||||
|
Each of these probes has a single argument: the string that would be written to the log\. Note that when a probe is enabled, it will fire whenever the corresponding function is called, even if the level of the log message is less than that of any stream\.
|
||||||
|
.
|
||||||
|
.P
|
||||||
|
See \fIhttps://github\.com/trentm/node\-bunyan#dtrace\-support\fR for more details and the \'\-p PID\' option above for convenience usage\.
|
||||||
|
.
|
||||||
|
.SH "ENVIRONMENT"
|
||||||
|
.
|
||||||
|
.TP
|
||||||
|
\fBBUNYAN_NO_COLOR\fR
|
||||||
|
Set to a non\-empty value to force no output coloring\. See \'\-\-no\-color\'\.
|
||||||
|
.
|
||||||
|
.SH "PROJECT & BUGS"
|
||||||
|
\fBbunyan\fR is written in JavaScript and requires node\.js (\fBnode\fR)\. The project lives at \fIhttps://github\.com/trentm/node\-bunyan\fR and is published to npm as "bunyan"\.
|
||||||
|
.
|
||||||
|
.IP "\(bu" 4
|
||||||
|
README, Install notes: \fIhttps://github\.com/trentm/node\-bunyan#readme\fR
|
||||||
|
.
|
||||||
|
.IP "\(bu" 4
|
||||||
|
Report bugs to \fIhttps://github\.com/trentm/node\-bunyan/issues\fR\.
|
||||||
|
.
|
||||||
|
.IP "\(bu" 4
|
||||||
|
See the full changelog at: \fIhttps://github\.com/trentm/node\-bunyan/blob/master/CHANGES\.md\fR
|
||||||
|
.
|
||||||
|
.IP "" 0
|
||||||
|
.
|
||||||
|
.SH "LICENSE"
|
||||||
|
MIT License (see \fIhttps://github\.com/trentm/node\-bunyan/blob/master/LICENSE\.txt\fR)
|
||||||
|
.
|
||||||
|
.SH "COPYRIGHT"
|
||||||
|
node\-bunyan is Copyright (c) 2012 Joyent, Inc\. Copyright (c) 2012 Trent Mick\. All rights reserved\.
|
|
@ -0,0 +1,281 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta http-equiv='content-type' value='text/html;charset=utf8'>
|
||||||
|
<meta name='generator' value='Ronn/v0.7.3 (http://github.com/rtomayko/ronn/tree/0.7.3)'>
|
||||||
|
<title>bunyan(1) - filter and pretty-print Bunyan log file content</title>
|
||||||
|
<style type='text/css' media='all'>
|
||||||
|
/* style: man */
|
||||||
|
body#manpage {margin:0}
|
||||||
|
.mp {max-width:100ex;padding:0 9ex 1ex 4ex}
|
||||||
|
.mp p,.mp pre,.mp ul,.mp ol,.mp dl {margin:0 0 20px 0}
|
||||||
|
.mp h2 {margin:10px 0 0 0}
|
||||||
|
.mp > p,.mp > pre,.mp > ul,.mp > ol,.mp > dl {margin-left:8ex}
|
||||||
|
.mp h3 {margin:0 0 0 4ex}
|
||||||
|
.mp dt {margin:0;clear:left}
|
||||||
|
|
||||||
|
.mp dd {margin:0 0 0 9ex}
|
||||||
|
.mp h1,.mp h2,.mp h3,.mp h4 {clear:left}
|
||||||
|
.mp pre {margin-bottom:20px}
|
||||||
|
.mp pre+h2,.mp pre+h3 {margin-top:22px}
|
||||||
|
.mp h2+pre,.mp h3+pre {margin-top:5px}
|
||||||
|
.mp img {display:block;margin:auto}
|
||||||
|
.mp h1.man-title {display:none}
|
||||||
|
.mp,.mp code,.mp pre,.mp tt,.mp kbd,.mp samp,.mp h3,.mp h4 {font-family:monospace;font-size:14px;line-height:1.42857142857143}
|
||||||
|
.mp h2 {font-size:16px;line-height:1.25}
|
||||||
|
.mp h1 {font-size:20px;line-height:2}
|
||||||
|
.mp {text-align:justify;background:#fff}
|
||||||
|
.mp,.mp code,.mp pre,.mp pre code,.mp tt,.mp kbd,.mp samp {color:#131211}
|
||||||
|
.mp h1,.mp h2,.mp h3,.mp h4 {color:#030201}
|
||||||
|
.mp u {text-decoration:underline}
|
||||||
|
.mp code,.mp strong,.mp b {font-weight:bold;color:#131211}
|
||||||
|
.mp em,.mp var {font-style:italic;color:#232221;text-decoration:none}
|
||||||
|
.mp a,.mp a:link,.mp a:hover,.mp a code,.mp a pre,.mp a tt,.mp a kbd,.mp a samp {color:#0000ff}
|
||||||
|
.mp b.man-ref {font-weight:normal;color:#434241}
|
||||||
|
.mp pre {padding:0 4ex}
|
||||||
|
.mp pre code {font-weight:normal;color:#434241}
|
||||||
|
.mp h2+pre,h3+pre {padding-left:0}
|
||||||
|
ol.man-decor,ol.man-decor li {margin:3px 0 10px 0;padding:0;float:left;width:33%;list-style-type:none;text-transform:uppercase;color:#999;letter-spacing:1px}
|
||||||
|
ol.man-decor {width:100%}
|
||||||
|
ol.man-decor li.tl {text-align:left}
|
||||||
|
ol.man-decor li.tc {text-align:center;letter-spacing:4px}
|
||||||
|
ol.man-decor li.tr {text-align:right;float:right}
|
||||||
|
</style>
|
||||||
|
<style type='text/css' media='all'>
|
||||||
|
/* style: toc */
|
||||||
|
.man-navigation {display:block !important;position:fixed;top:0;left:113ex;height:100%;width:100%;padding:48px 0 0 0;border-left:1px solid #dbdbdb;background:#eee}
|
||||||
|
.man-navigation a,.man-navigation a:hover,.man-navigation a:link,.man-navigation a:visited {display:block;margin:0;padding:5px 2px 5px 30px;color:#999;text-decoration:none}
|
||||||
|
.man-navigation a:hover {color:#111;text-decoration:underline}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<!--
|
||||||
|
The following styles are deprecated and will be removed at some point:
|
||||||
|
div#man, div#man ol.man, div#man ol.head, div#man ol.man.
|
||||||
|
|
||||||
|
The .man-page, .man-decor, .man-head, .man-foot, .man-title, and
|
||||||
|
.man-navigation should be used instead.
|
||||||
|
-->
|
||||||
|
<body id='manpage'>
|
||||||
|
<div class='mp' id='man'>
|
||||||
|
|
||||||
|
<div class='man-navigation' style='display:none'>
|
||||||
|
<a href="#NAME">NAME</a>
|
||||||
|
<a href="#SYNOPSIS">SYNOPSIS</a>
|
||||||
|
<a href="#DESCRIPTION">DESCRIPTION</a>
|
||||||
|
<a href="#OPTIONS">OPTIONS</a>
|
||||||
|
<a href="#LOG-LEVELS">LOG LEVELS</a>
|
||||||
|
<a href="#OUTPUT-FORMATS">OUTPUT FORMATS</a>
|
||||||
|
<a href="#DTRACE-SUPPORT">DTRACE SUPPORT</a>
|
||||||
|
<a href="#ENVIRONMENT">ENVIRONMENT</a>
|
||||||
|
<a href="#PROJECT-BUGS">PROJECT & BUGS</a>
|
||||||
|
<a href="#LICENSE">LICENSE</a>
|
||||||
|
<a href="#COPYRIGHT">COPYRIGHT</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<ol class='man-decor man-head man head'>
|
||||||
|
<li class='tl'>bunyan(1)</li>
|
||||||
|
<li class='tc'>bunyan manual</li>
|
||||||
|
<li class='tr'>bunyan(1)</li>
|
||||||
|
</ol>
|
||||||
|
|
||||||
|
<h2 id="NAME">NAME</h2>
|
||||||
|
<p class="man-name">
|
||||||
|
<code>bunyan</code> - <span class="man-whatis">filter and pretty-print Bunyan log file content</span>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2 id="SYNOPSIS">SYNOPSIS</h2>
|
||||||
|
|
||||||
|
<p><code>bunyan</code> [OPTIONS]</p>
|
||||||
|
|
||||||
|
<p>... | <code>bunyan</code> [OPTIONS]</p>
|
||||||
|
|
||||||
|
<p><code>bunyan</code> [OPTIONS] -p PID</p>
|
||||||
|
|
||||||
|
<h2 id="DESCRIPTION">DESCRIPTION</h2>
|
||||||
|
|
||||||
|
<p>"Bunyan" is <strong>a simple and fast a JSON logging library</strong> for node.js services,
|
||||||
|
a one-JSON-object-per-line log format, and <strong>a <code>bunyan</code> CLI tool</strong> for nicely
|
||||||
|
viewing those logs. This man page describes the latter.</p>
|
||||||
|
|
||||||
|
<h3 id="Pretty-printing">Pretty-printing</h3>
|
||||||
|
|
||||||
|
<p>A bunyan log file is a stream of JSON objects, optionally interspersed with
|
||||||
|
non-JSON log lines. The primary usage of <a href="bunyan.1.html" class="man-ref">bunyan<span class="s">(1)</span></a> is to pretty print,
|
||||||
|
for example:</p>
|
||||||
|
|
||||||
|
<pre><code>$ bunyan foo.log # or `cat foo.log | bunyan
|
||||||
|
[2012-02-08T22:56:52.856Z] INFO: myservice/123 on example.com: My message
|
||||||
|
extra: multi
|
||||||
|
line
|
||||||
|
[2012-02-08T22:56:54.856Z] ERROR: myservice/123 on example.com: My message
|
||||||
|
...
|
||||||
|
</code></pre>
|
||||||
|
|
||||||
|
<p>By default the "long" output format is used. Use the <code>-o FORMAT</code> option to
|
||||||
|
emit other formats. E.g.:</p>
|
||||||
|
|
||||||
|
<pre><code>$ bunyan foo.log -o short
|
||||||
|
22:56:52.856Z INFO myservice: My message
|
||||||
|
extra: multi
|
||||||
|
line
|
||||||
|
22:56:54.856Z ERROR myservice: My message
|
||||||
|
...
|
||||||
|
</code></pre>
|
||||||
|
|
||||||
|
<p>These will color the output if supported in your terminal.
|
||||||
|
See "OUTPUT FORMATS" below.</p>
|
||||||
|
|
||||||
|
<h3 id="Filtering">Filtering</h3>
|
||||||
|
|
||||||
|
<p>The <code>bunyan</code> CLI can also be used to filter a bunyan log. Use <code>-l LEVEL</code>
|
||||||
|
to filter by level:</p>
|
||||||
|
|
||||||
|
<pre><code>$ bunyan foo.log -l error # show only 'error' level records
|
||||||
|
[2012-02-08T22:56:54.856Z] ERROR: myservice/123 on example.com: My message
|
||||||
|
</code></pre>
|
||||||
|
|
||||||
|
<p>Use <code>-c COND</code> to filter on a JavaScript expression returning true on the
|
||||||
|
record data. In the COND code, <code>this</code> refers to the record object:</p>
|
||||||
|
|
||||||
|
<pre><code>$ bunyan foo.log -c `this.three` # show records with the 'extra' field
|
||||||
|
[2012-02-08T22:56:52.856Z] INFO: myservice/123 on example.com: My message
|
||||||
|
extra: multi
|
||||||
|
line
|
||||||
|
</code></pre>
|
||||||
|
|
||||||
|
<h2 id="OPTIONS">OPTIONS</h2>
|
||||||
|
|
||||||
|
<dl>
|
||||||
|
<dt><code>-h</code>, <code>--help</code></dt><dd><p>Print this help info and exit.</p></dd>
|
||||||
|
<dt><code>--version</code></dt><dd><p>Print version of this command and exit.</p></dd>
|
||||||
|
<dt><code>-q</code>, <code>--quiet</code></dt><dd><p>Don't warn if input isn't valid JSON.</p></dd>
|
||||||
|
</dl>
|
||||||
|
|
||||||
|
|
||||||
|
<p>Dtrace options (only on dtrace-supporting platforms):</p>
|
||||||
|
|
||||||
|
<dl>
|
||||||
|
<dt><code>-p PID</code>, <code>-p NAME</code></dt><dd>Process bunyan:log-* probes from the process with the given PID.
|
||||||
|
Can be used multiple times, or specify all processes with '*',
|
||||||
|
or a set of processes whose command & args match a pattern with
|
||||||
|
'-p NAME'.</dd>
|
||||||
|
</dl>
|
||||||
|
|
||||||
|
|
||||||
|
<p>Filtering options:</p>
|
||||||
|
|
||||||
|
<dl>
|
||||||
|
<dt><code>-l</code>, <code>--level LEVEL</code></dt><dd><p>Only show messages at or above the specified level. You can specify level
|
||||||
|
<em>names</em> or numeric values. (See 'Log Levels' below.)</p></dd>
|
||||||
|
<dt><code>-c COND</code>, <code>--condition COND</code></dt><dd><p>Run each log message through the condition and only show those that
|
||||||
|
resolve to a truish value. E.g. <code>-c 'this.pid == 123'</code>.</p></dd>
|
||||||
|
<dt><code>--strict</code></dt><dd><p>Suppress all but legal Bunyan JSON log lines. By default non-JSON, and
|
||||||
|
non-Bunyan lines are passed through.</p></dd>
|
||||||
|
</dl>
|
||||||
|
|
||||||
|
|
||||||
|
<p>Output options:</p>
|
||||||
|
|
||||||
|
<dl>
|
||||||
|
<dt class="flush"><code>--color</code></dt><dd><p>Colorize output. Defaults to try if output stream is a TTY.</p></dd>
|
||||||
|
<dt><code>--no-color</code></dt><dd><p>Force no coloring (e.g. terminal doesn't support it)</p></dd>
|
||||||
|
<dt><code>-o FORMAT</code>, <code>--output FORMAT</code></dt><dd><p>Specify an output format. One of <code>long</code> (the default), <code>short</code>, <code>json</code>,
|
||||||
|
<code>json-N</code>, <code>bunyan</code> (the native bunyan 0-indent JSON output) or <code>inspect</code>.</p></dd>
|
||||||
|
<dt class="flush"><code>-j</code></dt><dd><p>Shortcut for <code>-o json</code>.</p></dd>
|
||||||
|
<dt><code>-L</code>, <code>--time local</code></dt><dd><p>Display the time field in <em>local</em> time, rather than the default UTC
|
||||||
|
time.</p></dd>
|
||||||
|
</dl>
|
||||||
|
|
||||||
|
|
||||||
|
<h2 id="LOG-LEVELS">LOG LEVELS</h2>
|
||||||
|
|
||||||
|
<p>In Bunyan log records, then <code>level</code> field is a number. For the <code>-l|--level</code>
|
||||||
|
argument the level <strong>names</strong> are supported as shortcuts. In <code>-c|--condition</code>
|
||||||
|
scripts, uppercase symbols like "DEBUG" are defined for convenience.</p>
|
||||||
|
|
||||||
|
<pre><code>Level Name Level Number Symbol in COND Scripts
|
||||||
|
trace 10 TRACE
|
||||||
|
debug 20 DEBUG
|
||||||
|
info 30 INFO
|
||||||
|
warn 40 WARN
|
||||||
|
error 50 ERROR
|
||||||
|
fatal 60 FATAL
|
||||||
|
</code></pre>
|
||||||
|
|
||||||
|
<h2 id="OUTPUT-FORMATS">OUTPUT FORMATS</h2>
|
||||||
|
|
||||||
|
<pre><code>FORMAT NAME DESCRIPTION
|
||||||
|
long (default) The default output. Long form. Colored and "pretty".
|
||||||
|
'req' and 'res' and 'err' fields are rendered specially
|
||||||
|
as an HTTP request, HTTP response and exception
|
||||||
|
stack trace, respectively. For backward compat, the
|
||||||
|
name "paul" also works for this.
|
||||||
|
short Like the default output, but more concise. Some
|
||||||
|
typically redundant fields are ellided.
|
||||||
|
json JSON output, 2-space indentation.
|
||||||
|
json-N JSON output, N-space indentation, e.g. "json-4"
|
||||||
|
bunyan Alias for "json-0", the Bunyan "native" format.
|
||||||
|
inspect Node.js `util.inspect` output.
|
||||||
|
</code></pre>
|
||||||
|
|
||||||
|
<h2 id="DTRACE-SUPPORT">DTRACE SUPPORT</h2>
|
||||||
|
|
||||||
|
<p>On systems that support DTrace (e.g., MacOS, FreeBSD, illumos derivatives
|
||||||
|
like SmartOS and OmniOS), Bunyan will create a DTrace provider (<code>bunyan</code>)
|
||||||
|
that makes available the following probes:</p>
|
||||||
|
|
||||||
|
<pre><code>log-trace
|
||||||
|
log-debug
|
||||||
|
log-info
|
||||||
|
log-warn
|
||||||
|
log-error
|
||||||
|
log-fatal
|
||||||
|
</code></pre>
|
||||||
|
|
||||||
|
<p>Each of these probes has a single argument: the string that would be
|
||||||
|
written to the log. Note that when a probe is enabled, it will
|
||||||
|
fire whenever the corresponding function is called, even if the level of
|
||||||
|
the log message is less than that of any stream.</p>
|
||||||
|
|
||||||
|
<p>See <a href="https://github.com/trentm/node-bunyan#dtrace-support" data-bare-link="true">https://github.com/trentm/node-bunyan#dtrace-support</a> for more details
|
||||||
|
and the '-p PID' option above for convenience usage.</p>
|
||||||
|
|
||||||
|
<h2 id="ENVIRONMENT">ENVIRONMENT</h2>
|
||||||
|
|
||||||
|
<dl>
|
||||||
|
<dt><code>BUNYAN_NO_COLOR</code></dt><dd>Set to a non-empty value to force no output coloring. See '--no-color'.</dd>
|
||||||
|
</dl>
|
||||||
|
|
||||||
|
|
||||||
|
<h2 id="PROJECT-BUGS">PROJECT & BUGS</h2>
|
||||||
|
|
||||||
|
<p><code>bunyan</code> is written in JavaScript and requires node.js (<code>node</code>). The project
|
||||||
|
lives at <a href="https://github.com/trentm/node-bunyan" data-bare-link="true">https://github.com/trentm/node-bunyan</a> and is published to npm as
|
||||||
|
"bunyan".</p>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li>README, Install notes: <a href="https://github.com/trentm/node-bunyan#readme" data-bare-link="true">https://github.com/trentm/node-bunyan#readme</a></li>
|
||||||
|
<li>Report bugs to <a href="https://github.com/trentm/node-bunyan/issues" data-bare-link="true">https://github.com/trentm/node-bunyan/issues</a>.</li>
|
||||||
|
<li>See the full changelog at: <a href="https://github.com/trentm/node-bunyan/blob/master/CHANGES.md" data-bare-link="true">https://github.com/trentm/node-bunyan/blob/master/CHANGES.md</a></li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
|
||||||
|
<h2 id="LICENSE">LICENSE</h2>
|
||||||
|
|
||||||
|
<p>MIT License (see <a href="https://github.com/trentm/node-bunyan/blob/master/LICENSE.txt" data-bare-link="true">https://github.com/trentm/node-bunyan/blob/master/LICENSE.txt</a>)</p>
|
||||||
|
|
||||||
|
<h2 id="COPYRIGHT">COPYRIGHT</h2>
|
||||||
|
|
||||||
|
<p>node-bunyan is Copyright (c) 2012 Joyent, Inc. Copyright (c) 2012 Trent Mick.
|
||||||
|
All rights reserved.</p>
|
||||||
|
|
||||||
|
|
||||||
|
<ol class='man-decor man-foot man foot'>
|
||||||
|
<li class='tl'></li>
|
||||||
|
<li class='tc'>January 2015</li>
|
||||||
|
<li class='tr'>bunyan(1)</li>
|
||||||
|
</ol>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<a href="https://github.com/trentm/node-bunyan"><img style="position: absolute; top: 0; right: 0; border: 0;" src="https://s3.amazonaws.com/github/ribbons/forkme_right_darkblue_121621.png" alt="Fork me on GitHub"></a></body>
|
||||||
|
</html>
|
|
@ -0,0 +1,195 @@
|
||||||
|
# bunyan(1) -- filter and pretty-print Bunyan log file content
|
||||||
|
|
||||||
|
|
||||||
|
## SYNOPSIS
|
||||||
|
|
||||||
|
`bunyan` \[OPTIONS\]
|
||||||
|
|
||||||
|
... | `bunyan` \[OPTIONS\]
|
||||||
|
|
||||||
|
`bunyan` \[OPTIONS\] -p PID
|
||||||
|
|
||||||
|
|
||||||
|
## DESCRIPTION
|
||||||
|
|
||||||
|
"Bunyan" is **a simple and fast a JSON logging library** for node.js services,
|
||||||
|
a one-JSON-object-per-line log format, and **a `bunyan` CLI tool** for nicely
|
||||||
|
viewing those logs. This man page describes the latter.
|
||||||
|
|
||||||
|
|
||||||
|
### Pretty-printing
|
||||||
|
|
||||||
|
A bunyan log file is a stream of JSON objects, optionally interspersed with
|
||||||
|
non-JSON log lines. The primary usage of bunyan(1) is to pretty print,
|
||||||
|
for example:
|
||||||
|
|
||||||
|
$ bunyan foo.log # or `cat foo.log | bunyan
|
||||||
|
[2012-02-08T22:56:52.856Z] INFO: myservice/123 on example.com: My message
|
||||||
|
extra: multi
|
||||||
|
line
|
||||||
|
[2012-02-08T22:56:54.856Z] ERROR: myservice/123 on example.com: My message
|
||||||
|
...
|
||||||
|
|
||||||
|
By default the "long" output format is used. Use the `-o FORMAT` option to
|
||||||
|
emit other formats. E.g.:
|
||||||
|
|
||||||
|
$ bunyan foo.log -o short
|
||||||
|
22:56:52.856Z INFO myservice: My message
|
||||||
|
extra: multi
|
||||||
|
line
|
||||||
|
22:56:54.856Z ERROR myservice: My message
|
||||||
|
...
|
||||||
|
|
||||||
|
These will color the output if supported in your terminal.
|
||||||
|
See "OUTPUT FORMATS" below.
|
||||||
|
|
||||||
|
|
||||||
|
### Filtering
|
||||||
|
|
||||||
|
The `bunyan` CLI can also be used to filter a bunyan log. Use `-l LEVEL`
|
||||||
|
to filter by level:
|
||||||
|
|
||||||
|
$ bunyan foo.log -l error # show only 'error' level records
|
||||||
|
[2012-02-08T22:56:54.856Z] ERROR: myservice/123 on example.com: My message
|
||||||
|
|
||||||
|
Use `-c COND` to filter on a JavaScript expression returning true on the
|
||||||
|
record data. In the COND code, `this` refers to the record object:
|
||||||
|
|
||||||
|
$ bunyan foo.log -c `this.three` # show records with the 'extra' field
|
||||||
|
[2012-02-08T22:56:52.856Z] INFO: myservice/123 on example.com: My message
|
||||||
|
extra: multi
|
||||||
|
line
|
||||||
|
|
||||||
|
|
||||||
|
## OPTIONS
|
||||||
|
|
||||||
|
* `-h`, `--help`:
|
||||||
|
Print this help info and exit.
|
||||||
|
|
||||||
|
* `--version`:
|
||||||
|
Print version of this command and exit.
|
||||||
|
|
||||||
|
* `-q`, `--quiet`:
|
||||||
|
Don't warn if input isn't valid JSON.
|
||||||
|
|
||||||
|
Dtrace options (only on dtrace-supporting platforms):
|
||||||
|
|
||||||
|
* `-p PID`, `-p NAME`:
|
||||||
|
Process bunyan:log-\* probes from the process with the given PID.
|
||||||
|
Can be used multiple times, or specify all processes with '\*',
|
||||||
|
or a set of processes whose command & args match a pattern with
|
||||||
|
'-p NAME'.
|
||||||
|
|
||||||
|
Filtering options:
|
||||||
|
|
||||||
|
* `-l`, `--level LEVEL`:
|
||||||
|
Only show messages at or above the specified level. You can specify level
|
||||||
|
*names* or numeric values. (See 'Log Levels' below.)
|
||||||
|
|
||||||
|
* `-c COND`, `--condition COND`:
|
||||||
|
Run each log message through the condition and only show those that
|
||||||
|
resolve to a truish value. E.g. `-c 'this.pid == 123'`.
|
||||||
|
|
||||||
|
* `--strict`:
|
||||||
|
Suppress all but legal Bunyan JSON log lines. By default non-JSON, and
|
||||||
|
non-Bunyan lines are passed through.
|
||||||
|
|
||||||
|
Output options:
|
||||||
|
|
||||||
|
* `--color`:
|
||||||
|
Colorize output. Defaults to try if output stream is a TTY.
|
||||||
|
|
||||||
|
* `--no-color`:
|
||||||
|
Force no coloring (e.g. terminal doesn't support it)
|
||||||
|
|
||||||
|
* `-o FORMAT`, `--output FORMAT`:
|
||||||
|
Specify an output format. One of `long` (the default), `short`, `json`,
|
||||||
|
`json-N`, `bunyan` (the native bunyan 0-indent JSON output) or `inspect`.
|
||||||
|
|
||||||
|
* `-j`:
|
||||||
|
Shortcut for `-o json`.
|
||||||
|
|
||||||
|
* `-L`, `--time local`:
|
||||||
|
Display the time field in *local* time, rather than the default UTC
|
||||||
|
time.
|
||||||
|
|
||||||
|
|
||||||
|
## LOG LEVELS
|
||||||
|
|
||||||
|
In Bunyan log records, then `level` field is a number. For the `-l|--level`
|
||||||
|
argument the level **names** are supported as shortcuts. In `-c|--condition`
|
||||||
|
scripts, uppercase symbols like "DEBUG" are defined for convenience.
|
||||||
|
|
||||||
|
Level Name Level Number Symbol in COND Scripts
|
||||||
|
trace 10 TRACE
|
||||||
|
debug 20 DEBUG
|
||||||
|
info 30 INFO
|
||||||
|
warn 40 WARN
|
||||||
|
error 50 ERROR
|
||||||
|
fatal 60 FATAL
|
||||||
|
|
||||||
|
|
||||||
|
## OUTPUT FORMATS
|
||||||
|
|
||||||
|
FORMAT NAME DESCRIPTION
|
||||||
|
long (default) The default output. Long form. Colored and "pretty".
|
||||||
|
'req' and 'res' and 'err' fields are rendered specially
|
||||||
|
as an HTTP request, HTTP response and exception
|
||||||
|
stack trace, respectively. For backward compat, the
|
||||||
|
name "paul" also works for this.
|
||||||
|
short Like the default output, but more concise. Some
|
||||||
|
typically redundant fields are ellided.
|
||||||
|
json JSON output, 2-space indentation.
|
||||||
|
json-N JSON output, N-space indentation, e.g. "json-4"
|
||||||
|
bunyan Alias for "json-0", the Bunyan "native" format.
|
||||||
|
inspect Node.js `util.inspect` output.
|
||||||
|
|
||||||
|
|
||||||
|
## DTRACE SUPPORT
|
||||||
|
|
||||||
|
On systems that support DTrace (e.g., MacOS, FreeBSD, illumos derivatives
|
||||||
|
like SmartOS and OmniOS), Bunyan will create a DTrace provider (`bunyan`)
|
||||||
|
that makes available the following probes:
|
||||||
|
|
||||||
|
log-trace
|
||||||
|
log-debug
|
||||||
|
log-info
|
||||||
|
log-warn
|
||||||
|
log-error
|
||||||
|
log-fatal
|
||||||
|
|
||||||
|
Each of these probes has a single argument: the string that would be
|
||||||
|
written to the log. Note that when a probe is enabled, it will
|
||||||
|
fire whenever the corresponding function is called, even if the level of
|
||||||
|
the log message is less than that of any stream.
|
||||||
|
|
||||||
|
See <https://github.com/trentm/node-bunyan#dtrace-support> for more details
|
||||||
|
and the '-p PID' option above for convenience usage.
|
||||||
|
|
||||||
|
|
||||||
|
## ENVIRONMENT
|
||||||
|
|
||||||
|
* `BUNYAN_NO_COLOR`:
|
||||||
|
Set to a non-empty value to force no output coloring. See '--no-color'.
|
||||||
|
|
||||||
|
|
||||||
|
## PROJECT & BUGS
|
||||||
|
|
||||||
|
`bunyan` is written in JavaScript and requires node.js (`node`). The project
|
||||||
|
lives at <https://github.com/trentm/node-bunyan> and is published to npm as
|
||||||
|
"bunyan".
|
||||||
|
|
||||||
|
* README, Install notes: <https://github.com/trentm/node-bunyan#readme>
|
||||||
|
* Report bugs to <https://github.com/trentm/node-bunyan/issues>.
|
||||||
|
* See the full changelog at: <https://github.com/trentm/node-bunyan/blob/master/CHANGES.md>
|
||||||
|
|
||||||
|
|
||||||
|
## LICENSE
|
||||||
|
|
||||||
|
MIT License (see <https://github.com/trentm/node-bunyan/blob/master/LICENSE.txt>)
|
||||||
|
|
||||||
|
|
||||||
|
## COPYRIGHT
|
||||||
|
|
||||||
|
node-bunyan is Copyright (c) 2012 Joyent, Inc. Copyright (c) 2012 Trent Mick.
|
||||||
|
All rights reserved.
|
BIN
GT2-Android/node_modules/@expo/bunyan/docs/img/bunyan.browserify.png
generated
vendored
Normal file
BIN
GT2-Android/node_modules/@expo/bunyan/docs/img/bunyan.browserify.png
generated
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 194 KiB |
|
@ -0,0 +1 @@
|
||||||
|
<a href="bunyan.1.html">bunyan(1) man page</a>
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
|
@ -0,0 +1,3 @@
|
||||||
|
module.exports = {
|
||||||
|
extends: 'exponent',
|
||||||
|
};
|
|
@ -0,0 +1,27 @@
|
||||||
|
# Logs
|
||||||
|
logs
|
||||||
|
*.log
|
||||||
|
|
||||||
|
# Runtime data
|
||||||
|
pids
|
||||||
|
*.pid
|
||||||
|
*.seed
|
||||||
|
|
||||||
|
# Directory for instrumented libs generated by jscoverage/JSCover
|
||||||
|
lib-cov
|
||||||
|
|
||||||
|
# Coverage directory used by tools like istanbul
|
||||||
|
coverage
|
||||||
|
|
||||||
|
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
|
||||||
|
.grunt
|
||||||
|
|
||||||
|
# node-waf configuration
|
||||||
|
.lock-wscript
|
||||||
|
|
||||||
|
# Compiled binary addons (http://nodejs.org/api/addons.html)
|
||||||
|
build/Release
|
||||||
|
|
||||||
|
# Dependency directory
|
||||||
|
# https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git
|
||||||
|
node_modules
|
|
@ -0,0 +1,204 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
let fsp = require('mz/fs');
|
||||||
|
let _ = require('lodash');
|
||||||
|
let util = require('util');
|
||||||
|
let JSON5 = require('json5');
|
||||||
|
|
||||||
|
let JsonFileError = require('./JsonFileError');
|
||||||
|
|
||||||
|
const DEFAULT_OPTIONS = {
|
||||||
|
badJsonDefault: undefined,
|
||||||
|
cantReadFileDefault: undefined,
|
||||||
|
default: undefined,
|
||||||
|
json5: false,
|
||||||
|
space: 2,
|
||||||
|
};
|
||||||
|
|
||||||
|
class JsonFile {
|
||||||
|
constructor(file, options) {
|
||||||
|
this.file = file;
|
||||||
|
this.options = options;
|
||||||
|
}
|
||||||
|
|
||||||
|
readAsync(options) {
|
||||||
|
return readAsync(this.file, this._getOptions(options));
|
||||||
|
}
|
||||||
|
|
||||||
|
writeAsync(object, options) {
|
||||||
|
return writeAsync(this.file, object, this._getOptions(options));
|
||||||
|
}
|
||||||
|
|
||||||
|
getAsync(key, defaultValue, options) {
|
||||||
|
return getAsync(this.file, key, defaultValue, this._getOptions(options));
|
||||||
|
}
|
||||||
|
|
||||||
|
setAsync(key, value, options) {
|
||||||
|
return setAsync(this.file, key, value, this._getOptions(options));
|
||||||
|
}
|
||||||
|
|
||||||
|
updateAsync(key, value, options) {
|
||||||
|
return updateAsync(this.file, key, value, this._getOptions(options));
|
||||||
|
}
|
||||||
|
|
||||||
|
mergeAsync(sources, options) {
|
||||||
|
return mergeAsync(this.file, sources, this._getOptions(options));
|
||||||
|
}
|
||||||
|
|
||||||
|
deleteKeyAsync(key, options) {
|
||||||
|
return deleteKeyAsync(this.file, key, this._getOptions(options));
|
||||||
|
}
|
||||||
|
|
||||||
|
deleteKeysAsync(keys, options) {
|
||||||
|
return deleteKeysAsync(this.file, keys, this._getOptions(options));
|
||||||
|
}
|
||||||
|
|
||||||
|
rewriteAsync(options) {
|
||||||
|
return rewriteAsync(this.file, this._getOptions(options));
|
||||||
|
}
|
||||||
|
|
||||||
|
_getOptions(options) {
|
||||||
|
return Object.assign({}, this.options, options);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function readAsync(file, options) {
|
||||||
|
var json5 = _getOption(options, 'json5');
|
||||||
|
return fsp.readFile(file, 'utf8').then(json => {
|
||||||
|
try {
|
||||||
|
if (json5) {
|
||||||
|
return JSON5.parse(json);
|
||||||
|
} else {
|
||||||
|
return JSON.parse(json);
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
let defaultValue = jsonParseErrorDefault(options);
|
||||||
|
if (defaultValue === undefined) {
|
||||||
|
throw new JsonFileError(`Error parsing JSON file: ${file}`, e);
|
||||||
|
} else {
|
||||||
|
return defaultValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, error => {
|
||||||
|
let defaultValue = cantReadFileDefault(options);
|
||||||
|
if (defaultValue === undefined) {
|
||||||
|
throw new JsonFileError(`Can't read JSON file: ${file}`, error);
|
||||||
|
} else {
|
||||||
|
return defaultValue;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function getAsync(file, key, defaultValue, options) {
|
||||||
|
return readAsync(file, options).then(object => {
|
||||||
|
if (defaultValue === undefined && !_.has(object, key)) {
|
||||||
|
throw new JsonFileError(
|
||||||
|
`No value at key path "${key}" in JSON object from: ${file}`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return _.get(object, key, defaultValue);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function writeAsync(file, object, options) {
|
||||||
|
var space = _getOption(options, 'space');
|
||||||
|
var json5 = _getOption(options, 'json5');
|
||||||
|
try {
|
||||||
|
var json;
|
||||||
|
if (json5) {
|
||||||
|
json = JSON5.stringify(object, null, space);
|
||||||
|
} else {
|
||||||
|
json = JSON.stringify(object, null, space);
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
throw new JsonFileError(`Couldn't JSON.stringify object for file: ${file}`, e);
|
||||||
|
}
|
||||||
|
return fsp.writeFile(file, json, 'utf8').then(() => object);
|
||||||
|
}
|
||||||
|
|
||||||
|
function setAsync(file, key, value, options) {
|
||||||
|
// TODO: Consider implementing some kind of locking mechanism, but
|
||||||
|
// it's not critical for our use case, so we'll leave it out for now
|
||||||
|
return readAsync(file, options).then(object => {
|
||||||
|
object = _.set(object, key, value);
|
||||||
|
return writeAsync(file, object, options);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
let updateAsync = util.deprecate(setAsync);
|
||||||
|
|
||||||
|
function mergeAsync(file, sources, options) {
|
||||||
|
return readAsync(file, options).then(object => {
|
||||||
|
Object.assign(object, sources);
|
||||||
|
return writeAsync(file, object, options);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function deleteKeyAsync(file, key, options) {
|
||||||
|
return deleteKeysAsync(file, [key], options);
|
||||||
|
}
|
||||||
|
|
||||||
|
function deleteKeysAsync(file, keys, options) {
|
||||||
|
return readAsync(file, options).then(object => {
|
||||||
|
let didDelete = false;
|
||||||
|
|
||||||
|
for (let i = 0; i < keys.length; i++) {
|
||||||
|
let key = keys[i];
|
||||||
|
if (object.hasOwnProperty(key)) {
|
||||||
|
delete object[key];
|
||||||
|
didDelete = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (didDelete) {
|
||||||
|
return writeAsync(file, object, options);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function rewriteAsync(file, options) {
|
||||||
|
return readAsync(file, options).then(object => {
|
||||||
|
return writeAsync(file, object, options);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function jsonParseErrorDefault(options) {
|
||||||
|
options = options || {};
|
||||||
|
if (options.jsonParseErrorDefault === undefined) {
|
||||||
|
return options.default;
|
||||||
|
} else {
|
||||||
|
return options.jsonParseErrorDefault;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function cantReadFileDefault(options) {
|
||||||
|
options = options || {};
|
||||||
|
if (options.cantReadFileDefault === undefined) {
|
||||||
|
return options.default;
|
||||||
|
} else {
|
||||||
|
return options.cantReadFileDefault;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function _getOption(options, field) {
|
||||||
|
if (options) {
|
||||||
|
if (options[field] !== undefined) {
|
||||||
|
return options[field];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return DEFAULT_OPTIONS[field];
|
||||||
|
}
|
||||||
|
|
||||||
|
Object.assign(JsonFile, {
|
||||||
|
readAsync,
|
||||||
|
writeAsync,
|
||||||
|
getAsync,
|
||||||
|
setAsync,
|
||||||
|
updateAsync,
|
||||||
|
mergeAsync,
|
||||||
|
deleteKeyAsync,
|
||||||
|
deleteKeysAsync,
|
||||||
|
rewriteAsync,
|
||||||
|
});
|
||||||
|
|
||||||
|
module.exports = JsonFile;
|
|
@ -0,0 +1,18 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Note that instances of this class do NOT pass `instanceof JsonFileError`.
|
||||||
|
*/
|
||||||
|
class JsonFileError extends Error {
|
||||||
|
constructor(message, cause) {
|
||||||
|
let fullMessage = cause ?
|
||||||
|
`${message}\n└─ Cause: ${cause.name}: ${cause.message}` :
|
||||||
|
message;
|
||||||
|
super(fullMessage);
|
||||||
|
this.name = this.constructor.name;
|
||||||
|
this.cause = cause;
|
||||||
|
this.isJsonFileError = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = JsonFileError;
|
|
@ -0,0 +1,22 @@
|
||||||
|
The MIT License (MIT)
|
||||||
|
|
||||||
|
Copyright (c) 2015 650 Industries
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
|
|
|
@ -0,0 +1,78 @@
|
||||||
|
# json-file
|
||||||
|
A module for reading, writing, and manipulating JSON files
|
||||||
|
|
||||||
|
## Importing the package
|
||||||
|
```js
|
||||||
|
import JsonFile from '@exponent/json-file';
|
||||||
|
```
|
||||||
|
|
||||||
|
## Promise-based async API
|
||||||
|
|
||||||
|
Everything returns `Promise`s. If you are using ES7 (or Babel), you can write code like this:
|
||||||
|
```js
|
||||||
|
let config = await JsonFile.readAsync('config.json', {cantReadFileDefault: {}});
|
||||||
|
```
|
||||||
|
If you are using ES6, you can just use the return values the way you normally would use Promises.
|
||||||
|
```js
|
||||||
|
JsonFile.readAsync('config.json', {cantReadFileDefault: {}}).then(config => {
|
||||||
|
...
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
## Used as an object
|
||||||
|
```js
|
||||||
|
|
||||||
|
var file = new JsonFile('config.json', {cantReadFileDefault: {}});
|
||||||
|
var somethingSaved = await file.getAsync('somethingSaved', null);
|
||||||
|
```
|
||||||
|
|
||||||
|
## Used as functions
|
||||||
|
```js
|
||||||
|
|
||||||
|
var pkg = await JsonFile.readAsync('package.json');
|
||||||
|
var main = await JsonFile.getAsync('package.json', 'main', 'index.js');
|
||||||
|
...
|
||||||
|
```
|
||||||
|
|
||||||
|
## Options you can set, and their default values
|
||||||
|
|
||||||
|
|Option | Description | Default Value|
|
||||||
|
|-------|-------------|--------------|
|
||||||
|
|`space`|How many spaces to use when pretty-printing, (0 for no pretty-printing)|`2`|
|
||||||
|
|`default`|Catch-all default value for missing values, bad JSON, and files that can't be read|`undefined`|
|
||||||
|
|`jsonParseErrorDefault`|The default value for when a file is read but it doesn't contain valid JSON|`undefined`|
|
||||||
|
|`cantReadFileDefault`|The default value for when a file can't be read|`undefined`|
|
||||||
|
|
||||||
|
* Note that if defaults are `undefined`, then an `Error` will be thrown instead of `undefined` being returned
|
||||||
|
|
||||||
|
## Methods
|
||||||
|
|
||||||
|
#### .readAsync([options])
|
||||||
|
|
||||||
|
Returns the parse of the whole file as an object
|
||||||
|
|
||||||
|
#### .getAsync(key, [default-value], [options])
|
||||||
|
|
||||||
|
Returns a single value from a JSON file, using lodash's `_.get` to query the whole object.
|
||||||
|
|
||||||
|
See https://lodash.com/docs#get
|
||||||
|
|
||||||
|
#### .writeAsync(data, [options])
|
||||||
|
|
||||||
|
Writes out the given data to the file
|
||||||
|
|
||||||
|
#### .setAsync(key, val, [options])
|
||||||
|
|
||||||
|
Updates the file, inserting or updating the value for `<key>` with `<val>`
|
||||||
|
|
||||||
|
#### .mergeAsync(sources, [options])
|
||||||
|
|
||||||
|
Merges the values in `<sources>` into the object currently encoded in the file.
|
||||||
|
|
||||||
|
#### .deleteKeyAsync(key, [options])
|
||||||
|
|
||||||
|
Deletes a single key from the top level of the file.
|
||||||
|
|
||||||
|
## Functions
|
||||||
|
|
||||||
|
The functions available all mirror the methods above but take `file` (filename as a string) as their first argument.
|
35
GT2-Android/node_modules/@expo/json-file/__tests__/JsonFile-test.js
generated
vendored
Normal file
35
GT2-Android/node_modules/@expo/json-file/__tests__/JsonFile-test.js
generated
vendored
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
let JsonFile = require('../JsonFile');
|
||||||
|
|
||||||
|
describe('JsonFile', () => {
|
||||||
|
it(`is a class`, () => {
|
||||||
|
let file = new JsonFile('../package.json');
|
||||||
|
expect(file instanceof JsonFile).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it(`has static functions`, () => {
|
||||||
|
expect(JsonFile.readAsync).toBeDefined();
|
||||||
|
expect(JsonFile.writeAsync).toBeDefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
pit(`reads JSON from a file`, () => {
|
||||||
|
let file = new JsonFile('./package.json');
|
||||||
|
return file.readAsync().then(object => {
|
||||||
|
expect(object.version).toBeDefined();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
pit(`reads JSON statically from a file`, () => {
|
||||||
|
return JsonFile.readAsync('./package.json').then(object => {
|
||||||
|
expect(object.version).toBeDefined();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
pit(`reads JSON5 from a file`, () => {
|
||||||
|
let file = new JsonFile('./test-json5.json', {json5: true});
|
||||||
|
return file.readAsync().then(object => {
|
||||||
|
expect(object.itParsedProperly).toBe(42);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
23
GT2-Android/node_modules/@expo/json-file/__tests__/JsonFileError-test.js
generated
vendored
Normal file
23
GT2-Android/node_modules/@expo/json-file/__tests__/JsonFileError-test.js
generated
vendored
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
let JsonFileError = require('../JsonFileError');
|
||||||
|
|
||||||
|
describe('JsonFileError', () => {
|
||||||
|
it(`is an error`, () => {
|
||||||
|
let error = new JsonFileError('Example');
|
||||||
|
expect(error instanceof Error).toBe(true);
|
||||||
|
expect(error instanceof JsonFileError).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it(`has a flag that says it's a JsonFileError`, () => {
|
||||||
|
let error = new JsonFileError('Example');
|
||||||
|
expect(error.isJsonFileError).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it(`includes its cause`, () => {
|
||||||
|
let cause = new Error('Root cause');
|
||||||
|
let error = new JsonFileError('Example', cause);
|
||||||
|
expect(error.cause).toBe(cause);
|
||||||
|
expect(error.message).toMatch(cause.message);
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,7 @@
|
||||||
|
machine:
|
||||||
|
node:
|
||||||
|
version: node
|
||||||
|
|
||||||
|
dependencies:
|
||||||
|
override:
|
||||||
|
- npm prune && npm install
|
|
@ -0,0 +1,100 @@
|
||||||
|
{
|
||||||
|
"_args": [
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"raw": "@expo/json-file@^5.3.0",
|
||||||
|
"scope": "@expo",
|
||||||
|
"escapedName": "@expo%2fjson-file",
|
||||||
|
"name": "@expo/json-file",
|
||||||
|
"rawSpec": "^5.3.0",
|
||||||
|
"spec": ">=5.3.0 <6.0.0",
|
||||||
|
"type": "range"
|
||||||
|
},
|
||||||
|
"/home/jdaugherty/work/GT2/GT2-Android/node_modules/xdl"
|
||||||
|
]
|
||||||
|
],
|
||||||
|
"_from": "@expo/json-file@>=5.3.0 <6.0.0",
|
||||||
|
"_id": "@expo/json-file@5.3.0",
|
||||||
|
"_inCache": true,
|
||||||
|
"_location": "/@expo/json-file",
|
||||||
|
"_nodeVersion": "8.0.0",
|
||||||
|
"_npmOperationalInternal": {
|
||||||
|
"host": "s3://npm-registry-packages",
|
||||||
|
"tmp": "tmp/json-file-5.3.0.tgz_1499121624137_0.2968416837975383"
|
||||||
|
},
|
||||||
|
"_npmUser": {
|
||||||
|
"name": "wilzh40",
|
||||||
|
"email": "wilzh40@gmail.com"
|
||||||
|
},
|
||||||
|
"_npmVersion": "4.2.0",
|
||||||
|
"_phantomChildren": {},
|
||||||
|
"_requested": {
|
||||||
|
"raw": "@expo/json-file@^5.3.0",
|
||||||
|
"scope": "@expo",
|
||||||
|
"escapedName": "@expo%2fjson-file",
|
||||||
|
"name": "@expo/json-file",
|
||||||
|
"rawSpec": "^5.3.0",
|
||||||
|
"spec": ">=5.3.0 <6.0.0",
|
||||||
|
"type": "range"
|
||||||
|
},
|
||||||
|
"_requiredBy": [
|
||||||
|
"/xdl"
|
||||||
|
],
|
||||||
|
"_resolved": "https://registry.npmjs.org/@expo/json-file/-/json-file-5.3.0.tgz",
|
||||||
|
"_shasum": "9274fd22e68cfdcae1f06aed8d2d1f953a4f7168",
|
||||||
|
"_shrinkwrap": null,
|
||||||
|
"_spec": "@expo/json-file@^5.3.0",
|
||||||
|
"_where": "/home/jdaugherty/work/GT2/GT2-Android/node_modules/xdl",
|
||||||
|
"author": {
|
||||||
|
"name": "support@expo.io"
|
||||||
|
},
|
||||||
|
"bugs": {
|
||||||
|
"url": "https://github.com/expo/json-file/issues"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"json5": "^0.5.0",
|
||||||
|
"lodash": "^4.6.1",
|
||||||
|
"mz": "^2.6.0"
|
||||||
|
},
|
||||||
|
"description": "A module for reading, writing, and manipulating JSON files",
|
||||||
|
"devDependencies": {
|
||||||
|
"babel-eslint": "^6.0.0",
|
||||||
|
"eslint": "^2.5.3",
|
||||||
|
"eslint-config-expo": "^1.0.7",
|
||||||
|
"eslint-plugin-react": "^4.2.3",
|
||||||
|
"jest-cli": "^12.1.1"
|
||||||
|
},
|
||||||
|
"directories": {},
|
||||||
|
"dist": {
|
||||||
|
"shasum": "9274fd22e68cfdcae1f06aed8d2d1f953a4f7168",
|
||||||
|
"tarball": "https://registry.npmjs.org/@expo/json-file/-/json-file-5.3.0.tgz"
|
||||||
|
},
|
||||||
|
"gitHead": "2d1d9e52d13aaf8896a82164043db361607d296f",
|
||||||
|
"homepage": "https://github.com/expo/json-file#readme",
|
||||||
|
"jest": {
|
||||||
|
"automock": false
|
||||||
|
},
|
||||||
|
"keywords": [
|
||||||
|
"json"
|
||||||
|
],
|
||||||
|
"license": "MIT",
|
||||||
|
"main": "JsonFile.js",
|
||||||
|
"maintainers": [
|
||||||
|
{
|
||||||
|
"name": "wilzh40",
|
||||||
|
"email": "wilzh40@gmail.com"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "@expo/json-file",
|
||||||
|
"optionalDependencies": {},
|
||||||
|
"readme": "# json-file\nA module for reading, writing, and manipulating JSON files\n\n## Importing the package\n```js\nimport JsonFile from '@exponent/json-file';\n```\n\n## Promise-based async API\n\nEverything returns `Promise`s. If you are using ES7 (or Babel), you can write code like this:\n```js\nlet config = await JsonFile.readAsync('config.json', {cantReadFileDefault: {}});\n```\nIf you are using ES6, you can just use the return values the way you normally would use Promises.\n```js\nJsonFile.readAsync('config.json', {cantReadFileDefault: {}}).then(config => {\n ...\n});\n```\n\n## Used as an object\n```js\n\nvar file = new JsonFile('config.json', {cantReadFileDefault: {}});\nvar somethingSaved = await file.getAsync('somethingSaved', null);\n```\n\n## Used as functions\n```js\n\nvar pkg = await JsonFile.readAsync('package.json');\nvar main = await JsonFile.getAsync('package.json', 'main', 'index.js');\n...\n```\n\n## Options you can set, and their default values\n\n|Option | Description | Default Value|\n|-------|-------------|--------------|\n|`space`|How many spaces to use when pretty-printing, (0 for no pretty-printing)|`2`|\n|`default`|Catch-all default value for missing values, bad JSON, and files that can't be read|`undefined`|\n|`jsonParseErrorDefault`|The default value for when a file is read but it doesn't contain valid JSON|`undefined`|\n|`cantReadFileDefault`|The default value for when a file can't be read|`undefined`|\n\n* Note that if defaults are `undefined`, then an `Error` will be thrown instead of `undefined` being returned\n\n## Methods\n\n#### .readAsync([options])\n\nReturns the parse of the whole file as an object\n\n#### .getAsync(key, [default-value], [options])\n\nReturns a single value from a JSON file, using lodash's `_.get` to query the whole object.\n\nSee https://lodash.com/docs#get\n\n#### .writeAsync(data, [options])\n\nWrites out the given data to the file\n\n#### .setAsync(key, val, [options])\n\nUpdates the file, inserting or updating the value for `<key>` with `<val>`\n\n#### .mergeAsync(sources, [options])\n\nMerges the values in `<sources>` into the object currently encoded in the file.\n\n#### .deleteKeyAsync(key, [options])\n\nDeletes a single key from the top level of the file.\n\n## Functions\n\nThe functions available all mirror the methods above but take `file` (filename as a string) as their first argument.\n",
|
||||||
|
"readmeFilename": "README.md",
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "git+https://github.com/expo/json-file.git"
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"test": "jest --no-cache"
|
||||||
|
},
|
||||||
|
"version": "5.3.0"
|
||||||
|
}
|
|
@ -0,0 +1,15 @@
|
||||||
|
{
|
||||||
|
'3': 4,
|
||||||
|
// Another comment!
|
||||||
|
'5': {
|
||||||
|
'6': {
|
||||||
|
/* Comment comment comment! */
|
||||||
|
'7': 8
|
||||||
|
},
|
||||||
|
'9': 10
|
||||||
|
},
|
||||||
|
'11': 12,
|
||||||
|
itParsedProperly: 42,
|
||||||
|
score: 5,
|
||||||
|
x: 'z'
|
||||||
|
}
|
|
@ -0,0 +1,12 @@
|
||||||
|
{
|
||||||
|
"3": 4,
|
||||||
|
"5": {
|
||||||
|
"6": {
|
||||||
|
"7": 8
|
||||||
|
},
|
||||||
|
"9": 10
|
||||||
|
},
|
||||||
|
"11": 12,
|
||||||
|
"score": 5,
|
||||||
|
"x": "z"
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,7 @@
|
||||||
|
2.1.5
|
||||||
|
==================
|
||||||
|
|
||||||
|
* flawless use of latest ngrok 2.1.1
|
||||||
|
* major subdomain [issue](https://github.com/bubenshchykov/ngrok/issues/34) fixed
|
||||||
|
* specs covering 3 groups of use: without authtoken, with free authtoken and with paid authtoken
|
||||||
|
* breaking: env var for changing ngrok cdn renamed to NGROK_CDN_URL, path to bins changed too
|
|
@ -0,0 +1,98 @@
|
||||||
|
ngrok [![Build Status](https://travis-ci.org/bubenshchykov/ngrok.png?branch=master)](https://travis-ci.org/bubenshchykov/ngrok)
|
||||||
|
=====
|
||||||
|
|
||||||
|
![alt ngrok.com](https://ngrok.com/static/img/overview.png)
|
||||||
|
|
||||||
|
Ngrok exposes your localhost to the web. https://ngrok.com/
|
||||||
|
|
||||||
|
usage
|
||||||
|
===
|
||||||
|
|
||||||
|
[![NPM](https://nodei.co/npm/ngrok.png?global=true&&downloads=true&downloadRank=true&stars=true)](https://nodei.co/npm/ngrok/)
|
||||||
|
|
||||||
|
```
|
||||||
|
var ngrok = require('ngrok');
|
||||||
|
ngrok.connect(function (err, url) {});
|
||||||
|
|
||||||
|
or
|
||||||
|
|
||||||
|
npm install ngrok -g
|
||||||
|
ngrok http 8080
|
||||||
|
```
|
||||||
|
|
||||||
|
## authtoken
|
||||||
|
You can create basic http-https-tcp tunnel without authtoken. For custom subdomains and more you should obtain authtoken by signing up at [ngrok.com](https://ngrok.com). Once you set it, it's stored in ngrok config and used for all tunnels. Few ways:
|
||||||
|
|
||||||
|
```
|
||||||
|
ngrok.authtoken(token, function(err, token) {});
|
||||||
|
ngrok.connect({authtoken: token, ...}, function (err, url) {});
|
||||||
|
ngrok authtoken <token>
|
||||||
|
```
|
||||||
|
|
||||||
|
## connect
|
||||||
|
```javascript
|
||||||
|
var ngrok = require('ngrok');
|
||||||
|
|
||||||
|
ngrok.connect(function (err, url) {}); // https://757c1652.ngrok.io -> http://localhost:80
|
||||||
|
ngrok.connect(9090, function (err, url) {}); // https://757c1652.ngrok.io -> http://localhost:9090
|
||||||
|
ngrok.connect({proto: 'tcp', addr: 22}, function (err, url) {}); // tcp://0.tcp.ngrok.io:48590
|
||||||
|
ngrok.connect(opts, function(err, url) {});
|
||||||
|
```
|
||||||
|
|
||||||
|
## options
|
||||||
|
```javascript
|
||||||
|
ngrok.connect({
|
||||||
|
proto: 'http', // http|tcp|tls
|
||||||
|
addr: 8080, // port or network address
|
||||||
|
auth: 'user:pwd', // http basic authentication for tunnel
|
||||||
|
subdomain: 'alex', // reserved tunnel name https://alex.ngrok.io
|
||||||
|
authtoken: '12345', // your authtoken from ngrok.com
|
||||||
|
region: 'us' // one of ngrok regions (us, eu, au, ap), defaults to us
|
||||||
|
}, function (err, url) {});
|
||||||
|
```
|
||||||
|
|
||||||
|
Other options: `name, inspect, host_header, bind_tls, hostname, crt, key, client_cas, remote_addr` - read [here](https://ngrok.com/docs)
|
||||||
|
|
||||||
|
Note on regions: region used in first tunnel will be used for all next tunnels too.
|
||||||
|
|
||||||
|
## disconnect
|
||||||
|
The ngrok and all tunnels will be killed when node process is done. To stop the tunnels use
|
||||||
|
```javascript
|
||||||
|
ngrok.disconnect(url); // stops one
|
||||||
|
ngrok.disconnect(); // stops all
|
||||||
|
ngrok.kill(); // kills ngrok process
|
||||||
|
```
|
||||||
|
|
||||||
|
Note on http tunnels: by default bind_tls is true, so whenever you use http proto two tunnels are created - http and https. If you disconnect https tunnel, http tunnel remains open. You might want to close them both by passing http-version url, or simply by disconnecting all in one go ```ngrok.disconnect()```.
|
||||||
|
|
||||||
|
## emitter
|
||||||
|
Also you can use ngrok as an event emitter, it fires "connect", "disconnect" and "error" events
|
||||||
|
```javascript
|
||||||
|
ngrok.once('connect', function (url) {};
|
||||||
|
ngrok.connect(port);
|
||||||
|
```
|
||||||
|
|
||||||
|
## configs
|
||||||
|
You can use ngrok's [configurations files](https://ngrok.com/docs#config), then just pass `name` option when making a tunnel. Configuration files allow to specify more options, eg ngrok region you want to use.
|
||||||
|
```
|
||||||
|
OS X /Users/example/.ngrok2/ngrok.yml
|
||||||
|
Linux /home/example/.ngrok2/ngrok.yml
|
||||||
|
Windows C:\Users\example\.ngrok2\ngrok.yml
|
||||||
|
```
|
||||||
|
|
||||||
|
## inspector
|
||||||
|
When tunnel is established you can use the ngrok interface http://127.0.0.1:4040 to inspect the webhooks done via ngrok.
|
||||||
|
|
||||||
|
## process
|
||||||
|
To get a handle to the spawned ngrok process use
|
||||||
|
```javascript
|
||||||
|
ngrok.process(); // returns ChildProcess
|
||||||
|
```
|
||||||
|
|
||||||
|
## how it works
|
||||||
|
npm install downloads ngrok binaries for you platform and puts them into bin folder. You can host binaries yourself and set NGROK_CDN_URL env var before installing ngrok. Or you can force specific arch by setting NGROK_ARCH, eg NGROK_ARCH=freebsdia32
|
||||||
|
|
||||||
|
First time you create tunnel ngrok process is spawned and runs until you disconnect or when parent process killed. All further tunnels are created or stopped by using internal ngrok api which usually runs on http://127.0.0.1:4040
|
||||||
|
|
||||||
|
## contributors
|
||||||
|
Please run ```git update-index --assume-unchanged bin/ngrok``` to not override [ngrok stub](https://github.com/bubenshchykov/ngrok/blob/master/bin/ngrok) in your pr. Unfortunately it can't be gitignored.
|
Binary file not shown.
BIN
GT2-Android/node_modules/@expo/ngrok/bin/ngrok-stable-darwin-ia32.zip
generated
vendored
Normal file
BIN
GT2-Android/node_modules/@expo/ngrok/bin/ngrok-stable-darwin-ia32.zip
generated
vendored
Normal file
Binary file not shown.
BIN
GT2-Android/node_modules/@expo/ngrok/bin/ngrok-stable-darwin-x64.zip
generated
vendored
Normal file
BIN
GT2-Android/node_modules/@expo/ngrok/bin/ngrok-stable-darwin-x64.zip
generated
vendored
Normal file
Binary file not shown.
BIN
GT2-Android/node_modules/@expo/ngrok/bin/ngrok-stable-freebsd-ia32.zip
generated
vendored
Normal file
BIN
GT2-Android/node_modules/@expo/ngrok/bin/ngrok-stable-freebsd-ia32.zip
generated
vendored
Normal file
Binary file not shown.
BIN
GT2-Android/node_modules/@expo/ngrok/bin/ngrok-stable-freebsd-x64.zip
generated
vendored
Normal file
BIN
GT2-Android/node_modules/@expo/ngrok/bin/ngrok-stable-freebsd-x64.zip
generated
vendored
Normal file
Binary file not shown.
BIN
GT2-Android/node_modules/@expo/ngrok/bin/ngrok-stable-linux-arm.zip
generated
vendored
Normal file
BIN
GT2-Android/node_modules/@expo/ngrok/bin/ngrok-stable-linux-arm.zip
generated
vendored
Normal file
Binary file not shown.
BIN
GT2-Android/node_modules/@expo/ngrok/bin/ngrok-stable-linux-ia32.zip
generated
vendored
Normal file
BIN
GT2-Android/node_modules/@expo/ngrok/bin/ngrok-stable-linux-ia32.zip
generated
vendored
Normal file
Binary file not shown.
BIN
GT2-Android/node_modules/@expo/ngrok/bin/ngrok-stable-linux-x64.zip
generated
vendored
Normal file
BIN
GT2-Android/node_modules/@expo/ngrok/bin/ngrok-stable-linux-x64.zip
generated
vendored
Normal file
Binary file not shown.
BIN
GT2-Android/node_modules/@expo/ngrok/bin/ngrok-stable-win32-ia32.zip
generated
vendored
Normal file
BIN
GT2-Android/node_modules/@expo/ngrok/bin/ngrok-stable-win32-ia32.zip
generated
vendored
Normal file
Binary file not shown.
BIN
GT2-Android/node_modules/@expo/ngrok/bin/ngrok-stable-win32-x64.zip
generated
vendored
Normal file
BIN
GT2-Android/node_modules/@expo/ngrok/bin/ngrok-stable-win32-x64.zip
generated
vendored
Normal file
Binary file not shown.
|
@ -0,0 +1,3 @@
|
||||||
|
authtoken: 5W1bR67GNbWcXqmxZzBG1_56GezNeaX6sSRvn8npeQ8
|
||||||
|
json_resolver_url: ""
|
||||||
|
dns_resolver_ips: []
|
|
@ -0,0 +1,263 @@
|
||||||
|
var request = require('request');
|
||||||
|
var spawn = require('child_process').spawn;
|
||||||
|
var Emitter = require('events').EventEmitter;
|
||||||
|
var platform = require('os').platform();
|
||||||
|
var lock = require('lock')();
|
||||||
|
var async = require('async');
|
||||||
|
var uuid = require('uuid');
|
||||||
|
var url = require('url');
|
||||||
|
var logfmt = require('logfmt');
|
||||||
|
|
||||||
|
var bin = './ngrok' + (platform === 'win32' ? '.exe' : '');
|
||||||
|
|
||||||
|
var noop = function() {};
|
||||||
|
var emitter = new Emitter().on('error', noop);
|
||||||
|
var ngrok, api, tunnels = {};
|
||||||
|
|
||||||
|
function connect(opts, cb) {
|
||||||
|
|
||||||
|
if (typeof opts === 'function') {
|
||||||
|
cb = opts;
|
||||||
|
}
|
||||||
|
|
||||||
|
cb = cb || noop;
|
||||||
|
opts = defaults(opts);
|
||||||
|
|
||||||
|
if (api) {
|
||||||
|
return runTunnel(opts, cb);
|
||||||
|
}
|
||||||
|
|
||||||
|
lock('ngrok', function(release) {
|
||||||
|
function run(err) {
|
||||||
|
if (err) {
|
||||||
|
emitter.emit('error', err);
|
||||||
|
return cb(err);
|
||||||
|
}
|
||||||
|
runNgrok(opts, release(function(err) {
|
||||||
|
if (err) {
|
||||||
|
emitter.emit('error', err);
|
||||||
|
return cb(err);
|
||||||
|
}
|
||||||
|
runTunnel(opts, cb)
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
opts.authtoken ?
|
||||||
|
authtoken(opts.authtoken, opts.configPath, run) :
|
||||||
|
run(null);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function defaults(opts) {
|
||||||
|
opts = opts || {proto: 'http', addr: 80};
|
||||||
|
|
||||||
|
if (typeof opts === 'function') {
|
||||||
|
opts = {proto: 'http', addr: 80};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof opts !== 'object') {
|
||||||
|
opts = {proto: 'http', addr: opts};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!opts.proto) {
|
||||||
|
opts.proto = 'http';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!opts.addr) {
|
||||||
|
opts.addr = opts.port || opts.host || 80;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (opts.httpauth) {
|
||||||
|
opts.auth = opts.httpauth;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (['us', 'eu', 'au', 'ap'].indexOf(opts.region) === -1) {
|
||||||
|
opts.region = 'us';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!opts.configPath) {
|
||||||
|
opts.configPath = '~/.ngrok2/ngrok.yml';
|
||||||
|
}
|
||||||
|
|
||||||
|
return opts;
|
||||||
|
}
|
||||||
|
|
||||||
|
function runNgrok(opts, cb) {
|
||||||
|
if (api) {
|
||||||
|
return cb();
|
||||||
|
}
|
||||||
|
|
||||||
|
emitter.emit('statuschange', 'starting');
|
||||||
|
|
||||||
|
ngrok = spawn(
|
||||||
|
bin,
|
||||||
|
['start', '--none', '--log=stdout', '--region=' + opts.region, '-config=' + opts.configPath],
|
||||||
|
{cwd: __dirname + '/bin'});
|
||||||
|
|
||||||
|
ngrok.stdout.on('data', function (chunk) {
|
||||||
|
var lines = chunk.toString().split(/\r?\n/);
|
||||||
|
lines.forEach(function (line) {
|
||||||
|
if (!line) return;
|
||||||
|
var data = logfmt.parse(line);
|
||||||
|
if (data.obj === 'web' && data.msg === 'starting web service' && data.addr) {
|
||||||
|
api = request.defaults({
|
||||||
|
baseUrl: 'http://' + data.addr,
|
||||||
|
json: true
|
||||||
|
});
|
||||||
|
cb();
|
||||||
|
} else if (data.obj === 'csess' && data.msg === 'session closed, starting reconnect loop') {
|
||||||
|
emitter.emit('statuschange', 'reconnecting');
|
||||||
|
} else if (data.obj === 'csess' && data.msg === 'client session established') {
|
||||||
|
emitter.emit('statuschange', 'online');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
ngrok.stderr.on('data', function (data) {
|
||||||
|
var info = data.toString().substring(0, 10000);
|
||||||
|
return cb(new Error(info));
|
||||||
|
});
|
||||||
|
|
||||||
|
ngrok.on('exit', function () {
|
||||||
|
ngrok = null;
|
||||||
|
api = null;
|
||||||
|
tunnels = {};
|
||||||
|
});
|
||||||
|
|
||||||
|
ngrok.on('close', function () {
|
||||||
|
return emitter.emit('close');
|
||||||
|
});
|
||||||
|
|
||||||
|
process.on('exit', function() {
|
||||||
|
kill();
|
||||||
|
});
|
||||||
|
|
||||||
|
ngrok.on('error', function(err) {
|
||||||
|
cb(err);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function runTunnel(opts, cb) {
|
||||||
|
_runTunnel(opts, function(err, publicUrl, uiUrl) {
|
||||||
|
if (err) {
|
||||||
|
emitter.emit('error', err);
|
||||||
|
return cb(err);
|
||||||
|
}
|
||||||
|
emitter.emit('connect', publicUrl, uiUrl);
|
||||||
|
return cb(null, publicUrl, uiUrl);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function _runTunnel(opts, cb) {
|
||||||
|
var retries = 100;
|
||||||
|
opts.name = String(opts.name || uuid.v4());
|
||||||
|
var retry = function() {
|
||||||
|
api.post(
|
||||||
|
{url: 'api/tunnels', json: opts},
|
||||||
|
function(err, resp, body) {
|
||||||
|
if (err) {
|
||||||
|
return cb(err);
|
||||||
|
}
|
||||||
|
var notReady = resp.statusCode === 500 && /panic/.test(body) ||
|
||||||
|
resp.statusCode === 502 && body.details &&
|
||||||
|
body.details.err === 'tunnel session not ready yet';
|
||||||
|
|
||||||
|
if (notReady) {
|
||||||
|
return retries-- ?
|
||||||
|
setTimeout(retry, 200) :
|
||||||
|
cb(new Error(body));
|
||||||
|
}
|
||||||
|
var publicUrl = body && body.public_url;
|
||||||
|
if (!publicUrl) {
|
||||||
|
var err = Object.assign(new Error(body.msg || 'failed to start tunnel'), body);
|
||||||
|
return cb(err);
|
||||||
|
}
|
||||||
|
tunnels[publicUrl] = body.uri;
|
||||||
|
if (opts.proto === 'http' && opts.bind_tls !== false) {
|
||||||
|
tunnels[publicUrl.replace('https', 'http')] = body.uri + ' (http)';
|
||||||
|
}
|
||||||
|
var uiUrl = url.parse(resp.request.uri);
|
||||||
|
uiUrl = uiUrl.resolve('/').slice(0, -1);
|
||||||
|
return cb(null, publicUrl, uiUrl);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
retry();
|
||||||
|
}
|
||||||
|
|
||||||
|
function authtoken(token, configPath, cb) {
|
||||||
|
cb = cb || noop;
|
||||||
|
var a = spawn(
|
||||||
|
bin,
|
||||||
|
['authtoken', token, '-config=' + configPath],
|
||||||
|
{cwd: __dirname + '/bin'});
|
||||||
|
a.stdout.once('data', done.bind(null, null, token));
|
||||||
|
a.stderr.once('data', done.bind(null, new Error('cant set authtoken')));
|
||||||
|
a.on('error', function(err) {
|
||||||
|
cb(err);
|
||||||
|
});
|
||||||
|
|
||||||
|
function done(err, token) {
|
||||||
|
cb(err, token);
|
||||||
|
a.kill();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function disconnect(publicUrl, cb) {
|
||||||
|
cb = cb || noop;
|
||||||
|
if (typeof publicUrl === 'function') {
|
||||||
|
cb = publicUrl;
|
||||||
|
publicUrl = null;
|
||||||
|
}
|
||||||
|
if (!api) {
|
||||||
|
return cb();
|
||||||
|
}
|
||||||
|
if (publicUrl) {
|
||||||
|
return api.del(
|
||||||
|
tunnels[publicUrl],
|
||||||
|
function(err, resp, body) {
|
||||||
|
if (err || resp.statusCode !== 204) {
|
||||||
|
return cb(err || new Error(body));
|
||||||
|
}
|
||||||
|
delete tunnels[publicUrl];
|
||||||
|
emitter.emit('disconnect', publicUrl);
|
||||||
|
return cb();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return async.each(
|
||||||
|
Object.keys(tunnels),
|
||||||
|
disconnect,
|
||||||
|
function(err) {
|
||||||
|
if (err) {
|
||||||
|
emitter.emit('error', err);
|
||||||
|
return cb(err);
|
||||||
|
}
|
||||||
|
emitter.emit('disconnect');
|
||||||
|
return cb();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function kill(cb) {
|
||||||
|
cb = cb || noop;
|
||||||
|
if (!ngrok) {
|
||||||
|
return cb();
|
||||||
|
}
|
||||||
|
ngrok.on('exit', function() {
|
||||||
|
emitter.emit('disconnect');
|
||||||
|
return cb();
|
||||||
|
});
|
||||||
|
return ngrok.kill();
|
||||||
|
}
|
||||||
|
|
||||||
|
function ngrokProcess() {
|
||||||
|
return ngrok;
|
||||||
|
}
|
||||||
|
|
||||||
|
emitter.connect = connect;
|
||||||
|
emitter.disconnect = disconnect;
|
||||||
|
emitter.authtoken = authtoken;
|
||||||
|
emitter.kill = kill;
|
||||||
|
emitter.process = ngrokProcess;
|
||||||
|
|
||||||
|
module.exports = emitter;
|
|
@ -0,0 +1,154 @@
|
||||||
|
{
|
||||||
|
"_args": [
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"raw": "@expo/ngrok@2.3.0",
|
||||||
|
"scope": "@expo",
|
||||||
|
"escapedName": "@expo%2fngrok",
|
||||||
|
"name": "@expo/ngrok",
|
||||||
|
"rawSpec": "2.3.0",
|
||||||
|
"spec": "2.3.0",
|
||||||
|
"type": "version"
|
||||||
|
},
|
||||||
|
"/home/jdaugherty/work/GT2/GT2-Android/node_modules/xdl"
|
||||||
|
]
|
||||||
|
],
|
||||||
|
"_from": "@expo/ngrok@2.3.0",
|
||||||
|
"_id": "@expo/ngrok@2.3.0",
|
||||||
|
"_inCache": true,
|
||||||
|
"_location": "/@expo/ngrok",
|
||||||
|
"_nodeVersion": "8.5.0",
|
||||||
|
"_npmOperationalInternal": {
|
||||||
|
"host": "s3://npm-registry-packages",
|
||||||
|
"tmp": "tmp/ngrok-2.3.0.tgz_1510858119484_0.08566191466525197"
|
||||||
|
},
|
||||||
|
"_npmUser": {
|
||||||
|
"name": "fson",
|
||||||
|
"email": "ville.immonen@iki.fi"
|
||||||
|
},
|
||||||
|
"_npmVersion": "5.5.1",
|
||||||
|
"_phantomChildren": {},
|
||||||
|
"_requested": {
|
||||||
|
"raw": "@expo/ngrok@2.3.0",
|
||||||
|
"scope": "@expo",
|
||||||
|
"escapedName": "@expo%2fngrok",
|
||||||
|
"name": "@expo/ngrok",
|
||||||
|
"rawSpec": "2.3.0",
|
||||||
|
"spec": "2.3.0",
|
||||||
|
"type": "version"
|
||||||
|
},
|
||||||
|
"_requiredBy": [
|
||||||
|
"/xdl"
|
||||||
|
],
|
||||||
|
"_resolved": "https://registry.npmjs.org/@expo/ngrok/-/ngrok-2.3.0.tgz",
|
||||||
|
"_shasum": "e6c37c74c2ede6c32f04b13d30383e10255908d3",
|
||||||
|
"_shrinkwrap": null,
|
||||||
|
"_spec": "@expo/ngrok@2.3.0",
|
||||||
|
"_where": "/home/jdaugherty/work/GT2/GT2-Android/node_modules/xdl",
|
||||||
|
"author": {
|
||||||
|
"name": "bubenshchykov"
|
||||||
|
},
|
||||||
|
"bin": {
|
||||||
|
"ngrok": "./bin/ngrok"
|
||||||
|
},
|
||||||
|
"bugs": {
|
||||||
|
"url": "https://github.com/expo/ngrok/issues"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"async": "^0.9.0",
|
||||||
|
"decompress-zip": "^0.3.0",
|
||||||
|
"lock": "^0.1.2",
|
||||||
|
"logfmt": "^1.2.0",
|
||||||
|
"request": "^2.81.0",
|
||||||
|
"uuid": "^3.0.0"
|
||||||
|
},
|
||||||
|
"description": "node wrapper for ngrok",
|
||||||
|
"devDependencies": {
|
||||||
|
"chai": "~1.8.1",
|
||||||
|
"homedir": "^0.6.0",
|
||||||
|
"mocha": "~1.14.0",
|
||||||
|
"sinon": "^4.1.2"
|
||||||
|
},
|
||||||
|
"directories": {},
|
||||||
|
"dist": {
|
||||||
|
"integrity": "sha512-zLAl2gzBs4ddqnmYYVTzQpxnTlF8iK/CMWNpngZfgrhrmzDVzTNNy4+hu0PjKuXIubfyWHy+wtp+wgewOUj9KA==",
|
||||||
|
"shasum": "e6c37c74c2ede6c32f04b13d30383e10255908d3",
|
||||||
|
"tarball": "https://registry.npmjs.org/@expo/ngrok/-/ngrok-2.3.0.tgz"
|
||||||
|
},
|
||||||
|
"files": [
|
||||||
|
"index.js",
|
||||||
|
"postinstall.js",
|
||||||
|
"bin"
|
||||||
|
],
|
||||||
|
"gitHead": "0b82126f3f877244f9a2022084fffeb016f2ce82",
|
||||||
|
"homepage": "https://github.com/expo/ngrok#readme",
|
||||||
|
"keywords": [
|
||||||
|
"ngrok",
|
||||||
|
"localhost",
|
||||||
|
"tunneling",
|
||||||
|
"localtunnel",
|
||||||
|
"webhook"
|
||||||
|
],
|
||||||
|
"license": "BSD-2-Clause",
|
||||||
|
"main": "index.js",
|
||||||
|
"maintainers": [
|
||||||
|
{
|
||||||
|
"name": "fson",
|
||||||
|
"email": "ville.immonen@iki.fi"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "abi",
|
||||||
|
"email": "abimanyuraja@gmail.com"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "jesseruder",
|
||||||
|
"email": "jesse@sixfivezero.net"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "terribleben",
|
||||||
|
"email": "ben@exp.host"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "ccheever",
|
||||||
|
"email": "ccheever@gmail.com"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "dikaiosune",
|
||||||
|
"email": "adam.n.perry@gmail.com"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "nikki93",
|
||||||
|
"email": "s.nikhilesh@gmail.com"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "brentvatne",
|
||||||
|
"email": "brentvatne@gmail.com"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "skevy",
|
||||||
|
"email": "adam@sk3vy.com"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "ide",
|
||||||
|
"email": "ide+npm@jameside.com"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "expoadmin",
|
||||||
|
"email": "exponent.team@gmail.com"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "@expo/ngrok",
|
||||||
|
"optionalDependencies": {},
|
||||||
|
"readme": "ngrok [![Build Status](https://travis-ci.org/bubenshchykov/ngrok.png?branch=master)](https://travis-ci.org/bubenshchykov/ngrok)\n=====\n\n![alt ngrok.com](https://ngrok.com/static/img/overview.png)\n\nNgrok exposes your localhost to the web. https://ngrok.com/\n\nusage\n===\n\n[![NPM](https://nodei.co/npm/ngrok.png?global=true&&downloads=true&downloadRank=true&stars=true)](https://nodei.co/npm/ngrok/)\n\n```\nvar ngrok = require('ngrok');\nngrok.connect(function (err, url) {});\n\nor\n\nnpm install ngrok -g\nngrok http 8080\n```\n\n## authtoken\nYou can create basic http-https-tcp tunnel without authtoken. For custom subdomains and more you should obtain authtoken by signing up at [ngrok.com](https://ngrok.com). Once you set it, it's stored in ngrok config and used for all tunnels. Few ways:\n\n```\nngrok.authtoken(token, function(err, token) {});\nngrok.connect({authtoken: token, ...}, function (err, url) {});\nngrok authtoken <token>\n```\n\n## connect\n```javascript\nvar ngrok = require('ngrok');\n\nngrok.connect(function (err, url) {}); // https://757c1652.ngrok.io -> http://localhost:80\nngrok.connect(9090, function (err, url) {}); // https://757c1652.ngrok.io -> http://localhost:9090\nngrok.connect({proto: 'tcp', addr: 22}, function (err, url) {}); // tcp://0.tcp.ngrok.io:48590\nngrok.connect(opts, function(err, url) {});\n```\n\n## options\n```javascript\nngrok.connect({\n\tproto: 'http', // http|tcp|tls\n\taddr: 8080, // port or network address\n\tauth: 'user:pwd', // http basic authentication for tunnel\n\tsubdomain: 'alex', // reserved tunnel name https://alex.ngrok.io\n\tauthtoken: '12345', // your authtoken from ngrok.com\n\tregion: 'us' // one of ngrok regions (us, eu, au, ap), defaults to us\n}, function (err, url) {});\n```\n\nOther options: `name, inspect, host_header, bind_tls, hostname, crt, key, client_cas, remote_addr` - read [here](https://ngrok.com/docs)\n\nNote on regions: region used in first tunnel will be used for all next tunnels too.\n\n## disconnect\nThe ngrok and all tunnels will be killed when node process is done. To stop the tunnels use\n```javascript\nngrok.disconnect(url); // stops one\nngrok.disconnect(); // stops all\nngrok.kill(); // kills ngrok process\n```\n\nNote on http tunnels: by default bind_tls is true, so whenever you use http proto two tunnels are created - http and https. If you disconnect https tunnel, http tunnel remains open. You might want to close them both by passing http-version url, or simply by disconnecting all in one go ```ngrok.disconnect()```.\n\n## emitter\nAlso you can use ngrok as an event emitter, it fires \"connect\", \"disconnect\" and \"error\" events\n```javascript\nngrok.once('connect', function (url) {};\nngrok.connect(port);\n```\n\n## configs\nYou can use ngrok's [configurations files](https://ngrok.com/docs#config), then just pass `name` option when making a tunnel. Configuration files allow to specify more options, eg ngrok region you want to use.\n```\nOS X\t/Users/example/.ngrok2/ngrok.yml\nLinux\t/home/example/.ngrok2/ngrok.yml\nWindows\tC:\\Users\\example\\.ngrok2\\ngrok.yml\n```\n\n## inspector\nWhen tunnel is established you can use the ngrok interface http://127.0.0.1:4040 to inspect the webhooks done via ngrok.\n\n## process\nTo get a handle to the spawned ngrok process use\n```javascript\nngrok.process(); // returns ChildProcess\n```\n\n## how it works\nnpm install downloads ngrok binaries for you platform and puts them into bin folder. You can host binaries yourself and set NGROK_CDN_URL env var before installing ngrok. Or you can force specific arch by setting NGROK_ARCH, eg NGROK_ARCH=freebsdia32\n\nFirst time you create tunnel ngrok process is spawned and runs until you disconnect or when parent process killed. All further tunnels are created or stopped by using internal ngrok api which usually runs on http://127.0.0.1:4040\n\n## contributors\nPlease run ```git update-index --assume-unchanged bin/ngrok``` to not override [ngrok stub](https://github.com/bubenshchykov/ngrok/blob/master/bin/ngrok) in your pr. Unfortunately it can't be gitignored.\n",
|
||||||
|
"readmeFilename": "README.md",
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "git://github.com/expo/ngrok.git"
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"postinstall": "node ./postinstall.js",
|
||||||
|
"postupdate": "node ./postinstall.js",
|
||||||
|
"test": "node ./node_modules/mocha/bin/_mocha"
|
||||||
|
},
|
||||||
|
"version": "2.3.0"
|
||||||
|
}
|
|
@ -0,0 +1,39 @@
|
||||||
|
var os = require('os');
|
||||||
|
var fs = require('fs');
|
||||||
|
var path = require('path');
|
||||||
|
var Zip = require('decompress-zip');
|
||||||
|
|
||||||
|
var localPath = __dirname + '/bin/';
|
||||||
|
var localFile = 'ngrok-stable-' + os.platform() + '-' + os.arch() + '.zip';
|
||||||
|
|
||||||
|
if (!localFile) {
|
||||||
|
console.error('ngrok - platform ' + arch + ' is not supported.');
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
new Zip(path.join(localPath, localFile)).extract({
|
||||||
|
path: localPath
|
||||||
|
})
|
||||||
|
.once('error', error)
|
||||||
|
.once('extract', function () {
|
||||||
|
|
||||||
|
var suffix = os.platform() === 'win32' ? '.exe' : '';
|
||||||
|
if (suffix === '.exe') {
|
||||||
|
fs.writeFileSync(localPath + 'ngrok.cmd', 'ngrok.exe');
|
||||||
|
}
|
||||||
|
|
||||||
|
var target = localPath + 'ngrok' + suffix;
|
||||||
|
fs.chmodSync(target, 0755);
|
||||||
|
|
||||||
|
if (!fs.existsSync(target) || fs.statSync(target).size <= 0) {
|
||||||
|
return error(new Error('corrupted file ' + target));
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('ngrok - binary unpacked.');
|
||||||
|
process.exit(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
function error(e) {
|
||||||
|
console.error('ngrok - error unpacking binary', e);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue