First commit

This commit is contained in:
2025-12-25 11:16:59 +01:00
commit 0c5ca09a63
720 changed files with 329234 additions and 0 deletions

View File

@@ -0,0 +1,22 @@
export default class ajaxSocket{
async send( message ) {
var json = JSON.parse( message );
json.sessionKey = new String( that.sessionKey );
message = JSON.stringify( json );
var result = await that.fetch( message );
var a = new Object();
a.data = result;
that.message( a )
}
}

View File

@@ -0,0 +1,163 @@
/*
Copyright (c) 2020, 2023, The Unified Company.
This code is part of Unify.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE,
as published by the Free Software Foundation.
See the GNU AFFERO GENERAL PUBLIC LICENSE, for more details.
https://unifyjs.org
*/
import keyFrame from "./animation.keyFrame.js";
export default class animation{
name;
element;
keyFrames = new Array();
animationManager;
duration;
createKeyFrame( percent ) {
var newKeyFrame = new keyFrame();
newKeyFrame.percent = percent;
this.keyFrames.push( newKeyFrame );
return newKeyFrame;
}
createPromiseFunction( id ) {
var that = this;
function promiseFunction( resolveFunction ){
var promiseObject = new Object;
promiseObject.id = id;
promiseObject.resolve = resolveFunction;
that.animationManager.addPromise( promiseObject );
}
return promiseFunction;
}
async stop() {
if( !this.element.classList.contains("keyFrameAnimations") ) {
var animationClassName = this.animationManager.getAnimationClassName();
this.element.classList.remove( animationClassName );
}
}
async pause() {
this.element.classList.add("pause-animation");
}
setDuration( duration ) {
this.duration = duration;
}
setDirection( direction ) {
this.direction = direction;
}
setIterationCount( iterationCount ) {
this.iterationCount = iterationCount;
}
setFillMode( fillMode ) {
this.fillMode = fillMode;
}
async play( duration ) {
if( this.element.classList.contains("pause-animation") ) {
this.element.classList.remove("pause-animation");
return true;
}
if( !this.element.classList.contains("keyFrameAnimations") ) {
var animationClassName = this.animationManager.getAnimationClassName();
this.element.classList.add( animationClassName );
}
if( duration ) {
this.duration = duration;
}
this.active = true;
var source = this.animationManager.composeCss();
this.writeStyleToDOM( source );
var promiseFunction = this.createPromiseFunction( this.id );
var promise = new Promise( promiseFunction );
this.animationManager.createEventListener();
await promise;
return true;
}
writeStyleToDOM( source ) {
var style = document.createElement("style")
style.type = 'text/css';
style.appendChild( document.createTextNode( source ) );
document.getElementsByTagName("head")[0].appendChild( style );
}
}

View File

@@ -0,0 +1,59 @@
/*
Copyright (c) 2020, 2023, The Unified Company.
This code is part of Unify.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE,
as published by the Free Software Foundation.
See the GNU AFFERO GENERAL PUBLIC LICENSE, for more details.
https://unifyjs.org
*/
import property from "./animation.property.js";
export default class keyFrame{
percent;
properties = new Array();
setProperty( name, value ) {
var newProperty = new property();
newProperty.name = name;
if(typeof value == "number") {
value += "px";
}
newProperty.value = value;
this.properties.push( newProperty );
}
composeCss() {
var properties = this.properties;
var propertyLines = "";
for (var i = 0; i < properties.length; i++) {
propertyLines += properties[i].composeCss();
}
return propertyLines;
}
}

View File

@@ -0,0 +1,38 @@
/*
Copyright (c) 2020, 2023, The Unified Company.
This code is part of Unify.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE,
as published by the Free Software Foundation.
See the GNU AFFERO GENERAL PUBLIC LICENSE, for more details.
https://unifyjs.org
*/
export default class property{
name;
value;
composeCss() {
var functionNames = new Array( "rotate", "translate", "scaleX", "scaleY", "scale", "skewX", "skewY", "skew", "matrix" );
if( functionNames.includes( this.name ) ) {
return "transform: " + this.name + "( " + this.value + " ); ";
} else {
return "\n " + this.name + " : " + this.value + ";\n";
}
}
}

View File

@@ -0,0 +1,454 @@
/*
Copyright (c) 2020, 2023, The Unified Company.
This code is part of Unify.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE,
as published by the Free Software Foundation.
See the GNU AFFERO GENERAL PUBLIC LICENSE, for more details.
https://unifyjs.org
*/
import animation from "./animation.js";
export default class animationManager{
id = 0;
start = 0;
animations = new Array();
element = document.querySelector(".test");
promises = new Array();
eventListener;
constructor() {
this.id = document.animationID++;
}
createAnimation( name ) {
var newAnimation = new animation();
newAnimation.animationManager = this
newAnimation.id = document.keyframeID++;
newAnimation.name = name + newAnimation.id;
newAnimation.element = this.element;
newAnimation.created = false;
this.animations[ newAnimation.name ] = newAnimation;
this.createListeners( newAnimation );
return newAnimation;
}
getAnimationClassName() {
return "keyFrameAnimation" + this.id;
}
createListeners( animation ) {
if( !animation.direction ) {
animation.__direction = "normal"
} else {
animation.__direction = animation.direction;
}
var that = this;
animation.__defineSetter__( "direction", function( value ){
animation.__direction = value;
var animationManager = animation.animationManager;
var source = that.composeCss();
animation.writeStyleToDOM( source );
});
animation.__defineGetter__( "direction", function(){
return animation.__direction;
});
}
composeKeyFrameCss( source ) {
var animations = this.animations;
for ( var i in animations ) {
var currentAnimation = animations[i];
//if( !currentAnimation.active ) {
source += "@keyframes " + currentAnimation.name + "{ \n";
var keyFrames = currentAnimation.keyFrames;
for (var i = 0; i < keyFrames.length; i++) {
var currentKeyFrame = keyFrames[i];
source += "\t" + currentKeyFrame.percent + "% {";
source += currentKeyFrame.composeCss();
source += "}\n";
}
source += "} \n";
currentAnimation.created = true;
//}
}
return source;
}
composeAnimationCss( source ) {
var names = new Array();
var durations = new Array();
var interationCounts = new Array();
var fillModes = new Array();
var directions = new Array();
var animations = this.animations;
for ( var i in animations ) {
var currentAnimation = animations[i];
if( currentAnimation.active ) {
if( currentAnimation.duration ) {
names.push( currentAnimation.name );
durations.push( currentAnimation.duration );
directions.push( currentAnimation.direction );
if( !currentAnimation.iterationCount ) {
currentAnimation.iterationCount = 1;
}
interationCounts.push( currentAnimation.iterationCount );
if( !currentAnimation.fillMode ) {
currentAnimation.fillMode = "none";
}
fillModes.push( currentAnimation.fillMode );
}
}
}
source += ".keyFrameAnimation" + this.id + "{\n";
source += "\tanimation-name: " + names.join(",") + ";\n";
source += "\tanimation-duration: " + durations.join(",") + ";\n";
source += "\tanimation-iteration-count: " + interationCounts.join(",") + ";\n";
source += "\tanimation-fill-mode: " + fillModes.join(",") + ";\n";
source += "\tanimation-direction: " + directions.join(",") + ";\n";
source += "}";
return source;
}
composeCss() {
var source = "";
source += this.composeKeyFrameCss( source );
source += this.composeAnimationCss( source );
return source;
}
addPromise( promiseObject ) {
this.promises[ promiseObject.id ] = promiseObject;
}
getPromiseByID( id ) {
return this.promises[ id ];
}
createPromiseFunction( animationID ) {
var that = this;
function promiseFunction( resolveFunction ){
var promiseObject = {};
promiseObject.id = animationID;
promiseObject.resolve = resolveFunction;
that.addPromise( promiseObject );
}
return promiseFunction;
}
attach( object ){
object.__proto__.animate = this.createCallback( object );
var animationManager = this;
object.createAnimation = function( name ) {
return object.animationManager.createAnimation( name );
}
this.element = object.element;
}
createCallback( object ) {
object.animationManager.object = object;
return async function( from, to, callback ) {
return object.animationManager.animate( from, to, callback );
}
}
async animate( from, to, callback, firstTick = true, animationID, value = false, start = false ) {
var object = this.object;
if( firstTick ) {
animationID = document.animationID++;
}
var sign = Math.sign( from - to );
var stop = false;
if( sign > 0) {
value = from - value;
if( value < to ) {
var stop = true;
}
} else {
value = from + value;
if( value > to ) {
var stop = true;
}
}
if( firstTick ) {
this.object[ "animationCallback" + animationID ] = callback;
}
if( !stop ) {
this.object[ "animationCallback" + animationID ]( value );
window.requestAnimationFrame( function( timestamp ) {
if( !start ) {
start = timestamp;
}
var progress = ( timestamp - start );
object.animationManager.animate( from, to, callback, false, animationID, progress, start );
});
} else {
var promise = this.getPromiseByID( animationID );
promise.resolve();
}
if( firstTick ) {
this.object[ "animationCallback" + animationID ]( value );
var promiseFunction = this.createPromiseFunction( animationID );
await new Promise( promiseFunction )
return true;
}
}
createEventListener() {
var that = this;
if( this.element.keyFrameEventListener ) {
canvas.removeEventListener('click', this.element.keyFrameEventListener);
}
this.element.keyFrameEventListener = this.element.addEventListener("animationend", async function( event ) {
var animations = that.animations;
var animationName = event.animationName;
//console.log(animationName, that.promises);
//console.log(animations, animationName)
var currentAnimation = animations[ animationName ];
console.log("turn off animation", currentAnimation);
currentAnimation.active = false;
//console.log("promise with animationName", animationName, "and animationID", currentAnimation.animationID, "removed");
if( currentAnimation ) {
var promise = that.promises[currentAnimation.id];
if( promise ) {
promise.resolve();
} else {
return false;
}
}
//console.log("ended animation", currentAnimation);
that.promises.splice( currentAnimation.id, 1, false )
for (var i = 0; i < that.promises.length; i++) {
if( that.promises[i] ) {
return false
}
}
//console.log("all promises are resolved resetting animation");
//that.resetAnimation();
var animationClassName = that.getAnimationClassName();
that.element.classList.remove(animationClassName);
}, false);
return true;
}
resetAnimation() {
//if( this.element.classList.contains("keyFrameAnimations") ) {
this.element.classList.remove("keyFrameAnimations")
//}
}
}

View File

@@ -0,0 +1,702 @@
/*
Copyright (c) 2020, 2023, The Unified Company.
This code is part of Unify.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE,
as published by the Free Software Foundation.
See the GNU AFFERO GENERAL PUBLIC LICENSE, for more details.
https://unifyjs.org
*/
import core from './core.js';
import dom from './dom.js';
import css from './css.js';
import eventManager from './eventManager.js';
import socketManager from './socketManager.js';
import animationManager from './animation/animationManager.js';
import collection from './collection.js';
import codePreview from './codePreview.js';
import themeLoader from './themeLoader.js';
import tools from '../unify/tools.js';
import defaultObject from '../unify/defaultObject.js';
//import cookieManager from '../unify/cookieManager.js';
import cacheManager from "../unify/cacheManager.js";
import config from "../configs/config.js";
import applicationImport from './import.js';
import progressBar from './progressBar.js';
import applications from '../configs/applications.js';
import simplePath from "../unify/simplePath.js";
// For Benchmarking
//document.timer.lap("before");
//document.timer.lap("after");
document.promises = new Array();
document.cacheManager = new cacheManager();
document.cacheManager.useDB = false;
document.debugALL = false;
export default class applicationManager{
socketPort = 5002;
defaultSocketPort = 5002;
loadEditor = true;
defaultObject = new defaultObject();
themeLoader = new themeLoader();
mode = "development";
serverAddress = "localhost";
serverPort = 8090;
application;
applications;
applicationInstances = new Array();
ssl = false;
themeObjects = new Array();
connectPromise;
signinPromise;
constructor() {
this.themeLoader.applicationManager = this;
}
setParameters( config ) {
this.mode = config.mode;
this.ssl = config.ssl;
this.socketPort = config.socketPort;
this.loadThemes = config.loadThemes;
this.os = tools.CamelCase( config.os );
this.tint = tools.CamelCase( config.tint );
this.device = tools.CamelCase( config.device );
if( config.serverAddress ) {
this.serverAddress = config.serverAddress;
} else {
this.serverAddress = "localhost";
}
if( config.port ) {
this.port = config.port;
} else {
this.port = 3000;
}
}
setGlobal() {
document.mode = this.mode;
document.config = new Object();
document.config.os = this.os;
document.config.tint = this.tint;
document.config.device = this.device;
}
logConfig( config ) {
console.log( config );
console.log("set socket port", this.socketPort );
console.log( "running in ", config.mode, " mode.", "address : " + this.serverAddress );
}
parseConfig() {
this.setParameters( config );
this.setGlobal();
this.logConfig( config );
}
createApplicationPath( path ) {
var device = tools.CamelCase( this.device );
var os = tools.CamelCase( this.os );
var tint = tools.CamelCase( this.tint );
var applicationPath = '/framework/cache/platforms/' + os + '/' + device + '/' + tint + '/' + path + '/application.js';
return applicationPath;
}
async getApplicationInstance( path, applicationID ) {
if( this.mode == "development" ) {
var applicationPath = this.createApplicationPath( path );
var importObject = await import( applicationPath );
this.application = new importObject.default();
} else {
var currentBundle = applicationImport[ applicationID ];
//console.log("loading application with id", applicationID);
if( currentBundle ) {
this.application = new currentBundle();
}
}
return this.application;
}
getUserObject( core, application, username, sessionKey ) {
if( !username ) {
var userObject = core.getFirstByClassName( "signin", application );
} else {
var userObject = core.getFirstByClassName( "signin", application );
if( !userObject ){
return false;
}
if( sessionKey ) {
userObject.sessionKey.value = sessionKey;
}
}
return userObject;
}
async singinUser( core, socketManager, userObject ) {
//var user = await socketManager.get( "settings", "signIn", userObject );
var user = await userObject.process();
//await userObject.socketManager.get( "table", "process", userObject );
//var user = await userObject.process();
core.user = user;
await core.setUser( user, application );
console.log( "update user permissions", user );
if( !user.permissionObjects ) {
return false;
}
core.updatePermissions( user.permissionObjects );
}
configurePath() {
this.url = window.location;
this.pathName = this.url.pathname;
}
parseUrlByID( core, tableName, id ) {
var objects = core.getObjectsByPropertyName( tableName );
if( objects.length > 0 ) {
var object = objects[0];
if( object.parent.create ) {
object.parent.create();
}
object.id = parseFloat( id );
if( object.loadPage ) {
object.loadPage();
}
object.showParents();
}
}
async parseUrl( core, application ) {
this.configurePath();
var pathName = this.pathName;
var pathParts = pathName.split("/");
pathParts.shift();
var tableName = pathParts[0];
var id = pathParts[1];
if( id ) {
this.parseUrlByID( core, tableName, id );
} else {
document.stateMachine.composeState()
core.runDefault( application );
}
}
createBaseUrl() {
var base = document.createElement("base");
if( this.ssl ) {
base.href = "https://" + this.serverAddress;
} else {
base.href = "http://" + this.serverAddress + ":" + this.port;
}
document.head.appendChild( base );
}
createMetaDescription() {
if( this.application.description ) {
document.querySelector(".metaDescription").setAttribute("content", this.application.description );
} else {
document.querySelector(".metaDescription").setAttribute("content", "A unifyJS application." );
}
}
async initializeSocketManager( core, application ) {
var socket = new socketManager( this.socketPort );
socket.ssl = this.ssl;
socket.serverAddress = this.serverAddress;
this.connectPromise = socket.connect();
document.connectPromise = this.connectPromise;
await this.connectPromise;
socket.addClient();
return socket;
}
async createApplicationInstances() {
for( var applicationID = 0; applicationID < this.applications.length; applicationID++ ) {
var applicationFile = this.applications[ applicationID ];
this.applicationInstances[ applicationID ] = await this.getApplicationInstance( applicationFile.path, applicationID );
}
}
bindApplications() {
this.applications = applications;
document.applications = applications;
}
getApplication() {
var applicationFile = this.applications[ 0 ];
applicationFile.socket = socket;
}
async start() {
var unifyCore = new core();
this.parseConfig();
this.bindApplications();
this.createBaseUrl();
await this.createApplicationInstances();
var socket = this.initializeSocketManager( unifyCore, this.applicationInstances[0] );
await this.runApplication( socket, 0, unifyCore );
this.createMetaDescription();
document.timer.lap("Everything is loaded");
console.log( this.applicationInstances[0] );
}
async updateApplications() {
for( var applicationID = 1; applicationID < this.applications.length; applicationID++) {
var applicationFile = this.applications[ applicationID ];
var unifyCore = new core();
this.runApplication( applicationFile.socket, applicationID, unifyCore );
}
}
async attachSocket( applicationFile, socket, applicationID ) {
if( !applicationFile.socket ) {
applicationFile.socket = await new socketManager( this.defaultSocketPort + applicationID );
if( this.serverAddress ) {
applicationFile.socket.serverAddress = this.serverAddress;
}
await applicationFile.socket.connect();
}
return applicationFile.socket;
}
preventDoubleLoading( element ) {
if( element && element.childElementCount != 0 ) {
return true;
}
}
createCodeEditor( app, applicationID ) {
if( applicationID != 0 ) {
new codePreview( app );
}
}
getDomElement( application ) {
if( this.applications.length == 1) {
application.selector = "#application";
}
var element = document.querySelector( application.selector );
if( document.querySelectorAll( application.selector ).length == 0 ) {
return true;
} else {
if( this.preventDoubleLoading( element ) ) {
return true;
}
}
return false;
}
configureCore( core ) {
core.device = this.device;
core.os = this.os;
core.tint = this.tint;
}
setGlobalCore( unifyCore, applicationID ) {
if( !document.cores ) {
document.cores = new Array();
}
document.cores[ applicationID ] = unifyCore;
}
async parseApplication( core, application, applicationID ) {
this.defaultObject.agregateDefaultObject( application );
this.setGlobalCore( core, applicationID );
await core.prepareObjects( application );
await document.connectPromise;
this.configureCore( core );
core.setTheme();
application.core = core;
await core.parse( application, true );
core.createDependencyMap();
}
hidePreloader() {
if( document.querySelector(".loadingBarPanel, .preloader, #preloader" )) {
document.querySelector(".loadingBarPanel, .preloader, #preloader").style.opacity = "0%";
}
setTimeout(function(){
document.querySelector(".loadingBarPanel, .preloader, #preloader").style.display = "none";
}, 1000)
}
logApplication( application, unifyCore ) {
if( document.debugALL ) {
console.log( "" );
console.log( "run application", application.selector );
console.log( "Core", unifyCore );
console.log( "Application", application );
console.log( "" );
}
}
setServerPort( port ) {
if( application.port ) {
this.serverPort = application.port;
}
}
prepareApplication(applicationID) {
var application = this.applicationInstances[ applicationID ];
application.applicationID = applicationID;
this.setServerPort( application.port );
return application;
}
bindObjectsToSocket( socket, application, unifyCore, applicationID ) {
if( applicationID == 0 ) {
socket.application = application;
socket.core = unifyCore;
}
}
async runApplication( socket = false, applicationID, unifyCore ) {
if ( this.applicationInstances[ applicationID ] ) {
var application = this.prepareApplication( applicationID );
this.bindObjectsToSocket( socket, application, unifyCore, applicationID );
if( this.getDomElement( application ) ) {
return true;
}
unifyCore.socketManager = await socket;
this.hidePreloader();
this.createCodeEditor( application, applicationID );
await this.parseApplication( unifyCore, application, applicationID );
//this.signinPromise = this.checkSignIn( socket, unifyCore, application );
//console.log("after signin");
if( applicationID == 0 ) {
//this.parseUrl( unifyCore, application );
}
//await Promise.all( document.promises );
await unifyCore.callAfterLoad( application );
this.logApplication( application, unifyCore );
if( this.loadThemes ) {
await this.themeLoader.loadThemes( application, applicationID, unifyCore );
}
this.setGlobals();
await unifyCore.callAfterThemeLoad( application );
}
return true;
}
setGlobals() {
document.timer.initialising = false;
document.themeObjects = this.themeObjects;
}
}

