<commit_before>const { Pool } = require('pg');
const express = require('express');
const asyncHandler = require('express-async-handler');
const passport = require('passport');
const FacebookStrategy = require('passport-facebook').Strategy;
const session = require('express-session');
const RedisStore = require('connect-redis')(session);
const { param, body, validationResult } = require('express-validator/check');
const { matchedData } = require('express-validator/filter');
const error = require('./utils').appThrow;

const app = express();
app.set('trust proxy', 1);
app.use(session({
  store: new RedisStore({ host: 'redis' }),
  secret: process.env.SESSION_SECRET,
  resave: false,
}));
passport.use(new FacebookStrategy({
  clientID: process.env.FACEBOOK_APP_ID,
  clientSecret: process.env.FACEBOOK_APP_SECRET,
  callbackURL: `${process.env.FRONTEND}/api/connect/facebook/callback`,
}, (accessToken, refreshToken, profile, done) => {
  const connected = `fb:${profile.id}`;
  done(null, { connected });
}));
app.use(passport.initialize());
const pool = new Pool({ connectionString: process.env.DATABASE_URL });

const requireUser = asyncHandler(async (req, res, next) => {
  const { userId } = req.session;
  if (!userId) {
    error(403, 'user');
    return;
  }
  const queryResult = await pool.query('SELECT * FROM users WHERE id = $1;', [userId]);
  if (queryResult.rows.length !== 1) {
    error(403, 'user');
    return;
  }
  [req.user] = queryResult.rows;
  next();
});
const createOrUpdateUser = async (connected) => {
  const queryResult = await pool.query(`
    INSERT INTO users (connected, logged_in_at) VALUES ($1, current_timestamp)
    ON CONFLICT (connected) DO UPDATE SET logged_in_at = current_timestamp
    RETURNING id;`, [connected]);
  return queryResult.rows[0].id;
};
const router = express.Router();
router.get('/connect/facebook', passport.authenticate('facebook'));
router.get('/connect/facebook/callback', passport.authenticate('facebook', { session: false }), asyncHandler(async (req, res) => {
  const { connected } = req.user;
  req.session.userId = await createOrUpdateUser(connected);
  res.redirect('/');
}));
router.get('/logout', (req, res) => {
  delete req.session.userId;
  res.redirect('/');
});
router.get('/mai/me', requireUser, asyncHandler(async (req, res) => {
  const { user } = req;
  const queryResult = await pool.query('SELECT * FROM laundry_players WHERE user_id = $1;', [user.id]);
  res.send(JSON.stringify(queryResult.rows));
}));
router.get('/mai/songs', asyncHandler(async (req, res) => {
  const queryResult = await pool.query('SELECT * FROM laundry_songs ORDER BY seq ASC;');
  res.send(JSON.stringify(queryResult.rows));
}));
router.get('/mai/:nickname', asyncHandler(async (req, res) => {
  const { nickname } = req.params;
  const queryResult = await pool.query('SELECT * FROM laundry_players WHERE nickname = $1;', [nickname]);
  if (queryResult.rows.length === 0) {
    error(404, 'not_found');
  }
  const player = queryResult.rows[0];
  const recordResult = await pool.query('SELECT * FROM laundry_records_recent WHERE player_id = $1;', [player.id]);
  if (recordResult.rows.length > 0) {
    [player.record] = recordResult.rows;
  }
  const scoreResult = await pool.query('SELECT song_id, difficulty, score, raw_score, flag FROM laundry_scores_recent WHERE player_id = $1;', [player.id]);
  if (scoreResult.rows.length > 0) {
    player.scores = scoreResult.rows;
  }
  res.send(JSON.stringify(player));
}));
router.get('/mai/:nickname/timeline', asyncHandler(async (req, res) => {
  const { nickname } = req.params;
  const queryResult = await pool.query('SELECT * FROM laundry_players WHERE nickname = $1;', [nickname]);
  if (queryResult.rows.length === 0) {
    error(404, 'not_found');
  }
  const player = queryResult.rows[0];
  const timelineResult = await pool.query(`
    SELECT to_json(lower) AS lower FROM (
    SELECT DISTINCT lower(period) FROM laundry_records WHERE player_id = $1 UNION
    SELECT DISTINCT lower(period) FROM laundry_scores WHERE player_id = $1 ORDER BY lower ASC) AS lowers;
  `, [player.id]);
  res.send(JSON.stringify(timelineResult.rows.map(val => val.lower)));
}));
router.get('/mai/:nickname/timeline/:time', [
  param('time').isISO8601(),
], asyncHandler(async (req, res) => {
  const errors = validationResult(req);
  if (!errors.isEmpty()) {
    error(422, 'validation');
  }
  const { nickname, time } = req.params;
  const queryResult = await pool.query('SELECT * FROM laundry_players WHERE nickname = $1;', [nickname]);
  if (queryResult.rows.length === 0) {
    error(404, 'not_found');
  }
  const player = queryResult.rows[0];
  const recordResult = await pool.query(`
    SELECT *, 'before' AS from FROM laundry_records WHERE player_id = $1 AND period -|- tstzrange($2, 'infinity') UNION
    SELECT *, 'after' AS from FROM laundry_records WHERE player_id = $1 AND period -|- tstzrange('-infinity', $2);
  `, [player.id, time]);
  const scoreResult = await pool.query(`
    SELECT *, 'before' AS from FROM laundry_scores WHERE player_id = $1 AND score > 0 AND period -|- tstzrange($2, 'infinity') UNION
    SELECT *, 'after' AS from FROM laundry_scores WHERE player_id = $1 AND score > 0 AND period -|- tstzrange('-infinity', $2);
  `, [player.id, time]);
  res.send(JSON.stringify({
    records: recordResult.rows,
    scores: scoreResult.rows,
  }));
}));
router.post('/mai/new', express.json(), requireUser, [
  body('nickname').matches(/[0-9a-z\-_]/),
  body('privacy').matches(/^(public|anonymous|private)$/),
], asyncHandler(async (req, res) => {
  const errors = validationResult(req);
  if (!errors.isEmpty()) {
    console.log(errors.mapped()); // eslint-disable-line no-console
    error(422, 'validation');
  }
  const data = matchedData(req);
  const { nickname, privacy } = data;
  const { user } = req;
  const queryResult = await pool.query('SELECT id FROM laundry_players WHERE nickname = $1;', [nickname]);
  if (queryResult.rows.length > 0) {
    error(400, 'exists');
    return;
  }
  await pool.query('INSERT INTO laundry_players (nickname, user_id, privacy) VALUES ($1, $2, $3);', [nickname, user.id, privacy]);
  res.send(JSON.stringify({}));
}));

router.post('/mai/:nickname', express.json({ limit: '2mb' }), requireUser, [
  body('cardName').isString(),
  body('rating').isFloat({ min: 0, max: 20 }),
  body('maxRating').isFloat({ min: 0, max: 20 }),
  body('icon').isString(),
  body('title').isString(),
  body('class').isString(),
], asyncHandler(async (req, res) => {
  const errors = validationResult(req);
  if (!errors.isEmpty()) {
    console.log(errors.mapped()); // eslint-disable-line no-console
    error(422, 'validation');
  }
  const data = matchedData(req);
  const { nickname } = req.params;
  const { user } = req;
  if (nickname === 'me') {
    error(422, 'validation');
  }
  const queryResult = await pool.query('SELECT id, user_id FROM laundry_players WHERE nickname = $1 AND user_id = $2;', [nickname, user.id]);
  if (queryResult.rows.length === 0) {
    error(404, 'not_exists');
  }
  const [player] = queryResult.rows;
  // Validate data, and make sure the scores are non-decreasing.
  const scoreQueryResult = await pool.query('SELECT song_id, difficulty, score FROM laundry_scores_recent WHERE player_id = $1;', [player.id]);
  const oldScoreMap = new Map();
  for (let i = 0; i < scoreQueryResult.rows.length; i += 1) {
    const score = scoreQueryResult.rows[i];
    oldScoreMap.set(`${score.song_id}.${score.difficulty}`, parseFloat(score.score));
  }

  const { scores } = req.body;
  if (!Array.isArray(scores)) {
    error(422, 'validation');
  }
  for (let i = 0; i < scores.length; i += 1) {
    const score = scores[i];
    if (!Number.isInteger(score.songId) || score.songId < 0) {
      error(422, 'validation');
    }
    if (!score.category || !score.songName) {
      error(422, 'validation');
    }
    if (!Number.isInteger(score.difficulty) ||
        score.difficulty < 0 || score.difficulty > 5) {
      error(422, 'validation');
    }
    if (!Number.isFinite(score.score) || score.score < 0 || score.score > 104) {
      error(422, 'validation');
    }
    if (!Number.isInteger(score.rawScore) || score.rawScore < 0) {
      error(422, 'validation');
    }
    const oldScore = oldScoreMap.get(`${score.songId}.${score.difficulty}`);
    if (score.score < oldScore) {
      error(422, 'validation');
    }
    if (score.flag) {
      const flags = score.flag.split('|');
      for (let j = 0; j < flags.length; j += 1) {
        if (flags[j].search(/^(fc_silver|fc_gold|ap|100)$/) === -1) {
          error(422, 'validation');
        }
      }
    }
  }
  const client = await pool.connect();
  try {
    await client.query('BEGIN');
    await client.query(
      `INSERT INTO laundry_records_recent
      (player_id, card_name, rating, max_rating, icon, title, class) VALUES ($1, $2, $3, $4, $5, $6, $7)
      ON CONFLICT(player_id) DO UPDATE SET card_name = $2, rating = $3, max_rating = $4, icon = $5, title = $6, class = $7;`,
      [player.id, data.cardName, data.rating, data.maxRating, data.icon, data.title, data.class],
    );

    const promises = [];
    for (let i = 0; i < scores.length; i += 1) {
      const score = scores[i];
      if (score.difficulty === 0) {
        // Only update the song sequence, insert the category and song name.
        const songQuery = {
          name: 'insert-songs',
          text: `INSERT INTO laundry_songs
          (id, seq, category, name) VALUES ($1, $2, $3, $4)
          ON CONFLICT(id) DO UPDATE SET seq = $2;`,
          values: [score.songId, i, score.category, score.songName],
        };
        promises.push(client.query(songQuery));
      }
      const query = {
        name: 'insert-scores-recent',
        text: `INSERT INTO laundry_scores_recent
        (player_id, song_id, difficulty, score, raw_score, flag) VALUES ($1, $2, $3, $4, $5, $6)
        ON CONFLICT(player_id, song_id, difficulty) DO UPDATE SET score = $4, raw_score = $5, flag = $6;`,
        values: [player.id, score.songId, score.difficulty,
          score.score, score.rawScore, score.flag],
      };
      promises.push(client.query(query));
    }
    await Promise.all(promises);
    await client.query('COMMIT');
  } catch (e) {
    await client.query('ROLLBACK');
    throw e;
  } finally {
    client.release();
  }
  res.send(JSON.stringify({}));
}));
app.use('/api', router);
app.use((err, req, res, next) => { // eslint-disable-line no-unused-vars
  if (!err.exposed) {
    console.log(err); // eslint-disable-line no-console
    res.status(500).send(JSON.stringify({ err: 'internal' }));
  } else {
    res.status(err.status).send(JSON.stringify({ err: err.message }));
  }
});

