<commit_before>const fs = require('fs');
const path = require('path');
const jsYaml = require('js-yaml');
const { installForTests } = require('./esbuild');
const test262Dir = path.join(__dirname, '..', 'demo', 'test262', 'test');

function findFiles() {
  function visit(dir) {
    for (const entry of fs.readdirSync(dir)) {
      const fullEntry = path.join(dir, entry);
      const stats = fs.statSync(fullEntry);
      if (stats.isDirectory()) {
        visit(fullEntry);
      } else if (stats.isFile() && entry.endsWith('.js') && !entry.endsWith('_FIXTURE.js')) {
        files.push(fullEntry);
      }
    }
  }

  const files = [];
  visit(test262Dir);
  return files;
}

function formatErrors(content, error) {
  if (error.errors) {
    return error.errors.map(({ text, location }) => {
      if (location) {
        const { line, column } = location;
        const contentLine = content.split(/(?:\r\n|\n|\r|\u2028|\u2029)/g)[line - 1];
        return `<stdin>:${line}:${column}: error: ${text}\n${contentLine}\n${' '.repeat(column)}^`;
      }
      return `error: ${text}`;
    }).join('\n');
  }
  return error + '';
}

async function main() {
  const esbuild = installForTests();
  const files = findFiles();
  let runCount = 0;
  let shouldHavePassed = 0;
  let shouldHaveFailed = 0;
  let reparseCount = 0;
  let reprintCount = 0;
  let minifyCount = 0;

  async function esbuildFile(input, options) {
    try {
      const { code } = await esbuild.transform(input, options);
      return { success: true, output: code };
    } catch (error) {
      return { success: false, error };
    }
  }

  async function processFile(file) {
    let content = fs.readFileSync(file, 'utf8');
    const start = content.indexOf('/*---');
    const end = content.indexOf('---*/');

    if (start < 0 || end < 0) {
      console.warn(`Missing YAML metadata: ${file}`);
      return;
    }

    const yaml = jsYaml.safeLoad(content.slice(start + 5, end));
    const shouldParse = !yaml.negative || yaml.negative.phase === 'runtime';

    if (yaml.features) {
      if (yaml.features.includes('hashbang')) return
      if (yaml.features.includes('regexp-match-indices')) return
      if (yaml.features.includes('regexp-named-groups')) return
      if (yaml.features.includes('regexp-unicode-property-escapes')) return
    }

    if (yaml.flags) {
      if (yaml.flags.includes('onlyStrict')) content = '"use strict";\n' + content
      if (yaml.flags.includes('module')) content = 'export {};\n' + content
    }

    const result = await esbuildFile(content, { minify: false });

    if (result.success !== shouldParse) {
      if (!result.success) shouldHavePassed++;
      else shouldHaveFailed++;
      const text = result.success
        ? (yaml.description || '').trim()
        : formatErrors(content, result.error);
      console.log('\n' + `${file}\n${text}`.replace(/\n/g, '\n  '));
    }

    else if (result.success) {
      const result2 = await esbuildFile(result.output, { minify: false });
      if (!result2.success) {
        console.log(`\n!!! REPARSE ERROR: ${file} !!!`);
        console.log(`${result2.error}`);
        reparseCount++;
      } else if (result2.output !== result.output) {
        console.log(`\n!!! REPRINT ERROR: ${file} !!!`);
        reprintCount++;
      } else {
        const result3 = await esbuildFile(result2.output, { minify: true });
        if (!result3.success) {
          throw new Error('This should have succeeded');
        }
        const result4 = await esbuildFile(result3.output, { minify: true });
        if (!result4.success) {
          console.log(`\n!!! MINIFY ERROR: ${file} !!!`);
          console.log(`${result4.error}`);
          minifyCount++;
        }
      }
    }
    runCount++;
  }

  // Process tests in parallel for speed
  await new Promise((resolve, reject) => {
    let inFlight = 0;
    let i = 0;

    function next() {
      if (i === files.length && inFlight === 0) {
        return resolve();
      }

      while (i < files.length && inFlight < 5) {
        inFlight++;
        processFile(files[i++]).then(() => {
          inFlight--;
          next();
        }, reject);
      }
    }

    next();
  });

  console.log(`tests ran: ${runCount}`);
  console.log(`  tests incorrectly failed: ${shouldHavePassed}`);
  console.log(`  tests incorrectly passed: ${shouldHaveFailed}`);
  console.log(`tests skipped: ${files.length - runCount}`);
  console.log(`reparse failures: ${reparseCount}`);
  console.log(`reprint failures: ${reprintCount}`);
  console.log(`minify failures: ${minifyCount}`);
}

main().catch(e => setTimeout(() => {
  throw e
}));
<commit_msg>start a list of test262 tests to skip<commit_after>const fs = require('fs');
const path = require('path');
const jsYaml = require('js-yaml');
const { installForTests } = require('./esbuild');
const test262Dir = path.join(__dirname, '..', 'demo', 'test262', 'test');

function findFiles() {
  function visit(dir) {
    for (const entry of fs.readdirSync(dir)) {
      const fullEntry = path.join(dir, entry);
      const stats = fs.statSync(fullEntry);
      if (stats.isDirectory()) {
        visit(fullEntry);
      } else if (stats.isFile() && entry.endsWith('.js') && !entry.endsWith('_FIXTURE.js')) {
        files.push(fullEntry);
      }
    }
  }

  const files = [];
  visit(test262Dir);
  return files;
}

function formatErrors(content, error) {
  if (error.errors) {
    return error.errors.map(({ text, location }) => {
      if (location) {
        const { line, column } = location;
        const contentLine = content.split(/(?:\r\n|\n|\r|\u2028|\u2029)/g)[line - 1];
        return `<stdin>:${line}:${column}: error: ${text}\n${contentLine}\n${' '.repeat(column)}^`;
      }
      return `error: ${text}`;
    }).join('\n');
  }
  return error + '';
}

async function main() {
  const esbuild = installForTests();
  const files = findFiles();
  let runCount = 0;
  let shouldHavePassed = 0;
  let shouldHaveFailed = 0;
  let reparseCount = 0;
  let reprintCount = 0;
  let minifyCount = 0;

  async function esbuildFile(input, options) {
    try {
      const { code } = await esbuild.transform(input, options);
      return { success: true, output: code };
    } catch (error) {
      return { success: false, error };
    }
  }

  const skipList = [
    // Skip these tests because we deliberately support top-level return (input
    // files are treated as CommonJS and/or ESM but never as global code, and
    // top-level return is allowed in CommonJS)
    'S12.9_A1_T1.js', // Checking if execution of "return" with no function fails
    'S12.9_A1_T10.js', // Checking if execution of "return (0)" with no function fails
    'S12.9_A1_T2.js', // Checking if execution of "return x" with no function fails
    'S12.9_A1_T3.js', // Checking if execution of "return" within "try" statement fails
    'S12.9_A1_T4.js', // Checking if execution of "return" with no function fails
    'S12.9_A1_T5.js', // Checking if execution of "return" with no function, placed into a Block, fails
    'S12.9_A1_T6.js', // Checking if execution of "return" with no function, placed into a loop, fails
    'S12.9_A1_T7.js', // Checking if execution of "return x" with no function, placed inside Block, fails
    'S12.9_A1_T8.js', // Checking if execution of "return x" with no function, placed into a loop, fails
    'S12.9_A1_T9.js', // Checking if execution of "return", placed into a catch Block, fails

    // Skip these tests because we deliberately support parsing top-level await
    // in all files. Files containing top-level await are always interpreted as
    // ESM, never as CommonJS.
    'simple-basic-identifierreference-await.js', // IdentifierReference  await Return simple. (Simple Direct assignment)
    'identifier-shorthand-await-strict-mode.js', // Object literal shorthands are limited to valid identifier references. await is valid in non-module strict mode code.
    'await-BindingIdentifier-in-global.js', // Await is allowed as a binding identifier in global scope
    'await-in-global.js', // Await is an identifier in global scope
    'await-in-nested-function.js', // Await is allowed as an identifier in functions nested in async functions
    'await-in-nested-generator.js', // Await is allowed as an identifier in generator functions nested in async functions
    'class-name-ident-await-escaped.js', // `await` with escape sequence is a valid class-name identifier.
    'class-name-ident-await.js', // `await` is a valid class-name identifier.
    'await-identifier.js', // Dynamic Import receives an AssignmentExpression (IdentifierReference: await)
    'new-await-script-code.js', // await is not a keyword in script code
    'await-script.js', // The `await` token is permitted as an identifier in script code
    'class-name-ident-await-escaped.js', // `await` with escape sequence is a valid class-name identifier.
    'class-name-ident-await.js', // `await` is a valid class-name identifier.
    'value-await-non-module-escaped.js', // `await` is not a reserved identifier in non-module code and may be used as a label.
    'value-await-non-module.js', // `await` is not a reserved identifier in non-module code and may be used as a label.
  ]

  async function processFile(file) {
    let content = fs.readFileSync(file, 'utf8');
    const start = content.indexOf('/*---');
    const end = content.indexOf('---*/');

    if (start < 0 || end < 0) {
      console.warn(`Missing YAML metadata: ${file}`);
      return;
    }

    const yaml = jsYaml.safeLoad(content.slice(start + 5, end));
    const shouldParse = !yaml.negative || yaml.negative.phase === 'runtime';

    if (yaml.features) {
      if (yaml.features.includes('hashbang')) return
      if (yaml.features.includes('regexp-match-indices')) return
      if (yaml.features.includes('regexp-named-groups')) return
      if (yaml.features.includes('regexp-unicode-property-escapes')) return
    }

    if (yaml.flags) {
      if (yaml.flags.includes('onlyStrict')) content = '"use strict";\n' + content
      if (yaml.flags.includes('module')) content = 'export {};\n' + content
    }

    if (skipList.includes(path.basename(file))) return

    const result = await esbuildFile(content, { minify: false });

    if (result.success !== shouldParse) {
      if (!result.success) shouldHavePassed++;
      else shouldHaveFailed++;
      const text = result.success
        ? (yaml.description || '').trim()
        : formatErrors(content, result.error);
      console.log('\n' + `${file}\n${text}`.replace(/\n/g, '\n  '));
    }

    else if (result.success) {
      const result2 = await esbuildFile(result.output, { minify: false });
      if (!result2.success) {
        console.log(`\n!!! REPARSE ERROR: ${file} !!!`);
        console.log(`${result2.error}`);
        reparseCount++;
      } else if (result2.output !== result.output) {
        console.log(`\n!!! REPRINT ERROR: ${file} !!!`);
        reprintCount++;
      } else {
        const result3 = await esbuildFile(result2.output, { minify: true });
        if (!result3.success) {
          throw new Error('This should have succeeded');
        }
        const result4 = await esbuildFile(result3.output, { minify: true });
        if (!result4.success) {
          console.log(`\n!!! MINIFY ERROR: ${file} !!!`);
          console.log(`${result4.error}`);
          minifyCount++;
        }
      }
    }
    runCount++;
  }

  // Process tests in parallel for speed
  await new Promise((resolve, reject) => {
    let inFlight = 0;
    let i = 0;

    function next() {
      if (i === files.length && inFlight === 0) {
        return resolve();
      }

      while (i < files.length && inFlight < 5) {
        inFlight++;
        processFile(files[i++]).then(() => {
          inFlight--;
          next();
        }, reject);
      }
    }

    next();
  });

  console.log(`tests ran: ${runCount}`);
  console.log(`  tests incorrectly failed: ${shouldHavePassed}`);
  console.log(`  tests incorrectly passed: ${shouldHaveFailed}`);
  console.log(`tests skipped: ${files.length - runCount}`);
  console.log(`reparse failures: ${reparseCount}`);
  console.log(`reprint failures: ${reprintCount}`);
  console.log(`minify failures: ${minifyCount}`);
}

