Compare commits

..

No commits in common. "master" and "v0.6.0" have entirely different histories.

38 changed files with 248 additions and 654 deletions

View File

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

View File

@ -1,45 +0,0 @@
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,5 +1,4 @@
const Unit = require('libflitter/Unit')
const cors = require('cors')
/*
* The Miscellaneous Unit
@ -33,25 +32,15 @@ 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.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
},
version: '0.6.0',
code: {
node: `require("devbugjs")
dbsetup({
\tserver: "{{ Server URL }}", // DevBug Server URL
\tproject: "{{ Project API Key }}", // Project API Key
\tserver: "https://CHANGEME:8000/", // DevBug Server URL
\tproject: "CHANGEME", // Project API Key
})`,
api: `// Send a multipart/form-data POST request to:
// http://#{_flitter.config('server.url')}/api/v1/out/<project api key>
@ -69,34 +58,27 @@ dbsetup({
// ===========================================================
// DEVBUG INLINE DEBUGGING HELPER - FOR USE WITH DEVBUG SERVER
// TODO: REMOVE BEFORE COMMITTING
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();
$dev_outs = [];
function out($key, $what, $group = null){
$dev_outs = $GLOBALS['devbug_dev_outs'];
global $dev_outs;
if ( $group ){
if ( !array_key_exists($group, $dev_outs) ) $dev_outs[$group] = [ $key => $what ];
else $dev_outs[$group][$key] = $what;
if ( !array_key_exists($group, $dev_outs) ){
$dev_outs[$group] = [ $key => $what ];
}
else {
$dev_outs[$group][$key] = $what;
}
}
else {
$dev_outs[$key] = $what;
}
else $dev_outs[$key] = $what;
$GLOBALS['devbug_dev_outs'] = $dev_outs;
}
function breakpoint($continue = false, $name = null){
$dev_outs = $GLOBALS['devbug_dev_outs'];
$devbug = "{{ Server URL }}/";
$project_api_key = "{{ Project API Key }}";
global $dev_outs;
$devbug = "http://localhost:8000/";
$project_api_key = "CHANGEME";
$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();
@ -109,31 +91,13 @@ function breakpoint($continue = false, $name = null){
'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(except = false, name){
breakpoint(name, exception = false){
var e = new Error();
this.libs(() => {
var s = e.stack.split('at'); var caller = '';

52
app/assets/agents/web.js Normal file
View File

@ -0,0 +1,52 @@
// ===========================================================
// 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,5 +40,3 @@ 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, created_by_user: user})
return _flitter.view(res, 'dash_v1:accept', {invite, project, user})
}
async invite_accept(req, res, next){

View File

@ -138,38 +138,7 @@ 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, 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+')'
})
return _flitter.view(res, 'dash_v1:view', {user: req.session.auth.user, snippets, project, outs, show_back: true, title: 'View: '+project.name })
}
async out_view(req, res, next){
@ -197,37 +166,6 @@ 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,9 +6,7 @@
* globally using the model() function.
*/
const Greeting = {
schema: {
name: String,
},
}
module.exports = Greeting

View File

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

View File

