Skip to content

Commit

Permalink
replaced mermaid diagrams with pictures (#243)
Browse files Browse the repository at this point in the history
  • Loading branch information
mlhaufe authored Oct 23, 2022
1 parent 6a7ede5 commit b8a11fa
Show file tree
Hide file tree
Showing 8 changed files with 1,815 additions and 3,388 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
# Changelog

## v0.24.2

* Updated README to use images instead of mermaid diagrams
* Updated dependencies

## v0.24.1

* Bugfix of generated type declaration (#238)
Expand Down
38 changes: 2 additions & 36 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -906,9 +906,7 @@ where you can lexically determine where the handling occurs and optionally perfo

When `obj.feature` is called the happy path is:

```ts
invariant -> demands -> { feature body } -> ensures -> invariant
```
![image](./docs/happy-path.png)

If an error is thrown and there is no `rescue` defined then the `invariant`
is checked before the error is raised to the caller.
Expand All @@ -927,39 +925,7 @@ starts from the beginning.
If `rescue` throws an error or does not call `retry` then the
`invariant` is checked before the error is raised to the caller.

```mermaid
flowchart LR
Feature(("obj.feature(...)"))
Invariant["@invariant"]
Invariant2["@invariant"]
Invariant3["@invariant"]
Demands["@demands"]
Ensures["@ensures"]
Rescue["@rescue"]
Error(("Error"))
Body["{feature body}"]
Result(("Result"))
Feature --> Invariant
Invariant -->|throws| Error
Invariant --> Demands
Demands -->|throws| Error
Demands --> Body
Body -->|throws| Rescue
Rescue -->|retry| Invariant
Body -->|returns| Ensures
Ensures -->|throws| Rescue
Ensures --> Invariant3
Invariant3 --> Result
Rescue --> |throws| Invariant2
Rescue --> |returns| Invariant2
Invariant2 --> Error
style Error fill:red
style Result fill:green
style Rescue fill:darkorange
```
![image](./docs/order-of-assertions.png)

## Further Reading

Expand Down
Binary file added docs/happy-path.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/order-of-assertions.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
5,124 changes: 1,790 additions & 3,334 deletions package-lock.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@final-hill/decorator-contracts",
"version": "0.24.1",
"version": "0.24.2",
"description": "Code Contracts for TypeScript and ECMAScript classes",
"main": "dist/index.js",
"types": "dist/index.d.ts",
Expand Down
22 changes: 11 additions & 11 deletions src/Contract.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,17 @@
* @see <https://spdx.org/licenses/AGPL-3.0-only.html>
*/

import {deepFreeze, fnTrue} from './lib';
import { deepFreeze, fnTrue } from './lib';

const checkedMode = Symbol('checkedMode'),
invariant = Symbol('invariant'),
extend = Symbol('extend');
invariant = Symbol('invariant'),
extend = Symbol('extend');

type AnyObject = Record<PropertyKey, any>;
type AnyFunc = (...args: any[]) => any;

type NonFunctionPropertyNames<T extends AnyObject> = { [K in keyof T]: T[K] extends AnyFunc ? never : K }[keyof T];
type Properties<T extends AnyObject> = Pick<T, NonFunctionPropertyNames<T>>;
export type Properties<T extends AnyObject> = Pick<T, NonFunctionPropertyNames<T>>;

export type Invariant<T extends AnyObject> = (self: T) => boolean;
export type Demands<T extends AnyObject, F extends T[any]> = (self: T, ...args: Parameters<F>) => boolean;
Expand All @@ -34,13 +34,13 @@ export type ContractOptions<
[invariant]: Invariant<T>;
[checkedMode]: boolean;
} & {
[K in keyof T]?: FeatureOption<T, T[K]>
};
[K in keyof T]?: FeatureOption<T, T[K]>
};

export interface FeatureOption<T extends AnyObject, F extends T[any]> {
demands?: Demands<T,F>;
ensures?: Ensures<T,F>;
rescue?: Rescue<T,F>;
demands?: Demands<T, F>;
ensures?: Ensures<T, F>;
rescue?: Rescue<T, F>;
within?: number;
}

Expand All @@ -57,7 +57,7 @@ export class Contract<T extends AnyObject> {

Object.keys(assertions).forEach(propertyKey => {
const featureOption = assertions[propertyKey]!;
Object.defineProperty(this.assertions,propertyKey, {
Object.defineProperty(this.assertions, propertyKey, {
value: {
demands: featureOption.demands ?? fnTrue,
ensures: featureOption.ensures ?? fnTrue,
Expand All @@ -75,4 +75,4 @@ export class Contract<T extends AnyObject> {
}
}

export {checkedMode, extend, invariant};
export { checkedMode, extend, invariant };
12 changes: 6 additions & 6 deletions src/lib/assertEnsures.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
* @see <https://spdx.org/licenses/AGPL-3.0-only.html>
*/

import { Ensures, extend } from '../Contract';
import { Ensures, extend, Properties } from '../Contract';
import { assert, checkedMode, Contract } from '../';
import unChecked from './unChecked';

Expand All @@ -20,26 +20,26 @@ import unChecked from './unChecked';
* @param {any[]} args - The arguments of the feature to apply to the assertion
* @throws {AssertionError}
*/
function assertEnsures<U>(
function assertEnsures<U extends Properties<any>>(
ctx: U,
contract: Contract<any>,
className: string,
featureName: PropertyKey,
old: U,
args: any[]
){
) {
const e: Ensures<any, any> | undefined = Reflect.get(contract.assertions, featureName)?.ensures,
ensuresError = `ensures not met on ${className}.prototype.${String(featureName)}\r\n${e}`;

if(contract[checkedMode]) {
if(e) {
if (contract[checkedMode]) {
if (e) {
unChecked(contract, () =>
assert(e.call(ctx, ctx, old, ...args), ensuresError)
);
}
}

if(contract[extend]) {
if (contract[extend]) {
assertEnsures(ctx, contract[extend]!, className, featureName, old, args);
}
}
Expand Down

0 comments on commit b8a11fa

Please sign in to comment.