main().catch(e => setTimeout(() => {
  throw e
}));
<|endoftext|>


<commit_before>const { serveHTTP, addonBuilder } = require('stremio-addon-sdk')
const needle = require('needle')
const _ = require('lodash')

const twitch_head = { headers: { 'Client-ID': process.env.TWITCH_CLIENT_ID } }

const caches = {
    catalog: 15 * 60, // 15min
    meta: 30 * 60, // 30min
    streams: 15 * 60, // 15min
    search: 15 * 60, // 15min, searching is currently disabled
}

const cursors = {}

let genreMap = {}

needle.get('https://api.twitch.tv/helix/games/top?first=100', twitch_head, (err, res) => {

    let genres = []

    if (err || !res || !res.body || !res.body.data || !res.body.data.length)
        console.log('Could not get game list for filter')
    else
        genres = res.body.data.map( game => { return game.name })

    genreMap = res.body.data

    const twitch_chans = {}

    const pkg = require("./package");

    const addon = new addonBuilder({
        id: 'org.stremio.twitch',
        version: pkg.version,
        name: pkg.displayName,
        description: pkg.description,
        icon: 'http://s.jtvnw.net/jtv_user_pictures/hosted_images/GlitchIcon_purple.png',
        logo: 'https://rack1.chipmeup.com/assets/twitch/logo-cd148048b88ce417a0c815548e7e4681.png',
        resources: ['stream', 'meta', 'catalog'],
        types: ['tv'],
        idPrefixes: ['twitch_id:'],
        catalogs: [
            {
                type: 'tv',
                id: 'twitch_catalog',
                genres,
                extraSupported: [
                    { name: 'genre' },
//                    { name: 'search'},
                    { name: 'skip' }
                ]
            }
        ]
    })

    var expire = {};

    // Get all channels
    const twitchStreams = (cb, limit, offset, genre) => {

        const tag = genre || 'top'

        let tagId

        if (genre != 'top') {
            genreMap.some(el => {
                if (el.name == genre)
                    tagId = el.id
            })
        }

        if (!cursors[tag])
            cursors[tag] = {}

        if (!expire[tag])
            expire[tag] = []

        if (!twitch_chans[tag])
            twitch_chans[tag] = []

        if (expire[tag][offset] && expire[tag][offset] > Date.now()) {
            if (twitch_chans[tag][offset] && twitch_chans[tag][offset].length && cb) {
                cb(null, twitch_chans[tag][offset])
                return
            }
        }

        let twitchUrl = 'https://api.twitch.tv/helix/streams?'

        if (genre) {
            if (tagId)
                twitchUrl += 'game_id=' + tagId
            else {
                cb(Error('no genre id found for genre: ' + tag))
                return
            }
        }

        twitchUrl += '&first=' + (limit || 100)

        if (offset) {
            if (cursors[tag][offset + ''])
                twitchUrl += '&after=' + cursors[tag][offset + '']
            else {
                cb(Error('cursor for pagination missing for offset ' + offset + ' of genre ' + tag))
                return
            }
        }

        needle.get(twitchUrl, twitch_head, (err, res) => {
            if (err) {
                cb && cb(err)
                return
            }
            twitch_chans[tag][offset] = []
            if (res && res.body && res.body.data && res.body.data.length) {
                res.body.data.forEach( (el, ij) => {
                    let channel = res.body.data[0].user_name;
                    if ((el.thumbnail_url || '').includes('user_')) {
                        channel = el.thumbnail_url.split('user_')[1]
                        channel = channel.split('-')[0]
                    }
                    twitch_chans[tag][offset].push({
                        id: 'twitch_id:' + channel,
                        name: el.title,
                        poster: el.thumbnail_url ? el.thumbnail_url.replace('{width}', '300').replace('{height}', '170') : undefined,
                        posterShape: 'landscape',
//                        logo: el.logo,
                        background: el.thumbnail_url ? el.thumbnail_url.replace('{width}', '1920').replace('{height}', '1080') : undefined,
//                        genres: [ el.game ],
                        type: 'tv'
                    });
                });
                if ((res.body.pagination || {}).cursor)
                    cursors[tag][parseInt(limit || 100) + parseInt(offset || 0) + ''] = res.body.pagination.cursor
                expire[tag][offset] = Date.now() + 900000; // expire in 15 mins
                cb && cb(null, twitch_chans[tag][offset]);
            } else if (cb)
                cb(new Error('Network Error'));
        });
    }

    const searchMeta = args => {

        return new Promise((resolve, reject) => {

            var searcher = encodeURIComponent(args.extra.search).split('%20').join('+');

            needle.get('https://api.twitch.tv/helix/search/streams?limit=' + (args.extra.limit || 75) + '&q=' + searcher, twitch_head, (err, res) => {
                if (err) {
                    reject(err);
                    return;
                }
                const results = [];

                if ((((res || {}).body || {}).data || []).length) {
                    res.body.data.forEach( (el, ij) => {
                        let channel = res.body.data[0].user_name;
                        if ((el.thumbnail_url || '').includes('user_')) {
                            channel = el.thumbnail_url.split('user_')[1]
                            channel = channel.split('-')[0]
                        }
                        results.push({
                            id: 'twitch_id:' + channel,
                            name: el.title,
                            poster: el.thumbnail_url ? el.thumbnail_url.replace('{width}', '300').replace('{height}', '170') : undefined,
                            posterShape: 'landscape',
    //                        logo: el.logo,
                            background: el.thumbnail_url ? el.thumbnail_url.replace('{width}', '1920').replace('{height}', '1080') : undefined,
    //                        genres: [ el.game ],
                            type: 'tv'
                        });
                    });
                    resolve({ metas: results, cacheMaxAge: caches.search })
                } else
                    reject(Error('Network Error'))
            })
        })
    }

    const getStream = args => {

        return new Promise((resolve, reject) => {
            const channel = args.id.replace('twitch_id:', '');
            if (channel) {

                needle.get('https://api.twitch.tv/api/channels/' + encodeURIComponent(channel) + '/access_token', twitch_head, (err, res) => {
                    if (err) {
                        reject(err);
                        return;
                    }

                    if ((res || {}).body && res.body.sig && res.body.token) {

                        const title = res.body.status;
                        const token = encodeURIComponent(res.body.token);
                        const sig = res.body.sig;
                        const rand = Math.floor((Math.random() * 999999) + 1);
                        const mrl = 'https://usher.ttvnw.net/api/channel/hls/' + encodeURIComponent(channel) + '.m3u8?player=twitchweb&token=' + token + '&sig=' + sig + '&allow_audio_only=true&allow_source=true&type=any&p=' + rand;

                        needle.get(mrl, twitch_head, (err, res) => {

                            if (err || !res || !res.body) {
                                reject(err || new Error('No Response Body'))
                                return
                            }

                            const m3u = Buffer.from(res.body, 'base64').toString('binary')

                            const lines = m3u.split(/\r?\n/)

                            const streams = []

                            lines.forEach((line, ij) => {
                                if (line.startsWith('https:')) {

                                    const prevLine = lines[ij-1]

                                    let getRes = () => {
                                        return prevLine.includes('RESOLUTION=') ? prevLine.split('RESOLUTION=')[1].split(',')[0] : null
                                    }

                                    let getPixels = (resolution) => {
                                        return resolution ? resolution.split('x')[1] + 'p' : null
                                    }

                                    let tag

                                    let videoData

                                    if (prevLine.includes('VIDEO="')) {

                                        videoData = prevLine.split('VIDEO="')[1].split('"')[0]

                                        let fps

                                        if (videoData.includes('p'))
                                            fps = videoData.split('p')[1] + 'fps'

                                        const pixels = getPixels(getRes())

                                        tag = videoData == 'audio_only' ? 'Audio Only' : (pixels + ' / ' + (fps || videoData))

                                    } else {

                                        tag = getPixels(getRes()) || 'Audio Only'

                                        if (prevLine.includes('CODECS="'))
                                            tag += ' , ' + prevLine.split('CODECS="')[1].split('",')[0]

                                    }

                                    streams.push({
                                        url: line,
                                        title: tag
                                    })
                                }
                            })

                            streams.push({
                                title: 'Channel Chat',
                                externalUrl: 'https://www.twitch.tv/popout/' + encodeURIComponent(channel) + '/chat'
                            })

                            resolve({ streams, cacheMaxAge: caches.streams })

                        })
                    } else
                        reject(Error('Network Error'));
                })
            } else
                reject(Error('Stream Missing'))
        })
    }

    const getMeta = args => {
        return new Promise((resolve, reject) => {
            if (args.id) {
                const twitchId = args.id.replace('twitch_id:','')
                const found = twitch_chans['top'] ? twitch_chans['top'].some( chans => {
                    return chans.some( el => {
                        if (el.id == args.id) {
                            resolve({ meta: el })
                            return true
                        }
                    })
                }) : false
                if (!found) {
                    needle.get('https://api.twitch.tv/api/channels/' + twitchId, twitch_head, (err, res) => {
                        if (err) {
                            reject(err);
                            return;
                        }
                        if (res && res.body) {
                            resolve({
                                meta: {
                                    id: args.id,
                                    name: res.body.status,
                                    poster: 'https://static-cdn.jtvnw.net/previews-ttv/live_user_' + twitchId + '-320x180.jpg',
                                    posterShape: 'landscape',
                                    backgroundShape: 'contain',
                                    logo: res.body.logo,
                                    description: res.body.bio,
                                    genres: [res.body.game],
                                    background: 'https://static-cdn.jtvnw.net/previews-ttv/live_user_' + twitchId + '-1920x1080.jpg',
                                    isFree: 1,
                                    type: 'tv'
                                },
                                cacheMaxAge: caches.meta
                            })
                        } else
                            reject(Error('No Results'))
                    })
                }
            } else {
                reject(Error('No ID'))
            }
        })
    }

    const catalogMeta = args => {

        return new Promise((resolve, reject) => {

            const offset = args.extra && args.extra.skip ? args.extra.skip : 0
            const limit = args.extra && args.extra.limit ? args.extra.limit : 100
            const genre = args.extra && args.extra.genre ? args.extra.genre : null

            if (args.extra && args.extra.search)
                searchMeta(args).then(resolve).catch(reject)
            else if (genre)
                twitchStreams((err, chans) => {
                    if (err) reject(err)
                    else
                        resolve({ metas: args.extra && args.extra.limit ? chans.slice(0, args.extra.limit) : chans, cacheMaxAge: caches.catalog })
                }, limit, offset, genre)
            else
                twitchStreams((err, chans) => {
                    if (err) reject(err)
                    else
                        resolve({ metas: args.extra && args.extra.limit ? chans.slice(0, args.extra.limit) : chans, cacheMaxAge: caches.catalog })
                }, limit, offset)

        })
    }

    addon.defineStreamHandler(getStream)
    addon.defineMetaHandler(getMeta)
    addon.defineCatalogHandler(catalogMeta)

    const addonInterface = addon.getInterface();
    serveHTTP(addonInterface, { port: process.env.PORT || 9028 });

})
<commit_msg>Fix manifest<commit_after>const { serveHTTP, addonBuilder } = require('stremio-addon-sdk')
const needle = require('needle')
const _ = require('lodash')

