From 0de1cc585c4d2445a26657714af4ed6a0b6c296b Mon Sep 17 00:00:00 2001
From: Sergei Zharinov <zharinov@users.noreply.github.com>
Date: Fri, 30 Sep 2022 18:45:22 +0300
Subject: [PATCH] feat(schema): Different options for error handling (#18058)

---
 lib/modules/platform/github/common.ts |  2 +-
 lib/util/schema.spec.ts               | 77 ++++++++++++++++-----------
 lib/util/schema.ts                    |  8 ++-
 3 files changed, 53 insertions(+), 34 deletions(-)

diff --git a/lib/modules/platform/github/common.ts b/lib/modules/platform/github/common.ts
index fb5f083802..7a5748c52b 100644
--- a/lib/modules/platform/github/common.ts
+++ b/lib/modules/platform/github/common.ts
@@ -52,6 +52,6 @@ export function coerceRestPr(pr: GhRestPr): GhPr {
     result.closedAt = pr.closed_at;
   }
 
-  schema.match(platformSchemas.Pr, result, true);
+  schema.match(platformSchemas.Pr, result, 'warn');
   return result;
 }
diff --git a/lib/util/schema.spec.ts b/lib/util/schema.spec.ts
index 590ed4d10b..1b15920c73 100644
--- a/lib/util/schema.spec.ts
+++ b/lib/util/schema.spec.ts
@@ -28,42 +28,57 @@ describe('util/schema', () => {
     expect(logger.logger.warn).not.toHaveBeenCalled();
   });
 
-  it('reports nothing if there are no any reports', () => {
-    schema.reportErrors();
-    expect(logger.logger.warn).not.toHaveBeenCalled();
-  });
+  describe('warn', () => {
+    it('reports nothing if there are no any reports', () => {
+      schema.reportErrors();
+      expect(logger.logger.warn).not.toHaveBeenCalled();
+    });
 
-  it('reports same warning one time', () => {
-    const testSchema = z.object(
-      { foo: z.string() },
-      { description: 'Some test schema' }
-    );
-    const invalidData = { foo: 42 };
+    it('reports same warning one time', () => {
+      const testSchema = z.object(
+        { foo: z.string() },
+        { description: 'Some test schema' }
+      );
+      const invalidData = { foo: 42 };
 
-    schema.match(testSchema, invalidData, true);
-    schema.match(testSchema, invalidData, true);
-    schema.match(testSchema, invalidData, true);
-    schema.match(testSchema, invalidData, true);
-    schema.reportErrors();
+      schema.match(testSchema, invalidData, 'warn');
+      schema.match(testSchema, invalidData, 'warn');
+      schema.match(testSchema, invalidData, 'warn');
+      schema.match(testSchema, invalidData, 'warn');
+      schema.reportErrors();
 
-    expect(logger.logger.warn).toHaveBeenCalledOnce();
-    expect(logger.logger.warn.mock.calls[0]).toMatchObject([
-      { description: 'Some test schema' },
-      'Schema validation error',
-    ]);
-  });
+      expect(logger.logger.warn).toHaveBeenCalledOnce();
+      expect(logger.logger.warn.mock.calls[0]).toMatchObject([
+        { description: 'Some test schema' },
+        'Schema validation error',
+      ]);
+    });
 
-  it('reports unspecified schema', () => {
-    const testSchema = z.object({ foo: z.string() });
-    const invalidData = { foo: 42 };
+    it('reports unspecified schema', () => {
+      const testSchema = z.object({ foo: z.string() });
+      const invalidData = { foo: 42 };
 
-    schema.match(testSchema, invalidData, true);
-    schema.reportErrors();
+      schema.match(testSchema, invalidData, 'warn');
+      schema.reportErrors();
+
+      expect(logger.logger.warn).toHaveBeenCalledOnce();
+      expect(logger.logger.warn.mock.calls[0]).toMatchObject([
+        { description: 'Unspecified schema' },
+        'Schema validation error',
+      ]);
+    });
+  });
+
+  describe('throw', () => {
+    it('throws for invalid data', () => {
+      const testSchema = z.object({
+        foo: z.string({ invalid_type_error: 'foobar' }),
+      });
+      const invalidData = { foo: 123 };
 
-    expect(logger.logger.warn).toHaveBeenCalledOnce();
-    expect(logger.logger.warn.mock.calls[0]).toMatchObject([
-      { description: 'Unspecified schema' },
-      'Schema validation error',
-    ]);
+      expect(() => schema.match(testSchema, invalidData, 'throw')).toThrow(
+        'foobar'
+      );
+    });
   });
 });
diff --git a/lib/util/schema.ts b/lib/util/schema.ts
index ce00525f94..8e874cb957 100644
--- a/lib/util/schema.ts
+++ b/lib/util/schema.ts
@@ -47,15 +47,19 @@ export function reportErrors(): void {
 export function match<T extends z.ZodSchema>(
   schema: T,
   input: unknown,
-  report = false
+  onError?: 'warn' | 'throw'
 ): input is z.infer<T> {
   const res = schema.safeParse(input);
   const { success } = res;
   if (!success) {
-    if (report) {
+    if (onError === 'warn') {
       collectError(schema, res.error);
     }
 
+    if (onError === 'throw') {
+      throw res.error;
+    }
+
     return false;
   }
 
-- 
GitLab