├── .gitignore
├── .npmignore
├── README.md
├── package.json
├── src
├── index.ts
├── templates
│ └── clean-architecture
│ │ ├── .babelrc
│ │ ├── .editorconfig
│ │ ├── .eslintignore
│ │ ├── .eslintrc
│ │ ├── .gitignore
│ │ ├── .prettierrc
│ │ ├── __mocks__
│ │ ├── emptyFileMock.js
│ │ ├── setupTest.js
│ │ └── svgMock.js
│ │ ├── jest.config.js
│ │ ├── package.json
│ │ ├── public
│ │ └── index.html
│ │ ├── src
│ │ ├── @types
│ │ │ └── declarations.d.ts
│ │ ├── domain
│ │ │ ├── models
│ │ │ │ └── ITodo.model.ts
│ │ │ └── usecases
│ │ │ │ └── ICreateTodoList.usecase.ts
│ │ ├── infrastructure
│ │ │ ├── cache
│ │ │ │ ├── __tests__
│ │ │ │ │ └── localStorage.spec.ts
│ │ │ │ ├── implementation
│ │ │ │ │ └── LocalStorage.ts
│ │ │ │ ├── inMemory
│ │ │ │ │ └── LocalStorage.ts
│ │ │ │ ├── index.ts
│ │ │ │ └── models
│ │ │ │ │ └── ICache.model.ts
│ │ │ └── http
│ │ │ │ └── httpClient
│ │ │ │ ├── __tests__
│ │ │ │ └── axios.spec.ts
│ │ │ │ ├── dtos
│ │ │ │ └── IHttpClient.dto.ts
│ │ │ │ ├── implementation
│ │ │ │ └── Axios.ts
│ │ │ │ ├── index.ts
│ │ │ │ └── models
│ │ │ │ └── IHttpClient.model.ts
│ │ ├── presentation
│ │ │ ├── App.tsx
│ │ │ ├── __tests__
│ │ │ │ └── App.spec.tsx
│ │ │ ├── assets
│ │ │ │ └── styles
│ │ │ │ │ └── global.ts
│ │ │ ├── bootstrap.tsx
│ │ │ ├── index.ts
│ │ │ └── pages
│ │ │ │ └── Home
│ │ │ │ ├── __tests__
│ │ │ │ └── index.spec.tsx
│ │ │ │ ├── index.tsx
│ │ │ │ └── styles.ts
│ │ ├── shared
│ │ │ └── Either.ts
│ │ └── usecases
│ │ │ ├── CreateTodoList.usecase.ts
│ │ │ ├── __tests__
│ │ │ └── CreateTodoList.usecase.spec.ts
│ │ │ └── index.ts
│ │ ├── tsconfig.json
│ │ └── webpack.config.js
└── utils
│ └── template.ts
├── tsconfig.json
└── yarn.lock
/.gitignore:
--------------------------------------------------------------------------------
1 |
2 | node_modules
3 | dist
4 | yarn-error.log
5 | .DS_Store
6 | .vscode/**
7 | .idea/
8 | result.xml
9 |
--------------------------------------------------------------------------------
/.npmignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | ./src
3 | ./tsconfig.json
4 | .gitignore
5 | yarn.lock
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # React Clean Architecture CLI
2 |
3 | Create an App React with clean architecture and Typescript.
4 | Jest, styled components and webpack 5 with federation module for microfrontend already configured.
5 |
6 | ## Install
7 |
8 | ```shell
9 | npm install -g react-clean-architecture-cli
10 | ```
11 |
12 | or
13 |
14 | ```shell
15 | yarn global add react-clean-architecture-cli
16 | ```
17 |
18 | ## Creating an App
19 |
20 | ```shell
21 | npx react-clean-architecture-cli my-app
22 | ```
23 |
24 | or
25 |
26 | ```shell
27 | react-clean-architecture my-app
28 | ```
29 |
30 | or
31 |
32 | ```shell
33 | react-clean-architecture
34 | ```
35 |
36 | and insert app name
37 |
38 | It will create a directory called `my-app` inside the current folder.
39 | Inside that directory, it will generate the initial project structure and install the transitive dependencies:
40 |
41 | ```
42 | my-app
43 | ├── node_modules
44 | ├── __mocks__
45 | │ ├── emptyFileMock.js
46 | │ └── setupTest.js
47 | ├── package.json
48 | ├── .editorconfig
49 | ├── .eslintignore
50 | ├── .eslintrc
51 | ├── .gitignore
52 | ├── .prettierrc
53 | ├── jest.config.js
54 | ├── tsconfig.json
55 | ├── webpack.config.js
56 | ├── public
57 | │ └── index.html
58 | └── src
59 | ├── @types
60 | │── domain
61 | │ ├── models
62 | │ └── usecases
63 | ├── infrastructure
64 | │ ├── http
65 | │ │ ├── __tests__
66 | │ │ ├── implementation
67 | │ │ ├── inMemory
68 | │ │ ├── models
69 | │ │ └── index.ts
70 | │ └── cache
71 | │ ├── __tests__
72 | │ ├── dtos
73 | │ ├── implementation
74 | │ ├── models
75 | │ └── index.ts
76 | ├── presentation
77 | │ ├── __tests__
78 | │ ├── assets
79 | │ ├── components
80 | │ ├── hooks
81 | │ ├── pages
82 | │ ├── App.tsx
83 | │ └── index.tsx
84 | ├── shared
85 | │ └── Either.ts
86 | └── usecases
87 | ```
88 |
89 | ```sh
90 | cd my-app
91 | ```
92 |
93 | Inside the newly created project, you can run some built-in commands:
94 |
95 | ### `npm start:dev` or `yarn start:dev`
96 |
97 | Runs the app in development mode.
98 | Open [http://localhost:3000](http://localhost:3000) to view it in the browser.
99 |
100 | The page will automatically reload if you make changes to the code.
101 | You will see the build errors and lint warnings in the console.
102 |
103 | ### `npm test` or `yarn test`
104 |
105 | Runs the test.
106 |
107 | ### `npm test:cov` or `yarn test:cov`
108 |
109 | Runs the test and generate coverage.
110 |
111 | ### `npm test:watch` or `yarn test:watch`
112 |
113 | Runs the test watcher in an interactive mode.
114 |
115 | ### `npm run build` or `yarn build`
116 |
117 | Builds the app for production to the `dist` folder.
118 |
119 | Your app is ready to be deployed.
120 |
121 | ## License
122 |
123 | This project is licensed under the [MIT License](https://opensource.org/licenses/MIT).
124 |
125 | Development by: [andrecoelho.dev](https://andrecoelho.dev) | Software Engineer
126 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "react-clean-architecture-cli",
3 | "description": "React.js Clean Architecture application",
4 | "version": "1.0.21",
5 | "main": "dist/index.js",
6 | "keywords": [
7 | "react",
8 | "javascript",
9 | "typescript",
10 | "cli",
11 | "clean architecture",
12 | "clean",
13 | "architecture",
14 | "webpack",
15 | "styled-components",
16 | "node",
17 | "jest",
18 | "testing-library"
19 | ],
20 | "author": "André Coelho",
21 | "repository": {
22 | "type": "git",
23 | "url": "https://github.com/avrcoelho/react-clean-architecture-cli.git"
24 | },
25 | "bugs": {
26 | "url": "https://github.com/avrcoelho/react-clean-architecture-cli/issues"
27 | },
28 | "homepage": "https://github.com/avrcoelho/react-clean-architecture-cli",
29 | "scripts": {
30 | "start": "ts-node src/index.ts",
31 | "build": "tsc && shx cp -r src/templates dist"
32 | },
33 | "bin": {
34 | "react-clean-architecture": "./dist/index.js"
35 | },
36 | "license": "MIT",
37 | "devDependencies": {
38 | "@types/ejs": "^3.0.6",
39 | "@types/inquirer": "^7.3.1",
40 | "@types/node": "^15.0.2",
41 | "@types/shelljs": "^0.8.8",
42 | "@types/yargs": "^16.0.1",
43 | "shx": "^0.3.3",
44 | "ts-node": "^7.0.1",
45 | "typescript": "^3.0.3"
46 | },
47 | "dependencies": {
48 | "ejs": "^3.1.6",
49 | "inquirer": "^8.0.0",
50 | "shelljs": "^0.8.4",
51 | "yargs": "^17.0.1"
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/src/index.ts:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env node
2 |
3 | import * as inquirer from "inquirer";
4 | import * as fs from "fs";
5 | import * as path from "path";
6 | import * as shell from "shelljs";
7 | import * as template from "./utils/template";
8 | import * as chalk from "chalk";
9 | import * as yargs from "yargs";
10 |
11 | const QUESTIONS = [
12 | {
13 | name: "name",
14 | type: "input",
15 | message: "App name:",
16 | when: () => !yargs.argv["name"] && !yargs.argv._[0],
17 | validate: (input: string) => {
18 | if (/^([A-Za-z\-\_\d])+$/.test(input)) return true;
19 | else
20 | return "App name may only include letters, numbers, underscores and hashes.";
21 | },
22 | },
23 | ];
24 |
25 | const CURR_DIR = process.cwd();
26 |
27 | export interface TemplateConfig {
28 | files?: string[];
29 | postMessage?: string;
30 | }
31 |
32 | export interface CliOptions {
33 | projectName: string;
34 | templateName: string;
35 | templatePath: string;
36 | tartgetPath: string;
37 | config: TemplateConfig;
38 | }
39 |
40 | console.log(
41 | chalk.blue(`
42 | -------------------------------------
43 | andrecoelho.dev | Software Enginner
44 | -------------------------------------
45 | `)
46 | );
47 |
48 | inquirer.prompt(QUESTIONS).then((answers) => {
49 | answers = Object.assign({}, answers, {
50 | name: yargs.argv["name"] || yargs.argv._[0],
51 | });
52 |
53 | const projectChoice = "clean-architecture";
54 | const projectName = answers["name"];
55 | const templatePath = path.join(__dirname, "templates", projectChoice);
56 | const tartgetPath = path.join(CURR_DIR, projectName);
57 | const templateConfig = getTemplateConfig(templatePath);
58 |
59 | const options: CliOptions = {
60 | projectName,
61 | templateName: projectChoice,
62 | templatePath,
63 | tartgetPath,
64 | config: templateConfig,
65 | };
66 |
67 | if (!createProject(tartgetPath)) {
68 | return;
69 | }
70 |
71 | createDirectoryContents(templatePath, projectName, templateConfig);
72 |
73 | if (!postProcess(options)) {
74 | return;
75 | }
76 |
77 | showMessage(options);
78 | });
79 |
80 | function showMessage(options: CliOptions) {
81 | console.log("");
82 | console.log(chalk.green("Done."));
83 | console.log(chalk.green(`Go into the project: cd ${options.projectName}`));
84 |
85 | const message = options.config.postMessage;
86 |
87 | if (message) {
88 | console.log("");
89 | console.log(chalk.yellow(message));
90 | console.log("");
91 | }
92 | }
93 |
94 | function getTemplateConfig(templatePath: string): TemplateConfig {
95 | const configPath = path.join(templatePath, ".template.json");
96 |
97 | if (!fs.existsSync(configPath)) return {};
98 |
99 | const templateConfigContent = fs.readFileSync(configPath);
100 |
101 | if (templateConfigContent) {
102 | return JSON.parse(templateConfigContent.toString());
103 | }
104 |
105 | return {};
106 | }
107 |
108 | function createProject(projectPath: string) {
109 | if (fs.existsSync(projectPath)) {
110 | console.log(
111 | chalk.red(`Folder ${projectPath} exists. Delete or use another name.`)
112 | );
113 | return false;
114 | }
115 |
116 | fs.mkdirSync(projectPath);
117 | return true;
118 | }
119 |
120 | function postProcess(options: CliOptions) {
121 | if (isNode(options)) {
122 | return postProcessNode(options);
123 | }
124 | return true;
125 | }
126 |
127 | function isNode(options: CliOptions) {
128 | return fs.existsSync(path.join(options.templatePath, "package.json"));
129 | }
130 |
131 | function postProcessNode(options: CliOptions) {
132 | shell.cd(options.tartgetPath);
133 |
134 | let cmd = "";
135 |
136 | if (shell.which("yarn")) {
137 | cmd = "yarn";
138 | } else if (shell.which("npm")) {
139 | cmd = "npm install";
140 | }
141 |
142 | if (cmd) {
143 | const result = shell.exec(cmd);
144 |
145 | if (result.code !== 0) {
146 | return false;
147 | }
148 | } else {
149 | console.log(chalk.red("No yarn or npm found. Cannot run installation."));
150 | }
151 |
152 | return true;
153 | }
154 |
155 | const SKIP_FILES = ["node_modules", ".template.json"];
156 |
157 | function createDirectoryContents(
158 | templatePath: string,
159 | projectName: string,
160 | config: TemplateConfig
161 | ) {
162 | const filesToCreate = fs.readdirSync(templatePath);
163 |
164 | filesToCreate.forEach((file) => {
165 | const origFilePath = path.join(templatePath, file);
166 |
167 | // get stats about the current file
168 | const stats = fs.statSync(origFilePath);
169 |
170 | if (SKIP_FILES.indexOf(file) > -1) return;
171 |
172 | if (stats.isFile()) {
173 | let contents = fs.readFileSync(origFilePath, "utf8");
174 | const microName = projectName.replace(/[^a-zA-Z0-9]/g, "");
175 | contents = template.render(contents, { projectName, microName });
176 | const writePath = path.join(CURR_DIR, projectName, file);
177 | fs.writeFileSync(writePath, contents, "utf8");
178 | } else if (stats.isDirectory()) {
179 | fs.mkdirSync(path.join(CURR_DIR, projectName, file));
180 |
181 | // recursive call
182 | createDirectoryContents(
183 | path.join(templatePath, file),
184 | path.join(projectName, file),
185 | config
186 | );
187 | }
188 | });
189 | }
190 |
--------------------------------------------------------------------------------
/src/templates/clean-architecture/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": [
3 | "@babel/preset-env",
4 | ["@babel/preset-react", {
5 | "runtime": "automatic"
6 | }],
7 | "@babel/preset-typescript"
8 | ],
9 | "plugins": ["babel-plugin-styled-components"]
10 | }
11 |
--------------------------------------------------------------------------------
/src/templates/clean-architecture/.editorconfig:
--------------------------------------------------------------------------------
1 | # https://editorconfig.org
2 | root = true
3 |
4 | [*]
5 | charset = utf-8
6 | end_of_line = lf
7 | indent_size = 2
8 | indent_style = space
9 | insert_final_newline = true
10 | max_line_length = 80
11 | trim_trailing_whitespace = true
12 |
13 | [*.md]
14 | max_line_length = 0
15 | trim_trailing_whitespace = false
16 |
17 | [COMMIT_EDITMSG]
18 | max_line_length = 0
--------------------------------------------------------------------------------
/src/templates/clean-architecture/.eslintignore:
--------------------------------------------------------------------------------
1 | node_modules/**
2 |
--------------------------------------------------------------------------------
/src/templates/clean-architecture/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "parser": "@typescript-eslint/parser",
3 |
4 | "plugins": [
5 | "react",
6 | "react-hooks",
7 | "jsx-a11y",
8 | "@typescript-eslint",
9 | "prettier"
10 | ],
11 |
12 | "settings": {
13 | "react": { "version": "detect" }
14 | },
15 |
16 | "env": {
17 | "jest": true,
18 | "browser": true
19 | },
20 |
21 | "parserOptions": {
22 | "ecmaFeatures": {
23 | "jsx": true,
24 | "modules": true
25 | }
26 | },
27 |
28 | "extends": [
29 | "eslint:recommended",
30 | "plugin:react/recommended",
31 | "plugin:jsx-a11y/recommended",
32 | "plugin:@typescript-eslint/eslint-recommended",
33 | "plugin:@typescript-eslint/recommended",
34 | "prettier/@typescript-eslint",
35 | "plugin:prettier/recommended"
36 | ],
37 |
38 | "rules": {
39 | "react/jsx-uses-react": "off",
40 | "react/react-in-jsx-scope": "off",
41 |
42 | // Spacing
43 | "no-mixed-spaces-and-tabs": "error",
44 | "no-tabs": "error",
45 |
46 | // Semicolons
47 | "semi": ["error", "always"],
48 | "semi-spacing": "warn",
49 | "no-extra-semi": "error",
50 |
51 | // General Syntax
52 | "prefer-arrow-callback": "warn",
53 | "no-extra-boolean-cast": "off",
54 |
55 | // React
56 | "react/prop-types": "error",
57 | "react-hooks/rules-of-hooks": "error",
58 |
59 | // Code smells
60 | "max-lines": ["warn", { "max": 150, "skipBlankLines": true, "skipComments": true}],
61 | "max-statements": ["warn", { "max": 15 }],
62 | "array-callback-return": ["error", { "checkForEach": true }],
63 | "max-nested-callbacks": ["warn", { "max": 5 }],
64 | "no-console": "error",
65 |
66 | // Typescript
67 | "@typescript-eslint/explicit-module-boundary-types": "off"
68 | },
69 |
70 | "overrides": [
71 | {
72 | // Disable prop types check on TypeScript files since props rely on Interfaces
73 | "files": ["*.tsx"],
74 | "rules": {
75 | "react/prop-types": "off"
76 | }
77 | },
78 | {
79 | // Empty functions and long files are acceptable on tests
80 | "files": ["*.spec.js", "*.spec.jsx", "*.spec.ts", "*.spec.tsx"],
81 | "rules": {
82 | "@typescript-eslint/no-empty-function": "off",
83 | "max-lines": "off",
84 | "max-statements": "off"
85 | }
86 | }
87 | ]
88 | }
89 |
--------------------------------------------------------------------------------
/src/templates/clean-architecture/.gitignore:
--------------------------------------------------------------------------------
1 | coverage
2 | node_modules
3 | dist
4 | yarn-error.log
5 | .DS_Store
6 | eslint-report.json
7 | .vscode/**
8 | .idea/
9 | result.xml
10 |
--------------------------------------------------------------------------------
/src/templates/clean-architecture/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "printWidth": 80,
3 | "tabWidth": 2,
4 | "useTabs": false,
5 | "singleQuote": true,
6 | "trailingComma": "all",
7 | "arrowParens": "avoid"
8 | }
9 |
--------------------------------------------------------------------------------
/src/templates/clean-architecture/__mocks__/emptyFileMock.js:
--------------------------------------------------------------------------------
1 | /* globals module */
2 | module.exports = 'empty-file-mock';
3 |
--------------------------------------------------------------------------------
/src/templates/clean-architecture/__mocks__/setupTest.js:
--------------------------------------------------------------------------------
1 | import 'core-js/stable';
2 | import 'regenerator-runtime/runtime';
3 |
4 | process.env.API_URL = 'http://localhost:3333';
5 |
--------------------------------------------------------------------------------
/src/templates/clean-architecture/__mocks__/svgMock.js:
--------------------------------------------------------------------------------
1 | export default 'empty-file-mock'
2 | export const ReactComponent = 'empty-file-mock'
3 |
--------------------------------------------------------------------------------
/src/templates/clean-architecture/jest.config.js:
--------------------------------------------------------------------------------
1 | /* globals module */
2 | module.exports = {
3 | clearMocks: true,
4 | collectCoverageFrom: [
5 | '/src/**/*.{ts,tsx}',
6 | '!/src/**/dtos/*',
7 | '!/src/**/models/*',
8 | '!/src/@types/*',
9 | '!/src/presentation/assets/**/*',
10 | '!/src/presentation/index.tsx',
11 | '!/src/infrastructure/**/index.ts',
12 | '!/src/**/inMemory/*',
13 | '!/src/domain/usecases/*',
14 | '!/src/usecases/index.ts',
15 | '!/src/shared/Either.ts',
16 | ],
17 | coverageDirectory: 'coverage',
18 | coverageThreshold: {
19 | global: {
20 | branches: 0,
21 | functions: 0,
22 | lines: 0,
23 | },
24 | },
25 | moduleNameMapper: {
26 | '\\.(css|png|jpe?g)$': '/__mocks__/emptyFileMock.js',
27 | '\\.svg$': '/__mocks__/svgMock.js',
28 | '@/(.*)': '/src/$1',
29 | },
30 | testMatch: ['/src/**/__tests__/**/*.spec.{ts,tsx}'],
31 | setupFiles: ['/__mocks__/setupTest.js'],
32 | };
33 |
--------------------------------------------------------------------------------
/src/templates/clean-architecture/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "<%= projectName %>",
3 | "version": "1.0.0",
4 | "main": "index.js",
5 | "license": "MIT",
6 | "private": true,
7 | "scripts": {
8 | "start:dev": "NODE_OPTIONS=--max-old-space-size=3584 webpack-cli serve --mode development",
9 | "build": "NODE_OPTIONS=--max-old-space-size=3584 webpack --mode production",
10 | "test": "jest --config=jest.config.js",
11 | "test:cov": "jest --config=jest.config.js --coverage",
12 | "test:watch": "jest --config=jest.config.json --watch"
13 | },
14 | "dependencies": {
15 | "axios": "^0.21.1",
16 | "react": "^17.0.2",
17 | "react-dom": "^17.0.2",
18 | "styled-components": "^5.2.3"
19 | },
20 | "devDependencies": {
21 | "@babel/cli": "^7.13.16",
22 | "@babel/core": "^7.14.0",
23 | "@babel/plugin-transform-react-jsx": "^7.13.12",
24 | "@babel/polyfill": "^7.12.1",
25 | "@babel/preset-env": "^7.14.1",
26 | "@babel/preset-react": "^7.13.13",
27 | "@babel/preset-typescript": "^7.13.0",
28 | "@babel/runtime": "^7.14.0",
29 | "@svgr/webpack": "^5.5.0",
30 | "@testing-library/jest-dom": "^5.12.0",
31 | "@testing-library/react": "^11.2.6",
32 | "@testing-library/react-hooks": "^5.1.2",
33 | "@types/jest": "^26.0.23",
34 | "@types/react": "^17.0.5",
35 | "@types/react-dom": "^17.0.3",
36 | "@types/styled-components": "^5.1.9",
37 | "@typescript-eslint/eslint-plugin": "^4.22.1",
38 | "@typescript-eslint/parser": "^4.22.1",
39 | "autoprefixer": "^10.2.5",
40 | "babel-loader": "^8.2.2",
41 | "babel-jest": "^26.6.3",
42 | "babel-plugin-styled-components": "^1.12.0",
43 | "babel-polyfill": "^6.26.0",
44 | "clean-webpack-plugin": "^4.0.0-alpha.0",
45 | "core-js": "^3.12.1",
46 | "css-loader": "^5.2.4",
47 | "eslint": "^7.25.0",
48 | "eslint-config-airbnb": "^18.2.1",
49 | "eslint-config-prettier": "^8.3.0",
50 | "eslint-plugin-import": "^2.22.1",
51 | "eslint-plugin-jsx-a11y": "^6.4.1",
52 | "eslint-plugin-prettier": "^3.4.0",
53 | "eslint-plugin-react": "^7.21.5",
54 | "eslint-plugin-react-hooks": "^4",
55 | "html-webpack-plugin": "^5.3.1",
56 | "jest": "^26.6.3",
57 | "mini-css-extract-plugin": "^1.6.0",
58 | "msw": "^0.28.2",
59 | "node-polyfill-webpack-plugin": "^1.1.0",
60 | "postcss": "^8.2.13",
61 | "postcss-loader": "^5.2.0",
62 | "postcss-preset-env": "^6.7.0",
63 | "prettier": "^2.2.1",
64 | "regenerator-runtime": "^0.13.7",
65 | "sass": "^1.32.12",
66 | "sass-loader": "^11.0.1",
67 | "style-loader": "^2.0.0",
68 | "ts-loader": "^9.1.1",
69 | "typescript": "^4.2.4",
70 | "url-loader": "^4.1.1",
71 | "webpack": "^5.36.2",
72 | "webpack-cli": "^4.6.0",
73 | "webpack-dev-server": "^3.11.2"
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/src/templates/clean-architecture/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
9 |
10 |
11 |
12 | Document
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/src/templates/clean-architecture/src/@types/declarations.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 |
3 | declare module '*.svg' {
4 | const content: any;
5 | export default content;
6 | export const ReactComponent: React.ComponentType;
7 | }
8 |
9 | declare module '*.png' {
10 | const content: any;
11 | export default content;
12 | }
13 |
14 | declare module '*.jpg' {
15 | const content: any;
16 | export default content;
17 | }
18 |
--------------------------------------------------------------------------------
/src/templates/clean-architecture/src/domain/models/ITodo.model.ts:
--------------------------------------------------------------------------------
1 | export default interface ITodoListModel {
2 | id: string;
3 | title: string;
4 | }
5 |
--------------------------------------------------------------------------------
/src/templates/clean-architecture/src/domain/usecases/ICreateTodoList.usecase.ts:
--------------------------------------------------------------------------------
1 | import { Either } from '@/shared/Either';
2 | import ITodoModel from '../models/ITodo.model';
3 |
4 | export interface ICreateTodoListUsecaseArgs {
5 | title: string;
6 | }
7 |
8 | export interface ICreateTodoListUsecase {
9 | execute: (
10 | args: ICreateTodoListUsecaseArgs,
11 | ) => Promise>;
12 | }
13 |
--------------------------------------------------------------------------------
/src/templates/clean-architecture/src/infrastructure/cache/__tests__/localStorage.spec.ts:
--------------------------------------------------------------------------------
1 | import LocalStorage from '../implementation/LocalStorage';
2 |
3 | let localStorageCache: LocalStorage;
4 |
5 | describe('LocalStorage', () => {
6 | beforeEach(() => {
7 | localStorageCache = new LocalStorage();
8 | });
9 |
10 | it('should be able to save data in localstorage', async () => {
11 | const setItemSpy = jest.spyOn(Storage.prototype, 'setItem');
12 | const data = JSON.stringify({ name: 'John Doe' });
13 |
14 | localStorageCache.save('test', data);
15 |
16 | expect(setItemSpy).toBeCalledWith('test', data);
17 | });
18 |
19 | it('should be able to get data item in localstorage', async () => {
20 | const data = JSON.stringify({ name: 'John Doe' });
21 | localStorageCache.save('test', data);
22 |
23 | const itemData = localStorageCache.get('test');
24 |
25 | expect(itemData).toEqual({ name: 'John Doe' });
26 | });
27 |
28 | it('should be able to returned null when item not exists', async () => {
29 | const itemData = localStorageCache.get('test-2');
30 |
31 | expect(itemData).toBe(null);
32 | });
33 | });
34 |
--------------------------------------------------------------------------------
/src/templates/clean-architecture/src/infrastructure/cache/implementation/LocalStorage.ts:
--------------------------------------------------------------------------------
1 | import ICacheModel from '../models/ICache.model';
2 |
3 | class LocalStorage implements ICacheModel {
4 | private readonly storage: Storage;
5 |
6 | constructor() {
7 | this.storage = localStorage;
8 | }
9 |
10 | public get(key: string): T | null {
11 | const data = this.storage.getItem(key);
12 |
13 | if (!data) {
14 | return null;
15 | }
16 |
17 | const parsedData = JSON.parse(data) as T;
18 |
19 | return parsedData;
20 | }
21 |
22 | public save(key: string, value: string): void {
23 | this.storage.setItem(key, value);
24 | }
25 | }
26 |
27 | export default LocalStorage;
28 |
--------------------------------------------------------------------------------
/src/templates/clean-architecture/src/infrastructure/cache/inMemory/LocalStorage.ts:
--------------------------------------------------------------------------------
1 | import ICacheModel from '../models/ICache.model';
2 |
3 | interface ICacheData {
4 | [key: string]: string;
5 | }
6 |
7 | class LocalStorage implements ICacheModel {
8 | private storage: ICacheData = {};
9 |
10 | public get(key: string): T | null {
11 | const data = this.storage[key];
12 |
13 | if (!data) {
14 | return null;
15 | }
16 |
17 | const parsedData = JSON.parse(data) as T;
18 |
19 | return parsedData;
20 | }
21 |
22 | public save(key: string, value: string): void {
23 | this.storage[key] = value;
24 | }
25 | }
26 |
27 | export default LocalStorage;
28 |
--------------------------------------------------------------------------------
/src/templates/clean-architecture/src/infrastructure/cache/index.ts:
--------------------------------------------------------------------------------
1 | import LocalStorage from './implementation/LocalStorage';
2 |
3 | const providers = {
4 | LocalStorage: new LocalStorage(),
5 | };
6 |
7 | export default providers.LocalStorage;
8 |
--------------------------------------------------------------------------------
/src/templates/clean-architecture/src/infrastructure/cache/models/ICache.model.ts:
--------------------------------------------------------------------------------
1 | export default interface ICache {
2 | save(key: string, value: string): void;
3 | get(key: string): T | null;
4 | }
5 |
--------------------------------------------------------------------------------
/src/templates/clean-architecture/src/infrastructure/http/httpClient/__tests__/axios.spec.ts:
--------------------------------------------------------------------------------
1 | import { rest } from 'msw';
2 | import { setupServer } from 'msw/node';
3 |
4 | import Axios from '../implementation/Axios';
5 |
6 | let axios: Axios;
7 |
8 | const BASE_URL = process.env.API_URL;
9 |
10 | const server = setupServer(
11 | rest.get(`${BASE_URL}/`, (req, res, ctx) => {
12 | return res(ctx.json(['a', 'b', 'c']));
13 | }),
14 | rest.post(`${BASE_URL}/`, (req, res, ctx) => {
15 | return res(ctx.json({ success: true }));
16 | }),
17 | rest.put(`${BASE_URL}/`, (req, res, ctx) => {
18 | return res(ctx.json({ success: true }));
19 | }),
20 | rest.patch(`${BASE_URL}/`, (req, res, ctx) => {
21 | return res(ctx.json({ success: true }));
22 | }),
23 | rest.delete(`${BASE_URL}/`, (req, res, ctx) => {
24 | return res(ctx.json({ success: true }));
25 | }),
26 | );
27 |
28 | describe('Axios', () => {
29 | beforeAll(() => server.listen());
30 |
31 | beforeEach(() => {
32 | axios = new Axios();
33 | });
34 |
35 | afterEach(() => server.resetHandlers());
36 |
37 | afterAll(() => server.close());
38 |
39 | it('should be able to return data on method GET', async () => {
40 | const { data } = await axios.get({ url: '/' });
41 |
42 | expect(data).toEqual(['a', 'b', 'c']);
43 | });
44 |
45 | it('should be able to return data on method POST', async () => {
46 | const { data } = await axios.post({ url: '/' });
47 |
48 | expect(data).toEqual({ success: true });
49 | });
50 |
51 | it('should be able to return data on method PUT', async () => {
52 | const { data } = await axios.put({ url: '/' });
53 |
54 | expect(data).toEqual({ success: true });
55 | });
56 |
57 | it('should be able to return data on method PATCH', async () => {
58 | const { data } = await axios.patch({ url: '/' });
59 |
60 | expect(data).toEqual({ success: true });
61 | });
62 |
63 | it('should be able to DELETE', async () => {
64 | const { data } = await axios.delete({ url: '/' });
65 |
66 | expect(data).toEqual({ success: true });
67 | });
68 | });
69 |
--------------------------------------------------------------------------------
/src/templates/clean-architecture/src/infrastructure/http/httpClient/dtos/IHttpClient.dto.ts:
--------------------------------------------------------------------------------
1 | export interface IHttpClientGetDTO {
2 | url: string;
3 | params?: any;
4 | headers?: any;
5 | }
6 |
7 | export interface IHttpClientPostDTO {
8 | url: string;
9 | data?: any;
10 | params?: any;
11 | headers?: any;
12 | }
13 |
14 | export interface IHttpClientPutDTO {
15 | url: string;
16 | data?: any;
17 | params?: any;
18 | headers?: any;
19 | }
20 |
21 | export interface IHttpClientPatchDTO {
22 | url: string;
23 | data?: any;
24 | params?: any;
25 | headers?: any;
26 | }
27 |
28 | export interface IHttpClientDeleteDTO {
29 | url: string;
30 | params?: any;
31 | headers?: any;
32 | }
33 |
--------------------------------------------------------------------------------
/src/templates/clean-architecture/src/infrastructure/http/httpClient/implementation/Axios.ts:
--------------------------------------------------------------------------------
1 | import axios, { AxiosInstance, AxiosResponse } from 'axios';
2 |
3 | import {
4 | IHttpClientDeleteDTO,
5 | IHttpClientGetDTO,
6 | IHttpClientPatchDTO,
7 | IHttpClientPostDTO,
8 | IHttpClientPutDTO,
9 | } from '../dtos/IHttpClient.dto';
10 | import IHttpClientModel from '../models/IHttpClient.model';
11 |
12 | class AxiosHttpClient implements IHttpClientModel {
13 | private readonly baseUrl: string | undefined;
14 |
15 | private readonly axiosInstance: AxiosInstance;
16 |
17 | constructor() {
18 | this.axiosInstance = axios.create({});
19 | this.baseUrl = process.env.API_URL;
20 | }
21 |
22 | public get({
23 | url,
24 | params = null,
25 | headers = null,
26 | }: IHttpClientGetDTO): Promise> {
27 | return this.axiosInstance({
28 | method: 'GET',
29 | url: `${this.baseUrl}${url}`,
30 | params,
31 | headers,
32 | });
33 | }
34 |
35 | public post({
36 | url,
37 | params = null,
38 | data = null,
39 | headers = null,
40 | }: IHttpClientPostDTO): Promise> {
41 | return this.axiosInstance({
42 | method: 'POST',
43 | url: `${this.baseUrl}${url}`,
44 | params,
45 | data,
46 | headers,
47 | });
48 | }
49 |
50 | public put({
51 | url,
52 | params = null,
53 | data = null,
54 | headers = null,
55 | }: IHttpClientPutDTO): Promise> {
56 | return this.axiosInstance({
57 | method: 'PUT',
58 | url: `${this.baseUrl}${url}`,
59 | params,
60 | data,
61 | headers,
62 | });
63 | }
64 |
65 | public patch({
66 | url,
67 | params = null,
68 | data = null,
69 | headers = null,
70 | }: IHttpClientPatchDTO): Promise> {
71 | return this.axiosInstance({
72 | method: 'PUT',
73 | url: `${this.baseUrl}${url}`,
74 | params,
75 | data,
76 | headers,
77 | });
78 | }
79 |
80 | public delete({
81 | url,
82 | params = null,
83 | headers = null,
84 | }: IHttpClientDeleteDTO): Promise> {
85 | return this.axiosInstance({
86 | method: 'DELETE',
87 | url: `${this.baseUrl}${url}`,
88 | params,
89 | headers,
90 | });
91 | }
92 | }
93 |
94 | export default AxiosHttpClient;
95 |
--------------------------------------------------------------------------------
/src/templates/clean-architecture/src/infrastructure/http/httpClient/index.ts:
--------------------------------------------------------------------------------
1 | import Axios from './implementation/Axios';
2 |
3 | const providers = {
4 | Axios: new Axios(),
5 | };
6 |
7 | export default providers.Axios;
8 |
--------------------------------------------------------------------------------
/src/templates/clean-architecture/src/infrastructure/http/httpClient/models/IHttpClient.model.ts:
--------------------------------------------------------------------------------
1 | import { AxiosResponse } from 'axios';
2 |
3 | import {
4 | IHttpClientDeleteDTO,
5 | IHttpClientGetDTO,
6 | IHttpClientPatchDTO,
7 | IHttpClientPostDTO,
8 | IHttpClientPutDTO,
9 | } from '../dtos/IHttpClient.dto';
10 |
11 | export default interface IHttpClientModel {
12 | get: (
13 | data: IHttpClientGetDTO,
14 | ) => Promise>;
15 | post: (
16 | data: IHttpClientPostDTO,
17 | ) => Promise>;
18 | put: (
19 | data: IHttpClientPutDTO,
20 | ) => Promise>;
21 | patch: (
22 | data: IHttpClientPatchDTO,
23 | ) => Promise>;
24 | delete: (
25 | data: IHttpClientDeleteDTO,
26 | ) => Promise>;
27 | }
28 |
--------------------------------------------------------------------------------
/src/templates/clean-architecture/src/presentation/App.tsx:
--------------------------------------------------------------------------------
1 | import { GlobalStyle } from './assets/styles/global';
2 | import Home from './pages/Home';
3 |
4 | const App = () => (
5 | <>
6 |
7 |
8 | >
9 | );
10 |
11 | export default App;
12 |
--------------------------------------------------------------------------------
/src/templates/clean-architecture/src/presentation/__tests__/App.spec.tsx:
--------------------------------------------------------------------------------
1 | import { render } from '@testing-library/react';
2 |
3 | import App from '../App';
4 |
5 | describe('App', () => {
6 | it('should be able to render App', () => {
7 | expect(() => {
8 | render();
9 | }).not.toThrow();
10 | });
11 | });
12 |
--------------------------------------------------------------------------------
/src/templates/clean-architecture/src/presentation/assets/styles/global.ts:
--------------------------------------------------------------------------------
1 | import { createGlobalStyle } from 'styled-components';
2 |
3 | export const GlobalStyle = createGlobalStyle`
4 | * {
5 | padding: 0;
6 | margin: 0;
7 | box-sizing: border-box
8 | }
9 |
10 | :root {
11 | --white: #fff;
12 |
13 | font-size: 62.5%;
14 | }
15 |
16 | body {
17 | background: var(--white);
18 | }
19 |
20 | body,
21 | input,
22 | textarea,
23 | select,
24 | button {
25 | font: 400 1.6rem "Inter",Helvetica,Arial,sans-serif;
26 | }
27 |
28 | h1, h2, h3, h4, h5, h6 {
29 | font-family: inherit;
30 | font-weight: 600;
31 | line-height: 1.1;
32 | color: inherit;
33 | }
34 |
35 | button {
36 | cursor: pointer;
37 | border: none;
38 | background-color: transparent;
39 | }
40 |
41 | `;
42 |
--------------------------------------------------------------------------------
/src/templates/clean-architecture/src/presentation/bootstrap.tsx:
--------------------------------------------------------------------------------
1 | import * as ReactDOM from 'react-dom';
2 |
3 | import App from './App';
4 |
5 | ReactDOM.render(, document.getElementById('root'));
6 |
--------------------------------------------------------------------------------
/src/templates/clean-architecture/src/presentation/index.ts:
--------------------------------------------------------------------------------
1 | // @ts-ignore
2 | import('./bootstrap');
3 |
--------------------------------------------------------------------------------
/src/templates/clean-architecture/src/presentation/pages/Home/__tests__/index.spec.tsx:
--------------------------------------------------------------------------------
1 | import { screen, render } from '@testing-library/react';
2 |
3 | import Home from '..';
4 |
5 | describe('Home page', () => {
6 | it('should be able to render page', () => {
7 | render();
8 |
9 | expect(screen.getByText('Hello, Dev :)')).toBeTruthy();
10 | });
11 | });
12 |
--------------------------------------------------------------------------------
/src/templates/clean-architecture/src/presentation/pages/Home/index.tsx:
--------------------------------------------------------------------------------
1 | import { Container } from './styles';
2 |
3 | const Home = () => {
4 | return (
5 |
6 | Hello, Dev :)
7 |
8 | );
9 | };
10 |
11 | export default Home;
12 |
--------------------------------------------------------------------------------
/src/templates/clean-architecture/src/presentation/pages/Home/styles.ts:
--------------------------------------------------------------------------------
1 | import styled from 'styled-components';
2 |
3 | export const Container = styled.div``;
4 |
--------------------------------------------------------------------------------
/src/templates/clean-architecture/src/shared/Either.ts:
--------------------------------------------------------------------------------
1 | export type Either = Left | Right;
2 |
3 | export class Left {
4 | readonly value: L;
5 |
6 | constructor(value: L) {
7 | this.value = value;
8 | }
9 |
10 | isLeft(): this is Left {
11 | return true;
12 | }
13 |
14 | isRight(): this is Right {
15 | return false;
16 | }
17 | }
18 |
19 | export class Right {
20 | readonly value: A;
21 |
22 | constructor(value: A) {
23 | this.value = value;
24 | }
25 |
26 | isLeft(): this is Left {
27 | return false;
28 | }
29 |
30 | isRight(): this is Right {
31 | return true;
32 | }
33 | }
34 |
35 | export const left = (l: L): Either => {
36 | return new Left(l);
37 | };
38 |
39 | export const right = (a: A): Either => {
40 | return new Right(a);
41 | };
42 |
--------------------------------------------------------------------------------
/src/templates/clean-architecture/src/usecases/CreateTodoList.usecase.ts:
--------------------------------------------------------------------------------
1 | import {
2 | ICreateTodoListUsecase,
3 | ICreateTodoListUsecaseArgs,
4 | } from '@/domain/usecases/ICreateTodoList.usecase';
5 | import ICacheModel from '@/infrastructure/cache/models/ICache.model';
6 | import IHttpClientModel from '@/infrastructure/http/httpClient/models/IHttpClient.model';
7 | import ITodoModel from '@/domain/models/ITodo.model';
8 | import { Either, right } from '@/shared/Either';
9 |
10 | class CreateTodoListUsecase implements ICreateTodoListUsecase {
11 | constructor(
12 | private readonly cache: ICacheModel,
13 | private readonly httpClient: IHttpClientModel,
14 | ) {}
15 |
16 | async execute(
17 | args: ICreateTodoListUsecaseArgs,
18 | ): Promise> {
19 | const { data } = await this.httpClient.post({
20 | url: '/todo-list',
21 | data: args,
22 | });
23 |
24 | const parsedData = JSON.stringify(data);
25 | this.cache.save('todolist', parsedData);
26 |
27 | return right(data);
28 | }
29 | }
30 |
31 | export default CreateTodoListUsecase;
32 |
--------------------------------------------------------------------------------
/src/templates/clean-architecture/src/usecases/__tests__/CreateTodoList.usecase.spec.ts:
--------------------------------------------------------------------------------
1 | import { rest } from 'msw';
2 | import { setupServer } from 'msw/node';
3 |
4 | import Localstorage from '@/infrastructure/cache/inMemory/LocalStorage';
5 | import AxiosHttpClient from '@/infrastructure/http/httpClient/implementation/Axios';
6 | import CreateTodoListUsecase from '../CreateTodoList.usecase';
7 |
8 | let createTodoListUsecase: CreateTodoListUsecase;
9 | let localstorage: Localstorage;
10 | let httpClient: AxiosHttpClient;
11 | const { API_URL } = process.env;
12 |
13 | const data = {
14 | id: '123',
15 | title: 'Create project',
16 | };
17 | const server = setupServer(
18 | rest.post(`${API_URL}/todo-list`, (req, res, ctx) => {
19 | return res(ctx.json(data));
20 | }),
21 | );
22 |
23 | describe('CreateTodoList usecase', () => {
24 | beforeAll(() => server.listen());
25 |
26 | afterEach(() => server.resetHandlers());
27 |
28 | afterAll(() => server.close());
29 |
30 | beforeEach(() => {
31 | localstorage = new Localstorage();
32 | httpClient = new AxiosHttpClient();
33 | createTodoListUsecase = new CreateTodoListUsecase(localstorage, httpClient);
34 | });
35 |
36 | it('should be able to create', async () => {
37 | const response = await createTodoListUsecase.execute({
38 | title: data.title,
39 | });
40 |
41 | expect(response.value).toEqual(data);
42 | });
43 | });
44 |
--------------------------------------------------------------------------------
/src/templates/clean-architecture/src/usecases/index.ts:
--------------------------------------------------------------------------------
1 | import httpClient from '@/infrastructure/http/httpClient';
2 | import cache from '@/infrastructure/cache';
3 | import CreateTodoListUsecase from './CreateTodoList.usecase';
4 |
5 | const createTodoListUsecase = new CreateTodoListUsecase(cache, httpClient);
6 |
7 | export { createTodoListUsecase };
8 |
--------------------------------------------------------------------------------
/src/templates/clean-architecture/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "lib": ["ES6", "ES2017", "DOM"],
4 | "target": "ES5",
5 | "jsx": "react-jsx",
6 | "allowJs": true,
7 | "outDir": "",
8 | "noImplicitAny": true,
9 | "strictNullChecks": true,
10 | "isolatedModules": true,
11 | "esModuleInterop": true,
12 | "typeRoots": ["src/types", "node_modules/@types"],
13 | "resolveJsonModule": true,
14 | "baseUrl": "./",
15 | "paths": {
16 | "@/*": ["./src/*"],
17 | }
18 | },
19 | "include": ["src/**/*"],
20 | "exclude": ["node_modules", "public", "dist"]
21 | }
22 |
--------------------------------------------------------------------------------
/src/templates/clean-architecture/webpack.config.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable */
2 | const path = require('path');
3 | const HtmlWebpackPlugin = require('html-webpack-plugin');
4 | const { CleanWebpackPlugin } = require('clean-webpack-plugin');
5 | const NodePolyfillPlugin = require('node-polyfill-webpack-plugin');
6 | const { ModuleFederationPlugin } = require('webpack').container;
7 |
8 | module.exports = (env, argv) => {
9 | const isProduction = argv['mode'] === 'production';
10 |
11 | return {
12 | entry: ['babel-polyfill', './src/presentation/index'],
13 | output: {
14 | publicPath: 'auto',
15 | path: path.join(__dirname, 'dist'),
16 | filename: '[name].[contenthash].js',
17 | },
18 | resolve: {
19 | extensions: ['.ts', '.tsx', '.js', '.svg'],
20 | alias: {
21 | '@': path.resolve(__dirname, 'src'),
22 | },
23 | },
24 | module: {
25 | rules: [
26 | {
27 | test: /\.tsx?$/,
28 | loader: 'babel-loader',
29 | exclude: /node_modules/,
30 | },
31 | {
32 | test: /\.css$/i,
33 | use: ['style-loader', 'css-loader'],
34 | },
35 | {
36 | test: /\.(png|jpe?g)$/,
37 | use: [
38 | {
39 | loader: 'url-loader',
40 | options: {
41 | limit: 8000,
42 | name: 'images/[hash]-[name].[ext]',
43 | },
44 | },
45 | ],
46 | },
47 | {
48 | test: /\.svg$/,
49 | use: ['@svgr/webpack', 'url-loader'],
50 | },
51 | {
52 | test: /\.(eot|ttf|woff|woff2)$/,
53 | loader: 'file-loader',
54 | options: {
55 | name: 'public/fonts/[name].[ext]',
56 | },
57 | },
58 | ],
59 | },
60 | plugins: [
61 | new NodePolyfillPlugin(),
62 | new HtmlWebpackPlugin({
63 | template: './public/index.html',
64 | }),
65 | new ModuleFederationPlugin({
66 | name: '<%= microName %>',
67 | filename: 'remoteEntry.js',
68 | exposes: {
69 | '.': './src/presentation/App',
70 | },
71 | remotes: {},
72 | shared: [{ react: { singleton: true } }],
73 | }),
74 | new CleanWebpackPlugin(),
75 | ],
76 |
77 | devtool: isProduction ? false : 'eval-cheap-module-source-map',
78 |
79 | devServer: {
80 | overlay: true,
81 | contentBase: path.join(__dirname, 'public'),
82 | disableHostCheck: true,
83 | historyApiFallback: {
84 | disableDotRule: true,
85 | },
86 | port: 3000,
87 | },
88 | };
89 | };
90 |
--------------------------------------------------------------------------------
/src/utils/template.ts:
--------------------------------------------------------------------------------
1 | import * as ejs from "ejs";
2 |
3 | export interface TemplateData {
4 | projectName: string;
5 | microName: string;
6 | }
7 | export function render(content: string, data: TemplateData) {
8 | return ejs.render(content, data);
9 | }
10 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "outDir": "dist",
4 | "target": "es5",
5 | "lib": ["es6", "dom"],
6 | "sourceMap": true,
7 | "allowJs": true,
8 | "moduleResolution": "node",
9 | "rootDir": "src",
10 | "forceConsistentCasingInFileNames": true,
11 | "noImplicitReturns": true,
12 | "noImplicitThis": true,
13 | "noImplicitAny": true,
14 | "strictNullChecks": true,
15 | "suppressImplicitAnyIndexErrors": true,
16 | "noUnusedLocals": true
17 | },
18 | "exclude": [
19 | "node_modules",
20 | "dist",
21 | "src/templates"
22 | ]
23 | }
24 |
--------------------------------------------------------------------------------
/yarn.lock:
--------------------------------------------------------------------------------
1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
2 | # yarn lockfile v1
3 |
4 |
5 | "@types/ejs@^3.0.6":
6 | version "3.0.6"
7 | resolved "https://registry.yarnpkg.com/@types/ejs/-/ejs-3.0.6.tgz#aca442289df623bfa8e47c23961f0357847b83fe"
8 | integrity sha512-fj1hi+ZSW0xPLrJJD+YNwIh9GZbyaIepG26E/gXvp8nCa2pYokxUYO1sK9qjGxp2g8ryZYuon7wmjpwE2cyASQ==
9 |
10 | "@types/glob@*":
11 | version "7.1.3"
12 | resolved "https://registry.yarnpkg.com/@types/glob/-/glob-7.1.3.tgz#e6ba80f36b7daad2c685acd9266382e68985c183"
13 | integrity sha512-SEYeGAIQIQX8NN6LDKprLjbrd5dARM5EXsd8GI/A5l0apYI1fGMWgPHSe4ZKL4eozlAyI+doUE9XbYS4xCkQ1w==
14 | dependencies:
15 | "@types/minimatch" "*"
16 | "@types/node" "*"
17 |
18 | "@types/inquirer@^7.3.1":
19 | version "7.3.1"
20 | resolved "https://registry.yarnpkg.com/@types/inquirer/-/inquirer-7.3.1.tgz#1f231224e7df11ccfaf4cf9acbcc3b935fea292d"
21 | integrity sha512-osD38QVIfcdgsPCT0V3lD7eH0OFurX71Jft18bZrsVQWVRt6TuxRzlr0GJLrxoHZR2V5ph7/qP8se/dcnI7o0g==
22 | dependencies:
23 | "@types/through" "*"
24 | rxjs "^6.4.0"
25 |
26 | "@types/minimatch@*":
27 | version "3.0.4"
28 | resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.4.tgz#f0ec25dbf2f0e4b18647313ac031134ca5b24b21"
29 | integrity sha512-1z8k4wzFnNjVK/tlxvrWuK5WMt6mydWWP7+zvH5eFep4oj+UkrfiJTRtjCeBXNpwaA/FYqqtb4/QS4ianFpIRA==
30 |
31 | "@types/node@*", "@types/node@^15.0.2":
32 | version "15.0.2"
33 | resolved "https://registry.yarnpkg.com/@types/node/-/node-15.0.2.tgz#51e9c0920d1b45936ea04341aa3e2e58d339fb67"
34 | integrity sha512-p68+a+KoxpoB47015IeYZYRrdqMUcpbK8re/zpFB8Ld46LHC1lPEbp3EXgkEhAYEcPvjJF6ZO+869SQ0aH1dcA==
35 |
36 | "@types/shelljs@^0.8.8":
37 | version "0.8.8"
38 | resolved "https://registry.yarnpkg.com/@types/shelljs/-/shelljs-0.8.8.tgz#e439c69929b88a2c8123c1a55e09eb708315addf"
39 | integrity sha512-lD3LWdg6j8r0VRBFahJVaxoW0SIcswxKaFUrmKl33RJVeeoNYQAz4uqCJ5Z6v4oIBOsC5GozX+I5SorIKiTcQA==
40 | dependencies:
41 | "@types/glob" "*"
42 | "@types/node" "*"
43 |
44 | "@types/through@*":
45 | version "0.0.30"
46 | resolved "https://registry.yarnpkg.com/@types/through/-/through-0.0.30.tgz#e0e42ce77e897bd6aead6f6ea62aeb135b8a3895"
47 | integrity sha512-FvnCJljyxhPM3gkRgWmxmDZyAQSiBQQWLI0A0VFL0K7W1oRUrPJSqNO0NvTnLkBcotdlp3lKvaT0JrnyRDkzOg==
48 | dependencies:
49 | "@types/node" "*"
50 |
51 | "@types/yargs-parser@*":
52 | version "20.2.0"
53 | resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-20.2.0.tgz#dd3e6699ba3237f0348cd085e4698780204842f9"
54 | integrity sha512-37RSHht+gzzgYeobbG+KWryeAW8J33Nhr69cjTqSYymXVZEN9NbRYWoYlRtDhHKPVT1FyNKwaTPC1NynKZpzRA==
55 |
56 | "@types/yargs@^16.0.1":
57 | version "16.0.1"
58 | resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-16.0.1.tgz#5fc5d41f69762e00fbecbc8d4bf9dea47d8726f4"
59 | integrity sha512-x4HABGLyzr5hKUzBC9dvjciOTm11WVH1NWonNjGgxapnTHu5SWUqyqn0zQ6Re0yQU0lsQ6ztLCoMAKDGZflyxA==
60 | dependencies:
61 | "@types/yargs-parser" "*"
62 |
63 | ansi-escapes@^4.2.1:
64 | version "4.3.2"
65 | resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.2.tgz#6b2291d1db7d98b6521d5f1efa42d0f3a9feb65e"
66 | integrity sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==
67 | dependencies:
68 | type-fest "^0.21.3"
69 |
70 | ansi-regex@^5.0.0:
71 | version "5.0.0"
72 | resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.0.tgz#388539f55179bf39339c81af30a654d69f87cb75"
73 | integrity sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==
74 |
75 | ansi-styles@^3.2.1:
76 | version "3.2.1"
77 | resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d"
78 | integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==
79 | dependencies:
80 | color-convert "^1.9.0"
81 |
82 | ansi-styles@^4.0.0, ansi-styles@^4.1.0:
83 | version "4.3.0"
84 | resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937"
85 | integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==
86 | dependencies:
87 | color-convert "^2.0.1"
88 |
89 | arrify@^1.0.0:
90 | version "1.0.1"
91 | resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d"
92 |
93 | async@0.9.x:
94 | version "0.9.2"
95 | resolved "https://registry.yarnpkg.com/async/-/async-0.9.2.tgz#aea74d5e61c1f899613bf64bda66d4c78f2fd17d"
96 | integrity sha1-rqdNXmHB+JlhO/ZL2mbUx48v0X0=
97 |
98 | balanced-match@^1.0.0:
99 | version "1.0.2"
100 | resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee"
101 | integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==
102 |
103 | brace-expansion@^1.1.7:
104 | version "1.1.11"
105 | resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd"
106 | integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==
107 | dependencies:
108 | balanced-match "^1.0.0"
109 | concat-map "0.0.1"
110 |
111 | buffer-from@^1.0.0, buffer-from@^1.1.0:
112 | version "1.1.1"
113 | resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef"
114 |
115 | chalk@^2.4.2:
116 | version "2.4.2"
117 | resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424"
118 | integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==
119 | dependencies:
120 | ansi-styles "^3.2.1"
121 | escape-string-regexp "^1.0.5"
122 | supports-color "^5.3.0"
123 |
124 | chalk@^4.1.0:
125 | version "4.1.1"
126 | resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.1.tgz#c80b3fab28bf6371e6863325eee67e618b77e6ad"
127 | integrity sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==
128 | dependencies:
129 | ansi-styles "^4.1.0"
130 | supports-color "^7.1.0"
131 |
132 | chardet@^0.7.0:
133 | version "0.7.0"
134 | resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e"
135 | integrity sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==
136 |
137 | cli-cursor@^3.1.0:
138 | version "3.1.0"
139 | resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-3.1.0.tgz#264305a7ae490d1d03bf0c9ba7c925d1753af307"
140 | integrity sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==
141 | dependencies:
142 | restore-cursor "^3.1.0"
143 |
144 | cli-width@^3.0.0:
145 | version "3.0.0"
146 | resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-3.0.0.tgz#a2f48437a2caa9a22436e794bf071ec9e61cedf6"
147 | integrity sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==
148 |
149 | cliui@^7.0.2:
150 | version "7.0.4"
151 | resolved "https://registry.yarnpkg.com/cliui/-/cliui-7.0.4.tgz#a0265ee655476fc807aea9df3df8df7783808b4f"
152 | integrity sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==
153 | dependencies:
154 | string-width "^4.2.0"
155 | strip-ansi "^6.0.0"
156 | wrap-ansi "^7.0.0"
157 |
158 | color-convert@^1.9.0:
159 | version "1.9.3"
160 | resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8"
161 | integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==
162 | dependencies:
163 | color-name "1.1.3"
164 |
165 | color-convert@^2.0.1:
166 | version "2.0.1"
167 | resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3"
168 | integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==
169 | dependencies:
170 | color-name "~1.1.4"
171 |
172 | color-name@1.1.3:
173 | version "1.1.3"
174 | resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25"
175 | integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=
176 |
177 | color-name@~1.1.4:
178 | version "1.1.4"
179 | resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2"
180 | integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==
181 |
182 | concat-map@0.0.1:
183 | version "0.0.1"
184 | resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
185 | integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=
186 |
187 | diff@^3.1.0:
188 | version "3.5.0"
189 | resolved "https://registry.yarnpkg.com/diff/-/diff-3.5.0.tgz#800c0dd1e0a8bfbc95835c202ad220fe317e5a12"
190 |
191 | ejs@^3.1.6:
192 | version "3.1.6"
193 | resolved "https://registry.yarnpkg.com/ejs/-/ejs-3.1.6.tgz#5bfd0a0689743bb5268b3550cceeebbc1702822a"
194 | integrity sha512-9lt9Zse4hPucPkoP7FHDF0LQAlGyF9JVpnClFLFH3aSSbxmyoqINRpp/9wePWJTUl4KOQwRL72Iw3InHPDkoGw==
195 | dependencies:
196 | jake "^10.6.1"
197 |
198 | emoji-regex@^8.0.0:
199 | version "8.0.0"
200 | resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37"
201 | integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==
202 |
203 | escalade@^3.1.1:
204 | version "3.1.1"
205 | resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40"
206 | integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==
207 |
208 | escape-string-regexp@^1.0.5:
209 | version "1.0.5"
210 | resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4"
211 | integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=
212 |
213 | external-editor@^3.0.3:
214 | version "3.1.0"
215 | resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-3.1.0.tgz#cb03f740befae03ea4d283caed2741a83f335495"
216 | integrity sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==
217 | dependencies:
218 | chardet "^0.7.0"
219 | iconv-lite "^0.4.24"
220 | tmp "^0.0.33"
221 |
222 | figures@^3.0.0:
223 | version "3.2.0"
224 | resolved "https://registry.yarnpkg.com/figures/-/figures-3.2.0.tgz#625c18bd293c604dc4a8ddb2febf0c88341746af"
225 | integrity sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==
226 | dependencies:
227 | escape-string-regexp "^1.0.5"
228 |
229 | filelist@^1.0.1:
230 | version "1.0.2"
231 | resolved "https://registry.yarnpkg.com/filelist/-/filelist-1.0.2.tgz#80202f21462d4d1c2e214119b1807c1bc0380e5b"
232 | integrity sha512-z7O0IS8Plc39rTCq6i6iHxk43duYOn8uFJiWSewIq0Bww1RNybVHSCjahmcC87ZqAm4OTvFzlzeGu3XAzG1ctQ==
233 | dependencies:
234 | minimatch "^3.0.4"
235 |
236 | fs.realpath@^1.0.0:
237 | version "1.0.0"
238 | resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
239 | integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8=
240 |
241 | function-bind@^1.1.1:
242 | version "1.1.1"
243 | resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d"
244 | integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==
245 |
246 | get-caller-file@^2.0.5:
247 | version "2.0.5"
248 | resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e"
249 | integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==
250 |
251 | glob@^7.0.0:
252 | version "7.1.7"
253 | resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.7.tgz#3b193e9233f01d42d0b3f78294bbeeb418f94a90"
254 | integrity sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==
255 | dependencies:
256 | fs.realpath "^1.0.0"
257 | inflight "^1.0.4"
258 | inherits "2"
259 | minimatch "^3.0.4"
260 | once "^1.3.0"
261 | path-is-absolute "^1.0.0"
262 |
263 | has-flag@^3.0.0:
264 | version "3.0.0"
265 | resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd"
266 | integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0=
267 |
268 | has-flag@^4.0.0:
269 | version "4.0.0"
270 | resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b"
271 | integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==
272 |
273 | has@^1.0.3:
274 | version "1.0.3"
275 | resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796"
276 | integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==
277 | dependencies:
278 | function-bind "^1.1.1"
279 |
280 | iconv-lite@^0.4.24:
281 | version "0.4.24"
282 | resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b"
283 | integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==
284 | dependencies:
285 | safer-buffer ">= 2.1.2 < 3"
286 |
287 | inflight@^1.0.4:
288 | version "1.0.6"
289 | resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9"
290 | integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=
291 | dependencies:
292 | once "^1.3.0"
293 | wrappy "1"
294 |
295 | inherits@2:
296 | version "2.0.4"
297 | resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c"
298 | integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
299 |
300 | inquirer@^8.0.0:
301 | version "8.0.0"
302 | resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-8.0.0.tgz#957a46db1abcf0fdd2ab82deb7470e90afc7d0ac"
303 | integrity sha512-ON8pEJPPCdyjxj+cxsYRe6XfCJepTxANdNnTebsTuQgXpRyZRRT9t4dJwjRubgmvn20CLSEnozRUayXyM9VTXA==
304 | dependencies:
305 | ansi-escapes "^4.2.1"
306 | chalk "^4.1.0"
307 | cli-cursor "^3.1.0"
308 | cli-width "^3.0.0"
309 | external-editor "^3.0.3"
310 | figures "^3.0.0"
311 | lodash "^4.17.21"
312 | mute-stream "0.0.8"
313 | run-async "^2.4.0"
314 | rxjs "^6.6.6"
315 | string-width "^4.1.0"
316 | strip-ansi "^6.0.0"
317 | through "^2.3.6"
318 |
319 | interpret@^1.0.0:
320 | version "1.4.0"
321 | resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.4.0.tgz#665ab8bc4da27a774a40584e812e3e0fa45b1a1e"
322 | integrity sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==
323 |
324 | is-core-module@^2.2.0:
325 | version "2.3.0"
326 | resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.3.0.tgz#d341652e3408bca69c4671b79a0954a3d349f887"
327 | integrity sha512-xSphU2KG9867tsYdLD4RWQ1VqdFl4HTO9Thf3I/3dLEfr0dbPTWKsuCKrgqMljg4nPE+Gq0VCnzT3gr0CyBmsw==
328 | dependencies:
329 | has "^1.0.3"
330 |
331 | is-fullwidth-code-point@^3.0.0:
332 | version "3.0.0"
333 | resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d"
334 | integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==
335 |
336 | jake@^10.6.1:
337 | version "10.8.2"
338 | resolved "https://registry.yarnpkg.com/jake/-/jake-10.8.2.tgz#ebc9de8558160a66d82d0eadc6a2e58fbc500a7b"
339 | integrity sha512-eLpKyrfG3mzvGE2Du8VoPbeSkRry093+tyNjdYaBbJS9v17knImYGNXQCUV0gLxQtF82m3E8iRb/wdSQZLoq7A==
340 | dependencies:
341 | async "0.9.x"
342 | chalk "^2.4.2"
343 | filelist "^1.0.1"
344 | minimatch "^3.0.4"
345 |
346 | lodash@^4.17.21:
347 | version "4.17.21"
348 | resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
349 | integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
350 |
351 | make-error@^1.1.1:
352 | version "1.3.5"
353 | resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.5.tgz#efe4e81f6db28cadd605c70f29c831b58ef776c8"
354 |
355 | mimic-fn@^2.1.0:
356 | version "2.1.0"
357 | resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b"
358 | integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==
359 |
360 | minimatch@^3.0.4:
361 | version "3.0.4"
362 | resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083"
363 | integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==
364 | dependencies:
365 | brace-expansion "^1.1.7"
366 |
367 | minimist@0.0.8:
368 | version "0.0.8"
369 | resolved "http://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d"
370 |
371 | minimist@^1.2.0:
372 | version "1.2.0"
373 | resolved "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284"
374 |
375 | minimist@^1.2.3:
376 | version "1.2.5"
377 | resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602"
378 | integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==
379 |
380 | mkdirp@^0.5.1:
381 | version "0.5.1"
382 | resolved "http://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903"
383 | dependencies:
384 | minimist "0.0.8"
385 |
386 | mute-stream@0.0.8:
387 | version "0.0.8"
388 | resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.8.tgz#1630c42b2251ff81e2a283de96a5497ea92e5e0d"
389 | integrity sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==
390 |
391 | once@^1.3.0:
392 | version "1.4.0"
393 | resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1"
394 | integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E=
395 | dependencies:
396 | wrappy "1"
397 |
398 | onetime@^5.1.0:
399 | version "5.1.2"
400 | resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e"
401 | integrity sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==
402 | dependencies:
403 | mimic-fn "^2.1.0"
404 |
405 | os-tmpdir@~1.0.2:
406 | version "1.0.2"
407 | resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274"
408 | integrity sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=
409 |
410 | path-is-absolute@^1.0.0:
411 | version "1.0.1"
412 | resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f"
413 | integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18=
414 |
415 | path-parse@^1.0.6:
416 | version "1.0.6"
417 | resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.6.tgz#d62dbb5679405d72c4737ec58600e9ddcf06d24c"
418 | integrity sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==
419 |
420 | rechoir@^0.6.2:
421 | version "0.6.2"
422 | resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.6.2.tgz#85204b54dba82d5742e28c96756ef43af50e3384"
423 | integrity sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=
424 | dependencies:
425 | resolve "^1.1.6"
426 |
427 | require-directory@^2.1.1:
428 | version "2.1.1"
429 | resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42"
430 | integrity sha1-jGStX9MNqxyXbiNE/+f3kqam30I=
431 |
432 | resolve@^1.1.6:
433 | version "1.20.0"
434 | resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.20.0.tgz#629a013fb3f70755d6f0b7935cc1c2c5378b1975"
435 | integrity sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==
436 | dependencies:
437 | is-core-module "^2.2.0"
438 | path-parse "^1.0.6"
439 |
440 | restore-cursor@^3.1.0:
441 | version "3.1.0"
442 | resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-3.1.0.tgz#39f67c54b3a7a58cea5236d95cf0034239631f7e"
443 | integrity sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==
444 | dependencies:
445 | onetime "^5.1.0"
446 | signal-exit "^3.0.2"
447 |
448 | run-async@^2.4.0:
449 | version "2.4.1"
450 | resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.4.1.tgz#8440eccf99ea3e70bd409d49aab88e10c189a455"
451 | integrity sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==
452 |
453 | rxjs@^6.4.0, rxjs@^6.6.6:
454 | version "6.6.7"
455 | resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.6.7.tgz#90ac018acabf491bf65044235d5863c4dab804c9"
456 | integrity sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==
457 | dependencies:
458 | tslib "^1.9.0"
459 |
460 | "safer-buffer@>= 2.1.2 < 3":
461 | version "2.1.2"
462 | resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a"
463 | integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==
464 |
465 | shelljs@^0.8.4:
466 | version "0.8.4"
467 | resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.8.4.tgz#de7684feeb767f8716b326078a8a00875890e3c2"
468 | integrity sha512-7gk3UZ9kOfPLIAbslLzyWeGiEqx9e3rxwZM0KE6EL8GlGwjym9Mrlx5/p33bWTu9YG6vcS4MBxYZDHYr5lr8BQ==
469 | dependencies:
470 | glob "^7.0.0"
471 | interpret "^1.0.0"
472 | rechoir "^0.6.2"
473 |
474 | shx@^0.3.3:
475 | version "0.3.3"
476 | resolved "https://registry.yarnpkg.com/shx/-/shx-0.3.3.tgz#681a88c7c10db15abe18525349ed474f0f1e7b9f"
477 | integrity sha512-nZJ3HFWVoTSyyB+evEKjJ1STiixGztlqwKLTUNV5KqMWtGey9fTd4KU1gdZ1X9BV6215pswQ/Jew9NsuS/fNDA==
478 | dependencies:
479 | minimist "^1.2.3"
480 | shelljs "^0.8.4"
481 |
482 | signal-exit@^3.0.2:
483 | version "3.0.3"
484 | resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.3.tgz#a1410c2edd8f077b08b4e253c8eacfcaf057461c"
485 | integrity sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==
486 |
487 | source-map-support@^0.5.6:
488 | version "0.5.9"
489 | resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.9.tgz#41bc953b2534267ea2d605bccfa7bfa3111ced5f"
490 | dependencies:
491 | buffer-from "^1.0.0"
492 | source-map "^0.6.0"
493 |
494 | source-map@^0.6.0:
495 | version "0.6.1"
496 | resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263"
497 |
498 | string-width@^4.1.0, string-width@^4.2.0:
499 | version "4.2.2"
500 | resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.2.tgz#dafd4f9559a7585cfba529c6a0a4f73488ebd4c5"
501 | integrity sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==
502 | dependencies:
503 | emoji-regex "^8.0.0"
504 | is-fullwidth-code-point "^3.0.0"
505 | strip-ansi "^6.0.0"
506 |
507 | strip-ansi@^6.0.0:
508 | version "6.0.0"
509 | resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.0.tgz#0b1571dd7669ccd4f3e06e14ef1eed26225ae532"
510 | integrity sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==
511 | dependencies:
512 | ansi-regex "^5.0.0"
513 |
514 | supports-color@^5.3.0:
515 | version "5.5.0"
516 | resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f"
517 | integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==
518 | dependencies:
519 | has-flag "^3.0.0"
520 |
521 | supports-color@^7.1.0:
522 | version "7.2.0"
523 | resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da"
524 | integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==
525 | dependencies:
526 | has-flag "^4.0.0"
527 |
528 | through@^2.3.6:
529 | version "2.3.8"
530 | resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5"
531 | integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=
532 |
533 | tmp@^0.0.33:
534 | version "0.0.33"
535 | resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9"
536 | integrity sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==
537 | dependencies:
538 | os-tmpdir "~1.0.2"
539 |
540 | ts-node@^7.0.1:
541 | version "7.0.1"
542 | resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-7.0.1.tgz#9562dc2d1e6d248d24bc55f773e3f614337d9baf"
543 | dependencies:
544 | arrify "^1.0.0"
545 | buffer-from "^1.1.0"
546 | diff "^3.1.0"
547 | make-error "^1.1.1"
548 | minimist "^1.2.0"
549 | mkdirp "^0.5.1"
550 | source-map-support "^0.5.6"
551 | yn "^2.0.0"
552 |
553 | tslib@^1.9.0:
554 | version "1.14.1"
555 | resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00"
556 | integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==
557 |
558 | type-fest@^0.21.3:
559 | version "0.21.3"
560 | resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.21.3.tgz#d260a24b0198436e133fa26a524a6d65fa3b2e37"
561 | integrity sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==
562 |
563 | typescript@^3.0.3:
564 | version "3.9.9"
565 | resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.9.9.tgz#e69905c54bc0681d0518bd4d587cc6f2d0b1a674"
566 | integrity sha512-kdMjTiekY+z/ubJCATUPlRDl39vXYiMV9iyeMuEuXZh2we6zz80uovNN2WlAxmmdE/Z/YQe+EbOEXB5RHEED3w==
567 |
568 | wrap-ansi@^7.0.0:
569 | version "7.0.0"
570 | resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
571 | integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==
572 | dependencies:
573 | ansi-styles "^4.0.0"
574 | string-width "^4.1.0"
575 | strip-ansi "^6.0.0"
576 |
577 | wrappy@1:
578 | version "1.0.2"
579 | resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
580 | integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=
581 |
582 | y18n@^5.0.5:
583 | version "5.0.8"
584 | resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55"
585 | integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==
586 |
587 | yargs-parser@^20.2.2:
588 | version "20.2.7"
589 | resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.7.tgz#61df85c113edfb5a7a4e36eb8aa60ef423cbc90a"
590 | integrity sha512-FiNkvbeHzB/syOjIUxFDCnhSfzAL8R5vs40MgLFBorXACCOAEaWu0gRZl14vG8MR9AOJIZbmkjhusqBYZ3HTHw==
591 |
592 | yargs@^17.0.1:
593 | version "17.0.1"
594 | resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.0.1.tgz#6a1ced4ed5ee0b388010ba9fd67af83b9362e0bb"
595 | integrity sha512-xBBulfCc8Y6gLFcrPvtqKz9hz8SO0l1Ni8GgDekvBX2ro0HRQImDGnikfc33cgzcYUSncapnNcZDjVFIH3f6KQ==
596 | dependencies:
597 | cliui "^7.0.2"
598 | escalade "^3.1.1"
599 | get-caller-file "^2.0.5"
600 | require-directory "^2.1.1"
601 | string-width "^4.2.0"
602 | y18n "^5.0.5"
603 | yargs-parser "^20.2.2"
604 |
605 | yn@^2.0.0:
606 | version "2.0.0"
607 | resolved "https://registry.yarnpkg.com/yn/-/yn-2.0.0.tgz#e5adabc8acf408f6385fc76495684c88e6af689a"
608 |
--------------------------------------------------------------------------------