separated JavaScript and TypeScript export,

added AGENTS.md for AI bot
This commit is contained in:
2026-02-13 09:54:08 +01:00
parent fab8efd780
commit d258bcc919
8 changed files with 288 additions and 117 deletions

View File

@ -1,3 +1,39 @@
<?php
$mapType = function (?string $type): string {
if (!is_string($type) || $type === '') {
return 'unknown';
}
$type = strtolower(ltrim($type, '\\'));
return match ($type) {
'int', 'integer', 'float', 'double' => 'number',
'string' => 'string',
'bool', 'boolean' => 'boolean',
'array', 'iterable' => 'unknown[]',
'object', 'stdclass' => 'Record<string, unknown>',
'mixed', 'resource' => 'unknown',
'null', 'void' => 'null',
'scalar' => 'string | number | boolean',
'callable', 'closure' => '(...args: unknown[]) => unknown',
'never' => 'never',
default => 'unknown',
};
};
$mapUnionType = function (mixed $type) use ($mapType): string {
if (is_array($type)) {
$parts = array();
foreach ($type as $singleType) {
$parts[] = $mapType(is_string($singleType) ? $singleType : null);
}
$parts = array_values(array_unique($parts));
return empty($parts) ? 'unknown' : implode(' | ', $parts);
}
return $mapType(is_string($type) ? $type : null);
};
?>
/**
* Generated by APIlite
* https://gitea.tpsoft.org/TPsoft.org/APIlite
@ -5,64 +41,117 @@
* <?php echo date('Y-m-d H:i:s'); ?>
*/
class <?php echo $this->apiName; ?> {
endpoint = <?php echo sprintf(substr($this->endpoint, 0, 4) == 'http' ? '"%s"' : '%s', $this->endpoint); ?>;
export interface APIliteActionResponse<T> {
status: 'OK';
data: T;
}
/* ----------------------------------------------------
* General API call
*/
call(method, data, callback) {
var xhttp = new XMLHttpRequest();
export interface APIliteErrorResponse {
status: 'ERROR';
msg: string;
}
export interface APIliteMethodParam {
name: string;
type: string | null;
optional: boolean;
default: unknown;
doc: string | null;
}
export interface APIliteMethodDoc {
name: string;
doc: string | null;
description: string | null;
params: APIliteMethodParam[];
return: string | string[] | null;
}
export interface APIliteHelpResponse {
name: string;
html_version: string;
javascript_version: string;
typescript_version: string;
actions: APIliteMethodDoc[];
}
class <?php echo $this->apiName; ?> {
endpoint: string = <?php echo sprintf(substr($this->endpoint, 0, 4) == 'http' ? '"%s"' : '%s', $this->endpoint); ?>;
private call(
method: string,
data: Record<string, unknown>,
callback: (response: APIliteHelpResponse | APIliteActionResponse<unknown> | APIliteErrorResponse) => void
): void {
const 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));
if (this.readyState === 4) {
if (this.status === 200) {
const response = JSON.parse(this.responseText) as APIliteHelpResponse | APIliteActionResponse<unknown> | APIliteErrorResponse;
callback(response);
} else {
if (callback != null) callback({'status': 'ERROR', 'message': 'HTTP STATUS ' + this.status});
callback({ status: 'ERROR', msg: '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);
};
const formData = new FormData();
Object.keys(data).forEach((key) => {
const rawValue = data[key];
if (typeof rawValue === 'undefined') {
return;
}
let value: string | Blob;
if (rawValue instanceof Blob) {
value = rawValue;
} else if (typeof rawValue === 'object' && rawValue !== null) {
value = JSON.stringify(rawValue);
} else {
value = String(rawValue);
}
formData.append(key, value);
});
xhttp.open('POST', this.endpoint + '?action=' + method);
xhttp.send(form_data);
xhttp.send(formData);
}
callPromise(method, data) {
return new Promise((resolve, reject) => {
this.call(method, data, function(response) {
if (method == '__HELP__') {
resolve(response);
private callPromise<T>(method: string, data: Record<string, unknown>): Promise<T> {
return new Promise<T>((resolve, reject) => {
this.call(method, data, (response) => {
if (method === '__HELP__') {
resolve(response as T);
return;
}
if (response.status == 'OK') {
resolve(response.data);
} else {
reject(response.msg);
if (response.status === 'OK') {
resolve(response.data as T);
return;
}
reject(response.msg);
});
})
});
}
/* ----------------------------------------------------
* API actions
*/
help() {
return this.callPromise('__HELP__', {});
help(): Promise<APIliteHelpResponse> {
return this.callPromise<APIliteHelpResponse>('__HELP__', {});
}
<?php if (is_array($this->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";
$paramsSignature = array();
$paramsPayload = array();
foreach ($method['params'] as $param) {
$paramType = $mapType($param['type']);
$paramsSignature[] = $param['name'] . ($param['optional'] ? '?' : '') . ': ' . $paramType;
$paramsPayload[] = $param['name'];
}
$returnType = $mapUnionType($method['return']);
?>
<?php echo $method['name']; ?>(<?php echo implode(', ', $paramsSignature); ?>): Promise<APIliteActionResponse<<?php echo $returnType; ?>>> {
return this.callPromise<APIliteActionResponse<<?php echo $returnType; ?>>>('<?php echo $method['name']; ?>', { <?php echo implode(', ', $paramsPayload); ?> });
}
};
<?php } ?>
}
export default new <?php echo $this->apiName; ?>();