View File

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,80 @@
/*
Copyright (c) 2020, 2023, The Unified Company.
This code is part of Unify.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE,
as published by the Free Software Foundation.
See the GNU AFFERO GENERAL PUBLIC LICENSE, for more details.
https://unifyjs.org
*/
export default class codePreview{
constructor( application ) {
return this.createPreviewApplication( application );
}
createPreviewApplication( app ) {
// Create those light blue preview applications on the right side of the code blocks
var id = app.selector;
var element = document.querySelector( id );
if( element && element.children.length == 0 ) {
this.stylePreviewApplication( element, id );
}
return element;
}
stylePreviewApplication( element, id ) {
var examplePre = element.previousElementSibling;
if( examplePre && examplePre.firstChild ) {
var codeElement = examplePre.firstChild;
codeElement.className = codeElement.className + " halfCodeElement";
examplePre.className = "examplePre";
element.remove();
var examplePanel = document.createElement("div");
examplePanel.className = "examplePanel";
examplePanel.id = id.replace("#", "").replace(".", "");
examplePre.appendChild( examplePanel );
}
}
createPreviewLabel( element ) {
var previewLabel = document.createElement("div");
previewLabel.className = "previewLabel";
previewLabel.innerHTML = "preview";
element.appendChild( previewLabel );
}
}

View File

@@ -0,0 +1,46 @@
/*
Copyright (c) 2020, 2023, The Unified Company.
This code is part of Unify.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE,
as published by the Free Software Foundation.
See the GNU AFFERO GENERAL PUBLIC LICENSE, for more details.
https://unifyjs.org
*/
import tools from '../unify/tools.js';
import baseCollection from '../unify/collection.js';
export default class collection extends baseCollection{
__className = "collection";
clearCollection() {
var rows = this.rows;
console.log("clear collection", rows, this);
for( var c = 0; c < rows.length; c++ ) {
var object = rows[c];
object.remove();
}
this.rows = new Array();
}
}

View File

@@ -0,0 +1 @@
{"mode":"development","serverAddress":"localhost","ssl":false,"socketPort":5000,"port":3000}

1523
framework/client/core.js Normal file
View File

File diff suppressed because it is too large Load Diff

637
framework/client/css.js Normal file
View File

@@ -0,0 +1,637 @@
/*
Copyright (c) 2020, 2023, The Unified Company.
This code is part of Unify.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE,
as published by the Free Software Foundation.
See the GNU AFFERO GENERAL PUBLIC LICENSE, for more details.
https://unifyjs.org
*/
import cssRules from './cssRules.js';
import document from '../unify/document.js';
import cssManager from './cssManager.js';
import tools from '../unify/tools.js';
import definitions from '../unify/definitions.js';
export default class css{
cssCache = new cssManager();
global_css = "";
skipBoxTerms = new Array( "box-sizing", "box-shadow", "box-reflect", "box-decoration-break" );
constructor() {
this.boxTermWithoutPrefix = new Array();
for (var i = 0; i < this.skipBoxTerms.length; i++) {
var boxTerm = this.skipBoxTerms[i]
this.boxTermWithoutPrefix[i] = boxTerm.replace("box-")
}
}
PerformPropertyGridCorrection( property ) {
for ( var i = 0; i < this.skipBoxTerms.length; i++ ) {
if( this.boxTermWithoutPrefix[ i ].includes( property ) ) {
property = this.skipBoxTerms[ i ];
}
}
return property;
}
parseObject( object ){
var objectName = object.propertyName;
object.__proto__.css = new cssRules();
object.__proto__.boxRules = new cssRules();
object.__proto__.cssRules = new cssRules();
object.cssRules.addStyleListener( "hover", ":hover" );
object.cssRules.addStyleListener( "visited", ":visited" );
object.cssRules.addStyleListener( "link", ":link" );
object.cssRules.addStyleListener( "active", ":active" );
object.cssRules.addStyleListener( "placeholder", "::placeholder" );
object.cssRules.addStyleListener( "scrollbar", "::-webkit-scrollbar" );
object.cssRules.addStyleListener( "scrollbarTrack", "::-webkit-scrollbar-track" );
object.cssRules.addStyleListener( "scrollbarThumb", "::-webkit-scrollbar-thumb" );
object.cssRules.addStyleListener( "scrollbarThumbHover", "::-webkit-scrollbar-thumb:hover" );
}
parseCSSValue( value ) {
if( typeof value == "number" ) {
value += "px";
}
return value;
}
createStyleRule( normalizedProperty, value ){
if( !value ) {
return "";
}
value = this.parseCSSValue( value );
normalizedProperty = this.PerformPropertyGridCorrection( normalizedProperty );
return "\t" + normalizedProperty + ":" + value + "; \n";
}
compareUpperCase( term ) {
const compare = function( current ){ if( term.indexOf( current ) != -1 ){ return true; } }
const n = definitions.alphabet;
var map = n.map( compare );
return map; // [false, false, true, false] where true is where higher case is
}
hasUpperCase( a ) {
let regExp = /[A-Z]/;
return regExp.test( a );
}
replaceUpperCase( word ) {
var map = this.compareUpperCase( word );
var letter = definitions.alphabet[ map.indexOf( true ) ];
return word.replace( letter, "-" + letter.toLowerCase() );
}
normalizePropertyName( name ) {
return tools.firstLowerCase( name.replace("__", "").replace("box", "") );
}
// needs caching
normalizeProperty( name ) {
// webkit -> -webkit
if( name.slice( 0, 6 ) == "webkit" ) {
name = "-" + name;
}
for (var i = 0; i < 6; i++) {
if( this.hasUpperCase( name ) ) {
name = this.replaceUpperCase( name ); // backgroundColor -> background-color-and-something
}
}
return name;
}
setter( object, domStyleObject, propertyName, property, value ) {
object[ "__" + propertyName ] = value;
value = this.parseCSSValue( value );
property = this.PerformPropertyGridCorrection( property );
var NSTabNames = new Array("svg", "circle")
// todo : doesnt work properly
//if( NSTabNames.includes( object.element.tagName ) ) {
// domStyleObject.setAttributeNS( null, property, value );
//} else {
domStyleObject.setProperty( property, value );
//}
}
createSetter( property, objectProperty, object, domStyleObject ) {
var css = this;
object[ "__" + objectProperty ] = object[ objectProperty ];
object.__defineSetter__( objectProperty, this.setter.bind( this, object, domStyleObject, objectProperty, property ) );
}
getter( object, objectProperty, value ) {
var newValue = object[ "__" + objectProperty ];
if(typeof newValue == "string") {
var chars = newValue.split();
if( chars[chars.length-2] == "p" && chars[chars.length-1] == "x" ) {
chars = chars.slice(0, -2);
newValue = chars.join();
}
}
if( tools.isCustomNumber( newValue ) ) {
return parseFloat( newValue );
} else {
return newValue;
}
}
createGetter( property, objectProperty, object, domStyleObject ) {
object.__defineGetter__( objectProperty, this.getter.bind( this, object, objectProperty ) );
}
parseProperty( property, object ) {
var propertyName = property.name;
var propertyValue = property.value;
var normalizedProperty = this.normalizeProperty( propertyName );
//if( propertyName == "gridArea" && propertyValue == "none" ) {
// return false;
//}
var slicedProperty = propertyName.toLowerCase().slice( 0, 3 );
if( slicedProperty == "box" ) {
object.boxRules.style += this.parseCssTerm( object, propertyName, propertyValue, object.elements[0], "box" );
} else {
object.css.style += this.parseCssTerm( object, propertyName, propertyValue, object.element )
}
this.parseExtraStyleSuffixes( object, propertyName, propertyValue );
}
parseExtraStyleSuffixes( object, propertyName, propertyValue ) {
var styleTypes = object.cssRules.styleTypes;
for ( var i = 0; i < styleTypes.length; i++ ) {
var cssType = styleTypes[i];
var propertyTerm = cssType.propertyTerm;
var slicedProperty = propertyName.slice( 0, propertyTerm.length );
if( slicedProperty == propertyTerm && propertyName.length > slicedProperty.length ) {
cssType.css += this.parseCssTerm( object, propertyName, propertyValue, object.elements[0], propertyTerm );
}
}
}
parseCssTerm( object, propertyName, propertyValue, element, term = "" ) {
var cssPropertyName = tools.firstLowerCase( propertyName.replace( term, "" ) );
var normalizedProperty = this.normalizeProperty( cssPropertyName );
if( this.propertyIsStyle( normalizedProperty ) ) {
// Setters and getters don't work yet for special suffixes.
if( !term || term == "box" ) {
this.createSetter( normalizedProperty, propertyName, object, element.style );
this.createGetter( normalizedProperty, propertyName, object, element.style );
}
return this.createStyleRule( normalizedProperty, propertyValue );
} else {
return "";
}
}
clearCache() {
this.cssCache.rules = new Array();
}
parseCssRule( object, objectPropertyName, propertyName, propertyValue ) {
var normalizedProperty = this.normalizeProperty( objectPropertyName );
object.boxRules.style += this.createStyleRule( normalizedProperty, propertyValue );
this.createSetter( objectPropertyName, propertyName, object, object.elements[0].style );
this.createGetter( objectPropertyName, propertyName, object, object.elements[0].style );
}
createSelector( className, afterTerm ) {
var selector = "." + className;
selector += "." + this.device;
selector += "." + this.os;
selector += "." + this.tint;
// this doesnt work yet.
if( afterTerm ) {
selector += afterTerm;
}
//selector += "," + selector.replace( "_" + id, "" );
return selector;
}
createStyleSheet( object ){
var objectName = tools.createCSSClassName( object );
var body = object.css.style;
if( object.customElement ) {
var selector = this.createSelector( objectName + "Element" );
this.global_css += this.cssCache.getRule( selector, body );
var selector = this.createSelector( objectName + "Grid" );
this.global_css += this.cssCache.getRule( selector, body );
} else {
var selector = this.createSelector( objectName + "Grid" );
this.global_css += this.cssCache.getRule( selector, body );
}
if( object.boxRules ) {
var selector = this.createSelector( objectName + "Box" );
var body = object.boxRules.style;
this.global_css += this.cssCache.getRule( selector, body );
}
var styleTypes = object.cssRules.styleTypes;
for (var i = 0; i < styleTypes.length; i++) {
var cssType = styleTypes[i];
if( object.useCustomElement ) {
var selector = this.createSelector( objectName + "Element", cssType.cssSuffix );
} else {
var selector = this.createSelector( objectName + "Grid", cssType.cssSuffix );
}
var body = cssType.css;
if( body != "" ) {
//console.log("cssType.cssSuffix", cssType.cssSuffix);
this.global_css += this.cssCache.getRule( selector, body );
}
}
if( !object.parent ) {
this.writeCssToPage( this.global_css );
this.global_css = "";
}
if( object.dynamic ) {
this.writeCssToPage( this.global_css );
this.global_css = "";
}
}
writeCssToPage( css ) {
if( css == "" ) {
return false;
}
var style = document.createElement("style");
style.innerHTML = css;
document.head.appendChild( style );
}
removeStripe( name ) {
var splitName = name.split("-");
if( splitName.length > 1 ) {
return splitName[1].toLowerCase();
} else {
return name;
}
}
getStyleSheetObject(){
if( !document.body ) {
return definitions.css;
/*
var array = JSON.parse(cssDef);
var object = new Object();
for (var i = 0; i < array.length; i++) {
var def = array[i];
if( this.hasUpperCase( def ) ) {
object[ this.replaceUpperCase( def ) ] = '';
console.log( this.replaceUpperCase( def ) );
} else {
object[ def ] = '';
}
}
*/
return object;
}
if( document.body.style ) {
var bodyStyle = document.body.style;
bodyStyle.webkitBoxShadow = "";
return bodyStyle;
}
if( document.body.styleSheets ) {
// fix please!!!! not allowed
return document.styleSheets[1].cssRules[0].style;
} else {
return document.customStyleTerms;
}
}
camelCaseToDash( name ) {
for ( var i = 0; i < 4; i++ ) {
if( this.hasUpperCase( name ) ) {
name = this.replaceUpperCase( name ); // backgroundColor -> background-color
}
}
return name;
}
removeBoxPrefix( name ) {
if( !name.includes("webkit-box") ) {
name = name.replace("box", "").toLowerCase();
}
return name;
}
checkBoxSpecialCase( name ) {
for (var i = 0; i < this.boxTermWithoutPrefix.length; i++) {
if( this.boxTermWithoutPrefix[ i ].includes( name ) ) {
return true;
}
}
}
propertyIsStyle( name ){
name = this.camelCaseToDash( name );
name = this.removeBoxPrefix( name );
if( this.checkBoxSpecialCase( name ) ) {
return true;
}
var styleTerms = this.getStyleSheetObject();
if( typeof styleTerms[ name ] == "string" ) {
return true;
} else {
return false;
}
}
propertyHasStyle( name ){
var styleTerms = Object.keys( definitions.css );
if( styleTerms.includes( name.toLowerCase() ) ) {
return true;
} else {
return false;
}
}
}

View File

@@ -0,0 +1,63 @@
/*
Copyright (c) 2020, 2023, The Unified Company.
This code is part of Unify.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE,
as published by the Free Software Foundation.
See the GNU AFFERO GENERAL PUBLIC LICENSE, for more details.
https://unifyjs.org
*/
import tools from '../unify/tools.js';
export default class cssManager{
rules = new Array();
addRule( selector, body ) {
var rule = new Object();
rule.selector = selector;
rule.body = body;
this.rules[ selector ] = body;
}
composeCss( selector, body ) {
if( body == "") {
return "";
}
return "\n" + selector + "{ " + "\n" + body + "\n" + " } " + "\n";
}
getRule( selector, body ) {
selector = tools.cleanRollup( selector );
if( this.rules[ selector ] ) {
return "";
} else {
this.addRule( selector, body );
return this.composeCss( selector, body );
}
}
}

View File

@@ -0,0 +1,39 @@
/*
Copyright (c) 2020, 2023, The Unified Company.
This code is part of Unify.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE,
as published by the Free Software Foundation.
See the GNU AFFERO GENERAL PUBLIC LICENSE, for more details.
https://unifyjs.org
*/
export default class cssRules{
style = "";
styleTypes = new Array();
addStyleListener( propertyTerm, cssSuffix ) {
var styleType = new Object();
styleType.propertyTerm = propertyTerm;
styleType.cssSuffix = cssSuffix;
styleType.css = "";
this.styleTypes.push( styleType );
}
}

40
framework/client/debug.js Normal file
View File

@@ -0,0 +1,40 @@
import socketManager from './socketManager.js';
//import highlight from '../node_modules/highlight.js/lib/index.js';
//import core from './core.js';
async function run() {
var socket = new socketManager();
socket.mode = "debug";
await socket.connect();
socket.registerClientType("debug");
//var unifyCore = new core();
//unifyCore.parseServer( app, true );
//unifyCore.loadModulesFromFiles( "./application/" );
//console.log( unifyCore );
//socket.debugMessage();
}
run();

View File

