From ab7bd573621c4d7fd095b190dce89086866ad979 Mon Sep 17 00:00:00 2001 From: igor Date: Wed, 28 May 2025 13:05:09 +0200 Subject: [PATCH] added generator for TypeScript backend --- src/APIlite.php | 15 ++++++++++ src/help.tpl.php | 21 ++++++++++++-- src/typescript.tpl.php | 62 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 96 insertions(+), 2 deletions(-) create mode 100644 src/typescript.tpl.php diff --git a/src/APIlite.php b/src/APIlite.php index e2a7149..0460714 100644 --- a/src/APIlite.php +++ b/src/APIlite.php @@ -29,6 +29,8 @@ class APIlite } else { if (isset($_REQUEST['format']) && $_REQUEST['format'] == 'html') { $this->printHelpHTML(); + } elseif (isset($_REQUEST['format']) && $_REQUEST['format'] == 'typescript') { + $this->printHelpTypescript(); } else { $this->printHelpJSON(); } @@ -148,6 +150,7 @@ class APIlite $this->response(array( 'name' => $this->apiName, 'html_version' => $this->getCurrentUrl().'?format=html', + 'typescript_version' => $this->getCurrentUrl().'?format=typescript', 'actions' => $this->methods )); } @@ -157,6 +160,14 @@ class APIlite include __DIR__ . '/help.tpl.php'; } + private function printHelpTypescript(): void + { + ob_clean(); + header('Content-Type: application/javascript'); + header('Content-Disposition: attachment; filename="' . $this->apiName . '.js"'); + include __DIR__ . '/typescript.tpl.php'; + } + private function getCurrentUrl(): string { $protocol = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off' || $_SERVER['SERVER_PORT'] == 443) ? "https://" : "http://"; @@ -178,6 +189,10 @@ class APIlite private function doAction(string $action): void { + if ($action == '__HELP__') { + $this->printHelpJSON(); + return; + } $method = $this->getMethod($action); if (is_null($method)) { $this->responseERROR('Action "' . $action . '" not found'); diff --git a/src/help.tpl.php b/src/help.tpl.php index 6ccfae7..0602b46 100644 --- a/src/help.tpl.php +++ b/src/help.tpl.php @@ -182,6 +182,14 @@ margin-left: 0.5rem; } + /* Footer */ + .footer { + background-color: #F4F5F8; + padding: 2rem 0; + text-align: center; + margin-top: 3rem; + } + /* Responsive design */ @media (max-width: 768px) { .container { @@ -253,8 +261,8 @@ @@ -303,6 +311,15 @@ + + + diff --git a/src/typescript.tpl.php b/src/typescript.tpl.php new file mode 100644 index 0000000..5da2739 --- /dev/null +++ b/src/typescript.tpl.php @@ -0,0 +1,62 @@ +/** + * Generated by APIlite + * https://gitea.tpsoft.org/TPsoft.org/APIlite + * + * + */ + +export const backend = { + endpont: window.location.origin + "apiName; ?>.php", + + /* ---------------------------------------------------- + * General API call + */ + call(method, data, callback) { + var xhttp = new XMLHttpRequest(); + xhttp.withCredentials = true; + xhttp.onreadystatechange = function() { + if (this.readyState == 4) { + if (this.status == 200) { + if (callback != null) callback(JSON.parse(this.responseText)); + } else { + if (callback != null) callback({'status': 'ERROR', 'message': 'HTTP STATUS ' + this.status}); + } + } + } + var form_data = new FormData(); + Object.keys(data).forEach(key => { + let val = data[key]; + if (typeof val == 'object') val = JSON.stringify(val); + form_data.append(key, val); + }); + xhttp.open('POST', this.endpont + '?action=' + method); + xhttp.send(form_data); + }, + + callPromise(method, data) { + return new Promise((resolve, reject) => { + this.call(method, data, function(response) { + if (response.status == 'OK') { + resolve(response.data); + } else { + reject(response.msg); + } + }); + }) + }, + + /* ---------------------------------------------------- + * API actions + */ + help() { + return this.callPromise('__HELP__', {}); + }, + +methods)) foreach ($this->methods as $method) { + echo "\t".$method['name'].'('.implode(', ', array_map(function($param) { return $param['name']; }, $method['params'])).') {'; + echo "\n\t\treturn this.callPromise('".$method['name']."', {".implode(', ', array_map(function($param) { return $param['name'].': '.$param['name']; }, $method['params']))."});"; + echo "\n\t},\n\n"; + } +?> + +};