app.listen(8585);
<commit_msg>Introduce requireNicknameAccess middleware.<commit_after>const { Pool } = require('pg');
const express = require('express');
const asyncHandler = require('express-async-handler');
const passport = require('passport');
const FacebookStrategy = require('passport-facebook').Strategy;
const session = require('express-session');
const RedisStore = require('connect-redis')(session);
const { param, body, validationResult } = require('express-validator/check');
const { matchedData } = require('express-validator/filter');
const error = require('./utils').appThrow;

const app = express();
app.set('trust proxy', 1);
app.use(session({
  store: new RedisStore({ host: 'redis' }),
  secret: process.env.SESSION_SECRET,
  resave: false,
}));
passport.use(new FacebookStrategy({
  clientID: process.env.FACEBOOK_APP_ID,
  clientSecret: process.env.FACEBOOK_APP_SECRET,
  callbackURL: `${process.env.FRONTEND}/api/connect/facebook/callback`,
}, (accessToken, refreshToken, profile, done) => {
  const connected = `fb:${profile.id}`;
  done(null, { connected });
}));
app.use(passport.initialize());
const pool = new Pool({ connectionString: process.env.DATABASE_URL });

const requireUser = asyncHandler(async (req, res, next) => {
  const { userId } = req.session;
  if (!userId) {
    error(403, 'user');
    return;
  }
  const queryResult = await pool.query('SELECT * FROM users WHERE id = $1;', [userId]);
  if (queryResult.rows.length !== 1) {
    error(403, 'user');
    return;
  }
  [req.user] = queryResult.rows;
  next();
});
const requireNicknameAccess = asyncHandler(async (req, res, next) => {
  const { nickname } = req.params;
  const { user } = req;
  if (nickname === 'me') {
    error(422, 'validation');
  }
  const queryResult = await pool.query('SELECT id, nickname, user_id FROM laundry_players WHERE nickname = $1 AND user_id = $2;', [nickname, user.id]);
  if (queryResult.rows.length === 0) {
    error(404, 'not_exists');
  }
  [req.player] = queryResult.rows;
  next();
});
const createOrUpdateUser = async (connected) => {
  const queryResult = await pool.query(`
    INSERT INTO users (connected, logged_in_at) VALUES ($1, current_timestamp)
    ON CONFLICT (connected) DO UPDATE SET logged_in_at = current_timestamp
    RETURNING id;`, [connected]);
  return queryResult.rows[0].id;
};
const router = express.Router();
router.get('/connect/facebook', passport.authenticate('facebook'));
router.get('/connect/facebook/callback', passport.authenticate('facebook', { session: false }), asyncHandler(async (req, res) => {
  const { connected } = req.user;
  req.session.userId = await createOrUpdateUser(connected);
  res.redirect('/');
}));
router.get('/logout', (req, res) => {
  delete req.session.userId;
  res.redirect('/');
});
router.get('/mai/me', requireUser, asyncHandler(async (req, res) => {
  const { user } = req;
  const queryResult = await pool.query('SELECT * FROM laundry_players WHERE user_id = $1;', [user.id]);
  res.send(JSON.stringify(queryResult.rows));
}));
router.get('/mai/songs', asyncHandler(async (req, res) => {
  const queryResult = await pool.query('SELECT * FROM laundry_songs ORDER BY seq ASC;');
  res.send(JSON.stringify(queryResult.rows));
}));
router.get('/mai/:nickname', asyncHandler(async (req, res) => {
  const { nickname } = req.params;
  const queryResult = await pool.query('SELECT * FROM laundry_players WHERE nickname = $1;', [nickname]);
  if (queryResult.rows.length === 0) {
    error(404, 'not_found');
  }
  const player = queryResult.rows[0];
  const recordResult = await pool.query('SELECT * FROM laundry_records_recent WHERE player_id = $1;', [player.id]);
  if (recordResult.rows.length > 0) {
    [player.record] = recordResult.rows;
  }
  const scoreResult = await pool.query('SELECT song_id, difficulty, score, raw_score, flag FROM laundry_scores_recent WHERE player_id = $1;', [player.id]);
  if (scoreResult.rows.length > 0) {
    player.scores = scoreResult.rows;
  }
  res.send(JSON.stringify(player));
}));
router.get('/mai/:nickname/timeline', asyncHandler(async (req, res) => {
  const { nickname } = req.params;
  const queryResult = await pool.query('SELECT * FROM laundry_players WHERE nickname = $1;', [nickname]);
  if (queryResult.rows.length === 0) {
    error(404, 'not_found');
  }
  const player = queryResult.rows[0];
  const timelineResult = await pool.query(`
    SELECT to_json(lower) AS lower FROM (
    SELECT DISTINCT lower(period) FROM laundry_records WHERE player_id = $1 UNION
    SELECT DISTINCT lower(period) FROM laundry_scores WHERE player_id = $1 ORDER BY lower ASC) AS lowers;
  `, [player.id]);
  res.send(JSON.stringify(timelineResult.rows.map(val => val.lower)));
}));
router.get('/mai/:nickname/timeline/:time', [
  param('time').isISO8601(),
], asyncHandler(async (req, res) => {
  const errors = validationResult(req);
  if (!errors.isEmpty()) {
    error(422, 'validation');
  }
  const { nickname, time } = req.params;
  const queryResult = await pool.query('SELECT * FROM laundry_players WHERE nickname = $1;', [nickname]);
  if (queryResult.rows.length === 0) {
    error(404, 'not_found');
  }
  const player = queryResult.rows[0];
  const recordResult = await pool.query(`
    SELECT *, 'before' AS from FROM laundry_records WHERE player_id = $1 AND period -|- tstzrange($2, 'infinity') UNION
    SELECT *, 'after' AS from FROM laundry_records WHERE player_id = $1 AND period -|- tstzrange('-infinity', $2);
  `, [player.id, time]);
  const scoreResult = await pool.query(`
    SELECT *, 'before' AS from FROM laundry_scores WHERE player_id = $1 AND score > 0 AND period -|- tstzrange($2, 'infinity') UNION
    SELECT *, 'after' AS from FROM laundry_scores WHERE player_id = $1 AND score > 0 AND period -|- tstzrange('-infinity', $2);
  `, [player.id, time]);
  res.send(JSON.stringify({
    records: recordResult.rows,
    scores: scoreResult.rows,
  }));
}));
router.post('/mai/new', express.json(), requireUser, [
  body('nickname').matches(/[0-9a-z\-_]/),
  body('privacy').matches(/^(public|anonymous|private)$/),
], asyncHandler(async (req, res) => {
  const errors = validationResult(req);
  if (!errors.isEmpty()) {
    console.log(errors.mapped()); // eslint-disable-line no-console
    error(422, 'validation');
  }
  const data = matchedData(req);
  const { nickname, privacy } = data;
  const { user } = req;
  const queryResult = await pool.query('SELECT id FROM laundry_players WHERE nickname = $1;', [nickname]);
  if (queryResult.rows.length > 0) {
    error(400, 'exists');
    return;
  }
  await pool.query('INSERT INTO laundry_players (nickname, user_id, privacy) VALUES ($1, $2, $3);', [nickname, user.id, privacy]);
  res.send(JSON.stringify({}));
}));

router.post('/mai/:nickname', express.json({ limit: '2mb' }), requireUser, requireNicknameAccess, [
  body('cardName').isString(),
  body('rating').isFloat({ min: 0, max: 20 }),
  body('maxRating').isFloat({ min: 0, max: 20 }),
  body('icon').isString(),
  body('title').isString(),
  body('class').isString(),
], asyncHandler(async (req, res) => {
  const errors = validationResult(req);
  if (!errors.isEmpty()) {
    console.log(errors.mapped()); // eslint-disable-line no-console
    error(422, 'validation');
  }
  const data = matchedData(req);
  const { player } = req;
  // Validate data, and make sure the scores are non-decreasing.
  const scoreQueryResult = await pool.query('SELECT song_id, difficulty, score FROM laundry_scores_recent WHERE player_id = $1;', [player.id]);
  const oldScoreMap = new Map();
  for (let i = 0; i < scoreQueryResult.rows.length; i += 1) {
    const score = scoreQueryResult.rows[i];
    oldScoreMap.set(`${score.song_id}.${score.difficulty}`, parseFloat(score.score));
  }

  const { scores } = req.body;
  if (!Array.isArray(scores)) {
    error(422, 'validation');
  }
  for (let i = 0; i < scores.length; i += 1) {
    const score = scores[i];
    if (!Number.isInteger(score.songId) || score.songId < 0) {
      error(422, 'validation');
    }
    if (!score.category || !score.songName) {
      error(422, 'validation');
    }
    if (!Number.isInteger(score.difficulty) ||
        score.difficulty < 0 || score.difficulty > 5) {
      error(422, 'validation');
    }
    if (!Number.isFinite(score.score) || score.score < 0 || score.score > 104) {
      error(422, 'validation');
    }
    if (!Number.isInteger(score.rawScore) || score.rawScore < 0) {
      error(422, 'validation');
    }
    const oldScore = oldScoreMap.get(`${score.songId}.${score.difficulty}`);
    if (score.score < oldScore) {
      error(422, 'validation');
    }
    if (score.flag) {
      const flags = score.flag.split('|');
      for (let j = 0; j < flags.length; j += 1) {
        if (flags[j].search(/^(fc_silver|fc_gold|ap|100)$/) === -1) {
          error(422, 'validation');
        }
      }
    }
  }
  const client = await pool.connect();
  try {
    await client.query('BEGIN');
    await client.query(
      `INSERT INTO laundry_records_recent
      (player_id, card_name, rating, max_rating, icon, title, class) VALUES ($1, $2, $3, $4, $5, $6, $7)
      ON CONFLICT(player_id) DO UPDATE SET card_name = $2, rating = $3, max_rating = $4, icon = $5, title = $6, class = $7;`,
      [player.id, data.cardName, data.rating, data.maxRating, data.icon, data.title, data.class],
    );

    const promises = [];
    for (let i = 0; i < scores.length; i += 1) {
      const score = scores[i];
      if (score.difficulty === 0) {
        // Only update the song sequence, insert the category and song name.
        const songQuery = {
          name: 'insert-songs',
          text: `INSERT INTO laundry_songs
          (id, seq, category, name) VALUES ($1, $2, $3, $4)
          ON CONFLICT(id) DO UPDATE SET seq = $2;`,
          values: [score.songId, i, score.category, score.songName],
        };
        promises.push(client.query(songQuery));
      }
      const query = {
        name: 'insert-scores-recent',
        text: `INSERT INTO laundry_scores_recent
        (player_id, song_id, difficulty, score, raw_score, flag) VALUES ($1, $2, $3, $4, $5, $6)
        ON CONFLICT(player_id, song_id, difficulty) DO UPDATE SET score = $4, raw_score = $5, flag = $6;`,
        values: [player.id, score.songId, score.difficulty,
          score.score, score.rawScore, score.flag],
      };
      promises.push(client.query(query));
    }
    await Promise.all(promises);
    await client.query('COMMIT');
  } catch (e) {
    await client.query('ROLLBACK');
    throw e;
  } finally {
    client.release();
  }
  res.send(JSON.stringify({}));
}));
app.use('/api', router);
app.use((err, req, res, next) => { // eslint-disable-line no-unused-vars
  if (!err.exposed) {
    console.log(err); // eslint-disable-line no-console
    res.status(500).send(JSON.stringify({ err: 'internal' }));
  } else {
    res.status(err.status).send(JSON.stringify({ err: err.message }));
  }
});

