<commit_before>/* @flow */

import {
  Animated,
  Dimensions,
  Modal,
  PanResponder,
  ScrollView,
  StatusBar,
  StyleSheet,
  Text,
  TouchableWithoutFeedback,
  View,
} from 'react-native'; // eslint-disable-line import/no-unresolved, import/extensions
import React, {Component} from 'react';
import SwipeableViews from 'react-swipeable-views-native';

const ANIM_CONFIG = {duration: 300};
const {width: screenWidth, height: screenHeight} = Dimensions.get('window');

type PropsType = {
  style?: ?ReactNative$StyleType,
  contentContainerStyle?: ?ReactNative$StyleType,
  activeProps?: ?{[key: string]: mixed},
  activeComponents?: ?Array<React$Element<*>>,
  children?: ?Array<React$Element<*>>,
  zoomEnabled?: ?boolean,
  hideStatusBarOnOpen?: ?boolean,
  renderHeader?: ?() => ?React$Element<*>,
  renderFooter?: ?() => ?React$Element<*>,
  renderContent?: ?(idx: number) => ?React$Element<*>,
  onIdxChange?: ?(idx: number) => void,
  onOpen?: ?() => void,
  onClose?: ?() => void,
  horizontal?: ?boolean,
};
type StateType = {
  origin: {
    x: number,
    y: number,
    width: number,
    height: number,
  },
  target: {
    x: number,
    y: number,
    opacity: number,
  },
  fullscreen: boolean,
  selectedIdx: number,
  animating: boolean,
  panning: boolean,
  selectedImageHidden: boolean,
  slidesDown: boolean,
};

class ImageCarousel extends Component {
  props: PropsType;
  state: StateType;
  panResponder: Object; // eslint-disable-line flowtype/no-weak-types
  openAnim = new Animated.Value(0);
  pan = new Animated.Value(0);
  carouselItems: Array<?React$Element<*>> = Array.isArray(this.props.children)
    ? this.props.children.map(() => null)
    : [null];

  state = {
    origin: {
      x: 0,
      y: 0,
      width: 0,
      height: 0,
    },
    target: {
      x: 0,
      y: 0,
      opacity: 1,
    },
    fullscreen: false,
    selectedIdx: 0,
    animating: false,
    panning: false,
    selectedImageHidden: false,
    slidesDown: false,
  };

  static defaultProps = {
    zoomEnabled: true,
    hideStatusBarOnOpen: true,
  };

  componentWillMount() {
    this.panResponder = PanResponder.create({
      onStartShouldSetPanResponder: () => !this.state.animating,
      onStartShouldSetPanResponderCapture: () => !this.state.animating,
      onMoveShouldSetPanResponder: () => !this.state.animating,
      onMoveShouldSetPanResponderCapture: () => !this.state.animating,
      onPanResponderTerminationRequest: () => true,
      // eslint-disable-next-line flowtype/no-weak-types
      onPanResponderMove: (evt: Object, gestureState: Object) => {
        this.pan.setValue(gestureState.dy);

        // eslint-disable-next-line no-magic-numbers
        if (Math.abs(gestureState.dy) > 15 && !this.state.panning) {
          this.pan.setValue(0);
          this.setState({panning: true});
        }
      },
      onPanResponderRelease: this.handlePanEnd,
      onPanResponderTerminate: this.handlePanEnd,
    });
  }

  open = (startIdx: number) => {
    const activeComponent = this.getComponentAtIdx(startIdx);

    if (!activeComponent) return;

    const {hideStatusBarOnOpen, onIdxChange, onOpen} = this.props;

    hideStatusBarOnOpen && StatusBar.setHidden(true, 'fade');
    this.setState({fullscreen: true});

    (activeComponent: $FlowFixMe).measure(
      // eslint-disable-next-line max-params
      (
        rx: number,
        ry: number,
        width: number,
        height: number,
        x: number,
        y: number,
      ) => {
        this.setState({
          selectedIdx: startIdx,
          animating: true,
          origin: {x, y, width, height},
          target: {x: 0, y: 0, opacity: 1},
        });

        onIdxChange && onIdxChange(startIdx);

        this.animateOpenAnimToValue(1, onOpen);
      },
    );
  };

  close = () => {
    const activeComponent = this.getComponentAtIdx(this.state.selectedIdx);

    if (!activeComponent) return;

    const {hideStatusBarOnOpen, onClose} = this.props;

    hideStatusBarOnOpen && StatusBar.setHidden(false, 'fade');
    this.setState({animating: true});

    (activeComponent: $FlowFixMe).measure(
      // eslint-disable-next-line max-params
      (
        rx: number,
        ry: number,
        width: number,
        height: number,
        x: number,
        y: number,
      ) => {
        this.setState({
          origin: {x, y, width, height},
          slidesDown: x + width < 0 || x > screenWidth,
        });

        this.animateOpenAnimToValue(0, () => {
          this.setState({
            fullscreen: false,
            selectedImageHidden: false,
            slidesDown: false,
          });

          onClose && onClose();
        });
      },
    );
  };

  captureCarouselItem = (carouselItem: React$Element<*>, idx: number) => {
    this.carouselItems[idx] = carouselItem;
  };

  getChildren = (): Array<React$Element<*>> => {
    const {children} = this.props;

    if (Array.isArray(children)) {
      return children;
    } else if (children !== null && children !== undefined) {
      return [children];
    }

    return [];
  };

  getComponentAtIdx = (idx: number) => {
    const {activeComponents} = this.props;
    return activeComponents ? activeComponents[idx] : this.carouselItems[idx];
  };

  animateOpenAnimToValue = (toValue: number, onComplete?: ?() => void) =>
    Animated.timing(this.openAnim, {
      ...ANIM_CONFIG,
      toValue,
    }).start(() => {
      this.setState({animating: false});
      onComplete && onComplete();
    });

  // eslint-disable-next-line flowtype/no-weak-types
  handlePanEnd = (evt: Object, gestureState: {dx: number, dy: number}) => {
    // eslint-disable-next-line no-magic-numbers
    if (Math.abs(gestureState.dy) > 150) {
      this.setState({
        panning: false,
        target: {
          x: gestureState.dx,
          y: gestureState.dy,
          opacity: 1 - Math.abs(gestureState.dy / screenHeight),
        },
      });

      this.close();
    } else {
      Animated.timing(this.pan, {
        toValue: 0,
        ...ANIM_CONFIG,
      }).start(() => this.setState({panning: false}));
    }
  };

  getSwipeableStyle = (idx: number): ReactNative$StyleType => {
    const {fullscreen, origin, selectedIdx, slidesDown, target} = this.state;

    if (!fullscreen || idx !== selectedIdx) return {flex: 1};

    const inputRange = [0, 1];

    return !slidesDown
      ? {
          left: this.openAnim.interpolate({
            inputRange,
            outputRange: [origin.x, target.x],
          }),
          top: this.openAnim.interpolate({
            inputRange,
            outputRange: [origin.y, target.y],
          }),
          width: this.openAnim.interpolate({
            inputRange,
            outputRange: [origin.width, screenWidth],
          }),
          height: this.openAnim.interpolate({
            inputRange,
            outputRange: [origin.height, screenHeight],
          }),
        }
      : {
          left: 0,
          right: 0,
          height: screenHeight,
          top: this.openAnim.interpolate({
            inputRange,
            outputRange: [screenHeight, target.y],
          }),
        };
  };

  handleModalShow = () => {
    const {animating, selectedImageHidden} = this.state;

    if (!selectedImageHidden && animating) {
      this.setState({selectedImageHidden: true});
    }
  };

  handleChangeIdx = (idx: number) => {
    this.setState({selectedIdx: idx});
    this.props.onIdxChange && this.props.onIdxChange(idx);
  };

  renderFullscreenContent = (child: React$Element<*>, idx: number) => {
    const {renderContent, zoomEnabled} = this.props;
    const {selectedIdx, panning} = this.state;

    const content = renderContent && renderContent(idx);
    const containerStyle = [
      this.getSwipeableStyle(idx),
      selectedIdx === idx && panning && {top: this.pan},
    ];

    return (
      <Animated.View key={idx} style={containerStyle}>
        <ScrollView
          style={styles.fill}
          contentContainerStyle={styles.fill}
          maximumZoomScale={zoomEnabled ? 2 : 1} // eslint-disable-line no-magic-numbers
          alwaysBounceVertical={false}
        >
          {content
            ? React.cloneElement(content, {
                ...content.props,
                ...this.panResponder.panHandlers,
              })
            : React.cloneElement(child, {
                ...child.props,
                ...this.props.activeProps,
                ...this.panResponder.panHandlers,
              })}
        </ScrollView>
      </Animated.View>
    );
  };

  renderDefaultHeader = () =>
    <TouchableWithoutFeedback onPress={this.close}>
      <View>
        <Text style={styles.closeText}>Close</Text>
      </View>
    </TouchableWithoutFeedback>;

  getFullscreenOpacity = () => {
    const {panning, target} = this.state;

    return {
      opacity: panning
        ? this.pan.interpolate({
            inputRange: [-screenHeight, 0, screenHeight],
            outputRange: [0, 1, 0],
          })
        : this.openAnim.interpolate({
            inputRange: [0, 1],
            outputRange: [0, target.opacity],
          }),
    };
  };

  renderFullscreen = () => {
    const {renderHeader, renderFooter} = this.props;
    const {animating, fullscreen, panning, selectedIdx} = this.state;

    const opacity = this.getFullscreenOpacity();

    const header = renderHeader && renderHeader();
    const footer = renderFooter && renderFooter();

    return (
      <Modal
        transparent
        visible={fullscreen}
        onShow={this.handleModalShow}
        onRequestClose={this.close}
      >
        <Animated.View style={[styles.modalBackground, opacity]} />
        <SwipeableViews
          style={StyleSheet.absoluteFill}
          index={selectedIdx}
          onChangeIndex={this.handleChangeIdx}
          scrollEnabled={!animating && !panning}
        >
          {this.getChildren().map(this.renderFullscreenContent)}
        </SwipeableViews>
        <Animated.View style={[opacity, styles.headerContainer]}>
          {header
            ? React.cloneElement(header, {
                ...header.props,
                style: [header.props.style],
              })
            : this.renderDefaultHeader()}
        </Animated.View>
        {footer &&
          <Animated.View style={[opacity, styles.footerContainer]}>
            {footer}
          </Animated.View>}
      </Modal>
    );
  };