const twitch_head = { headers: { 'Client-ID': process.env.TWITCH_CLIENT_ID } }

const caches = {
    catalog: 15 * 60, // 15min
    meta: 30 * 60, // 30min
    streams: 15 * 60, // 15min
    search: 15 * 60, // 15min, searching is currently disabled
}

const cursors = {}

let genreMap = {}

needle.get('https://api.twitch.tv/helix/games/top?first=100', twitch_head, (err, res) => {

    let genres = []

    if (err || !res || !res.body || !res.body.data || !res.body.data.length)
        console.log('Could not get game list for filter')
    else
        genres = res.body.data.map( game => { return game.name })

    genreMap = res.body.data

    const twitch_chans = {}

    const pkg = require("./package");

    const addon = new addonBuilder({
        id: 'org.stremio.twitch',
        version: pkg.version,
        name: pkg.displayName,
        description: pkg.description,
        icon: 'http://s.jtvnw.net/jtv_user_pictures/hosted_images/GlitchIcon_purple.png',
        logo: 'https://rack1.chipmeup.com/assets/twitch/logo-cd148048b88ce417a0c815548e7e4681.png',
        resources: ['stream', 'meta', 'catalog'],
        types: ['tv'],
        idPrefixes: ['twitch_id:'],
        catalogs: [
            {
                type: 'tv',
                id: 'twitch_catalog',
                genres,
                extra: [
                    { name: 'genre' },
//                    { name: 'search'},
                    { name: 'skip' }
                ]
            }
        ]
    })

    var expire = {};

    // Get all channels
    const twitchStreams = (cb, limit, offset, genre) => {

        const tag = genre || 'top'

        let tagId

        if (genre != 'top') {
            genreMap.some(el => {
                if (el.name == genre)
                    tagId = el.id
            })
        }

        if (!cursors[tag])
            cursors[tag] = {}

        if (!expire[tag])
            expire[tag] = []

        if (!twitch_chans[tag])
            twitch_chans[tag] = []

        if (expire[tag][offset] && expire[tag][offset] > Date.now()) {
            if (twitch_chans[tag][offset] && twitch_chans[tag][offset].length && cb) {
                cb(null, twitch_chans[tag][offset])
                return
            }
        }

        let twitchUrl = 'https://api.twitch.tv/helix/streams?'

        if (genre) {
            if (tagId)
                twitchUrl += 'game_id=' + tagId
            else {
                cb(Error('no genre id found for genre: ' + tag))
                return
            }
        }

        twitchUrl += '&first=' + (limit || 100)

        if (offset) {
            if (cursors[tag][offset + ''])
                twitchUrl += '&after=' + cursors[tag][offset + '']
            else {
                cb(Error('cursor for pagination missing for offset ' + offset + ' of genre ' + tag))
                return
            }
        }

        needle.get(twitchUrl, twitch_head, (err, res) => {
            if (err) {
                cb && cb(err)
                return
            }
            twitch_chans[tag][offset] = []
            if (res && res.body && res.body.data && res.body.data.length) {
                res.body.data.forEach( (el, ij) => {
                    let channel = res.body.data[0].user_name;
                    if ((el.thumbnail_url || '').includes('user_')) {
                        channel = el.thumbnail_url.split('user_')[1]
                        channel = channel.split('-')[0]
                    }
                    twitch_chans[tag][offset].push({
                        id: 'twitch_id:' + channel,
                        name: el.title,
                        poster: el.thumbnail_url ? el.thumbnail_url.replace('{width}', '300').replace('{height}', '170') : undefined,
                        posterShape: 'landscape',
//                        logo: el.logo,
                        background: el.thumbnail_url ? el.thumbnail_url.replace('{width}', '1920').replace('{height}', '1080') : undefined,
//                        genres: [ el.game ],
                        type: 'tv'
                    });
                });
                if ((res.body.pagination || {}).cursor)
                    cursors[tag][parseInt(limit || 100) + parseInt(offset || 0) + ''] = res.body.pagination.cursor
                expire[tag][offset] = Date.now() + 900000; // expire in 15 mins
                cb && cb(null, twitch_chans[tag][offset]);
            } else if (cb)
                cb(new Error('Network Error'));
        });
    }

    const searchMeta = args => {

        return new Promise((resolve, reject) => {

            var searcher = encodeURIComponent(args.extra.search).split('%20').join('+');

            needle.get('https://api.twitch.tv/helix/search/streams?limit=' + (args.extra.limit || 75) + '&q=' + searcher, twitch_head, (err, res) => {
                if (err) {
                    reject(err);
                    return;
                }
                const results = [];

                if ((((res || {}).body || {}).data || []).length) {
                    res.body.data.forEach( (el, ij) => {
                        let channel = res.body.data[0].user_name;
                        if ((el.thumbnail_url || '').includes('user_')) {
                            channel = el.thumbnail_url.split('user_')[1]
                            channel = channel.split('-')[0]
                        }
                        results.push({
                            id: 'twitch_id:' + channel,
                            name: el.title,
                            poster: el.thumbnail_url ? el.thumbnail_url.replace('{width}', '300').replace('{height}', '170') : undefined,
                            posterShape: 'landscape',
    //                        logo: el.logo,
                            background: el.thumbnail_url ? el.thumbnail_url.replace('{width}', '1920').replace('{height}', '1080') : undefined,
    //                        genres: [ el.game ],
                            type: 'tv'
                        });
                    });
                    resolve({ metas: results, cacheMaxAge: caches.search })
                } else
                    reject(Error('Network Error'))
            })
        })
    }

    const getStream = args => {

        return new Promise((resolve, reject) => {
            const channel = args.id.replace('twitch_id:', '');
            if (channel) {

                needle.get('https://api.twitch.tv/api/channels/' + encodeURIComponent(channel) + '/access_token', twitch_head, (err, res) => {
                    if (err) {
                        reject(err);
                        return;
                    }

                    if ((res || {}).body && res.body.sig && res.body.token) {

                        const title = res.body.status;
                        const token = encodeURIComponent(res.body.token);
                        const sig = res.body.sig;
                        const rand = Math.floor((Math.random() * 999999) + 1);
                        const mrl = 'https://usher.ttvnw.net/api/channel/hls/' + encodeURIComponent(channel) + '.m3u8?player=twitchweb&token=' + token + '&sig=' + sig + '&allow_audio_only=true&allow_source=true&type=any&p=' + rand;

                        needle.get(mrl, twitch_head, (err, res) => {

                            if (err || !res || !res.body) {
                                reject(err || new Error('No Response Body'))
                                return
                            }

                            const m3u = Buffer.from(res.body, 'base64').toString('binary')

                            const lines = m3u.split(/\r?\n/)

                            const streams = []

                            lines.forEach((line, ij) => {
                                if (line.startsWith('https:')) {

                                    const prevLine = lines[ij-1]

                                    let getRes = () => {
                                        return prevLine.includes('RESOLUTION=') ? prevLine.split('RESOLUTION=')[1].split(',')[0] : null
                                    }

                                    let getPixels = (resolution) => {
                                        return resolution ? resolution.split('x')[1] + 'p' : null
                                    }

                                    let tag

                                    let videoData

                                    if (prevLine.includes('VIDEO="')) {

                                        videoData = prevLine.split('VIDEO="')[1].split('"')[0]

                                        let fps

                                        if (videoData.includes('p'))
                                            fps = videoData.split('p')[1] + 'fps'

                                        const pixels = getPixels(getRes())

                                        tag = videoData == 'audio_only' ? 'Audio Only' : (pixels + ' / ' + (fps || videoData))

                                    } else {

                                        tag = getPixels(getRes()) || 'Audio Only'

                                        if (prevLine.includes('CODECS="'))
                                            tag += ' , ' + prevLine.split('CODECS="')[1].split('",')[0]

                                    }

                                    streams.push({
                                        url: line,
                                        title: tag
                                    })
                                }
                            })

                            streams.push({
                                title: 'Channel Chat',
                                externalUrl: 'https://www.twitch.tv/popout/' + encodeURIComponent(channel) + '/chat'
                            })

                            resolve({ streams, cacheMaxAge: caches.streams })

                        })
                    } else
                        reject(Error('Network Error'));
                })
            } else
                reject(Error('Stream Missing'))
        })
    }

    const getMeta = args => {
        return new Promise((resolve, reject) => {
            if (args.id) {
                const twitchId = args.id.replace('twitch_id:','')
                const found = twitch_chans['top'] ? twitch_chans['top'].some( chans => {
                    return chans.some( el => {
                        if (el.id == args.id) {
                            resolve({ meta: el })
                            return true
                        }
                    })
                }) : false
                if (!found) {
                    needle.get('https://api.twitch.tv/api/channels/' + twitchId, twitch_head, (err, res) => {
                        if (err) {
                            reject(err);
                            return;
                        }
                        if (res && res.body) {
                            resolve({
                                meta: {
                                    id: args.id,
                                    name: res.body.status,
                                    poster: 'https://static-cdn.jtvnw.net/previews-ttv/live_user_' + twitchId + '-320x180.jpg',
                                    posterShape: 'landscape',
                                    backgroundShape: 'contain',
                                    logo: res.body.logo,
                                    description: res.body.bio,
                                    genres: [res.body.game],
                                    background: 'https://static-cdn.jtvnw.net/previews-ttv/live_user_' + twitchId + '-1920x1080.jpg',
                                    isFree: 1,
                                    type: 'tv'
                                },
                                cacheMaxAge: caches.meta
                            })
                        } else
                            reject(Error('No Results'))
                    })
                }
            } else {
                reject(Error('No ID'))
            }
        })
    }

    const catalogMeta = args => {

        return new Promise((resolve, reject) => {

            const offset = args.extra && args.extra.skip ? args.extra.skip : 0
            const limit = args.extra && args.extra.limit ? args.extra.limit : 100
            const genre = args.extra && args.extra.genre ? args.extra.genre : null

            if (args.extra && args.extra.search)
                searchMeta(args).then(resolve).catch(reject)
            else if (genre)
                twitchStreams((err, chans) => {
                    if (err) reject(err)
                    else
                        resolve({ metas: args.extra && args.extra.limit ? chans.slice(0, args.extra.limit) : chans, cacheMaxAge: caches.catalog })
                }, limit, offset, genre)
            else
                twitchStreams((err, chans) => {
                    if (err) reject(err)
                    else
                        resolve({ metas: args.extra && args.extra.limit ? chans.slice(0, args.extra.limit) : chans, cacheMaxAge: caches.catalog })
                }, limit, offset)

        })
    }

    addon.defineStreamHandler(getStream)
    addon.defineMetaHandler(getMeta)
    addon.defineCatalogHandler(catalogMeta)

    const addonInterface = addon.getInterface();
    serveHTTP(addonInterface, { port: process.env.PORT || 9028 });

})
<|endoftext|>