app.listen(8585);
<|endoftext|>


<commit_before>var Ember = require('ember');

App = Ember.Application.create({
    ready: function() {
        Ember.$('title').text(this.get('config').name);
        console.log(this.get('config').name, 'is ready !');
    }
});

App.Router.map(function() {
    this.resource('type', { path: '/' }, function() {
        this.route('show', {path: '/:type/:id'});
        this.route('edit', {path: '/:type/:id/edit'});
        this.route('list', {path: '/:type'});
        this.route('new', {path: '/:type/new'});
    });
});

App.ApplicationRoute = Ember.Route.extend({
    model: function() {
        return App;
    }
});

App.ApplicationController = Ember.Controller.extend({
    modelNames: function() {
        var _modelNames = [];
        for (var modelName in App.config.schemas){
            _modelNames.push({classified: modelName.camelize().capitalize(), underscored: modelName.underscore()});
        }
        return _modelNames;
    }.property('App.config.schemas')
});

App.TypeListRoute = Ember.Route.extend({
    model: function(params) {
        return {type: params.type, results: ['TODO']};
        // var type = _.str.classify(params.type);
        // return new Ember.RSVP.Promise(function(resolve, reject) {
        //     App.db[type].find({}, function(err, data) {
        //         if(err) {
        //             return reject(err);
        //         }
        //         else{
        //             var objects = [];
        //             data.forEach(function(item) {
        //                 objects.push(item.toJSONObject());
        //             });
        //             var model = {type: params.type, objects: objects, data:data};
        //             resolve(model);
        //         }
        //     });
        // });
    },
    renderTemplate: function(controller, model) {
        var template = 'type/list';
        console.log(model);
        if (Ember.TEMPLATES[model.type+'/list']) {
            template = model.type+'/list';
        }
        return this.render(template);
    }
});

App.IndexRoute = Ember.Route.extend({
  model: function() {
    return ['red', 'yellow', 'blue'];
  }
});

Ember.TEMPLATES = require('./templates');
for (var templateName in Ember.TEMPLATES){
    Ember.TEMPLATES[templateName.replace('.', '/')] = Ember.TEMPLATES[templateName];
    delete Ember.TEMPLATES[templateName];
}

module.exports = (function(config){
    App.initializer({
        name: "oreka",

        initialize: function(container, application) {
            application.register('oreka:config', config, {instantiate: false});
            application.inject('route', 'config', 'oreka:config');
            application.set('config', config);

        }
    });
    return App;
});<commit_msg>drop hack for template name<commit_after>var Ember = require('ember');

App = Ember.Application.create({
    ready: function() {
        Ember.$('title').text(this.get('config').name);
        console.log(this.get('config').name, 'is ready !');
    }
});

App.Router.map(function() {
    this.resource('type', { path: '/' }, function() {
        this.route('show', {path: '/:type/:id'});
        this.route('edit', {path: '/:type/:id/edit'});
        this.route('new', {path: '/:type/new'});
        this.route('list', {path: '/:type'});
    });
});

App.ApplicationRoute = Ember.Route.extend({
    model: function() {
        return App;
    }
});

App.ApplicationController = Ember.Controller.extend({
    modelNames: function() {
        var _modelNames = [];
        for (var modelName in App.config.schemas){
            _modelNames.push({classified: modelName.camelize().capitalize(), underscored: modelName.underscore()});
        }
        return _modelNames;
    }.property('App.config.schemas')
});

App.TypeListRoute = Ember.Route.extend({
    model: function(params) {
        return {type: params.type, results: ['TODO']};
        // var type = _.str.classify(params.type);
        // return new Ember.RSVP.Promise(function(resolve, reject) {
        //     App.db[type].find({}, function(err, data) {
        //         if(err) {
        //             return reject(err);
        //         }
        //         else{
        //             var objects = [];
        //             data.forEach(function(item) {
        //                 objects.push(item.toJSONObject());
        //             });
        //             var model = {type: params.type, objects: objects, data:data};
        //             resolve(model);
        //         }
        //     });
        // });
    },
    renderTemplate: function(controller, model) {
        var template = 'type/list';
        console.log(model);
        if (Ember.TEMPLATES[model.type+'/list']) {
            template = model.type+'/list';
        }
        return this.render(template);
    }
});

App.IndexRoute = Ember.Route.extend({
  model: function() {
    return ['red', 'yellow', 'blue'];
  }
});

Ember.TEMPLATES = require('./templates');

module.exports = (function(config){
    App.initializer({
        name: "oreka",

        initialize: function(container, application) {
            application.register('oreka:config', config, {instantiate: false});
            application.inject('route', 'config', 'oreka:config');
            application.set('config', config);

        }
    });
    return App;
});<|endoftext|>


<commit_before>
var N = require('libnested')

function hasAll(set, keys) {
  return keys.every(function (k) {
    return !!set[k]
  })
}

function isString (s) {
  return 'string' === typeof s
}

function isEmpty (e) {
  for(var k in e) return false
  return true
}

function isFunction (f) {
  return 'function' === typeof f
}

var isArray = Array.isArray

var apply = require('./apply')

function filter(modules, fn) {
  if(Array.isArray(modules))
    return modules.filter(fn)
  var o = {}
    for(var k in modules)
      if(fn(modules[k], k, modules))
        o[k] = modules[k]
  return o
}

function append(obj, path, value) {
 var a = N.get(obj, path)
  if(!a) N.set(obj, path, a = [])
  a.push(value)
}

module.exports  = function combine () {
  //iterate over array, and collect new plugs which are satisfyable.

  var modules = [].slice.call(arguments).reduce(function (a, b) {
    for(var k in b)
      if(!b[k]) delete a[k]
      else      a[k] = b[k]
    return a
  }, {})

  var allNeeds = {}, allGives = {}
  for (var k in modules) {
    var module = modules[k]
    N.each(module.needs, function (v, path) {
      N.set(allNeeds, path, true)
    })
    if(isString(module.gives))
      N.set(allGives, [module.gives], true)
    else
      N.each(module.gives, function (v, path) {
        N.set(allGives, path, true)
      })
  }

  N.each(allNeeds, function (_, path) {
    if(!N.get(allGives, path))
      console.log('MISSING', path)
  })

  console.log("NEEDS", allNeeds)
  console.log("GIVES", allGives)

  //okay, instead of iterating over everything, in dependency order.
  //just create things in order added?

  var sockets = {}
  while (true) {
    var newSockets = {}
    //filter modules that have not been resolved yet.
    modules = filter(modules, function (module, key) {
      //if this module cannot be resolved yet, keep it for next time.
//      if(!N.each(module.needs, function (type, path) {
//        if(!N.get(sockets, path)) return false
//      })) return true
//
      //collect the functions that this module needs.
      var m = N.map(module.needs, function (type, path) {
          var a = N.get(sockets, path)
          if(!a)
            a = N.set(sockets, path, [])
          return apply[type](a)
//          if(isArray(a)) return apply[type](a)
//          else           throw new Error('expected array at path:'+path.join('.'))
        })

      //create module, and get function(s) it returns.
      var exported = module.create(m)

      //for the functions it declares, merge these into newSockets
      if(isString(module.gives))
        append(newSockets, [module.gives], exported)
      else
        N.each(module.gives, function (_, path) {
          var fun = N.get(exported, path)
          if(!isFunction(fun))
            throw new Error('export declared but not returned'+path.join('.') + ' in:'+key)
          append(newSockets, path, fun)
        })
    })

    if(isEmpty(newSockets)) {
      console.log(sockets, modules)
      throw new Error('could not resolve all modules')
    }
    else
      N.each(newSockets, function (_ary, path) {
        var ary = N.get(sockets, path) || N.set(sockets, path, [])
        _ary.forEach(function (e) { ary.push(e) })
      })
    if(isEmpty(modules))
      return sockets
  }
}

<commit_msg>helpful error messages<commit_after>
var N = require('libnested')

function hasAll(set, keys) {
  return keys.every(function (k) {
    return !!set[k]
  })
}

function isString (s) {
  return 'string' === typeof s
}

function isEmpty (e) {
  for(var k in e) return false
  return true
}

function isFunction (f) {
  return 'function' === typeof f
}

var isArray = Array.isArray

var apply = require('./apply')

function filter(modules, fn) {
  if(Array.isArray(modules))
    return modules.filter(fn)
  var o = {}
    for(var k in modules)
      if(fn(modules[k], k, modules))
        o[k] = modules[k]
  return o
}

function append(obj, path, value) {
 var a = N.get(obj, path)
  if(!a) N.set(obj, path, a = [])
  a.push(value)
}

module.exports  = function combine () {
  //iterate over array, and collect new plugs which are satisfyable.

  var modules = [].slice.call(arguments).reduce(function (a, b) {
    for(var k in b)
      if(!b[k]) delete a[k]
      else      a[k] = b[k]
    return a
  }, {})

  var allNeeds = {}, allGives = {}
  for (var k in modules) {
    var module = modules[k]
    N.each(module.needs, function (v, path) {
      N.set(allNeeds, path, true)
    })
    if(isString(module.gives))
      N.set(allGives, [module.gives], true)
    else
      N.each(module.gives, function (v, path) {
        N.set(allGives, path, true)
      })
  }

  N.each(allNeeds, function (_, path) {
    if(!N.get(allGives, path))
      console.log('MISSING', path)
  })

  console.log("NEEDS", allNeeds)
  console.log("GIVES", allGives)

  //okay, instead of iterating over everything, in dependency order.
  //just create things in order added?

  var sockets = {}
  while (true) {
    var newSockets = {}
    //filter modules that have not been resolved yet.
    modules = filter(modules, function (module, key) {
      //if this module cannot be resolved yet, keep it for next time.
//      if(!N.each(module.needs, function (type, path) {
//        if(!N.get(sockets, path)) return false
//      })) return true
//
      //collect the functions that this module needs.
      var m = N.map(module.needs, function (type, path) {
          var a = N.get(sockets, path)
          if(!a)
            a = N.set(sockets, path, [])
          return apply[type](a)
//          if(isArray(a)) return apply[type](a)
//          else           throw new Error('expected array at path:'+path.join('.'))
        })

      //create module, and get function(s) it returns.
      if(!isFunction(module.create))
        throw new Error('module:'+key + ' did not have a create function')
      var exported = module.create(m)

      //for the functions it declares, merge these into newSockets
      if(isString(module.gives))
        append(newSockets, [module.gives], exported)
      else
        N.each(module.gives, function (_, path) {
          var fun = N.get(exported, path)
          if(!isFunction(fun))
            throw new Error('export declared but not returned'+path.join('.') + ' in:'+key)
          append(newSockets, path, fun)
        })
    })

    if(isEmpty(newSockets)) {
      console.log(sockets, modules)
      throw new Error('could not resolve all modules')
    }
    else
      N.each(newSockets, function (_ary, path) {
        var ary = N.get(sockets, path) || N.set(sockets, path, [])
        _ary.forEach(function (e) { ary.push(e) })
      })
    if(isEmpty(modules))
      return sockets
  }
}

