From 2dd23129f5cee6388f622a38a75eca39e1c918a1 Mon Sep 17 00:00:00 2001
From: Blazej Kustra <blazej.kustra@swmansion.com>
Date: Wed, 21 Feb 2024 17:56:27 +0100
Subject: [PATCH 1/2] Migrate reamaining files to TS

---
 lib/Logger.d.ts                               | 13 ----
 lib/Logger.js                                 | 31 ----------
 lib/Logger.ts                                 | 31 ++++++++++
 lib/Str.js                                    | 27 ---------
 lib/Str.ts                                    | 24 ++++++++
 lib/SyncQueue.js                              | 59 -------------------
 lib/compose.js                                | 34 -----------
 ...eDeferredTask.js => createDeferredTask.ts} | 13 ++--
 8 files changed, 63 insertions(+), 169 deletions(-)
 delete mode 100644 lib/Logger.d.ts
 delete mode 100644 lib/Logger.js
 create mode 100644 lib/Logger.ts
 delete mode 100644 lib/Str.js
 create mode 100644 lib/Str.ts
 delete mode 100644 lib/SyncQueue.js
 delete mode 100644 lib/compose.js
 rename lib/{createDeferredTask.js => createDeferredTask.ts} (61%)

diff --git a/lib/Logger.d.ts b/lib/Logger.d.ts
deleted file mode 100644
index 5c7e4d545..000000000
--- a/lib/Logger.d.ts
+++ /dev/null
@@ -1,13 +0,0 @@
-declare type LogData = {
-    message: string;
-    level: 'alert' | 'info';
-};
-
-/**
- * Register the logging callback
- *
- * @param callback
- */
-declare function registerLogger(callback: (data: LogData) => void): void;
-
-export {registerLogger};
diff --git a/lib/Logger.js b/lib/Logger.js
deleted file mode 100644
index 1cc6240b9..000000000
--- a/lib/Logger.js
+++ /dev/null
@@ -1,31 +0,0 @@
-// Logging callback
-let logger = () => {};
-
-/**
- * Register the logging callback
- *
- * @param {Function} callback
- */
-function registerLogger(callback) {
-    logger = callback;
-}
-
-/**
- * Send an alert message to the logger
- *
- * @param {String} message
- */
-function logAlert(message) {
-    logger({message: `[Onyx] ${message}`, level: 'alert'});
-}
-
-/**
- * Send an info message to the logger
- *
- * @param {String} message
- */
-function logInfo(message) {
-    logger({message: `[Onyx] ${message}`, level: 'info'});
-}
-
-export {registerLogger, logInfo, logAlert};
diff --git a/lib/Logger.ts b/lib/Logger.ts
new file mode 100644
index 000000000..b83df67fb
--- /dev/null
+++ b/lib/Logger.ts
@@ -0,0 +1,31 @@
+type LogData = {
+    message: string;
+    level: 'alert' | 'info';
+};
+type LoggerCallback = (data: LogData) => void;
+
+// eslint-disable-next-line @typescript-eslint/no-empty-function
+let logger: LoggerCallback = () => {};
+
+/**
+ * Register the logging callback
+ */
+function registerLogger(callback: LoggerCallback) {
+    logger = callback;
+}
+
+/**
+ * Send an alert message to the logger
+ */
+function logAlert(message: string) {
+    logger({message: `[Onyx] ${message}`, level: 'alert'});
+}
+
+/**
+ * Send an info message to the logger
+ */
+function logInfo(message: string) {
+    logger({message: `[Onyx] ${message}`, level: 'info'});
+}
+
+export {registerLogger, logInfo, logAlert};
diff --git a/lib/Str.js b/lib/Str.js
deleted file mode 100644
index 71f00f628..000000000
--- a/lib/Str.js
+++ /dev/null
@@ -1,27 +0,0 @@
-import _ from 'underscore';
-
-/**
- * Returns true if the haystack begins with the needle
- *
- * @param {String} haystack  The full string to be searched
- * @param {String} needle    The case-sensitive string to search for
- * @return {Boolean} Returns true if the haystack starts with the needle.
- */
-function startsWith(haystack, needle) {
-    return _.isString(haystack) && _.isString(needle) && haystack.startsWith(needle);
-}
-
-/**
- * Checks if parameter is a string or function.
- * If it is a string, then we will just return it.
- * If it is a function, then we will call it with
- * any additional arguments and return the result.
- *
- * @param {String|Function} parameter
- * @returns {*}
- */
-function result(parameter, ...args) {
-    return _.isFunction(parameter) ? parameter(...args) : parameter;
-}
-
-export {startsWith, result};
diff --git a/lib/Str.ts b/lib/Str.ts
new file mode 100644
index 000000000..bb1429b42
--- /dev/null
+++ b/lib/Str.ts
@@ -0,0 +1,24 @@
+/**
+ * Returns true if the haystack begins with the needle
+ *
+ * @param haystack  The full string to be searched
+ * @param needle    The case-sensitive string to search for
+ * @return Returns true if the haystack starts with the needle.
+ */
+function startsWith(haystack: string, needle: string) {
+    return typeof haystack === 'string' && typeof needle === 'string' && haystack.startsWith(needle);
+}
+
+/**
+ * Checks if parameter is a string or function.
+ * If it is a string, then we will just return it.
+ * If it is a function, then we will call it with
+ * any additional arguments and return the result.
+ */
+function result(parameter: string): string;
+function result<TFunction extends (...a: TArgs) => unknown, TArgs extends unknown[]>(parameter: TFunction, ...args: TArgs): ReturnType<TFunction>;
+function result<TFunction extends (...a: TArgs) => unknown, TArgs extends unknown[]>(parameter: TFunction, ...args: TArgs): ReturnType<TFunction> | string {
+    return typeof parameter === 'function' ? (parameter(...args) as ReturnType<TFunction>) : parameter;
+}
+
+export {startsWith, result};
diff --git a/lib/SyncQueue.js b/lib/SyncQueue.js
deleted file mode 100644
index baf5e5691..000000000
--- a/lib/SyncQueue.js
+++ /dev/null
@@ -1,59 +0,0 @@
-/**
- * Synchronous queue that can be used to ensure promise based tasks are run in sequence.
- * Pass to the constructor a function that returns a promise to run the task then add data.
- *
- * @example
- *
- *     const queue = new SyncQueue(({key, val}) => {
- *         return someAsyncProcess(key, val);
- *     });
- *
- *     queue.push({key: 1, val: '1'});
- *     queue.push({key: 2, val: '2'});
- */
-export default class SyncQueue {
-    /**
-     * @param {Function} run - must return a promise
-     */
-    constructor(run) {
-        this.queue = [];
-        this.isProcessing = false;
-        this.run = run;
-    }
-
-    /**
-     * Stop the queue from being processed and clear out any existing tasks
-     */
-    abort() {
-        this.queue = [];
-        this.isProcessing = false;
-    }
-
-    process() {
-        if (this.isProcessing || this.queue.length === 0) {
-            return;
-        }
-
-        this.isProcessing = true;
-
-        const {data, resolve, reject} = this.queue.shift();
-        this.run(data)
-            .then(resolve)
-            .catch(reject)
-            .finally(() => {
-                this.isProcessing = false;
-                this.process();
-            });
-    }
-
-    /**
-     * @param {*} data
-     * @returns {Promise}
-     */
-    push(data) {
-        return new Promise((resolve, reject) => {
-            this.queue.push({resolve, reject, data});
-            this.process();
-        });
-    }
-}
diff --git a/lib/compose.js b/lib/compose.js
deleted file mode 100644
index 702f3683c..000000000
--- a/lib/compose.js
+++ /dev/null
@@ -1,34 +0,0 @@
-/**
- * This is a utility function taken directly from Redux. (We don't want to add Redux as a dependency)
- * It enables functional composition, useful for the chaining/composition of HOCs.
- *
- * For example, instead of:
- *
- * export default hoc1(config1, hoc2(config2, hoc3(config3)))(Component);
- *
- * Use this instead:
- *
- * export default compose(
- *     hoc1(config1),
- *     hoc2(config2),
- *     hoc3(config3),
- * )(Component)
- *
- * @returns {Function}
- */
-export default function compose(...funcs) {
-    if (funcs.length === 0) {
-        return (arg) => arg;
-    }
-
-    if (funcs.length === 1) {
-        return funcs[0];
-    }
-
-    // eslint-disable-next-line rulesdir/prefer-underscore-method
-    return funcs.reduce(
-        (a, b) =>
-            (...args) =>
-                a(b(...args)),
-    );
-}
diff --git a/lib/createDeferredTask.js b/lib/createDeferredTask.ts
similarity index 61%
rename from lib/createDeferredTask.js
rename to lib/createDeferredTask.ts
index b5b2e308a..81610e2bc 100644
--- a/lib/createDeferredTask.js
+++ b/lib/createDeferredTask.ts
@@ -1,13 +1,16 @@
+type DeferredTask = {
+    promise: Promise<unknown>;
+    resolve: (value: unknown) => void;
+};
+
 /**
  * Create a deferred task that can be resolved when we call `resolve()`
  * The returned promise will complete when we call `resolve`
  * Useful when we want to wait for a tasks that is resolved from an external action
- *
- * @template T
- * @returns {{ resolve: function(*), promise: Promise<T|void> }}
  */
