@azu azu released this Jul 21, 2017 · 219 commits to master since this release

Assets 2

Summary

  • πŸ”₯ Breaking Changes
    • Drop IE9/IE10
    • No need to change code in almost case
  • ⚠️ Deprecated
    • Rename context.onWillExecuteEachUseCase to context.events.onWillExecuteEachUseCase
    • You can update via almin/migration-tools
  • πŸ†• Features
    • Strict mode
    • Transaction that is work in strict mode
    • executor that is Type-safe version of execute
  • 🏠 Internal
    • Introduce Unit of Work as actual class

Breaking Change πŸ”₯

Almin 0.13 include some breaking change, but it will work without changing code in almost case.

Drop IE9 and IE10 #168 #234

IE 9/10 have been EOL.

Almin has removed E2E tests on IE 9/IE 10.

Store#onDispatch receive only dispatched the Payload by UseCase#dispatch #224 #254 #255

Store#onDispatch can receive only dispatched the Payload by UseCase#dispatch.
Previously, Store#onDispatch can receive all events of almin.
Store should not depended on almin system events.

If You want to see almin system events, please use context.events(LifeCycleEventHub).

Example:

class MyStore extends Store {
  constructor(){
    super();
    this.unsubscribe = store.onDispatch((payload, meta) => {
        // This handler is called when call `UseCase#dispatch`
        console.log(payload);
    });
  }
  // ....
}

Some UseCase dispatch the payload and Store#onDispatch catch that.

class MyUseCase extends UseCase{
  execute(){
    this.dispatch({
      type: "test"
    }); // => Store#onDispatch catch this
}

Recommened: Implement updating logic of the Store into Store#receivePayload.

Automatically catch throwing Error from UseCase#execute() #193 #194

0.12 can catch sync error in UseCase#execute.
Previously, Almin only catch async error(return rejected promise).

class ThrowUseCase extends UseCase {
  execute() {
     throw new Error("error");
  }
}

context.useCase(new ThrowUseCase).catch(error => {
    console.log("It can catch")
});

new Store() throw Error

Store is abstract class.
You should inherited Store and use it.

Notable Changes

Renaming: context.on* to context.events.on* #239

Rename context.on* to context.events.on* without context.onChange((stores) => {}).

Migration

You can migrate this by using almin/migration-tools.

npm install -g @almin/migration-tools
almin-migration-tools [<file|glob> ...]

Before:

context.onWillExecuteEachUseCase((payload, meta) => {});
context.onDispatch((payload, meta) => {});
context.onDidExecuteEachUseCase((payload, meta) => {});
context.onCompleteEachUseCase((payload, meta) => {});
context.onErrorDispatch((payload, meta) => {});

After:

context.events.onWillExecuteEachUseCase((payload, meta) => {});
context.events.onDispatch((payload, meta) => {});
context.events.onDidExecuteEachUseCase((payload, meta) => {});
context.events.onCompleteEachUseCase((payload, meta) => {});
context.events.onErrorDispatch((payload, meta) => {});

Remove undocument UseCaseExecutor#on handler #243

Remove

UseCaseExecutor#onWillExecuteEachUseCase
UseCaseExecutor#onDidExecuteEachUseCase
UseCaseExecutor#onCompleteExecuteEachUseCase

Feature πŸ†•

Strict mode

See documents: https://almin.js.org/docs/tips/strict-mode.html

  • Strict mode check that updating store/state in Store#receivePayload
    • It means that show warning if update store outside of receivePayload
// enable strict mode
const context = new Context({ 
   dispatcher, 
   store, 
   options: {
     strict: true
   }
});

Context#transaction #226

  • Stability: Experimental
  • This feature is subject to change. It may change or be removed in future versions.
  • This feature is enabled in strict mode

It allow to execute multiple UseCases in a transaction.
It aim to reduce unnessary updating of view/store.

UseCase vs. Transaction

const context = new Context({
    dispatcher: new Dispatcher(),
    store: storeGroup,
    options: {
        strict: true
    }
});
// then - called change handler a one-time
let onChangeCount = 0;
context.onChange(stores => {
    onChangeCount++;
});
// when
context
    .transaction("transaction name", transactionContext => {
        return transactionContext
            .useCase(new ChangeAUseCase())
            .execute(1)
            .then(() => transactionContext.useCase(new ChangeAUseCase()).execute(2))
            .then(() => transactionContext.useCase(new ChangeAUseCase()).execute(3))
            .then(() => transactionContext.useCase(new ChangeAUseCase()).execute(4))
            .then(() => transactionContext.useCase(new ChangeAUseCase()).execute(5))
            .then(() => {
                // commit the result to StoreGroup
                transactionContext.commit();
            });
    })
    .then(() => {
        // finish the transation
        console.log(onChangeCount); // => 1
    });

Add Fluent style executor #193

  • Stability: Experimental
  • This feature is subject to change. It may change or be removed in future versions.
  • See #193

It is type-safe version of execute() function.
It is useful for TypeScript user.

context.useCase(new MyUseCase())
    .executor(useCase => useCase.execute("test"))
    .then(value => {
        console.log(value);
    });

context.useCase(useCase).execute() is syntax suger of context.useCase(useCase).executor(useCase => useCase.execute()).

TypeScript

Export UseCaseExecutor interface #243 #247

Export UseCaseExecutor from index.d.ts.
It will be used for wrapping function of context.useCase.

StoreLike<T> have default generics type

Almin 0.13 change StoreLike<T> to StoreLike<T = any>.

Documentaions πŸ“

Update API documents.

Please See https://almin.js.org/

Almin-logger

Internals

Almin's test code move forward to TypeScript #232

Welcome to Pull Request that convert test/ to TypeScript code :)

Notes πŸ“

Unit of Work

Introduce Unit of work as a class.
It aim to implement transaction between executing UseCase.
In other word, unit of work can control updating StoreGroup.
The user can stop unintended updating StoreGroup.

Unit of Work