<|endoftext|>


<commit_before>'use strict';

var colors = require('colors'),
    util = require('util'),
    q = require('q');

/**
 * ConsoleTransport class. Transport for the console.
 * @param {Object}  configs An object containing configurations to initialize the Transport
 * @param {Array}   configs.levels A list of levels that the transport has to log. By default every message are logged at each level
 * @param {Boolean} configs.timestamp Flag to allow timestamp in the log. True by default
 * @param {Boolean} configs.colorize Flag to allow colors in the log. True by default
 * @param {Object}  configs.colors A map of level-color. Each level is logged colored by his color
 * @returns {ConsoleTransport} A new ConsoleTransport instance
 * @constructor
 */
function ConsoleTransport (configs) {
    var me = this;

    configs = configs || {};
    me.levels = configs.levels || [];
    me.timestamp = configs.timestamp || true;
    me.colorize = configs.colorize || true;
    me.colors = {
        info: 'green',
        warning: 'yellow',
        error: 'red'
    };

    if (configs.colors) {
        me.colors = configs.colors;
        colors.setTheme(me.colors);
    }

    /**
     * It logs a message at the specified level
     * @param {String} level The level the logger has to log
     * @param {String} message The message to log
     * @param {Object} metadata An object containing extra data to log
     * @param {Function} callback A callback function called after logging
     * @returns {Promise} A promise resolved or rejected
     */
    me.log = function (level, message, metadata, callback, deferred) {
        deferred = deferred || q.defer();

        if (me.levels.length === 0 || (me.levels.length > 0 && me.levels.indexOf(level) > -1)) {
            var prefix = me.timestamp ? ('[' + (new Date()).toJSON() + ' - ' + level + ']: ') : ('[' + level + ']: '),
                msg = prefix + message;

            if (metadata) msg += ' ' + util.inspect(metadata);
            if (me.colorize && me.colors[level].length > 0) msg = msg[me.colors[level]];

            console.log(msg);

            if (typeof callback === 'function') callback(null, msg);
            deferred.resolve(msg);
        }

        return deferred.promise;
    };

    return me;
};

module.exports = ConsoleTransport;
<commit_msg>added semantic methods<commit_after>'use strict';

var colors = require('colors'),
    util = require('util'),
    q = require('q');

/**
 * ConsoleTransport class. Transport for the console.
 * @param {Object}  configs An object containing configurations to initialize the Transport
 * @param {Array}   configs.levels A list of levels that the transport has to log. By default every message are logged at each level
 * @param {Boolean} configs.timestamp Flag to allow timestamp in the log. True by default
 * @param {Boolean} configs.colorize Flag to allow colors in the log. True by default
 * @param {Object}  configs.colors A map of level-color. Each level is logged colored by his color
 * @returns {ConsoleTransport} A new ConsoleTransport instance
 * @constructor
 */
function ConsoleTransport (configs) {
    var me = this;

    configs = configs || {};
    me.levels = configs.levels || ['info', 'warning', 'error'];
    me.timestamp = configs.timestamp || true;
    me.colorize = configs.colorize || true;
    me.colors = {
        info: 'green',
        warning: 'yellow',
        error: 'red'
    };

    if (configs.colors) {
        me.colors = configs.colors;
        colors.setTheme(me.colors);
    }

    me.levels.forEach(function (level) {
        me[level] = function (message, metadata, callback) {
            return me.log(level, message, metadata, callback);
        };
    });

    /**
     * It logs a message at the specified level
     * @param {String} level The level the logger has to log
     * @param {String} message The message to log
     * @param {Object} metadata An object containing extra data to log
     * @param {Function} callback A callback function called after logging
     * @returns {Promise} A promise resolved or rejected
     */
    me.log = function (level, message, metadata, callback, deferred) {
        deferred = deferred || q.defer();

        if (me.levels.length === 0 || (me.levels.length > 0 && me.levels.indexOf(level) > -1)) {
            var prefix = me.timestamp ? ('[' + (new Date()).toJSON() + ' - ' + level + ']: ') : ('[' + level + ']: '),
                msg = prefix + message;

            if (metadata) msg += ' ' + util.inspect(metadata);
            if (me.colorize && me.colors[level].length > 0) msg = msg[me.colors[level]];

            console.log(msg);

            if (typeof callback === 'function') callback(null, msg);
            deferred.resolve(msg);
        }

        return deferred.promise;
    };

    return me;
};

module.exports = ConsoleTransport;
<|endoftext|>


<commit_before>/*var express = require('express');
var app = express();
var http = require('http').Server(app);*/
var express = require('express');
var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);
var shortid = require('shortid');
var this_user_id;
shortid.characters('0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_');

app.get('/cache.manifest', function(req, res){
  res.header("Content-Type", "text/cache-manifest");
  res.sendFile(__dirname + '/public/cache.manifest');
  console.log('cache in use');
});

app.use(express.static(__dirname + '/public'));

io.on('connection', function(socket){
  socket.on('chat message', function(msg){
    console.log('message: ' + msg);
    this_user_id = shortid.generate();
    socket.emit('player_id', this_user_id);
  });

  socket.on('player_info', function(pid, posFromLeft, facing, velocity, display_name){
    //console.log('player id: ' + pid + ' with position ' + posFromLeft + ' facing ' + facing + ' with velocity ' + velocity);

    //prevent html tag and javascript
    display_name = display_name.replace(/</g, "<").replace(/>/g, ">");

    socket.broadcast.emit('other_players', pid, posFromLeft, facing, velocity, display_name);
  });

  socket.on('disconnect', function(){
    socket.broadcast.emit('disconnect_player', this_user_id);
    console.log('disconnect player ' + this_user_id);
  });
});

http.listen(3000, function(){
  console.log('listening on *:3000');
});

<commit_msg>For heroku<commit_after>/*var express = require('express');
var app = express();
var http = require('http').Server(app);*/
var express = require('express');
var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);
var shortid = require('shortid');
var this_user_id;
shortid.characters('0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_');

app.get('/cache.manifest', function(req, res){
  res.header("Content-Type", "text/cache-manifest");
  res.sendFile(__dirname + '/public/cache.manifest');
  console.log('cache in use');
});

app.use(express.static(__dirname + '/public'));

io.on('connection', function(socket){
  socket.on('chat message', function(msg){
    console.log('message: ' + msg);
    this_user_id = shortid.generate();
    socket.emit('player_id', this_user_id);
  });

  socket.on('player_info', function(pid, posFromLeft, facing, velocity, display_name){
    //console.log('player id: ' + pid + ' with position ' + posFromLeft + ' facing ' + facing + ' with velocity ' + velocity);

    //prevent html tag and javascript
    display_name = display_name.replace(/</g, "<").replace(/>/g, ">");

    socket.broadcast.emit('other_players', pid, posFromLeft, facing, velocity, display_name);
  });

  socket.on('disconnect', function(){
    socket.broadcast.emit('disconnect_player', this_user_id);
    console.log('disconnect player ' + this_user_id);
  });
});

http.listen(process.env.PORT, function(){
  console.log('listening on *:' + process.env.PORT);
});

<|endoftext|>


<commit_before>var merge = require('lodash.merge');
var Primus = require('primus');
var PrimusResponder = require('primus-responder');
var VirtualRequest = require('express-virtual-request').request;
var VirtualResponse = require('express-virtual-request').response;
var debug = require('debug')('express-websocket');

module.exports = function initExpressWebsocket(expressApp, server, opts) {
  var options = merge({transformer: 'engine.io'}, opts);

  debug('Init');
  var primus = new Primus(server, options);
  primus.use('responder', PrimusResponder);

  primus.on('connection', function(spark) {
    debug('[' + spark.id + ']', 'connected from', spark.address.ip);

    spark.on('request', function(jreq, done) {

      // check if its a json-web-request
      if(typeof jreq !== 'object' || !jreq.url || jreq.type !== 'json-web-request') {
        debug('['+spark.id+']', 'request is not a json-web-request, ignoring');
        return;
      }

      jreq.method = jreq.method ? jreq.method.toUpperCase() : 'GET';
      jreq = merge({
        method: 'GET',
        url: '/',
        headers: {
          'Accept': 'application/json',
        },
        connection: {
          remoteAddress: spark.address,
          encrypted: false // TODO: is the ws connection httpS?
        },
        isWebsocket: true,
        spark: spark,
        primus: primus
      }, {headers: spark.headers}, jreq);

      var req = new VirtualRequest(jreq);
      var res = new VirtualResponse(req);
      res.on('finish', function() {
        done({
          status: res.statusMessage,
          statusCode: res.statusCode,
          headers: res.headers,
          body: res.body
        });
        debug('[' + spark.id + '] response:', res.statusCode, res.statusMessage);
      });

      if(options.beforeExpress) {
        debug('[' + spark.id + '] invoke beforeExpress hook');
        options.beforeExpress(req, res, function(err) {
          if(err) return;
          debug('[' + spark.id + '] request:', req.method, req.url);
          expressApp.handle(req, res);
        });
      } else {
        debug('[' + spark.id + '] request:', req.method, req.url);
        expressApp.handle(req, res);
      }
    });
  });

  return primus;
};<commit_msg>Parse json-body<commit_after>var merge = require('lodash.merge');
var Primus = require('primus');
var PrimusResponder = require('primus-responder');
var VirtualRequest = require('express-virtual-request').request;
var VirtualResponse = require('express-virtual-request').response;
var debug = require('debug')('express-websocket');

module.exports = function initExpressWebsocket(expressApp, server, opts) {
  var options = merge({transformer: 'engine.io'}, opts);

  debug('Init');
  var primus = new Primus(server, options);
  primus.use('responder', PrimusResponder);

  primus.on('connection', function(spark) {
    debug('[' + spark.id + ']', 'connected from', spark.address.ip);

    spark.on('request', function(jreq, done) {

      // check if its a json-web-request
      if(typeof jreq !== 'object' || !jreq.url || jreq.type !== 'json-web-request') {
        debug('['+spark.id+']', 'request is not a json-web-request, ignoring');
        return;
      }

      jreq.method = jreq.method ? jreq.method.toUpperCase() : 'GET';
      jreq = merge({
        method: 'GET',
        url: '/',
        headers: {
          'Accept': 'application/json',
        },
        connection: {
          remoteAddress: spark.address,
          encrypted: false // TODO: is the ws connection httpS?
        },
        isWebsocket: true,
        spark: spark,
        primus: primus
      }, {headers: spark.headers}, jreq);

      var req = new VirtualRequest(jreq);
      var res = new VirtualResponse(req);
      res.on('finish', function() {
        // try to decode body-json
        if(res.headers['Content-Type'] && res.headers['Content-Type'].indexOf('application/json') > -1) {
          try {
            res.body = JSON.parse(res.body);
          } catch(e) {}
        }

        done({
          status: res.statusMessage,
          statusCode: res.statusCode,
          headers: res.headers,
          body: res.body
        });
        debug('[' + spark.id + '] response:', res.statusCode, res.statusMessage);
      });

      if(options.beforeExpress) {
        debug('[' + spark.id + '] invoke beforeExpress hook');
        options.beforeExpress(req, res, function(err) {
          if(err) return;
          debug('[' + spark.id + '] request:', req.method, req.url);
          expressApp.handle(req, res);
        });
      } else {
        debug('[' + spark.id + '] request:', req.method, req.url);
        expressApp.handle(req, res);
      }
    });
  });

  return primus;
};
<|endoftext|>