@@ -0,0 +1,314 @@
import tools from '../unify/tools.js';
import socketMessage from '../unify/socketMessage.js';
import unify from '../unify/unify.js';
import groupsFlat from '../server/themeGroups.js';
export default class debug {
objects = new Array();
socketManager = false;
parseFilename( filename ) {
if( filename[0] == "-" ) {
return false;
}
if( !filename ) {
filename = "Unknown";
}
var emtpySpaces = 28 - filename.length;
for( var c = 0; c < emtpySpaces; c++) {
filename += " ";
}
return filename;
}
processDebugMessage( message ) {
switch( message.parameters.action ) {
case "log":
this.logDebugMessage( message );
break;
case "addObject":
this.addDebugObject( message );
break;
case "updateFile":
this.updateFile( message );
break;
}
}
checkVisible( element ) {
return element.offsetWidth > 0 || element.offsetHeight > 0;
}
getVisibleInherites( className, visible ) {
var core = document.cores[0];
this.cacheArray = new Array();
var objects = core.dependencieMap[className];
if( !objects ) {
return false;
}
for (var b = 0; b < objects.length; b++) {
var object = objects[b];
if( tools.isVisible( object.element ) || visible ) {
this.cacheArray.push( object );
}
}
console.log("created cache array", this.cacheArray);
}
async updateFile( message ) {
var parameters = message.parameters;
var file = parameters.file;
var fullPath = file.path + "/" + file.name;
var currentPath = "../cache/platforms/"+document.config.os+"/"+document.config.device+"/"+document.config.tint+"/" + fullPath + "?disableCache=" + Math.random();
console.log("message", message);
console.log("currentPath", currentPath);
var newImport = await import(currentPath);
var newInstance = new newImport.default();
unify.extend( newInstance );
console.log("newInstance", newInstance);
var className = newInstance.getClassName();
this.getVisibleInherites( className, false );
newInstance.create = false;
this.updateMainObjects( newInstance );
this.updateInherites( newInstance );
var that = this;
setTimeout(function(){
that.getVisibleInherites( className, true );
that.updateInherites( newInstance );
}, 1000);
//function () {
//this.getVisibleInherites( className, true );
//this.updateInherites( newInstance );
//}
}
updateInherites() {
var objects = this.cacheArray;
for ( var c = 0; c < objects.length; c++ ) {
var object = objects[c];
this.instantiateInheritence( object );
}
}
updateMainObjects( newInstance ) {
var core = document.cores[0];
var idObjects = core.classObjects[ newInstance.getClassName() ];
if( idObjects ) {
idObjects = idObjects.filter( n => n );
console.log( idObjects );
for ( var i = 0; i < idObjects.length; i++ ) {
var object = idObjects[i];
object.updateProperties( newInstance );
}
}
}
async instantiateInheritence( object ) {
var newConstructor = object.constructor;
if( object.__sourcePath ) {
var currentPath = "../cache/platforms/" + document.config.os + "/" + document.config.device + "/" + document.config.tint +"/" + object.__sourcePath + "?disableCache=" + Math.random();
var newImport = await import( currentPath );
if( newImport.default ) {
var newInstance = new newImport.default();
unify.extend( newInstance );
console.log("Hot swap Unify Object", object.getClassName(), object.element, newInstance["background"]);
var reload = object.updateProperties( newInstance );
}
} else {
console.log("error object doesnt have sourcePath", object);
}
}
addDebugObject( message ) {
var object = cycle.retrocycle( message.parameters.object );
if( object.applicationPathString ) {
console.log( "add object", object );
var div = document.createElement("div");
div.innerHTML = object.applicationPathString;
var socket = this.socketManager.socket;
div.onclick = function(){
console.log( object.applicationPathString );
var message = new socketMessage();
message.controller = "settings";
message.method = "debugObject";
message.object = object.applicationPathString;
socket.send( JSON.stringify( message ) );
this.style.color = "green";
console.log( this.style.color );
};
document.body.appendChild( div );
}
}
logDebugMessage( message ) {
var parameters = message.parameters;
var parameter1 = cycle.retrocycle( parameters.parameter1 );
var parameter2 = cycle.retrocycle( parameters.parameter2 );
var parameter3 = cycle.retrocycle( parameters.parameter3 );
if(parameter1 == "clear_console") {
console.clear();
}
var filename = parameters.filename;
if( parameters.lineNumber ) {
filename += ":" + parameters.lineNumber;
}
filename = this.parseFilename( filename );
if( parameters.parameter3 ) {
console.log( filename, parameter1, parameter2, parameter3 );
} else if( parameters.parameter2 ) {
console.log( filename, parameter1, parameter2 );
} else {
console.log( filename, parameter1 );
}
}
}

291
framework/client/dom.js Normal file
View File

@@ -0,0 +1,291 @@
/*
Copyright (c) 2020, 2023, The Unified Company.
This code is part of Unify.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE,
as published by the Free Software Foundation.
See the GNU AFFERO GENERAL PUBLIC LICENSE, for more details.
https://unifyjs.org
*/
import document from '../unify/document.js';
import tools from '../unify/tools.js';
export default class dom{
addDOMToSelector = true;
setElement() {
var objectName = tools.createCSSClassName( object );
element.className = this.getClassName( object.editable, objectName ); //tools.cleanRollup( objectName )
}
getClassName( editable, objectName ) {
if( editable ) {
return objectName + "Element";
} else {
return objectName + "Grid grid";
}
}
createSetter( object ) {
object.__defineSetter__( "text", function( value ){
if( typeof value == "number" ) {
value = value.toString();
}
object.__text = value;
object.updateElementContent();
});
}
createGetter( object ) {
object.__defineGetter__( "text", function(){
return object.__text;
});
}
createSetterAndGetters( object ) {
object.__text = object.text;
this.createSetter( object );
this.createGetter( object );
}
createDOMElements( object, objectName ) {
object.elements = [];
if( object.layers == 2 ) {
object.boxElement = this.createDiv( objectName, "box", object.id );
object.elements.push( object.boxElement );
}
object.defaultElement = this.createDiv( objectName, "grid", object.id );
if( object.useCustomElement ) {
object.element = object.customElement;
} else {
object.element = object.defaultElement;
}
object.elements.push( object.element );
}
addClasses( object, objectName ) {
var type = "Element";
var mainClassName = objectName; //tools.cleanRollup( );
object.customElement.classList.add( mainClassName + type );
object.customElement.classList.add( type );
object.customElement.classList.add( this.device );
object.customElement.classList.add( this.tint );
object.customElement.classList.add( this.os );
}
updateZIndex( object ) {
if( !object.zIndex && object.setZIndex ) {
object.element.style["z-index"] = tools.getApplicationDepth( object );
if( object.inverseZIndex ) {
object.element.style["z-index"] = 1000 - tools.getApplicationDepth( object )
}
}
}
attachUnifyObjectToElements( object ) {
for( var c = 0; c < object.elements.length; c++ ) {
object.elements[ c ].object = object;
}
}
parseObject( object ) {
var objectName = tools.createCSSClassName( object );
this.createDOMElements( object, objectName );
if( object.customElement ) {
this.addClasses( object, objectName );
} else {
object.customElement = object.defaultElement;
}
this.createSetterAndGetters( object );
object.updateElementContent();
this.updateZIndex( object );
this.attachUnifyObjectToElements( object );
if( !object.selector && object.parent && object.addToDom ) {
this.parseProperty( objectName, object, object.parent );
}
}
addElementToDOMParent( object, propertyValue ) {
if( propertyValue.propertyName[0] == "_" ) {
object.elements[ object.elements.length - 1 ].prepend( propertyValue.elements[0] );
} else {
if( object.elements ) {
object.elements[ object.elements.length - 1 ].appendChild( propertyValue.elements[0] );
}
}
}
addElementToBody( propertyValue ) {
document.body.appendChild( propertyValue.elements[0] );
}
parseProperty( propertyName, propertyValue, object ) {
if( tools.isUnifyObject( propertyName, propertyValue ) ) {
if( propertyValue.absolute ) {
this.addElementToBody( propertyValue );
return true;
}
this.addElementToDOMParent( object, propertyValue );
}
}
parseInnerElements( object ){
var elements = object.elements;
for( var c = elements.length - 1; c > 0; c--) {
elements[ c - 1 ].appendChild( elements[c] );
}
if( object.selector && this.addDOMToSelector ) {
this.appendToSelector( object, elements );
}
}
appendToSelector( object, elements ) {
var selector = object.selector;
var element = document.querySelector( selector );
if( element ) {
element.appendChild( elements[0] );
}
}
createDiv( divName, type, id ){
var div = document.createElement("div");
var mainClassName = divName + tools.CamelCase( type.toUpperCase() ); //tools.cleanRollup(
div.classList.add( mainClassName );
if( id ) {
div.classList.add( mainClassName.replace( "_" + id, "" ).replace(id, "") );
}
div.classList.add( type );
div.classList.add( this.device );
div.classList.add( this.tint );
div.classList.add( this.os );
return div;
}
}

216
framework/client/editor.js Normal file
View File

@@ -0,0 +1,216 @@
class editor{
create( applicationThree, selector ) {
//var selector =
//var id = app.selector.replace("#", "");
var playground = document.createElement("div");
playground.className = "playground";
var fileTree = document.createElement("div");
fileTree.className = "_fileTree fileTree";
var textarea = document.createElement("textarea");
playground.appendChild( textarea );
selector.appendChild( playground );
textarea.value = applicationThree.files[0].source;
/*
editor
*/
var filetree = this.createFileTreeMenu( applicationThree, editor );
//filetree = document.createElement("div");
//filetree.className = "";
fileTree.appendChild( filetree );
var outputDiv = document.createElement("div");
outputDiv.className = "outputDiv";
//outputDiv.id = id;
console.log( "applicationThree", applicationThree );
console.log("textarea", textarea);
playground.prepend( fileTree );
//playground.appendChild( outputDiv );
//this.createTreeJS( applicationThree, editor, app.selector );
document.querySelector(".CodeMirror").style.height = "900px";//document.body.clientHeight - 46 + "px";
document.querySelector(".fileTree").style.height = "569px";//document.body.clientHeight - 46 + "px";
//document.querySelector(".outputDiv").style.height = "569px";//document.body.clientHeight - 46 + "px";
var documentWidth = document.body.clientWidth;
var editorWidth = document.querySelector(".CodeMirror").clientWidth;
var fileTreeWidth = document.querySelector(".fileTree").clientWidth;
//document.querySelector(".outputDiv").style.width = documentWidth - ( fileTreeWidth + editorWidth ) - 12 + "px";
var outputDiv = document.createElement("div");
outputDiv.className = "outputDiv";
//outputDiv.id = id;
selector.appendChild( outputDiv );
/*
const ps = new PerfectScrollbar(selector, {
wheelSpeed: 2,
wheelPropagation: true,
minScrollbarLength: 20
});
*/
return editor;
}
createFileTreeMenu( applicationThree, editor ) {
var fileList = this.createFileTreeMenuItem( applicationThree, true, editor );
return fileList;
}
createFileTreeMenuItem( file, first, editor ) {
var files = file.files;
var fileList = document.createElement("li");
var row = document.createElement("div");
var label = document.createElement("div");
if( file.type == "directory" ) {
row.className = "caret";
row.state = "closed";
row.onclick = function() {
this.parentElement.querySelector(".nested").classList.toggle("active");
this.querySelector(".directory_icon").classList.toggle("open_directory");
if( this.state == "closed" ) {
this.state = "open";
} else {
this.state = "closed";
}
}
var icon = document.createElement("div");
icon.className = "directory_icon";
row.prepend( icon );
} else {
var icon = document.createElement("div");
icon.className = "file_icon";
row.prepend( icon );
}
row.className = "file_row";
label.innerText = file.name;
row.appendChild( label );
if( file.type == "file" ) {
row.onclick = function() {
if(document.querySelectorAll(".file_row.highlighted").length > 0) {
document.querySelector(".file_row.highlighted").classList.toggle("highlighted");
}
this.classList.toggle("highlighted");
var mode = {name: "javascript"};
var codeMirrorDocument = CodeMirror.Doc( file.source, mode );
//editor.swapDoc( codeMirrorDocument );
// alternative
}
}
fileList.appendChild( row );
var treeMenu = document.createElement("ul");
if( !first ) {
treeMenu.className = "nested"
}
for( var c = 0; c<files.length;c++ ) {
var childFile = files[c];
var childList = this.createFileTreeMenuItem( childFile, false, editor );
treeMenu.appendChild( childList );
}
fileList.appendChild( treeMenu );
if(first) {
return treeMenu;
}
return fileList;
}
}
export default new editor();

26
framework/client/event.js Normal file
View File

@@ -0,0 +1,26 @@
/*
Copyright (c) 2020, 2023, The Unified Company.
This code is part of Unify.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE,
as published by the Free Software Foundation.
See the GNU AFFERO GENERAL PUBLIC LICENSE, for more details.
https://unifyjs.org
*/
export default class event {
name;
className;
callback;
}

View File

@@ -0,0 +1,440 @@
/*
Copyright (c) 2020, 2023, The Unified Company.
This code is part of Unify.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE,
as published by the Free Software Foundation.
See the GNU AFFERO GENERAL PUBLIC LICENSE, for more details.
https://unifyjs.org
*/
import vector2 from '../unify/math/vector2.js';
import event from './event.js';
import tools from '../unify/tools.js';
export default class eventManager{
events = new Array();
eventTerms = new Array();
constructor() {
var prototype = Object.getPrototypeOf( document.body );
var innerPrototype = Object.getPrototypeOf( prototype );
var objectProperties = Object.getOwnPropertyNames( innerPrototype );
var eventProperties = objectProperties.filter( this.filterEvent );
var properEventTerms = eventProperties.map( this.removeOn );
// console.log( "properEventTerms", JSON.stringify( properEventTerms ) );
this.eventTerms = properEventTerms;
}
filterEvent( name ) {
if( name[0] == "o" && name[1] == "n" ){
return true;
} else {
return false;
}
}
removeOn( name ) {
return name.substr( 2, name.length );
}
addClientEvent( className, eventName, callback ) {
var newEvent = new event();
newEvent.className = className;
newEvent.name = eventName;
newEvent.callback = callback;
this.events.push(newEvent);
}
getClientEvents( classname, eventName ){
var events = [];
for(var c = 0; c<this.events.length; c++) {
var event = this.events[c];
if( event.className == classname && event.name == eventName ) {
events.push( event );
}
}
return events;
}
parentHasEvent( object, eventTerm ) {
if( !object ) {
return false;
}
if( object[ eventTerm ] ) {
return true;
}
if( object.parent ){
return this.parentHasEvent( object.parent, eventTerm );
} else {
return false;
}
}
update_value( object ) {
if( object.value && object.value != "undefined" ) {
object._value = object.value;
}
}
createInputSetter( object, element ) {
object.__defineSetter__( "value", function( value ){
if( object.datatype == "BOOLEAN" ) {
object._value = value;
element.value = object._value;
}
if( value && value != undefined && value != "undefined" ) {
object._value = value;
element.value = object._value;
}
if( value == "" ) {
object._value = "";
element.value = "";
}
if( typeof value == "number" ) {
object._value = value;
element.value = object._value;
}
});
}
createUploadSetter( object, element ) {
object.__defineSetter__( "value", function( value ){
if( value != "undefined" ) {
object._value = value;
}
if( element.value ) {
//element.value = value;
}
});
}
createSetter( object, element ) {
this.update_value( object );
if( object.inputType != "file" ) {
this.createInputSetter( object, element );
} else {
this.createUploadSetter( object, element );
}
}
createGetter( object ) {
object.__defineGetter__( "value", function( value ){
if( typeof object._value == "undefined" ) {
return "";
} else {
return object._value;
}
});
}
parseEvents( object ){
if( object.defaultElement ) {
this.createSetter( object, object.defaultElement );
this.createGetter( object );
}
if( object.customElement ) {
this.createSetter( object, object.customElement );
this.createGetter( object );
}
var eventTerms = this.eventTerms;
for(var c = 0; c<eventTerms.length; c++) {
var eventTerm = eventTerms[ c ];
this.parseEvent( object, eventTerm );
}
}
defineEventCallback( object, element, eventTerm ) {
var eventManager = this;
if( !this.parentHasEvent( object.parent, eventTerm ) || object.selector ) {
var eventNormalized = eventTerm.replace("box", "");
if( object.getClassName() != "fileChooserSelectButton" ){
element[ "on" + eventNormalized ] = function( event ) { eventManager.createEventCallback( event, eventManager ); };
}
}
}
createWindowResizeEventListener( object ) {
/*
if( object.parent && object.parent["windowResize"] ) {
window.addEventListener("resize", function(){
object.parent.windowResize();
})
object.parent.windowResize();
}
if( object["windowResize"] ) {
window.onresize = function() {
object.windowResize();
}
object.windowResize();
}
*/
}
parseElement( object, element, eventTerm, box = false ) {
element.object = object;
element.eventTerm = eventTerm;
this.defineEventCallback( object, element, eventTerm );
//this.createWindowResizeEventListener( object );
}
parseDefaultElement( object, eventTerm ) {
if( object[ eventTerm ] ) {
this.parseElement( object, object.defaultElement, eventTerm );
if( object.customElement ) {
this.parseElement( object, object.customElement, eventTerm );
}
}
}
parseBoxElement( object, eventTerm ) {
if( object[ "box" + tools.CamelCase( eventTerm ) ] ) {
if( object.boxElement ) {
var element = object.boxElement;
} else {
var element = object.defaultElement;
}
this.parseElement( object, element, "box" + tools.CamelCase( eventTerm ), true );
}
}
parseEvent( object, eventTerm ) {
this.parseDefaultElement( object, eventTerm );
this.parseBoxElement( object, eventTerm );
}
callMethod( object, event, eventTerm ) {
if( object[ eventTerm ] ) {
object.lastEvent = eventTerm;
object[ eventTerm ]( event, object );
}
}
createEventListener( event, object, box = false ) {
var eventTerm = event.type.replace("on", "");
if( box ) {
eventTerm = "box" + tools.CamelCase( eventTerm );
}
this.callMethod( object, event, eventTerm );
if( !object.isRoot && object.parent ) {
if( object.propegateEvent ) {
this.createEventListener( event, object.parent );
}
}
}
createEventListeners( event, target, eventManager, object ) {
if( object.boxElement && target.className == object.boxElement.className ) {
eventManager.createEventListener( event, object, true );
} else if( target.className == object.defaultElement.className ) {
eventManager.createEventListener( event, object );
} else if( target.className == object.customElement.className ) {
eventManager.createEventListener( event, object );
}
}
logEvent( event, target ) {
//console.log( "Event triggered", event.type.replace("on", ""), target, target.object );
}
createEventCallback( event, eventManager ) {
var target = event.target;
var object = target.object;
if( !object ) {
console.error("This element does not have an object", target);
return false;
}
this.logEvent( event, target );
this.createEventListeners( event, target, eventManager, object );
}
}

