<commit_before>
module.exports = {
    w3cmemes: {
        origin:         "W3CMemes"
    ,   name:           "W3CMemes"
    ,   description:    "The official news agency for the W3C community"
    }
,   w3cnews: {
        origin:         "W3C News"
    ,   name:           "W3C News"
    ,   description:    "The party line"
    }
,   "html-wg":  {
        origin:         "github"
    ,   name:           "HTML WG"
    ,   description:    "HTML Working Group work stream"
    ,   repository:     [
                            "w3c/html"
                        ,   "w3c/charter-html"
                        ,   "w3c/test-results"
                        ,   "w3c/dom"
                        ,   "w3c/aria-in-html"
                        ]
    }
,   wpt:  {
        origin:         "github"
    ,   name:           "WPT"
    ,   description:    "Web Platform Tests work stream"
    ,   repository:     [
                            "w3c/web-platform-tests"
                        ,   "w3c/wpt-runner"
                        ,   "w3c/test-results"
                        ,   "w3c/wpt-tools"
                        ,   "w3c/testharness.js"
                        ]
    }
,   "modern-tooling":   {
        origin:         "github"
    ,   name:           "Modern Tooling"
    ,   description:    "Work stream for the Modern Tooling project"
    ,   repository:     [
                            "w3c/echidna"
                        ,   "w3c/modern-tooling"
                        ,   "w3c/pheme"
                        ,   "w3c/midgard"
                        ,   "w3c/ash-nazg"
                        ,   "w3c/specberus"
                        ,   "w3c/respec"
                        ,   "w3c/respec-docs"
                        ,   "w3c/w3c-api"
                        ,   "w3c/developers"
                        ,   "w3c/third-party-resources-checker"
                        ,   "w3c/tr-design"
                        ]
    }
,   "html-future":   {
        origin:         "github"
    ,   name:           "Future of HTML"
    ,   description:    "Discussion on the future of HTML"
    ,   repository:     [
                            "w3c/charter-html"
                        ]
    }
,   "webrtc":   {
        origin:         "github"
    ,   name:           "WebRTC specs"
    ,   description:    "Github activity on WebRTC specs"
    ,   repository:     [
                            "w3c/webrtc-pc"
                        ,   "w3c/mediacapture-main"
                        ,   "w3c/mediacapture-record"
                        ,   "w3c/mediacapture-image"
                        ,   "w3c/mediacapture-depth"
                        ,   "w3c/mediacapture-fromelement"
                        ,   "w3c/mediacapture-output"
                        ,   "w3c/webrtc-stats"
                        ,   "w3c/webrtc-screen-share"
                        ,   "w3c/mediacapture-worker"
                        ,   "w3c/webrtc-charter"
                        ,   "w3c/webrtc-respec-ci"
                        ]
    }
,   "csvw":   {
        origin:         "github"
    ,   name:           "CSVW Specs"
    ,   description:    "Github activity on the CSV on the Web specs"
    ,   repository:     [
                            "w3c/csvw"
                        ]
    }
,   "dpub":   {
        origin:         "github"
    ,   name:           "DPUB documents"
    ,   description:    "Github activity around digital publishing"
    ,   repository:     [
                            "w3c/dpub",
                            "w3c/dpub-accessibility",
                            "w3c/dpub-annotation",
                            "w3c/dpub-content-and-markup",
                            "w3c/dpub-metadata",
                            "w3c/dpub-stem",
                            "w3c/dpub-validation",
                            "w3c/dpub-pwp",
                            "w3c/dpub-pwp-loc",
                            "w3c/dpub-pwp-arch",
                            "w3c/dpub-pwp-ucr"
                        ]
    }
,   "publ": {
        origin:      "github"
    ,   name:        "Publishing Working Group documents"
    ,   description: "Github activities around the Publishing on the Web WG specs"
    ,   repository:  [
                         "w3c/publ-wg",
                         "w3c/wpub",
                         "w3c/pwpub",
                         "w3c/epub4",
                         "w3c/dpub-aria-2.0",
                         "w3c/publ-a11y"
                     ]
    }
,   "poe": {
        origin:      "github"
    ,   name:        "POE Working Group documents"
    ,   description: "Github activity around the Permissions and Obligations Expression Working Group"
    ,   repository:  [
                         "w3c/poe"
                     ]
    }
,   "annotation":   {
        origin:         "github"
    ,   name:           "Web Annotations specs"
    ,   description:    "Github activity on Web Annotation specs"
    ,   repository:     [
                            "w3c/web-annotation",
                            "w3c/findtext"
                        ]
    }
,   "das":   {
        origin:         "github"
    ,   name:           "Device & Sensors specs"
    ,   description:    "Github activity on Device & Sensors Working Group specs"
    ,   repository:     [
                            "w3c/sensors"
                        ,   "w3c/ambient-light"
                        ,   "w3c/proximity"
                        ,   "w3c/vibration"
                        ,   "w3c/battery"
                        ,   "w3c/wake-lock"
                        ,   "w3c/html-media-capture"
                        ,   "w3c/devicesensors-wg"
                        ,   "w3c/gyroscope"
                        ,   "w3c/accelerometer"
                        ]
    }
};
<commit_msg>Add new WebRTC repos<commit_after>
module.exports = {
    w3cmemes: {
        origin:         "W3CMemes"
    ,   name:           "W3CMemes"
    ,   description:    "The official news agency for the W3C community"
    }
,   w3cnews: {
        origin:         "W3C News"
    ,   name:           "W3C News"
    ,   description:    "The party line"
    }
,   "html-wg":  {
        origin:         "github"
    ,   name:           "HTML WG"
    ,   description:    "HTML Working Group work stream"
    ,   repository:     [
                            "w3c/html"
                        ,   "w3c/charter-html"
                        ,   "w3c/test-results"
                        ,   "w3c/dom"
                        ,   "w3c/aria-in-html"
                        ]
    }
,   wpt:  {
        origin:         "github"
    ,   name:           "WPT"
    ,   description:    "Web Platform Tests work stream"
    ,   repository:     [
                            "w3c/web-platform-tests"
                        ,   "w3c/wpt-runner"
                        ,   "w3c/test-results"
                        ,   "w3c/wpt-tools"
                        ,   "w3c/testharness.js"
                        ]
    }
,   "modern-tooling":   {
        origin:         "github"
    ,   name:           "Modern Tooling"
    ,   description:    "Work stream for the Modern Tooling project"
    ,   repository:     [
                            "w3c/echidna"
                        ,   "w3c/modern-tooling"
                        ,   "w3c/pheme"
                        ,   "w3c/midgard"
                        ,   "w3c/ash-nazg"
                        ,   "w3c/specberus"
                        ,   "w3c/respec"
                        ,   "w3c/respec-docs"
                        ,   "w3c/w3c-api"
                        ,   "w3c/developers"
                        ,   "w3c/third-party-resources-checker"
                        ,   "w3c/tr-design"
                        ]
    }
,   "html-future":   {
        origin:         "github"
    ,   name:           "Future of HTML"
    ,   description:    "Discussion on the future of HTML"
    ,   repository:     [
                            "w3c/charter-html"
                        ]
    }
,   "webrtc":   {
        origin:         "github"
    ,   name:           "WebRTC specs"
    ,   description:    "Github activity on WebRTC specs"
    ,   repository:     [
                            "w3c/webrtc-pc"
                        ,   "w3c/webrtc-identity"
                        ,   "w3c/webrtc-quic"
                        ,   "w3c/webrtc-ice"
                        ,   "w3c/webrtc-dscp-exp"
                        ,   "w3c/webrtc-nv-use-cases"
                        ,   "w3c/mediacapture-main"
                        ,   "w3c/mediacapture-record"
                        ,   "w3c/mediacapture-image"
                        ,   "w3c/mediacapture-depth"
                        ,   "w3c/mediacapture-fromelement"
                        ,   "w3c/mediacapture-output"
                        ,   "w3c/webrtc-stats"
                        ,   "w3c/mediacapture-screen-share"
                        ,   "w3c/webrtc-charter"
                        ,   "w3c/webrtc-respec-ci"
                        ,   "w3c/mst-content-hint"
                        ]
    }
,   "csvw":   {
        origin:         "github"
    ,   name:           "CSVW Specs"
    ,   description:    "Github activity on the CSV on the Web specs"
    ,   repository:     [
                            "w3c/csvw"
                        ]
    }
,   "dpub":   {
        origin:         "github"
    ,   name:           "DPUB documents"
    ,   description:    "Github activity around digital publishing"
    ,   repository:     [
                            "w3c/dpub",
                            "w3c/dpub-accessibility",
                            "w3c/dpub-annotation",
                            "w3c/dpub-content-and-markup",
                            "w3c/dpub-metadata",
                            "w3c/dpub-stem",
                            "w3c/dpub-validation",
                            "w3c/dpub-pwp",
                            "w3c/dpub-pwp-loc",
                            "w3c/dpub-pwp-arch",
                            "w3c/dpub-pwp-ucr"
                        ]
    }
,   "publ": {
        origin:      "github"
    ,   name:        "Publishing Working Group documents"
    ,   description: "Github activities around the Publishing on the Web WG specs"
    ,   repository:  [
                         "w3c/publ-wg",
                         "w3c/wpub",
                         "w3c/pwpub",
                         "w3c/epub4",
                         "w3c/dpub-aria-2.0",
                         "w3c/publ-a11y"
                     ]
    }
,   "poe": {
        origin:      "github"
    ,   name:        "POE Working Group documents"
    ,   description: "Github activity around the Permissions and Obligations Expression Working Group"
    ,   repository:  [
                         "w3c/poe"
                     ]
    }
,   "annotation":   {
        origin:         "github"
    ,   name:           "Web Annotations specs"
    ,   description:    "Github activity on Web Annotation specs"
    ,   repository:     [
                            "w3c/web-annotation",
                            "w3c/findtext"
                        ]
    }
,   "das":   {
        origin:         "github"
    ,   name:           "Device & Sensors specs"
    ,   description:    "Github activity on Device & Sensors Working Group specs"
    ,   repository:     [
                            "w3c/sensors"
                        ,   "w3c/ambient-light"
                        ,   "w3c/proximity"
                        ,   "w3c/vibration"
                        ,   "w3c/battery"
                        ,   "w3c/wake-lock"
                        ,   "w3c/html-media-capture"
                        ,   "w3c/devicesensors-wg"
                        ,   "w3c/gyroscope"
                        ,   "w3c/accelerometer"
                        ]
    }
};
<|endoftext|>


<commit_before>'use strict';
const debug = require('debug')('brunch:write');
const sysPath = require('path');
const logger = require('loggy');