  render() {
    const {style, horizontal = true, contentContainerStyle} = this.props;
    const {
      fullscreen,
      animating,
      selectedImageHidden,
      selectedIdx,
    } = this.state;

    const getOpacity = (idx: number) => ({
      opacity: selectedImageHidden && selectedIdx === idx ? 0 : 1,
    });

    return (
      <View style={style}>
        <ScrollView
          horizontal={horizontal}
          contentContainerStyle={contentContainerStyle}
          scrollEnabled={!animating}
          alwaysBounceHorizontal={false}
          showsHorizontalScrollIndicator={false}
        >
          {this.getChildren().map((child: React$Element<*>, idx: number) =>
            <TouchableWithoutFeedback
              key={`slider-image-${idx}`} // eslint-disable-line react/no-array-index-key
              onPress={() => this.open(idx)}
            >
              <View
                ref={(view: React$Element<*>) =>
                  this.captureCarouselItem(view, idx)}
                style={getOpacity(idx)}
              >
                {child}
              </View>
            </TouchableWithoutFeedback>,
          )}
        </ScrollView>
        {fullscreen && this.renderFullscreen()}
      </View>
    );
  }
}

const styles = StyleSheet.create({
  fill: {
    flex: 1,
  },
  modalBackground: {
    ...StyleSheet.absoluteFillObject,
    backgroundColor: 'black',
  },
  headerContainer: {
    position: 'absolute',
    top: 0,
    left: 0,
    right: 0,
  },
  footerContainer: {
    position: 'absolute',
    bottom: 0,
    left: 0,
    right: 0,
  },
  closeText: {
    color: 'white',
    textAlign: 'right',
    padding: 10,
  },
});

export default ImageCarousel;
<commit_msg>fix: fix opening anim<commit_after>/* @flow */

import {
  Animated,
  Dimensions,
  Modal,
  PanResponder,
  ScrollView,
  StatusBar,
  StyleSheet,
  Text,
  TouchableWithoutFeedback,
  View,
} from 'react-native'; // eslint-disable-line import/no-unresolved, import/extensions
import React, {Component} from 'react';
import SwipeableViews from 'react-swipeable-views-native';

const ANIM_CONFIG = {duration: 300};
const {width: screenWidth, height: screenHeight} = Dimensions.get('window');

type PropsType = {
  style?: ?ReactNative$StyleType,
  contentContainerStyle?: ?ReactNative$StyleType,
  activeProps?: ?{[key: string]: mixed},
  activeComponents?: ?Array<React$Element<*>>,
  children?: ?Array<React$Element<*>>,
  zoomEnabled?: ?boolean,
  hideStatusBarOnOpen?: ?boolean,
  renderHeader?: ?() => ?React$Element<*>,
  renderFooter?: ?() => ?React$Element<*>,
  renderContent?: ?(idx: number) => ?React$Element<*>,
  onIdxChange?: ?(idx: number) => void,
  onOpen?: ?() => void,
  onClose?: ?() => void,
  horizontal?: ?boolean,
};
type StateType = {
  origin: {
    x: number,
    y: number,
    width: number,
    height: number,
  },
  target: {
    x: number,
    y: number,
    opacity: number,
  },
  fullscreen: boolean,
  selectedIdx: number,
  animating: boolean,
  panning: boolean,
  selectedImageHidden: boolean,
  slidesDown: boolean,
};

class ImageCarousel extends Component {
  props: PropsType;
  state: StateType;
  panResponder: Object; // eslint-disable-line flowtype/no-weak-types
  openAnim = new Animated.Value(0);
  pan = new Animated.Value(0);
  carouselItems: Array<?React$Element<*>> = Array.isArray(this.props.children)
    ? this.props.children.map(() => null)
    : [null];

  state = {
    origin: {
      x: 0,
      y: 0,
      width: 0,
      height: 0,
    },
    target: {
      x: 0,
      y: 0,
      opacity: 1,
    },
    fullscreen: false,
    selectedIdx: 0,
    animating: false,
    panning: false,
    selectedImageHidden: false,
    slidesDown: false,
  };

  static defaultProps = {
    zoomEnabled: true,
    hideStatusBarOnOpen: true,
  };

  componentWillMount() {
    this.panResponder = PanResponder.create({
      onStartShouldSetPanResponder: () => !this.state.animating,
      onStartShouldSetPanResponderCapture: () => !this.state.animating,
      onMoveShouldSetPanResponder: () => !this.state.animating,
      onMoveShouldSetPanResponderCapture: () => !this.state.animating,
      onPanResponderTerminationRequest: () => true,
      // eslint-disable-next-line flowtype/no-weak-types
      onPanResponderMove: (evt: Object, gestureState: Object) => {
        this.pan.setValue(gestureState.dy);

        // eslint-disable-next-line no-magic-numbers
        if (Math.abs(gestureState.dy) > 15 && !this.state.panning) {
          this.pan.setValue(0);
          this.setState({panning: true});
        }
      },
      onPanResponderRelease: this.handlePanEnd,
      onPanResponderTerminate: this.handlePanEnd,
    });
  }

  open = (startIdx: number) => {
    const activeComponent = this.getComponentAtIdx(startIdx);

    if (!activeComponent) return;

    const {hideStatusBarOnOpen, onIdxChange, onOpen} = this.props;

    hideStatusBarOnOpen && StatusBar.setHidden(true, 'fade');

    (activeComponent: $FlowFixMe).measure(
      // eslint-disable-next-line max-params
      (
        rx: number,
        ry: number,
        width: number,
        height: number,
        x: number,
        y: number,
      ) => {
        this.setState({
          fullscreen: true,
          selectedIdx: startIdx,
          animating: true,
          origin: {x, y, width, height},
          target: {x: 0, y: 0, opacity: 1},
        });

        onIdxChange && onIdxChange(startIdx);

        this.animateOpenAnimToValue(1, onOpen);
      },
    );
  };

  close = () => {
    const activeComponent = this.getComponentAtIdx(this.state.selectedIdx);

    if (!activeComponent) return;

    const {hideStatusBarOnOpen, onClose} = this.props;

    hideStatusBarOnOpen && StatusBar.setHidden(false, 'fade');
    this.setState({animating: true});

    (activeComponent: $FlowFixMe).measure(
      // eslint-disable-next-line max-params
      (
        rx: number,
        ry: number,
        width: number,
        height: number,
        x: number,
        y: number,
      ) => {
        this.setState({
          origin: {x, y, width, height},
          slidesDown: x + width < 0 || x > screenWidth,
        });

        this.animateOpenAnimToValue(0, () => {
          this.setState({
            fullscreen: false,
            selectedImageHidden: false,
            slidesDown: false,
          });

          onClose && onClose();
        });
      },
    );
  };

  captureCarouselItem = (carouselItem: React$Element<*>, idx: number) => {
    this.carouselItems[idx] = carouselItem;
  };

  getChildren = (): Array<React$Element<*>> => {
    const {children} = this.props;

    if (Array.isArray(children)) {
      return children;
    } else if (children) {
      return [children];
    }

    return [];
  };

  getComponentAtIdx = (idx: number) => {
    const {activeComponents} = this.props;
    return activeComponents ? activeComponents[idx] : this.carouselItems[idx];
  };

  animateOpenAnimToValue = (toValue: number, onComplete?: ?() => void) =>
    Animated.timing(this.openAnim, {
      ...ANIM_CONFIG,
      toValue,
    }).start(() => {
      this.setState({animating: false});
      onComplete && onComplete();
    });

  // eslint-disable-next-line flowtype/no-weak-types
  handlePanEnd = (evt: Object, gestureState: {dx: number, dy: number}) => {
    // eslint-disable-next-line no-magic-numbers
    if (Math.abs(gestureState.dy) > 150) {
      this.setState({
        panning: false,
        target: {
          x: gestureState.dx,
          y: gestureState.dy,
          opacity: 1 - Math.abs(gestureState.dy / screenHeight),
        },
      });

      this.close();
    } else {
      Animated.timing(this.pan, {
        toValue: 0,
        ...ANIM_CONFIG,
      }).start(() => this.setState({panning: false}));
    }
  };

  getSwipeableStyle = (idx: number): ReactNative$StyleType => {
    const {fullscreen, origin, selectedIdx, slidesDown, target} = this.state;

    if (!fullscreen || idx !== selectedIdx) return {flex: 1};

    const inputRange = [0, 1];

    return !slidesDown
      ? {
          left: this.openAnim.interpolate({
            inputRange,
            outputRange: [origin.x, target.x],
          }),
          top: this.openAnim.interpolate({
            inputRange,
            outputRange: [origin.y, target.y],
          }),
          width: this.openAnim.interpolate({
            inputRange,
            outputRange: [origin.width, screenWidth],
          }),
          height: this.openAnim.interpolate({
            inputRange,
            outputRange: [origin.height, screenHeight],
          }),
        }
      : {
          left: 0,
          right: 0,
          height: screenHeight,
          top: this.openAnim.interpolate({
            inputRange,
            outputRange: [screenHeight, target.y],
          }),
        };
  };

  handleModalShow = () => {
    const {animating, selectedImageHidden} = this.state;

    if (!selectedImageHidden && animating) {
      this.setState({selectedImageHidden: true});
    }
  };

  handleChangeIdx = (idx: number) => {
    this.setState({selectedIdx: idx});
    this.props.onIdxChange && this.props.onIdxChange(idx);
  };

  renderFullscreenContent = (child: React$Element<*>, idx: number) => {
    const {renderContent, zoomEnabled} = this.props;
    const {selectedIdx, panning} = this.state;

    const content = renderContent && renderContent(idx);
    const containerStyle = [
      this.getSwipeableStyle(idx),
      selectedIdx === idx && panning && {top: this.pan},
    ];

    return (
      <Animated.View key={idx} style={containerStyle}>
        <ScrollView
          style={styles.fill}
          contentContainerStyle={styles.fill}
          maximumZoomScale={zoomEnabled ? 2 : 1} // eslint-disable-line no-magic-numbers
          alwaysBounceVertical={false}
        >
          {content
            ? React.cloneElement(content, {
                ...content.props,
                ...this.panResponder.panHandlers,
              })
            : React.cloneElement(child, {
                ...child.props,
                ...this.props.activeProps,
                ...this.panResponder.panHandlers,
              })}
        </ScrollView>
      </Animated.View>
    );
  };

  renderDefaultHeader = () =>
    <TouchableWithoutFeedback onPress={this.close}>
      <View>
        <Text style={styles.closeText}>Close</Text>
      </View>
    </TouchableWithoutFeedback>;

  getFullscreenOpacity = () => {
    const {panning, target} = this.state;

    return {
      opacity: panning
        ? this.pan.interpolate({
            inputRange: [-screenHeight, 0, screenHeight],
            outputRange: [0, 1, 0],
          })
        : this.openAnim.interpolate({
            inputRange: [0, 1],
            outputRange: [0, target.opacity],
          }),
    };
  };