View File

@@ -0,0 +1,75 @@
/*
Copyright (c) 2020, 2023, The Unified Company.
This code is part of Unify.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE,
as published by the Free Software Foundation.
See the GNU AFFERO GENERAL PUBLIC LICENSE, for more details.
https://unifyjs.org
*/
export default class fileLoader{
files = new Array();
filesExists = new Array();
async get( url ) {
return await this.getFile( url );
}
exists( url )
{
if( this.filesExists[ url ] ) {
return this.filesExists[ url ];
}
var http = new XMLHttpRequest();
http.open('HEAD', url, false);
http.send();
this.filesExists[ url ] = http.status != 404;
return http.status != 404;
}
async getFile( url ) {
if( this.files[ url ] ) {
return this.files[ url ];
} else {
var response = await fetch( url );
var json = await response.json();
this.addFile( url, json );
return json;
}
}
addFile( url, json ) {
this.files[ url ] = json;
}
}

View File

@@ -0,0 +1,2 @@
import bundle0 from "../../framework/cache/platforms/Windows/Pc/Dark/demo/application.js"
export default [bundle0];

View File

@@ -0,0 +1,3 @@
import bundle0 from "../android/news/application.js"
export default [bundle0];

View File

@@ -0,0 +1,3 @@
import bundle0 from "../ios/news/application.js"
export default [bundle0];

View File

@@ -0,0 +1,3 @@
import bundle0 from "../windows/news/application.js"
export default [bundle0];

View File

@@ -0,0 +1,2 @@
export default [];

View File

@@ -0,0 +1,3 @@
import bundle0 from "../../platform_cache/android/news/application.js"
export default [bundle0];

View File

@@ -0,0 +1,3 @@
import bundle0 from "../../platform_cache/ios/news/application.js"
export default [bundle0];

View File

@@ -0,0 +1,3 @@
import bundle0 from "../../platform_cache/windows/news/application.js"
export default [bundle0];

View File

@@ -0,0 +1 @@
export default {};

126
framework/client/index.js Normal file
View File

@@ -0,0 +1,126 @@
/*
Copyright (c) 2020, 2023, The Unified Company.
This code is part of Unify.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE,
as published by the Free Software Foundation.
See the GNU AFFERO GENERAL PUBLIC LICENSE, for more details.
https://unifyjs.org
*/
import applicationManager from './applicationManager.js';
import timer from './timer.js';
import tools from '../unify/tools.js';
import vector2 from '../unify/math/vector2.js';
document.states = new Array();
window.addEventListener('popstate', function( event ) {
console.log( "popstate tiggered", event, event.state.id );
var stateMachine = document.stateMachine;
console.log( stateMachine );
var state = stateMachine.getState( event.state.id );
console.log( "stateMachine.getState", state, state.id );
state.triggerEvents();
//var table = state.table;
//table.id = state.id;
//table.sync( false, true, false );
}, false);
// Set globals
document.globalZIndex = 2000;
document.animationID = 0;
document.keyframeID = 0;
document.timer = new timer();
if( !document.extendMap ) {
document.extendMap = new Array();
}
function main() {
document.timer.lap("start");
//createGlobalMouseEventListener() {
document.mouse = new vector2(0,0);
document.mouseVelocity = new vector2(0,0);
var lastMouseUpdate = Date.now();
var previousMouse = new vector2(0,0);
document.body.addEventListener('mousemove', function( bodyEvent ) {
if( document.mouse ) {
previousMouse = document.mouse;
document.mouse = new vector2( bodyEvent.clientX, bodyEvent.clientY );
var delta = Date.now() - lastMouseUpdate;
var differenceX = document.mouse.x - previousMouse.x;
var differenceY = document.mouse.y - previousMouse.y;
document.mouseVelocity = new vector2( differenceX / delta, differenceY / delta );
lastMouseUpdate = Date.now();
} else {
document.mouse = new vector2( bodyEvent.screenX, bodyEvent.screenY );
}
});
//}
var applications = new applicationManager();
applications.start();
document.launcher = applications;
}
document.onload = main();

View File

@@ -0,0 +1,146 @@
/*
Copyright (c) 2020, 2023, The Unified Company.
This code is part of Unify.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE,
as published by the Free Software Foundation.
See the GNU AFFERO GENERAL PUBLIC LICENSE, for more details.
https://unifyjs.org
*/
import tools from '../../unify/tools.js';
import unify from '../../unify/unify.js';
//import unParsedObjects from '../unparsed.js'
export default class processManagerAdd{
createPath( sourcePath, random = false ) {
var currentPath = "../cache/platforms/" + document.config.os + "/" + document.config.device + "/" + document.config.tint + "/" + sourcePath;
if( random ) {
currentPath += "?disableCache=" + Math.random();
}
return currentPath;
}
async createObject( objectData ) {
if( document.mode == "development" ) {
var currentPath = "../" + this.createPath( objectData.__sourcePath, true );
console.log("loading???", currentPath);
var newImport = await import( currentPath );
var object = new newImport.default();
} else {
var currentPath = this.createPath( objectData.__sourcePath );
//var object = new unParsedObjects[currentPath]();
}
return object;
}
configureObject( object, applicationPath, objectData ) {
var core = document.cores[0];
var propertyName = applicationPath.shift();
var parent = core.getObjectByPath( applicationPath );
unify.extend( object );
object.serialize( objectData );
object.propertyName = propertyName;
object.dynamic = true;
object.parent = parent;
parent[ propertyName ] = object;
}
logObject( message ) {
var className = tools.getClassNameByObject( message.data );
var type = message.type;
console.log("--------------------- recieved message: " + className + " : "+ type +"---------------------");
}
parseObject( object ) {
var core = document.cores[0];
core.executeMethods = true;
core.parse( object );
object.show();
}
setObjectID( object ) {
if( !object.id ) {
console.log("debug", this);
object.id = object.getChildren().length;
}
}
async process( message ) {
var objectData = tools.getFirstChild( message.data );
this.logObject( message );
var object = await this.createObject( objectData );
var applicationPath = message.applicationPath;
this.configureObject( object, applicationPath, objectData );
this.setObjectID( object );
this.parseObject( object );
}
}

View File

@@ -0,0 +1,84 @@
/*
Copyright (c) 2020, 2023, The Unified Company.
This code is part of Unify.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE,
as published by the Free Software Foundation.
See the GNU AFFERO GENERAL PUBLIC LICENSE, for more details.
https://unifyjs.org
*/
import processManagerAdd from "./processManager.add.js";
import processManagerUpdate from "./processManager.update.js";
import processManagerPromise from "./processManager.promise.js";
import debugManager from "../debugManager.js";
export default class processManager{
add = new processManagerAdd();
update = new processManagerUpdate();
promise = new processManagerPromise();
debugger = new debugManager();
process( content ) {
var message = JSON.parse( content.data );
switch( message.type ) {
case "promise":
this.promise.process( message );
break;
case "clientUpdate":
this.update.process( message );
break;
case "addObject":
this.add.process( message );
break;
case "debug":
console.log( "debug", message,this.mode );
//if( this.mode == "debug" ) {
this.debugger.processDebugMessage( message );
//}
break;
case "logClient":
console.log( "----------------- Log client", this.application.selector, message );
break;
default:
}
}
}

View File

@@ -0,0 +1,44 @@
/*
Copyright (c) 2020, 2023, The Unified Company.
This code is part of Unify.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE,
as published by the Free Software Foundation.
See the GNU AFFERO GENERAL PUBLIC LICENSE, for more details.
https://unifyjs.org
*/
import tools from '../../unify/tools.js';
export default class processManagerPromise{
process( message ) {
var promise = this.promiseManager.getPromiseByID( message.id );
this.promiseManager.addMessage( message );
promise.resolve();
var object = message.data;
if( object && typeof object == "object" && !Array.isArray( object ) ) {
var className = tools.getClassNameByObject( object );
if( promise.object.debug | document.debugALL ) {
console.log( "%c recieved message: ", "background: #8bc34a;", this.port, message, className );
}
}
}
}

View File

@@ -0,0 +1,170 @@
/*
Copyright (c) 2020, 2023, The Unified Company.
This code is part of Unify.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE,
as published by the Free Software Foundation.
See the GNU AFFERO GENERAL PUBLIC LICENSE, for more details.
https://unifyjs.org
*/
import unify from '../../unify/unify.js';
export default class processManagerUpdate{
process( message ) {
var object = message.data;
var className = tools.getClassNameByObject( object );
console.log("--------------------- recieved message: " + className + " : "+ message.type +"---------------------");
switch( className ) {
case "collection":
this.parseCollection( message );
break;
default:
this.parseObject( message );
}
console.log("--------------------- /recieved message: " + className + " ----------------------");
}
filter( objects ) {
var objectCollection = new collection();
objectCollection.set( this.core.objects );
objectCollection.filter( "type", "renderCollection" );
objectCollection.filter( "custom", function( object ){
var collection = object.getCollection();
if( collection.applicationPathString == applicationPathString ) {
return true;
}
});
return objectCollection.rows;
}
fetchRenderCollections( renderCollections ) {
for( var c = 0; c < renderCollections.length; c++ ) {
var renderCollection = renderCollections[c];
console.log( "renderCollection", renderCollection );
renderCollection.clear();
renderCollection.fetch();
}
}
logRenderCollection( message, objectCollection ) {
console.log( "parse collection", message );
console.log( "search renderCollection", objectCollection );
}
parseCollection( message ) {
var applicationPath = message.applicationPath;
//var objectCollection = this.core.getObjectByPath( applicationPath );
var collectionName = applicationPath[ 0 ];
var applicationPathString = applicationPath.join("/");
var renderCollections = this.filter( this.core.objects );
this.fetchRenderCollections( renderCollections );
this.logRenderCollection( message, objectCollection );
}
getObject( message ) {
var entry = tools.parseObject( message.data );
var className = tools.getClassNameByEntry( entry );
var object = tools.getObjectByEntry( entry );
unify.extend( object );
return object;
}
callMethod( application, eventName, object ) {
application[ "server" + tools.CamelCase( eventName ) ]( object );
}
filterApplication( objects, className, id ) {
var objectCollection = new collection();
objectCollection.set( objects );
objectCollection.filter( "class", className );
objectCollection.filter( "id", id );
var application = objectCollection.getFirstRow();
return application;
}
parseObject( message ) {
var object = this.getObject( message );
// Can be optimized client->core
var className = object.getClassName();
var id = object.id;
var eventName = message.eventName;
this.filterApplication( this.core.objects, className, id )
application.serialize( object );
this.callMethod( application, eventName, object );
this.logRecieveMessage( message );
}
}

View File

@@ -0,0 +1,49 @@
/*
Copyright (c) 2020, 2023, The Unified Company.
This code is part of Unify.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE,
as published by the Free Software Foundation.
See the GNU AFFERO GENERAL PUBLIC LICENSE, for more details.
https://unifyjs.org
*/
export default class progressBar{
progress = 0;
element = document.querySelector(".progressBar");
set( newProgress ) {
var difference = newProgress - this.progress;
this.progress = newProgress;
//console.log("difference", difference, newProgress);
}
setApplicationProgress( newProgress, applicationID ) {
var beforeProgress = 40;
var currentApplicationProgress = ( newProgress / document.applications.length );
var currentProgress = currentApplicationProgress * applicationID;
var progress = beforeProgress + currentProgress;
this.set( progress )
this.progress = progress;
}
}

View File

@@ -0,0 +1,98 @@
/*
Copyright (c) 2020, 2023, The Unified Company.
This code is part of Unify.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE,
as published by the Free Software Foundation.
See the GNU AFFERO GENERAL PUBLIC LICENSE, for more details.
https://unifyjs.org
*/
export default class promiseManager{
promises = new Array();
messages = new Array();
socketManager;
addPromise( promiseObject ) {
this.promises.push( promiseObject );
}
addMessage( message ) {
this.messages.push( message );
}
getPromiseByID( id ) {
var promises = this.promises;
for(var c = 0; c<promises.length; c++) {
var currentPromise = promises[c];
if( currentPromise.id == id ) {
return currentPromise;
}
}
console.error("Promise with id " + id + " not found:", this);
return false;
}
getMessageByID( id ) {
var messages = this.messages;
for(var c = 0; c<messages.length; c++) {
var message = messages[c];
if( message.id == id ) {
return message;
}
}
}
createPromiseFunction( messageID, object = false ) {
var promiseManager = this;
function promiseFunction( resolveFunction ){
var promiseObject = {};
promiseObject.id = messageID;
promiseObject.resolve = resolveFunction;
promiseObject.object = object;
promiseManager.addPromise( promiseObject );
}
return promiseFunction;
}
}

View File

@@ -0,0 +1,418 @@
export default class queryManager{
selectors = new Array();
createSelector( character, name ) {
var selector = new Object();
selector.character = character;
selector.name = name;
this.selectors.push( selector );
}
constructor() {
this.createSelector( "#", "id" )
this.createSelector( ":", "selector" )
this.createSelector( "@", "propertyName" )
}
query( query, unifyObject ) {
var terms = query.split(" ");
var objectSelection = new Array( unifyObject );
for ( var i = 0; i < terms.length; i++ ) {
var term = terms[i];
objectSelection = this.processTerm( term, objectSelection );
}
//console.log( objectSelection );
return objectSelection;
}
clone( object ) {
return JSON.parse( JSON.stringify( object ) )
}
processTerm( term, objectSelection ) {
//console.log("\n\n" )
//console.log( "process term", term );
var newSelection = new Array();
for (var j = 0; j < objectSelection.length; j++) {
var currentObjectSelection = objectSelection[j];
var selected = this.processSelector( term, currentObjectSelection );
newSelection = [...newSelection, ...selected]
}
return newSelection;
}
processSelector( term, objectSelection ) {
var allSelectors = new Array();
for ( var j = 0; j < this.selectors.length; j++ ) {
var selector = this.selectors[j];
var indices = this.getIndicesOf( selector.character, term );
for (var i = 0; i < indices.length; i++) {
var index = indices[i];
var uniuqeSelector = this.clone( selector );
uniuqeSelector.startIndex = index;
allSelectors.push( uniuqeSelector );
}
}
var sortedSelectors = allSelectors.sort( function ( a, b ) { return a.startIndex - b.startIndex } );
var firstSelector = sortedSelectors[0];
//console.log(allSelectors);
if( firstSelector ) {
var startIndex = firstSelector.startIndex;
} else {
var createFirstSelector = true;
}
if( createFirstSelector || startIndex != 0 ) {
var selector = new Object();
selector.character = "";
selector.name = "className";
selector.startIndex = 0;
sortedSelectors = this.addItemToStartOfArray( sortedSelectors, selector );
}
for (var i = 0; i < sortedSelectors.length; i++) {
var selector = sortedSelectors[i];
var nextSelector = sortedSelectors[i+1];
var currentStartIndex = selector.startIndex;
if( nextSelector ) {
var nextStartIndex = nextSelector.startIndex;
} else {
var nextStartIndex = term.length;
}
selector.term = term.substr( currentStartIndex + selector.character.length, nextStartIndex - currentStartIndex - selector.character.length );
}
var objectSelection = new Array( objectSelection );
//console.log(" process selector", term, sortedSelectors)
for ( var i = 0; i < sortedSelectors.length; i++ ) {
//console.log(" executeSelector", objectSelection);
var selector = sortedSelectors[i];
objectSelection = this.executeSelector( selector, objectSelection );
//console.log( " objectSelection", objectSelection );
}
//console.log( " objectSelection", objectSelection );
return objectSelection;
}
executeSelector( selector, ObjectSelection ) {
var name = selector.name;
switch( name ) {
case "className":
var allSelectors = new Array();
for (var i = 0; i < ObjectSelection.length; i++) {
var currentUnifyObject = ObjectSelection[i];
//console.log(currentUnifyObject);
//console.log(" currentUnifyObject.findAll( selector.term )", selector.term);
// by class name
var results = currentUnifyObject.findAll( selector.term );
allSelectors = [...allSelectors, ...results]
}
ObjectSelection = allSelectors
//console.log(" afterObjectSelection", ObjectSelection);
break;
case "propertyName":
if( selector.startIndex == 0 ) {
var allSelectors = new Array();
for (var i = 0; i < ObjectSelection.length; i++) {
var currentUnifyObject = ObjectSelection[i];
var results = currentUnifyObject.getByPropertyName( selector.term );
allSelectors = [...allSelectors, ...results]
}
ObjectSelection = allSelectors
} else {
for (var i = 0; i < ObjectSelection.length; i++) {
var currentUnifyObject = ObjectSelection[i];
//console.log("currentUnifyObject.findChildByID( selector.term )", selector.term);
if( currentUnifyObject.propertyName == selector.term ) {
return new Array( currentUnifyObject );
} else {
return new Array( );
}
// by class name
//ObjectSelection = currentUnifyObject.getChildById( selector.term );
}
}
break;
case "id":
if( selector.startIndex == 0 ) {
var allSelectors = new Array();
for (var i = 0; i < ObjectSelection.length; i++) {
var currentUnifyObject = ObjectSelection[i];
var results = currentUnifyObject.getByID( selector.term );
allSelectors = [...allSelectors, ...results]
}
ObjectSelection = allSelectors
} else {
for (var i = 0; i < ObjectSelection.length; i++) {
var currentUnifyObject = ObjectSelection[i];
//console.log("currentUnifyObject.findChildByID( selector.term )", selector.term);
if( currentUnifyObject.id == selector.term ) {
return new Array( currentUnifyObject );
} else {
return new Array( );
}
// by class name
//ObjectSelection = currentUnifyObject.getChildById( selector.term );
}
}
break;
case "selector":
var term = selector.term;
switch( term ) {
case "first-child":
//console.log("return ObjectSelection[0];", term);
if( ObjectSelection[0] ) {
return new Array( ObjectSelection[0] );
} else {
return new Array( );
}
break;
case "last-child":
//console.log("return ObjectSelection[ObjectSelection.length-1]", term);
var lastObject = ObjectSelection[ObjectSelection.length-1];
if( lastObject ) {
return new Array( lastObject );
} else {
return new Array( );
}
break;
}
break;
}
return ObjectSelection;
}
addItemToStartOfArray( array, newFirstElement ) {
return [ newFirstElement ].concat( array )
}
getIndicesOf( searchStr, str, caseSensitive ) {
var searchStrLen = searchStr.length;
if ( searchStrLen == 0 ) {
return new Array();
}
var startIndex = 0;
var index;
var indices = new Array();
if ( !caseSensitive ) {
str = str.toLowerCase();
searchStr = searchStr.toLowerCase();
}
while ( ( index = str.indexOf( searchStr, startIndex ) ) > -1 ) {
indices.push( index );
startIndex = index + searchStrLen;
}
return indices;
}
}