const deppack = require('deppack'); // getAllDependents
const formatError = require('../helpers').formatError;
const generate = require('./generate');

// For use in `.filter()`.
const changedSince = startTime => generated => {
  const g = generated;
  return g.allSourceFiles.some(f => f.compilationTime >= startTime || f.removed);
};

const formatWriteError = sourceFile => {
  return formatError(sourceFile.error, sourceFile.path);
};

const getPaths = (type, isHelper, path, sourceFileJoinConfig) => {
  const hlprs = sourceFileJoinConfig.pluginHelpers;
  return Object.keys(sourceFileJoinConfig)
  .filter(key => key !== 'pluginHelpers')
  .filter(generatedFilePath => {
    if (isHelper) {
      return hlprs.indexOf(generatedFilePath) >= 0;
    } else {
      const checker = sourceFileJoinConfig[generatedFilePath];
      return checker(path);
    }
  });
};

const filterTargetsForEntry = (files, type, entry) => {
  const targets = files.map(file => {
    return Object.keys(file.targets).filter(ttype => ttype+'s' === type).map(ttype => {
      const target = file.targets[ttype];
      if (file.error == null && target.data == null) return;
      const mainTarget = file.type === ttype;
      return {
        path: file.path,
        data: target.data,
        node: target.node,
        type: type,
        isHelper: file.isHelper,
        source: mainTarget ? file.source : target.data,
        file: file
      };
    })
  }).filter(targets => targets).reduce((allTargets, targets) => allTargets.concat(targets));

  if (entry === '*') return targets;
  const depPaths = deppack.getAllDependents(entry);
  return targets.filter(t => depPaths.indexOf(t.path) !== -1);
};

const getFiles = (fileList, config, joinConfig) => {
  const _targetMap = {};
  const _sourcesMap = {};

  Object.keys(joinConfig).forEach(type => {
    const entryPoints = joinConfig[type];

    Object.keys(entryPoints).map(entry => {
      const subCfg = entryPoints[entry];

      const targets = filterTargetsForEntry(fileList.files, type, entry);
      targets.forEach(target => {
        const paths = getPaths(target.type, target.isHelper, target.path, subCfg);
        paths.forEach(path => {
          if (_targetMap[path] == null) _targetMap[path] = [];
          if (_sourcesMap[path] == null) _sourcesMap[path] = [];
          _targetMap[path].push(target);
          _sourcesMap[path].push(target.file);
        });
      });
    });
  });

  return Object.keys(_targetMap).map(generatedFilePath => {
    const targets = _targetMap[generatedFilePath];
    const sourceFiles = _sourcesMap[generatedFilePath];
    const type = targets[0] && targets[0].type;
    const legacySourceFiles = !type ? [] : sourceFiles.filter(f => f.type === type);
    const fullPath = sysPath.join(config.paths['public'], generatedFilePath);
    return {
      allSourceFiles: sourceFiles,
      sourceFiles: legacySourceFiles,
      targets: targets,
      path: fullPath,
      type: type
    };
  });
};

const checkWritten = (fileList, files, startTime) => {
  const allWrittenTargets = {};
  files.map(file => {
    file.targets.forEach(target => {
      if (!allWrittenTargets[target.type]) allWrittenTargets[target.type] = [];
      allWrittenTargets[target.type].push(target.path);
    });
  });

  fileList.files.forEach(file => {
    if (file.error) logger.error(formatWriteError(file));
    if (file.compilationTime >= startTime) {
      Object.keys(file.targets).forEach(type => {
        const target = file.targets[type];
        if (allWrittenTargets[type+'s'].indexOf(file.path) === -1 && target.data) {
          logger.warn(`${file.path} compiled, but not written. ` +
            `Check your ${type}s.joinTo config`);
        }
      });
    }
  });
};

const write = (fileList, config, joinConfig, optimizers, startTime) => {
  const files = getFiles(fileList, config, joinConfig);
  checkWritten(fileList, files, startTime);
  const errors = files
    .map(generated => {
      return generated.sourceFiles
        .filter(f => f.error != null)
        .map(formatWriteError);
    })
    .reduce((a, b) => a.concat(b), []);

  if (errors.length > 0) return Promise.reject(errors.join(' ; '));

  const changed = files.filter(changedSince(startTime));
  debug(`Writing ${changed.length}/${files.length} files`);

  /* Remove files marked as such and dispose them, clean memory. */
  const disposed = {
    generated: [],
    sourcePaths: []
  };
  changed.forEach(generated => {
    const sourceFiles = generated.allSourceFiles;
    sourceFiles
      .filter(file => file.removed)
      .forEach(file => {
        disposed.generated.push(generated);
        disposed.sourcePaths.push(sysPath.basename(file.path));
        file.dispose();
        sourceFiles.splice(sourceFiles.indexOf(file), 1);
      });
  });

  const gen = file => {
    return generate(file.path, file.type, file.targets, config, optimizers);
  };

  return Promise.resolve(changed)
    .then(changedFiles => {
      return Promise.all(changedFiles.map(gen));
    })
    .then(() => {
      return Promise.resolve({
        changed: changed,
        disposed: disposed
      });
    });
};

module.exports = write;
<commit_msg>Work with fileList.files as a Map<commit_after>'use strict';
const debug = require('debug')('brunch:write');
const sysPath = require('path');
const logger = require('loggy');

const deppack = require('deppack'); // getAllDependents
const formatError = require('../helpers').formatError;
const generate = require('./generate');

// For use in `.filter()`.
const changedSince = startTime => generated => {
  const g = generated;
  return g.allSourceFiles.some(f => f.compilationTime >= startTime || f.removed);
};

const formatWriteError = sourceFile => {
  return formatError(sourceFile.error, sourceFile.path);
};

const getPaths = (type, isHelper, path, sourceFileJoinConfig) => {
  const hlprs = sourceFileJoinConfig.pluginHelpers;
  return Object.keys(sourceFileJoinConfig)
  .filter(key => key !== 'pluginHelpers')
  .filter(generatedFilePath => {
    if (isHelper) {
      return hlprs.indexOf(generatedFilePath) >= 0;
    } else {
      const checker = sourceFileJoinConfig[generatedFilePath];
      return checker(path);
    }
  });
};

const filterTargetsForEntry = (files, type, entry) => {
  const targets = files.map(file => {
    return Object.keys(file.targets).filter(ttype => ttype+'s' === type).map(ttype => {
      const target = file.targets[ttype];
      if (file.error == null && target.data == null) return;
      const mainTarget = file.type === ttype;
      return {
        path: file.path,
        data: target.data,
        node: target.node,
        type: type,
        isHelper: file.isHelper,
        source: mainTarget ? file.source : target.data,
        file: file
      };
    })
  }).filter(targets => targets).reduce((allTargets, targets) => allTargets.concat(targets));

  if (entry === '*') return targets;
  const depPaths = deppack.getAllDependents(entry);
  return targets.filter(t => depPaths.indexOf(t.path) !== -1);
};

const getFiles = (fileList, config, joinConfig) => {
  const _targetMap = {};
  const _sourcesMap = {};

  Object.keys(joinConfig).forEach(type => {
    const entryPoints = joinConfig[type];

    Object.keys(entryPoints).map(entry => {
      const subCfg = entryPoints[entry];

      const targets = filterTargetsForEntry(Array.from(fileList.files.values()), type, entry);
      targets.forEach(target => {
        const paths = getPaths(target.type, target.isHelper, target.path, subCfg);
        paths.forEach(path => {
          if (_targetMap[path] == null) _targetMap[path] = [];
          if (_sourcesMap[path] == null) _sourcesMap[path] = [];
          _targetMap[path].push(target);
          _sourcesMap[path].push(target.file);
        });
      });
    });
  });

  return Object.keys(_targetMap).map(generatedFilePath => {
    const targets = _targetMap[generatedFilePath];
    const sourceFiles = _sourcesMap[generatedFilePath];
    const type = targets[0] && targets[0].type;
    const legacySourceFiles = !type ? [] : sourceFiles.filter(f => f.type === type);
    const fullPath = sysPath.join(config.paths['public'], generatedFilePath);
    return {
      allSourceFiles: sourceFiles,
      sourceFiles: legacySourceFiles,
      targets: targets,
      path: fullPath,
      type: type
    };
  });
};

const checkWritten = (fileList, files, startTime) => {
  const allWrittenTargets = {};
  files.map(file => {
    file.targets.forEach(target => {
      if (!allWrittenTargets[target.type]) allWrittenTargets[target.type] = [];
      allWrittenTargets[target.type].push(target.path);
    });
  });

  fileList.files.forEach(file => {
    if (file.error) logger.error(formatWriteError(file));
    if (file.compilationTime >= startTime) {
      Object.keys(file.targets).forEach(type => {
        const target = file.targets[type];
        if (allWrittenTargets[type+'s'].indexOf(file.path) === -1 && target.data) {
          logger.warn(`${file.path} compiled, but not written. ` +
            `Check your ${type}s.joinTo config`);
        }
      });
    }
  });
};

const write = (fileList, config, joinConfig, optimizers, startTime) => {
  const files = getFiles(fileList, config, joinConfig);
  checkWritten(fileList, files, startTime);
  const errors = files
    .map(generated => {
      return generated.sourceFiles
        .filter(f => f.error != null)
        .map(formatWriteError);
    })
    .reduce((a, b) => a.concat(b), []);

  if (errors.length > 0) return Promise.reject(errors.join(' ; '));

  const changed = files.filter(changedSince(startTime));
  debug(`Writing ${changed.length}/${files.length} files`);

  /* Remove files marked as such and dispose them, clean memory. */
  const disposed = {
    generated: [],
    sourcePaths: []
  };
  changed.forEach(generated => {
    const sourceFiles = generated.allSourceFiles;
    sourceFiles
      .filter(file => file.removed)
      .forEach(file => {
        disposed.generated.push(generated);
        disposed.sourcePaths.push(sysPath.basename(file.path));
        file.dispose();
        sourceFiles.splice(sourceFiles.indexOf(file), 1);
      });
  });

  const gen = file => {
    return generate(file.path, file.type, file.targets, config, optimizers);
  };

  return Promise.resolve(changed)
    .then(changedFiles => {
      return Promise.all(changedFiles.map(gen));
    })
    .then(() => {
      return Promise.resolve({
        changed: changed,
        disposed: disposed
      });
    });
};

module.exports = write;
<|endoftext|>


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

'use strict';

var Promise = require('../util/promise').Promise;
var Status = require('./types').Status;
var Conversion = require('./types').Conversion;