@ -8,14 +8,13 @@
* 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 = {
schema: {
username: String,
password: String,
data: String,
uuid: String,
role: String,
permissions: [String],
},
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -3,8 +3,7 @@
* -------------------------------------------------------------
* Put some description here!
*/
const Middleware = require('libflitter/middleware/Middleware')
class Debug extends Middleware {
class Debug {
/*
* Run the middleware test.

View File

@ -6,8 +6,7 @@
* the '/' route is accessed. It can be injected in routes globally using
* the global mw() function.
*/
const Middleware = require('libflitter/middleware/Middleware')
class HomeLogger extends Middleware {
class HomeLogger {
/*
* Run the middleware test.

View File

@ -8,8 +8,7 @@
*
* @class
*/
const Middleware = require('libflitter/middleware/Middleware')
class Permission extends Middleware {
class Permission {
/**
* Run the middleware's check. If an authenticated session exists and the user has the specified permission,
@ -24,25 +23,23 @@ class Permission extends Middleware {
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) ){
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 {
}
else {
return _flitter.error(res, 401, {reason: 'Insufficient user permissions.'})
}
}
else {
req.session.destination = req.originalUrl
return res.redirect('/auth/login')
}

View File

@ -8,8 +8,7 @@
*
* @class
*/
const Middleware = require('libflitter/middleware/Middleware')
class RequireAuth extends Middleware {
class RequireAuth {
/**
* Run the middleware's check. If an authenticated session exists, let the request continue.
@ -25,7 +24,8 @@ class RequireAuth extends Middleware {
* Call the next function in the stack.
*/
next()
} else {
}
else {
req.session.destination = req.originalUrl
return res.redirect('/auth/login')
}

View File

@ -8,8 +8,7 @@
*
* @class
*/
const Middleware = require('libflitter/middleware/Middleware')
class RequireGuest extends Middleware {
class RequireGuest {
/**
* Run the middleware test. If an authenticated session exists, redirect the user to an error page.

View File

@ -8,8 +8,7 @@
*
* @class
*/
const Middleware = require('libflitter/middleware/Middleware')
class Role extends Middleware {
class Role {
/**
* Run the middleware's check. If an authenticated session exists and the user has the specified role,
@ -24,12 +23,12 @@ class Role extends Middleware {
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 {
else {
return _flitter.error(res, 401, {reason: 'Insufficient user permissions.'})
}
}
else {
req.session.destination = req.originalUrl
return res.redirect('/auth/login')
}

View File

@ -3,8 +3,7 @@
* -------------------------------------------------------------
* Put some description here!
*/
const Middleware = require('libflitter/middleware/Middleware')
class Invite extends Middleware {
class Invite {
/*
* Run the middleware test.

View File

@ -39,7 +39,6 @@ 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 ],
@ -57,7 +56,6 @@ 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,150 +1,19 @@
html
head
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;
}
title Sharing Invitation | DevBug
link(rel='stylesheet' href='/assets/dash_v1.css')
script(src='/assets/dash_v1.js')
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.
.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.

View File

@ -2,4 +2,4 @@ extends ./template
block content
p #{text}
form(method='post' action=destination)
button.btn(type='submit') Yes, I'm sure.
button(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,14 +26,7 @@ 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 && (!project || window_back)
if show_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

@ -1,17 +0,0 @@
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,8 +15,6 @@ 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(window.devbug_editor_theme);
editor.setTheme('ace/theme/cobalt');
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(window.devbug_editor_theme);
editor.setTheme('ace/theme/cobalt');
console.log('preset mode: ', preset_mode);
editor.session.setMode(preset_mode);
document.getElementById('snippet_mode').value = preset_mode

View File

@ -14,19 +14,11 @@ 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 && (!project || window_back)
if show_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/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:
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:
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. Instead, the breakpoint throws an exception.
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.
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,23 +1,6 @@
extends ./template
block content
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
h3 Project API Key: #{project.uuid}
h2 Code Snippets
a.btn(href='/dash/v1/project/snippet/'+project.id+'/new') +
@ -43,7 +26,6 @@ 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,15 +18,5 @@
"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,14 +16,12 @@
"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.4.0",
"flitter-flap": "^0.2.2",
"flitter-forms": "^0.7.2",
"flitter-upload": "^0.7.6",
"js-beautify": "^1.10.2",
"libflitter": "^0.31.1",
"libflitter": "^0.27.4",
"stringify-object": "^3.3.0"
}
}

View File

@ -1,4 +0,0 @@
- 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.19.0, commander@^2.5.0, commander@^2.9.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,14 +512,6 @@ 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"
@ -585,14 +577,6 @@ 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"
@ -717,16 +701,6 @@ 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"
@ -877,13 +851,12 @@ flitter-cli@^0.10.0:
mkdirp "^0.5.1"
nesh "^1.7.0"
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==
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==
dependencies:
del "^4.1.0"
js-beautify "^1.10.2"
node-migration "^1.0.1"
touch "^3.1.0"
@ -1087,7 +1060,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.4, ini@~1.3.0:
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==
@ -1200,17 +1173,6 @@ 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"
@ -1282,6 +1244,24 @@ 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"
@ -1297,24 +1277,6 @@ 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"
@ -1360,14 +1322,6 @@ 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"
@ -1449,7 +1403,7 @@ minizlib@^1.1.1:
dependencies:
minipass "^2.2.1"
mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@~0.5.1:
mkdirp@^0.5.0, mkdirp@^0.5.1:
version "0.5.1"
resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903"
integrity sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=
@ -1605,7 +1559,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=
@ -1648,7 +1602,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, object-assign@^4.0.1, object-assign@^4.1.0:
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=
@ -1788,11 +1742,6 @@ 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"
@ -1801,11 +1750,6 @@ 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"
@ -2144,11 +2088,6 @@ 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"
@ -2198,11 +2137,6 @@ 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"
@ -2476,7 +2410,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, vary@~1.1.2:
vary@~1.1.2:
version "1.1.2"
resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc"
integrity sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=
@ -2531,11 +2465,6 @@ 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"