feat: Use prettier-eslint to format code

This commit is contained in:
Bouncey
2019-02-18 19:32:49 +00:00
committed by mrugesh mohapatra
parent 1ba67c4e2b
commit b13e5fb41a
82 changed files with 1767 additions and 1017 deletions

View File

@ -115,10 +115,10 @@ export default function(UserIdent) {
return identity
? Observable.of(identity.user())
: User.findOne$({ where: { email } }).flatMap(user => {
return user
? Observable.of(user)
: User.create$({ email }).toPromise();
});
return user
? Observable.of(user)
: User.create$({ email }).toPromise();
});
})
.flatMap(user => {
const createToken = observeQuery(AccessToken, 'create', {

View File

@ -2,11 +2,8 @@ import { Observable } from 'rx';
export default function(Block) {
Block.on('dataSourceAttached', () => {
Block.findOne$ =
Observable.fromNodeCallback(Block.findOne, Block);
Block.findById$ =
Observable.fromNodeCallback(Block.findById, Block);
Block.find$ =
Observable.fromNodeCallback(Block.find, Block);
Block.findOne$ = Observable.fromNodeCallback(Block.findOne, Block);
Block.findById$ = Observable.fromNodeCallback(Block.findById, Block);
Block.find$ = Observable.fromNodeCallback(Block.find, Block);
});
}

View File

@ -1,10 +1,8 @@
import _ from 'lodash';
export const alertTypes = _.keyBy([
'success',
'info',
'warning',
'danger'
], _.identity);
export const alertTypes = _.keyBy(
['success', 'info', 'warning', 'danger'],
_.identity
);
export const normalizeAlertType = alertType => alertTypes[alertType] || 'info';

View File

@ -1,15 +1,9 @@
import emptyProtector from './empty-protector';
export function checkMapData(
{
entities: {
challenge,
block,
superBlock
},
result: { superBlocks }
}
) {
export function checkMapData({
entities: { challenge, block, superBlock },
result: { superBlocks }
}) {
if (
!challenge ||
!block ||
@ -17,9 +11,7 @@ export function checkMapData(
!superBlocks ||
!superBlocks.length
) {
throw new Error(
'entities not found, db may not be properly seeded'
);
throw new Error('entities not found, db may not be properly seeded');
}
}
// getFirstChallenge(
@ -33,11 +25,8 @@ export function getFirstChallenge({
result: { superBlocks }
}) {
return challenge[
emptyProtector(block[
emptyProtector(superBlock[
superBlocks[0]
]).blocks[0]
]).challenges[0]
emptyProtector(block[emptyProtector(superBlock[superBlocks[0]]).blocks[0]])
.challenges[0]
];
}
@ -52,12 +41,10 @@ export function getFirstChallenge({
// };
export function createNameIdMap({ challenge }) {
return {
challengeIdToName: Object.keys(challenge)
.reduce((map, challengeName) => {
map[challenge[challengeName].id] =
challenge[challengeName].dashedName;
return map;
}, {})
challengeIdToName: Object.keys(challenge).reduce((map, challengeName) => {
map[challenge[challengeName].id] = challenge[challengeName].dashedName;
return map;
}, {})
};
}
// addNameIdMap(

View File

@ -3,14 +3,11 @@ import invariant from 'invariant';
import { Observable } from 'rx';
import castToObservable from '../../server/utils/cast-to-observable';
// createFileStream(
// files: [...PolyVinyl]
// ) => Observable[...Observable[...PolyVinyl]]
export function createFileStream(files = []) {
return Observable.of(
Observable.from(files)
);
return Observable.of(Observable.from(files));
}
// Observable::pipe(
@ -20,8 +17,8 @@ export function createFileStream(files = []) {
// ) => Observable[...Observable[...PolyVinyl]]
export function pipe(project) {
const source = this;
return source.map(
files => files.flatMap(file => castToObservable(project(file)))
return source.map(files =>
files.flatMap(file => castToObservable(project(file)))
);
}
@ -44,24 +41,10 @@ export function pipe(project) {
// contents: String,
// history?: [...String],
// }) => PolyVinyl, throws
export function createPoly({
name,
ext,
contents,
history,
...rest
} = {}) {
invariant(
typeof name === 'string',
'name must be a string but got %s',
name
);
export function createPoly({ name, ext, contents, history, ...rest } = {}) {
invariant(typeof name === 'string', 'name must be a string but got %s', name);
invariant(
typeof ext === 'string',
'ext must be a string, but was %s',
ext
);
invariant(typeof ext === 'string', 'ext must be a string, but was %s', ext);
invariant(
typeof contents === 'string',
@ -71,7 +54,7 @@ export function createPoly({
return {
...rest,
history: Array.isArray(history) ? history : [ name + ext ],
history: Array.isArray(history) ? history : [name + ext],
name,
ext,
path: name + '.' + ext,
@ -83,11 +66,13 @@ export function createPoly({
// isPoly(poly: Any) => Boolean
export function isPoly(poly) {
return poly &&
return (
poly &&
typeof poly.contents === 'string' &&
typeof poly.name === 'string' &&
typeof poly.ext === 'string' &&
Array.isArray(poly.history);
Array.isArray(poly.history)
);
}
// checkPoly(poly: Any) => Void, throws
@ -125,7 +110,7 @@ export function setExt(ext, poly) {
path: poly.name + '.' + ext,
key: poly.name + ext
};
newPoly.history = [ ...poly.history, newPoly.path ];
newPoly.history = [...poly.history, newPoly.path];
return newPoly;
}
@ -138,7 +123,7 @@ export function setName(name, poly) {
path: name + '.' + poly.ext,
key: name + poly.ext
};
newPoly.history = [ ...poly.history, newPoly.path ];
newPoly.history = [...poly.history, newPoly.path];
return newPoly;
}
@ -177,10 +162,12 @@ export function appendToTail(tail, poly) {
// compileHeadTail(padding: String, poly: PolyVinyl) => PolyVinyl
export function compileHeadTail(padding = '', poly) {
return clearHeadTail(transformContents(
() => [ poly.head, poly.contents, poly.tail ].join(padding),
poly
));
return clearHeadTail(
transformContents(
() => [poly.head, poly.contents, poly.tail].join(padding),
poly
)
);
}
// transformContents(
@ -192,10 +179,7 @@ export function compileHeadTail(padding = '', poly) {
// already contains a source, this version will continue as
// the source property
export function transformContents(wrap, poly) {
const newPoly = setContent(
wrap(poly.contents),
poly
);
const newPoly = setContent(wrap(poly.contents), poly);
// if no source exist, set the original contents as source
newPoly.source = poly.source || poly.contents;
return newPoly;
@ -207,10 +191,7 @@ export function transformContents(wrap, poly) {
// ) => PolyVinyl
export function transformHeadTailAndContents(wrap, poly) {
return {
...transformContents(
wrap,
poly
),
...transformContents(wrap, poly),
head: wrap(poly.head),
tail: wrap(poly.tail)
};

View File

@ -3,8 +3,7 @@ export const themes = {
default: 'default'
};
export const invertTheme = currentTheme => (
!currentTheme || currentTheme === themes.default ?
themes.night :
themes.default
);
export const invertTheme = currentTheme =>
!currentTheme || currentTheme === themes.default
? themes.night
: themes.default;

View File

@ -16,7 +16,5 @@ module.exports = {
transform: {
'^.+\\.js$': 'babel-jest'
},
transformIgnorePatterns: [
'node_modules/(?!(gatsby)/)'
]
transformIgnorePatterns: ['node_modules/(?!(gatsby)/)']
};

View File

@ -350,9 +350,8 @@ function createShowCert(app) {
messages: [
{
type: 'info',
message: `We could not find a user with the username "${
username
}"`
message:
'We could not find a user with the username "' + username + '"'
}
]
});

View File

@ -321,7 +321,7 @@ export default async function bootChallenge(app, done) {
) {
req.flash(
'danger',
'You haven\'t supplied the necessary URLs for us to inspect your work.'
"You haven't supplied the necessary URLs for us to inspect your work."
);
return res.sendStatus(403);
}

View File

@ -6,23 +6,13 @@ import dedent from 'dedent';
import { homeLocation } from '../../../config/env';
import nonprofits from '../utils/commit.json';
import {
commitGoals,
completeCommitment$
} from '../utils/commit';
import { commitGoals, completeCommitment$ } from '../utils/commit';
import {
unDasherize
} from '../utils';
import { unDasherize } from '../utils';
import {
observeQuery,
saveInstance
} from '../utils/rx';
import { observeQuery, saveInstance } from '../utils/rx';
import {
ifNoUserRedirectTo
} from '../utils/middleware';
import { ifNoUserRedirectTo } from '../utils/middleware';
const sendNonUserToSignIn = ifNoUserRedirectTo(
`${homeLocation}/signin`,
@ -41,12 +31,12 @@ const debug = debugFactory('fcc:commit');
function findNonprofit(name) {
let nonprofit;
if (name) {
nonprofit = _.find(nonprofits, (nonprofit) => {
nonprofit = _.find(nonprofits, nonprofit => {
return name === nonprofit.name;
});
}
nonprofit = nonprofit || nonprofits[ _.random(0, nonprofits.length - 1) ];
nonprofit = nonprofit || nonprofits[_.random(0, nonprofits.length - 1)];
return nonprofit;
}
@ -55,33 +45,15 @@ export default function commit(app) {
const api = app.loopback.Router();
const { Pledge } = app.models;
router.get(
'/commit',
commitToNonprofit
);
router.get('/commit', commitToNonprofit);
router.get(
'/commit/pledge',
sendNonUserToSignIn,
pledge
);
router.get('/commit/pledge', sendNonUserToSignIn, pledge);
router.get(
'/commit/directory',
renderDirectory
);
router.get('/commit/directory', renderDirectory);
api.post(
'/commit/stop-commitment',
sendNonUserToCommit,
stopCommit
);
api.post('/commit/stop-commitment', sendNonUserToCommit, stopCommit);
api.post(
'/commit/complete-goal',
sendNonUserToCommit,
completeCommitment
);
api.post('/commit/complete-goal', sendNonUserToCommit, completeCommitment);
app.use(api);
app.use(router);
@ -101,33 +73,26 @@ export default function commit(app) {
}
return Observable.just();
})
.subscribe(
pledge => {
if (pledge) {
debug('found previous pledge');
req.flash(
'info',
dedent`
.subscribe(pledge => {
if (pledge) {
debug('found previous pledge');
req.flash(
'info',
dedent`
Looks like you already have a pledge to ${pledge.displayName}.
Clicking "Commit" here will replace your old commitment. If you
do change your commitment, please remember to cancel your
previous recurring donation directly with ${pledge.displayName}.
`
);
}
res.render(
'commit/',
{
title: 'Commit to a nonprofit. Commit to your goal.',
pledge,
...commitGoals,
...nonprofit
}
);
},
next
);
}
res.render('commit/', {
title: 'Commit to a nonprofit. Commit to your goal.',
pledge,
...commitGoals,
...nonprofit
});
}, next);
}
function pledge(req, res, next) {
@ -143,14 +108,12 @@ export default function commit(app) {
observeQuery(user, 'pledge')
.flatMap(oldPledge => {
// create new pledge for user
const pledge = Pledge(
{
amount,
goal,
userId: user.id,
...nonprofit
}
);
const pledge = Pledge({
amount,
goal,
userId: user.id,
...nonprofit
});
if (oldPledge) {
debug('user already has pledge, creating a new one');
@ -159,28 +122,24 @@ export default function commit(app) {
oldPledge.formerUser = user.id;
oldPledge.endDate = new Date();
oldPledge.isOrphaned = true;
return saveInstance(oldPledge)
.flatMap(() => {
return saveInstance(pledge);
});
return saveInstance(oldPledge).flatMap(() => {
return saveInstance(pledge);
});
}
return saveInstance(pledge);
})
.subscribe(
({ displayName, goal, amount }) => {
req.flash(
'success',
dedent`
.subscribe(({ displayName, goal, amount }) => {
req.flash(
'success',
dedent`
Congratulations, you have committed to giving
${displayName} $${amount} each month until you have completed
your ${goal}. Please remember to cancel your pledge directly
with ${displayName} once you finish.
`
);
res.redirect('/' + user.username);
},
next
);
);
res.redirect('/' + user.username);
}, next);
}
function renderDirectory(req, res) {
@ -193,16 +152,12 @@ export default function commit(app) {
function completeCommitment(req, res, next) {
const { user } = req;
return completeCommitment$(user)
.subscribe(
msgOrPledge => {
if (typeof msgOrPledge === 'string') {
return res.send(msgOrPledge);
}
return res.send(true);
},
next
);
return completeCommitment$(user).subscribe(msgOrPledge => {
if (typeof msgOrPledge === 'string') {
return res.send(msgOrPledge);
}
return res.send(true);
}, next);
}
function stopCommit(req, res, next) {
@ -220,23 +175,20 @@ export default function commit(app) {
pledge.dateEnded = new Date();
return saveInstance(pledge);
})
.subscribe(
pledge => {
let msg = dedent`
.subscribe(pledge => {
let msg = dedent`
You have successfully stopped your pledge. Please
remember to cancel your recurring donation directly
with the nonprofit if you haven't already done so.
`;
if (!pledge) {
msg = dedent`
if (!pledge) {
msg = dedent`
It doesn't look like you had an active pledge, so
there's no pledge to stop.
`;
}
req.flash('info', msg);
return res.redirect(`/${user.username}`);
},
next
);
}
req.flash('info', msg);
return res.redirect(`/${user.username}`);
}, next);
}
}

View File

@ -6,7 +6,6 @@ import keys from '../../../config/secrets';
const log = debug('fcc:boot:donate');
export default function donateBoot(app, done) {
let stripe = false;
const { User } = app.models;
const api = app.loopback.Router();
@ -25,7 +24,8 @@ export default function donateBoot(app, done) {
currency: 'usd',
id: `monthly-donation-${current}`
}
}), {}
}),
{}
);
function connectToStripe() {
@ -70,23 +70,26 @@ export default function donateBoot(app, done) {
return res.status(400).send({ error: 'Amount Required' });
}
const { amount, token: {email, id} } = body;
const {
amount,
token: { email, id }
} = body;
const fccUser = user ?
Promise.resolve(user) :
new Promise((resolve, reject) =>
User.findOrCreate(
{ where: { email }},
{ email },
(err, instance, isNew) => {
log('is new user instance: ', isNew);
if (err) {
return reject(err);
}
return resolve(instance);
}
)
);
const fccUser = user
? Promise.resolve(user)
: new Promise((resolve, reject) =>
User.findOrCreate(
{ where: { email } },
{ email },
(err, instance, isNew) => {
log('is new user instance: ', isNew);
if (err) {
return reject(err);
}
return resolve(instance);
}
)
);
let donatingUser = {};
let donation = {
@ -96,14 +99,13 @@ export default function donateBoot(app, done) {
startDate: new Date(Date.now()).toISOString()
};
return fccUser.then(
user => {
return fccUser
.then(user => {
donatingUser = user;
return stripe.customers
.create({
email,
card: id
});
return stripe.customers.create({
email,
card: id
});
})
.then(customer => {
donation.customerId = customer.id;
@ -121,7 +123,9 @@ export default function donateBoot(app, done) {
return res.send(subscription);
})
.then(() => {
donatingUser.createDonation(donation).toPromise()
donatingUser
.createDonation(donation)
.toPromise()
.catch(err => {
throw new Error(err);
});

View File

@ -15,7 +15,7 @@ module.exports = function mountLoopBackExplorer(app) {
app.once('started', function() {
log(
'Run `npm install loopback-component-explorer` to enable ' +
'the LoopBack explorer'
'the LoopBack explorer'
);
});
return;

View File

@ -32,9 +32,7 @@ function createShortLinkHandler(app) {
if (!article) {
return res.redirect('/news');
}
const {
slugPart
} = article;
const { slugPart } = article;
const slug = `/news/${slugPart}`;
return res.redirect(slug);
}

View File

@ -88,7 +88,7 @@ module.exports = function(app) {
.then(() => {
req.flash(
'success',
'We\'ve successfully updated your email preferences.'
"We've successfully updated your email preferences."
);
return res.redirectWithFlash(
`${homeLocation}/unsubscribed/${unsubscribeId}`
@ -144,7 +144,7 @@ module.exports = function(app) {
.then(() => {
req.flash(
'success',
'We\'ve successfully updated your email preferences. Thank you ' +
"We've successfully updated your email preferences. Thank you " +
'for resubscribing.'
);
return res.redirectWithFlash(homeLocation);
@ -175,7 +175,7 @@ module.exports = function(app) {
}
pulls = pulls
? Object.keys(JSON.parse(pulls)).length
: 'Can\'t connect to github';
: "Can't connect to github";
return request(
[
@ -193,7 +193,7 @@ module.exports = function(app) {
issues =
pulls === parseInt(pulls, 10) && issues
? Object.keys(JSON.parse(issues)).length - pulls
: 'Can\'t connect to GitHub';
: "Can't connect to GitHub";
return res.send({
issues: issues,
pulls: pulls

View File

@ -1,6 +1,6 @@
export default function bootStatus(app) {
const api = app.loopback.Router();
api.get('/status/ping', (req, res) => res.json({msg: 'pong'}));
api.get('/status/ping', (req, res) => res.json({ msg: 'pong' }));
app.use(api);
}

View File

@ -5,8 +5,6 @@ module.exports = function(app) {
app.use(router);
function showForum(req, res) {
res.redirect(
'http://forum.freecodecamp.org/'
);
res.redirect('http://forum.freecodecamp.org/');
}
};

View File

@ -219,8 +219,7 @@ function createPostReportUserProfile(app) {
if (!username || !report || report === '') {
return res.json({
type: 'danger',
message:
'Oops, something is not right please re-check your submission.'
message: 'Oops, something is not right please re-check your submission.'
});
}
return Email.send$(

View File

@ -1,5 +1,7 @@
import passport from 'passport';
// eslint-disable-next-line
import {
// prettier ignore
PassportConfigurator
} from '@freecodecamp/loopback-component-passport';
import url from 'url';
@ -132,9 +134,7 @@ export function setupPassport(app) {
}
export const saveResponseAuthCookies = () => {
return (req, res, next) => {
const user = req.user;
if (!user) {
@ -157,7 +157,6 @@ export const saveResponseAuthCookies = () => {
};
export const loginRedirect = () => {
return (req, res) => {
const successRedirect = req => {
if (!!req && req.session && req.session.returnTo) {

View File

@ -11,11 +11,7 @@ const pathsOfNoReturn = [
'css'
];
const pathsWhiteList = [
'challenges',
'map',
'commit'
];
const pathsWhiteList = ['challenges', 'map', 'commit'];
const pathsOfNoReturnRegex = new RegExp(pathsOfNoReturn.join('|'), 'i');
const whiteListRegex = new RegExp(pathsWhiteList.join('|'), 'i');
@ -33,9 +29,9 @@ export default function addReturnToUrl() {
) {
return next();
}
req.session.returnTo = req.originalUrl.includes('/map') ?
'/' :
req.originalUrl;
req.session.returnTo = req.originalUrl.includes('/map')
? '/'
: req.originalUrl;
return next();
};
}

View File

@ -1,7 +1,8 @@
export default function constantHeaders() {
return function(req, res, next) {
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Headers',
res.header(
'Access-Control-Allow-Headers',
'Origin, X-Requested-With, Content-Type, Accept'
);
next();

View File

@ -3,7 +3,7 @@ import helmet from 'helmet';
import { homeLocation } from '../../../config/env';
let trusted = [
'\'self\'',
"'self'",
'https://search.freecodecamp.org',
homeLocation,
'https://' + process.env.AUTH0_DOMAIN
@ -31,8 +31,8 @@ export default function csp() {
'https://*.algolia.net'
]),
scriptSrc: [
'\'unsafe-eval\'',
'\'unsafe-inline\'',
"'unsafe-eval'",
"'unsafe-inline'",
'*.google-analytics.com',
'*.gstatic.com',
'https://*.cloudflare.com',
@ -48,7 +48,7 @@ export default function csp() {
'*.ytimg.com'
].concat(trusted),
styleSrc: [
'\'unsafe-inline\'',
"'unsafe-inline'",
'*.gstatic.com',
'*.googleapis.com',
'*.bootstrapcdn.com',

View File

@ -1,15 +1,12 @@
import csurf from 'csurf';
export default function() {
const protection = csurf(
{
cookie: {
domain: process.env.COOKIE_DOMAIN || 'localhost'
}
const protection = csurf({
cookie: {
domain: process.env.COOKIE_DOMAIN || 'localhost'
}
);
});
return function csrf(req, res, next) {
const path = req.path.split('/')[1];
if ((/(^api$|^unauthenticated$|^internal$|^p$)/).test(path)) {
return next();

View File

@ -14,7 +14,9 @@ export default function flashCheaters() {
if (
ALLOWED_METHODS.indexOf(req.method) !== -1 &&
EXCLUDED_PATHS.indexOf(req.path) === -1 &&
req.user && req.url !== '/' && req.user.isCheater
req.user &&
req.url !== '/' &&
req.user.isCheater
) {
req.flash(
'danger',

View File

@ -20,11 +20,13 @@ export default function() {
return false;
}
const keys = Object.keys(value);
return !!keys.length &&
return (
!!keys.length &&
// every key is a file
keys.every(key => isObject(value[key])) &&
// every file has contents
keys.map(key => value[key]).every(file => isPoly(file));
keys.map(key => value[key]).every(file => isPoly(file))
);
}
},
customSanitizers: {
@ -32,16 +34,20 @@ export default function() {
trimTags(value) {
const tagBody = '(?:[^"\'>]|"[^"]*"|\'[^\']*\')*';
const tagOrComment = new RegExp(
'<(?:'
// Comment body.
+ '!--(?:(?:-*[^->])*--+|-?)'
// Special "raw text" elements whose content should be elided.
+ '|script\\b' + tagBody + '>[\\s\\S]*?</script\\s*'
+ '|style\\b' + tagBody + '>[\\s\\S]*?</style\\s*'
// Regular name
+ '|/?[a-z]'
+ tagBody
+ ')>',
'<(?:' +
// Comment body.
'!--(?:(?:-*[^->])*--+|-?)' +
// Special "raw text" elements whose content should be elided.
'|script\\b' +
tagBody +
'>[\\s\\S]*?</script\\s*' +
'|style\\b' +
tagBody +
'>[\\s\\S]*?</style\\s*' +
// Regular name
'|/?[a-z]' +
tagBody +
')>',
'gi'
);
let rawValue;

View File

@ -1,6 +1,5 @@
import { createActiveUsers } from '../utils/about.js';
module.exports = function(About) {
const activeUsers = createActiveUsers();
let activeUsersForRendering = 0;
@ -14,17 +13,14 @@ module.exports = function(About) {
About.getActiveUsersForRendering = () => activeUsersForRendering;
About.remoteMethod(
'getActiveUsers',
{
http: {
path: '/get-active-users',
verb: 'get'
},
returns: {
type: 'number',
arg: 'activeUsers'
}
About.remoteMethod('getActiveUsers', {
http: {
path: '/get-active-users',
verb: 'get'
},
returns: {
type: 'number',
arg: 'activeUsers'
}
);
});
};

View File

@ -11,7 +11,6 @@ log.enabled = true;
// this is where server starts booting up
const app = require('./server');
let timeoutHandler;
let killTime = 15;

View File

@ -11,7 +11,6 @@ const fiveMinutes = 1000 * 60 * 5;
class NewsFeed {
constructor() {
this.state = {
readyState: false,
mediumFeed: [],
@ -27,26 +26,23 @@ class NewsFeed {
const newState = stateUpdater(this.state);
this.state = _.merge({}, this.state, newState);
return;
}
};
refreshFeeds = () => {
const currentFeed = this.state.combinedFeed.slice(0);
log('grabbing feeds');
return Promise.all([
getMediumFeed(),
getLybsynFeed()
]).then(
([mediumFeed, lybsynFeed]) => this.setState(
state => ({
return Promise.all([getMediumFeed(), getLybsynFeed()])
.then(([mediumFeed, lybsynFeed]) =>
this.setState(state => ({
...state,
mediumFeed,
lybsynFeed
})
))
}))
)
.then(() => {
log('crossing the streams');
const { mediumFeed, lybsynFeed} = this.state;
const combinedFeed = [ ...mediumFeed, ...lybsynFeed ].sort((a, b) => {
const { mediumFeed, lybsynFeed } = this.state;
const combinedFeed = [...mediumFeed, ...lybsynFeed].sort((a, b) => {
return compareDesc(a.isoDate, b.isoDate);
});
this.setState(state => ({
@ -62,25 +58,24 @@ class NewsFeed {
combinedFeed: currentFeed
}));
});
}
};
getFeed = () => new Promise((resolve) => {
getFeed = () =>
new Promise(resolve => {
let notReadyCount = 0;
function waitForReady() {
log('notReadyCount', notReadyCount);
notReadyCount++;
return this.state.readyState || notReadyCount === 5 ?
resolve(this.state.combinedFeed) :
setTimeout(waitForReady, 100);
return this.state.readyState || notReadyCount === 5
? resolve(this.state.combinedFeed)
: setTimeout(waitForReady, 100);
}
log('are we ready?', this.state.readyState);
return this.state.readyState ?
resolve(this.state.combinedFeed) :
setTimeout(waitForReady, 100);
})
return this.state.readyState
? resolve(this.state.combinedFeed)
: setTimeout(waitForReady, 100);
});
}
export default NewsFeed;

View File

@ -9,7 +9,6 @@ function getExtract(str) {
return str.slice(0, str.indexOf('</p>') + 4);
}
function addResponsiveClass(str) {
return str.replace(/<img/g, '<img class="img-responsive"');
}
@ -22,17 +21,15 @@ export function getMediumFeed() {
}
const items = feed.items
.map(
item => _.pick(item, ['title', 'link', 'isoDate', 'content:encoded'])
)
.map(
(item) => ({
...item,
extract: getExtract(item['content:encoded'])
})
.map(item =>
_.pick(item, ['title', 'link', 'isoDate', 'content:encoded'])
)
.map(item => ({
...item,
extract: getExtract(item['content:encoded'])
}))
.map(item => _.omit(item, ['content:encoded']))
.map(item => ({ ...item, extract: addResponsiveClass(item.extract)}));
.map(item => ({ ...item, extract: addResponsiveClass(item.extract) }));
resolve(items);
});
});

View File

@ -64,7 +64,7 @@ export function createActiveUsers() {
credentials['client_email'],
null,
credentials['private_key'],
[scope],
[scope]
);
const authorize = observeMethod(client, 'authorize');
const options = {
@ -89,7 +89,5 @@ export function createActiveUsers() {
.do(null, err => console.error(err))
// always send a number down
.catch(() => Observable.of(0))
// cache for 2 seconds to prevent hitting our daily request limit
::timeCache(2, 'seconds');
}

View File

@ -1,18 +1,18 @@
const githubRegex = (/github/i);
const githubRegex = /github/i;
const providerHash = {
facebook: ({ id }) => id,
github: ({ username }) => username,
twitter: ({ username }) => username,
linkedin({ _json }) {
return _json && _json.publicProfileUrl || null;
return (_json && _json.publicProfileUrl) || null;
},
google: ({ id }) => id
};
export function getUsernameFromProvider(provider, profile) {
return typeof providerHash[provider] === 'function' ?
providerHash[provider](profile) :
null;
return typeof providerHash[provider] === 'function'
? providerHash[provider](profile)
: null;
}
// createProfileAttributes(provider: String, profile: {}) => Object
@ -32,13 +32,7 @@ function createProfileAttributesFromGithub(profile) {
const {
profileUrl: githubProfile,
username,
_json: {
avatar_url: picture,
blog: website,
location,
bio,
name
} = {}
_json: { avatar_url: picture, blog: website, location, bio, name } = {}
} = profile;
return {
name,

View File

@ -20,36 +20,34 @@ export function completeCommitment$(user) {
isInfosecQaCert
} = user;
return Observable.fromNodeCallback(user.pledge, user)()
.flatMap(pledge => {
if (!pledge) {
return Observable.just('No pledge found');
}
return Observable.fromNodeCallback(user.pledge, user)().flatMap(pledge => {
if (!pledge) {
return Observable.just('No pledge found');
}
const { goal } = pledge;
const { goal } = pledge;
if (
(isFrontEndCert && goal === commitGoals.frontEndCert) ||
(isBackEndCert && goal === commitGoals.backEndCert) ||
(isFullStackCert && goal === commitGoals.fullStackCert) ||
(isRespWebDesignCert && goal === commitGoals.respWebDesignCert) ||
(isFrontEndLibsCert && goal === commitGoals.frontEndLibsCert) ||
(isJsAlgoDataStructCert && goal === commitGoals.jsAlgoDataStructCert) ||
(isDataVisCert && goal === commitGoals.dataVisCert) ||
(isApisMicroservicesCert &&
goal === commitGoals.apisMicroservicesCert) ||
(isInfosecQaCert && goal === commitGoals.infosecQaCert)
) {
debug('marking goal complete');
pledge.isCompleted = true;
pledge.dateEnded = new Date();
pledge.formerUserId = pledge.userId;
pledge.userId = null;
return Observable.fromNodeCallback(pledge.save, pledge)();
}
return Observable.just(dedent`
if (
(isFrontEndCert && goal === commitGoals.frontEndCert) ||
(isBackEndCert && goal === commitGoals.backEndCert) ||
(isFullStackCert && goal === commitGoals.fullStackCert) ||
(isRespWebDesignCert && goal === commitGoals.respWebDesignCert) ||
(isFrontEndLibsCert && goal === commitGoals.frontEndLibsCert) ||
(isJsAlgoDataStructCert && goal === commitGoals.jsAlgoDataStructCert) ||
(isDataVisCert && goal === commitGoals.dataVisCert) ||
(isApisMicroservicesCert && goal === commitGoals.apisMicroservicesCert) ||
(isInfosecQaCert && goal === commitGoals.infosecQaCert)
) {
debug('marking goal complete');
pledge.isCompleted = true;
pledge.dateEnded = new Date();
pledge.formerUserId = pledge.userId;
pledge.userId = null;
return Observable.fromNodeCallback(pledge.save, pledge)();
}
return Observable.just(dedent`
You have not yet reached your goal of completing the ${goal}
Please retry when you have met the requirements.
`);
});
});
}

View File

@ -8,25 +8,20 @@ export function unwrapHandledError(err) {
return err[_handledError] || {};
}
export function wrapHandledError(err, {
type,
message,
redirectTo,
status = 200
}) {
export function wrapHandledError(
err,
{ type, message, redirectTo, status = 200 }
) {
err[_handledError] = { type, message, redirectTo, status };
return err;
}
// for use with express-validator error formatter
export const createValidatorErrorFormatter = (type, redirectTo) =>
({ msg }) => wrapHandledError(
new Error(msg),
{
type,
message: msg,
redirectTo,
// we default to 400 as these are malformed requests
status: 400
}
);
export const createValidatorErrorFormatter = (type, redirectTo) => ({ msg }) =>
wrapHandledError(new Error(msg), {
type,
message: msg,
redirectTo,
// we default to 400 as these are malformed requests
status: 400
});

View File

@ -3,9 +3,16 @@ import moment from 'moment-timezone';
// day count between two epochs (inclusive)
export function dayCount([head, tail], timezone = 'UTC') {
return Math.ceil(
moment(moment(head).tz(timezone).endOf('day')).diff(
moment(tail).tz(timezone).startOf('day'),
moment(
moment(head)
.tz(timezone)
.endOf('day')
).diff(
moment(tail)
.tz(timezone)
.startOf('day'),
'days',
true)
true
)
);
}

View File

@ -1,8 +1,4 @@
export default [
'auth',
'services',
'link'
].reduce((throughs, route) => {
export default ['auth', 'services', 'link'].reduce((throughs, route) => {
throughs[route] = true;
return throughs;
}, {});

View File

@ -32,64 +32,59 @@ const getFirstChallenge = _.once(_getFirstChallenge);
*/
export function _cachedMap({ Block, Challenge }) {
const challenges = Challenge.find$({
order: [ 'order ASC', 'suborder ASC' ],
order: ['order ASC', 'suborder ASC'],
where: { isPrivate: false }
});
const challengeMap = challenges
.map(
challenges => challenges
.map(challenge => challenge.toJSON())
.reduce((hash, challenge) => {
hash[challenge.dashedName] = challenge;
return hash;
}, {})
);
const challengeMap = challenges.map(challenges =>
challenges
.map(challenge => challenge.toJSON())
.reduce((hash, challenge) => {
hash[challenge.dashedName] = challenge;
return hash;
}, {})
);
const blocks = Block.find$({
order: [ 'superOrder ASC', 'order ASC' ],
order: ['superOrder ASC', 'order ASC'],
where: { isPrivate: false }
});
const blockMap = Observable.combineLatest(
blocks.map(
blocks => blocks
.map(block => block.toJSON())
.reduce((hash, block) => {
hash[block.dashedName] = block;
return hash;
}, {})
blocks.map(blocks =>
blocks.map(block => block.toJSON()).reduce((hash, block) => {
hash[block.dashedName] = block;
return hash;
}, {})
),
challenges
)
.map(([ blocksMap, challenges ]) => {
return challenges.reduce((blocksMap, challenge) => {
if (blocksMap[challenge.block].challenges) {
blocksMap[challenge.block].challenges.push(challenge.dashedName);
} else {
blocksMap[challenge.block] = {
...blocksMap[challenge.block],
challenges: [ challenge.dashedName ]
};
}
return blocksMap;
}, blocksMap);
});
const superBlockMap = blocks.map(blocks => blocks.reduce((map, block) => {
if (
map[block.superBlock] &&
map[block.superBlock].blocks
) {
map[block.superBlock].blocks.push(block.dashedName);
} else {
map[block.superBlock] = {
title: _.startCase(block.superBlock),
order: block.superOrder,
name: nameify(_.startCase(block.superBlock)),
dashedName: block.superBlock,
blocks: [block.dashedName],
message: block.superBlockMessage
};
}
return map;
}, {}));
).map(([blocksMap, challenges]) => {
return challenges.reduce((blocksMap, challenge) => {
if (blocksMap[challenge.block].challenges) {
blocksMap[challenge.block].challenges.push(challenge.dashedName);
} else {
blocksMap[challenge.block] = {
...blocksMap[challenge.block],
challenges: [challenge.dashedName]
};
}
return blocksMap;
}, blocksMap);
});
const superBlockMap = blocks.map(blocks =>
blocks.reduce((map, block) => {
if (map[block.superBlock] && map[block.superBlock].blocks) {
map[block.superBlock].blocks.push(block.dashedName);
} else {
map[block.superBlock] = {
title: _.startCase(block.superBlock),
order: block.superOrder,
name: nameify(_.startCase(block.superBlock)),
dashedName: block.superBlock,
blocks: [block.dashedName],
message: block.superBlockMessage
};
}
return map;
}, {})
);
const superBlocks = superBlockMap.map(superBlockMap => {
return Object.keys(superBlockMap)
.map(key => superBlockMap[key])
@ -126,30 +121,25 @@ export function getChallengeById(map, id) {
return Observable.if(
() => !id,
map.map(getFirstChallenge),
map.map(addNameIdMap)
.map(map => {
const {
entities: { challenge: challengeMap, challengeIdToName }
} = map;
let finalChallenge;
const dashedName = challengeIdToName[id];
finalChallenge = challengeMap[dashedName];
if (!finalChallenge) {
finalChallenge = getFirstChallenge(map);
}
return finalChallenge;
})
map.map(addNameIdMap).map(map => {
const {
entities: { challenge: challengeMap, challengeIdToName }
} = map;
let finalChallenge;
const dashedName = challengeIdToName[id];
finalChallenge = challengeMap[dashedName];
if (!finalChallenge) {
finalChallenge = getFirstChallenge(map);
}
return finalChallenge;
})
);
}
export function getChallengeInfo(map) {
return map.map(addNameIdMap)
.map(({
entities: {
challenge: challengeMap,
challengeIdToName
}
}) => ({
return map
.map(addNameIdMap)
.map(({ entities: { challenge: challengeMap, challengeIdToName } }) => ({
challengeMap,
challengeIdToName
}));
@ -168,42 +158,37 @@ function loadComingSoonOrBetaChallenge({
// this is a hard search
// falls back to soft search
export function getChallenge(
challengeDashedName,
blockDashedName,
map) {
return map
.flatMap(({ entities, result: { superBlocks } }) => {
const superBlock = entities.superBlock;
const block = entities.block[blockDashedName];
const challenge = entities.challenge[challengeDashedName];
return Observable.if(
() => (
!blockDashedName ||
!block ||
!challenge ||
!loadComingSoonOrBetaChallenge(challenge)
),
getChallengeByDashedName(challengeDashedName, map),
Observable.just({ block, challenge })
)
.map(({ challenge, block }) => ({
redirect: challenge.block !== blockDashedName ?
`/challenges/${block.dashedName}/${challenge.dashedName}` :
false,
entities: {
superBlock,
challenge: {
[challenge.dashedName]: challenge
}
},
result: {
block: block.dashedName,
challenge: challenge.dashedName,
superBlocks
}
}));
});
export function getChallenge(challengeDashedName, blockDashedName, map) {
return map.flatMap(({ entities, result: { superBlocks } }) => {
const superBlock = entities.superBlock;
const block = entities.block[blockDashedName];
const challenge = entities.challenge[challengeDashedName];
return Observable.if(
() =>
!blockDashedName ||
!block ||
!challenge ||
!loadComingSoonOrBetaChallenge(challenge),
getChallengeByDashedName(challengeDashedName, map),
Observable.just({ block, challenge })
).map(({ challenge, block }) => ({
redirect:
challenge.block !== blockDashedName
? `/challenges/${block.dashedName}/${challenge.dashedName}`
: false,
entities: {
superBlock,
challenge: {
[challenge.dashedName]: challenge
}
},
result: {
block: block.dashedName,
challenge: challenge.dashedName,
superBlocks
}
}));
});
}
export function getBlockForChallenge(map, challenge) {
@ -211,19 +196,21 @@ export function getBlockForChallenge(map, challenge) {
}
export function getChallengeByDashedName(dashedName, map) {
const challengeName = unDasherize(dashedName)
.replace(challengesRegex, '');
const challengeName = unDasherize(dashedName).replace(challengesRegex, '');
const testChallengeName = new RegExp(challengeName, 'i');
return map
.map(({ entities }) => entities.challenge)
.flatMap(challengeMap => {
return Observable.from(Object.keys(challengeMap))
.map(key => challengeMap[key]);
return Observable.from(Object.keys(challengeMap)).map(
key => challengeMap[key]
);
})
.filter(challenge => {
return loadComingSoonOrBetaChallenge(challenge) &&
testChallengeName.test(challenge.name);
return (
loadComingSoonOrBetaChallenge(challenge) &&
testChallengeName.test(challenge.name)
);
})
.last({ defaultValue: null })
.flatMap(challengeOrNull => {
@ -234,8 +221,9 @@ export function getChallengeByDashedName(dashedName, map) {
);
})
.flatMap(challenge => {
return getBlockForChallenge(map, challenge)
.map(block => ({ challenge, block }));
return getBlockForChallenge(map, challenge).map(block => ({
challenge,
block
}));
});
}

View File

@ -57,9 +57,11 @@ export const userPropsForSession = [
export function normaliseUserFields(user) {
const about = user.bio && !user.about ? user.bio : user.about;
const picture = user.picture || addPlaceholderImage(user.username);
const twitter = user.twitter && isURL(user.twitter) ?
user.twitter :
user.twitter && `https://www.twitter.com/${user.twitter.replace(/^@/, '')}`;
const twitter =
user.twitter && isURL(user.twitter)
? user.twitter
: user.twitter &&
`https://www.twitter.com/${user.twitter.replace(/^@/, '')}`;
return { about, picture, twitter };
}

View File

@ -49,7 +49,9 @@ export function timeCache(time, unit) {
// set new expire time in MS and create new subscription to source
if (!expireCacheAt || expireCacheAt < Date.now()) {
// set expire in ms;
expireCacheAt = moment().add(time, unit).valueOf();
expireCacheAt = moment()
.add(time, unit)
.valueOf();
cache = new AsyncSubject();
source.subscribe(cache);
}

View File

@ -25,13 +25,7 @@ export function getHost() {
export function getServerFullURL() {
if (!isDev) {
return getProtocol()
+ '://'
+ getHost();
return getProtocol() + '://' + getHost();
}
return getProtocol()
+ '://'
+ getHost()
+ ':'
+ getPort();
return getProtocol() + '://' + getHost() + ':' + getPort();
}

View File

@ -13,7 +13,6 @@ const hoursBetween = 24;
const hoursDay = 24;
export function prepUniqueDaysByHours(cals, tz = 'UTC') {
let prev = null;
// compose goes bottom to top (map > sortBy > transform)
@ -25,27 +24,34 @@ export function prepUniqueDaysByHours(cals, tz = 'UTC') {
} else if (
moment(cur)
.tz(tz)
.diff(moment(prev).tz(tz).startOf('day'), 'hours')
>= hoursDay
.diff(
moment(prev)
.tz(tz)
.startOf('day'),
'hours'
) >= hoursDay
) {
data.push(cur);
prev = cur;
}
}, []),
sortBy(e => e),
map(ts => moment(ts).tz(tz).startOf('hours').valueOf())
map(ts =>
moment(ts)
.tz(tz)
.startOf('hours')
.valueOf()
)
)(cals);
}
export function calcCurrentStreak(cals, tz = 'UTC') {
let prev = last(cals);
if (
moment()
.tz(tz)
.startOf('day')
.diff(moment(prev).tz(tz), 'hours')
> hoursBetween
.diff(moment(prev).tz(tz), 'hours') > hoursBetween
) {
return 0;
}
@ -56,8 +62,7 @@ export function calcCurrentStreak(cals, tz = 'UTC') {
moment(prev)
.tz(tz)
.startOf('day')
.diff(moment(cur).tz(tz), 'hours')
<= hoursBetween
.diff(moment(cur).tz(tz), 'hours') <= hoursBetween
) {
prev = cur;
currentStreak++;
@ -72,20 +77,26 @@ export function calcCurrentStreak(cals, tz = 'UTC') {
}
export function calcLongestStreak(cals, tz = 'UTC') {
let tail = cals[0];
const longest = cals.reduce((longest, head, index) => {
const last = cals[index === 0 ? 0 : index - 1];
// is streak broken
if (moment(head).tz(tz).startOf('day').diff(moment(last).tz(tz), 'hours')
> hoursBetween) {
tail = head;
}
if (dayCount(longest, tz) < dayCount([head, tail], tz)) {
return [head, tail];
}
return longest;
}, [cals[0], cals[0]]);
const longest = cals.reduce(
(longest, head, index) => {
const last = cals[index === 0 ? 0 : index - 1];
// is streak broken
if (
moment(head)
.tz(tz)
.startOf('day')
.diff(moment(last).tz(tz), 'hours') > hoursBetween
) {
tail = head;
}
if (dayCount(longest, tz) < dayCount([head, tail], tz)) {
return [head, tail];
}
return longest;
},
[cals[0], cals[0]]
);
return dayCount(longest, tz);
}

View File

@ -16,7 +16,5 @@ module.exports = {
transform: {
'^.+\\.js$': '<rootDir>/jest.transform.js'
},
transformIgnorePatterns: [
'node_modules/(?!(gatsby)/)'
]
transformIgnorePatterns: ['node_modules/(?!(gatsby)/)']
};

View File

@ -1,12 +1,10 @@
const babelOptions = {
presets: [
'@babel/preset-env',
'@babel/react'
],
presets: ['@babel/preset-env', '@babel/react'],
plugins: [
'@babel/plugin-proposal-function-bind',
[
'transform-imports', {
'transform-imports',
{
'@freecodecamp/react-bootstrap': {
transform: '@freecodecamp/react-bootstrap/lib/${member}',
preventFullImport: true

View File

@ -29,7 +29,10 @@ exports.createNavigationNode = function createNavigationNode(node) {
const nodeDir = path.resolve(fileAbsolutePath).replace(indexMdRe, '');
const dashedName = nodeDir.split(path.sep).slice(-1)[0];
const nodePath = nodeDir.split(pagesDir)[1].split(path.sep).join('/');
const nodePath = nodeDir
.split(pagesDir)[1]
.split(path.sep)
.join('/');
const parentPath = nodePath
.split('/')
.slice(0, -1)

View File

@ -33,15 +33,9 @@ function DonateCompletion({ processing, reset, success, error = null }) {
/>
)}
{success && (
<p>
Thank you for supporting the freeCodeCamp.org community.
</p>
)}
{error && (
<p>
{error}
</p>
<p>Thank you for supporting the freeCodeCamp.org community.</p>
)}
{error && <p>{error}</p>}
</div>
<p className='donation-completion-buttons'>
{error && (

View File

@ -20,10 +20,9 @@ import DonateText from './DonateText';
import '../Donation.css';
const mapStateToProps = createSelector(
isDonationModalOpenSelector,
show => ({ show })
);
const mapStateToProps = createSelector(isDonationModalOpenSelector, show => ({
show
}));
const mapDispatchToProps = dispatch =>
bindActionCreators(
@ -73,7 +72,9 @@ class DonateModal extends Component {
};
return (
<div className='modal-close-btn-container'>
<Button bsStyle='link' onClick={handleClick}>Close</Button>
<Button bsStyle='link' onClick={handleClick}>
Close
</Button>
</div>
);
}
@ -84,25 +85,25 @@ class DonateModal extends Component {
ga.modalview('/donation-modal');
}
return (
<StripeProvider stripe={this.state.stripe}>
<Elements>
<Modal bsSize='lg' className='donation-modal' show={show}>
<Modal.Header className='fcc-modal'>
<Modal.Title className='text-center'>
Support Our NonProfit
</Modal.Title>
</Modal.Header>
<Modal.Body>
<DonateText />
<DonateForm />
{this.renderMaybe()}
</Modal.Body>
<Modal.Footer>
<StripeProvider stripe={this.state.stripe}>
<Elements>
<Modal bsSize='lg' className='donation-modal' show={show}>
<Modal.Header className='fcc-modal'>
<Modal.Title className='text-center'>
Support Our NonProfit
</Modal.Title>
</Modal.Header>
<Modal.Body>
<DonateText />
<DonateForm />
{this.renderMaybe()}
</Modal.Body>
<Modal.Footer>
<PoweredByStripe />
</Modal.Footer>
</Modal>
</Elements>
</StripeProvider>
</Modal.Footer>
</Modal>
</Elements>
</StripeProvider>
);
}
}

View File

@ -19,15 +19,14 @@ const DonateText = ({ activeDonations }) => {
return (
<div className='text-center'>
<p>
freeCodeCamp.org is a tiny nonprofit that's helping millions of
people learn to code for free.
freeCodeCamp.org is a tiny nonprofit that's helping millions of people
learn to code for free.
</p>
<p>
Join <strong>{donationsLocale}</strong> supporters.
</p>
<p>
Your $5 / month donation will help keep tech education free and
open.
Your $5 / month donation will help keep tech education free and open.
</p>
</div>
);

View File

@ -77,9 +77,7 @@ class StripeCardForm extends Component {
return (
<div className='donation-elements'>
<FormGroup>
<ControlLabel>
Your Card Number:
</ControlLabel>
<ControlLabel>Your Card Number:</ControlLabel>
<CardNumberElement
className='form-control donate-input-element'
onChange={this.handleInputChange}
@ -87,9 +85,7 @@ class StripeCardForm extends Component {
/>
</FormGroup>
<FormGroup>
<ControlLabel>
Your Card Expiration Month:
</ControlLabel>
<ControlLabel>Your Card Expiration Month:</ControlLabel>
<CardExpiryElement
className='form-control donate-input-element'
onChange={this.handleInputChange}
@ -97,9 +93,7 @@ class StripeCardForm extends Component {
/>
</FormGroup>
<FormGroup>
<ControlLabel>
Your Card CVC (3-digit security number):
</ControlLabel>
<ControlLabel>Your Card CVC (3-digit security number):</ControlLabel>
<CardCVCElement
className='form-control donate-input-element'
onChange={this.handleInputChange}

View File

@ -96,12 +96,8 @@ function Footer() {
</Col>
<Col lg={3} sm={2} xs={12}>
<ColHeader>Our Learning Resources</ColHeader>
<Link to='/learn'>
Learn
</Link>
<Link to='/guide'>
Guide
</Link>
<Link to='/learn'>Learn</Link>
<Link to='/guide'>Guide</Link>
<Link to='https://www.youtube.com/freecodecamp'>Youtube</Link>
<Link to='https://podcast.freecodecamp.org'>Podcast</Link>
<Link to='https://twitter.com/freecodecamp'>Twitter</Link>

View File

@ -154,4 +154,7 @@ export class Block extends Component {
Block.displayName = 'Block';
Block.propTypes = propTypes;
export default connect(mapStateToProps, mapDispatchToProps)(Block);
export default connect(
mapStateToProps,
mapDispatchToProps
)(Block);

View File

@ -33,7 +33,9 @@ export function DynamicForm({
errors,
fields,
handleSubmit,
fields: { _meta: { allPristine } },
fields: {
_meta: { allPristine }
},
// HOC
buttonText,

View File

@ -166,7 +166,7 @@ class DefaultLayout extends Component {
) : null}
{children}
</div>
{showFooter && (<Footer />)}
{showFooter && <Footer />}
</Fragment>
);
}

View File

@ -67,7 +67,9 @@ class NavPanel extends Component {
'caret ' + (isExpanded ? 'caretStyle expanded' : 'caretStyle')
}
/>
<Link onClick={this.handleTitleClick} to={path}>{title}</Link>
<Link onClick={this.handleTitleClick} to={path}>
{title}
</Link>
</div>
);
}

View File

@ -8,32 +8,38 @@ import ReactGA from '../analytics/index.js';
import Spacer from '../components/helpers/Spacer';
const paypalMonthlyDonations = [
{ eventLabel: 'paypal',
{
eventLabel: 'paypal',
eventValue: 5,
defaultValueHash: 'KTAXU8B4MYAT8',
defaultValue: 'Donate $5 each month'
},
{ eventLabel: 'paypal',
{
eventLabel: 'paypal',
eventValue: 10,
defaultValueHash: 'BYEBQEHS5LHNC',
defaultValue: 'Donate $10 each month'
},
{ eventLabel: 'paypal',
{
eventLabel: 'paypal',
eventValue: 35,
defaultValueHash: '57ZPMKJ8G893Y',
defaultValue: 'Donate $35 each month'
},
{ eventLabel: 'paypal',
{
eventLabel: 'paypal',
eventValue: 50,
defaultValueHash: '2ZVYTHK6Q7AFW',
defaultValue: 'Donate $50 each month'
},
{ eventLabel: 'paypal',
{
eventLabel: 'paypal',
eventValue: 100,
defaultValueHash: 'C7PUT3LMJHKK2',
defaultValue: 'Donate $100 each month'
},
{ eventLabel: 'paypal',
{
eventLabel: 'paypal',
eventValue: 250,
defaultValueHash: '69JGTY4DHSTEN',
defaultValue: 'Donate $250 each month'
@ -48,13 +54,19 @@ const paypalOneTimeDonation = {
};
class DonateOtherPage extends Component {
renderForm(item) {
return (
<form
action='https://www.paypal.com/cgi-bin/webscr'
method='post'
onSubmit={() => ReactGA.event({category: 'donation', action: 'click', label: item.eventLabel, value: item.eventValue})}
onSubmit={() =>
ReactGA.event({
category: 'donation',
action: 'click',
label: item.eventLabel,
value: item.eventValue
})
}
target='_blank'
>
<input defaultValue='_s-xclick' name='cmd' type='hidden' />{' '}
@ -74,122 +86,143 @@ class DonateOtherPage extends Component {
}
render() {
return (
<Fragment>
<Helmet title='Other ways to donate | freeCodeCamp.org' />
<Spacer />
<Grid className='container'>
<Row>
<Col md={6} mdOffset={3} sm={10} smOffset={1} xs={12}>
<h2 className='text-center'>
Other ways you can support the freeCodeCamp.org nonprofit
</h2>
<p>
freeCodeCamp is a small donor-supported 501(c)(3) public charity. We
are tax-exempt, so you can deduct donations you make to our
nonprofit from your taxes. You can{' '}
<a href='https://s3.amazonaws.com/freecodecamp/Free+Code+Camp+Inc+IRS+Determination+Letter.pdf'>
download our IRS Determination Letter here
</a>.
</p>
<hr />
<h3>Set up a monthly donation using PayPal</h3>
<p>
You can set up a monthly donation to freeCodeCamp by clicking one of
the links below and following the instructions on PayPal. You can
easily stop your donations at any time in the future.
</p>
{paypalMonthlyDonations.map((item) => {
return this.renderForm(item);
})}
<hr />
<h3>Make a one-time donation using PayPal</h3>
<p>
You can make a one-time monthly donation to freeCodeCamp for any
amount of money by clicking one of the links below and following the
instructions on PayPal:
</p>
{this.renderForm(paypalOneTimeDonation)}
<hr />
<h3>Get your employer to match your donation</h3>
<p>
Many freeCodeCamp supporters are able to get their employers to
match their donations to freeCodeCamp. Our Tax-exempt number (EIN)
is 82-0779546. If we can help you with setting this up, please email{' '}
<a href='mailto:team@freecodecamp.org'>team@freecodecamp.org</a>.
</p>
<hr />
<h3>Donate through a payroll deduction</h3>
<p>
In the US and Canada, some employers have a convenient way to give
to freeCodeCamp through a payroll deduction. Ask your employer if
they can do this, and have them send any necessary paperwork to:
</p>
<p>
Free Code Camp, Inc.<br />7800 W Hefner Rd, PO BOX 721024<br />Oklahoma
City, Oklahoma 73172<br />United States
</p>
<hr />
<h3>Donate cryptocurrency to freeCodeCamp</h3>
<p>
Below are our wallets where we can receive cryptocurrency donations.
</p>
<h4>Make a one-time Bitcoin donation</h4>
<p className='negative-15'>
Our Bitcoin wallet is{' '}
<code>12skYi7aMCjDUdrVdoB3JjZ77ug8gxJfbL</code>
</p>
<h4>Make a one-time Ethereum donation</h4>
<p className='negative-15'>
Our Ethereum wallet is{' '}
<code>0x0ADbEf2471416BD8732cf0f3944294eE393CcAF5</code>
</p>
<h4>Make a one-time Litecoin donation</h4>
<p className='negative-15'>
Our Litecoin wallet is{' '}
<code>LKu8UG8Z1nbTxnq9Do96PsC3FwbNtycf3X</code>
</p>
<h4>Make a one-time Bitcoin Cash donation</h4>
<p className='negative-15'>
Our Bitcoin Cash wallet is{' '}
<code>1EBxPEJWrGZWxe2UayyAsnd5VsRg5H9xfu</code>
</p>
<hr />
<h3>Donate to freeCodeCamp by mailing us a check</h3>
<p>Our mailing address is:</p>
<p>
Free Code Camp, Inc.<br />7800 W Hefner Rd, PO BOX 721024<br />Oklahoma
City, Oklahoma 73172<br />United States
</p>
<hr />
<h3>Donate Stock to freeCodeCamp</h3>
<p>
If you want to donate stocks to freeCodeCamp, please email us at{' '}
<a href='mailto:team@freecodecamp.org'>team@freecodecamp.org</a>.
</p>
<hr />
<h3>Legacy Gift</h3>
<p>
You can help future generations of learners by listing freeCodeCamp
in your will or living trust. If you're interested in doing this,
email Quincy directly and we can discuss this:{' '}
<a href='mailto:quincy@freecodecamp.org'>quincy@freecodecamp.org</a>.
</p>
<hr />
<h3>
Thank you for supporting our nonprofit and the freeCodeCamp
community.
</h3>
<Spacer />
<div className='text-center'>
<Link to='/donate'>Or donate using a Credit or Debit Card.</Link>
</div>
<Spacer />
</Col>
</Row>
</Grid>
</Fragment>
);
return (
<Fragment>
<Helmet title='Other ways to donate | freeCodeCamp.org' />
<Spacer />
<Grid className='container'>
<Row>
<Col md={6} mdOffset={3} sm={10} smOffset={1} xs={12}>
<h2 className='text-center'>
Other ways you can support the freeCodeCamp.org nonprofit
</h2>
<p>
freeCodeCamp is a small donor-supported 501(c)(3) public
charity. We are tax-exempt, so you can deduct donations you make
to our nonprofit from your taxes. You can{' '}
<a href='https://s3.amazonaws.com/freecodecamp/Free+Code+Camp+Inc+IRS+Determination+Letter.pdf'>
download our IRS Determination Letter here
</a>
.
</p>
<hr />
<h3>Set up a monthly donation using PayPal</h3>
<p>
You can set up a monthly donation to freeCodeCamp by clicking
one of the links below and following the instructions on PayPal.
You can easily stop your donations at any time in the future.
</p>
{paypalMonthlyDonations.map(item => {
return this.renderForm(item);
})}
<hr />
<h3>Make a one-time donation using PayPal</h3>
<p>
You can make a one-time monthly donation to freeCodeCamp for any
amount of money by clicking one of the links below and following
the instructions on PayPal:
</p>
{this.renderForm(paypalOneTimeDonation)}
<hr />
<h3>Get your employer to match your donation</h3>
<p>
Many freeCodeCamp supporters are able to get their employers to
match their donations to freeCodeCamp. Our Tax-exempt number
(EIN) is 82-0779546. If we can help you with setting this up,
please email{' '}
<a href='mailto:team@freecodecamp.org'>team@freecodecamp.org</a>
.
</p>
<hr />
<h3>Donate through a payroll deduction</h3>
<p>
In the US and Canada, some employers have a convenient way to
give to freeCodeCamp through a payroll deduction. Ask your
employer if they can do this, and have them send any necessary
paperwork to:
</p>
<p>
Free Code Camp, Inc.
<br />
7800 W Hefner Rd, PO BOX 721024
<br />
Oklahoma City, Oklahoma 73172
<br />
United States
</p>
<hr />
<h3>Donate cryptocurrency to freeCodeCamp</h3>
<p>
Below are our wallets where we can receive cryptocurrency
donations.
</p>
<h4>Make a one-time Bitcoin donation</h4>
<p className='negative-15'>
Our Bitcoin wallet is{' '}
<code>12skYi7aMCjDUdrVdoB3JjZ77ug8gxJfbL</code>
</p>
<h4>Make a one-time Ethereum donation</h4>
<p className='negative-15'>
Our Ethereum wallet is{' '}
<code>0x0ADbEf2471416BD8732cf0f3944294eE393CcAF5</code>
</p>
<h4>Make a one-time Litecoin donation</h4>
<p className='negative-15'>
Our Litecoin wallet is{' '}
<code>LKu8UG8Z1nbTxnq9Do96PsC3FwbNtycf3X</code>
</p>
<h4>Make a one-time Bitcoin Cash donation</h4>
<p className='negative-15'>
Our Bitcoin Cash wallet is{' '}
<code>1EBxPEJWrGZWxe2UayyAsnd5VsRg5H9xfu</code>
</p>
<hr />
<h3>Donate to freeCodeCamp by mailing us a check</h3>
<p>Our mailing address is:</p>
<p>
Free Code Camp, Inc.
<br />
7800 W Hefner Rd, PO BOX 721024
<br />
Oklahoma City, Oklahoma 73172
<br />
United States
</p>
<hr />
<h3>Donate Stock to freeCodeCamp</h3>
<p>
If you want to donate stocks to freeCodeCamp, please email us at{' '}
<a href='mailto:team@freecodecamp.org'>team@freecodecamp.org</a>
.
</p>
<hr />
<h3>Legacy Gift</h3>
<p>
You can help future generations of learners by listing
freeCodeCamp in your will or living trust. If you're interested
in doing this, email Quincy directly and we can discuss this:{' '}
<a href='mailto:quincy@freecodecamp.org'>
quincy@freecodecamp.org
</a>
.
</p>
<hr />
<h3>
Thank you for supporting our nonprofit and the freeCodeCamp
community.
</h3>
<Spacer />
<div className='text-center'>
<Link to='/donate'>
Or donate using a Credit or Debit Card.
</Link>
</div>
<Spacer />
</Col>
</Row>
</Grid>
</Fragment>
);
}
}

View File

@ -60,9 +60,7 @@ class DonatePage extends Component {
<Spacer />
<Row>
<Col sm={8} smOffset={2} xs={12}>
<h2 className='text-center'>
Become a Supporter
</h2>
<h2 className='text-center'>Become a Supporter</h2>
<DonateText />
</Col>
<Col sm={6} smOffset={3} xs={12}>

View File

@ -85,9 +85,7 @@ export const query = graphql`
slug
}
}
allChallengeNode(
sort: { fields: [superOrder, order, challengeOrder] }
) {
allChallengeNode(sort: { fields: [superOrder, order, challengeOrder] }) {
edges {
node {
fields {

View File

@ -16,7 +16,7 @@ function setTheme(currentTheme = defaultTheme, theme) {
html.classList.add(theme);
}
function* updateLocalThemeSaga({ payload: {user, theme } }) {
function* updateLocalThemeSaga({ payload: { user, theme } }) {
const currentTheme = store.get(themeKey) || defaultTheme;
if (user) {
const { theme = defaultTheme } = user;

View File

@ -6,10 +6,5 @@ import { sagas as challengeSagas } from '../templates/Challenges/redux';
import { sagas as settingsSagas } from './settings';
export default function* rootSaga() {
yield all([
...errorSagas,
...appSagas,
...challengeSagas,
...settingsSagas
]);
yield all([...errorSagas, ...appSagas, ...challengeSagas, ...settingsSagas]);
}

View File

@ -170,7 +170,7 @@ export class BackEnd extends Component {
<LearnLayout>
<Grid>
<Row>
<Col md={8} mdOffset={2} sm={10} smOffset={1} xs={12} >
<Col md={8} mdOffset={2} sm={10} smOffset={1} xs={12}>
<Spacer />
<ChallengeTitle>{blockNameTitle}</ChallengeTitle>
<ChallengeDescription

View File

@ -10,8 +10,9 @@ const propTypes = {
};
function emptyInstruction(instructions) {
return (/^<section\s+id\s*=\s*("|')instructions\1\s*>\s*<\/section>$/)
.test(instructions);
return (/^<section\s+id\s*=\s*("|')instructions\1\s*>\s*<\/section>$/).test(
instructions
);
}
function ChallengeDescription({ description, instructions, section }) {

View File

@ -73,4 +73,7 @@ function ResetModal({ reset, close, isOpen }) {
ResetModal.displayName = 'ResetModal';
ResetModal.propTypes = propTypes;
export default connect(mapStateToProps, mapDispatchToProps)(ResetModal);
export default connect(
mapStateToProps,
mapDispatchToProps
)(ResetModal);

View File

@ -41,9 +41,11 @@ function ToolPanel({
}) {
return (
<Fragment>
<div className={`tool-panel-group ${
<div
className={`tool-panel-group ${
isMobile ? 'tool-panel-group-mobile' : ''
}`}>
}`}
>
<Button block={true} bsStyle='primary' onClick={executeChallenge}>
{isMobile ? 'Run' : 'Run the Tests'}
</Button>
@ -92,7 +94,10 @@ function ToolPanel({
ToolPanel.displayName = 'ToolPanel';
ToolPanel.propTypes = propTypes;
export default connect(mapStateToProps, mapDispatchToProps)(ToolPanel);
export default connect(
mapStateToProps,
mapDispatchToProps
)(ToolPanel);
/*
<Button

View File

@ -89,7 +89,9 @@ export class ProjectForm extends Component {
}
}
handleSubmit(values) {
const { keysDown: { Control, Enter } } = this.state;
const {
keysDown: { Control, Enter }
} = this.state;
if ((Control && Enter) || !Enter) {
this.props.openModal('completion');
this.props.updateProjectForm(values);

View File

@ -55,35 +55,8 @@ export class ToolPanel extends Component {
ToolPanel.displayName = 'ProjectToolPanel';
ToolPanel.propTypes = propTypes;
export default connect(mapStateToProps, mapDispatchToProps)(ToolPanel);
export default connect(
mapStateToProps,
mapDispatchToProps
)(ToolPanel);
/**
*
* <Fragment>
<ProjectForm isFrontEnd={isFrontEnd} openModal={openCompletionModal} />
<ButtonSpacer />
{guideUrl && (
<Fragment>
<Button
block={true}
bsStyle='primary'
className='btn-primary-ghost btn-big'
href={guideUrl}
target='_blank'
>
Get a hint
</Button>
<ButtonSpacer />
</Fragment>
)}
<Button
block={true}
bsStyle='primary'
className='btn-primary-ghost btn-big'
onClick={openHelpModal}
>
Ask for help on the forum
</Button>
<ButtonSpacer />
</Fragment>
*/

View File

@ -1,4 +1,4 @@
import {cond, identity, stubTrue, conforms} from 'lodash';
import { cond, identity, stubTrue, conforms } from 'lodash';
const HTML$JSReg = /html|js/;

View File

@ -46,9 +46,7 @@ export const testJS$JSX = overSome(testJS, testJSX);
export const replaceNBSP = cond([
[
testHTML$JS$JSX,
partial(vinyl.transformContents, contents =>
contents.replace(NBSPReg, ' ')
)
partial(vinyl.transformContents, contents => contents.replace(NBSPReg, ' '))
],
[stubTrue, identity]
]);

View File

@ -3,7 +3,10 @@ import { ofType } from 'redux-observable';
import { types, unlockCode } from './';
function codeLockEpic(action$) {
return action$.pipe(ofType(types.updateFile), map(unlockCode));
return action$.pipe(
ofType(types.updateFile),
map(unlockCode)
);
}
export default codeLockEpic;

View File

@ -7,16 +7,12 @@ function* fetchIdToNameMapSaga() {
try {
const { data } = yield call(getIdToNameMap);
yield put(
fetchIdToNameMapComplete(data)
);
yield put(fetchIdToNameMapComplete(data));
} catch (e) {
yield put(fetchIdToNameMapError(e));
}
}
export function createIdToNameMapSaga(types) {
return [
takeEvery(types.fetchIdToNameMap, fetchIdToNameMapSaga)
];
return [takeEvery(types.fetchIdToNameMap, fetchIdToNameMapSaga)];
}

View File

@ -58,7 +58,6 @@ export function createFetchLink() {
}
const link = await axios
.get({ url: href, crossDomain })
.then(thing => { console.log(thing); return thing;})
.then(res => {
if (res.status !== 200) {
throw new Error('Request error: ' + res.status);
@ -67,7 +66,7 @@ export function createFetchLink() {
.then(({ data }) => data)
.then(styles => `<style>${styles}</style>`)
.catch(() => '');
cache.set(href, link);
cache.set(href, link);
return link;
};
}

View File

@ -13,7 +13,10 @@ const propTypes = {
};
function SuperBlockIntroductionPage({ data: { markdownRemark } }) {
const { html, frontmatter: { superBlock } } = markdownRemark;
const {
html,
frontmatter: { superBlock }
} = markdownRemark;
return (
<Fragment>
<Helmet>

View File

@ -17,10 +17,11 @@ const arrToString = arr =>
exports.localeChallengesRootDir = getChallengesDirForLang(locale);
exports.replaceChallengeNode =
async function replaceChallengeNode(fullFilePath) {
return prepareChallenge(await createChallenge(fullFilePath));
};
exports.replaceChallengeNode = async function replaceChallengeNode(
fullFilePath
) {
return prepareChallenge(await createChallenge(fullFilePath));
};
exports.buildChallenges = async function buildChallenges() {
const curriculum = await getChallengesForLang(locale);

View File

@ -157,7 +157,7 @@ const stopWords = [
'in',
'into',
'it',
'it\'s',
"it's",
'its',
'no',
'nor',

View File

@ -17,7 +17,10 @@ function prototyper(str) {
if (prototypeRE.test(str)) {
if (str.length > 9) {
return prototyper(
str.trim().split('prototype').join('-prototype-')
str
.trim()
.split('prototype')
.join('-prototype-')
);
}
return str;
@ -26,15 +29,13 @@ function prototyper(str) {
})
.join(' ')
.split(' ');
const noProto = formatted
.filter(removeProto)
.filter(x => !!x);
const noProto = formatted.filter(removeProto).filter(x => !!x);
if (noProto.length === 2) {
const [ first, second ] = noProto;
const [first, second] = noProto;
const secondLC = second.toLowerCase();
const finalSecond = preFormatted[secondLC] ?
preFormatted[secondLC] :
secondLC;
const finalSecond = preFormatted[secondLC]
? preFormatted[secondLC]
: secondLC;
return `${titleify(first)}.prototype.${finalSecond}`;
}
if (noProto.length === 1) {
@ -43,7 +44,7 @@ function prototyper(str) {
.toLowerCase()
.split('.')
.join('-')
);
);
}
return titleify(str, true);
}
@ -62,9 +63,7 @@ function titleify(str, triedPrototyper) {
if (stopWords.some(x => x === word) && i !== 0) {
return word;
}
return preFormatted[word] ?
preFormatted[word] :
titleCase(word);
return preFormatted[word] ? preFormatted[word] : titleCase(word);
})
.join(' ');
}

View File

@ -114,7 +114,7 @@ function superBlockInfoFromPath(filePath) {
}
function superBlockInfoFromFullPath(fullFilePath) {
const [,, maybeSuper] = fullFilePath.split(path.sep).reverse();
const [, , maybeSuper] = fullFilePath.split(path.sep).reverse();
return superBlockInfo(maybeSuper);
}

View File

@ -1,13 +1,9 @@
const fs = require('fs-extra');
const gulp = require('gulp');
const {
locale
} = require('../config/env.json');
const { locale } = require('../config/env.json');
const {
getChallengesForLang
} = require('./getChallenges');
const { getChallengesForLang } = require('./getChallenges');
function generateCurriculum(done) {
return getChallengesForLang(locale)

View File

@ -8,9 +8,7 @@ const _ = require('lodash');
const createDebugger = require('debug');
const utils = require('../server/utils');
const getChallenges = require('./getChallenges');
const { validateChallenge } = require(
'./schema/challengeSchema'
);
const { validateChallenge } = require('./schema/challengeSchema');
const app = require('../server/server');
const log = createDebugger('fcc:seed');
@ -23,10 +21,14 @@ const nameify = utils.nameify;
const Observable = Rx.Observable;
const Challenge = app.models.Challenge;
const destroyChallenges =
Observable.fromNodeCallback(Challenge.destroyAll, Challenge);
const createChallenges =
Observable.fromNodeCallback(Challenge.create, Challenge);
const destroyChallenges = Observable.fromNodeCallback(
Challenge.destroyAll,
Challenge
);
const createChallenges = Observable.fromNodeCallback(
Challenge.create,
Challenge
);
const Block = app.models.Block;
const destroyBlocks = Observable.fromNodeCallback(Block.destroyAll, Block);
@ -34,12 +36,11 @@ const createBlocks = Observable.fromNodeCallback(Block.create, Block);
const arrToString = arr =>
Array.isArray(arr) ? arr.join('\n') : _.toString(arr);
Observable.combineLatest(
destroyChallenges(),
destroyBlocks()
)
Observable.combineLatest(destroyChallenges(), destroyBlocks())
.last()
.flatMap(function() { return Observable.from(getChallenges()); })
.flatMap(function() {
return Observable.from(getChallenges());
})
.flatMap(function(challengeSpec) {
const order = challengeSpec.order;
const blockName = challengeSpec.name;
@ -80,23 +81,24 @@ Observable.combineLatest(
.map(block => {
log('successfully created %s block', block.name);
return challengeSpec.challenges
.map(function(challenge, index) {
challenge.name = nameify(challenge.title);
return challengeSpec.challenges.map(function(challenge, index) {
challenge.name = nameify(challenge.title);
challenge.dashedName = dasherize(challenge.name);
challenge.dashedName = dasherize(challenge.name);
challenge.checksum = adler32.sum(
Buffer(
challenge.title +
challenge.checksum = adler32.sum(
Buffer(
challenge.title +
JSON.stringify(challenge.description) +
JSON.stringify(challenge.challengeSeed) +
JSON.stringify(challenge.tests)
)
);
)
);
if (challenge.files) {
challenge.files = _.reduce(challenge.files, (map, file) => {
if (challenge.files) {
challenge.files = _.reduce(
challenge.files,
(map, file) => {
map[file.key] = {
...file,
head: arrToString(file.head),
@ -104,46 +106,45 @@ Observable.combineLatest(
tail: arrToString(file.tail)
};
return map;
}, {});
}
challenge.fileName = fileName;
challenge.helpRoom = helpRoom;
challenge.order = order;
challenge.suborder = index + 1;
challenge.block = dasherize(blockName);
challenge.blockId = '' + block.id;
challenge.isBeta = challenge.isBeta || isBeta;
challenge.isComingSoon = challenge.isComingSoon || isComingSoon;
challenge.isLocked = challenge.isLocked || isLocked;
challenge.isPrivate = challenge.isPrivate || isPrivate;
challenge.time = challengeSpec.time;
challenge.superOrder = superOrder;
challenge.superBlock = superBlock
.split('-')
.map(function(word) {
return _.capitalize(word);
})
.join(' ');
challenge.required = (challenge.required || []).concat(required);
challenge.template = challenge.template || template;
return _.omit(
challenge,
[
'betaSolutions',
'betaTests',
'hints',
'MDNlinks',
'null',
'rawSolutions',
'react',
'reactRedux',
'redux',
'releasedOn',
'translations',
'type'
]
},
{}
);
});
}
challenge.fileName = fileName;
challenge.helpRoom = helpRoom;
challenge.order = order;
challenge.suborder = index + 1;
challenge.block = dasherize(blockName);
challenge.blockId = '' + block.id;
challenge.isBeta = challenge.isBeta || isBeta;
challenge.isComingSoon = challenge.isComingSoon || isComingSoon;
challenge.isLocked = challenge.isLocked || isLocked;
challenge.isPrivate = challenge.isPrivate || isPrivate;
challenge.time = challengeSpec.time;
challenge.superOrder = superOrder;
challenge.superBlock = superBlock
.split('-')
.map(function(word) {
return _.capitalize(word);
})
.join(' ');
challenge.required = (challenge.required || []).concat(required);
challenge.template = challenge.template || template;
return _.omit(challenge, [
'betaSolutions',
'betaTests',
'hints',
'MDNlinks',
'null',
'rawSolutions',
'react',
'reactRedux',
'redux',
'releasedOn',
'translations',
'type'
]);
});
})
.flatMap(challenges => {
challenges.forEach(challenge => {
@ -160,7 +161,9 @@ Observable.combineLatest(
function(challenges) {
log('%s successfully saved', challenges[0].block);
},
function(err) { throw err; },
function(err) {
throw err;
},
function() {
log('challenge seed completed');
process.exit(0);

View File

@ -55,11 +55,7 @@ async function translateChallenge(file) {
];
return Promise.all(translatePromises).then(
([title, description, instructions, ...tests]) => {
const {
files = {},
solutions = [],
...challengeMeta
} = challenge;
const { files = {}, solutions = [], ...challengeMeta } = challenge;
const md = `---
${YAML.dump(
Object.assign(challengeMeta, {

View File

@ -20,7 +20,7 @@ class ChallengeTitles {
The title ${title} is already assigned
`);
}
this.knownTitles = [ ...this.knownTitles, titleToCheck ];
this.knownTitles = [...this.knownTitles, titleToCheck];
}
}

View File

@ -17,7 +17,7 @@ class MongoIds {
The id for ${title} is already assigned
`);
}
this.knownIds = [ ...this.knownIds, id ];
this.knownIds = [...this.knownIds, id];
}
}

883
package-lock.json generated
View File

@ -1155,6 +1155,12 @@
"json-schema-traverse": "^0.3.0"
}
},
"ajv-keywords": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-2.1.1.tgz",
"integrity": "sha1-YXmX/F9gV2iUxDX5QNgZ4TW4B2I=",
"dev": true
},
"ansi-escapes": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.1.0.tgz",
@ -1837,6 +1843,12 @@
"integrity": "sha512-/qKPUQlaW1OyR51WeCPBvRnAlnZFUJkCSG5HzGnuIqhgyJtF+T94lFnn33eiazjRm2LAHVy2guNnaq48X9SJuw==",
"dev": true
},
"boolify": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/boolify/-/boolify-1.0.1.tgz",
"integrity": "sha1-tcCeF8rNET0Rt7s+04TMASmU2Gs=",
"dev": true
},
"brace-expansion": {
"version": "1.1.11",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
@ -2256,6 +2268,12 @@
"dev": true,
"optional": true
},
"common-tags": {
"version": "1.8.0",
"resolved": "https://registry.npmjs.org/common-tags/-/common-tags-1.8.0.tgz",
"integrity": "sha512-6P6g0uetGpW/sdyUy/iQQCbFF0kWVMSIVSyYz7Zgjcgh8mgw8PQzDNZeyZ5DQ2gM7LBoZPHmnjz8rUthkBG5tw==",
"dev": true
},
"compare-func": {
"version": "1.3.2",
"resolved": "https://registry.npmjs.org/compare-func/-/compare-func-1.3.2.tgz",
@ -2801,6 +2819,12 @@
"path-type": "^3.0.0"
}
},
"dlv": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.2.tgz",
"integrity": "sha512-xxD4VSH67GbRvSGUrckvha94RD7hjgOH7rqGxiytLpkaeMvixOHFZTGFK6EkIm3T761OVHT8ABHmGkq9gXgu6Q==",
"dev": true
},
"doctrine": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz",
@ -5489,6 +5513,12 @@
"has": "^1.0.1"
}
},
"is-resolvable": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.1.0.tgz",
"integrity": "sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg==",
"dev": true
},
"is-ssh": {
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/is-ssh/-/is-ssh-1.3.1.tgz",
@ -7097,6 +7127,18 @@
"integrity": "sha1-I+89lTVWUgOmbO/VuDD4SJEa+0g=",
"dev": true
},
"lodash.memoize": {
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz",
"integrity": "sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4=",
"dev": true
},
"lodash.merge": {
"version": "4.6.1",
"resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.1.tgz",
"integrity": "sha512-AOYza4+Hf5z1/0Hztxpm2/xiPZgi/cjMqdnKTUWTBSKchJlxXXuUSxCCl8rJlf4g6yww/j6mA8nC8Hw/EZWxKQ==",
"dev": true
},
"lodash.set": {
"version": "4.3.2",
"resolved": "https://registry.npmjs.org/lodash.set/-/lodash.set-4.3.2.tgz",
@ -7128,6 +7170,12 @@
"lodash._reinterpolate": "~3.0.0"
}
},
"lodash.unescape": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/lodash.unescape/-/lodash.unescape-4.0.1.tgz",
"integrity": "sha1-vyJJiGzlFM2hEvrpIYzcBlIR/Jw=",
"dev": true
},
"lodash.uniq": {
"version": "4.5.0",
"resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz",
@ -7143,6 +7191,58 @@
"chalk": "^2.0.1"
}
},
"loglevel": {
"version": "1.6.1",
"resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.6.1.tgz",
"integrity": "sha1-4PyVEztu8nbNyIh82vJKpvFW+Po=",
"dev": true
},
"loglevel-colored-level-prefix": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/loglevel-colored-level-prefix/-/loglevel-colored-level-prefix-1.0.0.tgz",
"integrity": "sha1-akAhj9x64V/HbD0PPmdsRlOIYD4=",
"dev": true,
"requires": {
"chalk": "^1.1.3",
"loglevel": "^1.4.1"
},
"dependencies": {
"ansi-styles": {
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
"integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=",
"dev": true
},
"chalk": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
"integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
"dev": true,
"requires": {
"ansi-styles": "^2.2.1",
"escape-string-regexp": "^1.0.2",
"has-ansi": "^2.0.0",
"strip-ansi": "^3.0.0",
"supports-color": "^2.0.0"
}
},
"strip-ansi": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
"integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
"dev": true,
"requires": {
"ansi-regex": "^2.0.0"
}
},
"supports-color": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
"integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=",
"dev": true
}
}
},
"loose-envify": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
@ -7214,6 +7314,24 @@
"ssri": "^6.0.0"
}
},
"make-plural": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/make-plural/-/make-plural-4.3.0.tgz",
"integrity": "sha512-xTYd4JVHpSCW+aqDof6w/MebaMVNTVYBZhbB/vi513xXdiPT92JMVCo0Jq8W2UZnzYRFeVbQiQ+I25l13JuKvA==",
"dev": true,
"requires": {
"minimist": "^1.2.0"
},
"dependencies": {
"minimist": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
"integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=",
"dev": true,
"optional": true
}
}
},
"makeerror": {
"version": "1.0.11",
"resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.11.tgz",
@ -7322,6 +7440,41 @@
"integrity": "sha512-gdUU1Fwj5ep4kplwcmftruWofEFt6lfpkkr3h860CXbAB9c3hGb55EOL2ali0Td5oebvW0E1+3Sr+Ur7XfKpRA==",
"dev": true
},
"messageformat": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/messageformat/-/messageformat-1.1.1.tgz",
"integrity": "sha512-Q0uXcDtF5pEZsVSyhzDOGgZZK6ykN79VY9CwU3Nv0gsqx62BjdJW0MT+63UkHQ4exe3HE33ZlxR2/YwoJarRTg==",
"dev": true,
"requires": {
"glob": "~7.0.6",
"make-plural": "^4.1.1",
"messageformat-parser": "^1.1.0",
"nopt": "~3.0.6",
"reserved-words": "^0.1.2"
},
"dependencies": {
"glob": {
"version": "7.0.6",
"resolved": "https://registry.npmjs.org/glob/-/glob-7.0.6.tgz",
"integrity": "sha1-IRuvr0nlJbjNkyYNFKsTYVKz9Xo=",
"dev": true,
"requires": {
"fs.realpath": "^1.0.0",
"inflight": "^1.0.4",
"inherits": "2",
"minimatch": "^3.0.2",
"once": "^1.3.0",
"path-is-absolute": "^1.0.0"
}
}
}
},
"messageformat-parser": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/messageformat-parser/-/messageformat-parser-1.1.0.tgz",
"integrity": "sha512-Hwem6G3MsKDLS1FtBRGIs8T50P1Q00r3srS6QJePCFbad9fq0nYxwf3rnU2BreApRGhmpKMV7oZI06Sy1c9TPA==",
"dev": true
},
"micromatch": {
"version": "3.1.10",
"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz",
@ -8433,6 +8586,569 @@
"integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=",
"dev": true
},
"prettier": {
"version": "1.16.4",
"resolved": "https://registry.npmjs.org/prettier/-/prettier-1.16.4.tgz",
"integrity": "sha512-ZzWuos7TI5CKUeQAtFd6Zhm2s6EpAD/ZLApIhsF9pRvRtM1RFo61dM/4MSRUA0SuLugA/zgrZD8m0BaY46Og7g==",
"dev": true
},
"prettier-eslint": {
"version": "8.8.2",
"resolved": "https://registry.npmjs.org/prettier-eslint/-/prettier-eslint-8.8.2.tgz",
"integrity": "sha512-2UzApPuxi2yRoyMlXMazgR6UcH9DKJhNgCviIwY3ixZ9THWSSrUww5vkiZ3C48WvpFl1M1y/oU63deSy1puWEA==",
"dev": true,
"requires": {
"babel-runtime": "^6.26.0",
"common-tags": "^1.4.0",
"dlv": "^1.1.0",
"eslint": "^4.0.0",
"indent-string": "^3.2.0",
"lodash.merge": "^4.6.0",
"loglevel-colored-level-prefix": "^1.0.0",
"prettier": "^1.7.0",
"pretty-format": "^23.0.1",
"require-relative": "^0.8.7",
"typescript": "^2.5.1",
"typescript-eslint-parser": "^16.0.0",
"vue-eslint-parser": "^2.0.2"
},
"dependencies": {
"acorn-jsx": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-3.0.1.tgz",
"integrity": "sha1-r9+UiPsezvyDSPb7IvRk4ypYs2s=",
"dev": true,
"requires": {
"acorn": "^3.0.4"
},
"dependencies": {
"acorn": {
"version": "3.3.0",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz",
"integrity": "sha1-ReN/s56No/JbruP/U2niu18iAXo=",
"dev": true
}
}
},
"chardet": {
"version": "0.4.2",
"resolved": "https://registry.npmjs.org/chardet/-/chardet-0.4.2.tgz",
"integrity": "sha1-tUc7M9yXxCTl2Y3IfVXU2KKci/I=",
"dev": true
},
"debug": {
"version": "3.2.6",
"resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz",
"integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==",
"dev": true,
"requires": {
"ms": "^2.1.1"
}
},
"eslint": {
"version": "4.19.1",
"resolved": "https://registry.npmjs.org/eslint/-/eslint-4.19.1.tgz",
"integrity": "sha512-bT3/1x1EbZB7phzYu7vCr1v3ONuzDtX8WjuM9c0iYxe+cq+pwcKEoQjl7zd3RpC6YOLgnSy3cTN58M2jcoPDIQ==",
"dev": true,
"requires": {
"ajv": "^5.3.0",
"babel-code-frame": "^6.22.0",
"chalk": "^2.1.0",
"concat-stream": "^1.6.0",
"cross-spawn": "^5.1.0",
"debug": "^3.1.0",
"doctrine": "^2.1.0",
"eslint-scope": "^3.7.1",
"eslint-visitor-keys": "^1.0.0",
"espree": "^3.5.4",
"esquery": "^1.0.0",
"esutils": "^2.0.2",
"file-entry-cache": "^2.0.0",
"functional-red-black-tree": "^1.0.1",
"glob": "^7.1.2",
"globals": "^11.0.1",
"ignore": "^3.3.3",
"imurmurhash": "^0.1.4",
"inquirer": "^3.0.6",
"is-resolvable": "^1.0.0",
"js-yaml": "^3.9.1",
"json-stable-stringify-without-jsonify": "^1.0.1",
"levn": "^0.3.0",
"lodash": "^4.17.4",
"minimatch": "^3.0.2",
"mkdirp": "^0.5.1",
"natural-compare": "^1.4.0",
"optionator": "^0.8.2",
"path-is-inside": "^1.0.2",
"pluralize": "^7.0.0",
"progress": "^2.0.0",
"regexpp": "^1.0.1",
"require-uncached": "^1.0.3",
"semver": "^5.3.0",
"strip-ansi": "^4.0.0",
"strip-json-comments": "~2.0.1",
"table": "4.0.2",
"text-table": "~0.2.0"
}
},
"eslint-scope": {
"version": "3.7.3",
"resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-3.7.3.tgz",
"integrity": "sha512-W+B0SvF4gamyCTmUc+uITPY0989iXVfKvhwtmJocTaYoc/3khEHmEmvfY/Gn9HA9VV75jrQECsHizkNw1b68FA==",
"dev": true,
"requires": {
"esrecurse": "^4.1.0",
"estraverse": "^4.1.1"
}
},
"espree": {
"version": "3.5.4",
"resolved": "https://registry.npmjs.org/espree/-/espree-3.5.4.tgz",
"integrity": "sha512-yAcIQxtmMiB/jL32dzEp2enBeidsB7xWPLNiw3IIkpVds1P+h7qF9YwJq1yUNzp2OKXgAprs4F61ih66UsoD1A==",
"dev": true,
"requires": {
"acorn": "^5.5.0",
"acorn-jsx": "^3.0.0"
}
},
"external-editor": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/external-editor/-/external-editor-2.2.0.tgz",
"integrity": "sha512-bSn6gvGxKt+b7+6TKEv1ZycHleA7aHhRHyAqJyp5pbUFuYYNIzpZnQDk7AsYckyWdEnTeAnay0aCy2aV6iTk9A==",
"dev": true,
"requires": {
"chardet": "^0.4.0",
"iconv-lite": "^0.4.17",
"tmp": "^0.0.33"
}
},
"inquirer": {
"version": "3.3.0",
"resolved": "https://registry.npmjs.org/inquirer/-/inquirer-3.3.0.tgz",
"integrity": "sha512-h+xtnyk4EwKvFWHrUYsWErEVR+igKtLdchu+o0Z1RL7VU/jVMFbYir2bp6bAj8efFNxWqHX0dIss6fJQ+/+qeQ==",
"dev": true,
"requires": {
"ansi-escapes": "^3.0.0",
"chalk": "^2.0.0",
"cli-cursor": "^2.1.0",
"cli-width": "^2.0.0",
"external-editor": "^2.0.4",
"figures": "^2.0.0",
"lodash": "^4.3.0",
"mute-stream": "0.0.7",
"run-async": "^2.2.0",
"rx-lite": "^4.0.8",
"rx-lite-aggregates": "^4.0.8",
"string-width": "^2.1.0",
"strip-ansi": "^4.0.0",
"through": "^2.3.6"
}
},
"ms": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz",
"integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==",
"dev": true
},
"regexpp": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/regexpp/-/regexpp-1.1.0.tgz",
"integrity": "sha512-LOPw8FpgdQF9etWMaAfG/WRthIdXJGYp4mJ2Jgn/2lpkbod9jPn0t9UqN7AxBOKNfzRbYyVfgc7Vk4t/MpnXgw==",
"dev": true
},
"slice-ansi": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-1.0.0.tgz",
"integrity": "sha512-POqxBK6Lb3q6s047D/XsDVNPnF9Dl8JSaqe9h9lURl0OdNqy/ujDrOiIHtsqXMGbWWTIomRzAMaTyawAU//Reg==",
"dev": true,
"requires": {
"is-fullwidth-code-point": "^2.0.0"
}
},
"table": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/table/-/table-4.0.2.tgz",
"integrity": "sha512-UUkEAPdSGxtRpiV9ozJ5cMTtYiqz7Ni1OGqLXRCynrvzdtR1p+cfOWe2RJLwvUG8hNanaSRjecIqwOjqeatDsA==",
"dev": true,
"requires": {
"ajv": "^5.2.3",
"ajv-keywords": "^2.1.0",
"chalk": "^2.1.0",
"lodash": "^4.17.4",
"slice-ansi": "1.0.0",
"string-width": "^2.1.1"
}
}
}
},
"prettier-eslint-cli": {
"version": "4.7.1",
"resolved": "https://registry.npmjs.org/prettier-eslint-cli/-/prettier-eslint-cli-4.7.1.tgz",
"integrity": "sha512-hQbsGaEVz97oBBcKdsJ46khv0kOGkMyWrXzcFOXW6X8UuetZ/j0yDJkNJgUTVc6PVFbbzBXk+qgd5vos9qzXPQ==",
"dev": true,
"requires": {
"arrify": "^1.0.1",
"babel-runtime": "^6.23.0",
"boolify": "^1.0.0",
"camelcase-keys": "^4.1.0",
"chalk": "2.3.0",
"common-tags": "^1.4.0",
"eslint": "^4.5.0",
"find-up": "^2.1.0",
"get-stdin": "^5.0.1",
"glob": "^7.1.1",
"ignore": "^3.2.7",
"indent-string": "^3.1.0",
"lodash.memoize": "^4.1.2",
"loglevel-colored-level-prefix": "^1.0.0",
"messageformat": "^1.0.2",
"prettier-eslint": "^8.5.0",
"rxjs": "^5.3.0",
"yargs": "10.0.3"
},
"dependencies": {
"acorn-jsx": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-3.0.1.tgz",
"integrity": "sha1-r9+UiPsezvyDSPb7IvRk4ypYs2s=",
"dev": true,
"requires": {
"acorn": "^3.0.4"
},
"dependencies": {
"acorn": {
"version": "3.3.0",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz",
"integrity": "sha1-ReN/s56No/JbruP/U2niu18iAXo=",
"dev": true
}
}
},
"chalk": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz",
"integrity": "sha512-Az5zJR2CBujap2rqXGaJKaPHyJ0IrUimvYNX+ncCy8PJP4ltOGTrHUIo097ZaL2zMeKYpiCdqDvS6zdrTFok3Q==",
"dev": true,
"requires": {
"ansi-styles": "^3.1.0",
"escape-string-regexp": "^1.0.5",
"supports-color": "^4.0.0"
}
},
"chardet": {
"version": "0.4.2",
"resolved": "https://registry.npmjs.org/chardet/-/chardet-0.4.2.tgz",
"integrity": "sha1-tUc7M9yXxCTl2Y3IfVXU2KKci/I=",
"dev": true
},
"cliui": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz",
"integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=",
"dev": true,
"requires": {
"string-width": "^1.0.1",
"strip-ansi": "^3.0.1",
"wrap-ansi": "^2.0.0"
},
"dependencies": {
"is-fullwidth-code-point": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz",
"integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=",
"dev": true,
"requires": {
"number-is-nan": "^1.0.0"
}
},
"string-width": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
"integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=",
"dev": true,
"requires": {
"code-point-at": "^1.0.0",
"is-fullwidth-code-point": "^1.0.0",
"strip-ansi": "^3.0.0"
}
},
"strip-ansi": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
"integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
"dev": true,
"requires": {
"ansi-regex": "^2.0.0"
}
}
}
},
"debug": {
"version": "3.2.6",
"resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz",
"integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==",
"dev": true,
"requires": {
"ms": "^2.1.1"
}
},
"eslint": {
"version": "4.19.1",
"resolved": "https://registry.npmjs.org/eslint/-/eslint-4.19.1.tgz",
"integrity": "sha512-bT3/1x1EbZB7phzYu7vCr1v3ONuzDtX8WjuM9c0iYxe+cq+pwcKEoQjl7zd3RpC6YOLgnSy3cTN58M2jcoPDIQ==",
"dev": true,
"requires": {
"ajv": "^5.3.0",
"babel-code-frame": "^6.22.0",
"chalk": "^2.1.0",
"concat-stream": "^1.6.0",
"cross-spawn": "^5.1.0",
"debug": "^3.1.0",
"doctrine": "^2.1.0",
"eslint-scope": "^3.7.1",
"eslint-visitor-keys": "^1.0.0",
"espree": "^3.5.4",
"esquery": "^1.0.0",
"esutils": "^2.0.2",
"file-entry-cache": "^2.0.0",
"functional-red-black-tree": "^1.0.1",
"glob": "^7.1.2",
"globals": "^11.0.1",
"ignore": "^3.3.3",
"imurmurhash": "^0.1.4",
"inquirer": "^3.0.6",
"is-resolvable": "^1.0.0",
"js-yaml": "^3.9.1",
"json-stable-stringify-without-jsonify": "^1.0.1",
"levn": "^0.3.0",
"lodash": "^4.17.4",
"minimatch": "^3.0.2",
"mkdirp": "^0.5.1",
"natural-compare": "^1.4.0",
"optionator": "^0.8.2",
"path-is-inside": "^1.0.2",
"pluralize": "^7.0.0",
"progress": "^2.0.0",
"regexpp": "^1.0.1",
"require-uncached": "^1.0.3",
"semver": "^5.3.0",
"strip-ansi": "^4.0.0",
"strip-json-comments": "~2.0.1",
"table": "4.0.2",
"text-table": "~0.2.0"
}
},
"eslint-scope": {
"version": "3.7.3",
"resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-3.7.3.tgz",
"integrity": "sha512-W+B0SvF4gamyCTmUc+uITPY0989iXVfKvhwtmJocTaYoc/3khEHmEmvfY/Gn9HA9VV75jrQECsHizkNw1b68FA==",
"dev": true,
"requires": {
"esrecurse": "^4.1.0",
"estraverse": "^4.1.1"
}
},
"espree": {
"version": "3.5.4",
"resolved": "https://registry.npmjs.org/espree/-/espree-3.5.4.tgz",
"integrity": "sha512-yAcIQxtmMiB/jL32dzEp2enBeidsB7xWPLNiw3IIkpVds1P+h7qF9YwJq1yUNzp2OKXgAprs4F61ih66UsoD1A==",
"dev": true,
"requires": {
"acorn": "^5.5.0",
"acorn-jsx": "^3.0.0"
}
},
"execa": {
"version": "0.7.0",
"resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz",
"integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=",
"dev": true,
"requires": {
"cross-spawn": "^5.0.1",
"get-stream": "^3.0.0",
"is-stream": "^1.1.0",
"npm-run-path": "^2.0.0",
"p-finally": "^1.0.0",
"signal-exit": "^3.0.0",
"strip-eof": "^1.0.0"
}
},
"external-editor": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/external-editor/-/external-editor-2.2.0.tgz",
"integrity": "sha512-bSn6gvGxKt+b7+6TKEv1ZycHleA7aHhRHyAqJyp5pbUFuYYNIzpZnQDk7AsYckyWdEnTeAnay0aCy2aV6iTk9A==",
"dev": true,
"requires": {
"chardet": "^0.4.0",
"iconv-lite": "^0.4.17",
"tmp": "^0.0.33"
}
},
"find-up": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz",
"integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=",
"dev": true,
"requires": {
"locate-path": "^2.0.0"
}
},
"get-stdin": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-5.0.1.tgz",
"integrity": "sha1-Ei4WFZHiH/TFJTAwVpPyDmOTo5g=",
"dev": true
},
"get-stream": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz",
"integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=",
"dev": true
},
"has-flag": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz",
"integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=",
"dev": true
},
"inquirer": {
"version": "3.3.0",
"resolved": "https://registry.npmjs.org/inquirer/-/inquirer-3.3.0.tgz",
"integrity": "sha512-h+xtnyk4EwKvFWHrUYsWErEVR+igKtLdchu+o0Z1RL7VU/jVMFbYir2bp6bAj8efFNxWqHX0dIss6fJQ+/+qeQ==",
"dev": true,
"requires": {
"ansi-escapes": "^3.0.0",
"chalk": "^2.0.0",
"cli-cursor": "^2.1.0",
"cli-width": "^2.0.0",
"external-editor": "^2.0.4",
"figures": "^2.0.0",
"lodash": "^4.3.0",
"mute-stream": "0.0.7",
"run-async": "^2.2.0",
"rx-lite": "^4.0.8",
"rx-lite-aggregates": "^4.0.8",
"string-width": "^2.1.0",
"strip-ansi": "^4.0.0",
"through": "^2.3.6"
}
},
"invert-kv": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz",
"integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=",
"dev": true
},
"lcid": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz",
"integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=",
"dev": true,
"requires": {
"invert-kv": "^1.0.0"
}
},
"mem": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/mem/-/mem-1.1.0.tgz",
"integrity": "sha1-Xt1StIXKHZAP5kiVUFOZoN+kX3Y=",
"dev": true,
"requires": {
"mimic-fn": "^1.0.0"
}
},
"ms": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz",
"integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==",
"dev": true
},
"os-locale": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/os-locale/-/os-locale-2.1.0.tgz",
"integrity": "sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA==",
"dev": true,
"requires": {
"execa": "^0.7.0",
"lcid": "^1.0.0",
"mem": "^1.1.0"
}
},
"regexpp": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/regexpp/-/regexpp-1.1.0.tgz",
"integrity": "sha512-LOPw8FpgdQF9etWMaAfG/WRthIdXJGYp4mJ2Jgn/2lpkbod9jPn0t9UqN7AxBOKNfzRbYyVfgc7Vk4t/MpnXgw==",
"dev": true
},
"slice-ansi": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-1.0.0.tgz",
"integrity": "sha512-POqxBK6Lb3q6s047D/XsDVNPnF9Dl8JSaqe9h9lURl0OdNqy/ujDrOiIHtsqXMGbWWTIomRzAMaTyawAU//Reg==",
"dev": true,
"requires": {
"is-fullwidth-code-point": "^2.0.0"
}
},
"supports-color": {
"version": "4.5.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz",
"integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=",
"dev": true,
"requires": {
"has-flag": "^2.0.0"
}
},
"table": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/table/-/table-4.0.2.tgz",
"integrity": "sha512-UUkEAPdSGxtRpiV9ozJ5cMTtYiqz7Ni1OGqLXRCynrvzdtR1p+cfOWe2RJLwvUG8hNanaSRjecIqwOjqeatDsA==",
"dev": true,
"requires": {
"ajv": "^5.2.3",
"ajv-keywords": "^2.1.0",
"chalk": "^2.1.0",
"lodash": "^4.17.4",
"slice-ansi": "1.0.0",
"string-width": "^2.1.1"
}
},
"y18n": {
"version": "3.2.1",
"resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz",
"integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=",
"dev": true
},
"yargs": {
"version": "10.0.3",
"resolved": "https://registry.npmjs.org/yargs/-/yargs-10.0.3.tgz",
"integrity": "sha512-DqBpQ8NAUX4GyPP/ijDGHsJya4tYqLQrjPr95HNsr1YwL3+daCfvBwg7+gIC6IdJhR2kATh3hb61vjzMWEtjdw==",
"dev": true,
"requires": {
"cliui": "^3.2.0",
"decamelize": "^1.1.1",
"find-up": "^2.1.0",
"get-caller-file": "^1.0.1",
"os-locale": "^2.0.0",
"require-directory": "^2.1.1",
"require-main-filename": "^1.0.1",
"set-blocking": "^2.0.0",
"string-width": "^2.0.0",
"which-module": "^2.0.0",
"y18n": "^3.2.1",
"yargs-parser": "^8.0.0"
}
},
"yargs-parser": {
"version": "8.1.0",
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-8.1.0.tgz",
"integrity": "sha512-yP+6QqN8BmrgW2ggLtTbdrOyBNSI7zBa4IykmiV5R1wl1JWNxQvWhMfMdmzIYtKU7oP3OOInY/tl2ov3BDjnJQ==",
"dev": true,
"requires": {
"camelcase": "^4.1.0"
}
}
}
},
"pretty-format": {
"version": "23.6.0",
"resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-23.6.0.tgz",
@ -8965,6 +9681,51 @@
"integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=",
"dev": true
},
"require-relative": {
"version": "0.8.7",
"resolved": "https://registry.npmjs.org/require-relative/-/require-relative-0.8.7.tgz",
"integrity": "sha1-eZlTn8ngR6N5KPoZb44VY9q9Nt4=",
"dev": true
},
"require-uncached": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/require-uncached/-/require-uncached-1.0.3.tgz",
"integrity": "sha1-Tg1W1slmL9MeQwEcS5WqSZVUIdM=",
"dev": true,
"requires": {
"caller-path": "^0.1.0",
"resolve-from": "^1.0.0"
},
"dependencies": {
"caller-path": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/caller-path/-/caller-path-0.1.0.tgz",
"integrity": "sha1-lAhe9jWB7NPaqSREqP6U6CV3dR8=",
"dev": true,
"requires": {
"callsites": "^0.2.0"
}
},
"callsites": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/callsites/-/callsites-0.2.0.tgz",
"integrity": "sha1-r6uWJikQp/M8GaV3WCXGnzTjUMo=",
"dev": true
},
"resolve-from": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-1.0.1.tgz",
"integrity": "sha1-Jsv+k10a7uq7Kbw/5a6wHpPUQiY=",
"dev": true
}
}
},
"reserved-words": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/reserved-words/-/reserved-words-0.1.2.tgz",
"integrity": "sha1-AKCUD5jNUBrqqsMWQR2a3FKzGrE=",
"dev": true
},
"resolve": {
"version": "1.10.0",
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.10.0.tgz",
@ -9058,6 +9819,30 @@
"aproba": "^1.1.1"
}
},
"rx-lite": {
"version": "4.0.8",
"resolved": "https://registry.npmjs.org/rx-lite/-/rx-lite-4.0.8.tgz",
"integrity": "sha1-Cx4Rr4vESDbwSmQH6S2kJGe3lEQ=",
"dev": true
},
"rx-lite-aggregates": {
"version": "4.0.8",
"resolved": "https://registry.npmjs.org/rx-lite-aggregates/-/rx-lite-aggregates-4.0.8.tgz",
"integrity": "sha1-dTuHqJoRyVRnxKwWJsTvxOBcZ74=",
"dev": true,
"requires": {
"rx-lite": "*"
}
},
"rxjs": {
"version": "5.5.12",
"resolved": "https://registry.npmjs.org/rxjs/-/rxjs-5.5.12.tgz",
"integrity": "sha512-xx2itnL5sBbqeeiVgNPVuQQ1nC8Jp2WfNJhXWHmElW9YmrpS9UVnNzhP3EH3HFqexO5Tlp8GhYY+WEcqcVMvGw==",
"dev": true,
"requires": {
"symbol-observable": "1.0.1"
}
},
"safe-buffer": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
@ -9689,6 +10474,12 @@
"has-flag": "^3.0.0"
}
},
"symbol-observable": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.0.1.tgz",
"integrity": "sha1-g0D8RwLDEi310iKI+IKD9RPT/dQ=",
"dev": true
},
"symbol-tree": {
"version": "3.2.2",
"resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.2.tgz",
@ -10109,6 +10900,30 @@
"integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=",
"dev": true
},
"typescript": {
"version": "2.9.2",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-2.9.2.tgz",
"integrity": "sha512-Gr4p6nFNaoufRIY4NMdpQRNmgxVIGMs4Fcu/ujdYk3nAZqk7supzBE9idmvfZIlH/Cuj//dvi+019qEue9lV0w==",
"dev": true
},
"typescript-eslint-parser": {
"version": "16.0.1",
"resolved": "https://registry.npmjs.org/typescript-eslint-parser/-/typescript-eslint-parser-16.0.1.tgz",
"integrity": "sha512-IKawLTu4A2xN3aN/cPLxvZ0bhxZHILGDKTZWvWNJ3sLNhJ3PjfMEDQmR2VMpdRPrmWOadgWXRwjLBzSA8AGsaQ==",
"dev": true,
"requires": {
"lodash.unescape": "4.0.1",
"semver": "5.5.0"
},
"dependencies": {
"semver": {
"version": "5.5.0",
"resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz",
"integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==",
"dev": true
}
}
},
"uglify-js": {
"version": "3.4.9",
"resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.4.9.tgz",
@ -10336,6 +11151,74 @@
"extsprintf": "^1.2.0"
}
},
"vue-eslint-parser": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-2.0.3.tgz",
"integrity": "sha512-ZezcU71Owm84xVF6gfurBQUGg8WQ+WZGxgDEQu1IHFBZNx7BFZg3L1yHxrCBNNwbwFtE1GuvfJKMtb6Xuwc/Bw==",
"dev": true,
"requires": {
"debug": "^3.1.0",
"eslint-scope": "^3.7.1",
"eslint-visitor-keys": "^1.0.0",
"espree": "^3.5.2",
"esquery": "^1.0.0",
"lodash": "^4.17.4"
},
"dependencies": {
"acorn-jsx": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-3.0.1.tgz",
"integrity": "sha1-r9+UiPsezvyDSPb7IvRk4ypYs2s=",
"dev": true,
"requires": {
"acorn": "^3.0.4"
},
"dependencies": {
"acorn": {
"version": "3.3.0",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz",
"integrity": "sha1-ReN/s56No/JbruP/U2niu18iAXo=",
"dev": true
}
}
},
"debug": {
"version": "3.2.6",
"resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz",
"integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==",
"dev": true,
"requires": {
"ms": "^2.1.1"
}
},
"eslint-scope": {
"version": "3.7.3",
"resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-3.7.3.tgz",
"integrity": "sha512-W+B0SvF4gamyCTmUc+uITPY0989iXVfKvhwtmJocTaYoc/3khEHmEmvfY/Gn9HA9VV75jrQECsHizkNw1b68FA==",
"dev": true,
"requires": {
"esrecurse": "^4.1.0",
"estraverse": "^4.1.1"
}
},
"espree": {
"version": "3.5.4",
"resolved": "https://registry.npmjs.org/espree/-/espree-3.5.4.tgz",
"integrity": "sha512-yAcIQxtmMiB/jL32dzEp2enBeidsB7xWPLNiw3IIkpVds1P+h7qF9YwJq1yUNzp2OKXgAprs4F61ih66UsoD1A==",
"dev": true,
"requires": {
"acorn": "^5.5.0",
"acorn-jsx": "^3.0.0"
}
},
"ms": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz",
"integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==",
"dev": true
}
}
},
"w3c-hr-time": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.1.tgz",

View File

@ -8,6 +8,7 @@
"develop:client": "cd ./client && npm run develop",
"develop:server": "cd ./api-server && node development-entry.js",
"ensure-env": "cross-env DEBUG=fcc:* node ./tools/scripts/ensure-env.js",
"format": "prettier-eslint --trailing-comma none --semi --eslint-ignore --ignore curriculum/challenges --ignore guide --ignore mock-guide --write './**/*.js'",
"lint": "eslint .",
"seed": "npm-run-all -p seed:*",
"seed:auth-user": "cross-env DEBUG=fcc:* node ./tools/scripts/seed/seedAuthUser",
@ -39,6 +40,7 @@
"lodash": "^4.17.11",
"npm-run-all": "^4.1.5",
"ora": "^3.0.0",
"prettier-eslint-cli": "^4.7.1",
"readdirp-walk": "^1.6.0",
"shortid": "^2.2.14",
"slugg": "^1.2.1"

View File

@ -36,9 +36,7 @@ describe('createRedirects', () => {
const { api, forum } = testLocations;
expect(redirects.includes(`${api}/internal/:splat`)).toBe(true);
expect(
redirects.includes(
`${forum}/t/free-code-camp-privacy-policy/19545 301`
)
redirects.includes(`${forum}/t/free-code-camp-privacy-policy/19545 301`)
).toBe(true);
expect(redirects.includes(`${forum}`)).toBe(true);
});

View File

@ -22,80 +22,77 @@ function handleError(err, client) {
}
}
MongoClient.connect(
MONGOHQ_URL,
{ useNewUrlParser: true },
function(err, client) {
MongoClient.connect(MONGOHQ_URL, { useNewUrlParser: true }, function(
err,
client
) {
handleError(err, client);
log('Connected successfully to mongo');
const db = client.db('freecodecamp');
const user = db.collection('user');
user.deleteOne({ _id: ObjectId('5bd30e0f1caf6ac3ddddddb5') }, err => {
handleError(err, client);
log('Connected successfully to mongo');
const db = client.db('freecodecamp');
const user = db.collection('user');
user.deleteOne({_id: ObjectId('5bd30e0f1caf6ac3ddddddb5') }, (err) => {
handleError(err, client);
try {
user.insertOne(
{
_id: ObjectId('5bd30e0f1caf6ac3ddddddb5'),
email: 'foo@bar.com',
emailVerified: true,
progressTimestamps: [],
isBanned: false,
isCheater: false,
username: 'DevelopmentUser',
about: '',
name: 'Development User',
location: '',
picture: 'https://identicon.org/?t=dev&s=256',
acceptedPrivacyTerms: true,
sendQuincyEmail: false,
currentChallengeId: '',
isHonest: false,
isFrontEndCert: false,
isDataVisCert: false,
isBackEndCert: false,
isFullStackCert: false,
isRespWebDesignCert: false,
is2018DataVisCert: false,
isFrontEndLibsCert: false,
isJsAlgoDataStructCert: false,
isApisMicroservicesCert: false,
isInfosecQaCert: false,
is2018FullStackCert: false,
completedChallenges: [],
portfolio: [],
yearsTopContributor: [],
rand: 0.6126749173148205,
theme: 'default',
profileUI: {
isLocked: true,
showAbout: false,
showCerts: false,
showDonation: false,
showHeatMap: false,
showLocation: false,
showName: false,
showPoints: false,
showPortfolio: false,
showTimeLine: false
},
badges: {
coreTeam: []
},
isDonating: false,
emailAuthLinkTTL: null,
emailVerifyTTL: null
}
);
} catch (e) {
handleError(e, client);
} finally {
log('local auth user seed complete');
client.close();
}
});
}
);
try {
user.insertOne({
_id: ObjectId('5bd30e0f1caf6ac3ddddddb5'),
email: 'foo@bar.com',
emailVerified: true,
progressTimestamps: [],
isBanned: false,
isCheater: false,
username: 'DevelopmentUser',
about: '',
name: 'Development User',
location: '',
picture: 'https://identicon.org/?t=dev&s=256',
acceptedPrivacyTerms: true,
sendQuincyEmail: false,
currentChallengeId: '',
isHonest: false,
isFrontEndCert: false,
isDataVisCert: false,
isBackEndCert: false,
isFullStackCert: false,
isRespWebDesignCert: false,
is2018DataVisCert: false,
isFrontEndLibsCert: false,
isJsAlgoDataStructCert: false,
isApisMicroservicesCert: false,
isInfosecQaCert: false,
is2018FullStackCert: false,
completedChallenges: [],
portfolio: [],
yearsTopContributor: [],
rand: 0.6126749173148205,
theme: 'default',
profileUI: {
isLocked: true,
showAbout: false,
showCerts: false,
showDonation: false,
showHeatMap: false,
showLocation: false,
showName: false,
showPoints: false,
showPortfolio: false,
showTimeLine: false
},
badges: {
coreTeam: []
},
isDonating: false,
emailAuthLinkTTL: null,
emailVerifyTTL: null
});
} catch (e) {
handleError(e, client);
} finally {
log('local auth user seed complete');
client.close();
}
});
});

View File

@ -26,66 +26,61 @@ function handleError(err, client) {
}
}
MongoClient.connect(
MONGOHQ_URL,
{ useNewUrlParser: true },
function(err, client) {
MongoClient.connect(MONGOHQ_URL, { useNewUrlParser: true }, function(
err,
client
) {
handleError(err, client);
log('Connected successfully to mongo at %s', MONGOHQ_URL);
const db = client.db('freecodecamp');
const challengeCollection = db.collection('challenge');
challengeCollection.deleteMany({}, async err => {
handleError(err, client);
log('Connected successfully to mongo at %s', MONGOHQ_URL);
log('deleted all the challenges');
const db = client.db('freecodecamp');
const challengeCollection = db.collection('challenge');
const curriculum = await getChallengesForLang(lang);
challengeCollection.deleteMany({}, async err => {
handleError(err, client);
log('deleted all the challenges');
const curriculum = await getChallengesForLang(lang);
const allChallenges = Object.keys(curriculum)
.map(key => curriculum[key].blocks)
.reduce((challengeArray, superBlock) => {
const challengesForBlock = Object.keys(superBlock).map(
key => superBlock[key].challenges
);
return [...challengeArray, ...flatten(challengesForBlock)];
}, [])
.map(challenge => {
const currentId = challenge.id.slice(0);
challenge._id = ObjectID(currentId);
delete challenge.id;
return challenge;
});
try {
challengeCollection.insertMany(
allChallenges,
{ ordered: false },
err => {
handleError(err, client);
log('challenge seed complete');
client.close();
}
const allChallenges = Object.keys(curriculum)
.map(key => curriculum[key].blocks)
.reduce((challengeArray, superBlock) => {
const challengesForBlock = Object.keys(superBlock).map(
key => superBlock[key].challenges
);
} catch (e) {
handleError(e, client);
} finally {
log('generating path migration map');
const pathMap = createPathMigrationMap(curriculum);
const outputDir = path.resolve(
__dirname,
'../../../api-server/server/resources/pathMigration.json'
);
fs.writeFile(outputDir, JSON.stringify(pathMap), err => {
if (err) {
console.error('Oh noes!!');
console.error(err);
}
log('path migration map generated');
});
}
});
}
);
return [...challengeArray, ...flatten(challengesForBlock)];
}, [])
.map(challenge => {
const currentId = challenge.id.slice(0);
challenge._id = ObjectID(currentId);
delete challenge.id;
return challenge;
});
try {
challengeCollection.insertMany(allChallenges, { ordered: false }, err => {
handleError(err, client);
log('challenge seed complete');
client.close();
});
} catch (e) {
handleError(e, client);
} finally {
log('generating path migration map');
const pathMap = createPathMigrationMap(curriculum);
const outputDir = path.resolve(
__dirname,
'../../../api-server/server/resources/pathMigration.json'
);
fs.writeFile(outputDir, JSON.stringify(pathMap), err => {
if (err) {
console.error('Oh noes!!');
console.error(err);
}
log('path migration map generated');
});
}
});
});