  renderFullscreen = () => {
    const {renderHeader, renderFooter} = this.props;
    const {animating, fullscreen, panning, selectedIdx} = this.state;

    const opacity = this.getFullscreenOpacity();

    const header = renderHeader && renderHeader();
    const footer = renderFooter && renderFooter();

    return (
      <Modal
        transparent
        visible={fullscreen}
        onShow={this.handleModalShow}
        onRequestClose={this.close}
      >
        <Animated.View style={[styles.modalBackground, opacity]} />
        <SwipeableViews
          style={StyleSheet.absoluteFill}
          index={selectedIdx}
          onChangeIndex={this.handleChangeIdx}
          scrollEnabled={!animating && !panning}
        >
          {this.getChildren().map(this.renderFullscreenContent)}
        </SwipeableViews>
        <Animated.View style={[opacity, styles.headerContainer]}>
          {header
            ? React.cloneElement(header, {
                ...header.props,
                style: [header.props.style],
              })
            : this.renderDefaultHeader()}
        </Animated.View>
        {footer &&
          <Animated.View style={[opacity, styles.footerContainer]}>
            {footer}
          </Animated.View>}
      </Modal>
    );
  };

  render() {
    const {style, horizontal = true, contentContainerStyle} = this.props;
    const {
      fullscreen,
      animating,
      selectedImageHidden,
      selectedIdx,
    } = this.state;

    const getOpacity = (idx: number) => ({
      opacity: selectedImageHidden && selectedIdx === idx ? 0 : 1,
    });

    return (
      <View style={style}>
        <ScrollView
          horizontal={horizontal}
          contentContainerStyle={contentContainerStyle}
          scrollEnabled={!animating}
          alwaysBounceHorizontal={false}
          showsHorizontalScrollIndicator={false}
        >
          {this.getChildren().map((child: React$Element<*>, idx: number) =>
            <TouchableWithoutFeedback
              key={`slider-image-${idx}`} // eslint-disable-line react/no-array-index-key
              onPress={() => this.open(idx)}
            >
              <View
                ref={(view: React$Element<*>) =>
                  this.captureCarouselItem(view, idx)}
                style={getOpacity(idx)}
              >
                {child}
              </View>
            </TouchableWithoutFeedback>,
          )}
        </ScrollView>
        {fullscreen && this.renderFullscreen()}
      </View>
    );
  }
}

const styles = StyleSheet.create({
  fill: {
    flex: 1,
  },
  modalBackground: {
    ...StyleSheet.absoluteFillObject,
    backgroundColor: 'black',
  },
  headerContainer: {
    position: 'absolute',
    top: 0,
    left: 0,
    right: 0,
  },
  footerContainer: {
    position: 'absolute',
    bottom: 0,
    left: 0,
    right: 0,
  },
  closeText: {
    color: 'white',
    textAlign: 'right',
    padding: 10,
  },
});

export default ImageCarousel;
<|endoftext|>


<commit_before>'use strict';

//  ---------------------------------------------------------------------------

const Exchange = require ('./base/Exchange');
const { ExchangeError, OrderNotFound } = require ('./base/errors');

//  ---------------------------------------------------------------------------

module.exports = class bitflyer extends Exchange {
    describe () {
        return this.deepExtend (super.describe (), {
            'id': 'bitflyer',
            'name': 'bitFlyer',
            'countries': 'JP',
            'version': 'v1',
            'rateLimit': 1000, // their nonce-timestamp is in seconds...
            'has': {
                'CORS': false,
                'withdraw': true,
                'fetchMyTrades': true,
                'fetchOrders': true,
                'fetchOrder': true,
                'fetchOpenOrders': 'emulated',
                'fetchClosedOrders': 'emulated',
            },
            'urls': {
                'logo': 'https://user-images.githubusercontent.com/1294454/28051642-56154182-660e-11e7-9b0d-6042d1e6edd8.jpg',
                'api': 'https://api.bitflyer.jp',
                'www': 'https://bitflyer.jp',
                'doc': 'https://bitflyer.jp/API',
            },
            'api': {
                'public': {
                    'get': [
                        'getmarkets/usa', // new (wip)
                        'getmarkets/eu',  // new (wip)
                        'getmarkets',     // or 'markets'
                        'getboard',       // ...
                        'getticker',
                        'getexecutions',
                        'gethealth',
                        'getchats',
                    ],
                },
                'private': {
                    'get': [
                        'getpermissions',
                        'getbalance',
                        'getcollateral',
                        'getcollateralaccounts',
                        'getaddresses',
                        'getcoinins',
                        'getcoinouts',
                        'getbankaccounts',
                        'getdeposits',
                        'getwithdrawals',
                        'getchildorders',
                        'getparentorders',
                        'getparentorder',
                        'getexecutions',
                        'getpositions',
                        'gettradingcommission',
                    ],
                    'post': [
                        'sendcoin',
                        'withdraw',
                        'sendchildorder',
                        'cancelchildorder',
                        'sendparentorder',
                        'cancelparentorder',
                        'cancelallchildorders',
                    ],
                },
            },
            'fees': {
                'trading': {
                    'maker': 0.25 / 100,
                    'taker': 0.25 / 100,
                },
            },
        });
    }

    async fetchMarkets () {
        let jp_markets = await this.publicGetGetmarkets ();
        let us_markets = await this.publicGetGetmarketsUsa ();
        let eu_markets = await this.publicGetGetmarketsEu ();
        let markets = this.arrayConcat (jp_markets, us_markets);
        markets = this.arrayConcat (markets, eu_markets);
        let result = [];
        for (let p = 0; p < markets.length; p++) {
            let market = markets[p];
            let id = market['product_code'];
            let currencies = id.split ('_');
            let base = undefined;
            let quote = undefined;
            let symbol = id;
            let numCurrencies = currencies.length;
            if (numCurrencies === 1) {
                base = symbol.slice (0, 3);
                quote = symbol.slice (3, 6);
            } else if (numCurrencies === 2) {
                base = currencies[0];
                quote = currencies[1];
                symbol = base + '/' + quote;
            } else {
                base = currencies[1];
                quote = currencies[2];
            }
            result.push ({
                'id': id,
                'symbol': symbol,
                'base': base,
                'quote': quote,
                'info': market,
            });
        }
        return result;
    }

    async fetchBalance (params = {}) {
        await this.loadMarkets ();
        let response = await this.privateGetGetbalance ();
        let balances = {};
        for (let b = 0; b < response.length; b++) {
            let account = response[b];
            let currency = account['currency_code'];
            balances[currency] = account;
        }
        let result = { 'info': response };
        let currencies = Object.keys (this.currencies);
        for (let i = 0; i < currencies.length; i++) {
            let currency = currencies[i];
            let account = this.account ();
            if (currency in balances) {
                account['total'] = balances[currency]['amount'];
                account['free'] = balances[currency]['available'];
                account['used'] = account['total'] - account['free'];
            }
            result[currency] = account;
        }
        return this.parseBalance (result);
    }

    async fetchOrderBook (symbol, limit = undefined, params = {}) {
        await this.loadMarkets ();
        let orderbook = await this.publicGetGetboard (this.extend ({
            'product_code': this.marketId (symbol),
        }, params));
        return this.parseOrderBook (orderbook, undefined, 'bids', 'asks', 'price', 'size');
    }

    async fetchTicker (symbol, params = {}) {
        await this.loadMarkets ();
        let ticker = await this.publicGetGetticker (this.extend ({
            'product_code': this.marketId (symbol),
        }, params));
        let timestamp = this.parse8601 (ticker['timestamp']);
        let last = parseFloat (ticker['ltp']);
        return {
            'symbol': symbol,
            'timestamp': timestamp,
            'datetime': this.iso8601 (timestamp),
            'high': undefined,
            'low': undefined,
            'bid': parseFloat (ticker['best_bid']),
            'bidVolume': undefined,
            'ask': parseFloat (ticker['best_ask']),
            'askVolume': undefined,
            'vwap': undefined,
            'open': undefined,
            'close': last,
            'last': last,
            'previousClose': undefined,
            'change': undefined,
            'percentage': undefined,
            'average': undefined,
            'baseVolume': parseFloat (ticker['volume_by_product']),
            'quoteVolume': undefined,
            'info': ticker,
        };
    }

    parseTrade (trade, market = undefined) {
        let side = undefined;
        let order = undefined;
        if ('side' in trade)
            if (trade['side']) {
                side = trade['side'].toLowerCase ();
                let id = side + '_child_order_acceptance_id';
                if (id in trade)
                    order = trade[id];
            }
        let timestamp = this.parse8601 (trade['exec_date']);
        return {
            'id': trade['id'].toString (),
            'info': trade,
            'timestamp': timestamp,
            'datetime': this.iso8601 (timestamp),
            'symbol': market['symbol'],
            'order': order,
            'type': undefined,
            'side': side,
            'price': trade['price'],
            'amount': trade['size'],
        };
    }

    async fetchTrades (symbol, since = undefined, limit = undefined, params = {}) {
        await this.loadMarkets ();
        let market = this.market (symbol);
        let response = await this.publicGetGetexecutions (this.extend ({
            'product_code': market['id'],
        }, params));
        return this.parseTrades (response, market, since, limit);
    }

    async createOrder (symbol, type, side, amount, price = undefined, params = {}) {
        await this.loadMarkets ();
        let order = {
            'product_code': this.marketId (symbol),
            'child_order_type': type.toUpperCase (),
            'side': side.toUpperCase (),
            'price': price,
            'size': amount,
        };
        let result = await this.privatePostSendchildorder (this.extend (order, params));
        // { "status": - 200, "error_message": "Insufficient funds", "data": null }
        return {
            'info': result,
            'id': result['child_order_acceptance_id'],
        };
    }

    async cancelOrder (id, symbol = undefined, params = {}) {
        if (typeof symbol === 'undefined')
            throw new ExchangeError (this.id + ' cancelOrder() requires a symbol argument');
        await this.loadMarkets ();
        return await this.privatePostCancelchildorder (this.extend ({
            'product_code': this.marketId (symbol),
            'child_order_acceptance_id': id,
        }, params));
    }

    parseOrderStatus (status) {
        let statuses = {
            'ACTIVE': 'open',
            'COMPLETED': 'closed',
            'CANCELED': 'canceled',
            'EXPIRED': 'canceled',
            'REJECTED': 'canceled',
        };
        if (status in statuses)
            return statuses[status];
        return status.toLowerCase ();
    }

    parseOrder (order, market = undefined) {
        let timestamp = this.parse8601 (order['child_order_date']);
        let amount = this.safeFloat (order, 'size');
        let remaining = this.safeFloat (order, 'outstanding_size');
        let filled = this.safeFloat (order, 'executed_size');
        let price = this.safeFloat (order, 'price');
        let cost = price * filled;
        let status = this.parseOrderStatus (order['child_order_state']);
        let type = order['child_order_type'].toLowerCase ();
        let side = order['side'].toLowerCase ();
        let symbol = undefined;
        if (typeof market === 'undefined') {
            let marketId = this.safeString (order, 'product_code');
            if (typeof marketId !== 'undefined') {
                if (marketId in this.markets_by_id)
                    market = this.markets_by_id[marketId];
            }
        }
        if (typeof market !== 'undefined')
            symbol = market['symbol'];
        let fee = undefined;
        let feeCost = this.safeFloat (order, 'total_commission');
        if (typeof feeCost !== 'undefined') {
            fee = {
                'cost': feeCost,
                'currency': undefined,
                'rate': undefined,
            };
        }
        return {
            'id': order['child_order_acceptance_id'],
            'info': order,
            'timestamp': timestamp,
            'datetime': this.iso8601 (timestamp),
            'status': status,
            'symbol': symbol,
            'type': type,
            'side': side,
            'price': price,
            'cost': cost,
            'amount': amount,
            'filled': filled,
            'remaining': remaining,
            'fee': fee,
        };
    }

    async fetchOrders (symbol = undefined, since = undefined, limit = 100, params = {}) {
        if (typeof symbol === 'undefined')
            throw new ExchangeError (this.id + ' fetchOrders() requires a symbol argument');
        await this.loadMarkets ();
        let market = this.market (symbol);
        let request = {
            'product_code': market['id'],
            'count': limit,
        };
        let response = await this.privateGetGetchildorders (this.extend (request, params));
        let orders = this.parseOrders (response, market, since, limit);
        if (symbol)
            orders = this.filterBy (orders, 'symbol', symbol);
        return orders;
    }

    async fetchOpenOrders (symbol = undefined, since = undefined, limit = 100, params = {}) {
        params['child_order_state'] = 'ACTIVE';
        return this.fetchOrders (symbol, since, limit, params);
    }

    async fetchClosedOrders (symbol = undefined, since = undefined, limit = 100, params = {}) {
        params['child_order_state'] = 'COMPLETED';
        return this.fetchOrders (symbol, since, limit, params);
    }

    async fetchOrder (id, symbol = undefined, params = {}) {
        if (typeof symbol === 'undefined')
            throw new ExchangeError (this.id + ' fetchOrder() requires a symbol argument');
        let orders = await this.fetchOrders (symbol);
        let ordersById = this.indexBy (orders, 'id');
        if (id in ordersById)
            return ordersById[id];
        throw new OrderNotFound (this.id + ' No order found with id ' + id);
    }

    async fetchMyTrades (symbol = undefined, since = undefined, limit = undefined, params = {}) {
        if (typeof symbol === 'undefined')
            throw new ExchangeError (this.id + ' fetchMyTrades requires a symbol argument');
        await this.loadMarkets ();
        let market = this.market (symbol);
        let request = {
            'product_code': market['id'],
        };
        if (limit)
            request['count'] = limit;
        let response = await this.privateGetGetexecutions (this.extend (request, params));
        return this.parseTrades (response, market, since, limit);
    }

    async withdraw (code, amount, address, tag = undefined, params = {}) {
        this.checkAddress (address);
        await this.loadMarkets ();
        if (code !== 'JPY' && code !== 'USD' && code !== 'EUR')
            throw new ExchangeError (this.id + ' allows withdrawing JPY, USD, EUR only, ' + code + ' is not supported');
        let currency = this.currency (code);
        let response = await this.privatePostWithdraw (this.extend ({
            'currency_code': currency['id'],
            'amount': amount,
            // 'bank_account_id': 1234,
        }, params));
        return {
            'info': response,
            'id': response['message_id'],
        };
    }

    sign (path, api = 'public', method = 'GET', params = {}, headers = undefined, body = undefined) {
        let request = '/' + this.version + '/';
        if (api === 'private')
            request += 'me/';
        request += path;
        if (method === 'GET') {
            if (Object.keys (params).length)
                request += '?' + this.urlencode (params);
        }
        let url = this.urls['api'] + request;
        if (api === 'private') {
            this.checkRequiredCredentials ();
            let nonce = this.nonce ().toString ();
            let auth = [ nonce, method, request ].join ('');
            if (Object.keys (params).length) {
                if (method !== 'GET') {
                    body = this.json (params);
                    auth += body;
                }
            }
            headers = {
                'ACCESS-KEY': this.apiKey,
                'ACCESS-TIMESTAMP': nonce,
                'ACCESS-SIGN': this.hmac (this.encode (auth), this.encode (this.secret)),
                'Content-Type': 'application/json',
            };
        }
        return { 'url': url, 'method': method, 'body': body, 'headers': headers };
    }
};
<commit_msg>bitflyer: fix parseTrade()<commit_after>'use strict';