<commit_before>'use strict';

/**
 * Module dependencies
 */

var path = require('path');
var base = require('base-methods');
var Base = base.namespace('data');
var proto = Base.prototype;
var utils = require('./utils');

/**
 * Expose `Store`
 */

module.exports =  Store;

/**
 * Initialize a new `Store` with the given `name`
 * and `options`.
 *
 * ```js
 * var store = require('data-store')('abc');
 * //=> '~/data-store/a.json'
 *
 * var store = require('data-store')('abc', {
 *   cwd: 'test/fixtures'
 * });
 * //=> './test/fixtures/abc.json'
 * ```
 *
 * @param  {String} `name` Store name.
 * @param  {Object} `options`
 *   @option {String} [options] `cwd` Current working directory for storage. If not defined, the user home directory is used, based on OS. This is the only option currently, other may be added in the future.
 *   @option {Number} [options] `indent` Number passed to `JSON.stringify` when saving the data. Defaults to `2` if `null` or `undefined`
 * @api public
 */

function Store(name, options) {
  if (typeof name !== 'string') {
    throw new TypeError('expected a string as the first argument');
  }
  if (!(this instanceof Store)) {
    return new Store(name, options);
  }

  Base.call(this);
  this.options = options || {};
  var cwd = utils.resolve(this.options.cwd || '~/data-store');

  this.name = name;
  this.path = path.join(cwd, name + '.json');
  this.data = readFile(this.path);
}

/**
 * Inherit `Base`
 */

Base.extend(Store);

/**
 * Assign `value` to `key` and save to disk. Can be
 * a key-value pair or an object.
 *
 * ```js
 * // key, value
 * store.set('a', 'b');
 * //=> {a: 'b'}
 *
 * // extend the store with an object
 * store.set({a: 'b'});
 * //=> {a: 'b'}
 *
 * // extend the the given value
 * store.set('a', {b: 'c'});
 * store.set('a', {d: 'e'}, true);
 * //=> {a: {b 'c', d: 'e'}}
 *
 * // overwrite the the given value
 * store.set('a', {b: 'c'});
 * store.set('a', {d: 'e'});
 * //=> {d: 'e'}
 * ```
 * @param {String} `key`
 * @param {any} `val` The value to save to `key`. Must be a valid JSON type: String, Number, Array or Object.
 * @return {Object} `Store` for chaining
 * @api public
 */

Store.prototype.set = function(key, val) {
  proto.set.apply(this, arguments);
  this.save();
  return this;
};

/**
 * Add or append an array of unique values to the given `key`.
 *
 * ```js
 * store.union('a', ['a']);
 * store.union('a', ['b']);
 * store.union('a', ['c']);
 * store.get('a');
 * //=> ['a', 'b', 'c']
 * ```
 *
 * @param  {String} `key`
 * @return {any} The array to add or append for `key`.
 * @api public
 */

Store.prototype.union = function (key, val) {
  utils.union(this.data, key, val);
  this.emit('union', key, val);
  this.save();
  return this;
};

/**
 * Get the stored `value` of `key`, or return the entire store
 * if no `key` is defined.
 *
 * ```js
 * store.set('a', {b: 'c'});
 * store.get('a');
 * //=> {b: 'c'}
 *
 * store.get();
 * //=> {b: 'c'}
 * ```
 *
 * @param  {String} `key`
 * @return {any} The value to store for `key`.
 * @api public
 */

Store.prototype.get = function (key) {
  return key ? proto.get.call(this, key) : {
    name: this.name,
    data: this.data
  };
};

/**
 * Returns `true` if the specified `key` has truthy value.
 *
 * ```js
 * store.set('a', 'b');
 * store.set('c', null);
 * store.has('a'); //=> true
 * store.has('c'); //=> false
 * store.has('d'); //=> false
 * ```
 *
 * @param  {String} `key`
 * @return {Boolean} Returns true if `key` has
 * @api public
 */

Store.prototype.has = function(key) {
  return utils.has(this.data, key);
};

/**
 * Returns `true` if the specified `key` exists.
 *
 * ```js
 * store.set('a', 'b');
 * store.set('b', false);
 * store.set('c', null);
 * store.set('d', true);
 *
 * store.hasOwn('a'); //=> true
 * store.hasOwn('b'); //=> true
 * store.hasOwn('c'); //=> true
 * store.hasOwn('d'); //=> true
 * store.hasOwn('foo'); //=> false
 * ```
 *
 * @param  {String} `key`
 * @return {Boolean} Returns true if `key` exists
 * @api public
 */

Store.prototype.hasOwn = function(key) {
  if (key.indexOf('.') === -1) {
    return this.data.hasOwnProperty(key);
  }
  return utils.hasOwn(this.data, key);
};

/**
 * Persist the store to disk.
 *
 * ```js
 * store.save();
 * ```
 * @param {String} `dest` Optionally define an alternate destination file path.
 * @api public
 */

Store.prototype.save = function(dest) {
  writeJson(dest || this.path, this.data, this.options.indent);
  return this;
};

/**
 * Delete `keys` from the store, or delete the entire store
 * if no keys are passed.
 *
 * **Note that to delete the entire store you must pass `{force: true}`**
 *
 * ```js
 * store.del();
 *
 * // to delete paths outside cwd
 * store.del({force: true});
 * ```
 *
 * @param {String|Array|Object} `keys` Keys to remove, or options.
 * @param {Object} `options`
 * @api public
 */

Store.prototype.del = function(keys, options) {
  var isArray = Array.isArray(keys);
  if (typeof keys === 'string' || isArray) {
    keys = utils.arrayify(keys);
  } else {
    options = keys;
    keys = null;
  }

  options = options || {};

  if (keys) {
    keys.forEach(function (key) {
      proto.del.call(this, key);
    }.bind(this));
    this.save();
    return this;
  }

  keys = Object.keys(this.data);
  if (options.force !== true) {
    throw new Error('options.force is required to delete the entire cache.');
  }

  // if no keys are passed, delete the entire store
  utils.del.sync(this.path, options);
  this.data = {};
  this.emit('del', keys);
  return this;
};

/**
 * Read JSON files.
 *
 * @param {String} `fp`
 * @return {Object}
 */

function readFile(fp) {
  try {
    var str = utils.fs.readFileSync(path.resolve(fp), 'utf8');
    return JSON.parse(str);
  } catch(err) {}
  return {};
}

/**
 * Synchronously write files to disk, also creating any
 * intermediary directories if they don't exist.
 *
 * @param {String} `dest`
 * @param {String} `str`
 * @param {Number} `indent` Indent passed to JSON.stringify (default 2)
 */

function writeJson(dest, str, indent) {
  if (typeof indent === 'undefined' || indent === null) {
    indent = 2;
  }
  var dir = path.dirname(dest);
  try {
    if (!utils.fs.existsSync(dir)) {
      utils.mkdirp.sync(dir);
    }
    utils.fs.writeFileSync(dest, JSON.stringify(str, null, indent));
  } catch (err) {
    err.origin = __filename;
    err.reason = 'data-store cannot write to: ' + dest;
    throw new Error(err);
  }
}
<commit_msg>adds events to `has` and `hasOwn`<commit_after>'use strict';

/**
 * Module dependencies
 */

var path = require('path');
var base = require('base-methods');
var Base = base.namespace('data');
var proto = Base.prototype;
var utils = require('./utils');

/**
 * Expose `Store`
 */

module.exports =  Store;

/**
 * Initialize a new `Store` with the given `name`
 * and `options`.
 *
 * ```js
 * var store = require('data-store')('abc');
 * //=> '~/data-store/a.json'
 *
 * var store = require('data-store')('abc', {
 *   cwd: 'test/fixtures'
 * });
 * //=> './test/fixtures/abc.json'
 * ```
 *
 * @param  {String} `name` Store name.
 * @param  {Object} `options`
 *   @option {String} [options] `cwd` Current working directory for storage. If not defined, the user home directory is used, based on OS. This is the only option currently, other may be added in the future.
 *   @option {Number} [options] `indent` Number passed to `JSON.stringify` when saving the data. Defaults to `2` if `null` or `undefined`
 * @api public
 */

function Store(name, options) {
  if (typeof name !== 'string') {
    throw new TypeError('expected a string as the first argument');
  }
  if (!(this instanceof Store)) {
    return new Store(name, options);
  }

  Base.call(this);
  this.options = options || {};
  var cwd = utils.resolve(this.options.cwd || '~/data-store');

  this.name = name;
  this.path = path.join(cwd, name + '.json');
  this.data = readFile(this.path);
}

/**
 * Inherit `Base`
 */

Base.extend(Store);

/**
 * Assign `value` to `key` and save to disk. Can be
 * a key-value pair or an object.
 *
 * ```js
 * // key, value
 * store.set('a', 'b');
 * //=> {a: 'b'}
 *
 * // extend the store with an object
 * store.set({a: 'b'});
 * //=> {a: 'b'}
 *
 * // extend the the given value
 * store.set('a', {b: 'c'});
 * store.set('a', {d: 'e'}, true);
 * //=> {a: {b 'c', d: 'e'}}
 *
 * // overwrite the the given value
 * store.set('a', {b: 'c'});
 * store.set('a', {d: 'e'});
 * //=> {d: 'e'}
 * ```
 * @param {String} `key`
 * @param {any} `val` The value to save to `key`. Must be a valid JSON type: String, Number, Array or Object.
 * @return {Object} `Store` for chaining
 * @api public
 */

Store.prototype.set = function(key, val) {
  proto.set.apply(this, arguments);
  this.save();
  return this;
};

/**
 * Add or append an array of unique values to the given `key`.
 *
 * ```js
 * store.union('a', ['a']);
 * store.union('a', ['b']);
 * store.union('a', ['c']);
 * store.get('a');
 * //=> ['a', 'b', 'c']
 * ```
 *
 * @param  {String} `key`
 * @return {any} The array to add or append for `key`.
 * @api public
 */

Store.prototype.union = function (key, val) {
  utils.union(this.data, key, val);
  this.emit('union', key, val);
  this.save();
  return this;
};

/**
 * Get the stored `value` of `key`, or return the entire store
 * if no `key` is defined.
 *
 * ```js
 * store.set('a', {b: 'c'});
 * store.get('a');
 * //=> {b: 'c'}
 *
 * store.get();
 * //=> {b: 'c'}
 * ```
 *
 * @param  {String} `key`
 * @return {any} The value to store for `key`.
 * @api public
 */