View File

@@ -0,0 +1,504 @@
/*
Copyright (c) 2020, 2023, The Unified Company.
This code is part of Unify.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE,
as published by the Free Software Foundation.
See the GNU AFFERO GENERAL PUBLIC LICENSE, for more details.
https://unifyjs.org
*/
import tools from '../unify/tools.js';
import defaultObject from '../unify/defaultObject.js';
import omitMethods from "../unify/omitMethodNames.js";
import unify from '../unify/unify.js';
//import cacheString from '../../assets/cache/cache.js'
var cache;
async function loadCache() {
var randomInt = Math.floor( Math.random() * 100000 );
var cacheString = await import('../../assets/cache/cache.js?random=' +randomInt );
cache = JSON.parse( cacheString.default );
}
loadCache();
export default class renderCollection{
__className = "renderCollection";
methodCache = new Array();
//create() {
// this.fetch();
//}
synced = false;
clearOnSync = true;
cache = false;
cacheLastModified = false;
useCache = false;
async updateCache() {
var randomInt = Math.floor( Math.random() * 100000 );
var cacheString = await import('../../assets/cache/cache.js?random=' +randomInt );
cache = JSON.parse( cacheString.default );
}
clearRenderCollection() {
var collection = this.getCollection();
if( collection ) {
collection.clear();
}
var children = this.getChildren();
for( var c = 0; c < children.length; c++ ) {
var child = children[ c ];
child.remove();
}
this.defaultElement.innerHTML = "";
}
async sync() {
await this.fetch();
this.getCore().createDependencyMap();
return true;
}
hasURL() {
var hasUrl = false
if( this.parent.type != "table" ) {
hasUrl = true;
}
if( this.parent.type == "renderCollection" ) {
hasUrl = false;
}
if( this.title && this.title.value == "" ) {
hasUrl = false;
}
if( !this.title ) {
hasUrl = false;
}
return hasUrl;
}
composePath() {
var urlPath = new Array();
urlPath.push( this.propertyName );
if( this.id ) {
urlPath.push( this.id );
}
if( this.title ) {
if( this.title.value == "" ) {
urlPath.push( this.propertyName.replaceAll(" ", "_") + ".html" );
} else {
urlPath.push( this.title.value.replaceAll(" ", "_") + ".html" );
}
} else {
urlPath.push( this.propertyName.replaceAll(" ", "_") + ".html" );
}
return urlPath.join("/");
}
async createUrl( pass ) {
var hasURL = this.hasURL();
if( hasURL || pass ) {
var path = this.composePath();
var state = new Object();
state.id = this.id;
state.applicationPath = this.applicationPath;
var url = window.location;
await history.pushState( state, "Unify", "/" + path );
}
}
cleanChildren( object ) {
if( this.rows ) {
this.rows = new Array();
}
if( object.getChildren ) {
var children = object.getChildren();
for (var i = 0; i < children.length; i++) {
var child = children[i];
if( child.rowID ) {
console.log("delete", child.propertyName);
delete this[ child.propertyName ];
}
this.cleanChildren( child );
}
}
}
logRenderCollection() {
if( this.debug || document.debugALL ) {
console.log( "" );
console.log("%c renderCollection::fetch", "background: #a6e22e;", this.getClassName() );
console.log( this );
}
}
async recreateCache() {
var cacheDateTime = await this.core.socketManager.get( "settings", "recreateCache", this, "recreateCache", false );
this.core.socketManager.get( "table", "get", this, "fetch", false );
}
async fetch( ) {
this.logRenderCollection();
this.rows = new Array();
if( this.core ) {
//var result = await this.core.socketManager.get( "table", "get", this, "fetch" );
if( this.useCache && !this.id ) {
var cacheDateTime = await this.core.socketManager.get( "settings", "getCacheDateTime", this, "fetch", false );
if( !this.cacheLastModified ) {
this.cacheLastModified = cacheDateTime;
}
if( this.cacheLastModified != cacheDateTime ) {
console.log("cache has been modified, reloading cache.");
await this.updateCache();
this.cacheLastModified = cacheDateTime;
} else {
console.log("Use old cache because cache has not been modified.");
}
var currentCache = cache[ this.getClassName() ];
if( currentCache ) {
this.core.socketManager.get( "table", "get", this, "fetch", false );
result = currentCache;
} else {
console.log("dont use cache, await fetch");
var result = await this.core.socketManager.get( "table", "get", this, "fetch" );
}
} else {
var result = await this.core.socketManager.get( "table", "get", this, "fetch" );
}
this.synced = true;
if( this.clearOnSync ) {
this.empty();
console.log("empty renderCollection");
this.rows = new Array();
}
await this.parseRows( result.rows );
this.getCore().communicateVisibleElements();
}
return true;
}
remapCurrentMethod( object ) {
var className = object.__className;
var methods = this.methodCache[ className ];
if( methods ){
const keys = Object.keys(methods);
for (var i = 0; i < keys.length; i++) {
var methodName = keys[i]
object[ methodName ] = this.methodCache[className][methodName];
}
}
}
remapMethods( object ) {
unify.extend( object, true );
this.remapCurrentMethod( object );
var children = object.getChildren();
for( var c = 0; c < children.length; c++ ) {
var child = children[c];
this.remapMethods( child );
}
}
deleteProperties() {
if( object.elements ) {
for (var i = 0; i < object.elements.length; i++) {
delete object.elements[i];
}
}
delete object.element;
delete object.customElement;
delete object.boxElement;
delete object.defaultElement;
delete object.user;
delete object.fileLoader;
}
copyMethods() {
var properties = Object.getOwnPropertyNames( object )
for (var j = 0; j < properties.length; j++) {
var methodName = properties[ j ]
if( typeof object[ methodName ] == "function" ) {
this.methodCache[ className ][ methodName ] = object[ methodName ];
object[ methodName ] = false;
}
}
var methods = tools.getAllFuncs( object );
for (var i = 0; i < methods.length; i++) {
methodName = methods[ i ];
this.methodCache[ className ][ methodName ] = object[ methodName ];
}
}
removeDOM( object ) {
var className = object.getClassName();
if( !this.methodCache[className] ) {
this.methodCache[ className ] = new Array();
}
this.deleteProperties();
this.copyMethods();
var children = object.getChildren();
for( var c = 0; c < children.length; c++ ) {
var child = children[c];
this.removeDOM( child );
}
}
async parseRows( rows ) {
var promises = new Array();
if( !rows || !Array.isArray(rows) ) {
console.log("rows doesnt contain an array.", rows, this);
return false;
}
for( var c = 0; c < rows.length; c++ ) {
var object = rows[ c ];
object = this.addRowSync( object, false, c );
this.rows.push( object );
}
await Promise.all( promises );
return true;
}
serializeRenderCollection( object ) {
if( object.rows && tools.isArray( object.rows ) ) {
var rows = object.rows;
var rows = new Array();
for( var c = 0; c < rows.length; c++ ) {
var object = rows[ c ];
var object = targetObject.addRow( object, false, c );
rows.push( object );
}
}
}
}

View File

@@ -0,0 +1,4 @@
import simplePathBase from "../unify/simplePath.js";

View File

@@ -0,0 +1,691 @@
/*
Copyright (c) 2020, 2023, The Unified Company.
This code is part of Unify.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE,
as published by the Free Software Foundation.
See the GNU AFFERO GENERAL PUBLIC LICENSE, for more details.
https://unifyjs.org
*/
import tools from '../unify/tools.js';
import socketMessage from '../unify/socketMessage.js';
import promiseManager from './promiseManager.js';
import collection from './collection.js';
//import debugManager from './debugManager.js';
import unify from '../unify/unify.js';
import defaultObject from '../unify/defaultObject.js';
//import unParsedObjects from './unparsed.js'
import processManager from "./processManager/processManager.js"
import ajaxSocket from './ajaxSocket.js'
document.requests = new Array();
export default class socketManager{
promiseManager = new promiseManager();
//debugger = new debugManager();
processManager = new processManager();
socket = false;
mode = "client";
state = "disconnected";
serverAddress = "localhost";
messageID = 0;
tries = 0;
port = 5002;
ssl = false;
promises = new Array();
constructor( port ) {
this.promiseManager.socketManager = this;
this.processManager.promise.promiseManager = this.promiseManager;
//this.debugger.socketManager = this;
document.socketManager = this;
if( port ) {
this.port = port;
}
}
getSocketAddress() {
if( !this.ssl ) {
console.log( "%c Trying to connect with server on host: ws://" + this.serverAddress + ":" + this.port, "background: yellow;" );
var socketAddress = "ws://" + this.serverAddress + ":" + this.port;
} else {
console.log( "%c Ssl set to true, Tying to create Secure connection with server on host: wss://" + this.serverAddress.split(":")[0], "background: yellow;" );
var socketAddress = "wss://" + this.serverAddress.split(":")[0] + ":" + this.port ;// + ":" + this.port
}
return socketAddress;
}
createSocket() {
var socketManager = this;
var socketAddress = this.getSocketAddress()
this.socket = new WebSocket( socketAddress );
var promiseManager = this.promiseManager;
this.socket.onclose = function(){ socketManager.onClose() };
this.socket.onopen = function(){ socketManager.onOpen() };
}
pingServer() {
var message = new socketMessage();
message.controller = "ping";
this.socket.send( JSON.stringify( message ) );
var that = this;
setTimeout( function(){ that.pingServer() }, 5000 );
}
async connect() {
var promiseManager = this.promiseManager;
promiseManager.promises = new Array();
promiseManager.messages = new Array();
this.messageID = 0;
this.createSocket();
var promiseFunction = promiseManager.createPromiseFunction( this.messageID );
var promise = new Promise( promiseFunction );
await promise;
var message = promiseManager.getMessageByID( this.messageID );
this.logRecieveMessage( message );
this.messageID++;
this.pingServer();
return message.applications;
}
logRecieveMessage( message ) {
//console.log( "Client recieved message via socket: ", message );
var className = tools.getClassNameByObject( message );
if( document.debugALL ) {
console.log("");
console.log( "%c recieved message: ", "background: #8bc34a;" );
console.log( "className: ", className);
console.log( message );
console.log("");
}
}
onOpen() {
console.log("%c Connected to Socket server", "background: green;");
this.state = "connected";
this.registerClientType( this.mode );
this.createEventListeners();
}
logAjaxConnection( data ) {
console.log( "first message recieved", data );
console.log( "sessionKey", this.sessionKey );
}
async registerClient( sessionKey ) {
var promiseManager = this.promiseManager;
var promiseFunction = promiseManager.createPromiseFunction( this.messageID );
var promise = new Promise( promiseFunction );
var message = new socketMessage();
message.id = this.messageID;
if( this.sessionKey ) {
message.type = "reconnectClient";
message.object = this.sessionKey;
} else {
message.type = "registerClient";
message.object = "none";
}
console.log("message", message);
this.socket.send( JSON.stringify( message ) );
console.log("awaiting promise");
await promise;
var message = promiseManager.getMessageByID( this.messageID );
this.messageID++
console.log("promise recieved", message);
}
disconnect() {
this.socket.close();
}
async addClient() {
var promiseManager = this.promiseManager;
this.messageID++;
var messageID = this.messageID;
var data = await this.registerClient( );
var message = promiseManager.getMessageByID( messageID );
this.sessionKey = message.data.sessionKey;
return message;
}
createAjaxSocketClass() {
var that = this;
return class ajaxSocket{
async send( message ) {
var json = JSON.parse( message );
json.sessionKey = new String( that.sessionKey );
message = JSON.stringify( json );
var result = await that.fetch( message );
var a = new Object();
a.data = result;
that.message( a )
}
}
}
async connectAjax() {
var message = new Object();
message.eventName = "connect";
var data = await this.fetch( JSON.stringify( message ) );
this.sessionKey = new String( JSON.parse( data ).sessionKey );
this.logAjaxConnection( data );
//this.socket = new ajaxSocket();
this.socket = this.createAjaxSocketClass();
this.registerClientType( this.mode );
}
async fetch( jsonString ) {
const response = await fetch(
"/api/",
{
body: jsonString,
method:'post',
headers:{
"Accept": "application/json, text/plain, */*",
"Content-type": "application/json; charset = UTF-8"
},
}
);
return response.json();
}
onClose() {
this.state = "disconnected";
this.tries++;
this.reconnect();
this.retry();
}
retry() {
// Ajax fallback
// todo disabled because android requires reconnection
/*
if( this.tries < 1 ) {
this.reconnect();
} else {
console.log("connect ajax");
var message = this.connectAjax();
//this.message( content );
}
*/
}
async reconnect() {
await this.connect();
this.registerClient( this.sessionKey );
}
createEventListeners() {
var socketManager = this;
this.socket.onmessage = function( content ) { socketManager.message( content ) }
}
registerClientType( type ) {
this.mode = type;
var message = new socketMessage();
message.controller = "settings";
message.method = "setType";
message.path = new Array();
message.object = type;
this.socket.send( JSON.stringify( message ) );
}
signin( user ) {
var message = new socketMessage();
message.controller = "settings";
message.method = "signIn";
message.object = user;
this.socket.send( JSON.stringify( message ) );
}
async signOut() {
var message = new socketMessage();
message.controller = "settings";
message.method = "signOut";
this.get( "settings", "signOut", new Object() );
}
message( content ) {
this.processManager.process( content );
}
createMessage( messageID, controller, method, eventName, object, data ) {
var message = new socketMessage();
message.id = messageID;
message.controller = controller;
message.method = method;
message.parse = object.parse;
message.data = data;
message.eventName = eventName;
if( object.getClassName ) {
message.object = object.clean( method )[ object.getClassName() ];
if( object.nodeMethodArguments && method == "callNodeMethod" ) {
message.object.nodeMethodName = tools.validateValue( object.nodeMethodName );
message.object.nodeMethodArguments = tools.validateValue( object.nodeMethodArguments );
}
message.applicationPath = tools.getApplicationPath( object );
} else {
message.object = object;
}
if( typeof object == "string" ) {
message.object = object;
}
return message;
}
createPromise( promiseFunction ) {
var promise = new Promise( promiseFunction )
document.promises.push( promise );
return promise;
}
async get( controller, method, object, eventName, data ) {
var messageID = ++this.messageID;
var promiseFunction = this.promiseManager.createPromiseFunction( messageID, object );
var message = this.createMessage( messageID, controller, method, eventName, object, data );
this.logSendMessage( message, object );
console.log("send raw message", JSON.stringify( message ));
if( document.requestsObject ) {
document.requestsObject.addRequest(controller, method, object, eventName, message);
} else {
document.requests.push({ controller, method, object, eventName, message });
}
this.socket.send( JSON.stringify( message ) );
var promise = this.createPromise( promiseFunction );
await promise;
return this.processMessage( method, messageID );
}
async getRaw( message ) {
var messageID = ++this.messageID;
var promiseFunction = this.promiseManager.createPromiseFunction( messageID );
console.log( "" );
console.log("messageID", messageID)
console.log( "%c send message: ", "background: #11db33;", message );
console.log( "" );
message.id = messageID;
this.socket.send( JSON.stringify( message ) );
var promise = this.createPromise( promiseFunction );
await promise;
console.log("promise fulfilled");
var data = this.promiseManager.getMessageByID( messageID );
return JSON.stringify( data, null, 4 );
}
processMessage( method, messageID ) {
var data = this.promiseManager.getMessageByID( messageID ).data;
switch( method ) {
case "count":
if( !tools.getFirstChild( data ) ) {
return 0;
}
return tools.getFirstChild( data ).count;
break;
default:
if( Object.prototype.toString.call( data ) === '[object Array]' ) {
return data;
}
if( typeof data == "object" ) {
return tools.getFirstChild( data );
} else {
return data;
}
}
}
logInjection( message ) {
var path = message.applicationPath.join("/");
console.log( "socketMessage", message.id );
console.log( "" );
console.log( "%c send message: ", "background: #eb2666;", path, message );
console.log( "" );
}
handleInjection( messageID, data ) {
var data = this.promiseManager.getMessageByID( messageID ).data;
switch( method ) {
case "count":
return tools.getFirstChild( data ).count;
break;
default:
return tools.getFirstChild( data );
}
}
async inject( message ) {
var promiseFunction = this.promiseManager.createPromiseFunction( message.id );
var messageID = message.id;
var method = message.method;
this.logInjection( message );
this.socket.send( JSON.stringify( message ) );
await new Promise( promiseFunction );
return this.handleInjection( messageID, data );
}
logSendMessage( message, object ) {
var path = "";
if( message.applicationPath ) {
path = message.applicationPath.join("/");
}
if( ( object.getClassName && object.debug ) || document.debugALL ) {
console.log( "" );
console.log( "%c send message: ", "background: #11db33;", path, message );
//console.log( object.getClassName() );
//console.log( path );
//console.log( message );
console.log( "" );
}
}
async update( eventName, object ) {
var result = await this.get( "column", "update", object, eventName );
}
}

View File

