├── packages
├── ssr
│ ├── .nvmrc
│ ├── .prettierignore
│ ├── .commitlintrc.json
│ ├── .prettierrc
│ ├── tests
│ │ ├── setupTests.ts
│ │ ├── mocks
│ │ │ ├── fileTransformer.js
│ │ │ └── image.tsx
│ │ └── snapshotResolver.ts
│ ├── tsconfig.jest.json
│ ├── .babelrc
│ ├── src
│ │ ├── modules
│ │ │ └── home
│ │ │ │ └── screens
│ │ │ │ └── Main
│ │ │ │ └── index.tsx
│ │ ├── config
│ │ │ └── routes
│ │ │ │ ├── types.ts
│ │ │ │ └── index.ts
│ │ └── pages
│ │ │ ├── home
│ │ │ └── index.tsx
│ │ │ └── index.tsx
│ ├── .editorconfig
│ ├── next-env.d.ts
│ ├── .vscode
│ │ └── settings.json
│ ├── next.config.js
│ ├── tsconfig.json
│ ├── jest.config.js
│ ├── package.json
│ └── .eslintrc.js
├── mobile
│ ├── .watchmanconfig
│ ├── .gitattributes
│ ├── app.json
│ ├── babel.config.js
│ ├── android
│ │ ├── app
│ │ │ ├── src
│ │ │ │ ├── main
│ │ │ │ │ ├── res
│ │ │ │ │ │ ├── values
│ │ │ │ │ │ │ ├── strings.xml
│ │ │ │ │ │ │ └── styles.xml
│ │ │ │ │ │ ├── mipmap-hdpi
│ │ │ │ │ │ │ ├── ic_launcher.png
│ │ │ │ │ │ │ └── ic_launcher_round.png
│ │ │ │ │ │ ├── mipmap-mdpi
│ │ │ │ │ │ │ ├── ic_launcher.png
│ │ │ │ │ │ │ └── ic_launcher_round.png
│ │ │ │ │ │ ├── mipmap-xhdpi
│ │ │ │ │ │ │ ├── ic_launcher.png
│ │ │ │ │ │ │ └── ic_launcher_round.png
│ │ │ │ │ │ ├── mipmap-xxhdpi
│ │ │ │ │ │ │ ├── ic_launcher.png
│ │ │ │ │ │ │ └── ic_launcher_round.png
│ │ │ │ │ │ └── mipmap-xxxhdpi
│ │ │ │ │ │ │ ├── ic_launcher.png
│ │ │ │ │ │ │ └── ic_launcher_round.png
│ │ │ │ │ ├── java
│ │ │ │ │ │ └── com
│ │ │ │ │ │ │ └── mobile
│ │ │ │ │ │ │ ├── MainActivity.java
│ │ │ │ │ │ │ └── MainApplication.java
│ │ │ │ │ └── AndroidManifest.xml
│ │ │ │ └── debug
│ │ │ │ │ └── AndroidManifest.xml
│ │ │ ├── debug.keystore
│ │ │ ├── proguard-rules.pro
│ │ │ ├── build_defs.bzl
│ │ │ └── _BUCK
│ │ ├── gradle
│ │ │ └── wrapper
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ ├── settings.gradle
│ │ ├── build.gradle
│ │ └── gradle.properties
│ ├── ios
│ │ ├── mobile
│ │ │ ├── Images.xcassets
│ │ │ │ ├── Contents.json
│ │ │ │ └── AppIcon.appiconset
│ │ │ │ │ └── Contents.json
│ │ │ ├── AppDelegate.h
│ │ │ ├── main.m
│ │ │ ├── Info.plist
│ │ │ └── AppDelegate.m
│ │ ├── mobile.xcworkspace
│ │ │ └── contents.xcworkspacedata
│ │ ├── Podfile
│ │ ├── mobileTests
│ │ │ ├── Info.plist
│ │ │ └── mobileTests.m
│ │ ├── mobile-tvOSTests
│ │ │ └── Info.plist
│ │ └── mobile-tvOS
│ │ │ └── Info.plist
│ ├── src
│ │ ├── index.spec.tsx
│ │ └── index.tsx
│ ├── .buckconfig
│ ├── .prettierrc.js
│ ├── index.js
│ ├── tsconfig.json
│ ├── App.tsx
│ ├── .eslintrc.js
│ ├── metro.config.js
│ ├── .gitignore
│ └── package.json
├── design-system
│ ├── src
│ │ ├── web
│ │ │ ├── Typography
│ │ │ │ └── index.tsx
│ │ │ ├── index.ts
│ │ │ ├── Button
│ │ │ │ ├── index.tsx
│ │ │ │ ├── OutlinedButton
│ │ │ │ │ ├── interface.ts
│ │ │ │ │ ├── index.tsx
│ │ │ │ │ └── styles.tsx
│ │ │ │ ├── story
│ │ │ │ │ ├── Button.story.mdx
│ │ │ │ │ ├── OutlinedButton.story.tsx
│ │ │ │ │ └── Button.story.tsx
│ │ │ │ └── DefaultButton
│ │ │ │ │ ├── styles.tsx
│ │ │ │ │ ├── interface.ts
│ │ │ │ │ ├── index.tsx
│ │ │ │ │ └── __tests__
│ │ │ │ │ ├── __snapshots__
│ │ │ │ │ └── index.spec.tsx.snap
│ │ │ │ │ └── index.spec.tsx
│ │ │ └── Grid
│ │ │ │ ├── styles.tsx
│ │ │ │ ├── index.tsx
│ │ │ │ └── interface.ts
│ │ ├── index.ts
│ │ ├── interfaces
│ │ │ ├── index.ts
│ │ │ ├── colors.ts
│ │ │ ├── align.ts
│ │ │ └── units.ts
│ │ ├── theme
│ │ │ ├── fonts.ts
│ │ │ ├── globalStyle.tsx
│ │ │ ├── colors.ts
│ │ │ ├── units.ts
│ │ │ └── index.ts
│ │ ├── provider
│ │ │ └── index.tsx
│ │ └── utils
│ │ │ └── config
│ │ │ └── setupEnzyme.ts
│ ├── lib
│ │ ├── utils
│ │ │ ├── config
│ │ │ │ ├── setupEnzyme.d.ts
│ │ │ │ └── setupEnzyme.js
│ │ │ └── theme
│ │ │ │ ├── globalStyle.d.ts
│ │ │ │ ├── globalStyle.js
│ │ │ │ ├── index.d.ts
│ │ │ │ └── index.js
│ │ ├── Button
│ │ │ ├── index.d.ts
│ │ │ ├── index.js
│ │ │ └── web
│ │ │ │ ├── StyledButton.d.ts
│ │ │ │ ├── OutlinedButton.d.ts
│ │ │ │ ├── DefaultButton.d.ts
│ │ │ │ ├── Button.d.ts
│ │ │ │ ├── Button.js
│ │ │ │ ├── StyledButton.js
│ │ │ │ ├── DefaultButton.js
│ │ │ │ └── OutlinedButton.js
│ │ ├── web
│ │ │ ├── Button
│ │ │ │ ├── index.d.ts
│ │ │ │ ├── index.js
│ │ │ │ ├── StyledButton.d.ts
│ │ │ │ ├── OutlinedButton.d.ts
│ │ │ │ ├── DefaultButton.d.ts
│ │ │ │ ├── Button.d.ts
│ │ │ │ ├── Button.js
│ │ │ │ ├── StyledButton.js
│ │ │ │ ├── DefaultButton.js
│ │ │ │ └── OutlinedButton.js
│ │ │ ├── index.d.ts
│ │ │ ├── Grid
│ │ │ │ ├── Container.d.ts
│ │ │ │ ├── index.d.ts
│ │ │ │ ├── Flex.d.ts
│ │ │ │ ├── Container.js
│ │ │ │ ├── Flex.js
│ │ │ │ └── index.js
│ │ │ └── index.js
│ │ ├── Grid
│ │ │ ├── index.d.ts
│ │ │ ├── web
│ │ │ │ ├── Container.d.ts
│ │ │ │ ├── Flex.d.ts
│ │ │ │ ├── Container.js
│ │ │ │ └── Flex.js
│ │ │ └── index.js
│ │ ├── index.d.ts
│ │ ├── theme
│ │ │ ├── globalStyle.d.ts
│ │ │ ├── index.d.ts
│ │ │ ├── globalStyle.js
│ │ │ └── index.js
│ │ └── index.js
│ ├── lib-esm
│ │ ├── Button
│ │ │ ├── index.js
│ │ │ └── web
│ │ │ │ ├── StyledButton.js
│ │ │ │ ├── Button.js
│ │ │ │ ├── DefaultButton.js
│ │ │ │ └── OutlinedButton.js
│ │ ├── Grid
│ │ │ ├── index.js
│ │ │ └── web
│ │ │ │ └── Container.js
│ │ ├── index.js
│ │ └── theme
│ │ │ ├── globalStyle.js
│ │ │ └── index.js
│ ├── .storybook
│ │ ├── presets.js
│ │ ├── addons.js
│ │ ├── themeDecorator.js
│ │ ├── config.js
│ │ └── webpack.config.js
│ ├── .prettierrc
│ ├── .editorconfig
│ ├── tsconfig.json
│ ├── tsconfig.esm.json
│ ├── jest.config.js
│ ├── __tests__
│ │ └── helpers
│ │ │ └── index.tsx
│ ├── .eslintrc.js
│ └── package.json
├── web
│ ├── src
│ │ ├── react-app-env.d.ts
│ │ ├── store
│ │ │ ├── reducers.ts
│ │ │ ├── sagas.ts
│ │ │ └── index.ts
│ │ ├── index.tsx
│ │ ├── root
│ │ │ └── index.tsx
│ │ └── modules
│ │ │ └── views
│ │ │ └── home
│ │ │ └── index.tsx
│ ├── public
│ │ ├── favicon.ico
│ │ ├── manifest.json
│ │ └── index.html
│ ├── .prettierrc
│ ├── .editorconfig
│ ├── tsconfig.json
│ ├── .eslintrc.js
│ └── package.json
├── sdk
│ ├── lib
│ │ ├── utils
│ │ │ ├── global.interface.js
│ │ │ ├── global.interface.d.ts
│ │ │ ├── httpClient.d.ts
│ │ │ ├── routes.constants.d.ts
│ │ │ └── routes.constants.js
│ │ ├── index.d.ts
│ │ ├── products
│ │ │ ├── product.interface.js
│ │ │ ├── product.provider.d.ts
│ │ │ ├── product.interface.d.ts
│ │ │ ├── product.schema.d.ts
│ │ │ ├── product.schema.js
│ │ │ └── product.provider.js
│ │ └── index.js
│ ├── src
│ │ ├── index.ts
│ │ ├── utils
│ │ │ ├── global.interface.ts
│ │ │ ├── routes.constants.ts
│ │ │ └── httpClient.ts
│ │ └── products
│ │ │ ├── product.interface.ts
│ │ │ ├── product.schema.ts
│ │ │ └── product.provider.ts
│ ├── .prettierrc
│ ├── .editorconfig
│ ├── tsconfig.json
│ ├── tsconfig.esm.json
│ ├── babel.config.js
│ ├── __tests__
│ │ └── products
│ │ │ └── products.spec.ts
│ ├── package.json
│ └── .eslintrc.js
└── server
│ ├── src
│ ├── user
│ │ ├── dto
│ │ │ ├── index.ts
│ │ │ └── create-user.dto.ts
│ │ ├── user.module.ts
│ │ ├── user.decorator.ts
│ │ ├── user.interface.ts
│ │ ├── user.resolver.ts
│ │ ├── user.entity.ts
│ │ └── user.service.ts
│ ├── store
│ │ ├── dto
│ │ │ ├── index.ts
│ │ │ ├── link-employee.dto.ts
│ │ │ ├── link-product.dto.ts
│ │ │ └── create-store.dto.ts
│ │ ├── store.module.ts
│ │ ├── store.resolver.ts
│ │ └── store.entity.ts
│ ├── app.controller.ts
│ ├── product
│ │ ├── dto
│ │ │ ├── index.ts
│ │ │ ├── link-attribute.dto.ts
│ │ │ ├── link-category.dto.ts
│ │ │ └── create-product.dto.ts
│ │ ├── product.module.ts
│ │ ├── product.resolver.ts
│ │ └── product.entity.ts
│ ├── attribute
│ │ ├── attribute.interface.ts
│ │ ├── attribute.module.ts
│ │ ├── dto
│ │ │ └── create-attribute.dto.ts
│ │ ├── attribute.entity.ts
│ │ ├── attribute.resolver.ts
│ │ └── attribute.service.ts
│ ├── auth
│ │ ├── dto
│ │ │ ├── auth.interface.ts
│ │ │ └── auth.input.ts
│ │ ├── auth.guard.ts
│ │ ├── auth.resolver.ts
│ │ ├── auth.module.ts
│ │ ├── jwt.strategy.ts
│ │ └── auth.service.ts
│ ├── main.ts
│ ├── shared
│ │ ├── base.controller.ts
│ │ └── pipes
│ │ │ └── validation.pipe.ts
│ ├── category
│ │ ├── dto
│ │ │ └── create-category.dto.ts
│ │ ├── category.module.ts
│ │ ├── category.entity.ts
│ │ ├── category.resolver.ts
│ │ └── category.service.ts
│ ├── utils
│ │ └── helpers.ts
│ └── app.module.ts
│ ├── .env.example
│ ├── tsconfig.build.json
│ ├── nest-cli.json
│ ├── .prettierrc
│ ├── test
│ ├── jest-e2e.json
│ └── app.e2e-spec.ts
│ ├── .gitignore
│ ├── docker-compose.yml
│ ├── tsconfig.json
│ ├── .eslintrc.js
│ └── package.json
├── tsconfig.json
├── commitlint.config.js
├── typings.d.ts
├── lerna.json
├── .github
├── ISSUE_TEMPLATE
│ ├── question.md
│ ├── feature_request.md
│ └── bug_report.md
├── stale.yml
└── PULL_REQUEST_TEMPLATE.md
├── tsconfig.base.json
├── .gitignore
├── LICENSE
├── package.json
└── README.md
/packages/ssr/.nvmrc:
--------------------------------------------------------------------------------
1 | v14.15.4
--------------------------------------------------------------------------------
/packages/mobile/.watchmanconfig:
--------------------------------------------------------------------------------
1 | {}
--------------------------------------------------------------------------------
/packages/ssr/.prettierignore:
--------------------------------------------------------------------------------
1 | README.md
2 |
--------------------------------------------------------------------------------
/packages/design-system/src/web/Typography/index.tsx:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/packages/mobile/.gitattributes:
--------------------------------------------------------------------------------
1 | *.pbxproj -text
2 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./tsconfig.base.json"
3 | }
4 |
--------------------------------------------------------------------------------
/packages/design-system/lib/utils/config/setupEnzyme.d.ts:
--------------------------------------------------------------------------------
1 | import 'jest-enzyme';
2 |
--------------------------------------------------------------------------------
/packages/web/src/react-app-env.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 |
--------------------------------------------------------------------------------
/packages/design-system/lib/Button/index.d.ts:
--------------------------------------------------------------------------------
1 | export { Button } from './web/Button';
2 |
--------------------------------------------------------------------------------
/packages/mobile/app.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "mobile",
3 | "displayName": "mobile"
4 | }
--------------------------------------------------------------------------------
/commitlint.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {extends: ['@commitlint/config-conventional']};
2 |
--------------------------------------------------------------------------------
/packages/design-system/lib-esm/Button/index.js:
--------------------------------------------------------------------------------
1 | export { Button } from './web/Button';
2 |
--------------------------------------------------------------------------------
/packages/sdk/lib/utils/global.interface.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | exports.__esModule = true;
3 |
--------------------------------------------------------------------------------
/packages/sdk/src/index.ts:
--------------------------------------------------------------------------------
1 | export { ProductProvider } from './products/product.provider';
2 |
--------------------------------------------------------------------------------
/packages/server/src/user/dto/index.ts:
--------------------------------------------------------------------------------
1 | export { CreateUserDto } from './create-user.dto';
2 |
--------------------------------------------------------------------------------
/packages/sdk/lib/index.d.ts:
--------------------------------------------------------------------------------
1 | export { ProductProvider } from './products/product.provider';
2 |
--------------------------------------------------------------------------------
/packages/sdk/lib/products/product.interface.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | exports.__esModule = true;
3 |
--------------------------------------------------------------------------------
/packages/sdk/src/utils/global.interface.ts:
--------------------------------------------------------------------------------
1 | export interface IApiResponse {
2 | data: T;
3 | }
--------------------------------------------------------------------------------
/packages/ssr/.commitlintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": ["@commitlint/config-conventional"]
3 | }
4 |
--------------------------------------------------------------------------------
/typings.d.ts:
--------------------------------------------------------------------------------
1 |
2 | declare module "*.json" {
3 | const value: any;
4 | export default value;
5 | }
6 |
--------------------------------------------------------------------------------
/packages/design-system/.storybook/presets.js:
--------------------------------------------------------------------------------
1 | module.exports = ['@storybook/addon-docs/react/preset'];
2 |
--------------------------------------------------------------------------------
/packages/sdk/lib/utils/global.interface.d.ts:
--------------------------------------------------------------------------------
1 | export interface IApiResponse {
2 | data: T;
3 | }
4 |
--------------------------------------------------------------------------------
/packages/design-system/lib/web/Button/index.d.ts:
--------------------------------------------------------------------------------
1 | export { default as DefaultButton } from './DefaultButton';
2 |
--------------------------------------------------------------------------------
/packages/mobile/babel.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | presets: ['module:metro-react-native-babel-preset'],
3 | };
4 |
--------------------------------------------------------------------------------
/packages/web/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/react-shop/react-ecommerce/HEAD/packages/web/public/favicon.ico
--------------------------------------------------------------------------------
/packages/design-system/lib-esm/Grid/index.js:
--------------------------------------------------------------------------------
1 | export { Container } from './web/Container';
2 | export { Flex } from './web/Flex';
3 |
--------------------------------------------------------------------------------
/packages/design-system/lib-esm/index.js:
--------------------------------------------------------------------------------
1 | export * from './web';
2 | export { default as GlobalStyles } from './theme/globalStyle';
3 |
--------------------------------------------------------------------------------
/packages/design-system/lib/Grid/index.d.ts:
--------------------------------------------------------------------------------
1 | export { Container } from './web/Container';
2 | export { Flex } from './web/Flex';
3 |
--------------------------------------------------------------------------------
/packages/design-system/lib/web/index.d.ts:
--------------------------------------------------------------------------------
1 | export { DefaultButton } from './Button';
2 | export { default as Grid } from './Grid';
3 |
--------------------------------------------------------------------------------
/packages/design-system/src/index.ts:
--------------------------------------------------------------------------------
1 | export * from './web';
2 | export { default as GlobalStyles } from './theme/globalStyle';
3 |
--------------------------------------------------------------------------------
/packages/design-system/src/web/index.ts:
--------------------------------------------------------------------------------
1 | export { DefaultButton } from './Button';
2 | export { default as Grid } from './Grid';
3 |
--------------------------------------------------------------------------------
/packages/web/src/store/reducers.ts:
--------------------------------------------------------------------------------
1 | import { combineReducers } from 'redux';
2 |
3 | export default () => combineReducers({});
4 |
--------------------------------------------------------------------------------
/lerna.json:
--------------------------------------------------------------------------------
1 | {
2 | "packages": ["packages/*"],
3 | "version": "0.0.0",
4 | "npmClient": "yarn",
5 | "useWorkspaces": true
6 | }
7 |
--------------------------------------------------------------------------------
/packages/design-system/src/interfaces/index.ts:
--------------------------------------------------------------------------------
1 | export * from './colors';
2 | export * from './units';
3 | export * from './align';
4 |
--------------------------------------------------------------------------------
/packages/ssr/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "trailingComma": "all",
3 | "singleQuote": true,
4 | "printWidth": 100,
5 | "tabWidth": 2
6 | }
7 |
--------------------------------------------------------------------------------
/packages/mobile/android/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | mobile
3 |
4 |
--------------------------------------------------------------------------------
/packages/mobile/ios/mobile/Images.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "version" : 1,
4 | "author" : "xcode"
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/packages/server/.env.example:
--------------------------------------------------------------------------------
1 | DATABASE_HOST=
2 | DATABASE_NAME=
3 | DATABASE_USER=
4 | DATABASE_PASSWORD=
5 | DATABASE_PORT=
6 |
7 | SECRET=
--------------------------------------------------------------------------------
/packages/ssr/tests/setupTests.ts:
--------------------------------------------------------------------------------
1 | import '@testing-library/jest-dom';
2 | import 'jest-styled-components';
3 | import '@tests/mocks/image';
4 |
--------------------------------------------------------------------------------
/packages/mobile/android/app/debug.keystore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/react-shop/react-ecommerce/HEAD/packages/mobile/android/app/debug.keystore
--------------------------------------------------------------------------------
/packages/server/tsconfig.build.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./tsconfig.json",
3 | "exclude": ["node_modules", "test", "dist", "**/*spec.ts"]
4 | }
5 |
--------------------------------------------------------------------------------
/packages/ssr/tsconfig.jest.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./tsconfig.json",
3 | "compilerOptions": {
4 | "jsx": "react-jsx"
5 | }
6 | }
--------------------------------------------------------------------------------
/packages/design-system/lib/index.d.ts:
--------------------------------------------------------------------------------
1 | export { DefaultButton, Grid } from './web';
2 | export { default as GlobalStyles } from './theme/globalStyle';
3 |
--------------------------------------------------------------------------------
/packages/web/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "bracketSpacing": false,
3 | "jsxBracketSameLine": true,
4 | "singleQuote": true,
5 | "trailingComma": "es5"
6 | }
--------------------------------------------------------------------------------
/packages/web/src/store/sagas.ts:
--------------------------------------------------------------------------------
1 | import { all } from 'redux-saga/effects';
2 |
3 | export default function* rootSaga() {
4 | yield all([]);
5 | }
6 |
--------------------------------------------------------------------------------
/packages/design-system/lib/Grid/web/Container.d.ts:
--------------------------------------------------------------------------------
1 | export declare const Container: import("styled-components").StyledComponent<"div", any, {}, never>;
2 |
--------------------------------------------------------------------------------
/packages/design-system/lib/web/Grid/Container.d.ts:
--------------------------------------------------------------------------------
1 | export declare const Container: import("styled-components").StyledComponent<"div", any, {}, never>;
2 |
--------------------------------------------------------------------------------
/packages/mobile/src/index.spec.tsx:
--------------------------------------------------------------------------------
1 | describe('When sum 2 numbers', () => {
2 | it('should be 5', () => {
3 | expect(4 + 1).toBe(5);
4 | });
5 | });
6 |
--------------------------------------------------------------------------------
/packages/sdk/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "bracketSpacing": false,
3 | "jsxBracketSameLine": true,
4 | "singleQuote": true,
5 | "trailingComma": "es5"
6 | }
7 |
--------------------------------------------------------------------------------
/packages/design-system/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "bracketSpacing": false,
3 | "jsxBracketSameLine": true,
4 | "singleQuote": true,
5 | "trailingComma": "es5"
6 | }
--------------------------------------------------------------------------------
/packages/design-system/src/web/Button/index.tsx:
--------------------------------------------------------------------------------
1 | /* eslint-disable import/prefer-default-export */
2 | export { default as DefaultButton } from './DefaultButton';
3 |
--------------------------------------------------------------------------------
/packages/mobile/.buckconfig:
--------------------------------------------------------------------------------
1 |
2 | [android]
3 | target = Google Inc.:Google APIs:23
4 |
5 | [maven_repositories]
6 | central = https://repo1.maven.org/maven2
7 |
--------------------------------------------------------------------------------
/packages/mobile/.prettierrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | bracketSpacing: true,
3 | jsxBracketSameLine: true,
4 | singleQuote: true,
5 | trailingComma: 'all',
6 | };
--------------------------------------------------------------------------------
/packages/sdk/lib/utils/httpClient.d.ts:
--------------------------------------------------------------------------------
1 | export declare const http: import("axios").AxiosInstance;
2 | export interface IAccessUser {
3 | token: string;
4 | }
5 |
--------------------------------------------------------------------------------
/packages/ssr/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": ["next/babel"],
3 | "plugins": [["styled-components", { "ssr": true, "displayName": true, "preprocess": false }]]
4 | }
--------------------------------------------------------------------------------
/packages/design-system/lib/Button/index.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | exports.__esModule = true;
3 | var Button_1 = require("./web/Button");
4 | exports.Button = Button_1.Button;
5 |
--------------------------------------------------------------------------------
/packages/mobile/android/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/react-shop/react-ecommerce/HEAD/packages/mobile/android/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/packages/sdk/lib/utils/routes.constants.d.ts:
--------------------------------------------------------------------------------
1 | export declare const api: {
2 | BASE_URL: string;
3 | };
4 | export declare const ENDPOINTS: {
5 | PRODUCTS: string;
6 | };
7 |
--------------------------------------------------------------------------------
/packages/server/nest-cli.json:
--------------------------------------------------------------------------------
1 | {
2 | "collection": "@nestjs/schematics",
3 | "sourceRoot": "src",
4 | "compilerOptions": {
5 | "plugins": ["@nestjs/graphql"]
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/packages/ssr/src/modules/home/screens/Main/index.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | const Home = () => {
4 | return Home screen
5 | }
6 |
7 | export default Home;
8 |
--------------------------------------------------------------------------------
/packages/mobile/android/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/react-shop/react-ecommerce/HEAD/packages/mobile/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/packages/mobile/android/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/react-shop/react-ecommerce/HEAD/packages/mobile/android/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/packages/design-system/src/theme/fonts.ts:
--------------------------------------------------------------------------------
1 | const weights = {
2 | light: 300,
3 | regular: 500,
4 | bold: 700,
5 | black: 900,
6 | };
7 |
8 | export default {
9 | weights,
10 | };
11 |
--------------------------------------------------------------------------------
/packages/mobile/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/react-shop/react-ecommerce/HEAD/packages/mobile/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/packages/mobile/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/react-shop/react-ecommerce/HEAD/packages/mobile/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/packages/ssr/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | [*]
4 | indent_style = space
5 | indent_size = 2
6 | charset = utf-8
7 | end_of_line = lf
8 | trim_trailing_whitespace = true
9 | insert_final_newline = tr
--------------------------------------------------------------------------------
/packages/design-system/lib/theme/globalStyle.d.ts:
--------------------------------------------------------------------------------
1 | declare const GlobalStyle: import("styled-components").GlobalStyleComponent<{}, import("styled-components").DefaultTheme>;
2 | export default GlobalStyle;
3 |
--------------------------------------------------------------------------------
/packages/mobile/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/react-shop/react-ecommerce/HEAD/packages/mobile/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/packages/sdk/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | [*]
4 | end_of_line = lf
5 | indent_style = space
6 | indent_size = 2
7 | charset = utf-8
8 | trim_trailing_whitespace = true
9 | insert_final_newline = true
--------------------------------------------------------------------------------
/packages/web/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | [*]
4 | end_of_line = lf
5 | indent_style = space
6 | indent_size = 2
7 | charset = utf-8
8 | trim_trailing_whitespace = true
9 | insert_final_newline = true
--------------------------------------------------------------------------------
/packages/mobile/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/react-shop/react-ecommerce/HEAD/packages/mobile/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/packages/mobile/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/react-shop/react-ecommerce/HEAD/packages/mobile/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/packages/mobile/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/react-shop/react-ecommerce/HEAD/packages/mobile/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/packages/sdk/lib/index.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | exports.__esModule = true;
3 | var product_provider_1 = require("./products/product.provider");
4 | exports.ProductProvider = product_provider_1.ProductProvider;
5 |
--------------------------------------------------------------------------------
/packages/ssr/src/config/routes/types.ts:
--------------------------------------------------------------------------------
1 | export type Route = (...args: string[]) => string;
2 |
3 | export interface Routes {
4 | PUBLIC: Record;
5 | PRIVATE: Record;
6 | }
7 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/question.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: 💬 Question
3 | about: You need help with the project.
4 | labels: "question"
5 | ---
6 |
7 | ## Ask your Question
8 |
9 |
10 |
--------------------------------------------------------------------------------
/packages/design-system/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | [*]
4 | end_of_line = lf
5 | indent_style = space
6 | indent_size = 2
7 | charset = utf-8
8 | trim_trailing_whitespace = true
9 | insert_final_newline = true
--------------------------------------------------------------------------------
/packages/design-system/lib/utils/theme/globalStyle.d.ts:
--------------------------------------------------------------------------------
1 | declare const GlobalStyle: import("styled-components").GlobalStyleComponent<{}, import("styled-components").DefaultTheme>;
2 | export default GlobalStyle;
3 |
--------------------------------------------------------------------------------
/packages/mobile/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/react-shop/react-ecommerce/HEAD/packages/mobile/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/packages/mobile/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/react-shop/react-ecommerce/HEAD/packages/mobile/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/packages/design-system/lib/web/Grid/index.d.ts:
--------------------------------------------------------------------------------
1 | import { FunctionComponent } from 'react';
2 | import { TGridProps } from './interface';
3 | declare const Grid: FunctionComponent;
4 | export default Grid;
5 |
--------------------------------------------------------------------------------
/packages/design-system/.storybook/addons.js:
--------------------------------------------------------------------------------
1 | import '@storybook/addon-knobs/register';
2 | import '@storybook/addon-a11y/register';
3 | import '@storybook/addon-docs/register';
4 | import '@storybook/addon-actions/register';
5 |
--------------------------------------------------------------------------------
/packages/design-system/lib/Button/web/StyledButton.d.ts:
--------------------------------------------------------------------------------
1 | declare const StyledButton: import("styled-components").StyledComponent<"button", any, import("./DefaultButton").IButtonProps, never>;
2 | export default StyledButton;
3 |
--------------------------------------------------------------------------------
/packages/server/src/store/dto/index.ts:
--------------------------------------------------------------------------------
1 | export { CreateStoreDto } from './create-store.dto';
2 | export { LinkEmployeeToStoreDto } from './link-employee.dto';
3 | export { LinkProductToStoreDto } from './link-product.dto';
4 |
--------------------------------------------------------------------------------
/packages/ssr/tests/mocks/fileTransformer.js:
--------------------------------------------------------------------------------
1 | const path = require(`path`);
2 |
3 | module.exports = {
4 | process(_, filename) {
5 | return `module.exports = ${JSON.stringify(path.basename(filename))};`;
6 | },
7 | };
--------------------------------------------------------------------------------
/packages/design-system/lib/Button/web/OutlinedButton.d.ts:
--------------------------------------------------------------------------------
1 | declare const OutlinedButton: import("styled-components").StyledComponent<"button", any, import("./DefaultButton").IButtonProps, never>;
2 | export default OutlinedButton;
3 |
--------------------------------------------------------------------------------
/tsconfig.base.json:
--------------------------------------------------------------------------------
1 | {
2 | "exclude": ["node_modules"],
3 | "files": ["./typings.d.ts"],
4 | "compilerOptions": {
5 | "jsx": "react",
6 | "esModuleInterop": true,
7 | "skipLibCheck": true
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/packages/server/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "trailingComma": "all",
3 | "singleQuote": true,
4 | "printWidth": 100,
5 | "tabWidth": 2,
6 | "prettier/prettier": ["error",{
7 | "endOfLine": "auto"
8 | }
9 | ]
10 | }
11 |
--------------------------------------------------------------------------------
/packages/server/src/app.controller.ts:
--------------------------------------------------------------------------------
1 | import { Get, Controller } from '@nestjs/common';
2 |
3 | @Controller()
4 | export class AppController {
5 | @Get()
6 | root(): string {
7 | return 'Health check ok!';
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/packages/server/src/product/dto/index.ts:
--------------------------------------------------------------------------------
1 | export { CreateProductDto } from './create-product.dto';
2 | export { LinkAttributeToProductDto } from './link-attribute.dto';
3 | export { LinkCategoryToProductDto } from './link-category.dto';
4 |
--------------------------------------------------------------------------------
/packages/mobile/android/settings.gradle:
--------------------------------------------------------------------------------
1 | rootProject.name = 'mobile'
2 | apply from: file("../../../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesSettingsGradle(settings)
3 | include ':app'
4 |
--------------------------------------------------------------------------------
/packages/sdk/lib/products/product.provider.d.ts:
--------------------------------------------------------------------------------
1 | import { TGetProducts } from './product.interface';
2 |
3 | export interface IProductProvider {
4 | getProducts: TGetProducts;
5 | }
6 | export declare const ProductProvider: IProductProvider;
7 |
--------------------------------------------------------------------------------
/packages/ssr/tests/mocks/image.tsx:
--------------------------------------------------------------------------------
1 | /* eslint-disable @next/next/no-img-element */
2 |
3 | jest.mock(`next/image`, () => ({ src, alt }: Pick) => (
4 |
5 | ));
6 |
7 | export {};
--------------------------------------------------------------------------------
/packages/mobile/index.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @format
3 | */
4 |
5 | import {AppRegistry} from 'react-native';
6 | import App from './App';
7 | import {name as appName} from './app.json';
8 |
9 | AppRegistry.registerComponent(appName, () => App);
10 |
--------------------------------------------------------------------------------
/packages/sdk/lib/products/product.interface.d.ts:
--------------------------------------------------------------------------------
1 | import { IApiResponse } from '../utils/global.interface';
2 | export interface IProduct {
3 | name: string;
4 | }
5 | export declare type TGetProducts = () => Promise>;
6 |
--------------------------------------------------------------------------------
/packages/sdk/src/products/product.interface.ts:
--------------------------------------------------------------------------------
1 | import { IApiResponse } from '../utils/global.interface';
2 |
3 | export interface IProduct {
4 | name: string;
5 | }
6 |
7 | export type TGetProducts = (
8 | ) => Promise>;
9 |
--------------------------------------------------------------------------------
/packages/design-system/lib/Grid/index.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | exports.__esModule = true;
3 | var Container_1 = require("./web/Container");
4 | exports.Container = Container_1.Container;
5 | var Flex_1 = require("./web/Flex");
6 | exports.Flex = Flex_1.Flex;
7 |
--------------------------------------------------------------------------------
/packages/design-system/lib/web/index.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | exports.__esModule = true;
3 | var Button_1 = require("./Button");
4 | exports.DefaultButton = Button_1.DefaultButton;
5 | var Grid_1 = require("./Grid");
6 | exports.Grid = Grid_1["default"];
7 |
--------------------------------------------------------------------------------
/packages/design-system/lib-esm/Grid/web/Container.js:
--------------------------------------------------------------------------------
1 | import styled from 'styled-components';
2 | export const Container = styled.div `
3 | width: 100%;
4 | height: 100%;
5 | display: flex;
6 | justify-content: center;
7 | align-items: center;
8 | `;
9 |
--------------------------------------------------------------------------------
/packages/design-system/lib/web/Button/index.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | exports.__esModule = true;
3 | /* eslint-disable import/prefer-default-export */
4 | var DefaultButton_1 = require("./DefaultButton");
5 | exports.DefaultButton = DefaultButton_1["default"];
6 |
--------------------------------------------------------------------------------
/packages/sdk/src/utils/routes.constants.ts:
--------------------------------------------------------------------------------
1 | export const api = {
2 | BASE_URL: 'https://api.github.com/users/viniarruda',
3 | };
4 |
5 | const ROOT_PRODUCTS = '/repos';
6 |
7 | export const ENDPOINTS = {
8 | PRODUCTS: `${ROOT_PRODUCTS}`,
9 | };
10 |
--------------------------------------------------------------------------------
/packages/server/test/jest-e2e.json:
--------------------------------------------------------------------------------
1 | {
2 | "moduleFileExtensions": ["js", "json", "ts"],
3 | "rootDir": ".",
4 | "testEnvironment": "node",
5 | "testRegex": ".e2e-spec.ts$",
6 | "transform": {
7 | "^.+\\.(t|j)s$": "ts-jest"
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/packages/design-system/.storybook/themeDecorator.js:
--------------------------------------------------------------------------------
1 | import React from "react"
2 | import ThemeProvider from "../src/provider"
3 |
4 | const ThemeDecorator = storyFn => (
5 | {storyFn()}
6 | )
7 |
8 | export default ThemeDecorator
9 |
--------------------------------------------------------------------------------
/packages/design-system/lib/web/Button/StyledButton.d.ts:
--------------------------------------------------------------------------------
1 | declare const StyledButton: import("styled-components").StyledComponent<"button", import("styled-components").DefaultTheme, import("./DefaultButton").IButtonProps, never>;
2 | export default StyledButton;
3 |
--------------------------------------------------------------------------------
/packages/mobile/ios/mobile/AppDelegate.h:
--------------------------------------------------------------------------------
1 | #import
2 | #import
3 |
4 | @interface AppDelegate : UIResponder
5 |
6 | @property (nonatomic, strong) UIWindow *window;
7 |
8 | @end
9 |
--------------------------------------------------------------------------------
/packages/design-system/lib/web/Button/OutlinedButton.d.ts:
--------------------------------------------------------------------------------
1 | declare const OutlinedButton: import("styled-components").StyledComponent<"button", import("styled-components").DefaultTheme, import("./DefaultButton").IButtonProps, never>;
2 | export default OutlinedButton;
3 |
--------------------------------------------------------------------------------
/packages/sdk/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "exclude": ["node_modules", "lib-esm", "lib", "**/*.spec*"],
3 | "include": ["src"],
4 | "extends": "../../tsconfig.base.json",
5 | "compilerOptions": {
6 | "outDir": "lib",
7 | "declaration": true
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/packages/mobile/ios/mobile/main.m:
--------------------------------------------------------------------------------
1 | #import
2 |
3 | #import "AppDelegate.h"
4 |
5 | int main(int argc, char * argv[]) {
6 | @autoreleasepool {
7 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/packages/mobile/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../../tsconfig.base.json",
3 | "compilerOptions": {
4 | "lib": ["esnext", "dom"],
5 | "allowJs": false,
6 | "checkJs": false,
7 | "jsx": "react-native"
8 | },
9 | "include": ["./src/**/*"]
10 | }
11 |
--------------------------------------------------------------------------------
/packages/mobile/android/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionBase=GRADLE_USER_HOME
2 | distributionPath=wrapper/dists
3 | distributionUrl=https\://services.gradle.org/distributions/gradle-6.2-all.zip
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 |
--------------------------------------------------------------------------------
/packages/sdk/lib/utils/routes.constants.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | exports.__esModule = true;
3 | exports.api = {
4 | BASE_URL: 'https://api.github.com/users/viniarruda'
5 | };
6 | var ROOT_PRODUCTS = '/repos';
7 | exports.ENDPOINTS = {
8 | PRODUCTS: "" + ROOT_PRODUCTS
9 | };
10 |
--------------------------------------------------------------------------------
/packages/ssr/next-env.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 | ///
3 | ///
4 |
5 | // NOTE: This file should not be edited
6 | // see https://nextjs.org/docs/basic-features/typescript for more information.
7 |
--------------------------------------------------------------------------------
/packages/design-system/lib/Button/web/DefaultButton.d.ts:
--------------------------------------------------------------------------------
1 | export interface IButtonProps {
2 | full?: boolean;
3 | secondary?: boolean;
4 | }
5 | declare const DefaultButton: import("styled-components").StyledComponent<"button", any, IButtonProps, never>;
6 | export default DefaultButton;
7 |
--------------------------------------------------------------------------------
/packages/design-system/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "exclude": ["node_modules", "lib-esm", "lib", "**/*.story*", "**/*.spec*"],
3 | "include": ["src"],
4 | "extends": "../../tsconfig.base.json",
5 | "compilerOptions": {
6 | "outDir": "lib",
7 | "declaration": true
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/packages/mobile/App.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | import Routes from './src';
4 |
5 | declare const global: {HermesInternal: null | {}};
6 |
7 | const App = () => {
8 | return (
9 | <>
10 |
11 | >
12 | );
13 | };
14 |
15 | export default App;
16 |
--------------------------------------------------------------------------------
/packages/server/src/attribute/attribute.interface.ts:
--------------------------------------------------------------------------------
1 | import { registerEnumType } from '@nestjs/graphql';
2 |
3 | export enum Types {
4 | COLOR = 'color',
5 | SIZE = 'size',
6 | }
7 |
8 | registerEnumType(Types, {
9 | name: 'Types',
10 | description: 'Attribute types',
11 | });
12 |
--------------------------------------------------------------------------------
/packages/server/src/auth/dto/auth.interface.ts:
--------------------------------------------------------------------------------
1 | import { Field, ObjectType } from '@nestjs/graphql';
2 | import { User } from '@user/user.entity';
3 |
4 | @ObjectType()
5 | export class AuthType {
6 | @Field(() => User)
7 | user: User;
8 |
9 | @Field()
10 | token: string;
11 | }
12 |
--------------------------------------------------------------------------------
/packages/design-system/lib/index.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | exports.__esModule = true;
3 | var web_1 = require("./web");
4 | exports.DefaultButton = web_1.DefaultButton;
5 | exports.Grid = web_1.Grid;
6 | var globalStyle_1 = require("./theme/globalStyle");
7 | exports.GlobalStyles = globalStyle_1["default"];
8 |
--------------------------------------------------------------------------------
/packages/sdk/lib/products/product.schema.d.ts:
--------------------------------------------------------------------------------
1 | import * as Yup from 'yup';
2 | export declare const ProductsSchema: Yup.ArraySchema>;
6 | export declare const ProductSchema: Yup.ObjectSchema>;
9 |
--------------------------------------------------------------------------------
/packages/design-system/lib/Button/web/Button.d.ts:
--------------------------------------------------------------------------------
1 | import { FunctionComponent, ReactNode } from 'react';
2 | export interface IButton {
3 | children: ReactNode;
4 | outline?: boolean;
5 | full?: boolean;
6 | secondary?: boolean;
7 | }
8 | export declare const Button: FunctionComponent;
9 |
--------------------------------------------------------------------------------
/packages/ssr/src/pages/home/index.tsx:
--------------------------------------------------------------------------------
1 | import Head from 'next/head';
2 |
3 | import HomeScreen from '@home/screens/Main';
4 |
5 | export default function Page() {
6 | return (
7 | <>
8 |
9 | Home
10 |
11 |
12 | >
13 | );
14 | }
15 |
--------------------------------------------------------------------------------
/packages/design-system/lib/web/Button/DefaultButton.d.ts:
--------------------------------------------------------------------------------
1 | export interface IButtonProps {
2 | full?: boolean;
3 | secondary?: boolean;
4 | }
5 | declare const DefaultButton: import("styled-components").StyledComponent<"button", import("styled-components").DefaultTheme, IButtonProps, never>;
6 | export default DefaultButton;
7 |
--------------------------------------------------------------------------------
/packages/mobile/ios/mobile.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/packages/sdk/tsconfig.esm.json:
--------------------------------------------------------------------------------
1 | {
2 | "include": ["src"],
3 | "extends": "./tsconfig.json",
4 | "compilerOptions": {
5 | "outDir": "lib-esm",
6 | "module": "esnext",
7 | "target": "esnext",
8 | "moduleResolution": "node",
9 | "lib": ["dom", "esnext"],
10 | "declaration": false
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/packages/design-system/tsconfig.esm.json:
--------------------------------------------------------------------------------
1 | {
2 | "include": ["src"],
3 | "extends": "./tsconfig.json",
4 | "compilerOptions": {
5 | "outDir": "lib-esm",
6 | "module": "esnext",
7 | "target": "esnext",
8 | "moduleResolution": "node",
9 | "lib": ["dom", "esnext"],
10 | "declaration": false
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/packages/sdk/babel.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | presets: [
3 | [
4 | '@babel/preset-env',
5 | {
6 | targets: {
7 | node: 'current',
8 | },
9 | },
10 | ],
11 | '@babel/preset-typescript',
12 | ],
13 | plugins: ['@babel/plugin-proposal-export-default-from'],
14 | };
15 |
--------------------------------------------------------------------------------
/packages/sdk/src/products/product.schema.ts:
--------------------------------------------------------------------------------
1 | import * as Yup from 'yup';
2 |
3 | export const ProductsSchema = Yup.array().of(
4 | Yup.object().shape({
5 | id: Yup.string(),
6 | name: Yup.string(),
7 | })
8 | );
9 |
10 | export const ProductSchema = Yup.object().shape({
11 | name: Yup.string().required(),
12 | });
13 |
--------------------------------------------------------------------------------
/packages/web/src/index.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { render } from 'react-dom';
3 | import Root from './root';
4 |
5 | // import 'slick-carousel/slick/slick.css';
6 | // import 'slick-carousel/slick/slick-theme.css';
7 |
8 | // eslint-disable-next-line no-undef
9 | render(, document.getElementById('root'));
10 |
--------------------------------------------------------------------------------
/packages/mobile/android/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/packages/server/src/auth/dto/auth.input.ts:
--------------------------------------------------------------------------------
1 | import { InputType, Field } from '@nestjs/graphql';
2 |
3 | import { IsNotEmpty } from 'class-validator';
4 |
5 | @InputType()
6 | export class AuthDto {
7 | @Field()
8 | @IsNotEmpty()
9 | readonly email: string;
10 |
11 | @Field()
12 | @IsNotEmpty()
13 | readonly password: string;
14 | }
15 |
--------------------------------------------------------------------------------
/packages/ssr/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "editor.defaultFormatter": "esbenp.prettier-vscode",
3 | "editor.formatOnSave": true,
4 | "editor.formatOnPaste": true,
5 | "editor.codeActionsOnSave": {
6 | "source.fixAll": true,
7 | "source.organizeImports": false
8 | },
9 | "search.exclude": {
10 | "coverage": true
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/packages/server/src/main.ts:
--------------------------------------------------------------------------------
1 | import { NestFactory } from '@nestjs/core';
2 |
3 | import { AppModule } from './app.module';
4 |
5 | async function bootstrap() {
6 | const appOptions = { cors: true };
7 | const app = await NestFactory.create(AppModule, appOptions);
8 |
9 | app.setGlobalPrefix('api');
10 |
11 | await app.listen(5000);
12 | }
13 | bootstrap();
14 |
--------------------------------------------------------------------------------
/packages/design-system/lib/Grid/web/Flex.d.ts:
--------------------------------------------------------------------------------
1 | export interface IFlexProps {
2 | justify?: 'center' | 'flex-start' | 'space-between' | 'flex-end';
3 | align?: 'center' | 'flex-start' | 'space-between' | 'flex-end' | 'stretch';
4 | direction?: 'row' | 'column';
5 | }
6 | export declare const Flex: import("styled-components").StyledComponent<"div", any, IFlexProps, never>;
7 |
--------------------------------------------------------------------------------
/packages/design-system/lib/web/Grid/Flex.d.ts:
--------------------------------------------------------------------------------
1 | export interface IFlexProps {
2 | justify?: 'center' | 'flex-start' | 'space-between' | 'flex-end';
3 | align?: 'center' | 'flex-start' | 'space-between' | 'flex-end' | 'stretch';
4 | direction?: 'row' | 'column';
5 | }
6 | export declare const Flex: import("styled-components").StyledComponent<"div", any, IFlexProps, never>;
7 |
--------------------------------------------------------------------------------
/packages/design-system/src/web/Grid/styles.tsx:
--------------------------------------------------------------------------------
1 | import styled from 'styled-components';
2 |
3 | import {
4 | border, color, flexbox, layout, position, space,
5 | } from 'styled-system';
6 |
7 | const Container = styled.div`
8 | ${border}
9 | ${color}
10 | ${flexbox}
11 | ${layout}
12 | ${position}
13 | ${space}
14 | `;
15 |
16 | export default Container;
17 |
--------------------------------------------------------------------------------
/packages/design-system/src/provider/index.tsx:
--------------------------------------------------------------------------------
1 | import React, { FunctionComponent } from 'react';
2 |
3 | import { ThemeProvider } from 'styled-components';
4 |
5 | import { theme } from '../theme';
6 |
7 | const ContainerTheme: FunctionComponent = ({ children }) => (
8 | {children}
9 | );
10 |
11 | export default ContainerTheme;
12 |
--------------------------------------------------------------------------------
/packages/design-system/src/web/Button/OutlinedButton/interface.ts:
--------------------------------------------------------------------------------
1 | import { TColorsTypes } from '../../../interfaces';
2 |
3 | export type TDefaultButtonProps = {
4 | text: string;
5 | onClick: () => void;
6 | borderColor: TColorsTypes;
7 | }
8 |
9 | export type TContainerStyleProps = {
10 | width: number;
11 | height: number;
12 | borderColor: TColorsTypes;
13 | }
14 |
--------------------------------------------------------------------------------
/packages/server/src/shared/base.controller.ts:
--------------------------------------------------------------------------------
1 | import * as jwt from 'jsonwebtoken';
2 |
3 | export class BaseController {
4 | protected getUserIdFromToken(authorization) {
5 | if (!authorization) return null;
6 |
7 | const token = authorization.split(' ')[1];
8 | const decoded: any = jwt.verify(token, process.env.SECRET);
9 | return decoded.id;
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature_request.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: ✨ Feature request
3 | about: Suggest an idea.
4 | labels: "enhancement"
5 | ---
6 |
7 | ## Describe the Feature
8 |
9 |
10 |
11 | ## Possible Implementations
12 |
13 |
14 |
15 | ## Related Issues
16 |
17 |
18 |
--------------------------------------------------------------------------------
/packages/design-system/lib-esm/theme/globalStyle.js:
--------------------------------------------------------------------------------
1 | import { createGlobalStyle } from 'styled-components';
2 | const GlobalStyle = createGlobalStyle `
3 | @import url("https://use.typekit.net/pqn7oor.css");
4 | * {
5 | padding: 0;
6 | margin: 0;
7 | box-sizing: border-box;
8 | font-family: proxima-nova, sans-serif;
9 | }
10 | `;
11 | export default GlobalStyle;
12 |
--------------------------------------------------------------------------------
/packages/design-system/src/interfaces/colors.ts:
--------------------------------------------------------------------------------
1 | export type TColors = {
2 | primary: string;
3 | secondary: string;
4 | primaryDark: string;
5 | secondaryDark: string;
6 | error: string;
7 | black: string;
8 | blackNormal: string;
9 | blackDark: string;
10 | blackLight: string;
11 | white: string;
12 | gray: string;
13 | }
14 |
15 | export type TColorsTypes = keyof TColors;
16 |
--------------------------------------------------------------------------------
/packages/design-system/src/theme/globalStyle.tsx:
--------------------------------------------------------------------------------
1 | import { createGlobalStyle } from 'styled-components';
2 |
3 | const GlobalStyle = createGlobalStyle`
4 | @import url("https://use.typekit.net/pqn7oor.css");
5 | * {
6 | padding: 0;
7 | margin: 0;
8 | box-sizing: border-box;
9 | font-family: proxima-nova, sans-serif;
10 | }
11 | `;
12 |
13 | export default GlobalStyle;
14 |
--------------------------------------------------------------------------------
/packages/design-system/lib/theme/index.d.ts:
--------------------------------------------------------------------------------
1 | import { DefaultTheme } from 'styled-components/native';
2 | import { TColors, TSpacingSizes, TBorderRadius } from '../interfaces';
3 | declare module 'styled-components' {
4 | interface DefaultTheme {
5 | colors: TColors;
6 | space: TSpacingSizes;
7 | radii: TBorderRadius;
8 | }
9 | }
10 | export declare const theme: DefaultTheme;
11 |
--------------------------------------------------------------------------------
/packages/web/public/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "short_name": "React App",
3 | "name": "Create React App Sample",
4 | "icons": [
5 | {
6 | "src": "favicon.ico",
7 | "sizes": "64x64 32x32 24x24 16x16",
8 | "type": "image/x-icon"
9 | }
10 | ],
11 | "start_url": "./index.html",
12 | "display": "standalone",
13 | "theme_color": "#000000",
14 | "background_color": "#ffffff"
15 | }
16 |
--------------------------------------------------------------------------------
/packages/design-system/src/theme/colors.ts:
--------------------------------------------------------------------------------
1 | const colors = {
2 | primary: '#43FECB',
3 | secondary: '#743AF2',
4 | primaryDark: '#6ffcd6',
5 | secondaryDark: '#9c73f5',
6 | error: '#FF3773',
7 | black: '#1F1F24',
8 | blackNormal: '#34353D',
9 | blackDark: '#27272D',
10 | blackLight: '#484854',
11 | white: '#FFFFFF',
12 | gray: '#cccccc',
13 | };
14 |
15 | export default {
16 | ...colors,
17 | };
18 |
--------------------------------------------------------------------------------
/packages/server/src/store/dto/link-employee.dto.ts:
--------------------------------------------------------------------------------
1 | import { InputType, Field, ID } from '@nestjs/graphql';
2 | import { IsNotEmpty, IsNumber } from 'class-validator';
3 |
4 | @InputType()
5 | export class LinkEmployeeToStoreDto {
6 | @Field()
7 | @IsNumber()
8 | @IsNotEmpty({ message: 'Field required ' })
9 | readonly storeId: string;
10 |
11 | @Field(() => [ID])
12 | readonly employeesId: string[];
13 | }
14 |
--------------------------------------------------------------------------------
/packages/web/src/store/index.ts:
--------------------------------------------------------------------------------
1 | import { createStore, applyMiddleware } from 'redux';
2 | import createSagaMiddleware from 'redux-saga';
3 |
4 | import reducers from './reducers';
5 | import sagas from './sagas';
6 |
7 | const sagaMiddleware = createSagaMiddleware();
8 |
9 | const store = createStore(reducers(), applyMiddleware(sagaMiddleware));
10 |
11 | sagaMiddleware.run(sagas);
12 |
13 | export default store;
14 |
--------------------------------------------------------------------------------
/packages/mobile/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | root: true,
3 | extends: ['@react-native-community', 'plugin:@typescript-eslint/recommended'],
4 | parser: '@typescript-eslint/parser',
5 | parserOptions: {
6 | ecmaVersion: 2018,
7 | sourceType: 'module',
8 | },
9 | plugins: ['@typescript-eslint'],
10 | "rules": {
11 | "@typescript-eslint/explicit-function-return-type": "off",
12 | }
13 | };
14 |
--------------------------------------------------------------------------------
/packages/server/src/store/dto/link-product.dto.ts:
--------------------------------------------------------------------------------
1 | import { InputType, Field, ID } from '@nestjs/graphql';
2 | import { IsNotEmpty, IsString } from 'class-validator';
3 |
4 | @InputType()
5 | export class LinkProductToStoreDto {
6 | @Field(() => ID)
7 | @IsString()
8 | @IsNotEmpty({ message: 'Field required ' })
9 | readonly storeId: string;
10 |
11 | @Field(() => [ID])
12 | readonly productsId: string[];
13 | }
14 |
--------------------------------------------------------------------------------
/packages/mobile/android/app/src/debug/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/packages/server/src/product/dto/link-attribute.dto.ts:
--------------------------------------------------------------------------------
1 | import { InputType, Field, ID } from '@nestjs/graphql';
2 | import { IsNotEmpty, IsString } from 'class-validator';
3 |
4 | @InputType()
5 | export class LinkAttributeToProductDto {
6 | @Field(() => ID)
7 | @IsString()
8 | @IsNotEmpty({ message: 'Field required ' })
9 | readonly productId: string;
10 |
11 | @Field(() => [ID])
12 | readonly attributesId: string[];
13 | }
14 |
--------------------------------------------------------------------------------
/packages/ssr/src/pages/index.tsx:
--------------------------------------------------------------------------------
1 | import { GetServerSideProps } from 'next';
2 |
3 | import { ROUTES } from '@config/routes';
4 |
5 | const Index = () => {
6 | return null;
7 | };
8 |
9 | export const getServerSideProps: GetServerSideProps = async (context) => {
10 | return {
11 | redirect: {
12 | destination: ROUTES.PRIVATE.ROOT(),
13 | permanent: false,
14 | },
15 | };
16 | };
17 |
18 | export default Index;
19 |
--------------------------------------------------------------------------------
/packages/design-system/lib-esm/Button/web/StyledButton.js:
--------------------------------------------------------------------------------
1 | import styled from 'styled-components';
2 | import theme from '../../theme';
3 | import DefaultButton from './DefaultButton';
4 | const StyledButton = styled(DefaultButton) `
5 | background-color: ${(props) => (props.secondary ? theme.colors.secondary : theme.colors.primary)};
6 | color: ${(props) => (props.secondary ? theme.colors.white : theme.colors.black)};
7 | `;
8 | export default StyledButton;
9 |
--------------------------------------------------------------------------------
/packages/design-system/lib-esm/Button/web/Button.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import StyledButton from './StyledButton';
3 | import OutlinedButton from './OutlinedButton';
4 | export const Button = ({ children, outline, full, secondary, }) => (React.createElement(React.Fragment, null, outline ? React.createElement(OutlinedButton, { full: full, secondary: secondary }, children) : React.createElement(StyledButton, { full: full, secondary: secondary }, children)));
5 |
--------------------------------------------------------------------------------
/packages/sdk/src/products/product.provider.ts:
--------------------------------------------------------------------------------
1 | import { http as httpClient } from '../utils/httpClient';
2 |
3 | import {
4 | TGetProducts,
5 | } from './product.interface';
6 | import { ENDPOINTS } from '../utils/routes.constants';
7 |
8 | export interface IProductProvider {
9 | getProducts: TGetProducts;
10 | }
11 |
12 | export const ProductProvider: IProductProvider = {
13 | getProducts: async () => httpClient.get(`${ENDPOINTS.PRODUCTS}`),
14 | };
15 |
--------------------------------------------------------------------------------
/packages/mobile/android/app/src/main/java/com/mobile/MainActivity.java:
--------------------------------------------------------------------------------
1 | package com.mobile;
2 |
3 | import com.facebook.react.ReactActivity;
4 |
5 | public class MainActivity extends ReactActivity {
6 |
7 | /**
8 | * Returns the name of the main component registered from JavaScript. This is used to schedule
9 | * rendering of the component.
10 | */
11 | @Override
12 | protected String getMainComponentName() {
13 | return "mobile";
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/packages/server/src/category/dto/create-category.dto.ts:
--------------------------------------------------------------------------------
1 | import { InputType, Field } from '@nestjs/graphql';
2 | import { IsNotEmpty, IsString } from 'class-validator';
3 |
4 | @InputType()
5 | export class CreateCategoryDto {
6 | @Field()
7 | @IsString()
8 | @IsNotEmpty({ message: 'Field required ' })
9 | readonly name: string;
10 |
11 | @Field()
12 | @IsString()
13 | @IsNotEmpty({ message: 'Field required ' })
14 | readonly description: string;
15 | }
16 |
--------------------------------------------------------------------------------
/packages/design-system/src/web/Button/OutlinedButton/index.tsx:
--------------------------------------------------------------------------------
1 | import React, { FunctionComponent } from 'react';
2 |
3 | import Container from './styles';
4 |
5 | import { TDefaultButtonProps } from './interface';
6 |
7 | const Button: FunctionComponent = ({ text, onClick, borderColor }) => (
8 |
9 | {text}
10 |
11 | );
12 |
13 | export default Button;
14 |
--------------------------------------------------------------------------------
/packages/server/src/user/user.module.ts:
--------------------------------------------------------------------------------
1 | import { Module } from '@nestjs/common';
2 | import { TypeOrmModule } from '@nestjs/typeorm';
3 |
4 | import { UserResolver } from '@user/user.resolver';
5 | import { User } from '@user/user.entity';
6 | import { UserService } from '@user/user.service';
7 |
8 | @Module({
9 | imports: [TypeOrmModule.forFeature([User])],
10 | providers: [UserService, UserResolver],
11 | exports: [UserService],
12 | })
13 | export class UserModule {}
14 |
--------------------------------------------------------------------------------
/packages/design-system/lib/utils/config/setupEnzyme.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | var __importDefault = (this && this.__importDefault) || function (mod) {
3 | return (mod && mod.__esModule) ? mod : { "default": mod };
4 | };
5 | exports.__esModule = true;
6 | var enzyme_1 = require("enzyme");
7 | var enzyme_adapter_react_16_1 = __importDefault(require("enzyme-adapter-react-16"));
8 | require("jest-enzyme");
9 | enzyme_1.configure({ adapter: new enzyme_adapter_react_16_1["default"]() });
10 |
--------------------------------------------------------------------------------
/packages/server/src/product/dto/link-category.dto.ts:
--------------------------------------------------------------------------------
1 | import { InputType, Field, ID } from '@nestjs/graphql';
2 | import { IsNotEmpty, IsString } from 'class-validator';
3 |
4 | @InputType()
5 | export class LinkCategoryToProductDto {
6 | @Field(() => ID)
7 | @IsString()
8 | @IsNotEmpty({ message: 'Field required ' })
9 | readonly productId: string;
10 |
11 | @Field(() => [ID])
12 | @IsNotEmpty({ message: 'Field required ' })
13 | readonly categoriesId: string[];
14 | }
15 |
--------------------------------------------------------------------------------
/packages/ssr/src/config/routes/index.ts:
--------------------------------------------------------------------------------
1 | import { Route, Routes } from './types';
2 |
3 | const mapParameters = (base: string): Route => {
4 | return (...args: string[]) => {
5 | return `/${base}${args.map((parameter) => `/${parameter}`)}`;
6 | };
7 | };
8 |
9 | export const ROUTES: Routes = {
10 | PUBLIC: {
11 | ROOT: mapParameters(`home`),
12 | SIGNIN: mapParameters(`sign-in`),
13 | },
14 | PRIVATE: {
15 | ROOT: mapParameters(`home`),
16 | },
17 | };
18 |
--------------------------------------------------------------------------------
/packages/mobile/src/index.tsx:
--------------------------------------------------------------------------------
1 | import React, { useEffect } from 'react';
2 |
3 | import { SafeAreaView, View, Text } from 'react-native';
4 |
5 | import { ProductProvider } from '@react-shop/sdk';
6 |
7 | const Routes = () => {
8 | useEffect(() => {
9 | ProductProvider.getProducts();
10 | }, []);
11 |
12 | return (
13 |
14 |
15 | Routes
16 |
17 |
18 | );
19 | };
20 |
21 | export default Routes;
22 |
--------------------------------------------------------------------------------
/packages/server/src/auth/auth.guard.ts:
--------------------------------------------------------------------------------
1 | import { Injectable, ExecutionContext } from '@nestjs/common';
2 | import { GqlExecutionContext } from '@nestjs/graphql';
3 | import { AuthGuard } from '@nestjs/passport';
4 | import { Request } from 'express';
5 |
6 | @Injectable()
7 | export class GqlAuthGuard extends AuthGuard('jwt') {
8 | getRequest(context: ExecutionContext): Request {
9 | const ctx = GqlExecutionContext.create(context);
10 |
11 | return ctx.getContext().req;
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/packages/design-system/src/web/Grid/index.tsx:
--------------------------------------------------------------------------------
1 | import React, { FunctionComponent } from 'react';
2 |
3 | import Container from './styles';
4 |
5 | import { TGridProps } from './interface';
6 |
7 | // import Skeleton from '../Skeleton';
8 |
9 | const Grid: FunctionComponent = ({
10 | children,
11 | skeleton,
12 | skeletonHeight,
13 | skeletonWidth,
14 | ...rest
15 | }) => (
16 |
17 | {children}
18 |
19 | );
20 |
21 | export default Grid;
22 |
--------------------------------------------------------------------------------
/packages/mobile/android/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in /usr/local/Cellar/android-sdk/24.3.3/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
--------------------------------------------------------------------------------
/packages/design-system/src/web/Button/story/Button.story.mdx:
--------------------------------------------------------------------------------
1 | import {Meta, Story, Preview} from '@storybook/addon-docs/blocks';
2 | import DefaultButton from '../DefaultButton';
3 |
4 |
5 |
6 | # Button
7 |
8 | With `MDX` we can define a story for `DefaultButton` right in the middle of our
9 | markdown documentation.
10 |
11 |
12 |
13 | 'clicked'} />
14 |
15 |
16 |
--------------------------------------------------------------------------------
/packages/design-system/src/web/Button/DefaultButton/styles.tsx:
--------------------------------------------------------------------------------
1 | import styled from 'styled-components';
2 | import { color, layout, border } from 'styled-system';
3 |
4 | import { TContainerStyleProps } from './interface';
5 |
6 | const Container = styled.button`
7 | ${color}
8 | ${layout}
9 | ${border}
10 |
11 | box-shadow: 0px 10px 12px rgba(0,0,0,0.2);
12 |
13 | &:hover {
14 | background-color: ${({ hoverColor, theme }) => theme.colors[hoverColor]}
15 | }
16 | `;
17 |
18 | export default Container;
19 |
--------------------------------------------------------------------------------
/packages/server/src/category/category.module.ts:
--------------------------------------------------------------------------------
1 | import { Module } from '@nestjs/common';
2 | import { TypeOrmModule } from '@nestjs/typeorm';
3 |
4 | import { Category } from '@category/category.entity';
5 | import { CategoryService } from '@category/category.service';
6 | import { CategoryResolver } from '@category/category.resolver';
7 |
8 | @Module({
9 | imports: [TypeOrmModule.forFeature([Category])],
10 | providers: [CategoryResolver, CategoryService],
11 | exports: [CategoryService],
12 | })
13 | export class CategoryModule {}
14 |
--------------------------------------------------------------------------------
/packages/web/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "include": ["src"],
3 | "extends": "../../tsconfig.base.json",
4 | "compilerOptions": {
5 | "target": "es5",
6 | "lib": ["dom", "dom.iterable", "esnext"],
7 | "allowJs": true,
8 | "skipLibCheck": true,
9 | "allowSyntheticDefaultImports": true,
10 | "strict": true,
11 | "forceConsistentCasingInFileNames": true,
12 | "module": "esnext",
13 | "moduleResolution": "node",
14 | "resolveJsonModule": true,
15 | "isolatedModules": true,
16 | "noEmit": true
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/packages/design-system/src/theme/units.ts:
--------------------------------------------------------------------------------
1 | const sizes = {
2 | spacing1: 1,
3 | spacing2: 2,
4 | spacing4: 4,
5 | spacing8: 8,
6 | spacing10: 10,
7 | spacing12: 12,
8 | spacing16: 16,
9 | spacing18: 18,
10 | spacing20: 20,
11 | spacing24: 24,
12 | spacing32: 32,
13 | };
14 |
15 | const borderRadius = {
16 | xsmall: sizes.spacing2,
17 | small: sizes.spacing4,
18 | medium: sizes.spacing8,
19 | large: sizes.spacing12,
20 | full: sizes.spacing32,
21 | };
22 |
23 | export default {
24 | sizes,
25 | borderRadius,
26 | };
27 |
--------------------------------------------------------------------------------
/packages/sdk/__tests__/products/products.spec.ts:
--------------------------------------------------------------------------------
1 | import { ProductProvider } from '../../src/products/product.provider';
2 | import { ProductsSchema } from '../../src/products/product.schema';
3 |
4 | describe('Integration | Test get product', () => {
5 | it('should be return all products', async () => {
6 | const { data } = await ProductProvider.getProducts();
7 |
8 | const isValidSchema = await ProductsSchema.isValid(data);
9 |
10 | expect(isValidSchema).toBe(true);
11 | expect(data.length).toBeGreaterThan(1);
12 | });
13 | });
14 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/ignore-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | node_modules
5 |
6 | # testing
7 | /coverage
8 |
9 | # production
10 | /build
11 |
12 | # misc
13 | .DS_Store
14 | .env.local
15 | .env.development.local
16 | .env.test.local
17 | .env.production.local
18 |
19 | npm-debug.log*
20 | yarn-debug.log*
21 | yarn-error.log*
22 |
23 | # IDE
24 | .idea/
25 |
26 | packages/**/lib
27 | packages/**/lib-esm
28 |
29 |
30 | # next.js
31 | packages/ssr/out
32 | packages/ssr/.next
33 | packages/ssr/.vercel
--------------------------------------------------------------------------------
/packages/server/src/attribute/attribute.module.ts:
--------------------------------------------------------------------------------
1 | import { Module } from '@nestjs/common';
2 | import { TypeOrmModule } from '@nestjs/typeorm';
3 |
4 | import { Attribute } from '@attribute/attribute.entity';
5 | import { AttributeService } from '@attribute/attribute.service';
6 | import { AttributeResolver } from '@attribute/attribute.resolver';
7 |
8 | @Module({
9 | imports: [TypeOrmModule.forFeature([Attribute])],
10 | providers: [AttributeService, AttributeResolver],
11 | exports: [AttributeService],
12 | })
13 | export class AttributeModule {}
14 |
--------------------------------------------------------------------------------
/packages/design-system/src/web/Button/OutlinedButton/styles.tsx:
--------------------------------------------------------------------------------
1 | import styled from 'styled-components';
2 | import { color, layout, border } from 'styled-system';
3 |
4 | import { TContainerStyleProps } from './interface';
5 |
6 | const Container = styled.button`
7 | ${color}
8 | ${layout}
9 | ${border}
10 |
11 | box-shadow: 0px 10px 12px rgba(0,0,0,0.2);
12 | background-color: transparent;
13 |
14 | &:hover {
15 | background-color: ${({ theme }) => theme.colors.primaryDark}
16 | }
17 | `;
18 |
19 | export default Container;
20 |
--------------------------------------------------------------------------------
/packages/ssr/next.config.js:
--------------------------------------------------------------------------------
1 | const path = require('path');
2 |
3 | module.exports = {
4 | webpack: (config, options) => {
5 | const configExternals = ['styled-components', 'react', 'react-dom'];
6 | if (options.isServer) {
7 | config.externals = [...configExternals, ...config.externals];
8 | }
9 |
10 | configExternals.forEach((configExternal) => {
11 | config.resolve.alias[configExternal] = path.resolve(
12 | __dirname,
13 | '.',
14 | 'node_modules',
15 | configExternal,
16 | );
17 | });
18 |
19 | return config;
20 | },
21 | };
--------------------------------------------------------------------------------
/packages/mobile/metro.config.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Metro configuration for React Native
3 | * https://github.com/facebook/react-native
4 | *
5 | * @format
6 | */
7 |
8 | const path = require('path');
9 |
10 | module.exports = {
11 | projectRoot: path.resolve(__dirname, '.'),
12 |
13 | watchFolders: [
14 | path.resolve(__dirname, '../'),
15 | path.resolve(__dirname, '../../node_modules'),
16 | ],
17 | transformer: {
18 | getTransformOptions: async () => ({
19 | transform: {
20 | experimentalImportSupport: false,
21 | inlineRequires: false,
22 | },
23 | }),
24 | },
25 | };
26 |
--------------------------------------------------------------------------------
/packages/server/.gitignore:
--------------------------------------------------------------------------------
1 | # compiled output
2 | /dist
3 | /node_modules
4 |
5 | # Logs
6 | logs
7 | *.log
8 | npm-debug.log*
9 | pnpm-debug.log*
10 | yarn-debug.log*
11 | yarn-error.log*
12 | lerna-debug.log*
13 |
14 | # OS
15 | .DS_Store
16 |
17 | # Tests
18 | /coverage
19 | /.nyc_output
20 |
21 | # IDEs and editors
22 | /.idea
23 | .project
24 | .classpath
25 | .c9/
26 | *.launch
27 | .settings/
28 | *.sublime-workspace
29 |
30 | # IDE - VSCode
31 | .vscode/*
32 | !.vscode/settings.json
33 | !.vscode/tasks.json
34 | !.vscode/launch.json
35 | !.vscode/extensions.json
36 |
37 | .env.development
38 | .env.production
39 | .env
--------------------------------------------------------------------------------
/packages/design-system/src/interfaces/align.ts:
--------------------------------------------------------------------------------
1 | export type TAligns = 'flex-start' | 'center' | 'flex-end';
2 |
3 | export type TAlignItems = TAligns | 'stretch' | 'baseline';
4 |
5 | export type TJustifyContent =
6 | | TAligns
7 | | 'space-between'
8 | | 'space-around'
9 | | 'space-evenly';
10 |
11 | export type TFlexDirection = 'row' | 'column' | 'row-reverse' | 'column-reverse';
12 |
13 | export type TAlignContent = TAligns | 'space-between' | 'space-around';
14 |
15 | export type TFlexWrap = 'nowrap' | 'wrap';
16 |
17 | export type TPosition = 'relative' | 'absolute';
18 |
19 | export type TSizes = 'auto' | string;
20 |
--------------------------------------------------------------------------------
/packages/web/src/root/index.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { Provider } from 'react-redux';
3 | import { BrowserRouter as Router, Route, Switch } from 'react-router-dom';
4 |
5 | import { GlobalStyles } from '@react-shop/design-system';
6 |
7 | import store from '../store';
8 |
9 | import Home from '../modules/views/home';
10 |
11 | const Root = () => (
12 |
13 |
14 |
15 | <>
16 |
17 |
18 |
19 | >
20 |
21 |
22 | );
23 |
24 | export default Root;
25 |
--------------------------------------------------------------------------------
/packages/sdk/lib/products/product.schema.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | var __importStar = (this && this.__importStar) || function (mod) {
3 | if (mod && mod.__esModule) return mod;
4 | var result = {};
5 | if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
6 | result["default"] = mod;
7 | return result;
8 | };
9 | exports.__esModule = true;
10 | var Yup = __importStar(require("yup"));
11 | exports.ProductsSchema = Yup.array().of(Yup.object().shape({
12 | id: Yup.string(),
13 | name: Yup.string()
14 | }));
15 | exports.ProductSchema = Yup.object().shape({
16 | name: Yup.string().required()
17 | });
18 |
--------------------------------------------------------------------------------
/packages/server/src/attribute/dto/create-attribute.dto.ts:
--------------------------------------------------------------------------------
1 | import { Types } from '@attribute/attribute.interface';
2 | import { InputType, Field } from '@nestjs/graphql';
3 | import { IsNotEmpty, IsString, IsEnum } from 'class-validator';
4 |
5 | @InputType()
6 | export class CreateAttributeDto {
7 | @Field()
8 | @IsString()
9 | @IsNotEmpty({ message: 'Field required ' })
10 | readonly value: string;
11 |
12 | @Field()
13 | @IsString()
14 | @IsNotEmpty({ message: 'Field required ' })
15 | readonly name: string;
16 |
17 | @Field(() => Types)
18 | @IsEnum(Types)
19 | @IsNotEmpty({ message: 'Field required ' })
20 | readonly type: Types;
21 | }
22 |
--------------------------------------------------------------------------------
/packages/design-system/lib-esm/Button/web/DefaultButton.js:
--------------------------------------------------------------------------------
1 | import styled from 'styled-components';
2 | import theme from '../../theme';
3 | const DefaultButton = styled.button `
4 | padding: 15px 55px;
5 | border: none;
6 | border-radius: 6px;
7 | width: ${(props) => (props.full ? '100%' : 'auto')};
8 | text-align: center;
9 | font-family: proxima-nova, sans-serif;
10 | font-size: ${theme.fonts.sizes.body};
11 | cursor: pointer;
12 |
13 | &:hover {
14 | box-shadow: ${(props) => (props.secondary ? 'none' : '0px 11px 16px rgba(40, 245, 190, 0.2)')};
15 | opacity: ${(props) => (props.secondary ? 0.8 : 1)}
16 | }
17 | `;
18 | export default DefaultButton;
19 |
--------------------------------------------------------------------------------
/packages/server/src/auth/auth.resolver.ts:
--------------------------------------------------------------------------------
1 | import { Args, Mutation, Resolver } from '@nestjs/graphql';
2 |
3 | import { AuthDto } from '@auth/dto/auth.input';
4 | import { AuthType } from '@auth/dto/auth.interface';
5 | import { AuthService } from '@auth/auth.service';
6 |
7 | @Resolver('Auth')
8 | export class AuthResolver {
9 | constructor(private authService: AuthService) {}
10 |
11 | @Mutation(() => AuthType)
12 | public async login(@Args('data') data: AuthDto): Promise {
13 | const response = await this.authService.validateUser(data);
14 |
15 | return {
16 | user: response.user,
17 | token: response.token,
18 | };
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/packages/mobile/android/app/build_defs.bzl:
--------------------------------------------------------------------------------
1 | """Helper definitions to glob .aar and .jar targets"""
2 |
3 | def create_aar_targets(aarfiles):
4 | for aarfile in aarfiles:
5 | name = "aars__" + aarfile[aarfile.rindex("/") + 1:aarfile.rindex(".aar")]
6 | lib_deps.append(":" + name)
7 | android_prebuilt_aar(
8 | name = name,
9 | aar = aarfile,
10 | )
11 |
12 | def create_jar_targets(jarfiles):
13 | for jarfile in jarfiles:
14 | name = "jars__" + jarfile[jarfile.rindex("/") + 1:jarfile.rindex(".jar")]
15 | lib_deps.append(":" + name)
16 | prebuilt_jar(
17 | name = name,
18 | binary_jar = jarfile,
19 | )
20 |
--------------------------------------------------------------------------------
/packages/design-system/lib/web/Button/Button.d.ts:
--------------------------------------------------------------------------------
1 | import { FunctionComponent, MouseEvent, ReactNode } from 'react';
2 | declare type Props = {
3 | /**
4 | * Component to be rendered
5 | */
6 | children: ReactNode;
7 | /**
8 | * Set this if you want a transparent bg button
9 | */
10 | outline?: boolean;
11 | /**
12 | * Full width button
13 | */
14 | full?: boolean;
15 | /**
16 | * Button variant
17 | */
18 | secondary?: boolean;
19 | /**
20 | * onClick event, that inherits the onClick from React Event
21 | */
22 | onClick: (e: MouseEvent) => void;
23 | };
24 | declare const Button: FunctionComponent;
25 | export default Button;
26 |
--------------------------------------------------------------------------------
/packages/design-system/src/theme/index.ts:
--------------------------------------------------------------------------------
1 | import { DefaultTheme } from 'styled-components/native';
2 |
3 | import colors from './colors';
4 | import units from './units';
5 |
6 | import {
7 | TColors,
8 | TSpacingSizes,
9 | TBorderRadius,
10 | } from '../interfaces';
11 |
12 | declare module 'styled-components' {
13 | // eslint-disable-next-line @typescript-eslint/interface-name-prefix
14 | export interface DefaultTheme {
15 | colors: TColors;
16 | space: TSpacingSizes;
17 | radii: TBorderRadius;
18 | }
19 | }
20 |
21 | export const theme: DefaultTheme = {
22 | colors: {
23 | ...colors,
24 | },
25 | space: {
26 | ...units.sizes,
27 | },
28 | radii: {
29 | ...units.borderRadius,
30 | },
31 | };
32 |
--------------------------------------------------------------------------------
/packages/server/docker-compose.yml:
--------------------------------------------------------------------------------
1 | # Use postgres/example user/password credentials
2 | version: '3.1'
3 |
4 | services:
5 | db:
6 | container_name: pg_database
7 | image: postgres
8 | restart: always
9 | ports:
10 | - '${DATABASE_PORT}:${DATABASE_PORT}'
11 | hostname: '${DATABASE_HOST}'
12 | environment:
13 | POSTGRES_USER: '${DATABASE_USER}'
14 | POSTGRES_PASSWORD: '${DATABASE_PASSWORD}'
15 | POSTGRES_DB: '${DATABASE_NAME}'
16 | pgadmin:
17 | container_name: pgadmin4_container
18 | image: dpage/pgadmin4
19 | restart: always
20 | environment:
21 | PGADMIN_DEFAULT_EMAIL: admin@admin.com
22 | PGADMIN_DEFAULT_PASSWORD: root
23 | ports:
24 | - "5050:80"
25 |
--------------------------------------------------------------------------------
/packages/server/src/store/store.module.ts:
--------------------------------------------------------------------------------
1 | import { Module } from '@nestjs/common';
2 | import { TypeOrmModule } from '@nestjs/typeorm';
3 |
4 | import { Store } from '@store/store.entity';
5 | import { StoreService } from '@store/store.service';
6 | import { StoreResolver } from '@store/store.resolver';
7 | import { User } from '@user/user.entity';
8 | import { Product } from '@product/product.entity';
9 | import { Helpers } from '@utils/helpers';
10 |
11 | @Module({
12 | imports: [
13 | TypeOrmModule.forFeature([Store]),
14 | TypeOrmModule.forFeature([User]),
15 | TypeOrmModule.forFeature([Product]),
16 | ],
17 | providers: [StoreService, StoreResolver, Helpers],
18 | exports: [StoreService],
19 | })
20 | export class StoreModule {}
21 |
--------------------------------------------------------------------------------
/packages/web/src/modules/views/home/index.tsx:
--------------------------------------------------------------------------------
1 | import React, { useEffect, useState } from 'react';
2 | import { Button, Container } from '@react-shop/design-system';
3 | import { ProductProvider } from '@react-shop/sdk';
4 |
5 | const Home = () => {
6 | const fetchProducts = async () => {
7 | const response = await ProductProvider.getProducts();
8 |
9 | console.log('response', response);
10 | };
11 |
12 | useEffect(() => {
13 | fetchProducts();
14 | }, []);
15 |
16 | const [text, setText] = useState('My Button');
17 |
18 | return (
19 |
20 |
23 |
24 | );
25 | };
26 |
27 | export default Home;
28 |
--------------------------------------------------------------------------------
/packages/mobile/ios/Podfile:
--------------------------------------------------------------------------------
1 | require_relative '../../../node_modules/react-native/scripts/react_native_pods'
2 | require_relative '../../../node_modules/@react-native-community/cli-platform-ios/native_modules'
3 |
4 | platform :ios, '10.0'
5 |
6 | target 'mobile' do
7 | config = use_native_modules!
8 |
9 | use_react_native!(:path => '../../../node_modules/react-native')
10 |
11 | target 'mobileTests' do
12 | inherit! :complete
13 | # Pods for testing
14 | end
15 |
16 | # Enables Flipper.
17 | #
18 | # Note that if you have use_frameworks! enabled, Flipper will not work and
19 | # you should disable these next few lines.
20 | use_flipper!
21 | post_install do |installer|
22 | flipper_post_install(installer)
23 | end
24 | end
25 |
--------------------------------------------------------------------------------
/packages/server/test/app.e2e-spec.ts:
--------------------------------------------------------------------------------
1 | import { Test, TestingModule } from '@nestjs/testing';
2 | import { INestApplication } from '@nestjs/common';
3 | import * as request from 'supertest';
4 | import { AppModule } from '../src/app.module';
5 |
6 | describe('AppController (e2e)', () => {
7 | let app: INestApplication;
8 |
9 | beforeEach(async () => {
10 | const moduleFixture: TestingModule = await Test.createTestingModule({
11 | imports: [AppModule],
12 | }).compile();
13 |
14 | app = moduleFixture.createNestApplication();
15 | await app.init();
16 | });
17 |
18 | it('/ (GET)', () => {
19 | return request(app.getHttpServer())
20 | .get('/')
21 | .expect(200)
22 | .expect('Hello World!');
23 | });
24 | });
25 |
--------------------------------------------------------------------------------
/packages/design-system/lib-esm/Button/web/OutlinedButton.js:
--------------------------------------------------------------------------------
1 | import styled from 'styled-components';
2 | import theme from '../../theme';
3 | import DefaultButton from './DefaultButton';
4 | const OutlinedButton = styled(DefaultButton) `
5 | border: 1px solid ${(props) => (props.secondary ? theme.colors.secondary : theme.colors.primary)};
6 | color: ${(props) => (props.secondary ? theme.colors.secondary : theme.colors.primary)};
7 | font-weight: ${theme.fonts.weight.semiBold};
8 | background-color: transparent;
9 |
10 | &:hover {
11 | background-color: ${(props) => (props.secondary ? theme.colors.secondary : theme.colors.primary)};
12 | color: ${(props) => (props.secondary ? theme.colors.white : theme.colors.black)};
13 | }
14 | `;
15 | export default OutlinedButton;
16 |
--------------------------------------------------------------------------------
/packages/ssr/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "ES2020",
4 | "lib": ["dom", "dom.iterable", "esnext", "ES2020"],
5 | "allowJs": true,
6 | "skipLibCheck": true,
7 | "strict": true,
8 | "forceConsistentCasingInFileNames": true,
9 | "noEmit": true,
10 | "esModuleInterop": true,
11 | "module": "esnext",
12 | "moduleResolution": "node",
13 | "resolveJsonModule": true,
14 | "isolatedModules": true,
15 | "jsx": "preserve",
16 | "baseUrl": "./src",
17 | "paths": {
18 | "@pages/*": ["./pages/*"],
19 | "@home/*": ["./modules/home/*"],
20 | "@config/*": ["./config/*"]
21 | }
22 | },
23 | "exclude": ["node_modules"],
24 | "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", "src/*"]
25 | }
26 |
--------------------------------------------------------------------------------
/packages/server/src/product/product.module.ts:
--------------------------------------------------------------------------------
1 | import { Module } from '@nestjs/common';
2 | import { TypeOrmModule } from '@nestjs/typeorm';
3 |
4 | import { Product } from '@product/product.entity';
5 | import { ProductResolver } from '@product/product.resolver';
6 | import { ProductService } from '@product/product.service';
7 |
8 | import { Attribute } from '@attribute/attribute.entity';
9 | import { Category } from '@category/category.entity';
10 |
11 | import { Helpers } from '@utils/helpers';
12 |
13 | @Module({
14 | imports: [
15 | TypeOrmModule.forFeature([Product]),
16 | TypeOrmModule.forFeature([Attribute]),
17 | TypeOrmModule.forFeature([Category]),
18 | ],
19 | providers: [ProductResolver, ProductService, Helpers],
20 | exports: [ProductService],
21 | })
22 | export class ProductModule {}
23 |
--------------------------------------------------------------------------------
/packages/server/src/user/user.decorator.ts:
--------------------------------------------------------------------------------
1 | import { createParamDecorator, ExecutionContext } from '@nestjs/common';
2 | import jwt from 'jsonwebtoken';
3 |
4 | export const User = createParamDecorator((data: any, ctx: ExecutionContext) => {
5 | const req = ctx.switchToHttp().getRequest();
6 | // if route is protected, there is a user set in auth.middleware
7 | if (!!req.user) {
8 | return !!data ? req.user[data] : req.user;
9 | }
10 |
11 | // in case a route is not protected, we still want to get the optional auth user from jwt
12 | const token = req.headers.authorization ? (req.headers.authorization as string).split(' ') : null;
13 | if (token && token[1]) {
14 | const decoded: any = jwt.verify(token[1], process.env.SECRET);
15 | return !!data ? decoded[data] : decoded.user;
16 | }
17 | });
18 |
--------------------------------------------------------------------------------
/packages/ssr/tests/snapshotResolver.ts:
--------------------------------------------------------------------------------
1 | const replacePath = (path: string, oldContent: string, newContent: string) => {
2 | const position = path.lastIndexOf(oldContent);
3 | return path.slice(0, position) + path.slice(position).replace(oldContent, newContent);
4 | };
5 |
6 | module.exports = {
7 | resolveSnapshotPath: (testPath: string, snapshotExtension: string) => {
8 | return replacePath(testPath, `src/`, `tests/__snapshots__/`) + snapshotExtension;
9 | },
10 | resolveTestPath: (snapshotFilePath: string, snapshotExtension: string) => {
11 | return replacePath(snapshotFilePath, `tests/__snapshots__/`, `src/`).slice(
12 | 0,
13 | -snapshotExtension.length,
14 | );
15 | },
16 | testPathForConsistencyCheck: `folder/tests.tsx`,
17 | };
18 |
19 | export {};
--------------------------------------------------------------------------------
/packages/mobile/ios/mobile/Images.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "iphone",
5 | "size" : "29x29",
6 | "scale" : "2x"
7 | },
8 | {
9 | "idiom" : "iphone",
10 | "size" : "29x29",
11 | "scale" : "3x"
12 | },
13 | {
14 | "idiom" : "iphone",
15 | "size" : "40x40",
16 | "scale" : "2x"
17 | },
18 | {
19 | "idiom" : "iphone",
20 | "size" : "40x40",
21 | "scale" : "3x"
22 | },
23 | {
24 | "idiom" : "iphone",
25 | "size" : "60x60",
26 | "scale" : "2x"
27 | },
28 | {
29 | "idiom" : "iphone",
30 | "size" : "60x60",
31 | "scale" : "3x"
32 | }
33 | ],
34 | "info" : {
35 | "version" : 1,
36 | "author" : "xcode"
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/packages/server/src/user/user.interface.ts:
--------------------------------------------------------------------------------
1 | import { registerEnumType } from '@nestjs/graphql';
2 |
3 | export enum Roles {
4 | MEMBER = 'member',
5 | ADMIN = 'admin',
6 | SELLER = 'seller',
7 | }
8 |
9 | registerEnumType(Roles, {
10 | name: 'Roles',
11 | description: 'User possible roles',
12 | });
13 |
14 | export enum Status {
15 | ACTIVE = 'active',
16 | DISABLED = 'disabled',
17 | }
18 |
19 | registerEnumType(Status, {
20 | name: 'Status',
21 | description: 'Account status',
22 | });
23 |
24 | export interface UserData {
25 | id: string;
26 | name: string;
27 | username: string;
28 | email: string;
29 | bio: string;
30 | image: string;
31 | role: Roles;
32 | status: Status;
33 | password: string;
34 | token?: string;
35 | }
36 |
37 | export interface UserModel {
38 | user: UserData;
39 | }
40 |
--------------------------------------------------------------------------------
/packages/server/src/category/category.entity.ts:
--------------------------------------------------------------------------------
1 | import { Field, InputType, ObjectType, ID } from '@nestjs/graphql';
2 | import { IsString } from 'class-validator';
3 | import { Entity, PrimaryGeneratedColumn, Column, ManyToOne } from 'typeorm';
4 |
5 | import { Product } from '@product/product.entity';
6 |
7 | @ObjectType()
8 | @InputType('CategoryInput')
9 | @Entity()
10 | export class Category {
11 | @PrimaryGeneratedColumn('increment')
12 | @Field(() => ID)
13 | id: string;
14 |
15 | @Column()
16 | @IsString()
17 | @Field()
18 | name: string;
19 |
20 | @Column()
21 | @IsString()
22 | @Field()
23 | description: string;
24 |
25 | @ManyToOne(
26 | () => Product,
27 | product => product.categories,
28 | )
29 | @Field(() => [Product], {
30 | nullable: true,
31 | })
32 | products: Product[];
33 | }
34 |
--------------------------------------------------------------------------------
/packages/design-system/jest.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | roots: ['/src'],
3 | transform: {
4 | '^.+\\.(ts|tsx)$': 'ts-jest',
5 | },
6 | testRegex: '(/__tests__/.*|(\\.|/)(test|spec))\\.tsx?$',
7 | moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node'],
8 | testEnvironment: 'jsdom',
9 | globals: {
10 | 'ts-jest': {
11 | diagnostics: {
12 | warnOnly: true,
13 | },
14 | },
15 | },
16 | testPathIgnorePatterns: [
17 | '/__tests__/helpers',
18 | ],
19 | collectCoverageFrom: [
20 | '/src/**/*.tsx',
21 | ],
22 |
23 | // Setup Enzyme
24 | snapshotSerializers: ['enzyme-to-json/serializer'],
25 | setupFilesAfterEnv: ['/src/utils/config/setupEnzyme.ts'],
26 | coveragePathIgnorePatterns: [
27 | '/node_modules',
28 | ],
29 | };
30 |
--------------------------------------------------------------------------------
/packages/design-system/src/web/Button/story/OutlinedButton.story.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { storiesOf } from '@storybook/react';
3 | import { withKnobs, text } from '@storybook/addon-knobs';
4 |
5 | import OutlinedButton from '../OutlinedButton';
6 | import { Grid } from '../..';
7 |
8 | const buttonText = text('Name', 'Buy');
9 |
10 | const stories = storiesOf('Button', module);
11 |
12 | stories
13 | .addParameters({
14 | component: OutlinedButton,
15 | })
16 | .addDecorator(withKnobs)
17 | .add('Outlined Button', () => (
18 |
19 | console.log('Hey, you jest clicked me!')}
23 | />
24 |
25 | ));
26 |
--------------------------------------------------------------------------------
/packages/server/src/auth/auth.module.ts:
--------------------------------------------------------------------------------
1 | import { Module } from '@nestjs/common';
2 | import { JwtModule } from '@nestjs/jwt';
3 | import { TypeOrmModule } from '@nestjs/typeorm';
4 |
5 | import { AuthService } from '@auth/auth.service';
6 | import { AuthResolver } from '@auth/auth.resolver';
7 | import { JwtStrategy } from '@auth/jwt.strategy';
8 |
9 | import { UserService } from '@user/user.service';
10 | import { User } from '@user/user.entity';
11 |
12 | @Module({
13 | imports: [
14 | TypeOrmModule.forFeature([User]),
15 | JwtModule.registerAsync({
16 | useFactory: () => ({
17 | secret: process.env.SECRET,
18 | signOptions: {
19 | expiresIn: '60m',
20 | },
21 | }),
22 | }),
23 | ],
24 | providers: [AuthService, AuthResolver, UserService, JwtStrategy],
25 | })
26 | export class AuthModule {}
27 |
--------------------------------------------------------------------------------
/packages/mobile/ios/mobileTests/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | BNDL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1
23 |
24 |
25 |
--------------------------------------------------------------------------------
/packages/design-system/src/web/Button/DefaultButton/interface.ts:
--------------------------------------------------------------------------------
1 | import { TColorsTypes } from '../../../interfaces';
2 |
3 | export type TButtonVariants = 'primary' | 'secondary'
4 |
5 | export type TDefaultButtonProps = {
6 | testID?: string;
7 | text: string;
8 | onClick: () => void;
9 | variant: TButtonVariants;
10 | disabled?: boolean;
11 | }
12 |
13 | export type TContainerStyleProps = {
14 | testID?: string;
15 | width: number;
16 | height: number;
17 | bg: TColorsTypes;
18 | hoverColor: TColorsTypes;
19 | border: string;
20 | }
21 |
22 | export type TGetVariants = {
23 | primary: {
24 | bg: TColorsTypes;
25 | hoverColor: TColorsTypes;
26 | };
27 | secondary: {
28 | bg: TColorsTypes;
29 | hoverColor: TColorsTypes;
30 | };
31 | disabled: {
32 | bg: TColorsTypes;
33 | hoverColor: TColorsTypes;
34 | };
35 | }
36 |
--------------------------------------------------------------------------------
/packages/design-system/.storybook/config.js:
--------------------------------------------------------------------------------
1 | import {configure, addParameters, addDecorator} from '@storybook/react';
2 | import {themes} from '@storybook/theming';
3 | import {withA11y} from '@storybook/addon-a11y';
4 | import { withKnobs } from '@storybook/addon-knobs';
5 | import '@storybook/addon-console';
6 |
7 | import {DocsPage, DocsContainer} from '@storybook/addon-docs/blocks';
8 |
9 | import themeDecorator from "./themeDecorator"
10 |
11 | const req = require.context('../src', true, /\.story\.(ts|tsx|mdx)$/);
12 |
13 | addParameters({
14 | options: {
15 | theme: themes.dark,
16 | },
17 | docs: {
18 | container: DocsContainer,
19 | page: DocsPage,
20 | },
21 | });
22 |
23 | addDecorator(withKnobs);
24 | addDecorator(withA11y);
25 | addDecorator(themeDecorator);
26 |
27 | configure(() => {
28 | req.keys().forEach(filename => req(filename));
29 | }, module);
30 |
--------------------------------------------------------------------------------
/packages/design-system/lib/Button/web/Button.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | var __importDefault = (this && this.__importDefault) || function (mod) {
3 | return (mod && mod.__esModule) ? mod : { "default": mod };
4 | };
5 | exports.__esModule = true;
6 | var react_1 = __importDefault(require("react"));
7 | var StyledButton_1 = __importDefault(require("./StyledButton"));
8 | var OutlinedButton_1 = __importDefault(require("./OutlinedButton"));
9 | exports.Button = function (_a) {
10 | var children = _a.children, outline = _a.outline, full = _a.full, secondary = _a.secondary;
11 | return (react_1["default"].createElement(react_1["default"].Fragment, null, outline ? react_1["default"].createElement(OutlinedButton_1["default"], { full: full, secondary: secondary }, children) : react_1["default"].createElement(StyledButton_1["default"], { full: full, secondary: secondary }, children)));
12 | };
13 |
--------------------------------------------------------------------------------
/packages/mobile/ios/mobile-tvOSTests/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | BNDL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1
23 |
24 |
25 |
--------------------------------------------------------------------------------
/packages/design-system/lib/Grid/web/Container.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | var __makeTemplateObject = (this && this.__makeTemplateObject) || function (cooked, raw) {
3 | if (Object.defineProperty) { Object.defineProperty(cooked, "raw", { value: raw }); } else { cooked.raw = raw; }
4 | return cooked;
5 | };
6 | var __importDefault = (this && this.__importDefault) || function (mod) {
7 | return (mod && mod.__esModule) ? mod : { "default": mod };
8 | };
9 | exports.__esModule = true;
10 | var styled_components_1 = __importDefault(require("styled-components"));
11 | exports.Container = styled_components_1["default"].div(templateObject_1 || (templateObject_1 = __makeTemplateObject(["\n width: 100%;\n height: 100%;\n display: flex;\n justify-content: center;\n align-items: center;\n"], ["\n width: 100%;\n height: 100%;\n display: flex;\n justify-content: center;\n align-items: center;\n"])));
12 | var templateObject_1;
13 |
--------------------------------------------------------------------------------
/packages/design-system/lib/web/Grid/Container.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | var __makeTemplateObject = (this && this.__makeTemplateObject) || function (cooked, raw) {
3 | if (Object.defineProperty) { Object.defineProperty(cooked, "raw", { value: raw }); } else { cooked.raw = raw; }
4 | return cooked;
5 | };
6 | var __importDefault = (this && this.__importDefault) || function (mod) {
7 | return (mod && mod.__esModule) ? mod : { "default": mod };
8 | };
9 | exports.__esModule = true;
10 | var styled_components_1 = __importDefault(require("styled-components"));
11 | exports.Container = styled_components_1["default"].div(templateObject_1 || (templateObject_1 = __makeTemplateObject(["\n width: 100%;\n height: 100%;\n display: flex;\n justify-content: center;\n align-items: center;\n"], ["\n width: 100%;\n height: 100%;\n display: flex;\n justify-content: center;\n align-items: center;\n"])));
12 | var templateObject_1;
13 |
--------------------------------------------------------------------------------
/packages/server/src/attribute/attribute.entity.ts:
--------------------------------------------------------------------------------
1 | import { Entity, PrimaryGeneratedColumn, Column, ManyToOne } from 'typeorm';
2 | import { Field, ObjectType, ID, InputType } from '@nestjs/graphql';
3 |
4 | import { Product } from '@product/product.entity';
5 |
6 | import { Types } from '@attribute/attribute.interface';
7 |
8 | @ObjectType()
9 | @InputType('AttributeInput')
10 | @Entity()
11 | export class Attribute {
12 | @PrimaryGeneratedColumn('increment')
13 | @Field(() => ID)
14 | id: string;
15 |
16 | @Column({
17 | type: 'enum',
18 | enum: Types,
19 | nullable: true,
20 | })
21 | @Field(() => Types)
22 | type: Types;
23 |
24 | @Column()
25 | value: string;
26 |
27 | @Column()
28 | name: string;
29 |
30 | @ManyToOne(
31 | () => Product,
32 | product => product.attributes,
33 | )
34 | @Field(() => Product, {
35 | nullable: true,
36 | })
37 | product: Product;
38 | }
39 |
--------------------------------------------------------------------------------
/packages/server/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "module": "commonjs",
4 | "declaration": true,
5 | "removeComments": true,
6 | "emitDecoratorMetadata": true,
7 | "experimentalDecorators": true,
8 | "allowSyntheticDefaultImports": true,
9 | "target": "es2017",
10 | "sourceMap": true,
11 | "outDir": "./dist",
12 | "incremental": true,
13 | "skipLibCheck": true,
14 | "baseUrl": "./src",
15 | "paths": {
16 | "@user/*": ["./user/*"],
17 | "@auth/*": ["./auth/*"],
18 | "@shared/*": ["./shared/*"],
19 | "@graphql/*": ["./graphql/*"],
20 | "@product/*": ["./product/*"],
21 | "@store/*": ["./store/*"],
22 | "@utils/*": ["./utils/*"],
23 | "@attribute/*": ["./attribute/*"],
24 | "@category/*": ["./category/*"]
25 | }
26 | },
27 | "exclude": ["node_modules"],
28 | "include": ["**/*.ts", "**/*.tsx", "src/*"]
29 | }
30 |
--------------------------------------------------------------------------------
/packages/server/src/auth/jwt.strategy.ts:
--------------------------------------------------------------------------------
1 | import { Injectable, UnauthorizedException } from '@nestjs/common';
2 | import { PassportStrategy } from '@nestjs/passport';
3 | import { ExtractJwt, Strategy } from 'passport-jwt';
4 |
5 | import { UserService } from '@user/user.service';
6 | import { User } from '@user/user.entity';
7 |
8 | @Injectable()
9 | export class JwtStrategy extends PassportStrategy(Strategy) {
10 | constructor(private userService: UserService) {
11 | super({
12 | jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
13 | ignoreExpiration: false,
14 | secretOrKey: process.env.SECRET,
15 | });
16 | }
17 |
18 | async validate(payload: { sub: User['id']; username: User['username'] }) {
19 | const user = this.userService.findById(payload.sub);
20 |
21 | if (!user) {
22 | throw new UnauthorizedException('Unauthorized');
23 | }
24 |
25 | return user;
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/packages/design-system/lib/theme/globalStyle.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | var __makeTemplateObject = (this && this.__makeTemplateObject) || function (cooked, raw) {
3 | if (Object.defineProperty) { Object.defineProperty(cooked, "raw", { value: raw }); } else { cooked.raw = raw; }
4 | return cooked;
5 | };
6 | exports.__esModule = true;
7 | var styled_components_1 = require("styled-components");
8 | var GlobalStyle = styled_components_1.createGlobalStyle(templateObject_1 || (templateObject_1 = __makeTemplateObject(["\n @import url(\"https://use.typekit.net/pqn7oor.css\");\n * {\n padding: 0;\n margin: 0;\n box-sizing: border-box;\n font-family: proxima-nova, sans-serif;\n }\n"], ["\n @import url(\"https://use.typekit.net/pqn7oor.css\");\n * {\n padding: 0;\n margin: 0;\n box-sizing: border-box;\n font-family: proxima-nova, sans-serif;\n }\n"])));
9 | exports["default"] = GlobalStyle;
10 | var templateObject_1;
11 |
--------------------------------------------------------------------------------
/packages/design-system/lib/utils/theme/globalStyle.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | var __makeTemplateObject = (this && this.__makeTemplateObject) || function (cooked, raw) {
3 | if (Object.defineProperty) { Object.defineProperty(cooked, "raw", { value: raw }); } else { cooked.raw = raw; }
4 | return cooked;
5 | };
6 | exports.__esModule = true;
7 | var styled_components_1 = require("styled-components");
8 | var GlobalStyle = styled_components_1.createGlobalStyle(templateObject_1 || (templateObject_1 = __makeTemplateObject(["\n @import url(\"https://use.typekit.net/pqn7oor.css\");\n * {\n padding: 0;\n margin: 0;\n box-sizing: border-box;\n font-family: proxima-nova, sans-serif;\n }\n"], ["\n @import url(\"https://use.typekit.net/pqn7oor.css\");\n * {\n padding: 0;\n margin: 0;\n box-sizing: border-box;\n font-family: proxima-nova, sans-serif;\n }\n"])));
9 | exports["default"] = GlobalStyle;
10 | var templateObject_1;
11 |
--------------------------------------------------------------------------------
/packages/design-system/lib/utils/theme/index.d.ts:
--------------------------------------------------------------------------------
1 | declare const theme: Readonly<{
2 | colors: {
3 | primary: string;
4 | secondary: string;
5 | primaryDark: string;
6 | error: string;
7 | black: string;
8 | blackNormal: string;
9 | blackDark: string;
10 | blackLight: string;
11 | white: string;
12 | gray: string;
13 | };
14 | viewports: {
15 | smartphone: string;
16 | tablet: string;
17 | desktop: string;
18 | };
19 | fonts: {
20 | sizes: {
21 | heading: string;
22 | subHeading: string;
23 | body: string;
24 | text: string;
25 | };
26 | weight: {
27 | thin: number;
28 | semiBold: number;
29 | regular: number;
30 | bold: number;
31 | black: number;
32 | };
33 | };
34 | }>;
35 | export default theme;
36 |
--------------------------------------------------------------------------------
/packages/design-system/lib/utils/theme/index.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | exports.__esModule = true;
3 | var colors = {
4 | primary: '#43FECB',
5 | secondary: '#743AF2',
6 | primaryDark: '#1BE0AB',
7 | error: '#FF3773',
8 | black: '#1F1F24',
9 | blackNormal: '#34353D',
10 | blackDark: '#27272D',
11 | blackLight: '#484854',
12 | white: '#FFFFFF',
13 | gray: '#737380'
14 | };
15 | var viewports = {
16 | smartphone: '360px',
17 | tablet: '720px',
18 | desktop: '1280px'
19 | };
20 | var fonts = {
21 | sizes: {
22 | heading: '32px',
23 | subHeading: '24px',
24 | body: '16px',
25 | text: '14px'
26 | },
27 | weight: {
28 | thin: 100,
29 | semiBold: 600,
30 | regular: 400,
31 | bold: 700,
32 | black: 900
33 | }
34 | };
35 | var theme = Object.freeze({
36 | colors: colors,
37 | viewports: viewports,
38 | fonts: fonts
39 | });
40 | exports["default"] = theme;
41 |
--------------------------------------------------------------------------------
/packages/design-system/src/web/Grid/interface.ts:
--------------------------------------------------------------------------------
1 | import {
2 | TColorsTypes,
3 | TBorderRadiusTypes,
4 | TCommonSpacingProps,
5 | TAlignContent,
6 | TAlignItems,
7 | TAligns,
8 | TJustifyContent,
9 | TSizes,
10 | TPosition,
11 | TFlexDirection,
12 | TFlexWrap,
13 | } from '../../interfaces';
14 |
15 |
16 | export type TGridProps =
17 | TCommonSpacingProps & {
18 | bg?: TColorsTypes;
19 | alignContent?: TAlignContent;
20 | alignItems?: TAlignItems;
21 | alignSelf?: TAligns;
22 | borderRadius?: TBorderRadiusTypes;
23 | flex?: number;
24 | flexDirection?: TFlexDirection;
25 | flexWrap?: TFlexWrap;
26 | height?: TSizes;
27 | justifyContent?: TJustifyContent;
28 | opacity?: number;
29 | position?: TPosition;
30 | bottom?: string;
31 | top?: string;
32 | left?: string;
33 | right?: string;
34 | width?: TSizes;
35 | zIndex?: number;
36 | skeleton?: boolean;
37 | skeletonWidth?: number;
38 | skeletonHeight?: number;
39 | display: string;
40 | };
41 |
--------------------------------------------------------------------------------
/packages/design-system/src/interfaces/units.ts:
--------------------------------------------------------------------------------
1 | export type TSpacingSizes = {
2 | spacing1: number;
3 | spacing2: number;
4 | spacing4: number;
5 | spacing8: number;
6 | spacing10: number;
7 | spacing12: number;
8 | spacing16: number;
9 | spacing18: number;
10 | spacing20: number;
11 | spacing24: number;
12 | spacing32: number;
13 | }
14 |
15 | export type TBorderRadius = {
16 | xsmall: number;
17 | small: number;
18 | medium: number;
19 | large: number;
20 | full: number;
21 | }
22 |
23 | export type TCommonSpacingProps = {
24 | padding?: TSpacingSizes;
25 | margin?: TSpacingSizes;
26 | p?: TSpacingSizes;
27 | pt?: TSpacingSizes;
28 | pb?: TSpacingSizes;
29 | pr?: TSpacingSizes;
30 | pl?: TSpacingSizes;
31 | m?: TSpacingSizes;
32 | mt?: TSpacingSizes;
33 | mr?: TSpacingSizes;
34 | mb?: TSpacingSizes;
35 | ml?: TSpacingSizes;
36 | };
37 |
38 | export type TSpacingSizesTypes = keyof TSpacingSizes;
39 | export type TBorderRadiusTypes = keyof TBorderRadius;
40 |
--------------------------------------------------------------------------------
/packages/server/src/user/dto/create-user.dto.ts:
--------------------------------------------------------------------------------
1 | import { InputType, Field } from '@nestjs/graphql';
2 | import { IsNotEmpty, IsString, IsEmail, MinLength } from 'class-validator';
3 |
4 | @InputType()
5 | export class CreateUserDto {
6 | @Field()
7 | @IsString()
8 | @IsNotEmpty({ message: 'Field required ' })
9 | readonly username: string;
10 |
11 | @Field()
12 | @IsString()
13 | @IsNotEmpty({ message: 'Field required ' })
14 | readonly name: string;
15 |
16 | @Field()
17 | @IsEmail()
18 | @IsNotEmpty({ message: 'Field required ' })
19 | readonly email: string;
20 |
21 | @Field()
22 | @IsString()
23 | @IsNotEmpty({ message: 'Field required ' })
24 | @MinLength(6, { message: 'The password need have more than 6 characters' })
25 | readonly password: string;
26 |
27 | @Field()
28 | @IsString()
29 | @IsNotEmpty({ message: 'Field required ' })
30 | @MinLength(6, { message: 'The password need have more than 6 characters' })
31 | readonly confirmPassword: string;
32 | }
33 |
--------------------------------------------------------------------------------
/packages/server/src/utils/helpers.ts:
--------------------------------------------------------------------------------
1 | type GenerateSkuProps = {
2 | name: string;
3 | attributeName: string;
4 | brand: string;
5 | };
6 |
7 | type GenericProvider = {
8 | id: string;
9 | };
10 |
11 | type GenericExists = {
12 | data: GenericProvider[];
13 | dataIds: string[];
14 | };
15 |
16 | export class Helpers {
17 | generateSku({ name, attributeName, brand }: GenerateSkuProps) {
18 | const nameSplitted = name.split(' ');
19 |
20 | const nameCode =
21 | nameSplitted.length > 1
22 | ? `${nameSplitted[0].charAt(0)}${nameSplitted[1].charAt(0)}`
23 | : nameSplitted[0].substr(0, 2);
24 |
25 | const attributeCode = attributeName.substr(0, 2);
26 |
27 | const brandCode = brand.substr(0, 3);
28 |
29 | const sku = `${nameCode}-${attributeCode}-${brandCode}`;
30 |
31 | return sku.toUpperCase();
32 | }
33 |
34 | dataExists({ data, dataIds }: GenericExists): boolean {
35 | return data.some(d => dataIds.every(id => id === d.id));
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/packages/server/.eslintrc.js:
--------------------------------------------------------------------------------
1 | const tsconfig = require(`./tsconfig`);
2 |
3 | module.exports = {
4 | parser: '@typescript-eslint/parser',
5 | parserOptions: {
6 | sourceType: 'module',
7 | tsconfigRootDir: __dirname,
8 | project: ["./tsconfig.json"],
9 | },
10 | plugins: ['@typescript-eslint/eslint-plugin'],
11 | extends: [
12 | 'plugin:@typescript-eslint/recommended',
13 | `plugin:@typescript-eslint/eslint-recommended`,
14 | 'plugin:prettier/recommended',
15 | ],
16 | root: true,
17 | env: {
18 | node: true,
19 | jest: true,
20 | },
21 | ignorePatterns: ['.eslintrc.js'],
22 | rules: {
23 | '@typescript-eslint/interface-name-prefix': 'off',
24 | '@typescript-eslint/explicit-function-return-type': 'off',
25 | '@typescript-eslint/explicit-module-boundary-types': 'off',
26 | '@typescript-eslint/no-explicit-any': 'off',
27 | },
28 | settings: {
29 | 'import/resolver': {
30 | typescript: {
31 | project: `.`,
32 | },
33 | },
34 | },
35 | };
36 |
--------------------------------------------------------------------------------
/packages/design-system/lib/Grid/web/Flex.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | var __makeTemplateObject = (this && this.__makeTemplateObject) || function (cooked, raw) {
3 | if (Object.defineProperty) { Object.defineProperty(cooked, "raw", { value: raw }); } else { cooked.raw = raw; }
4 | return cooked;
5 | };
6 | var __importDefault = (this && this.__importDefault) || function (mod) {
7 | return (mod && mod.__esModule) ? mod : { "default": mod };
8 | };
9 | exports.__esModule = true;
10 | var styled_components_1 = __importDefault(require("styled-components"));
11 | exports.Flex = styled_components_1["default"].div(templateObject_1 || (templateObject_1 = __makeTemplateObject(["\n display: 'flex';\n direction: ", ";\n justify-content: ", ";\n align-items: ", ";\n"], ["\n display: 'flex';\n direction: ", ";\n justify-content: ", ";\n align-items: ", ";\n"])), function (props) { return (props.direction ? props.direction : 'row'); }, function (props) { return props.justify; }, function (props) { return props.align; });
12 | var templateObject_1;
13 |
--------------------------------------------------------------------------------
/packages/design-system/lib/web/Grid/Flex.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | var __makeTemplateObject = (this && this.__makeTemplateObject) || function (cooked, raw) {
3 | if (Object.defineProperty) { Object.defineProperty(cooked, "raw", { value: raw }); } else { cooked.raw = raw; }
4 | return cooked;
5 | };
6 | var __importDefault = (this && this.__importDefault) || function (mod) {
7 | return (mod && mod.__esModule) ? mod : { "default": mod };
8 | };
9 | exports.__esModule = true;
10 | var styled_components_1 = __importDefault(require("styled-components"));
11 | exports.Flex = styled_components_1["default"].div(templateObject_1 || (templateObject_1 = __makeTemplateObject(["\n display: 'flex';\n direction: ", ";\n justify-content: ", ";\n align-items: ", ";\n"], ["\n display: 'flex';\n direction: ", ";\n justify-content: ", ";\n align-items: ", ";\n"])), function (props) { return (props.direction ? props.direction : 'row'); }, function (props) { return props.justify; }, function (props) { return props.align; });
12 | var templateObject_1;
13 |
--------------------------------------------------------------------------------
/packages/web/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | extends: ['airbnb', 'plugin:@typescript-eslint/recommended'],
3 | parser: '@typescript-eslint/parser',
4 | plugins: ['@typescript-eslint', 'prettier'],
5 | settings: {
6 | 'import/parsers': {
7 | '@typescript-eslint/parser': ['.ts', '.tsx'],
8 | },
9 | 'import/resolver': {
10 | typescript: {},
11 | },
12 | },
13 | rules: {
14 | 'react/jsx-filename-extension': [2, { extensions: ['.js', '.jsx', '.ts', '.tsx'] }],
15 | 'import/no-extraneous-dependencies': [2, { devDependencies: ['**/test.tsx', '**/test.ts'] }],
16 | '@typescript-eslint/indent': [2, 2],
17 | '@typescript-eslint/explicit-function-return-type': "off",
18 | '@typescript-eslint/interface-name-prefix': ["error", { "prefixWithI": "always" }],
19 | "@typescript-eslint/no-unused-vars": [2, { "args": "none" }],
20 | "import/extensions": ["error", "ignorePackages", {
21 | "js": "never",
22 | "jsx": "never",
23 | "ts": "never",
24 | "tsx": "never",
25 | }]
26 | },
27 | };
28 |
--------------------------------------------------------------------------------
/packages/design-system/lib/web/Button/Button.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | var __importDefault = (this && this.__importDefault) || function (mod) {
3 | return (mod && mod.__esModule) ? mod : { "default": mod };
4 | };
5 | exports.__esModule = true;
6 | var react_1 = __importDefault(require("react"));
7 | var StyledButton_1 = __importDefault(require("./StyledButton"));
8 | var OutlinedButton_1 = __importDefault(require("./OutlinedButton"));
9 | var Button = function (_a) {
10 | var children = _a.children, _b = _a.outline, outline = _b === void 0 ? false : _b, _c = _a.full, full = _c === void 0 ? false : _c, _d = _a.secondary, secondary = _d === void 0 ? false : _d, onClick = _a.onClick;
11 | return (react_1["default"].createElement(react_1["default"].Fragment, null, outline ? (react_1["default"].createElement(OutlinedButton_1["default"], { full: full, onClick: onClick, secondary: secondary }, children)) : (react_1["default"].createElement(StyledButton_1["default"], { full: full, onClick: onClick, secondary: secondary }, children))));
12 | };
13 | exports["default"] = Button;
14 |
--------------------------------------------------------------------------------
/packages/server/src/category/category.resolver.ts:
--------------------------------------------------------------------------------
1 | import { UseGuards } from '@nestjs/common';
2 | import { Resolver, Args, Mutation, Query } from '@nestjs/graphql';
3 |
4 | import { CategoryService } from '@category/category.service';
5 | import { Category } from '@category/category.entity';
6 | import { CreateCategoryDto } from '@category/dto/create-category.dto';
7 |
8 | import { GqlAuthGuard } from '@auth/auth.guard';
9 |
10 | @Resolver()
11 | export class CategoryResolver {
12 | constructor(private categoryService: CategoryService) {}
13 |
14 | @UseGuards(GqlAuthGuard)
15 | @Mutation(() => Category)
16 | async createCategory(@Args('data') data: CreateCategoryDto): Promise {
17 | const category = await this.categoryService.create(data);
18 |
19 | return category;
20 | }
21 |
22 | @UseGuards(GqlAuthGuard)
23 | @Query(() => [Category], {
24 | nullable: true,
25 | })
26 | async getAllCategories(): Promise {
27 | const categories = await this.categoryService.findAll();
28 |
29 | return categories;
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/packages/sdk/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@react-shop/sdk",
3 | "version": "0.0.1",
4 | "private": true,
5 | "description": "a Sdk provider for react-ecommerce",
6 | "main": "./lib/index.js",
7 | "module": "./lib-esm/index.js",
8 | "types": "./lib/index.d.ts",
9 | "author": "Vinicius Arruda",
10 | "scripts": {
11 | "libbuild": "tsc && tsc --build tsconfig.esm.json",
12 | "start": "tsc && tsc --build tsconfig.esm.json -w",
13 | "test": "jest --color"
14 | },
15 | "dependencies": {
16 | "axios": "^0.21.1"
17 | },
18 | "devDependencies": {
19 | "@babel/core": "^7.7.7",
20 | "@babel/plugin-proposal-export-default-from": "^7.7.4",
21 | "@babel/preset-env": "^7.7.7",
22 | "@babel/preset-typescript": "^7.7.7",
23 | "@types/jest": "^24.0.25",
24 | "@types/yup": "^0.26.27",
25 | "jest": "^24.9.0",
26 | "yup": "^0.28.0"
27 | },
28 | "jest": {
29 | "transformIgnorePatterns": [
30 | "/node_modules"
31 | ],
32 | "coveragePathIgnorePatterns": [
33 | "/node_modules"
34 | ]
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/packages/server/src/attribute/attribute.resolver.ts:
--------------------------------------------------------------------------------
1 | import { UseGuards } from '@nestjs/common';
2 | import { Resolver, Args, Mutation, Query } from '@nestjs/graphql';
3 |
4 | import { AttributeService } from '@attribute/attribute.service';
5 | import { Attribute } from '@attribute/attribute.entity';
6 | import { CreateAttributeDto } from '@attribute/dto/create-attribute.dto';
7 |
8 | import { GqlAuthGuard } from '@auth/auth.guard';
9 |
10 | @Resolver()
11 | export class AttributeResolver {
12 | constructor(private attributeService: AttributeService) {}
13 |
14 | @UseGuards(GqlAuthGuard)
15 | @Mutation(() => Attribute)
16 | async createAttribute(@Args('data') data: CreateAttributeDto): Promise {
17 | const attribute = await this.attributeService.create(data);
18 |
19 | return attribute;
20 | }
21 |
22 | @UseGuards(GqlAuthGuard)
23 | @Query(() => [Attribute], {
24 | nullable: true,
25 | })
26 | async getAllAttributes(): Promise {
27 | const attributes = await this.attributeService.getAll();
28 |
29 | return attributes;
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/packages/design-system/__tests__/helpers/index.tsx:
--------------------------------------------------------------------------------
1 | import {
2 | mount, shallow, ShallowWrapper, ReactWrapper,
3 | } from 'enzyme';
4 |
5 | import { ThemeProvider, DefaultTheme } from 'styled-components';
6 |
7 | import React from 'react';
8 |
9 | import { theme as designSystemTheme } from '../../src/theme';
10 |
11 | export const mountWithTheme = (
12 | tree: React.ReactElement,
13 | theme: DefaultTheme = designSystemTheme,
14 | ): ReactWrapper => {
15 | const WrappingThemeProvider: React.FC<{
16 | children: React.ReactChild;
17 | }> = ({ children }) => {children};
18 |
19 | return mount(tree, { wrappingComponent: WrappingThemeProvider });
20 | };
21 |
22 | export const shallowWithTheme = (
23 | tree: React.ReactElement,
24 | theme: DefaultTheme = designSystemTheme,
25 | ): ShallowWrapper => {
26 | const WrappingThemeProvider: React.FC<{
27 | children: React.ReactChild;
28 | }> = ({ children }) => {children};
29 |
30 | return shallow(tree, { wrappingComponent: WrappingThemeProvider });
31 | };
32 |
--------------------------------------------------------------------------------
/packages/ssr/jest.config.js:
--------------------------------------------------------------------------------
1 | const { pathsToModuleNameMapper } = require(`ts-jest/utils`);
2 |
3 | const { compilerOptions } = require(`./tsconfig`);
4 |
5 | module.exports = {
6 | preset: `ts-jest`,
7 | testEnvironment: `jsdom`,
8 | testPathIgnorePatterns: [`/node_modules/`, `/.next/`],
9 | snapshotResolver: `/tests/snapshotResolver.ts`,
10 | testMatch: [`**/__tests__/**/*.[jt]s?(x)`, `**/?(*.)+(specs|tests).[tj]s?(x)`],
11 | collectCoverage: true,
12 | collectCoverageFrom: [`src/**/*.ts(x)?`],
13 | coverageDirectory: `/tests/coverage/`,
14 | setupFilesAfterEnv: [`/tests/setupTests.ts`],
15 | modulePaths: [`/src/`],
16 | moduleNameMapper: pathsToModuleNameMapper(compilerOptions.paths, {
17 | prefix: `/src/`,
18 | }),
19 | transform: {
20 | '\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$': `/tests/mocks/fileTransformer.js`,
21 | },
22 | globals: {
23 | NODE_ENV: `test`,
24 | 'ts-jest': {
25 | tsconfig: `tsconfig.jest.json`,
26 | diagnostics: true,
27 | },
28 | },
29 | };
--------------------------------------------------------------------------------
/packages/server/src/product/dto/create-product.dto.ts:
--------------------------------------------------------------------------------
1 | import { InputType, Field, ID } from '@nestjs/graphql';
2 | import { IsNotEmpty, IsString, IsNumber, IsPositive } from 'class-validator';
3 |
4 | @InputType()
5 | export class CreateProductDto {
6 | @Field()
7 | @IsString()
8 | @IsNotEmpty({ message: 'Field required ' })
9 | readonly title: string;
10 |
11 | @Field()
12 | @IsString()
13 | @IsNotEmpty({ message: 'Field required ' })
14 | readonly description: string;
15 |
16 | @Field()
17 | @IsString()
18 | @IsNotEmpty({ message: 'Field required ' })
19 | readonly brand: string;
20 |
21 | @Field()
22 | @IsPositive()
23 | @IsNumber()
24 | @IsNotEmpty({ message: 'Field required ' })
25 | readonly price: number;
26 |
27 | @Field()
28 | @IsPositive()
29 | @IsNumber()
30 | @IsNotEmpty({ message: 'Field required ' })
31 | readonly quantity: number;
32 |
33 | @Field()
34 | @IsString()
35 | @IsNotEmpty({ message: 'Field required ' })
36 | readonly dimension: string;
37 |
38 | @IsNotEmpty({ message: 'Field required ' })
39 | @Field(() => [ID])
40 | readonly attributesId: string[];
41 | }
42 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2020 Vinícius Arruda
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.
22 |
--------------------------------------------------------------------------------
/packages/mobile/.gitignore:
--------------------------------------------------------------------------------
1 | # OSX
2 | #
3 | .DS_Store
4 |
5 | # Xcode
6 | #
7 | build/
8 | *.pbxuser
9 | !default.pbxuser
10 | *.mode1v3
11 | !default.mode1v3
12 | *.mode2v3
13 | !default.mode2v3
14 | *.perspectivev3
15 | !default.perspectivev3
16 | xcuserdata
17 | *.xccheckout
18 | *.moved-aside
19 | DerivedData
20 | *.hmap
21 | *.ipa
22 | *.xcuserstate
23 |
24 | # Android/IntelliJ
25 | #
26 | build/
27 | .idea
28 | .gradle
29 | local.properties
30 | *.iml
31 |
32 | # Visual Studio Code
33 | #
34 | .vscode/
35 |
36 | # node.js
37 | #
38 | node_modules/
39 | npm-debug.log
40 | yarn-error.log
41 |
42 | # BUCK
43 | buck-out/
44 | \.buckd/
45 | *.keystore
46 | !debug.keystore
47 |
48 | # fastlane
49 | #
50 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the
51 | # screenshots whenever they are needed.
52 | # For more information about the recommended setup visit:
53 | # https://docs.fastlane.tools/best-practices/source-control/
54 |
55 | */fastlane/report.xml
56 | */fastlane/Preview.html
57 | */fastlane/screenshots
58 |
59 | # Bundle artifact
60 | *.jsbundle
61 |
62 | # CocoaPods
63 | /ios/Pods/
64 |
--------------------------------------------------------------------------------
/packages/mobile/android/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
5 |
6 |
13 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/packages/design-system/.storybook/webpack.config.js:
--------------------------------------------------------------------------------
1 | const path = require('path');
2 | module.exports = {
3 | module: {
4 | rules: [
5 | {
6 | test: /\.scss$/,
7 | loaders: ['style-loader', 'css-loader', 'sass-loader'],
8 | include: path.resolve(__dirname, '../'),
9 | },
10 | {
11 | test: /\.css/,
12 | loaders: ['style-loader', 'css-loader'],
13 | include: path.resolve(__dirname, '../'),
14 | },
15 | {
16 | enforce: 'pre',
17 | test: /\.js$/,
18 | loader: 'source-map-loader',
19 | exclude: [/node_modules\//],
20 | },
21 | {
22 | test: /\.tsx?$/,
23 | include: path.resolve(__dirname, '../src'),
24 | loader: 'awesome-typescript-loader',
25 | },
26 | {
27 | test: /\.tsx?$/,
28 | include: path.resolve(__dirname, '../src'),
29 | loader: 'react-docgen-typescript-loader',
30 | },
31 | {
32 | test: /\.(woff|woff2|eot|ttf|otf|svg)$/,
33 | loader: 'file-loader',
34 | },
35 | ],
36 | },
37 | resolve: {
38 | extensions: ['.tsx', '.ts', '.js'],
39 | },
40 | };
41 |
--------------------------------------------------------------------------------
/packages/mobile/android/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 |
3 | buildscript {
4 | ext {
5 | buildToolsVersion = "29.0.2"
6 | minSdkVersion = 16
7 | compileSdkVersion = 29
8 | targetSdkVersion = 29
9 | }
10 | repositories {
11 | google()
12 | jcenter()
13 | }
14 | dependencies {
15 | classpath("com.android.tools.build:gradle:3.5.3")
16 | // NOTE: Do not place your application dependencies here; they belong
17 | // in the individual module build.gradle files
18 | }
19 | }
20 |
21 | allprojects {
22 | repositories {
23 | mavenLocal()
24 | maven {
25 | // All of React Native (JS, Obj-C sources, Android binaries) is installed from npm
26 | url("$rootDir/../../../node_modules/react-native/android")
27 | }
28 | maven {
29 | // Android JSC is installed from npm
30 | url("$rootDir/../../../node_modules/jsc-android/dist")
31 | }
32 |
33 | google()
34 | jcenter()
35 | maven { url 'https://www.jitpack.io' }
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/packages/design-system/src/utils/config/setupEnzyme.ts:
--------------------------------------------------------------------------------
1 | import { configure } from 'enzyme';
2 | import EnzymeAdapter from 'enzyme-adapter-react-16';
3 | import 'jest-enzyme';
4 |
5 | // jest.useFakeTimers();
6 |
7 | // /**
8 | // * Set up DOM in node.js environment for Enzyme to mount to
9 | // */
10 | // // eslint-disable-next-line @typescript-eslint/no-var-requires
11 | // const { JSDOM } = require('jsdom');
12 |
13 | // const jsdom = new JSDOM('');
14 | // const { window } = jsdom;
15 |
16 | // function copyProps(src, target) {
17 | // Object.defineProperties(target, {
18 | // ...Object.getOwnPropertyDescriptors(src),
19 | // ...Object.getOwnPropertyDescriptors(target),
20 | // });
21 | // }
22 |
23 | // jest.useFakeTimers();
24 |
25 | // global.window = window;
26 | // global.document = window.document;
27 | // global.navigator = {
28 | // userAgent: 'node.js',
29 | // };
30 |
31 | // copyProps(window, global);
32 |
33 | configure({ adapter: new EnzymeAdapter() });
34 |
35 | // const originalConsoleError = console.error;
36 | // console.error = (message, ...args) => !message.startsWith('Warning: ') && originalConsoleError(message, ...args);
37 |
--------------------------------------------------------------------------------
/packages/design-system/src/web/Button/DefaultButton/index.tsx:
--------------------------------------------------------------------------------
1 | import React, { FunctionComponent } from 'react';
2 |
3 | import Container from './styles';
4 |
5 | import { TDefaultButtonProps, TGetVariants } from './interface';
6 |
7 | const Button: FunctionComponent = ({
8 | text, onClick, variant, disabled,
9 | }) => {
10 | const getButtonVariants = () => {
11 | const getVariants: TGetVariants = {
12 | primary: {
13 | bg: 'primary',
14 | hoverColor: 'primaryDark',
15 | },
16 | secondary: {
17 | bg: 'secondary',
18 | hoverColor: 'secondaryDark',
19 | },
20 | disabled: {
21 | bg: 'gray',
22 | hoverColor: 'gray',
23 | },
24 | };
25 |
26 | return disabled ? getVariants.disabled : (getVariants[variant] || getVariants.primary);
27 | };
28 |
29 | return (
30 |
39 | {text}
40 |
41 | );
42 | };
43 |
44 | export default Button;
45 |
--------------------------------------------------------------------------------
/packages/mobile/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "mobile",
3 | "version": "0.0.1",
4 | "private": true,
5 | "scripts": {
6 | "android": "react-native run-android",
7 | "ios": "react-native run-ios",
8 | "start": "react-native start",
9 | "test": "jest --color",
10 | "lint": "eslint . --ext .js,.jsx,.ts,.tsx"
11 | },
12 | "dependencies": {
13 | "@react-shop/sdk": "*",
14 | "react": "16.13.1",
15 | "react-native": "0.64.2"
16 | },
17 | "devDependencies": {
18 | "@babel/core": "^7.8.4",
19 | "@babel/runtime": "^7.8.4",
20 | "@react-native-community/eslint-config": "^1.1.0",
21 | "@types/jest": "^25.2.3",
22 | "@types/react-native": "^0.63.2",
23 | "@types/react-test-renderer": "^16.9.2",
24 | "babel-jest": "^25.1.0",
25 | "eslint": "^6.5.1",
26 | "jest": "^25.1.0",
27 | "metro-react-native-babel-preset": "^0.59.0",
28 | "prettier": "^2.0.4",
29 | "react-test-renderer": "16.13.1",
30 | "typescript": "^3.8.3"
31 | },
32 | "jest": {
33 | "preset": "react-native",
34 | "moduleFileExtensions": [
35 | "ts",
36 | "tsx",
37 | "js",
38 | "jsx",
39 | "json",
40 | "node"
41 | ]
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/packages/design-system/lib/Button/web/StyledButton.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | var __makeTemplateObject = (this && this.__makeTemplateObject) || function (cooked, raw) {
3 | if (Object.defineProperty) { Object.defineProperty(cooked, "raw", { value: raw }); } else { cooked.raw = raw; }
4 | return cooked;
5 | };
6 | var __importDefault = (this && this.__importDefault) || function (mod) {
7 | return (mod && mod.__esModule) ? mod : { "default": mod };
8 | };
9 | exports.__esModule = true;
10 | var styled_components_1 = __importDefault(require("styled-components"));
11 | var theme_1 = __importDefault(require("../../theme"));
12 | var DefaultButton_1 = __importDefault(require("./DefaultButton"));
13 | var StyledButton = styled_components_1["default"](DefaultButton_1["default"])(templateObject_1 || (templateObject_1 = __makeTemplateObject(["\n background-color: ", ";\n color: ", ";\n"], ["\n background-color: ", ";\n color: ", ";\n"])), function (props) { return (props.secondary ? theme_1["default"].colors.secondary : theme_1["default"].colors.primary); }, function (props) { return (props.secondary ? theme_1["default"].colors.white : theme_1["default"].colors.black); });
14 | exports["default"] = StyledButton;
15 | var templateObject_1;
16 |
--------------------------------------------------------------------------------
/packages/design-system/lib/web/Button/StyledButton.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | var __makeTemplateObject = (this && this.__makeTemplateObject) || function (cooked, raw) {
3 | if (Object.defineProperty) { Object.defineProperty(cooked, "raw", { value: raw }); } else { cooked.raw = raw; }
4 | return cooked;
5 | };
6 | var __importDefault = (this && this.__importDefault) || function (mod) {
7 | return (mod && mod.__esModule) ? mod : { "default": mod };
8 | };
9 | exports.__esModule = true;
10 | var styled_components_1 = __importDefault(require("styled-components"));
11 | var theme_1 = __importDefault(require("../../theme"));
12 | var DefaultButton_1 = __importDefault(require("./DefaultButton"));
13 | var StyledButton = styled_components_1["default"](DefaultButton_1["default"])(templateObject_1 || (templateObject_1 = __makeTemplateObject(["\n background-color: ", ";\n color: ", ";\n"], ["\n background-color: ", ";\n color: ", ";\n"])), function (props) { return (props.secondary ? theme_1["default"].colors.secondary : theme_1["default"].colors.primary); }, function (props) { return (props.secondary ? theme_1["default"].colors.white : theme_1["default"].colors.black); });
14 | exports["default"] = StyledButton;
15 | var templateObject_1;
16 |
--------------------------------------------------------------------------------
/packages/sdk/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | extends: ['airbnb', 'plugin:@typescript-eslint/recommended'],
3 | parser: '@typescript-eslint/parser',
4 | plugins: ['@typescript-eslint', 'prettier'],
5 | settings: {
6 | 'import/parsers': {
7 | '@typescript-eslint/parser': ['.ts', '.tsx'],
8 | },
9 | 'import/resolver': {
10 | typescript: {},
11 | },
12 | },
13 | rules: {
14 | 'react/jsx-filename-extension': [2, { extensions: ['.js', '.jsx', '.ts', '.tsx'] }],
15 | 'import/no-extraneous-dependencies': [2, { devDependencies: ['**/test.tsx', '**/test.ts'] }],
16 | 'import/prefer-default-export': "off",
17 | '@typescript-eslint/indent': [2, 2],
18 | '@typescript-eslint/explicit-function-return-type': "off",
19 | '@typescript-eslint/interface-name-prefix': ["error", { "prefixWithI": "always" }],
20 | "@typescript-eslint/no-unused-vars": [2, { "args": "none" }],
21 | "import/extensions": ["error", "ignorePackages", {
22 | "js": "never",
23 | "jsx": "never",
24 | "ts": "never",
25 | "tsx": "never",
26 | }],
27 | "import/no-extraneous-dependencies": "off",
28 | 'react/prop-types': 0,
29 | "max-len": ["error", { "code": 120 }]
30 | },
31 | };
32 |
--------------------------------------------------------------------------------
/packages/design-system/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | extends: ['airbnb', 'plugin:@typescript-eslint/recommended'],
3 | parser: '@typescript-eslint/parser',
4 | plugins: ['@typescript-eslint', 'prettier'],
5 | settings: {
6 | 'import/parsers': {
7 | '@typescript-eslint/parser': ['.ts', '.tsx'],
8 | },
9 | 'import/resolver': {
10 | typescript: {},
11 | },
12 | },
13 | env: {
14 | "jest": true
15 | },
16 | rules: {
17 | 'react/jsx-filename-extension': [2, { extensions: ['.js', '.jsx', '.ts', '.tsx'] }],
18 | 'import/no-extraneous-dependencies': [2, { devDependencies: ['**/test.tsx', '**/test.ts'] }],
19 | '@typescript-eslint/indent': [2, 2],
20 | '@typescript-eslint/explicit-function-return-type': "off",
21 | '@typescript-eslint/interface-name-prefix': ["error", { "prefixWithI": "always" }],
22 | "@typescript-eslint/no-unused-vars": [2, { "args": "none" }],
23 | "import/extensions": ["error", "ignorePackages", {
24 | "js": "never",
25 | "jsx": "never",
26 | "ts": "never",
27 | "tsx": "never",
28 | }],
29 | "import/no-extraneous-dependencies": "off",
30 | 'react/prop-types': 0,
31 | "max-len": ["error", { "code": 120 }],
32 | "react/jsx-props-no-spreading": "off"
33 | },
34 |
35 | };
36 |
--------------------------------------------------------------------------------
/packages/sdk/src/utils/httpClient.ts:
--------------------------------------------------------------------------------
1 | /* eslint-disable no-undef */
2 | /* eslint-disable no-param-reassign */
3 | import axios from 'axios';
4 |
5 | import { api } from './routes.constants';
6 | // Create a basic Axios instance to all requests (this object can be customized before making the call)
7 | export const http = axios.create({
8 | baseURL: api.BASE_URL,
9 | headers: {
10 | 'Content-Type': 'application/json',
11 | },
12 | });
13 |
14 | export interface IAccessUser {
15 | token: string;
16 | }
17 |
18 | // Insert token on all requests when there is a token in the device storage
19 | http.interceptors.request.use(async (config) => {
20 | const accessUser: IAccessUser = JSON.parse(localStorage.getItem('access_token'));
21 |
22 | if (accessUser) {
23 | config.headers.common.Authorization = `Bearer ${accessUser.token}`;
24 | }
25 |
26 | return config;
27 | });
28 |
29 | http.interceptors.response.use(
30 | (response) => response,
31 | (error) => {
32 | if (error.response && error.response.status === 401) {
33 | localStorage.clear();
34 | }
35 |
36 | console.log('REQUEST error', error);
37 |
38 | if (!error.response) {
39 | error.response = { data: { genericError: error } };
40 | }
41 |
42 | return Promise.reject(error);
43 | },
44 | );
45 |
--------------------------------------------------------------------------------
/packages/server/src/auth/auth.service.ts:
--------------------------------------------------------------------------------
1 | import { Injectable, UnauthorizedException } from '@nestjs/common';
2 | import { JwtService } from '@nestjs/jwt';
3 | import { compareSync } from 'bcrypt';
4 |
5 | import { AuthDto } from '@auth/dto/auth.input';
6 | import { UserService } from '@user/user.service';
7 | import { AuthType } from '@auth/dto/auth.interface';
8 | import { User } from '@user/user.entity';
9 |
10 | @Injectable()
11 | export class AuthService {
12 | constructor(private userService: UserService, private jwtService: JwtService) {}
13 |
14 | async validateUser(data: AuthDto): Promise {
15 | const user = await this.userService.findByEmail(data.email);
16 |
17 | if (!user) {
18 | throw new UnauthorizedException('User not found!');
19 | }
20 |
21 | const validPassword = compareSync(data.password, user.password);
22 |
23 | if (!validPassword) {
24 | throw new UnauthorizedException('Incorrect Password');
25 | }
26 |
27 | const token = await this.generateJWT(user);
28 |
29 | return {
30 | user,
31 | token,
32 | };
33 | }
34 |
35 | public async generateJWT(user: User): Promise {
36 | const payload = { username: user.username, sub: user.id };
37 |
38 | return this.jwtService.signAsync(payload);
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/packages/server/src/user/user.resolver.ts:
--------------------------------------------------------------------------------
1 | import { UseGuards, UsePipes } from '@nestjs/common';
2 |
3 | import { Resolver, Mutation, Query, Args } from '@nestjs/graphql';
4 |
5 | import { UserService } from '@user/user.service';
6 | import { User } from '@user/user.entity';
7 | import { CreateUserDto } from '@user/dto';
8 | import { UserData } from '@user/user.interface';
9 |
10 | import { ValidationPipe } from '@shared/pipes/validation.pipe';
11 | import { GqlAuthGuard } from '@auth/auth.guard';
12 |
13 | @Resolver('User')
14 | export class UserResolver {
15 | constructor(private userService: UserService) {}
16 |
17 | @UseGuards(GqlAuthGuard)
18 | @Query(() => User)
19 | async findById(@Args('id') id: string): Promise {
20 | const user = this.userService.findById(id);
21 |
22 | return user;
23 | }
24 |
25 | @UseGuards(GqlAuthGuard)
26 | @Query(() => User)
27 | async findByEmail(@Args('email') email: string): Promise {
28 | const user = this.userService.findByEmail(email);
29 |
30 | return user;
31 | }
32 |
33 | @UsePipes(new ValidationPipe())
34 | @Mutation(() => User)
35 | async createUser(@Args('data') data: CreateUserDto): Promise {
36 | const user = await this.userService.create(data);
37 |
38 | return user;
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "react-ecommerce",
3 | "private": true,
4 | "version": "1.0.0",
5 | "description": "React E-commerce monorepo",
6 | "repository": "https://github.com/react-shop/react-ecommerce",
7 | "author": "Vinicius Arruda",
8 | "engines": {
9 | "node": "14.x",
10 | "npm": "You must use yarn in this project!",
11 | "yarn": "^1.22.x"
12 | },
13 | "scripts": {
14 | "story": "lerna run story --stream",
15 | "start": "lerna run start --parallel --scope '{web,@react-shop/design-system,@react-shop/sdk}'",
16 | "test": "lerna run test --stream ",
17 | "server:dev": "lerna run dev --scope @react-shop/server"
18 | },
19 | "workspaces": {
20 | "packages": [
21 | "packages/*"
22 | ],
23 | "nohoist": [
24 | "@commitlint/*"
25 | ]
26 | },
27 | "npmClient": "yarn",
28 | "useWorkspaces": true,
29 | "devDependencies": {
30 | "@commitlint/cli": "^13.1.0",
31 | "@commitlint/config-conventional": "^13.1.0",
32 | "@types/react": "17.0.14",
33 | "@types/react-dom": "17.0.9",
34 | "@types/styled-components": "^5.1.12",
35 | "husky": "^7.0.2",
36 | "lerna": "3.19.0",
37 | "typescript": "4.3.5"
38 | },
39 | "husky": {
40 | "hooks": {
41 | "commit-msg": "commitlint -E HUSKY_GIT_PARAMS"
42 | }
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/packages/design-system/lib-esm/theme/index.js:
--------------------------------------------------------------------------------
1 | import colors from './colors';
2 | import units from './units';
3 | export const theme = {
4 | colors: {
5 | primary: colors.primary,
6 | secondary: colors.secondary,
7 | primaryDark: colors.primaryDark,
8 | secondaryDark: colors.secondaryDark,
9 | error: colors.error,
10 | black: colors.black,
11 | blackNormal: colors.blackNormal,
12 | blackDark: colors.blackDark,
13 | blackLight: colors.blackLight,
14 | white: colors.white,
15 | gray: colors.gray,
16 | },
17 | space: {
18 | spacing1: units.sizes.spacing1,
19 | spacing2: units.sizes.spacing2,
20 | spacing4: units.sizes.spacing4,
21 | spacing8: units.sizes.spacing8,
22 | spacing10: units.sizes.spacing10,
23 | spacing12: units.sizes.spacing12,
24 | spacing16: units.sizes.spacing16,
25 | spacing18: units.sizes.spacing18,
26 | spacing20: units.sizes.spacing20,
27 | spacing24: units.sizes.spacing24,
28 | spacing32: units.sizes.spacing32,
29 | },
30 | radii: {
31 | xsmall: units.borderRadius.xsmall,
32 | small: units.borderRadius.small,
33 | medium: units.borderRadius.medium,
34 | large: units.borderRadius.large,
35 | full: units.borderRadius.full,
36 | },
37 | };
38 |
--------------------------------------------------------------------------------
/packages/mobile/android/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 |
3 | # IDE (e.g. Android Studio) users:
4 | # Gradle settings configured through the IDE *will override*
5 | # any settings specified in this file.
6 |
7 | # For more details on how to configure your build environment visit
8 | # http://www.gradle.org/docs/current/userguide/build_environment.html
9 |
10 | # Specifies the JVM arguments used for the daemon process.
11 | # The setting is particularly useful for tweaking memory settings.
12 | # Default value: -Xmx10248m -XX:MaxPermSize=256m
13 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
14 |
15 | # When configured, Gradle will run in incubating parallel mode.
16 | # This option should only be used with decoupled projects. More details, visit
17 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
18 | # org.gradle.parallel=true
19 |
20 | # AndroidX package structure to make it clearer which packages are bundled with the
21 | # Android operating system, and which are packaged with your app's APK
22 | # https://developer.android.com/topic/libraries/support-library/androidx-rn
23 | android.useAndroidX=true
24 | # Automatically convert third-party libraries to use AndroidX
25 | android.enableJetifier=true
26 |
27 | # Version of flipper SDK to use with React Native
28 | FLIPPER_VERSION=0.37.0
29 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/bug_report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Bug report 🐛
3 | about: Create a bug report for react-ecommerce.
4 | ---
5 |
6 |
7 |
8 |
9 |
10 | - [ ] The issue is present in the latest release.
11 | - [ ] I have searched the [issues](https://github.com/react-shop/react-ecommerce/issues) of this repository and believe that this is not a duplicate.
12 |
13 | ## Current Behavior 😯
14 |
15 |
16 |
17 | ## Expected Behavior 🤔
18 |
19 |
20 |
21 | ## Steps to Reproduce 🕹
22 |
23 |
24 |
25 | Steps:
26 |
27 | 1.
28 | 2.
29 | 3.
30 | 4.
31 |
32 | ## Context 🔦
33 |
34 |
38 |
39 | ## Your Environment 🌎
40 |
41 |
45 |
46 | | Tech | Version |
47 | | --------------- | ------- |
48 | | react-ecommerce | v0.?.? |
49 | | React | |
50 | | Browser | |
51 | | TypeScript | |
52 | | etc. | |
--------------------------------------------------------------------------------
/packages/server/src/store/dto/create-store.dto.ts:
--------------------------------------------------------------------------------
1 | import { InputType, Field, ID } from '@nestjs/graphql';
2 | import { IsNotEmpty, IsString } from 'class-validator';
3 |
4 | @InputType()
5 | export class CreateStoreDto {
6 | @Field()
7 | @IsString()
8 | @IsNotEmpty({ message: 'Field required ' })
9 | readonly name: string;
10 |
11 | @Field()
12 | @IsString()
13 | @IsNotEmpty({ message: 'Field required ' })
14 | readonly bio: string;
15 |
16 | @Field()
17 | @IsString()
18 | @IsNotEmpty({ message: 'Field required ' })
19 | readonly slug: string;
20 |
21 | @Field()
22 | @IsString()
23 | @IsNotEmpty({ message: 'Field required ' })
24 | readonly street: string;
25 |
26 | @Field()
27 | @IsString()
28 | @IsNotEmpty({ message: 'Field required ' })
29 | readonly city: string;
30 |
31 | @Field()
32 | @IsString()
33 | @IsNotEmpty({ message: 'Field required ' })
34 | readonly state: string;
35 |
36 | @Field()
37 | @IsString()
38 | @IsNotEmpty({ message: 'Field required ' })
39 | readonly country: string;
40 |
41 | @Field()
42 | @IsString()
43 | @IsNotEmpty({ message: 'Field required ' })
44 | readonly neighborhood: string;
45 |
46 | @Field()
47 | @IsString()
48 | @IsNotEmpty({ message: 'Field required ' })
49 | readonly zipCode: string;
50 |
51 | @Field()
52 | @IsString()
53 | @IsNotEmpty({ message: 'Field required ' })
54 | readonly number: string;
55 |
56 | @Field(() => [ID], {
57 | nullable: true,
58 | })
59 | readonly employeesId: string[];
60 | }
61 |
--------------------------------------------------------------------------------
/packages/design-system/lib/web/Button/DefaultButton.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | var __makeTemplateObject = (this && this.__makeTemplateObject) || function (cooked, raw) {
3 | if (Object.defineProperty) { Object.defineProperty(cooked, "raw", { value: raw }); } else { cooked.raw = raw; }
4 | return cooked;
5 | };
6 | var __importDefault = (this && this.__importDefault) || function (mod) {
7 | return (mod && mod.__esModule) ? mod : { "default": mod };
8 | };
9 | exports.__esModule = true;
10 | var styled_components_1 = __importDefault(require("styled-components"));
11 | var DefaultButton = styled_components_1["default"].button(templateObject_1 || (templateObject_1 = __makeTemplateObject(["\n padding: 15px 55px;\n border: none;\n border-radius: 6px;\n width: ", ";\n text-align: center;\n font-family: proxima-nova, sans-serif;\n font-size: ", ";\n cursor: pointer;\n\n &:hover {\n box-shadow: ", ";\n opacity: ", "\n }\n"], ["\n padding: 15px 55px;\n border: none;\n border-radius: 6px;\n width: ", ";\n text-align: center;\n font-family: proxima-nova, sans-serif;\n font-size: ", ";\n cursor: pointer;\n\n &:hover {\n box-shadow: ", ";\n opacity: ", "\n }\n"])), function (props) { return (props.full ? '100%' : 'auto'); }, function (_a) {
12 | var theme = _a.theme;
13 | return theme.fonts.sizes.body;
14 | }, function (props) { return (props.secondary ? 'none' : '0px 11px 16px rgba(40, 245, 190, 0.2)'); }, function (props) { return (props.secondary ? 0.8 : 1); });
15 | exports["default"] = DefaultButton;
16 | var templateObject_1;
17 |
--------------------------------------------------------------------------------
/packages/design-system/lib/Button/web/DefaultButton.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | var __makeTemplateObject = (this && this.__makeTemplateObject) || function (cooked, raw) {
3 | if (Object.defineProperty) { Object.defineProperty(cooked, "raw", { value: raw }); } else { cooked.raw = raw; }
4 | return cooked;
5 | };
6 | var __importDefault = (this && this.__importDefault) || function (mod) {
7 | return (mod && mod.__esModule) ? mod : { "default": mod };
8 | };
9 | exports.__esModule = true;
10 | var styled_components_1 = __importDefault(require("styled-components"));
11 | var theme_1 = __importDefault(require("../../theme"));
12 | var DefaultButton = styled_components_1["default"].button(templateObject_1 || (templateObject_1 = __makeTemplateObject(["\n padding: 15px 55px;\n border: none;\n border-radius: 6px;\n width: ", ";\n text-align: center;\n font-family: proxima-nova, sans-serif;\n font-size: ", ";\n cursor: pointer;\n\n &:hover {\n box-shadow: ", ";\n opacity: ", "\n }\n"], ["\n padding: 15px 55px;\n border: none;\n border-radius: 6px;\n width: ", ";\n text-align: center;\n font-family: proxima-nova, sans-serif;\n font-size: ", ";\n cursor: pointer;\n\n &:hover {\n box-shadow: ", ";\n opacity: ", "\n }\n"])), function (props) { return (props.full ? '100%' : 'auto'); }, theme_1["default"].fonts.sizes.body, function (props) { return (props.secondary ? 'none' : '0px 11px 16px rgba(40, 245, 190, 0.2)'); }, function (props) { return (props.secondary ? 0.8 : 1); });
13 | exports["default"] = DefaultButton;
14 | var templateObject_1;
15 |
--------------------------------------------------------------------------------
/packages/mobile/android/app/_BUCK:
--------------------------------------------------------------------------------
1 | # To learn about Buck see [Docs](https://buckbuild.com/).
2 | # To run your application with Buck:
3 | # - install Buck
4 | # - `npm start` - to start the packager
5 | # - `cd android`
6 | # - `keytool -genkey -v -keystore keystores/debug.keystore -storepass android -alias androiddebugkey -keypass android -dname "CN=Android Debug,O=Android,C=US"`
7 | # - `./gradlew :app:copyDownloadableDepsToLibs` - make all Gradle compile dependencies available to Buck
8 | # - `buck install -r android/app` - compile, install and run application
9 | #
10 |
11 | load(":build_defs.bzl", "create_aar_targets", "create_jar_targets")
12 |
13 | lib_deps = []
14 |
15 | create_aar_targets(glob(["libs/*.aar"]))
16 |
17 | create_jar_targets(glob(["libs/*.jar"]))
18 |
19 | android_library(
20 | name = "all-libs",
21 | exported_deps = lib_deps,
22 | )
23 |
24 | android_library(
25 | name = "app-code",
26 | srcs = glob([
27 | "src/main/java/**/*.java",
28 | ]),
29 | deps = [
30 | ":all-libs",
31 | ":build_config",
32 | ":res",
33 | ],
34 | )
35 |
36 | android_build_config(
37 | name = "build_config",
38 | package = "com.mobile",
39 | )
40 |
41 | android_resource(
42 | name = "res",
43 | package = "com.mobile",
44 | res = "src/main/res",
45 | )
46 |
47 | android_binary(
48 | name = "app",
49 | keystore = "//android/keystores:debug",
50 | manifest = "src/main/AndroidManifest.xml",
51 | package_type = "debug",
52 | deps = [
53 | ":app-code",
54 | ],
55 | )
56 |
--------------------------------------------------------------------------------
/packages/server/src/app.module.ts:
--------------------------------------------------------------------------------
1 | import { Module } from '@nestjs/common';
2 | import { GraphQLModule } from '@nestjs/graphql';
3 | import { TypeOrmModule } from '@nestjs/typeorm';
4 | import { ConfigModule } from '@nestjs/config';
5 | import { join } from 'path';
6 |
7 | import { UserModule } from '@user/user.module';
8 | import { AuthModule } from '@auth/auth.module';
9 | import { ProductModule } from '@product/product.module';
10 | import { StoreModule } from '@store/store.module';
11 | import { AttributeModule } from '@attribute/attribute.module';
12 | import { CategoryModule } from '@category/category.module';
13 |
14 | import { AppController } from './app.controller';
15 |
16 | @Module({
17 | imports: [
18 | ConfigModule.forRoot({
19 | envFilePath: ['.env.development', '.env.production'],
20 | }),
21 | GraphQLModule.forRoot({
22 | autoSchemaFile: join(process.cwd(), 'src/graphql/schemas/schema.gql'),
23 | context: ({ req }) => ({ req }),
24 | }),
25 | TypeOrmModule.forRoot({
26 | type: 'postgres',
27 | host: process.env.DATABASE_HOST,
28 | port: (process.env.DATABASE_PORT as unknown) as number,
29 | username: process.env.DATABASE_USER,
30 | password: process.env.DATABASE_PASSWORD,
31 | database: process.env.DATABASE_NAME,
32 | autoLoadEntities: true,
33 | synchronize: true,
34 | }),
35 | UserModule,
36 | AuthModule,
37 | ProductModule,
38 | AttributeModule,
39 | StoreModule,
40 | CategoryModule,
41 | ],
42 | controllers: [AppController],
43 | })
44 | export class AppModule {}
45 |
--------------------------------------------------------------------------------
/packages/server/src/shared/pipes/validation.pipe.ts:
--------------------------------------------------------------------------------
1 | import {
2 | PipeTransform,
3 | ArgumentMetadata,
4 | BadRequestException,
5 | HttpStatus,
6 | Injectable,
7 | } from '@nestjs/common';
8 | import { validate } from 'class-validator';
9 | import { plainToClass } from 'class-transformer';
10 | import { HttpException } from '@nestjs/common/exceptions/http.exception';
11 |
12 | @Injectable()
13 | export class ValidationPipe implements PipeTransform {
14 | async transform(value, metadata: ArgumentMetadata) {
15 | if (!value) {
16 | throw new BadRequestException('No data submitted');
17 | }
18 |
19 | const { metatype } = metadata;
20 | if (!metatype || !this.toValidate(metatype)) {
21 | return value;
22 | }
23 | const object = plainToClass(metatype, value);
24 | const errors = await validate(object);
25 | if (errors.length > 0) {
26 | throw new HttpException(
27 | { message: 'Input data validation failed', errors: this.buildError(errors) },
28 | HttpStatus.BAD_REQUEST,
29 | );
30 | }
31 | return value;
32 | }
33 |
34 | private buildError(errors) {
35 | const result = {};
36 | errors.forEach(el => {
37 | const prop = el.property;
38 | Object.entries(el.constraints).forEach(constraint => {
39 | result[prop + constraint[0]] = `${constraint[1]}`;
40 | });
41 | });
42 | return result;
43 | }
44 |
45 | private toValidate(metatype): boolean {
46 | const types = [String, Boolean, Number, Array, Object];
47 | return !types.find(type => metatype === type);
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/.github/stale.yml:
--------------------------------------------------------------------------------
1 | # Configuration for probot-stale based on: https://github.com/facebook/react-native/blob/master/.github/stale.yml
2 |
3 | # Number of days of inactivity before an Issue or Pull Request becomes stale
4 | daysUntilStale: 30
5 |
6 | # Number of days of inactivity before an Issue or Pull Request with the stale label is closed.
7 | daysUntilClose: 7
8 |
9 | # Issues or Pull Requests with these labels will never be considered stale. Set to `[]` to disable
10 | exemptLabels:
11 | - pinned
12 | - security
13 | - discussion
14 | - good first issue
15 | - "help wanted"
16 |
17 | # Set to true to ignore issues in a project (defaults to false)
18 | exemptProjects: false
19 |
20 | # Set to true to ignore issues in a milestone (defaults to false)
21 | exemptMilestones: false
22 |
23 | # Set to true to ignore issues with an assignee (defaults to false)
24 | exemptAssignees: false
25 |
26 | # Label to use when marking as stale
27 | staleLabel: stale
28 |
29 | # Comment to post when marking as stale. Set to `false` to disable
30 | markComment: >
31 | This issue has been automatically marked as stale because it has not had
32 | recent activity. It will be closed if no further activity occurs. Thank you
33 | for your contributions. You may also mark this issue as a "discussion" and i
34 | will leave this open.
35 | # Comment to post when closing a stale Issue or Pull Request.
36 | closeComment: >
37 | Closing this issue after a prolonged period of inactivity. Fell free to reopen
38 | this issue, if this still affecting you.
39 | # Limit the number of actions per hour, from 1-30. Default is 30
40 | limitPerRun: 30
41 |
42 | # Limit to only `issues` or `pulls`
43 | only: issues
44 |
--------------------------------------------------------------------------------
/packages/design-system/lib/web/Grid/index.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | var __assign = (this && this.__assign) || function () {
3 | __assign = Object.assign || function(t) {
4 | for (var s, i = 1, n = arguments.length; i < n; i++) {
5 | s = arguments[i];
6 | for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
7 | t[p] = s[p];
8 | }
9 | return t;
10 | };
11 | return __assign.apply(this, arguments);
12 | };
13 | var __rest = (this && this.__rest) || function (s, e) {
14 | var t = {};
15 | for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
16 | t[p] = s[p];
17 | if (s != null && typeof Object.getOwnPropertySymbols === "function")
18 | for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
19 | if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
20 | t[p[i]] = s[p[i]];
21 | }
22 | return t;
23 | };
24 | var __importDefault = (this && this.__importDefault) || function (mod) {
25 | return (mod && mod.__esModule) ? mod : { "default": mod };
26 | };
27 | exports.__esModule = true;
28 | var react_1 = __importDefault(require("react"));
29 | var styles_1 = __importDefault(require("./styles"));
30 | // import Skeleton from '../Skeleton';
31 | var Grid = function (_a) {
32 | var children = _a.children, skeleton = _a.skeleton, skeletonHeight = _a.skeletonHeight, skeletonWidth = _a.skeletonWidth, rest = __rest(_a, ["children", "skeleton", "skeletonHeight", "skeletonWidth"]);
33 | return (react_1["default"].createElement(styles_1["default"], __assign({}, rest), children));
34 | };
35 | exports["default"] = Grid;
36 |
--------------------------------------------------------------------------------
/packages/server/src/product/product.resolver.ts:
--------------------------------------------------------------------------------
1 | import { UseGuards } from '@nestjs/common';
2 | import { Resolver, Args, Mutation, Query } from '@nestjs/graphql';
3 |
4 | import { ProductService } from '@product/product.service';
5 | import { Product } from '@product/product.entity';
6 | import {
7 | CreateProductDto,
8 | LinkAttributeToProductDto,
9 | LinkCategoryToProductDto,
10 | } from '@product/dto';
11 |
12 | import { GqlAuthGuard } from '@auth/auth.guard';
13 |
14 | @Resolver()
15 | export class ProductResolver {
16 | constructor(private productService: ProductService) {}
17 |
18 | @UseGuards(GqlAuthGuard)
19 | @Mutation(() => Product)
20 | async createProduct(@Args('data') data: CreateProductDto): Promise {
21 | const product = await this.productService.create(data);
22 |
23 | return product;
24 | }
25 |
26 | @UseGuards(GqlAuthGuard)
27 | @Query(() => [Product], {
28 | nullable: true,
29 | })
30 | async getAllProducts(): Promise {
31 | const products = await this.productService.findAll();
32 |
33 | return products;
34 | }
35 |
36 | @UseGuards(GqlAuthGuard)
37 | @Mutation(() => Product, {
38 | nullable: true,
39 | })
40 | async linkAttributeToProduct(@Args('data') data: LinkAttributeToProductDto): Promise {
41 | const product = await this.productService.linkAttribute(data);
42 |
43 | return product;
44 | }
45 |
46 | @UseGuards(GqlAuthGuard)
47 | @Mutation(() => Product, {
48 | nullable: true,
49 | })
50 | async linkCategoryToProduct(@Args('data') data: LinkCategoryToProductDto): Promise {
51 | const product = await this.productService.linkCategory(data);
52 |
53 | return product;
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/packages/mobile/ios/mobile-tvOS/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | APPL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1
23 | LSRequiresIPhoneOS
24 |
25 | NSAppTransportSecurity
26 |
27 | NSExceptionDomains
28 |
29 | localhost
30 |
31 | NSExceptionAllowsInsecureHTTPLoads
32 |
33 |
34 |
35 |
36 | NSLocationWhenInUseUsageDescription
37 |
38 | UILaunchStoryboardName
39 | LaunchScreen
40 | UIRequiredDeviceCapabilities
41 |
42 | armv7
43 |
44 | UISupportedInterfaceOrientations
45 |
46 | UIInterfaceOrientationPortrait
47 | UIInterfaceOrientationLandscapeLeft
48 | UIInterfaceOrientationLandscapeRight
49 |
50 | UIViewControllerBasedStatusBarAppearance
51 |
52 |
53 |
54 |
--------------------------------------------------------------------------------
/packages/design-system/src/web/Button/story/Button.story.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { storiesOf } from '@storybook/react';
3 | import { text, select } from '@storybook/addon-knobs';
4 |
5 | import DefaultButton from '../DefaultButton';
6 | import { Grid } from '../..';
7 |
8 | import { TButtonVariants } from '../DefaultButton/interface';
9 |
10 | const stories = storiesOf('Button', module);
11 |
12 | stories
13 | .addParameters({
14 | component: DefaultButton,
15 | })
16 | .add('Default Button', () => {
17 | const buttonText = text('Name', 'Buy');
18 | const label = 'Variant';
19 | const options: TButtonVariants[] = ['primary', 'secondary'];
20 | const buttonVariant: TButtonVariants = select(label, options, 'primary');
21 |
22 | return (
23 |
24 | console.log('Hey, you jest clicked me!')}
28 | />
29 |
30 | );
31 | })
32 | .add('Default Button Disabled', () => {
33 | const buttonText = text('Name', 'Buy');
34 | const label = 'Variant';
35 | const options: TButtonVariants[] = ['primary', 'secondary'];
36 | const buttonVariant: TButtonVariants = select(label, options, 'primary');
37 |
38 | return (
39 |
40 | console.log('Hey, you jest clicked me!')}
44 | disabled
45 | />
46 |
47 | );
48 | });
49 |
--------------------------------------------------------------------------------
/packages/design-system/lib/Button/web/OutlinedButton.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | var __makeTemplateObject = (this && this.__makeTemplateObject) || function (cooked, raw) {
3 | if (Object.defineProperty) { Object.defineProperty(cooked, "raw", { value: raw }); } else { cooked.raw = raw; }
4 | return cooked;
5 | };
6 | var __importDefault = (this && this.__importDefault) || function (mod) {
7 | return (mod && mod.__esModule) ? mod : { "default": mod };
8 | };
9 | exports.__esModule = true;
10 | var styled_components_1 = __importDefault(require("styled-components"));
11 | var theme_1 = __importDefault(require("../../theme"));
12 | var DefaultButton_1 = __importDefault(require("./DefaultButton"));
13 | var OutlinedButton = styled_components_1["default"](DefaultButton_1["default"])(templateObject_1 || (templateObject_1 = __makeTemplateObject(["\n border: 1px solid ", ";\n color: ", ";\n font-weight: ", ";\n background-color: transparent;\n\n &:hover {\n background-color: ", ";\n color: ", ";\n }\n"], ["\n border: 1px solid ", ";\n color: ", ";\n font-weight: ", ";\n background-color: transparent;\n\n &:hover {\n background-color: ", ";\n color: ", ";\n }\n"])), function (props) { return (props.secondary ? theme_1["default"].colors.secondary : theme_1["default"].colors.primary); }, function (props) { return (props.secondary ? theme_1["default"].colors.secondary : theme_1["default"].colors.primary); }, theme_1["default"].fonts.weight.semiBold, function (props) { return (props.secondary ? theme_1["default"].colors.secondary : theme_1["default"].colors.primary); }, function (props) { return (props.secondary ? theme_1["default"].colors.white : theme_1["default"].colors.black); });
14 | exports["default"] = OutlinedButton;
15 | var templateObject_1;
16 |
--------------------------------------------------------------------------------
/packages/web/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "web",
3 | "version": "0.0.1",
4 | "private": true,
5 | "dependencies": {
6 | "@react-shop/design-system": "*",
7 | "@react-shop/sdk": "*",
8 | "react-redux": "^7.1.3",
9 | "react-router-dom": "^4.2.2",
10 | "react-slick": "^0.23.2",
11 | "redux": "^4.0.5",
12 | "redux-actions": "^2.6.4",
13 | "redux-promise-middleware": "^5.0.0",
14 | "redux-saga": "^1.1.3",
15 | "react-scripts": "3.2.0",
16 | "slick-carousel": "^1.8.1"
17 | },
18 | "devDependencies": {
19 | "@types/jest": "^24.0.25",
20 | "@types/node": "^13.1.1",
21 | "@types/react-redux": "^7.1.5",
22 | "@types/react-router-dom": "^5.1.3",
23 | "@typescript-eslint/eslint-plugin": "^2.13.0",
24 | "@typescript-eslint/parser": "^2.13.0",
25 | "eslint": "^6.8.0",
26 | "eslint-config-airbnb": "^18.0.1",
27 | "eslint-config-prettier": "^6.8.0",
28 | "eslint-import-resolver-typescript": "^2.0.0",
29 | "eslint-plugin-import": "^2.19.1",
30 | "eslint-plugin-json": "^2.0.1",
31 | "eslint-plugin-jsx-a11y": "^6.2.3",
32 | "eslint-plugin-prettier": "^3.1.2",
33 | "eslint-plugin-react": "^7.17.0",
34 | "prettier": "^1.19.1"
35 | },
36 | "scripts": {
37 | "start": "react-scripts start",
38 | "build": "react-scripts build",
39 | "test": "react-scripts test --env=jsdom",
40 | "eject": "react-scripts eject",
41 | "lint": "eslint . --ext .js,.jsx,.ts,.tsx"
42 | },
43 | "browserslist": {
44 | "production": [
45 | ">0.2%",
46 | "not dead",
47 | "not op_mini all"
48 | ],
49 | "development": [
50 | "last 1 chrome version",
51 | "last 1 firefox version",
52 | "last 1 safari version"
53 | ]
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/packages/design-system/lib/web/Button/OutlinedButton.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | var __makeTemplateObject = (this && this.__makeTemplateObject) || function (cooked, raw) {
3 | if (Object.defineProperty) { Object.defineProperty(cooked, "raw", { value: raw }); } else { cooked.raw = raw; }
4 | return cooked;
5 | };
6 | var __importDefault = (this && this.__importDefault) || function (mod) {
7 | return (mod && mod.__esModule) ? mod : { "default": mod };
8 | };
9 | exports.__esModule = true;
10 | var styled_components_1 = __importDefault(require("styled-components"));
11 | var DefaultButton_1 = __importDefault(require("./DefaultButton"));
12 | var OutlinedButton = styled_components_1["default"](DefaultButton_1["default"])(templateObject_1 || (templateObject_1 = __makeTemplateObject(["\n border: 1px solid ", ";\n color: ", ";\n font-weight: ", ";\n background-color: transparent;\n\n &:hover {\n background-color: ", ";\n color: ", ";\n }\n"], ["\n border: 1px solid ", ";\n color: ", ";\n font-weight: ", ";\n background-color: transparent;\n\n &:hover {\n background-color: ", ";\n color: ", ";\n }\n"])), function (_a) {
13 | var secondary = _a.secondary, theme = _a.theme;
14 | return (secondary ? theme.colors.secondary : theme.colors.primary);
15 | }, function (_a) {
16 | var secondary = _a.secondary, theme = _a.theme;
17 | return (secondary ? theme.colors.secondary : theme.colors.primary);
18 | }, theme.fonts.weight.semiBold, function (_a) {
19 | var secondary = _a.secondary, theme = _a.theme;
20 | return (secondary ? theme.colors.secondary : theme.colors.primary);
21 | }, function (_a) {
22 | var secondary = _a.secondary, theme = _a.theme;
23 | return (secondary ? theme.colors.white : theme.colors.black);
24 | });
25 | exports["default"] = OutlinedButton;
26 | var templateObject_1;
27 |
--------------------------------------------------------------------------------
/packages/design-system/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@react-shop/design-system",
3 | "version": "0.0.1",
4 | "private": true,
5 | "description": "a UI library for react-ecommerce",
6 | "main": "./lib/index.js",
7 | "module": "./lib-esm/index.js",
8 | "types": "./lib/index.d.ts",
9 | "author": "Vinicius Arruda",
10 | "scripts": {
11 | "story": "start-storybook",
12 | "libbuild": "tsc && tsc --build tsconfig.esm.json",
13 | "start": "tsc && tsc --build tsconfig.esm.json -w",
14 | "test": "jest --color"
15 | },
16 | "peerDependencies": {
17 | "react": "^16.12.0",
18 | "react-dom": "^16.12.0"
19 | },
20 | "devDependencies": {
21 | "@babel/core": "^7.6.4",
22 | "@storybook/addon-a11y": "^5.2.8",
23 | "@storybook/addon-actions": "^5.3.6",
24 | "@storybook/addon-console": "^1.2.1",
25 | "@storybook/addon-docs": "^5.2.8",
26 | "@storybook/addon-knobs": "^5.2.8",
27 | "@storybook/react": "^5.2.5",
28 | "@types/enzyme": "^3.10.4",
29 | "@types/enzyme-adapter-react-16": "^1.0.5",
30 | "@types/jest": "^24.0.25",
31 | "@types/storybook__react": "^4.0.2",
32 | "@types/styled-system": "^5.1.9",
33 | "awesome-typescript-loader": "^5.2.1",
34 | "babel-loader": "^8.0.6",
35 | "enzyme": "^3.11.0",
36 | "enzyme-adapter-react-16": "^1.15.2",
37 | "enzyme-to-json": "^3.4.3",
38 | "eslint": "^6.8.0",
39 | "eslint-config-prettier": "^6.8.0",
40 | "eslint-plugin-prettier": "^3.1.2",
41 | "jest": "^24.9.0",
42 | "jest-enzyme": "^7.1.2",
43 | "prettier": "^1.19.1",
44 | "react-docgen-typescript-loader": "^3.6.0",
45 | "sass-loader": "^8.0.0",
46 | "source-map-loader": "^0.2.4",
47 | "style-loader": "^1.0.0",
48 | "ts-jest": "^24.3.0"
49 | },
50 | "dependencies": {
51 | "styled-system": "^5.1.5"
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/packages/mobile/ios/mobile/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleDisplayName
8 | mobile
9 | CFBundleExecutable
10 | $(EXECUTABLE_NAME)
11 | CFBundleIdentifier
12 | $(PRODUCT_BUNDLE_IDENTIFIER)
13 | CFBundleInfoDictionaryVersion
14 | 6.0
15 | CFBundleName
16 | $(PRODUCT_NAME)
17 | CFBundlePackageType
18 | APPL
19 | CFBundleShortVersionString
20 | 1.0
21 | CFBundleSignature
22 | ????
23 | CFBundleVersion
24 | 1
25 | LSRequiresIPhoneOS
26 |
27 | NSAppTransportSecurity
28 |
29 | NSAllowsArbitraryLoads
30 |
31 | NSExceptionDomains
32 |
33 | localhost
34 |
35 | NSExceptionAllowsInsecureHTTPLoads
36 |
37 |
38 |
39 |
40 | NSLocationWhenInUseUsageDescription
41 |
42 | UILaunchStoryboardName
43 | LaunchScreen
44 | UIRequiredDeviceCapabilities
45 |
46 | armv7
47 |
48 | UISupportedInterfaceOrientations
49 |
50 | UIInterfaceOrientationPortrait
51 | UIInterfaceOrientationLandscapeLeft
52 | UIInterfaceOrientationLandscapeRight
53 |
54 | UIViewControllerBasedStatusBarAppearance
55 |
56 |
57 |
58 |
--------------------------------------------------------------------------------
/packages/web/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
11 |
12 |
13 |
14 |
23 | React App
24 |
25 |
26 |
29 |
30 |
40 |
41 |
42 |
--------------------------------------------------------------------------------
/packages/server/src/user/user.entity.ts:
--------------------------------------------------------------------------------
1 | import { Field, ObjectType, ID, HideField, InputType } from '@nestjs/graphql';
2 | import {
3 | BeforeInsert,
4 | Column,
5 | Entity,
6 | PrimaryGeneratedColumn,
7 | CreateDateColumn,
8 | UpdateDateColumn,
9 | ManyToMany,
10 | JoinTable,
11 | } from 'typeorm';
12 | import * as bcrypt from 'bcrypt';
13 | import { IsEmail } from 'class-validator';
14 |
15 | import { Roles, Status } from '@user/user.interface';
16 | import { Store } from '@store/store.entity';
17 |
18 | @ObjectType()
19 | @InputType('UserInput')
20 | @Entity('users')
21 | export class User {
22 | @PrimaryGeneratedColumn('uuid')
23 | @Field(() => ID)
24 | id: string;
25 |
26 | @CreateDateColumn({ name: 'created_at' })
27 | createdAt: Date;
28 |
29 | @UpdateDateColumn({ name: 'updated_at' })
30 | updatedAt: Date;
31 |
32 | @Column({
33 | length: '256',
34 | })
35 | name: string;
36 |
37 | @Column({
38 | length: '100',
39 | })
40 | username: string;
41 |
42 | @Column()
43 | @IsEmail()
44 | email: string;
45 |
46 | @Column({ default: '' })
47 | bio: string;
48 |
49 | @Column({ default: '' })
50 | image: string;
51 |
52 | @Column({
53 | type: 'enum',
54 | enum: Roles,
55 | default: Roles.MEMBER,
56 | })
57 | @Field(() => Roles)
58 | role: Roles;
59 |
60 | @Column({
61 | type: 'enum',
62 | enum: Status,
63 | default: Status.ACTIVE,
64 | })
65 | @Field(() => Status)
66 | status: Status;
67 |
68 | @HideField()
69 | @Column()
70 | password: string;
71 |
72 | @ManyToMany(
73 | () => Store,
74 | (store: Store) => store.employees,
75 | )
76 | @Field(() => [Store], {
77 | nullable: true,
78 | })
79 | store: Store[];
80 |
81 | @BeforeInsert()
82 | async hashPassword() {
83 | this.password = await bcrypt.hash(this.password, 10);
84 | }
85 | }
86 |
--------------------------------------------------------------------------------
/packages/ssr/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@react-shop/ssr",
3 | "version": "0.1.0",
4 | "private": true,
5 | "scripts": {
6 | "dev": "next dev",
7 | "build": "next build",
8 | "start": "next start",
9 | "lint": "next lint"
10 | },
11 | "lint-staged": {
12 | "./src/**/*.{ts,js,jsx,tsx}": [
13 | "yarn eslint --ignore-path .gitignore \"src/**/*.+(ts|js|tsx)\" --fix",
14 | "yarn prettier --ignore-path .gitignore \"src/**/*.+(ts|js|tsx)\" --write"
15 | ]
16 | },
17 | "dependencies": {
18 | "next": "11.1.0",
19 | "react": "17.0.2",
20 | "react-dom": "17.0.2",
21 | "styled-components": "^5.3.0"
22 | },
23 | "devDependencies": {
24 | "@commitlint/cli": "13.1.0",
25 | "@commitlint/config-conventional": "13.1.0",
26 | "@types/jest": "26.0.23",
27 | "@types/node": "16.4.0",
28 | "@types/react": "17.0.14",
29 | "@types/react-dom": "17.0.9",
30 | "@types/styled-components": "^5.1.12",
31 | "@typescript-eslint/eslint-plugin": "4.28.4",
32 | "@typescript-eslint/parser": "4.28.4",
33 | "babel-plugin-styled-components": "1.13.2",
34 | "eslint": "7.31.0",
35 | "eslint-config-airbnb": "18.2.1",
36 | "eslint-config-next": "11.0.1",
37 | "eslint-config-prettier": "8.3.0",
38 | "eslint-import-resolver-typescript": "2.4.0",
39 | "eslint-plugin-import": "2.23.4",
40 | "eslint-plugin-jsx-a11y": "6.4.1",
41 | "eslint-plugin-prettier": "3.4.0",
42 | "eslint-plugin-react": "7.24.0",
43 | "eslint-plugin-react-hooks": "4.2.0",
44 | "husky": "6.0.0",
45 | "jest": "27.0.4",
46 | "jest-environment-jsdom": "27.0.3",
47 | "jest-styled-components": "7.0.4",
48 | "lint-staged": "11.0.0",
49 | "prettier": "2.3.2",
50 | "ts-jest": "27.0.3",
51 | "ts-loader": "9.2.3",
52 | "typescript": "4.3.5",
53 | "webpack": "5.45.1"
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/packages/server/src/store/store.resolver.ts:
--------------------------------------------------------------------------------
1 | import { UseGuards } from '@nestjs/common';
2 | import { Resolver, Args, Mutation, Query } from '@nestjs/graphql';
3 |
4 | import { StoreService } from '@store/store.service';
5 | import { Store } from '@store/store.entity';
6 | import { CreateStoreDto, LinkEmployeeToStoreDto, LinkProductToStoreDto } from '@store/dto';
7 |
8 | import { GqlAuthGuard } from '@auth/auth.guard';
9 |
10 | @Resolver()
11 | export class StoreResolver {
12 | constructor(private storeService: StoreService) {}
13 |
14 | @UseGuards(GqlAuthGuard)
15 | @Mutation(() => Store)
16 | async createStore(@Args('data') data: CreateStoreDto): Promise {
17 | const store = await this.storeService.create(data);
18 |
19 | return store;
20 | }
21 |
22 | @UseGuards(GqlAuthGuard)
23 | @Mutation(() => Store, {
24 | nullable: true,
25 | })
26 | async linkEmployeesToStore(@Args('data') data: LinkEmployeeToStoreDto): Promise {
27 | const store = await this.storeService.linkEmployees(data);
28 |
29 | return store;
30 | }
31 |
32 | @UseGuards(GqlAuthGuard)
33 | @Mutation(() => Store, {
34 | nullable: true,
35 | })
36 | async linkProductsToStore(@Args('data') data: LinkProductToStoreDto): Promise {
37 | const store = await this.storeService.linkProducts(data);
38 |
39 | return store;
40 | }
41 |
42 | @UseGuards(GqlAuthGuard)
43 | @Query(() => Store, {
44 | nullable: true,
45 | })
46 | async findStoreById(@Args('id') id: string): Promise {
47 | const store = await this.storeService.findById(id);
48 |
49 | return store;
50 | }
51 |
52 | @UseGuards(GqlAuthGuard)
53 | @Query(() => [Store], {
54 | nullable: true,
55 | })
56 | async getAllStores(): Promise {
57 | const stores = await this.storeService.findAll();
58 |
59 | return stores;
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/packages/server/src/store/store.entity.ts:
--------------------------------------------------------------------------------
1 | import {
2 | Entity,
3 | PrimaryGeneratedColumn,
4 | Column,
5 | ManyToMany,
6 | JoinTable,
7 | OneToMany,
8 | CreateDateColumn,
9 | UpdateDateColumn,
10 | } from 'typeorm';
11 | import { Field, ObjectType, ID, InputType } from '@nestjs/graphql';
12 |
13 | import { Product } from '@product/product.entity';
14 |
15 | import { User } from '@user/user.entity';
16 |
17 | @ObjectType()
18 | @InputType('StoreInput')
19 | @Entity()
20 | export class Store {
21 | @PrimaryGeneratedColumn('increment')
22 | @Field(() => ID)
23 | id: string;
24 |
25 | @CreateDateColumn({ name: 'created_at' })
26 | createdAt: Date;
27 |
28 | @UpdateDateColumn({ name: 'updated_at' })
29 | updatedAt: Date;
30 |
31 | @Column()
32 | name: string;
33 |
34 | @Column()
35 | bio: string;
36 |
37 | @Column({
38 | default: 0,
39 | })
40 | rate: number;
41 |
42 | @Column({
43 | unique: true,
44 | })
45 | slug: string;
46 |
47 | @Column()
48 | street: string;
49 |
50 | @Column()
51 | city: string;
52 |
53 | @Column()
54 | state: string;
55 |
56 | @Column()
57 | country: string;
58 |
59 | @Column()
60 | neighborhood: string;
61 |
62 | @Column()
63 | number: string;
64 |
65 | @Column()
66 | zipCode: string;
67 |
68 | @Column({
69 | default: 0,
70 | })
71 | sales: number;
72 |
73 | @OneToMany(
74 | () => Product,
75 | (product: Product) => product.store,
76 | {
77 | cascade: true,
78 | },
79 | )
80 | @JoinTable()
81 | @Field(() => [Product], {
82 | nullable: true,
83 | })
84 | products: Product[];
85 |
86 | @ManyToMany(
87 | () => User,
88 | (user: User) => user.store,
89 | {
90 | cascade: true,
91 | },
92 | )
93 | @JoinTable()
94 | @Field(() => [User], {
95 | nullable: true,
96 | })
97 | employees: User[];
98 | }
99 |
--------------------------------------------------------------------------------
/packages/design-system/lib/theme/index.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | var __importDefault = (this && this.__importDefault) || function (mod) {
3 | return (mod && mod.__esModule) ? mod : { "default": mod };
4 | };
5 | exports.__esModule = true;
6 | var colors_1 = __importDefault(require("./colors"));
7 | var units_1 = __importDefault(require("./units"));
8 | exports.theme = {
9 | colors: {
10 | primary: colors_1["default"].primary,
11 | secondary: colors_1["default"].secondary,
12 | primaryDark: colors_1["default"].primaryDark,
13 | error: colors_1["default"].error,
14 | black: colors_1["default"].black,
15 | blackNormal: colors_1["default"].blackNormal,
16 | blackDark: colors_1["default"].blackDark,
17 | blackLight: colors_1["default"].blackLight,
18 | white: colors_1["default"].white,
19 | gray: colors_1["default"].gray
20 | },
21 | space: {
22 | spacing1: units_1["default"].sizes.spacing1,
23 | spacing2: units_1["default"].sizes.spacing2,
24 | spacing4: units_1["default"].sizes.spacing4,
25 | spacing8: units_1["default"].sizes.spacing8,
26 | spacing10: units_1["default"].sizes.spacing10,
27 | spacing12: units_1["default"].sizes.spacing12,
28 | spacing16: units_1["default"].sizes.spacing16,
29 | spacing18: units_1["default"].sizes.spacing18,
30 | spacing20: units_1["default"].sizes.spacing20,
31 | spacing24: units_1["default"].sizes.spacing24,
32 | spacing32: units_1["default"].sizes.spacing32
33 | },
34 | radii: {
35 | xsmall: units_1["default"].borderRadius.xsmall,
36 | small: units_1["default"].borderRadius.small,
37 | medium: units_1["default"].borderRadius.medium,
38 | large: units_1["default"].borderRadius.large,
39 | full: units_1["default"].borderRadius.full
40 | }
41 | };
42 |
--------------------------------------------------------------------------------
/.github/PULL_REQUEST_TEMPLATE.md:
--------------------------------------------------------------------------------
1 | ## Pull request checklist
2 |
3 | Please check if your PR fulfills the following requirements:
4 |
5 | - [ ] Tests for the changes have been added (for bug fixes / features)
6 | - [ ] Build (`yarn build`) was run locally and any changes were pushed
7 | - [ ] Lint has passed locally and any fixes were made for failures
8 | - [ ] Code Coverage stayed the same or increased
9 |
10 | ## Pull request type
11 |
12 |
13 |
14 |
15 |
16 | Please check the type of change your PR introduces:
17 |
18 | - [ ] Bugfix
19 | - [ ] Feature
20 | - [ ] Code style update (formatting, renaming)
21 | - [ ] Refactoring (no functional changes, no api changes)
22 | - [ ] Build related changes
23 | - [ ] Tests related changes
24 | - [ ] Documentation content changes
25 | - [ ] Other (please describe):
26 |
27 | ## What is the current behavior?
28 |
29 |
30 |
31 |
32 | ## What is the new behavior?
33 |
34 |
35 |
36 | ### - Ex: Adding a new cool button at home screen
37 |
38 |
39 |
40 | ## Does this introduce a breaking change?
41 |
42 | - [ ] Yes
43 | - [ ] No
44 |
45 |
46 |
47 | ## Other information
48 |
49 |
50 |
51 | ## Screenshots (optional)
52 |
53 |
54 |
--------------------------------------------------------------------------------
/packages/server/src/category/category.service.ts:
--------------------------------------------------------------------------------
1 | import { Injectable, HttpStatus, HttpException } from '@nestjs/common';
2 | import { InjectRepository } from '@nestjs/typeorm';
3 | import { Repository, getRepository } from 'typeorm';
4 | import { validate } from 'class-validator';
5 |
6 | import { Category } from '@category/category.entity';
7 | import { CreateCategoryDto } from '@category/dto/create-category.dto';
8 |
9 | @Injectable()
10 | export class CategoryService {
11 | constructor(
12 | @InjectRepository(Category)
13 | private readonly categoryRepository: Repository,
14 | ) {}
15 |
16 | async create(dto: CreateCategoryDto): Promise {
17 | const { name, description } = dto;
18 | const qb = await getRepository(Category)
19 | .createQueryBuilder('category')
20 | .where('category.name = :name', { name });
21 |
22 | const category = await qb.getOne();
23 |
24 | if (category) {
25 | const errors = { message: 'This category already been registered' };
26 | throw new HttpException(
27 | { message: 'Input data validation failed', errors },
28 | HttpStatus.BAD_REQUEST,
29 | );
30 | }
31 |
32 | const newCategory = new Category();
33 | newCategory.name = name;
34 | newCategory.description = description;
35 |
36 | const errors = await validate(newCategory);
37 | if (errors.length > 0) {
38 | const _errors = { name: 'Name is not valid.' };
39 | throw new HttpException(
40 | { message: 'Input data validation failed', _errors },
41 | HttpStatus.BAD_REQUEST,
42 | );
43 | } else {
44 | const savedCategory = await this.categoryRepository.save(newCategory);
45 |
46 | return savedCategory;
47 | }
48 | }
49 |
50 | async findAll(): Promise {
51 | const categories = await this.categoryRepository.find();
52 |
53 | return categories;
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/packages/server/src/attribute/attribute.service.ts:
--------------------------------------------------------------------------------
1 | import { Injectable, HttpStatus, HttpException } from '@nestjs/common';
2 | import { InjectRepository } from '@nestjs/typeorm';
3 | import { Repository, getRepository } from 'typeorm';
4 | import { validate } from 'class-validator';
5 |
6 | import { Attribute } from '@attribute/attribute.entity';
7 | import { CreateAttributeDto } from '@attribute/dto/create-attribute.dto';
8 |
9 | @Injectable()
10 | export class AttributeService {
11 | constructor(
12 | @InjectRepository(Attribute)
13 | private readonly attributeRepository: Repository,
14 | ) {}
15 |
16 | async create(dto: CreateAttributeDto): Promise {
17 | const { value, name, type } = dto;
18 |
19 | const attribute = await this.attributeRepository.findOne({
20 | where: {
21 | value,
22 | },
23 | });
24 |
25 | if (attribute) {
26 | const errors = { message: 'This value already been registered' };
27 | throw new HttpException(
28 | { message: 'Input data validation failed', errors },
29 | HttpStatus.BAD_REQUEST,
30 | );
31 | }
32 |
33 | const newAttribute = new Attribute();
34 | newAttribute.name = name;
35 | newAttribute.type = type;
36 | newAttribute.value = value;
37 |
38 | const errors = await validate(newAttribute);
39 | if (errors.length > 0) {
40 | const _errors = { message: 'Value is not valid.' };
41 | throw new HttpException(
42 | { message: 'Input data validation failed', _errors },
43 | HttpStatus.BAD_REQUEST,
44 | );
45 | } else {
46 | const savedAttribute = await this.attributeRepository.save(newAttribute);
47 |
48 | return savedAttribute;
49 | }
50 | }
51 |
52 | async getAll(): Promise {
53 | const attributes = await this.attributeRepository.find({
54 | relations: ['product'],
55 | });
56 |
57 | return attributes;
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/packages/server/src/product/product.entity.ts:
--------------------------------------------------------------------------------
1 | import {
2 | Entity,
3 | PrimaryGeneratedColumn,
4 | Column,
5 | JoinTable,
6 | OneToMany,
7 | ManyToOne,
8 | CreateDateColumn,
9 | UpdateDateColumn,
10 | } from 'typeorm';
11 | import { Field, ObjectType, ID, InputType } from '@nestjs/graphql';
12 |
13 | import { Attribute } from '@attribute/attribute.entity';
14 | import { Store } from '@store/store.entity';
15 | import { Category } from '@category/category.entity';
16 | @ObjectType()
17 | @InputType('ProductInput')
18 | @Entity()
19 | export class Product {
20 | @PrimaryGeneratedColumn('increment')
21 | @Field(() => ID)
22 | id: string;
23 |
24 | @CreateDateColumn({ name: 'created_at' })
25 | createdAt: Date;
26 |
27 | @UpdateDateColumn({ name: 'updated_at' })
28 | updatedAt: Date;
29 |
30 | @Column()
31 | title: string;
32 |
33 | @Column()
34 | description: string;
35 |
36 | @Column()
37 | brand: string;
38 |
39 | @Column({
40 | unique: true,
41 | })
42 | sku: string;
43 |
44 | @Column()
45 | price: number;
46 |
47 | @Column({ default: '' })
48 | thumbnail: string;
49 |
50 | @Column({ default: '' })
51 | images: string; //TODO - array images
52 |
53 | @Column({ default: 0 })
54 | reviews: number;
55 |
56 | @Column()
57 | quantity: number;
58 |
59 | @Column()
60 | dimension: string;
61 |
62 | @OneToMany(
63 | () => Attribute,
64 | attribute => attribute.product,
65 | {
66 | cascade: true,
67 | },
68 | )
69 | @JoinTable()
70 | @Field(() => [Attribute], {
71 | nullable: true,
72 | })
73 | attributes: Attribute[];
74 |
75 | @ManyToOne(
76 | () => Store,
77 | (store: Store) => store.products,
78 | )
79 | @Field(() => Store, {
80 | nullable: true,
81 | })
82 | store: Store;
83 |
84 | @OneToMany(
85 | () => Category,
86 | category => category.products,
87 | {
88 | cascade: true,
89 | },
90 | )
91 | @JoinTable()
92 | @Field(() => [Category], {
93 | nullable: true,
94 | })
95 | categories: Category[];
96 | }
97 |
--------------------------------------------------------------------------------
/packages/mobile/ios/mobileTests/mobileTests.m:
--------------------------------------------------------------------------------
1 | #import
2 | #import
3 |
4 | #import
5 | #import
6 |
7 | #define TIMEOUT_SECONDS 600
8 | #define TEXT_TO_LOOK_FOR @"Welcome to React"
9 |
10 | @interface mobileTests : XCTestCase
11 |
12 | @end
13 |
14 | @implementation mobileTests
15 |
16 | - (BOOL)findSubviewInView:(UIView *)view matching:(BOOL(^)(UIView *view))test
17 | {
18 | if (test(view)) {
19 | return YES;
20 | }
21 | for (UIView *subview in [view subviews]) {
22 | if ([self findSubviewInView:subview matching:test]) {
23 | return YES;
24 | }
25 | }
26 | return NO;
27 | }
28 |
29 | - (void)testRendersWelcomeScreen
30 | {
31 | UIViewController *vc = [[[RCTSharedApplication() delegate] window] rootViewController];
32 | NSDate *date = [NSDate dateWithTimeIntervalSinceNow:TIMEOUT_SECONDS];
33 | BOOL foundElement = NO;
34 |
35 | __block NSString *redboxError = nil;
36 | #ifdef DEBUG
37 | RCTSetLogFunction(^(RCTLogLevel level, RCTLogSource source, NSString *fileName, NSNumber *lineNumber, NSString *message) {
38 | if (level >= RCTLogLevelError) {
39 | redboxError = message;
40 | }
41 | });
42 | #endif
43 |
44 | while ([date timeIntervalSinceNow] > 0 && !foundElement && !redboxError) {
45 | [[NSRunLoop mainRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]];
46 | [[NSRunLoop mainRunLoop] runMode:NSRunLoopCommonModes beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]];
47 |
48 | foundElement = [self findSubviewInView:vc.view matching:^BOOL(UIView *view) {
49 | if ([view.accessibilityLabel isEqualToString:TEXT_TO_LOOK_FOR]) {
50 | return YES;
51 | }
52 | return NO;
53 | }];
54 | }
55 |
56 | #ifdef DEBUG
57 | RCTSetLogFunction(RCTDefaultLogFunction);
58 | #endif
59 |
60 | XCTAssertNil(redboxError, @"RedBox error: %@", redboxError);
61 | XCTAssertTrue(foundElement, @"Couldn't find element with text '%@' in %d seconds", TEXT_TO_LOOK_FOR, TIMEOUT_SECONDS);
62 | }
63 |
64 |
65 | @end
66 |
--------------------------------------------------------------------------------
/packages/design-system/src/web/Button/DefaultButton/__tests__/__snapshots__/index.spec.tsx.snap:
--------------------------------------------------------------------------------
1 | // Jest Snapshot v1, https://goo.gl/fbAQLP
2 |
3 | exports[`Unit | DefaultButton should compare a snapshot with a disabled style 1`] = `
4 |
77 | `;
78 |
79 | exports[`Unit | DefaultButton should create snapshot 1`] = `"Press me"`;
80 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # React E-commerce
2 |
3 | This project is being restructured.
4 |
5 | ## This project is created using:
6 |
7 | - [x] Monorepo
8 | - [x] Lerna
9 | - [x] Design System
10 | - [x] NextJs (SSR)
11 | - [ ] Hooks
12 | - [ ] Redux Hooks
13 | - [x] Storybook
14 | - [x] NestJs
15 | - [x] Graphql
16 |
17 | ## Future Features
18 |
19 | - Home (List products)
20 | - Detail products
21 | - Recommended products
22 | - Cart
23 | - Login / Register
24 | - Admin (Seller)
25 | - Profile (Buyer)
26 | - Contact Us
27 | - Message between Seller and Buyer
28 | - Ratings about the Seller
29 | - Dashboard for Sellers
30 | - Notifications
31 | - Favorites
32 | - Pwa
33 | - Firebase or storage
34 | - Socket.io
35 | - App
36 | - SSR
37 |
38 | ## Sitemap
39 |
40 | ```
41 | ├── Home
42 | │
43 | ├── Social Media Links
44 | │ ├── Twitter
45 | │ ├── Instagram
46 | │ └── Facebook
47 | │
48 | ├── Shop Categories
49 | │ ├── Mens
50 | │ │ ├── T-Shirts
51 | │ │ └── Caps
52 | │ │
53 | │ ├── Womans
54 | │ │
55 | │ │
56 | │ └── News
57 | │ └── Any
58 | │
59 | ├── About Us
60 | │ └── Out Story
61 | │
62 | ├── Contact
63 | │ ├── Info/Form
64 | │ ├── Terms
65 | │ └── FAQ
66 | │
67 | ├── Account
68 | │ ├── Profile
69 | │ ├── Payment Methods
70 | │ ├── Saved Address
71 | │ ├── Order History
72 | │ └── Password
73 | │
74 | ├── Forms
75 | │ ├── Login
76 | │ ├── Register
77 | │ ├── Forgot Password
78 | │ └── Contact
79 | │
80 | └── Cart / Checkout
81 | ├── Cart Overview
82 | ├── Shipping Address
83 | ├── Billing Details
84 | ├── Payment Method
85 | └── Order Summary
86 | ```
87 |
88 | ## Run the project
89 |
90 | `yarn`
91 |
92 | `yarn start`
93 |
94 |
95 | Install dependencies in package: `cd packages/name && yarn add -W dependencie-name`
96 |
97 | ## Storybook for Design System
98 |
99 | `yarn story`
100 |
101 | ## Tests
102 |
103 | `yarn test` to run ALL packages test at the same time or `cd packages/ && yarn test`
104 |
105 | ### Lerna commands
106 |
107 | https://lerna.js.org/
108 |
109 | Api: https://github.com/viniarruda/elixir-ecommerce-api [Elixir]
110 |
111 | Enjoy!
112 |
--------------------------------------------------------------------------------
/packages/design-system/src/web/Button/DefaultButton/__tests__/index.spec.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { mountWithTheme } from '../../../../../__tests__/helpers';
3 |
4 | import DefaultButton from '..';
5 |
6 | describe('Unit | DefaultButton', () => {
7 | const onPress = jest.fn();
8 |
9 | afterEach(() => {
10 | jest.clearAllMocks();
11 | });
12 |
13 | it('should create snapshot', () => {
14 | const wrapper = mountWithTheme(
15 | ,
16 | );
17 |
18 | expect(wrapper.text()).toMatchSnapshot();
19 | });
20 |
21 | it('should render a Button with a label Press me', () => {
22 | const wrapper = mountWithTheme(
23 | ,
24 | );
25 |
26 | expect(wrapper.text()).toContain('Press me');
27 | });
28 |
29 | it('should call the onPress function one time', () => {
30 | const wrapper = mountWithTheme(
31 | ,
32 | );
33 |
34 | const onPressHandler = wrapper
35 | .find('[testID="button"]')
36 | .first()
37 | .prop('onPress') as () => void;
38 |
39 | onPressHandler();
40 |
41 | expect(onPress).toBeCalledTimes(1);
42 |
43 | wrapper.unmount();
44 | });
45 |
46 | it.skip('should render a Button with a Loading', () => {
47 | const wrapper = mountWithTheme(
48 | ,
49 | );
50 |
51 | expect(wrapper.find('[testID="loadingIndicator"]').exists()).toBeTruthy();
52 | });
53 |
54 | it.skip('should call the onPress function zero times if the button is loading', () => {
55 | const wrapper = mountWithTheme(
56 | ,
57 | );
58 |
59 | const onPressHandler = wrapper
60 | .find('[testID="button"]')
61 | .first()
62 | .prop('onPress') as () => void;
63 |
64 | onPressHandler();
65 |
66 | expect(onPress).toBeCalledTimes(0);
67 | });
68 |
69 | it('should compare a snapshot with a disabled style', () => {
70 | const wrapper = mountWithTheme(
71 | ,
72 | );
73 |
74 | expect(wrapper).toMatchSnapshot();
75 | });
76 |
77 | it.skip('should compare a snapshot with a loading style', () => {
78 | const wrapper = mountWithTheme(
79 | ,
80 | );
81 |
82 | expect(wrapper).toMatchSnapshot();
83 | });
84 | });
85 |
--------------------------------------------------------------------------------
/packages/server/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@react-shop/server",
3 | "version": "0.0.1",
4 | "description": "",
5 | "author": "",
6 | "private": true,
7 | "license": "UNLICENSED",
8 | "scripts": {
9 | "prebuild": "rimraf dist",
10 | "build": "nest build",
11 | "format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"",
12 | "start": "nest start",
13 | "dev": "nest start --watch",
14 | "start:debug": "nest start --debug --watch",
15 | "start:prod": "node dist/main",
16 | "lint": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix",
17 | "test": "jest",
18 | "test:watch": "jest --watch",
19 | "test:cov": "jest --coverage",
20 | "test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand",
21 | "test:e2e": "jest --config ./test/jest-e2e.json"
22 | },
23 | "dependencies": {
24 | "@nestjs/common": "^8.0.0",
25 | "@nestjs/config": "^1.0.1",
26 | "@nestjs/core": "^8.0.0",
27 | "@nestjs/graphql": "^9.0.2",
28 | "@nestjs/jwt": "^8.0.0",
29 | "@nestjs/passport": "^8.0.1",
30 | "@nestjs/platform-express": "^8.0.0",
31 | "@nestjs/swagger": "^5.0.9",
32 | "@nestjs/typeorm": "^8.0.2",
33 | "apollo-server-express": "^3.3.0",
34 | "bcrypt": "^5.0.1",
35 | "class-transformer": "^0.4.0",
36 | "class-validator": "^0.13.1",
37 | "graphql": "^15.5.1",
38 | "passport": "^0.4.1",
39 | "passport-jwt": "^4.0.0",
40 |
41 | "pg": "^8.7.1",
42 | "reflect-metadata": "^0.1.13",
43 | "rimraf": "^3.0.2",
44 | "rxjs": "^7.2.0",
45 | "swagger-ui-express": "^4.1.6",
46 | "typeorm": "^0.2.37"
47 | },
48 | "devDependencies": {
49 | "@nestjs/cli": "^8.0.0",
50 | "@nestjs/schematics": "^8.0.0",
51 | "@nestjs/testing": "^8.0.0",
52 | "@types/bcrypt": "^5.0.0",
53 | "@types/express": "^4.17.13",
54 | "@types/jest": "^26.0.24",
55 | "@types/node": "^16.0.0",
56 | "@types/passport-jwt": "^3.0.6",
57 | "@types/supertest": "^2.0.11",
58 | "@typescript-eslint/eslint-plugin": "^4.28.2",
59 | "@typescript-eslint/parser": "^4.28.2",
60 | "eslint": "^7.30.0",
61 | "eslint-config-prettier": "^8.3.0",
62 | "eslint-plugin-prettier": "^3.4.0",
63 | "jest": "27.0.6",
64 | "prettier": "^2.3.2",
65 | "supertest": "^6.1.3",
66 | "ts-jest": "^27.0.3",
67 | "ts-loader": "^9.2.3",
68 | "ts-node": "^10.0.0",
69 | "tsconfig-paths": "^3.10.1",
70 | "typescript": "^4.3.5"
71 | },
72 | "jest": {
73 | "moduleFileExtensions": [
74 | "js",
75 | "json",
76 | "ts"
77 | ],
78 | "rootDir": "src",
79 | "testRegex": ".*\\.spec\\.ts$",
80 | "transform": {
81 | "^.+\\.(t|j)s$": "ts-jest"
82 | },
83 | "collectCoverageFrom": [
84 | "**/*.(t|j)s"
85 | ],
86 | "coverageDirectory": "../coverage",
87 | "testEnvironment": "node"
88 | }
89 | }
90 |
--------------------------------------------------------------------------------
/packages/mobile/ios/mobile/AppDelegate.m:
--------------------------------------------------------------------------------
1 | #import "AppDelegate.h"
2 |
3 | #import
4 | #import
5 | #import
6 |
7 | #ifdef FB_SONARKIT_ENABLED
8 | #import
9 | #import
10 | #import
11 | #import
12 | #import
13 | #import
14 |
15 | static void InitializeFlipper(UIApplication *application) {
16 | FlipperClient *client = [FlipperClient sharedClient];
17 | SKDescriptorMapper *layoutDescriptorMapper =
18 | [[SKDescriptorMapper alloc] initWithDefaults];
19 | [client addPlugin:[[FlipperKitLayoutPlugin alloc]
20 | initWithRootNode:application
21 | withDescriptorMapper:layoutDescriptorMapper]];
22 | [client addPlugin:[[FKUserDefaultsPlugin alloc] initWithSuiteName:nil]];
23 | [client addPlugin:[FlipperKitReactPlugin new]];
24 | [client addPlugin:[[FlipperKitNetworkPlugin alloc]
25 | initWithNetworkAdapter:[SKIOSNetworkAdapter new]]];
26 | [client start];
27 | }
28 | #endif
29 |
30 | @implementation AppDelegate
31 |
32 | - (BOOL)application:(UIApplication *)application
33 | didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
34 | #ifdef FB_SONARKIT_ENABLED
35 | InitializeFlipper(application);
36 | #endif
37 |
38 | RCTBridge *bridge = [[RCTBridge alloc] initWithDelegate:self
39 | launchOptions:launchOptions];
40 | RCTRootView *rootView = [[RCTRootView alloc] initWithBridge:bridge
41 | moduleName:@"mobile"
42 | initialProperties:nil];
43 |
44 | rootView.backgroundColor = [[UIColor alloc] initWithRed:1.0f
45 | green:1.0f
46 | blue:1.0f
47 | alpha:1];
48 |
49 | self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
50 | UIViewController *rootViewController = [UIViewController new];
51 | rootViewController.view = rootView;
52 | self.window.rootViewController = rootViewController;
53 | [self.window makeKeyAndVisible];
54 | return YES;
55 | }
56 |
57 | - (NSURL *)sourceURLForBridge:(RCTBridge *)bridge {
58 | #ifdef FB_SONARKIT_ENABLED
59 | return
60 | [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index"
61 | fallbackResource:nil];
62 | #else
63 | return [[NSBundle mainBundle] URLForResource:@"main"
64 | withExtension:@"jsbundle"];
65 | #endif
66 | }
67 |
68 | @end
69 |
--------------------------------------------------------------------------------
/packages/mobile/android/app/src/main/java/com/mobile/MainApplication.java:
--------------------------------------------------------------------------------
1 | package com.mobile;
2 |
3 | import android.app.Application;
4 | import android.content.Context;
5 | import com.facebook.react.PackageList;
6 | import com.facebook.react.ReactApplication;
7 | import com.facebook.react.ReactInstanceManager;
8 | import com.facebook.react.ReactNativeHost;
9 | import com.facebook.react.ReactPackage;
10 | import com.facebook.soloader.SoLoader;
11 | import java.lang.reflect.InvocationTargetException;
12 | import java.util.List;
13 |
14 | public class MainApplication extends Application implements ReactApplication {
15 |
16 | private final ReactNativeHost mReactNativeHost =
17 | new ReactNativeHost(this) {
18 | @Override
19 | public boolean getUseDeveloperSupport() {
20 | return BuildConfig.DEBUG;
21 | }
22 |
23 | @Override
24 | protected List getPackages() {
25 | @SuppressWarnings("UnnecessaryLocalVariable")
26 | List packages = new PackageList(this).getPackages();
27 | // Packages that cannot be autolinked yet can be added manually here, for example:
28 | // packages.add(new MyReactNativePackage());
29 | return packages;
30 | }
31 |
32 | @Override
33 | protected String getJSMainModuleName() {
34 | return "index";
35 | }
36 | };
37 |
38 | @Override
39 | public ReactNativeHost getReactNativeHost() {
40 | return mReactNativeHost;
41 | }
42 |
43 | @Override
44 | public void onCreate() {
45 | super.onCreate();
46 | SoLoader.init(this, /* native exopackage */ false);
47 | initializeFlipper(this, getReactNativeHost().getReactInstanceManager());
48 | }
49 |
50 | /**
51 | * Loads Flipper in React Native templates. Call this in the onCreate method with something like
52 | * initializeFlipper(this, getReactNativeHost().getReactInstanceManager());
53 | *
54 | * @param context
55 | * @param reactInstanceManager
56 | */
57 | private static void initializeFlipper(
58 | Context context, ReactInstanceManager reactInstanceManager) {
59 | if (BuildConfig.DEBUG) {
60 | try {
61 | /*
62 | We use reflection here to pick up the class that initializes Flipper,
63 | since Flipper library is not available in release mode
64 | */
65 | Class> aClass = Class.forName("com.mobile.ReactNativeFlipper");
66 | aClass
67 | .getMethod("initializeFlipper", Context.class, ReactInstanceManager.class)
68 | .invoke(null, context, reactInstanceManager);
69 | } catch (ClassNotFoundException e) {
70 | e.printStackTrace();
71 | } catch (NoSuchMethodException e) {
72 | e.printStackTrace();
73 | } catch (IllegalAccessException e) {
74 | e.printStackTrace();
75 | } catch (InvocationTargetException e) {
76 | e.printStackTrace();
77 | }
78 | }
79 | }
80 | }
81 |
--------------------------------------------------------------------------------
/packages/server/src/user/user.service.ts:
--------------------------------------------------------------------------------
1 | import { Injectable, HttpStatus, HttpException } from '@nestjs/common';
2 | import { InjectRepository } from '@nestjs/typeorm';
3 | import { Repository, getRepository } from 'typeorm';
4 | import { validate } from 'class-validator';
5 |
6 | import { User } from '@user/user.entity';
7 | import { Status, UserData } from '@user/user.interface';
8 | import { CreateUserDto } from '@user/dto';
9 |
10 | @Injectable()
11 | export class UserService {
12 | constructor(
13 | @InjectRepository(User)
14 | private readonly userRepository: Repository,
15 | ) {}
16 |
17 | async findByEmail(email: string): Promise {
18 | const user = await this.userRepository.findOne({ email: email });
19 |
20 | return user;
21 | }
22 |
23 | async findById(id: string): Promise {
24 | const user = await this.userRepository.findOne(id);
25 |
26 | if (!user) {
27 | const errors = { message: 'User not found' };
28 | throw new HttpException({ errors }, HttpStatus.BAD_REQUEST);
29 | }
30 |
31 | return user;
32 | }
33 |
34 | async create(dto: CreateUserDto): Promise {
35 | // check uniqueness of username/email
36 | const { username, email, password, name, confirmPassword } = dto;
37 | const qb = await getRepository(User)
38 | .createQueryBuilder('user')
39 | .where('user.username = :username', { username })
40 | .orWhere('user.email = :email', { email });
41 |
42 | const user = await qb.getOne();
43 |
44 | if (user) {
45 | const errors = { message: 'Username and email must be unique.' };
46 | throw new HttpException(
47 | { message: 'Input data validation failed', errors },
48 | HttpStatus.BAD_REQUEST,
49 | );
50 | }
51 |
52 | if (password !== confirmPassword) {
53 | throw new HttpException({ message: 'The password must be equals' }, HttpStatus.BAD_REQUEST);
54 | }
55 |
56 | // create new user
57 | const newUser = new User();
58 | newUser.username = username;
59 | newUser.email = email;
60 | newUser.password = password;
61 | newUser.name = name;
62 |
63 | const errors = await validate(newUser);
64 | if (errors.length > 0) {
65 | const _errors = { message: 'Userinput is not valid.' };
66 | throw new HttpException(
67 | { message: 'Input data validation failed', _errors },
68 | HttpStatus.BAD_REQUEST,
69 | );
70 | } else {
71 | const savedUser = await this.userRepository.save(newUser);
72 |
73 | return savedUser;
74 | }
75 | }
76 |
77 | async delete(id: string): Promise {
78 | const user = await this.userRepository.findOne(id);
79 |
80 | if (!user) {
81 | const errors = { message: 'User not found' };
82 | throw new HttpException({ errors }, HttpStatus.BAD_REQUEST);
83 | }
84 |
85 | await this.userRepository.update(id, { status: Status.DISABLED });
86 |
87 | return user;
88 | }
89 | }
90 |
--------------------------------------------------------------------------------
/packages/sdk/lib/products/product.provider.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3 | function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4 | return new (P || (P = Promise))(function (resolve, reject) {
5 | function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6 | function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7 | function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8 | step((generator = generator.apply(thisArg, _arguments || [])).next());
9 | });
10 | };
11 | var __generator = (this && this.__generator) || function (thisArg, body) {
12 | var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
13 | return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
14 | function verb(n) { return function (v) { return step([n, v]); }; }
15 | function step(op) {
16 | if (f) throw new TypeError("Generator is already executing.");
17 | while (_) try {
18 | if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
19 | if (y = 0, t) op = [op[0] & 2, t.value];
20 | switch (op[0]) {
21 | case 0: case 1: t = op; break;
22 | case 4: _.label++; return { value: op[1], done: false };
23 | case 5: _.label++; y = op[1]; op = [0]; continue;
24 | case 7: op = _.ops.pop(); _.trys.pop(); continue;
25 | default:
26 | if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
27 | if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
28 | if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
29 | if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
30 | if (t[2]) _.ops.pop();
31 | _.trys.pop(); continue;
32 | }
33 | op = body.call(thisArg, _);
34 | } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
35 | if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
36 | }
37 | };
38 | exports.__esModule = true;
39 | var httpClient_1 = require("../utils/httpClient");
40 | var routes_constants_1 = require("../utils/routes.constants");
41 | exports.ProductProvider = {
42 | getProducts: function () { return __awaiter(void 0, void 0, void 0, function () { return __generator(this, function (_a) {
43 | return [2 /*return*/, httpClient_1.http.get("" + routes_constants_1.ENDPOINTS.PRODUCTS)];
44 | }); }); }
45 | };
46 |
--------------------------------------------------------------------------------
/packages/ssr/.eslintrc.js:
--------------------------------------------------------------------------------
1 | const tsconfig = require(`./tsconfig`);
2 |
3 | module.exports = {
4 | env: {
5 | browser: true,
6 | es6: true,
7 | },
8 | globals: {
9 | Atomics: `readonly`,
10 | SharedArrayBuffer: `readonly`,
11 | },
12 | extends: [
13 | `plugin:@typescript-eslint/eslint-recommended`,
14 | `plugin:@typescript-eslint/recommended`,
15 | `plugin:prettier/recommended`,
16 | `next`,
17 | ],
18 | rules: {
19 | 'no-shadow': `off`,
20 | camelcase: `off`,
21 | 'no-mixed-operators': `error`,
22 | 'no-unneeded-ternary': `error`,
23 | 'no-nested-ternary': `error`,
24 | 'no-use-before-define': [`off`],
25 | '@typescript-eslint/explicit-function-return-type': `off`,
26 | '@typescript-eslint/explicit-module-boundary-types': `off`,
27 | '@typescript-eslint/no-use-before-define': [`warn`],
28 | '@typescript-eslint/no-explicit-any': `error`,
29 | '@typescript-eslint/no-var-requires': `off`,
30 | '@typescript-eslint/no-unused-vars': `error`,
31 | '@typescript-eslint/no-shadow': [`error`],
32 | '@typescript-eslint/quotes': [
33 | 2,
34 | `backtick`,
35 | {
36 | avoidEscape: true,
37 | },
38 | ],
39 | 'react/jsx-no-bind': `error`,
40 | 'react/prop-types': `off`,
41 | 'react/display-name': `off`,
42 | 'react/jsx-filename-extension': `off`,
43 | 'react/jsx-props-no-spreading': `off`,
44 | 'react/no-unused-prop-types': `off`,
45 | 'react/react-in-jsx-scope': `off`,
46 | 'react/require-default-props': `off`,
47 | 'import/prefer-default-export': `off`,
48 | 'import/extensions': [
49 | `error`,
50 | `ignorePackages`,
51 | {
52 | ts: `never`,
53 | tsx: `never`,
54 | js: `never`,
55 | jsx: `never`,
56 | },
57 | ],
58 | 'import/order': [
59 | `error`,
60 | {
61 | groups: [[`builtin`, `external`], `internal`, [`sibling`, `index`]],
62 | pathGroups: [
63 | {
64 | pattern: `react`,
65 | group: `external`,
66 | position: `before`,
67 | },
68 | {
69 | pattern: `@react-shop/**`,
70 | group: `external`,
71 | position: `after`,
72 | },
73 | ...Object.keys(tsconfig.compilerOptions.paths).map(key => ({
74 | pattern: `${key}*`,
75 | group: `internal`,
76 | position: `after`,
77 | })),
78 | ],
79 | pathGroupsExcludedImportTypes: [],
80 | 'newlines-between': `always`,
81 | alphabetize: {
82 | order: `asc`,
83 | caseInsensitive: true,
84 | },
85 | },
86 | ],
87 | },
88 | ignorePatterns: [`next.config.js`],
89 | settings: {
90 | 'import/resolver': {
91 | typescript: {
92 | project: `.`,
93 | },
94 | },
95 | 'import/core-modules': [`styled-components`],
96 | react: {
97 | version: `detect`,
98 | },
99 | },
100 | };
101 |
--------------------------------------------------------------------------------