//  ---------------------------------------------------------------------------

const Exchange = require ('./base/Exchange');
const { ExchangeError, OrderNotFound } = require ('./base/errors');

//  ---------------------------------------------------------------------------

module.exports = class bitflyer extends Exchange {
    describe () {
        return this.deepExtend (super.describe (), {
            'id': 'bitflyer',
            'name': 'bitFlyer',
            'countries': 'JP',
            'version': 'v1',
            'rateLimit': 1000, // their nonce-timestamp is in seconds...
            'has': {
                'CORS': false,
                'withdraw': true,
                'fetchMyTrades': true,
                'fetchOrders': true,
                'fetchOrder': true,
                'fetchOpenOrders': 'emulated',
                'fetchClosedOrders': 'emulated',
            },
            'urls': {
                'logo': 'https://user-images.githubusercontent.com/1294454/28051642-56154182-660e-11e7-9b0d-6042d1e6edd8.jpg',
                'api': 'https://api.bitflyer.jp',
                'www': 'https://bitflyer.jp',
                'doc': 'https://bitflyer.jp/API',
            },
            'api': {
                'public': {
                    'get': [
                        'getmarkets/usa', // new (wip)
                        'getmarkets/eu',  // new (wip)
                        'getmarkets',     // or 'markets'
                        'getboard',       // ...
                        'getticker',
                        'getexecutions',
                        'gethealth',
                        'getchats',
                    ],
                },
                'private': {
                    'get': [
                        'getpermissions',
                        'getbalance',
                        'getcollateral',
                        'getcollateralaccounts',
                        'getaddresses',
                        'getcoinins',
                        'getcoinouts',
                        'getbankaccounts',
                        'getdeposits',
                        'getwithdrawals',
                        'getchildorders',
                        'getparentorders',
                        'getparentorder',
                        'getexecutions',
                        'getpositions',
                        'gettradingcommission',
                    ],
                    'post': [
                        'sendcoin',
                        'withdraw',
                        'sendchildorder',
                        'cancelchildorder',
                        'sendparentorder',
                        'cancelparentorder',
                        'cancelallchildorders',
                    ],
                },
            },
            'fees': {
                'trading': {
                    'maker': 0.25 / 100,
                    'taker': 0.25 / 100,
                },
            },
        });
    }

    async fetchMarkets () {
        let jp_markets = await this.publicGetGetmarkets ();
        let us_markets = await this.publicGetGetmarketsUsa ();
        let eu_markets = await this.publicGetGetmarketsEu ();
        let markets = this.arrayConcat (jp_markets, us_markets);
        markets = this.arrayConcat (markets, eu_markets);
        let result = [];
        for (let p = 0; p < markets.length; p++) {
            let market = markets[p];
            let id = market['product_code'];
            let currencies = id.split ('_');
            let base = undefined;
            let quote = undefined;
            let symbol = id;
            let numCurrencies = currencies.length;
            if (numCurrencies === 1) {
                base = symbol.slice (0, 3);
                quote = symbol.slice (3, 6);
            } else if (numCurrencies === 2) {
                base = currencies[0];
                quote = currencies[1];
                symbol = base + '/' + quote;
            } else {
                base = currencies[1];
                quote = currencies[2];
            }
            result.push ({
                'id': id,
                'symbol': symbol,
                'base': base,
                'quote': quote,
                'info': market,
            });
        }
        return result;
    }

    async fetchBalance (params = {}) {
        await this.loadMarkets ();
        let response = await this.privateGetGetbalance ();
        let balances = {};
        for (let b = 0; b < response.length; b++) {
            let account = response[b];
            let currency = account['currency_code'];
            balances[currency] = account;
        }
        let result = { 'info': response };
        let currencies = Object.keys (this.currencies);
        for (let i = 0; i < currencies.length; i++) {
            let currency = currencies[i];
            let account = this.account ();
            if (currency in balances) {
                account['total'] = balances[currency]['amount'];
                account['free'] = balances[currency]['available'];
                account['used'] = account['total'] - account['free'];
            }
            result[currency] = account;
        }
        return this.parseBalance (result);
    }

    async fetchOrderBook (symbol, limit = undefined, params = {}) {
        await this.loadMarkets ();
        let orderbook = await this.publicGetGetboard (this.extend ({
            'product_code': this.marketId (symbol),
        }, params));
        return this.parseOrderBook (orderbook, undefined, 'bids', 'asks', 'price', 'size');
    }

    async fetchTicker (symbol, params = {}) {
        await this.loadMarkets ();
        let ticker = await this.publicGetGetticker (this.extend ({
            'product_code': this.marketId (symbol),
        }, params));
        let timestamp = this.parse8601 (ticker['timestamp']);
        let last = parseFloat (ticker['ltp']);
        return {
            'symbol': symbol,
            'timestamp': timestamp,
            'datetime': this.iso8601 (timestamp),
            'high': undefined,
            'low': undefined,
            'bid': parseFloat (ticker['best_bid']),
            'bidVolume': undefined,
            'ask': parseFloat (ticker['best_ask']),
            'askVolume': undefined,
            'vwap': undefined,
            'open': undefined,
            'close': last,
            'last': last,
            'previousClose': undefined,
            'change': undefined,
            'percentage': undefined,
            'average': undefined,
            'baseVolume': parseFloat (ticker['volume_by_product']),
            'quoteVolume': undefined,
            'info': ticker,
        };
    }

    parseTrade (trade, market = undefined) {
        let side = undefined;
        let order = undefined;
        if ('side' in trade)
            if (trade['side']) {
                side = trade['side'].toLowerCase ();
                let id = side + '_child_order_acceptance_id';
                if (id in trade)
                    order = trade[id];
            }
        if (typeof order === 'undefined') {
            if ('child_order_acceptance_id' in trade) {
                order = trade['child_order_acceptance_id'];
            }
        }
        let timestamp = this.parse8601 (trade['exec_date']);
        return {
            'id': trade['id'].toString (),
            'info': trade,
            'timestamp': timestamp,
            'datetime': this.iso8601 (timestamp),
            'symbol': market['symbol'],
            'order': order,
            'type': undefined,
            'side': side,
            'price': trade['price'],
            'amount': trade['size'],
        };
    }

    async fetchTrades (symbol, since = undefined, limit = undefined, params = {}) {
        await this.loadMarkets ();
        let market = this.market (symbol);
        let response = await this.publicGetGetexecutions (this.extend ({
            'product_code': market['id'],
        }, params));
        return this.parseTrades (response, market, since, limit);
    }

    async createOrder (symbol, type, side, amount, price = undefined, params = {}) {
        await this.loadMarkets ();
        let order = {
            'product_code': this.marketId (symbol),
            'child_order_type': type.toUpperCase (),
            'side': side.toUpperCase (),
            'price': price,
            'size': amount,
        };
        let result = await this.privatePostSendchildorder (this.extend (order, params));
        // { "status": - 200, "error_message": "Insufficient funds", "data": null }
        return {
            'info': result,
            'id': result['child_order_acceptance_id'],
        };
    }

    async cancelOrder (id, symbol = undefined, params = {}) {
        if (typeof symbol === 'undefined')
            throw new ExchangeError (this.id + ' cancelOrder() requires a symbol argument');
        await this.loadMarkets ();
        return await this.privatePostCancelchildorder (this.extend ({
            'product_code': this.marketId (symbol),
            'child_order_acceptance_id': id,
        }, params));
    }

    parseOrderStatus (status) {
        let statuses = {
            'ACTIVE': 'open',
            'COMPLETED': 'closed',
            'CANCELED': 'canceled',
            'EXPIRED': 'canceled',
            'REJECTED': 'canceled',
        };
        if (status in statuses)
            return statuses[status];
        return status.toLowerCase ();
    }

    parseOrder (order, market = undefined) {
        let timestamp = this.parse8601 (order['child_order_date']);
        let amount = this.safeFloat (order, 'size');
        let remaining = this.safeFloat (order, 'outstanding_size');
        let filled = this.safeFloat (order, 'executed_size');
        let price = this.safeFloat (order, 'price');
        let cost = price * filled;
        let status = this.parseOrderStatus (order['child_order_state']);
        let type = order['child_order_type'].toLowerCase ();
        let side = order['side'].toLowerCase ();
        let symbol = undefined;
        if (typeof market === 'undefined') {
            let marketId = this.safeString (order, 'product_code');
            if (typeof marketId !== 'undefined') {
                if (marketId in this.markets_by_id)
                    market = this.markets_by_id[marketId];
            }
        }
        if (typeof market !== 'undefined')
            symbol = market['symbol'];
        let fee = undefined;
        let feeCost = this.safeFloat (order, 'total_commission');
        if (typeof feeCost !== 'undefined') {
            fee = {
                'cost': feeCost,
                'currency': undefined,
                'rate': undefined,
            };
        }
        return {
            'id': order['child_order_acceptance_id'],
            'info': order,
            'timestamp': timestamp,
            'datetime': this.iso8601 (timestamp),
            'status': status,
            'symbol': symbol,
            'type': type,
            'side': side,
            'price': price,
            'cost': cost,
            'amount': amount,
            'filled': filled,
            'remaining': remaining,
            'fee': fee,
        };
    }

    async fetchOrders (symbol = undefined, since = undefined, limit = 100, params = {}) {
        if (typeof symbol === 'undefined')
            throw new ExchangeError (this.id + ' fetchOrders() requires a symbol argument');
        await this.loadMarkets ();
        let market = this.market (symbol);
        let request = {
            'product_code': market['id'],
            'count': limit,
        };
        let response = await this.privateGetGetchildorders (this.extend (request, params));
        let orders = this.parseOrders (response, market, since, limit);
        if (symbol)
            orders = this.filterBy (orders, 'symbol', symbol);
        return orders;
    }

    async fetchOpenOrders (symbol = undefined, since = undefined, limit = 100, params = {}) {
        params['child_order_state'] = 'ACTIVE';
        return this.fetchOrders (symbol, since, limit, params);
    }

    async fetchClosedOrders (symbol = undefined, since = undefined, limit = 100, params = {}) {
        params['child_order_state'] = 'COMPLETED';
        return this.fetchOrders (symbol, since, limit, params);
    }

    async fetchOrder (id, symbol = undefined, params = {}) {
        if (typeof symbol === 'undefined')
            throw new ExchangeError (this.id + ' fetchOrder() requires a symbol argument');
        let orders = await this.fetchOrders (symbol);
        let ordersById = this.indexBy (orders, 'id');
        if (id in ordersById)
            return ordersById[id];
        throw new OrderNotFound (this.id + ' No order found with id ' + id);
    }

    async fetchMyTrades (symbol = undefined, since = undefined, limit = undefined, params = {}) {
        if (typeof symbol === 'undefined')
            throw new ExchangeError (this.id + ' fetchMyTrades requires a symbol argument');
        await this.loadMarkets ();
        let market = this.market (symbol);
        let request = {
            'product_code': market['id'],
        };
        if (limit)
            request['count'] = limit;
        let response = await this.privateGetGetexecutions (this.extend (request, params));
        return this.parseTrades (response, market, since, limit);
    }

    async withdraw (code, amount, address, tag = undefined, params = {}) {
        this.checkAddress (address);
        await this.loadMarkets ();
        if (code !== 'JPY' && code !== 'USD' && code !== 'EUR')
            throw new ExchangeError (this.id + ' allows withdrawing JPY, USD, EUR only, ' + code + ' is not supported');
        let currency = this.currency (code);
        let response = await this.privatePostWithdraw (this.extend ({
            'currency_code': currency['id'],
            'amount': amount,
            // 'bank_account_id': 1234,
        }, params));
        return {
            'info': response,
            'id': response['message_id'],
        };
    }

    sign (path, api = 'public', method = 'GET', params = {}, headers = undefined, body = undefined) {
        let request = '/' + this.version + '/';
        if (api === 'private')
            request += 'me/';
        request += path;
        if (method === 'GET') {
            if (Object.keys (params).length)
                request += '?' + this.urlencode (params);
        }
        let url = this.urls['api'] + request;
        if (api === 'private') {
            this.checkRequiredCredentials ();
            let nonce = this.nonce ().toString ();
            let auth = [ nonce, method, request ].join ('');
            if (Object.keys (params).length) {
                if (method !== 'GET') {
                    body = this.json (params);
                    auth += body;
                }
            }
            headers = {
                'ACCESS-KEY': this.apiKey,
                'ACCESS-TIMESTAMP': nonce,
                'ACCESS-SIGN': this.hmac (this.encode (auth), this.encode (this.secret)),
                'Content-Type': 'application/json',
            };
        }
        return { 'url': url, 'method': method, 'body': body, 'headers': headers };
    }
};
<|endoftext|>


