master
Garrett Mills 3 years ago
parent 8b8c636cff
commit db536010d4
  1. 133
      app/MiscUnit.js
  2. 12
      app/assets/dash_v1.css
  3. 14
      app/controllers/dash/v1.controller.js
  4. 2
      app/routing/routers/dash/v1.routes.js
  5. 24
      app/views/dash_v1/main.pug
  6. 10
      app/views/dash_v1/out.pug
  7. 2
      app/views/dash_v1/project.pug
  8. 4
      app/views/dash_v1/share.pug
  9. 2
      app/views/dash_v1/snippet.pug
  10. 2
      app/views/dash_v1/template.pug
  11. 13
      app/views/dash_v1/use/api.pug
  12. 17
      app/views/dash_v1/use/ecma.pug
  13. 51
      app/views/dash_v1/use/main.pug
  14. 17
      app/views/dash_v1/use/node.pug
  15. 17
      app/views/dash_v1/use/php.pug

@ -35,23 +35,24 @@ class MiscUnit extends Unit {
// do stuff here
global.devbug = {
version: '0.2.0',
version: '0.5.1',
code: {
node: `require("devbugjs")
dbsetup({
\tserver: "https://CHANGEME:8000/", // DevBug Server URL
\tproject: "CHANGEME", // Project API Key
})`,
api: `Send a multipart/form-data POST request to:
http(s)://<devbug url>/api/v1/out/<project api key>
api: `// Send a multipart/form-data POST request to:
// http://#{_flitter.config('server.url')}/api/v1/out/<project api key>
The form should have a single field with the name "data".
This field should contain a valid JSON string with the following structure:
// The form should have a single field with the name "data".
// This field should contain a valid JSON string with the following structure:
{
"brief": "Some preview text to be displayed. Whatever you want.",
"data": {
// the output data (key-pairs) goes here
}
// the output data (key-pairs) goes here:
"some name": "some data",
},
}`,
php: `<?php
// ===========================================================
@ -59,99 +60,45 @@ This field should contain a valid JSON string with the following structure:
// TODO: REMOVE BEFORE COMMITTING
$dev_outs = [];
function out($key, $what, $group = null){
\tglobal $dev_outs;
\tif ( $group ){
\t\tif ( !array_key_exists($group, $dev_outs) ){
\t\t\t$dev_outs[$group] = [ $key => $what ];
\t\t}
\t\telse {
\t\t\t$dev_outs[$group][$key] = $what;
\t\t}
\t}
\telse {
\t\t$dev_outs[$key] = $what;
\t}
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;
}
}
function breakpoint($html = false, $name = null){
\tglobal $dev_outs;
\t$devbug = "http://CHANGEME:8000/";
\t$project_api_key = "CHANGEME";
\t$bt = debug_backtrace();
\t$caller = array_shift($bt);
function breakpoint($continue = false, $name = null){
global $dev_outs;
$devbug = "http://localhost:8000/";
$project_api_key = "CHANGEME";
$bt = debug_backtrace();
$caller = array_shift($bt);
\tif ( !$html ){
\t\tvar_dump([($item ? $item : $caller), 'outs' => $dev_outs]);
\t}
\telse {
\t\techo "<pre><code>";
\t\tvar_dump([($item ? $item : $caller), 'outs' => $dev_outs]);
\t\techo "</code></pre>";
\t}
// 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,
])
]);
\t// Send to devbug server
\t$ch = curl_init();
\t$url = $devbug.'api/v1/out/'.$project_api_key;
\tvar_dump($url);
\tcurl_setopt($ch, CURLOPT_URL, $url);
\tcurl_setopt($ch, CURLOPT_POST, 1);
\tcurl_setopt($ch, CURLOPT_POSTFIELDS, [
\t 'data' => json_encode([
\t 'brief' => ($name ? $name : 'Breakpoint').': '.$caller['file'].': '.$caller['line'],
\t 'data' => $dev_outs,
\t ])
\t]);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
\tcurl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
\t
\t$odata = curl_exec($ch);
$odata = curl_exec($ch);
\texit();
if ( !$continue ) { exit(); }
}
// ===========================================================`,
js: `// ===========================================================
// DEVBUG INLINE DEBUGGING HELPER - FOR USE WITH DEVBUG SERVER
// TODO: REMOVE BEFORE COMMITTING
let outs = {}
const devbug_url = 'http://CHANGEME:8000/'
const project_api_key = 'CHANGEME'
const out = (key, what, group=false) => {
if ( group ){
if ( Object.keys(outs).includes(group) ) outs[group][key] = what
else outs[group] = {}; outs[group][key] = where
}
else {
outs[key] = what
}
}
const breakpoint = (html = false, name = null) => {
var e = new Error();
(function() {
// 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;
$(() => {
e = e.stack.split('at'); var caller = '';
if ( e.length < 3 ) e = e.stack.split('@')
if ( e.length > 2 ) caller = e[2].trim()
else if ( e.length > 1 ) caller = e[1]
else caller = 'Unable to determine stacktrace'
var data = new FormData();
data.append('data', JSON.stringify({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);
})();
}
if ( window ) window.out = out; window.breakpoint = breakpoint;
// ===========================================================`
},
permission: {
project: {

@ -88,7 +88,7 @@ a {
color: #eee;
}
.btn {
.btn, .action {
margin: 5;
margin-bottom: 20;
padding: 5;
@ -101,7 +101,13 @@ a {
transition: all 0.5s ease;
}
.btn:hover {
.action {
padding: 0;
padding-left: 5;
padding-right: 5;
}
.btn:hover, .action:hover {
background: #eee;
color: #307d7d;
}
@ -115,7 +121,7 @@ pre {outline: 1px solid #ccc; padding: 5px; margin: 5px; }
.action-li {
display: inline;
margin-right: 15px;
/*margin-right: 15px;*/
}
#editor {

@ -538,6 +538,20 @@ class v1 {
return res.redirect('/dash/v1/project/snippet/'+project.id+'/view/'+snippet.uuid)
}
async show_usage_page(req, res, next){
const valid_pages = ['main', 'node', 'php', 'ecma', 'api'];
if ( !valid_pages.includes(req.params.page) ) return _flitter.error(res, 404, {reason: 'The page could not be found.'})
const title = req.params.page.charAt(0).toUpperCase() + req.params.page.slice(1);
return _flitter.view(res, 'dash_v1:use:'+req.params.page.replace(/\W/g, ''), {
show_back: true,
title: 'Using DevBug - '+title,
user: req.session.auth.user,
})
}
}
module.exports = exports = v1

@ -53,6 +53,8 @@ const v1 = {
'/project/snippet/:id/delete/:snippet': [ _flitter.controller('dash:v1').project_snippet_delete ],
'/project/snippet/:id/edit/:snippet': [ _flitter.controller('dash:v1').project_snippet_edit ],
'/using_devbug/:page': [ _flitter.controller('dash:v1').show_usage_page ],
'/out/view/:id': [ _flitter.controller('dash:v1').out_view ],
'/out/delete/:id/:project': [ _flitter.controller('dash:v1').out_delete ],

@ -1,9 +1,7 @@
extends ./template
block content
h3 My Projects
ul(style='list-style-type: none;')
li
a(href='/dash/v1/project/new') Create New Project
a.btn(href='/dash/v1/project/new') +
table
thead
tr
@ -37,20 +35,20 @@ block content
td #{project.name}
td
ul(style='list-style-type: none; margin: 0; padding: 0;')
li
li.action-li
a.action(href='/dash/v1/project/view/'+project.id) View
li
li.action-li
a.action(href='/dash/v1/project/share/'+project.id+'/revoke/'+user.uuid+'/edit') Remove
li
li.action-li
a.action(href='/dash/v1/project/edit/'+project.id) Edit
each project in shared_projects.view
tr
td #{project.name}
td
ul(style='list-style-type: none; margin: 0; padding: 0;')
li
li.action-li
a.action(href='/dash/v1/project/view/'+project.id) View
li
li.action-li
a.action(href='/dash/v1/project/share/'+project.id+'/revoke/'+user.uuid) Remove
if shared_snippets.view || shared_snippets.edit
h3 Snippets Shared With Me
@ -65,18 +63,18 @@ block content
td #{snippet.name}
td
ul(style='list-style-type: none; margin: 0; padding: 0;')
li
li.action-li
a.action(href='/dash/v1/project/snippet/'+snippet.project_id+'/view/'+snippet.uuid) View
li
li.action-li
a.action(href='/dash/v1/snippet/share/'+snippet.id+'/revoke/'+user.uuid+'/edit') Remove
li
li.action-li
a.action(href='/dash/v1/project/snippet/'+snippet.project_id+'/edit/'+snippet.uuid) Edit
each snippet in shared_snippets.view
tr
td #{snippet.name}
td
ul(style='list-style-type: none; margin: 0; padding: 0;')
li
li.action-li
a.action(href='/dash/v1/project/snippet/'+snippet.project_id+'/view/'+snippet.uuid) View
li
li.action-li
a.action(href='/dash/v1/snippet/share/'+snippet.id+'/revoke/'+user.uuid) Remove

@ -1,4 +1,12 @@
extends ./template
block content
pre#editor(style="height: 75%;") #{prettyd}
script(src='/assets/dash_v1.js')
script output(syntaxHighlight(`#{prettyd}`));
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.session.setMode('ace/mode/json');
editor.setOption('readOnly', true);

@ -8,4 +8,4 @@ block content
input#project_name(type='text', name='name' value=(project_name ? project_name : '') required autofocus)
br
br
button(type='submit') #{project_name ? 'Update Project' : 'Create Project'}
button.btn(type='submit') #{project_name ? 'Update Project' : 'Create Project'}

@ -26,7 +26,7 @@ block content
if !(user.uuid === item.user_id)
li.action-li
a.action(href='/dash/v1/'+api+'/share/'+item.id+'/revoke/'+user.uuid) Revoke
li
li.action-li
a.action(href='/dash/v1/'+api+'/share/'+item.id+'/transfer/'+user.uuid) Transfer Ownership
else
li.action-li
@ -51,7 +51,7 @@ block content
if !(user.uuid === item.user_id)
li.action-li
a.action(href='/dash/v1/'+api+'/share/'+item.id+'/revoke/'+user.uuid+'/edit') Revoke
li
li.action-li
a.action(href='/dash/v1/'+api+'/share/'+item.id+'/transfer/'+user.uuid) Transfer Ownership
else
li.action-li

@ -84,7 +84,7 @@ block content
a.btn(href='/dash/v1/project/snippet/'+project.id+'/edit/'+snippet.uuid style='margin-left: 10px') Edit
pre#editor #{ snippet ? snippet.data : '' }
if (!readonly)
button(onclick='submitSnippet()') #{ snippet ? 'Update Snippet' : 'Create Snippet' }
button.btn(onclick='submitSnippet()') #{ snippet ? 'Update Snippet' : 'Create Snippet' }
input#preset_mode(type='hidden' value=snippet ? snippet.mode : 'ace/mode/javascript')
block scripts

@ -16,7 +16,7 @@ html
li.navli
a.nava(href='/dash/v1') Home
li.navli
a.nava(href='/dash/v1/code') Using DevBug
a.nava(href='/dash/v1/using_devbug/main') Using DevBug
li.navli
a.nava(href='/auth/logout') Logout
if show_back

@ -0,0 +1,13 @@
extends ../template
block content
h3 DevBug supports anywhere within the reach of your network.
p You can use DevBug in any language that supports sending multipart/form-data POST requests. This is accomplished via the DevBug API. This is the same procedure the native DevBug clients use. The API is fairly simple to use and contains a single endpoint. The snippet below details how to use it:
pre#editor #{devbug.code.api}
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.session.setMode('ace/mode/javascript');
editor.setOption('readOnly', true);

@ -0,0 +1,17 @@
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:
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.
pre#editor // Run the following as early in your application as your can:&#10;devbug_url="http://localhost:8000/";&#10;project_api_key="CHANGEME";
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.session.setMode('ace/mode/javascript');
editor.setOption('readOnly', true);

@ -0,0 +1,51 @@
extends ../template
block content
h2 Welcome to DevBug!
p DevBug is a development helper tool designed to make it easy to collect program output and code snippets for your projects.
| The basic principle here is that you include DevBug's inline-helper scripts which provide helper functions.
| You can call these helper functions from your code to output data. When a breakpoint is reached, that data is sent to
| the DevBug server as JSON, where it is logged in a project along with some other information about the breakpoint.
| You can then view the outputs through the DevBug console. DevBug is designed to be hosted on the local network of the
| developers who use it. This alleviates some worries about code and development output being sent over the open web.
p Because output data is sent over HTTP, DevBug is helpful for debugging software that may run in an environment where the direct output is not easily accessible.
p Inline helper functions are included with DevBug for the following languages (however, the DevBug api is easy to use, even if your favorite language isn't supported):
br
ul(style='list-style-type: none; margin: 0; padding: 0;')
li.action-li
a.btn(href='./node') Node.js
li.action-li
a.btn(href='./ecma') JavaScript (Web)
li.action-li
a.btn(href='./php') PHP
li.action-li
a.btn(href='./api') DevBug API
br
h3 Changelog
h4 v0.5.1 - Use Ace.js for Outputs
ul
li Switched over to use Ace.js to view development output. Might make this a user preference in the future.
h4 v0.5.0 - Better Documentation and UI
ul
li Improved the "Using DevBug" section to be more readable and accessible.
li Added individual pages for each of the supported languages with details on the client functions.
li Use a consistent button theme throughtout the application.
h4 v0.4.0 - Snippets
ul
li Projects can now contain various code snippets.
li These snippets can be shared individually with view/edit/transfer/invite support.
li Users with view/edit access to the parent project automatically inherit these permissions.
li Snippets make use of the Ace.js embedded editor, which provides syntax highlighting.
h4 v0.3.0 - Sharing!
ul
li DevBug now supports sharing project with other users.
li This includes view/edit mode, as well as the ability to transfer ownership of a project to that user.
li Projects can also be shared via invitation URL. If the recipient doesn't have an account on this DevBug server, they will be prompted to create one.
h3 About
p Copyright (C) 2019 Garrett L Mills.
p
| DevBug is licensed under the GNU Affero GPL Version 3. Read more about what that means
a(href="https://choosealicense.com/licenses/agpl-3.0/" target="_blank") here.

@ -0,0 +1,17 @@
extends ../template
block content
h3 Node.js has a first-class DevBug client.
p To use the client, install the <code>devbugjs</code> package from NPM. Probably best to include this in your development dependencies. Then, run the following code as early in your application initialization as you can. 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 Node.js 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.
pre#editor #{ devbug.code.node }
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.session.setMode('ace/mode/javascript');
editor.setOption('readOnly', true);

@ -0,0 +1,17 @@
extends ../template
block content
h3 DevBug supports the code behind the web.
p To use the client, include the code snippet in your PHP application as early as you can. You'll need to go to the <code>breakpoint()</code> function and customize the DevBug server URL and project API key. It's best to do this in a global namespace. That way the functions defined by DevBug are available everywhere in your program. 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 PHP 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.
pre#editor #{devbug.code.php}
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.session.setMode('ace/mode/php');
editor.setOption('readOnly', true);
Loading…
Cancel
Save