You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
134 lines
3.0 KiB
JavaScript
134 lines
3.0 KiB
JavaScript
"use strict";
|
|
|
|
function createResultObject(isSuccessful, containedValue) {
|
|
return {
|
|
__isResultType: true,
|
|
isOK: isSuccessful,
|
|
isError: !isSuccessful,
|
|
error: function () {
|
|
if (!isSuccessful) {
|
|
return containedValue;
|
|
} else {
|
|
// FIXME: Clearer error message, definitely a bug!
|
|
throw new Error(`The Result is in a success state`);
|
|
}
|
|
},
|
|
value: function () {
|
|
if (isSuccessful) {
|
|
return containedValue;
|
|
} else {
|
|
throw containedValue;
|
|
}
|
|
},
|
|
valueOr: function (defaultValue) {
|
|
if (isSuccessful) {
|
|
return containedValue;
|
|
} else {
|
|
return defaultValue;
|
|
}
|
|
},
|
|
mapTo: function ({ ok, error }) {
|
|
let okMapper = ok ?? ((value) => Result.ok(value));
|
|
let errorMapper = error ?? ((error) => Result.error(error));
|
|
|
|
if (this.isOK) {
|
|
let mapped = okMapper(containedValue);
|
|
|
|
return (Result.isResult(mapped))
|
|
? mapped
|
|
: Result.ok(mapped);
|
|
} else {
|
|
let mapped = errorMapper(containedValue);
|
|
|
|
return (Result.isResult(mapped))
|
|
? mapped
|
|
: Result.error(mapped);
|
|
}
|
|
},
|
|
// valueOr: function (errorCode, errorMessage) {
|
|
// if (isSuccessful) {
|
|
// return containedValue;
|
|
// } else {
|
|
// // FIXME: Integrate with error-chain somehow?
|
|
// let error = new Error(errorMessage);
|
|
// error.code = errorCode;
|
|
// throw error;
|
|
// }
|
|
// },
|
|
// FIXME: Chaining, Promise chain integration?
|
|
// FIXME: Serialization
|
|
// FIXME: Chaining with error filtering
|
|
};
|
|
}
|
|
|
|
let Result = module.exports = {
|
|
isResult: function (value) {
|
|
return (value != null && value.__isResultType === true);
|
|
},
|
|
ok: function (value) {
|
|
// Emulate what Promises do on `resolve(...)`
|
|
if (this.isResult(value)) {
|
|
return value;
|
|
} else {
|
|
return createResultObject(true, value);
|
|
}
|
|
},
|
|
error: function (error) {
|
|
return createResultObject(false, error);
|
|
},
|
|
wrap: function (callback) {
|
|
// Always returns a Result
|
|
try {
|
|
let result = callback();
|
|
return this.ok(result);
|
|
} catch (error) {
|
|
return this.error(error);
|
|
}
|
|
},
|
|
wrapAsync: function (callback) {
|
|
// Always returns a Promise that resolves to a Result
|
|
return new Promise((resolve, _reject) => {
|
|
resolve(callback());
|
|
}).then((result) => {
|
|
return this.ok(result);
|
|
}).catch((error) => {
|
|
return this.error(error);
|
|
});
|
|
},
|
|
// The below methods are used when it's unknown whether something will produce a Result or just return/throw
|
|
unwrapValue: function (value) {
|
|
if (Result.isResult(value)) {
|
|
return value.unwrap();
|
|
} else {
|
|
return value;
|
|
}
|
|
},
|
|
unwrap: function (callback) {
|
|
return Result.unwrapValue(callback());
|
|
},
|
|
unwrapAsync: function (callback) {
|
|
return new Promise((resolve, _reject) => {
|
|
resolve(callback());
|
|
}).then((result) => {
|
|
return Result.unwrapValue(result);
|
|
});
|
|
}
|
|
};
|
|
|
|
|
|
/* IDEA:
|
|
|
|
result.mapTo({
|
|
ok: (value) => value * 2,
|
|
error: (error) => chain(error, ErrorType, "Foo Bar")
|
|
})
|
|
|
|
result.mapTo({
|
|
// can return either a result or any value
|
|
ok: (value) => value * 2,
|
|
// can return either a result or an Error
|
|
error: (_error) => result.ok(0)
|
|
})
|
|
|
|
*/
|