<commit_before>import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';

import ReactAudioPlayer from 'react-audio-player';
import axios from "axios";

class availableDatalist extends React.Component {
   availableDatalist(props) {
    return(

{props.all_songs.map(c => <{c.name} {c.album} />)}

    )

  }
}

class SongBoard extends React.Component {
getAllSongs() {
  axios
  .get("http://localhost:8000/song/")
  .then(response => {
    const songs = response.data.map(c => {
      return{
        name: c.name
        album: c.album
      };
    });

    const newState = Object.assign({}, this.state, {
          all_songs: songs
        });

    this.setState(newState);

  })
  .catch(error => console.log(error));
}

  render() {
    return(

            <button className="song">
              Song
            </button>
            <button className="album">
              Album
            </button>

          <availableDatalist songs={this.state.all_songs} />

    )
  }
}

class Player extends React.Component {
  render() {
    return(
      <ReactAudioPlayer
        src="my_audio_file.ogg"
        autoPlay
        controls
      />
    )
  }
}

class Site extends React.Component {
  render() {
    return (

          <Player />

          <SongBoard />

    )
  }
}

ReactDOM.render(
  <Site />,
  document.getElementById('root')
);
<commit_msg>reactplayer<commit_after>import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';

import ReactAudioPlayer from 'react-audio-player';
import axios from "axios";

class availableDatalist extends React.Component {
   availableDatalist(props) {
    return(

{props.all_songs.map(c =>
c.name

c.album
 )}

    )

  }
}

class SongBoard extends React.Component {
getAllSongs() {
  axios
  .get("http://localhost:8000/song/")
  .then(response => {
    const songs = response.data.map(c => {
      return{
        name: c.name
        album: c.album
      };
    });

    const newState = Object.assign({}, this.state, {
          all_songs: songs
        });

    this.setState(newState);

  })
  .catch(error => console.log(error));
}

  render() {
    return(

            <button className="song">
              Song
            </button>
            <button className="album">
              Album
            </button>

          <availableDatalist songs={this.state.all_songs} />

    )
  }
}

class Player extends React.Component {
  render() {
    return(
      <ReactAudioPlayer
        src="my_audio_file.ogg"
        autoPlay
        controls
      />
    )
  }
}

class Site extends React.Component {
  render() {
    return (

          <Player />

          <SongBoard />

    )
  }
}

ReactDOM.render(
  <Site />,
  document.getElementById('root')
);
<|endoftext|>


<commit_before>const os = require('os')
const path = require('path')
const zlib = require('zlib')
const fse = require('fs-extra')
const miss = require('mississippi')
const split = require('split2')
const archiver = require('archiver')
const debug = require('./debug')
const AssetHandler = require('./AssetHandler')
const stringifyStream = require('./stringifyStream')
const validateOptions = require('./validateOptions')
const rejectOnApiError = require('./rejectOnApiError')
const getDocumentsStream = require('./getDocumentsStream')
const filterSystemDocuments = require('./filterSystemDocuments')
const filterDocumentTypes = require('./filterDocumentTypes')
const filterDrafts = require('./filterDrafts')
const logFirstChunk = require('./logFirstChunk')

const noop = () => null

function exportDataset(opts) {
  const options = validateOptions(opts)
  const onProgress = options.onProgress || noop
  const archive = archiver('tar', {
    gzip: true,
    gzipOptions: {level: options.compress ? zlib.Z_DEFAULT_COMPRESSION : zlib.Z_NO_COMPRESSION}
  })

  const slugDate = new Date()
    .toISOString()
    .replace(/[^a-z0-9]/gi, '-')
    .toLowerCase()

  const prefix = `${opts.dataset}-export-${slugDate}`
  const tmpDir = path.join(os.tmpdir(), prefix)
  const assetHandler = new AssetHandler({
    client: options.client,
    tmpDir,
    prefix
  })

  debug('Outputting assets (temporarily) to %s', tmpDir)
  debug('Outputting to %s', options.outputPath === '-' ? 'stdout' : options.outputPath)
  const outputStream =
    options.outputPath === '-' ? process.stdout : fse.createWriteStream(options.outputPath)

  let assetStreamHandler = assetHandler.noop
  if (!options.raw) {
    assetStreamHandler = options.assets ? assetHandler.rewriteAssets : assetHandler.stripAssets
  }

  return new Promise(async (resolve, reject) => {
    miss.finished(archive, archiveErr => {
      if (archiveErr) {
        debug('Archiving errored! %s', archiveErr.stack)
        reject(archiveErr)
        return
      }

      debug('Archive finished!')
    })

    debug('Getting dataset export stream')
    onProgress({step: 'Exporting documents...'})

    let documentCount = 0
    let lastReported = Date.now()
    const reportDocumentCount = (chunk, enc, cb) => {
      ++documentCount

      const now = Date.now()
      if (now - lastReported > 50) {
        onProgress({
          step: 'Exporting documents...',
          current: documentCount,
          total: '?',
          update: true
        })

        lastReported = now
      }

      cb(null, chunk)
    }

    const inputStream = await getDocumentsStream(options.client, options.dataset)
    debug('Got HTTP %d', inputStream.statusCode)
    debug('Response headers: %o', inputStream.headers)

    const jsonStream = miss.pipeline(
      inputStream,
      logFirstChunk(),
      split(JSON.parse),
      rejectOnApiError(),
      filterSystemDocuments(),
      assetStreamHandler,
      filterDocumentTypes(options.types),
      options.drafts ? miss.through.obj() : filterDrafts(),
      stringifyStream(),
      miss.through(reportDocumentCount)
    )

    miss.finished(jsonStream, async err => {
      if (err) {
        return
      }

      onProgress({
        step: 'Exporting documents...',
        current: documentCount,
        total: documentCount,
        update: true
      })

      if (!options.raw && options.assets) {
        onProgress({step: 'Downloading assets...'})
      }

      let prevCompleted = 0
      const progressInterval = setInterval(() => {
        const completed = assetHandler.queueSize - assetHandler.queue.size
        if (prevCompleted === completed) {
          return
        }

        prevCompleted = completed
        onProgress({
          step: 'Downloading assets...',
          current: completed,
          total: assetHandler.queueSize,
          update: true
        })
      }, 500)

      debug('Waiting for asset handler to complete downloads')
      try {
        const assetMap = await assetHandler.finish()
        archive.append(JSON.stringify(assetMap), {name: 'assets.json', prefix})
        clearInterval(progressInterval)
      } catch (assetErr) {
        clearInterval(progressInterval)
        reject(assetErr)
        return
      }

      // Add all downloaded assets to archive
      archive.directory(path.join(tmpDir, 'files'), `${prefix}/files`, {store: true})
      archive.directory(path.join(tmpDir, 'images'), `${prefix}/images`, {store: true})

      debug('Finalizing archive, flushing streams')
      onProgress({step: 'Adding assets to archive...'})
      archive.finalize()
    })

    archive.on('warning', err => {
      debug('Archive warning: %s', err.message)
    })

    archive.append(jsonStream, {name: 'data.ndjson', prefix})
    miss.pipe(
      archive,
      outputStream,
      onComplete
    )

    async function onComplete(err) {
      onProgress({step: 'Clearing temporary files...'})
      await fse.remove(tmpDir)

      if (!err) {
        resolve()
        return
      }

      debug('Error during streaming: %s', err.stack)
      assetHandler.clear()
      reject(err)
    }
  })
}