@@ -0,0 +1,154 @@
class stateEvent{
object;
method;
args;
}
class state{
events = new Array();
registerEvent( object, method, args ) {
var event = new stateEvent();
event.object = object;
event.method = method;
event.args = args;
this.events.push( event );
}
async triggerEvents() {
var events = this.events;
for ( var i = 0; i < events.length; i++ ) {
var event = events[ i ];
var object = event.object;
var method = event.method;
var args = event.args;
object["__" + method]( args[0], args[1], args[2], args[3], args[4] );
//object[ method ]()
}
}
}
export default class stateMachine{
states = new Array();
currentState;
stateID = 0;
constructor() {
var state = this.createState();
//history.pushState( { id: state.id }, "Unify" );
}
createState() {
var newState = new state();
newState.id = this.stateID++;
this.states.push( newState );
this.currentState = newState;
return newState;
}
registerEvent( object, method, args ) {
var state = this.currentState;
state.registerEvent( object, method, args )
//console.log( "event registered in stateMachine", this );
}
async composeState( ...args ) {
this.createState();
var state = this.currentState;
if( args.length == 0 ) {
history.pushState( { id: state.id }, "Unify" );
} else if( args.length == 1 ) {
var title = args.pop().replaceAll( " ", "_" );
//if( !title ) {
history.pushState( { id: state.id }, "localhost", title + "/" );
//} else {
// history.pushState( { id: state.id }, "Unify", "/" + title + ".html" );
//}
} else {
var title = args.pop();
title = title.toString().replaceAll( " ", "_" )
if(title == "") {
title = "page"
}
history.pushState( { id: state.id }, "Unify", "/" + args.join("/") + "/" + title + ".html" );
}
}
generateUrl( ...args ) {
var title = args.pop().replaceAll( " ", "_" );
return "https://unifyjs.org" + "/" + args.join("/") + "/" + title + ".html";
}
getState( id ) {
return this.states[ id ];
}
}

427
framework/client/table.js Normal file
View File

@@ -0,0 +1,427 @@
/*
Copyright (c) 2020, 2023, The Unified Company.
This code is part of Unify.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE,
as published by the Free Software Foundation.
See the GNU AFFERO GENERAL PUBLIC LICENSE, for more details.
https://unifyjs.org
*/
import tools from "../unify/tools.js";
export default class table{
__className = "table";
type = "table";
id = 0;
collection = false;
collections = new Array();
load = true;
synced = false;
useCustomElement = false;
useCache = false;
createOnSync = true;
deleteProperty( child ) {
if( child.rowID ) {
delete this[ child.propertyName ];
}
}
cleanChildren( object ) {
if( object.getChildren ) {
var children = object.getChildren();
for (var i = 0; i < children.length; i++) {
var child = children[i];
if( child.rows ) {
child.rows = new Array();
}
this.deleteProperty( child );
this.cleanChildren( child );
}
}
}
destroyEventListener( object ) {
if( object.render ) {
// this could be enabled to destory the render functions still running.
// But this causes problems when loading a new page, and then
// loading the old one again, The render method is not called.
if( object.autoDestroyRenderLoop ) {
window.cancelAnimationFrame( object.requestAnimationFrameID );
}
}
if( object.destroy ) {
object.destroy();
}
}
destroyEventListeners( element ) {
if( element.object ) {
var object = element.object;
this.destroyEventListener( object );
}
var children = element.childNodes;
for (var i = 0; i < children.length; i++) {
var child = children[i];
this.destroyEventListeners(child);
}
}
logSync() {
if( this.debug | document.debugALL ) {
console.log( "" );
console.log("%ctable::sync", "background: #5dc2d6;" );
console.log( "className: ", this.getClassName() );
console.log( "Path: ", this.applicationPathString );
console.log( this );
}
}
async loadObject( sign ) {
if( this.load ) {
//this.cleanChildren( this );
//this.destroyEventListeners( this.element );
if( !this.id ) {
await this.createObject( sign );
} else {
await this.updateObject();
}
}
}
scrollPage( show ) {
if( show ) {
this.show();
if( this.element ) {
this.element.scrollTo( 0, 0 );
}
if( this.boxElement ) {
this.boxElement.scrollTo( 0, 0 );
}
}
}
hasURL() {
var hasUrl = false
if( this.parent.type != "table" ) {
hasUrl = true;
}
if( this.parent.type == "renderCollection" ) {
hasUrl = false;
}
if( this.title && this.title.value == "" ) {
hasUrl = false;
}
if( !this.title ) {
hasUrl = false;
}
return hasUrl;
}
composePath() {
var urlPath = new Array();
urlPath.push( this.propertyName );
if( this.id ) {
urlPath.push( this.id );
}
if( this.title ) {
if( this.title.value == "" ) {
urlPath.push( this.propertyName.replaceAll(" ", "_") + ".html" );
} else {
urlPath.push( this.title.value.replaceAll(" ", "_") + ".html" );
}
} else {
urlPath.push( this.propertyName.replaceAll(" ", "_") + ".html" );
}
return urlPath.join("/");
}
async createUrl( pass ) {
var hasURL = this.hasURL();
if( hasURL || pass ) {
var path = this.composePath();
var state = new Object();
state.id = this.id;
state.applicationPath = this.applicationPath;
state.table = this;
document.states.push( state );
var url = window.location;
await history.pushState( { id: document.states.length-1 }, "Unify", "/" + path );
}
}
async sync( sign = false, show = true, createUrl = true ) {
var sign = true;
this.setApplicationPath();
this.logSync();
await this.loadObject( sign );
if( createUrl ) {
//this.createUrl();
}
this.scrollPage( show );
this.getCore().communicateVisibleElements();
return true;
}
async createObject( sign ) {
if( sign ) {
var table = await this.socketManager.get( "table", "create", this, "sign" );
} else {
var table = await this.socketManager.get( "table", "create", this );
}
this.setID( table.id );
this.updatePermissions( table.permissions );
return true;
}
async getObject() {
if( this.useCache ) {
var object = document.cacheManager.getLocalObject( this, this.id, tools.getTableName( this ) );
} else {
var object = false;
}
if( !object ) {
var object = await this.socketManager.get( "table", "get", this );
//document.cacheManager.addObject( object, this.id, tools.getTableName( this ) );
}
return object;
}
updateChildrenPermissionsClient( object ) {
if( object.permissions && object.updatePermissions ) {
object.updatePermissions( object.permissions );
}
if( object.getChildren ) {
var children = object.getChildren();
for (var i = 0; i < children.length; i++) {
var child = children[i]
console.log( "updateChildrenPermissions", child.propertyName);
this.updateChildrenPermissionsClient( child );
}
}
}
async prepareObject( object ) {
this.setID( object.id );
this.serialize( object );
console.log("after serialize", this);
//this.updatePermissions( object.permissions );
this.updateChildrenPermissionsClient( this );
await this.setupChildren();
if( this.create && this.createOnSync ) {
await this.create();
}
}
async updateObject() {
var object = await this.getObject();
await this.prepareObject( object );
this.getCore().appendAllToSelector();
return true;
}
async setupChildren() {
var children = this.getChildren();
for( var c = 0; c < children.length; c++ ) {
var child = children[c];
if( child.setup ) {
await child.setup();
}
}
}
}

View File

@@ -0,0 +1,217 @@
/*
Copyright (c) 2020, 2023, The Unified Company.
This code is part of Unify.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE,
as published by the Free Software Foundation.
See the GNU AFFERO GENERAL PUBLIC LICENSE, for more details.
https://unifyjs.org
*/
import defaultObject from '../unify/defaultObject.js';
import tools from '../unify/tools.js';
import core from './core.js';
import themeImports from './imports/themeImports.js';
export default class themeLoader{
defaultObject = new defaultObject();
prepareThemeCore( themeCore, socketManager, os, device, tint ) {
themeCore.addDOMToSelector = false;
themeCore.parseEvents = false;
themeCore.executeMethods = false;
themeCore.initializeRenderLoop = false;
themeCore.socketManager = socketManager;
themeCore.os = os;
themeCore.device = device;
themeCore.tint = tint;
if( os == this.os && device == this.device && tint == this.tint ) {
themeCore.createStyleSheet = false;
}
}
async loadCustomThemes( os, device, tint ) {
var customThemes = new Array();
var applications = this.applicationManager.applications;
for( var applicationID = 0; applicationID < applications.length; applicationID++ ) {
var applicationFile = applications[ applicationID ];
//console.log(applicationFile.path, applicationID, os, device, tint);
customThemes[ applicationID ] = await this.loadCustomTheme( applicationFile.path, applicationID, os, device, tint );
}
return customThemes;
}
async createObject( applicationPath ) {
if( document.mode == "production" ) {
var importObject = themeImports[ applicationPath ];
return new importObject();
} else {
var importObject = await import( "/" + applicationPath );
return new importObject.default();
}
}
createApplicationPath( path, os, device, tint ) {
device = tools.CamelCase( device );
os = tools.CamelCase( os );
tint = tools.CamelCase( tint );
var applicationPath = 'framework/cache/platforms/' + os + '/' + device + '/' + tint + '/' + path + '/application.js';
return applicationPath;
}
async loadCustomTheme( path, applicationID, os, device, tint ) {
//console.log(path, applicationID, os, device, tint);
var applicationPath = this.createApplicationPath( path, os, device, tint );
//console.log( "load custom theme from url", applicationPath );
return await this.createObject( applicationPath );
}
setThemeObjects( themeCore, os, device, tint ) {
var applicationManager = this.applicationManager;
if( !applicationManager.themeObjects ) {
applicationManager.themeObjects = new Array();
}
if( !applicationManager.themeObjects[os] ) {
applicationManager.themeObjects[os] = new Array();
}
if( !applicationManager.themeObjects[os][device] ) {
applicationManager.themeObjects[os][device] = new Array();
}
applicationManager.themeObjects[os][device][tint] = themeCore.classObjects;
}
async setupApplication( unifyCore, themeCore, application ) {
this.defaultObject.agregateDefaultObject( application );
this.applicationManager.getDomElement( application )
themeCore.setTheme();
application.core = themeCore;
await unifyCore.prepareObjects( application );
themeCore.parse( application, true );
themeCore.callAfterLoad( application );
}
async parseTheme( unifyCore, os, device, tint ) {
var themeApplications = await this.loadCustomThemes( os, device, tint );
var themeCore = new core();
var application = themeApplications[0];
this.prepareThemeCore( themeCore, unifyCore.socketManager, os, device, tint );
await this.setupApplication( unifyCore, themeCore, application );
console.log("setThemeObjects", themeCore, os, device, tint);
this.setThemeObjects( themeCore, os, device, tint )
}
async loadThemes( application, applicationID, core ) {
if( application.loadThemes && applicationID == 0 ) {
var osList = new Array("Windows", "Macos", "Android");
var deviceList = new Array("Pc");
var tintList = new Array("Light", "Dark");
for ( var i = 0; i < osList.length; i++ ) {
var os = osList[i];
for ( var j = 0; j < deviceList.length; j++ ) {
var device = deviceList[j];
for ( var k = 0; k < tintList.length; k++ ) {
var tint = tintList[k];
await this.parseTheme( core, os, device, tint );
}
}
}
}
}
}

View File

@@ -0,0 +1,389 @@
/*
Copyright (c) 2020, 2023, The Unified Company.
This code is part of Unify.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE,
as published by the Free Software Foundation.
See the GNU AFFERO GENERAL PUBLIC LICENSE, for more details.
https://unifyjs.org
*/
import omitMethods from "../unify/omitMethodNames.js";
import tools from '../unify/tools.js';
import definitions from '../unify/definitions.js';
export default class themeSwitcher{
setCore( core ) {
this.core = core;
}
communicateTheme( os, device, tint ) {
var themeProfile = new Object();
themeProfile.os = os;
themeProfile.device = device;
themeProfile.tint = tint;
this.core.socketManager.get( "settings", "setTheme", JSON.stringify( themeProfile ) );
}
parseObject( object ) {
if( !object.parent ) {
if( object.device ) {
object.__os = object.os;
object.__tint = object.tint;
object.__device = object.device;
this.createSetters( object );
}
}
}
updateClassName( oldValue, newValue ) {
var elements = document.querySelectorAll( "." + oldValue )
for (var i = 0; i < elements.length; i++) {
var element = elements[i];
//var display = element.style.display;
//element.setAttribute('style', '');
//element.style.display = display;
element.classList.remove( oldValue );
element.classList.add( newValue );
}
}
delayUpdateThemeProperties() {
var that = this;
setTimeout(function() {
that.updateThemeProperties();
}, 1000 );
}
updateCoreOS( newValue ) {
var core = this.core;
core.os = newValue;
core.setTheme();
core.os = newValue;
}
osSetter( newValue, object ) {
var core = this.core;
var oldValue = object.__os;
object.__os = newValue;
this.updateCoreOS( newValue );
this.updateClassName( oldValue, newValue )
core.callAfterLoad( object.getRoot() );
this.delayUpdateThemeProperties( themeSwitcher );
core.communicateTheme( object.__os, object.__device, object.__tint );
console.log( "this is the setter of os, changed value from", oldValue, "to", newValue );
}
createOSSetter( object ) {
var themeSwitcher = this;
object.__defineSetter__( "os", function( value ) { themeSwitcher.osSetter( value, object ); });
}
createOSGetter( object ) {
object.__defineGetter__( "os", function( value ){
return object.__os;
});
}
updateCoreTint( newValue ) {
var core = this.core;
core.tint = newValue;
core.setTheme();
core.tint = newValue;
}
tintSetter( newValue, object ){
var core = this.core;
var oldValue = object.__tint;
object.__tint = newValue;
this.updateCoreTint( newValue );
this.updateClassName( oldValue, newValue );
document.config.tint = newValue;
this.delayUpdateThemeProperties();
core.communicateTheme( object.__os, object.__device, object.__tint );
}
createTintSetter( object ) {
var themeSwitcher = this;
object.__defineSetter__( "tint", function( value ){ themeSwitcher.tintSetter( value, object ); } );
}
createTintGetter( object ) {
object.__defineGetter__( "tint", function( value ){
return object.__tint;
});
}
createSetters( object ) {
this.createOSSetter( object );
this.createOSGetter( object );
this.createTintSetter( object );
this.createTintGetter( object );
}
updateMethodA( object, themeObject ) {
var properties = Object.getOwnPropertyNames( object )
for (var j = 0; j < properties.length; j++) {
var methodName = properties[j]
if( !omitMethods.includes( methodName ) ){
if( themeObject[ methodName ] && typeof themeObject[ methodName ] == "function" ) {
// todo this destroys the all events
//object[ methodName ] = themeObject[methodName];
}
}
}
}
updateMethodB( object, themeObject ) {
Object.getOwnPropertyNames( Object.getPrototypeOf( object ) ).forEach( methodName => {
if( !omitMethods.includes(methodName) ){
if( themeObject[methodName] && typeof themeObject[methodName] == "function" ) {
// todo this destroys the all events
//object[methodName] = themeObject[methodName];
}
}
});
}
updateMethods( object, themeObject ) {
this.updateMethodA( object, themeObject );
this.updateMethodB( object, themeObject );
}
updateRenderCollection( object, themeObject ) {
if( object.type == "renderCollection" ) {
if( object.object ) {
object.object = themeObject.object;
}
}
}
updateProperty( object, themeObject, name ) {
var objectString = object["__" + name ];
var themeString = themeObject[ name ];
if( themeString != objectString ) {
var css = this.core.css;
var cssPropertyName = css.normalizePropertyName( name );
var normalizedProperty = css.normalizeProperty( cssPropertyName );
var isCSS = css.propertyIsStyle( normalizedProperty );
if( !isCSS && !definitions.invalid.includes( name ) ) {
object[name] = themeObject[name];
}
//object[name] = themeObject[name];
}
}
updateCustomProperties( object, themeObject ) {
var properties = themeObject.getProperties();
for (var j = 0; j < properties.length; j++) {
var name = properties[j].name;
var value = properties[j].value;
if( typeof value == "string" ) {
if( !definitions.invalid.includes( name ) ) {
this.updateProperty( object, themeObject, name );
}
}
}
}
getThemeObject( themeObjects, className ) {
var themeByClass = themeObjects[ className ];
themeByClass = themeByClass.filter( n => n );
var themeObject = themeByClass[ 0 ];
return themeObject;
}
updateObject( object, className, themeObjects ) {
var themeObject = this.getThemeObject( themeObjects, className );
if( themeObject ){
this.updateMethods( object, themeObject );
}
this.updateRenderCollection( object, themeObject );
if( themeObject ) {
this.updateCustomProperties( object, themeObject );
}
}
updateThemeProperties() {
var themeObjects = document.themeObjects[ this.core.os ][ this.core.device ][ this.core.tint ];
console.log("themeObjects", themeObjects);
for ( var i = 0; i < this.core.objects.length; i++ ) {
var object = this.core.objects[i];
var className = object.getClassName();
if( themeObjects[ className ] ) {
this.updateObject( object, className, themeObjects );
}
}
}
}

54
framework/client/timer.js Normal file
View File

@@ -0,0 +1,54 @@
/*
Copyright (c) 2020, 2023, The Unified Company.
This code is part of Unify.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE,
as published by the Free Software Foundation.
See the GNU AFFERO GENERAL PUBLIC LICENSE, for more details.
https://unifyjs.org
*/
export default class timer{
timings = new Array();
initialising = true;
lap( name ) {
var timing = new Object();
timing.time = new Date().getTime();
timing.name = name;
if( this.timings.length > 0 ) {
var previouseTiming = this.timings[this.timings.length - 1].time;
var timeBetweenPrev = ( timing.time - previouseTiming ) / 1000 ;
var firstTiming = this.timings[0].time;
var timeSinceFirst = ( timing.time - firstTiming ) / 1000 ;
//console.log("TimeBetween", timeBetweenPrev);
console.log("Time: ", timeSinceFirst, name);
}
this.timings.push( timing );
//console.log("TimeBetween", this.timings);
}
}

View File