exports.items = [
  {
    item: 'type',
    name: 'url',

    getSpec: function() {
      return 'url';
    },

    stringify: function(value, context) {
      if (value == null) {
        return '';
      }
      return value.href;
    },

    parse: function(arg, context) {
      var conversion;

      if (typeof URL === 'undefined') {
        return Promise.resolve(new Conversion(undefined, arg, Status.ERROR,
                                              'URL is not supported'));
      }

      try {
        var url = new URL(arg.text);
        conversion = new Conversion(url, arg);
      }
      catch (ex) {
        // Try to guess what the user is getting at. If there is a '.' before
        // the first '/' then assume it's a domain name, and prepend 'http://'
        // otherwise assume it's relative to the current URL (if that exists)
        var test;
        var firstDot = arg.text.indexOf('.');
        var firstSlash = arg.text.indexOf('/');
        if (firstDot !== -1) {
          if (firstSlash === -1 || (firstDot < firstSlash)) {
            test = new URL('http://' + arg.text);
          }
        }

        if (test == null && context.environment.window != null) {
          test = new URL(arg.text, context.environment.window.location.href);
        }

        var pred = (test == null) ? [] : [ { name: test.href, value: test } ];
        var status = (test == null) ? Status.ERROR : Status.INCOMPLETE;
        conversion = new Conversion(undefined, arg, status, ex.message, pred);
      }

      return Promise.resolve(conversion);
    }
  }
];
<commit_msg>union-1016578: Update url type to provide better predictions<commit_after>/*
 * Copyright 2012, Mozilla Foundation and contributors
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

'use strict';

var host = require('../util/host');
var Promise = require('../util/promise').Promise;
var Status = require('./types').Status;
var Conversion = require('./types').Conversion;

exports.items = [
  {
    item: 'type',
    name: 'url',

    getSpec: function() {
      return 'url';
    },

    stringify: function(value, context) {
      if (value == null) {
        return '';
      }
      return value.href;
    },

    parse: function(arg, context) {
      var conversion;

      try {
        var url = host.createUrl(arg.text);
        conversion = new Conversion(url, arg);
      }
      catch (ex) {
        var predictions = [];
        var status = Status.ERROR;

        // Maybe the URL was missing a scheme?
        if (arg.text.indexOf('://') === -1) {
          [ 'http', 'https' ].forEach(function(scheme) {
            try {
              var http = host.createUrl(scheme + '://' + arg.text);
              predictions.push({ name: http.href, value: http });
            }
            catch (ex) {
              // Ignore
            }
          }.bind(this));

          if (context.environment.window) {
            var base = context.environment.window.location.href;
            var localized = host.createUrl(arg.text, base);
            predictions.push({ name: localized.href, value: localized });
          }
        }

        if (predictions.length > 0) {
          status = Status.INCOMPLETE;
        }

        conversion = new Conversion(undefined, arg, status,
                                    ex.message, predictions);
      }

      return Promise.resolve(conversion);
    }
  }
];
<|endoftext|>


<commit_before>/*
 *    Glossy Producer - Generate valid syslog messages
 *
 *    Copyright Squeeks <privacymyass@gmail.com>.
 *    This is free software licensed under the MIT License -
 *    see the LICENSE file that should be included with this package.
 */

/*
 *    These values replace the integers in message that define the facility.
 */
var FacilityIndex = {
    'kern':   0,  // kernel messages
    'user':   1,  // user-level messages
    'mail':   2,  // mail system
    'daemon': 3,  // system daemons
    'auth':   4,  // security/authorization messages
    'syslog': 5,  // messages generated internally by syslogd
    'lpr':    6,  // line printer subsystem
    'news':   7,  // network news subsystem
    'uucp':   8,  // UUCP subsystem
    'clock':  9,  // clock daemon
    'sec':    10, // security/authorization messages
    'ftp':    11, // FTP daemon
    'ntp':    12, // NTP subsystem
    'audit':  13, // log audit
    'alert':  14, // log alert
//  'clock':  15, // clock daemon (note 2)
    'local0': 16, // local use 0  (local0)
    'local1': 17, // local use 1  (local1)
    'local2': 18, // local use 2  (local2)
    'local3': 19, // local use 3  (local3)
    'local4': 20, // local use 4  (local4)
    'local5': 21, // local use 5  (local5)
    'local6': 22, // local use 6  (local6)
    'local7': 23  // local use 7  (local7)
};

// Note 1 - Various operating systems have been found to utilize
//           Facilities 4, 10, 13 and 14 for security/authorization,
//           audit, and alert messages which seem to be similar.

// Note 2 - Various operating systems have been found to utilize
//           both Facilities 9 and 15 for clock (cron/at) messages.

/*
 *    These values replace the integers in message that define the severity.
 */
var SeverityIndex = {
    'emerg': 0,                 // Emergency: system is unusable
    'emergency': 0,

    'alert': 1,                 // Alert: action must be taken immediately

    'crit': 2,                  // Critical: critical conditions
    'critical': 2,

    'err': 3,                   // Error: error conditions
    'error': 3,

    'warn': 4,                  // Warning: warning conditions
    'warning': 4,

    'notice': 5,                // Notice: normal but significant condition

    'info': 6  ,                // Informational: informational messages
    'information': 6,
    'informational': 6,

    'debug':  7                 // Debug: debug-level messages
};

/*
 *    Defines the range matching BSD style months to integers.
 */
var BSDDateIndex = [
    'Jan',
    'Feb',
    'Mar',
    'Apr',
    'May',
    'Jun',
    'Jul',
    'Aug',
    'Sep',
    'Oct',
    'Nov',
    'Dec'
];

/*
 *  GlossyProducer class
 *  @param {Object} provides persistent details of all messages:
 *      facility: The facility index
 *      severity: Severity index
 *      host: Host address, either name or IP
 *      appName: Application/Process name
 *      pid: Process ID
 *      msgID: Message ID (RFC5424 only)
 *      type: RFC3164/RFC5424 message type
 *  @return {Object} GlossyProducer object
 */
var GlossyProducer = function(options) {
    if(options && typeof options =='object' && options.type) {
        this.type = options.type.match(/bsd|3164/i) ? "RFC3164" : "RFC5424";
    } else if(options && typeof options == 'string') {
        this.type = options.match(/bsd|3164/i) ? "RFC3164" : "RFC5424";
    } else {
        this.type = "RFC5424";
    }

    if(options && options.facility && FacilityIndex[options.facility]) {
        this.facility = options.facility;
    }
    if(options && options.pid && parseInt(options.pid, 10)) {
        this.pid = options.pid;
    }
    if(options && options.host)    this.host    = options.host.replace(/\s+/g, '');
    if(options && options.appName) this.appName = options.appName.replace(/\s+/g, '');
    if(options && options.msgID)   this.msgID   = options.msgID.replace(/\s+/g, '');

};

/*
 *  @param {Object} options object containing details of the message:
 *      facility: The facility index
 *      severity: Severity index
 *      host: Host address, either name or IP
 *      appName: Application ID
 *      pid: Process ID
 *      date: Timestamp to be applied, uses current GMT by default
 *      msgID: Message ID (RFC5424 only)
 *      structuredData: Object of structured data (RFC5424 only)
 *      message: The message to be sent
 *
 *  @param {Function} callback a callback run once the message is built
 *  @return {String} compiledMessage on completion, false on failure
 */
GlossyProducer.prototype.produce = function(options, callback) {
    if(options.time instanceof Date && !options.date) options.date = options.time;

    var msgData = [];
    if(!options.date instanceof Date) {
        options.date = new Date(Date());
    }

    if(!options.facility) options.facility = this.facility;

    if(this.type == 'RFC5424') {
        if (options.hasOwnProperty('prival') && options.prival >= 0 && options.prival <= 191) {
          var prival = '<' + options.prival + '>1';
        }
        else {
          var prival = calculatePrival({
            facility: options.facility,
            severity: options.severity,
            version:  1
          });
        }

        if (prival === false) return false;

        msgData.push(prival);
        msgData.push(generateDate(options.date));

        msgData.push(options.host    || this.host    || '-');
        msgData.push(options.appName || this.appName || '-');
        msgData.push(options.pid     || this.pid     || '-');
        msgData.push(options.msgID   || this.msgID   || '-');
        if(options.structuredData) {
            msgData.push(generateStructuredData(options.structuredData) || '-');
        } else {
            msgData.push('-');
        }

        if(!options.message) options.message = '-';

    } else {
        options.timestamp = generateBSDDate(options.date);
        msgData.push(
            calculatePrival({
                facility: options.facility,
                severity: options.severity
            }) + options.timestamp
        );

        msgData.push(options.host || this.host);
        msgData.push();
        if(options.appName || this.appName) {
            var app = options.appName || this.appName;
            var pid = options.pid     || this.pid;

            if(parseInt(pid, 10)) {
                msgData.push(app + '[' + pid + ']:');
            } else {
                msgData.push(app + ':');
            }
        }
    }

    var compiledMessage = msgData.filter(function (messageElement) {
        // Filter null/ undefined values
        return messageElement;
    }).map(function (messageElement) {
        // Trim messages to remove successive whitespace
        return messageElement.trim();
    }).join(' ');
    compiledMessage += ' ' + options.message || '';
    msgData.push(compiledMessage);

    if(callback) {
        return callback(compiledMessage);
    } else {
        return compiledMessage;
    }

};

/*
 *  @param {Object} options object containing details of the message with
 *      the severity as 'debug'
 *  @param {Function} callback a callback run once the message is built
 *  @return {String} compiledMessage on completion, false on failure
 */
GlossyProducer.prototype.debug = function(options, callback) {
    options.severity = 'debug';
    return this.produce(options, callback);
};

/*
 *  @param {Object} options object containing details of the message with
 *      the severity as 'info'
 *  @param {Function} callback a callback run once the message is built
 *  @return {String} compiledMessage on completion, false on failure
 */
GlossyProducer.prototype.info = function(options, callback) {
    options.severity = 'info';
    return this.produce(options, callback);
};

/*
 *  @param {Object} options object containing details of the message with
 *      the severity as 'notice'
 *  @param {Function} callback a callback run once the message is built
 *  @return {String} compiledMessage on completion, false on failure
 */
GlossyProducer.prototype.notice = function(options, callback) {
    options.severity = 'notice';
    return this.produce(options, callback);
};

/*
 *  @param {Object} options object containing details of the message with
 *      the severity as 'warn'
 *  @param {Function} callback a callback run once the message is built
 *  @return {String} compiledMessage on completion, false on failure
 */
GlossyProducer.prototype.warn = function(options, callback) {
    options.severity = 'warn';
    return this.produce(options, callback);
};