<commit_before>'use strict';

const assert = require('assert');
const { capture } = require('..');

describe('.capture()', () => {
  it('should return null if no match', () => {
    assert.equal(capture('test/*', 'hi/123'), null);
  });

  it('should return an empty array if there are no captures', () => {
    assert.deepEqual(capture('test/hi', 'test/hi'), []);
  });

  it('should capture stars', () => {
    assert.deepEqual(capture('test/*', 'test/foo'), ['foo']);
    assert.deepEqual(capture('test/*/bar', 'test/foo/bar'), ['foo']);
    assert.deepEqual(capture('test/*/bar/*', 'test/foo/bar/baz'), ['foo', 'baz']);
    assert.deepEqual(capture('test/*.js', 'test/foo.js'), ['foo']);
    assert.deepEqual(capture('test/*-controller.js', 'test/foo-controller.js'), ['foo']);
  });

  it('should capture globstars', () => {
    assert.deepEqual(capture('test/**/*.js', 'test/a.js'), ['', 'a']);
    assert.deepEqual(capture('test/**/*.js', 'test/dir/a.js'), ['dir', 'a']);
    assert.deepEqual(capture('test/**/*.js', 'test/dir/test/a.js'), ['dir/test', 'a']);
  });

  it('should capture extglobs', () => {
    assert.deepEqual(capture('test/+(a|b)/*.js', 'test/a/x.js'), ['a', 'x']);
    assert.deepEqual(capture('test/+(a|b)/*.js', 'test/b/x.js'), ['b', 'x']);
    assert.deepEqual(capture('test/+(a|b)/*.js', 'test/ab/x.js'), ['ab', 'x']);
  });

  it('should capture paren groups', () => {
    assert.deepEqual(capture('test/(a|b)/x.js', 'test/a/x.js'), ['a']);
    assert.deepEqual(capture('test/(a|b)/x.js', 'test/b/x.js'), ['b']);
  });

  it('should capture star groups', () => {
    assert.deepEqual(capture('test/a*(a|b)/x.js', 'test/a/x.js'), ['']);
    assert.deepEqual(capture('test/a*(a|b)/x.js', 'test/aa/x.js'), ['a']);
    assert.deepEqual(capture('test/a*(a|b)/x.js', 'test/ab/x.js'), ['b']);
    assert.deepEqual(capture('test/a*(a|b)/x.js', 'test/aba/x.js'), ['ba']);
  });

  it('should capture plus groups', () => {
    assert.deepEqual(capture('test/+(a|b)/x.js', 'test/a/x.js'), ['a']);
    assert.deepEqual(capture('test/+(a|b)/x.js', 'test/b/x.js'), ['b']);
    assert.deepEqual(capture('test/+(a|b)/x.js', 'test/ab/x.js'), ['ab']);
    assert.deepEqual(capture('test/+(a|b)/x.js', 'test/aba/x.js'), ['aba']);
  });

  it('should capture optional groups', () => {
    assert.deepEqual(capture('test/a?(a|b)/x.js', 'test/a/x.js'), ['']);
    assert.deepEqual(capture('test/a?(a|b)/x.js', 'test/ab/x.js'), ['b']);
    assert.deepEqual(capture('test/a?(a|b)/x.js', 'test/aa/x.js'), ['a']);
  });

  it('should capture @ groups', () => {
    assert.deepEqual(capture('test/@(a|b)/x.js', 'test/a/x.js'), ['a']);
    assert.deepEqual(capture('test/@(a|b)/x.js', 'test/b/x.js'), ['b']);
  });

  it('should capture negated groups', () => {
    assert.deepEqual(capture('test/!(a|b)/x.js', 'test/x/x.js'), ['x']);
    assert.deepEqual(capture('test/!(a|b)/x.js', 'test/y/x.js'), ['y']);
  });
});
<commit_msg>add globstar test where the globstar starts at the root<commit_after>'use strict';

const assert = require('assert');
const { capture } = require('..');

describe('.capture()', () => {
  it('should return null if no match', () => {
    assert.equal(capture('test/*', 'hi/123'), null);
  });

  it('should return an empty array if there are no captures', () => {
    assert.deepEqual(capture('test/hi', 'test/hi'), []);
  });

  it('should capture stars', () => {
    assert.deepEqual(capture('test/*', 'test/foo'), ['foo']);
    assert.deepEqual(capture('test/*/bar', 'test/foo/bar'), ['foo']);
    assert.deepEqual(capture('test/*/bar/*', 'test/foo/bar/baz'), ['foo', 'baz']);
    assert.deepEqual(capture('test/*.js', 'test/foo.js'), ['foo']);
    assert.deepEqual(capture('test/*-controller.js', 'test/foo-controller.js'), ['foo']);
  });

  it('should capture globstars', () => {
    assert.deepEqual(capture('test/**/*.js', 'test/a.js'), ['', 'a']);
    assert.deepEqual(capture('test/**/*.js', 'test/dir/a.js'), ['dir', 'a']);
    assert.deepEqual(capture('test/**/*.js', 'test/dir/test/a.js'), ['dir/test', 'a']);
    assert.deepEqual(capture('**/*.js', 'test/dir/a.js'), ['test/dir', 'a']);
  });

  it('should capture extglobs', () => {
    assert.deepEqual(capture('test/+(a|b)/*.js', 'test/a/x.js'), ['a', 'x']);
    assert.deepEqual(capture('test/+(a|b)/*.js', 'test/b/x.js'), ['b', 'x']);
    assert.deepEqual(capture('test/+(a|b)/*.js', 'test/ab/x.js'), ['ab', 'x']);
  });

  it('should capture paren groups', () => {
    assert.deepEqual(capture('test/(a|b)/x.js', 'test/a/x.js'), ['a']);
    assert.deepEqual(capture('test/(a|b)/x.js', 'test/b/x.js'), ['b']);
  });

  it('should capture star groups', () => {
    assert.deepEqual(capture('test/a*(a|b)/x.js', 'test/a/x.js'), ['']);
    assert.deepEqual(capture('test/a*(a|b)/x.js', 'test/aa/x.js'), ['a']);
    assert.deepEqual(capture('test/a*(a|b)/x.js', 'test/ab/x.js'), ['b']);
    assert.deepEqual(capture('test/a*(a|b)/x.js', 'test/aba/x.js'), ['ba']);
  });

  it('should capture plus groups', () => {
    assert.deepEqual(capture('test/+(a|b)/x.js', 'test/a/x.js'), ['a']);
    assert.deepEqual(capture('test/+(a|b)/x.js', 'test/b/x.js'), ['b']);
    assert.deepEqual(capture('test/+(a|b)/x.js', 'test/ab/x.js'), ['ab']);
    assert.deepEqual(capture('test/+(a|b)/x.js', 'test/aba/x.js'), ['aba']);
  });

  it('should capture optional groups', () => {
    assert.deepEqual(capture('test/a?(a|b)/x.js', 'test/a/x.js'), ['']);
    assert.deepEqual(capture('test/a?(a|b)/x.js', 'test/ab/x.js'), ['b']);
    assert.deepEqual(capture('test/a?(a|b)/x.js', 'test/aa/x.js'), ['a']);
  });

  it('should capture @ groups', () => {
    assert.deepEqual(capture('test/@(a|b)/x.js', 'test/a/x.js'), ['a']);
    assert.deepEqual(capture('test/@(a|b)/x.js', 'test/b/x.js'), ['b']);
  });

  it('should capture negated groups', () => {
    assert.deepEqual(capture('test/!(a|b)/x.js', 'test/x/x.js'), ['x']);
    assert.deepEqual(capture('test/!(a|b)/x.js', 'test/y/x.js'), ['y']);
  });
});
<|endoftext|>


<commit_before>'use strict';
var path = require('path');
var childProcess = require('child_process');
var objectAssign = require('object-assign');

module.exports = function (target, opts, cb) {
	if (typeof target !== 'string') {
		throw new Error('Expected a `target`');
	}

	if (typeof opts === 'function') {
		cb = opts;
		opts = null;
	}

	opts = objectAssign({wait: true}, opts);

	var cmd;
	var appArgs;
	var args = [];
	var cpOpts = {};

	if (Array.isArray(opts.app)) {
		appArgs = opts.app.slice(1);
		opts.app = opts.app[0];
	}

	if (process.platform === 'darwin') {
		cmd = 'open';

		if (cb && opts.wait) {
			args.push('-W');
		}

		if (opts.app) {
			args.push('-a', opts.app);
		}

		if (appArgs) {
			args.push('--args');
			args = args.concat(appArgs);
		}
	} else if (process.platform === 'win32') {
		cmd = 'cmd';
		args.push('/c', 'start');
		target = target.replace(/&/g, '^&');

		if (cb && opts.wait) {
			args.push('/wait');
		}

		if (opts.app) {
			args.push(opts.app);
		}

		if (appArgs) {
			args = args.concat(appArgs);
		}
	} else {
		if (opts.app) {
			cmd = opts.app;
		} else {
			cmd = path.join(__dirname, 'xdg-open');
		}

		if (appArgs) {
			args = args.concat(appArgs);
		}

		if (!(cb && opts.wait)) {
			// xdg-open will block the process unless
			// stdio is ignored even if it's unref'd
			cpOpts.stdio = 'ignore';
		}
	}

	args.push(target);

	var cp = childProcess.spawn(cmd, args, cpOpts);

	if (cb) {
		cp.once('error', cb);

		cp.once('close', function (code) {
			if (code > 0) {
				cb(new Error('Exited with code ' + code));
				return;
			}

			cb();
		});
	} else {
		cp.unref();
	}

	return cp;
};
<commit_msg>correctly check if there's any `appArgs`<commit_after>'use strict';
var path = require('path');
var childProcess = require('child_process');
var objectAssign = require('object-assign');

