├── .babelrc ├── .browserslistrc ├── .dockerignore ├── .env.development ├── .env.production ├── .eslintrc.cjs ├── .gitignore ├── .husky ├── commit-msg └── pre-commit ├── .lintstagedrc.js ├── .prettierrc ├── .versionrc.json ├── .vscode ├── extensions.json └── settings.json ├── .yarnrc.yml ├── Dockerfile.dev ├── Dockerfile.prod ├── Dockerfile.staging ├── LICENSE ├── README.md ├── build.sh ├── commitlint.config.js ├── index.html ├── jest.config.js ├── nginx └── nginx.conf ├── package.json ├── postcss.config.js ├── public ├── favicon.ico └── robots.txt ├── renovate.json ├── scripts └── create-merge-request.js ├── src ├── App.vue ├── api.ts ├── assets │ ├── css │ │ ├── main.css │ │ └── tailwind.css │ ├── fonts │ │ ├── Vazir-Black.woff2 │ │ ├── Vazir-Bold.woff2 │ │ ├── Vazir-Light.woff2 │ │ ├── Vazir-Medium.woff2 │ │ ├── Vazir-Regular.woff2 │ │ ├── Vazir-Thin.woff2 │ │ └── index.css │ └── images │ │ └── .gitkeep ├── bootstrap.ts ├── component.ts ├── components │ └── .gitkeep ├── composables │ └── .gitkeep ├── context.ts ├── layouts │ └── .gitkeep ├── main.ts ├── modules │ └── auth │ │ ├── components │ │ └── .gitkeep │ │ ├── index.ts │ │ ├── pages │ │ └── index.vue │ │ └── store │ │ ├── actions.ts │ │ ├── getters.ts │ │ ├── index.ts │ │ ├── mutations.ts │ │ └── state.ts ├── providers │ ├── component.ts │ ├── router.ts │ └── store.ts ├── repositories │ ├── auth │ │ ├── endpoint.ts │ │ ├── index.ts │ │ └── types.ts │ ├── index.ts │ └── version.ts ├── repository.ts ├── store │ ├── actions.ts │ ├── getters.ts │ ├── index.ts │ ├── mutations.ts │ └── state.ts └── test │ └── App.spec.ts ├── stylelint.config.js ├── tailwind.config.js ├── test └── __mocks__ │ └── style.js ├── tsconfig.json ├── types ├── env.d.ts └── global.d.ts ├── vite.config.ts └── yarn.lock /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "test": { 4 | "presets": [ 5 | [ 6 | "@babel/preset-env", 7 | { 8 | "targets": { 9 | "node": "current" 10 | } 11 | } 12 | ] 13 | ] 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /.browserslistrc: -------------------------------------------------------------------------------- 1 | > 1% 2 | last 2 versions 3 | not dead 4 | -------------------------------------------------------------------------------- /.dockerignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | .git 3 | .gitignore -------------------------------------------------------------------------------- /.env.development: -------------------------------------------------------------------------------- 1 | NODE_ENV=development 2 | -------------------------------------------------------------------------------- /.env.production: -------------------------------------------------------------------------------- 1 | NODE_ENV=production -------------------------------------------------------------------------------- /.eslintrc.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | env: { 3 | node: true, 4 | browser: true, 5 | es2021: true, 6 | }, 7 | extends: [ 8 | 'plugin:vue/vue3-recommended', 9 | 'eslint:recommended', 10 | '@vue/typescript/recommended', 11 | '@vue/prettier', 12 | ], 13 | rules: { 14 | 'vue/require-default-prop': 'off', 15 | '@typescript-eslint/no-empty-function': 'off', 16 | '@typescript-eslint/no-explicit-any': 'off', 17 | '@typescript-eslint/ban-ts-comment': 'off', 18 | '@typescript-eslint/explicit-module-boundary-types': 'off', 19 | 'vue/multi-word-component-names': 'off', 20 | 'no-console': process.env.NODE_ENV === 'production' ? 'error' : 'off', 21 | 'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off', 22 | }, 23 | globals: { 24 | defineProps: 'readonly', 25 | defineEmits: 'readonly', 26 | defineExpose: 'readonly', 27 | withDefaults: 'readonly', 28 | }, 29 | } 30 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .DS_Store 3 | dist 4 | dist-ssr 5 | *.local 6 | yarn-error.log 7 | .husky/_ 8 | coverage 9 | .yarn 10 | -------------------------------------------------------------------------------- /.husky/commit-msg: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | . "$(dirname "$0")/_/husky.sh" 3 | 4 | yarn commitlint --edit $1 5 | -------------------------------------------------------------------------------- /.husky/pre-commit: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | . "$(dirname "$0")/_/husky.sh" 3 | 4 | NODE_ENV=production 5 | CI=true 6 | yarn lint-staged -------------------------------------------------------------------------------- /.lintstagedrc.js: -------------------------------------------------------------------------------- 1 | export default { 2 | '**/*.{ts,js,vue}': (fileNames) => 3 | `cross-env NODE_ENV=production eslint --ext .js,.ts,.vue --ignore-path .gitignore ${fileNames.join( 4 | ' ' 5 | )} --fix`, 6 | '**/*': (fileNames) => 7 | `prettier --ignore-path .gitignore -u --write ${fileNames.join(' ')} --fix`, 8 | '**/*.{css,scss,vue}': (fileNames) => 9 | `stylelint --ignore-path .gitignore ${fileNames.join(' ')} --fix`, 10 | } 11 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "semi": false, 3 | "tabWidth": 2, 4 | "useTabs": true, 5 | "printWidth": 100, 6 | "singleQuote": true, 7 | "trailingComma": "es5", 8 | "bracketSpacing": true, 9 | "arrowParens": "always", 10 | "htmlWhitespaceSensitivity": "css", 11 | "endOfLine": "lf" 12 | } 13 | -------------------------------------------------------------------------------- /.versionrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "types": [ 3 | { 4 | "type": "feat", 5 | "section": "Features" 6 | }, 7 | { 8 | "type": "fix", 9 | "section": "Bug Fixes" 10 | }, 11 | { 12 | "type": "refactor", 13 | "section": "Refactor" 14 | }, 15 | { 16 | "type": "perf", 17 | "section": "Performance" 18 | }, 19 | { 20 | "type": "chore", 21 | "section": "Project Structure" 22 | }, 23 | { 24 | "type": "docs", 25 | "section": "Documentation" 26 | }, 27 | { 28 | "type": "style", 29 | "hidden": true 30 | }, 31 | { 32 | "type": "test", 33 | "hidden": true 34 | } 35 | ] 36 | } 37 | -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": ["johnsoncodehk.volar"] 3 | } 4 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "vetur.validation.template": false, 3 | "editor.formatOnSave": true, 4 | "editor.codeActionsOnSave": { 5 | "source.fixAll.eslint": "explicit" 6 | }, 7 | "[vue]": { 8 | "editor.defaultFormatter": "esbenp.prettier-vscode" 9 | }, 10 | "[javascript]": { 11 | "editor.defaultFormatter": "esbenp.prettier-vscode" 12 | }, 13 | "cSpell.words": ["elementable", "Elementor", "kishvadi", "Kishvandi", "primevue", "Vuelidate"] 14 | } 15 | -------------------------------------------------------------------------------- /.yarnrc.yml: -------------------------------------------------------------------------------- 1 | compressionLevel: mixed 2 | 3 | enableGlobalCache: false 4 | 5 | nodeLinker: node-modules 6 | -------------------------------------------------------------------------------- /Dockerfile.dev: -------------------------------------------------------------------------------- 1 | FROM node:lts-alpine as build 2 | 3 | WORKDIR /app 4 | 5 | COPY package.json yarn.lock ./ 6 | 7 | RUN NODE_ENV=development yarn install \ 8 | --prefer-offline \ 9 | --frozen-lockfile \ 10 | --non-interactive \ 11 | --production=false 12 | 13 | COPY . ./ 14 | 15 | CMD ["yarn", "dev"] -------------------------------------------------------------------------------- /Dockerfile.prod: -------------------------------------------------------------------------------- 1 | FROM node:lts-alpine as build 2 | 3 | WORKDIR /app 4 | 5 | COPY package.json yarn.lock ./ 6 | 7 | RUN NODE_ENV=development yarn install \ 8 | --prefer-offline \ 9 | --frozen-lockfile \ 10 | --non-interactive \ 11 | --production=false 12 | 13 | COPY . ./ 14 | 15 | ENV NODE_ENV=production 16 | 17 | RUN yarn build:prod 18 | 19 | FROM nginx:stable-alpine as base 20 | 21 | COPY --from=build /app/dist /usr/share/nginx/html 22 | 23 | COPY --from=build app/nginx/nginx.conf /etc/nginx/nginx.conf 24 | 25 | EXPOSE 80 26 | 27 | CMD ["nginx", "-g", "daemon off;"] -------------------------------------------------------------------------------- /Dockerfile.staging: -------------------------------------------------------------------------------- 1 | FROM node:lts-alpine as build 2 | 3 | WORKDIR /app 4 | 5 | COPY package.json yarn.lock ./ 6 | 7 | RUN NODE_ENV=development yarn install \ 8 | --prefer-offline \ 9 | --frozen-lockfile \ 10 | --non-interactive \ 11 | --production=false 12 | 13 | COPY . ./ 14 | 15 | ENV NODE_ENV=development 16 | 17 | RUN yarn build:stg 18 | 19 | FROM nginx:stable-alpine as base 20 | 21 | COPY --from=build /app/dist /usr/share/nginx/html 22 | 23 | COPY --from=build app/nginx/nginx.conf /etc/nginx/nginx.conf 24 | 25 | EXPOSE 80 26 | 27 | CMD ["nginx", "-g", "daemon off;"] -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 raminjafary 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Project Design and Structure 2 | 3 | The project architecture is designed to be (if not exclusively) Domain Driven and very close to the business model. In this section, we explore the project structure as a whole. Later we will study each concept piece by piece. 4 | 5 | The source code lives in the `src` directory. Each file or folder is to be perused in the following: 6 | 7 | ## Components 8 | 9 | The structure must be flat and no nesting should happen. The common components across the application are located here. They may or may not be registered globally, but in most cases local registration is preferred. 10 | 11 | The components should be prefixed with the `App` to imply application level and wild usage. Components with only some html markups and customizations, must be prefixed with `Base` (this is also the same for modules' `components`). 12 | 13 | There are few components like modal, for example, used and registered globally, they should be prefixed with `The` keyword. 14 | 15 | The component naming follows **PascalCase** naming convention. 16 | 17 | Example: 18 | 19 | ``` 20 | - components/ 21 | - AppFooter.vue 22 | - AppHeader.vue 23 | - BaseButton.vue 24 | - TheModal.vue 25 | ``` 26 | 27 | ## Assets 28 | 29 | General assets like images, fonts, global styling, etc. live here. 30 | 31 | ## Layouts 32 | 33 | This directory keeps our common layouts and theming for most of the code base. 34 | 35 | ## Store 36 | 37 | Here lives the global store. There should only exist codes common across the modules. Make a second thought before you pile some codes up. 38 | 39 | ## Repositories 40 | 41 | This is the business layer of the application. All client logic pertaining to API calls are kept here. Every module in `src` directory has a corresponding directory in here. When adding a repository, you have to deal with three different files: 42 | 43 | `endpoint.ts`: The request url from the server with the correct version. 44 | 45 | `types.ts`: It holds types for both function payloads going through and responses coming from the backend. 46 | 47 | `index.ts`: This a factory function that holds the client service calls. 48 | 49 | There is a file `index.ts` at the root of directory. After adding a repository, it must be imported and registered as a readonly getter property accessor in the service pool. 50 | 51 | In the `src` there is a file named `repository.ts` in which we defined a repository provider context mechanism used as a dependency injection to inject repositories pulled by components lazily. The only thing that needs to be done after writing a service in the `repositories` directory is to add the repository type to the `service` interface for type augmentation. 52 | 53 | ### Modules 54 | 55 | Having mentioned all the above, the same rules and conventions apply for each module. However, there are some minor nuances to be considered; That is rules for naming and type definitions. 56 | 57 | Every component or types or interfaces defined in the modules must be prefixed with the module name, that is, of the folder's name. 58 | 59 | #### Pages 60 | 61 | We define our routes only in the pages with a flat structure. 62 | 63 | ``` 64 | - pages/ 65 | Profile.vue 66 | UserId.vue 67 | ``` 68 | 69 | # Commit Message Conventions 70 | 71 | These rules are adopted from [the AngularJS commit conventions](https://docs.google.com/document/d/1QrDFcIiPjSLDn3EL15IJygNPiHORgU1_OOAqWjiDU5Y/). 72 | 73 | - [Goals](#goals) 74 | - [Generating CHANGELOG.md](#generating-changelogmd) 75 | - [Recognizing unimportant commits](#recognizing-unimportant-commits) 76 | - [Provide more information when browsing the history](#provide-more-information-when-browsing-the-history) 77 | - [Format of the commit message](#format-of-the-commit-message) 78 | - [Subject line](#subject-line) 79 | - [Allowed ``](#allowed-type) 80 | - [Allowed ``](#allowed-scope) 81 | - [`` text](#subject-text) 82 | - [Message body](#message-body) 83 | - [Message footer](#message-footer) 84 | - [Breaking changes](#breaking-changes) 85 | - [Referencing issues](#referencing-issues) 86 | - [Examples](#examples) 87 | 88 | ## Goals 89 | 90 | - allow generating CHANGELOG.md by script 91 | - allow ignoring commits by git bisect (not important commits like formatting) 92 | - provide better information when browsing the history 93 | 94 | ## Format of the commit message 95 | 96 | ``` 97 | (): 98 | 99 | 100 | 101 |