<commit_before>// Copyright 2018 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

/**
 * @namespace google
 */
/**
 * @namespace google.cloud
 */
/**
 * @namespace google.cloud.scheduler
 */
/**
 * @namespace google.cloud.scheduler.v1beta1
 */
/**
 * @namespace google.protobuf
 */
/**
 * @namespace google.rpc
 */

'use strict';

// Import the clients for each version supported by this package.
const gapic = Object.freeze({
  v1beta1: require('./v1beta1'),
});

/**
 * The `scheduler` package has the following named exports:
 *
 * - `CloudSchedulerClient` - Reference to
 *   {@link v1beta1.CloudSchedulerClient}
 * - `v1beta1` - This is used for selecting or pinning a
 *   particular backend service version. It exports:
 *     - `CloudSchedulerClient` - Reference to
 *       {@link v1beta1.CloudSchedulerClient}
 *
 * @module {object} @google-cloud/scheduler
 * @alias nodejs-scheduler
 *
 * @example
Install the client library with npm:

 * npm install --save scheduler
 *
 * @example
Import the client library:

 * const scheduler = require('scheduler');
 *
 * @example
Create a client that uses Application Default Credentials (ADC):

 * const client = new scheduler.CloudSchedulerClient();
 *
 * @example
Create a client with explicit credentials:

 * const client = new scheduler.CloudSchedulerClient({
 *   projectId: 'your-project-id',
 *   keyFilename: '/path/to/keyfile.json',
 * });
 */

/**
 * @type {object}
 * @property {constructor} CloudSchedulerClient
 *   Reference to {@link v1beta1.CloudSchedulerClient}
 */
module.exports = gapic.v1beta1;

/**
 * @type {object}
 * @property {constructor} CloudSchedulerClient
 *   Reference to {@link v1beta1.CloudSchedulerClient}
 */
module.exports.v1beta1 = gapic.v1beta1;