Store.prototype.get = function (key) {
  return key ? proto.get.call(this, key) : {
    name: this.name,
    data: this.data
  };
};

/**
 * Returns `true` if the specified `key` has truthy value.
 *
 * ```js
 * store.set('a', 'b');
 * store.set('c', null);
 * store.has('a'); //=> true
 * store.has('c'); //=> false
 * store.has('d'); //=> false
 * ```
 *
 * @param  {String} `key`
 * @return {Boolean} Returns true if `key` has
 * @api public
 */

Store.prototype.has = function(key) {
  var val = utils.has(this.data, key);
  this.emit('has', key, val);
  return val;
};

/**
 * Returns `true` if the specified `key` exists.
 *
 * ```js
 * store.set('a', 'b');
 * store.set('b', false);
 * store.set('c', null);
 * store.set('d', true);
 *
 * store.hasOwn('a'); //=> true
 * store.hasOwn('b'); //=> true
 * store.hasOwn('c'); //=> true
 * store.hasOwn('d'); //=> true
 * store.hasOwn('foo'); //=> false
 * ```
 *
 * @param  {String} `key`
 * @return {Boolean} Returns true if `key` exists
 * @api public
 */

Store.prototype.hasOwn = function(key) {
  var val;
  if (key.indexOf('.') === -1) {
    val = this.data.hasOwnProperty(key);
  } else {
    val = utils.hasOwn(this.data, key);
  }
  this.emit('hasOwn', key, val);
  return val;
};

/**
 * Persist the store to disk.
 *
 * ```js
 * store.save();
 * ```
 * @param {String} `dest` Optionally define an alternate destination file path.
 * @api public
 */

Store.prototype.save = function(dest) {
  writeJson(dest || this.path, this.data, this.options.indent);
  return this;
};

/**
 * Delete `keys` from the store, or delete the entire store
 * if no keys are passed. A `del` event is also emitted for each key
 * deleted.
 *
 * **Note that to delete the entire store you must pass `{force: true}`**
 *
 * ```js
 * store.del();
 *
 * // to delete paths outside cwd
 * store.del({force: true});
 * ```
 *
 * @param {String|Array|Object} `keys` Keys to remove, or options.
 * @param {Object} `options`
 * @api public
 */

Store.prototype.del = function(keys, options) {
  var isArray = Array.isArray(keys);
  if (typeof keys === 'string' || isArray) {
    keys = utils.arrayify(keys);
  } else {
    options = keys;
    keys = null;
  }

  options = options || {};

  if (keys) {
    keys.forEach(function (key) {
      proto.del.call(this, key);
    }.bind(this));
    this.save();
    return this;
  }

  if (options.force !== true) {
    throw new Error('options.force is required to delete the entire cache.');
  }

  keys = Object.keys(this.data);

  // if no keys are passed, delete the entire store
  utils.del.sync(this.path, options);
  this.data = {};
  keys.forEach(function (key) {
    this.emit('del', key);
  }.bind(this));
  return this;
};

/**
 * Read JSON files.
 *
 * @param {String} `fp`
 * @return {Object}
 */

function readFile(fp) {
  try {
    var str = utils.fs.readFileSync(path.resolve(fp), 'utf8');
    return JSON.parse(str);
  } catch(err) {}
  return {};
}

/**
 * Synchronously write files to disk, also creating any
 * intermediary directories if they don't exist.
 *
 * @param {String} `dest`
 * @param {String} `str`
 * @param {Number} `indent` Indent passed to JSON.stringify (default 2)
 */

function writeJson(dest, str, indent) {
  if (typeof indent === 'undefined' || indent === null) {
    indent = 2;
  }
  var dir = path.dirname(dest);
  try {
    if (!utils.fs.existsSync(dir)) {
      utils.mkdirp.sync(dir);
    }
    utils.fs.writeFileSync(dest, JSON.stringify(str, null, indent));
  } catch (err) {
    err.origin = __filename;
    err.reason = 'data-store cannot write to: ' + dest;
    throw new Error(err);
  }
}
<|endoftext|>


<commit_before>#!/usr/bin/env node
const { spawn } = require('child_process');
const fs = require('fs');
const path = require('path');
const inquirer = require('inquirer');
const initialQuestions = require('./initialQuestions');
const cwd = path.resolve(process.cwd());

// Escape hatches below for exception files
const validFiles = { Dockerfile: true };
const validExtensions = {
  '.js': true,
  '.json': true,
  '.yml': true,
  '.sh': true
};
const ignoreFiles = { 'launch.json': true };
const _ = require('lodash');

// Only watch for <%= %> swaps, lodash template swaps ES6 templates by default
_.templateSettings.interpolate = /<%=([\s\S]+?)%>/g;

function walkSync(dir, filelist) {
  let files = fs.readdirSync(dir);
  filelist = filelist || [];
  files.forEach(file => {
    if (fs.statSync(path.join(dir, file)).isDirectory()) {
      filelist = walkSync(path.join(dir, file), filelist);
    } else {
      filelist.push({ path: path.join(dir, file), name: file });
    }
  });
  return filelist;
}

function cloneRepo(url, projectName) {
  return new Promise(resolve => {
    // Assumption: Any source repos will have a template branch that we can use
    console.log(`Cloning ${url} to ./${projectName}`);
    const clone = spawn('git', [`clone`, `-b`, `template`, url, projectName]);
    clone.on('data', data => {
      console.log(data);
    });

    clone.on('close', code => {
      console.log(`Finished cloning ${url} to ./${projectName}`);
      resolve();
    });

    clone.on('error', error => {
      throw error;
    });
  });
}

function deleteGitFolder(projectName) {
  return new Promise(resolve => {
    const pathToGit = path.join(cwd, `./${projectName}/.git`);
    console.log(`Removing .git folder from ${pathToGit}`);
    const del = spawn('rm', ['-rf', pathToGit]);
    del.on('data', data => {
      console.log(data);
    });

    del.on('close', code => {
      console.log(`Finished deleting .git folder`);
      resolve();
    });
  });
}

function readTemplateJson(projectName) {
  const pathToTemplateJson = path.join(cwd, `./${projectName}/template.json`);
  console.log(`Reading ${pathToTemplateJson}...`);
  return require(pathToTemplateJson);
}

function deleteTemplateJson(projectName) {
  const pathToTemplateJson = path.join(cwd, `./${projectName}/template.json`);
  fs.unlinkSync(pathToTemplateJson); // Bye felicia
}

function templateReplace(answers) {
  const pathToProject = path.join(cwd, `./${answers.projectName}`);
  let files = walkSync(pathToProject);
  files.forEach(file => {
    let extension = path.extname(file.name);
    if (
      (validExtensions[extension] || validFiles[file.name]) &&
      !ignoreFiles[file.name]
    ) {
      console.log(`Swapping template values for ${file.path}...`);
      let fileTemplate = _.template(fs.readFileSync(file.path));
      fs.writeFileSync(file.path, fileTemplate(answers), { encoding: 'utf8' });
    }
  });
}

function createEnvFile(projectName, answers) {
  const pathToEnvFile = path.join(cwd, `./${projectName}/.env`);
  let contents = Object.keys(answers)
    .map(answerKey => {
      return `${answerKey}=${answers[answerKey]}\n`
    })
    .reduce((previous, current) => {
      return previous.concat(current);
    }, '');

  fs.writeFileSync(pathToEnvFile, contents, { encoding: 'utf8' });
}

async function run() {
  try {
    let answers = await inquirer.prompt(initialQuestions);
    await cloneRepo(answers.gitRepoURL, answers.projectName);
    await deleteGitFolder(answers.projectName);
    let templateJson = readTemplateJson(answers.projectName);
    let templateAnswers = await inquirer.prompt(
      templateJson.questions
    );
    templateReplace(
      Object.assign(
        { ...answers, ...templateAnswers },
        { projectNameDocker: answers.projectName.replace(/-/g, '_') }
      )
    );

    if (templateJson['.env']) {
      let envAnswers = await inquirer.prompt(templateJson['.env']);
      createEnvFile(answers.projectName, envAnswers);
    }

    deleteTemplateJson(answers.projectName);
  } catch (error) {
    console.error(error);
  }
}

run();
<commit_msg>don't ignore launch.json, need it<commit_after>#!/usr/bin/env node
const { spawn } = require('child_process');
const fs = require('fs');
const path = require('path');
const inquirer = require('inquirer');
const initialQuestions = require('./initialQuestions');
const cwd = path.resolve(process.cwd());

// Escape hatches below for exception files
const validFiles = { Dockerfile: true };
const validExtensions = {
  '.js': true,
  '.json': true,
  '.yml': true,
  '.sh': true
};
const ignoreFiles = {};
const _ = require('lodash');

// Only watch for <%= %> swaps, lodash template swaps ES6 templates by default
_.templateSettings.interpolate = /<%=([\s\S]+?)%>/g;

function walkSync(dir, filelist) {
  let files = fs.readdirSync(dir);
  filelist = filelist || [];
  files.forEach(file => {
    if (fs.statSync(path.join(dir, file)).isDirectory()) {
      filelist = walkSync(path.join(dir, file), filelist);
    } else {
      filelist.push({ path: path.join(dir, file), name: file });
    }
  });
  return filelist;
}

function cloneRepo(url, projectName) {
  return new Promise(resolve => {
    // Assumption: Any source repos will have a template branch that we can use
    console.log(`Cloning ${url} to ./${projectName}`);
    const clone = spawn('git', [`clone`, `-b`, `template`, url, projectName]);
    clone.on('data', data => {
      console.log(data);
    });

    clone.on('close', code => {
      console.log(`Finished cloning ${url} to ./${projectName}`);
      resolve();
    });

    clone.on('error', error => {
      throw error;
    });
  });
}

function deleteGitFolder(projectName) {
  return new Promise(resolve => {
    const pathToGit = path.join(cwd, `./${projectName}/.git`);
    console.log(`Removing .git folder from ${pathToGit}`);
    const del = spawn('rm', ['-rf', pathToGit]);
    del.on('data', data => {
      console.log(data);
    });

    del.on('close', code => {
      console.log(`Finished deleting .git folder`);
      resolve();
    });
  });
}

function readTemplateJson(projectName) {
  const pathToTemplateJson = path.join(cwd, `./${projectName}/template.json`);
  console.log(`Reading ${pathToTemplateJson}...`);
  return require(pathToTemplateJson);
}

function deleteTemplateJson(projectName) {
  const pathToTemplateJson = path.join(cwd, `./${projectName}/template.json`);
  fs.unlinkSync(pathToTemplateJson); // Bye felicia
}

function templateReplace(answers) {
  const pathToProject = path.join(cwd, `./${answers.projectName}`);
  let files = walkSync(pathToProject);
  files.forEach(file => {
    let extension = path.extname(file.name);
    if (
      (validExtensions[extension] || validFiles[file.name]) &&
      !ignoreFiles[file.name]
    ) {
      console.log(`Swapping template values for ${file.path}...`);
      let fileTemplate = _.template(fs.readFileSync(file.path));
      fs.writeFileSync(file.path, fileTemplate(answers), { encoding: 'utf8' });
    }
  });
}