module.exports = function (target, opts, cb) {
	if (typeof target !== 'string') {
		throw new Error('Expected a `target`');
	}

	if (typeof opts === 'function') {
		cb = opts;
		opts = null;
	}

	opts = objectAssign({wait: true}, opts);

	var cmd;
	var appArgs = [];
	var args = [];
	var cpOpts = {};

	if (Array.isArray(opts.app)) {
		appArgs = opts.app.slice(1);
		opts.app = opts.app[0];
	}

	if (process.platform === 'darwin') {
		cmd = 'open';

		if (cb && opts.wait) {
			args.push('-W');
		}

		if (opts.app) {
			args.push('-a', opts.app);
		}

		if (appArgs.length > 0) {
			args.push('--args');
			args = args.concat(appArgs);
		}
	} else if (process.platform === 'win32') {
		cmd = 'cmd';
		args.push('/c', 'start');
		target = target.replace(/&/g, '^&');

		if (cb && opts.wait) {
			args.push('/wait');
		}

		if (opts.app) {
			args.push(opts.app);
		}

		if (appArgs.length > 0) {
			args = args.concat(appArgs);
		}
	} else {
		if (opts.app) {
			cmd = opts.app;
		} else {
			cmd = path.join(__dirname, 'xdg-open');
		}

		if (appArgs.length > 0) {
			args = args.concat(appArgs);
		}

		if (!(cb && opts.wait)) {
			// xdg-open will block the process unless
			// stdio is ignored even if it's unref'd
			cpOpts.stdio = 'ignore';
		}
	}

	args.push(target);

	var cp = childProcess.spawn(cmd, args, cpOpts);

	if (cb) {
		cp.once('error', cb);

		cp.once('close', function (code) {
			if (code > 0) {
				cb(new Error('Exited with code ' + code));
				return;
			}

			cb();
		});
	} else {
		cp.unref();
	}

	return cp;
};
<|endoftext|>


<commit_before>'use strict';
/* global window */
var debounce = require('lodash/debounce');
var assign = require('lodash/assign');

function LaserCarousel(el, opts) {
    var self = this;

    self.el = el.children[0];

    self.opts = {
        itemWidth: '100px',
        namespace: '',
        initialSlide: 0,
        itemNavigation: true,
        currentItemSpacing: 1,
        touch: true,
        speed: 300,
        dots: true
    };

    assign(self.opts, opts);

    self.currentItemIdx = self.opts.initialSlide;

    self.items = [];
    self.storeItems();
    self.itemCount = self.items.length;

    self.currentX = 0;
    self.trackWidth = 0;
    self.dragging = false;

    self.settings = {};
    self.initialised = false;

    self.initialize();
}

LaserCarousel.prototype = {
    swipe: require('./swipe'),

    storeItems: function() {
        var self = this,
            items = self.el.getElementsByClassName(self.opts.namespace + 'carousel__item'),
            i = items.length - 1;

        for (i; i >= 0; i--) {
            self.items[i] = {};
            self.items[i].el = items[i].cloneNode(true);
            self.el.removeChild(items[i]);
        }
    },

    applyTrackTransition: function() {
        var self = this;
        self.track.style.transitionProperty = 'transform';
        self.track.style.transitionDuration = self.opts.speed + 'ms';
    },

    panToCurrent: function() {
        var self = this,
            idx = self.currentItemIdx,
            itemWidth = self.el.offsetWidth;

        self.currentX = -idx * itemWidth;
        self.track.style.transform = 'translate3d(' + self.currentX + 'px, 0 ,0)';
    },

    addTrack: function() {
        var self = this,
            i,
            items = self.items;

        self.track = document.createElement('div');
        self.track.classList.add(self.opts.namespace + 'lasercarousel__track');
        self.el.insertBefore(self.track, self.el.firstChild);

        for (i = 0; i < self.items.length; i++) {
            self.track.appendChild(self.items[i].el);
        }
    },

    setTrackWidth: function() {
        var self = this;
        var itemWidth = self.el.offsetWidth;
        itemWidth = parseInt(itemWidth);

        self.trackWidth = itemWidth * self.items.length;
        self.track.style.width = self.trackWidth + 'px';
    },

    addDots: function() {
        var self = this,
            html = '';

        self.carouselNavigation = document.createElement('ul');
        self.carouselNavigation.classList.add(self.opts.namespace + 'carousel__navigation');
        self.el.appendChild(self.carouselNavigation);

        for (var i = 0; i < self.items.length; i++) {
            html += '
' + (i + 1) + '
\n';
        }

        self.carouselNavigation.innerHTML = html;
    },

    setCurrent: function(idx) {
        var self = this,
            items,
            current;

        if (self.currentItem) {
            self.currentItem.classList.remove(self.opts.namespace + 'carousel__item--current');
        }

        self.currentItem = self.items[idx].el;

        if (self.currentItem) {
            self.currentItemIdx = idx;
            self.currentItem.classList.add(self.opts.namespace + 'carousel__item--current');
        }

        if (self.carouselNavigation) {
            current = self.carouselNavigation.getElementsByClassName(self.opts.namespace + 'carousel__navigation-item--current')[0];

            if (current) {
                current.classList.remove(self.opts.namespace + 'carousel__navigation-item--current');
            }

            items = self.carouselNavigation.getElementsByClassName(self.opts.namespace + 'carousel__navigation-item');

            if (items[idx]) {
                items[idx].classList.add(self.opts.namespace + 'carousel__navigation-item--current');
            }
        }
    },

    positionItems: function() {
        var self = this;
        var idx = 0;
        var current;
        var isCurrent = false;

        for (var i = 0; i < self.items.length; i++) {
            current = self.items[i].el;
            isCurrent = false;

            if (self.currentItem && current === self.currentItem) {
                isCurrent = true;
                idx = idx + self.opts.currentItemSpacing;
            }

            current.style.width = self.el.offsetWidth + 'px';
            current.style.transform = 'translate3d(' + (i * 100) + '%, 0%, 0)';
            current.style.display = 'block';
        }
    },

    goto: function(idx) {
        var self = this;
        self.setCurrent(idx);
        self.positionItems();
        self.panToCurrent();
    },

    next: function() {
        var self = this;

        if (self.currentItemIdx + 1 <= self.itemCount - 1 ) {
            self.goto(self.currentItemIdx + 1);
        } else {
            self.goto(self.currentItemIdx);
        }
    },

    previous: function() {
        var self = this;

        if (self.currentItemIdx - 1 >= 0) {
            self.goto(self.currentItemIdx - 1);
        } else {
            self.goto(self.currentItemIdx);
        }
    },

    attachNavigationHandler: function() {
        var self = this;
        var items = self.el.getElementsByClassName(self.opts.namespace + 'carousel__navigation-item');

        var attachClickHandler = function(el, idx) {
            el.addEventListener('click', function(e) {
                if (!self.dragging) {
                    self.goto(idx);
                }

                e.preventDefault();
            });
        };

        for (var i = 0; i < items.length; i++) {
            attachClickHandler(items[i], i);
        }
    },

    settingsFromBreakpoint: function(breakpoint) {
        var self = this;

        self.settings.itemWidth = breakpoint.itemWidth || self.opts.itemWidth;
        self.settings.initialSlide = breakpoint.initialSlide || self.opts.initialSlide;
        self.settings.currentItemSpacing = breakpoint.currentItemSpacing || self.opts.currentItemSpacing;
        self.settings.speed = breakpoint.speed || self.opts.speed;
    },

    settingsByScreenSize: function() {
        var self = this,
            wWidth = window.offsetWidth,
            breakpointToUse = false;

        // Reset to defaults.
        self.settings.itemWidth = self.opts.itemWidth;
        self.settings.initialSlide = self.opts.initialSlide;
        self.settings.currentItemSpacing = self.opts.currentItemSpacing;
        self.settings.speed = self.opts.speed;

        if (self.opts.responsive) {
            for (var key in self.opts.responsive) {
                if (wWidth > key) {
                    breakpointToUse = key;
                }
            }
        }

        if (breakpointToUse) {
            self.settingsFromBreakpoint(self.opts.responsive[breakpointToUse]);
        }
    },

    start: function() {
        var self = this;

        self.setTrackWidth();
        self.setCurrent(self.currentItemIdx);
        self.positionItems();

        self.panToCurrent();
        self.applyTrackTransition();
    },

    initialize: function() {
        var self = this;

        self.addTrack();

        window.addEventListener('resize', debounce(self.start.bind(self), 300));

        if (self.opts.dots) {
            self.addDots();
        }

        if (self.opts.touch) {
            self.swipe();
        }

        self.start();

        self.attachNavigationHandler();
    }
};

if (typeof module !== 'undefined' && typeof module.exports !== 'undefined') {
    module.exports = LaserCarousel;
} else {
    window.LaserCarousel = LaserCarousel;
}
<commit_msg>removed laser from track class<commit_after>'use strict';
/* global window */
var debounce = require('lodash/debounce');
var assign = require('lodash/assign');

function LaserCarousel(el, opts) {
    var self = this;

    self.el = el.children[0];

    self.opts = {
        itemWidth: '100px',
        namespace: '',
        initialSlide: 0,
        itemNavigation: true,
        currentItemSpacing: 1,
        touch: true,
        speed: 300,
        dots: true
    };

    assign(self.opts, opts);

    self.currentItemIdx = self.opts.initialSlide;

    self.items = [];
    self.storeItems();
    self.itemCount = self.items.length;

    self.currentX = 0;
    self.trackWidth = 0;
    self.dragging = false;

    self.settings = {};
    self.initialised = false;

    self.initialize();
}