/*
 *  @param {Object} options object containing details of the message with
 *      the severity as 'crit'
 *  @param {Function} callback a callback run once the message is built
 *  @return {String} compiledMessage on completion, false on failure
 */
GlossyProducer.prototype.crit = function(options, callback) {
    options.severity = 'crit';
    return this.produce(options, callback);
};

/*
 *  @param {Object} options object containing details of the message with
 *      the severity as 'alert'
 *  @param {Function} callback a callback run once the message is built
 *  @return {String} compiledMessage on completion, false on failure
 */
GlossyProducer.prototype.alert = function(options, callback) {
    options.severity = 'alert';
    return this.produce(options, callback);
};

/*
 *  @param {Object} options object containing details of the message with
 *      the severity as 'emergency'
 *  @param {Function} callback a callback run once the message is built
 *  @return {String} compiledMessage on completion, false on failure
 */
GlossyProducer.prototype.emergency = function(options, callback) {
    options.severity = 'emergency';
    return this.produce(options, callback);
};

/*
 *  Prepend a zero to a number less than 10
 *  @param {Number} n
 *  @return {String}
 *
 *  Where's sprintf when you need it?
 */
function leadZero(n) {
    if(typeof n != 'number') return n;
    n = n < 10 ? '0' + n : n ;
    return n;
}

/*
 *  Get current date in RFC 3164 format. If no date is supplied, the default
 *  is the current time in GMT + 0.
 *  @param {Date} dateObject optional Date object
 *  @returns {String}
 *
 *  Features code taken from https://github.com/akaspin/ain
 */
function generateBSDDate(dateObject) {
    if(!(dateObject instanceof Date)) dateObject = new Date(Date());
    var hours   = leadZero(dateObject.getHours());
    var minutes = leadZero(dateObject.getMinutes());
    var seconds = leadZero(dateObject.getSeconds());
    var month   = dateObject.getMonth();
    var day     = dateObject.getDate();
    if(day < 10) (day = ' ' + day);
    return BSDDateIndex[month] + " " + day + " " + hours + ":" + minutes + ":" + seconds;
}

/*
 *  Generate date in RFC 3339 format. If no date is supplied, the default is
 *  the current time in GMT + 0.
 *  @param {Date} dateObject optional Date object
 *  @returns {String} formatted date
 */
function generateDate(dateObject) {
    if(!(dateObject instanceof Date)) dateObject = new Date(Date());

    // Calcutate the offset
    var timeOffset;
    var minutes = Math.abs(dateObject.getTimezoneOffset());
    var hours = 0;
    while(minutes >= 60) {
        hours++;
        minutes -= 60;
    }

    if(dateObject.getTimezoneOffset() < 0) {
        // Ahead of UTC
        timeOffset = '+' + leadZero(hours) + '' + ':' + leadZero(minutes);
    } else if(dateObject.getTimezoneOffset() > 0) {
        // Behind UTC
        timeOffset = '-' + leadZero(hours) + '' + ':' + leadZero(minutes);
    } else {
        // UTC
        timeOffset = 'Z';
    }

    // Date
    formattedDate = dateObject.getUTCFullYear()         + '-' +
    // N.B. Javascript Date objects return months of the year indexed from
    // zero, while the RFC 5424 syslog standard expects months indexed from
    // one.
    leadZero(dateObject.getUTCMonth() + 1)  + '-' +
    // N.B. Javascript Date objects return days of the month indexed from one
    // (unlike months of year), so this does not need any correction.
    leadZero(dateObject.getUTCDate())   + 'T' +
    // Time
    leadZero(dateObject.getUTCHours())         + ':' +
    leadZero(dateObject.getUTCMinutes())       + ':' +
    leadZero(dateObject.getUTCSeconds())       + '.' +
    leadZero(dateObject.getUTCMilliseconds())  +
    timeOffset;

    return formattedDate;

}

/*
 *  Calculate the PRIVAL for a given facility
 *  @param {Object} values Contains the three key arguments
 *      facility {Number}/{String} the Facility Index
 *      severity {Number}
 *      version  {Number} For RFC 5424 messages, this should be 1
 *
 *  @return {String}
 */
function calculatePrival(values) {

    var pri = {};
    // Facility
    if(typeof values.facility == 'string' && !values.facility.match(/^\d+$/)) {
        pri.facility = FacilityIndex[values.facility.toLowerCase()];
    } else if( parseInt(values.facility, 10) && parseInt(values.facility, 10) < 24) {
        pri.facility = parseInt(values.facility, 10);
    }

    //Severity
    if(typeof values.severity == 'string' && !values.severity.match(/^\d+$/)) {
        pri.severity = SeverityIndex[values.severity.toLowerCase()];
    } else if( parseInt(values.severity, 10) && parseInt(values.severity, 10) < 8) {
        pri.severity = parseInt(values.severity, 10);
    }

    if(!isNaN(pri.severity) && !isNaN(pri.facility)) {
        pri.prival = (pri.facility * 8) + pri.severity;
        pri.str = values.version ? '<' + pri.prival + '>' + values.version : '<' + pri.prival + '>';
        return pri.str;
    } else {
        return false;
    }

}

/*
 *  Serialise objects into the structured data segment
 *  @param {Object} struct The object to serialise
 *  @return {String} structuredData the serialised data
 */