// Alias `module.exports` as `module.exports.default`, for future-proofing.
module.exports.default = Object.assign({}, module.exports);
<commit_msg>fix(docs): require stmt (#30)<commit_after>// Copyright 2018 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

/**
 * @namespace google
 */
/**
 * @namespace google.cloud
 */
/**
 * @namespace google.cloud.scheduler
 */
/**
 * @namespace google.cloud.scheduler.v1beta1
 */
/**
 * @namespace google.protobuf
 */
/**
 * @namespace google.rpc
 */

'use strict';

// Import the clients for each version supported by this package.
const gapic = Object.freeze({
  v1beta1: require('./v1beta1'),
});

/**
 * The `scheduler` package has the following named exports:
 *
 * - `CloudSchedulerClient` - Reference to
 *   {@link v1beta1.CloudSchedulerClient}
 * - `v1beta1` - This is used for selecting or pinning a
 *   particular backend service version. It exports:
 *     - `CloudSchedulerClient` - Reference to
 *       {@link v1beta1.CloudSchedulerClient}
 *
 * @module {object} @google-cloud/scheduler
 * @alias nodejs-scheduler
 *
 * @example
Install the client library with npm:

 * npm install --save @google-cloud/scheduler
 *
 * @example
Import the client library:

 * const scheduler = require('@google-cloud/scheduler');
 *
 * @example
Create a client that uses Application Default Credentials (ADC):

 * const client = new scheduler.CloudSchedulerClient();
 *
 * @example
Create a client with explicit credentials:

 * const client = new scheduler.CloudSchedulerClient({
 *   projectId: 'your-project-id',
 *   keyFilename: '/path/to/keyfile.json',
 * });
 */

/**
 * @type {object}
 * @property {constructor} CloudSchedulerClient
 *   Reference to {@link v1beta1.CloudSchedulerClient}
 */
module.exports = gapic.v1beta1;

/**
 * @type {object}
 * @property {constructor} CloudSchedulerClient
 *   Reference to {@link v1beta1.CloudSchedulerClient}
 */
module.exports.v1beta1 = gapic.v1beta1;

// Alias `module.exports` as `module.exports.default`, for future-proofing.
module.exports.default = Object.assign({}, module.exports);
<|endoftext|>


<commit_before>'use strict';
var Alexa = require("alexa-sdk");
var request = require("request");
var APP_ID = "amzn1.ask.skill.c958f220-e3fb-4d54-876a-f9bf0e7bf43c"

exports.handler = function(event, context, callback) {
    var alexa = Alexa.handler(event, context);
    alexa.registerHandlers(handlers);
    alexa.execute();
};

var handlers = {
    'LaunchRequest': function () {
        this.emit('SayLunch');
    },
    'unhandled': function () {
        this.emit('SayLunch');
    },
    'LunchIntent': function () {
        this.emit('SayLunch');
    },
    'SayLunch': function () {
        var speechOutput = "I am having trouble getting the lunch menu.";
        var thisObj = this;

        var dateSlot = this.event.request.intent.slots.Date
        if (dateSlot && dateSlot.value) {
            var dateRequested = getDateFromSlot(dateSlot.value);
            console.log('Date specified.');
        }
        else {
            var dateRequested=new Date();
            console.log('No date in slot.');
        }
        console.log('The date requested is', dateRequested.toString());

        var ical = require('ical');
        ical.fromURL('http://www.chapin.edu/data/calendar/rsscache/calendar_282.ics', {}, function(err, data) {
        for (var k in data){
            if (data.hasOwnProperty(k)) {
              var ev = data[k]
//              console.log(ev.start.toString());
              if (dateRequested.getDate() == ev.start.getDate() && dateRequested.getMonth() == ev.start.getMonth())  {
                    speechOutput = "Lunch is " + ev.summary + ' on ' + dateRequested.toLocaleString("en-us", { month: "long" }) + " " + dateRequested.getDate();
                    console.log(speechOutput);

              }

            }
          }
          thisObj.emit(speechOutput);
        }); //ical

    } //saylunch
}; //handlers

// Given an AMAZON.DATE slot value parse out to usable JavaScript Date object
// Utterances that map to the weekend for a specific week (such as �this weekend�) convert to a date indicating the week number and weekend: 2015-W49-WE.
// Utterances that map to a month, but not a specific day (such as �next month�, or �December�) convert to a date with just the year and month: 2015-12.
// Utterances that map to a year (such as �next year�) convert to a date containing just the year: 2016.
// Utterances that map to a decade convert to a date indicating the decade: 201X.
// Utterances that map to a season (such as �next winter�) convert to a date with the year and a season indicator: winter: WI, spring: SP, summer: SU, fall: FA)
function getDateFromSlot(rawDate) {
    // try to parse data
    var date = new Date(Date.parse(rawDate));
    return date;
    var result;
    // create an empty object to use later
    var eventDate = {

    };

    // if could not parse data must be one of the other formats
    if (isNaN(date)) {
        // to find out what type of date this is, we can split it and count how many parts we have see comments above.
        var res = rawDate.split("-");
        // if we have 2 bits that include a 'W' week number
        if (res.length === 2 && res[1].indexOf('W') > -1) {
            var dates = getWeekData(res);
            eventDate["startDate"] = new Date(dates.startDate);
            eventDate["endDate"] = new Date(dates.endDate);
            // if we have 3 bits, we could either have a valid date (which would have parsed already) or a weekend
        } else if (res.length === 3) {
            var dates = getWeekendData(res);
            eventDate["startDate"] = new Date(dates.startDate);
            eventDate["endDate"] = new Date(dates.endDate);
            // anything else would be out of range for this skill
        } else {
            eventDate["error"] = dateOutOfRange;
        }
        // original slot value was parsed correctly
    } else {
        eventDate["startDate"] = new Date(date).setUTCHours(0, 0, 0, 0);
        eventDate["endDate"] = new Date(date).setUTCHours(24, 0, 0, 0);
    }
    return eventDate;
}
<commit_msg>Update index.js<commit_after>'use strict';
var Alexa = require("alexa-sdk");
var request = require("request");
var APP_ID = "amzn1.ask.skill.c958f220-e3fb-4d54-876a-f9bf0e7bf43c"
var monthNames = ["January", "February", "March", "April", "May", "June",
  "July", "August", "September", "October", "November", "December"
];

exports.handler = function(event, context, callback) {
    var alexa = Alexa.handler(event, context);
    alexa.registerHandlers(handlers);
    alexa.execute();
};

var handlers = {
    'LaunchRequest': function () {
        this.emit('SayLunch');
    },
    'unhandled': function () {
        this.emit('SayLunch');
    },
    'LunchIntent': function () {
        this.emit('SayLunch');
    },
    'SayLunch': function () {
        var speechOutput = "I am having trouble getting the lunch menu.";
        var thisObj = this;

        var dateSlot = this.event.request.intent.slots.Date
        if (dateSlot && dateSlot.value) {
            var dateRequested = getDateFromSlot(dateSlot.value);
            console.log('Date specified.');
        }
        else {
            var dateRequested=new Date();
            console.log('No date in slot.');
        }
        console.log('The date requested is', dateRequested.toString());

        var ical = require('ical');
        ical.fromURL('http://www.chapin.edu/data/calendar/rsscache/calendar_282.ics', {}, function(err, data) {
        for (var k in data){
            if (data.hasOwnProperty(k)) {
              var ev = data[k]
//              console.log(ev.start.toString());
              if (dateRequested.getDate() == ev.start.getDate() && dateRequested.getMonth() == ev.start.getMonth())  {
                    speechOutput = "Lunch is " + ev.summary + ' on ' +  monthNames[dateRequested.getMonth()] + " " + dateRequested.getDate();
                    console.log(speechOutput);

              }

            }
          }
          thisObj.emit(speechOutput);
        }); //ical

    } //saylunch
}; //handlers

// Given an AMAZON.DATE slot value parse out to usable JavaScript Date object
// Utterances that map to the weekend for a specific week (such as �this weekend�) convert to a date indicating the week number and weekend: 2015-W49-WE.
// Utterances that map to a month, but not a specific day (such as �next month�, or �December�) convert to a date with just the year and month: 2015-12.
// Utterances that map to a year (such as �next year�) convert to a date containing just the year: 2016.
// Utterances that map to a decade convert to a date indicating the decade: 201X.
// Utterances that map to a season (such as �next winter�) convert to a date with the year and a season indicator: winter: WI, spring: SP, summer: SU, fall: FA)
function getDateFromSlot(rawDate) {
    // try to parse data
    var date = new Date(Date.parse(rawDate));
    return date;
    var result;
    // create an empty object to use later
    var eventDate = {

    };

    // if could not parse data must be one of the other formats
    if (isNaN(date)) {
        // to find out what type of date this is, we can split it and count how many parts we have see comments above.
        var res = rawDate.split("-");
        // if we have 2 bits that include a 'W' week number
        if (res.length === 2 && res[1].indexOf('W') > -1) {
            var dates = getWeekData(res);
            eventDate["startDate"] = new Date(dates.startDate);
            eventDate["endDate"] = new Date(dates.endDate);
            // if we have 3 bits, we could either have a valid date (which would have parsed already) or a weekend
        } else if (res.length === 3) {
            var dates = getWeekendData(res);
            eventDate["startDate"] = new Date(dates.startDate);
            eventDate["endDate"] = new Date(dates.endDate);
            // anything else would be out of range for this skill
        } else {
            eventDate["error"] = dateOutOfRange;
        }
        // original slot value was parsed correctly
    } else {
        eventDate["startDate"] = new Date(date).setUTCHours(0, 0, 0, 0);
        eventDate["endDate"] = new Date(date).setUTCHours(24, 0, 0, 0);
    }
    return eventDate;
}
<|endoftext|>


<commit_before>import stylelint from 'stylelint'
import shortCSS from 'shortcss'

import {
  validProperties, validOptions, expected, getTypes, getIgnoredKeywords, getIgnoredValues, getAutoFixFunc,
} from './lib/validation'
import defaults from './defaults'

/**
 * Rule Name.
 *
 * @constant {string}
 * @default
 */
const ruleName = 'scale-unlimited/declaration-strict-value'
const { utils } = stylelint
const messages = utils.ruleMessages(ruleName, {
  expected,
})
/**
 * RegExp to skip non-CSS properties.
 *
 * @constant  {RegExp}
 * @default
 */
const reSkipProp = /^(?:@|\$|--).+$/
/**
 * RegExp to parse CSS, SCSS and less variables.
 * - allowing CSS variables to be multi line
 * - Sass namespaces and CSS <ident-token> supported
 *
 * @see https://github.com/sass/sass/blob/master/accepted/module-system.md#member-references
 * @see  https://drafts.csswg.org/css-syntax-3/#ident-token-diagram
 * @constant {RegExp}
 * @default
 */
// eslint-disable-next-line no-control-regex
const reVar = /^-?(?:@.+|(?:(?:[a-zA-Z_-]|[^\x00-\x7F])+(?:[a-zA-Z0-9_-]|[^\x00-\x7F])*\.)?\$.+|var\(\s*--[\s\S]+\))$/
/**
 * RegExp to parse functions.
 * - irgnoring CSS variables `var(--*)`
 * - allow multi line arguments
 *
 * @constant  {RegExp}
 * @default
 */
const reFunc = /^(?!var\(\s*--)[\s\S]+\([\s\S]*\)$/
/**
 * RegExp to parse regular expressions.
 * - supporting patterns
 * - and optional flags
 *
 * @constant  {RegExp}
 * @default
 */
const reRegex = /^\/(.*)\/([a-zA-Z]*)$/
const isRegexString = (value) => reRegex.test(value)
const getRegexString = (value) => value.match(reRegex).slice(1)
const stringToRegex = (value) => new RegExp(...getRegexString(value))
const mapIgnoreValue = (ignoreValue) => (isRegexString(ignoreValue) ? stringToRegex(ignoreValue) : new RegExp(`^${ignoreValue}$`))

/**
 * A rule function essentially returns a little PostCSS plugin.
 * It will report violations of this rule.
 *
 * @typedef {Function} PostCSSPlugin
 * @param {object} root - PostCSS root (the parsed AST).
 * @param {object} result - PostCSS lazy result.
 */

/**
 * Stylelint declaration strict value rule function.
 *
 * @see https://stylelint.io/developer-guide/plugins
 * @param {string|string[]} properties - Primary options, a CSS property or list of CSS properties to lint.
 * @param {SecondaryOptions} [options=defaults] - Secondary options, configure edge cases.
 * @param {*} [context] - Only used for autofixing.
 *
 * @returns {PostCSSPlugin} - Returns a PostCSS Plugin.
 */
const ruleFunction = (properties, options, context = {}) => (root, result) => {
  // validate stylelint plugin options
  const hasValidOptions = utils.validateOptions(
    result,
    ruleName,
    {
      actual: properties,
      possible: validProperties,
    },
    {
      actual: options,
      possible: validOptions,
      optional: true,
    },
  )

  if (!hasValidOptions) return

  // normalize options
  if (!Array.isArray(properties)) {
    // eslint-disable-next-line no-param-reassign
    properties = [properties]
  }

  const config = {
    ...defaults,
    ...options,
  }
  const {
    ignoreVariables, ignoreFunctions, ignoreKeywords, ignoreValues, message, disableFix, autoFixFunc, expandShorthand, recurseLonghand,
  } = config
  const autoFixFuncNormalized = getAutoFixFunc(autoFixFunc)
  const reKeywords = ignoreKeywords ? {} : null
  const reValues = ignoreValues ? {} : null

  // loop through all properties
  properties.forEach((property) => {
    let propFilter = property

    // parse RegExp
    if (isRegexString(propFilter)) {
      propFilter = stringToRegex(propFilter)
    }

    // walk through all declarations filtered by configured properties
    root.walkDecls(filterDesls)

    /**
     * Filter declarations for matching properties and expand shorthand properties.
     *
     * @callback
     * @param {object} node - A Declaration-Node from PostCSS AST-Parser.
     */
    function filterDesls(node) {
      const { value: originalValue, prop: originalProp } = node

      // skip variable declarations
      if (reSkipProp.test(originalProp)) return

      if (originalProp === propFilter || (propFilter instanceof RegExp && propFilter.test(originalProp))) {
        lintDeclStrictValue(node)
      } else if (expandShorthand && shortCSS.isShorthand(originalProp)) {
        const expandedProps = shortCSS.expand(originalProp, originalValue, recurseLonghand)

        Object.keys(expandedProps).forEach((prop) => {
          const value = expandedProps[prop]

          if (prop === propFilter || (propFilter instanceof RegExp && propFilter.test(prop))) {
            const { raws } = node

            lintDeclStrictValue(node.clone({ value, prop, raws }))
          }
        })
      }
    }

    /**
     * Lint usages of declarations values againts, variables, functions
     * or custum keywords - as configured.
     *
     * @callback
     * @param {object} node - A Declaration-Node from PostCSS AST-Parser.
     */
    function lintDeclStrictValue(node) {
      const { value, prop } = node

      // falsify everything by default
      let validVar = false
      let validFunc = false
      let validKeyword = false
      let validValue = false

      // test variable
      if (ignoreVariables) {
        validVar = reVar.test(value)
      }

      // test function
      if (ignoreFunctions && !validVar) {
        validFunc = reFunc.test(value)
      }

      // test keywords
      if (ignoreKeywords && (!validVar || !validFunc)) {
        let reKeyword = reKeywords[property]

        if (!reKeyword) {
          const ignoreKeyword = getIgnoredKeywords(ignoreKeywords, property)

          if (ignoreKeyword) {
            reKeyword = new RegExp(`^${ignoreKeyword.join('$|^')}$`)
            reKeywords[property] = reKeyword
          }
        }

        if (reKeyword) {
          validKeyword = reKeyword.test(value)
        }
      }

      if (ignoreValues && (!validVar || !validFunc || !validKeyword)) {
        let reValueList = reValues[property]

        if (!reValueList) {
          const ignoreValue = getIgnoredValues(ignoreValues, property)

          if (ignoreValue) {
            reValueList = ignoreValue.map(mapIgnoreValue)
            reValues[property] = reValueList
          }
        }

        if (reValueList) {
          validValue = reValueList.filter((reValue) => reValue.test(value)).length > 0
        }
      }

      // report only if all failed
      if (!validVar && !validFunc && !validKeyword && !validValue) {
        const types = getTypes(config, property)
        const { raws } = node
        const { start } = node.source

        // support auto fixing
        if (context.fix && !disableFix) {
          const fixedValue = autoFixFuncNormalized(node, {
            validVar,
            validFunc,
            validKeyword,
            validValue,
          }, root, config)

          // apply fixed value if returned
          if (fixedValue) {
            // eslint-disable-next-line no-param-reassign
            node.value = fixedValue
          }
        } else {
          utils.report({
            ruleName,
            result,
            node,
            line: start.line,
            column: start.column + prop.length + raws.between.length,
            message: messages.expected(types, value, prop, message),
          })
        }
      }
    }
  })
}

ruleFunction.primaryOptionArray = true

const declarationStrictValuePlugin = stylelint.createPlugin(ruleName, ruleFunction)

export default declarationStrictValuePlugin
export { ruleName, messages }
<commit_msg>fix: typo<commit_after>import stylelint from 'stylelint'
import shortCSS from 'shortcss'

import {
  validProperties, validOptions, expected, getTypes, getIgnoredKeywords, getIgnoredValues, getAutoFixFunc,
} from './lib/validation'
import defaults from './defaults'

/**
 * Rule Name.
 *
 * @constant {string}
 * @default
 */
const ruleName = 'scale-unlimited/declaration-strict-value'
const { utils } = stylelint
const messages = utils.ruleMessages(ruleName, {
  expected,
})
/**
 * RegExp to skip non-CSS properties.
 *
 * @constant  {RegExp}
 * @default
 */
const reSkipProp = /^(?:@|\$|--).+$/
/**
 * RegExp to parse CSS, SCSS and less variables.
 * - allowing CSS variables to be multi line
 * - Sass namespaces and CSS <ident-token> supported
 *
 * @see https://github.com/sass/sass/blob/master/accepted/module-system.md#member-references
 * @see  https://drafts.csswg.org/css-syntax-3/#ident-token-diagram
 * @constant {RegExp}
 * @default
 */
// eslint-disable-next-line no-control-regex
const reVar = /^-?(?:@.+|(?:(?:[a-zA-Z_-]|[^\x00-\x7F])+(?:[a-zA-Z0-9_-]|[^\x00-\x7F])*\.)?\$.+|var\(\s*--[\s\S]+\))$/
/**
 * RegExp to parse functions.
 * - irgnoring CSS variables `var(--*)`
 * - allow multi line arguments
 *
 * @constant  {RegExp}
 * @default
 */
const reFunc = /^(?!var\(\s*--)[\s\S]+\([\s\S]*\)$/
/**
 * RegExp to parse regular expressions.
 * - supporting patterns
 * - and optional flags
 *
 * @constant  {RegExp}
 * @default
 */
const reRegex = /^\/(.*)\/([a-zA-Z]*)$/
const isRegexString = (value) => reRegex.test(value)
const getRegexString = (value) => value.match(reRegex).slice(1)
const stringToRegex = (value) => new RegExp(...getRegexString(value))
const mapIgnoreValue = (ignoreValue) => (isRegexString(ignoreValue) ? stringToRegex(ignoreValue) : new RegExp(`^${ignoreValue}$`))

/**
 * A rule function essentially returns a little PostCSS plugin.
 * It will report violations of this rule.
 *
 * @typedef {Function} PostCSSPlugin
 * @param {object} root - PostCSS root (the parsed AST).
 * @param {object} result - PostCSS lazy result.
 */

/**
 * Stylelint declaration strict value rule function.
 *
 * @see https://stylelint.io/developer-guide/plugins
 * @param {string|string[]} properties - Primary options, a CSS property or list of CSS properties to lint.
 * @param {SecondaryOptions} [options=defaults] - Secondary options, configure edge cases.
 * @param {*} [context] - Only used for autofixing.
 *
 * @returns {PostCSSPlugin} - Returns a PostCSS Plugin.
 */
const ruleFunction = (properties, options, context = {}) => (root, result) => {
  // validate stylelint plugin options
  const hasValidOptions = utils.validateOptions(
    result,
    ruleName,
    {
      actual: properties,
      possible: validProperties,
    },
    {
      actual: options,
      possible: validOptions,
      optional: true,
    },
  )

  if (!hasValidOptions) return

  // normalize options
  if (!Array.isArray(properties)) {
    // eslint-disable-next-line no-param-reassign
    properties = [properties]
  }

  const config = {
    ...defaults,
    ...options,
  }
  const {
    ignoreVariables, ignoreFunctions, ignoreKeywords, ignoreValues, message, disableFix, autoFixFunc, expandShorthand, recurseLonghand,
  } = config
  const autoFixFuncNormalized = getAutoFixFunc(autoFixFunc)
  const reKeywords = ignoreKeywords ? {} : null
  const reValues = ignoreValues ? {} : null

  // loop through all properties
  properties.forEach((property) => {
    let propFilter = property

    // parse RegExp
    if (isRegexString(propFilter)) {
      propFilter = stringToRegex(propFilter)
    }

    // walk through all declarations filtered by configured properties
    root.walkDecls(filterDecl)

    /**
     * Filter declarations for matching properties and expand shorthand properties.
     *
     * @callback
     * @param {object} node - A Declaration-Node from PostCSS AST-Parser.
     */
    function filterDecl(node) {
      const { value: originalValue, prop: originalProp } = node

      // skip variable declarations
      if (reSkipProp.test(originalProp)) return

      if (originalProp === propFilter || (propFilter instanceof RegExp && propFilter.test(originalProp))) {
        lintDeclStrictValue(node)
      } else if (expandShorthand && shortCSS.isShorthand(originalProp)) {
        const expandedProps = shortCSS.expand(originalProp, originalValue, recurseLonghand)

        Object.keys(expandedProps).forEach((prop) => {
          const value = expandedProps[prop]

          if (prop === propFilter || (propFilter instanceof RegExp && propFilter.test(prop))) {
            const { raws } = node

            lintDeclStrictValue(node.clone({ value, prop, raws }))
          }
        })
      }
    }

    /**
     * Lint usages of declarations values againts, variables, functions
     * or custum keywords - as configured.
     *
     * @callback
     * @param {object} node - A Declaration-Node from PostCSS AST-Parser.
     */
    function lintDeclStrictValue(node) {
      const { value, prop } = node

      // falsify everything by default
      let validVar = false
      let validFunc = false
      let validKeyword = false
      let validValue = false

      // test variable
      if (ignoreVariables) {
        validVar = reVar.test(value)
      }

      // test function
      if (ignoreFunctions && !validVar) {
        validFunc = reFunc.test(value)
      }

      // test keywords
      if (ignoreKeywords && (!validVar || !validFunc)) {
        let reKeyword = reKeywords[property]

        if (!reKeyword) {
          const ignoreKeyword = getIgnoredKeywords(ignoreKeywords, property)

          if (ignoreKeyword) {
            reKeyword = new RegExp(`^${ignoreKeyword.join('$|^')}$`)
            reKeywords[property] = reKeyword
          }
        }

        if (reKeyword) {
          validKeyword = reKeyword.test(value)
        }
      }

      if (ignoreValues && (!validVar || !validFunc || !validKeyword)) {
        let reValueList = reValues[property]

        if (!reValueList) {
          const ignoreValue = getIgnoredValues(ignoreValues, property)

          if (ignoreValue) {
            reValueList = ignoreValue.map(mapIgnoreValue)
            reValues[property] = reValueList
          }
        }

        if (reValueList) {
          validValue = reValueList.filter((reValue) => reValue.test(value)).length > 0
        }
      }

      // report only if all failed
      if (!validVar && !validFunc && !validKeyword && !validValue) {
        const types = getTypes(config, property)
        const { raws } = node
        const { start } = node.source

        // support auto fixing
        if (context.fix && !disableFix) {
          const fixedValue = autoFixFuncNormalized(node, {
            validVar,
            validFunc,
            validKeyword,
            validValue,
          }, root, config)

          // apply fixed value if returned
          if (fixedValue) {
            // eslint-disable-next-line no-param-reassign
            node.value = fixedValue
          }
        } else {
          utils.report({
            ruleName,
            result,
            node,
            line: start.line,
            column: start.column + prop.length + raws.between.length,
            message: messages.expected(types, value, prop, message),
          })
        }
      }
    }
  })
}

ruleFunction.primaryOptionArray = true

const declarationStrictValuePlugin = stylelint.createPlugin(ruleName, ruleFunction)

export default declarationStrictValuePlugin
export { ruleName, messages }
<|endoftext|>


<commit_before>import { readFile } from 'fs'
import { createServer as createHttpsServer } from 'https'
import { createServer } from 'http'
import { resolve } from 'path'

import mime from 'mime'
import opener from 'opener'

let server

/**
 * Serve your rolled up bundle like webpack-dev-server
 * @param {ServeOptions|string|string[]} options
 */
function serve (options = { contentBase: '' }) {
  if (Array.isArray(options) || typeof options === 'string') {
    options = { contentBase: options }
  }
  options.contentBase = Array.isArray(options.contentBase) ? options.contentBase : [options.contentBase]
  options.host = options.host || 'localhost'
  options.port = options.port || 10001
  options.headers = options.headers || {}
  options.https = options.https || false
  options.openPage = options.openPage || ''
  mime.default_type = 'text/plain'

  const requestListener = (request, response) => {
    // Remove querystring
    const urlPath = decodeURI(request.url.split('?')[0])

    Object.keys(options.headers).forEach((key) => {
      response.setHeader(key, options.headers[key])
    })

    readFileFromContentBase(options.contentBase, urlPath, function (error, content, filePath) {
      if (!error) {
        return found(response, filePath, content)
      }
      if (error.code !== 'ENOENT') {
        response.writeHead(500)
        response.end('500 Internal Server Error' +
          '\n\n' + filePath +
          '\n\n' + Object.values(error).join('\n') +
          '\n\n(rollup-plugin-serve)', 'utf-8')
        return
      }
      if (options.historyApiFallback) {
        var fallbackPath = typeof options.historyApiFallback === 'string' ? options.historyApiFallback : '/index.html'
        readFileFromContentBase(options.contentBase, fallbackPath, function (error, content, filePath) {
          if (error) {
            notFound(response, filePath)
          } else {
            found(response, filePath, content)
          }
        })
      } else {
        notFound(response, filePath)
      }
    })
  }

  // release previous server instance if rollup is reloading configuration in watch mode
  if (server) {
    server.close()
  }

  // If HTTPS options are available, create an HTTPS server
  if (options.https) {
    server = createHttpsServer(options.https, requestListener).listen(options.port, options.host)
  } else {
    server = createServer(requestListener).listen(options.port, options.host)
  }

  closeServerOnTermination(server)

  var running = options.verbose === false

  return {
    name: 'serve',
    generateBundle () {
      if (!running) {
        running = true

        // Log which url to visit
        const url = (options.https ? 'https' : 'http') + '://' + options.host + ':' + options.port
        options.contentBase.forEach(base => {
          console.log(green(url) + ' -> ' + resolve(base))
        })

        // Open browser
        if (options.open) {
          opener(url + options.openPage)
        }
      }
    }
  }
}

function readFileFromContentBase (contentBase, urlPath, callback) {
  let filePath = resolve(contentBase[0] || '.', '.' + urlPath)

  // Load index.html in directories
  if (urlPath.endsWith('/')) {
    filePath = resolve(filePath, 'index.html')
  }

  readFile(filePath, (error, content) => {
    if (error && contentBase.length > 1) {
      // Try to read from next contentBase
      readFileFromContentBase(contentBase.slice(1), urlPath, callback)
    } else {
      // We know enough
      callback(error, content, filePath)
    }
  })
}

function notFound (response, filePath) {
  response.writeHead(404)
  response.end('404 Not Found' +
    '\n\n' + filePath +
    '\n\n(rollup-plugin-serve)', 'utf-8')
}

function found (response, filePath, content) {
  response.writeHead(200, { 'Content-Type': mime.getType(filePath) })
  response.end(content, 'utf-8')
}

function green (text) {
  return '\u001b[1m\u001b[32m' + text + '\u001b[39m\u001b[22m'
}

function closeServerOnTermination (server) {
  const terminationSignals = ['SIGINT', 'SIGTERM']
  terminationSignals.forEach((signal) => {
    process.on(signal, () => {
      server.close()
      process.exit()
    })
  })
}

export default serve

/**
 * @typedef {Object} ServeOptions
 * @property {boolean} [open=false] Launch in browser (default: `false`)
 * @property {string} [openPage=''] Page to navigate to when opening the browser. Will not do anything if `open` is `false`. Remember to start with a slash e.g. `'/different/page'`
 * @property {boolean} [verbose=true] Show server address in console (default: `true`)
 * @property {string|string[]} [contentBase=''] Folder(s) to serve files from
 * @property {string|boolean} [historyApiFallback] Path to fallback page. Set to `true` to return index.html (200) instead of error page (404)
 * @property {string} [host='localhost'] Server host (default: `'localhost'`)
 * @property {number} [port=10001] Server port (default: `10001`)
 * @property {ServeOptionsHttps} [https=false] By default server will be served over HTTP (https: `false`). It can optionally be served over HTTPS
 * @property {{[header:string]: string}} [headers] Set headers
 */

/**
 * @typedef {Object} ServeOptionsHttps
 * @property {string|Buffer|Buffer[]|Object[]} key
 * @property {string|Buffer|Array<string|Buffer>} cert
 * @property {string|Buffer|Array<string|Buffer>} ca
 * @see https.ServerOptions
 */
<commit_msg>Also listen to SIGQUIT and SIGHUP<commit_after>import { readFile } from 'fs'
import { createServer as createHttpsServer } from 'https'
import { createServer } from 'http'
import { resolve } from 'path'

import mime from 'mime'
import opener from 'opener'

let server

/**
 * Serve your rolled up bundle like webpack-dev-server
 * @param {ServeOptions|string|string[]} options
 */
function serve (options = { contentBase: '' }) {
  if (Array.isArray(options) || typeof options === 'string') {
    options = { contentBase: options }
  }
  options.contentBase = Array.isArray(options.contentBase) ? options.contentBase : [options.contentBase]
  options.host = options.host || 'localhost'
  options.port = options.port || 10001
  options.headers = options.headers || {}
  options.https = options.https || false
  options.openPage = options.openPage || ''
  mime.default_type = 'text/plain'

  const requestListener = (request, response) => {
    // Remove querystring
    const urlPath = decodeURI(request.url.split('?')[0])

    Object.keys(options.headers).forEach((key) => {
      response.setHeader(key, options.headers[key])
    })

    readFileFromContentBase(options.contentBase, urlPath, function (error, content, filePath) {
      if (!error) {
        return found(response, filePath, content)
      }
      if (error.code !== 'ENOENT') {
        response.writeHead(500)
        response.end('500 Internal Server Error' +
          '\n\n' + filePath +
          '\n\n' + Object.values(error).join('\n') +
          '\n\n(rollup-plugin-serve)', 'utf-8')
        return
      }
      if (options.historyApiFallback) {
        var fallbackPath = typeof options.historyApiFallback === 'string' ? options.historyApiFallback : '/index.html'
        readFileFromContentBase(options.contentBase, fallbackPath, function (error, content, filePath) {
          if (error) {
            notFound(response, filePath)
          } else {
            found(response, filePath, content)
          }
        })
      } else {
        notFound(response, filePath)
      }
    })
  }

  // release previous server instance if rollup is reloading configuration in watch mode
  if (server) {
    server.close()
  }

  // If HTTPS options are available, create an HTTPS server
  if (options.https) {
    server = createHttpsServer(options.https, requestListener).listen(options.port, options.host)
  } else {
    server = createServer(requestListener).listen(options.port, options.host)
  }

  closeServerOnTermination(server)

  var running = options.verbose === false

  return {
    name: 'serve',
    generateBundle () {
      if (!running) {
        running = true

        // Log which url to visit
        const url = (options.https ? 'https' : 'http') + '://' + options.host + ':' + options.port
        options.contentBase.forEach(base => {
          console.log(green(url) + ' -> ' + resolve(base))
        })

        // Open browser
        if (options.open) {
          opener(url + options.openPage)
        }
      }
    }
  }
}

function readFileFromContentBase (contentBase, urlPath, callback) {
  let filePath = resolve(contentBase[0] || '.', '.' + urlPath)

  // Load index.html in directories
  if (urlPath.endsWith('/')) {
    filePath = resolve(filePath, 'index.html')
  }

  readFile(filePath, (error, content) => {
    if (error && contentBase.length > 1) {
      // Try to read from next contentBase
      readFileFromContentBase(contentBase.slice(1), urlPath, callback)
    } else {
      // We know enough
      callback(error, content, filePath)
    }
  })
}

function notFound (response, filePath) {
  response.writeHead(404)
  response.end('404 Not Found' +
    '\n\n' + filePath +
    '\n\n(rollup-plugin-serve)', 'utf-8')
}

function found (response, filePath, content) {
  response.writeHead(200, { 'Content-Type': mime.getType(filePath) })
  response.end(content, 'utf-8')
}

function green (text) {
  return '\u001b[1m\u001b[32m' + text + '\u001b[39m\u001b[22m'
}

function closeServerOnTermination (server) {
  const terminationSignals = ['SIGINT', 'SIGTERM', 'SIGQUIT', 'SIGHUP']
  terminationSignals.forEach((signal) => {
    process.on(signal, () => {
      server.close()
      process.exit()
    })
  })
}

export default serve

/**
 * @typedef {Object} ServeOptions
 * @property {boolean} [open=false] Launch in browser (default: `false`)
 * @property {string} [openPage=''] Page to navigate to when opening the browser. Will not do anything if `open` is `false`. Remember to start with a slash e.g. `'/different/page'`
 * @property {boolean} [verbose=true] Show server address in console (default: `true`)
 * @property {string|string[]} [contentBase=''] Folder(s) to serve files from
 * @property {string|boolean} [historyApiFallback] Path to fallback page. Set to `true` to return index.html (200) instead of error page (404)
 * @property {string} [host='localhost'] Server host (default: `'localhost'`)
 * @property {number} [port=10001] Server port (default: `10001`)
 * @property {ServeOptionsHttps} [https=false] By default server will be served over HTTP (https: `false`). It can optionally be served over HTTPS
 * @property {{[header:string]: string}} [headers] Set headers
 */

/**
 * @typedef {Object} ServeOptionsHttps
 * @property {string|Buffer|Buffer[]|Object[]} key
 * @property {string|Buffer|Array<string|Buffer>} cert
 * @property {string|Buffer|Array<string|Buffer>} ca
 * @see https.ServerOptions
 */
<|endoftext|>