Skip to content

Commit

Permalink
example app updates
Browse files Browse the repository at this point in the history
  • Loading branch information
jczacharia committed Oct 22, 2021
1 parent f463d3e commit d303890
Show file tree
Hide file tree
Showing 30 changed files with 227 additions and 229 deletions.
1 change: 0 additions & 1 deletion libs/angular/src/lib/orcha.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,6 @@ export class OrchaModule {
switch (event.type) {
case HttpEventType.UploadProgress:
return { ...event, progress: Math.round((100 * event.loaded) / (event.total ?? 1)) };

case HttpEventType.Response:
if (files) {
return event;
Expand Down
16 changes: 8 additions & 8 deletions libs/nestjs/src/lib/decorators/server.decorator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,24 +20,24 @@ import { QueryValidationPipe } from '../pipes/query-validation.pipe';
* ```ts
* @ServerOrchestration('user')
* export class UserOrchestration implements IServerOrchestration<IUserOrchestration> {
* constructor(private readonly user: UserService) {}
* constructor(private readonly _user: UserService) {}
*
* // `/orcha/user/login`
* @ServerOperation({ validateQuery: LoginQueryModel })
* login(query: IQuery<{ token: string }>, _: string, { id, password }: LoginDto) {
* return this.user.login(id, password, query);
* return this._user.login(id, password, query);
* }
*
* // `/orcha/user/signUp`
* @ServerOperation({ validateQuery: SignUpQueryModel })
* signUp(query: IQuery<{ token: string }>, _: string, { id, password }: SignUpDto) {
* return this.user.signUp(id, password, query);
* return this._user.signUp(id, password, query);
* }
*
* // `/orcha/user/getProfile`
* @ServerOperation({ validateQuery: EntireProfile })
* getProfile(query: IQuery<User>, token: string) {
* return this.user.verifyUserToken(token, query);
* return this._user.verifyUserToken(token, query);
* }
* }
* ```
Expand Down Expand Up @@ -68,24 +68,24 @@ function transform(val: string) {
* ```ts
* @ServerOrchestration('user')
* export class UserOrchestration implements IServerOrchestration<IUserOrchestration> {
* constructor(private readonly user: UserService) {}
* constructor(private readonly _user: UserService) {}
*
* // `/orcha/user/login`
* @ServerOperation({ validateQuery: LoginQueryModel })
* login(query: IQuery<{ token: string }>, _: string, { id, password }: LoginDto) {
* return this.user.login(id, password, query);
* return this._user.login(id, password, query);
* }
*
* // `/orcha/user/signUp`
* @ServerOperation({ validateQuery: SignUpQueryModel })
* signUp(query: IQuery<{ token: string }>, _: string, { id, password }: SignUpDto) {
* return this.user.signUp(id, password, query);
* return this._user.signUp(id, password, query);
* }
*
* // `/orcha/user/getProfile`
* @ServerOperation({ validateQuery: EntireProfile })
* getProfile(query: IQuery<User>, token: string) {
* return this.user.verifyUserToken(token, query);
* return this._user.verifyUserToken(token, query);
* }
* }
* ```
Expand Down
8 changes: 4 additions & 4 deletions libs/nestjs/src/lib/pipes/validation.pipe.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,26 +6,26 @@ import { validate } from 'class-validator';
@Injectable()
export class ValidationPipe implements PipeTransform<unknown> {
async transform(value: unknown, { metatype }: ArgumentMetadata): Promise<unknown> {
if (!metatype || !this.toValidate(metatype)) {
if (!metatype || !this._toValidate(metatype)) {
return value;
}
const object = plainToClass(metatype, value);
const errors = await validate(object);
if (errors.length > 0) {
throw new HttpException(
`Validation failed: ${this.formatErrors(errors as { constraints: {} }[])}`,
`Validation failed: ${this._formatErrors(errors as { constraints: {} }[])}`,
HttpStatus.BAD_REQUEST
);
}
return value;
}

private toValidate(metaType: Function): boolean {
private _toValidate(metaType: Function): boolean {
const types: Function[] = [String, Boolean, Number, Array, Object];
return !types.includes(metaType);
}

private formatErrors(errors: { constraints: {} }[]): string {
private _formatErrors(errors: { constraints: {} }[]): string {
return errors
.map(({ constraints }) => {
for (const value of Object.values(constraints)) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
export * from './lib/app.facade';
export * from './lib/client-shared-data-access.module';
export { TagStoreModel } from './lib/tag/tag.reducer';
export { TodoStoreModel } from './lib/todo/todo.reducer';
export * from './lib/user/user.orchestration';
Original file line number Diff line number Diff line change
Expand Up @@ -2,77 +2,74 @@ import { Injectable } from '@angular/core';
import { Actions, ofType } from '@ngrx/effects';
import { select, Store } from '@ngrx/store';
import { UpdateTodoDto } from '@orcha-todo-example-app/shared/domain';
import { UnArray, UnObservable } from '@orcha-todo-example-app/shared/util';
import { tap } from 'rxjs/operators';
import * as TodoActions from './todo/todo.actions';
import * as TagActions from './tag/tag.actions';
import * as TagSelectors from './tag/tag.selectors';
import * as TodoActions from './todo/todo.actions';
import { TodoStoreModel } from './todo/todo.reducer';
import * as TodoSelectors from './todo/todo.selectors';
import * as TagSelectors from './tag/tag.selectors';
import * as UserActions from './user/user.actions';
import * as UserSelectors from './user/user.selectors';

export type TagStoreModel = UnArray<UnObservable<typeof AppFacade.prototype.tag.selectors.tags$>['tags']>;

@Injectable()
export class AppFacade {
readonly user = {
dispatchers: {
login: (id: string, password: string) => {
this.store.dispatch(UserActions.userLogin({ id, password }));
this._store.dispatch(UserActions.userLogin({ id, password }));
},
signUp: (id: string, password: string) => {
this.store.dispatch(UserActions.userSignUp({ id, password }));
this._store.dispatch(UserActions.userSignUp({ id, password }));
},
getProfile: () => {
this.store.dispatch(UserActions.getProfile());
this._store.dispatch(UserActions.getProfile());
},
logout: () => {
this.store.dispatch(UserActions.logout());
this._store.dispatch(UserActions.logout());
},
},
actionListeners: {
login: {
success: this.actions$.pipe(ofType(UserActions.userLoginSuccess)),
error: this.actions$.pipe(ofType(UserActions.userLoginError)),
success: this._actions$.pipe(ofType(UserActions.userLoginSuccess)),
error: this._actions$.pipe(ofType(UserActions.userLoginError)),
},
signUp: {
success: this.actions$.pipe(ofType(UserActions.userSignUpSuccess)),
error: this.actions$.pipe(ofType(UserActions.userSignUpError)),
success: this._actions$.pipe(ofType(UserActions.userSignUpSuccess)),
error: this._actions$.pipe(ofType(UserActions.userSignUpError)),
},
getProfile: {
success: this.actions$.pipe(ofType(UserActions.getProfileSuccess)),
error: this.actions$.pipe(ofType(UserActions.getProfileError)),
success: this._actions$.pipe(ofType(UserActions.getProfileSuccess)),
error: this._actions$.pipe(ofType(UserActions.getProfileError)),
},
},
selectors: {
state$: this.store.select(UserSelectors.getState),
state$: this._store.select(UserSelectors.getState),
},
};

readonly todo = {
dispatchers: {
create: (content: string) => {
this.store.dispatch(TodoActions.createTodo({ content }));
this._store.dispatch(TodoActions.createTodo({ content }));
},
delete: (todo: TodoStoreModel) => {
this.store.dispatch(TodoActions.deleteTodo({ todo }));
this._store.dispatch(TodoActions.deleteTodo({ todo }));
},
update: (dto: UpdateTodoDto) => {
this.store.dispatch(TodoActions.updateTodo({ dto }));
this._store.dispatch(TodoActions.updateTodo({ dto }));
},
tag: (todo: TodoStoreModel, tagName: string) => {
this.store.dispatch(TodoActions.tagTodo({ todo, tagName }));
this._store.dispatch(TodoActions.tagTodo({ todo, tagName }));
},
untag: (taggedTodoId: string) => {
this.store.dispatch(TodoActions.untagTodo({ taggedTodoId }));
this._store.dispatch(TodoActions.untagTodo({ taggedTodoId }));
},
},
selectors: {
todos$: this.store.pipe(select(TodoSelectors.getTodos)).pipe(
todos$: this._store.pipe(select(TodoSelectors.getTodos)).pipe(
tap(({ loaded }) => {
if (!loaded) {
this.store.dispatch(TodoActions.readTodos());
this._store.dispatch(TodoActions.readTodos());
}
})
),
Expand All @@ -81,15 +78,15 @@ export class AppFacade {

readonly tag = {
selectors: {
tags$: this.store.pipe(select(TagSelectors.getTags)).pipe(
tags$: this._store.pipe(select(TagSelectors.getTags)).pipe(
tap(({ loaded }) => {
if (!loaded) {
this.store.dispatch(TagActions.readTags());
this._store.dispatch(TagActions.readTags());
}
})
),
},
};

constructor(private readonly store: Store, private readonly actions$: Actions) {}
constructor(private readonly _store: Store, private readonly _actions$: Actions) {}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,11 @@ import { TagOrchestration } from './tag.orchestration';
@Injectable()
export class TagEffects {
readonly readTags$ = createEffect(() =>
this.actions$.pipe(
this._actions$.pipe(
ofType(TagActions.readTags),
fetch({
run: () =>
this.tag.read(TagQueryModel).pipe(
this._tag.read(TagQueryModel).pipe(
map((tags) => {
return TagActions.readTagsSuccess({ tags });
})
Expand All @@ -26,5 +26,5 @@ export class TagEffects {
)
);

constructor(private readonly actions$: Actions, private readonly tag: TagOrchestration) {}
constructor(private readonly _actions$: Actions, private readonly _tag: TagOrchestration) {}
}
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { createEntityAdapter, EntityState } from '@ngrx/entity';
import { createReducer, on } from '@ngrx/store';
import { TagQueryModel, Todo } from '@orcha-todo-example-app/shared/domain';
import { Tag, TagQueryModel } from '@orcha-todo-example-app/shared/domain';
import { IParser } from '@orcha/common';
import * as TagActions from './tag.actions';

export const TAG_KEY = 'tag';

export type TagStoreModel = IParser<Todo, typeof TagQueryModel>;
export type TagStoreModel = IParser<Tag, typeof TagQueryModel>;

export interface TagState {
tags: EntityState<TagStoreModel>;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,11 @@ import { TodoOrchestration } from './todo.orchestration';
@Injectable()
export class TodoEffects {
readonly readTodos$ = createEffect(() =>
this.actions$.pipe(
this._actions$.pipe(
ofType(TodoActions.readTodos),
fetch({
run: () =>
this.todo.read(TodoQueryModel).pipe(
this._.read(TodoQueryModel).pipe(
map((todos) => {
return TodoActions.readTodosSuccess({ todos });
})
Expand All @@ -29,11 +29,11 @@ export class TodoEffects {
);

readonly createTodo$ = createEffect(() =>
this.actions$.pipe(
this._actions$.pipe(
ofType(TodoActions.createTodo),
pessimisticUpdate({
run: ({ content }) =>
this.todo.create(TodoQueryModel, { content }).pipe(
this._.create(TodoQueryModel, { content }).pipe(
map((todo) => {
return TodoActions.createTodoSuccess({ todo });
})
Expand All @@ -47,11 +47,11 @@ export class TodoEffects {
);

readonly deleteTodo$ = createEffect(() =>
this.actions$.pipe(
this._actions$.pipe(
ofType(TodoActions.deleteTodo),
pessimisticUpdate({
run: ({ todo }) =>
this.todo.delete(DeleteTodoQueryModel, { todoId: todo.id }).pipe(
this._.delete(DeleteTodoQueryModel, { todoId: todo.id }).pipe(
map(({ deletedId }) => {
return TodoActions.deleteTodoSuccess({ deletedId });
})
Expand All @@ -65,11 +65,11 @@ export class TodoEffects {
);

readonly updateTodo$ = createEffect(() =>
this.actions$.pipe(
this._actions$.pipe(
ofType(TodoActions.updateTodo),
pessimisticUpdate({
run: ({ dto }) =>
this.todo.update(TodoQueryModel, dto).pipe(
this._.update(TodoQueryModel, dto).pipe(
map((todo) => {
return TodoActions.updateTodoSuccess({ todo });
})
Expand All @@ -83,12 +83,13 @@ export class TodoEffects {
);

readonly tagTodo$ = createEffect(() =>
this.actions$.pipe(
this._actions$.pipe(
ofType(TodoActions.tagTodo),
pessimisticUpdate({
run: ({ todo, tagName }) =>
this.todo.tag(TodoQueryModel, { todoId: todo.id, tagName }).pipe(
this._.tag(TodoQueryModel, { todoId: todo.id, tagName }).pipe(
switchMap((todo) => {
// Here reload tags since it's possible a new one was created.
return of(TodoActions.tagTodoSuccess({ todo }), TagActions.readTags());
})
),
Expand All @@ -101,12 +102,13 @@ export class TodoEffects {
);

readonly untagTodo$ = createEffect(() =>
this.actions$.pipe(
this._actions$.pipe(
ofType(TodoActions.untagTodo),
pessimisticUpdate({
run: ({ taggedTodoId }) =>
this.todo.untag(TodoQueryModel, { taggedTodoId }).pipe(
this._.untag(TodoQueryModel, { taggedTodoId }).pipe(
switchMap((todo) => {
// Here reload tags since it's possible one was deleted.
return of(TodoActions.untagTodoSuccess({ todo }), TagActions.readTags());
})
),
Expand All @@ -118,5 +120,5 @@ export class TodoEffects {
)
);

constructor(private readonly actions$: Actions, private readonly todo: TodoOrchestration) {}
constructor(private readonly _actions$: Actions, private readonly _: TodoOrchestration) {}
}
Loading

0 comments on commit d303890

Please sign in to comment.