LaserCarousel.prototype = {
    swipe: require('./swipe'),

    storeItems: function() {
        var self = this,
            items = self.el.getElementsByClassName(self.opts.namespace + 'carousel__item'),
            i = items.length - 1;

        for (i; i >= 0; i--) {
            self.items[i] = {};
            self.items[i].el = items[i].cloneNode(true);
            self.el.removeChild(items[i]);
        }
    },

    applyTrackTransition: function() {
        var self = this;
        self.track.style.transitionProperty = 'transform';
        self.track.style.transitionDuration = self.opts.speed + 'ms';
    },

    panToCurrent: function() {
        var self = this,
            idx = self.currentItemIdx,
            itemWidth = self.el.offsetWidth;

        self.currentX = -idx * itemWidth;
        self.track.style.transform = 'translate3d(' + self.currentX + 'px, 0 ,0)';
    },

    addTrack: function() {
        var self = this,
            i,
            items = self.items;

        self.track = document.createElement('div');
        self.track.classList.add(self.opts.namespace + 'carousel__track');
        self.el.insertBefore(self.track, self.el.firstChild);

        for (i = 0; i < self.items.length; i++) {
            self.track.appendChild(self.items[i].el);
        }
    },

    setTrackWidth: function() {
        var self = this;
        var itemWidth = self.el.offsetWidth;
        itemWidth = parseInt(itemWidth);

        self.trackWidth = itemWidth * self.items.length;
        self.track.style.width = self.trackWidth + 'px';
    },

    addDots: function() {
        var self = this,
            html = '';

        self.carouselNavigation = document.createElement('ul');
        self.carouselNavigation.classList.add(self.opts.namespace + 'carousel__navigation');
        self.el.appendChild(self.carouselNavigation);

        for (var i = 0; i < self.items.length; i++) {
            html += '
' + (i + 1) + '
\n';
        }

        self.carouselNavigation.innerHTML = html;
    },

    setCurrent: function(idx) {
        var self = this,
            items,
            current;

        if (self.currentItem) {
            self.currentItem.classList.remove(self.opts.namespace + 'carousel__item--current');
        }

        self.currentItem = self.items[idx].el;

        if (self.currentItem) {
            self.currentItemIdx = idx;
            self.currentItem.classList.add(self.opts.namespace + 'carousel__item--current');
        }

        if (self.carouselNavigation) {
            current = self.carouselNavigation.getElementsByClassName(self.opts.namespace + 'carousel__navigation-item--current')[0];

            if (current) {
                current.classList.remove(self.opts.namespace + 'carousel__navigation-item--current');
            }

            items = self.carouselNavigation.getElementsByClassName(self.opts.namespace + 'carousel__navigation-item');

            if (items[idx]) {
                items[idx].classList.add(self.opts.namespace + 'carousel__navigation-item--current');
            }
        }
    },

    positionItems: function() {
        var self = this;
        var idx = 0;
        var current;
        var isCurrent = false;

        for (var i = 0; i < self.items.length; i++) {
            current = self.items[i].el;
            isCurrent = false;

            if (self.currentItem && current === self.currentItem) {
                isCurrent = true;
                idx = idx + self.opts.currentItemSpacing;
            }

            current.style.width = self.el.offsetWidth + 'px';
            current.style.transform = 'translate3d(' + (i * 100) + '%, 0%, 0)';
            current.style.display = 'block';
        }
    },

    goto: function(idx) {
        var self = this;
        self.setCurrent(idx);
        self.positionItems();
        self.panToCurrent();
    },

    next: function() {
        var self = this;

        if (self.currentItemIdx + 1 <= self.itemCount - 1 ) {
            self.goto(self.currentItemIdx + 1);
        } else {
            self.goto(self.currentItemIdx);
        }
    },

    previous: function() {
        var self = this;

        if (self.currentItemIdx - 1 >= 0) {
            self.goto(self.currentItemIdx - 1);
        } else {
            self.goto(self.currentItemIdx);
        }
    },

    attachNavigationHandler: function() {
        var self = this;
        var items = self.el.getElementsByClassName(self.opts.namespace + 'carousel__navigation-item');

        var attachClickHandler = function(el, idx) {
            el.addEventListener('click', function(e) {
                if (!self.dragging) {
                    self.goto(idx);
                }

                e.preventDefault();
            });
        };

        for (var i = 0; i < items.length; i++) {
            attachClickHandler(items[i], i);
        }
    },

    settingsFromBreakpoint: function(breakpoint) {
        var self = this;

        self.settings.itemWidth = breakpoint.itemWidth || self.opts.itemWidth;
        self.settings.initialSlide = breakpoint.initialSlide || self.opts.initialSlide;
        self.settings.currentItemSpacing = breakpoint.currentItemSpacing || self.opts.currentItemSpacing;
        self.settings.speed = breakpoint.speed || self.opts.speed;
    },

    settingsByScreenSize: function() {
        var self = this,
            wWidth = window.offsetWidth,
            breakpointToUse = false;

        // Reset to defaults.
        self.settings.itemWidth = self.opts.itemWidth;
        self.settings.initialSlide = self.opts.initialSlide;
        self.settings.currentItemSpacing = self.opts.currentItemSpacing;
        self.settings.speed = self.opts.speed;

        if (self.opts.responsive) {
            for (var key in self.opts.responsive) {
                if (wWidth > key) {
                    breakpointToUse = key;
                }
            }
        }

        if (breakpointToUse) {
            self.settingsFromBreakpoint(self.opts.responsive[breakpointToUse]);
        }
    },

    start: function() {
        var self = this;

        self.setTrackWidth();
        self.setCurrent(self.currentItemIdx);
        self.positionItems();

        self.panToCurrent();
        self.applyTrackTransition();
    },

    initialize: function() {
        var self = this;

        self.addTrack();

        window.addEventListener('resize', debounce(self.start.bind(self), 300));

        if (self.opts.dots) {
            self.addDots();
        }

        if (self.opts.touch) {
            self.swipe();
        }

        self.start();

        self.attachNavigationHandler();
    }
};

if (typeof module !== 'undefined' && typeof module.exports !== 'undefined') {
    module.exports = LaserCarousel;
} else {
    window.LaserCarousel = LaserCarousel;
}
<|endoftext|>


<commit_before>/* jshint node: true */
/* global require */
'use strict';

var mergeTrees = require('broccoli-merge-trees');
var Funnel = require('broccoli-funnel');
var path = require('path');
var fs = require('fs');

var SustainConversion = require('./dsl/sustain-conversion');

function assert(statement, test) {
  if (!test) {
    throw new Error(statement);
  }
}

module.exports = {
  name: 'flexi',

  included: function(app, parentAddon) {
    this._super.included.apply(this, arguments);

    // Quick fix for add-on nesting
    // https://github.com/aexmachina/ember-cli-sass/blob/v5.3.0/index.js#L73-L75
    // see: https://github.com/ember-cli/ember-cli/issues/3718
    while (typeof app.import !== 'function' && (app.app || app.parent)) {
      app = app.app || app.parent;
    }

    // if app.import and parentAddon are blank, we're probably being consumed by an in-repo-addon
    // or engine, for which the "bust through" technique above does not work.
    if (typeof app.import !== 'function' && !parentAddon) {
      if (app.registry && app.registry.app) {
        app = app.registry.app;
      }
    }

    if (!parentAddon && typeof app.import !== 'function') {
      throw new Error('ember-font-awesome is being used within another addon or engine and is' +
        ' having trouble registering itself to the parent application.');
    }

    this.app = app;
    return app;
  },

  isDevelopingAddon: function() {
    return false;
  },

  _flexiConfig: null,
  flexiConfig: function() {
    if (!this._flexiConfig) {
      var configPath = path.join(this.project.root, 'config', 'flexi.js');

      if (fs.existsSync(configPath)) {
        this._flexiConfig = require(configPath);

        assert("config/flexi.js is defined, but could not be imported", this._flexiConfig);
        assert("config/flexi.js is defined, but did not contain property [array] breakpoints", this._flexiConfig.breakpoints instanceof Array);
        assert("config/flexi.js is defined, but did not contain property [number] columns", typeof this._flexiConfig.columns === 'number');

      } else {
        if (process.argv[2] !== 'install' && process.argv[3].indexOf('flexi') === -1) {
          throw new Error("You must define a config file for flexi at '" + configPath + "'");
        }
      }
    }
    return this._flexiConfig || {};
  },

  config: function() {
    var org = this._super.config.apply(this, arguments);

    org.flexi = this.flexiConfig();
    return org;
  },

  setupPreprocessorRegistry: function(type, registry) {
    registry.add('htmlbars-ast-plugin', {
      name: "flexi-sustain-conversion",
      plugin: SustainConversion,
      baseDir: function() { return __dirname; }
    });

  }

};
<commit_msg>Fix names<commit_after>/* jshint node: true */
/* global require */
'use strict';

var mergeTrees = require('broccoli-merge-trees');
var Funnel = require('broccoli-funnel');
var path = require('path');
var fs = require('fs');

var SustainConversion = require('./dsl/sustain-conversion');

function assert(statement, test) {
  if (!test) {
    throw new Error(statement);
  }
}

module.exports = {
  name: 'flexi-sustain',

  included: function(app, parentAddon) {
    this._super.included.apply(this, arguments);

    // Quick fix for add-on nesting
    // https://github.com/aexmachina/ember-cli-sass/blob/v5.3.0/index.js#L73-L75
    // see: https://github.com/ember-cli/ember-cli/issues/3718
    while (typeof app.import !== 'function' && (app.app || app.parent)) {
      app = app.app || app.parent;
    }

    // if app.import and parentAddon are blank, we're probably being consumed by an in-repo-addon
    // or engine, for which the "bust through" technique above does not work.
    if (typeof app.import !== 'function' && !parentAddon) {
      if (app.registry && app.registry.app) {
        app = app.registry.app;
      }
    }

    if (!parentAddon && typeof app.import !== 'function') {
      throw new Error('flexi-sustain is being used within another addon or engine and is' +
        ' having trouble registering itself to the parent application.');
    }

    this.app = app;
    return app;
  },

  isDevelopingAddon: function() {
    return false;
  },

  _flexiConfig: null,
  flexiConfig: function() {
    if (!this._flexiConfig) {
      var configPath = path.join(this.project.root, 'config', 'flexi.js');

      if (fs.existsSync(configPath)) {
        this._flexiConfig = require(configPath);

        assert("config/flexi.js is defined, but could not be imported", this._flexiConfig);
        assert("config/flexi.js is defined, but did not contain property [array] breakpoints", this._flexiConfig.breakpoints instanceof Array);
        assert("config/flexi.js is defined, but did not contain property [number] columns", typeof this._flexiConfig.columns === 'number');

      } else {
        if (process.argv[2] !== 'install' && process.argv[3].indexOf('flexi') === -1) {
          throw new Error("You must define a config file for flexi at '" + configPath + "'");
        }
      }
    }
    return this._flexiConfig || {};
  },

  config: function() {
    var org = this._super.config.apply(this, arguments);

    org.flexi = this.flexiConfig();
    return org;
  },

  setupPreprocessorRegistry: function(type, registry) {
    registry.add('htmlbars-ast-plugin', {
      name: "flexi-sustain-conversion",
      plugin: SustainConversion,
      baseDir: function() { return __dirname; }
    });

  }

};
<|endoftext|>


<commit_before>const localtunnel = require('localtunnel')
const _ = require('lodash')

class ServerlessLocaltunnel {
  constructor (serverless, options) {
    this.serverless = serverless
    this.options = options
    this.hooks = {
      'before:offline:start:init': this.runServer.bind(this)
    }
  }
  runServer() {
    this.serverless.cli.log('Localtunnel running server')
    let serverRestarted = false
    let tunnel
    const errorHandler = (e) => {
      this.serverless.cli.log('Localtunnel error - restarting in 15 seconds')
      console.log(e)
      if(serverRestarted) return
      serverRestarted = true
      tunnel.close()
      setTimeout(this.runServer.bind(this), 15000)
    }
    try {
      tunnel = localtunnel(_.get(this.serverless, 'service.custom.localtunnel.port', 8080), {subdomain: _.get(this.serverless, 'service.custom.localtunnel.subdomain')}, (err, tunnel) => {
        if (err) {
          this.serverless.cli.log('Localtunnel error')
        }else{
          this.serverless.cli.log(`Localtunnel.me started: ${tunnel.url}`)
        }
      })
      tunnel.on('close', () => {
        this.serverless.cli.log('Localtunnel closed')
      })
      tunnel.on('error', errorHandler)
    } catch (e) {
      errorHandler(e)
    }
  }
}

module.exports = ServerlessLocaltunnel;<commit_msg>error handling<commit_after>const localtunnel = require('localtunnel')
const _ = require('lodash')