function createEnvFile(projectName, answers) {
  const pathToEnvFile = path.join(cwd, `./${projectName}/.env`);
  let contents = Object.keys(answers)
    .map(answerKey => {
      return `${answerKey}=${answers[answerKey]}\n`
    })
    .reduce((previous, current) => {
      return previous.concat(current);
    }, '');

  fs.writeFileSync(pathToEnvFile, contents, { encoding: 'utf8' });
}

async function run() {
  try {
    let answers = await inquirer.prompt(initialQuestions);
    await cloneRepo(answers.gitRepoURL, answers.projectName);
    await deleteGitFolder(answers.projectName);
    let templateJson = readTemplateJson(answers.projectName);
    let templateAnswers = await inquirer.prompt(
      templateJson.questions
    );
    templateReplace(
      Object.assign(
        { ...answers, ...templateAnswers },
        { projectNameDocker: answers.projectName.replace(/-/g, '_') }
      )
    );

    if (templateJson['.env']) {
      let envAnswers = await inquirer.prompt(templateJson['.env']);
      createEnvFile(answers.projectName, envAnswers);
    }

    deleteTemplateJson(answers.projectName);
  } catch (error) {
    console.error(error);
  }
}

run();
<|endoftext|>


<commit_before>//index.js
//sass-lifter-loader
//lift sass from dependencies and write css to fs
var webpack = require('webpack');
var path = require('path');
var fs = require('fs');
var loaderUtils = require("loader-utils");
var ExtractTextPlugin = require("extract-text-webpack-plugin");
var gutil = require('gulp-util');
var _ = require('lodash');
var sass = require('node-sass');
var CachePlugin = require("webpack/lib/CachePlugin");
var crypto = require('crypto');
var myCache = {};

//require common.js for node_modules (better for server)
var node_modules = fs.readdirSync('node_modules').filter(function(x) { return x !== '.bin' });
function node_externals(context, request, cb) {
    if(node_modules.indexOf(request) !== -1) {
        cb(null, 'commonjs ' + request);
        return;
    }
    cb();
}

var myWebpackConfig = {
    name: 'lift sass webpack',
    target: 'node',
    output: {
        libraryTarget: 'commonjs2',
        path: path.join(__dirname, 'example', 'dist'),
        filename: 'sass-lifter-loader-output'
    },
    resolve: {
        root: __dirname,
        fallback: __dirname + '/node_modules',
        modulesDirectories: ['node_modules'],
        extensions: ['', '.json', '.js', '.jsx', '.scss', '.png', '.jpg', '.jpeg', '.gif']
    },
    plugins: [
        new CachePlugin(myCache)
    ],
    resolveLoader: {
        root: __dirname,
        alias: {
            'lift-sass': 'passthru-loader',
            'passthru-loader': path.join(__dirname, 'passthru-loader')
        }
    },
    module: {
        loaders: [
                {
                    test: /\.scss$/,
                    loaders: [
                        'noop-loader'
                    ]
                }
                , {
                    test: /\.(jpe?g|png|gif|svg)$/i,
                    loaders: [
                        'passthru-loader'
                    ]
                }
                , {
                    test: /\.json$/,
                    loaders: ['json-loader']
                }
                , {
                    test: /\.jsx$/,
                    loaders: ['babel?optional[]=es7.classProperties']
                }
            ]
    },
    bail: true,
    cache: true,
    debug: true,
    externals: [{ 'react/addons' : true, 'newrelic' : true }, node_externals]
};

module.exports = function(moduleSource) {

    if(this.cacheable) this.cacheable();

    var query = loaderUtils.parseQuery(this.query);
    var testString = query.testString || 'scss';
    var re = new RegExp('' + testString + '', 'g');
    var callback = this.async();
    var self = this;
    var fileName = this.resourcePath.split('/').splice(-1)[0];
    var manifest = path.join(query.outputDir, query.manifest);
    var outputStyle = query.outputStyle || 'nested';

    gutil.log('sass-lifter: lifting', gutil.colors.blue(fileName));

    myWebpackConfig.entry = {
        'lift-sass-loader-entry': this.resourcePath
    };

    webpack(myWebpackConfig, function (err, stats) {

        if (err) throw err;

        stats.compilation.entries.map(function(entry) {

            var deps = entry.dependencies;
            //storage for recursive dependencies and output
            var visited = {};
            var cssOutput = [];

            function getNodes(root)  {
                //console.log('getNodes', root.userRequest);
                if (root.dependencies.length > 0) {
                    //console.log('has deps');
                    root.dependencies.forEach(function (child) {
                        //console.log('get child nodes');
                        if ( child.module && child.module.userRequest && !visited[child.module.userRequest]) {
                            visited[child.module.userRequest] = true;
                            getNodes(child.module);
                        }
                    });
                } else {
                    //console.log('no deps', root.userRequest);
                    visited[root.userRequest] = true;
                }
            }

            function replaceImages(source, options, cb) {

                var manifest = require(path.join(options.outputDir, options.manifest));
                var urlRE = new RegExp('[\\w.\\/\\-]*(png|gif|jpg|jpeg|svg)', 'gi');
                var urls = source.match(urlRE) || [];

                urls.map(function(url){
                    var fileRE = new RegExp(url);
                    var prefix = options.prefix || '';
                    if (manifest[url]) {
                        source = source.replace(fileRE, path.join(prefix, manifest[url]));
                    }
                });
                cb(source);
            }

            for (var i = 0; i < deps.length; i++) {
                //console.log('depsi', deps[i].userRequest);
                if (deps[i].userRequest) {
                    //console.log('deps.........', deps[i].module.userRequest);
                    getNodes(deps[i].module);
                }
            }

            //get paths for match
            var foundPaths = [];
            _.mapKeys(visited, function (value, key) {
                if (re.test(key.toString())) {
                    //console.log('scss', key);
                    foundPaths.push(key);
                }
            });

            for (var j = 0; j < foundPaths.length; j++) {

                self.addDependency(foundPaths[j]);

                var result = sass.renderSync({
                    file: foundPaths[j],
                    outputStyle: outputStyle
                });

                if (query.manifest) {
                    //console.log('replacing images', manifest);
                    replaceImages(result.css.toString(), query, function(str){
                        //console.log(str);
                        cssOutput.push(str);
                    });

                } else {
                    cssOutput.push(result.css.toString());
                }
            }

            //create outputs
            var fileOut = cssOutput.join('');
            var hash = crypto.createHash('md5').update(fileOut).digest('hex').substr(0, 8);
            var outputFileNameBasic = fileName.split('.')[0] +'-' + hash + '.css';
            var outputFileName = path.join(query.outputDir, outputFileNameBasic);
            var outputManifestFile = path.join(query.outputDir, 'sass-loader-manifest.json');

            //create current manifest
            var outputManifest = {};
            outputManifest[fileName.split('.')[0]] = outputFileNameBasic;

            //join with previous manifest
            try {
                var readManifest = fs.readFileSync(outputManifestFile, 'utf8');
                outputManifest = _.extend(outputManifest, JSON.parse(readManifest));
                //console.log('output manifest joined', outputManifest);
                try {
                    fs.writeFileSync(outputManifestFile, JSON.stringify(outputManifest), 'utf8');
                } catch (err) {
                    gutil.log('sass-lifter:', gutil.colors.red('error appending manifest'), err);
                }
            } catch (err) {
                gutil.log('sass-lifter:', gutil.colors.blue('manifest not found, creating manifest...'));
                try {
                    fs.writeFileSync(outputManifestFile, JSON.stringify(outputManifest), 'utf8');
                } catch(err) {
                    gutil.log('sass-lifter:', gutil.colors.red('could not create manifest'), err);
                }
            }

            //write css
            fs.writeFile(outputFileName, fileOut, function (err) {
                if (err) {
                    return console.log(err);
                }
                gutil.log('sass-lifter:', gutil.colors.green(outputFileNameBasic), 'was saved');
            });

            callback(null, moduleSource);

        });
    });

};<commit_msg>updating babel options<commit_after>//index.js
//sass-lifter-loader
//lift sass from dependencies and write css to fs
var webpack = require('webpack');
var path = require('path');
var fs = require('fs');
var loaderUtils = require("loader-utils");
var ExtractTextPlugin = require("extract-text-webpack-plugin");
var gutil = require('gulp-util');
var _ = require('lodash');
var sass = require('node-sass');
var CachePlugin = require("webpack/lib/CachePlugin");
var crypto = require('crypto');
var myCache = {};

//require common.js for node_modules (better for server)
var node_modules = fs.readdirSync('node_modules').filter(function(x) { return x !== '.bin' });
function node_externals(context, request, cb) {
    if(node_modules.indexOf(request) !== -1) {
        cb(null, 'commonjs ' + request);
        return;
    }
    cb();
}

var myWebpackConfig = {
    name: 'lift sass webpack',
    target: 'node',
    output: {
        libraryTarget: 'commonjs2',
        path: path.join(__dirname, 'example', 'dist'),
        filename: 'sass-lifter-loader-output'
    },
    resolve: {
        root: __dirname,
        fallback: __dirname + '/node_modules',
        modulesDirectories: ['node_modules'],
        extensions: ['', '.json', '.js', '.jsx', '.scss', '.png', '.jpg', '.jpeg', '.gif']
    },
    plugins: [
        new CachePlugin(myCache)
    ],
    resolveLoader: {
        root: __dirname,
        alias: {
            'lift-sass': 'passthru-loader',
            'passthru-loader': path.join(__dirname, 'passthru-loader')
        }
    },
    module: {
        loaders: [
                {
                    test: /\.scss$/,
                    loaders: [
                        'noop-loader'
                    ]
                }
                , {
                    test: /\.(jpe?g|png|gif|svg)$/i,
                    loaders: [
                        'passthru-loader'
                    ]
                }
                , {
                    test: /\.json$/,
                    loaders: ['json-loader']
                }
                , {
                    test: /\.jsx$/,
                    loader: 'babel',
                    query: {
                        optional: ['es7.classProperties']
                    }
                }
            ]
    },
    bail: true,
    cache: true,
    debug: true,
    externals: [{ 'react/addons' : true, 'newrelic' : true }, node_externals]
};

