├── src
├── client
│ ├── index.ts
│ ├── signUp
│ │ ├── selectors.ts
│ │ ├── index.ts
│ │ ├── operations.ts
│ │ ├── actions.ts
│ │ ├── reducer.ts
│ │ └── types.ts
│ ├── pages
│ │ ├── Timeline.tsx
│ │ ├── index.ts
│ │ ├── SignUp.tsx
│ │ └── SignIn.tsx
│ ├── index.html
│ ├── app
│ │ ├── index.ts
│ │ ├── actions.ts
│ │ ├── types.ts
│ │ └── reducer.ts
│ ├── signIn
│ │ ├── index.ts
│ │ ├── operations.ts
│ │ ├── actions.ts
│ │ ├── reducer.ts
│ │ └── types.ts
│ ├── Root.tsx
│ ├── main.tsx
│ ├── webpack.config.js
│ ├── diContainer.ts
│ ├── types.ts
│ └── store.ts
├── data-access
│ ├── index.ts
│ └── MemoryDataAccess.ts
├── utils
│ ├── AutoNamedError.ts
│ ├── index.ts
│ ├── WrapError.ts
│ └── WrapError.test.ts
├── usecases
│ ├── createRetweet
│ │ ├── DataAccessError.ts
│ │ ├── index.ts
│ │ ├── factory.ts
│ │ └── interface.ts
│ ├── createTweet
│ │ ├── DataAccessError.ts
│ │ ├── UserNotExists.ts
│ │ ├── InvalidTweetText.ts
│ │ ├── index.ts
│ │ ├── factory.ts
│ │ └── interface.ts
│ ├── createUser
│ │ ├── DataAccessError.ts
│ │ ├── InvalidUserName.ts
│ │ ├── UserNameDuplicated.ts
│ │ ├── index.ts
│ │ ├── interface.ts
│ │ └── factory.ts
│ ├── getTweets
│ │ ├── DataAccessError.ts
│ │ ├── index.ts
│ │ ├── factory.ts
│ │ └── interface.ts
│ ├── signInWithPassword
│ │ ├── DataAccessError.ts
│ │ ├── index.ts
│ │ ├── factory.ts
│ │ └── interface.ts
│ ├── signUpWithPassword
│ │ ├── DataAccessError.ts
│ │ ├── index.ts
│ │ ├── interface.ts
│ │ └── factory.ts
│ ├── interface.ts
│ └── index.ts
└── entities
│ └── index.ts
├── README.md
├── .prettierrc.json
├── jest.config.js
├── tslint.json
├── LICENSE
├── .gitignore
├── package.json
└── tsconfig.json
/src/client/index.ts:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/client/signUp/selectors.ts:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # twitter-like-app-clean-architecture
--------------------------------------------------------------------------------
/.prettierrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "singleQuote": true
3 | }
4 |
--------------------------------------------------------------------------------
/src/data-access/index.ts:
--------------------------------------------------------------------------------
1 | export { default as MemoryDataAccess } from './MemoryDataAccess';
2 |
--------------------------------------------------------------------------------
/jest.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | preset: 'ts-jest',
3 | testEnvironment: 'node'
4 | };
5 |
--------------------------------------------------------------------------------
/src/utils/AutoNamedError.ts:
--------------------------------------------------------------------------------
1 | export default class AutoNamedError extends Error {
2 | public name = this.constructor.name;
3 | }
4 |
--------------------------------------------------------------------------------
/src/utils/index.ts:
--------------------------------------------------------------------------------
1 | export { default as AutoNamedError } from './AutoNamedError';
2 | export { default as WrapError } from './WrapError';
3 |
--------------------------------------------------------------------------------
/src/usecases/createRetweet/DataAccessError.ts:
--------------------------------------------------------------------------------
1 | import { WrapError } from '@pirosikick/utils';
2 |
3 | export default class DataAccessError extends WrapError {}
4 |
--------------------------------------------------------------------------------
/src/usecases/createTweet/DataAccessError.ts:
--------------------------------------------------------------------------------
1 | import { WrapError } from '@pirosikick/utils';
2 |
3 | export default class DataAccessError extends WrapError {}
4 |
--------------------------------------------------------------------------------
/src/usecases/createUser/DataAccessError.ts:
--------------------------------------------------------------------------------
1 | import { WrapError } from '@pirosikick/utils';
2 |
3 | export default class DataAccessError extends WrapError {}
4 |
--------------------------------------------------------------------------------
/src/client/pages/Timeline.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 |
3 | const Timeline: React.FC<{}> = () =>
Timeline
;
4 |
5 | export default Timeline;
6 |
--------------------------------------------------------------------------------
/src/usecases/createTweet/UserNotExists.ts:
--------------------------------------------------------------------------------
1 | import { AutoNamedError } from '@pirosikick/utils';
2 |
3 | export default class UserNotExists extends AutoNamedError {}
4 |
--------------------------------------------------------------------------------
/src/usecases/getTweets/DataAccessError.ts:
--------------------------------------------------------------------------------
1 | import { WrapError } from '@pirosikick/utils';
2 |
3 | export default class GetTweetsDataAccessError extends WrapError {}
4 |
--------------------------------------------------------------------------------
/src/usecases/createTweet/InvalidTweetText.ts:
--------------------------------------------------------------------------------
1 | import { AutoNamedError } from '@pirosikick/utils';
2 |
3 | export default class InvalidTweetText extends AutoNamedError {}
4 |
--------------------------------------------------------------------------------
/src/usecases/createUser/InvalidUserName.ts:
--------------------------------------------------------------------------------
1 | import { AutoNamedError } from '@pirosikick/utils';
2 |
3 | export default class InvalidUserName extends AutoNamedError {}
4 |
--------------------------------------------------------------------------------
/src/usecases/createUser/UserNameDuplicated.ts:
--------------------------------------------------------------------------------
1 | import { AutoNamedError } from '@pirosikick/utils';
2 |
3 | export default class UserNameDuplicated extends AutoNamedError {}
4 |
--------------------------------------------------------------------------------
/src/client/pages/index.ts:
--------------------------------------------------------------------------------
1 | export { default as SignIn } from './SignIn';
2 | export { default as SignUp } from './SignUp';
3 | export { default as Timeline } from './Timeline';
4 |
--------------------------------------------------------------------------------
/src/client/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | サンプルアップ
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/src/client/app/index.ts:
--------------------------------------------------------------------------------
1 | import { IAction } from './types';
2 | import * as actions from './actions';
3 | import reducer, { IState } from './reducer';
4 |
5 | export { actions, reducer, IState, IAction };
6 |
--------------------------------------------------------------------------------
/src/usecases/signInWithPassword/DataAccessError.ts:
--------------------------------------------------------------------------------
1 | import { WrapError } from '@pirosikick/utils';
2 |
3 | export default class SignInWithPasswordDataAccessError extends WrapError {
4 | public name = 'SignInWithPasswordDataAccessError';
5 | }
6 |
--------------------------------------------------------------------------------
/src/usecases/signUpWithPassword/DataAccessError.ts:
--------------------------------------------------------------------------------
1 | import { WrapError } from '@pirosikick/utils';
2 |
3 | export default class SignUpWithPasswordDataAccessError extends WrapError {
4 | public name = 'SignUpWithPasswordDataAccessError';
5 | }
6 |
--------------------------------------------------------------------------------
/src/client/app/actions.ts:
--------------------------------------------------------------------------------
1 | import { IUser } from '../types';
2 | import { ActionType, ISetUserAction } from './types';
3 |
4 | export const setUser = (user: IUser): ISetUserAction => ({
5 | type: ActionType.SET_USER,
6 | payload: user
7 | });
8 |
--------------------------------------------------------------------------------
/src/client/signIn/index.ts:
--------------------------------------------------------------------------------
1 | import reducer, { IState } from './reducer';
2 | import { IAction } from './types';
3 | import * as actions from './actions';
4 | import * as operations from './operations';
5 |
6 | export { reducer, actions, operations, IState, IAction };
7 |
--------------------------------------------------------------------------------
/src/client/signUp/index.ts:
--------------------------------------------------------------------------------
1 | import * as actions from './actions';
2 | import * as operations from './operations';
3 | import { IAction } from './types';
4 | import reducer, { IState } from './reducer';
5 |
6 | export { actions, operations, reducer, IState, IAction };
7 |
--------------------------------------------------------------------------------
/src/usecases/interface.ts:
--------------------------------------------------------------------------------
1 | // ユースケースの型
2 | export type IUseCase = (input: Input) => Promise