class ServerlessLocaltunnel {
  constructor (serverless, options) {
    this.serverless = serverless
    this.options = options
    this.hooks = {
      'before:offline:start:init': this.runServer.bind(this)
    }
  }
  runServer() {
    this.serverless.cli.log('Localtunnel running server')
    let serverRestarted = false
    let tunnel
    const errorHandler = (e) => {
      this.serverless.cli.log('Localtunnel error - restarting in 15 seconds')
      console.log(e)
      if(serverRestarted) return
      serverRestarted = true
      tunnel.close()
      setTimeout(this.runServer.bind(this), 15000)
    }
    try {
      tunnel = localtunnel(_.get(this.serverless, 'service.custom.localtunnel.port', 8080), {subdomain: _.get(this.serverless, 'service.custom.localtunnel.subdomain')}, (err, tunnel) => {
        if (err) {
          this.serverless.cli.log(`Localtunnel.me error: ${err.message}`)
        }else{
          this.serverless.cli.log(`Localtunnel.me started: ${tunnel.url}`)
        }
      })
      tunnel.on('close', () => {
        this.serverless.cli.log('Localtunnel closed')
      })
      tunnel.on('error', errorHandler)
    } catch (e) {
      errorHandler(e)
    }
  }
}

module.exports = ServerlessLocaltunnel;<|endoftext|>


<commit_before>'use strict';
var amqp = require('amqp10'),
    BrokerAgent = require('../lib/broker-agent'),
    config = require('./config'),
    expect = require('chai').expect;

var test = {};
describe('Broker', () => {
  before(() => {
    test.client = new amqp.Client();
    return test.client.connect(config.address)
      .then(() => {
        test.agent = new BrokerAgent(test.client);
        return test.agent.initialize();
      });
  });

  it('should support an echo command', () => {
    return test.agent.getAllBrokers()
      .then((brokers) => brokers.map(broker => broker.echo({ sequence: 0, body: 'test' })))
      .map(response => {
        expect(response).to.eql({ sequence: 0, body: 'test' });
      });
  });
});
<commit_msg>test(broker): fix test to use 0.12 compatible syntax<commit_after>'use strict';
var amqp = require('amqp10'),
    BrokerAgent = require('../lib/broker-agent'),
    config = require('./config'),
    expect = require('chai').expect;

var test = {};
describe('Broker', function() {
  before(function() {
    test.client = new amqp.Client();
    return test.client.connect(config.address)
      .then(function() {
        test.agent = new BrokerAgent(test.client);
        return test.agent.initialize();
      });
  });

  it('should support an echo command', function() {
    return test.agent.getAllBrokers()
      .map(function(broker) { return broker.echo({ sequence: 0, body: 'test' }); })
      .map(function(response) { expect(response).to.eql({ sequence: 0, body: 'test' }); });
  });
});
<|endoftext|>


<commit_before>/* jshint node: true */
'use strict';

var fs = require('fs');

module.exports = {
  name: 'ember-websockets',
  included: function(app) {
    this._super.included(app);

    var stats;
    var socketIOPath = app.bowerDirectory + '/socket.io-client/socket.io.js';

    app.import(app.bowerDirectory + '/uri.js/src/URI.min.js');

    try {
      stats = fs.lstatSync(socketIOPath);

      if(stats.isFile()) {
        app.import(socketIOPath);
      }
    }
    catch(e) {
      throw new Error('Error reading socket.io file. Please run `ember g socket-io` first');
    }
  }
};
<commit_msg>Removing throw if socket.io is not found<commit_after>/* jshint node: true */
'use strict';

var fs = require('fs');

module.exports = {
  name: 'ember-websockets',
  included: function(app) {
    this._super.included(app);

    var stats;
    var socketIOPath = app.bowerDirectory + '/socket.io-client/socket.io.js';

    app.import(app.bowerDirectory + '/uri.js/src/URI.min.js');

    /*
    * Only import the socket.io file if one is found
    */
    try {
      stats = fs.lstatSync(socketIOPath);

      if(stats.isFile()) {
        app.import(socketIOPath);
      }
    }
    catch(e) {}
  }
};
<|endoftext|>


<commit_before>/* global casper */

casper.on("page.error", function(msg, trace) {
  this.echo("Error:    " + msg, "ERROR");
  this.echo("file:     " + trace[0].file, "WARNING");
  this.echo("line:     " + trace[0].line, "WARNING");
  this.echo("function: " + trace[0].function, "WARNING");
});

casper.on("remote.message", function(msg) {
    this.echo("Console message: " + msg);
});

casper.test.begin("Box Tests", function(test) {

  casper
    .start("http://localhost:4000/test/browser/box.html", function(){

      test.assertElementCount("svg", 1, "Automatically added <svg> element to page.");
      test.assertElementCount("text", 1, "Created <text> container element.");
      test.assertElementCount("tspan", 2, "Created 2 <tspan> elements.");
      test.assertEval(function(){
        var tspans = document.body.getElementsByTagName("tspan");

        function getText(t) {
          return t.textContent || t.innerText;
        }

        return getText(tspans[0]) === "Hello D3plus, please wrap" &&
               getText(tspans[1]) === "this sentence for me.";
      }, "Wrapped text correctly.");

    })
    .run(function(){
      test.done();
    });
});
<commit_msg>another potential test fix<commit_after>/* global casper */

casper.on("page.error", function(msg, trace) {
  this.echo("Error:    " + msg, "ERROR");
  this.echo("file:     " + trace[0].file, "WARNING");
  this.echo("line:     " + trace[0].line, "WARNING");
  this.echo("function: " + trace[0].function, "WARNING");
});

casper.on("remote.message", function(msg) {
    this.echo("Console message: " + msg);
});

casper.test.begin("Box Tests", function(test) {

  casper
    .start("http://localhost:4000/test/browser/box.html", function(){

      test.assertElementCount("svg", 1, "Automatically added <svg> element to page.");
      test.assertElementCount("text", 1, "Created <text> container element.");
      test.assertElementCount("tspan", 2, "Created 2 <tspan> elements.");
      test.assertEval(function(){
        var tspans = this.document.getElementsByTagName("tspan");

        function getText(t) {
          return t.textContent || t.innerText;
        }

        return getText(tspans[0]) === "Hello D3plus, please wrap" &&
               getText(tspans[1]) === "this sentence for me.";
      }, "Wrapped text correctly.");

    })
    .run(function(){
      test.done();
    });
});
<|endoftext|>


<commit_before>'use strict';

const Promise = require('pinkie-promise');
const queryString = require('querystring');
const fetch = require('node-fetch');
const objectAssign = require('object-assign');
const nodeUrl = require('url');
const electron = require('electron');
const BrowserWindow = electron.BrowserWindow || electron.remote.BrowserWindow;

module.exports = function (config, windowParams) {
  function getAuthorizationCode(opts) {
    opts = opts || {};

    if (!config.redirectUri) {
      config.redirectUri = 'urn:ietf:wg:oauth:2.0:oob';
    }

    var urlParams = {
      response_type: 'code',
      redirect_uri: config.redirectUri,
      client_id: config.clientId
    };

    if (opts.scope) {
      urlParams.scope = opts.scope;
    }

    if (opts.accessType) {
      urlParams.access_type = opts.accessType;
    }

    var url = config.authorizationUrl + '?' + queryString.stringify(urlParams);

    return new Promise(function (resolve, reject) {
      const authWindow = new BrowserWindow(windowParams || {'use-content-size': true});

      authWindow.loadURL(url);
      authWindow.show();

      authWindow.on('closed', () => {
        reject(new Error('window was closed by user'));
      });

      function onCallback(url) {
        var url_parts = nodeUrl.parse(url, true);
        var query = url_parts.query;
        var code = query.code;
        var error = query.error;

        if (error !== undefined) {
          reject(error);
          authWindow.removeAllListeners('closed');
          setImmediate(function () {
            authWindow.close();
          });
        } else if (code) {
          resolve(code);
          authWindow.removeAllListeners('closed');
          setImmediate(function () {
            authWindow.close();
          });
        }
      }

      authWindow.webContents.on('will-navigate', (event, url) => {
        onCallback(url);
      });

      authWindow.webContents.on('did-get-redirect-request', (event, oldUrl, newUrl) => {
        onCallback(newUrl);
      });
    });
  }

  function tokenRequest(data) {
    const header = {
      'Accept': 'application/json',
      'Content-Type': 'application/x-www-form-urlencoded'
    };

    if (config.useBasicAuthorizationHeader) {
      header.Authorization = 'Basic ' + new Buffer(config.clientId + ':' + config.clientSecret).toString('base64');
    } else {
      objectAssign(data, {
        client_id: config.clientId,
        client_secret: config.clientSecret
      });
    }

    return fetch(config.tokenUrl, {
      method: 'POST',
      headers: header,
      body: queryString.stringify(data)
    }).then(res => {
      return res.json();
    });
  }

  function getAccessToken(opts) {
    return getAuthorizationCode(opts)
      .then(authorizationCode => {
        var tokenRequestData = {
          code: authorizationCode,
          grant_type: 'authorization_code',
          redirect_uri: config.redirectUri
        };
        tokenRequestData = Object.assign(tokenRequestData, opts.additionalTokenRequestData);
        return tokenRequest(tokenRequestData);
      });
  }

  function refreshToken(refreshToken) {
    return tokenRequest({
      refresh_token: refreshToken,
      grant_type: 'refresh_token',
      redirect_uri: config.redirectUri
    });
  }

  return {
    getAuthorizationCode: getAuthorizationCode,
    getAccessToken: getAccessToken,
    refreshToken: refreshToken
  };
};
<commit_msg>- Added state param.<commit_after>'use strict';

const Promise = require('pinkie-promise');
const queryString = require('querystring');
const fetch = require('node-fetch');
const objectAssign = require('object-assign');
const nodeUrl = require('url');
const electron = require('electron');
const BrowserWindow = electron.BrowserWindow || electron.remote.BrowserWindow;

var generateRandomString = function(length) {
    var text = '';
    var possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';

    for (var i = 0; i < length; i++) {
        text += possible.charAt(Math.floor(Math.random() * possible.length));
    }
    return text;
};

