Compare commits
No commits in common. "0dbba014d81ae85ac11f6b938c5ce0805f1a03e0" and "62532b0cb1be1fa88c2a130fee70425835a9e9d5" have entirely different histories.
0dbba014d8
...
62532b0cb1
4
.gitignore
vendored
4
.gitignore
vendored
@ -11,7 +11,3 @@ test_code.php
|
|||||||
modules/
|
modules/
|
||||||
|
|
||||||
requirements.txt
|
requirements.txt
|
||||||
package.json
|
|
||||||
package-lock.json
|
|
||||||
npm.sync
|
|
||||||
node_modules/
|
|
||||||
|
|||||||
@ -2,12 +2,10 @@
|
|||||||
cd "$(dirname ${BASH_SOURCE[0]})"
|
cd "$(dirname ${BASH_SOURCE[0]})"
|
||||||
while [[ 1 ]]
|
while [[ 1 ]]
|
||||||
do
|
do
|
||||||
killall DbContinuousIntegrationWrapper.sh
|
killall DbContinuousIntegrationWrapper.sh
|
||||||
/usr/bin/php composer.json.php > composer.json
|
/usr/bin/php composer.json.php > composer.json
|
||||||
touch -t $(/usr/bin/mysql -se "SELECT DATE_FORMAT(LastUpdated, '%Y%m%d%H%i.%s') FROM SYS_PRD_BND.Composer ORDER BY LastUpdated DESC LIMIT 1") composer.json
|
touch -t $(/usr/bin/mysql -se "SELECT DATE_FORMAT(LastUpdated, '%Y%m%d%H%i.%s') FROM SYS_PRD_BND.Composer ORDER BY LastUpdated DESC LIMIT 1") composer.json
|
||||||
/usr/bin/php package.json.php > package.json
|
make
|
||||||
touch -t $(/usr/bin/mysql -se "SELECT DATE_FORMAT(LastUpdated, '%Y%m%d%H%i.%s') FROM SYS_PRD_BND.Npm ORDER BY LastUpdated DESC LIMIT 1") package.json
|
/usr/bin/php DbContinuousIntegration.php
|
||||||
make
|
sleep 10
|
||||||
/usr/bin/php DbContinuousIntegration.php
|
|
||||||
sleep 10
|
|
||||||
done
|
done
|
||||||
|
|||||||
16
Makefile
16
Makefile
@ -1,18 +1,12 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
all: composer.sync requirements.sync npm.sync
|
|
||||||
|
|
||||||
composer.sync: composer.json
|
composer.sync: composer.json
|
||||||
COMPOSER_ALLOW_SUPERUSER=1 composer update > $@ 2>&1
|
COMPOSER_ALLOW_SUPERUSER=1 composer update > $@ 2>&1
|
||||||
|
|
||||||
requirements.sync: requirements.txt
|
requirements.sync: requirements.txt
|
||||||
pip install -r requirements.txt > $@ 2>&1
|
pip install -r requirements.txt $@
|
||||||
|
|
||||||
npm.sync: package.json
|
|
||||||
npm install > $@ 2>&1
|
|
||||||
|
|
||||||
install:
|
install:
|
||||||
@echo "Add this line to crontab -e"
|
echo "Add this line to crontab -e"
|
||||||
@echo '@reboot /bin/bash /root/DbContinuousIntegration/DbContinuousIntegrationWrapper.sh 2> /dev/null > /dev/null &'
|
echo '@reboot /bin/bash /root/DbContinuousIntegration/DbContinuousIntegrationWrapper.sh 2> /dev/null > /dev/null &'
|
||||||
@echo
|
echo
|
||||||
@echo 'CREATE TABLE SYS_PRD_BND.Tables (Name, onUpdate_phpCode, onUpdate_pyCode, onUpdate_jsCode, LastUpdated);' | sudo mysql
|
echo 'CREATE TABLE SYS_PRD_BND.Tables (Name, onUpdate_phpCode, onUpdate_pyCode, LastUpdated);' | sudo mysql
|
||||||
|
|||||||
@ -4,13 +4,11 @@
|
|||||||
|
|
||||||
### TO BE:
|
### TO BE:
|
||||||
|
|
||||||
v0.4 - has an "export" and "import" module that converts sql data into a "git repo" / folder with code
|
v0.3 - has an "export" and "import" module that converts sql data into a "git repo" / folder with code
|
||||||
|
|
||||||
|
|
||||||
## AS IS:
|
|
||||||
|
|
||||||
v0.3 - supports Javascript / ECMA Script, and npm package manager
|
|
||||||
v0.2 - has a function called "sql_read_hidrate()" that gives the foreign keys hidrated
|
v0.2 - has a function called "sql_read_hidrate()" that gives the foreign keys hidrated
|
||||||
- (useful for trigger functions like telegram outbox that need data like recipients hidrated)
|
- (useful for trigger functions like telegram outbox that need data like recipients hidrated)
|
||||||
|
|
||||||
|
## AS IS:
|
||||||
|
|
||||||
v0.1 - works.
|
v0.1 - works.
|
||||||
@ -1,8 +0,0 @@
|
|||||||
USE SYS_PRD_BND;
|
|
||||||
CREATE TABLE `Npm` (
|
|
||||||
`PackageName` varchar(255) NOT NULL,
|
|
||||||
`AliasName` varchar(255) DEFAULT NULL,
|
|
||||||
`VersionOrTag` varchar(25) DEFAULT NULL,
|
|
||||||
`LastUpdated` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(),
|
|
||||||
PRIMARY KEY (`PackageName`)
|
|
||||||
);
|
|
||||||
@ -3,7 +3,6 @@ CREATE TABLE `Tables` (
|
|||||||
`Name` varchar(255) NOT NULL,
|
`Name` varchar(255) NOT NULL,
|
||||||
`onUpdate_phpCode` text DEFAULT NULL,
|
`onUpdate_phpCode` text DEFAULT NULL,
|
||||||
`onUpdate_pyCode` text DEFAULT NULL,
|
`onUpdate_pyCode` text DEFAULT NULL,
|
||||||
`onUpdate_jsCode` text DEFAULT NULL,
|
|
||||||
`LastError` text DEFAULT NULL,
|
`LastError` text DEFAULT NULL,
|
||||||
`LastUpdated` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(),
|
`LastUpdated` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(),
|
||||||
PRIMARY KEY (`Name`)
|
PRIMARY KEY (`Name`)
|
||||||
|
|||||||
@ -1,29 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
$dsn = "mysql:unix_socket=/var/run/mysqld/mysqld.sock;dbname=SYS_PRD_BND;charset=utf8mb4";
|
|
||||||
$options = [
|
|
||||||
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
|
|
||||||
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
|
|
||||||
];
|
|
||||||
|
|
||||||
try {
|
|
||||||
$pdo = new PDO($dsn, "root", "", $options);
|
|
||||||
|
|
||||||
$stmt = $pdo->query("SELECT PackageName, VersionOrTag FROM Npm ORDER BY PackageName");
|
|
||||||
$dependencies = [];
|
|
||||||
foreach ($stmt as $row) {
|
|
||||||
$ver = $row['VersionOrTag'];
|
|
||||||
$dependencies[$row['PackageName']] = $ver ?: '*';
|
|
||||||
}
|
|
||||||
|
|
||||||
$packageJson = [
|
|
||||||
'type' => 'module',
|
|
||||||
'dependencies' => (object)$dependencies,
|
|
||||||
];
|
|
||||||
|
|
||||||
file_put_contents('php://stdout', json_encode($packageJson, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES));
|
|
||||||
file_put_contents('php://stderr', "✅ package.json generated successfully.\n");
|
|
||||||
|
|
||||||
} catch (PDOException $e) {
|
|
||||||
file_put_contents('php://stderr', "❌ Database error: " . $e->getMessage() . "\n");
|
|
||||||
}
|
|
||||||
@ -1,32 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* Generates JavaScript code for sandbox execution based on provided trigger code and row data.
|
|
||||||
*
|
|
||||||
* @param string $functionName The name of the JavaScript function to generate.
|
|
||||||
* @param string $jsCode The JavaScript code to embed within the generated function.
|
|
||||||
* @param array $row The row data to pass to the generated function.
|
|
||||||
*
|
|
||||||
* @return string The complete JavaScript code ready for sandbox execution.
|
|
||||||
*/
|
|
||||||
function generateJSTriggerCode($functionName, $jsCode, $row) {
|
|
||||||
$constants = getJSConstantsDefinition();
|
|
||||||
$supportFunctions = getJavascriptSupportFunctionsDefinition();
|
|
||||||
$requires = getNodeRequires();
|
|
||||||
|
|
||||||
$rowJson = json_encode($row, JSON_UNESCAPED_SLASHES);
|
|
||||||
$indentedCode = implode("\n", array_map(fn($l) => ' ' . $l, explode("\n", $jsCode)));
|
|
||||||
|
|
||||||
$javascript = <<<JS
|
|
||||||
$requires
|
|
||||||
$constants
|
|
||||||
$supportFunctions
|
|
||||||
function $functionName(data, error) {
|
|
||||||
$indentedCode
|
|
||||||
}
|
|
||||||
let data = $rowJson;
|
|
||||||
let error = null;
|
|
||||||
$functionName(data, error);
|
|
||||||
console.log(JSON.stringify(data));
|
|
||||||
JS;
|
|
||||||
return $javascript;
|
|
||||||
}
|
|
||||||
@ -6,7 +6,7 @@
|
|||||||
* Overview:
|
* Overview:
|
||||||
* This PHP script automates database updates by processing rows marked for action in various tables.
|
* This PHP script automates database updates by processing rows marked for action in various tables.
|
||||||
* It dynamically executes predefined functions based on table-specific instructions stored in the database.
|
* It dynamically executes predefined functions based on table-specific instructions stored in the database.
|
||||||
* Functions are executed in PHP, Python, or JavaScript environments depending on configuration.
|
* Functions are executed in either PHP or Python environments depending on configuration.
|
||||||
*
|
*
|
||||||
* How It Works:
|
* How It Works:
|
||||||
* 1. The script queries the `SYS_PRD_BND.Tables` table to determine which tables require processing.
|
* 1. The script queries the `SYS_PRD_BND.Tables` table to determine which tables require processing.
|
||||||
@ -19,8 +19,8 @@
|
|||||||
*
|
*
|
||||||
* Tables and Their Purpose:
|
* Tables and Their Purpose:
|
||||||
* - SYS_PRD_BND.Tables:
|
* - SYS_PRD_BND.Tables:
|
||||||
* Defines active tables and their respective PHP, Python, or JavaScript trigger codes.
|
* Defines active tables and their respective PHP or Python trigger codes.
|
||||||
* Columns: Name, onUpdate_phpCode, onUpdate_pyCode, onUpdate_jsCode, LastUpdated, LastError
|
* Columns: Name, onUpdate_phpCode, onUpdate_pyCode, LastUpdated, LastError
|
||||||
*
|
*
|
||||||
* - SYS_PRD_BND.Constants:
|
* - SYS_PRD_BND.Constants:
|
||||||
* Holds constants that are injected into the PHP environment during execution.
|
* Holds constants that are injected into the PHP environment during execution.
|
||||||
@ -34,10 +34,6 @@
|
|||||||
* Lists external Python libraries imported into Python trigger execution.
|
* Lists external Python libraries imported into Python trigger execution.
|
||||||
* Columns: LibName, AliasName
|
* Columns: LibName, AliasName
|
||||||
*
|
*
|
||||||
* - SYS_PRD_BND.Npm:
|
|
||||||
* Lists external Node modules imported into JavaScript trigger execution.
|
|
||||||
* Columns: PackageName, AliasName, VersionOrTag
|
|
||||||
*
|
|
||||||
* Dynamic Tables:
|
* Dynamic Tables:
|
||||||
* - Application-specific tables, each must include at least:
|
* - Application-specific tables, each must include at least:
|
||||||
* - LastUpdated (timestamp for tracking)
|
* - LastUpdated (timestamp for tracking)
|
||||||
@ -72,7 +68,7 @@ foreach(scandir(__DIR__) as $filename) if (substr($filename,-8) == ".inc.php") r
|
|||||||
*/
|
*/
|
||||||
function processAllTheActiveTables() {
|
function processAllTheActiveTables() {
|
||||||
echo "Scanning all the tables that need updating...\n";
|
echo "Scanning all the tables that need updating...\n";
|
||||||
$activeTables = sql("SELECT Name, onUpdate_phpCode, onUpdate_pyCode, onUpdate_jsCode, LastUpdated FROM SYS_PRD_BND.Tables");
|
$activeTables = sql("SELECT Name, onUpdate_phpCode, onUpdate_pyCode, LastUpdated FROM SYS_PRD_BND.Tables");
|
||||||
|
|
||||||
foreach ($activeTables as $activeTable) {
|
foreach ($activeTables as $activeTable) {
|
||||||
processActiveTable($activeTable);
|
processActiveTable($activeTable);
|
||||||
@ -122,10 +118,6 @@ function processTableRow($activeTable, $unprocessedRow) {
|
|||||||
if (!empty($activeTable['onUpdate_pyCode'])) {
|
if (!empty($activeTable['onUpdate_pyCode'])) {
|
||||||
runPythonCodeTrigger($functionName, $activeTable, $unprocessedRow);
|
runPythonCodeTrigger($functionName, $activeTable, $unprocessedRow);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!empty($activeTable['onUpdate_jsCode'])) {
|
|
||||||
runJavascriptCodeTrigger($functionName, $activeTable, $unprocessedRow);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -164,17 +156,6 @@ function runPythonCodeTrigger($functionName, $activeTable, $row) {
|
|||||||
handleTriggerExecutionResult($result, $stdout, $stderr, $row, $activeTable);
|
handleTriggerExecutionResult($result, $stdout, $stderr, $row, $activeTable);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Executes database-level dynamic JavaScript trigger code.
|
|
||||||
*/
|
|
||||||
function runJavascriptCodeTrigger($functionName, $activeTable, $row) {
|
|
||||||
echo "Running JavaScript Code trigger...\n";
|
|
||||||
$jsCode = generateJSTriggerCode($functionName, $activeTable['onUpdate_jsCode'], $row);
|
|
||||||
$result = runSandboxedJavascript($jsCode, $stdout, $stderr);
|
|
||||||
|
|
||||||
handleTriggerExecutionResult($result, $stdout, $stderr, $row, $activeTable);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper functions implementations.
|
* Helper functions implementations.
|
||||||
*/
|
*/
|
||||||
@ -235,43 +216,6 @@ function getPythonImports() {
|
|||||||
}
|
}
|
||||||
return $imports;
|
return $imports;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getNodeRequires() {
|
|
||||||
$requires = "";
|
|
||||||
foreach (sql("SELECT PackageName, AliasName FROM SYS_PRD_BND.Npm") as $module) {
|
|
||||||
$alias = !empty($module['AliasName']) ? $module['AliasName'] : basename($module['PackageName']);
|
|
||||||
$alias = preg_replace('/[^A-Za-z0-9_]/', '_', $alias);
|
|
||||||
$requires .= "const $alias = require('{$module['PackageName']}');\n";
|
|
||||||
}
|
|
||||||
return $requires;
|
|
||||||
}
|
|
||||||
|
|
||||||
function getJSConstantsDefinition() {
|
|
||||||
$constants = "";
|
|
||||||
foreach (sql("SELECT Name, Type, Value FROM SYS_PRD_BND.Constants") as $const) {
|
|
||||||
switch ($const['Type']) {
|
|
||||||
case 'String':
|
|
||||||
$val = '`' . str_replace('`', '\\`', $const['Value']) . '`';
|
|
||||||
break;
|
|
||||||
case 'Json':
|
|
||||||
$val = json_encode(json_decode($const['Value'], true));
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
$val = $const['Value'];
|
|
||||||
}
|
|
||||||
$constants .= "const {$const['Name']} = {$val};\n";
|
|
||||||
}
|
|
||||||
return $constants;
|
|
||||||
}
|
|
||||||
|
|
||||||
function getJavascriptSupportFunctionsDefinition() {
|
|
||||||
$functions = "";
|
|
||||||
foreach (sql("SELECT Name, InputArgs_json, JavascriptCode FROM SYS_PRD_BND.SupportFunctions WHERE JavascriptCode IS NOT NULL") as $f) {
|
|
||||||
$args = implode(', ', array_keys(json_decode($f['InputArgs_json'], true)));
|
|
||||||
$functions .= "function {$f['Name']}($args) {\n{$f['JavascriptCode']}\n}\n";
|
|
||||||
}
|
|
||||||
return $functions;
|
|
||||||
}
|
|
||||||
function greenText($string) { $green = "\033[0;32m"; $reset = "\033[0m"; return $green . $string . $reset ; }
|
function greenText($string) { $green = "\033[0;32m"; $reset = "\033[0m"; return $green . $string . $reset ; }
|
||||||
function blueText($string) { $green = "\033[0;34m"; $reset = "\033[0m"; return $green . $string . $reset ; }
|
function blueText($string) { $green = "\033[0;34m"; $reset = "\033[0m"; return $green . $string . $reset ; }
|
||||||
function redText($string) { $green = "\033[0;31m"; $reset = "\033[0m"; return $green . $string . $reset ; }
|
function redText($string) { $green = "\033[0;31m"; $reset = "\033[0m"; return $green . $string . $reset ; }
|
||||||
|
|||||||
@ -1,41 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* Runs dynamically generated JavaScript code in a sandboxed environment using Node.js.
|
|
||||||
*
|
|
||||||
* @param string $code The JavaScript code to execute.
|
|
||||||
* @param string &$stdout Captured standard output from the execution.
|
|
||||||
* @param string &$stderr Captured standard error from the execution.
|
|
||||||
*
|
|
||||||
* @return int Exit code of the executed script (0 means success).
|
|
||||||
*/
|
|
||||||
function runSandboxedJavascript($code, &$stdout = null, &$stderr = null) {
|
|
||||||
$tempFile = tempnam(sys_get_temp_dir(), 'sandboxed_') . '.js';
|
|
||||||
|
|
||||||
file_put_contents($tempFile, $code);
|
|
||||||
|
|
||||||
$command = "/usr/bin/node " . escapeshellarg($tempFile);
|
|
||||||
|
|
||||||
$descriptorspec = [
|
|
||||||
1 => ['pipe', 'w'],
|
|
||||||
2 => ['pipe', 'w'],
|
|
||||||
];
|
|
||||||
|
|
||||||
$process = proc_open($command, $descriptorspec, $pipes);
|
|
||||||
|
|
||||||
if (!is_resource($process)) {
|
|
||||||
unlink($tempFile);
|
|
||||||
throw new Exception('Failed to execute sandboxed JavaScript code.');
|
|
||||||
}
|
|
||||||
|
|
||||||
$stdout = stream_get_contents($pipes[1]);
|
|
||||||
fclose($pipes[1]);
|
|
||||||
|
|
||||||
$stderr = stream_get_contents($pipes[2]);
|
|
||||||
fclose($pipes[2]);
|
|
||||||
|
|
||||||
$exitCode = proc_close($process);
|
|
||||||
|
|
||||||
unlink($tempFile);
|
|
||||||
|
|
||||||
return $exitCode;
|
|
||||||
}
|
|
||||||
Loading…
x
Reference in New Issue
Block a user