-export default function createDeferredTask() {
-    const deferred = {};
+export default function createDeferredTask(): DeferredTask {
+    const deferred: DeferredTask = {} as DeferredTask;
+
     deferred.promise = new Promise((res) => {
         deferred.resolve = res;
     });

From 39768e58ed95c1b72ae8f4a2f31ea0796d608d17 Mon Sep 17 00:00:00 2001
From: Blazej Kustra <blazej.kustra@swmansion.com>
Date: Thu, 29 Feb 2024 11:48:06 +0100
Subject: [PATCH 2/2] Fix after review

---
 lib/createDeferredTask.ts | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/lib/createDeferredTask.ts b/lib/createDeferredTask.ts
index 81610e2bc..3d37c91f3 100644
--- a/lib/createDeferredTask.ts
+++ b/lib/createDeferredTask.ts
@@ -1,6 +1,6 @@
 type DeferredTask = {
-    promise: Promise<unknown>;
-    resolve: (value: unknown) => void;
+    promise: Promise<void>;
+    resolve?: () => void;
 };
 
 /**
@@ -9,7 +9,7 @@ type DeferredTask = {
  * Useful when we want to wait for a tasks that is resolved from an external action
  */
 export default function createDeferredTask(): DeferredTask {
-    const deferred: DeferredTask = {} as DeferredTask;
+    const deferred = {} as DeferredTask;
 
     deferred.promise = new Promise((res) => {
         deferred.resolve = res;
