'number', 'string' => 'string', 'bool', 'boolean' => 'boolean', 'array', 'iterable' => 'unknown[]', 'object', 'stdclass' => 'Record', '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); }; $normalizeTypeStructures = function (mixed $structure): array { if (!is_array($structure)) { return array(); } if (array_key_exists('type', $structure) && array_key_exists('properties', $structure)) { return array($structure); } return array_values(array_filter($structure, 'is_array')); }; $findTypeStructure = function (?string $type, mixed $structure) use ($normalizeTypeStructures): array|null { if (!is_string($type) || $type === '') { return null; } $type = ltrim($type, '\\'); foreach ($normalizeTypeStructures($structure) as $one_structure) { if (($one_structure['type'] ?? null) === $type) { return $one_structure; } } return null; }; $mapTypeWithStructure = null; $mapUnionTypeWithStructure = null; $mapTypeWithStructure = function (?string $type, mixed $structure) use ($mapType, &$mapUnionTypeWithStructure): string { if (is_array($structure) && array_key_exists('type', $structure) && array_key_exists('properties', $structure)) { $properties = array(); foreach (($structure['properties'] ?? array()) as $property) { if (!is_array($property) || !isset($property['name'])) { continue; } $propertyType = $mapUnionTypeWithStructure($property['type'] ?? null, $property['type_structure'] ?? null); if (!empty($property['nullable']) && strpos($propertyType, 'null') === false) { $propertyType .= ' | null'; } $properties[] = $property['name'] . ': ' . $propertyType; } return empty($properties) ? 'Record' : '{ ' . implode('; ', $properties) . ' }'; } return $mapType($type); }; $mapUnionTypeWithStructure = function (mixed $type, mixed $structure) use ($mapType, $findTypeStructure, &$mapTypeWithStructure): string { if (is_array($type)) { $parts = array(); foreach ($type as $singleType) { $typeName = is_string($singleType) ? $singleType : null; $parts[] = $mapTypeWithStructure($typeName, $findTypeStructure($typeName, $structure)); } $parts = array_values(array_unique($parts)); return empty($parts) ? 'unknown' : implode(' | ', $parts); } return $mapTypeWithStructure(is_string($type) ? $type : null, $structure); }; ?> /** * Generated by APIlite * https://gitea.tpsoft.org/TPsoft.org/APIlite * * */ export interface APIliteActionResponse { status: 'OK'; data: T; msg: string; } 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; return_structure: APIliteTypeStructure | APIliteTypeStructure[] | null; } export interface APIliteTypeStructureProperty { name: string; type: string | string[] | null; nullable: boolean; type_structure: APIliteTypeStructure | APIliteTypeStructure[] | null; } export interface APIliteTypeStructure { type: string; recursive?: boolean; properties: APIliteTypeStructureProperty[]; } export interface APIliteHelpResponse { name: string; html_version: string; javascript_version: string; typescript_version: string; actions: APIliteMethodDoc[]; status: string; data: string; msg: string; } type APIliteRequestHeaders = Partial>; class apiName; ?> { endpoint: string = endpoint, 0, 4) == 'http' ? '"%s"' : '%s', $this->endpoint); ?>; private readonly bearerStorageKey: string = 'apilite_bearer_token'; private normalizeBearerToken(token: string | null | undefined): string | null { if (typeof token !== 'string') { return null; } const normalizedToken = token.trim(); return normalizedToken === '' ? null : normalizedToken; } private getStorage(): Storage | null { try { if (typeof window !== 'undefined' && typeof window.localStorage !== 'undefined') { return window.localStorage; } } catch { return null; } return null; } private getBearerToken(): string | null { const storage = this.getStorage(); if (storage === null) { return null; } return this.normalizeBearerToken(storage.getItem(this.bearerStorageKey)); } private getRequestHeaders(headers: APIliteRequestHeaders = {}): APIliteRequestHeaders { const requestHeaders: APIliteRequestHeaders = { ...headers }; if (typeof requestHeaders.Authorization === 'undefined') { const token = this.getBearerToken(); if (token !== null) { requestHeaders.Authorization = `Bearer ${token}`; } } return requestHeaders; } private applyHeaders(xhttp: XMLHttpRequest, headers: APIliteRequestHeaders): void { Object.keys(headers).forEach((key) => { const value = headers[key]; if (typeof value === 'undefined' || value === null) { return; } xhttp.setRequestHeader(key, value); }); } bearerSet(token: string | null): void { const storage = this.getStorage(); if (storage === null) { return; } const normalizedToken = this.normalizeBearerToken(token); if (normalizedToken === null) { storage.removeItem(this.bearerStorageKey); return; } storage.setItem(this.bearerStorageKey, normalizedToken); } private call( method: string, data: Record, callback: (response: APIliteHelpResponse | APIliteActionResponse | APIliteErrorResponse) => void ): void { const xhttp = new XMLHttpRequest(); const headers = this.getRequestHeaders(); xhttp.withCredentials = true; xhttp.onreadystatechange = function() { if (this.readyState === 4) { if (this.status === 200) { const response = JSON.parse(this.responseText) as APIliteHelpResponse | APIliteActionResponse | APIliteErrorResponse; callback(response); } else { callback({ status: 'ERROR', msg: 'HTTP STATUS ' + this.status }); } } }; 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); this.applyHeaders(xhttp, headers); xhttp.send(formData); } private callPromise(method: string, data: Record): Promise { return new Promise((resolve, reject) => { this.call(method, data, (response) => { if (method === '__HELP__') { resolve(response as T); return; } if (response.status === 'OK') { resolve(response.data as T); return; } reject(response.msg); }); }); } help(): Promise { return this.callPromise('__HELP__', {}); } methods)) foreach ($this->methods as $method) { $paramsSignature = array(); $paramsPayload = array(); foreach ($method['params'] as $param) { $paramType = $mapType($param['type']); $paramsSignature[] = $param['name'] . ($param['optional'] ? '?' : '') . ': ' . $paramType; $paramsPayload[] = $param['name']; } $returnType = $mapUnionTypeWithStructure($method['return'], $method['return_structure'] ?? null); ?> (): Promise>> { return this.callPromise>>('', { }); } } export default new apiName; ?>();