Skip to content

Commit

Permalink
fix(observable): better error handling
Browse files Browse the repository at this point in the history
  • Loading branch information
bezoerb committed Apr 26, 2022
1 parent 18c622d commit 7a3b4be
Show file tree
Hide file tree
Showing 6 changed files with 31 additions and 9 deletions.
2 changes: 1 addition & 1 deletion packages/contentful-ssg/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,7 @@ The same as collectValues just without the value from the current entry
###### waitFor
Wait for specific entry to be transformed.
Be aware that this can lead to dead ends when you're awaiting something which
Be aware that this can lead to deadlocks when you're awaiting something which
itself is waiting for the current entry to be transformed.

```js
Expand Down
5 changes: 3 additions & 2 deletions packages/contentful-ssg/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -130,8 +130,9 @@ export const run = async (config: Config): Promise<void> => {
} catch (error: unknown) {
if (error instanceof Error) {
subject.next({ ...transformContext, error });
} else if (typeof error === 'string') {
subject.next({ ...transformContext, error: new Error(error) });
} else {
// eslint-disable-next-line @typescript-eslint/no-base-to-string, @typescript-eslint/restrict-template-expressions
subject.next({ ...transformContext, error: new Error(`${error}`) });
}

if (error instanceof ValidationError) {
Expand Down
10 changes: 10 additions & 0 deletions packages/contentful-ssg/src/lib/error.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,13 @@ export class ValidationError extends Error {
this.name = 'ValidationError';
}
}

export class WrappedError extends Error {
originalError: unknown;

constructor(message: string, error: unknown) {
super(message);
this.originalError = error;
this.name = 'WrappedError';
}
}
9 changes: 5 additions & 4 deletions packages/contentful-ssg/src/lib/stats.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,12 @@ export class Stats {
this.success.push({ message, ...this.toEntry(context) });
}

addError(context: TransformContext, error: string | Error): void {
if (typeof error === 'string') {
this.errors.push({ error: new Error(error), ...this.toEntry(context) });
} else {
addError(context: TransformContext, error: unknown): void {
if (error instanceof Error) {
this.errors.push({ error, ...this.toEntry(context) });
} else {
// eslint-disable-next-line @typescript-eslint/no-base-to-string, @typescript-eslint/restrict-template-expressions
this.errors.push({ error: new Error(`${error}`), ...this.toEntry(context) });
}
}

Expand Down
11 changes: 10 additions & 1 deletion packages/contentful-ssg/src/lib/utils.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Entry, TransformContext } from '../types.js';
import { collect, collectParentValues, collectValues, waitFor } from './utils.js';
import { BehaviorSubject } from 'rxjs';
import { WrappedError } from './error.js';

const data = new Map([
['1', { sys: { id: '1' }, fields: { slug: 'a' } }],
Expand Down Expand Up @@ -183,7 +184,15 @@ describe('Utils', () => {

await expect(async () => {
await waitFor({ ...transformContext, entry, observable })('4');
}).rejects.toThrowError('test error');
}).rejects.toThrowError(WrappedError);

try {
await waitFor({ ...transformContext, entry, observable })('4');
} catch (error) {
expect(error).toBeInstanceOf(WrappedError);
expect(error.message).toMatch('Awaited entry 4 (test-type) errored');
expect(error.originalError.message).toEqual('test error');
}
});

test('detect cyclic dependency', async () => {
Expand Down
3 changes: 2 additions & 1 deletion packages/contentful-ssg/src/lib/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import type { CollectOptions, Entry, TransformContext } from '../types.js';
import { getContentId, getContentTypeId } from './contentful.js';
import { ReplaySubject, map, distinct, filter } from 'rxjs';
import dlv from 'dlv';
import { WrappedError } from './error.js';

// eslint-disable-next-line @typescript-eslint/naming-convention
const DEFAULT_WAIT_TIMEOUT = 20000;
Expand Down Expand Up @@ -130,7 +131,7 @@ Entry ${source} waiting for ${dest}.`
.subscribe((value) => {
clearTimeout(timeout);
if (value.error) {
reject(new Error(`Awaited entry ${dest} errored: ${value?.error?.message ?? ''}`));
reject(new WrappedError(`Awaited entry ${dest} errored`, value.error));
} else {
resolve(value);
}
Expand Down

0 comments on commit 7a3b4be

Please sign in to comment.