Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(database): Implement hooks to get database load status so models…
… can be seeded. feat(exceptions): Implement exceptions with docs & tests. feat(schema hydration): Implement @StoredProperty decorator for migrating all properties
- Loading branch information
Showing
16 changed files
with
549 additions
and
82 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
--- | ||
title: Exceptions | ||
description: Something gone terribly wrong? Thow an exception | ||
date: 2016-06-20 | ||
collection: guide | ||
collectionSort: 1 | ||
layout: guide.hbs | ||
--- | ||
|
||
Ubiquits provides a number of built-in `HttpExceptions` that should be thrown rather than `Error` when an unexpected | ||
event occurs. This allows the call stack handler to inspect the exception status code, and return that to the client so | ||
it can handle the error in a meaningful way. | ||
|
||
The exceptions that are available are: | ||
|
||
* BadRequestException (code 400) | ||
* UnauthorizedException (code 401) | ||
* PaymentRequiredException (code 402) | ||
* ForbiddenException (code 403) | ||
* NotFoundException (code 404) | ||
* MethodNotAllowedException (code 405) | ||
* NotAcceptableException (code 406) | ||
* ProxyAuthenticationRequiredException (code 407) | ||
* RequestTimeoutException (code 408) | ||
* ConflictException (code 409) | ||
* GoneException (code 410) | ||
* LengthRequiredException (code 411) | ||
* PreconditionFailedException (code 412) | ||
* PayloadTooLargeException (code 413) | ||
* URITooLongException (code 414) | ||
* UnsupportedMediaTypeException (code 415) | ||
* RangeNotSatisfiableException (code 416) | ||
* ExpectationFailedException (code 417) | ||
* UnprocessableEntityException (code 422) | ||
* TooManyRequestsException (code 429) | ||
* UnavailableForLegalReasonsException (code 451) | ||
* InternalServerErrorException (code 500) | ||
* NotImplementedException (code 501) | ||
* ServiceUnavailableException (code 503) | ||
* InsufficientStorageException (code 507) | ||
|
||
|
||
## Example | ||
|
||
In a database store, the NotFoundException is thrown when the record is not present in the database: | ||
|
||
```typescript | ||
public findOne(id: identifier): Promise<T> { | ||
return this.orm.findByPrimary(<number|string>id) | ||
.then((modelData: Instance<any>): T => { | ||
if (!modelData){ | ||
throw new NotFoundException(`Model not found for id [${id}]`); | ||
} | ||
return new this.modelStatic(modelData.get()); | ||
}); | ||
} | ||
``` | ||
|
||
The exception is eventually caught by the stack handler, and will return the following response: | ||
|
||
``` | ||
HTTP/1.1 404 Not Found | ||
{ | ||
"message": "Model not found for id [72eed629-c4ab-4520-a987-4ea26b134d8c]" | ||
} | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,3 @@ | ||
export * from './date.decorator'; | ||
export * from './primary.decorator'; | ||
export * from './storedProperty.decorator'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
|
||
export function primary(target: any, propertyKey: string) { | ||
if (!target.constructor.storedProperties) { | ||
target.constructor.storedProperties = new Map(); | ||
} | ||
let type = Reflect.getMetadata("design:type", target, propertyKey); | ||
target.constructor.storedProperties.set(propertyKey, type); | ||
|
||
target.constructor.identifierKey = propertyKey; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
export function StoredProperty(target: any, propertyKey: string): void { | ||
|
||
if (!target.constructor.storedProperties) { | ||
target.constructor.storedProperties = new Map(); | ||
} | ||
let type = Reflect.getMetadata("design:type", target, propertyKey); | ||
target.constructor.storedProperties.set(propertyKey, type); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
import { it, expect, describe } from '@angular/core/testing'; | ||
import { | ||
InsufficientStorageException, | ||
ServiceUnavailableException, | ||
NotImplementedException, | ||
InternalServerErrorException, | ||
UnavailableForLegalReasonsException, | ||
TooManyRequestsException, | ||
UnprocessableEntityException, | ||
ExpectationFailedException, | ||
RangeNotSatisfiableException, | ||
UnsupportedMediaTypeException, | ||
URITooLongException, | ||
PayloadTooLargeException, | ||
PreconditionFailedException, | ||
LengthRequiredException, | ||
GoneException, | ||
ConflictException, | ||
RequestTimeoutException, | ||
ProxyAuthenticationRequiredException, | ||
NotAcceptableException, | ||
MethodNotAllowedException, | ||
NotFoundException, | ||
ForbiddenException, | ||
PaymentRequiredException, | ||
UnauthorizedException, | ||
BadRequestException, | ||
HttpException | ||
} from './exceptions'; | ||
|
||
describe('Exceptions', () => { | ||
|
||
const exceptions = [ | ||
{exception: BadRequestException, code: 400}, | ||
{exception: UnauthorizedException, code: 401}, | ||
{exception: PaymentRequiredException, code: 402}, | ||
{exception: ForbiddenException, code: 403}, | ||
{exception: NotFoundException, code: 404}, | ||
{exception: MethodNotAllowedException, code: 405}, | ||
{exception: NotAcceptableException, code: 406}, | ||
{exception: ProxyAuthenticationRequiredException, code: 407}, | ||
{exception: RequestTimeoutException, code: 408}, | ||
{exception: ConflictException, code: 409}, | ||
{exception: GoneException, code: 410}, | ||
{exception: LengthRequiredException, code: 411}, | ||
{exception: PreconditionFailedException, code: 412}, | ||
{exception: PayloadTooLargeException, code: 413}, | ||
{exception: URITooLongException, code: 414}, | ||
{exception: UnsupportedMediaTypeException, code: 415}, | ||
{exception: RangeNotSatisfiableException, code: 416}, | ||
{exception: ExpectationFailedException, code: 417}, | ||
{exception: UnprocessableEntityException, code: 422}, | ||
{exception: TooManyRequestsException, code: 429}, | ||
{exception: UnavailableForLegalReasonsException, code: 451}, | ||
{exception: InternalServerErrorException, code: 500}, | ||
{exception: NotImplementedException, code: 501}, | ||
{exception: ServiceUnavailableException, code: 503}, | ||
{exception: InsufficientStorageException, code: 507}, | ||
]; | ||
|
||
exceptions.forEach((check) => { | ||
|
||
it(`creates instance of ${check.exception.prototype.constructor.name} with status code ${check.code}`, () => { | ||
|
||
const exceptionInstance = new check.exception; | ||
|
||
expect(exceptionInstance instanceof Error).toBe(true); | ||
expect(exceptionInstance instanceof HttpException).toBe(true); | ||
expect(exceptionInstance.getStatusCode()).toEqual(check.code); | ||
expect(exceptionInstance.name).toEqual(exceptionInstance.constructor.name); | ||
|
||
}); | ||
|
||
}); | ||
|
||
|
||
|
||
}); |
Oops, something went wrong.