module.exports = function(moduleSource) {

    if(this.cacheable) this.cacheable();

    var query = loaderUtils.parseQuery(this.query);
    var testString = query.testString || 'scss';
    var re = new RegExp('' + testString + '', 'g');
    var callback = this.async();
    var self = this;
    var fileName = this.resourcePath.split('/').splice(-1)[0];
    var manifest = path.join(query.outputDir, query.manifest);
    var outputStyle = query.outputStyle || 'nested';

    gutil.log('sass-lifter: lifting', gutil.colors.blue(fileName));

    myWebpackConfig.entry = {
        'lift-sass-loader-entry': this.resourcePath
    };

    webpack(myWebpackConfig, function (err, stats) {

        if (err) throw err;

        stats.compilation.entries.map(function(entry) {

            var deps = entry.dependencies;
            //storage for recursive dependencies and output
            var visited = {};
            var cssOutput = [];

            function getNodes(root)  {
                //console.log('getNodes', root.userRequest);
                if (root.dependencies.length > 0) {
                    //console.log('has deps');
                    root.dependencies.forEach(function (child) {
                        //console.log('get child nodes');
                        if ( child.module && child.module.userRequest && !visited[child.module.userRequest]) {
                            visited[child.module.userRequest] = true;
                            getNodes(child.module);
                        }
                    });
                } else {
                    //console.log('no deps', root.userRequest);
                    visited[root.userRequest] = true;
                }
            }

            function replaceImages(source, options, cb) {

                var manifest = require(path.join(options.outputDir, options.manifest));
                var urlRE = new RegExp('[\\w.\\/\\-]*(png|gif|jpg|jpeg|svg)', 'gi');
                var urls = source.match(urlRE) || [];

                urls.map(function(url){
                    var fileRE = new RegExp(url);
                    var prefix = options.prefix || '';
                    if (manifest[url]) {
                        source = source.replace(fileRE, path.join(prefix, manifest[url]));
                    }
                });
                cb(source);
            }

            for (var i = 0; i < deps.length; i++) {
                //console.log('depsi', deps[i].userRequest);
                if (deps[i].userRequest) {
                    //console.log('deps.........', deps[i].module.userRequest);
                    getNodes(deps[i].module);
                }
            }

            //get paths for match
            var foundPaths = [];
            _.mapKeys(visited, function (value, key) {
                if (re.test(key.toString())) {
                    //console.log('scss', key);
                    foundPaths.push(key);
                }
            });

            for (var j = 0; j < foundPaths.length; j++) {

                self.addDependency(foundPaths[j]);

                var result = sass.renderSync({
                    file: foundPaths[j],
                    outputStyle: outputStyle
                });

                if (query.manifest) {
                    //console.log('replacing images', manifest);
                    replaceImages(result.css.toString(), query, function(str){
                        //console.log(str);
                        cssOutput.push(str);
                    });

                } else {
                    cssOutput.push(result.css.toString());
                }
            }

            //create outputs
            var fileOut = cssOutput.join('');
            var hash = crypto.createHash('md5').update(fileOut).digest('hex').substr(0, 8);
            var outputFileNameBasic = fileName.split('.')[0] +'-' + hash + '.css';
            var outputFileName = path.join(query.outputDir, outputFileNameBasic);
            var outputManifestFile = path.join(query.outputDir, 'sass-loader-manifest.json');

            //create current manifest
            var outputManifest = {};
            outputManifest[fileName.split('.')[0]] = outputFileNameBasic;

            //join with previous manifest
            try {
                var readManifest = fs.readFileSync(outputManifestFile, 'utf8');
                outputManifest = _.extend(outputManifest, JSON.parse(readManifest));
                //console.log('output manifest joined', outputManifest);
                try {
                    fs.writeFileSync(outputManifestFile, JSON.stringify(outputManifest), 'utf8');
                } catch (err) {
                    gutil.log('sass-lifter:', gutil.colors.red('error appending manifest'), err);
                }
            } catch (err) {
                gutil.log('sass-lifter:', gutil.colors.blue('manifest not found, creating manifest...'));
                try {
                    fs.writeFileSync(outputManifestFile, JSON.stringify(outputManifest), 'utf8');
                } catch(err) {
                    gutil.log('sass-lifter:', gutil.colors.red('could not create manifest'), err);
                }
            }

            //write css
            fs.writeFile(outputFileName, fileOut, function (err) {
                if (err) {
                    return console.log(err);
                }
                gutil.log('sass-lifter:', gutil.colors.green(outputFileNameBasic), 'was saved');
            });

            callback(null, moduleSource);

        });
    });

};<|endoftext|>


<commit_before>var schemeSweet = (function () {
  'use strict';

  const fs = require('fs');
  const plist = require('plist');
  const tinycolor = require('tinycolor2');
  const uuid = require('uuid');
  var template = require('./template.js');

  const AUTHOR = 'Scheme Sweet (https://github.com/briles/scheme-sweet)';

  /**
   * The `SchemeSweet` class builds a tmTheme by populating a
   * template with colors specified in a palette and optional metadata
   *
   * @class SchemeSweet
   * @constructor
   * @param {object} options configuration object
   */
  var SchemeSweet = function (options) {
    if (!(this instanceof SchemeSweet)) {
      return new SchemeSweet(arguments);
    }

    this._palette = this._paletteToHex(options.palette);
    this._metadata = options.metadata || {
      name: '',
      author: AUTHOR,
      comment: 'Made by Scheme Sweet',
    };

    return this;
  };

  /**
   * Converts the tmTheme to plist XML
   * @return {string} the tmTheme as plist XML
   */
  SchemeSweet.prototype.buildTmTheme = function () {
    if (!this._tmTheme) {
      this._prepareTemplate();
    }

    return plist.build(this._tmTheme);
  };

  /**
   * Writes the tmTheme to a file
   * @param  {string} filepath the path where the file will be written
   */
  SchemeSweet.prototype.writeTmTheme = function (filepath) {
    if (typeof filepath !== 'string') {
      throw new Error(
        'Expected "filepath" to be string, was "' + typeof filepath + '"'
      );
    }

    var tmTheme = this.buildTmTheme();
    fs.writeFileSync(filepath, tmTheme, 'utf-8');
  };

  /**
   * Converts colors in the palette to Hex or Hex8 strings
   * @private
   * @param  {object} palette the palette to transform
   * @return {obj}         the modified palette
   */
  SchemeSweet.prototype._paletteToHex = function (palette) {
    for (var color in palette) {
      var colorObj = tinycolor(palette[color]);

      if (!colorObj.isValid()) {
        throw new Error(
          '"' + palette[color] + '" is not a valid tinycolor color'
        );
      }

      palette[color] = colorObj._a !== 1
                     ? colorObj.toSublimeHex8String()
                     : colorObj.toHexString();
    }

    return palette;
  };

  /**
   * populates the instance template with colors & metadata
   * @private
   */
  SchemeSweet.prototype._prepareTemplate = function () {
    var _tmTheme = this._tmTheme;
    _tmTheme = template(this._palette);
    _tmTheme.name = this._metadata.name;
    _tmTheme.author = this._metadata.author;
    _tmTheme.comment = this._metadata.comment;
    _tmTheme.uuid = uuid.v4();

    // Join the scope arrays so Sublime Text can parse them
    _tmTheme.settings.slice(1).forEach(function (group, index) {
      index += 1;

      if (isArray(group.scope)) {
        _tmTheme.settings[index].scope = group.scope.sort().join(',');
      }
    });

    this._tmTheme = _tmTheme;
  };

  /**
   * Converts tinycolor color to Hex8 string suitable for Sublime Text.
   * Sublime Text expects the alpha channel at the end of the string:
   * IE: #000000FF instead of #FF000000
   * @private
   * @return {string} the color string as Hex8
   */
  tinycolor.prototype.toSublimeHex8String = function () {
    var hex = this.toHex8();
    return '#' + hex.slice(2) + hex.slice(0, 2);
  };

  /**
   * tests if is an Array
   * @private
   * @param  {any} arr
   * @return {boolean}
   */
  var isArray = Array.isArray || function (arr) {
    return Object.prototype.toString.call(arr) === '[object Array]';
  };

  return SchemeSweet;
}());

module.exports = schemeSweet;
<commit_msg>Used var instead of const<commit_after>var schemeSweet = (function () {
  'use strict';

  var fs = require('fs');
  var plist = require('plist');
  var tinycolor = require('tinycolor2');
  var uuid = require('uuid');
  var template = require('./template.js');

  var AUTHOR = 'Scheme Sweet (https://github.com/briles/scheme-sweet)';

  /**
   * The `SchemeSweet` class builds a tmTheme by populating a
   * template with colors specified in a palette and optional metadata
   *
   * @class SchemeSweet
   * @constructor
   * @param {object} options configuration object
   */
  var SchemeSweet = function (options) {
    if (!(this instanceof SchemeSweet)) {
      return new SchemeSweet(arguments);
    }

    this._palette = this._paletteToHex(options.palette);
    this._metadata = options.metadata || {
      name: '',
      author: AUTHOR,
      comment: 'Made by Scheme Sweet',
    };

    return this;
  };

  /**
   * Converts the tmTheme to plist XML
   * @return {string} the tmTheme as plist XML
   */
  SchemeSweet.prototype.buildTmTheme = function () {
    if (!this._tmTheme) {
      this._prepareTemplate();
    }

    return plist.build(this._tmTheme);
  };

  /**
   * Writes the tmTheme to a file
   * @param  {string} filepath the path where the file will be written
   */
  SchemeSweet.prototype.writeTmTheme = function (filepath) {
    if (typeof filepath !== 'string') {
      throw new Error(
        'Expected "filepath" to be string, was "' + typeof filepath + '"'
      );
    }

    var tmTheme = this.buildTmTheme();
    fs.writeFileSync(filepath, tmTheme, 'utf-8');
  };

  /**
   * Converts colors in the palette to Hex or Hex8 strings
   * @private
   * @param  {object} palette the palette to transform
   * @return {obj}         the modified palette
   */
  SchemeSweet.prototype._paletteToHex = function (palette) {
    for (var color in palette) {
      var colorObj = tinycolor(palette[color]);

      if (!colorObj.isValid()) {
        throw new Error(
          '"' + palette[color] + '" is not a valid tinycolor color'
        );
      }

      palette[color] = colorObj._a !== 1
                     ? colorObj.toSublimeHex8String()
                     : colorObj.toHexString();
    }

    return palette;
  };

  /**
   * populates the instance template with colors & metadata
   * @private
   */
  SchemeSweet.prototype._prepareTemplate = function () {
    var _tmTheme = this._tmTheme;
    _tmTheme = template(this._palette);
    _tmTheme.name = this._metadata.name;
    _tmTheme.author = this._metadata.author;
    _tmTheme.comment = this._metadata.comment;
    _tmTheme.uuid = uuid.v4();

    // Join the scope arrays so Sublime Text can parse them
    _tmTheme.settings.slice(1).forEach(function (group, index) {
      index += 1;

      if (isArray(group.scope)) {
        _tmTheme.settings[index].scope = group.scope.sort().join(',');
      }
    });

    this._tmTheme = _tmTheme;
  };

  /**
   * Converts tinycolor color to Hex8 string suitable for Sublime Text.
   * Sublime Text expects the alpha channel at the end of the string:
   * IE: #000000FF instead of #FF000000
   * @private
   * @return {string} the color string as Hex8
   */
  tinycolor.prototype.toSublimeHex8String = function () {
    var hex = this.toHex8();
    return '#' + hex.slice(2) + hex.slice(0, 2);
  };

  /**
   * tests if is an Array
   * @private
   * @param  {any} arr
   * @return {boolean}
   */
  var isArray = Array.isArray || function (arr) {
    return Object.prototype.toString.call(arr) === '[object Array]';
  };

  return SchemeSweet;
}());

module.exports = schemeSweet;
<|endoftext|>