Compare commits

...

14 Commits

38 changed files with 650 additions and 244 deletions

View File

@ -30,6 +30,7 @@ const FlitterUnits = {
* available to the middleware-routing-controller stack.
*/
'Upload' : new (require('flitter-upload/UploadUnit'))(),
'CORS' : new (require('./app/CorsUnit'))(),
/*
* The Core Flitter Units

45
app/CorsUnit.js Normal file
View File

@ -0,0 +1,45 @@
const Unit = require('libflitter/Unit')
const cors = require('cors')
/*
* The Miscellaneous Unit
* -------------------------------------------------------------
* This is a Unit file where you should make any modifications that
* your application may need such as custom Express add-ons. Changes
* here are loaded after the core Flitter units, but before the other
* units (secondary, custom, error, and App), so they are available to
* other units in the stack.
*/
class CorsUnit extends Unit {
/*
* Initializes the unit class.
* This is called OUTSIDE of a Flitter context,
* so no other contexts are available. Modifications here
* take place before any part of Flitter is loaded or available.
*/
constructor(){
super()
}
/*
* Initialize the actual Unit.
* This is where most of the changes will go.
* This is provided an instance of the Express app
* so any custom changes can be made. The core Flitter
* contexts are available here, so things like config(),
* model(), etc. work.
*/
async go(app, context){
app.express.use(cors());
}
name(){
return "cors"
}
}
module.exports = exports = CorsUnit

View File

@ -1,4 +1,5 @@
const Unit = require('libflitter/Unit')
const cors = require('cors')
/*
* The Miscellaneous Unit
@ -32,15 +33,25 @@ class MiscUnit extends Unit {
* model(), etc. work.
*/
async go(app, context){
String.prototype.capitalize = function(){
return this.charAt(0).toUpperCase() + this.slice(1)
}
// do stuff here
global.devbug = {
version: '0.6.0',
version: '0.7.0',
get_inline: function(type, project){
let code = this.code[type];
if (!code) return false
code = code.replace(/{{ Project API Key }}/g, project.uuid).replace(/{{ Server URL }}/g, _flitter.config('server.url'))
return code
},
code: {
node: `require("devbugjs")
dbsetup({
\tserver: "https://CHANGEME:8000/", // DevBug Server URL
\tproject: "CHANGEME", // Project API Key
\tserver: "{{ Server URL }}", // DevBug Server URL
\tproject: "{{ Project API Key }}", // Project API Key
})`,
api: `// Send a multipart/form-data POST request to:
// http://#{_flitter.config('server.url')}/api/v1/out/<project api key>
@ -58,46 +69,71 @@ dbsetup({
// ===========================================================
// DEVBUG INLINE DEBUGGING HELPER - FOR USE WITH DEVBUG SERVER
// TODO: REMOVE BEFORE COMMITTING
$dev_outs = [];
function devbug_microtime($difftime = 0){
$time = explode(' ', microtime()); return ((float)$time[1]+(float)$time[0])-$difftime; }
$GLOBALS['devbug_dev_outs'] = [];
$GLOBALS['devbug_dev_out_iters'] = [];
$GLOBALS['devbug_bench_iters'] = [];
$GLOBALS['devbug_mark_time'] = devbug_microtime();
function out($key, $what, $group = null){
global $dev_outs;
if ( $group ){
if ( !array_key_exists($group, $dev_outs) ){
$dev_outs[$group] = [ $key => $what ];
}
else {
$dev_outs[$group][$key] = $what;
}
}
else {
$dev_outs[$key] = $what;
}
$dev_outs = $GLOBALS['devbug_dev_outs'];
if ( $group ){
if ( !array_key_exists($group, $dev_outs) ) $dev_outs[$group] = [ $key => $what ];
else $dev_outs[$group][$key] = $what;
}
else $dev_outs[$key] = $what;
$GLOBALS['devbug_dev_outs'] = $dev_outs;
}
function breakpoint($continue = false, $name = null){
global $dev_outs;
$devbug = "http://localhost:8000/";
$project_api_key = "CHANGEME";
$bt = debug_backtrace();
$caller = array_shift($bt);
$dev_outs = $GLOBALS['devbug_dev_outs'];
$devbug = "{{ Server URL }}/";
$project_api_key = "{{ Project API Key }}";
$bt = debug_backtrace();
$caller = array_shift($bt);
$time = devbug_microtime();
$dev_outs['DevBug Summary'] = [
'Start Time' => $GLOBALS['devbug_mark_time'],
'Breakpoint Time' => $time,
'Total Execution Time' => $time - $GLOBALS['devbug_mark_time'],
'Breakpoint Stacktrace' => $caller,
];
// Send to devbug server
$ch = curl_init();
$url = $devbug.'api/v1/out/'.$project_api_key;
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, [
'data' => json_encode([
'brief' => ($name ? $name : 'Breakpoint').': '.$caller['file'].': '.$caller['line'],
'data' => $dev_outs,
])
]);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$odata = curl_exec($ch);
if ( !$continue ) { exit(); }
// Send to devbug server
$ch = curl_init();
$url = $devbug.'api/v1/out/'.$project_api_key;
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, [
'data' => json_encode([
'brief' => ($name ? $name : 'Breakpoint').': '.$caller['file'].': '.$caller['line'],
'data' => $dev_outs,
])
]);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$odata = curl_exec($ch);
if ( !$continue ) { exit(); }
}
function devbugtime($prefix = 'time: '){ $mt = explode(' ', microtime()); $mt = $mt[1].' '.$mt[0]; return $prefix.$mt; }
function outt($key, $what, $group = null){ out(devbugtime($key), $what, $group); }
function outi($key, $what, $group = null){
$keyname = $group ? $key.$group : $key;
if ( !$GLOBALS['devbug_dev_out_iters'][$keyname] ) $GLOBALS['devbug_dev_out_iters'][$keyname] = 0;
out($key.'_'.$GLOBALS['devbug_dev_out_iters'][$keyname], $what, $group);
$GLOBALS['devbug_dev_out_iters'][$keyname]++;
}
function point(){
if ( !$GLOBALS['devbug_current_bench'] ) benchmark();
$bt = debug_backtrace();
$caller = array_shift($bt);
out('point: '.$caller['file'].': '.$caller['line'], devbugtime(), $GLOBALS['devbug_current_bench']);
}
function benchmark($name = "DevBug"){ $GLOBALS['devbug_current_bench'] = "Benchmark: ".$name; point(); }
function benchmarki($name = "DevBug"){
if ( !$GLOBALS['devbug_bench_iters'][$name] ) $GLOBALS['devbug_bench_iters'][$name] = 1;
benchmark($name.'('.$GLOBALS['devbug_bench_iters'][$name].')');
$GLOBALS['devbug_bench_iters'][$name]++;
}
function devbug_chop($string, $at=120){ return substr($string, 0, 30); }
// ===========================================================`,
},
permission: {

View File

@ -40,7 +40,7 @@ const devbug = {
json(data){
return JSON.stringify(JSON.rmref(JSON.decycle(data)));
},
breakpoint(name, exception = false){
breakpoint(except = false, name){
var e = new Error();
this.libs(() => {
var s = e.stack.split('at'); var caller = '';

View File

@ -1,52 +0,0 @@
// ===========================================================
// DEVBUG INLINE DEBUGGING HELPER - FOR USE WITH DEVBUG SERVER
// TODO: REMOVE BEFORE COMMITTING
let outs = {}
let devbug_url = 'http://localhost:8000/'
let project_api_key = 'CHANGEME'
const out = (key, what, group="") => {
if ( group ){
if ( Object.keys(outs).includes(group) ) outs[group][key] = what
else outs[group] = {}; outs[group][key] = what
}
else {
outs[key] = what
}
}
const breakpoint = (html = false, name = null) => {
var e = new Error();
(function() {
// Load better json
var js_decycle = document.createElement("script");
js_decycle.src = devbug_url+"assets/cycle.js";
js_decycle.type = 'text/javascript';
js_decycle.onload = () => {
// Load the script
var script = document.createElement("script");
script.src = 'https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js';
script.type = 'text/javascript';
script.onload = () => {
var $ = window.jQuery;
$(() => {
var s = e.stack.split('at'); var caller = '';
if ( s.length < 3 ) s = e.stack.split('@')
if ( s.length > 2 ) caller = s[2].trim()
else if ( s.length > 1 ) caller = s[1]
else caller = 'Unable to determine stacktrace'
var data = new FormData();
console.log(JSON.decycle({brief: (name ? name : 'Breakpoint: ')+caller,data: outs}))
data.append('data', JSON.stringify(JSON.rmref(JSON.decycle({brief: (name ? name : 'Breakpoint: ')+caller,data: outs}))))
$.ajax({
url: devbug_url+'api/v1/out/'+project_api_key,
data: data, cache: false, contentType: false, processData: false, method: 'POST', type: 'POST',
success: (res) => { console.log('DevBug POST Completed'); console.log(res) }
})
});
};
document.getElementsByTagName("head")[0].appendChild(script);
}
document.getElementsByTagName("head")[0].appendChild(js_decycle);
})();
}
window.out = out; window.breakpoint = breakpoint;
// ===========================================================

View File

@ -40,3 +40,5 @@ window.onscroll = () => {
navbar.classList.remove('sticky')
}
}
window.devbug_editor_theme = 'ace/theme/idle_fingers'

View File

@ -95,7 +95,7 @@ class v1 {
const user = await _flitter.model('User').findOne({uuid: invite.by_user_id})
if ( !user ) _flitter.error(res, 500, {reason: 'This user no longer exists. Sorry.'})
return _flitter.view(res, 'dash_v1:accept', {invite, project, user})
return _flitter.view(res, 'dash_v1:accept', {invite, project, created_by_user: user})
}
async invite_accept(req, res, next){

View File

@ -138,7 +138,38 @@ class v1 {
return _flitter.error(res, 401, {reason: 'You do not have permission to view this project.'})
}
return _flitter.view(res, 'dash_v1:view', {user: req.session.auth.user, snippets, project, outs, show_back: true, title: 'View: '+project.name })
return _flitter.view(res, 'dash_v1:view', {user: req.session.auth.user, snippets, project, outs, show_back: true, window_back: true, title: 'View: '+project.name })
}
async project_view_inline_helper(req, res, next){
const project = await Project.findById(req.params.id)
if ( !project ){
return _flitter.error(res, 404, {reason: 'Project not found with the specified ID.'})
}
if ( !await devbug.permission.project.view(project, req.session.auth.user) ){
return _flitter.error(res, 401, {reason: 'You do not have permission to view this project.'})
}
const code = devbug.get_inline(req.params.type, project)
if ( !code ) return _flitter.error(res, 404, {reason: 'Inline helper snippet not found with the specified type.'})
let type;
if ( req.params.type === 'node' ) type = 'javascript'
else if ( req.params.type === 'php' ) type = 'php'
else type = 'text'
return _flitter.view(res, 'dash_v1:in_editor', {
user: req.session.auth.user,
project,
show_back: true,
readonly: true,
editor_code: code,
editor_lang: 'ace/mode/'+type,
title: 'Inline Helper for '+project.name+' ('+req.params.type+')'
})
}
async out_view(req, res, next){
@ -166,6 +197,37 @@ class v1 {
return _flitter.view(res, 'dash_v1:out', {project, user: req.session.auth.user, out, prettyd:pretty, show_back: true, title: out.brief, title_small: true });
}
async out_latest(req, res, next){
const project = await Project.findById(req.params.project)
if ( !project || (!await devbug.permission.project.view(project, req.session.auth.user)) ){
return _flitter.error(res, 401, {reason: 'You do not have permission to view this project.'})
}
const out = await Out.findOne({project_id: project.id}, {}, { sort: { 'created': -1 } })
if ( !out ){
return _flitter.error(res, 404, {reason: 'This project has no outputs yet.'})
}
let pretty
try {
pretty = JSON.stringify(JSON.parse(out.data), null, 4)
console.log('Pretty out: ', pretty)
}
catch (e){
return _flitter.error(res, 500, {reason: 'Unable to parse output data. Data contains invalid JSON.'})
}
return _flitter.view(res, 'dash_v1:out', {
project,
user: req.session.auth.user,
out,
prettyd:pretty,
show_back: true,
title: `Latest output: ${out.brief} <small>(${out.created.toLocaleString({timeZone: 'America/Chicago'})})</small>`,
title_small: true
});
}
async out_delete(req, res, next){
const out = await Out.findById(req.params.id)

View File

@ -6,7 +6,9 @@
* globally using the model() function.
*/
const Greeting = {
name: String,
schema: {
name: String,
},
}
module.exports = Greeting

View File

@ -5,10 +5,11 @@
/**
* This model stores the role data from Flitter-auth.
*
* @type {Object}
*/
module.exports = exports = {
name: String,
permissions: [String],
data: String,
schema: {
name: String,
permissions: [String],
data: String,
},
}

View File

@ -8,13 +8,14 @@
* stored instead of cleartext. The data field is for JSON data that
* holds various non-DB essential pieces of information about users.
*
* @type {Object}
*/
module.exports = exports = {
username: String,
password: String,
data: String,
uuid: String,
role: String,
permissions: [String],
schema: {
username: String,
password: String,
data: String,
uuid: String,
role: String,
permissions: [String],
},
}

View File

@ -4,10 +4,12 @@
* Put some description here!
*/
const File = {
original_name: String,
new_name: String,
mime: String,
type: String,
schema: {
original_name: String,
new_name: String,
mime: String,
type: String,
},
}
module.exports = exports = File

View File

@ -4,11 +4,16 @@
* Put some description here!
*/
const Invite = {
project_id: String,
by_user_id: String,
api_type: String,
created_on: Date,
used: { type: Boolean, default: false }
schema: {
project_id: String,
by_user_id: String,
api_type: String,
created_on: Date,
used: {
type: Boolean,
default: false
}
},
}
module.exports = exports = Invite

View File

@ -4,10 +4,15 @@
* Put some description here!
*/
const Out = {
project_id: String,
created: { type: Date, default: Date.now },
brief: String,
data: String,
schema: {
project_id: String,
created: {
type: Date,
default: Date.now
},
brief: String,
data: String,
},
}
module.exports = exports = Out

View File

@ -5,13 +5,21 @@
*/
const uuid = require('uuid/v4')
const Project = {
name: String,
user_id: String,
archived: { type: Boolean, default: false },
data: String,
shared_user_ids: [String],
edit_user_ids: [String],
uuid: { type: String, default: uuid }
schema: {
name: String,
user_id: String,
archived: {
type: Boolean,
default: false
},
data: String,
shared_user_ids: [String],
edit_user_ids: [String],
uuid: {
type: String,
default: uuid
}
},
}
module.exports = exports = Project

View File

@ -5,16 +5,24 @@
*/
const uuid = require('uuid/v4')
const Snippet = {
name: String,
user_id: String,
archived: { type: Boolean, default: false },
data: String,
shared_user_ids: [String],
edit_user_ids: [String],
uuid: { type: String, default: uuid },
public_share: String,
mode: String,
project_id: String,
schema: {
name: String,
user_id: String,
archived: {
type: Boolean,
default: false
},
data: String,
shared_user_ids: [String],
edit_user_ids: [String],
uuid: {
type: String,
default: uuid
},
public_share: String,
mode: String,
project_id: String,
},
}
module.exports = exports = Snippet

View File

@ -3,7 +3,8 @@
* -------------------------------------------------------------
* Put some description here!
*/
class Debug {
const Middleware = require('libflitter/middleware/Middleware')
class Debug extends Middleware {
/*
* Run the middleware test.
@ -11,10 +12,10 @@ class Debug {
* It should either call the next function in the stack,
* or it should handle the response accordingly.
*/
test(req, res, next, args = {}){
test(req, res, next, args = {}) {
console.log('DEBUGGING LAYER:')
console.log('Incoming destination: '+req.originalUrl)
console.log('Incoming method: '+req.method)
console.log('Incoming destination: ' + req.originalUrl)
console.log('Incoming method: ' + req.method)
/*
* Call the next function in the stack.

View File

@ -6,7 +6,8 @@
* the '/' route is accessed. It can be injected in routes globally using
* the global mw() function.
*/
class HomeLogger {
const Middleware = require('libflitter/middleware/Middleware')
class HomeLogger extends Middleware {
/*
* Run the middleware test.
@ -14,7 +15,7 @@ class HomeLogger {
* It should either call the next function in the stack,
* or it should handle the response accordingly.
*/
test(req, res, next){
test(req, res, next) {
console.log("Home was accessed!")
/*

View File

@ -8,7 +8,8 @@
*
* @class
*/
class Permission {
const Middleware = require('libflitter/middleware/Middleware')
class Permission extends Middleware {
/**
* Run the middleware's check. If an authenticated session exists and the user has the specified permission,
@ -19,27 +20,29 @@ class Permission {
* @param {Function} next - Express handler stack callback. This should be called if the middleware check passed to allow the request to continue.
* @param {string} permission - Name of the permission to require
*/
async test(req, res, next, permission){
if ( req.session && req.session.auth && (req.session.auth.authenticated === true || req.session.auth.user) ){
if ( req.session.auth.user.permissions && req.session.auth.user.permissions.includes(permission) ){
async test(req, res, next, permission) {
if (req.session && req.session.auth && (req.session.auth.authenticated === true || req.session.auth.user)) {
if (req.session.auth.user.permissions && req.session.auth.user.permissions.includes(permission)) {
next()
}
else if ( req.session.auth.user.role ){
} else if (req.session.auth.user.role) {
const Role = _flitter.model('auth:Role')
const role = await Role.findOne({name: req.session.auth.user.role})
const role = await Role.findOne({
name: req.session.auth.user.role
})
if ( role.permissions.includes(permission) ){
if (role.permissions.includes(permission)) {
next()
} else {
return _flitter.error(res, 401, {
reason: 'Insufficient user permissions.'
})
}
else {
return _flitter.error(res, 401, {reason: 'Insufficient user permissions.'})
}
} else {
return _flitter.error(res, 401, {
reason: 'Insufficient user permissions.'
})
}
else {
return _flitter.error(res, 401, {reason: 'Insufficient user permissions.'})
}
}
else {
} else {
req.session.destination = req.originalUrl
return res.redirect('/auth/login')
}

View File

@ -8,7 +8,8 @@
*
* @class
*/
class RequireAuth {
const Middleware = require('libflitter/middleware/Middleware')
class RequireAuth extends Middleware {
/**
* Run the middleware's check. If an authenticated session exists, let the request continue.
@ -18,14 +19,13 @@ class RequireAuth {
* @param {Express/Response} res - the corresponding Express response
* @param {Function} next - Express handler stack callback. This should be called if the middleware check passed to allow the request to continue.
*/
test(req, res, next){
if ( req.session && req.session.auth && (req.session.auth.authenticated === true || req.session.auth.user) ){
test(req, res, next) {
if (req.session && req.session.auth && (req.session.auth.authenticated === true || req.session.auth.user)) {
/*
* Call the next function in the stack.
*/
next()
}
else {
} else {
req.session.destination = req.originalUrl
return res.redirect('/auth/login')
}

View File

@ -8,7 +8,8 @@
*
* @class
*/
class RequireGuest {
const Middleware = require('libflitter/middleware/Middleware')
class RequireGuest extends Middleware {
/**
* Run the middleware test. If an authenticated session exists, redirect the user to an error page.
@ -17,8 +18,8 @@ class RequireGuest {
* @param {Express/Response} res - the corresponding Express response
* @param {Function} next - The callback to continue the Express request handling stack. This is called if the middleware check passes.
*/
test(req, res, next){
if ( req.session && req.session.auth && (req.session.auth.authenticated === true || req.session.auth.user) ){
test(req, res, next) {
if (req.session && req.session.auth && (req.session.auth.authenticated === true || req.session.auth.user)) {
return _flitter.view(res, 'errors/requires_guest')
}

View File

@ -8,7 +8,8 @@
*
* @class
*/
class Role {
const Middleware = require('libflitter/middleware/Middleware')
class Role extends Middleware {
/**
* Run the middleware's check. If an authenticated session exists and the user has the specified role,
@ -19,16 +20,16 @@ class Role {
* @param {Function} next - Express handler stack callback. This should be called if the middleware check passed to allow the request to continue.
* @param {string} role - Name of the role to require
*/
test(req, res, next, role){
if ( req.session && req.session.auth && (req.session.auth.authenticated === true || req.session.auth.user) ){
if ( req.session.auth.user.role && req.session.auth.user.role === role ){
test(req, res, next, role) {
if (req.session && req.session.auth && (req.session.auth.authenticated === true || req.session.auth.user)) {
if (req.session.auth.user.role && req.session.auth.user.role === role) {
next()
} else {
return _flitter.error(res, 401, {
reason: 'Insufficient user permissions.'
})
}
else {
return _flitter.error(res, 401, {reason: 'Insufficient user permissions.'})
}
}
else {
} else {
req.session.destination = req.originalUrl
return res.redirect('/auth/login')
}

View File

@ -3,7 +3,8 @@
* -------------------------------------------------------------
* Put some description here!
*/
class Invite {
const Middleware = require('libflitter/middleware/Middleware')
class Invite extends Middleware {
/*
* Run the middleware test.
@ -11,8 +12,8 @@ class Invite {
* It should either call the next function in the stack,
* or it should handle the response accordingly.
*/
test(req, res, next, args = {}){
if ( req.session.invite && !req.originalUrl.includes('/dash/v1/invitation/accept') ){
test(req, res, next, args = {}) {
if (req.session.invite && !req.originalUrl.includes('/dash/v1/invitation/accept')) {
return res.redirect('/dash/v1/invitation/accept')
}

View File

@ -39,6 +39,7 @@ const v1 = {
'/project/new': [ _flitter.controller('dash:v1').new_project_show ],
'/project/view/:id': [ _flitter.controller('dash:v1').project_view ],
'/project/view/:id/inline/:type': [ _flitter.controller('dash:v1').project_view_inline_helper ],
'/project/delete/:id': [ _flitter.controller('dash:v1').project_delete_show ],
'/project/edit/:id': [ _flitter.controller('dash:v1').project_edit_show ],
'/:api/share/:id': [ _flitter.controller('dash:v1').project_share_show ],
@ -56,6 +57,7 @@ const v1 = {
'/using_devbug/:page': [ _flitter.controller('dash:v1').show_usage_page ],
'/out/view/:id': [ _flitter.controller('dash:v1').out_view ],
'/out/view-latest/:project': [ _flitter.controller('dash:v1').out_latest ],
'/out/delete/:id/:project': [ _flitter.controller('dash:v1').out_delete ],
'/code': [ _flitter.controller('dash:v1').view_code ],

View File

@ -1,19 +1,150 @@
html
head
title Sharing Invitation | DevBug
link(rel='stylesheet' href='/assets/dash_v1.css')
script(src='/assets/dash_v1.js')
body
.page-header
.devbug-header DevBug | v#{devbug.version} #{(project ? " | Project: "+project.name : "")}
h1 Accept Invitation?
ul.navul
li.navli
a.nava(href='/dash/v1') Dashboard Login
.spacer
p You've been invited to view the debugging #{invite.api_type} "#{project.name}" by #{user.username}.
p To accept this invitation, you must have a DevBug account. You may be redirected to the registration portal.
a.btn(href='/api/v1/invitation/'+invite.id+'/accept') Accept
br
h3 What's DevBug?
p DevBug is a debugging output server used to help developers work more efficiently. Using inline-code clients, developers can output variables and data from their programs. This data is stored in a DevBug project, where it can easily be shared with others.
title #{title ? title : "Accept Invitation | DevBug"}
style(type="text/css").
@import url(https://fonts.googleapis.com/css?family=Roboto:300);
.login-page {
width: 500px;
padding: 6% 0 0;
margin: auto;
}
.form {
position: relative;
z-index: 1;
background: #FFFFFF;
max-width: 500px;
min-width: 360px;
margin: 0 auto 100px;
padding: 45px;
text-align: center;
box-shadow: 0 0 20px 0 rgba(0, 0, 0, 0.2), 0 5px 5px 0 rgba(0, 0, 0, 0.24);
}
.form input {
font-family: "Roboto", sans-serif;
outline: 0;
background: #f2f2f2;
width: 100%;
border: 0;
margin: 0 0 15px;
padding: 15px;
box-sizing: border-box;
font-size: 14px;
color: #006a81;
}
.form button, .form-button {
font-family: "Roboto", sans-serif;
text-transform: uppercase;
outline: 0;
background: #006a81;
width: 100%;
border: 0;
padding: 12px;
color: #FFFFFF;
font-size: 16px;
-webkit-transition: background 0.6s;
-moz-transition: background 0.6s;
-ms-transition: background 0.6s;
-o-transition: background 0.6s;
transition: background 0.6s;
cursor: pointer;
}
.form button:hover, .form button:active, .form button:focus, .form-button:hover, .form-button:active, .form-button:focus {
background: #00b3da;
}
.form-button {
text-decoration: none;
}
.form .message {
margin: 15px 0 0;
color: #b3b3b3;
font-size: 12px;
}
.form .message a {
color: #006a81;
text-decoration: none;
}
.container .info h1 {
margin: 0 0 15px;
padding: 0;
font-size: 36px;
font-weight: 300;
color: #1a1a1a;
}
.container .info span {
color: #4d4d4d;
font-size: 12px;
}
.container .info span a {
color: #000000;
text-decoration: none;
}
body {
background: #c7dbdf;
font-family: "Roboto", sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.flitter-logo {
height: 100px;
margin-bottom: 15px;
}
.form-title, .form-subtitle {
font-family: "Roboto", sans-serif;
font-size: 16pt;
color: #006a81;
}
.form-subtitle {
text-align: left;
/*margin-top: 50px;*/
font-size: 14pt;
padding: 15px;
padding-bottom: 0;
padding-top: 0;
margin-bottom: 0;
}
.left-body {
text-align: left;
padding: 15px;
margin-top: 0;
}
.row-item {
margin-left: 10px;
}
.item-row {
margin-top: 65px;
}
.body-sep {
margin-top: 45px;
margin-bottom: 45px;
}
body
.login-page
.form
img.flitter-logo(src="/assets/flitter.png")
p.form-title View #{invite.api_type.capitalize()}: #{project.name}
p.left-body You've been invited to view a debugging #{invite.api_type} by #{created_by_user.username}. To accept this invitation, you must have a DevBug account. You may be redirected to the sign-in portal.
.item-row
a.form-button.row-item-first(href='/api/v1/invitation/'+invite.id+'/accept') Accept & View
a.form-button.row-item(href='/dash/v1') Decline
hr.body-sep
p.form-subtitle What's DevBug?
p.left-body DevBug is a debugging output server used to help developers work more efficiently. Using inline-code clients, developers can output variables and data from their programs. This data is stored in a DevBug project, where it can easily be shared with others.

View File

@ -2,4 +2,4 @@ extends ./template
block content
p #{text}
form(method='post' action=destination)
button(type='submit') Yes, I'm sure.
button.btn(type='submit') Yes, I'm sure.

View File

@ -11,7 +11,7 @@ html
- var e_project = (user && project && devbug.permission.project.sync_edit(project, user))
#pre-header-content DevBug | v#{devbug.version} #{(user ? " | User: "+user.username : "")} #{(e_project ? " | Project: "+project.name+" | API: "+project.uuid : "")} #{((_flitter.config('server.environment') === 'development') ? " | Development" : "" )} | <i>Editor Mode</i>
#title-header
#title-header-content-sm #{title ? title : 'DevBug Dashboard'}
#title-header-content-sm !{title ? title : 'DevBug Dashboard'}
.iheader
block header
.idiv
@ -26,7 +26,14 @@ html
a#navbar-usage(href='/dash/v1/using_devbug/main') Using DevBug
li.navbar-right
a#navbar-logout(href='/auth/logout') Logout
if show_back
if show_back && (!project || window_back)
li.navbar-right
a#navbar-back(href='javascript:window.history.back()') Back
else if show_back && project
li.navbar-right
a#navbar-back(href='/dash/v1/project/view/'+project.id) Back to Project
if project && !hide_project_latest
li.navbar-right
a#navbar-project-latest(href="/dash/v1/out/view-latest/"+project.id) View Latest Output
script(src="/assets/dash_v1.js")
block scripts

View File

@ -0,0 +1,17 @@
extends ./editor_template
block content
pre#editor #{ editor_code ? editor_code : '' }
input#preset_mode(type='hidden' value=editor_lang ? editor_lang : 'ace/mode/text')
block scripts
script(src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.4.5/ace.js")
script.
const readonly = #{!!readonly}
const preset_mode = document.getElementById('preset_mode').value
const editor = ace.edit('editor');
editor.setTheme(window.devbug_editor_theme);
console.log('preset mode: ', preset_mode);
editor.session.setMode(preset_mode);
if ( readonly ){
editor.setOption('readOnly', true)
}

View File

@ -15,6 +15,8 @@ block content
ul(style='list-style-type: none; margin: 0; padding: 0;')
li.action-li
a.action(href='/dash/v1/project/view/'+project.id) View
li.action-li
a.action(href='/dash/v1/out/view-latest/'+project.id) Latest Output
li.action-li
a.action(href='/dash/v1/project/share/'+project.id) Share
li.action-li

View File

@ -6,6 +6,6 @@ block scripts
script(src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.4.5/ace.js")
script.
const editor = ace.edit('editor');
editor.setTheme('ace/theme/cobalt');
editor.setTheme(window.devbug_editor_theme);
editor.session.setMode('ace/mode/json');
editor.setOption('readOnly', true);

View File

@ -96,7 +96,7 @@ block scripts
const readonly = #{!!readonly}
const preset_mode = document.getElementById('preset_mode').value
const editor = ace.edit('editor');
editor.setTheme('ace/theme/cobalt');
editor.setTheme(window.devbug_editor_theme);
console.log('preset mode: ', preset_mode);
editor.session.setMode(preset_mode);
document.getElementById('snippet_mode').value = preset_mode

View File

@ -14,11 +14,19 @@ html
a#navbar-home(href='/dash/v1') Home
li
a#navbar-usage(href='/dash/v1/using_devbug/main') Using DevBug
block navbar-left
li.navbar-right
a#navbar-logout(href='/auth/logout') Logout
if show_back
if show_back && (!project || window_back)
li.navbar-right
a#navbar-back(href='javascript:window.history.back()') Back
else if show_back && project
li.navbar-right
a#navbar-back(href='/dash/v1/project/view/'+project.id) Back to Project
if project && !hide_project_latest
li.navbar-right
a#navbar-project-latest(href="/dash/v1/out/view-latest/"+project.id) View Latest Output
block navbar-right
.content
block content
block scripts

View File

@ -1,11 +1,11 @@
extends ../template
block content
h3 DevBug supports ECMAscript on the web.
p To use the client, include the ECMAscript client file in your application, as early as possible. This file is hosted by your local DevBug server, and is available <a href="/assets/agents/web.js" target="_blank">here.</a> Then, set the project API key and server addresses (see the code snippet below). This gives you access to the global <code>out()</code> and <code>breakpoint()</code> functions. Here's how to use them:
h3 DevBug supports ECMAScript on the web.
p To use the client, include the ECMAScript client file in your application, as early as possible. This file is hosted by your local DevBug server, and is available <a href="/assets/agents/ecma5.js" target="_blank">here.</a> Then, set the project API key and server addresses (see the code snippet below). This gives you access to the global <code>out()</code> and <code>breakpoint()</code> functions. Here's how to use them:
h4 <code>out(<i>info</i>, <i>data</i>)</code> - output data to DevBug
p This function is similar to logging data. It stores data to be outputted to DevBug. The first parameter should be a string with a brief description of the data, and the second is the data to be outputted. Note that the info string should be unique and multiple outputs with the same name will overwrite their predecessors. It's important to note that calling this function doesn't actually <i>send</i> any data to DevBug. Instead, it stores it to be sent.
h4 <code>breakpoint(<i>continue = false</i>, <i>name = ""</i>)</code> - send the outputted data to DevBug
p This is the magic of the operation. When this function is called, any data that has been passed to the output function will be sent to the DevBug server and stored under the configured project. There are several things you can change about this function. The <code>continue</code> parameter determines whether or not program execution continues, or if the interpreter's exit method is called. The <code>name</code> parameter allows you to change the name of the breakpoint. This can be useful to help distinguish multiple breakpoints in the DevBug dashboard. Note that the continuation parameter is non-functional in browser-based ECMAscript.
p This is the magic of the operation. When this function is called, any data that has been passed to the output function will be sent to the DevBug server and stored under the configured project. There are several things you can change about this function. The <code>continue</code> parameter determines whether or not program execution continues, or if the interpreter's exit method is called. The <code>name</code> parameter allows you to change the name of the breakpoint. This can be useful to help distinguish multiple breakpoints in the DevBug dashboard. Note that the continuation parameter is non-functional in browser-based ECMAScript. Instead, the breakpoint throws an exception.
pre#editor.inline // Run the following as early in your application as your can:&#10;devbug_url="http://localhost:8000/";&#10;project_api_key="CHANGEME";
block scripts

View File

@ -1,6 +1,23 @@
extends ./template
block content
h3 Project API Key: #{project.uuid}
h2 Project API Key:
pre
code #{project.uuid}
h2 Inline Helpers
p You can use the links below to generate inline helper scripts which are pre-configured for this project.
ul(style='list-style-type: none; margin: 0; padding: 0;')
li.action-li
a.btn(href=project.id+'/inline/node') Node.js
//li.action-li
// a.btn(href=project.id+'/inline/ecma') JavaScript (Web)
li.action-li
a.btn(href=project.id+'/inline/php') PHP
//li.action-li
// a.btn(href=project.id+'/inline/api') DevBug API
br
br
h2 Code Snippets
a.btn(href='/dash/v1/project/snippet/'+project.id+'/new') +
@ -26,6 +43,7 @@ block content
a.action(href='/dash/v1/snippet/share/'+snippet.id) Share
h2 Development Outputs
a.btn(href='/dash/v1/out/view-latest/'+project.id) Latest
table
thead
tr

View File

@ -18,5 +18,15 @@
"id": 1560988609,
"name": "move_database_unit_before_express_unit",
"migratedOn": "2019-06-21T00:31:38.019Z"
},
{
"id": 1565741502,
"name": "convert_to_new_model_schema_definitions",
"migratedOn": "2019-08-15T14:58:30.109Z"
},
{
"id": 1565925593,
"name": "make_existing_middleware_extend_base_class",
"migratedOn": "2019-08-16T14:49:39.934Z"
}
]

View File

@ -16,12 +16,14 @@
"author": "Garrett Mills <garrett@glmdev.tech> (https://glmdev.tech/)",
"license": "MIT",
"dependencies": {
"cors": "^2.8.5",
"flitter-auth": "^0.4.0",
"flitter-cli": "^0.10.0",
"flitter-flap": "^0.2.2",
"flitter-flap": "^0.4.0",
"flitter-forms": "^0.7.2",
"flitter-upload": "^0.7.6",
"libflitter": "^0.27.4",
"js-beautify": "^1.10.2",
"libflitter": "^0.31.1",
"stringify-object": "^3.3.0"
}
}

4
todo.txt Normal file
View File

@ -0,0 +1,4 @@
- Standardize inline TypeScript - load dynamically?
- Standardize inline PHP
- Serve jQuery from local server assets
- Use a closer-matching Ace theme

127
yarn.lock
View File

@ -487,7 +487,7 @@ command-line-args@^5.0.2:
lodash.camelcase "^4.3.0"
typical "^4.0.0"
commander@^2.5.0, commander@^2.9.0:
commander@^2.19.0, commander@^2.5.0, commander@^2.9.0:
version "2.20.0"
resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.0.tgz#d58bb2b5c1ee8f87b0d340027e9e94e222c5a422"
integrity sha512-7j2y+40w61zy6YC2iRNpUe/NwhNyoXrYpHMrSunaMG64nRnaf96zO/KMQR4OyN/UnE5KLyEBnKHd4aG3rskjpQ==
@ -512,6 +512,14 @@ concat-map@0.0.1:
resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=
config-chain@^1.1.12:
version "1.1.12"
resolved "https://registry.yarnpkg.com/config-chain/-/config-chain-1.1.12.tgz#0fde8d091200eb5e808caf25fe618c02f48e4efa"
integrity sha512-a1eOIcu8+7lUInge4Rpf/n4Krkf3Dd9lqhljRzII1/Zno/kRtUWnznPO3jOKBmTEktkt3fkxisUcivoj0ebzoA==
dependencies:
ini "^1.3.4"
proto-list "~1.2.1"
connect-mongodb-session@^2.2.0:
version "2.2.0"
resolved "https://registry.yarnpkg.com/connect-mongodb-session/-/connect-mongodb-session-2.2.0.tgz#3d70bc9912756bfdfd2aeeda4def1fd9e07c69a6"
@ -577,6 +585,14 @@ core-util-is@~1.0.0:
resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7"
integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=
cors@^2.8.5:
version "2.8.5"
resolved "https://registry.yarnpkg.com/cors/-/cors-2.8.5.tgz#eac11da51592dd86b9f06f6e7ac293b3df875d29"
integrity sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==
dependencies:
object-assign "^4"
vary "^1"
debug@2.6.9, debug@^2.1.0, debug@^2.1.1:
version "2.6.9"
resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f"
@ -701,6 +717,16 @@ dotenv@^6.2.0:
resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-6.2.0.tgz#941c0410535d942c8becf28d3f357dbd9d476064"
integrity sha512-HygQCKUBSFl8wKQZBSemMywRWcEDNidvNbjGVyZu3nbZ8qq9ubiPoGLMdRDpfSrpkkm9BXYFkpKxxFX38o/76w==
editorconfig@^0.15.3:
version "0.15.3"
resolved "https://registry.yarnpkg.com/editorconfig/-/editorconfig-0.15.3.tgz#bef84c4e75fb8dcb0ce5cee8efd51c15999befc5"
integrity sha512-M9wIMFx96vq0R4F+gRpY3o2exzb8hEj/n9S8unZtHSvYjibBp/iMufSzvmOcV/laG0ZtuTVGtiJggPOSW2r93g==
dependencies:
commander "^2.19.0"
lru-cache "^4.1.5"
semver "^5.6.0"
sigmund "^1.0.1"
ee-first@1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d"
@ -851,12 +877,13 @@ flitter-cli@^0.10.0:
mkdirp "^0.5.1"
nesh "^1.7.0"
flitter-flap@^0.2.2:
version "0.2.2"
resolved "https://registry.yarnpkg.com/flitter-flap/-/flitter-flap-0.2.2.tgz#5735567510ba85ebfede2e1ed47dc2f36c0e962b"
integrity sha512-iy1RqEcls36NDTGO6u/IZ58z/2yQFeR1Sa/BqTGkKzPQFOBoxMl7uoFSsMvmiwH9d6qJDOZ5SE2jGTav9NJNtw==
flitter-flap@^0.4.0:
version "0.4.0"
resolved "https://registry.yarnpkg.com/flitter-flap/-/flitter-flap-0.4.0.tgz#ab1cdfc5b9ffe0b5b9fe2e3a8bdc87e9aac82c0e"
integrity sha512-1pfGAckDJ7RZIK6qheAz2dwA4PV/03Z7rPhhVuDqZbuemtiozLgDLPQXzGwSLQESWNuG6CBg3KMEd0CPppB1/Q==
dependencies:
del "^4.1.0"
js-beautify "^1.10.2"
node-migration "^1.0.1"
touch "^3.1.0"
@ -1060,7 +1087,7 @@ inherits@2, inherits@2.0.3, inherits@~2.0.1, inherits@~2.0.3:
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de"
integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=
ini@~1.3.0:
ini@^1.3.4, ini@~1.3.0:
version "1.3.5"
resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.5.tgz#eee25f56db1c9ec6085e0c22778083f596abf927"
integrity sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==
@ -1173,6 +1200,17 @@ isarray@~1.0.0:
resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11"
integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=
js-beautify@^1.10.2:
version "1.10.2"
resolved "https://registry.yarnpkg.com/js-beautify/-/js-beautify-1.10.2.tgz#88c9099cd6559402b124cfab18754936f8a7b178"
integrity sha512-ZtBYyNUYJIsBWERnQP0rPN9KjkrDfJcMjuVGcvXOUJrD1zmOGwhRwQ4msG+HJ+Ni/FA7+sRQEMYVzdTQDvnzvQ==
dependencies:
config-chain "^1.1.12"
editorconfig "^0.15.3"
glob "^7.1.3"
mkdirp "~0.5.1"
nopt "~4.0.1"
js-stringify@^1.0.1:
version "1.0.2"
resolved "https://registry.yarnpkg.com/js-stringify/-/js-stringify-1.0.2.tgz#1736fddfd9724f28a3682adc6230ae7e4e9679db"
@ -1244,24 +1282,6 @@ leven@^1.0.2:
resolved "https://registry.yarnpkg.com/leven/-/leven-1.0.2.tgz#9144b6eebca5f1d0680169f1a6770dcea60b75c3"
integrity sha1-kUS27ryl8dBoAWnxpncNzqYLdcM=
libflitter@^0.27.4:
version "0.27.4"
resolved "https://registry.yarnpkg.com/libflitter/-/libflitter-0.27.4.tgz#858a49c0be7424b47eab36295cd1c001a3b32b61"
integrity sha512-/62fjAJCu/7dh1xQMdpNhV4LofAGGKB615dXTnWGvUBXWSYwtlwZuEWzcooEO4SdyT+ooeyTpVxy8XauFGX8pA==
dependencies:
busboy-body-parser "^0.3.2"
connect-mongodb-session "^2.2.0"
dotenv "^6.2.0"
es6-promisify "^6.0.1"
express "^4.16.4"
express-favicon "^2.0.1"
express-session "^1.15.6"
mongoose "^5.4.13"
pug "^2.0.3"
recursive-readdir "^2.2.2"
recursive-readdir-async "^1.1.3"
uuid "^3.3.2"
libflitter@^0.3.5:
version "0.3.6"
resolved "https://registry.yarnpkg.com/libflitter/-/libflitter-0.3.6.tgz#748d1fb9d5abcda61393eedb735f9cb875d1701f"
@ -1277,6 +1297,24 @@ libflitter@^0.3.5:
recursive-readdir "^2.2.2"
uuid "^3.3.2"
libflitter@^0.31.1:
version "0.31.1"
resolved "https://registry.yarnpkg.com/libflitter/-/libflitter-0.31.1.tgz#a513a4bd7acbdf8ba3ce91d1fdf837dfcc3217ca"
integrity sha512-z/mURNOe1aZLIWG7W2A8/fUPYkalRdqQmTfCLhyDWDJ2Nho+vGGLp9GLbiY9rj1I+W/x5U5p+W7Vv6EtYru+PA==
dependencies:
busboy-body-parser "^0.3.2"
connect-mongodb-session "^2.2.0"
dotenv "^6.2.0"
es6-promisify "^6.0.1"
express "^4.16.4"
express-favicon "^2.0.1"
express-session "^1.15.6"
mongoose "^5.4.13"
pug "^2.0.3"
recursive-readdir "^2.2.2"
recursive-readdir-async "^1.1.3"
uuid "^3.3.2"
lodash-node@^3.9.3:
version "3.10.2"
resolved "https://registry.yarnpkg.com/lodash-node/-/lodash-node-3.10.2.tgz#2598d5b1b54e6a68b4cb544e5c730953cbf632f7"
@ -1322,6 +1360,14 @@ longest@^1.0.1:
resolved "https://registry.yarnpkg.com/longest/-/longest-1.0.1.tgz#30a0b2da38f73770e8294a0d22e6625ed77d0097"
integrity sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc=
lru-cache@^4.1.5:
version "4.1.5"
resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.5.tgz#8bbe50ea85bed59bc9e33dcab8235ee9bcf443cd"
integrity sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==
dependencies:
pseudomap "^1.0.2"
yallist "^2.1.2"
media-typer@0.3.0:
version "0.3.0"
resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748"
@ -1403,7 +1449,7 @@ minizlib@^1.1.1:
dependencies:
minipass "^2.2.1"
mkdirp@^0.5.0, mkdirp@^0.5.1:
mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@~0.5.1:
version "0.5.1"
resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903"
integrity sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=
@ -1559,7 +1605,7 @@ node-pre-gyp@0.12.0:
semver "^5.3.0"
tar "^4"
nopt@^4.0.1:
nopt@^4.0.1, nopt@~4.0.1:
version "4.0.1"
resolved "https://registry.yarnpkg.com/nopt/-/nopt-4.0.1.tgz#d0d4685afd5415193c8c7505602d0d17cd64474d"
integrity sha1-0NRoWv1UFRk8jHUFYC0NF81kR00=
@ -1602,7 +1648,7 @@ number-is-nan@^1.0.0:
resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d"
integrity sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=
object-assign@^4.0.1, object-assign@^4.1.0:
object-assign@^4, object-assign@^4.0.1, object-assign@^4.1.0:
version "4.1.1"
resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863"
integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=
@ -1742,6 +1788,11 @@ promise@^7.0.1:
dependencies:
asap "~2.0.3"
proto-list@~1.2.1:
version "1.2.4"
resolved "https://registry.yarnpkg.com/proto-list/-/proto-list-1.2.4.tgz#212d5bfe1318306a420f6402b8e26ff39647a849"
integrity sha1-IS1b/hMYMGpCD2QCuOJv85ZHqEk=
proxy-addr@~2.0.4:
version "2.0.4"
resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.4.tgz#ecfc733bf22ff8c6f407fa275327b9ab67e48b93"
@ -1750,6 +1801,11 @@ proxy-addr@~2.0.4:
forwarded "~0.1.2"
ipaddr.js "1.8.0"
pseudomap@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3"
integrity sha1-8FKijacOYYkX7wqKw0wa5aaChrM=
pug-attrs@^2.0.3:
version "2.0.3"
resolved "https://registry.yarnpkg.com/pug-attrs/-/pug-attrs-2.0.3.tgz#a3095f970e64151f7bdad957eef55fb5d7905d15"
@ -2088,6 +2144,11 @@ semver@^5.1.0, semver@^5.3.0:
resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.0.tgz#790a7cf6fea5459bac96110b29b60412dc8ff96b"
integrity sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==
semver@^5.6.0:
version "5.7.1"
resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7"
integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==
send@0.16.2:
version "0.16.2"
resolved "https://registry.yarnpkg.com/send/-/send-0.16.2.tgz#6ecca1e0f8c156d141597559848df64730a6bbc1"
@ -2137,6 +2198,11 @@ sift@7.0.1:
resolved "https://registry.yarnpkg.com/sift/-/sift-7.0.1.tgz#47d62c50b159d316f1372f8b53f9c10cd21a4b08"
integrity sha512-oqD7PMJ+uO6jV9EQCl0LrRw1OwsiPsiFQR5AR30heR+4Dl7jBBbDLnNvWiak20tzZlSE1H7RB30SX/1j/YYT7g==
sigmund@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/sigmund/-/sigmund-1.0.1.tgz#3ff21f198cad2175f9f3b781853fd94d0d19b590"
integrity sha1-P/IfGYytIXX587eBhT/ZTQ0ZtZA=
signal-exit@^3.0.0:
version "3.0.2"
resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d"
@ -2410,7 +2476,7 @@ validator@^10.11.0:
resolved "https://registry.yarnpkg.com/validator/-/validator-10.11.0.tgz#003108ea6e9a9874d31ccc9e5006856ccd76b228"
integrity sha512-X/p3UZerAIsbBfN/IwahhYaBbY68EN/UQBWHtsbXGT5bfrH/p4NQzUCG1kF/rtKaNpnJ7jAu6NGTdSNtyNIXMw==
vary@~1.1.2:
vary@^1, vary@~1.1.2:
version "1.1.2"
resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc"
integrity sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=
@ -2465,6 +2531,11 @@ y18n@^3.2.0:
resolved "https://registry.yarnpkg.com/y18n/-/y18n-3.2.1.tgz#6d15fba884c08679c0d77e88e7759e811e07fa41"
integrity sha1-bRX7qITAhnnA136I53WegR4H+kE=
yallist@^2.1.2:
version "2.1.2"
resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52"
integrity sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=
yallist@^3.0.0, yallist@^3.0.2:
version "3.0.3"
resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.0.3.tgz#b4b049e314be545e3ce802236d6cd22cd91c3de9"