@@ -0,0 +1 @@
export default {};

View File

@@ -0,0 +1,61 @@
//import applications from '../configs/applications.js';
import core from './core.js';
//import applicationImports from './imports.js';
console.log("spawned webworker");
console.log(core);
postMessage("webworker");
/*
class main{
applicationInstances = new Array();
async createApplicationInstances() {
for( var applicationID = 0; applicationID < applications.length; applicationID++ ) {
var applicationFile = applications[ applicationID ];
this.applicationInstances[ applicationID ] = await this.getApplication( applicationFile.path, applicationID );
}
}
async getApplication( path, applicationID ) {
var currentBundle = applicationImports[ applicationID ];
if( currentBundle ) {
this.application = new currentBundle();
}
return this.application;
}
application() {
this.createApplicationInstances();
//console.log(this.applicationInstances);
postMessage("webworker");
}
}
var treadWorker = new main();
treadWorker.application();
*/

View File

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,2 @@
var a = {"mode":"development","serverAddress":"localhost","ssl":false,"socketPort":5000,"port":3000,"maxClusters":1,"os":"Windows","device":"Pc","tint":"Dark","syncClientID":0,"loadThemes":true};
export default a;

View File

@@ -0,0 +1 @@
{"mode":"development","serverAddress":"localhost","ssl":false,"socketPort":5000,"port":3000,"maxClusters":1,"os":"Windows","device":"Pc","tint":"Dark","syncClientID":0,"loadThemes":true}

View File

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1 @@
0481

7
framework/node_modules/Dependencies generated vendored Normal file
View File

@@ -0,0 +1,7 @@
# Unify Dependencies
🗸 https://sourceforge.net/projects/better-sqlite3.mirror/
🗸 https://sourceforge.net/projects/uwebsockets-js.mirror/
🗸 https://sourceforge.net/projects/esbuild.mirror/

5
framework/node_modules/better-sqlite3/.gitattributes generated vendored Normal file
View File

@@ -0,0 +1,5 @@
*.lzz linguist-language=C++
*.cpp -diff
*.hpp -diff
*.c -diff
*.h -diff

21
framework/node_modules/better-sqlite3/LICENSE generated vendored Normal file
View File

@@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2017 Joshua Wise
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

Binary file not shown.

25
framework/node_modules/better-sqlite3/getBinary.js generated vendored Normal file
View File

@@ -0,0 +1,25 @@
var platform = process.platform;
var version = process.versions.modules;
var architecture = process.arch;
var betterSqliteVersion = "8.1.0";
console.log( platform );
console.log( version );
console.log( architecture );
var filename = "better-sqlite3-v"+ betterSqliteVersion +"-node-v" + version + "-" + platform + "-" + architecture + ".tar.gz";
console.log(filename);
//better-sqlite3-v8.1.0-node-v108-linux-x64.tar.gz
//better-sqlite3-v8.1.0-node-v108-linux-x64.tar.gz

100
framework/node_modules/better-sqlite3/lib/database.js generated vendored Normal file
View File

@@ -0,0 +1,100 @@
'use strict';
const fs = require('fs');
const path = require('path');
const util = require('./util');
const SqliteError = require('./sqlite-error');
let DEFAULT_ADDON;
function Database(filenameGiven, options) {
if (new.target == null) {
return new Database(filenameGiven, options);
}
// Apply defaults
let buffer;
if (Buffer.isBuffer(filenameGiven)) {
buffer = filenameGiven;
filenameGiven = ':memory:';
}
if (filenameGiven == null) filenameGiven = '';
if (options == null) options = {};
// Validate arguments
if (typeof filenameGiven !== 'string') throw new TypeError('Expected first argument to be a string');
if (typeof options !== 'object') throw new TypeError('Expected second argument to be an options object');
if ('readOnly' in options) throw new TypeError('Misspelled option "readOnly" should be "readonly"');
if ('memory' in options) throw new TypeError('Option "memory" was removed in v7.0.0 (use ":memory:" filename instead)');
// Interpret options
const filename = filenameGiven.trim();
const anonymous = filename === '' || filename === ':memory:';
const readonly = util.getBooleanOption(options, 'readonly');
const fileMustExist = util.getBooleanOption(options, 'fileMustExist');
const timeout = 'timeout' in options ? options.timeout : 5000;
const verbose = 'verbose' in options ? options.verbose : null;
const nativeBindingPath = 'nativeBinding' in options ? options.nativeBinding : null;
// Validate interpreted options
if (readonly && anonymous && !buffer) throw new TypeError('In-memory/temporary databases cannot be readonly');
if (!Number.isInteger(timeout) || timeout < 0) throw new TypeError('Expected the "timeout" option to be a positive integer');
if (timeout > 0x7fffffff) throw new RangeError('Option "timeout" cannot be greater than 2147483647');
if (verbose != null && typeof verbose !== 'function') throw new TypeError('Expected the "verbose" option to be a function');
if (nativeBindingPath != null && typeof nativeBindingPath !== 'string') throw new TypeError('Expected the "nativeBinding" option to be a string');
// Load the native addon
let addon;
if ( nativeBindingPath == null ) {
//console.log("loading Better_sqlite3.node")
var platform = process.platform;
var version = process.versions.modules;
var architecture = process.arch;
var betterSqliteVersion = "8.1.0";
var folderName = "better-sqlite3-v"+ betterSqliteVersion +"-node-v" + version + "-" + platform + "-" + architecture;
addon = DEFAULT_ADDON || (DEFAULT_ADDON = require('../binaries/'+ folderName + "/Release/better_sqlite3.node"));
} else {
addon = require(path.resolve(nativeBindingPath).replace(/(\.node)?$/, '.node'));
}
if (!addon.isInitialized) {
addon.setErrorConstructor(SqliteError);
addon.isInitialized = true;
}
// Make sure the specified directory exists
if (!anonymous && !fs.existsSync(path.dirname(filename))) {
throw new TypeError('Cannot open database because the directory does not exist');
}
Object.defineProperties(this, {
[util.cppdb]: { value: new addon.Database(filename, filenameGiven, anonymous, readonly, fileMustExist, timeout, verbose || null, buffer || null) },
...wrappers.getters,
});
}
const wrappers = require('./methods/wrappers');
Database.prototype.prepare = wrappers.prepare;
Database.prototype.transaction = require('./methods/transaction');
Database.prototype.pragma = require('./methods/pragma');
Database.prototype.backup = require('./methods/backup');
Database.prototype.serialize = require('./methods/serialize');
Database.prototype.function = require('./methods/function');
Database.prototype.aggregate = require('./methods/aggregate');
Database.prototype.table = require('./methods/table');
Database.prototype.loadExtension = wrappers.loadExtension;
Database.prototype.exec = wrappers.exec;
Database.prototype.close = wrappers.close;
Database.prototype.defaultSafeIntegers = wrappers.defaultSafeIntegers;
Database.prototype.unsafeMode = wrappers.unsafeMode;
Database.prototype[util.inspect] = require('./methods/inspect');
module.exports = Database;

3
framework/node_modules/better-sqlite3/lib/index.js generated vendored Normal file
View File

@@ -0,0 +1,3 @@
'use strict';
module.exports = require('./database');
module.exports.SqliteError = require('./sqlite-error');

View File

@@ -0,0 +1,43 @@
'use strict';
const { getBooleanOption, cppdb } = require('../util');
module.exports = function defineAggregate(name, options) {
// Validate arguments
if (typeof name !== 'string') throw new TypeError('Expected first argument to be a string');
if (typeof options !== 'object' || options === null) throw new TypeError('Expected second argument to be an options object');
if (!name) throw new TypeError('User-defined function name cannot be an empty string');
// Interpret options
const start = 'start' in options ? options.start : null;
const step = getFunctionOption(options, 'step', true);
const inverse = getFunctionOption(options, 'inverse', false);
const result = getFunctionOption(options, 'result', false);
const safeIntegers = 'safeIntegers' in options ? +getBooleanOption(options, 'safeIntegers') : 2;
const deterministic = getBooleanOption(options, 'deterministic');
const directOnly = getBooleanOption(options, 'directOnly');
const varargs = getBooleanOption(options, 'varargs');
let argCount = -1;
// Determine argument count
if (!varargs) {
argCount = Math.max(getLength(step), inverse ? getLength(inverse) : 0);
if (argCount > 0) argCount -= 1;
if (argCount > 100) throw new RangeError('User-defined functions cannot have more than 100 arguments');
}
this[cppdb].aggregate(start, step, inverse, result, name, argCount, safeIntegers, deterministic, directOnly);
return this;
};
const getFunctionOption = (options, key, required) => {
const value = key in options ? options[key] : null;
if (typeof value === 'function') return value;
if (value != null) throw new TypeError(`Expected the "${key}" option to be a function`);
if (required) throw new TypeError(`Missing required option "${key}"`);
return null;
};
const getLength = ({ length }) => {
if (Number.isInteger(length) && length >= 0) return length;
throw new TypeError('Expected function.length to be a positive integer');
};

View File

@@ -0,0 +1,67 @@
'use strict';
const fs = require('fs');
const path = require('path');
const { promisify } = require('util');
const { cppdb } = require('../util');
const fsAccess = promisify(fs.access);
module.exports = async function backup(filename, options) {
if (options == null) options = {};
// Validate arguments
if (typeof filename !== 'string') throw new TypeError('Expected first argument to be a string');
if (typeof options !== 'object') throw new TypeError('Expected second argument to be an options object');
// Interpret options
filename = filename.trim();
const attachedName = 'attached' in options ? options.attached : 'main';
const handler = 'progress' in options ? options.progress : null;
// Validate interpreted options
if (!filename) throw new TypeError('Backup filename cannot be an empty string');
if (filename === ':memory:') throw new TypeError('Invalid backup filename ":memory:"');
if (typeof attachedName !== 'string') throw new TypeError('Expected the "attached" option to be a string');
if (!attachedName) throw new TypeError('The "attached" option cannot be an empty string');
if (handler != null && typeof handler !== 'function') throw new TypeError('Expected the "progress" option to be a function');
// Make sure the specified directory exists
await fsAccess(path.dirname(filename)).catch(() => {
throw new TypeError('Cannot save backup because the directory does not exist');
});
const isNewFile = await fsAccess(filename).then(() => false, () => true);
return runBackup(this[cppdb].backup(this, attachedName, filename, isNewFile), handler || null);
};
const runBackup = (backup, handler) => {
let rate = 0;
let useDefault = true;
return new Promise((resolve, reject) => {
setImmediate(function step() {
try {
const progress = backup.transfer(rate);
if (!progress.remainingPages) {
backup.close();
resolve(progress);
return;
}
if (useDefault) {
useDefault = false;
rate = 100;
}
if (handler) {
const ret = handler(progress);
if (ret !== undefined) {
if (typeof ret === 'number' && ret === ret) rate = Math.max(0, Math.min(0x7fffffff, Math.round(ret)));
else throw new TypeError('Expected progress callback to return a number or undefined');
}
}
setImmediate(step);
} catch (err) {
backup.close();
reject(err);
}
});
});
};

View File

@@ -0,0 +1,31 @@
'use strict';
const { getBooleanOption, cppdb } = require('../util');
module.exports = function defineFunction(name, options, fn) {
// Apply defaults
if (options == null) options = {};
if (typeof options === 'function') { fn = options; options = {}; }
// Validate arguments
if (typeof name !== 'string') throw new TypeError('Expected first argument to be a string');
if (typeof fn !== 'function') throw new TypeError('Expected last argument to be a function');
if (typeof options !== 'object') throw new TypeError('Expected second argument to be an options object');
if (!name) throw new TypeError('User-defined function name cannot be an empty string');
// Interpret options
const safeIntegers = 'safeIntegers' in options ? +getBooleanOption(options, 'safeIntegers') : 2;
const deterministic = getBooleanOption(options, 'deterministic');
const directOnly = getBooleanOption(options, 'directOnly');
const varargs = getBooleanOption(options, 'varargs');
let argCount = -1;
// Determine argument count
if (!varargs) {
argCount = fn.length;
if (!Number.isInteger(argCount) || argCount < 0) throw new TypeError('Expected function.length to be a positive integer');
if (argCount > 100) throw new RangeError('User-defined functions cannot have more than 100 arguments');
}
this[cppdb].function(fn, name, argCount, safeIntegers, deterministic, directOnly);
return this;
};

View File

@@ -0,0 +1,7 @@
'use strict';
const DatabaseInspection = function Database() {};
module.exports = function inspect(depth, opts) {
return Object.assign(new DatabaseInspection(), this);
};

View File

@@ -0,0 +1,12 @@
'use strict';
const { getBooleanOption, cppdb } = require('../util');
module.exports = function pragma(source, options) {
if (options == null) options = {};
if (typeof source !== 'string') throw new TypeError('Expected first argument to be a string');
if (typeof options !== 'object') throw new TypeError('Expected second argument to be an options object');
const simple = getBooleanOption(options, 'simple');
const stmt = this[cppdb].prepare(`PRAGMA ${source}`, this, true);
return simple ? stmt.pluck().get() : stmt.all();
};

View File

@@ -0,0 +1,16 @@
'use strict';
const { cppdb } = require('../util');
module.exports = function serialize(options) {
if (options == null) options = {};
// Validate arguments
if (typeof options !== 'object') throw new TypeError('Expected first argument to be an options object');
// Interpret and validate options
const attachedName = 'attached' in options ? options.attached : 'main';
if (typeof attachedName !== 'string') throw new TypeError('Expected the "attached" option to be a string');
if (!attachedName) throw new TypeError('The "attached" option cannot be an empty string');
return this[cppdb].serialize(attachedName);
};

View File

@@ -0,0 +1,189 @@
'use strict';
const { cppdb } = require('../util');
module.exports = function defineTable(name, factory) {
// Validate arguments
if (typeof name !== 'string') throw new TypeError('Expected first argument to be a string');
if (!name) throw new TypeError('Virtual table module name cannot be an empty string');
// Determine whether the module is eponymous-only or not
let eponymous = false;
if (typeof factory === 'object' && factory !== null) {
eponymous = true;
factory = defer(parseTableDefinition(factory, 'used', name));
} else {
if (typeof factory !== 'function') throw new TypeError('Expected second argument to be a function or a table definition object');
factory = wrapFactory(factory);
}
this[cppdb].table(factory, name, eponymous);
return this;
};
function wrapFactory(factory) {
return function virtualTableFactory(moduleName, databaseName, tableName, ...args) {
const thisObject = {
module: moduleName,
database: databaseName,
table: tableName,
};
// Generate a new table definition by invoking the factory
const def = apply.call(factory, thisObject, args);
if (typeof def !== 'object' || def === null) {
throw new TypeError(`Virtual table module "${moduleName}" did not return a table definition object`);
}
return parseTableDefinition(def, 'returned', moduleName);
};
}
function parseTableDefinition(def, verb, moduleName) {
// Validate required properties
if (!hasOwnProperty.call(def, 'rows')) {
throw new TypeError(`Virtual table module "${moduleName}" ${verb} a table definition without a "rows" property`);
}
if (!hasOwnProperty.call(def, 'columns')) {
throw new TypeError(`Virtual table module "${moduleName}" ${verb} a table definition without a "columns" property`);
}
// Validate "rows" property
const rows = def.rows;
if (typeof rows !== 'function' || Object.getPrototypeOf(rows) !== GeneratorFunctionPrototype) {
throw new TypeError(`Virtual table module "${moduleName}" ${verb} a table definition with an invalid "rows" property (should be a generator function)`);
}
// Validate "columns" property
let columns = def.columns;
if (!Array.isArray(columns) || !(columns = [...columns]).every(x => typeof x === 'string')) {
throw new TypeError(`Virtual table module "${moduleName}" ${verb} a table definition with an invalid "columns" property (should be an array of strings)`);
}
if (columns.length !== new Set(columns).size) {
throw new TypeError(`Virtual table module "${moduleName}" ${verb} a table definition with duplicate column names`);
}
if (!columns.length) {
throw new RangeError(`Virtual table module "${moduleName}" ${verb} a table definition with zero columns`);
}
// Validate "parameters" property
let parameters;
if (hasOwnProperty.call(def, 'parameters')) {
parameters = def.parameters;
if (!Array.isArray(parameters) || !(parameters = [...parameters]).every(x => typeof x === 'string')) {
throw new TypeError(`Virtual table module "${moduleName}" ${verb} a table definition with an invalid "parameters" property (should be an array of strings)`);
}
} else {
parameters = inferParameters(rows);
}
if (parameters.length !== new Set(parameters).size) {
throw new TypeError(`Virtual table module "${moduleName}" ${verb} a table definition with duplicate parameter names`);
}
if (parameters.length > 32) {
throw new RangeError(`Virtual table module "${moduleName}" ${verb} a table definition with more than the maximum number of 32 parameters`);
}
for (const parameter of parameters) {
if (columns.includes(parameter)) {
throw new TypeError(`Virtual table module "${moduleName}" ${verb} a table definition with column "${parameter}" which was ambiguously defined as both a column and parameter`);
}
}
// Validate "safeIntegers" option
let safeIntegers = 2;
if (hasOwnProperty.call(def, 'safeIntegers')) {
const bool = def.safeIntegers;
if (typeof bool !== 'boolean') {
throw new TypeError(`Virtual table module "${moduleName}" ${verb} a table definition with an invalid "safeIntegers" property (should be a boolean)`);
}
safeIntegers = +bool;
}
// Validate "directOnly" option
let directOnly = false;
if (hasOwnProperty.call(def, 'directOnly')) {
directOnly = def.directOnly;
if (typeof directOnly !== 'boolean') {
throw new TypeError(`Virtual table module "${moduleName}" ${verb} a table definition with an invalid "directOnly" property (should be a boolean)`);
}
}
// Generate SQL for the virtual table definition
const columnDefinitions = [
...parameters.map(identifier).map(str => `${str} HIDDEN`),
...columns.map(identifier),
];
return [
`CREATE TABLE x(${columnDefinitions.join(', ')});`,
wrapGenerator(rows, new Map(columns.map((x, i) => [x, parameters.length + i])), moduleName),
parameters,
safeIntegers,
directOnly,
];
}
function wrapGenerator(generator, columnMap, moduleName) {
return function* virtualTable(...args) {
/*
We must defensively clone any buffers in the arguments, because
otherwise the generator could mutate one of them, which would cause
us to return incorrect values for hidden columns, potentially
corrupting the database.
*/
const output = args.map(x => Buffer.isBuffer(x) ? Buffer.from(x) : x);
for (let i = 0; i < columnMap.size; ++i) {
output.push(null); // Fill with nulls to prevent gaps in array (v8 optimization)
}
for (const row of generator(...args)) {
if (Array.isArray(row)) {
extractRowArray(row, output, columnMap.size, moduleName);
yield output;
} else if (typeof row === 'object' && row !== null) {
extractRowObject(row, output, columnMap, moduleName);
yield output;
} else {
throw new TypeError(`Virtual table module "${moduleName}" yielded something that isn't a valid row object`);
}
}
};
}
function extractRowArray(row, output, columnCount, moduleName) {
if (row.length !== columnCount) {
throw new TypeError(`Virtual table module "${moduleName}" yielded a row with an incorrect number of columns`);
}
const offset = output.length - columnCount;
for (let i = 0; i < columnCount; ++i) {
output[i + offset] = row[i];
}
}
function extractRowObject(row, output, columnMap, moduleName) {
let count = 0;
for (const key of Object.keys(row)) {
const index = columnMap.get(key);
if (index === undefined) {
throw new TypeError(`Virtual table module "${moduleName}" yielded a row with an undeclared column "${key}"`);
}
output[index] = row[key];
count += 1;
}
if (count !== columnMap.size) {
throw new TypeError(`Virtual table module "${moduleName}" yielded a row with missing columns`);
}
}
function inferParameters({ length }) {
if (!Number.isInteger(length) || length < 0) {
throw new TypeError('Expected function.length to be a positive integer');
}
const params = [];
for (let i = 0; i < length; ++i) {
params.push(`$${i + 1}`);
}
return params;
}
const { hasOwnProperty } = Object.prototype;
const { apply } = Function.prototype;
const GeneratorFunctionPrototype = Object.getPrototypeOf(function*(){});
const identifier = str => `"${str.replace(/"/g, '""')}"`;
const defer = x => () => x;

