@re-shell/cli
Version:
Full-stack development platform uniting microservices and microfrontends. Build complete applications with .NET (ASP.NET Core Web API, Minimal API), Java (Spring Boot, Quarkus, Micronaut, Vert.x), Rust (Actix-Web, Warp, Rocket, Axum), Python (FastAPI, Dja
1,665 lines (1,376 loc) โข 42.7 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.totaljsTemplate = void 0;
exports.totaljsTemplate = {
id: 'backend-totaljs',
name: 'Total.js',
displayName: 'Total.js',
description: 'Full-featured framework with built-in CMS and real-time capabilities',
language: 'javascript',
framework: 'totaljs',
version: '4.0.0',
tags: ['cms', 'real-time', 'full-featured', 'nosql'],
port: 8000,
dependencies: {
'total4': '^4.0.0'
},
features: ['cms', 'real-time', 'routing', 'nosql', 'websockets'],
files: {
'index.js': `require('total4');
// Main application configuration
MAIN('default', function() {
// Application settings
CONF.name = 'Total.js Application';
CONF.version = '1.0.0';
CONF.author = 'Your Name';
CONF.secret = 'your-secret-key-' + GUID(10);
// Server configuration
CONF['allow-gzip'] = true;
CONF['allow-websocket'] = true;
CONF['allow-debug'] = true;
CONF['allow-compile'] = true;
// Database configuration
CONF.database = '/databases/';
CONF.directory_temp = '/tmp/';
// Mail configuration
CONF.mail_smtp = 'smtp.gmail.com';
CONF.mail_smtp_options = {
port: 465,
secure: true,
user: process.env.SMTP_USER,
password: process.env.SMTP_PASSWORD
};
// Start HTTP server
HTTP('release', { port: process.env.PORT || 8000 });
});
`,
'controllers/default.js': `exports.install = function() {
// Route definitions
ROUTE('GET /', view_homepage);
ROUTE('GET /api/', json_api_info);
ROUTE('GET /api/users/', json_users_list);
ROUTE('GET /api/users/{id}/', json_user_detail);
ROUTE('POST /api/users/ *User --> @save', json_user_create);
ROUTE('PUT /api/users/{id}/ *User --> @save', json_user_update);
ROUTE('DELETE /api/users/{id}/', json_user_delete);
// WebSocket routes
ROUTE('SOCKET /live/', socket_homepage);
ROUTE('SOCKET /chat/', socket_chat);
// File routes
FILE('/download/*.pdf', file_download);
FILE('/images/*.jpg', image_resize);
// CMS routes
ROUTE('GET /cms/', view_cms);
ROUTE('GET /cms/pages/', view_cms_pages);
ROUTE('GET /cms/widgets/', view_cms_widgets);
};
// Homepage controller
function view_homepage() {
var self = this;
self.view('index', {
title: 'Total.js Application',
user: self.user
});
}
// API endpoints
function json_api_info() {
this.json({
name: CONF.name,
version: CONF.version,
uptime: Math.floor(process.uptime() / 60) + ' minutes',
memory: (process.memoryUsage().heapUsed / 1024 / 1024).toFixed(2) + ' MB'
});
}
function json_users_list() {
var self = this;
// Query builder with pagination
var builder = NOSQL('users').find();
// Apply filters
if (self.query.search)
builder.search('name', self.query.search);
if (self.query.role)
builder.where('role', self.query.role);
// Pagination
builder.page(self.query.page || 1, 20);
builder.callback(function(err, users, count) {
self.json({
items: users,
count: count,
page: self.query.page || 1,
pages: Math.ceil(count / 20)
});
});
}
function json_user_detail(id) {
var self = this;
NOSQL('users').one().where('id', id).callback(function(err, user) {
if (err || !user) {
self.throw404();
return;
}
self.json(user);
});
}
function json_user_create() {
var self = this;
self.json({ success: true, id: UID() });
}
function json_user_update(id) {
var self = this;
self.json({ success: true, id: id });
}
function json_user_delete(id) {
var self = this;
NOSQL('users').remove().where('id', id).callback(function(err, count) {
self.json({
success: !err && count > 0,
count: count
});
});
}
// WebSocket controllers
function socket_homepage() {
var self = this;
self.on('open', function(client) {
console.log('WebSocket connected:', client.id);
client.send({ type: 'welcome', message: 'Connected to Total.js WebSocket' });
});
self.on('close', function(client) {
console.log('WebSocket disconnected:', client.id);
});
self.on('message', function(client, message) {
// Broadcast to all clients
self.send({ type: 'broadcast', data: message, from: client.id });
});
}
function socket_chat() {
var self = this;
var online = {};
self.on('open', function(client) {
online[client.id] = { id: client.id, name: 'Guest' + client.id.substring(0, 4) };
self.send({ type: 'users', users: Object.values(online) });
});
self.on('close', function(client) {
delete online[client.id];
self.send({ type: 'users', users: Object.values(online) });
});
self.on('message', function(client, message) {
if (message.type === 'name') {
online[client.id].name = message.name;
self.send({ type: 'users', users: Object.values(online) });
} else if (message.type === 'chat') {
self.send({
type: 'message',
text: message.text,
user: online[client.id],
timestamp: new Date()
});
}
});
}
// File controllers
function file_download(req, res) {
var filename = req.split[1];
var filepath = PATH.public('downloads/' + filename);
PATH.exists(filepath, function(exists) {
if (!exists) {
res.throw404();
return;
}
res.file(filepath);
});
}
function image_resize(req, res) {
var filename = req.split[1];
var image = PATH.public('images/' + filename);
// Automatic image resizing
res.image(image, function(image) {
image.resize('200x200');
image.quality(85);
});
}
// CMS controllers
function view_cms() {
this.view('@cms/index');
}
function view_cms_pages() {
var self = this;
NOSQL('pages').find().callback(function(err, pages) {
self.view('@cms/pages', { pages: pages });
});
}
function view_cms_widgets() {
var self = this;
NOSQL('widgets').find().callback(function(err, widgets) {
self.view('@cms/widgets', { widgets: widgets });
});
}
`,
'schemas/user.js': `NEWSCHEMA('User', function(schema) {
// Schema definition
schema.define('id', 'UID');
schema.define('name', 'String(50)', true);
schema.define('email', 'Email', true);
schema.define('password', 'String(100)', true);
schema.define('role', ['admin', 'user', 'guest'], true);
schema.define('active', Boolean, true);
schema.define('created', Date);
schema.define('updated', Date);
schema.define('profile', Object);
// Validations
schema.required('name', i => i.name && i.name.length > 2);
schema.required('email', i => i.email && i.email.isEmail());
// Setters
schema.setSave(function($, model) {
var user = $.clean();
// New user
if (!user.id) {
user.id = UID();
user.created = NOW;
user.password = user.password.sha256(CONF.secret);
// Check if email exists
NOSQL('users').one().where('email', user.email).callback(function(err, exists) {
if (exists) {
$.invalid('email', 'Email already exists');
return;
}
NOSQL('users').insert(user).callback(function() {
$.success(user.id);
});
});
} else {
// Update user
user.updated = NOW;
if (user.password)
user.password = user.password.sha256(CONF.secret);
else
delete user.password;
NOSQL('users').modify(user).where('id', user.id).callback(function(err, count) {
if (count)
$.success(user.id);
else
$.invalid('error', 'User not found');
});
}
});
// Getters
schema.setGet(function($) {
var opt = $.options;
var filter = $.query || $.options;
NOSQL('users').one().where('id', filter.id).callback(function(err, user) {
if (user) {
delete user.password;
$.callback(user);
} else {
$.invalid('error', 'User not found');
}
});
});
// Actions
schema.addWorkflow('login', function($, model) {
var user = model.$clean();
NOSQL('users').one()
.where('email', user.email)
.where('password', user.password.sha256(CONF.secret))
.where('active', true)
.callback(function(err, found) {
if (found) {
delete found.password;
$.success(found);
} else {
$.invalid('error', 'Invalid credentials');
}
});
});
schema.addWorkflow('register', function($, model) {
model.active = true;
model.role = 'user';
schema.setSave($, model);
});
schema.addWorkflow('forgot', function($, model) {
var email = model.email;
NOSQL('users').one().where('email', email).callback(function(err, user) {
if (!user) {
$.invalid('email', 'Email not found');
return;
}
var token = GUID(30);
// Save reset token
NOSQL('tokens').insert({
id: token,
user: user.id,
type: 'reset',
created: NOW,
expires: NOW.add('1 hour')
});
// Send email
MAIL(email, 'Password Reset', '@password-reset', {
name: user.name,
token: token,
url: 'http://localhost:8000/reset/' + token
}, $.done());
});
});
});
`,
'models/cms.js': `// CMS Page model
NEWSCHEMA('Page', function(schema) {
schema.define('id', 'UID');
schema.define('title', 'String(100)', true);
schema.define('slug', 'String(100)', true);
schema.define('content', 'String');
schema.define('meta_title', 'String(100)');
schema.define('meta_description', 'String(200)');
schema.define('template', 'String(50)');
schema.define('parent', 'UID');
schema.define('order', Number);
schema.define('published', Boolean);
schema.define('created', Date);
schema.define('updated', Date);
schema.define('author', 'UID');
schema.setSave(function($, model) {
var page = $.clean();
if (!page.id) {
page.id = UID();
page.created = NOW;
page.slug = page.title.slug();
} else {
page.updated = NOW;
}
// Generate slug if empty
if (!page.slug)
page.slug = page.title.slug();
NOSQL('pages').save(page).where('id', page.id).callback($.done());
});
schema.setRemove(function($) {
NOSQL('pages').remove().where('id', $.id).callback($.done());
});
schema.setQuery(function($) {
var builder = NOSQL('pages').find();
if ($.options.published)
builder.where('published', true);
if ($.options.parent)
builder.where('parent', $.options.parent);
builder.sort('order', true);
builder.callback($.callback);
});
});
// CMS Widget model
NEWSCHEMA('Widget', function(schema) {
schema.define('id', 'UID');
schema.define('name', 'String(50)', true);
schema.define('type', ['html', 'menu', 'form', 'gallery'], true);
schema.define('content', 'String');
schema.define('config', Object);
schema.define('active', Boolean);
schema.define('created', Date);
schema.define('updated', Date);
schema.setSave(function($, model) {
var widget = $.clean();
if (!widget.id) {
widget.id = UID();
widget.created = NOW;
} else {
widget.updated = NOW;
}
NOSQL('widgets').save(widget).where('id', widget.id).callback($.done());
});
schema.setRemove(function($) {
NOSQL('widgets').remove().where('id', $.id).callback($.done());
});
schema.setQuery(function($) {
var builder = NOSQL('widgets').find();
if ($.options.active)
builder.where('active', true);
if ($.options.type)
builder.where('type', $.options.type);
builder.callback($.callback);
});
});
// CMS Media model
NEWSCHEMA('Media', function(schema) {
schema.define('id', 'UID');
schema.define('name', 'String(100)', true);
schema.define('filename', 'String(200)', true);
schema.define('type', 'String(50)');
schema.define('size', Number);
schema.define('width', Number);
schema.define('height', Number);
schema.define('folder', 'String(100)');
schema.define('tags', '[String]');
schema.define('created', Date);
schema.define('author', 'UID');
schema.setSave(function($, model) {
var media = $.clean();
if (!media.id) {
media.id = UID();
media.created = NOW;
}
NOSQL('media').save(media).where('id', media.id).callback($.done());
});
schema.setRemove(function($) {
var id = $.id;
NOSQL('media').one().where('id', id).callback(function(err, media) {
if (!media) {
$.invalid('error', 'Media not found');
return;
}
// Delete physical file
var filepath = PATH.public('uploads/' + media.filename);
Fs.unlink(filepath, NOOP);
// Delete from database
NOSQL('media').remove().where('id', id).callback($.done());
});
});
});
`,
'definitions/auth.js': `// Authentication and authorization definitions
// Middleware for authentication
MIDDLEWARE('auth', function(req, res, next, options) {
var token = req.headers['x-token'] || req.query.token;
if (!token) {
res.throw401();
return;
}
// Verify token
NOSQL('sessions').one()
.where('token', token)
.where('expires', '>', NOW)
.callback(function(err, session) {
if (!session) {
res.throw401();
return;
}
// Load user
NOSQL('users').one().where('id', session.user).callback(function(err, user) {
if (!user || !user.active) {
res.throw401();
return;
}
req.user = user;
// Check role if specified
if (options && options.role && user.role !== options.role) {
res.throw403();
return;
}
next();
});
});
});
// Authorize decorator
F.decorator('authorize', function(role) {
var self = this;
return function(req, res, next) {
if (!req.user) {
res.throw401();
return;
}
if (role && req.user.role !== role) {
res.throw403();
return;
}
self.call(req, res, next);
};
});
// Login operation
OPERATION('auth.login', function($, model) {
EXEC('+User --> login', model, function(err, user) {
if (err) {
$.invalid(err);
return;
}
// Create session
var session = {
id: UID(),
token: GUID(40),
user: user.id,
created: NOW,
expires: NOW.add('7 days')
};
NOSQL('sessions').insert(session);
$.success({
token: session.token,
user: user
});
});
});
// Logout operation
OPERATION('auth.logout', function($) {
var token = $.headers['x-token'] || $.query.token;
if (token) {
NOSQL('sessions').remove().where('token', token).callback(NOOP);
}
$.success();
});
// Password reset operation
OPERATION('auth.reset', function($, model) {
var token = model.token;
var password = model.password;
NOSQL('tokens').one()
.where('id', token)
.where('type', 'reset')
.where('expires', '>', NOW)
.callback(function(err, reset) {
if (!reset) {
$.invalid('token', 'Invalid or expired token');
return;
}
// Update password
NOSQL('users').modify({
password: password.sha256(CONF.secret),
updated: NOW
}).where('id', reset.user).callback(function(err, count) {
if (count) {
// Delete used token
NOSQL('tokens').remove().where('id', token).callback(NOOP);
$.success();
} else {
$.invalid('error', 'User not found');
}
});
});
});
`,
'definitions/helpers.js': `// Global helper functions
// Localization helper
F.helpers.translate = function(key, lang) {
return TRANSLATE(lang || this.language, key);
};
// Date formatting helper
F.helpers.dateformat = function(date, format) {
return date ? date.format(format || 'yyyy-MM-dd') : '';
};
// Number formatting helper
F.helpers.number = function(num, decimals) {
return num ? num.format(decimals || 0) : '0';
};
// Currency helper
F.helpers.currency = function(amount, currency) {
currency = currency || CONF.currency || 'USD';
return currency + ' ' + (amount || 0).format(2);
};
// Truncate text helper
F.helpers.truncate = function(text, length, suffix) {
if (!text) return '';
length = length || 100;
suffix = suffix || '...';
return text.length > length ? text.substring(0, length) + suffix : text;
};
// URL slug helper
F.helpers.slug = function(text) {
return text ? text.slug() : '';
};
// Gravatar helper
F.helpers.gravatar = function(email, size) {
size = size || 80;
var hash = email ? email.md5() : '';
return 'https://www.gravatar.com/avatar/' + hash + '?s=' + size + '&d=mm';
};
// Active menu helper
F.helpers.active = function(path, className) {
className = className || 'active';
return this.url === path ? className : '';
};
// CSRF token helper
F.helpers.csrf = function() {
return '<input type="hidden" name="csrf" value="' + this.csrf + '" />';
};
// JSON helper for templates
F.helpers.json = function(obj, spaces) {
return JSON.stringify(obj, null, spaces || 0);
};
// Pagination helper
F.helpers.pagination = function(count, page, limit, max) {
page = page || 1;
limit = limit || 20;
max = max || 5;
var pages = Math.ceil(count / limit);
var half = Math.floor(max / 2);
var first = Math.max(1, page - half);
var last = Math.min(pages, first + max - 1);
if (last - first < max)
first = Math.max(1, last - max + 1);
var builder = [];
if (page > 1)
builder.push({ page: page - 1, text: 'Previous', active: false });
for (var i = first; i <= last; i++)
builder.push({ page: i, text: i, active: i === page });
if (page < pages)
builder.push({ page: page + 1, text: 'Next', active: false });
return builder;
};
// File size helper
F.helpers.filesize = function(bytes) {
if (!bytes) return '0 B';
var units = ['B', 'KB', 'MB', 'GB', 'TB'];
var i = 0;
while (bytes >= 1024 && i < units.length - 1) {
bytes /= 1024;
i++;
}
return bytes.toFixed(i > 0 ? 1 : 0) + ' ' + units[i];
};
// Time ago helper
F.helpers.timeago = function(date) {
if (!date) return '';
var diff = Date.now() - date.getTime();
var seconds = Math.floor(diff / 1000);
if (seconds < 60) return 'just now';
if (seconds < 3600) return Math.floor(seconds / 60) + ' minutes ago';
if (seconds < 86400) return Math.floor(seconds / 3600) + ' hours ago';
if (seconds < 604800) return Math.floor(seconds / 86400) + ' days ago';
return date.format('yyyy-MM-dd');
};
`,
'views/index.html': `@{layout('layout')}
<div class="hero">
<h1>Welcome to @{config.name}</h1>
<p>Full-featured Node.js framework with built-in CMS and real-time capabilities</p>
<div class="features">
<div class="feature">
<h3>๐ MVC Architecture</h3>
<p>Clean and organized code structure with automatic routing</p>
</div>
<div class="feature">
<h3>๐ฆ NoSQL Database</h3>
<p>Built-in database with powerful query builder</p>
</div>
<div class="feature">
<h3>๐ Real-time WebSockets</h3>
<p>Built-in support for real-time communication</p>
</div>
<div class="feature">
<h3>๐ Content Management</h3>
<p>Integrated CMS with pages, widgets, and media</p>
</div>
</div>
</div>
<div class="demo">
<h2>Live Demo</h2>
<div class="websocket-demo">
<h3>WebSocket Connection</h3>
<div id="status">Disconnected</div>
<button onclick="connect()">Connect</button>
<button onclick="disconnect()">Disconnect</button>
<div class="messages" id="messages"></div>
<form onsubmit="sendMessage(event)">
<input type="text" id="message" placeholder="Type a message..." />
<button type="submit">Send</button>
</form>
</div>
</div>
<script>
var ws = null;
function connect() {
ws = new WebSocket('ws://' + window.location.host + '/live/');
ws.onopen = function() {
document.getElementById('status').textContent = 'Connected';
addMessage('System', 'Connected to server');
};
ws.onclose = function() {
document.getElementById('status').textContent = 'Disconnected';
addMessage('System', 'Disconnected from server');
};
ws.onmessage = function(event) {
var data = JSON.parse(event.data);
if (data.type === 'welcome') {
addMessage('Server', data.message);
} else if (data.type === 'broadcast') {
addMessage('User ' + data.from.substring(0, 8), data.data);
}
};
}
function disconnect() {
if (ws) {
ws.close();
ws = null;
}
}
function sendMessage(event) {
event.preventDefault();
var input = document.getElementById('message');
var message = input.value.trim();
if (message && ws && ws.readyState === WebSocket.OPEN) {
ws.send(message);
addMessage('You', message);
input.value = '';
}
}
function addMessage(from, text) {
var messages = document.getElementById('messages');
var message = document.createElement('div');
message.innerHTML = '<strong>' + from + ':</strong> ' + text;
messages.appendChild(message);
messages.scrollTop = messages.scrollHeight;
}
</script>
<style>
.hero {
text-align: center;
padding: 4rem 0;
background: linear-gradient(135deg,
color: white;
}
.features {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
gap: 2rem;
margin-top: 3rem;
padding: 0 2rem;
}
.feature {
background: rgba(255, 255, 255, 0.1);
padding: 2rem;
border-radius: 8px;
}
.demo {
padding: 4rem 2rem;
max-width: 800px;
margin: 0 auto;
}
.websocket-demo {
background:
padding: 2rem;
border-radius: 8px;
}
display: inline-block;
padding: 0.5rem 1rem;
margin: 1rem 0;
background:
border-radius: 4px;
}
.messages {
height: 300px;
overflow-y: auto;
background: white;
border: 1px solid
padding: 1rem;
margin: 1rem 0;
border-radius: 4px;
}
.messages div {
margin-bottom: 0.5rem;
}
form {
display: flex;
gap: 0.5rem;
}
input[type="text"] {
flex: 1;
padding: 0.5rem;
border: 1px solid
border-radius: 4px;
}
button {
padding: 0.5rem 1rem;
background:
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
}
button:hover {
background:
}
</style>
`,
'views/layout.html': `<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>@{title || config.name}</title>
<meta name="description" content="@{description || 'Total.js Application'}" />
@{import('meta', 'head', 'favicon.ico', 'css')}
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
line-height: 1.6;
color:
}
header {
background:
color: white;
padding: 1rem 2rem;
}
nav {
display: flex;
justify-content: space-between;
align-items: center;
}
nav a {
color: white;
text-decoration: none;
margin-left: 2rem;
}
nav a:hover {
text-decoration: underline;
}
main {
min-height: calc(100vh - 140px);
}
footer {
background:
padding: 2rem;
text-align: center;
color:
}
.container {
max-width: 1200px;
margin: 0 auto;
padding: 0 2rem;
}
</style>
</head>
<body>
<header>
<nav>
<div>
<strong>@{config.name}</strong>
</div>
<div>
<a href="/">Home</a>
<a href="/api/">API</a>
<a href="/cms/">CMS</a>
@{if user}
<a href="/profile/">@{user.name}</a>
<a href="/logout/">Logout</a>
@{else}
<a href="/login/">Login</a>
@{fi}
</div>
</nav>
</header>
<main>
@{body}
</main>
<footer>
<p>© @{NOW.getFullYear()} @{config.name} - Powered by Total.js v@{F.version}</p>
</footer>
@{import('script')}
</body>
</html>
`,
'views/cms/index.html': `@{layout('layout')}
<div class="container cms">
<h1>Content Management System</h1>
<div class="cms-menu">
<a href="/cms/pages/" class="cms-item">
<h3>๐ Pages</h3>
<p>Manage website pages and content</p>
</a>
<a href="/cms/widgets/" class="cms-item">
<h3>๐งฉ Widgets</h3>
<p>Create and manage content widgets</p>
</a>
<a href="/cms/media/" class="cms-item">
<h3>๐ผ๏ธ Media</h3>
<p>Upload and organize media files</p>
</a>
<a href="/cms/users/" class="cms-item">
<h3>๐ฅ Users</h3>
<p>Manage users and permissions</p>
</a>
<a href="/cms/settings/" class="cms-item">
<h3>โ๏ธ Settings</h3>
<p>Configure system settings</p>
</a>
<a href="/cms/analytics/" class="cms-item">
<h3>๐ Analytics</h3>
<p>View site statistics and reports</p>
</a>
</div>
</div>
<style>
.cms {
padding: 3rem 0;
}
.cms h1 {
margin-bottom: 2rem;
}
.cms-menu {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
gap: 2rem;
}
.cms-item {
background:
padding: 2rem;
border-radius: 8px;
text-decoration: none;
color: inherit;
transition: transform 0.2s, box-shadow 0.2s;
border: 1px solid
}
.cms-item:hover {
transform: translateY(-2px);
box-shadow: 0 4px 12px rgba(0,0,0,0.1);
}
.cms-item h3 {
margin-bottom: 0.5rem;
color:
}
.cms-item p {
color:
font-size: 0.95rem;
}
</style>
`,
'tests/test.js': `// Total.js testing framework
// Load testing module
require('total4/test');
// Test user registration
TEST('user.register', function() {
var self = this;
RESTBuilder.POST('/api/users/', {
name: 'Test User',
email: 'test@example.com',
password: 'password123'
}).exec(function(err, response) {
self.ok(response.success === true, 'User should be created');
self.ok(response.id, 'Should return user ID');
self.done();
});
});
// Test user login
TEST('user.login', function() {
var self = this;
RESTBuilder.POST('/api/auth/login/', {
email: 'test@example.com',
password: 'password123'
}).exec(function(err, response) {
self.ok(!err, 'Should not have error');
self.ok(response.token, 'Should return auth token');
self.ok(response.user, 'Should return user data');
self.done();
});
});
// Test API endpoints
TEST('api.info', function() {
var self = this;
RESTBuilder.GET('/api/').exec(function(err, response) {
self.ok(!err, 'Should not have error');
self.ok(response.name, 'Should have app name');
self.ok(response.version, 'Should have version');
self.done();
});
});
// Test WebSocket connection
TEST('websocket.connect', function() {
var self = this;
WEBSOCKET('ws://localhost:8000/live/', function(client) {
client.on('open', function() {
self.ok(true, 'WebSocket should connect');
});
client.on('message', function(message) {
self.ok(message.type === 'welcome', 'Should receive welcome message');
client.close();
self.done();
});
client.on('error', function(err) {
self.ok(false, 'WebSocket error: ' + err);
self.done();
});
});
});
// Test schema validation
TEST('schema.validation', function() {
var self = this;
EXEC('+User --> validate', {
name: 'A', // Too short
email: 'invalid-email',
password: '123'
}, function(err) {
self.ok(err !== null, 'Should have validation errors');
self.ok(err.items.length > 0, 'Should have error items');
self.done();
});
});
// Test NOSQL operations
TEST('nosql.operations', function() {
var self = this;
var id = UID();
// Insert
NOSQL('test').insert({ id: id, name: 'Test' }).callback(function(err) {
self.ok(!err, 'Should insert without error');
// Find
NOSQL('test').find().callback(function(err, items) {
self.ok(!err, 'Should find without error');
self.ok(items.length > 0, 'Should have items');
// Update
NOSQL('test').modify({ name: 'Updated' }).where('id', id).callback(function(err, count) {
self.ok(!err, 'Should update without error');
self.ok(count > 0, 'Should update at least one item');
// Remove
NOSQL('test').remove().where('id', id).callback(function(err, count) {
self.ok(!err, 'Should remove without error');
self.ok(count > 0, 'Should remove at least one item');
self.done();
});
});
});
});
});
// Test localization
TEST('localization', function() {
var self = this;
self.ok(TRANSLATE('en', 'welcome'), 'Should have English translation');
self.ok(TRANSLATE('es', 'welcome'), 'Should have Spanish translation');
self.done();
});
// Test file operations
TEST('file.operations', function() {
var self = this;
var filename = 'test-' + UID() + '.txt';
var filepath = PATH.temp(filename);
// Write file
Fs.writeFile(filepath, 'Test content', function(err) {
self.ok(!err, 'Should write file');
// Read file
Fs.readFile(filepath, 'utf8', function(err, content) {
self.ok(!err, 'Should read file');
self.ok(content === 'Test content', 'Content should match');
// Delete file
Fs.unlink(filepath, function(err) {
self.ok(!err, 'Should delete file');
self.done();
});
});
});
});
// Run all tests
setTimeout(function() {
// Give server time to start
RUN();
}, 2000);
`,
'package.json': `{
"name": "totaljs-app",
"version": "1.0.0",
"description": "Total.js application with CMS and real-time features",
"main": "index.js",
"scripts": {
"start": "node index.js",
"dev": "node debug.js",
"test": "node tests/test.js",
"build": "total4 --minify --compile"
},
"dependencies": {
"total4": "^4.0.0"
},
"devDependencies": {
"nodemon": "^3.0.0"
},
"engines": {
"node": ">=14.0.0"
}
}
`,
'debug.js': `// Debug mode with auto-restart
require('total4/debug')({
port: 8000,
watch: true,
cluster: false
});
`,
'config': `
name : Total.js Application
version : 1.0.0
author : Your Name
default-ip : 127.0.0.1
default-port : 8000
secret : your-secret-key-change-this
cookie-secret : another-secret-key
database : ./databases/
directory-temp : /tmp/
directory-public : /public/
directory-logs : /logs/
directory-resources : /resources/
default-language : en
languages : en,es,fr,de
mail-smtp : smtp.gmail.com
mail-smtp-port : 465
mail-smtp-secure : true
mail-from : noreply@yourdomain.com
default-request-timeout : 5000
default-interval-clear : 60000
default-maximum-file : 10485760
allow-gzip : true
allow-websocket : true
allow-performance : false
allow-compile : true
allow-compress-html : true
allow-compress-js : true
allow-compress-css : true
cors : *
cors-credentials : true
currency : USD
items-per-page : 20
`,
'resources/en.resource': `// English translations
welcome : Welcome
login : Login
logout : Logout
register : Register
profile : Profile
settings : Settings
save : Save
cancel : Cancel
delete : Delete
edit : Edit
create : Create
search : Search
loading : Loading...
error : Error
success : Success
confirm : Are you sure?
// Forms
email : Email
password : Password
name : Name
username : Username
remember_me : Remember me
forgot_password : Forgot password?
// Messages
login_success : Successfully logged in
logout_success : Successfully logged out
save_success : Successfully saved
delete_success : Successfully deleted
error_generic : An error occurred
error_not_found : Not found
error_unauthorized : Unauthorized
error_forbidden : Forbidden
// CMS
pages : Pages
widgets : Widgets
media : Media
users : Users
analytics : Analytics
dashboard : Dashboard
content : Content
`,
'Dockerfile': `FROM node:18-alpine
RUN apk add --no-cache \
python3 \
make \
g++ \
cairo-dev \
jpeg-dev \
pango-dev \
giflib-dev
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
RUN mkdir -p /app/tmp /app/logs /app/databases /app/public/uploads
RUN chmod -R 755 /app
EXPOSE 8000
ENV NODE_ENV=production
CMD ["node", "index.js"]
`,
'docker-compose.yml': `version: '3.8'
services:
app:
build: .
container_name: totaljs-app
ports:
- "8000:8000"
environment:
- NODE_ENV=production
- PORT=8000
- DATABASE_PATH=/data/databases
- TEMP_PATH=/data/tmp
- SMTP_USER=\${SMTP_USER}
- SMTP_PASSWORD=\${SMTP_PASSWORD}
volumes:
- ./data:/data
- ./public/uploads:/app/public/uploads
- ./logs:/app/logs
restart: unless-stopped
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8000/api/"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s
redis:
image: redis:7-alpine
container_name: totaljs-redis
ports:
- "6379:6379"
volumes:
- redis_data:/data
restart: unless-stopped
postgres:
image: postgres:15-alpine
container_name: totaljs-postgres
environment:
- POSTGRES_DB=totaljs
- POSTGRES_USER=totaljs
- POSTGRES_PASSWORD=\${DB_PASSWORD}
ports:
- "5432:5432"
volumes:
- postgres_data:/var/lib/postgresql/data
restart: unless-stopped
volumes:
redis_data:
postgres_data:
`,
'.env.example': `
NODE_ENV=development
PORT=8000
SECRET_KEY=your-secret-key-here
DB_PASSWORD=your-db-password
SMTP_USER=your-email@gmail.com
SMTP_PASSWORD=your-email-password
GOOGLE_ANALYTICS_ID=
SENTRY_DSN=
STRIPE_API_KEY=
AWS_ACCESS_KEY_ID=
AWS_SECRET_ACCESS_KEY=
`,
'README.md': `
A full-featured web application built with Total.js framework, including CMS and real-time capabilities.
- ๐ **MVC Architecture** - Clean and organized code structure
- ๐ฆ **Built-in NoSQL Database** - No external database required
- ๐ **Real-time WebSockets** - Built-in support for real-time features
- ๐ **Content Management System** - Integrated CMS with pages and widgets
- ๐ **Authentication & Authorization** - Complete auth system
- ๐ง **Email System** - Built-in mail sending with templates
- ๐ **Internationalization** - Multi-language support
- ๐งช **Testing Framework** - Built-in testing tools
- ๐ณ **Docker Ready** - Containerized deployment
\`\`\`bash
npm install
npm run dev
npm test
\`\`\`
\`\`\`bash
npm run build
npm start
\`\`\`
\`\`\`bash
docker-compose up -d
docker-compose logs -f app
\`\`\`
\`\`\`
โโโ controllers/
โโโ definitions/
โโโ models/
โโโ schemas/
โโโ views/
โโโ public/
โโโ resources/
โโโ databases/
โโโ tests/
โโโ tmp/
\`\`\`
Edit the \`config\` file to customize your application:
- Server settings (port, IP, timeouts)
- Security (secret keys, CORS)
- Features (gzip, websocket, minification)
- Mail settings (SMTP configuration)
- Localization (languages, translations)
## API Documentation
### Authentication
- \`POST /api/auth/login\` - User login
- \`POST /api/auth/logout\` - User logout
- \`POST /api/auth/register\` - User registration
- \`POST /api/auth/forgot\` - Password reset
### Users
- \`GET /api/users\` - List users
- \`GET /api/users/{id}\` - Get user details
- \`POST /api/users\` - Create user
- \`PUT /api/users/{id}\` - Update user
- \`DELETE /api/users/{id}\` - Delete user
- \`ws://localhost:8000/live/\` - General WebSocket connection
- \`ws://localhost:8000/chat/\` - Chat room WebSocket
Access the CMS at \`/cms/\` with admin credentials.
- **Pages** - Create and manage website pages
- **Widgets** - Reusable content blocks
- **Media** - Upload and manage files
- **Users** - User management
- **Settings** - System configuration
- **Analytics** - Site statistics
Total.js includes a built-in testing framework:
\`\`\`javascript
TEST('test.name', function() {
var self = this;
// Your test code
self.ok(condition, 'Test description');
self.done();
});
\`\`\`
- \`NODE_ENV\` - Environment (development/production)
- \`PORT\` - Server port
- \`SECRET_KEY\` - Application secret
- \`SMTP_USER\` - Email username
- \`SMTP_PASSWORD\` - Email password
1. Use process manager (PM2, systemd)
2. Enable SSL/TLS with reverse proxy
3. Set up regular backups
4. Monitor application health
5. Use environment variables for secrets
## Resources
- [Total.js Documentation](https://docs.totaljs.com)
- [Total.js Examples](https://github.com/totaljs/examples)
- [Total.js Community](https://community.totaljs.com)
## License
MIT
`
}
};