module.exports = function (config, windowParams) {
  function getAuthorizationCode(opts) {
    opts = opts || {};

    if (!config.redirectUri) {
      config.redirectUri = 'urn:ietf:wg:oauth:2.0:oob';
    }

    var urlParams = {
      response_type: 'code',
      redirect_uri: config.redirectUri,
      client_id: config.clientId,
      state: generateRandomString(16)
    };

    if (opts.scope) {
      urlParams.scope = opts.scope;
    }

    if (opts.accessType) {
      urlParams.access_type = opts.accessType;
    }

    var url = config.authorizationUrl + '?' + queryString.stringify(urlParams);

    return new Promise(function (resolve, reject) {
      const authWindow = new BrowserWindow(windowParams || {'use-content-size': true});

      authWindow.loadURL(url);
      authWindow.show();

      authWindow.on('closed', () => {
        reject(new Error('window was closed by user'));
      });

      function onCallback(url) {
        var url_parts = nodeUrl.parse(url, true);
        var query = url_parts.query;
        var code = query.code;
        var error = query.error;

        if (error !== undefined) {
          reject(error);
          authWindow.removeAllListeners('closed');
          setImmediate(function () {
            authWindow.close();
          });
        } else if (code) {
          resolve(code);
          authWindow.removeAllListeners('closed');
          setImmediate(function () {
            authWindow.close();
          });
        }
      }

      authWindow.webContents.on('will-navigate', (event, url) => {
        onCallback(url);
      });

      authWindow.webContents.on('did-get-redirect-request', (event, oldUrl, newUrl) => {
        onCallback(newUrl);
      });
    });
  }

  function tokenRequest(data) {
    const header = {
      'Accept': 'application/json',
      'Content-Type': 'application/x-www-form-urlencoded'
    };

    if (config.useBasicAuthorizationHeader) {
      header.Authorization = 'Basic ' + new Buffer(config.clientId + ':' + config.clientSecret).toString('base64');
    } else {
      objectAssign(data, {
        client_id: config.clientId,
        client_secret: config.clientSecret
      });
    }

    return fetch(config.tokenUrl, {
      method: 'POST',
      headers: header,
      body: queryString.stringify(data)
    }).then(res => {
      return res.json();
    });
  }

  function getAccessToken(opts) {
    return getAuthorizationCode(opts)
      .then(authorizationCode => {
        var tokenRequestData = {
          code: authorizationCode,
          grant_type: 'authorization_code',
          redirect_uri: config.redirectUri
        };
        tokenRequestData = Object.assign(tokenRequestData, opts.additionalTokenRequestData);
        return tokenRequest(tokenRequestData);
      });
  }

  function refreshToken(refreshToken) {
    return tokenRequest({
      refresh_token: refreshToken,
      grant_type: 'refresh_token',
      redirect_uri: config.redirectUri
    });
  }

  return {
    getAuthorizationCode: getAuthorizationCode,
    getAccessToken: getAccessToken,
    refreshToken: refreshToken
  };
};
<|endoftext|>


<commit_before>var Lab = require('lab');
var RiakPBC = require('../');

var lab = exports.lab = Lab.script();
var after = lab.after;
var before = lab.before;
var describe = lab.experiment;
var expect = Lab.expect;
var it = lab.test;

var client = RiakPBC.createClient();

var n_val;

describe('Bucket Types', function () {

    describe('(callbacks)', function () {

        it('can get a bucket type', function (done) {

            client.getBucketType({
                type: '_test_crdt_counter'
            }, function (err, reply) {

                expect(err).to.not.exist;
                expect(reply).to.be.an('object');
                expect(reply).to.have.property('props');
                expect(reply.props).to.be.an('object');
                expect(reply.props).to.have.property('datatype', 'counter');
                expect(reply.props).to.have.property('allow_mult', true);
                n_val = reply.props.n_val;
                done();
            });
        });

        it('can change a bucket type', function (done) {

            client.setBucketType({
                type: '_test_crdt_counter',
                props: {
                    n_val: n_val + 1
                }
            }, function (err) {

                expect(err).to.not.exist;
                client.getBucketType({
                    type: '_test_crdt_counter'
                }, function (err, reply) {

                    expect(err).to.not.exist;
                    expect(reply).to.be.an('object');
                    expect(reply).to.have.property('props');
                    expect(reply.props).to.be.an('object');
                    expect(reply.props).to.have.property('datatype', 'counter');
                    expect(reply.props).to.have.property('allow_mult', true);
                    expect(reply.props).to.have.property('n_val', n_val + 1);
                    done();
                });
            });
        });

        after(function (done) {

            client.setBucketType({
                type: '_test_crdt_counter',
                props: {
                    n_val: n_val
                }
            }, function (err) {

                expect(err).to.not.exist;
                done();
            });
        });
    });

    describe('(streams)', function () {

        it('can get a bucket type', function (done) {

            var type = client.getBucketType({
                type: '_test_crdt_counter'
            });

            type.on('data', function (reply) {

                expect(reply).to.be.an('object');
                expect(reply).to.have.property('props');
                expect(reply.props).to.be.an('object');
                expect(reply.props).to.have.property('datatype', 'counter');
                expect(reply.props).to.have.property('allow_mult', true);
                n_val = reply.props.n_val;
            });

            type.on('end', done);
        });

        it('can change a bucket type', function (done) {

            var type = client.setBucketType({
                type: '_test_crdt_counter',
                props: {
                    n_val: n_val + 1
                }
            });

            type.resume();
            type.on('end', function () {

                var type = client.getBucketType({
                    type: '_test_crdt_counter'
                });

                type.on('data', function (reply) {

                    expect(reply).to.be.an('object');
                    expect(reply).to.have.property('props');
                    expect(reply.props).to.be.an('object');
                    expect(reply.props).to.have.property('datatype', 'counter');
                    expect(reply.props).to.have.property('allow_mult', true);
                    expect(reply.props).to.have.property('n_val', n_val + 1);
                });

                type.on('end', done);
            });
        });

        after(function (done) {

            var type = client.setBucketType({
                type: '_test_crdt_counter',
                props: {
                    n_val: n_val
                }
            });

            type.resume();
            type.on('end', done);
        });
    });
});
<commit_msg>clean up bucket type tests<commit_after>var Lab = require('lab');
var RiakPBC = require('../');

var lab = exports.lab = Lab.script();
var after = lab.after;
var before = lab.before;
var describe = lab.experiment;
var expect = Lab.expect;
var it = lab.test;

var client = RiakPBC.createClient();

var n_val;

describe('Bucket Types', function () {

    describe('(callbacks)', function () {

        it('can get a bucket type', function (done) {

            client.getBucketType({
                type: '_test_crdt_counter'
            }, function (err, reply) {

                expect(err).to.not.exist;
                expect(reply).to.be.an('object');
                expect(reply).to.have.property('props').that.is.an('object');
                expect(reply.props).to.have.property('datatype', 'counter');
                expect(reply.props).to.have.property('allow_mult', true);
                n_val = reply.props.n_val;
                done();
            });
        });

        it('can change a bucket type', function (done) {

            client.setBucketType({
                type: '_test_crdt_counter',
                props: {
                    n_val: n_val + 1
                }
            }, function (err) {

                expect(err).to.not.exist;
                client.getBucketType({
                    type: '_test_crdt_counter'
                }, function (err, reply) {

                    expect(err).to.not.exist;
                    expect(reply).to.be.an('object');
                    expect(reply).to.have.property('props').that.is.an('object');
                    expect(reply.props).to.have.property('datatype', 'counter');
                    expect(reply.props).to.have.property('allow_mult', true);
                    expect(reply.props).to.have.property('n_val', n_val + 1);
                    done();
                });
            });
        });

        after(function (done) {

            client.setBucketType({
                type: '_test_crdt_counter',
                props: {
                    n_val: n_val
                }
            }, done);
        });
    });

    describe('(streams)', function () {

        it('can get a bucket type', function (done) {

            client.getBucketType({
                type: '_test_crdt_counter'
            }).on('error', function (err) {

                expect(err).to.not.exist;
            }).on('data', function (reply) {

                expect(reply).to.be.an('object');
                expect(reply).to.have.property('props').that.is.an('object');
                expect(reply.props).to.have.property('datatype', 'counter');
                expect(reply.props).to.have.property('allow_mult', true);
                n_val = reply.props.n_val;
            }).on('end', done);
        });

        it('can change a bucket type', function (done) {

            client.setBucketType({
                type: '_test_crdt_counter',
                props: {
                    n_val: n_val + 1
                }
            }).on('error', function (err) {

                expect(err).to.not.exist;
            }).on('end', function () {

                client.getBucketType({
                    type: '_test_crdt_counter'
                }).on('error', function (err) {

                    expect(err).to.not.exist;
                }).on('data', function (reply) {

                    expect(reply).to.be.an('object');
                    expect(reply).to.have.property('props').that.is.an('object');
                    expect(reply.props).to.have.property('datatype', 'counter');
                    expect(reply.props).to.have.property('allow_mult', true);
                    expect(reply.props).to.have.property('n_val', n_val + 1);
                }).on('end', done);
            }).resume();
        });

        after(function (done) {

            client.setBucketType({
                type: '_test_crdt_counter',
                props: {
                    n_val: n_val
                }
            }).on('end', done).resume();
        });
    });
});
<|endoftext|>


<commit_before>/**
 * Loads environment variables from .env file
 * check for the missing environment variables at start
 * throw exception if .env file doesnot exist
 * @returns env
 */
function readFromEnvFile() {
  try {
    const data = require('fs').readFileSync('.env', 'utf8')

    const env = {}
    data.split('\n').filter((v) => {
      return v !== ''
    }).filter((v) => {
      return v.indexOf('#') === -1
    }).forEach((v) => {
      const temp = v.split('=').map((str) => {
        return str.trim()
      })
      env[temp[0]] = temp[1]
    })
    return env
  } catch (err) {
    throw err
  }
}

// it only supports spilitting using comma
function splitMultipleValues(envObject) {
  try {
    const data = Object.keys(envObject)
    return data.reduce((p, v) => {
      p[v] = envObject[v]
      if (envObject[v].indexOf(',') !== -1) {
        p[v] = envObject[v].split(',')
      }
      return p
    }, {})
  } catch (err) {
    throw err
  }
}

module.exports = (() => {
  try {
    const temp = splitMultipleValues(readFromEnvFile())
    process.env = temp
    return temp
  } catch (err) {
    throw err
  }
})()<commit_msg>muliplte == in the same line allowed<commit_after>/**
 * Loads environment variables from .env file
 * check for the missing environment variables at start
 * throw exception if .env file doesnot exist
 * @returns env
 */
function readFromEnvFile() {
  try {
    const data = require('fs').readFileSync('.env', 'utf8')

    const env = {}
    data.split('\n').filter((v) => {
      return v !== ''
    }).filter((v) => {
      return v.indexOf('#') === -1
    }).forEach((v) => {
      const splitPosition = v.indexOf('=')
      if (splitPosition === -1) {
        return
      }
      // only first '=' will be splitted
      const key = v.slice(0, splitPosition).trim()
      const value = v.slice(splitPosition + 1).trim()
      env[key] = value
    })
    return env
  } catch (err) {
    throw err
  }
}

// it only supports spilitting using comma
function splitMultipleValues(envObject) {
  try {
    const data = Object.keys(envObject)
    return data.reduce((p, v) => {
      p[v] = envObject[v]
      if (envObject[v].indexOf(',') !== -1) {
        p[v] = envObject[v].split(',')
      }
      return p
    }, {})
  } catch (err) {
    throw err
  }
}

module.exports = (() => {
  try {
    const temp = splitMultipleValues(readFromEnvFile())
    process.env = temp
    return temp
  } catch (err) {
    throw err
  }
})()<|endoftext|>