ferric-oxide 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,225 @@
1
+ # Rust like utils for typescript
2
+
3
+ Rust is famous for its exceptional design choices that helps reduce some class of bugs beforehand. It also force us to wrtite good code. You can now taste these features in typesriupt too.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm i @mr-m1m3/rusts
9
+ ```
10
+
11
+ ## Usage
12
+
13
+ Basically rusts exports classes that implements spceific rust standard library modules.
14
+
15
+ Currently rusts exports following classes:
16
+
17
+ * [Maybe](#Maybe) (`Option<T>` equivalent of rust)
18
+ * [Result](#Result)
19
+
20
+ #### Maybe `<T>`
21
+
22
+ Basically a wrapper around `null`. Use it when a value can either be something or nothing.
23
+
24
+ ```typescript
25
+
26
+ import {Maybe} from "@mr-m1m3/rusts";
27
+
28
+ // contains some value
29
+ const maybe_a_number = new Maybe(100);
30
+
31
+ // doesn't contain value
32
+ const or_maybe_not = new Maybe(null);
33
+
34
+ // methods
35
+ /*
36
+ * .is_value() -> returns `true` because it contains a value otherwise resturns false
37
+ */
38
+ maybe_a_number.is_value(); // true
39
+ or_maybe_not.is_value(); //false
40
+
41
+ /*
42
+ * is_not_a_value() -> opposite of .is_value()
43
+ */
44
+ or_maybe_not.is_not_a_value(); // true
45
+ maybe_a_number.is_not_a_value(); // false
46
+
47
+ /*
48
+ * .unwrap() -> returns the value if it contains any or throws if it doesn't
49
+ */
50
+ maybe_a_number.unwrap(); // 100
51
+ or_maybe_not.unwrap(); // throws
52
+
53
+
54
+ /*
55
+ * .expect(msg: string) -> same as .unwrap() but you can specify a message to be displayed as error
56
+ */
57
+ maybe_a_number.expect('oops!'); // logs: 100
58
+ or_maybe_not.expect('oops!'); // throws an error showing: oops!
59
+
60
+
61
+ /*
62
+ * .unwrap_or(default: T) -> returns the value if it contains any; provided default if it doesn't
63
+ */
64
+ maybe_a_number.unwrap_or(420); // 100
65
+ or_maybe_not.unwrap_or(420); // 420
66
+
67
+ /*
68
+ * .unwrap_or_else(fn: () => T) -> same as .unwrap_or() but takes a function calulate the default value
69
+ */
70
+ maybe_a_number.unwrap_or_else(() => Math.random() * 15); // 100
71
+ or_maybe_not.unwrap_or_else(() => Math.random() * 15); // a random number
72
+
73
+ /*
74
+ * .map() -> converts `Maybe` of one type to Maybe of another type.
75
+ */
76
+ maybe_a_number.map((n) => `number is one hundred`); // Maybe<string>
77
+ or_maybe_not.map((n) => `contains null`); // Maybe<string>
78
+
79
+
80
+ /*
81
+ * .transform(fn: (T) => U) -> transform the whole Maybe<T> to another type
82
+ */
83
+
84
+ maybe_a_number.transform((val) => {
85
+ if(val.is_value()){
86
+ return {
87
+ is_value: true
88
+ }
89
+ }else{
90
+ return {
91
+ is_value: false
92
+ }
93
+ }
94
+ }); // {is_value: true}
95
+ ```
96
+
97
+ #### Result `<T, E>`
98
+
99
+ typescript equivalent of rust `Result<T, E>`. It is use extensively in error handling. If a function can fail, it should always return `Result<T, E>` instead of throwing. Whoever calling the function should be the one to decide what to do with it. This approach also helps easily type a function that can fail. It takes advantage of typescript\'s discriminated union. Here, `T` represents the expected value and `E` represent the value if something happens really bad.
100
+
101
+ You can call two static methods from this function.
102
+
103
+ - `Result.Ok(expected_val)` returns an instance that contains the value we expect when all went well.
104
+ - `Result.Err(err_val)` returns an instance that contains the value that will be returned when an error happens.
105
+
106
+ Imagine, you have a function that looks like this:
107
+
108
+ ```typescript
109
+ function could_fail(): Data{
110
+ //..//
111
+ if(condition){
112
+ return {/*...*/}
113
+ }
114
+ throw Error(/**/);
115
+ }
116
+ ```
117
+
118
+ However, the caller can't really tell beforehand that this function can throw. Also, it is now difficult to return organized error details to the caller. What we can do now is use `Result<Data, ErrMsg>`. What we are expressing is that the function can return either of type `Data` or `ErrMsg` and the caller must check explicitely before using the value. Now, inside the function body, we return `Result.Ok(data: Data)` and instead of throwing, we return `Result.Err(err_msg: ErrMsg)`.
119
+
120
+ ```typescript
121
+ function could_fail(): Result<Data, ErrMsg>{
122
+ //..//
123
+ if(condition){
124
+ return Result.Ok({/*...*/});
125
+ }
126
+ throw Result.Err({/**/});
127
+ }
128
+ ```
129
+
130
+ The instance comes with some useful methods:
131
+
132
+ ```typescript
133
+ import Result from "@mr-m1m3/rusts/result";
134
+
135
+ type Data = {
136
+ name: string;
137
+ age: number;
138
+ };
139
+ type ErrMsg = {
140
+ msg: string;
141
+ status: number;
142
+ };
143
+
144
+ // +-------> ok variant or the value of a successfull operation
145
+ // | +-----> error variant or the value of a failed operation
146
+ // | |
147
+ // Result<T, E>
148
+
149
+ const ok_variant: Result<Data, ErrMsg> = Result.Ok({
150
+ name: "John Doe",
151
+ age: 30,
152
+ });
153
+
154
+ const err_variant: Result<Data, ErrMsg> = Result.Err({
155
+ msg: "oops!",
156
+ status: 500,
157
+ });
158
+
159
+ /**
160
+ * .is_ok() -> returns true if the instance contains the value of a successfull operation aka if it was instantiated with Result.Ok();
161
+ */
162
+ ok_variant.is_ok(); // true
163
+ err_variant.is_ok(); // false
164
+
165
+ /**
166
+ * .is_error() -> returns true if the instance contains the value of a failed operation aka if it was instantiated with Result.Err();
167
+ */
168
+ ok_variant.is_error(); // false
169
+ err_variant.is_error(); // true
170
+
171
+ /*
172
+ * .ok_value() -> returns Maybe<T>.
173
+ */
174
+ ok_variant.ok_value();
175
+ err_variant.ok_value();
176
+
177
+ /*
178
+ * .err_value() -> returns Maybe<E>.
179
+ */
180
+ ok_variant.err_value();
181
+ err_variant.err_value();
182
+
183
+ /*
184
+ * .map<U, Q>(
185
+ ok_mapper: (ok_val: T) => U,
186
+ err_mapper: (err_val: E) => Q,
187
+ ) -> converts to another instcance of Result that has `U` as Ok variant and `Q` as Error variant
188
+ calls first callback with the ok value to get the new ok value if exists otherwise calls second callback with error value to get the new error value.
189
+ returned Result variant will be an ok variant if it itself is the ok variant.
190
+ */
191
+ ok_variant.map(
192
+ (ok_val) => "mission passed",
193
+ (error_val) => 0,
194
+ ); // Result<string, number>
195
+ err_variant.map(
196
+ (ok_val) => new Date(),
197
+ (error_val) => "aura ---",
198
+ ); // Result<Date, string>
199
+
200
+ /**
201
+ * .map_ok<U>((ok_val) => U) -> same as .map() but only takes in one callback that is called with ok value to get the new ok value
202
+ returned Result contains the same error value as it itself contains
203
+ */
204
+ ok_variant.map_ok((ok_val) => "mission passed"); // Result<string, ErrMsg>
205
+ err_variant.map_ok((ok_val) => "mission passed"); // Result<string, ErrMsg>
206
+
207
+ /**
208
+ * .map_err<Q>((ok_val) => Q) -> same as .map() but only takes in one callback that is called with error value to get the new error value
209
+ returned Result contains the same ok value as it itself contains
210
+ */
211
+ ok_variant.map_err((err_val) => "mission failed"); // Result<Data, string>
212
+ err_variant.map_err((err_val) => "mission failed"); // Result<Data, string>
213
+
214
+ /*
215
+ * .transform(callback) -> transformsthe entire Result instance to another type and returns. applies the provided callback on the instance to get the new type.
216
+ */
217
+
218
+ ok_variant.transform((result_instnce) => {
219
+ return {
220
+ is_ok: result_instnce.is_ok(),
221
+ is_error: result_instnce.is_error(),
222
+ };
223
+ }); // {is_ok: true, is_error: false}
224
+
225
+ ```
package/dist/index.js ADDED
@@ -0,0 +1,4 @@
1
+ import Maybe from "./maybe/maybe.js";
2
+ import Result from "./result/result.js";
3
+ export { Maybe, Result };
4
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,kBAAkB,CAAC;AACrC,OAAO,MAAM,MAAM,oBAAoB,CAAC;AACxC,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC"}
@@ -0,0 +1,51 @@
1
+ export default class Maybe {
2
+ constructor(val = null) {
3
+ this.value = val;
4
+ }
5
+ //useful methods
6
+ is_value() {
7
+ if (this.value === null) {
8
+ return false;
9
+ }
10
+ else {
11
+ return true;
12
+ }
13
+ }
14
+ is_not_a_value() {
15
+ return !this.is_value();
16
+ }
17
+ expect(msg) {
18
+ if (this.is_value()) {
19
+ return this.value;
20
+ }
21
+ else {
22
+ throw new Error(msg);
23
+ }
24
+ }
25
+ unwrap() {
26
+ return this.expect('Expected a value but didnt get one.');
27
+ }
28
+ unwrap_or(def) {
29
+ if (this.is_value()) {
30
+ return this.value;
31
+ }
32
+ else {
33
+ return def;
34
+ }
35
+ }
36
+ unwrap_or_else(fn) {
37
+ return this.unwrap_or(fn());
38
+ }
39
+ map(fn) {
40
+ if (this.is_value()) {
41
+ return new Maybe(fn(this.value));
42
+ }
43
+ else {
44
+ return new Maybe(null);
45
+ }
46
+ }
47
+ transform(fn) {
48
+ return fn(this);
49
+ }
50
+ }
51
+ //# sourceMappingURL=maybe.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"maybe.js","sourceRoot":"","sources":["../../src/maybe/maybe.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,OAAO,OAAO,KAAK;IAGxB,YAAY,MAAgB,IAAI;QAC9B,IAAI,CAAC,KAAK,GAAG,GAAG,CAAC;IACnB,CAAC;IACD,gBAAgB;IACT,QAAQ;QACb,IAAI,IAAI,CAAC,KAAK,KAAK,IAAI,EAAE,CAAC;YACxB,OAAO,KAAK,CAAC;QACf,CAAC;aAAM,CAAC;YACN,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;IACM,cAAc;QACnB,OAAO,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC;IAC1B,CAAC;IACM,MAAM,CAAC,GAAW;QACvB,IAAI,IAAI,CAAC,QAAQ,EAAE,EAAE,CAAC;YACpB,OAAO,IAAI,CAAC,KAAU,CAAC;QACzB,CAAC;aAAM,CAAC;YACN,MAAM,IAAI,KAAK,CAAC,GAAG,CAAC,CAAC;QACvB,CAAC;IACH,CAAC;IACM,MAAM;QACX,OAAO,IAAI,CAAC,MAAM,CAAC,qCAAqC,CAAC,CAAA;IAC3D,CAAC;IACM,SAAS,CAAC,GAAM;QACrB,IAAI,IAAI,CAAC,QAAQ,EAAE,EAAE,CAAC;YACpB,OAAO,IAAI,CAAC,KAAU,CAAC;QACzB,CAAC;aAAM,CAAC;YACN,OAAO,GAAG,CAAC;QACb,CAAC;IACH,CAAC;IACM,cAAc,CAAC,EAAW;QAC/B,OAAO,IAAI,CAAC,SAAS,CAAC,EAAE,EAAE,CAAC,CAAA;IAC7B,CAAC;IACM,GAAG,CAAI,EAAe;QAC3B,IAAI,IAAI,CAAC,QAAQ,EAAE,EAAE,CAAC;YACpB,OAAO,IAAI,KAAK,CAAI,EAAE,CAAC,IAAI,CAAC,KAAU,CAAC,CAAC,CAAC;QAC3C,CAAC;aAAM,CAAC;YACN,OAAO,IAAI,KAAK,CAAI,IAAI,CAAC,CAAC;QAC5B,CAAC;IACH,CAAC;IACM,SAAS,CAAK,EAA6B;QAChD,OAAO,EAAE,CAAC,IAAI,CAAC,CAAC;IAClB,CAAC;CACF"}
@@ -0,0 +1,81 @@
1
+ import { describe, test, expect } from "vitest";
2
+ import { Maybe } from "@/index.js";
3
+ const has_value = new Maybe("value");
4
+ const not_a_value = new Maybe(null);
5
+ describe("Maybe<T>", () => {
6
+ describe(".is_value()", () => {
7
+ test("should be true", () => {
8
+ expect.soft(has_value.is_value()).toBe(true);
9
+ });
10
+ test("should be false", () => {
11
+ expect.soft(not_a_value.is_value()).toBe(false);
12
+ });
13
+ });
14
+ describe(".is_not_a_value()", () => {
15
+ test("should be false", () => {
16
+ expect.soft(has_value.is_not_a_value()).toBe(false);
17
+ });
18
+ test("should be true", () => {
19
+ expect.soft(not_a_value.is_not_a_value()).toBe(true);
20
+ });
21
+ });
22
+ describe(".expect.soft(msg: string)", () => {
23
+ test("should be the actual value it holds", () => {
24
+ expect.soft(has_value.expect("doesn't hold a value")).toBe("value");
25
+ });
26
+ test("should throw with the message passed", () => {
27
+ expect.soft(() => not_a_value.expect("error msg")).toThrow("error msg");
28
+ });
29
+ });
30
+ describe(".unwrap()", () => {
31
+ test("should be the actual value it holds", () => {
32
+ expect.soft(has_value.unwrap()).toBe("value");
33
+ });
34
+ test("should throw with default message: `Expected a value but didnt get one.`", () => {
35
+ expect.soft(() => {
36
+ not_a_value.unwrap();
37
+ }).toThrow("Expected a value but didnt get one.");
38
+ });
39
+ });
40
+ describe(".unwrap_or()", () => {
41
+ test("should be the actual value it holds", () => {
42
+ expect.soft(has_value.unwrap_or("default")).toBe("value");
43
+ });
44
+ test("should be the provided default value`", () => {
45
+ expect.soft(not_a_value.unwrap_or("default")).toBe("default");
46
+ });
47
+ });
48
+ describe(".unwrap_or_else()", () => {
49
+ test("should be the actual value it holds", () => {
50
+ expect.soft(has_value.unwrap_or_else(() => "calulated default")).toBe("value");
51
+ });
52
+ test("should be the return value of the provided function`", () => {
53
+ expect.soft(not_a_value.unwrap_or_else(() => "calulated default")).toBe("calulated default");
54
+ });
55
+ });
56
+ describe(".map()", () => {
57
+ test("should be a new instance of Maybe holding the returned value of the provided function", () => {
58
+ const new_maybe_with_val = has_value.map((val) => val.length);
59
+ expect.soft(new_maybe_with_val).toBeInstanceOf(Maybe);
60
+ expect.soft(new_maybe_with_val.unwrap()).toBe(5 /*length*/);
61
+ });
62
+ test("should be the a new instance of maybe that holds no value`", () => {
63
+ const new_maybe_with_no_val = not_a_value.map((val) => val.length);
64
+ expect.soft(new_maybe_with_no_val).toBeInstanceOf(Maybe);
65
+ expect.soft(() => {
66
+ new_maybe_with_no_val.unwrap();
67
+ }).toThrow();
68
+ });
69
+ });
70
+ describe(".transform()", () => {
71
+ test("should transform the whole Maybe<T> class to boolean", () => {
72
+ const tr_maybe_with_val = has_value.transform(val => true);
73
+ expect.soft(tr_maybe_with_val).toBe(true);
74
+ });
75
+ test("should transform the whole Maybe<T> class to Date object", () => {
76
+ const tr_maybe_with_no_val = not_a_value.transform(val => new Date());
77
+ expect.soft(tr_maybe_with_no_val).toBeInstanceOf(Date);
78
+ });
79
+ });
80
+ });
81
+ //# sourceMappingURL=maybe.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"maybe.test.js","sourceRoot":"","sources":["../../src/maybe/maybe.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,51 @@
1
+ import Maybe from "../maybe/maybe.js";
2
+ export default class Result {
3
+ constructor(ok, err) {
4
+ if (ok === null && err === null) {
5
+ throw Error(`both \`Ok\` and \'Err\' can't be null at the same time`);
6
+ }
7
+ if (ok !== null && err !== null) {
8
+ throw Error(`both \`Ok\` and \'Err\' can't be other than null at the same time`);
9
+ }
10
+ this.ok = new Maybe(ok);
11
+ this.err = new Maybe(err);
12
+ }
13
+ //public interface to construct an instance
14
+ static Ok(val) {
15
+ return new Result(val, null);
16
+ }
17
+ static Err(err) {
18
+ return new Result(null, err);
19
+ }
20
+ //useful methods
21
+ is_ok() {
22
+ return this.ok.is_value();
23
+ }
24
+ is_error() {
25
+ return this.err.is_value();
26
+ }
27
+ ok_value() {
28
+ return this.ok;
29
+ }
30
+ err_value() {
31
+ return this.err;
32
+ }
33
+ map(ok_mapper, err_mapper) {
34
+ if (this.is_ok()) {
35
+ return Result.Ok(ok_mapper(this.ok_value().unwrap()));
36
+ }
37
+ else {
38
+ return Result.Err(err_mapper(this.err_value().unwrap()));
39
+ }
40
+ }
41
+ map_ok(fn) {
42
+ return this.map(fn, (err) => err);
43
+ }
44
+ map_err(fn) {
45
+ return this.map((v) => v, fn);
46
+ }
47
+ transform(fn) {
48
+ return fn(this);
49
+ }
50
+ }
51
+ //# sourceMappingURL=result.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"result.js","sourceRoot":"","sources":["../../src/result/result.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,mBAAmB,CAAC;AAEtC,MAAM,CAAC,OAAO,OAAO,MAAM;IAIzB,YAAoB,EAAY,EAAE,GAAa;QAC7C,IAAI,EAAE,KAAK,IAAI,IAAI,GAAG,KAAK,IAAI,EAAE,CAAC;YAChC,MAAM,KAAK,CAAC,wDAAwD,CAAC,CAAC;QACxE,CAAC;QACD,IAAI,EAAE,KAAK,IAAI,IAAI,GAAG,KAAK,IAAI,EAAE,CAAC;YAChC,MAAM,KAAK,CACT,mEAAmE,CACpE,CAAC;QACJ,CAAC;QACD,IAAI,CAAC,EAAE,GAAG,IAAI,KAAK,CAAI,EAAE,CAAC,CAAC;QAC3B,IAAI,CAAC,GAAG,GAAG,IAAI,KAAK,CAAI,GAAG,CAAC,CAAC;IAC/B,CAAC;IAED,2CAA2C;IACpC,MAAM,CAAC,EAAE,CAAO,GAAM;QAC3B,OAAO,IAAI,MAAM,CAAO,GAAG,EAAE,IAAI,CAAC,CAAC;IACrC,CAAC;IACM,MAAM,CAAC,GAAG,CAAO,GAAM;QAC5B,OAAO,IAAI,MAAM,CAAO,IAAI,EAAE,GAAG,CAAC,CAAC;IACrC,CAAC;IACD,gBAAgB;IACT,KAAK;QACV,OAAO,IAAI,CAAC,EAAE,CAAC,QAAQ,EAAE,CAAC;IAC5B,CAAC;IACM,QAAQ;QACb,OAAO,IAAI,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC;IAC7B,CAAC;IACM,QAAQ;QACb,OAAO,IAAI,CAAC,EAAE,CAAC;IACjB,CAAC;IACM,SAAS;QACd,OAAO,IAAI,CAAC,GAAG,CAAC;IAClB,CAAC;IACM,GAAG,CACR,SAAwB,EACxB,UAAyB;QAEzB,IAAI,IAAI,CAAC,KAAK,EAAE,EAAE,CAAC;YACjB,OAAO,MAAM,CAAC,EAAE,CAAO,SAAS,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;QAC9D,CAAC;aAAM,CAAC;YACN,OAAO,MAAM,CAAC,GAAG,CAAO,UAAU,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;QACjE,CAAC;IACH,CAAC;IACM,MAAM,CAAI,EAAiB;QAChC,OAAO,IAAI,CAAC,GAAG,CAAO,EAAE,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC;IAC1C,CAAC;IACM,OAAO,CAAI,EAAiB;QACjC,OAAO,IAAI,CAAC,GAAG,CAAO,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IACtC,CAAC;IACM,SAAS,CAAK,EAA6B;QAChD,OAAO,EAAE,CAAC,IAAI,CAAC,CAAC;IAClB,CAAC;CACF"}
@@ -0,0 +1,101 @@
1
+ import { describe, test, expect } from "vitest";
2
+ import { Maybe, Result } from "@/index.js";
3
+ const ok_variant = Result.Ok({
4
+ data: "ok data",
5
+ });
6
+ const err_variant = Result.Err({
7
+ status: 400,
8
+ });
9
+ describe("Result<T, E>", () => {
10
+ describe(".is_ok()", () => {
11
+ test("should be true", () => {
12
+ expect.soft(ok_variant.is_ok()).toBe(true);
13
+ });
14
+ test("should be false", () => {
15
+ expect.soft(err_variant.is_ok()).toBe(false);
16
+ });
17
+ });
18
+ describe(".is_error()", () => {
19
+ test("should be false", () => {
20
+ expect.soft(ok_variant.is_error()).toBe(false);
21
+ });
22
+ test("should be true", () => {
23
+ expect.soft(err_variant.is_error()).toBe(true);
24
+ });
25
+ });
26
+ describe(".ok_value()", () => {
27
+ test("should be an instance of Maybe<T> containing the expected value", () => {
28
+ const ok_variant_ok_value = ok_variant.ok_value();
29
+ expect.soft(ok_variant_ok_value).toBeInstanceOf(Maybe);
30
+ expect.soft(ok_variant_ok_value.unwrap()).toStrictEqual({
31
+ data: "ok data",
32
+ });
33
+ });
34
+ test("should be an instance of Maybe<T> containing nothing", () => {
35
+ const err_variant_ok_value = err_variant.ok_value();
36
+ expect.soft(err_variant_ok_value).toBeInstanceOf(Maybe);
37
+ expect
38
+ .soft(() => {
39
+ err_variant_ok_value.unwrap();
40
+ })
41
+ .toThrow();
42
+ });
43
+ });
44
+ describe(".err_value()", () => {
45
+ test("should be an instance of Maybe<T> containing the nothing", () => {
46
+ const ok_variant_err_value = ok_variant.err_value();
47
+ expect.soft(ok_variant_err_value).toBeInstanceOf(Maybe);
48
+ expect
49
+ .soft(() => {
50
+ ok_variant_err_value.unwrap();
51
+ })
52
+ .toThrow();
53
+ });
54
+ });
55
+ test("should be an instance of Maybe<T> containing error details", () => {
56
+ const err_variant_err_value = err_variant.err_value();
57
+ expect.soft(err_variant_err_value).toBeInstanceOf(Maybe);
58
+ expect.soft(err_variant_err_value.unwrap()).toStrictEqual({
59
+ status: 400,
60
+ });
61
+ });
62
+ describe(".map()", () => {
63
+ test("should be ok variant of another Result with new calulated ok and error value", () => {
64
+ const mapped_ok_variant = ok_variant.map((ok_data) => "was ok variant", (err_data) => "was error variant");
65
+ expect.soft(mapped_ok_variant).toBeInstanceOf(Result);
66
+ expect.soft(mapped_ok_variant.is_ok()).toBe(true);
67
+ expect.soft(mapped_ok_variant.ok_value().unwrap()).toBe("was ok variant");
68
+ });
69
+ test("should be err variant of another Result with new calulated ok and error value", () => {
70
+ const mapped_err_variant = err_variant.map((ok_data) => "was ok variant", (err_data) => "was error variant");
71
+ expect.soft(mapped_err_variant).toBeInstanceOf(Result);
72
+ expect.soft(mapped_err_variant.is_error()).toBe(true);
73
+ expect.soft(mapped_err_variant.err_value().unwrap()).toBe("was error variant");
74
+ });
75
+ });
76
+ describe(".map_ok()", () => {
77
+ test("should be ok variant of another Result with new calculated ok value but old error value", () => {
78
+ const map_ok_of_ok_variant = ok_variant.map_ok((ok_data) => "was ok variant");
79
+ expect.soft(map_ok_of_ok_variant).toBeInstanceOf(Result);
80
+ expect.soft(map_ok_of_ok_variant.is_ok()).toBe(true);
81
+ expect.soft(map_ok_of_ok_variant.ok_value().unwrap()).toBe("was ok variant");
82
+ });
83
+ test("should be ok variant of another Result with new calculated error value but old ok value", () => {
84
+ const map_err_of_err_variant = err_variant.map_err((err_data) => "was error variant");
85
+ expect.soft(map_err_of_err_variant).toBeInstanceOf(Result);
86
+ expect.soft(map_err_of_err_variant.is_error()).toBe(true);
87
+ expect.soft(map_err_of_err_variant.err_value().unwrap()).toBe("was error variant");
88
+ });
89
+ });
90
+ describe(".transform()", () => {
91
+ test("should transform the whole Result<T, E> class to type string", () => {
92
+ const tr_maybe_with_val = ok_variant.transform(val => 'success');
93
+ expect.soft(tr_maybe_with_val).toBe('success');
94
+ });
95
+ test("should transform the whole Result<T, E> class to number", () => {
96
+ const tr_maybe_with_no_val = err_variant.transform(val => 500);
97
+ expect.soft(tr_maybe_with_no_val).toBe(500);
98
+ });
99
+ });
100
+ });
101
+ //# sourceMappingURL=result.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"result.test.js","sourceRoot":"","sources":["../../src/result/result.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import Maybe from "./maybe/maybe.js";
2
+ import Result from "./result/result.js";
3
+ export { Maybe, Result };
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,kBAAkB,CAAC;AACrC,OAAO,MAAM,MAAM,oBAAoB,CAAC;AACxC,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC"}
@@ -0,0 +1,13 @@
1
+ export default class Maybe<T> {
2
+ private value;
3
+ constructor(val?: T | null);
4
+ is_value(): boolean;
5
+ is_not_a_value(): boolean;
6
+ expect(msg: string): T;
7
+ unwrap(): T;
8
+ unwrap_or(def: T): T;
9
+ unwrap_or_else(fn: () => T): T;
10
+ map<U>(fn: (v: T) => U): Maybe<U>;
11
+ transform<To>(fn: (from: typeof this) => To): To;
12
+ }
13
+ //# sourceMappingURL=maybe.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"maybe.d.ts","sourceRoot":"","sources":["../../../src/maybe/maybe.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,OAAO,OAAO,KAAK,CAAC,CAAC;IAC1B,OAAO,CAAC,KAAK,CAAW;gBAEZ,GAAG,GAAE,CAAC,GAAG,IAAW;IAIzB,QAAQ,IAAI,OAAO;IAOnB,cAAc,IAAI,OAAO;IAGzB,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,CAAC;IAOtB,MAAM,IAAI,CAAC;IAGX,SAAS,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC;IAOpB,cAAc,CAAC,EAAE,EAAE,MAAM,CAAC,GAAG,CAAC;IAG9B,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC;IAOjC,SAAS,CAAC,EAAE,EAAE,EAAE,EAAE,CAAC,IAAI,EAAE,OAAO,IAAI,KAAK,EAAE,GAAG,EAAE;CAGxD"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=maybe.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"maybe.test.d.ts","sourceRoot":"","sources":["../../../src/maybe/maybe.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,17 @@
1
+ import Maybe from "../maybe/maybe.js";
2
+ export default class Result<T, E> {
3
+ private ok;
4
+ private err;
5
+ private constructor();
6
+ static Ok<T, E>(val: T): Result<T, E>;
7
+ static Err<T, E>(err: E): Result<T, E>;
8
+ is_ok(): boolean;
9
+ is_error(): boolean;
10
+ ok_value(): Maybe<T>;
11
+ err_value(): Maybe<E>;
12
+ map<U, Q>(ok_mapper: (val: T) => U, err_mapper: (err: E) => Q): Result<U, Q>;
13
+ map_ok<U>(fn: (val: T) => U): Result<U, E>;
14
+ map_err<Q>(fn: (val: E) => Q): Result<T, Q>;
15
+ transform<To>(fn: (from: typeof this) => To): To;
16
+ }
17
+ //# sourceMappingURL=result.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"result.d.ts","sourceRoot":"","sources":["../../../src/result/result.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,mBAAmB,CAAC;AAEtC,MAAM,CAAC,OAAO,OAAO,MAAM,CAAC,CAAC,EAAE,CAAC;IAC9B,OAAO,CAAC,EAAE,CAAW;IACrB,OAAO,CAAC,GAAG,CAAW;IAEtB,OAAO;WAcO,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,GAAG,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC;WAG9B,GAAG,CAAC,CAAC,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,GAAG,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC;IAItC,KAAK,IAAI,OAAO;IAGhB,QAAQ,IAAI,OAAO;IAGnB,QAAQ,IAAI,KAAK,CAAC,CAAC,CAAC;IAGpB,SAAS,IAAI,KAAK,CAAC,CAAC,CAAC;IAGrB,GAAG,CAAC,CAAC,EAAE,CAAC,EACb,SAAS,EAAE,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC,EACxB,UAAU,EAAE,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC,GACxB,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC;IAOR,MAAM,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC,GAAG,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC;IAG1C,OAAO,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC,GAAG,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC;IAG3C,SAAS,CAAC,EAAE,EAAE,EAAE,EAAE,CAAC,IAAI,EAAE,OAAO,IAAI,KAAK,EAAE,GAAG,EAAE;CAGxD"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=result.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"result.test.d.ts","sourceRoot":"","sources":["../../../src/result/result.test.ts"],"names":[],"mappings":""}
package/package.json ADDED
@@ -0,0 +1,54 @@
1
+ {
2
+ "name": "ferric-oxide",
3
+ "version": "1.0.0",
4
+ "description": "Rust liike utilities for typescript",
5
+ "homepage": "https://github.com/mr-m1m3/rsts",
6
+ "bugs": {
7
+ "url": "https://github.com/mr-m1m3/rsts/issues"
8
+ },
9
+ "repository": {
10
+ "type": "git",
11
+ "url": "git+https://github.com/mr-m1m3/rsts.git"
12
+ },
13
+ "scripts": {
14
+ "build": "tsc",
15
+ "test:watch": "vitest",
16
+ "test": "vitest run"
17
+ },
18
+ "exports": {
19
+ ".": {
20
+ "types": "./dist/types/index.d.ts",
21
+ "default": "./dist/index.js"
22
+ },
23
+ "./maybe": {
24
+ "types": "./dist/types/maybe/maybe.d.ts",
25
+ "default": "./dist/maybe/maybe.js"
26
+ },
27
+ "./result": {
28
+ "types": "./dist/types/result/result.d.ts",
29
+ "default": "./dist/result/result.js"
30
+ }
31
+ },
32
+ "files": [
33
+ "./src",
34
+ "./dist"
35
+ ],
36
+ "keywords": [
37
+ "rust",
38
+ "utilities",
39
+ "result",
40
+ "option",
41
+ "enum",
42
+ "error-handling",
43
+ "null-handling"
44
+ ],
45
+ "author": "@mr-m1m3",
46
+ "license": "ISC",
47
+ "packageManager": "pnpm@10.28.1",
48
+ "devDependencies": {
49
+ "@types/node": "^25.1.0",
50
+ "typescript": "^5.9.3",
51
+ "vitest": "^4.0.18"
52
+ },
53
+ "type": "module"
54
+ }
package/src/index.ts ADDED
@@ -0,0 +1,3 @@
1
+ import Maybe from "./maybe/maybe.js";
2
+ import Result from "./result/result.js";
3
+ export { Maybe, Result };
@@ -0,0 +1,91 @@
1
+ import { describe, test, expect } from "vitest";
2
+ import { Maybe } from "@/index.js";
3
+
4
+ const has_value = new Maybe("value");
5
+ const not_a_value = new Maybe<string>(null);
6
+ describe("Maybe<T>", () => {
7
+ describe(".is_value()", () => {
8
+ test("should be true", () => {
9
+ expect.soft(has_value.is_value()).toBe(true);
10
+ });
11
+ test("should be false", () => {
12
+ expect.soft(not_a_value.is_value()).toBe(false);
13
+ });
14
+ });
15
+
16
+ describe(".is_not_a_value()", () => {
17
+ test("should be false", () => {
18
+ expect.soft(has_value.is_not_a_value()).toBe(false);
19
+ });
20
+ test("should be true", () => {
21
+ expect.soft(not_a_value.is_not_a_value()).toBe(true);
22
+ });
23
+ });
24
+
25
+ describe(".expect.soft(msg: string)", () => {
26
+ test("should be the actual value it holds", () => {
27
+ expect.soft(has_value.expect("doesn't hold a value")).toBe("value");
28
+ });
29
+ test("should throw with the message passed", () => {
30
+ expect.soft(() => not_a_value.expect("error msg")).toThrow("error msg");
31
+ });
32
+ });
33
+
34
+ describe(".unwrap()", () => {
35
+ test("should be the actual value it holds", () => {
36
+ expect.soft(has_value.unwrap()).toBe("value");
37
+ });
38
+ test("should throw with default message: `Expected a value but didnt get one.`", () => {
39
+ expect.soft(() => {
40
+ not_a_value.unwrap();
41
+ }).toThrow("Expected a value but didnt get one.");
42
+ });
43
+ });
44
+
45
+ describe(".unwrap_or()", () => {
46
+ test("should be the actual value it holds", () => {
47
+ expect.soft(has_value.unwrap_or("default")).toBe("value");
48
+ });
49
+ test("should be the provided default value`", () => {
50
+ expect.soft(not_a_value.unwrap_or("default")).toBe("default");
51
+ });
52
+ });
53
+
54
+ describe(".unwrap_or_else()", () => {
55
+ test("should be the actual value it holds", () => {
56
+ expect.soft(has_value.unwrap_or_else(() => "calulated default")).toBe("value");
57
+ });
58
+ test("should be the return value of the provided function`", () => {
59
+ expect.soft(not_a_value.unwrap_or_else(() => "calulated default")).toBe(
60
+ "calulated default",
61
+ );
62
+ });
63
+ });
64
+
65
+ describe(".map()", () => {
66
+ test("should be a new instance of Maybe holding the returned value of the provided function", () => {
67
+ const new_maybe_with_val = has_value.map<number>((val) => val.length);
68
+ expect.soft(new_maybe_with_val).toBeInstanceOf(Maybe);
69
+ expect.soft(new_maybe_with_val.unwrap()).toBe(5 /*length*/);
70
+ });
71
+ test("should be the a new instance of maybe that holds no value`", () => {
72
+ const new_maybe_with_no_val = not_a_value.map((val) => val.length);
73
+ expect.soft(new_maybe_with_no_val).toBeInstanceOf(Maybe);
74
+ expect.soft(() => {
75
+ new_maybe_with_no_val.unwrap();
76
+ }).toThrow();
77
+ });
78
+ });
79
+
80
+ describe(".transform()", () => {
81
+ test("should transform the whole Maybe<T> class to boolean", () => {
82
+ const tr_maybe_with_val = has_value.transform(val => true);
83
+ expect.soft(tr_maybe_with_val).toBe(true);
84
+ });
85
+
86
+ test("should transform the whole Maybe<T> class to Date object", () => {
87
+ const tr_maybe_with_no_val = not_a_value.transform(val => new Date());
88
+ expect.soft(tr_maybe_with_no_val).toBeInstanceOf(Date);
89
+ });
90
+ });
91
+ });
@@ -0,0 +1,48 @@
1
+ export default class Maybe<T> {
2
+ private value: T | null;
3
+
4
+ constructor(val: T | null = null) {
5
+ this.value = val;
6
+ }
7
+ //useful methods
8
+ public is_value(): boolean {
9
+ if (this.value === null) {
10
+ return false;
11
+ } else {
12
+ return true;
13
+ }
14
+ }
15
+ public is_not_a_value(): boolean {
16
+ return !this.is_value();
17
+ }
18
+ public expect(msg: string): T {
19
+ if (this.is_value()) {
20
+ return this.value as T;
21
+ } else {
22
+ throw new Error(msg);
23
+ }
24
+ }
25
+ public unwrap(): T {
26
+ return this.expect('Expected a value but didnt get one.')
27
+ }
28
+ public unwrap_or(def: T): T {
29
+ if (this.is_value()) {
30
+ return this.value as T;
31
+ } else {
32
+ return def;
33
+ }
34
+ }
35
+ public unwrap_or_else(fn: () => T): T {
36
+ return this.unwrap_or(fn())
37
+ }
38
+ public map<U>(fn: (v: T) => U): Maybe<U> {
39
+ if (this.is_value()) {
40
+ return new Maybe<U>(fn(this.value as T));
41
+ } else {
42
+ return new Maybe<U>(null);
43
+ }
44
+ }
45
+ public transform<To>(fn: (from: typeof this) => To): To {
46
+ return fn(this);
47
+ }
48
+ }
@@ -0,0 +1,126 @@
1
+ import { describe, test, expect } from "vitest";
2
+ import { Maybe, Result } from "@/index.js";
3
+ type OkData = {
4
+ data: string;
5
+ };
6
+ type ErrData = {
7
+ status: number;
8
+ };
9
+ const ok_variant = Result.Ok<OkData, ErrData>({
10
+ data: "ok data",
11
+ });
12
+ const err_variant = Result.Err<OkData, ErrData>({
13
+ status: 400,
14
+ });
15
+
16
+ describe("Result<T, E>", () => {
17
+ describe(".is_ok()", () => {
18
+ test("should be true", () => {
19
+ expect.soft(ok_variant.is_ok()).toBe(true);
20
+ });
21
+ test("should be false", () => {
22
+ expect.soft(err_variant.is_ok()).toBe(false);
23
+ });
24
+ });
25
+
26
+ describe(".is_error()", () => {
27
+ test("should be false", () => {
28
+ expect.soft(ok_variant.is_error()).toBe(false);
29
+ });
30
+ test("should be true", () => {
31
+ expect.soft(err_variant.is_error()).toBe(true);
32
+ });
33
+ });
34
+
35
+ describe(".ok_value()", () => {
36
+ test("should be an instance of Maybe<T> containing the expected value", () => {
37
+ const ok_variant_ok_value = ok_variant.ok_value();
38
+ expect.soft(ok_variant_ok_value).toBeInstanceOf(Maybe);
39
+ expect.soft(ok_variant_ok_value.unwrap()).toStrictEqual({
40
+ data: "ok data",
41
+ });
42
+ });
43
+ test("should be an instance of Maybe<T> containing nothing", () => {
44
+ const err_variant_ok_value = err_variant.ok_value();
45
+ expect.soft(err_variant_ok_value).toBeInstanceOf(Maybe);
46
+ expect
47
+ .soft(() => {
48
+ err_variant_ok_value.unwrap();
49
+ })
50
+ .toThrow();
51
+ });
52
+ });
53
+
54
+ describe(".err_value()", () => {
55
+ test("should be an instance of Maybe<T> containing the nothing", () => {
56
+ const ok_variant_err_value = ok_variant.err_value();
57
+ expect.soft(ok_variant_err_value).toBeInstanceOf(Maybe);
58
+ expect
59
+ .soft(() => {
60
+ ok_variant_err_value.unwrap();
61
+ })
62
+ .toThrow();
63
+ });
64
+ });
65
+ test("should be an instance of Maybe<T> containing error details", () => {
66
+ const err_variant_err_value = err_variant.err_value();
67
+ expect.soft(err_variant_err_value).toBeInstanceOf(Maybe);
68
+ expect.soft(err_variant_err_value.unwrap()).toStrictEqual({
69
+ status: 400,
70
+ });
71
+ });
72
+
73
+ describe(".map()", () => {
74
+ test("should be ok variant of another Result with new calulated ok and error value", () => {
75
+ const mapped_ok_variant = ok_variant.map(
76
+ (ok_data) => "was ok variant",
77
+ (err_data) => "was error variant",
78
+ );
79
+ expect.soft(mapped_ok_variant).toBeInstanceOf(Result);
80
+ expect.soft(mapped_ok_variant.is_ok()).toBe(true);
81
+ expect.soft(mapped_ok_variant.ok_value().unwrap()).toBe("was ok variant")
82
+ });
83
+
84
+ test("should be err variant of another Result with new calulated ok and error value", () => {
85
+ const mapped_err_variant = err_variant.map(
86
+ (ok_data) => "was ok variant",
87
+ (err_data) => "was error variant",
88
+ );
89
+ expect.soft(mapped_err_variant).toBeInstanceOf(Result);
90
+ expect.soft(mapped_err_variant.is_error()).toBe(true);
91
+ expect.soft(mapped_err_variant.err_value().unwrap()).toBe("was error variant");
92
+ });
93
+ });
94
+
95
+ describe(".map_ok()", () => {
96
+ test("should be ok variant of another Result with new calculated ok value but old error value", () => {
97
+ const map_ok_of_ok_variant = ok_variant.map_ok(
98
+ (ok_data) => "was ok variant",
99
+ );
100
+ expect.soft(map_ok_of_ok_variant).toBeInstanceOf(Result);
101
+ expect.soft(map_ok_of_ok_variant.is_ok()).toBe(true);
102
+ expect.soft(map_ok_of_ok_variant.ok_value().unwrap()).toBe("was ok variant");
103
+ });
104
+
105
+ test("should be ok variant of another Result with new calculated error value but old ok value", () => {
106
+ const map_err_of_err_variant = err_variant.map_err(
107
+ (err_data) => "was error variant",
108
+ );
109
+ expect.soft(map_err_of_err_variant).toBeInstanceOf(Result);
110
+ expect.soft(map_err_of_err_variant.is_error()).toBe(true);
111
+ expect.soft(map_err_of_err_variant.err_value().unwrap()).toBe("was error variant");
112
+ });
113
+ });
114
+
115
+ describe(".transform()", () => {
116
+ test("should transform the whole Result<T, E> class to type string", () => {
117
+ const tr_maybe_with_val = ok_variant.transform(val => 'success');
118
+ expect.soft(tr_maybe_with_val).toBe('success');
119
+ });
120
+
121
+ test("should transform the whole Result<T, E> class to number", () => {
122
+ const tr_maybe_with_no_val = err_variant.transform(val => 500);
123
+ expect.soft(tr_maybe_with_no_val).toBe(500);
124
+ });
125
+ });
126
+ });
@@ -0,0 +1,59 @@
1
+ import Maybe from "../maybe/maybe.js";
2
+
3
+ export default class Result<T, E> {
4
+ private ok: Maybe<T>;
5
+ private err: Maybe<E>;
6
+
7
+ private constructor(ok: T | null, err: E | null) {
8
+ if (ok === null && err === null) {
9
+ throw Error(`both \`Ok\` and \'Err\' can't be null at the same time`);
10
+ }
11
+ if (ok !== null && err !== null) {
12
+ throw Error(
13
+ `both \`Ok\` and \'Err\' can't be other than null at the same time`,
14
+ );
15
+ }
16
+ this.ok = new Maybe<T>(ok);
17
+ this.err = new Maybe<E>(err);
18
+ }
19
+
20
+ //public interface to construct an instance
21
+ public static Ok<T, E>(val: T): Result<T, E> {
22
+ return new Result<T, E>(val, null);
23
+ }
24
+ public static Err<T, E>(err: E): Result<T, E> {
25
+ return new Result<T, E>(null, err);
26
+ }
27
+ //useful methods
28
+ public is_ok(): boolean {
29
+ return this.ok.is_value();
30
+ }
31
+ public is_error(): boolean {
32
+ return this.err.is_value();
33
+ }
34
+ public ok_value(): Maybe<T> {
35
+ return this.ok;
36
+ }
37
+ public err_value(): Maybe<E> {
38
+ return this.err;
39
+ }
40
+ public map<U, Q>(
41
+ ok_mapper: (val: T) => U,
42
+ err_mapper: (err: E) => Q,
43
+ ): Result<U, Q> {
44
+ if (this.is_ok()) {
45
+ return Result.Ok<U, Q>(ok_mapper(this.ok_value().unwrap()));
46
+ } else {
47
+ return Result.Err<U, Q>(err_mapper(this.err_value().unwrap()));
48
+ }
49
+ }
50
+ public map_ok<U>(fn: (val: T) => U): Result<U, E> {
51
+ return this.map<U, E>(fn, (err) => err);
52
+ }
53
+ public map_err<Q>(fn: (val: E) => Q): Result<T, Q> {
54
+ return this.map<T, Q>((v) => v, fn);
55
+ }
56
+ public transform<To>(fn: (from: typeof this) => To): To {
57
+ return fn(this);
58
+ }
59
+ }