function generateStructuredData(struct) {
    if(typeof struct != 'object') return false;

    var structuredData = '';

    for(var sdID in struct) {
        sdElement = struct[sdID];
        structuredData += '[' + sdID;
        for(var key in sdElement) {
            sdElement[key] = sdElement[key].toString().replace(/(\]|\\|")/g, '\\$1');
            structuredData += ' ' + key + '="' + sdElement[key] + '"';
        }
        structuredData += ']';

    }

    return structuredData;
}

if(typeof module == 'object') {
    module.exports = GlossyProducer;
}
<commit_msg>Added TODO note for produce/parse cleanup/consolidation at future date<commit_after>/*
 *    Glossy Producer - Generate valid syslog messages
 *
 *    Copyright Squeeks <privacymyass@gmail.com>.
 *    This is free software licensed under the MIT License -
 *    see the LICENSE file that should be included with this package.
 */

/*
 *    These values replace the integers in message that define the facility.
 */
var FacilityIndex = {
    'kern':   0,  // kernel messages
    'user':   1,  // user-level messages
    'mail':   2,  // mail system
    'daemon': 3,  // system daemons
    'auth':   4,  // security/authorization messages
    'syslog': 5,  // messages generated internally by syslogd
    'lpr':    6,  // line printer subsystem
    'news':   7,  // network news subsystem
    'uucp':   8,  // UUCP subsystem
    'clock':  9,  // clock daemon
    'sec':    10, // security/authorization messages
    'ftp':    11, // FTP daemon
    'ntp':    12, // NTP subsystem
    'audit':  13, // log audit
    'alert':  14, // log alert
//  'clock':  15, // clock daemon (note 2)
    'local0': 16, // local use 0  (local0)
    'local1': 17, // local use 1  (local1)
    'local2': 18, // local use 2  (local2)
    'local3': 19, // local use 3  (local3)
    'local4': 20, // local use 4  (local4)
    'local5': 21, // local use 5  (local5)
    'local6': 22, // local use 6  (local6)
    'local7': 23  // local use 7  (local7)
};

// Note 1 - Various operating systems have been found to utilize
//           Facilities 4, 10, 13 and 14 for security/authorization,
//           audit, and alert messages which seem to be similar.

// Note 2 - Various operating systems have been found to utilize
//           both Facilities 9 and 15 for clock (cron/at) messages.

/*
 *    These values replace the integers in message that define the severity.
 */
var SeverityIndex = {
    'emerg': 0,                 // Emergency: system is unusable
    'emergency': 0,

    'alert': 1,                 // Alert: action must be taken immediately

    'crit': 2,                  // Critical: critical conditions
    'critical': 2,

    'err': 3,                   // Error: error conditions
    'error': 3,

    'warn': 4,                  // Warning: warning conditions
    'warning': 4,

    'notice': 5,                // Notice: normal but significant condition

    'info': 6  ,                // Informational: informational messages
    'information': 6,
    'informational': 6,

    'debug':  7                 // Debug: debug-level messages
};

/*
 *    Defines the range matching BSD style months to integers.
 */
var BSDDateIndex = [
    'Jan',
    'Feb',
    'Mar',
    'Apr',
    'May',
    'Jun',
    'Jul',
    'Aug',
    'Sep',
    'Oct',
    'Nov',
    'Dec'
];

/*
 *  GlossyProducer class
 *  @param {Object} provides persistent details of all messages:
 *      facility: The facility index
 *      severity: Severity index
 *      host: Host address, either name or IP
 *      appName: Application/Process name
 *      pid: Process ID
 *      msgID: Message ID (RFC5424 only)
 *      type: RFC3164/RFC5424 message type
 *  @return {Object} GlossyProducer object
 */
var GlossyProducer = function(options) {
    if(options && typeof options =='object' && options.type) {
        this.type = options.type.match(/bsd|3164/i) ? "RFC3164" : "RFC5424";
    } else if(options && typeof options == 'string') {
        this.type = options.match(/bsd|3164/i) ? "RFC3164" : "RFC5424";
    } else {
        this.type = "RFC5424";
    }

    if(options && options.facility && FacilityIndex[options.facility]) {
        this.facility = options.facility;
    }
    if(options && options.pid && parseInt(options.pid, 10)) {
        this.pid = options.pid;
    }
    if(options && options.host)    this.host    = options.host.replace(/\s+/g, '');
    if(options && options.appName) this.appName = options.appName.replace(/\s+/g, '');
    if(options && options.msgID)   this.msgID   = options.msgID.replace(/\s+/g, '');

};

/*
 *  @param {Object} options object containing details of the message:
 *      facility: The facility index
 *      severity: Severity index
 *      host: Host address, either name or IP
 *      appName: Application ID
 *      pid: Process ID
 *      date: Timestamp to be applied, uses current GMT by default
 *      time: Optional Date() argument may be used in lieu of 'date' - allows parse() output to be used for produce args
 *      msgID: Message ID (RFC5424 only)
 *      structuredData: Object of structured data (RFC5424 only)
 *      message: The message to be sent
 *
 *  @param {Function} callback a callback run once the message is built
 *  @return {String} compiledMessage on completion, false on failure
 */
GlossyProducer.prototype.produce = function(options, callback) {
    // TODO: next breaking api change make key output from parse() consistent with produce input options
    if(options.time instanceof Date && !options.date) options.date = options.time;

    var msgData = [];
    if(!options.date instanceof Date) {
        options.date = new Date(Date());
    }

    if(!options.facility) options.facility = this.facility;

    if(this.type == 'RFC5424') {
        if (options.hasOwnProperty('prival') && options.prival >= 0 && options.prival <= 191) {
          var prival = '<' + options.prival + '>1';
        }
        else {
          var prival = calculatePrival({
            facility: options.facility,
            severity: options.severity,
            version:  1
          });
        }

        if (prival === false) return false;

        msgData.push(prival);
        msgData.push(generateDate(options.date));

        msgData.push(options.host    || this.host    || '-');
        msgData.push(options.appName || this.appName || '-');
        msgData.push(options.pid     || this.pid     || '-');
        msgData.push(options.msgID   || this.msgID   || '-');
        if(options.structuredData) {
            msgData.push(generateStructuredData(options.structuredData) || '-');
        } else {
            msgData.push('-');
        }

        if(!options.message) options.message = '-';

    } else {
        options.timestamp = generateBSDDate(options.date);
        msgData.push(
            calculatePrival({
                facility: options.facility,
                severity: options.severity
            }) + options.timestamp
        );

        msgData.push(options.host || this.host);
        msgData.push();
        if(options.appName || this.appName) {
            var app = options.appName || this.appName;
            var pid = options.pid     || this.pid;

            if(parseInt(pid, 10)) {
                msgData.push(app + '[' + pid + ']:');
            } else {
                msgData.push(app + ':');
            }
        }
    }

    var compiledMessage = msgData.filter(function (messageElement) {
        // Filter null/ undefined values
        return messageElement;
    }).map(function (messageElement) {
        // Trim messages to remove successive whitespace
        return messageElement.trim();
    }).join(' ');
    compiledMessage += ' ' + options.message || '';
    msgData.push(compiledMessage);

    if(callback) {
        return callback(compiledMessage);
    } else {
        return compiledMessage;
    }

};

/*
 *  @param {Object} options object containing details of the message with
 *      the severity as 'debug'
 *  @param {Function} callback a callback run once the message is built
 *  @return {String} compiledMessage on completion, false on failure
 */
GlossyProducer.prototype.debug = function(options, callback) {
    options.severity = 'debug';
    return this.produce(options, callback);
};

/*
 *  @param {Object} options object containing details of the message with
 *      the severity as 'info'
 *  @param {Function} callback a callback run once the message is built
 *  @return {String} compiledMessage on completion, false on failure
 */
GlossyProducer.prototype.info = function(options, callback) {
    options.severity = 'info';
    return this.produce(options, callback);
};

/*
 *  @param {Object} options object containing details of the message with
 *      the severity as 'notice'
 *  @param {Function} callback a callback run once the message is built
 *  @return {String} compiledMessage on completion, false on failure
 */
GlossyProducer.prototype.notice = function(options, callback) {
    options.severity = 'notice';
    return this.produce(options, callback);
};

/*
 *  @param {Object} options object containing details of the message with
 *      the severity as 'warn'
 *  @param {Function} callback a callback run once the message is built
 *  @return {String} compiledMessage on completion, false on failure
 */
GlossyProducer.prototype.warn = function(options, callback) {
    options.severity = 'warn';
    return this.produce(options, callback);
};

/*
 *  @param {Object} options object containing details of the message with
 *      the severity as 'crit'
 *  @param {Function} callback a callback run once the message is built
 *  @return {String} compiledMessage on completion, false on failure
 */
GlossyProducer.prototype.crit = function(options, callback) {
    options.severity = 'crit';
    return this.produce(options, callback);
};

/*
 *  @param {Object} options object containing details of the message with
 *      the severity as 'alert'
 *  @param {Function} callback a callback run once the message is built
 *  @return {String} compiledMessage on completion, false on failure
 */
GlossyProducer.prototype.alert = function(options, callback) {
    options.severity = 'alert';
    return this.produce(options, callback);
};

/*
 *  @param {Object} options object containing details of the message with
 *      the severity as 'emergency'
 *  @param {Function} callback a callback run once the message is built
 *  @return {String} compiledMessage on completion, false on failure
 */
GlossyProducer.prototype.emergency = function(options, callback) {
    options.severity = 'emergency';
    return this.produce(options, callback);
};

/*
 *  Prepend a zero to a number less than 10
 *  @param {Number} n
 *  @return {String}
 *
 *  Where's sprintf when you need it?
 */
function leadZero(n) {
    if(typeof n != 'number') return n;
    n = n < 10 ? '0' + n : n ;
    return n;
}

/*
 *  Get current date in RFC 3164 format. If no date is supplied, the default
 *  is the current time in GMT + 0.
 *  @param {Date} dateObject optional Date object
 *  @returns {String}
 *
 *  Features code taken from https://github.com/akaspin/ain
 */
function generateBSDDate(dateObject) {
    if(!(dateObject instanceof Date)) dateObject = new Date(Date());
    var hours   = leadZero(dateObject.getHours());
    var minutes = leadZero(dateObject.getMinutes());
    var seconds = leadZero(dateObject.getSeconds());
    var month   = dateObject.getMonth();
    var day     = dateObject.getDate();
    if(day < 10) (day = ' ' + day);
    return BSDDateIndex[month] + " " + day + " " + hours + ":" + minutes + ":" + seconds;
}

/*
 *  Generate date in RFC 3339 format. If no date is supplied, the default is
 *  the current time in GMT + 0.
 *  @param {Date} dateObject optional Date object
 *  @returns {String} formatted date
 */
function generateDate(dateObject) {
    if(!(dateObject instanceof Date)) dateObject = new Date(Date());

    // Calcutate the offset
    var timeOffset;
    var minutes = Math.abs(dateObject.getTimezoneOffset());
    var hours = 0;
    while(minutes >= 60) {
        hours++;
        minutes -= 60;
    }

    if(dateObject.getTimezoneOffset() < 0) {
        // Ahead of UTC
        timeOffset = '+' + leadZero(hours) + '' + ':' + leadZero(minutes);
    } else if(dateObject.getTimezoneOffset() > 0) {
        // Behind UTC
        timeOffset = '-' + leadZero(hours) + '' + ':' + leadZero(minutes);
    } else {
        // UTC
        timeOffset = 'Z';
    }

    // Date
    formattedDate = dateObject.getUTCFullYear()         + '-' +
    // N.B. Javascript Date objects return months of the year indexed from
    // zero, while the RFC 5424 syslog standard expects months indexed from
    // one.
    leadZero(dateObject.getUTCMonth() + 1)  + '-' +
    // N.B. Javascript Date objects return days of the month indexed from one
    // (unlike months of year), so this does not need any correction.
    leadZero(dateObject.getUTCDate())   + 'T' +
    // Time
    leadZero(dateObject.getUTCHours())         + ':' +
    leadZero(dateObject.getUTCMinutes())       + ':' +
    leadZero(dateObject.getUTCSeconds())       + '.' +
    leadZero(dateObject.getUTCMilliseconds())  +
    timeOffset;

    return formattedDate;

}

/*
 *  Calculate the PRIVAL for a given facility
 *  @param {Object} values Contains the three key arguments
 *      facility {Number}/{String} the Facility Index
 *      severity {Number}
 *      version  {Number} For RFC 5424 messages, this should be 1
 *
 *  @return {String}
 */
function calculatePrival(values) {

    var pri = {};
    // Facility
    if(typeof values.facility == 'string' && !values.facility.match(/^\d+$/)) {
        pri.facility = FacilityIndex[values.facility.toLowerCase()];
    } else if( parseInt(values.facility, 10) && parseInt(values.facility, 10) < 24) {
        pri.facility = parseInt(values.facility, 10);
    }

    //Severity
    if(typeof values.severity == 'string' && !values.severity.match(/^\d+$/)) {
        pri.severity = SeverityIndex[values.severity.toLowerCase()];
    } else if( parseInt(values.severity, 10) && parseInt(values.severity, 10) < 8) {
        pri.severity = parseInt(values.severity, 10);
    }

    if(!isNaN(pri.severity) && !isNaN(pri.facility)) {
        pri.prival = (pri.facility * 8) + pri.severity;
        pri.str = values.version ? '<' + pri.prival + '>' + values.version : '<' + pri.prival + '>';
        return pri.str;
    } else {
        return false;
    }

}

/*
 *  Serialise objects into the structured data segment
 *  @param {Object} struct The object to serialise
 *  @return {String} structuredData the serialised data
 */
function generateStructuredData(struct) {
    if(typeof struct != 'object') return false;

    var structuredData = '';

    for(var sdID in struct) {
        sdElement = struct[sdID];
        structuredData += '[' + sdID;
        for(var key in sdElement) {
            sdElement[key] = sdElement[key].toString().replace(/(\]|\\|")/g, '\\$1');
            structuredData += ' ' + key + '="' + sdElement[key] + '"';
        }
        structuredData += ']';

    }

    return structuredData;
}

if(typeof module == 'object') {
    module.exports = GlossyProducer;
}
<|endoftext|>


<commit_before>import { reloadRoutes } from 'react-static/node'
import fs from 'fs-extra'
import path from 'path'
import React, { Component } from 'react'
import { ServerStyleSheet } from 'styled-components'
import chokidar from 'chokidar'

chokidar.watch('../docs').on('all', () => reloadRoutes())

//

const repoName = 'nozzle/react-static'
const repo = `https://github.com/${repoName}`

try {
  // eslint-disable-next-line
  process.env.REPO_VERSION = require(path.resolve('../package.json')).version
} catch (err) {
  //
}

process.env.SMACKDOWN_SYNTAX = JSON.stringify({
  showLineNumbers: true,
  highlighter: 'hljs',
  theme: 'atom-one-light',
  languages: ['javascript'],
})

const pages = [
  {
    path: '/',
    title: 'Readme',
    markdownSrc: '../README.md',
  },
  {
    path: 'concepts',
    title: 'Concepts',
    markdownSrc: '../docs/concepts.md',
  },
  {
    path: 'config',
    title: 'Config',
    markdownSrc: '../docs/config.md',
  },
  {
    path: 'cli',
    title: 'CLI',
    markdownSrc: '../docs/cli.md',
  },
  {
    path: 'node-api',
    title: 'Node API',
    markdownSrc: '../docs/node-api.md',
  },
  {
    path: 'components',
    title: 'Components',
    markdownSrc: '../docs/components.md',
  },
  {
    path: 'methods',
    title: 'Methods',
    markdownSrc: '../docs/methods.md',
  },
  {
    path: 'changelog',
    title: 'Changelog',
    markdownSrc: '../CHANGELOG.md',
  },
  {
    path: 'contributing',
    title: 'Contributing',
    markdownSrc: '../CONTRIBUTING.md',
  },
]

const menu = [
  {
    name: 'Readme',
    link: '/docs/',
  },
  {
    name: 'Core Concepts',
    children: [
      { name: 'Overview', link: '/docs/concepts' },
      {
        name: 'CSS and CSS-in-JS',
        link: '/docs/concepts#css-and-css-in-js',
      },
      {
        name: 'Code, Data, and Prop Splitting',
        link: '/docs/concepts#code-data-and-prop-splitting',
      },
      {
        name: 'Writing universal, "node-safe" code',
        link: '/docs/concepts/#writing-universal-node-safe-code',
      },
      { name: 'Environment Variables', link: '/docs/concepts/#environment-variables' },
      {
        name: 'Building your site for production',
        link: '/docs/concepts/#building-your-site-for-production',
      },
      { name: 'Continuous Integration', link: '/docs/concepts/#continuous-integration' },
      { name: 'Hosting', link: '/docs/concepts/#hosting' },
      { name: 'Using a CMS', link: '/docs/concepts/#using-a-cms' },
      {
        name: 'Rebuilding your site with Webhooks',
        link: '/docs/concepts/#rebuilding-your-site-with-webhooks',
      },
      { name: '404 Handling', link: '/docs/concepts/#404-handling' },
      { name: 'Non-Static Routing', link: '/docs/concepts/#non-static-routing' },
      {
        name: 'Webpack Customization and Plugins',
        link: '/docs/concepts/#webpack-customization-and-plugins',
      },
      {
        name: 'Using Preact in Production',
        link: '/docs/concepts/#using-preact-in-production',
      },
      { name: 'Pagination', link: '/docs/concepts/#pagination' },
      { name: 'Browser Support', link: '/docs/concepts/#browser-support' },
    ],
  },
  {
    name: 'API Reference',
    children: [
      {
        name: 'Config (static.config.js)',
        link: '/docs/config',
      },
      {
        name: 'CLI',
        link: '/docs/cli',
      },
      {
        name: 'Node API',
        link: '/docs/node-api',
      },
      {
        name: 'Components',
        link: '/docs/components',
      },
      {
        name: 'Methods',
        link: '/docs/methods',
      },
    ],
  },
  {
    name: 'Changelog',
    link: '/docs/changelog',
  },
  {
    name: 'Contributing',
    link: '/docs/contributing',
  },
]

export default {
  getSiteData: () => ({
    menu,
    repo,
    repoName,
  }),
  getRoutes: () => [
    {
      path: '/',
      component: 'src/containers/Home',
    },
    ...pages.map(page => ({
      path: `docs/${page.path}`,
      component: 'src/containers/Doc',
      getData: () => ({
        markdown: fs.readFileSync(path.resolve(page.markdownSrc), 'utf8'),
        editPath: repo + path.join('/blob/master/', __dirname.split('/').pop(), page.markdownSrc),
        title: page.title,
      }),
    })),
    {
      is404: true,
      component: 'src/containers/404',
    },
  ],
  renderToHtml: (render, Comp, meta) => {
    const sheet = new ServerStyleSheet()
    const html = render(sheet.collectStyles(<Comp />))
    meta.styleTags = sheet.getStyleElement()
    return html
  },
  Document: class CustomHtml extends Component {
    render () {
      const {
        Html, Head, Body, children, renderMeta,
      } = this.props

      return (

            <meta charSet="UTF-8" />
            <meta name="viewport" content="width=device-width, initial-scale=1" />
            <link
              href="https://fonts.googleapis.com/css?family=Roboto:400,400i,700,700i"
              rel="stylesheet"
            />
            {renderMeta.styleTags}
            <title>React Static</title>

          {children}

      )
    }
  },
}
<commit_msg>www: fix title<commit_after>import { reloadRoutes } from 'react-static/node'
import fs from 'fs-extra'
import path from 'path'
import React, { Component } from 'react'
import { ServerStyleSheet } from 'styled-components'
import chokidar from 'chokidar'

chokidar.watch('../docs').on('all', () => reloadRoutes())

//

const repoName = 'React Static'
const repo = 'nozzle/react-static'
const repoURL = `https://github.com/${repoName}`

try {
  // eslint-disable-next-line
  process.env.REPO_VERSION = require(path.resolve('../package.json')).version
} catch (err) {
  //
}

process.env.SMACKDOWN_SYNTAX = JSON.stringify({
  showLineNumbers: true,
  highlighter: 'hljs',
  theme: 'atom-one-light',
  languages: ['javascript'],
})

const pages = [
  {
    path: '/',
    title: 'Readme',
    markdownSrc: '../README.md',
  },
  {
    path: 'concepts',
    title: 'Concepts',
    markdownSrc: '../docs/concepts.md',
  },
  {
    path: 'config',
    title: 'Config',
    markdownSrc: '../docs/config.md',
  },
  {
    path: 'cli',
    title: 'CLI',
    markdownSrc: '../docs/cli.md',
  },
  {
    path: 'node-api',
    title: 'Node API',
    markdownSrc: '../docs/node-api.md',
  },
  {
    path: 'components',
    title: 'Components',
    markdownSrc: '../docs/components.md',
  },
  {
    path: 'methods',
    title: 'Methods',
    markdownSrc: '../docs/methods.md',
  },
  {
    path: 'changelog',
    title: 'Changelog',
    markdownSrc: '../CHANGELOG.md',
  },
  {
    path: 'contributing',
    title: 'Contributing',
    markdownSrc: '../CONTRIBUTING.md',
  },
]

const menu = [
  {
    name: 'Readme',
    link: '/docs/',
  },
  {
    name: 'Core Concepts',
    children: [
      { name: 'Overview', link: '/docs/concepts' },
      {
        name: 'CSS and CSS-in-JS',
        link: '/docs/concepts#css-and-css-in-js',
      },
      {
        name: 'Code, Data, and Prop Splitting',
        link: '/docs/concepts#code-data-and-prop-splitting',
      },
      {
        name: 'Writing universal, "node-safe" code',
        link: '/docs/concepts/#writing-universal-node-safe-code',
      },
      { name: 'Environment Variables', link: '/docs/concepts/#environment-variables' },
      {
        name: 'Building your site for production',
        link: '/docs/concepts/#building-your-site-for-production',
      },
      { name: 'Continuous Integration', link: '/docs/concepts/#continuous-integration' },
      { name: 'Hosting', link: '/docs/concepts/#hosting' },
      { name: 'Using a CMS', link: '/docs/concepts/#using-a-cms' },
      {
        name: 'Rebuilding your site with Webhooks',
        link: '/docs/concepts/#rebuilding-your-site-with-webhooks',
      },
      { name: '404 Handling', link: '/docs/concepts/#404-handling' },
      { name: 'Non-Static Routing', link: '/docs/concepts/#non-static-routing' },
      {
        name: 'Webpack Customization and Plugins',
        link: '/docs/concepts/#webpack-customization-and-plugins',
      },
      {
        name: 'Using Preact in Production',
        link: '/docs/concepts/#using-preact-in-production',
      },
      { name: 'Pagination', link: '/docs/concepts/#pagination' },
      { name: 'Browser Support', link: '/docs/concepts/#browser-support' },
    ],
  },
  {
    name: 'API Reference',
    children: [
      {
        name: 'Config (static.config.js)',
        link: '/docs/config',
      },
      {
        name: 'CLI',
        link: '/docs/cli',
      },
      {
        name: 'Node API',
        link: '/docs/node-api',
      },
      {
        name: 'Components',
        link: '/docs/components',
      },
      {
        name: 'Methods',
        link: '/docs/methods',
      },
    ],
  },
  {
    name: 'Changelog',
    link: '/docs/changelog',
  },
  {
    name: 'Contributing',
    link: '/docs/contributing',
  },
]

export default {
  getSiteData: () => ({
    menu,
    repoName,
  }),
  getRoutes: () => [
    {
      path: '/',
      component: 'src/containers/Home',
    },
    ...pages.map(page => ({
      path: `docs/${page.path}`,
      component: 'src/containers/Doc',
      getData: () => ({
        markdown: fs.readFileSync(path.resolve(page.markdownSrc), 'utf8'),
        editPath:
          repoURL + path.join('/blob/master/', __dirname.split('/').pop(), page.markdownSrc),
        title: page.title,
      }),
    })),
    {
      is404: true,
      component: 'src/containers/404',
    },
  ],
  renderToHtml: (render, Comp, meta) => {
    const sheet = new ServerStyleSheet()
    const html = render(sheet.collectStyles(<Comp />))
    meta.styleTags = sheet.getStyleElement()
    return html
  },
  Document: class CustomHtml extends Component {
    render () {
      const {
        Html, Head, Body, children, renderMeta,
      } = this.props

      return (

            <meta charSet="UTF-8" />
            <meta name="viewport" content="width=device-width, initial-scale=1" />
            <link
              href="https://fonts.googleapis.com/css?family=Roboto:400,400i,700,700i"
              rel="stylesheet"
            />
            {renderMeta.styleTags}
            <title>{repoName}</title>

          {children}

      )
    }
  },
}
<|endoftext|>


<commit_before>var request = require('request');
var db = require('./db-api');
var log = require('debug')('broadcast:broadcast');

function broadcastOne(postUrl, message, fn) {
  request({
    method: 'post',
    url: postUrl,
    body: {
      text: message
    },
    json: true
  }, function (err, response, body) {
    if (err) return fn(err);

    log('Successfully send post to %s', postUrl);
    return fn(null, body);
  });
}

function broadCastMany(message, teamsToSend, idx, fn) {
  if (idx == teamsToSend.length) {
    log('Finished broadcasting. Returning teams %j', teamsToSend);
    return fn(null, teamsToSend);
  }

  broadcastOne(teamsToSend[idx].outUrl, message, function (err, body) {
    if (err) return fn(err);

    broadCastMany(message, teamsToSend, idx + 1, fn);
  });
}

module.exports = function broadcast(data, targetTeams, fn) {
  db.teamsFor(data.team_domain, function (err, teams) {
    var originTeam = teams.filter(t => t.domain == data.team_domain)[0];

    var displayName = originTeam.display;

    var text;
    if (targetTeams) text = data.text.substr(data.text.indexOf(']'));
    else text = data.text.substr(10);

    var teamsToSend = teams;
    if (targetTeams) teamsToSend = teams.filter(t => targetTeams.indexOf(t.domain) > -1);

    var message = `${'```'}${data.user_name} from ${displayName} says:${'```'}\n${text}`;

    if (!originTeam.notifications) message = message.replace('@', '');

    broadCastMany(message, teamsToSend, 0, function (err, teamsSent) {
      if (err) {
        log('Found error: %s', err);
        return fn(err);
      }
      fn(null, teamsSent.map(t => t.team_display));
    });

  });
}<commit_msg>fixed team display<commit_after>var request = require('request');
var db = require('./db-api');
var log = require('debug')('broadcast:broadcast');

function broadcastOne(postUrl, message, fn) {
  request({
    method: 'post',
    url: postUrl,
    body: {
      text: message
    },
    json: true
  }, function (err, response, body) {
    if (err) return fn(err);

    log('Successfully send post to %s', postUrl);
    return fn(null, body);
  });
}

function broadCastMany(message, teamsToSend, idx, fn) {
  if (idx == teamsToSend.length) {
    log('Finished broadcasting. Returning teams %j', teamsToSend);
    return fn(null, teamsToSend);
  }

  broadcastOne(teamsToSend[idx].outUrl, message, function (err, body) {
    if (err) return fn(err);

    broadCastMany(message, teamsToSend, idx + 1, fn);
  });
}

module.exports = function broadcast(data, targetTeams, fn) {
  db.teamsFor(data.team_domain, function (err, teams) {
    var originTeam = teams.filter(t => t.domain == data.team_domain)[0];

    var displayName = originTeam.display;

    var text;
    if (targetTeams) text = data.text.substr(data.text.indexOf(']'));
    else text = data.text.substr(10);

    var teamsToSend = teams;
    if (targetTeams) teamsToSend = teams.filter(t => targetTeams.indexOf(t.domain) > -1);

    var message = `${'```'}${data.user_name} from ${displayName} says:${'```'}\n${text}`;

    if (!originTeam.notifications) message = message.replace('@', '');

    broadCastMany(message, teamsToSend, 0, function (err, teamsSent) {
      if (err) {
        log('Found error: %s', err);
        return fn(err);
      }
      fn(null, teamsSent.map(t => t.display));
    });

  });
}<|endoftext|>


<commit_before>/*global cordova, module */
'use strict';
module.exports = (function() {

  var _show = function(url, successCallback, errorCallback, loading) {
    if(loading){
      cordova.exec(successCallback, errorCallback, 'WebViewPlugin', 'show', [url, loading]);
    }
    else{
      cordova.exec(successCallback, errorCallback, 'WebViewPlugin', 'show', [url]);
    }
  };

  var _hide = function(params, successCallback, errorCallback) {
    cordova.exec(successCallback, errorCallback, 'WebViewPlugin', 'hide', params);
  };

  var _hideLoading = function(successCallback, errorCallback) {
    cordova.exec(successCallback, errorCallback, 'WebViewPlugin', 'hideLoading', []);
  };

  var _subscribeCallback = function(successCallback, errorCallback) {
    cordova.exec(successCallback, errorCallback, 'WebViewPlugin', 'subscribeCallback', []);
  };

  var _subscribeExitCallback = function(successCallback, errorCallback) {
    cordova.exec(successCallback, errorCallback, 'WebViewPlugin', 'subscribeExitCallback', []);
  };

  var _exitApp = function() {
    cordova.exec(function(){},function(){}, 'WebViewPlugin', 'exitApp', []);
  };

  var _setWebViewBehavior = function() {
    cordova.exec(function(){},function(){}, 'WebViewPlugin', 'webViewAdjustmenBehavior', []);
  };

  return {
    Show: _show,
    Hide: _hide,
    Close: _hide,
    SubscribeCallback: _subscribeCallback,
    SubscribeExitCallback: _subscribeExitCallback,
    ExitApp: _exitApp,
    HideLoading: _hideLoading,
    SetWebViewBehavior: _setWebViewBehavior
  };

})();
<commit_msg>moving the new parameter of hide to the end to avoid making a breaking change<commit_after>/*global cordova, module */
'use strict';
module.exports = (function() {

  var _show = function(url, successCallback, errorCallback, loading) {
    if(loading){
      cordova.exec(successCallback, errorCallback, 'WebViewPlugin', 'show', [url, loading]);
    }
    else{
      cordova.exec(successCallback, errorCallback, 'WebViewPlugin', 'show', [url]);
    }
  };

  var _hide = function(successCallback, errorCallback, params) {
    cordova.exec(successCallback, errorCallback, 'WebViewPlugin', 'hide', params);
  };

  var _hideLoading = function(successCallback, errorCallback) {
    cordova.exec(successCallback, errorCallback, 'WebViewPlugin', 'hideLoading', []);
  };

  var _subscribeCallback = function(successCallback, errorCallback) {
    cordova.exec(successCallback, errorCallback, 'WebViewPlugin', 'subscribeCallback', []);
  };

  var _subscribeExitCallback = function(successCallback, errorCallback) {
    cordova.exec(successCallback, errorCallback, 'WebViewPlugin', 'subscribeExitCallback', []);
  };

  var _exitApp = function() {
    cordova.exec(function(){},function(){}, 'WebViewPlugin', 'exitApp', []);
  };

  var _setWebViewBehavior = function() {
    cordova.exec(function(){},function(){}, 'WebViewPlugin', 'webViewAdjustmenBehavior', []);
  };

  return {
    Show: _show,
    Hide: _hide,
    Close: _hide,
    SubscribeCallback: _subscribeCallback,
    SubscribeExitCallback: _subscribeExitCallback,
    ExitApp: _exitApp,
    HideLoading: _hideLoading,
    SetWebViewBehavior: _setWebViewBehavior
  };

})();
<|endoftext|>


<commit_before>var _ = require('lodash');
var debug = require('debug')('bucketeer');
var S3Adapter = require('./lib/s3-adapter.js');

var handleError = function(err) {
  console.error(err.stack || new Error(err).stack);
  process.exit(1);
};

var loadProcessors = function(type) {
  debug('loadProcessors', type);
  var plural = type + 's';
  var result = {};
  _.uniq(_.pluck(settings[plural], 'name')).forEach(function(name) {
    try {
      result[name] = require('./' + plural + '/' + name + '.js');
    } catch(e) {
      handleError(new Error('Failed to load ' + type + ' "' + name + '": '
        + e.message));
    }
  });
  debug('loadedProcessors', type, Object.keys(result));
  return result;
};

var auth = require('./config/auth.json');
var settings = _.assign({
  region: 'us-east-1',
  filters: []
}, require('./config/settings.json'));

var filters = loadProcessors('filter');
var actions = loadProcessors('action');

var s3 = new S3Adapter({
  bucket: settings.bucket,
  region: settings.region,
  key: auth.key,
  secret: auth.secret
});

var prefixQueue = [],
    seenPrefixes = {},
    currentPrefix = null;

var handleList = function(err, data) {
  if (err) {
    return handleError(err);
  }
  checkPrefixes(data.CommonPrefixes);
  debug('handleList', _.pluck(data.Contents, 'Key'));
  var afterwards = data.isTruncated ?
    function() {
      nextBatch(data.NextMarker);
    } :
    nextPrefix;
  applyAndContinue(data.Contents, false,
    processObject,
    afterwards);
};

var processObject = function(obj, toNextObj, idx) {
  debug('applyFiltersToObject', idx, obj.Key);
  applyAndContinue(settings.filters, true,
    applyFilter.bind(obj),
    function(err, result) {
      if (result) {
        debug('applyActions', obj.Key);
        applyAndContinue(settings.actions, false,
          applyAction.bind(obj),
          toNextObj);
      } else {
        toNextObj();
      }
    });
};

var applyFilter = function(filter, toNextFilter, idx) {
  debug('applyFilter', this.Key, idx, filter.name, filter.options);
  applyProcessor(filters[filter.name], this, filter.options, toNextFilter);
};

var applyAction = function(action, toNextAction, idx) {
  debug('applyAction', this.Key, idx, action.name, action.options);
  applyProcessor(actions[action.name], this, action.options, toNextAction);
};

var applyProcessor = function(proc, obj, opt, cb) {
  var ctx = {
    s3: s3
  };
  proc.call(ctx, obj, opt || {}, cb);
};

var addPrefix = function(prefix) {
  if (!seenPrefixes.hasOwnProperty(prefix)) {
    debug('addPrefix', prefix);
    seenPrefixes[prefix] = true;
    prefixQueue.push(prefix);
  }
};

var checkPrefixes = function(prefixes) {
  _.pluck(prefixes, 'Prefix')
    .filter(function(prefix) {
      return (prefix !== '/');
    }).forEach(addPrefix);
};

var nextPrefix = function() {
  if (prefixQueue.length) {
    currentPrefix = prefixQueue.shift();
    debug('nextPrefix', currentPrefix);
    nextBatch();
  } else {
    debug('done');
  }
};

var nextBatch = function(marker) {
  s3.listObjects(currentPrefix, marker, null, handleList);
};

var applyAndContinue = function(subjects, allowSkip, cb, after) {
  var i = 0;
  var step = function(err, result) {
    if (err) {
      return handleError(err);
    }
    if (allowSkip && result === false) {
      debug('skip', i);
      after(null, false);
    } else if (i >= subjects.length) {
      debug('after');
      after(null, true);
    } else {
      debug('apply', i);
      cb(subjects[i], step, i++);
    }
  };
  step();
};

addPrefix('');
nextPrefix();
<commit_msg>Cosmetic fixes<commit_after>var _ = require('lodash');
var debug = require('debug')('bucketeer');
var S3Adapter = require('./lib/s3-adapter.js');

var handleError = function(err) {
  console.error(err.stack || new Error(err).stack);
  process.exit(1);
};

var loadProcessors = function(type) {
  debug('loadProcessors', type);
  var plural = type + 's';
  var result = {};
  _.uniq(_.pluck(settings[plural], 'name')).forEach(function(name) {
    try {
      result[name] = require('./' + plural + '/' + name + '.js');
    } catch(e) {
      handleError(new Error('Failed to load ' + type + ' "' + name + '": '
        + e.message));
    }
  });
  debug('loadedProcessors', type, Object.keys(result));
  return result;
};

var auth = require('./config/auth.json');
var settings = _.assign({
  region: 'us-east-1',
  filters: []
}, require('./config/settings.json'));

var filters = loadProcessors('filter');
var actions = loadProcessors('action');

var s3 = new S3Adapter({
  bucket: settings.bucket,
  region: settings.region,
  key: auth.key,
  secret: auth.secret
});

var prefixQueue = [],
    seenPrefixes = {},
    currentPrefix = null;

var handleList = function(err, data) {
  if (err) {
    return handleError(err);
  }
  checkPrefixes(data.CommonPrefixes);
  debug('handleList', _.pluck(data.Contents, 'Key'));
  var afterwards = data.isTruncated ?
    function() {
      nextBatch(data.NextMarker);
    } :
    nextPrefix;
  applyAndContinue(data.Contents, false,
    processObject,
    afterwards);
};

var processObject = function(obj, toNextObject, idx) {
  debug('applyFiltersToObject', idx, obj.Key);
  applyAndContinue(settings.filters, true,
    applyFilter.bind(obj),
    function(err, result) {
      if (result) {
        debug('applyActionsToObject', obj.Key);
        applyAndContinue(settings.actions, false,
          applyAction.bind(obj),
          toNextObject);
      } else {
        toNextObject();
      }
    });
};

var applyFilter = function(filter, toNextFilter, idx) {
  debug('applyFilter', this.Key, idx, filter.name, filter.options);
  applyProcessor(filters[filter.name], this, filter.options, toNextFilter);
};

var applyAction = function(action, toNextAction, idx) {
  debug('applyAction', this.Key, idx, action.name, action.options);
  applyProcessor(actions[action.name], this, action.options, toNextAction);
};

var applyProcessor = function(proc, obj, opt, cb) {
  var ctx = {
    s3: s3
  };
  proc.call(ctx, obj, opt || {}, cb);
};

var addPrefix = function(prefix) {
  if (!seenPrefixes.hasOwnProperty(prefix)) {
    debug('addPrefix', prefix);
    seenPrefixes[prefix] = true;
    prefixQueue.push(prefix);
  }
};

var checkPrefixes = function(prefixes) {
  _.pluck(prefixes, 'Prefix')
    .filter(function(prefix) {
      return (prefix !== '/');
    }).forEach(addPrefix);
};

var nextPrefix = function() {
  if (prefixQueue.length) {
    currentPrefix = prefixQueue.shift();
    debug('nextPrefix', currentPrefix);
    nextBatch();
  } else {
    debug('done');
  }
};

var nextBatch = function(marker) {
  s3.listObjects(currentPrefix, marker, null, handleList);
};

var applyAndContinue = function(subjects, allowSkip, cb, after) {
  var i = 0;
  var step = function(err, result) {
    if (err) {
      return handleError(err);
    }
    if (allowSkip && result === false) {
      debug('skip', i);
      after(null, false);
    } else if (i >= subjects.length) {
      debug('after');
      after(null, true);
    } else {
      debug('apply', i);
      cb(subjects[i], step, i++);
    }
  };
  step();
};

addPrefix('');
nextPrefix();
<|endoftext|>


<commit_before>'use strict';

var modulePackage = require('gulp/package'),
    cliPackage = require('/usr/lib/node_modules/gulp/package');

var gulp = require('gulp');
var gutil = require('gulp-util');
var runtime = require('../gulp-runtime');
var Herror = require('herro').Herror;

runtime.config({
  cliPackage : cliPackage,
  modulePackage : modulePackage
});

//
// ## something could not be found
//
runtime.on('message', function(opts){

  if( opts.reason !== 'error' ){

    gutil.log(
      gutil.colors.yellow('gulp-runtime') + ': ' +
      opts.message
    );

  } else {

    var err = new gutil.PluginError({
         plugin : 'gulp-runtime',
        message : opts.message
    });
    err.stack = opts.stack;

    err = Herror.call(err, err.message);

    if( opts.throw ){
      throw err;
    } else {

      var logIsSilent = (gutil.log).toString().match(/{.*}/).trim() === '';

      err.stack.split('\n').forEach(function(line){

        if( logIsSilent ){
          console.log(line);
        } else {
          gutil.log(line);
        }
      });
    }
  }

  if( opts.prompt ){
    this.prompt();
  }
});

gulp.doneCallback = function(){
  setTimeout(function(){
    runtime.prompt();
  }, 50);
};
<commit_msg>lets suppose the error had no stack trace...<commit_after>'use strict';

var modulePackage = require('gulp/package'),
    cliPackage = require('/usr/lib/node_modules/gulp/package');

var gulp = require('gulp');
var gutil = require('gulp-util');
var runtime = require('../gulp-runtime');
var Herror = require('herro').Herror;

runtime.config({
  cliPackage : cliPackage,
  modulePackage : modulePackage
});

//
// ## something could not be found
//
runtime.on('message', function(opts){

  if( opts.reason !== 'error' ){

    gutil.log(
      gutil.colors.yellow('gulp-runtime') + ': ' +
      opts.message
    );

  } else {

    var err = new gutil.PluginError({
         plugin : 'gulp-runtime',
        message : opts.message
    });
    err.stack = opts.stack;

    err = Herror.call(err, err.message);

    if( opts.throw ){
      throw err;
    } else {

      var logIsSilent = (gutil.log).toString().match(/{.*}/).trim() === '';

      (err.stack || []).split('\n').forEach(function(line){

        if( logIsSilent ){
          console.log(line);
        } else {
          gutil.log(line);
        }
      });
    }
  }

  if( opts.prompt ){
    this.prompt();
  }
});

gulp.doneCallback = function(){
  setTimeout(function(){
    runtime.prompt();
  }, 50);
};
<|endoftext|>


<commit_before>'use strict';

const fsx = require('./fs-additions');
const path = require('path');
const root = require('find-root');
const _ = require('lodash');

// Information about LT itself
const pkg = require('../../package.json');
const majorVersion = pkg.version ? pkg.version.split('.')[0] : 'unknown';
const resourcePrefix = _.compact([pkg.name, majorVersion]).join('-');

/**
 *  Helper for loading config file of a project
 */

// Load configuration file from disk (if one exists)
// Default values
let result = {
    project: {},
    lambda: {
        runtime: 'nodejs'
    },
    aws: {
        region: 'us-east-1',
        stage: 'dev'
    },
    tools: {
        name: pkg.name,
        version: pkg.version,
        majorVersion: majorVersion,
        resources: {
            s3Bucket: [resourcePrefix, 'assets'].join('-'),
            iamRole: [resourcePrefix, 'resource'].join('-'),
            apiGateway: [resourcePrefix, 'api-gateway'].join('-'),
            lambdaVersion: [resourcePrefix, 'lambda-version'].join('-')
        }
    }
};

// Config file is assumed to be at "package root"
try {
    const rootPath = root(process.cwd());
    const configPath = path.resolve(rootPath, '.lambda-tools-rc.json');

    if (fsx.fileExists(configPath)) {
        result = _.merge(result, fsx.readJSONFileSync(configPath));
    }
} catch (err) {
    // Ignore
}

module.exports = result;
<commit_msg>Make sure config includes S3 bucket prefix<commit_after>'use strict';

const Configstore = require('configstore');
const fsx = require('./fs-additions');
const path = require('path');
const root = require('find-root');
const _ = require('lodash');

// Information about LT itself
const pkg = require('../../package.json');
const majorVersion = pkg.version ? pkg.version.split('.')[0] : 'unknown';
const resourcePrefix = _.compact([pkg.name, majorVersion]).join('-');

const bucketPrefix = (new Configstore(pkg.name)).get('S3BucketPrefix');

/**
 *  Helper for loading config file of a project
 */

// Load configuration file from disk (if one exists)
// Default values
let result = {
    project: {},
    lambda: {
        runtime: 'nodejs'
    },
    aws: {
        region: 'us-east-1',
        stage: 'dev'
    },
    tools: {
        name: pkg.name,
        version: pkg.version,
        majorVersion: majorVersion,
        resources: {
            s3Bucket: _.compact([bucketPrefix, resourcePrefix, 'assets']).join('-'),
            iamRole: [resourcePrefix, 'resource'].join('-'),
            apiGateway: [resourcePrefix, 'api-gateway'].join('-'),
            lambdaVersion: [resourcePrefix, 'lambda-version'].join('-')
        }
    }
};

// Config file is assumed to be at "package root"
try {
    const rootPath = root(process.cwd());
    const configPath = path.resolve(rootPath, '.lambda-tools-rc.json');

    if (fsx.fileExists(configPath)) {
        result = _.merge(result, fsx.readJSONFileSync(configPath));
    }
} catch (err) {
    // Ignore
}

module.exports = result;
<|endoftext|>


<commit_before>'use strict';

var debug = require('debug')('base:templates:helper');
var List = require('../list');

module.exports = function(app, collection) {
  var plural = collection.options.plural;

  /**
   * Creates an async helper for each view collection, and exposes
   * the collection as an instance of `List` to the helper context.
   *
   * If the helper is used as a handlebars block helper, the collection
   * array will be exposed as context to `options.fn()`, otherwise
   * the `List` array is returned.
   *
   * ```js
   * // create a collection
   * app.create('pages');
   *
   * // use the `pages` helper
   * // {{#pages}} ... {{/pages}}
   * ```
   * @param {Object} `options` Locals or handlebars options object
   * @param {String} `callback` Handled internally by the templates library.
   * @api public
   */

  app.asyncHelper(plural, function listHelper(options, cb) {
    if (typeof options === 'function') {
      cb = options;
      options = {};
    }

    options = options || {};
    if (typeof options === 'string') {
      var singular = this.app.getAsyncHelper(collection.options.inflection)
        || app.getAsyncHelper(collection.options.inflection);
      return singular.apply(this, arguments);
    }

    debug('list helper "%s", "%j"', plural, options);
    var list = new List(collection);

    // expose `items` as the plural name of the collection
    if (plural !== 'items') {
      list[plural] = list.items;
    }

    // render block helper with list as context
    if (typeof options.fn === 'function' && options.hash) {
      cb(null, options.fn(list));
      return;
    }

    // return list when not used as a block helper
    cb(null, list);
  });
};
<commit_msg>make collection helper sync<commit_after>'use strict';

var debug = require('debug')('base:templates:helper');
var List = require('../list');

module.exports = function(app, collection) {
  var plural = collection.options.plural;

  /**
   * Creates an async helper for each view collection, and exposes
   * the collection as an instance of `List` to the helper context.
   *
   * If the helper is used as a handlebars block helper, the collection
   * array will be exposed as context to `options.fn()`, otherwise
   * the `List` array is returned.
   *
   * ```js
   * // create a collection
   * app.create('pages');
   *
   * // use the `pages` helper
   * // {{#pages}} ... {{/pages}}
   * ```
   * @param {Object} `options` Locals or handlebars options object
   * @param {String} `callback` Handled internally by the templates library.
   * @api public
   */

  app.helper(plural, function listHelper(options) {
    debug('list helper "%s", "%j"', plural, options);
    var list = new List(collection);

    // expose `items` as the plural name of the collection
    if (plural !== 'items') {
      list[plural] = list.items;
    }

    // render block helper with list as context
    if (options && typeof options.fn === 'function' && options.hash) {
      return options.fn(list)
    }

    // return list when not used as a block helper
    return list;
  });
};
<|endoftext|>