util.error: Add coerce and wrap methods to registry(?) objects
authorMatthew Wild <mwild1@gmail.com>
Wed, 09 Dec 2020 13:55:10 +0000
changeset 11225 b0a563716334
parent 11224 9b25eecde9e6
child 11226 4b39691a274e
util.error: Add coerce and wrap methods to registry(?) objects
spec/util_error_spec.lua
util/error.lua
--- a/spec/util_error_spec.lua	Wed Dec 09 13:54:21 2020 +0000
+++ b/spec/util_error_spec.lua	Wed Dec 09 13:55:10 2020 +0000
@@ -140,6 +140,76 @@
 				nope = {type = "auth"; condition = "not-authorized"; text = "Can't let you do that Dave"};
 			}, compact2.registry);
 		end);
+
+		describe(".wrap", function ()
+			local reg = errors.init("test", "spec", {
+				myerror = { "cancel", "internal-server-error", "Oh no" };
+			});
+			it("is exposed", function ()
+				assert.is_function(reg.wrap);
+			end);
+			it("returns errors according to the registry", function ()
+				local e = reg.wrap("myerror");
+				assert.equal("cancel", e.type);
+				assert.equal("internal-server-error", e.condition);
+				assert.equal("Oh no", e.text);
+			end);
+
+			it("passes through existing errors", function ()
+				local e = reg.wrap(reg.new({ type = "auth", condition = "forbidden" }));
+				assert.equal("auth", e.type);
+				assert.equal("forbidden", e.condition);
+			end);
+
+			it("wraps arbitrary values", function ()
+				local e = reg.wrap(123);
+				assert.equal("cancel", e.type);
+				assert.equal("undefined-condition", e.condition);
+				assert.equal(123, e.context.wrapped_error);
+			end);
+		end);
+
+		describe(".coerce", function ()
+			local reg = errors.init("test", "spec", {
+				myerror = { "cancel", "internal-server-error", "Oh no" };
+			});
+
+			it("is exposed", function ()
+				assert.is_function(reg.coerce);
+			end);
+
+			it("passes through existing errors", function ()
+				local function test()
+					return nil, errors.new({ type = "auth", condition = "forbidden" });
+				end
+				local ok, err = reg.coerce(test());
+				assert.is_nil(ok);
+				assert.is_truthy(errors.is_err(err));
+				assert.equal("forbidden", err.condition);
+			end);
+
+			it("passes through successful return values", function ()
+				local function test()
+					return 1, 2, 3, 4;
+				end
+				local one, two, three, four = reg.coerce(test());
+				assert.equal(1, one);
+				assert.equal(2, two);
+				assert.equal(3, three);
+				assert.equal(4, four);
+			end);
+
+			it("wraps non-error objects", function ()
+				local function test()
+					return nil, "myerror";
+				end
+				local ok, err = reg.coerce(test());
+				assert.is_nil(ok);
+				assert.is_truthy(errors.is_err(err));
+				assert.equal("internal-server-error", err.condition);
+				assert.equal("Oh no", err.text);
+			end);
+		end);
 	end);
 
 end);
--- a/util/error.lua	Wed Dec 09 13:54:21 2020 +0000
+++ b/util/error.lua	Wed Dec 09 13:55:10 2020 +0000
@@ -98,12 +98,31 @@
 	if protoerr and type(next(protoerr)) == "number" then
 		registry = expand_registry(namespace, registry);
 	end
+
+	local function wrap(e, context)
+		if is_err(e) then
+			return e;
+		end
+		local err = new(registry[e] or {
+			type = "cancel", condition = "undefined-condition"
+		}, context, registry, source);
+		err.context.wrapped_error = e;
+		return err;
+	end
+
 	return {
 		source = source;
 		registry = registry;
 		new = function (e, context)
 			return new(e, context, registry, source);
 		end;
+		coerce = function (ok, err, ...)
+			if ok then
+				return ok, err, ...;
+			end
+			return nil, wrap(err);
+		end;
+		wrap = wrap;
 	};
 end