module.exports = exportDataset
<commit_msg>[export] Clean up temporary files on failure (#1347)<commit_after>const os = require('os')
const path = require('path')
const zlib = require('zlib')
const fse = require('fs-extra')
const miss = require('mississippi')
const split = require('split2')
const archiver = require('archiver')
const debug = require('./debug')
const AssetHandler = require('./AssetHandler')
const stringifyStream = require('./stringifyStream')
const validateOptions = require('./validateOptions')
const rejectOnApiError = require('./rejectOnApiError')
const getDocumentsStream = require('./getDocumentsStream')
const filterSystemDocuments = require('./filterSystemDocuments')
const filterDocumentTypes = require('./filterDocumentTypes')
const filterDrafts = require('./filterDrafts')
const logFirstChunk = require('./logFirstChunk')

const noop = () => null

function exportDataset(opts) {
  const options = validateOptions(opts)
  const onProgress = options.onProgress || noop
  const archive = archiver('tar', {
    gzip: true,
    gzipOptions: {level: options.compress ? zlib.Z_DEFAULT_COMPRESSION : zlib.Z_NO_COMPRESSION}
  })

  const slugDate = new Date()
    .toISOString()
    .replace(/[^a-z0-9]/gi, '-')
    .toLowerCase()

  const prefix = `${opts.dataset}-export-${slugDate}`
  const tmpDir = path.join(os.tmpdir(), prefix)
  const cleanup = () =>
    fse.remove(tmpDir).catch(err => {
      debug(`Error while cleaning up temporary files: ${err.message}`)
    })

  const assetHandler = new AssetHandler({
    client: options.client,
    tmpDir,
    prefix
  })

  debug('Outputting assets (temporarily) to %s', tmpDir)
  debug('Outputting to %s', options.outputPath === '-' ? 'stdout' : options.outputPath)
  const outputStream =
    options.outputPath === '-' ? process.stdout : fse.createWriteStream(options.outputPath)

  let assetStreamHandler = assetHandler.noop
  if (!options.raw) {
    assetStreamHandler = options.assets ? assetHandler.rewriteAssets : assetHandler.stripAssets
  }

  return new Promise(async (resolve, reject) => {
    miss.finished(archive, async archiveErr => {
      if (archiveErr) {
        debug('Archiving errored! %s', archiveErr.stack)
        await cleanup()
        reject(archiveErr)
        return
      }

      debug('Archive finished!')
    })

    debug('Getting dataset export stream')
    onProgress({step: 'Exporting documents...'})

    let documentCount = 0
    let lastReported = Date.now()
    const reportDocumentCount = (chunk, enc, cb) => {
      ++documentCount

      const now = Date.now()
      if (now - lastReported > 50) {
        onProgress({
          step: 'Exporting documents...',
          current: documentCount,
          total: '?',
          update: true
        })

        lastReported = now
      }

      cb(null, chunk)
    }

    const inputStream = await getDocumentsStream(options.client, options.dataset)
    debug('Got HTTP %d', inputStream.statusCode)
    debug('Response headers: %o', inputStream.headers)

    const jsonStream = miss.pipeline(
      inputStream,
      logFirstChunk(),
      split(JSON.parse),
      rejectOnApiError(),
      filterSystemDocuments(),
      assetStreamHandler,
      filterDocumentTypes(options.types),
      options.drafts ? miss.through.obj() : filterDrafts(),
      stringifyStream(),
      miss.through(reportDocumentCount)
    )

    miss.finished(jsonStream, async err => {
      if (err) {
        return
      }

      onProgress({
        step: 'Exporting documents...',
        current: documentCount,
        total: documentCount,
        update: true
      })

      if (!options.raw && options.assets) {
        onProgress({step: 'Downloading assets...'})
      }

      let prevCompleted = 0
      const progressInterval = setInterval(() => {
        const completed = assetHandler.queueSize - assetHandler.queue.size
        if (prevCompleted === completed) {
          return
        }

        prevCompleted = completed
        onProgress({
          step: 'Downloading assets...',
          current: completed,
          total: assetHandler.queueSize,
          update: true
        })
      }, 500)

      debug('Waiting for asset handler to complete downloads')
      try {
        const assetMap = await assetHandler.finish()
        archive.append(JSON.stringify(assetMap), {name: 'assets.json', prefix})
        clearInterval(progressInterval)
      } catch (assetErr) {
        clearInterval(progressInterval)
        await cleanup()
        reject(assetErr)
        return
      }

      // Add all downloaded assets to archive
      archive.directory(path.join(tmpDir, 'files'), `${prefix}/files`, {store: true})
      archive.directory(path.join(tmpDir, 'images'), `${prefix}/images`, {store: true})

      debug('Finalizing archive, flushing streams')
      onProgress({step: 'Adding assets to archive...'})
      archive.finalize()
    })

    archive.on('warning', err => {
      debug('Archive warning: %s', err.message)
    })

    archive.append(jsonStream, {name: 'data.ndjson', prefix})
    miss.pipe(
      archive,
      outputStream,
      onComplete
    )

    async function onComplete(err) {
      onProgress({step: 'Clearing temporary files...'})
      await cleanup()

      if (!err) {
        resolve()
        return
      }

      debug('Error during streaming: %s', err.stack)
      assetHandler.clear()
      reject(err)
    }
  })
}

module.exports = exportDataset
<|endoftext|>


<commit_before>import React from 'react'
import styled from 'styled-components'

const Text = styled.p`{
  font-family: 'Nunito Sans', sans-serif;
  font-size: 18px;
  font-weight: normal;
  line-height: 1.39;
  color: ${props => props.color || '#000'};
  text-align: ${props => props.align || 'left'};
  margin: ${props => props.margin}
}`

Text.displayName = 'Text'

export default Text
<commit_msg>chore(bonde-styleguide): add props to change fontSize in Text<commit_after>import React from 'react'
import styled from 'styled-components'

const Text = styled.p`{
  font-family: 'Nunito Sans', sans-serif;
  font-size: ${props => props.fontSize ? `${props.fontSize}px` : '18px'};
  font-weight: normal;
  line-height: 1.39;
  color: ${props => props.color || '#000'};
  text-align: ${props => props.align || 'left'};
  margin: ${props => props.margin}
}`

Text.displayName = 'Text'

export default Text
<|endoftext|>


<commit_before>
/*
moduleIdType 决定webpack打包模块的id
  number，默认的id
  hash 利用 webpack.HashedModuleIdsPlugin()
  name 利用webpack.NamedModulesPlugin()
  chameleon 利用chameleon-webpack-plugin 中开启moduleid的处理
*/
function clone (value) {
  if (Array.isArray(value)) {
    return value.map(clone)
  } else if (value && typeof value === 'object') {
    const res = {}
    // eslint-disable-next-line guard-for-in
    for (const key in value) {
      res[key] = clone(value[key])
    }
    return res
  } else {
    return value
  }
}
var miniappConfig = {
  dev: {
    moduleIdType: 'name',
    definePlugin: {
      'process.env.NODE_ENV': JSON.stringify('development')
    }
    //  increase:true, 是否增量部署打包代码
  },
  build: {
    hash: true,
    minimize: true,
    definePlugin: {
      'process.env.NODE_ENV': JSON.stringify('production')
    }
  },
  export: {
    hash: true,
    minimize: true,
    definePlugin: {
      'process.env.NODE_ENV': JSON.stringify('production')
    },
    entry: [
      './src/components'
    ],
    publicPath: '../../'
  }
};

var chameleonConfig = {
  platforms: ['web', 'weex', 'wx', 'baidu', 'alipay'],
  // devPort: 8000,
  // projectName: undefined,
  templateType: 'html', // 模板类型 smarty or html，决定web页面的格式与dev web服务器的类型
  isBuildInProject: false, // 是否是内置组件项目,该项目不嵌入内置组件
  devOffPlatform: [], // dev 命令关闭的端
  buildOffPlatform: [], // build 命令关闭的端
  builtinNpmName: 'chameleon-ui-builtin', // 内置组件npm包的名称
  check: {
    enable: true, // 是否开启接口校验
    enableTypes: [] // 接口校验支持的类型 可以开启["Object","Array","Nullable"]
  },
  cmlComponents: [ // 配置node_modules中cml组件库
  ],
  baseStyle: { // 是否插入各端的基础样式
    wx: true,
    web: true,
    weex: true,
    alipay: true,
    baidu: true,
    qq: true,
    tt: true
  },
  proxy: {
    enable: false,
    mapremote: []
  },
  // entry: {
  //   template: 'entry_test/entry.html',
  //   web: 'entry_test/web.js',
  //   weex: 'entry_test/weex.js'
  // },
  buildInfo: { // 打包信息
    wxAppId: ''
  },
  enableLinter: true,
  enableGlobalCheck: true,
  globalCheckWhiteList: [ // 全局校验的白名单文件 后缀匹配
  ],
  cmss: {
    rem: true,
    scale: 0.5,
    remOptions: {
      // base on 750px standard.
      rootValue: {cpx: 75}, // cpx转rem px不处理
      // to leave 1px alone.
      minPixelValue: null
    },
    autoprefixOptions: {
      browsers: ['> 0.1%', 'ios >= 8', 'not ie < 12']
    },
    // 是否对css开启autoprefix，默认为true  非weex端生效
    enableAutoPrefix: true
  },
  wx: clone(miniappConfig),
  alipay: clone(miniappConfig),
  baidu: clone(miniappConfig),
  qq: clone(miniappConfig),
  tt: clone(miniappConfig),
  web: {
    dev: {
      isWrapComponent: true, // 默认对组件进行一层包裹
      babelPolyfill: false, // 是否添加babel polyfill 只web端有此属性
      moduleIdType: 'name',
      hot: false,
      analysis: false,
      // apiPrefix: ,
      // staticPath: '', 静态资源路径前缀
      definePlugin: {
        'process.env.NODE_ENV': JSON.stringify('development')
      }
    },
    build: {
      isWrapComponent: true, // 默认对组件进行一层包裹
      babelPolyfill: false, // 是否添加babel polyfill 只web端有此属性
      hash: true,
      minimize: true,
      moduleIdType: 'chameleon',
      definePlugin: {
        'process.env.NODE_ENV': JSON.stringify('production')
      }
    },
    export: {
      isWrapComponent: true, // 默认对组件进行一层包裹
      hash: true,
      minimize: true,
      moduleIdType: 'chameleon',
      entry: [
        './components'
      ],
      definePlugin: {
        'process.env.NODE_ENV': JSON.stringify('production')
      }
    }
  },
  weex: {
    dev: {
      isWrapComponent: true, // 默认对组件进行一层包裹
      moduleIdType: 'name',
      definePlugin: {
        'process.env.NODE_ENV': JSON.stringify('development')
      }
    },
    build: {
      isWrapComponent: true, // 默认对组件进行一层包裹
      minimize: true,
      hash: true,
      moduleIdType: 'chameleon',
      definePlugin: {
        'process.env.NODE_ENV': JSON.stringify('production')
      }
    },
    export: {
      isWrapComponent: true, // 默认对组件进行一层包裹
      hash: true,
      minimize: true,
      moduleIdType: 'chameleon',
      entry: [
        './components'
      ],
      definePlugin: {
        'process.env.NODE_ENV': JSON.stringify('production')
      }
    }
  },
  optimize: {
    watchNodeModules: false, // 默认不对node_modules中的文件进行watch,提升编译性能
    showWarning: false,// 为了兼容原来的配置，默认不开启构建过程中的警告信息，开启之后配合，DuplicatePackageCheckerPlugin 可以在构建过程中检查是否有重复npm包引入
    dropConsole:true,
  }
}

var utils = require('./utils.js');

const _ = {};
module.exports = _;

_.get = function() {
  if (chameleonConfig.base) {
    let baseConfig = chameleonConfig.base;
    let platforms = chameleonConfig.platforms;
    let extPlatform = chameleonConfig.extPlatform || {};
    platforms = platforms.concat(Object.keys(extPlatform));
    platforms.forEach(platform => {
      if (chameleonConfig[platform]) {
        let base = JSON.parse(JSON.stringify(baseConfig));
        let newConfig = JSON.parse(JSON.stringify(chameleonConfig[platform]));
        utils.merge(base, newConfig);
        chameleonConfig[platform] = base;
      }
    })
  }
  return chameleonConfig;
}

_.merge = function(mergeConfig) {
  chameleonConfig = utils.merge(chameleonConfig, mergeConfig);
  return chameleonConfig;
}

_.assign = function(mergeConfig) {
  chameleonConfig = Object.assign(chameleonConfig, mergeConfig);
  return chameleonConfig;
}

<commit_msg>feat: 支持压缩模式可配置dropConsole<commit_after>
/*
moduleIdType 决定webpack打包模块的id
  number，默认的id
  hash 利用 webpack.HashedModuleIdsPlugin()
  name 利用webpack.NamedModulesPlugin()
  chameleon 利用chameleon-webpack-plugin 中开启moduleid的处理
*/
function clone (value) {
  if (Array.isArray(value)) {
    return value.map(clone)
  } else if (value && typeof value === 'object') {
    const res = {}
    // eslint-disable-next-line guard-for-in
    for (const key in value) {
      res[key] = clone(value[key])
    }
    return res
  } else {
    return value
  }
}
var miniappConfig = {
  dev: {
    moduleIdType: 'name',
    definePlugin: {
      'process.env.NODE_ENV': JSON.stringify('development')
    }
    //  increase:true, 是否增量部署打包代码
  },
  build: {
    hash: true,
    minimize: true,
    definePlugin: {
      'process.env.NODE_ENV': JSON.stringify('production')
    }
  },
  export: {
    hash: true,
    minimize: true,
    definePlugin: {
      'process.env.NODE_ENV': JSON.stringify('production')
    },
    entry: [
      './src/components'
    ],
    publicPath: '../../'
  }
};

var chameleonConfig = {
  platforms: ['web', 'weex', 'wx', 'baidu', 'alipay'],
  // devPort: 8000,
  // projectName: undefined,
  templateType: 'html', // 模板类型 smarty or html，决定web页面的格式与dev web服务器的类型
  isBuildInProject: false, // 是否是内置组件项目,该项目不嵌入内置组件
  devOffPlatform: [], // dev 命令关闭的端
  buildOffPlatform: [], // build 命令关闭的端
  builtinNpmName: 'chameleon-ui-builtin', // 内置组件npm包的名称
  check: {
    enable: true, // 是否开启接口校验
    enableTypes: [] // 接口校验支持的类型 可以开启["Object","Array","Nullable"]
  },
  cmlComponents: [ // 配置node_modules中cml组件库
  ],
  baseStyle: { // 是否插入各端的基础样式
    wx: true,
    web: true,
    weex: true,
    alipay: true,
    baidu: true,
    qq: true,
    tt: true
  },
  proxy: {
    enable: false,
    mapremote: []
  },
  // entry: {
  //   template: 'entry_test/entry.html',
  //   web: 'entry_test/web.js',
  //   weex: 'entry_test/weex.js'
  // },
  buildInfo: { // 打包信息
    wxAppId: ''
  },
  enableLinter: true,
  enableGlobalCheck: true,
  globalCheckWhiteList: [ // 全局校验的白名单文件 后缀匹配
  ],
  cmss: {
    rem: true,
    scale: 0.5,
    remOptions: {
      // base on 750px standard.
      rootValue: {cpx: 75}, // cpx转rem px不处理
      // to leave 1px alone.
      minPixelValue: null
    },
    autoprefixOptions: {
      browsers: ['> 0.1%', 'ios >= 8', 'not ie < 12']
    },
    // 是否对css开启autoprefix，默认为true  非weex端生效
    enableAutoPrefix: true
  },
  wx: clone(miniappConfig),
  alipay: clone(miniappConfig),
  baidu: clone(miniappConfig),
  qq: clone(miniappConfig),
  tt: clone(miniappConfig),
  web: {
    dev: {
      isWrapComponent: true, // 默认对组件进行一层包裹
      babelPolyfill: false, // 是否添加babel polyfill 只web端有此属性
      moduleIdType: 'name',
      hot: false,
      analysis: false,
      // apiPrefix: ,
      // staticPath: '', 静态资源路径前缀
      definePlugin: {
        'process.env.NODE_ENV': JSON.stringify('development')
      }
    },
    build: {
      isWrapComponent: true, // 默认对组件进行一层包裹
      babelPolyfill: false, // 是否添加babel polyfill 只web端有此属性
      hash: true,
      minimize: true,
      moduleIdType: 'chameleon',
      definePlugin: {
        'process.env.NODE_ENV': JSON.stringify('production')
      }
    },
    export: {
      isWrapComponent: true, // 默认对组件进行一层包裹
      hash: true,
      minimize: true,
      moduleIdType: 'chameleon',
      entry: [
        './components'
      ],
      definePlugin: {
        'process.env.NODE_ENV': JSON.stringify('production')
      }
    }
  },
  weex: {
    dev: {
      isWrapComponent: true, // 默认对组件进行一层包裹
      moduleIdType: 'name',
      definePlugin: {
        'process.env.NODE_ENV': JSON.stringify('development')
      }
    },
    build: {
      isWrapComponent: true, // 默认对组件进行一层包裹
      minimize: true,
      hash: true,
      moduleIdType: 'chameleon',
      definePlugin: {
        'process.env.NODE_ENV': JSON.stringify('production')
      }
    },
    export: {
      isWrapComponent: true, // 默认对组件进行一层包裹
      hash: true,
      minimize: true,
      moduleIdType: 'chameleon',
      entry: [
        './components'
      ],
      definePlugin: {
        'process.env.NODE_ENV': JSON.stringify('production')
      }
    }
  },
  optimize: {
    watchNodeModules: false, // 默认不对node_modules中的文件进行watch,提升编译性能
    showWarning: false, // 为了兼容原来的配置，默认不开启构建过程中的警告信息，开启之后配合，DuplicatePackageCheckerPlugin 可以在构建过程中检查是否有重复npm包引入
    dropConsole: true
  }
}

var utils = require('./utils.js');

const _ = {};
module.exports = _;

_.get = function() {
  if (chameleonConfig.base) {
    let baseConfig = chameleonConfig.base;
    let platforms = chameleonConfig.platforms;
    let extPlatform = chameleonConfig.extPlatform || {};
    platforms = platforms.concat(Object.keys(extPlatform));
    platforms.forEach(platform => {
      if (chameleonConfig[platform]) {
        let base = JSON.parse(JSON.stringify(baseConfig));
        let newConfig = JSON.parse(JSON.stringify(chameleonConfig[platform]));
        utils.merge(base, newConfig);
        chameleonConfig[platform] = base;
      }
    })
  }
  return chameleonConfig;
}

_.merge = function(mergeConfig) {
  chameleonConfig = utils.merge(chameleonConfig, mergeConfig);
  return chameleonConfig;
}

_.assign = function(mergeConfig) {
  chameleonConfig = Object.assign(chameleonConfig, mergeConfig);
  return chameleonConfig;
}

<|endoftext|>


<commit_before>/**
 * Blueprint API Configuration
 * (sails.config.blueprints)
 *
 * These settings are for the global configuration of blueprint routes and
 * request options (which impact the behavior of blueprint actions).
 *
 * You may also override any of these settings on a per-controller basis
 * by defining a '_config' key in your controller defintion, and assigning it
 * a configuration object with overrides for the settings in this file.
 *
 * For more information on configuring the blueprint API, check out:
 * http://links.sailsjs.org/docs/config/blueprints
 */

module.exports.blueprints = {

  /**
   * NOTE:
   * A lot of the configuration options below affect so-called "CRUD methods",
   * or your controllers' `find`, `create`, `update`, and `destroy` actions.
   *
   * It's important to realize that, even if you haven't defined these yourself, as long as
   * a model exists with the same name as the controller, Sails will respond with built-in CRUD
   * logic in the form of a JSON API, including support for sort, pagination, and filtering.
   */

  // Action blueprints speed up the backend development workflow by eliminating the need
  // to manually bind routes. When enabled, GET, POST, PUT, and DELETE routes will be
  // generated for every one of a controller's actions.
  //
  // If an `index` action exists, additional naked routes will be created for it.
  // Finally, all `actions` blueprints support an optional path parameter, `id`, for convenience.
  //
  // For example, assume we have an EmailController with actions `send` and `index`.
  // With `actions` enabled, the following blueprint routes would be bound at runtime:
  //
  // `EmailController.index`
  // :::::::::::::::::::::::::::::::::::::::::::::::::::::::
  // `GET     /email/:id?`        `GET    /email/index/:id?`
  // `POST    /email/:id?`        `POST   /email/index/:id?`
  // `PUT     /email/:id?`        `PUT    /email/index/:id?`
  // `DELETE  /email/:id?`        `DELETE /email/index/:id?`
  //
  // `EmailController.send`
  // :::::::::::::::::::::::::::::::::::::::::::::::::::::::
  // `GET     /email/send/:id?`
  // `POST    /email/send/:id?`
  // `PUT     /email/send/:id?`
  // `DELETE  /email/send/:id?`
  //
  //
  // `actions` are enabled by default, and can be OK for production-- however,
  // if you'd like to continue to use controller/action autorouting in a production deployment,
  // you must take great care not to inadvertently expose unsafe/unintentional controller logic
  // to GET requests.
  actions: true,

  // RESTful Blueprints
  // (`sails.config.blueprints.rest`)
  //
  // REST blueprints are the automatically generated routes Sails uses to expose
  // a conventional REST API on top of a controller's `find`, `create`, `update`, and `destroy`
  // actions.
  //
  // For example, a BoatController with `rest` enabled generates the following routes:
  // :::::::::::::::::::::::::::::::::::::::::::::::::::::::
  // GET      /boat/:id?      -> BoatController.find
  // POST     /boat           -> BoatController.create
  // PUT      /boat/:id       -> BoatController.update
  // DELETE   /boat/:id       -> BoatController.destroy
  //
  // `rest` blueprint routes are enabled by default, and are suitable for use
  // in a production scenario, as long you take standard security precautions
  // (combine w/ policies, etc.)
  rest: true,

  // Shortcut blueprints are simple helpers to provide access to a controller's CRUD methods
  // from your browser's URL bar.  When enabled, GET, POST, PUT, and DELETE routes will be generated
  // for the controller's`find`, `create`, `update`, and `destroy` actions.
  //
  // `shortcuts` are enabled by default, but should be disabled in production.
  shortcuts: true,

  // An optional mount path for all blueprint routes on a controller, including `rest`,
  // `actions`, and `shortcuts`.  This allows you to take advantage of blueprint routing,
  // even if you need to namespace your API methods.
  //
  // * (NOTE: This only applies to blueprint autoroutes, not manual routes from `sails.config.routes`)
  //
  // For example, `prefix: '/api/v2'` would make the following REST blueprint routes
  // for a FooController:
  //
  // `GET /api/v2/foo/:id?`
  // `POST /api/v2/foo`
  // `PUT /api/v2/foo/:id`
  // `DELETE /api/v2/foo/:id`
  //
  // By default, no prefix is used.
  prefix: '',

  // Whether to pluralize controller names in blueprint routes.
  //
  // (NOTE: This only applies to blueprint autoroutes, not manual routes from `sails.config.routes`)
  //
  // For example, REST blueprints for `FooController` with `pluralize` enabled:
  // GET    /foos/:id?
  // POST   /foos
  // PUT    /foos/:id?
  // DELETE /foos/:id?
  pluralize: false,

  // Whether the blueprint controllers should populate model fetches with
  // data from other models which are linked by associations

  // If you have a lot of data in one-to-many associations, leaving this on
  // may result in very heavy api calls

  populate: true

};
<commit_msg>Revoming comments...<commit_after>
module.exports.blueprints = {
  actions: true,
  rest: true,
  shortcuts: true,

  // An optional mount path for all blueprint routes on a controller, including `rest`,
  // `actions`, and `shortcuts`.  This allows you to take advantage of blueprint routing,
  // even if you need to namespace your API methods.
  //
  // * (NOTE: This only applies to blueprint autoroutes, not manual routes from `sails.config.routes`)
  //
  // For example, `prefix: '/api/v2'` would make the following REST blueprint routes
  // for a FooController:
  //
  // `GET /api/v2/foo/:id?`
  // `POST /api/v2/foo`
  // `PUT /api/v2/foo/:id`
  // `DELETE /api/v2/foo/:id`
  //
  // By default, no prefix is used.
  prefix: '',

  // Whether to pluralize controller names in blueprint routes.
  //
  // (NOTE: This only applies to blueprint autoroutes, not manual routes from `sails.config.routes`)
  //
  // For example, REST blueprints for `FooController` with `pluralize` enabled:
  // GET    /foos/:id?
  // POST   /foos
  // PUT    /foos/:id?
  // DELETE /foos/:id?
  pluralize: false,

  // Whether the blueprint controllers should populate model fetches with
  // data from other models which are linked by associations

  // If you have a lot of data in one-to-many associations, leaving this on
  // may result in very heavy api calls

  populate: true

};
<|endoftext|>


<commit_before>// Get the required shit together
const Discord = require('eris');
const config = require('config');
const utils = require('./utils.js');

const client = new Discord.Client(config.get('api').discord.token, { maxShards: config.get('shards') });
const prefixes = config.get('prefix');
let regex = null;

// Setup commands and util objects.
const commands = require('./cogs.js');

// Just plop all valid commands in for other cogs to look at it.
client.commands = commands;

client.on('ready', () => {
	// Set up regex for the bot.
	regex = new RegExp(`(${prefixes.join('|')}).?(${Object.keys(commands).join('|')})\\s?(.*)`);

	// Add mentions to the prefix list
	prefixes.push(`<@${client.user.id}>`);
	console.log('Connected to Discord!');

	// Send DBOTS info if it was provided.
	if (config.get('api').botsdiscordpw) {
		utils.botsdiscordpw(client);
		setInterval(() => {
			utils.botsdiscordpw(client);
		}, 1800000);
	}

	// Send FAKEDBOTS info if it was provided.
	if (config.get('api').discordbotsorg) {
		utils.discordbotsorg(client);
		setInterval(() => {
			utils.discordbotsorg(client);
		}, 1800000);
	}
});

client.on('messageCreate', (message) => {
	// Disallow if the author is a bot
	if (message.author.bot) return;

	// Test the message content on the regular expression
	const result = regex.exec(message.content.replace(/\n/g, ' '));

	// Return if it fails the regex commands check test
	if (!result) return;

	// Bake some cool extra crap into the message
	message.prefix = result[1];
	message.command = result[2];
	message.input = result[3] || null;
	message.words = result[3].split(/\n+|\s+/g);

	// Run the actual command
	commands[message.command].command(message, client);
});

// Connect to Discord
console.log('Discord loaded');
client.connect();

module.exports = client;
<commit_msg>include matching newlines<commit_after>// Get the required shit together
const Discord = require('eris');
const config = require('config');
const utils = require('./utils.js');

const client = new Discord.Client(config.get('api').discord.token, { maxShards: config.get('shards') });
const prefixes = config.get('prefix');
let regex = null;

// Setup commands and util objects.
const commands = require('./cogs.js');

// Just plop all valid commands in for other cogs to look at it.
client.commands = commands;

client.on('ready', () => {
	// Set up regex for the bot.
	regex = new RegExp(`(${prefixes.join('|')}).?(${Object.keys(commands).join('|')})\\s?([\s\S]*)`);

	// Add mentions to the prefix list
	prefixes.push(`<@${client.user.id}>`);
	console.log('Connected to Discord!');

	// Send DBOTS info if it was provided.
	if (config.get('api').botsdiscordpw) {
		utils.botsdiscordpw(client);
		setInterval(() => {
			utils.botsdiscordpw(client);
		}, 1800000);
	}

	// Send FAKEDBOTS info if it was provided.
	if (config.get('api').discordbotsorg) {
		utils.discordbotsorg(client);
		setInterval(() => {
			utils.discordbotsorg(client);
		}, 1800000);
	}
});

client.on('messageCreate', (message) => {
	// Disallow if the author is a bot
	if (message.author.bot) return;

	// Test the message content on the regular expression
	const result = regex.exec(message.content);

	// Return if it fails the regex commands check test
	if (!result) return;

	// Bake some cool extra crap into the message
	message.prefix = result[1];
	message.command = result[2];
	message.input = result[3] || null;
	message.words = result[3].split(/\n+|\s+/g);

	// Run the actual command
	commands[message.command].command(message, client);
});

// Connect to Discord
console.log('Discord loaded');
client.connect();

module.exports = client;
<|endoftext|>


<commit_before>// Get the required shit together
const Discord = require('eris');
const config = require('config');
const utils = require('./utils.js');
require('colors');

// Database
const r = require('./../db');

const client = new Discord.Client(config.get('api').discord.token, { maxShards: config.get('shards') });
const prefixes = config.get('prefix');
let prefix = null;
let suffix = null;

// Setup commands and util objects.
const commands = require('./cogs.js').cogs;

// Just plop all valid commands in for other cogs to look at it.
client.commands = commands;

client.on('shardReady', (id) => {
	console.log(`Shard ${id} is online`.green);
});

client.on('ready', () => {
	// Set up regex for the bot.
	// It's "man's essential illness"
	// Use this regex for testing in regexr.com
	// /^(mss).?(ping)\s?([\s\S]*)/
	// /(\w+)rly/
	prefix = new RegExp(`^(${prefixes.join('|')}).?(${Object.keys(commands).join('|')})\\s?([\\s\\S]*)`);
	suffix = /(\w+)pls/;

	// Add mentions to the prefix list
	prefixes.push(`<@${client.user.id}>`);
	console.log('All shards are online'.green.bold);

	// Send DBOTS info if it was provided.
	if (config.get('api').botsdiscordpw) {
		utils.botsdiscordpw(client);
		setInterval(() => {
			utils.botsdiscordpw(client);
		}, 1800000);
	}

	// Send FAKEDBOTS info if it was provided.
	if (config.get('api').discordbotsorg) {
		utils.discordbotsorg(client);
		setInterval(() => {
			utils.discordbotsorg(client);
		}, 1800000);
	}

	// Check for bot collection servers
	utils.collection.check(client);
	setInterval(() => {
		utils.collection.check(client);
	}, 1800000);
});

client.on('messageCreate', (message) => {
	// It crashed on this before. No explaination.
	if (!message.author) return;
	// Disallow if the author is a bot
	if (message.author.bot) return;

	// Test the message content on the regular expression for prefixed commands and the suffixed commands
	const pre = prefix.exec(message.content);
	const suf = suffix.exec(message.content);

	// If there's a result, do this crap.
	if (pre) {
		// Bake some cool extra crap into the message
		message.prefix = pre[1];
		message.command = pre[2];
		message.input = pre[3] || null;
		message.words = pre[3].split(/\n+|\s+/g);

		// Run the actual command
		commands[message.command].command(message, client);
	} else if (suf) {
		if (message.channel && message.channel.id !== '110373943822540800') {
			// If the suffix matches a user's name in the database...
			r.table('markov')
				.filter({ name: suf[1] })
				.run(r.conn, (err1, cursor) => {
					if (err1) return;
					cursor.toArray((err2, result) => {
						if (err2) return;
						if (result.length === 0) return;
						// Generate a Markov
						utils.markov.generate(suf[1], (embed) => {
							message.channel.createMessage(embed);
						});
					});
				});
		}
	} else {
		// If the user exists in the rethonk Markov database...
		r.table('markov')
			.filter({ author: message.author.id })
			.run(r.conn, (err1, cursor) => {
				if (err1) return;
				cursor.toArray((err2, result) => {
					if (err2) return;
					if (result.length === 0) return;
					// Save the markov.
					utils.markov.save(message);
				});
			});
	}
});

client.connect();
module.exports = client;
<commit_msg>setup regex first<commit_after>// Get the required shit together
const Discord = require('eris');
const config = require('config');
const utils = require('./utils.js');
require('colors');

// Database
const r = require('./../db');

const client = new Discord.Client(config.get('api').discord.token, { maxShards: config.get('shards') });
const prefixes = config.get('prefix');

// Setup commands and util objects.
const commands = require('./cogs.js').cogs;

// Set up regex for the bot.
// It's "man's essential illness"
// Use this regex for testing in regexr.com
// /^(mss).?(ping)\s?([\s\S]*)/
// /(\w+)rly/
const prefix = new RegExp(`^(${prefixes.join('|')}).?(${Object.keys(commands).join('|')})\\s?([\\s\\S]*)`);
const suffix = /(\w+)pls/;

client.on('shardReady', (id) => {
	console.log(`Shard ${id} is online`.green);
});

client.on('ready', () => {
	// Add mentions to the prefix list
	prefixes.push(`<@${client.user.id}>`);
	console.log('All shards are online'.green.bold);

	// Send DBOTS info if it was provided.
	if (config.get('api').botsdiscordpw) {
		utils.botsdiscordpw(client);
		setInterval(() => {
			utils.botsdiscordpw(client);
		}, 1800000);
	}

	// Send FAKEDBOTS info if it was provided.
	if (config.get('api').discordbotsorg) {
		utils.discordbotsorg(client);
		setInterval(() => {
			utils.discordbotsorg(client);
		}, 1800000);
	}

	// Check for bot collection servers
	utils.collection.check(client);
	setInterval(() => {
		utils.collection.check(client);
	}, 1800000);
});

client.on('messageCreate', (message) => {
	// It crashed on this before. No explaination.
	if (!message.author) return;
	// Disallow if the author is a bot
	if (message.author.bot) return;

	// Test the message content on the regular expression for prefixed commands and the suffixed commands
	const pre = prefix.exec(message.content);
	const suf = suffix.exec(message.content);

	// If there's a result, do this crap.
	if (pre) {
		// Bake some cool extra crap into the message
		message.prefix = pre[1];
		message.command = pre[2];
		message.input = pre[3] || null;
		message.words = pre[3].split(/\n+|\s+/g);

		// Run the actual command
		commands[message.command].command(message, client);
	} else if (suf) {
		if (message.channel && message.channel.id !== '110373943822540800') {
			// If the suffix matches a user's name in the database...
			r.table('markov')
				.filter({ name: suf[1] })
				.run(r.conn, (err1, cursor) => {
					if (err1) return;
					cursor.toArray((err2, result) => {
						if (err2) return;
						if (result.length === 0) return;
						// Generate a Markov
						utils.markov.generate(suf[1], (embed) => {
							message.channel.createMessage(embed);
						});
					});
				});
		}
	} else {
		// If the user exists in the rethonk Markov database...
		r.table('markov')
			.filter({ author: message.author.id })
			.run(r.conn, (err1, cursor) => {
				if (err1) return;
				cursor.toArray((err2, result) => {
					if (err2) return;
					if (result.length === 0) return;
					// Save the markov.
					utils.markov.save(message);
				});
			});
	}
});

client.connect();
module.exports = client;
<|endoftext|>


<commit_before>const _ = require('lodash')
const { assign } = Object
const formsConfig = require('../../config/formsConfig')
const inputHelpers = require('../helpers/inputs')
const languages = require('../../config/languages')
const capitalizeFirstLetter = require('../utils/capitalizeFirstLetter')
const localField = require('../utils/localField')

exports = module.exports = _.cloneDeep(require('./_common'))

exports.tableName = 'FormThreats'
exports.hasSpecies = true
exports.hasThreats = false

exports.fields = assign(exports.fields, {
  category: {
    type: 'choice',
    public: true,
    uniqueHash: true,
    relation: {
      model: 'nomenclature',
      filter: { type: 'threats_category' }
    }
  },
  species: {
    type: 'choice',
    public: true,
    uniqueHash: true,
    relation: {
      model: 'species'
    }
  },
  estimate: {
    type: 'choice',
    relation: {
      model: 'nomenclature',
      filter: { type: 'threats_estimate' }
    }
  },
  poisonedType: {
    type: 'text',
    public: true
  },
  stateCarcass: {
    type: 'choice',
    relation: {
      model: 'nomenclature',
      filter: { type: 'threats_state_carcass' }
    }
  },
  sampleTaken1: {
    type: 'choice',
    relation: {
      model: 'nomenclature',
      filter: { type: 'threats_sample' }
    }
  },
  sampleTaken2: {
    type: 'choice',
    relation: {
      model: 'nomenclature',
      filter: { type: 'threats_sample' }
    }
  },
  sampleTaken3: {
    type: 'choice',
    relation: {
      model: 'nomenclature',
      filter: { type: 'threats_sample' }
    }
  },
  location: {
    type: 'text',
    required: true
  },
  class: {
    type: 'text',
    public: true
  },
  sampleCode1: 'text',
  sampleCode2: 'text',
  sampleCode3: 'text',
  count: {
    type: '+int',
    public: true
  },
  threatsNotes: 'text',
  primaryType: {
    type: 'text',
    public: true,
    required: true
  }
})

exports.foreignKeys.push({
  targetModelName: 'species',
  as: 'speciesInfo',
  foreignKey: 'species',
  targetKey: 'labelLa'
})

exports.listInputs = {
  primaryType: {},
  class: {},
  category: {
    formatter: inputHelpers.formatter.nomenclature
  }
}

exports.filterList = async function (api, data, q) {
  if (data.params.primaryType) {
    q.where = _.extend(q.where || {}, {
      primaryType: data.params.primaryType
    })
  }
  if (data.params.class) {
    q.where = _.extend(q.where || {}, {
      class: data.params.class
    })
  }
  if (data.params.category) {
    q.where = _.extend(q.where || {}, {
      categoryEn: data.params.category
    })
  }
  return q
}

exports.indexes.push({ fields: ['species'] })

const afterApiUpdate = function (threat, options) {
  if (threat.primaryType === formsConfig.threatsPrimaryTypes.threat.id) {
    threat.poisonedType = null
    threat.stateCarcassLang = null
    threat.stateCarcassLocal = null
    threat.stateCarcassEn = null
    threat.sampleCode1 = null
    threat.sampleCode2 = null
    threat.sampleCode3 = null
    threat.sampleTaken1Lang = null
    threat.sampleTaken1Local = null
    threat.sampleTaken1En = null
    threat.sampleTaken2Lang = null
    threat.sampleTaken2Local = null
    threat.sampleTaken2En = null
    threat.sampleTaken3Lang = null
    threat.sampleTaken3Local = null
    threat.sampleTaken3En = null
  } else {
    threat.categoryLang = null
    threat.categoryLocal = null
    threat.categoryEn = null
    threat.estimateLang = null
    threat.estimateLocal = null
    threat.estimateEn = null
    switch (threat.poisonedType) {
      case formsConfig.threatsPoisonedType.alive.id:
        threat.stateCarcassLang = null
        threat.stateCarcassLocal = null
        threat.stateCarcassEn = null
        break
      case formsConfig.threatsPoisonedType.bait.id:
        threat.stateCarcassLang = null
        threat.stateCarcassLocal = null
        threat.stateCarcassEn = null
        threat.class = null
        threat.species = null
        break
      default:
        break
    }
  }
}

exports.hooks = {
  afterApiUpdate: afterApiUpdate
}

exports.validate = {
  validateTypeThreat: function () {
    if (this.primaryType === formsConfig.threatsPrimaryTypes.threat.id) {
      if (!this.categoryEn) {
        throw new Error('Category is required when primaryType is threat')
      }
    }
  },
  validateTypePoison: function () {
    if (this.primaryType === formsConfig.threatsPrimaryTypes.poison.id) {
      if (!this.poisonedType) {
        throw new Error('poisonedType is required when primaryType is poison')
      }

      if (!this.count) {
        throw new Error('count is required when poisonedType is bait')
      }

      if (
        this.poisonedType === formsConfig.threatsPoisonedType.dead.id ||
        this.poisonedType === formsConfig.threatsPoisonedType.alive.id) {
        if (!this.class) {
          throw new Error('class is required when poisonedType is bait')
        }

        if (!this.species) {
          throw new Error('species is required when poisonedType is bait')
        }

        if (this.poisonedType === formsConfig.threatsPoisonedType.dead.id) {
          if (!this.stateCarcassEn) {
            throw new Error('stateCarcass is required when poisonedType is dead')
          }
        }
      }
    }
  }
}

const categoryThreatsField = localField('categoryThreats')
const estimateThreatsField = localField('estimateThreats')

exports.prepareCsv = async function (api, record, csv) {
  // define all used fields, so the first record can output proper header
  csv = {
    ...csv,
    id: record.id,
    speciesThreats: '',
    countThreats: '',
    deadSpecies: '',
    deadSpeciesCount: '',
    aliveAnimal: 'N',
    aliveAnimalCount: '',
    poisonBaits: 'N',
    poisonBaitsCount: '',
    ...categoryThreatsField.values({}, { onlyAvailable: false, keysPrefix: 'categoryThreats' }),
    ...estimateThreatsField.values({}, { onlyAvailable: false, keysPrefix: 'estimateThreats' })
  }

  switch (record.primaryType) {
    case formsConfig.threatsPrimaryTypes.poison.id:
      for (const lang in languages) {
        csv[`categoryThreats${capitalizeFirstLetter(lang)}`] = languages[lang].threatsPrimaryType
      }

      switch (record.poisonedType) {
        case formsConfig.threatsPoisonedType.alive.id:
          csv = {
            ...csv,
            aliveAnimal: 'Y',
            aliveAnimalCount: record.count
          }
          break
        case formsConfig.threatsPoisonedType.bait.id:
          csv = {
            ...csv,
            poisonBaits: 'Y',
            poisonBaitsCount: record.count
          }
          break
        case formsConfig.threatsPoisonedType.dead.id:
          csv = {
            ...csv,
            aliveAnimal: 'N',
            deadSpecies: record.speciesInfo.labelLa,
            deadSpeciesCount: record.count
          }
          break
        default:
          throw new Error('Unsupported poisoned type: ' + record.poisonedType)
      }

      break
    case formsConfig.threatsPrimaryTypes.threat.id:
      csv = {
        ...csv,
        ...categoryThreatsField.values(record, { keysPrefix: 'categoryThreats' }),
        ...estimateThreatsField.values(record, { keysPrefix: 'estimateThreats' }),
        speciesThreats: record.speciesInfo && record.speciesInfo.labelLa,
        countThreats: record.count
      }
      break
    default:
      throw new Error('Unsupported primary type: ' + record.primaryType)
  }
  return csv
}
<commit_msg>Fix threats poison category (#386)<commit_after>const _ = require('lodash')
const { assign } = Object
const formsConfig = require('../../config/formsConfig')
const inputHelpers = require('../helpers/inputs')
const languages = require('../../config/languages')
const capitalizeFirstLetter = require('../utils/capitalizeFirstLetter')
const localField = require('../utils/localField')

exports = module.exports = _.cloneDeep(require('./_common'))

exports.tableName = 'FormThreats'
exports.hasSpecies = true
exports.hasThreats = false

exports.fields = assign(exports.fields, {
  category: {
    type: 'choice',
    public: true,
    uniqueHash: true,
    relation: {
      model: 'nomenclature',
      filter: { type: 'threats_category' }
    }
  },
  species: {
    type: 'choice',
    public: true,
    uniqueHash: true,
    relation: {
      model: 'species'
    }
  },
  estimate: {
    type: 'choice',
    relation: {
      model: 'nomenclature',
      filter: { type: 'threats_estimate' }
    }
  },
  poisonedType: {
    type: 'text',
    public: true
  },
  stateCarcass: {
    type: 'choice',
    relation: {
      model: 'nomenclature',
      filter: { type: 'threats_state_carcass' }
    }
  },
  sampleTaken1: {
    type: 'choice',
    relation: {
      model: 'nomenclature',
      filter: { type: 'threats_sample' }
    }
  },
  sampleTaken2: {
    type: 'choice',
    relation: {
      model: 'nomenclature',
      filter: { type: 'threats_sample' }
    }
  },
  sampleTaken3: {
    type: 'choice',
    relation: {
      model: 'nomenclature',
      filter: { type: 'threats_sample' }
    }
  },
  location: {
    type: 'text',
    required: true
  },
  class: {
    type: 'text',
    public: true
  },
  sampleCode1: 'text',
  sampleCode2: 'text',
  sampleCode3: 'text',
  count: {
    type: '+int',
    public: true
  },
  threatsNotes: 'text',
  primaryType: {
    type: 'text',
    public: true,
    required: true
  }
})

exports.foreignKeys.push({
  targetModelName: 'species',
  as: 'speciesInfo',
  foreignKey: 'species',
  targetKey: 'labelLa'
})

exports.listInputs = {
  primaryType: {},
  class: {},
  category: {
    formatter: inputHelpers.formatter.nomenclature
  }
}

exports.filterList = async function (api, data, q) {
  if (data.params.primaryType) {
    q.where = _.extend(q.where || {}, {
      primaryType: data.params.primaryType
    })
  }
  if (data.params.class) {
    q.where = _.extend(q.where || {}, {
      class: data.params.class
    })
  }
  if (data.params.category) {
    q.where = _.extend(q.where || {}, {
      categoryEn: data.params.category
    })
  }
  return q
}

exports.indexes.push({ fields: ['species'] })

const afterApiUpdate = function (threat, options) {
  if (threat.primaryType === formsConfig.threatsPrimaryTypes.threat.id) {
    threat.poisonedType = null
    threat.stateCarcassLang = null
    threat.stateCarcassLocal = null
    threat.stateCarcassEn = null
    threat.sampleCode1 = null
    threat.sampleCode2 = null
    threat.sampleCode3 = null
    threat.sampleTaken1Lang = null
    threat.sampleTaken1Local = null
    threat.sampleTaken1En = null
    threat.sampleTaken2Lang = null
    threat.sampleTaken2Local = null
    threat.sampleTaken2En = null
    threat.sampleTaken3Lang = null
    threat.sampleTaken3Local = null
    threat.sampleTaken3En = null
  } else {
    threat.categoryLang = null
    threat.categoryLocal = null
    threat.categoryEn = null
    threat.estimateLang = null
    threat.estimateLocal = null
    threat.estimateEn = null
    switch (threat.poisonedType) {
      case formsConfig.threatsPoisonedType.alive.id:
        threat.stateCarcassLang = null
        threat.stateCarcassLocal = null
        threat.stateCarcassEn = null
        break
      case formsConfig.threatsPoisonedType.bait.id:
        threat.stateCarcassLang = null
        threat.stateCarcassLocal = null
        threat.stateCarcassEn = null
        threat.class = null
        threat.species = null
        break
      default:
        break
    }
  }
}

exports.hooks = {
  afterApiUpdate: afterApiUpdate
}

exports.validate = {
  validateTypeThreat: function () {
    if (this.primaryType === formsConfig.threatsPrimaryTypes.threat.id) {
      if (!this.categoryEn) {
        throw new Error('Category is required when primaryType is threat')
      }
    }
  },
  validateTypePoison: function () {
    if (this.primaryType === formsConfig.threatsPrimaryTypes.poison.id) {
      if (!this.poisonedType) {
        throw new Error('poisonedType is required when primaryType is poison')
      }

      if (!this.count) {
        throw new Error('count is required when poisonedType is bait')
      }

      if (
        this.poisonedType === formsConfig.threatsPoisonedType.dead.id ||
        this.poisonedType === formsConfig.threatsPoisonedType.alive.id) {
        if (!this.class) {
          throw new Error('class is required when poisonedType is bait')
        }

        if (!this.species) {
          throw new Error('species is required when poisonedType is bait')
        }

        if (this.poisonedType === formsConfig.threatsPoisonedType.dead.id) {
          if (!this.stateCarcassEn) {
            throw new Error('stateCarcass is required when poisonedType is dead')
          }
        }
      }
    }
  }
}

const categoryThreatsField = localField('categoryThreats')
const estimateThreatsField = localField('estimateThreats')

exports.prepareCsv = async function (api, record, csv) {
  // define all used fields, so the first record can output proper header
  csv = {
    ...csv,
    id: record.id,
    speciesThreats: '',
    countThreats: '',
    deadSpecies: '',
    deadSpeciesCount: '',
    aliveAnimal: 'N',
    aliveAnimalCount: '',
    poisonBaits: 'N',
    poisonBaitsCount: '',
    ...categoryThreatsField.values({}, { onlyAvailable: false, keysPrefix: 'categoryThreats' }),
    ...estimateThreatsField.values({}, { onlyAvailable: false, keysPrefix: 'estimateThreats' })
  }

  switch (record.primaryType) {
    case formsConfig.threatsPrimaryTypes.poison.id:
      for (const lang in languages) {
        csv[`categoryThreats${capitalizeFirstLetter(lang)}`] = languages[lang].threatsPrimaryType.poison
      }

      switch (record.poisonedType) {
        case formsConfig.threatsPoisonedType.alive.id:
          csv = {
            ...csv,
            aliveAnimal: 'Y',
            aliveAnimalCount: record.count
          }
          break
        case formsConfig.threatsPoisonedType.bait.id:
          csv = {
            ...csv,
            poisonBaits: 'Y',
            poisonBaitsCount: record.count
          }
          break
        case formsConfig.threatsPoisonedType.dead.id:
          csv = {
            ...csv,
            aliveAnimal: 'N',
            deadSpecies: record.speciesInfo.labelLa,
            deadSpeciesCount: record.count
          }
          break
        default:
          throw new Error('Unsupported poisoned type: ' + record.poisonedType)
      }

      break
    case formsConfig.threatsPrimaryTypes.threat.id:
      csv = {
        ...csv,
        ...categoryThreatsField.values(record, { keysPrefix: 'categoryThreats' }),
        ...estimateThreatsField.values(record, { keysPrefix: 'estimateThreats' }),
        speciesThreats: record.speciesInfo && record.speciesInfo.labelLa,
        countThreats: record.count
      }
      break
    default:
      throw new Error('Unsupported primary type: ' + record.primaryType)
  }
  return csv
}
<|endoftext|>


<commit_before>import LocalizedStrings from './../src/LocalizedStrings';

describe('Main Library Functions', function () {
  let strings;
  beforeAll(() => {
    global.navigator = {};
    strings = new LocalizedStrings({
      en:{
        language:"english",
        how:"How do you want your egg today?",
        boiledEgg:"Boiled egg",
        softBoiledEgg:"Soft-boiled egg",
        choice:"How to choose the egg",
        formattedValue:"I'd like some {0} and {1}, or just {0}",
        ratings:{
          excellent:"excellent",
          good:"good",
          missingComplex:"missing value"
        },
        missing:"missing value"
      },
      it: {
        how:"Come vuoi il tuo uovo oggi?",
        boiledEgg:"Uovo sodo",
        softBoiledEgg:"Uovo alla coque",
        choice:"Come scegliere l'uovo",
          ratings:{
          excellent:"eccellente",
          good:"buono"
        },
        formattedValue:"Vorrei un po' di {0} e {1}, o solo {0}",
      }
    });
  });

  it("Set default language to en", function(){
    expect(strings.getLanguage()).toEqual("en");
  });

  it("List available languages", function(){
    expect(strings.getAvailableLanguages()).toEqual(["en", "it"]);
  });

  //Default language
  it('Extract simple value from default language', function () {
    expect(strings.how).toEqual('How do you want your egg today?');
  });
  it('Extract complex value from default language', function () {
    expect(strings.ratings.good).toEqual('good');
  });
  it('Get complex missing key from default language', function () {
    expect(strings.ratings.missingComplex).toEqual('missing value');
  });
  it('Get missing key from default language', function () {
    expect(strings.ratings.notfound).toBe(undefined);
  });
  it('Format string in default language', function () {
    expect(strings.formatString(strings.formattedValue, "cake", "ice-cream"))
      .toEqual(["I'd like some ", "cake", " and ", "ice-cream", ", or just ", "cake"]);
  });

  //Switch language
  it("Switch language to italian", function(){
    strings.setLanguage("it");
    expect(strings.getLanguage()).toEqual("it");
  });
  it('Extract simple value from  other language', function () {
    expect(strings.how).toEqual('Come vuoi il tuo uovo oggi?');
  });

  it('Extract complex value from other language', function () {
    expect(strings.ratings.good).toEqual('buono');
  });

  it('Get missing key from other language', function () {
    expect(strings.missing).toEqual('missing value');
  });

  it('Get complex missing key from other language', function () {
    expect(strings.ratings.missingComplex).toEqual('missing value');
  });
  it('Format string in other language', function () {
    expect(strings.formatString(strings.formattedValue, "torta", "gelato"))
      .toEqual(["Vorrei un po' di ", "torta", " e ", "gelato", ", o solo ", "torta"]);
  });

  it('Get string in a different language', function () {
    expect(strings.getString("choice", "en")).toBe("How to choose the egg");
  });

  it('Switch to different props', function () {
    strings.setContent({
      fr: {
        "hello":"bonjour"
      },
      en: {
        "hello":"hello"
      },
      it: {
        "hello":"ciao"
      }
    });
    strings.setLanguage("fr");
    expect(strings.hello).toEqual('bonjour');
  });

it('Switch to different props not working', function () {
    strings = new LocalizedStrings({
          en: {
            a: {
              b: { x: "foo", y: "bar" },
              c: { z: "baz" }
              }
          }
          });
    strings.setContent({
      en: {
        a: {
          b: { x: "a.b.x", y: "a.b.y" },
          c: { z: "a.c.z" }
        }
      }
    });
    strings.setLanguage("en");
    expect(strings.a.b.x).toEqual('a.b.x');
  });

it('Should throw an exception if a reserved word is used', function(){
  expect( function(){
    strings = new LocalizedStrings({
      en: {
        language: "language",
        _language: "language is forbidden"
      }
    });
   } ).toThrow(new Error("_language cannot be used as a key. It is a reserved word."));

});

});<commit_msg>Reindent tests correctly<commit_after>import LocalizedStrings from './../src/LocalizedStrings';

describe('Main Library Functions', function () {
  let strings;
  beforeAll(() => {
    global.navigator = {};
    strings = new LocalizedStrings({
      en:{
        language:"english",
        how:"How do you want your egg today?",
        boiledEgg:"Boiled egg",
        softBoiledEgg:"Soft-boiled egg",
        choice:"How to choose the egg",
        formattedValue:"I'd like some {0} and {1}, or just {0}",
        ratings:{
          excellent:"excellent",
          good:"good",
          missingComplex:"missing value"
        },
        missing:"missing value"
      },
      it: {
        how:"Come vuoi il tuo uovo oggi?",
        boiledEgg:"Uovo sodo",
        softBoiledEgg:"Uovo alla coque",
        choice:"Come scegliere l'uovo",
          ratings:{
          excellent:"eccellente",
          good:"buono"
        },
        formattedValue:"Vorrei un po' di {0} e {1}, o solo {0}",
      }
    });
  });

  it("Set default language to en", function(){
    expect(strings.getLanguage()).toEqual("en");
  });

  it("List available languages", function(){
    expect(strings.getAvailableLanguages()).toEqual(["en", "it"]);
  });

  //Default language
  it('Extract simple value from default language', function () {
    expect(strings.how).toEqual('How do you want your egg today?');
  });
  it('Extract complex value from default language', function () {
    expect(strings.ratings.good).toEqual('good');
  });
  it('Get complex missing key from default language', function () {
    expect(strings.ratings.missingComplex).toEqual('missing value');
  });
  it('Get missing key from default language', function () {
    expect(strings.ratings.notfound).toBe(undefined);
  });
  it('Format string in default language', function () {
    expect(strings.formatString(strings.formattedValue, "cake", "ice-cream"))
      .toEqual(["I'd like some ", "cake", " and ", "ice-cream", ", or just ", "cake"]);
  });

  //Switch language
  it("Switch language to italian", function(){
    strings.setLanguage("it");
    expect(strings.getLanguage()).toEqual("it");
  });
  it('Extract simple value from  other language', function () {
    expect(strings.how).toEqual('Come vuoi il tuo uovo oggi?');
  });

  it('Extract complex value from other language', function () {
    expect(strings.ratings.good).toEqual('buono');
  });

  it('Get missing key from other language', function () {
    expect(strings.missing).toEqual('missing value');
  });

  it('Get complex missing key from other language', function () {
    expect(strings.ratings.missingComplex).toEqual('missing value');
  });
  it('Format string in other language', function () {
    expect(strings.formatString(strings.formattedValue, "torta", "gelato"))
      .toEqual(["Vorrei un po' di ", "torta", " e ", "gelato", ", o solo ", "torta"]);
  });

  it('Get string in a different language', function () {
    expect(strings.getString("choice", "en")).toBe("How to choose the egg");
  });

  it('Switch to different props', function () {
    strings.setContent({
      fr: {
        "hello":"bonjour"
      },
      en: {
        "hello":"hello"
      },
      it: {
        "hello":"ciao"
      }
    });
    strings.setLanguage("fr");
    expect(strings.hello).toEqual('bonjour');
  });

  it('Switch to different props not working', function () {
    strings = new LocalizedStrings({
          en: {
            a: {
              b: { x: "foo", y: "bar" },
              c: { z: "baz" }
              }
          }
          });
    strings.setContent({
      en: {
        a: {
          b: { x: "a.b.x", y: "a.b.y" },
          c: { z: "a.c.z" }
        }
      }
    });
    strings.setLanguage("en");
    expect(strings.a.b.x).toEqual('a.b.x');
  });

  it('Should throw an exception if a reserved word is used', function() {
    expect( function(){
      strings = new LocalizedStrings({
        en: {
          language: "language",
          _language: "language is forbidden"
        }
      });
    } ).toThrow(new Error("_language cannot be used as a key. It is a reserved word."));
  });
});<|endoftext|>


<commit_before>const uuid = require('uuid');
const request = require('request');

module.exports = function initialize(params) {
  const {communicationsKey, knex, sebacon, restrictToGroup, testLogin, util} = params;

  function login(req, res, next) {
    const ssoId = req.body.ssoid;
    const validationReq = {
      id: uuid.v4(),
      method: "GetUser",
      params: [
        communicationsKey,
        ssoId
      ],
      jsonrpc: "2.0"
    };

    const moreDataReq = Object.assign({}, validationReq, { method: "GetUserData" });

    request.post({
      url: 'https://tunnistus.avoine.fi/mmserver',
      json: validationReq
    }, (err, response, validationBody) => {
      if (err) {
        console.error(err);
        return knex('events').insert({type: 'login_failure', data: {error: err}})
        .then(() => {
          return res.status(500).send('Jotain meni pieleen');
        });

      }

      if (validationBody.error) {
        console.error(validationBody);
        req.session = null;
        return knex('events').insert({type: 'login_failure', data: {error: validationBody.error}})
        .then(() => {
          return res.status(400).send('Kirjautuminen epäonnistui');
        });
      }

      request.post({
        url: 'https://tunnistus.avoine.fi/mmserver',
        json: moreDataReq
      }, (err, response, detailsBody) => {
        if (err) {
          console.error(err);
          return knex('events').insert({type: 'login_failure', data: {error: err}})
          .then(() => {
            return res.status(500).send('Jotain meni pieleen');
          });
        }

        if (detailsBody.error) {
          console.error(detailsBody);
          req.session = null;
          return knex('events').insert({type: 'login_failure', data: {error: detailsBody.error}})
          .then(() => {
            return res.status(400).send('Kirjautuminen epäonnistui');
          });
        }

        if (restrictToGroup && !detailsBody.result.groups.includes(restrictToGroup)) {
          console.log(detailsBody);
          req.session = null;
          return knex('events').insert({type: 'login_failure', data: {error: 'User not in restrictToGroup'}})
          .then(() => {
            return res.status(403).send('Ei oikeutta käyttää palvelua');
          });
        }

        const sessionId = uuid.v4();
        const remoteId = validationBody.result.local_id;
        return knex('users').where({ remote_id: remoteId })
          .then((resp) => {
            if (resp.length === 0) {
              return Promise.all([
                sebacon.getUserFirstName(remoteId),
                sebacon.getUserNickName(remoteId),
                sebacon.getUserLastName(remoteId),
                sebacon.getUserEmail(remoteId),
                sebacon.getUserPhoneNumber(remoteId)
              ]).then(([firstname, nickname, lastname, email, phone]) => {
                return knex('users')
                  .insert({
                    remote_id: validationBody.result.local_id,
                    data: {
                      name: nickname || firstname,
                      domains: [],
                      positions: [],
                      profile_creation_consented: false,
                      business_card: {
                        name: `${firstname} ${lastname}`, // This works for most Finnish names
                        phone: phone,
                        email: email
                      }
                    },
                    settings: {
                      email_address: email,
                      emails_for_answers: true
                    }
                    // postgres does not automatically return the id, ask for it explicitly
                  }, 'id').then(insertResp => ({
                    id: insertResp[0]
                  }))
                // insert will fail if user with the remote_id is already created
                // catch here so we don't catch sebacon errors that we want to go through to global error handling
                  .catch(e => knex('users').where({remote_id: remoteId}).then(rows => rows[0]))
              })
            } else {
              return resp[0];
            }
          })
          .then((user) => {
            return Promise.all([
              knex('sessions').insert({
                id: sessionId,
                user_id: user.id
              }),
              knex('events').insert({
                type: 'login_success',
                data: {user_id: user.id, session_id: sessionId}
              })
            ]).then(() => {
              req.session.id = sessionId;
              return res.redirect(req.query.path || '/');
            });
          }).catch(next)
      });
    });
  }

  // Can be cleaned if no events needed for test user logouts
  function logout(req, res, next) {
    if (req.session.id) {
      if (!testLogin) {
        util.userForSession(req)
        .then((user) => {
          return Promise.all([
            knex('events').insert({type: 'logout_success', data: {session_id: req.session.id, user_id: user.id}}),
            knex('sessions').where({id: req.session.id}).del()
          ]);
        }).then(() => {
          req.session = null;
          res.redirect('https://tunnistus.avoine.fi/sso-logout/')}
        ).catch(next);
      } else {
        util.userForSession(req)
        .then((user) => {
          return knex('events').insert({type: 'logout_testuser', data: {session_id: req.session.id, user_id: user.id}})
        }).then(() => {
          req.session = null;
          res.redirect('/');
        });
      }
    } else {
      return knex('events').insert({type: 'logout_failure', data: {message: 'no_session_id'}})
      .then(() => {
        if(!testLogin)
          res.redirect('https://tunnistus.avoine.fi/sso-logout/');
        else
          res.redirect('/')
      });
    }
  }

  return {
    login,
    logout
  };
}
<commit_msg>Added the missing returns<commit_after>const uuid = require('uuid');
const request = require('request');

module.exports = function initialize(params) {
  const {communicationsKey, knex, sebacon, restrictToGroup, testLogin, util} = params;

  function login(req, res, next) {
    const ssoId = req.body.ssoid;
    const validationReq = {
      id: uuid.v4(),
      method: "GetUser",
      params: [
        communicationsKey,
        ssoId
      ],
      jsonrpc: "2.0"
    };

    const moreDataReq = Object.assign({}, validationReq, { method: "GetUserData" });

    request.post({
      url: 'https://tunnistus.avoine.fi/mmserver',
      json: validationReq
    }, (err, response, validationBody) => {
      if (err) {
        console.error(err);
        return knex('events').insert({type: 'login_failure', data: {error: err}})
        .then(() => {
          return res.status(500).send('Jotain meni pieleen');
        });

      }

      if (validationBody.error) {
        console.error(validationBody);
        req.session = null;
        return knex('events').insert({type: 'login_failure', data: {error: validationBody.error}})
        .then(() => {
          return res.status(400).send('Kirjautuminen epäonnistui');
        });
      }

      request.post({
        url: 'https://tunnistus.avoine.fi/mmserver',
        json: moreDataReq
      }, (err, response, detailsBody) => {
        if (err) {
          console.error(err);
          return knex('events').insert({type: 'login_failure', data: {error: err}})
          .then(() => {
            return res.status(500).send('Jotain meni pieleen');
          });
        }

        if (detailsBody.error) {
          console.error(detailsBody);
          req.session = null;
          return knex('events').insert({type: 'login_failure', data: {error: detailsBody.error}})
          .then(() => {
            return res.status(400).send('Kirjautuminen epäonnistui');
          });
        }

        if (restrictToGroup && !detailsBody.result.groups.includes(restrictToGroup)) {
          console.log(detailsBody);
          req.session = null;
          return knex('events').insert({type: 'login_failure', data: {error: 'User not in restrictToGroup'}})
          .then(() => {
            return res.status(403).send('Ei oikeutta käyttää palvelua');
          });
        }

        const sessionId = uuid.v4();
        const remoteId = validationBody.result.local_id;
        return knex('users').where({ remote_id: remoteId })
          .then((resp) => {
            if (resp.length === 0) {
              return Promise.all([
                sebacon.getUserFirstName(remoteId),
                sebacon.getUserNickName(remoteId),
                sebacon.getUserLastName(remoteId),
                sebacon.getUserEmail(remoteId),
                sebacon.getUserPhoneNumber(remoteId)
              ]).then(([firstname, nickname, lastname, email, phone]) => {
                return knex('users')
                  .insert({
                    remote_id: validationBody.result.local_id,
                    data: {
                      name: nickname || firstname,
                      domains: [],
                      positions: [],
                      profile_creation_consented: false,
                      business_card: {
                        name: `${firstname} ${lastname}`, // This works for most Finnish names
                        phone: phone,
                        email: email
                      }
                    },
                    settings: {
                      email_address: email,
                      emails_for_answers: true
                    }
                    // postgres does not automatically return the id, ask for it explicitly
                  }, 'id').then(insertResp => ({
                    id: insertResp[0]
                  }))
                // insert will fail if user with the remote_id is already created
                // catch here so we don't catch sebacon errors that we want to go through to global error handling
                  .catch(e => knex('users').where({remote_id: remoteId}).then(rows => rows[0]))
              })
            } else {
              return resp[0];
            }
          })
          .then((user) => {
            return Promise.all([
              knex('sessions').insert({
                id: sessionId,
                user_id: user.id
              }),
              knex('events').insert({
                type: 'login_success',
                data: {user_id: user.id, session_id: sessionId}
              })
            ]).then(() => {
              req.session.id = sessionId;
              return res.redirect(req.query.path || '/');
            });
          }).catch(next)
      });
    });
  }

  // Can be cleaned if no events needed for test user logouts
  function logout(req, res, next) {
    if (req.session.id) {
      if (!testLogin) {
        util.userForSession(req)
        .then((user) => {
          return Promise.all([
            knex('events').insert({type: 'logout_success', data: {session_id: req.session.id, user_id: user.id}}),
            knex('sessions').where({id: req.session.id}).del()
          ]);
        }).then(() => {
          req.session = null;
          return res.redirect('https://tunnistus.avoine.fi/sso-logout/')}
        ).catch(next);
      } else {
        util.userForSession(req)
        .then((user) => {
          return knex('events').insert({type: 'logout_testuser', data: {session_id: req.session.id, user_id: user.id}})
        }).then(() => {
          req.session = null;
          return res.redirect('/');
        });
      }
    } else {
      return knex('events').insert({type: 'logout_failure', data: {message: 'no_session_id'}})
      .then(() => {
        if(!testLogin)
          return res.redirect('https://tunnistus.avoine.fi/sso-logout/');
        else
          return res.redirect('/')
      });
    }
  }

  return {
    login,
    logout
  };
}
<|endoftext|>


<commit_before>/*
** Module dependencies
*/
var mongoose = require('mongoose');
var Schema = mongoose.Schema;

/*
** Online resource schema
*/
var OnlineResourceSchema = new Schema({
    name: {
        type: String
    },
    link: {
        type: String
    },
    protocol: {
        type: String
    },
    description: {
        type: String
    }
});

/*
** Contact schema
*/
var ContactSchema = new Schema({
    organizationName: {
        type: String
    },
    individualName: {
        type: String
    },
    positionName: {
        type: String
    },
    email: {
        type: String
    },
    role: {
        type: String
    }
});

/*
** Record schema
*/
var RecordSchema = new Schema({
    parentCatalog: {
        type: Schema.Types.ObjectId,
        ref: 'Service',
        index: true
    },
    lastSync: { type: Schema.Types.ObjectId, ref: 'ServiceSync' },
    identifier: {
        type: String,
        index: true
    },
    metadata: {
        title: {
            type: String
        },
        abstract: {
            type: String
        },
        type: {
            type: String,
            index: true
        },
        representationType: {
            type: String,
            index: true
        },
        serviceType: {
            type: String,
            index: true
        },
        keywords: {
            type: [String],
            index: true
        },
        onlineResources: {
            type: [OnlineResourceSchema]
        },
        contacts: {
            type: [ContactSchema]
        },
        _contacts: {
            type: [ContactSchema]
        },
        _updated: {
            type: Date
        }
    }
});

RecordSchema.index({
    'metadata.title': 'text',
    'metadata.abstract': 'text',
    'metadata.keywords': 'text'
}, {
    default_language: 'french',
    name: 'default_text_index',
    weights: {
        'metadata.title': 10,
        'metadata.keywords': 5,
        'metadata.abstract': 2
    }
});

/*
** Attach model
*/
mongoose.model('Record', RecordSchema);
<commit_msg>Enforce record schema<commit_after>/*
** Module dependencies
*/
var mongoose = require('mongoose');
var Schema = mongoose.Schema;

/*
** Online resource schema
*/
var OnlineResourceSchema = new Schema({
    name: {
        type: String
    },
    link: {
        type: String
    },
    protocol: {
        type: String
    },
    description: {
        type: String
    }
});

/*
** Contact schema
*/
var ContactSchema = new Schema({
    organizationName: {
        type: String
    },
    individualName: {
        type: String
    },
    positionName: {
        type: String
    },
    email: {
        type: String
    },
    role: {
        type: String
    }
});

/*
** Record schema
*/
var RecordSchema = new Schema({
    parentCatalog: {
        type: Schema.Types.ObjectId,
        ref: 'Service',
        index: true
    },
    lastSync: { type: Schema.Types.ObjectId, ref: 'ServiceSync', required: true },
    identifier: {
        type: String,
        index: true
    },
    metadata: {
        title: {
            type: String
        },
        abstract: {
            type: String
        },
        type: {
            type: String,
            index: true
        },
        representationType: {
            type: String,
            index: true
        },
        serviceType: {
            type: String,
            index: true
        },
        keywords: {
            type: [String],
            index: true
        },
        onlineResources: {
            type: [OnlineResourceSchema]
        },
        contacts: {
            type: [ContactSchema]
        },
        _contacts: {
            type: [ContactSchema]
        },
        _updated: {
            type: Date
        }
    }
});

RecordSchema.index({
    'metadata.title': 'text',
    'metadata.abstract': 'text',
    'metadata.keywords': 'text'
}, {
    default_language: 'french',
    name: 'default_text_index',
    weights: {
        'metadata.title': 10,
        'metadata.keywords': 5,
        'metadata.abstract': 2
    }
});

/*
** Attach model
*/
mongoose.model('Record', RecordSchema);
<|endoftext|>


<commit_before>/* jshint node:true */
/* global gc */
var requestp = require('./requestp');
var u = require('underscore');
var JSON3 = require('json3');

var passThroughHeaders = function(incomingHeaders) {
  // remove those that node should generate
  var externalReqHeaders = u.omit(incomingHeaders, 'accept-encoding', 'connection', 'cookie', 'host', 'user-agent');
  externalReqHeaders.accept = 'application/json';
  return externalReqHeaders;
};

var isValidJson = function(str) {
  try {
    JSON3.parse(str);
  } catch (e) {
    return false;
  }
  return true;
};

module.exports = function(url, headers, raw) {
  var externalReqHeaders = passThroughHeaders(headers);

  var promise = requestp({
    uri: url,
    strictSSL: false, // node(jitsu?) has some SSL problems
    headers: externalReqHeaders,
    encoding: 'utf8'
  }).then(
    // process API response
    function(response){
      var body = response.body;

      if (!raw && !isValidJson(body)){
        // invalid JSON
        throw new Error(body);
      } else {
        // proxy successful
        return response;
      }
    }
  );

  if (process.env.NODE_ENV === 'production' || typeof gc === 'function') {
    // run garbage collection
    // https://github.com/afeld/jsonp/issues/18#issuecomment-54732166
    promise = promise.finally(gc);
  }

  return promise;
};
<commit_msg>run garbage collection out of request loop<commit_after>/* jshint node:true */
/* global gc */
var requestp = require('./requestp');
var u = require('underscore');
var JSON3 = require('json3');

var shouldGarbageCollect = function() {
  return process.env.NODE_ENV === 'production' || typeof gc === 'function';
};

var passThroughHeaders = function(incomingHeaders) {
  // remove those that node should generate
  var externalReqHeaders = u.omit(incomingHeaders, 'accept-encoding', 'connection', 'cookie', 'host', 'user-agent');
  externalReqHeaders.accept = 'application/json';
  return externalReqHeaders;
};

var isValidJson = function(str) {
  try {
    JSON3.parse(str);
  } catch (e) {
    return false;
  }
  return true;
};

module.exports = function(url, headers, raw) {
  var externalReqHeaders = passThroughHeaders(headers);

  var promise = requestp({
    uri: url,
    strictSSL: false, // node(jitsu?) has some SSL problems
    headers: externalReqHeaders,
    encoding: 'utf8'
  }).then(
    // process API response
    function(response){
      var body = response.body;

      if (!raw && !isValidJson(body)){
        // invalid JSON
        throw new Error(body);
      } else {
        // proxy successful
        return response;
      }
    }
  );

  if (shouldGarbageCollect()) {
    // https://github.com/afeld/jsonp/issues/18#issuecomment-54732166
    process.nextTick(gc);
  }

  return promise;
};
<|endoftext|>