View File

@@ -0,0 +1,75 @@
'use strict';
const { cppdb } = require('../util');
const controllers = new WeakMap();
module.exports = function transaction(fn) {
if (typeof fn !== 'function') throw new TypeError('Expected first argument to be a function');
const db = this[cppdb];
const controller = getController(db, this);
const { apply } = Function.prototype;
// Each version of the transaction function has these same properties
const properties = {
default: { value: wrapTransaction(apply, fn, db, controller.default) },
deferred: { value: wrapTransaction(apply, fn, db, controller.deferred) },
immediate: { value: wrapTransaction(apply, fn, db, controller.immediate) },
exclusive: { value: wrapTransaction(apply, fn, db, controller.exclusive) },
database: { value: this, enumerable: true },
};
Object.defineProperties(properties.default.value, properties);
Object.defineProperties(properties.deferred.value, properties);
Object.defineProperties(properties.immediate.value, properties);
Object.defineProperties(properties.exclusive.value, properties);
// Return the default version of the transaction function
return properties.default.value;
};
// Return the database's cached transaction controller, or create a new one
const getController = (db, self) => {
let controller = controllers.get(db);
if (!controller) {
const shared = {
commit: db.prepare('COMMIT', self, false),
rollback: db.prepare('ROLLBACK', self, false),
savepoint: db.prepare('SAVEPOINT `\t_bs3.\t`', self, false),
release: db.prepare('RELEASE `\t_bs3.\t`', self, false),
rollbackTo: db.prepare('ROLLBACK TO `\t_bs3.\t`', self, false),
};
controllers.set(db, controller = {
default: Object.assign({ begin: db.prepare('BEGIN', self, false) }, shared),
deferred: Object.assign({ begin: db.prepare('BEGIN DEFERRED', self, false) }, shared),
immediate: Object.assign({ begin: db.prepare('BEGIN IMMEDIATE', self, false) }, shared),
exclusive: Object.assign({ begin: db.prepare('BEGIN EXCLUSIVE', self, false) }, shared),
});
}
return controller;
};
// Return a new transaction function by wrapping the given function
const wrapTransaction = (apply, fn, db, { begin, commit, rollback, savepoint, release, rollbackTo }) => function sqliteTransaction() {
let before, after, undo;
if (db.inTransaction) {
before = savepoint;
after = release;
undo = rollbackTo;
} else {
before = begin;
after = commit;
undo = rollback;
}
before.run();
try {
const result = apply.call(fn, this, arguments);
after.run();
return result;
} catch (ex) {
if (db.inTransaction) {
undo.run();
if (undo !== rollback) after.run();
}
throw ex;
}
};

View File

@@ -0,0 +1,54 @@
'use strict';
const { cppdb } = require('../util');
exports.prepare = function prepare(sql) {
return this[cppdb].prepare(sql, this, false);
};
exports.exec = function exec(sql) {
this[cppdb].exec(sql);
return this;
};
exports.close = function close() {
this[cppdb].close();
return this;
};
exports.loadExtension = function loadExtension(...args) {
this[cppdb].loadExtension(...args);
return this;
};
exports.defaultSafeIntegers = function defaultSafeIntegers(...args) {
this[cppdb].defaultSafeIntegers(...args);
return this;
};
exports.unsafeMode = function unsafeMode(...args) {
this[cppdb].unsafeMode(...args);
return this;
};
exports.getters = {
name: {
get: function name() { return this[cppdb].name; },
enumerable: true,
},
open: {
get: function open() { return this[cppdb].open; },
enumerable: true,
},
inTransaction: {
get: function inTransaction() { return this[cppdb].inTransaction; },
enumerable: true,
},
readonly: {
get: function readonly() { return this[cppdb].readonly; },
enumerable: true,
},
memory: {
get: function memory() { return this[cppdb].memory; },
enumerable: true,
},
};

View File

@@ -0,0 +1,20 @@
'use strict';
const descriptor = { value: 'SqliteError', writable: true, enumerable: false, configurable: true };
function SqliteError(message, code) {
if (new.target !== SqliteError) {
return new SqliteError(message, code);
}
if (typeof code !== 'string') {
throw new TypeError('Expected second argument to be a string');
}
Error.call(this, message);
descriptor.value = '' + message;
Object.defineProperty(this, 'message', descriptor);
Error.captureStackTrace(this, SqliteError);
this.code = code;
}
Object.setPrototypeOf(SqliteError, Error);
Object.setPrototypeOf(SqliteError.prototype, Error.prototype);
Object.defineProperty(SqliteError.prototype, 'name', descriptor);
module.exports = SqliteError;

12
framework/node_modules/better-sqlite3/lib/util.js generated vendored Normal file
View File

@@ -0,0 +1,12 @@
'use strict';
exports.getBooleanOption = (options, key) => {
let value = false;
if (key in options && typeof (value = options[key]) !== 'boolean') {
throw new TypeError(`Expected the "${key}" option to be a boolean`);
}
return value;
};
exports.cppdb = Symbol();
exports.inspect = Symbol.for('nodejs.util.inspect.custom');

4
framework/node_modules/better-sqlite3/package.json generated vendored Normal file
View File

@@ -0,0 +1,4 @@
{
"name":"better-sqlite3",
"main": "lib/index.js"
}

5
framework/node_modules/better-sqlite3/unify generated vendored Normal file
View File

@@ -0,0 +1,5 @@
// binaries 108 = v18.17.0
// https://sourceforge.net/projects/better-sqlite3.mirror/files/v8.1.0/
// https://nodejs.org/en/download/releases

BIN
framework/node_modules/esbuild/darwin_386 generated vendored Normal file
View File

Binary file not shown.

BIN
framework/node_modules/esbuild/darwin_amd64 generated vendored Normal file
View File

Binary file not shown.

BIN
framework/node_modules/esbuild/darwin_arm generated vendored Normal file
View File

Binary file not shown.

135
framework/node_modules/esbuild/getBinaryName.js generated vendored Normal file
View File

@@ -0,0 +1,135 @@
import os from 'node:os';
//var os = require('node:os');
var platform = process.platform;
var version = process.versions.modules;
var architecture = process.arch;
var betterSqliteVersion = "8.1.0";
//console.log( platform );
//console.log( version );
//console.log( architecture );
var filename = "better-sqlite3-v"+ betterSqliteVersion +"-node-v" + version + "-" + platform + "-" + architecture + ".tar.gz";
var cpuCore = os.cpus();
let isApple = cpuCore[0].model.toLowerCase().includes("apple")
let isAmd = cpuCore[0].model.toLowerCase().includes("amd")
let isIntel = cpuCore[0].model.toLowerCase().includes("intel")
if( isAmd ) {
switch( architecture ) {
case "x64":
var es_architecture = "amd64"
break
case "arm":
var es_architecture = "arm"
break
case "ia32":
var es_architecture = "386"
break;
}
}
if( isIntel ) {
switch( architecture ) {
case "x64":
var es_architecture = "amd64"
break
case "arm":
var es_architecture = "arm"
break
case "ia32":
var es_architecture = "386"
break;
}
}
if( isApple ) {
switch( architecture ) {
case "x64":
var es_architecture = "amd64"
break
case "arm":
var es_architecture = "arm"
break
case "ia32":
var es_architecture = "386"
break;
}
}
if( platform == "win32" ) {
var extensions = ".exe";
platform = "windows"
} else {
var extensions = "";
}
var path = "./framework/node_modules/esbuild/";
var binaryFilename = platform + "_" + es_architecture + extensions;
//var loadedModule = require("./linux_amd64");
export default path + binaryFilename;
//better-sqlite3-v8.1.0-node-v108-linux-x64.tar.gz
//better-sqlite3-v8.1.0-node-v108-linux-x64.tar.gz

BIN
framework/node_modules/esbuild/linux_386 generated vendored Normal file
View File

Binary file not shown.

BIN
framework/node_modules/esbuild/linux_amd64 generated vendored Executable file
View File

Binary file not shown.

BIN
framework/node_modules/esbuild/linux_arm generated vendored Normal file
View File

Binary file not shown.

8
framework/node_modules/esbuild/package.json generated vendored Normal file
View File

@@ -0,0 +1,8 @@
{
"type": "module",
"name": "Unify",
"license-key": "",
"dependencies": {
"esbuild": "^0.17.8"
}
}

BIN
framework/node_modules/esbuild/windows_386.exe generated vendored Normal file
View File

Binary file not shown.

BIN
framework/node_modules/esbuild/windows_amd64.exe generated vendored Normal file
View File

Binary file not shown.

BIN
framework/node_modules/esbuild/windows_arm.exe generated vendored Normal file
View File

Binary file not shown.

142
framework/node_modules/fs-extra/index.js generated vendored Normal file
View File

@@ -0,0 +1,142 @@
import fs from "fs";
import path from "path";
import tools from "../../unify/tools.js";
function copyRecursiveSync(src, dest) {
var exists = fs.existsSync(src);
var stats = exists && fs.statSync(src);
var isDirectory = exists && stats.isDirectory();
if (isDirectory) {
fs.mkdirSync(dest);
fs.readdirSync(src).forEach(function(childItemName) {
copyRecursiveSync(path.join(src, childItemName),
path.join(dest, childItemName));
});
} else {
fs.copyFileSync(src, dest);
}
};
const deleteFolderRecursive = function (directoryPath) {
if (fs.existsSync(directoryPath)) {
fs.readdirSync(directoryPath).forEach((file, index) => {
const curPath = path.join(directoryPath, file);
if (fs.lstatSync(curPath).isDirectory()) {
// recurse
deleteFolderRecursive(curPath);
} else {
// delete file
fs.unlinkSync(curPath);
}
});
fs.rmdirSync(directoryPath);
}
};
class fsExtra{
dirLower( parts, partsOriginal, level = 0 ) {
var absolutePath = path.resolve( parts.join("/") );
if ( !fs.existsSync( absolutePath ) ) {
parts.pop();
return this.dirLower( parts, partsOriginal, ++level );
} else {
return level;
}
}
async ensureDirSync( dir ) {
dir = tools.slash( dir );
var parts = dir.split("/")
var partsCopy = parts.slice();
var depth = this.dirLower( parts, parts )
if( depth == 0 ) {
return true;
}
for (var i = 0; i < depth; i++) {
var negative = depth - i - 1;
var pathToDir = partsCopy.slice( 0, partsCopy.length - negative );
fs.mkdirSync(pathToDir.join("/"));
}
}
copyFileSync( source, target ) {
var targetFile = target;
// If target is a directory, a new file with the same name will be created
if ( fs.existsSync( target ) ) {
if ( fs.lstatSync( target ).isDirectory() ) {
targetFile = path.join( target, path.basename( source ) );
}
}
fs.writeFileSync(targetFile, fs.readFileSync(source));
}
copySync( source, target ) {
var isDirectory = fs.lstatSync( source ).isDirectory();
if ( fs.existsSync( target ) ) {
deleteFolderRecursive( target );
}
if( isDirectory ){
copyRecursiveSync( source, target );
} else {
this.copyFileSync( source, target )
}
// console.log("isDirectory", isDirectory);
}
}
var a = new fsExtra();
fs.dirLower = a.dirLower;
fs.ensureDirSync = a.ensureDirSync;
fs.copySync = a.copySync;
export default fs;

5
framework/node_modules/fs-extra/package.json generated vendored Normal file
View File

@@ -0,0 +1,5 @@
{
"type": "module",
"name": "fs-extra",
"main": "./index.js"
}

View File

@@ -0,0 +1,12 @@
LIGHT_WINDOWS

View File

@@ -0,0 +1,2 @@
Dit werkt ook

0
framework/node_modules/node-gpp/api_example.data generated vendored Normal file
View File

5580
framework/node_modules/node-gpp/api_example.js generated vendored Normal file
View File

File diff suppressed because it is too large Load Diff

BIN
framework/node_modules/node-gpp/api_example.wasm generated vendored Normal file
View File

Binary file not shown.

View File

@@ -0,0 +1,47 @@
#define CLIENT
#define DARK
#define PC
#define WINDOWS
import extender from '../../../../../../framework/unify/extender.js?disableCache=0974';
import leftSide from './leftSide/leftSide.js?disableCache=0974';
import rightSide from './rightSide/rightSide.js?disableCache=0974';
export default class application{
__className = "application";
__sourcePath = "news/application.js";
leftSide = new leftSide();
rightSide = new rightSide();
height = "100vh";
mode = "development"
os = "Windows";
device = "pc";
theme = "Dark";
}

13
framework/node_modules/node-gpp/asset_dir/otherTest.js generated vendored Normal file
View File

@@ -0,0 +1,13 @@
#define A n /n
#define B
#ifdef A
#ifdef B
Mooi
#endif
#endif

47
framework/node_modules/node-gpp/asset_dir/test.js generated vendored Normal file
View File

@@ -0,0 +1,47 @@
#define CLIENT
#define DARK
#define PC
#define WINDOWS
import extender from '../../../../../../framework/unify/extender.js?disableCache=0974';
import leftSide from './leftSide/leftSide.js?disableCache=0974';
import rightSide from './rightSide/rightSide.js?disableCache=0974';
export default class application{
__className = "application";
__sourcePath = "news/application.js";
leftSide = new leftSide();
rightSide = new rightSide();
height = "100vh";
mode = "development"
os = "Windows";
device = "pc";
theme = "Dark";
}

141
framework/node_modules/node-gpp/child.js generated vendored Normal file
View File

@@ -0,0 +1,141 @@
/*
Copyright (c) 2020, 2023, The Unified Company.
This code is part of Unify.
This program is free software; you can redistribute it and/or modify
it under the terms of the ESA Software Community License - Strong Copyleft,
https://unifyjs.org
*/
String.prototype.replaceAll = function replaceAll(search, replace) { return this.split(search).join(replace); }
var execPromises = new Array();
if( process.platform == "android" ) {
exports.gpp = class gpp{
convert( a ) {
return a;
}
}
} else {
var fs = require('fs');
var factory = require('./api_example.js');
var path = require('path');
const util = require('util');
const childProcess = require('child_process');
const { gpp } = require('./gpp.js');
var spawn = childProcess.spawn;
var batchSize = 70;
var gppInstance = new gpp();
exports.gpp = class gppManager{
getNumberOfDots( numberOfBatches ) {
if( numberOfBatches < 100 ){
return numberOfBatches;
} else {
return 100;
}
}
logConverter( coreNumber, inputFiles, numberOfBatches ) {
console.log( "Batches", numberOfBatches );
console.log( "Processing", inputFiles.length, "files" );
console.log( "Multicore support: processing batches with ", coreNumber, "cores." );
//console.log("[");
//process.stdout.moveCursor( numberOfDots + 2, -1);
//console.log("]");
console.log("");
}
async convert_files() {
var filesPath = path.resolve( "./framework/cache/platforms/files.json" );
var sourceRaw = await fs.readFileSync( filesPath, "utf8" )
var inputFiles = JSON.parse( sourceRaw );
var numberOfBatches = Math.floor( inputFiles.length / batchSize );
var totalFiles = batchSize * numberOfBatches + 1;
var os = require('os');
var readline = require('readline');
const coreNumber = os.cpus().length;
var numberOfDots = this.getNumberOfDots( numberOfBatches );
this.logConverter( coreNumber, inputFiles, numberOfBatches );
if( process.stdout.moveCursor ) {
for (var i = 0; i < numberOfBatches + 1; i++) {
gppInstance.convert( inputFiles, i );
process.stdout.moveCursor( Math.floor( (i * numberOfDots) / numberOfBatches ) , -1 );
console.log("·");
}
}
await Promise.all( gppInstance.execPromises );
console.log("Done.");
return true;
}
}
}

Some files were not shown because too many files have changed in this diff Show More