Convert `Ajax` to TypeScript
authorAlexander Ebert <ebert@woltlab.com>
Fri, 16 Oct 2020 23:28:55 +0000 (01:28 +0200)
committerTim Düsterhus <duesterhus@woltlab.com>
Wed, 28 Oct 2020 11:30:09 +0000 (12:30 +0100)
Moved the interfaces and types into a separate file to prevent a circular dependency.

global.d.ts
package-lock.json [new file with mode: 0644]
wcfsetup/install/files/js/WoltLabSuite/Core/Ajax.js
wcfsetup/install/files/js/WoltLabSuite/Core/Ajax/Data.js [new file with mode: 0644]
wcfsetup/install/files/ts/WoltLabSuite/Core/Ajax.ts [new file with mode: 0644]
wcfsetup/install/files/ts/WoltLabSuite/Core/Ajax/Data.ts [new file with mode: 0644]
wcfsetup/install/files/ts/WoltLabSuite/Core/Ajax/Request.ts

index 0410faf60a49c44f47eac4af15a4d16aefc2684d..70ad473efc776ec4d983b98f77de7cf104656206 100644 (file)
@@ -6,6 +6,7 @@ declare global {
   interface Window {
     Devtools?: typeof Devtools;
     ENABLE_DEBUG_MODE: boolean;
+    SECURITY_TOKEN: string;
     WCF_PATH: string;
     WSC_API_URL: string;
 
diff --git a/package-lock.json b/package-lock.json
new file mode 100644 (file)
index 0000000..eed871d
--- /dev/null
@@ -0,0 +1,18 @@
+{
+  "requires": true,
+  "lockfileVersion": 1,
+  "dependencies": {
+    "@types/pica": {
+      "version": "5.1.1",
+      "resolved": "https://registry.npmjs.org/@types/pica/-/pica-5.1.1.tgz",
+      "integrity": "sha512-zSLdgIcZXxqamFwIuogGVM22UwStYhWhHgzXXczW3GwNAv1LZdgL0XYGaufipf/FgB2Jj5jTT0ov0v5TVYnUjA==",
+      "dev": true
+    },
+    "typescript": {
+      "version": "4.0.3",
+      "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.0.3.tgz",
+      "integrity": "sha512-tEu6DGxGgRJPb/mVPIZ48e69xCn2yRmCgYmDugAVwmJ6o+0u1RI18eO7E7WBTLYLaEVVOhwQmcdhQHweux/WPg==",
+      "dev": true
+    }
+  }
+}
index b1a5e26020ddb2f6a09d59b2ac6bccc78d6a1007..822e6fc365452b59fbf4b7251b6224df3a57463e 100644 (file)
 /**
  * Handles AJAX requests.
- * 
- * @author     Alexander Ebert
- * @copyright  2001-2019 WoltLab GmbH
- * @license    GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- * @module     Ajax (alias)
- * @module     WoltLabSuite/Core/Ajax
+ *
+ * @author  Alexander Ebert
+ * @copyright  2001-2019 WoltLab GmbH
+ * @license  GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @module  Ajax (alias)
+ * @module  WoltLabSuite/Core/Ajax
  */
-define(['AjaxRequest', 'Core', 'ObjectMap'], function(AjaxRequest, Core, ObjectMap) {
-       "use strict";
-       
-       var _requests = new ObjectMap();
-       
-       /**
-        * @exports     WoltLabSuite/Core/Ajax
-        */
-       return {
-               /**
-                * Shorthand function to perform a request against the WCF-API with overrides
-                * for success and failure callbacks.
-                * 
-                * @param       {object}                callbackObject  callback object
-                * @param       {object<string, *>=}    data            request data
-                * @param       {function=}             success         success callback
-                * @param       {function=}             failure         failure callback
-                * @return      {AjaxRequest}
-                */
-               api: function(callbackObject, data, success, failure) {
-                       // Fetch AjaxRequest, as it cannot be provided because of a circular dependency
-                       if (AjaxRequest === undefined) AjaxRequest = require('AjaxRequest');
-                       
-                       if (typeof data !== 'object') data = {};
-                       
-                       var request = _requests.get(callbackObject);
-                       if (request === undefined) {
-                               if (typeof callbackObject._ajaxSetup !== 'function') {
-                                       throw new TypeError("Callback object must implement at least _ajaxSetup().");
-                               }
-                               
-                               var options = callbackObject._ajaxSetup();
-                               
-                               options.pinData = true;
-                               options.callbackObject = callbackObject;
-                               
-                               if (!options.url) {
-                                       options.url = 'index.php?ajax-proxy/&t=' + SECURITY_TOKEN;
-                                       options.withCredentials = true;
-                               }
-                               
-                               request = new AjaxRequest(options);
-                               
-                               _requests.set(callbackObject, request);
-                       }
-                       
-                       var oldSuccess = null;
-                       var oldFailure = null;
-                       
-                       if (typeof success === 'function') {
-                               oldSuccess = request.getOption('success');
-                               request.setOption('success', success);
-                       }
-                       if (typeof failure === 'function') {
-                               oldFailure = request.getOption('failure');
-                               request.setOption('failure', failure);
-                       }
-                       
-                       request.setData(data);
-                       request.sendRequest();
-                       
-                       // restore callbacks
-                       if (oldSuccess !== null) request.setOption('success', oldSuccess);
-                       if (oldFailure !== null) request.setOption('failure', oldFailure);
-                       
-                       return request;
-               },
-               
-               /**
-                * Shorthand function to perform a single request against the WCF-API.
-                * 
-                * Please use `Ajax.api` if you're about to repeatedly send requests because this
-                * method will spawn an new and rather expensive `AjaxRequest` with each call.
-                *  
-                * @param       {object<string, *>}     options         request options
-                */
-               apiOnce: function(options) {
-                       // Fetch AjaxRequest, as it cannot be provided because of a circular dependency
-                       if (AjaxRequest === undefined) AjaxRequest = require('AjaxRequest');
-                       
-                       options.pinData = false;
-                       options.callbackObject = null;
-                       if (!options.url) {
-                               options.url = 'index.php?ajax-proxy/&t=' + SECURITY_TOKEN;
-                               options.withCredentials = true;
-                       }
-                       
-                       var request = new AjaxRequest(options);
-                       request.sendRequest(false);
-               },
-               
-               /**
-                * Returns the request object used for an earlier call to `api()`.
-                * 
-                * @param       {Object}        callbackObject  callback object
-                * @return      {AjaxRequest}
-                */
-               getRequestObject: function(callbackObject) {
-                       if (!_requests.has(callbackObject)) {
-                               throw new Error('Expected a previously used callback object, provided object is unknown.');
-                       }
-                       
-                       return _requests.get(callbackObject);
-               }
-       };
+var __importDefault = (this && this.__importDefault) || function (mod) {
+    return (mod && mod.__esModule) ? mod : { "default": mod };
+};
+define(["require", "exports", "./Ajax/Request"], function (require, exports, Request_1) {
+    "use strict";
+    Object.defineProperty(exports, "__esModule", { value: true });
+    exports.getRequestObject = exports.apiOnce = exports.api = void 0;
+    Request_1 = __importDefault(Request_1);
+    const _cache = new WeakMap();
+    /**
+     * Shorthand function to perform a request against the WCF-API with overrides
+     * for success and failure callbacks.
+     */
+    function api(callbackObject, data, success, failure) {
+        if (typeof data !== 'object')
+            data = {};
+        let request = _cache.get(callbackObject);
+        if (request === undefined) {
+            if (typeof callbackObject._ajaxSetup !== 'function') {
+                throw new TypeError("Callback object must implement at least _ajaxSetup().");
+            }
+            const options = callbackObject._ajaxSetup();
+            options.pinData = true;
+            options.callbackObject = callbackObject;
+            if (!options.url) {
+                options.url = 'index.php?ajax-proxy/&t=' + window.SECURITY_TOKEN;
+                options.withCredentials = true;
+            }
+            request = new Request_1.default(options);
+            _cache.set(callbackObject, request);
+        }
+        let oldSuccess = null;
+        let oldFailure = null;
+        if (typeof success === 'function') {
+            oldSuccess = request.getOption('success');
+            request.setOption('success', success);
+        }
+        if (typeof failure === 'function') {
+            oldFailure = request.getOption('failure');
+            request.setOption('failure', failure);
+        }
+        request.setData(data);
+        request.sendRequest();
+        // restore callbacks
+        if (oldSuccess !== null)
+            request.setOption('success', oldSuccess);
+        if (oldFailure !== null)
+            request.setOption('failure', oldFailure);
+        return request;
+    }
+    exports.api = api;
+    /**
+     * Shorthand function to perform a single request against the WCF-API.
+     *
+     * Please use `Ajax.api` if you're about to repeatedly send requests because this
+     * method will spawn an new and rather expensive `AjaxRequest` with each call.
+     */
+    function apiOnce(options) {
+        options.pinData = false;
+        options.callbackObject = null;
+        if (!options.url) {
+            options.url = 'index.php?ajax-proxy/&t=' + window.SECURITY_TOKEN;
+            options.withCredentials = true;
+        }
+        const request = new Request_1.default(options);
+        request.sendRequest(false);
+    }
+    exports.apiOnce = apiOnce;
+    /**
+     * Returns the request object used for an earlier call to `api()`.
+     */
+    function getRequestObject(callbackObject) {
+        if (!_cache.has(callbackObject)) {
+            throw new Error('Expected a previously used callback object, provided object is unknown.');
+        }
+        return _cache.get(callbackObject);
+    }
+    exports.getRequestObject = getRequestObject;
 });
diff --git a/wcfsetup/install/files/js/WoltLabSuite/Core/Ajax/Data.js b/wcfsetup/install/files/js/WoltLabSuite/Core/Ajax/Data.js
new file mode 100644 (file)
index 0000000..2ae92b6
--- /dev/null
@@ -0,0 +1,4 @@
+define(["require", "exports"], function (require, exports) {
+    "use strict";
+    Object.defineProperty(exports, "__esModule", { value: true });
+});
diff --git a/wcfsetup/install/files/ts/WoltLabSuite/Core/Ajax.ts b/wcfsetup/install/files/ts/WoltLabSuite/Core/Ajax.ts
new file mode 100644 (file)
index 0000000..55f0f7b
--- /dev/null
@@ -0,0 +1,93 @@
+/**
+ * Handles AJAX requests.
+ *
+ * @author  Alexander Ebert
+ * @copyright  2001-2019 WoltLab GmbH
+ * @license  GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @module  Ajax (alias)
+ * @module  WoltLabSuite/Core/Ajax
+ */
+
+import AjaxRequest from './Ajax/Request';
+import { CallbackObject, CallbackSuccess, CallbackFailure, RequestData, RequestOptions } from './Ajax/Data';
+
+const _cache = new WeakMap();
+
+/**
+ * Shorthand function to perform a request against the WCF-API with overrides
+ * for success and failure callbacks.
+ */
+export function api(callbackObject: CallbackObject, data: RequestData, success: CallbackSuccess, failure: CallbackFailure): AjaxRequest {
+  if (typeof data !== 'object') data = {};
+
+  let request = _cache.get(callbackObject);
+  if (request === undefined) {
+    if (typeof callbackObject._ajaxSetup !== 'function') {
+      throw new TypeError("Callback object must implement at least _ajaxSetup().");
+    }
+
+    const options = callbackObject._ajaxSetup();
+
+    options.pinData = true;
+    options.callbackObject = callbackObject;
+
+    if (!options.url) {
+      options.url = 'index.php?ajax-proxy/&t=' + window.SECURITY_TOKEN;
+      options.withCredentials = true;
+    }
+
+    request = new AjaxRequest(options);
+
+    _cache.set(callbackObject, request);
+  }
+
+  let oldSuccess = null;
+  let oldFailure = null;
+
+  if (typeof success === 'function') {
+    oldSuccess = request.getOption('success');
+    request.setOption('success', success);
+  }
+  if (typeof failure === 'function') {
+    oldFailure = request.getOption('failure');
+    request.setOption('failure', failure);
+  }
+
+  request.setData(data);
+  request.sendRequest();
+
+  // restore callbacks
+  if (oldSuccess !== null) request.setOption('success', oldSuccess);
+  if (oldFailure !== null) request.setOption('failure', oldFailure);
+
+  return request;
+}
+
+/**
+ * Shorthand function to perform a single request against the WCF-API.
+ *
+ * Please use `Ajax.api` if you're about to repeatedly send requests because this
+ * method will spawn an new and rather expensive `AjaxRequest` with each call.
+ */
+export function apiOnce(options: RequestOptions): void {
+  options.pinData = false;
+  options.callbackObject = null;
+  if (!options.url) {
+    options.url = 'index.php?ajax-proxy/&t=' + window.SECURITY_TOKEN;
+    options.withCredentials = true;
+  }
+
+  const request = new AjaxRequest(options);
+  request.sendRequest(false);
+}
+
+/**
+ * Returns the request object used for an earlier call to `api()`.
+ */
+export function getRequestObject(callbackObject: CallbackObject): AjaxRequest {
+  if (!_cache.has(callbackObject)) {
+    throw new Error('Expected a previously used callback object, provided object is unknown.');
+  }
+
+  return _cache.get(callbackObject);
+}
diff --git a/wcfsetup/install/files/ts/WoltLabSuite/Core/Ajax/Data.ts b/wcfsetup/install/files/ts/WoltLabSuite/Core/Ajax/Data.ts
new file mode 100644 (file)
index 0000000..2422a61
--- /dev/null
@@ -0,0 +1,51 @@
+export interface RequestPayload {
+  [key: string]: any;
+}
+
+export type RequestData = FormData | RequestPayload;
+
+export interface ResponseData {
+  [key: string]: any;
+}
+
+export type CallbackFailure = (data: ResponseData, responseText: string, xhr: XMLHttpRequest, requestData: RequestData) => boolean;
+export type CallbackFinalize = (xhr: XMLHttpRequest) => void;
+export type CallbackProgress = (event: ProgressEvent) => void;
+export type CallbackSuccess = (data: ResponseData, responseText: string, xhr: XMLHttpRequest, requestData: RequestData) => void;
+export type CallbackUploadProgress = (event: ProgressEvent) => void;
+export type CallbackSetup = () => RequestOptions;
+
+export interface CallbackObject {
+  _ajaxFailure?: CallbackFailure;
+  _ajaxFinalize?: CallbackFinalize;
+  _ajaxProgress?: CallbackProgress;
+  _ajaxSuccess: CallbackSuccess;
+  _ajaxUploadProgress?: CallbackUploadProgress;
+  _ajaxSetup: CallbackSetup;
+}
+
+export interface RequestOptions {
+  // request data
+  data?: RequestData,
+  contentType?: string,
+  responseType?: string,
+  type?: string,
+  url?: string,
+  withCredentials?: boolean,
+
+  // behavior
+  autoAbort?: boolean,
+  ignoreError?: boolean,
+  pinData?: boolean,
+  silent?: boolean,
+  includeRequestedWith?: boolean,
+
+  // callbacks
+  failure?: CallbackFailure,
+  finalize?: CallbackFinalize,
+  success?: CallbackSuccess,
+  progress?: CallbackProgress,
+  uploadProgress?: CallbackUploadProgress,
+
+  callbackObject?: CallbackObject | null,
+}
index b8fb545a5ca181480a5524bfbc8e5c3a7bc07d15..1908550872fd1b67336d28fae1734c91a71c4456 100644 (file)
@@ -11,6 +11,7 @@
  */
 
 import * as AjaxStatus from './Status';
+import { ResponseData, RequestOptions, RequestData } from './Data';
 import * as Core from '../Core';
 import DomChangeListener from '../Dom/Change/Listener';
 
@@ -89,7 +90,7 @@ class AjaxRequest {
   /**
    * Dispatches a request, optionally aborting a currently active request.
    */
-  sendRequest(abortPrevious: boolean): void {
+  sendRequest(abortPrevious?: boolean): void {
     if (abortPrevious || this._options.autoAbort) {
       this.abortPrevious();
     }
@@ -346,54 +347,4 @@ class AjaxRequest {
   }
 }
 
-interface RequestPayload {
-  [key: string]: any;
-}
-
-type RequestData = FormData | RequestPayload;
-
-interface ResponseData {
-  [key: string]: any;
-}
-
-type CallbackFailure = (data: ResponseData, responseText: string, xhr: XMLHttpRequest, requestData: RequestData) => boolean;
-type CallbackFinalize = (xhr: XMLHttpRequest) => void;
-type CallbackProgress = (event: ProgressEvent) => void;
-type CallbackSuccess = (data: ResponseData, responseText: string, xhr: XMLHttpRequest, requestData: RequestData) => void;
-type CallbackUploadProgress = (event: ProgressEvent) => void;
-
-interface CallbackObject {
-  _ajaxFailure?: CallbackFailure;
-  _ajaxFinalize?: CallbackFinalize;
-  _ajaxProgress?: CallbackProgress;
-  _ajaxSuccess: CallbackSuccess;
-  _ajaxUploadProgress?: CallbackUploadProgress;
-}
-
-interface RequestOptions {
-  // request data
-  data?: RequestData,
-  contentType?: string,
-  responseType?: string,
-  type?: string,
-  url?: string,
-  withCredentials?: boolean,
-
-  // behavior
-  autoAbort?: boolean,
-  ignoreError?: boolean,
-  pinData?: boolean,
-  silent?: boolean,
-  includeRequestedWith?: boolean,
-
-  // callbacks
-  failure?: CallbackFailure,
-  finalize?: CallbackFinalize,
-  success?: CallbackSuccess,
-  progress?: CallbackProgress,
-  uploadProgress?: CallbackUploadProgress,
-
-  callbackObject?: CallbackObject | null,
-}
-
 export = AjaxRequest;