├── .browserlistrc
├── .docker
├── .gitignore
├── compose
│ ├── docker-compose.dev.yml
│ ├── docker-compose.prod.yml
│ └── docker-compose.services.yml
├── dockerfile
│ └── dev.Dockerfile
├── project.json
└── sh
│ └── entrypoint.dev.sh
├── .dockerignore
├── .editorconfig
├── .eslintrc.js
├── .gitattributes
├── .github
├── dependabot.yml
└── workflows
│ ├── build.yml
│ ├── lint.yml
│ └── storybook.yml
├── .gitignore
├── .husky
├── commit-msg
├── pre-commit
└── pre-push
├── .lintstagedrc
├── .nvmrc
├── .nxignore
├── .prettierignore
├── .prettierrc
├── .yarn
├── .gitignore
├── plugins
│ └── @yarnpkg
│ │ ├── plugin-interactive-tools.cjs
│ │ ├── plugin-typescript.cjs
│ │ └── plugin-workspace-tools.cjs
└── releases
│ └── yarn-3.6.3.cjs
├── .yarnrc.yml
├── CHANGELOG.md
├── LICENSE
├── README.md
├── apps
├── client
│ ├── .config
│ │ └── vite
│ │ │ ├── entry.ts
│ │ │ ├── fonts.ts
│ │ │ └── plugins.ts
│ ├── .eslintrc.js
│ ├── Dockerfile
│ ├── index.html
│ ├── nginx.conf
│ ├── package.json
│ ├── project.json
│ ├── public
│ │ ├── favicon.svg
│ │ ├── manifest-logo
│ │ │ ├── logo192.png
│ │ │ └── logo512.png
│ │ ├── manifest.json
│ │ └── service-worker.js
│ ├── src
│ │ ├── app
│ │ │ ├── entrypoint
│ │ │ │ └── core
│ │ │ │ │ └── entry.tsx
│ │ │ ├── index.ts
│ │ │ ├── providers
│ │ │ │ ├── router
│ │ │ │ │ ├── config
│ │ │ │ │ │ └── router.tsx
│ │ │ │ │ ├── index.ts
│ │ │ │ │ └── ui
│ │ │ │ │ │ └── router-provider.tsx
│ │ │ │ └── store
│ │ │ │ │ ├── config
│ │ │ │ │ └── store.ts
│ │ │ │ │ ├── index.ts
│ │ │ │ │ └── ui
│ │ │ │ │ └── store-provider.tsx
│ │ │ └── root
│ │ │ │ └── index.tsx
│ │ ├── entities
│ │ │ └── sign-in-modal-template
│ │ │ │ ├── index.ts
│ │ │ │ ├── lib
│ │ │ │ └── helpers.ts
│ │ │ │ └── ui
│ │ │ │ ├── sign-in-modal-template.styles.ts
│ │ │ │ └── sign-in-modal-template.tsx
│ │ ├── features
│ │ │ └── .gitkeep
│ │ ├── pages
│ │ │ ├── edit
│ │ │ │ ├── index.ts
│ │ │ │ └── ui
│ │ │ │ │ └── edit-page.tsx
│ │ │ └── main
│ │ │ │ ├── index.ts
│ │ │ │ └── ui
│ │ │ │ └── main.tsx
│ │ ├── shared
│ │ │ ├── hooks
│ │ │ │ ├── index.ts
│ │ │ │ └── useStore.ts
│ │ │ └── lib
│ │ │ │ ├── components
│ │ │ │ └── page
│ │ │ │ │ ├── auth-guard.tsx
│ │ │ │ │ ├── index.ts
│ │ │ │ │ └── page.tsx
│ │ │ │ └── index.ts
│ │ └── widgets
│ │ │ └── sign-in-modal
│ │ │ ├── graphql
│ │ │ ├── get-profile.query.ts
│ │ │ └── sign-in.mutation.ts
│ │ │ ├── index.ts
│ │ │ ├── lib
│ │ │ └── exceptions.ts
│ │ │ ├── store
│ │ │ ├── auth.services.ts
│ │ │ └── auth.store.ts
│ │ │ └── ui
│ │ │ └── sign-in-modal.tsx
│ ├── tsconfig.app.json
│ ├── tsconfig.json
│ └── tsconfig.spec.json
├── docs
│ ├── .eslintrc.js
│ ├── .vitepress
│ │ ├── config.mts
│ │ └── theme
│ │ │ ├── index.ts
│ │ │ └── style.css
│ ├── architecture
│ │ ├── backend.md
│ │ └── frontend.md
│ ├── ending
│ │ └── further-development.md
│ ├── features
│ │ ├── animations.md
│ │ ├── automation.md
│ │ ├── config-incapsulation.md
│ │ ├── custom-libraries.md
│ │ ├── file-system-api.md
│ │ ├── prisma.md
│ │ ├── pwa.md
│ │ └── storybook.md
│ ├── index.md
│ ├── introduction
│ │ ├── about-project.md
│ │ ├── getting-started.md
│ │ └── who-am-i.md
│ ├── other-concepts
│ │ ├── authorization.md
│ │ ├── code-generation.md
│ │ ├── frontend-business-logic.md
│ │ ├── graphql.md
│ │ ├── precommit-hooks.md
│ │ ├── testing.md
│ │ ├── ts-morph.md
│ │ └── validation.md
│ ├── package.json
│ ├── project.json
│ ├── public
│ │ ├── logo-large.png
│ │ ├── logo.svg
│ │ └── overview
│ │ │ ├── functionality-color-picker.png
│ │ │ ├── functionality-ending.png
│ │ │ ├── functionality-html.png
│ │ │ ├── functionality-intro.png
│ │ │ └── functionality-login.png
│ ├── scripts
│ │ └── deploy.sh
│ └── vite.config.ts
└── server
│ ├── gateway
│ ├── .config
│ │ ├── jest.ts
│ │ └── webpack.ts
│ ├── .eslintrc.json
│ ├── .gitignore
│ ├── Dockerfile
│ ├── package.json
│ ├── prisma
│ │ ├── .gitignore
│ │ ├── concat-prisma-files.js
│ │ ├── config
│ │ │ └── base.prisma
│ │ └── models
│ │ │ └── users.prisma
│ ├── project.json
│ ├── src
│ │ ├── app.module.ts
│ │ ├── config
│ │ │ ├── cors.ts
│ │ │ └── swagger.ts
│ │ ├── core
│ │ │ ├── auth
│ │ │ │ ├── auth.module.ts
│ │ │ │ └── auth.resolver.ts
│ │ │ └── code-executor
│ │ │ │ ├── code-executor.controller.ts
│ │ │ │ ├── code-executor.module.ts
│ │ │ │ └── index.ts
│ │ └── main.ts
│ ├── tsconfig.app.json
│ ├── tsconfig.json
│ └── tsconfig.spec.json
│ ├── service-auth
│ ├── .config
│ │ ├── jest.ts
│ │ └── webpack.ts
│ ├── .eslintrc.js
│ ├── Dockerfile
│ ├── README.md
│ ├── package.json
│ ├── project.json
│ ├── src
│ │ ├── auth.consumer.ts
│ │ ├── auth.module.ts
│ │ ├── auth.service.ts
│ │ ├── lib
│ │ │ ├── index.ts
│ │ │ └── types.ts
│ │ ├── main.ts
│ │ ├── repository
│ │ │ └── accounts.repository.ts
│ │ └── strategies
│ │ │ ├── jwt.strategy.ts
│ │ │ └── local.strategy.ts
│ ├── tsconfig.app.json
│ ├── tsconfig.json
│ └── tsconfig.spec.json
│ └── service-code-executor
│ ├── .config
│ ├── jest.ts
│ └── webpack.ts
│ ├── .eslintrc.json
│ ├── Dockerfile
│ ├── package.json
│ ├── project.json
│ ├── src
│ ├── code-executor.consumer.ts
│ ├── code-executor.module.ts
│ ├── exceptions
│ │ ├── failed-to-fetch.exception.ts
│ │ └── index.ts
│ ├── lib
│ │ ├── helpers
│ │ │ └── transform-language.ts
│ │ └── type-guards.ts
│ ├── main.ts
│ └── queries
│ │ ├── handlers
│ │ ├── execute-code.handler.ts
│ │ └── index.ts
│ │ └── impl
│ │ ├── execute-code.query.ts
│ │ └── index.ts
│ ├── tsconfig.app.json
│ ├── tsconfig.json
│ └── tsconfig.spec.json
├── commitlint.config.js
├── jest.config.ts
├── jest.preset.js
├── nx.json
├── package.json
├── packages
├── api
│ ├── common
│ │ ├── .config
│ │ │ └── jest.ts
│ │ ├── .eslintrc.json
│ │ ├── README.md
│ │ ├── package.json
│ │ ├── project.json
│ │ ├── src
│ │ │ ├── consts
│ │ │ │ ├── index.ts
│ │ │ │ └── microservices.ts
│ │ │ ├── decorators
│ │ │ │ ├── index.ts
│ │ │ │ ├── string-field.decorator.ts
│ │ │ │ └── user.decorator.ts
│ │ │ ├── exception-filters
│ │ │ │ ├── http-exception.filter.ts
│ │ │ │ ├── index.ts
│ │ │ │ └── rpc-exception.filter.ts
│ │ │ ├── guards
│ │ │ │ ├── gql-auth.guard.ts
│ │ │ │ ├── gql-local-auth.guard.ts
│ │ │ │ ├── index.ts
│ │ │ │ └── jwt-auth.guard.ts
│ │ │ ├── index.ts
│ │ │ ├── modules
│ │ │ │ ├── database
│ │ │ │ │ ├── database.module.ts
│ │ │ │ │ ├── database.service.ts
│ │ │ │ │ └── index.ts
│ │ │ │ ├── env
│ │ │ │ │ ├── conf
│ │ │ │ │ │ ├── database.config.ts
│ │ │ │ │ │ ├── index.ts
│ │ │ │ │ │ ├── kafka.config.ts
│ │ │ │ │ │ ├── misc.config.ts
│ │ │ │ │ │ └── server.config.ts
│ │ │ │ │ ├── env.decorator.ts
│ │ │ │ │ ├── env.module.ts
│ │ │ │ │ ├── index.ts
│ │ │ │ │ └── types
│ │ │ │ │ │ ├── enviroment.interfaces.ts
│ │ │ │ │ │ └── index.ts
│ │ │ │ ├── index.ts
│ │ │ │ ├── jwt
│ │ │ │ │ ├── index.ts
│ │ │ │ │ └── jwt.module.ts
│ │ │ │ ├── kafka
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── kafka.interface.ts
│ │ │ │ │ ├── kafka.module.ts
│ │ │ │ │ └── kafka.service.ts
│ │ │ │ └── listener
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── listener.consts.ts
│ │ │ │ │ ├── listener.interfaces.ts
│ │ │ │ │ ├── listener.module.ts
│ │ │ │ │ └── listener.service.ts
│ │ │ ├── pipes
│ │ │ │ ├── index.ts
│ │ │ │ └── validation.pipe.ts
│ │ │ ├── types
│ │ │ │ ├── _prisma.ts
│ │ │ │ └── guards
│ │ │ │ │ ├── index.ts
│ │ │ │ │ └── is-custom-rpc-exception.ts
│ │ │ └── utils
│ │ │ │ └── validators
│ │ │ │ ├── env.validator.ts
│ │ │ │ └── index.ts
│ │ ├── tsconfig.json
│ │ ├── tsconfig.lib.json
│ │ └── tsconfig.spec.json
│ └── contracts
│ │ ├── .eslintrc.json
│ │ ├── README.md
│ │ ├── package.json
│ │ ├── project.json
│ │ ├── src
│ │ ├── dto
│ │ │ ├── execute-code.dto.ts
│ │ │ └── index.ts
│ │ ├── index.ts
│ │ ├── inputs
│ │ │ ├── index.ts
│ │ │ └── sign-in.input.ts
│ │ ├── interfaces
│ │ │ ├── auth.interfaces.ts
│ │ │ ├── execute-code.interfaces.ts
│ │ │ └── index.ts
│ │ ├── responses
│ │ │ ├── index.ts
│ │ │ ├── token.response.ts
│ │ │ └── user.response.ts
│ │ └── rpc
│ │ │ ├── auth.rpc.ts
│ │ │ ├── code-executor.rpc.ts
│ │ │ └── index.ts
│ │ ├── tsconfig.json
│ │ └── tsconfig.lib.json
├── config
│ ├── .eslintrc.json
│ ├── README.md
│ ├── package.json
│ ├── project.json
│ ├── src
│ │ ├── babel
│ │ │ └── vite.json
│ │ ├── consts
│ │ │ ├── client.ts
│ │ │ └── server.ts
│ │ ├── index.ts
│ │ ├── jest
│ │ │ ├── create-jest-config.ts
│ │ │ └── index.ts
│ │ ├── lib.ts
│ │ ├── storybook
│ │ │ ├── create-preview-defaults.ts
│ │ │ ├── create-storybook-config.ts
│ │ │ ├── index.ts
│ │ │ └── plugins
│ │ │ │ └── create-viewports.ts
│ │ ├── tsconfig
│ │ │ ├── base.json
│ │ │ └── paths
│ │ │ │ ├── second-layer.json
│ │ │ │ └── third-layer.json
│ │ ├── types.ts
│ │ ├── vite
│ │ │ ├── builders
│ │ │ │ ├── aliases.ts
│ │ │ │ ├── build.ts
│ │ │ │ ├── globals.ts
│ │ │ │ ├── index.ts
│ │ │ │ ├── plugins.ts
│ │ │ │ ├── preview.ts
│ │ │ │ ├── server.ts
│ │ │ │ └── vitest.ts
│ │ │ ├── create-vite-config.ts
│ │ │ ├── index.ts
│ │ │ ├── misc.ts
│ │ │ └── types.ts
│ │ └── webpack
│ │ │ ├── build-webpack-config.ts
│ │ │ ├── index.ts
│ │ │ ├── resolvers
│ │ │ ├── index.ts
│ │ │ └── tsconfig-paths.ts
│ │ │ └── types.ts
│ ├── tsconfig.json
│ └── tsconfig.lib.json
├── generator
│ ├── README.md
│ ├── package.json
│ ├── project.json
│ └── templates
│ │ ├── _generator
│ │ └── g
│ │ │ ├── README.ejs.t
│ │ │ ├── new
│ │ │ └── index.ejs.t
│ │ │ ├── prompt.ejs.t
│ │ │ └── prompt.js
│ │ ├── fsd-module
│ │ ├── README.md
│ │ └── new
│ │ │ ├── hooks
│ │ │ └── index.ejs.t
│ │ │ ├── index.ejs.t
│ │ │ ├── lib
│ │ │ └── index.ejs.t
│ │ │ ├── prompt.js
│ │ │ ├── store
│ │ │ └── gitkeep.ejs.t
│ │ │ └── ui
│ │ │ ├── component.ejs.t
│ │ │ └── component.styles.ejs.t
│ │ └── ui
│ │ ├── README.md
│ │ └── new
│ │ ├── component.ejs.t
│ │ ├── component.stories.ejs.t
│ │ ├── component.styles.ejs.t
│ │ ├── index.ejs.t
│ │ └── prompt.js
└── web
│ ├── editor
│ ├── .babelrc
│ ├── .config
│ │ └── vite.ts
│ ├── .eslintrc.json
│ ├── README.md
│ ├── package.json
│ ├── project.json
│ ├── public
│ │ └── logo.svg
│ ├── src
│ │ ├── app
│ │ │ ├── editor.tsx
│ │ │ ├── index.ts
│ │ │ ├── providers
│ │ │ │ ├── editor-store
│ │ │ │ │ ├── config
│ │ │ │ │ │ ├── editor.actions.ts
│ │ │ │ │ │ ├── editor.getters.ts
│ │ │ │ │ │ ├── editor.services.ts
│ │ │ │ │ │ └── editor.store.ts
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── lib
│ │ │ │ │ │ └── default-code-template.ts
│ │ │ │ │ └── ui
│ │ │ │ │ │ └── editor-store-provider.tsx
│ │ │ │ ├── modals-provider
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── types.ts
│ │ │ │ │ └── ui
│ │ │ │ │ │ └── modals-context-provider.tsx
│ │ │ │ └── theme-loader
│ │ │ │ │ ├── hooks
│ │ │ │ │ ├── index.ts
│ │ │ │ │ ├── use-custom-theme
│ │ │ │ │ │ └── use-custom-theme.ts
│ │ │ │ │ └── use-theme-loader
│ │ │ │ │ │ ├── assert-theme-object.ts
│ │ │ │ │ │ ├── themes
│ │ │ │ │ │ ├── Dracula.json
│ │ │ │ │ │ ├── Dreamweaver.json
│ │ │ │ │ │ ├── Eiffel.json
│ │ │ │ │ │ ├── GitHub.json
│ │ │ │ │ │ ├── IDLE.json
│ │ │ │ │ │ ├── Monokai.json
│ │ │ │ │ │ ├── Nord.json
│ │ │ │ │ │ ├── Tomorrow.json
│ │ │ │ │ │ └── Twilight.json
│ │ │ │ │ │ └── use-theme-loader.ts
│ │ │ │ │ ├── index.ts
│ │ │ │ │ └── ui
│ │ │ │ │ └── theme-loader.tsx
│ │ │ └── styles
│ │ │ │ └── editor.styles.ts
│ │ ├── entities
│ │ │ ├── editor-core
│ │ │ │ ├── editor-core.tsx
│ │ │ │ └── index.ts
│ │ │ ├── header-options
│ │ │ │ ├── index.ts
│ │ │ │ └── ui
│ │ │ │ │ ├── header-options.styles.ts
│ │ │ │ │ └── header-options.tsx
│ │ │ ├── header-right-section
│ │ │ │ ├── index.ts
│ │ │ │ └── ui
│ │ │ │ │ ├── header-right-section.styles.ts
│ │ │ │ │ └── header-right-section.tsx
│ │ │ ├── key-buildings
│ │ │ │ ├── index.ts
│ │ │ │ └── key-buildings.tsx
│ │ │ ├── preview-editor
│ │ │ │ ├── index.ts
│ │ │ │ └── ui
│ │ │ │ │ ├── preview-editor.styles.ts
│ │ │ │ │ └── preview-editor.tsx
│ │ │ ├── preview-i-frame
│ │ │ │ ├── index.ts
│ │ │ │ ├── lib
│ │ │ │ │ └── create-html-template.ts
│ │ │ │ └── ui
│ │ │ │ │ └── i-frame.tsx
│ │ │ └── terminal-output
│ │ │ │ ├── hooks
│ │ │ │ ├── index.ts
│ │ │ │ └── use-terminal-output-animations.ts
│ │ │ │ ├── index.ts
│ │ │ │ └── ui
│ │ │ │ ├── bottom-scroll
│ │ │ │ └── bottom-scroll.tsx
│ │ │ │ ├── terminal-output.styles.ts
│ │ │ │ └── terminal-output
│ │ │ │ └── terminal-output.tsx
│ │ ├── features
│ │ │ ├── language-switcher
│ │ │ │ ├── hooks
│ │ │ │ │ ├── index.ts
│ │ │ │ │ └── use-mapped-languages.ts
│ │ │ │ ├── index.ts
│ │ │ │ └── ui
│ │ │ │ │ └── language-switcher.tsx
│ │ │ ├── switch-font-size
│ │ │ │ ├── index.ts
│ │ │ │ └── ui
│ │ │ │ │ └── font-size-switcher.tsx
│ │ │ ├── switch-tab-size
│ │ │ │ ├── index.ts
│ │ │ │ └── ui
│ │ │ │ │ └── tab-size-switcher.tsx
│ │ │ └── switch-theme
│ │ │ │ ├── index.ts
│ │ │ │ └── ui
│ │ │ │ └── theme-switcher.tsx
│ │ ├── index.ts
│ │ ├── shared
│ │ │ ├── consts
│ │ │ │ ├── font-sizes.ts
│ │ │ │ ├── key-buildings.ts
│ │ │ │ ├── languages.ts
│ │ │ │ └── themes.ts
│ │ │ ├── editor-config.ts
│ │ │ ├── exceptions.ts
│ │ │ └── hooks
│ │ │ │ ├── index.ts
│ │ │ │ ├── use-editor.ts
│ │ │ │ ├── use-modals-context.ts
│ │ │ │ └── use-store.ts
│ │ └── widgets
│ │ │ ├── aside
│ │ │ ├── hooks
│ │ │ │ ├── use-aside-animation.ts
│ │ │ │ └── use-editor-actions.ts
│ │ │ ├── index.ts
│ │ │ └── ui
│ │ │ │ ├── aside.styles.ts
│ │ │ │ └── aside.tsx
│ │ │ ├── editor-content
│ │ │ ├── hooks
│ │ │ │ ├── index.ts
│ │ │ │ ├── use-alt-navigation
│ │ │ │ │ └── use-alt-navigation.ts
│ │ │ │ ├── use-file-service
│ │ │ │ │ ├── lib
│ │ │ │ │ │ ├── consts.ts
│ │ │ │ │ │ └── get-language-from-name.ts
│ │ │ │ │ ├── use-file-handler.ts
│ │ │ │ │ ├── use-file-saver.ts
│ │ │ │ │ └── use-file-service.ts
│ │ │ │ └── use-keyboard-manager
│ │ │ │ │ └── use-keyboard-manager.ts
│ │ │ ├── index.ts
│ │ │ ├── store
│ │ │ │ └── content.actions.ts
│ │ │ ├── types
│ │ │ │ ├── guards
│ │ │ │ │ └── is-file-data.ts
│ │ │ │ ├── index.ts
│ │ │ │ └── types.ts
│ │ │ └── ui
│ │ │ │ ├── editor-content.styles.ts
│ │ │ │ └── editor-content.tsx
│ │ │ ├── header
│ │ │ ├── errors.ts
│ │ │ ├── hooks
│ │ │ │ ├── index.ts
│ │ │ │ ├── use-code-runner.ts
│ │ │ │ └── use-header-animation.ts
│ │ │ ├── index.ts
│ │ │ ├── store
│ │ │ │ └── execute.services.ts
│ │ │ ├── types.ts
│ │ │ └── ui
│ │ │ │ ├── header.styles.ts
│ │ │ │ └── header.tsx
│ │ │ ├── html-preview
│ │ │ ├── context
│ │ │ │ ├── html-preview-provider.tsx
│ │ │ │ └── index.ts
│ │ │ ├── index.ts
│ │ │ ├── types.ts
│ │ │ └── ui
│ │ │ │ ├── html-preview.styles.ts
│ │ │ │ └── html-preview.tsx
│ │ │ ├── settings
│ │ │ ├── hooks
│ │ │ │ ├── index.ts
│ │ │ │ └── use-color-callback.ts
│ │ │ ├── index.ts
│ │ │ └── ui
│ │ │ │ ├── settings.styles.ts
│ │ │ │ └── settings.tsx
│ │ │ ├── tabs
│ │ │ ├── hooks
│ │ │ │ ├── index.ts
│ │ │ │ ├── use-confirm.ts
│ │ │ │ └── use-mapped-tabs.ts
│ │ │ ├── index.ts
│ │ │ ├── lib
│ │ │ │ ├── helpers
│ │ │ │ │ ├── generate-new-tab.ts
│ │ │ │ │ └── is-max-tabs-length.ts
│ │ │ │ └── index.ts
│ │ │ ├── store
│ │ │ │ └── tabs.actions.ts
│ │ │ ├── types.ts
│ │ │ └── ui
│ │ │ │ ├── tabs.styles.ts
│ │ │ │ └── tabs.tsx
│ │ │ └── terminal
│ │ │ ├── hooks
│ │ │ ├── index.ts
│ │ │ └── use-terminal-tabs.ts
│ │ │ ├── index.ts
│ │ │ ├── store
│ │ │ └── terminal.actions.ts
│ │ │ ├── types.ts
│ │ │ └── ui
│ │ │ ├── terminal.styles.ts
│ │ │ └── terminal.tsx
│ ├── tsconfig.json
│ ├── tsconfig.lib.json
│ └── tsconfig.spec.json
│ ├── shared
│ ├── .babelrc
│ ├── .config
│ │ └── vite.ts
│ ├── .eslintrc.json
│ ├── README.md
│ ├── env.d.ts
│ ├── package.json
│ ├── project.json
│ ├── src
│ │ ├── assets
│ │ │ ├── index.ts
│ │ │ ├── logo.png
│ │ │ └── logo.svg
│ │ ├── config
│ │ │ ├── apollo-client.ts
│ │ │ ├── axios.ts
│ │ │ ├── index.ts
│ │ │ ├── local-storage.ts
│ │ │ └── paths.ts
│ │ ├── hooks
│ │ │ ├── index.ts
│ │ │ └── use-notifications.ts
│ │ ├── index.ts
│ │ ├── lib
│ │ │ ├── apollo
│ │ │ │ ├── apollo-middleware.ts
│ │ │ │ └── index.ts
│ │ │ ├── components
│ │ │ │ ├── Display.ts
│ │ │ │ └── index.ts
│ │ │ ├── helpers
│ │ │ │ ├── index.ts
│ │ │ │ └── local-storage.ts
│ │ │ └── icons.ts
│ │ ├── providers
│ │ │ ├── animations
│ │ │ │ └── animation-provider.tsx
│ │ │ ├── error-boundary
│ │ │ │ ├── error-boundary.tsx
│ │ │ │ └── ui
│ │ │ │ │ └── error-template.tsx
│ │ │ ├── index.ts
│ │ │ ├── notifications
│ │ │ │ └── notifications-provider.tsx
│ │ │ ├── styles
│ │ │ │ ├── app.styles.ts
│ │ │ │ └── index.ts
│ │ │ └── theme
│ │ │ │ ├── config
│ │ │ │ ├── antd-config.ts
│ │ │ │ └── themes.ts
│ │ │ │ ├── index.ts
│ │ │ │ ├── styled.d.ts
│ │ │ │ └── ui
│ │ │ │ └── theme-provider.tsx
│ │ ├── storybook
│ │ │ ├── decorators
│ │ │ │ ├── animation.decorator.tsx
│ │ │ │ ├── index.ts
│ │ │ │ ├── styles.decorator.tsx
│ │ │ │ └── theme.decorator.tsx
│ │ │ ├── index.ts
│ │ │ ├── lib
│ │ │ │ ├── create-storybook-variant.ts
│ │ │ │ └── index.ts
│ │ │ └── types.ts
│ │ ├── styles
│ │ │ ├── index.ts
│ │ │ ├── mixins.ts
│ │ │ └── variables.ts
│ │ └── types
│ │ │ ├── common
│ │ │ ├── graphql.ts
│ │ │ └── grnx.ts
│ │ │ ├── index.ts
│ │ │ └── lib
│ │ │ ├── animations.ts
│ │ │ └── context.ts
│ ├── tsconfig.json
│ ├── tsconfig.lib.json
│ └── tsconfig.spec.json
│ └── ui
│ ├── .babelrc
│ ├── .config
│ ├── storybook
│ │ ├── main.ts
│ │ ├── preview.ts
│ │ └── test-runner.config.ts
│ └── vite.ts
│ ├── .eslintrc.json
│ ├── README.md
│ ├── package.json
│ ├── project.json
│ ├── src
│ ├── color-button
│ │ ├── color-button.stories.tsx
│ │ └── color-button.tsx
│ ├── index.ts
│ ├── modal
│ │ ├── hooks
│ │ │ └── use-modal-transitions.ts
│ │ ├── index.ts
│ │ └── ui
│ │ │ ├── modal.stories.tsx
│ │ │ ├── modal.styles.ts
│ │ │ └── modal.tsx
│ ├── popover
│ │ ├── hooks
│ │ │ ├── index.ts
│ │ │ └── use-popover-animation.ts
│ │ ├── index.ts
│ │ └── ui
│ │ │ ├── popover.stories.tsx
│ │ │ ├── popover.styles.tsx
│ │ │ └── popover.tsx
│ └── select
│ │ ├── select.stories.tsx
│ │ └── select.tsx
│ ├── tsconfig.json
│ ├── tsconfig.lib.json
│ ├── tsconfig.spec.json
│ └── tsconfig.storybook.json
├── project.json
├── tools
├── database
│ └── dump.sql
├── dev
│ ├── package.json
│ ├── project.json
│ └── src
│ │ ├── env
│ │ ├── .env
│ │ ├── .gitignore
│ │ └── .override.env
│ │ └── img
│ │ ├── architecture_diagram.png
│ │ ├── git_flow_trunk_based.png
│ │ ├── microfrontend.png
│ │ └── nestjs_folders.png
├── generators
│ ├── .eslintrc.js
│ ├── generators.json
│ ├── package.json
│ ├── project.json
│ ├── src
│ │ └── microservice
│ │ │ ├── files
│ │ │ ├── .config
│ │ │ │ ├── jest.ts.template
│ │ │ │ └── webpack.ts.template
│ │ │ ├── .eslintrc.js.template
│ │ │ ├── Dockerfile.template
│ │ │ ├── README.md.template
│ │ │ ├── package.json.template
│ │ │ ├── project.json.template
│ │ │ ├── src
│ │ │ │ ├── __name__.consumer.ts.template
│ │ │ │ ├── __name__.module.ts.template
│ │ │ │ ├── lib
│ │ │ │ │ └── index.ts.template
│ │ │ │ ├── main.ts.template
│ │ │ │ └── queries
│ │ │ │ │ ├── handlers
│ │ │ │ │ └── index.ts.template
│ │ │ │ │ └── impl
│ │ │ │ │ └── index.ts.template
│ │ │ ├── tsconfig.app.json.template
│ │ │ ├── tsconfig.json.template
│ │ │ └── tsconfig.spec.json.template
│ │ │ ├── generator.ts
│ │ │ └── schema.json
│ ├── tsconfig.json
│ └── tsconfig.lib.json
└── scripts
│ ├── .eslintrc.json
│ ├── package.json
│ ├── project.json
│ ├── src
│ ├── lib
│ │ ├── helpers.ts
│ │ └── run-project-files.ts
│ └── ts-morph
│ │ ├── check-uppercase-files.ts
│ │ ├── remove-all-console-logs.ts
│ │ ├── rename-client-shared.ts
│ │ ├── rename-imports
│ │ ├── consts.ts
│ │ └── script.ts
│ │ └── rename-projects-to-kebab-case.ts
│ └── tsconfig.json
├── tsconfig.base.json
└── yarn.lock
/.browserlistrc:
--------------------------------------------------------------------------------
1 | [production]
2 | defaults
3 | not IE 11
4 |
5 | [development]
6 | last 2 Chrome versions
7 |
--------------------------------------------------------------------------------
/.docker/.gitignore:
--------------------------------------------------------------------------------
1 | .override.env
2 |
--------------------------------------------------------------------------------
/.docker/compose/docker-compose.dev.yml:
--------------------------------------------------------------------------------
1 | version: '3.9'
2 |
3 | services:
4 | workspace:
5 | build:
6 | dockerfile: .docker/dockerfile/dev.Dockerfile
7 | context: .
8 | restart: always
9 | profiles:
10 | - workspace
11 | env_file:
12 | - .env
13 | - .docker/.override.env
14 | volumes:
15 | - ./apps:/opt/app/apps
16 | - ./packages:/opt/app/packages
17 | - /opt/app/node_modules
18 | container_name: workspace
19 | networks:
20 | - cgnet
21 | entrypoint: sh entrypoint.sh
22 | ports:
23 | - 3000:3000
24 | - 6868:6868
25 |
--------------------------------------------------------------------------------
/.docker/dockerfile/dev.Dockerfile:
--------------------------------------------------------------------------------
1 | #/**
2 | # * This docker file is used only in development mode
3 | # * It runs all processes, microservices and libraries
4 | # * in one large container so as not to take up a lot of
5 | # * space. Hot reload enabled.
6 | # */
7 |
8 | FROM --platform=linux/amd64 node:20.8.0-alpine as build
9 | WORKDIR /opt/app
10 |
11 | ## Installing dependencies ##
12 |
13 | COPY package.json yarn.lock .yarnrc.yml ./
14 | COPY .yarn .yarn
15 |
16 | COPY packages/config/package.json packages/config/package.json
17 |
18 | RUN yarn install
19 |
20 | ## Copying source code ##
21 |
22 | COPY packages packages
23 |
24 | COPY apps apps
25 |
26 | RUN yarn install
27 |
28 | COPY . .
29 |
30 | ## Copying entrypoint scripts ##
31 |
32 | COPY .docker/sh/entrypoint.dev.sh entrypoint.sh
33 |
34 |
35 | RUN chmod +x entrypoint.sh;
36 |
37 | RUN echo "done."
38 |
--------------------------------------------------------------------------------
/.docker/sh/entrypoint.dev.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | yarn nx run gateway:prisma:init
4 |
5 | yarn nx serve --host=0.0.0.0
6 |
--------------------------------------------------------------------------------
/.dockerignore:
--------------------------------------------------------------------------------
1 | dist
2 | tmp
3 | node_modules
4 | .idea
5 | .husky
6 | .editorconfig
7 | .lintstagedrc
8 | commitlint.config.js
9 | CHANGELOG.md
10 | LICENSE
11 | README.md
12 | jest.config.ts
13 | jest.preset.js
14 | local
15 | data
16 | tmp
17 | .github
18 | .gitignore
19 | .gitattributes
20 | .yarn/cache
21 | .yarn/install-state.gz
22 |
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | [*]
4 | charset = utf-8
5 | indent_style = space
6 | indent_size = 2
7 | insert_final_newline = true
8 | trim_trailing_whitespace = true
9 |
10 | [*.md]
11 | max_line_length = off
12 | trim_trailing_whitespace = false
13 |
--------------------------------------------------------------------------------
/.eslintrc.js:
--------------------------------------------------------------------------------
1 | const grnx = require('@grnx-utils/eslint')
2 |
3 | module.exports = grnx({
4 | root: __dirname,
5 | tsconfig: 'tsconfig.base.json',
6 | monorepo: true,
7 | enableImports: false,
8 | ext: {
9 | 'max-len': 'off'
10 | }
11 | })
12 |
--------------------------------------------------------------------------------
/.github/dependabot.yml:
--------------------------------------------------------------------------------
1 | version: 2
2 | updates:
3 | - package-ecosystem: "npm"
4 | directory: "/"
5 | schedule:
6 | interval: "monthly"
7 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | dist
2 | tmp
3 | node_modules
4 | .idea
5 | local
6 | *.env
7 | data
8 | cache
9 |
--------------------------------------------------------------------------------
/.husky/commit-msg:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 | . "$(dirname -- "$0")/_/husky.sh"
3 |
4 | yarn dlx commitlint --edit $1
5 |
--------------------------------------------------------------------------------
/.husky/pre-commit:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 | . "$(dirname -- "$0")/_/husky.sh"
3 |
4 | yarn install
5 |
6 | yarn dlx yarn-upgrade-all
7 |
8 | yarn lint-staged --relative
9 |
10 |
--------------------------------------------------------------------------------
/.husky/pre-push:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 | . "$(dirname -- "$0")/_/husky.sh"
3 |
4 |
5 |
--------------------------------------------------------------------------------
/.lintstagedrc:
--------------------------------------------------------------------------------
1 | {
2 | "*.ts": ["yarn dlx nx lint"]
3 | }
4 |
--------------------------------------------------------------------------------
/.nvmrc:
--------------------------------------------------------------------------------
1 | 20.8.0
2 |
--------------------------------------------------------------------------------
/.nxignore:
--------------------------------------------------------------------------------
1 | # Added to avoid causing additional problems when serving nestjs applications.
2 | _schema.gql
3 |
--------------------------------------------------------------------------------
/.prettierignore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gearonix/code-gear/428293078745619b14bce932d30b9b73e5cce08c/.prettierignore
--------------------------------------------------------------------------------
/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "semi": false,
3 | "bracketSpacing": true,
4 | "bracketSameLine": true,
5 | "arrowParens": "always",
6 | "singleQuote": true
7 | }
8 |
--------------------------------------------------------------------------------
/.yarn/.gitignore:
--------------------------------------------------------------------------------
1 | install-state.gz
2 | unplugged
3 | cache
4 |
--------------------------------------------------------------------------------
/.yarnrc.yml:
--------------------------------------------------------------------------------
1 | nodeLinker: node-modules
2 |
3 | #checksumBehavior: update
4 |
5 | #cacheFolder: ./.yarn/cache
6 |
7 | #enableImmutableInstalls: false
8 |
9 | plugins:
10 | - path: .yarn/plugins/@yarnpkg/plugin-interactive-tools.cjs
11 | spec: "@yarnpkg/plugin-interactive-tools"
12 | - path: .yarn/plugins/@yarnpkg/plugin-workspace-tools.cjs
13 | spec: "@yarnpkg/plugin-workspace-tools"
14 | - path: .yarn/plugins/@yarnpkg/plugin-typescript.cjs
15 | spec: "@yarnpkg/plugin-typescript"
16 |
17 | yarnPath: .yarn/releases/yarn-3.6.3.cjs
18 |
--------------------------------------------------------------------------------
/apps/client/.config/vite/entry.ts:
--------------------------------------------------------------------------------
1 | // It is important to specify relative paths here.
2 | import { resolve } from 'path'
3 |
4 | import { createViteConfig } from '../../../../packages/config/src/vite'
5 | import { buildCustomPlugins } from './plugins'
6 |
7 | export default createViteConfig({
8 | projectName: 'client',
9 | projectType: 'application',
10 | rootDir: resolve(__dirname, '..'),
11 | layer: 'second',
12 | external: [],
13 | plugins: buildCustomPlugins()
14 | })
15 |
--------------------------------------------------------------------------------
/apps/client/.config/vite/fonts.ts:
--------------------------------------------------------------------------------
1 | export const fonts: string[] = [
2 | 'https://fonts.googleapis.com/css2?family=Poppins&display=swap'
3 | ]
4 |
--------------------------------------------------------------------------------
/apps/client/.config/vite/plugins.ts:
--------------------------------------------------------------------------------
1 | import preact from '@preact/preset-vite'
2 | import { PluginOption } from 'vite'
3 | import { VitePWA } from 'vite-plugin-pwa'
4 | import webfontDownload from 'vite-plugin-webfont-dl'
5 |
6 | import { fonts } from './fonts'
7 |
8 | export const buildCustomPlugins = (): PluginOption[] => [
9 | webfontDownload(fonts),
10 | preact(),
11 | VitePWA({
12 | registerType: 'autoUpdate',
13 | injectRegister: 'auto',
14 | strategies: 'injectManifest',
15 | srcDir: 'public',
16 | filename: 'service-worker.js',
17 | workbox: {
18 | globPatterns: ['**/*.{js,css,html,ico,png,svg}'],
19 | clientsClaim: true,
20 | skipWaiting: true
21 | },
22 | devOptions: {
23 | enabled: false
24 | },
25 | includeAssets: ['**/*']
26 | })
27 | ]
28 |
--------------------------------------------------------------------------------
/apps/client/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | parser: '@typescript-eslint/parser',
3 | plugins: ['preact'],
4 | extends: ['../../.eslintrc.js'],
5 | ignorePatterns: ['!**/*']
6 | }
7 |
--------------------------------------------------------------------------------
/apps/client/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM --platform=linux/amd64 node:20.8.0-alpine as build
2 | WORKDIR /opt/app
3 |
4 | ## Installing dependencies ##
5 |
6 | COPY package.json yarn.lock .yarnrc.yml ./
7 | COPY .yarn .yarn
8 |
9 | COPY packages/config/package.json packages/config/package.json
10 |
11 | RUN yarn install
12 |
13 | ## Copying source code ##
14 |
15 | COPY apps/client apps/client
16 |
17 | COPY packages packages
18 |
19 | RUN yarn install
20 |
21 | COPY . .
22 |
23 | ## Building app to produciton ##
24 |
25 | RUN yarn nx run client:build
26 |
27 | ## Nginx setup ##
28 |
29 | FROM nginx:1.24-alpine
30 |
31 | COPY --from=build /opt/app/dist/apps/client /usr/share/nginx/html
32 | COPY ./apps/client/nginx.conf /etc/nginx/conf.d/default.conf
33 |
34 | EXPOSE 80
35 |
--------------------------------------------------------------------------------
/apps/client/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | CodeGear
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/apps/client/nginx.conf:
--------------------------------------------------------------------------------
1 | server {
2 | listen 80;
3 | root /usr/share/nginx/html;
4 |
5 | location / {
6 | index index.html index.htm;
7 | try_files $uri $uri/ /index.html;
8 | }
9 |
10 | error_page 404 /index.html;
11 | location = /404 {
12 | return 404;
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/apps/client/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "cg-client",
3 | "version": "0.0.1",
4 | "devDependencies": {
5 | "cg-config": "workspace:^",
6 | "cg-ui": "workspace:^"
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/apps/client/public/manifest-logo/logo192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gearonix/code-gear/428293078745619b14bce932d30b9b73e5cce08c/apps/client/public/manifest-logo/logo192.png
--------------------------------------------------------------------------------
/apps/client/public/manifest-logo/logo512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gearonix/code-gear/428293078745619b14bce932d30b9b73e5cce08c/apps/client/public/manifest-logo/logo512.png
--------------------------------------------------------------------------------
/apps/client/public/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "CodeGear",
3 | "short_name": "CodeGear",
4 | "theme_color": "#2196f3",
5 | "background_color": "#2196f3",
6 | "scope": "/",
7 | "start_url": ".",
8 | "display": "standalone",
9 | "orientation": "portrait",
10 | "description": "Fast online text editor",
11 | "icons": [
12 | {
13 | "src": "/manifest-logo/logo192.png",
14 | "sizes": "192x192",
15 | "type": "image/png"
16 | },
17 | {
18 | "src": "/manifest-logo/logo512.png",
19 | "sizes": "512x512",
20 | "type": "image/png"
21 | }
22 | ]
23 | }
24 |
--------------------------------------------------------------------------------
/apps/client/src/app/entrypoint/core/entry.tsx:
--------------------------------------------------------------------------------
1 | import { render } from 'preact'
2 |
3 | import { Root } from '../../root'
4 |
5 | render(, document.querySelector('#root')!)
6 |
--------------------------------------------------------------------------------
/apps/client/src/app/index.ts:
--------------------------------------------------------------------------------
1 | export { RootStore, StoreContext } from './providers/store'
2 |
--------------------------------------------------------------------------------
/apps/client/src/app/providers/router/config/router.tsx:
--------------------------------------------------------------------------------
1 | import { RoutePaths } from '@code-gear/web/shared'
2 | import { createBrowserRouter } from 'react-router-dom'
3 |
4 | import { EditPage } from '@/pages/edit'
5 | import { Main } from '@/pages/main'
6 |
7 | const router = createBrowserRouter([
8 | {
9 | path: RoutePaths.MAIN,
10 | element:
11 | },
12 | {
13 | path: RoutePaths.EDITOR,
14 | element:
15 | }
16 | ])
17 |
18 | export default router
19 |
--------------------------------------------------------------------------------
/apps/client/src/app/providers/router/index.ts:
--------------------------------------------------------------------------------
1 | export { default as RouterProvider } from './ui/router-provider'
2 |
--------------------------------------------------------------------------------
/apps/client/src/app/providers/router/ui/router-provider.tsx:
--------------------------------------------------------------------------------
1 | import { RouterProvider as Router } from 'react-router-dom'
2 |
3 | import router from '../config/router'
4 |
5 | const RouterProvider = () => {
6 | return
7 | }
8 |
9 | export default RouterProvider
10 |
--------------------------------------------------------------------------------
/apps/client/src/app/providers/store/config/store.ts:
--------------------------------------------------------------------------------
1 | import { EditorStore } from '@code-gear/web/editor'
2 | import { makeAutoObservable } from 'mobx'
3 |
4 | import { AuthStore } from '@/widgets/sign-in-modal'
5 |
6 | class RootStore {
7 | editor: EditorStore
8 | auth: AuthStore
9 |
10 | constructor() {
11 | makeAutoObservable(this)
12 | this.editor = new EditorStore()
13 | this.auth = new AuthStore()
14 | }
15 | }
16 |
17 | export default RootStore
18 |
--------------------------------------------------------------------------------
/apps/client/src/app/providers/store/index.ts:
--------------------------------------------------------------------------------
1 | export { default as RootStore } from './config/store'
2 | export { StoreContext, default as StoreProvider } from './ui/store-provider'
3 |
--------------------------------------------------------------------------------
/apps/client/src/app/providers/store/ui/store-provider.tsx:
--------------------------------------------------------------------------------
1 | import { WithPreactChildren } from '@code-gear/web/shared'
2 | import { createContext } from 'react'
3 |
4 | import RootStore from '../config/store'
5 |
6 | export const StoreContext = createContext({} as RootStore)
7 |
8 | export const StoreProvider = ({ children }: WithPreactChildren) => {
9 | const root = new RootStore()
10 |
11 | return {children}
12 | }
13 |
14 | export default StoreProvider
15 |
--------------------------------------------------------------------------------
/apps/client/src/app/root/index.tsx:
--------------------------------------------------------------------------------
1 | import 'normalize.css'
2 |
3 | import { GlobalStyles } from '@code-gear/web/shared'
4 | import { ThemeProvider } from '@code-gear/web/shared'
5 |
6 | import { RouterProvider } from '../providers/router'
7 | import { StoreProvider } from '../providers/store'
8 |
9 | export const Root = () => {
10 | return (
11 |
12 |
13 |
14 |
15 |
16 |
17 | )
18 | }
19 |
--------------------------------------------------------------------------------
/apps/client/src/entities/sign-in-modal-template/index.ts:
--------------------------------------------------------------------------------
1 | export { SignInModalTemplate } from './ui/sign-in-modal-template'
2 |
--------------------------------------------------------------------------------
/apps/client/src/entities/sign-in-modal-template/lib/helpers.ts:
--------------------------------------------------------------------------------
1 | export const getFormItemRules = () => [{ required: true, min: 6, max: 14 }]
2 |
--------------------------------------------------------------------------------
/apps/client/src/entities/sign-in-modal-template/ui/sign-in-modal-template.styles.ts:
--------------------------------------------------------------------------------
1 | import { s } from '@code-gear/web/shared'
2 | import { Form } from 'antd'
3 | import styled from 'styled-components'
4 |
5 | export const SignInModalStyles = styled(Form)`
6 | width: 84%;
7 | margin: 0 auto;
8 | `
9 |
10 | export const SubmitButton = styled.button`
11 | height: 40px;
12 | width: 100%;
13 | cursor: pointer;
14 | font-size: ${({ theme }) => theme.fz7};
15 | margin: 0 auto;
16 | margin-top: 80px;
17 | display: block;
18 | `
19 |
20 | export const LogoWrapper = styled.img`
21 | ${s.wh('68px', '92px')}
22 | margin: 10px auto;
23 | display: block;
24 | `
25 |
--------------------------------------------------------------------------------
/apps/client/src/features/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gearonix/code-gear/428293078745619b14bce932d30b9b73e5cce08c/apps/client/src/features/.gitkeep
--------------------------------------------------------------------------------
/apps/client/src/pages/edit/index.ts:
--------------------------------------------------------------------------------
1 | export { default as EditPage } from './ui/edit-page'
2 |
--------------------------------------------------------------------------------
/apps/client/src/pages/edit/ui/edit-page.tsx:
--------------------------------------------------------------------------------
1 | import { Editor } from '@code-gear/web/editor'
2 | import { Suspense } from 'react'
3 |
4 | import { Page } from '@/shared/lib'
5 | import { SignInModal } from '@/widgets/sign-in-modal'
6 |
7 | const EditPage = () => {
8 | return (
9 |
10 |
11 |
12 |
13 |
14 | )
15 | }
16 |
17 | export default EditPage
18 |
--------------------------------------------------------------------------------
/apps/client/src/pages/main/index.ts:
--------------------------------------------------------------------------------
1 | export { default as Main } from './ui/main'
2 |
--------------------------------------------------------------------------------
/apps/client/src/pages/main/ui/main.tsx:
--------------------------------------------------------------------------------
1 | import { RoutePaths } from '@code-gear/web/shared'
2 | import { Link } from 'react-router-dom'
3 |
4 | import { Page } from '@/shared/lib'
5 |
6 | const Main = () => {
7 | return (
8 |
9 |
10 | Not Ready Yet.
11 | Link to Editor
12 |
13 |
14 | )
15 | }
16 |
17 | export default Main
18 |
--------------------------------------------------------------------------------
/apps/client/src/shared/hooks/index.ts:
--------------------------------------------------------------------------------
1 | export { useStore } from './useStore'
2 |
--------------------------------------------------------------------------------
/apps/client/src/shared/hooks/useStore.ts:
--------------------------------------------------------------------------------
1 | import { useContext } from 'react'
2 |
3 | import { RootStore } from '@/app'
4 | import { StoreContext } from '@/app'
5 |
6 | export const useStore = (name: T) => {
7 | return useContext(StoreContext)[name]
8 | }
9 |
--------------------------------------------------------------------------------
/apps/client/src/shared/lib/components/page/index.ts:
--------------------------------------------------------------------------------
1 | export { default as Page } from './page'
2 |
--------------------------------------------------------------------------------
/apps/client/src/shared/lib/components/page/page.tsx:
--------------------------------------------------------------------------------
1 | import { ErrorBoundary } from '@code-gear/web/shared'
2 | import { WithChildren } from '@code-gear/web/shared'
3 |
4 | import AuthGuard from '@/shared/lib/components/page/auth-guard'
5 |
6 | const Page = ({ children }: WithChildren) => {
7 | return (
8 |
9 | {children}
10 |
11 | )
12 | }
13 |
14 | export default Page
15 |
--------------------------------------------------------------------------------
/apps/client/src/shared/lib/index.ts:
--------------------------------------------------------------------------------
1 | export * from './components/page'
2 |
--------------------------------------------------------------------------------
/apps/client/src/widgets/sign-in-modal/graphql/get-profile.query.ts:
--------------------------------------------------------------------------------
1 | import { gql } from '@apollo/react-hooks'
2 | import { ApolloOperation } from '@code-gear/web/shared'
3 |
4 | export const getProfileQuery: ApolloOperation = {
5 | gql: gql`
6 | query {
7 | getProfile {
8 | username
9 | avatarUrl
10 | }
11 | }
12 | `,
13 | method: 'getProfile'
14 | }
15 |
--------------------------------------------------------------------------------
/apps/client/src/widgets/sign-in-modal/graphql/sign-in.mutation.ts:
--------------------------------------------------------------------------------
1 | import { gql } from '@apollo/react-hooks'
2 | import { ApolloOperation } from '@code-gear/web/shared'
3 |
4 | export const SignInMutation: ApolloOperation = {
5 | gql: gql`
6 | mutation SignIn($payload: SignIn!) {
7 | signIn(_graphql: $payload) {
8 | accessToken
9 | }
10 | }
11 | `,
12 | method: 'signIn'
13 | }
14 |
--------------------------------------------------------------------------------
/apps/client/src/widgets/sign-in-modal/index.ts:
--------------------------------------------------------------------------------
1 | export { AuthStore } from './store/auth.store'
2 | export { default as SignInModal } from './ui/sign-in-modal'
3 |
--------------------------------------------------------------------------------
/apps/client/src/widgets/sign-in-modal/lib/exceptions.ts:
--------------------------------------------------------------------------------
1 | export const WrongPassword = 'You entered the wrong password.'
2 |
--------------------------------------------------------------------------------
/apps/client/src/widgets/sign-in-modal/store/auth.store.ts:
--------------------------------------------------------------------------------
1 | import { makeAutoObservable } from 'mobx'
2 |
3 | import { AuthServices } from './auth.services'
4 |
5 | export class AuthStore {
6 | username: string
7 | isAuthorized: boolean
8 | readonly services: AuthServices
9 |
10 | constructor() {
11 | makeAutoObservable(this)
12 |
13 | this.services = new AuthServices(this)
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/apps/client/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "cg-config/src/tsconfig/paths/second-layer.json",
3 | "compilerOptions": {
4 | "target": "ESNext",
5 | "module": "ESNext",
6 | "moduleResolution": "node",
7 | "allowSyntheticDefaultImports": true,
8 | "esModuleInterop": true,
9 | "jsx": "preserve",
10 | "jsxFactory": "h",
11 | "jsxFragmentFactory": "Fragment",
12 | "jsxImportSource": "preact",
13 | "types": ["vite/client", "vitest"],
14 | "strictNullChecks": true
15 | },
16 | "files": [],
17 | "include": [],
18 | "references": [
19 | {
20 | "path": "./tsconfig.app.json"
21 | },
22 | {
23 | "path": "./tsconfig.spec.json"
24 | }
25 | ]
26 | }
27 |
--------------------------------------------------------------------------------
/apps/client/tsconfig.spec.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./tsconfig.json",
3 | "compilerOptions": {
4 | "outDir": "../../dist/out-tsc",
5 | "types": ["vitest/globals", "vitest/importMeta", "vite/client", "node"]
6 | },
7 | "include": [
8 | "vite.config.ts",
9 | "src/**/*.test.ts",
10 | "src/**/*.spec.ts",
11 | "src/**/*.test.tsx",
12 | "src/**/*.spec.tsx",
13 | "src/**/*.test.js",
14 | "src/**/*.spec.js",
15 | "src/**/*.test.jsx",
16 | "src/**/*.spec.jsx",
17 | "src/**/*.d.ts"
18 | ]
19 | }
20 |
--------------------------------------------------------------------------------
/apps/docs/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | extends: ['../../.eslintrc.js'],
3 | ignorePatterns: ['!**/*', '.vitepress/cache', 'node_modules']
4 | }
5 |
--------------------------------------------------------------------------------
/apps/docs/.vitepress/theme/index.ts:
--------------------------------------------------------------------------------
1 | import { h } from 'vue'
2 | import Theme from 'vitepress/theme'
3 | import './style.css'
4 |
5 | if (typeof localStorage !== 'undefined') {
6 | localStorage.setItem('vitepress-theme-appearance', 'dark')
7 | }
8 |
9 | export default {
10 | extends: Theme,
11 | Layout: () => {
12 | return h(Theme.Layout, null, {})
13 | },
14 | enhanceApp({ app, router, siteData }) {}
15 | }
16 |
--------------------------------------------------------------------------------
/apps/docs/ending/further-development.md:
--------------------------------------------------------------------------------
1 | # Further Development
2 |
3 | I'm not sure that the project will develop in the future.
4 |
5 | The main goal of the project was to try a bunch of technologies and make it work.
6 | And overall, I succeeded.
7 |
8 | In general, I planned to add more things, such as [Ansible](https://www.ansible.com/),
9 | deployment to AWS, [docker-swarm](https://habr.com/ru/articles/659813/).
10 | I also planned to cover everything with [tests](./../features/testing)
11 | as well, try DDD, make a cool landing page with framer-motion and
12 | [threejs](https://github.com/mrdoob/three.js) (currently actively studying).
13 |
14 | And maybe in the future I will do this. I stopped working on the project as it became
15 | more of a chore than learning something new.
16 |
17 | If you liked it, don't forget to star it on [github](https://github.com/Gearonix/code-gear).
18 |
19 | *Bye 8)*
20 |
--------------------------------------------------------------------------------
/apps/docs/other-concepts/authorization.md:
--------------------------------------------------------------------------------
1 | # Authorization
2 |
3 | The project has a regular JWT authorization via [passport.js](https://github.com/jaredhanson/passport).
4 | Plus, refresh tokens and access token expiry have been added.
5 |
6 | There is nothing unusual here, I would like to add that it was more difficult
7 | to do authorization with passport than to create it from scratch. lmao.
8 |
9 | You can look at it in the `auth` microservice.
10 |
--------------------------------------------------------------------------------
/apps/docs/other-concepts/frontend-business-logic.md:
--------------------------------------------------------------------------------
1 | # Frontend Business Logic
2 |
3 | In the project I use [MobX](https://mobx.js.org/installation.html) for the state manager.
4 |
5 | ## Division into services
6 |
7 | I divide mobx stores into 4 categories.
8 |
9 | - cats.`actions`.ts - state mutations
10 | - cats.`getters`.ts - state getters
11 | - cats.`services`.ts - anchyronous state mutations
12 | - cats.`store`.ts - a module that combines everything and adds the state itself
13 |
14 | ::: tip Examples
15 |
16 | Examples of usage can be found in the `web/editor` library
17 |
18 | :::
19 |
20 | ## Root Store
21 |
22 | Even though Mobx provides options for separating stores (and which I use), I still use one root store.
23 |
24 |
25 | ::: tip Global Store
26 |
27 | The global store can be found in the `client` application
28 |
29 | :::
30 |
--------------------------------------------------------------------------------
/apps/docs/other-concepts/testing.md:
--------------------------------------------------------------------------------
1 | # Testing
2 |
3 | Unfortunately, at the moment the project is not covered by testing (only `storybook` test-runner).
4 | If I continue to develop it, then it will be covered with testing.
5 |
6 | In general, I planned to do 5 types of tests:
7 |
8 | - Unit testing with [Vitest](https://vitest.dev/) ❌
9 | - RTL tests (Integration and Unit testing) ❌
10 | - e2e tests with [Cypress](https://www.cypress.io/) or [Playwright](https://playwright.dev/) [frontend] ❌
11 | - e2e tests with supertest [backend] ❌
12 | - storybook tests (storybook-test-runner) ✅
13 |
14 | ---
15 |
16 | I wanted to try these technologies and test some components at the end of the project.
17 | But somehow it didn’t work out. ( ͡° ͜ʖ ͡°)
18 |
--------------------------------------------------------------------------------
/apps/docs/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "cg-docs"
3 | }
4 |
--------------------------------------------------------------------------------
/apps/docs/public/logo-large.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gearonix/code-gear/428293078745619b14bce932d30b9b73e5cce08c/apps/docs/public/logo-large.png
--------------------------------------------------------------------------------
/apps/docs/public/overview/functionality-color-picker.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gearonix/code-gear/428293078745619b14bce932d30b9b73e5cce08c/apps/docs/public/overview/functionality-color-picker.png
--------------------------------------------------------------------------------
/apps/docs/public/overview/functionality-ending.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gearonix/code-gear/428293078745619b14bce932d30b9b73e5cce08c/apps/docs/public/overview/functionality-ending.png
--------------------------------------------------------------------------------
/apps/docs/public/overview/functionality-html.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gearonix/code-gear/428293078745619b14bce932d30b9b73e5cce08c/apps/docs/public/overview/functionality-html.png
--------------------------------------------------------------------------------
/apps/docs/public/overview/functionality-intro.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gearonix/code-gear/428293078745619b14bce932d30b9b73e5cce08c/apps/docs/public/overview/functionality-intro.png
--------------------------------------------------------------------------------
/apps/docs/public/overview/functionality-login.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gearonix/code-gear/428293078745619b14bce932d30b9b73e5cce08c/apps/docs/public/overview/functionality-login.png
--------------------------------------------------------------------------------
/apps/docs/scripts/deploy.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # This script should work only at the root of the project.
4 |
5 | source .local.env
6 |
7 | echo -e "deploy.sh"
8 | echo -e "BEGET_HOST: $BEGET_HOST"
9 | echo -e "WEBSITE_FOLDER: $WEBSITE_FOLDER"
10 |
11 | cd dist/docs
12 |
13 | zip -r _dist.zip .
14 |
15 | scp _dist.zip "$BEGET_HOST":~/"$WEBSITE_FOLDER"/public_html/code-gear/docs
16 |
17 | rm _dist.zip
18 |
19 | ssh "$BEGET_HOST" << EOF
20 | cd ~/$WEBSITE_FOLDER/public_html/code-gear/docs
21 | unzip -o _dist.zip && rm _dist.zip
22 |
23 | echo -e "[success] docs updated."
24 | EOF
25 |
26 |
--------------------------------------------------------------------------------
/apps/docs/vite.config.ts:
--------------------------------------------------------------------------------
1 | import { defineConfig } from 'vite'
2 |
3 | export default defineConfig({
4 | server: {
5 | port: 4080
6 | }
7 | })
8 |
--------------------------------------------------------------------------------
/apps/server/gateway/.config/jest.ts:
--------------------------------------------------------------------------------
1 | import { createJestConfig } from 'cg-config/src/jest'
2 |
3 | export default createJestConfig({
4 | displayName: 'server-gateway',
5 | layer: 'second'
6 | })
7 |
--------------------------------------------------------------------------------
/apps/server/gateway/.config/webpack.ts:
--------------------------------------------------------------------------------
1 | const { buildWebpackConfig } = require('cg-config/src/webpack')
2 | const { resolve } = require('path')
3 |
4 | module.exports = buildWebpackConfig({
5 | rootDir: resolve(__dirname, '..'),
6 | layer: 'third'
7 | })
8 |
--------------------------------------------------------------------------------
/apps/server/gateway/.eslintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": ["../../../.eslintrc.js"],
3 | "ignorePatterns": ["!**/*"]
4 | }
5 |
--------------------------------------------------------------------------------
/apps/server/gateway/.gitignore:
--------------------------------------------------------------------------------
1 | _schema.gql
2 |
--------------------------------------------------------------------------------
/apps/server/gateway/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM --platform=linux/amd64 node:20.8.0-alpine as build
2 | WORKDIR /opt/app
3 |
4 | ## Installing dependencies ##
5 |
6 | COPY package.json yarn.lock .yarnrc.yml ./
7 | COPY .yarn .yarn
8 |
9 | COPY packages/config/package.json packages/config/package.json
10 |
11 | RUN yarn install
12 |
13 | ## Copying source code ##
14 |
15 | COPY apps/server/gateway apps/server/gateway
16 |
17 | COPY packages packages
18 |
19 | RUN yarn install
20 |
21 | COPY . .
22 |
23 | ## Building app to produciton ##
24 |
25 | RUN yarn nx run gateway:build
26 |
27 | ## Entrypoint ##
28 |
29 | FROM --platform=linux/amd64 node:20.8.0-alpine
30 | WORKDIR /opt/app
31 |
32 | COPY --from=build /opt/app/dist/apps/server/gateway ./
33 |
34 | RUN sed -i '/workspace:/d' package.json
35 |
36 | RUN npm install --omit="dev" --force
37 |
38 | RUN npx prisma generate
39 |
40 | ENTRYPOINT node ./main.js
41 |
--------------------------------------------------------------------------------
/apps/server/gateway/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "cg-server-gateway",
3 | "version": "1.0.0",
4 | "dependencies": {
5 | "cg-api-common": "workspace:^",
6 | "cg-api-contracts": "workspace:^"
7 | },
8 | "devDependencies": {
9 | "cg-config": "workspace:^"
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/apps/server/gateway/prisma/.gitignore:
--------------------------------------------------------------------------------
1 | migrations
2 | schema.prisma
3 |
--------------------------------------------------------------------------------
/apps/server/gateway/prisma/concat-prisma-files.js:
--------------------------------------------------------------------------------
1 | const concat = require('concat-files')
2 | const path = require('path')
3 |
4 | const resolvePrisma = (...args) => path.join('prisma', ...args)
5 |
6 | const concatPrismaFiles = ({ config, models, dest }) => {
7 | concat(
8 | [
9 | resolvePrisma('config', config),
10 | ...models.map((model) => resolvePrisma('models', `${model}.prisma`))
11 | ],
12 | resolvePrisma(dest),
13 | (error) => {
14 | if (error) {
15 | throw error
16 | }
17 |
18 | console.log('Prisma files merged.')
19 | }
20 | )
21 | }
22 |
23 | concatPrismaFiles({
24 | config: 'base.prisma',
25 | models: ['users'],
26 | dest: 'schema.prisma'
27 | })
28 |
--------------------------------------------------------------------------------
/apps/server/gateway/prisma/config/base.prisma:
--------------------------------------------------------------------------------
1 | generator client {
2 | provider = "prisma-client-js"
3 | }
4 |
5 | datasource database {
6 | provider = "mysql"
7 | url = env("DATABASE_URL")
8 | }
9 |
--------------------------------------------------------------------------------
/apps/server/gateway/prisma/models/users.prisma:
--------------------------------------------------------------------------------
1 | // Users model
2 |
3 | model User {
4 | username String @id @database.VarChar(14)
5 | password String @database.VarChar(150)
6 | avatarUrl String? @database.VarChar(100)
7 | }
8 |
--------------------------------------------------------------------------------
/apps/server/gateway/src/config/cors.ts:
--------------------------------------------------------------------------------
1 | import { clientUrl } from '@code-gear/config'
2 | import { CorsOptions } from '@nestjs/common/interfaces/external/cors-options.interface'
3 |
4 | export const corsConfig: CorsOptions = {
5 | origin: clientUrl,
6 | methods: ['POST', 'PUT', 'DELETE', 'GET'],
7 | credentials: true
8 | }
9 |
--------------------------------------------------------------------------------
/apps/server/gateway/src/config/swagger.ts:
--------------------------------------------------------------------------------
1 | import { serverAppName } from '@code-gear/config'
2 | import { DocumentBuilder } from '@nestjs/swagger'
3 | import { OpenAPIObject } from '@nestjs/swagger'
4 | import { SwaggerModule } from '@nestjs/swagger'
5 |
6 | export const createSwaggerDocs = (app): OpenAPIObject => {
7 | const swagger = new DocumentBuilder()
8 | .setTitle(serverAppName)
9 | .setDescription('REST API documentation')
10 | .setVersion('1.0.0')
11 | .build()
12 |
13 | return SwaggerModule.createDocument(app, swagger)
14 | }
15 |
--------------------------------------------------------------------------------
/apps/server/gateway/src/core/auth/auth.module.ts:
--------------------------------------------------------------------------------
1 | import { Module } from '@nestjs/common'
2 |
3 | import { AuthResolver } from './auth.resolver'
4 | import { KafkaModule } from '@code-gear/api/common'
5 | import { Microservice } from '@code-gear/api/common'
6 |
7 | @Module({
8 | controllers: [],
9 | providers: [AuthResolver],
10 | imports: [KafkaModule.forRoot(Microservice.AUTH)],
11 | exports: []
12 | })
13 | export class AuthModule {}
14 |
--------------------------------------------------------------------------------
/apps/server/gateway/src/core/code-executor/code-executor.module.ts:
--------------------------------------------------------------------------------
1 | import { Module } from '@nestjs/common'
2 |
3 | import { CodeExecutorController } from './code-executor.controller'
4 | import { KafkaModule } from '@code-gear/api/common'
5 | import { Microservice } from '@code-gear/api/common'
6 |
7 | @Module({
8 | imports: [KafkaModule.forRoot(Microservice.CODE_EXECUTOR)],
9 | controllers: [CodeExecutorController],
10 | providers: []
11 | })
12 | export class CodeExecutorModule {}
13 |
--------------------------------------------------------------------------------
/apps/server/gateway/src/core/code-executor/index.ts:
--------------------------------------------------------------------------------
1 | export { CodeExecutorModule } from './code-executor.module'
2 |
--------------------------------------------------------------------------------
/apps/server/gateway/tsconfig.app.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./tsconfig.json",
3 | "compilerOptions": {
4 | "outDir": "../../../dist/out-tsc",
5 | "module": "commonjs",
6 | "types": ["node"],
7 | "emitDecoratorMetadata": true,
8 | "target": "es2021",
9 | "baseUrl": "."
10 | },
11 | "exclude": ["jest.config.ts", "src/**/*.spec.ts", "src/**/*.test.ts"],
12 | "include": ["src/**/*.ts"]
13 | }
14 |
--------------------------------------------------------------------------------
/apps/server/gateway/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "cg-config/src/tsconfig/paths/third-layer.json",
3 | "files": [],
4 | "include": [],
5 | "references": [
6 | {
7 | "path": "./tsconfig.app.json"
8 | },
9 | {
10 | "path": "./tsconfig.spec.json"
11 | }
12 | ],
13 | "compilerOptions": {
14 | "esModuleInterop": true,
15 | "resolveJsonModule": true,
16 | "strictNullChecks": true
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/apps/server/gateway/tsconfig.spec.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./tsconfig.json",
3 | "compilerOptions": {
4 | "outDir": "../../../dist/out-tsc",
5 | "module": "commonjs",
6 | "types": ["jest", "node"]
7 | },
8 | "include": [
9 | "jest.config.ts",
10 | "src/**/*.test.ts",
11 | "src/**/*.spec.ts",
12 | "src/**/*.d.ts"
13 | ]
14 | }
15 |
--------------------------------------------------------------------------------
/apps/server/service-auth/.config/jest.ts:
--------------------------------------------------------------------------------
1 | import { createJestConfig } from 'cg-config/src/jest'
2 |
3 | export default createJestConfig({
4 | displayName: 'service-auth',
5 | layer: 'second',
6 | })
7 |
--------------------------------------------------------------------------------
/apps/server/service-auth/.config/webpack.ts:
--------------------------------------------------------------------------------
1 | const { buildWebpackConfig } = require('cg-config/src/webpack')
2 | const { resolve } = require('path')
3 |
4 | module.exports = buildWebpackConfig({
5 | rootDir: resolve(__dirname, '..'),
6 | layer: 'third',
7 | })
8 |
--------------------------------------------------------------------------------
/apps/server/service-auth/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | extends: ['../../../.eslintrc.js'],
3 | ignorePatterns: ['!**/*'],
4 | }
5 |
--------------------------------------------------------------------------------
/apps/server/service-auth/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM --platform=linux/amd64 node:20.8.0-alpine as build
2 | WORKDIR /opt/app
3 |
4 | ## Installing dependencies ##
5 |
6 | COPY package.json yarn.lock .yarnrc.yml ./
7 | COPY .yarn .yarn
8 |
9 | COPY packages/config/package.json packages/config/package.json
10 |
11 | RUN yarn install
12 |
13 | ## Copying source code ##
14 |
15 | COPY apps/server/service-auth apps/server/service-auth
16 |
17 | COPY packages packages
18 |
19 | RUN yarn install
20 |
21 | COPY . .
22 |
23 | ## Building app to produciton ##
24 |
25 | RUN yarn nx run service-auth:build
26 |
27 | ## Entrypoint ##
28 |
29 | FROM --platform=linux/amd64 node:20.8.0-alpine
30 | WORKDIR /opt/app
31 |
32 | COPY --from=build /opt/app/dist/apps/server/service-auth ./
33 |
34 | RUN sed -i '/workspace:/d' package.json
35 |
36 | RUN npm install --omit="dev" --force
37 |
38 | ENTRYPOINT node ./main.js
39 |
--------------------------------------------------------------------------------
/apps/server/service-auth/README.md:
--------------------------------------------------------------------------------
1 | ## auth microservice
2 |
3 | generated by `tools/cg-global-generator`
4 |
--------------------------------------------------------------------------------
/apps/server/service-auth/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "cg-service-auth",
3 | "version": "1.0.0",
4 | "dependencies": {
5 | "cg-api-common": "workspace:^",
6 | "cg-api-contracts": "workspace:^"
7 | },
8 | "devDependencies": {
9 | "cg-config": "workspace:^"
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/apps/server/service-auth/src/auth.consumer.ts:
--------------------------------------------------------------------------------
1 | import { Controller } from '@nestjs/common'
2 | import { QueryBus } from '@nestjs/cqrs'
3 | import { User } from '@code-gear/api/common'
4 | import { MessagePattern } from '@nestjs/microservices'
5 | import { Payload } from '@nestjs/microservices'
6 | import { AccessTokenResponse } from '@code-gear/api/contracts'
7 | import { AuthTopic } from '@code-gear/api/contracts'
8 | import { AuthService } from './auth.service'
9 |
10 | @Controller()
11 | export class AuthConsumer {
12 | constructor(
13 | private readonly query: QueryBus,
14 | private readonly authService: AuthService
15 | ) {}
16 |
17 | @MessagePattern(AuthTopic.SIGN_IN)
18 | async signIn(@Payload() user: User): Promise {
19 | return this.authService.generateToken(user.username)
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/apps/server/service-auth/src/lib/index.ts:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gearonix/code-gear/428293078745619b14bce932d30b9b73e5cce08c/apps/server/service-auth/src/lib/index.ts
--------------------------------------------------------------------------------
/apps/server/service-auth/src/lib/types.ts:
--------------------------------------------------------------------------------
1 | import { UserResponse } from './responses'
2 |
3 | export type JwtTokenPayload = Pick
4 |
--------------------------------------------------------------------------------
/apps/server/service-auth/src/repository/accounts.repository.ts:
--------------------------------------------------------------------------------
1 | import { Injectable } from '@nestjs/common'
2 |
3 | import { DatabaseService } from '@code-gear/api/common'
4 | import { User } from '@code-gear/api/common'
5 | import { SignIn } from '@code-gear/api/contracts'
6 |
7 | @Injectable()
8 | export class AccountsRepository {
9 | constructor(private prisma: DatabaseService) {}
10 |
11 | public getUserByUsername(username: string): User {
12 | return this.prisma.user.findUnique({
13 | where: {
14 | username
15 | }
16 | })
17 | }
18 |
19 | public createUser(user: SignIn): User {
20 | return this.prisma.user.create({
21 | data: user
22 | })
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/apps/server/service-auth/src/strategies/jwt.strategy.ts:
--------------------------------------------------------------------------------
1 | import { jwtSecret } from '@code-gear/config'
2 | import { Injectable } from '@nestjs/common'
3 | import { PassportStrategy } from '@nestjs/passport'
4 | import { ExtractJwt } from 'passport-jwt'
5 | import { Strategy } from 'passport-jwt'
6 |
7 | import { JwtTokenPayload } from '../lib/types'
8 | import { AccountsRepository } from '@/repository/accounts.repository'
9 |
10 | @Injectable()
11 | export class JwtStrategy extends PassportStrategy(Strategy) {
12 | constructor(private readonly usersService: AccountsRepository) {
13 | super({
14 | jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
15 | ignoreExpiration: false,
16 | secretOrKey: jwtSecret
17 | })
18 | }
19 |
20 | validate(payload: JwtTokenPayload) {
21 | return this.usersService.getUserByUsername(payload.username)
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/apps/server/service-auth/tsconfig.app.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./tsconfig.json",
3 | "compilerOptions": {
4 | "outDir": "../../../dist/out-tsc",
5 | "module": "commonjs",
6 | "types": ["node"],
7 | "emitDecoratorMetadata": true,
8 | "target": "es2021",
9 | "baseUrl": "."
10 | },
11 | "exclude": ["jest.config.ts", "src/**/*.spec.ts", "src/**/*.test.ts"],
12 | "include": ["src/**/*.ts"]
13 | }
14 |
--------------------------------------------------------------------------------
/apps/server/service-auth/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "cg-config/src/tsconfig/paths/third-layer.json",
3 | "files": [],
4 | "include": [],
5 | "references": [
6 | {
7 | "path": "./tsconfig.app.json"
8 | },
9 | {
10 | "path": "./tsconfig.spec.json"
11 | }
12 | ],
13 | "compilerOptions": {
14 | "esModuleInterop": true,
15 | "resolveJsonModule": true,
16 | "strictNullChecks": true
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/apps/server/service-auth/tsconfig.spec.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./tsconfig.json",
3 | "compilerOptions": {
4 | "outDir": "../../../dist/out-tsc",
5 | "module": "commonjs",
6 | "types": ["jest", "node"]
7 | },
8 | "include": [
9 | "jest.config.ts",
10 | "src/**/*.test.ts",
11 | "src/**/*.spec.ts",
12 | "src/**/*.d.ts"
13 | ]
14 | }
15 |
--------------------------------------------------------------------------------
/apps/server/service-code-executor/.config/jest.ts:
--------------------------------------------------------------------------------
1 | import { createJestConfig } from 'cg-config/src/jest'
2 |
3 | export default createJestConfig({
4 | displayName: 'service-code-executor',
5 | layer: 'second'
6 | })
7 |
--------------------------------------------------------------------------------
/apps/server/service-code-executor/.config/webpack.ts:
--------------------------------------------------------------------------------
1 | const { buildWebpackConfig } = require('cg-config/src/webpack')
2 | const { resolve } = require('path')
3 |
4 | module.exports = buildWebpackConfig({
5 | rootDir: resolve(__dirname, '..'),
6 | layer: 'third'
7 | })
8 |
--------------------------------------------------------------------------------
/apps/server/service-code-executor/.eslintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": ["../../../.eslintrc.js"],
3 | "ignorePatterns": ["!**/*"]
4 | }
5 |
--------------------------------------------------------------------------------
/apps/server/service-code-executor/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM --platform=linux/amd64 node:20.8.0-alpine as build
2 | WORKDIR /opt/app
3 |
4 | ## Installing dependencies ##
5 |
6 | COPY package.json yarn.lock .yarnrc.yml ./
7 | COPY .yarn .yarn
8 |
9 | COPY packages/config/package.json packages/config/package.json
10 |
11 | RUN yarn install
12 |
13 | ## Copying source code ##
14 |
15 | COPY apps/server/service-code-executor apps/server/service-code-executor
16 |
17 | COPY packages packages
18 |
19 | RUN yarn install
20 |
21 | COPY . .
22 |
23 | ## Building app to produciton ##
24 |
25 | RUN yarn nx run service-code-executor:build
26 |
27 | ## Entrypoint ##
28 |
29 | FROM --platform=linux/amd64 node:20.8.0-alpine
30 | WORKDIR /opt/app
31 |
32 | COPY --from=build /opt/app/dist/apps/server/service-code-executor ./
33 |
34 | RUN sed -i '/workspace:/d' package.json
35 |
36 | RUN npm install --omit="dev" --force
37 |
38 | ENTRYPOINT node ./main.js
39 |
--------------------------------------------------------------------------------
/apps/server/service-code-executor/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "cg-service-code-executor",
3 | "version": "1.0.0",
4 | "dependencies": {
5 | "cg-api-common": "workspace:^",
6 | "cg-api-contracts": "workspace:^"
7 | },
8 | "devDependencies": {
9 | "cg-config": "workspace:^"
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/apps/server/service-code-executor/src/code-executor.module.ts:
--------------------------------------------------------------------------------
1 | import { HttpModule } from '@nestjs/axios'
2 | import { Module } from '@nestjs/common'
3 |
4 | import { CodeExecutorConsumer } from './code-executor.consumer'
5 | import { EnvModule } from '@code-gear/api/common'
6 | import { ListenerModule } from '@code-gear/api/common'
7 | import { KafkaService } from '@code-gear/api/common'
8 | import { QueryHandlers } from '@/queries/handlers'
9 | import { CqrsModule } from '@nestjs/cqrs'
10 |
11 | @Module({
12 | imports: [
13 | HttpModule,
14 | EnvModule,
15 | CqrsModule,
16 | ListenerModule.forRoot({
17 | isMicroservice: true
18 | })
19 | ],
20 | providers: [KafkaService, ...QueryHandlers],
21 | controllers: [CodeExecutorConsumer],
22 | exports: []
23 | })
24 | export class CodeExecutorModule {}
25 |
--------------------------------------------------------------------------------
/apps/server/service-code-executor/src/exceptions/failed-to-fetch.exception.ts:
--------------------------------------------------------------------------------
1 | import { RpcException } from '@nestjs/microservices'
2 |
3 | export class FailedToFetchException extends RpcException {
4 | constructor(status = 400) {
5 | super({
6 | code: status,
7 | message: `Failed to get response from api.codex.jaagrav.in (${status}).`
8 | })
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/apps/server/service-code-executor/src/exceptions/index.ts:
--------------------------------------------------------------------------------
1 | export { FailedToFetchException } from './failed-to-fetch.exception'
2 |
--------------------------------------------------------------------------------
/apps/server/service-code-executor/src/lib/helpers/transform-language.ts:
--------------------------------------------------------------------------------
1 | import { ExecuteCodeApiDTO } from '@code-gear/api/common'
2 | import { ExecutorLanguages } from '@code-gear/api/common'
3 | import { ExecutorLanguagesValues } from '@code-gear/api/common'
4 |
5 | type TransformLanguage = Omit & {
6 | language: ExecutorLanguagesValues
7 | }
8 |
9 | export const transformLanguage = (
10 | args: ExecuteCodeApiDTO
11 | ): TransformLanguage => {
12 | return {
13 | ...args,
14 | language: ExecutorLanguages[args.language]
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/apps/server/service-code-executor/src/lib/type-guards.ts:
--------------------------------------------------------------------------------
1 | import { ExecutorApiResponse } from '@code-gear/api/common'
2 | import { ExecutorLanguagesValues } from '@code-gear/api/common'
3 |
4 | export const isExecutorApiResponse = (
5 | res: unknown
6 | ): res is ExecutorApiResponse => {
7 | if (typeof res !== 'object' || res === null) {
8 | return false
9 | }
10 |
11 | if (
12 | 'timeStamp' in res &&
13 | typeof res.timeStamp === 'number' &&
14 | 'output' in res &&
15 | typeof res.output === 'string' &&
16 | 'language' in res &&
17 | typeof res.language === 'string'
18 | ) {
19 | return true
20 | }
21 |
22 | return false
23 | }
24 |
--------------------------------------------------------------------------------
/apps/server/service-code-executor/src/queries/handlers/index.ts:
--------------------------------------------------------------------------------
1 | import { ExecuteCodeHandler } from './execute-code.handler'
2 |
3 | export const QueryHandlers = [ExecuteCodeHandler]
4 |
--------------------------------------------------------------------------------
/apps/server/service-code-executor/src/queries/impl/execute-code.query.ts:
--------------------------------------------------------------------------------
1 | import { ExecuteCodeApiDTO } from '@code-gear/api/common'
2 |
3 | export class ExecuteCodeQuery {
4 | constructor(public readonly payload: ExecuteCodeApiDTO) {}
5 | }
6 |
--------------------------------------------------------------------------------
/apps/server/service-code-executor/src/queries/impl/index.ts:
--------------------------------------------------------------------------------
1 | export * from './execute-code.query'
2 |
--------------------------------------------------------------------------------
/apps/server/service-code-executor/tsconfig.app.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./tsconfig.json",
3 | "compilerOptions": {
4 | "outDir": "../../../dist/out-tsc",
5 | "module": "commonjs",
6 | "types": ["node"],
7 | "emitDecoratorMetadata": true,
8 | "target": "es2021",
9 | "baseUrl": "."
10 | },
11 | "exclude": ["jest.config.ts", "src/**/*.spec.ts", "src/**/*.test.ts"],
12 | "include": ["src/**/*.ts"]
13 | }
14 |
--------------------------------------------------------------------------------
/apps/server/service-code-executor/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "cg-config/src/tsconfig/paths/third-layer.json",
3 | "files": [],
4 | "include": [],
5 | "references": [
6 | {
7 | "path": "./tsconfig.app.json"
8 | },
9 | {
10 | "path": "./tsconfig.spec.json"
11 | }
12 | ],
13 | "compilerOptions": {
14 | "esModuleInterop": true,
15 | "resolveJsonModule": true,
16 | "strictNullChecks": true
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/apps/server/service-code-executor/tsconfig.spec.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./tsconfig.json",
3 | "compilerOptions": {
4 | "outDir": "../../../dist/out-tsc",
5 | "module": "commonjs",
6 | "types": ["jest", "node"]
7 | },
8 | "include": [
9 | "jest.config.ts",
10 | "src/**/*.test.ts",
11 | "src/**/*.spec.ts",
12 | "src/**/*.d.ts"
13 | ]
14 | }
15 |
--------------------------------------------------------------------------------
/commitlint.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | extends: ['@commitlint/config-conventional'],
3 | rules: {
4 | 'scope-case': [2, 'always', 'lower-case'],
5 | 'subject-case': [
6 | 2,
7 | 'never',
8 | ['sentence-case', 'start-case', 'pascal-case']
9 | ],
10 | 'subject-empty': [2, 'never'],
11 | 'subject-full-stop': [2, 'never', '.'],
12 | 'type-case': [2, 'always', 'lower-case'],
13 | 'type-empty': [2, 'never'],
14 | 'type-enum': [
15 | 2,
16 | 'always',
17 | [
18 | 'build',
19 | 'chore',
20 | 'ci',
21 | 'docs',
22 | 'feat',
23 | 'fix',
24 | 'refactor',
25 | 'style',
26 | 'test'
27 | ]
28 | ]
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/jest.config.ts:
--------------------------------------------------------------------------------
1 | import { getJestProjects } from '@nx/jest'
2 |
3 | export default {
4 | projects: getJestProjects(),
5 | }
6 |
--------------------------------------------------------------------------------
/jest.preset.js:
--------------------------------------------------------------------------------
1 | const nxPreset = require('@nx/jest/preset').default
2 |
3 | module.exports = { ...nxPreset }
4 |
--------------------------------------------------------------------------------
/packages/api/common/.config/jest.ts:
--------------------------------------------------------------------------------
1 | import { createJestConfig } from 'cg-config/src/jest'
2 |
3 | export default createJestConfig({
4 | displayName: 'api-common',
5 | layer: 'third'
6 | })
7 |
--------------------------------------------------------------------------------
/packages/api/common/.eslintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": [
3 | "../../../.eslintrc.js"
4 | ],
5 | "ignorePatterns": [
6 | "!**/*",
7 | "package.json",
8 | "jest.config.ts"
9 | ]
10 | }
11 |
--------------------------------------------------------------------------------
/packages/api/common/README.md:
--------------------------------------------------------------------------------
1 | ## api-common
2 |
3 | Reusable modules for nestjs microservices.
4 |
--------------------------------------------------------------------------------
/packages/api/common/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "cg-api-common",
3 | "version": "1.0.0",
4 | "main": "./src/index.js",
5 | "devDependencies": {
6 | "cg-config": "workspace:^"
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/packages/api/common/src/consts/index.ts:
--------------------------------------------------------------------------------
1 | export { Microservice } from './microservices'
2 |
--------------------------------------------------------------------------------
/packages/api/common/src/consts/microservices.ts:
--------------------------------------------------------------------------------
1 | export enum Microservice {
2 | CODE_EXECUTOR = 'codeExecutor',
3 | AUTH = 'auth'
4 | }
5 |
--------------------------------------------------------------------------------
/packages/api/common/src/decorators/index.ts:
--------------------------------------------------------------------------------
1 | export { StringField } from './string-field.decorator'
2 | export { WithUser } from './user.decorator'
3 |
--------------------------------------------------------------------------------
/packages/api/common/src/decorators/string-field.decorator.ts:
--------------------------------------------------------------------------------
1 | import { applyDecorators } from '@nestjs/common'
2 | import { Field } from '@nestjs/graphql'
3 | import { ApiProperty } from '@nestjs/swagger'
4 | import { IsString } from 'class-validator'
5 | import { MaxLength } from 'class-validator'
6 | import { MinLength } from 'class-validator'
7 |
8 | type StringFieldPayload = Partial<{
9 | min: number
10 | max: number
11 | example: string
12 | }>
13 |
14 | export const StringField = ({
15 | min = 6,
16 | max = 14,
17 | example
18 | }: StringFieldPayload) => {
19 | return applyDecorators(
20 | Field(),
21 | IsString(),
22 | MinLength(min),
23 | MaxLength(max),
24 | ApiProperty({ example })
25 | )
26 | }
27 |
--------------------------------------------------------------------------------
/packages/api/common/src/decorators/user.decorator.ts:
--------------------------------------------------------------------------------
1 | import { createParamDecorator } from '@nestjs/common'
2 | import { ExecutionContext } from '@nestjs/common'
3 | import { GqlExecutionContext } from '@nestjs/graphql'
4 |
5 | import { User } from '@/types/_prisma'
6 |
7 | export const WithUser = createParamDecorator((
8 | data: unknown,
9 | context: ExecutionContext
10 | ): User => {
11 | const ctx = GqlExecutionContext.create(context)
12 | return ctx.getContext().req.user
13 | })
14 |
--------------------------------------------------------------------------------
/packages/api/common/src/exception-filters/http-exception.filter.ts:
--------------------------------------------------------------------------------
1 | import { ArgumentsHost } from '@nestjs/common'
2 | import { Catch } from '@nestjs/common'
3 | import { ExceptionFilter } from '@nestjs/common'
4 | import { HttpException } from '@nestjs/common'
5 | import { Request } from 'express'
6 | import { Response } from 'express'
7 |
8 | @Catch(HttpException)
9 | export class HttpExceptionFilter implements ExceptionFilter {
10 | catch(exception: HttpException, host: ArgumentsHost) {
11 | const ctx = host.switchToHttp()
12 | const response = ctx.getResponse()
13 | const request = ctx.getRequest()
14 | const status = exception.getStatus()
15 |
16 | response.status(status).json({
17 | statusCode: status,
18 | timestamp: new Date().toISOString(),
19 | path: request.url,
20 | message: exception.message
21 | })
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/packages/api/common/src/exception-filters/index.ts:
--------------------------------------------------------------------------------
1 | export { HttpExceptionFilter } from './http-exception.filter'
2 | export { RpcExceptionFilter } from './rpc-exception.filter'
3 |
--------------------------------------------------------------------------------
/packages/api/common/src/guards/gql-auth.guard.ts:
--------------------------------------------------------------------------------
1 | import { graphqlArg } from '@code-gear/config'
2 | import { ExecutionContext } from '@nestjs/common'
3 | import { GqlExecutionContext } from '@nestjs/graphql'
4 | import { AuthGuard } from '@nestjs/passport'
5 |
6 | export class GqlAuthGuard extends AuthGuard('local') {
7 | // eslint-disable-next-line @typescript-eslint/no-useless-constructor
8 | constructor() {
9 | super()
10 | }
11 |
12 | getRequest(context: ExecutionContext) {
13 | const ctx = GqlExecutionContext.create(context)
14 | const gqlReq = ctx.getContext().req
15 | gqlReq.body = ctx.getArgs()[graphqlArg]
16 |
17 | return gqlReq
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/packages/api/common/src/guards/gql-local-auth.guard.ts:
--------------------------------------------------------------------------------
1 | import { ExecutionContext } from '@nestjs/common'
2 | import { Injectable } from '@nestjs/common'
3 | import { GqlExecutionContext } from '@nestjs/graphql'
4 | import { AuthGuard } from '@nestjs/passport'
5 |
6 | @Injectable()
7 | export class GqlLocalAuthGuard extends AuthGuard('local') {
8 | async canActivate(context: ExecutionContext): Promise {
9 | const ctxRequest = GqlExecutionContext.create(context).getContext().req
10 | return Boolean(ctxRequest)
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/packages/api/common/src/guards/index.ts:
--------------------------------------------------------------------------------
1 | export { GqlAuthGuard } from './gql-auth.guard'
2 | export { GqlLocalAuthGuard } from './gql-local-auth.guard'
3 | export { JwtAuthGuard } from './jwt-auth.guard'
4 |
--------------------------------------------------------------------------------
/packages/api/common/src/guards/jwt-auth.guard.ts:
--------------------------------------------------------------------------------
1 | import { ExecutionContext } from '@nestjs/common'
2 | import { GqlExecutionContext } from '@nestjs/graphql'
3 | import { AuthGuard } from '@nestjs/passport'
4 |
5 | export class JwtAuthGuard extends AuthGuard('jwt') {
6 | getRequest(context: ExecutionContext) {
7 | const ctx = GqlExecutionContext.create(context)
8 | return ctx.getContext().req
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/packages/api/common/src/index.ts:
--------------------------------------------------------------------------------
1 | export * from './decorators'
2 | export * from './exception-filters'
3 | export * from './guards'
4 | export * from './pipes'
5 | export * from './types/_prisma'
6 | export * from './modules'
7 | export * from './consts'
8 |
--------------------------------------------------------------------------------
/packages/api/common/src/modules/database/database.module.ts:
--------------------------------------------------------------------------------
1 | import { Module } from '@nestjs/common'
2 |
3 | import { DatabaseService } from './database.service'
4 |
5 | @Module({
6 | providers: [DatabaseService],
7 | exports: [DatabaseService]
8 | })
9 | export class DatabaseModule {}
10 |
--------------------------------------------------------------------------------
/packages/api/common/src/modules/database/database.service.ts:
--------------------------------------------------------------------------------
1 | import { INestApplication } from '@nestjs/common'
2 | import { Injectable } from '@nestjs/common'
3 | import { OnModuleInit } from '@nestjs/common'
4 | import { PrismaClient } from '@prisma/client'
5 |
6 | @Injectable()
7 | export class DatabaseService extends PrismaClient implements OnModuleInit {
8 | async onModuleInit() {
9 | await this.$connect()
10 | }
11 |
12 | async enableShutdownHooks(app: INestApplication) {
13 | this.$on('beforeExit', async () => {
14 | await app.close()
15 | })
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/packages/api/common/src/modules/database/index.ts:
--------------------------------------------------------------------------------
1 | export { DatabaseModule } from './database.module'
2 | export { DatabaseService } from './database.service'
3 |
--------------------------------------------------------------------------------
/packages/api/common/src/modules/env/conf/database.config.ts:
--------------------------------------------------------------------------------
1 | import { registerAs } from '@nestjs/config'
2 | import { Env } from '../env.decorator'
3 | import { validateConfig } from '../../../utils/validators'
4 |
5 | class DatabaseValidator {
6 | @Env()
7 | DATABASE_URL: string
8 | }
9 |
10 | export interface DatabaseConfig {
11 | url: string
12 | }
13 |
14 | export const database = registerAs('database', () => {
15 | const conf = validateConfig(process.env, DatabaseValidator)
16 |
17 | return {
18 | url: conf.DATABASE_URL
19 | }
20 | })
21 |
--------------------------------------------------------------------------------
/packages/api/common/src/modules/env/conf/index.ts:
--------------------------------------------------------------------------------
1 | export { misc } from './misc.config'
2 | export { database } from './database.config'
3 | export { server } from './server.config'
4 | export { kafka } from './kafka.config'
5 |
--------------------------------------------------------------------------------
/packages/api/common/src/modules/env/conf/misc.config.ts:
--------------------------------------------------------------------------------
1 | import { validateConfig } from '../../../utils/validators'
2 | import { registerAs } from '@nestjs/config'
3 | import { Env } from '../env.decorator'
4 | import { MiscConfig } from '../types'
5 |
6 | class MiscValidator {
7 | @Env()
8 | CODE_COMPILER_API_URL: string
9 |
10 | @Env()
11 | JWT_SECRET: string
12 |
13 | @Env()
14 | CLIENT_URL: string
15 | }
16 |
17 | export const misc = registerAs('misc', () => {
18 | const conf = validateConfig(process.env, MiscValidator)
19 |
20 | return {
21 | clientUrl: conf.CLIENT_URL,
22 | jwtSecret: conf.JWT_SECRET,
23 | codeExecutorUrl: conf.CODE_COMPILER_API_URL
24 | }
25 | })
26 |
--------------------------------------------------------------------------------
/packages/api/common/src/modules/env/conf/server.config.ts:
--------------------------------------------------------------------------------
1 | import { IsNotEmpty } from 'class-validator'
2 | import { IsString } from 'class-validator'
3 | import { IsNumberString } from 'class-validator'
4 | import { validateConfig } from '../../../utils/validators'
5 | import { registerAs } from '@nestjs/config'
6 | import { Env } from '../env.decorator'
7 | import { ServerConfig } from '../types'
8 |
9 | class ServerValidator {
10 | @IsNumberString()
11 | @IsNotEmpty()
12 | SERVER_PORT: string
13 |
14 | @IsString()
15 | SERVER_PREFIX: string
16 |
17 | @Env()
18 | SERVER_URL: string
19 | }
20 |
21 | export const server = registerAs('server', () => {
22 | const conf = validateConfig(process.env, ServerValidator)
23 |
24 | return {
25 | prefix: conf.SERVER_PREFIX,
26 | port: Number(conf.SERVER_PORT),
27 | url: conf.SERVER_URL
28 | }
29 | })
30 |
--------------------------------------------------------------------------------
/packages/api/common/src/modules/env/env.decorator.ts:
--------------------------------------------------------------------------------
1 | import { applyDecorators } from '@nestjs/common'
2 | import { IsNotEmpty } from 'class-validator'
3 | import { IsString } from 'class-validator'
4 |
5 | export const Env = () => {
6 | return applyDecorators(IsString(), IsNotEmpty())
7 | }
8 |
--------------------------------------------------------------------------------
/packages/api/common/src/modules/env/env.module.ts:
--------------------------------------------------------------------------------
1 | import { Module } from '@nestjs/common'
2 | import { ConfigModule } from '@nestjs/config'
3 | import { database } from './conf'
4 | import { kafka } from './conf'
5 | import { misc } from './conf'
6 | import { server } from './conf'
7 |
8 | @Module({
9 | imports: [
10 | ConfigModule.forRoot({
11 | load: [server, misc, database, kafka],
12 | isGlobal: true
13 | })
14 | ]
15 | })
16 | export class EnvModule {}
17 |
--------------------------------------------------------------------------------
/packages/api/common/src/modules/env/index.ts:
--------------------------------------------------------------------------------
1 | export { EnvModule } from './env.module'
2 |
3 | export { ServerConfig, MiscConfig, KafkaConfig, DatabaseConfig } from './types'
4 |
--------------------------------------------------------------------------------
/packages/api/common/src/modules/env/types/enviroment.interfaces.ts:
--------------------------------------------------------------------------------
1 | export interface DatabaseConfig {
2 | url: string
3 | }
4 |
5 | export interface KafkaConfig {
6 | brokers: string[]
7 | microservices: Record
8 | heartbeatInterval: number
9 | sessionTimeout: number
10 | }
11 |
12 | export interface MiscConfig {
13 | clientUrl: string
14 | jwtSecret: string
15 | codeExecutorUrl: string
16 | }
17 |
18 | export interface ServerConfig {
19 | prefix: string
20 | port: number
21 | url: string
22 | }
23 |
--------------------------------------------------------------------------------
/packages/api/common/src/modules/env/types/index.ts:
--------------------------------------------------------------------------------
1 | export {
2 | ServerConfig,
3 | MiscConfig,
4 | KafkaConfig,
5 | DatabaseConfig
6 | } from './enviroment.interfaces'
7 |
--------------------------------------------------------------------------------
/packages/api/common/src/modules/index.ts:
--------------------------------------------------------------------------------
1 | export * from './kafka'
2 | export * from './env'
3 | export * from './database'
4 | export * from './listener'
5 | export * from './jwt'
6 |
--------------------------------------------------------------------------------
/packages/api/common/src/modules/jwt/index.ts:
--------------------------------------------------------------------------------
1 | export { JwtModule } from './jwt.module'
2 |
--------------------------------------------------------------------------------
/packages/api/common/src/modules/jwt/jwt.module.ts:
--------------------------------------------------------------------------------
1 | import { Module } from '@nestjs/common'
2 | import { JwtModule as NestJwtModule } from '@nestjs/jwt'
3 | import { JwtService } from '@nestjs/jwt'
4 | import { jwtSecret } from '@code-gear/config'
5 |
6 | @Module({
7 | imports: [
8 | NestJwtModule.register({
9 | secret: jwtSecret,
10 | signOptions: {
11 | expiresIn: '24h'
12 | }
13 | })
14 | ],
15 | exports: [NestJwtModule]
16 | })
17 | export class JwtModule {}
18 |
--------------------------------------------------------------------------------
/packages/api/common/src/modules/kafka/index.ts:
--------------------------------------------------------------------------------
1 | export { KafkaModule } from './kafka.module'
2 | export { KafkaService } from './kafka.service'
3 |
--------------------------------------------------------------------------------
/packages/api/common/src/modules/kafka/kafka.interface.ts:
--------------------------------------------------------------------------------
1 | import { KafkaOptions } from '@nestjs/microservices'
2 | import { Microservice } from '../../consts'
3 |
4 | export interface GetKafkaOptions {
5 | getKafkaOptions: (service: Microservice) => KafkaOptions
6 | }
7 |
--------------------------------------------------------------------------------
/packages/api/common/src/modules/listener/index.ts:
--------------------------------------------------------------------------------
1 | export { ListenerModule } from './listener.module'
2 | export { ListenerService } from './listener.service'
3 |
--------------------------------------------------------------------------------
/packages/api/common/src/modules/listener/listener.consts.ts:
--------------------------------------------------------------------------------
1 | export const NESTJS_FREE_PORT = 0 as const
2 |
--------------------------------------------------------------------------------
/packages/api/common/src/modules/listener/listener.interfaces.ts:
--------------------------------------------------------------------------------
1 | export interface ListenerModuleOptions {
2 | isMicroservice: boolean
3 | }
4 |
5 | export interface ListenerConfig {
6 | isMicroservice: boolean
7 | port: number
8 | }
9 |
--------------------------------------------------------------------------------
/packages/api/common/src/modules/listener/listener.service.ts:
--------------------------------------------------------------------------------
1 | import { Inject } from '@nestjs/common'
2 | import { Injectable } from '@nestjs/common'
3 | import { ListenerConfig } from './listener.interfaces'
4 |
5 | @Injectable()
6 | export class ListenerService {
7 | private readonly isMicroservice: boolean
8 | private readonly port: number
9 |
10 | constructor(
11 | @Inject('ListenerServiceConfig')
12 | private readonly config: ListenerConfig
13 | ) {
14 | this.isMicroservice = config.isMicroservice
15 | this.port = config.port
16 | }
17 |
18 | getListenerCallback() {
19 | return () => {
20 | console.log('Server is running on port', this.port)
21 | }
22 | }
23 |
24 | get PORT() {
25 | return this.port
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/packages/api/common/src/pipes/index.ts:
--------------------------------------------------------------------------------
1 | export { ValidationPipe } from './validation.pipe'
2 |
--------------------------------------------------------------------------------
/packages/api/common/src/pipes/validation.pipe.ts:
--------------------------------------------------------------------------------
1 | import { ArgumentMetadata } from '@nestjs/common'
2 | import { BadRequestException } from '@nestjs/common'
3 | import { Injectable } from '@nestjs/common'
4 | import { PipeTransform } from '@nestjs/common'
5 | import { plainToClass } from 'class-transformer'
6 | import { validate } from 'class-validator'
7 |
8 | @Injectable()
9 | export class ValidationPipe implements PipeTransform {
10 | async transform(value: unknown, metadata: ArgumentMetadata) {
11 | const validationErrors = await validate(
12 | plainToClass(metadata.metatype, value)
13 | )
14 |
15 | if (validationErrors.length > 0) {
16 | const messages = validationErrors.map((err) => {
17 | return `${err.property} - ${Object.values(err.constraints).join(', ')}`
18 | })
19 | throw new BadRequestException(messages.join('. '))
20 | }
21 |
22 | return value
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/packages/api/common/src/types/_prisma.ts:
--------------------------------------------------------------------------------
1 | // AUTO GENERATED FILE BY @kalissaac/prisma-typegen
2 | // DO NOT EDIT
3 |
4 | export interface User {
5 | username: string
6 | password: string
7 | avatarUrl?: string
8 | }
9 |
--------------------------------------------------------------------------------
/packages/api/common/src/types/guards/index.ts:
--------------------------------------------------------------------------------
1 | export * from './is-custom-rpc-exception'
2 |
--------------------------------------------------------------------------------
/packages/api/common/src/types/guards/is-custom-rpc-exception.ts:
--------------------------------------------------------------------------------
1 | import { isObject } from '@grnx-utils/types'
2 | import { RpcException } from '@nestjs/microservices'
3 |
4 | export interface CustomRpcException extends RpcException {
5 | code: number
6 | }
7 |
8 | export const isCustomRpcException = (
9 | rpcException: unknown
10 | ): rpcException is CustomRpcException => {
11 | return (
12 | isObject(rpcException) &&
13 | 'code' in rpcException &&
14 | 'message' in rpcException
15 | )
16 | }
17 |
--------------------------------------------------------------------------------
/packages/api/common/src/utils/validators/env.validator.ts:
--------------------------------------------------------------------------------
1 | import { plainToClass } from 'class-transformer'
2 | import { validateSync } from 'class-validator'
3 | import { ClassConstructor } from 'class-transformer/types/interfaces'
4 | import { AnyObject } from '@grnx-utils/types'
5 |
6 | export const validateConfig = (
7 | config: AnyObject,
8 | envVariablesClass: ClassConstructor
9 | ): T => {
10 | const validatedConfig = plainToClass(envVariablesClass, config, {
11 | enableImplicitConversion: true
12 | })
13 |
14 | const errors = validateSync(validatedConfig, {
15 | skipMissingProperties: false
16 | })
17 |
18 | if (errors.length > 0) {
19 | throw new Error(errors.toString())
20 | }
21 |
22 | return validatedConfig
23 | }
24 |
--------------------------------------------------------------------------------
/packages/api/common/src/utils/validators/index.ts:
--------------------------------------------------------------------------------
1 | export { validateConfig } from './env.validator'
2 |
--------------------------------------------------------------------------------
/packages/api/common/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "cg-config/src/tsconfig/paths/third-layer.json",
3 | "compilerOptions": {
4 | "module": "commonjs",
5 | "forceConsistentCasingInFileNames": true,
6 | "strict": true,
7 | "noImplicitOverride": true,
8 | "noPropertyAccessFromIndexSignature": false,
9 | "noImplicitReturns": true,
10 | "noFallthroughCasesInSwitch": true,
11 | "strictNullChecks": true,
12 | "strictPropertyInitialization": false
13 | },
14 | "files": [],
15 | "include": [],
16 | "references": [
17 | {
18 | "path": "./tsconfig.lib.json"
19 | },
20 | {
21 | "path": "./tsconfig.spec.json"
22 | }
23 | ]
24 | }
25 |
--------------------------------------------------------------------------------
/packages/api/common/tsconfig.lib.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./tsconfig.json",
3 | "compilerOptions": {
4 | "outDir": "../../../dist/out-tsc",
5 | "declaration": true,
6 | "types": ["node"],
7 | "target": "es2021",
8 | "strictNullChecks": true,
9 | "noImplicitAny": true,
10 | "strictBindCallApply": true,
11 | "forceConsistentCasingInFileNames": true,
12 | "noFallthroughCasesInSwitch": true,
13 | "baseUrl": "."
14 | },
15 | "include": ["src/**/*.ts"],
16 | "exclude": ["jest.config.ts", "src/**/*.spec.ts", "src/**/*.test.ts"]
17 | }
18 |
--------------------------------------------------------------------------------
/packages/api/common/tsconfig.spec.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./tsconfig.json",
3 | "compilerOptions": {
4 | "outDir": "../../../dist/out-tsc",
5 | "module": "commonjs",
6 | "types": ["jest", "node"]
7 | },
8 | "include": [
9 | "jest.config.ts",
10 | "src/**/*.test.ts",
11 | "src/**/*.spec.ts",
12 | "src/**/*.d.ts"
13 | ]
14 | }
15 |
--------------------------------------------------------------------------------
/packages/api/contracts/.eslintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": [
3 | "../../../.eslintrc.js"
4 | ],
5 | "ignorePatterns": [
6 | "!**/*",
7 | "package.json",
8 | "jest.config.ts"
9 | ]
10 | }
11 |
--------------------------------------------------------------------------------
/packages/api/contracts/README.md:
--------------------------------------------------------------------------------
1 | # api-contracts
2 |
3 | This library was generated with [Nx](https://nx.dev).
4 |
--------------------------------------------------------------------------------
/packages/api/contracts/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "cg-api-contracts",
3 | "version": "1.0.0",
4 | "main": "./src/index.js",
5 | "devDependencies": {
6 | "cg-config": "workspace:^"
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/packages/api/contracts/project.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "api-contracts",
3 | "$schema": "../../../node_modules/nx/schemas/project-schema.json",
4 | "sourceRoot": "packages/api/contracts/src",
5 | "projectType": "library",
6 | "targets": {
7 | "lint": {
8 | "executor": "@nx/linter:eslint",
9 | "outputs": ["{options.outputFile}"],
10 | "options": {
11 | "lintFilePatterns": ["packages/api/contracts/**/*.ts"]
12 | }
13 | }
14 | },
15 | "tags": []
16 | }
17 |
--------------------------------------------------------------------------------
/packages/api/contracts/src/dto/execute-code.dto.ts:
--------------------------------------------------------------------------------
1 | import { ApiProperty } from '@nestjs/swagger'
2 | import { IsIn } from 'class-validator'
3 | import { IsOptional } from 'class-validator'
4 | import { IsString } from 'class-validator'
5 | import { CodeExecutorRequest } from './../interfaces'
6 | import { ExecutorLanguages } from './../interfaces'
7 | import { ExecutorLanguagesKeys } from './../interfaces'
8 |
9 | export class ExecuteCodeApiDTO implements CodeExecutorRequest {
10 | @IsString()
11 | @ApiProperty({ example: 'print("hello world")', description: 'Your code' })
12 | readonly code: string
13 |
14 | @IsIn(Object.keys(ExecutorLanguages))
15 | @ApiProperty({ example: 'python', description: 'Code language' })
16 | readonly language: ExecutorLanguagesKeys
17 |
18 | @IsString()
19 | @IsOptional()
20 | readonly input?: string
21 | }
22 |
--------------------------------------------------------------------------------
/packages/api/contracts/src/dto/index.ts:
--------------------------------------------------------------------------------
1 | export * from './execute-code.dto'
2 |
--------------------------------------------------------------------------------
/packages/api/contracts/src/index.ts:
--------------------------------------------------------------------------------
1 | export * from './rpc'
2 | export * from './interfaces'
3 | export * from './dto'
4 | export * from './inputs'
5 | export * from './responses'
6 |
--------------------------------------------------------------------------------
/packages/api/contracts/src/inputs/index.ts:
--------------------------------------------------------------------------------
1 | export * from './sign-in.input'
2 |
--------------------------------------------------------------------------------
/packages/api/contracts/src/inputs/sign-in.input.ts:
--------------------------------------------------------------------------------
1 | import { StringField } from '@code-gear/api/common'
2 | import { InputType } from '@nestjs/graphql'
3 |
4 | @InputType()
5 | export class SignIn {
6 | @StringField({ example: 'user123' })
7 | username: string
8 |
9 | @StringField({ example: 'password456' })
10 | password: string
11 | }
12 |
--------------------------------------------------------------------------------
/packages/api/contracts/src/interfaces/auth.interfaces.ts:
--------------------------------------------------------------------------------
1 | export interface AccessToken {
2 | accessToken: string
3 | }
4 |
5 | export interface WithUsername {
6 | username: string
7 | }
8 |
9 | export interface SignInForm extends WithUsername {
10 | password: string
11 | }
12 |
13 | export interface UserEntity extends WithUsername {
14 | avatarUrl: string
15 | }
16 |
17 | export interface SignInResponse {
18 | isError: boolean
19 | }
20 |
--------------------------------------------------------------------------------
/packages/api/contracts/src/interfaces/execute-code.interfaces.ts:
--------------------------------------------------------------------------------
1 | import { HttpStatus } from '@nestjs/common'
2 |
3 | export interface CodeExecutorRequest {
4 | code: string
5 | language: string
6 | input?: string
7 | }
8 |
9 | export interface ExecutorApiResponse {
10 | timeStamp: number
11 | status: HttpStatus
12 | output: string
13 | error: string
14 | language: T
15 | info: string
16 | }
17 |
18 | export const ExecutorLanguages = {
19 | java: 'java',
20 | python: 'py',
21 | cpp: 'cpp',
22 | c: 'c',
23 | go: 'go',
24 | cs: 'cs',
25 | javascript: 'js'
26 | } as const
27 |
28 | export type ExecutorLanguagesKeys = keyof typeof ExecutorLanguages
29 | export type ExecutorLanguagesValues =
30 | (typeof ExecutorLanguages)[ExecutorLanguagesKeys]
31 |
--------------------------------------------------------------------------------
/packages/api/contracts/src/interfaces/index.ts:
--------------------------------------------------------------------------------
1 | export * from './auth.interfaces'
2 | export * from './execute-code.interfaces'
3 |
--------------------------------------------------------------------------------
/packages/api/contracts/src/responses/index.ts:
--------------------------------------------------------------------------------
1 | export { AccessTokenResponse } from './token.response'
2 | export { UserResponse } from './user.response'
3 |
--------------------------------------------------------------------------------
/packages/api/contracts/src/responses/token.response.ts:
--------------------------------------------------------------------------------
1 | import { Field } from '@nestjs/graphql'
2 | import { ObjectType } from '@nestjs/graphql'
3 | import { ApiProperty } from '@nestjs/swagger'
4 |
5 | import { AccessToken as CommonAccessToken } from '@code-gear/api/common'
6 |
7 | @ObjectType()
8 | export class AccessTokenResponse implements CommonAccessToken {
9 | @Field()
10 | @ApiProperty({ description: 'Authorization token (jwt)' })
11 | accessToken: string
12 | }
13 |
--------------------------------------------------------------------------------
/packages/api/contracts/src/responses/user.response.ts:
--------------------------------------------------------------------------------
1 | import { Field } from '@nestjs/graphql'
2 | import { ObjectType } from '@nestjs/graphql'
3 | import { ApiProperty } from '@nestjs/swagger'
4 |
5 | import { User } from '@code-gear/api/common'
6 |
7 | @ObjectType()
8 | export class UserResponse implements Omit {
9 | @Field()
10 | @ApiProperty({ description: 'Username (used as userId)' })
11 | username: string
12 |
13 | @Field({ nullable: true })
14 | @ApiProperty({ description: 'User avatar location' })
15 | avatarUrl: string
16 | }
17 |
--------------------------------------------------------------------------------
/packages/api/contracts/src/rpc/auth.rpc.ts:
--------------------------------------------------------------------------------
1 | export const SIGN_IN = 'auth.sign-in' as const
2 |
3 | export const GET_PROFILE = 'auth.get-profile' as const
4 |
--------------------------------------------------------------------------------
/packages/api/contracts/src/rpc/code-executor.rpc.ts:
--------------------------------------------------------------------------------
1 | export const EXECUTE_CODE = 'code-executor.execute-code' as const
2 |
--------------------------------------------------------------------------------
/packages/api/contracts/src/rpc/index.ts:
--------------------------------------------------------------------------------
1 | export * as CodeExecutorTopic from './code-executor.rpc'
2 | export * as AuthTopic from './auth.rpc'
3 |
--------------------------------------------------------------------------------
/packages/api/contracts/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "cg-config/src/tsconfig/paths/third-layer.json",
3 | "compilerOptions": {
4 | "module": "commonjs",
5 | "forceConsistentCasingInFileNames": true,
6 | "strict": true,
7 | "noImplicitOverride": true,
8 | "noPropertyAccessFromIndexSignature": false,
9 | "noImplicitReturns": true,
10 | "noFallthroughCasesInSwitch": true,
11 | "strictNullChecks": true,
12 | "strictPropertyInitialization": false
13 | },
14 | "files": [],
15 | "include": [],
16 | "references": [
17 | {
18 | "path": "./tsconfig.lib.json"
19 | }
20 | ]
21 | }
22 |
--------------------------------------------------------------------------------
/packages/api/contracts/tsconfig.lib.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./tsconfig.json",
3 | "compilerOptions": {
4 | "outDir": "../../../dist/out-tsc",
5 | "declaration": true,
6 | "types": ["node"],
7 | "target": "es2021",
8 | "strictNullChecks": true,
9 | "noImplicitAny": true,
10 | "strictBindCallApply": true,
11 | "forceConsistentCasingInFileNames": true,
12 | "noFallthroughCasesInSwitch": true,
13 | "baseUrl": "."
14 | },
15 | "include": ["src/**/*.ts"],
16 | "exclude": ["jest.config.ts", "src/**/*.spec.ts", "src/**/*.test.ts"]
17 | }
18 |
--------------------------------------------------------------------------------
/packages/config/.eslintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": ["../../.eslintrc.js"],
3 | "ignorePatterns": ["!**/*"]
4 | }
5 |
--------------------------------------------------------------------------------
/packages/config/README.md:
--------------------------------------------------------------------------------
1 | ## config
2 |
3 | Reusable configurations for all applications and libraries.
4 |
--------------------------------------------------------------------------------
/packages/config/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "cg-config",
3 | "version": "1.0.0"
4 | }
5 |
--------------------------------------------------------------------------------
/packages/config/project.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "config",
3 | "$schema": "../../node_modules/nx/schemas/project-schema.json",
4 | "sourceRoot": "packages/config/src",
5 | "projectType": "library",
6 | "targets": {
7 | "lint": {
8 | "executor": "@nx/linter:eslint",
9 | "outputs": [
10 | "{options.outputFile}"
11 | ],
12 | "options": {
13 | "lintFilePatterns": [
14 | "packages/config/**/*.ts"
15 | ],
16 | "fix": true
17 | }
18 | }
19 | },
20 | "tags": []
21 | }
22 |
--------------------------------------------------------------------------------
/packages/config/src/babel/vite.json:
--------------------------------------------------------------------------------
1 | {
2 | "presets": [
3 | [
4 | "@nx/react/babel",
5 | {
6 | "runtime": "automatic",
7 | "useBuiltIns": "usage"
8 | }
9 | ]
10 | ],
11 | "plugins": [
12 | [
13 | "styled-components",
14 | {
15 | "pure": true,
16 | "ssr": true
17 | }
18 | ]
19 | ]
20 | }
21 |
--------------------------------------------------------------------------------
/packages/config/src/consts/client.ts:
--------------------------------------------------------------------------------
1 | export const clientUrl = process.env.CLIENT_URL ?? 'http://localhost:3000'
2 |
3 | export const appName = 'code_gear'
4 |
--------------------------------------------------------------------------------
/packages/config/src/consts/server.ts:
--------------------------------------------------------------------------------
1 | export const serverPrefix = process.env.SERVER_PREFIX ?? ''
2 |
3 | export const serverPort = process.env.SERVER_PORT ?? 6868
4 |
5 | export const compilerApiUrl =
6 | process.env.CODE_COMPILER_API_URL ?? 'https://api.codex.jaagrav.in'
7 |
8 | export const serverUrl = process.env.SERVER_URL ?? 'http://localhost:6868'
9 |
10 | export const EndPoints = {
11 | CODE_EXECUTOR_API: 'execute',
12 | _GRAPHQL: 'graphql'
13 | } as const
14 |
15 | export const serverAppName = 'CodeGear API'
16 |
17 | export const serverDocsPrefix = 'docs'
18 |
19 | export const graphqlArg = '_graphql'
20 |
21 | export const jwtSecret =
22 | process.env.JWT_SECRET || 'I_WILL_REMOVE_THIS_AND_REWRITE_TO_CONFIG_SERVICE'
23 |
--------------------------------------------------------------------------------
/packages/config/src/index.ts:
--------------------------------------------------------------------------------
1 | export * from './consts/client'
2 | export * from './consts/server'
3 | export { createPreviewDefaults, createStorybookConfig } from './storybook'
4 |
--------------------------------------------------------------------------------
/packages/config/src/jest/create-jest-config.ts:
--------------------------------------------------------------------------------
1 | import { resolveRootPath } from '../lib'
2 | import { ProjectLayer } from '../types'
3 |
4 | interface CreateJestConfigPayload {
5 | layer: ProjectLayer
6 | displayName: string
7 | }
8 |
9 | export const createJestConfig = (options: CreateJestConfigPayload) => {
10 | const rootPath = resolveRootPath(options.layer)
11 |
12 | return {
13 | displayName: options.displayName,
14 | preset: `${rootPath}/jest.preset.js`,
15 | testEnvironment: 'node',
16 | transform: {
17 | '^.+\\.[tj]s$': ['ts-jest', { tsconfig: '/tsconfig.spec.json' }]
18 | },
19 | moduleFileExtensions: ['ts', 'tsx'],
20 | coverageDirectory: `${rootPath}/coverage/apps/${options.displayName}`
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/packages/config/src/jest/index.ts:
--------------------------------------------------------------------------------
1 | export { createJestConfig } from './create-jest-config'
2 |
--------------------------------------------------------------------------------
/packages/config/src/lib.ts:
--------------------------------------------------------------------------------
1 | import { ProjectLayer } from './types'
2 |
3 | export const resolveRootPath = (layer: ProjectLayer) => {
4 | return layer === 'second' ? '../..' : '../../..'
5 | }
6 |
--------------------------------------------------------------------------------
/packages/config/src/storybook/create-storybook-config.ts:
--------------------------------------------------------------------------------
1 | import type { StorybookConfig } from '@storybook/react-vite'
2 |
3 | interface StorybookConfigPayload {
4 | viteConfigPath: string
5 | viteFinal: (config: StorybookConfig) => StorybookConfig
6 | }
7 |
8 | type CreateStorybookConfig = (args: StorybookConfigPayload) => StorybookConfig
9 |
10 | export const createStorybookConfig: CreateStorybookConfig = ({
11 | viteConfigPath,
12 | viteFinal
13 | }) => ({
14 | stories: ['../../src/**/*.stories.@(js|jsx|ts|tsx)'],
15 | addons: [
16 | '@storybook/addon-essentials',
17 | '@storybook/addon-interactions',
18 | '@storybook/addon-jest',
19 | '@storybook/addon-coverage',
20 | '@storybook/addon-actions'
21 | ],
22 | framework: {
23 | name: '@storybook/react-vite',
24 | options: {
25 | builder: {
26 | viteConfigPath
27 | }
28 | }
29 | },
30 | viteFinal
31 | })
32 |
--------------------------------------------------------------------------------
/packages/config/src/storybook/index.ts:
--------------------------------------------------------------------------------
1 | export { createPreviewDefaults } from './create-preview-defaults'
2 | export { createStorybookConfig } from './create-storybook-config'
3 |
--------------------------------------------------------------------------------
/packages/config/src/storybook/plugins/create-viewports.ts:
--------------------------------------------------------------------------------
1 | export const viewports = [600, 800, 1000, 1200, 1500]
2 |
3 | const widthToStr = (w: number) => w.toString() + 'px'
4 |
5 |
6 | const generateViewPort = (width: number) => {
7 | return {
8 | name: widthToStr(width),
9 | styles: {
10 | width: widthToStr(width),
11 | height: '1080px'
12 | }
13 | }
14 | }
15 | export const createViewPorts = () => {
16 | return Object.fromEntries(
17 | viewports.map((i) => [widthToStr(i), generateViewPort(i)])
18 | )
19 | }
20 |
--------------------------------------------------------------------------------
/packages/config/src/tsconfig/base.json:
--------------------------------------------------------------------------------
1 | {
2 | "compileOnSave": false,
3 | "compilerOptions": {
4 | "sourceMap": true,
5 | "declaration": false,
6 | "moduleResolution": "node",
7 | "emitDecoratorMetadata": true,
8 | "experimentalDecorators": true,
9 | "importHelpers": true,
10 | "target": "es2015",
11 | "module": "esnext",
12 | "lib": ["es2020", "dom"],
13 | "skipLibCheck": true,
14 | "skipDefaultLibCheck": true,
15 | "strictNullChecks": true
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/packages/config/src/tsconfig/paths/second-layer.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./../base.json",
3 | "compilerOptions": {
4 | "paths": {
5 | "@/*": ["./src/*"],
6 | "@code-gear/api/common": ["../../packages/api/common/src/index.ts"],
7 | "@code-gear/api/contracts": ["../../packages/api/contracts/src/index.ts"],
8 | "@code-gear/api/services": ["../../packages/api/services/src/index.ts"],
9 | "@code-gear/web/editor": ["../../packages/web/editor/src/app/index.ts"],
10 | "@code-gear/web/shared": ["../../packages/web/shared/src/index.ts"],
11 | "@code-gear/web/ui": ["../../packages/web/ui/src/index.ts"],
12 | "@code-gear/config": ["../../packages/config/src/index.ts"]
13 | }
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/packages/config/src/tsconfig/paths/third-layer.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./../base.json",
3 | "compilerOptions": {
4 | "paths": {
5 | "@/*": ["./src/*"],
6 | "@code-gear/api/common": ["../../../packages/api/common/src/index.ts"],
7 | "@code-gear/api/contracts": ["../../../packages/api/contracts/src/index.ts"],
8 | "@code-gear/api/services": ["../../../packages/api/services/src/index.ts"],
9 | "@code-gear/web/editor": ["../../../packages/web/editor/src/index.ts"],
10 | "@code-gear/web/shared": ["../../../packages/web/shared/src/index.ts"],
11 | "@code-gear/web/ui": ["../../../packages/web/ui/src/index.ts"],
12 | "@code-gear/config": ["../../../packages/config/src/index.ts"]
13 | }
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/packages/config/src/types.ts:
--------------------------------------------------------------------------------
1 | export type ProjectLayer = 'second' | 'third'
2 |
--------------------------------------------------------------------------------
/packages/config/src/vite/builders/aliases.ts:
--------------------------------------------------------------------------------
1 | import { AliasOptions } from 'vite'
2 | import { ResolveOptions } from 'vite'
3 |
4 | type DefineAliases = ResolveOptions & { alias: AliasOptions }
5 |
6 | export const defineAliases = (): DefineAliases => {
7 | return {
8 | preserveSymlinks: true,
9 | // Nx and Vite have issues with full support for yarn workspaces,
10 | // so i just will use tsconfig paths ;)
11 |
12 | alias: {}
13 |
14 | // alias: {
15 | // '@code-gear/client-shared': resolve(
16 | // __dirname,
17 | // resolvepackages('client-shared', 'src', 'index.js')
18 | // )
19 | // }
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/packages/config/src/vite/builders/build.ts:
--------------------------------------------------------------------------------
1 | import { BuildOptions } from 'vite'
2 |
3 | import { CreateViteConfigOptions } from '../types'
4 |
5 | export const defineBuildOptions = (
6 | options: CreateViteConfigOptions
7 | ): BuildOptions => {
8 | if (options.projectType === 'library') {
9 | return {
10 | lib: {
11 | entry: 'src/index.ts',
12 | name: options.projectName,
13 | fileName: 'index',
14 | formats: ['es', 'cjs']
15 | },
16 | rollupOptions: {
17 | external: [
18 | 'react',
19 | 'react-dom',
20 | 'react/jsx-runtime',
21 | ...options.external
22 | ]
23 | }
24 | }
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/packages/config/src/vite/builders/globals.ts:
--------------------------------------------------------------------------------
1 | export const defineGlobals = (): Record => {
2 | return {
3 | 'process.env': process.env,
4 | _isDev_: process.env.NODE_ENV === 'development'
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/packages/config/src/vite/builders/index.ts:
--------------------------------------------------------------------------------
1 | export { defineAliases } from './aliases'
2 | export { defineBuildOptions } from './build'
3 | export { defineGlobals } from './globals'
4 | export { definePlugins } from './plugins'
5 | export { definePreviewOptions } from './preview'
6 | export { defineServerOptions } from './server'
7 | export { defineVitest } from './vitest'
8 |
--------------------------------------------------------------------------------
/packages/config/src/vite/builders/plugins.ts:
--------------------------------------------------------------------------------
1 | // /
2 | import { join } from 'path'
3 | import { PluginOption } from 'vite'
4 | import dts from 'vite-plugin-dts'
5 | import viteTsConfigPaths from 'vite-tsconfig-paths'
6 |
7 | import { CreateViteConfigOptions } from '../types'
8 |
9 | export const definePlugins = (
10 | options: CreateViteConfigOptions
11 | ): PluginOption[] => {
12 | const defaultPlugins: PluginOption[] = [viteTsConfigPaths()]
13 |
14 | if (options.projectType === 'library') {
15 | defaultPlugins.push([
16 | dts({
17 | entryRoot: 'src',
18 | tsConfigFilePath: join(options.rootDir, 'tsconfig.lib.json'),
19 | skipDiagnostics: true
20 | })
21 | ])
22 | }
23 |
24 | return [...defaultPlugins, ...options.plugins]
25 | }
26 |
--------------------------------------------------------------------------------
/packages/config/src/vite/builders/preview.ts:
--------------------------------------------------------------------------------
1 | import { ServerOptions } from 'vite'
2 |
3 | import { CreateViteConfigOptions } from '../types'
4 |
5 | export const definePreviewOptions = (
6 | options: CreateViteConfigOptions
7 | ): ServerOptions => {
8 | if (options.projectType === 'application') {
9 | return {
10 | port: 4200,
11 | host: 'localhost'
12 | }
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/packages/config/src/vite/builders/server.ts:
--------------------------------------------------------------------------------
1 | import { PreviewOptions } from 'vite'
2 | import { ServerOptions } from 'vite'
3 |
4 | import { CreateViteConfigOptions } from '../types'
5 |
6 | export const defineServerOptions = (
7 | options: CreateViteConfigOptions
8 | ): ServerOptions => {
9 | if (options.projectType === 'application') {
10 | return {
11 | port: 3000,
12 | host: 'localhost',
13 | fs: {
14 | strict: false
15 | }
16 | }
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/packages/config/src/vite/builders/vitest.ts:
--------------------------------------------------------------------------------
1 | import { InlineConfig } from 'vite'
2 |
3 | import { resolveRootPath } from '../../lib'
4 | import { CreateViteConfigOptions } from '../types'
5 |
6 | export const defineVitest = (
7 | options: CreateViteConfigOptions
8 | ): InlineConfig => ({
9 | globals: true,
10 | cache: {
11 | dir: `${resolveRootPath(options.layer)}/node_modules/.vitest`
12 | },
13 | environment: 'jsdom',
14 | include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}']
15 | })
16 |
--------------------------------------------------------------------------------
/packages/config/src/vite/index.ts:
--------------------------------------------------------------------------------
1 | export { createViteConfig } from './create-vite-config'
2 |
--------------------------------------------------------------------------------
/packages/config/src/vite/misc.ts:
--------------------------------------------------------------------------------
1 | import { resolveRootPath } from '../lib'
2 | import { CreateViteConfigOptions } from './types'
3 |
4 | export const getCacheDir = (options: CreateViteConfigOptions) => {
5 | return `${resolveRootPath(options.layer)}/node_modules/.vite/${
6 | options.projectName
7 | }`
8 | }
9 |
--------------------------------------------------------------------------------
/packages/config/src/vite/types.ts:
--------------------------------------------------------------------------------
1 | import { PluginOption } from 'vite'
2 |
3 | import { ProjectLayer } from '../types'
4 |
5 | export interface CreateViteConfigOptions {
6 | layer: ProjectLayer
7 | projectName: string
8 | projectType: 'library' | 'application'
9 | rootDir: string
10 | plugins: PluginOption[]
11 | external: string[]
12 | }
13 |
--------------------------------------------------------------------------------
/packages/config/src/webpack/index.ts:
--------------------------------------------------------------------------------
1 | export { buildWebpackConfig } from './build-webpack-config'
2 |
--------------------------------------------------------------------------------
/packages/config/src/webpack/resolvers/index.ts:
--------------------------------------------------------------------------------
1 | export { resolveTsconfigPaths } from './tsconfig-paths'
2 |
--------------------------------------------------------------------------------
/packages/config/src/webpack/types.ts:
--------------------------------------------------------------------------------
1 | import { Configuration } from 'webpack'
2 |
3 | import { ProjectLayer } from '../types'
4 |
5 | export interface BuildWebpackConfigPayload {
6 | rootDir: string
7 | layer: ProjectLayer
8 | }
9 |
10 | export interface WebpackConfigOptions extends BuildWebpackConfigPayload {
11 | config: Configuration
12 | }
13 |
--------------------------------------------------------------------------------
/packages/config/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "cg-config/src/tsconfig/paths/second-layer.json",
3 | "compilerOptions": {
4 | "allowJs": false,
5 | "esModuleInterop": false,
6 | "allowSyntheticDefaultImports": true,
7 | "module": "ESNext",
8 | "moduleResolution": "Node",
9 | "strictNullChecks": true
10 | },
11 | "files": [],
12 | "include": ["src/**/*.ts"],
13 | "references": [
14 | {
15 | "path": "./tsconfig.lib.json"
16 | }
17 | ]
18 | }
19 |
--------------------------------------------------------------------------------
/packages/config/tsconfig.lib.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./tsconfig.json",
3 | "compilerOptions": {
4 | "target": "ES2017",
5 | "module": "ESNext",
6 | "outDir": "../../dist/out-tsc",
7 | "declaration": true,
8 | "types": ["node"],
9 | "baseUrl": "."
10 | },
11 | "include": ["src/**/*.ts"]
12 | }
13 |
--------------------------------------------------------------------------------
/packages/generator/README.md:
--------------------------------------------------------------------------------
1 | ## generator
2 |
3 | Library for generating small modules for applications.
4 |
--------------------------------------------------------------------------------
/packages/generator/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "cg-generator",
3 | "version": "1.0.0"
4 | }
5 |
--------------------------------------------------------------------------------
/packages/generator/project.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "generator",
3 | "$schema": "../../node_modules/nx/schemas/project-schema.json",
4 | "sourceRoot": "packages/generator/src",
5 | "projectType": "library",
6 | "tags": [],
7 | "targets": {
8 | "new": {
9 | "command": "cross-env HYGEN_TMPLS=templates hygen _generator g --generator_name {args.name}",
10 | "options": {
11 | "cwd": "packages/generator"
12 | }
13 | }
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/packages/generator/templates/_generator/g/README.ejs.t:
--------------------------------------------------------------------------------
1 | ---
2 | to: templates/<%= generator_name %>/README.md
3 | ---
4 |
5 | ### Generator: <%= generator_name %>
6 |
7 | ### Methods
8 |
9 | ---
10 |
11 |
12 |
13 |
14 | new (default)
15 |
16 |
17 | - Arguments
18 |
19 | ```ts
20 | // module_name: string
21 | ```
22 |
23 |
24 |
25 | ### Run
26 |
27 | `hygen <%= generator_name %> [method]`
28 |
--------------------------------------------------------------------------------
/packages/generator/templates/_generator/g/new/index.ejs.t:
--------------------------------------------------------------------------------
1 | ---
2 | to: templates/<%= generator_name %>/new/index.ejs
3 | ---
4 |
5 | ---
6 | to: /index.ts.template.template
7 | ---
8 |
--------------------------------------------------------------------------------
/packages/generator/templates/_generator/g/prompt.ejs.t:
--------------------------------------------------------------------------------
1 | ---
2 | to: templates/<%= generator_name %>/new/prompt.js
3 | ---
4 |
5 | module.exports = [
6 | {
7 | type: 'input',
8 | name: 'module_name',
9 | message: "Module name:"
10 | }
11 | ]
12 |
13 |
--------------------------------------------------------------------------------
/packages/generator/templates/_generator/g/prompt.js:
--------------------------------------------------------------------------------
1 | module.exports = [
2 | {
3 | type: 'input',
4 | name: 'generator_name',
5 | message: 'Generator name:'
6 | }
7 | ]
8 |
--------------------------------------------------------------------------------
/packages/generator/templates/fsd-module/README.md:
--------------------------------------------------------------------------------
1 | ### Generator: fsd-module
2 |
3 | This generator creates a module using the
4 | [Feature-Sliced-Design](https://feature-sliced.design/ru/docs/get-started/overview) methodology.
5 |
6 | ### Methods
7 |
8 | ---
9 |
10 | - new (General case)
11 |
12 | ### Run
13 |
14 | `hygen fsd-module [method]`
15 |
--------------------------------------------------------------------------------
/packages/generator/templates/fsd-module/new/hooks/index.ejs.t:
--------------------------------------------------------------------------------
1 | ---
2 | to: <%= module_name %>/hooks/index.ts.template.template
3 | ---
4 |
--------------------------------------------------------------------------------
/packages/generator/templates/fsd-module/new/index.ejs.t:
--------------------------------------------------------------------------------
1 | ---
2 | to: src/<%= module_name %>/index.ts.template.template
3 | ---
4 | export { <%= module_name.charAt(0).toUpperCase() + module_name.slice(1) %> } from './ui/<%= module_name %>'
5 |
--------------------------------------------------------------------------------
/packages/generator/templates/fsd-module/new/lib/index.ejs.t:
--------------------------------------------------------------------------------
1 | ---
2 | to: <%= module_name %>/lib/index.ts.template.template
3 | ---
4 |
--------------------------------------------------------------------------------
/packages/generator/templates/fsd-module/new/prompt.js:
--------------------------------------------------------------------------------
1 | module.exports = [
2 | {
3 | type: 'input',
4 | name: 'module_name',
5 | message: 'Module name:'
6 | }
7 | ]
8 |
--------------------------------------------------------------------------------
/packages/generator/templates/fsd-module/new/store/gitkeep.ejs.t:
--------------------------------------------------------------------------------
1 | ---
2 | to: <%= module_name %>/store/.gitkeep
3 | ---
4 |
5 |
--------------------------------------------------------------------------------
/packages/generator/templates/fsd-module/new/ui/component.ejs.t:
--------------------------------------------------------------------------------
1 | ---
2 | to: <%= module_name %>/ui/<%= module_name %>.tsx
3 | ---
4 |
5 | interface <%= module_name.charAt(0).toUpperCase() + module_name.slice(1) %>Props {
6 |
7 | }
8 |
9 | export const <%= module_name.charAt(0).toUpperCase() + module_name.slice(1) %> = () => {
10 | return null
11 | }
12 |
13 |
--------------------------------------------------------------------------------
/packages/generator/templates/fsd-module/new/ui/component.styles.ejs.t:
--------------------------------------------------------------------------------
1 | ---
2 | to: <%= module_name %>/ui/<%= module_name %>.styles.ts
3 | ---
4 | import styled from 'styled-components'
5 |
6 | export const <%= module_name.charAt(0).toUpperCase() + module_name.slice(1) %>Styles = styled.div`
7 |
8 | `
9 |
--------------------------------------------------------------------------------
/packages/generator/templates/ui/README.md:
--------------------------------------------------------------------------------
1 | ### Generator: ui
2 |
3 | ### Methods
4 |
5 | ---
6 |
7 |
8 | new (default)
9 |
10 |
11 | - Arguments
12 |
13 | ```ts
14 | // module_name: string
15 | ```
16 |
17 |
18 |
19 | ### Run
20 |
21 | `hygen ui [method]`
22 |
--------------------------------------------------------------------------------
/packages/generator/templates/ui/new/component.ejs.t:
--------------------------------------------------------------------------------
1 | ---
2 | to: src/<%= module_name %>/<%= module_name %>.tsx
3 | ---
4 | import { <%= h.changeCase.pascal(module_name) %>Styles } from './<%= module_name %>.styles'
5 |
6 | export interface <%= h.changeCase.pascal(module_name) %>Props {
7 |
8 | }
9 |
10 | export const <%= h.changeCase.pascal(module_name) %> = (props: <%= h.changeCase.pascal(module_name) %>Props) => {
11 | return <%= module_name %>
12 | }
13 |
14 |
--------------------------------------------------------------------------------
/packages/generator/templates/ui/new/component.styles.ejs.t:
--------------------------------------------------------------------------------
1 | ---
2 | to: src/<%= module_name %>/<%= module_name %>.styles.ts
3 | ---
4 | import styled from 'styled-components'
5 |
6 | export const <%= h.changeCase.pascal(module_name) %>Styles = styled.div`
7 |
8 | `
9 |
--------------------------------------------------------------------------------
/packages/generator/templates/ui/new/index.ejs.t:
--------------------------------------------------------------------------------
1 | ---
2 | to: src/<%= module_name %>/index.ts.template.template
3 | ---
4 |
5 | export { <%= h.changeCase.pascal(module_name) %> } from './<%= module_name %>'
6 |
--------------------------------------------------------------------------------
/packages/generator/templates/ui/new/prompt.js:
--------------------------------------------------------------------------------
1 | module.exports = [
2 | {
3 | type: 'input',
4 | name: 'module_name',
5 | message: 'Module name:'
6 | }
7 | ]
8 |
--------------------------------------------------------------------------------
/packages/web/editor/.babelrc:
--------------------------------------------------------------------------------
1 | {"extends": "cg-config/src/babel/vite.json"}
2 |
--------------------------------------------------------------------------------
/packages/web/editor/.config/vite.ts:
--------------------------------------------------------------------------------
1 | // It is important to specify relative paths here.
2 | import { resolve } from 'path'
3 | import react from '@vitejs/plugin-react'
4 | import dynamicImport from 'vite-plugin-dynamic-import'
5 |
6 | import { createViteConfig } from '../../../config/src/vite'
7 |
8 | export default createViteConfig({
9 | projectName: 'editor',
10 | projectType: 'library',
11 | rootDir: resolve(__dirname, '..'),
12 | layer: 'third',
13 | external: ['antd', 'react-router-dom', 'react-smooth-scrollbar'],
14 | plugins: [react(), dynamicImport()]
15 | })
16 |
--------------------------------------------------------------------------------
/packages/web/editor/.eslintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": [
3 | "../../../.eslintrc.js"
4 | ],
5 | "ignorePatterns": [
6 | "!**/*"
7 | ],
8 | "parser": "@typescript-eslint/parser",
9 | "globals": {
10 | "FileSystemFileHandle": true,
11 | "OpenFilePickerOptions": true
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/packages/web/editor/README.md:
--------------------------------------------------------------------------------
1 | # web-editor
2 |
3 | Code editor page. Logic core.
4 |
--------------------------------------------------------------------------------
/packages/web/editor/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "cg-editor",
3 | "version": "0.0.1",
4 | "main": "./index.js",
5 | "types": "./index.d.ts",
6 | "exports": {
7 | ".": {
8 | "import": "./index.mjs",
9 | "require": "./index.js"
10 | }
11 | },
12 | "devDependencies": {
13 | "cg-config": "workspace:^"
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/packages/web/editor/src/app/index.ts:
--------------------------------------------------------------------------------
1 | import { lazy } from 'react'
2 |
3 | const Editor = lazy(() => import('./editor'))
4 |
5 | export { Editor }
6 |
7 | export {
8 | EditorActions,
9 | EditorGetters,
10 | EditorStore,
11 | EditorStoreContext
12 | } from './providers/editor-store'
13 | export type { ModalsPayload, ModalsState } from './providers/modals-provider'
14 | export { ModalsContext } from './providers/modals-provider'
15 | export { useCustomTheme } from './providers/theme-loader'
16 |
--------------------------------------------------------------------------------
/packages/web/editor/src/app/providers/editor-store/config/editor.services.ts:
--------------------------------------------------------------------------------
1 | import { makeAutoObservable } from 'mobx'
2 |
3 | import { ExecuteServices } from '@/widgets/header'
4 |
5 | import EditorActions from './editor.actions'
6 | import EditorGetters from './editor.getters'
7 | import EditorStore from './editor.store'
8 |
9 | class EditorServices {
10 | private state: EditorStore
11 | private readonly getters: EditorGetters
12 | private readonly actions: EditorActions
13 | readonly codeRunner: ExecuteServices
14 |
15 | constructor(root: EditorStore) {
16 | makeAutoObservable(this)
17 |
18 | this.state = root
19 | this.getters = root.getters
20 | this.actions = root.actions
21 | this.codeRunner = new ExecuteServices(root)
22 | }
23 | }
24 |
25 | export default EditorServices
26 |
--------------------------------------------------------------------------------
/packages/web/editor/src/app/providers/editor-store/index.ts:
--------------------------------------------------------------------------------
1 | export { default as EditorActions } from './config/editor.actions'
2 | export { default as EditorGetters } from './config/editor.getters'
3 | export { default as EditorStore } from './config/editor.store'
4 | export {
5 | EditorStoreContext,
6 | default as EditorStoreProvider
7 | } from './ui/editor-store-provider'
8 |
--------------------------------------------------------------------------------
/packages/web/editor/src/app/providers/editor-store/lib/default-code-template.ts:
--------------------------------------------------------------------------------
1 | import { LanguagesValues } from '@/shared/consts/languages'
2 |
3 | export const defaultCodeTemplate = `// Hello World! Here you can edit the code in 10 different languages. 😎
4 |
5 | const camel = 'I like apples'
6 |
7 | // Run the code and look in the terminal.
8 | console.log(camel)
9 |
10 | // You can edit and run the code in real time
11 | // and your friends will see it! Sign in if you want to see more features.
12 | `
13 | export const defaultCodeLang: LanguagesValues = 'javascript'
14 |
--------------------------------------------------------------------------------
/packages/web/editor/src/app/providers/editor-store/ui/editor-store-provider.tsx:
--------------------------------------------------------------------------------
1 | import { createContext } from 'react'
2 | import { ReactNode } from 'react'
3 |
4 | import EditorStore from '../config/editor.store'
5 |
6 | export const EditorStoreContext = createContext({} as EditorStore)
7 |
8 | export const EditorStoreProvider = ({ children }: { children: ReactNode }) => {
9 | const root = new EditorStore()
10 |
11 | return (
12 |
13 | {children}
14 |
15 | )
16 | }
17 |
18 | export default EditorStoreProvider
19 |
--------------------------------------------------------------------------------
/packages/web/editor/src/app/providers/modals-provider/index.ts:
--------------------------------------------------------------------------------
1 | export type { ModalsPayload, ModalsState } from './types'
2 | export {
3 | ModalsContext,
4 | default as ModalsContextProvider
5 | } from './ui/modals-context-provider'
6 |
--------------------------------------------------------------------------------
/packages/web/editor/src/app/providers/modals-provider/types.ts:
--------------------------------------------------------------------------------
1 | import { AnyObject } from '@code-gear/web/shared'
2 | import { ReducerPayload } from '@code-gear/web/shared'
3 | import { ReactElement } from 'react'
4 |
5 | import { TerminalTabKeys } from '@/widgets/terminal'
6 |
7 | export interface ModalsState {
8 | isTerminalOpened: boolean
9 | isSettingsOpened: boolean
10 | isHtmlPreviewOpened: boolean
11 | isSignInOpened: boolean
12 | selectedTerminalTab: TerminalTabKeys
13 | ModalComponents: {
14 | SignIn: (props: AnyObject) => ReactElement
15 | }
16 | }
17 |
18 | export interface ModalsPayload extends ReducerPayload {
19 | toggle?: (prop: keyof ModalsState) => void
20 | }
21 |
--------------------------------------------------------------------------------
/packages/web/editor/src/app/providers/theme-loader/hooks/index.ts:
--------------------------------------------------------------------------------
1 | export { useCustomTheme } from './use-custom-theme/use-custom-theme'
2 | export { useThemeLoader } from './use-theme-loader/use-theme-loader'
3 |
--------------------------------------------------------------------------------
/packages/web/editor/src/app/providers/theme-loader/hooks/use-custom-theme/use-custom-theme.ts:
--------------------------------------------------------------------------------
1 | import { Hex } from '@code-gear/web/shared'
2 | import { useMonaco } from '@monaco-editor/react'
3 |
4 | import { CUSTOM_THEME } from '@/shared/consts/themes'
5 |
6 | interface CustomTheme {
7 | background: Hex
8 | color: Hex
9 | }
10 |
11 | export const useCustomTheme = () => {
12 | const monaco = useMonaco()
13 |
14 | return ({ background, color }: CustomTheme) => {
15 | monaco.editor.defineTheme(CUSTOM_THEME, {
16 | base: 'vs',
17 | inherit: true,
18 | rules: [],
19 | colors: {
20 | 'editor.background': background,
21 | 'editor.foreground': color
22 | }
23 | })
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/packages/web/editor/src/app/providers/theme-loader/hooks/use-theme-loader/assert-theme-object.ts:
--------------------------------------------------------------------------------
1 | import { isObject } from '@code-gear/web/shared'
2 | import { editor } from 'monaco-editor'
3 |
4 | import EditorErrors from '@/shared/exceptions'
5 |
6 | // eslint-disable-next-line prefer-arrow/prefer-arrow-functions
7 | export function assertThemeObject(
8 | value: unknown
9 | ): asserts value is editor.IStandaloneThemeData {
10 | if (
11 | isObject(value) &&
12 | 'base' in value &&
13 | typeof value.base === 'string' &&
14 | 'colors' in value &&
15 | isObject(value.colors)
16 | ) {
17 | return
18 | }
19 |
20 | throw new Error(EditorErrors.WrongJsonObject('ThemeObject'))
21 | }
22 |
--------------------------------------------------------------------------------
/packages/web/editor/src/app/providers/theme-loader/index.ts:
--------------------------------------------------------------------------------
1 | export * from './hooks'
2 | export { default as ThemeLoader } from './ui/theme-loader'
3 |
--------------------------------------------------------------------------------
/packages/web/editor/src/app/providers/theme-loader/ui/theme-loader.tsx:
--------------------------------------------------------------------------------
1 | import { Display } from '@code-gear/web/shared'
2 | import { WithChildren } from '@code-gear/web/shared'
3 |
4 | import { useThemeLoader } from '../hooks'
5 |
6 | const ThemeLoader = ({ children }: WithChildren) => {
7 | const isLoaded = useThemeLoader()
8 | return {children}
9 | }
10 |
11 | export default ThemeLoader
12 |
--------------------------------------------------------------------------------
/packages/web/editor/src/app/styles/editor.styles.ts:
--------------------------------------------------------------------------------
1 | import { s } from '@code-gear/web/shared'
2 | import styled from 'styled-components'
3 |
4 | export const EditorStyles = styled.div`
5 | ${s.wh('100vw', '100vh')}
6 | `
7 |
8 | export const EditorWrapper = styled.div`
9 | ${s.wh('100%', 'calc(100% - 45px)')};
10 | display: flex;
11 | `
12 |
--------------------------------------------------------------------------------
/packages/web/editor/src/entities/editor-core/index.ts:
--------------------------------------------------------------------------------
1 | export { default as EditorCore } from './editor-core'
2 |
--------------------------------------------------------------------------------
/packages/web/editor/src/entities/header-options/index.ts:
--------------------------------------------------------------------------------
1 | export { default as HeaderOptions } from './ui/header-options'
2 |
--------------------------------------------------------------------------------
/packages/web/editor/src/entities/header-options/ui/header-options.styles.ts:
--------------------------------------------------------------------------------
1 | import { s } from '@code-gear/web/shared'
2 | import styled from 'styled-components'
3 |
4 | export const HeaderOptionsStyles = styled.div`
5 | ${s.wh('23%', '28px')}
6 | ${s.flex('flex-start', 'center')}
7 | gap: 25px;
8 | img {
9 | transition: transform 200ms;
10 | &:hover {
11 | transform: scale(1.1) rotate(3deg);
12 | }
13 | }
14 | `
15 |
16 | export const Option = styled.span`
17 | color: ${({ theme }) => theme.light};
18 | cursor: pointer;
19 | `
20 |
--------------------------------------------------------------------------------
/packages/web/editor/src/entities/header-right-section/index.ts:
--------------------------------------------------------------------------------
1 | export { default as HeaderRightSection } from './ui/header-right-section'
2 |
--------------------------------------------------------------------------------
/packages/web/editor/src/entities/header-right-section/ui/header-right-section.styles.ts:
--------------------------------------------------------------------------------
1 | import { s } from '@code-gear/web/shared'
2 | import styled from 'styled-components'
3 |
4 | import { Icon } from '@/widgets/aside/ui/aside.styles'
5 |
6 | export const RightSection = styled.div`
7 | ${s.wh('23%', '100%')};
8 | ${s.flex('flex-start', 'center')};
9 | gap: 25px;
10 | `
11 |
12 | interface HeaderIconProps {
13 | readonly $disabled: boolean
14 | }
15 |
16 | export const HeaderIcon = styled(Icon)`
17 | margin-top: 0;
18 | margin-left: 20px;
19 | svg {
20 | color: ${({ theme, $disabled }) =>
21 | $disabled ? theme.secondaryGrey : theme.light};
22 | }
23 | `
24 |
--------------------------------------------------------------------------------
/packages/web/editor/src/entities/key-buildings/index.ts:
--------------------------------------------------------------------------------
1 | export { default as KeyBuildings } from './key-buildings'
2 |
--------------------------------------------------------------------------------
/packages/web/editor/src/entities/preview-editor/index.ts:
--------------------------------------------------------------------------------
1 | export { default as PreviewEditor } from './ui/preview-editor'
2 |
--------------------------------------------------------------------------------
/packages/web/editor/src/entities/preview-editor/ui/preview-editor.styles.ts:
--------------------------------------------------------------------------------
1 | import { s } from '@code-gear/web/shared'
2 | import styled from 'styled-components'
3 |
4 | export const EditorContainer = styled.div`
5 | ${s.wh('33%', '100%')};
6 | border-radius: 6px;
7 | `
8 |
9 | export const EditorTitle = styled.h4`
10 | &:first-letter {
11 | text-transform: capitalize;
12 | }
13 | svg {
14 | margin-bottom: -3px;
15 | }
16 | color: ${s.color('light')};
17 | margin: 9px 4px;
18 | margin-top: 5px;
19 | font-size: ${({ theme }) => theme.fz9};
20 | `
21 |
--------------------------------------------------------------------------------
/packages/web/editor/src/entities/preview-i-frame/index.ts:
--------------------------------------------------------------------------------
1 | export { default as IFrame } from './ui/i-frame'
2 |
--------------------------------------------------------------------------------
/packages/web/editor/src/entities/preview-i-frame/lib/create-html-template.ts:
--------------------------------------------------------------------------------
1 | import { PreviewState } from '@/components/html-preivew/types'
2 |
3 | export const createHtmlTemplate = ({ html, css, javascript }: PreviewState) => `
4 |
5 | ${html}
6 |
7 |
8 |
15 |
16 | `
17 |
--------------------------------------------------------------------------------
/packages/web/editor/src/entities/terminal-output/hooks/index.ts:
--------------------------------------------------------------------------------
1 | export { useTerminalOutputAnimations } from './use-terminal-output-animations'
2 |
--------------------------------------------------------------------------------
/packages/web/editor/src/entities/terminal-output/index.ts:
--------------------------------------------------------------------------------
1 | export type { TerminalOutputHandle } from './ui/terminal-output/terminal-output'
2 | export { default as TerminalOutput } from './ui/terminal-output/terminal-output'
3 |
--------------------------------------------------------------------------------
/packages/web/editor/src/features/language-switcher/hooks/index.ts:
--------------------------------------------------------------------------------
1 | export { useMappedLanguages } from './use-mapped-languages'
2 |
--------------------------------------------------------------------------------
/packages/web/editor/src/features/language-switcher/hooks/use-mapped-languages.ts:
--------------------------------------------------------------------------------
1 | import { languages } from '@/shared/consts/languages'
2 |
3 | export const useMappedLanguages = () => {
4 | const mapped = [...new Set(Object.values(languages))]
5 |
6 | return mapped.map((lang) => ({
7 | value: lang,
8 | label: lang
9 | }))
10 | }
11 |
--------------------------------------------------------------------------------
/packages/web/editor/src/features/language-switcher/index.ts:
--------------------------------------------------------------------------------
1 | export { default as LanguageSwitcher } from './ui/language-switcher'
2 |
--------------------------------------------------------------------------------
/packages/web/editor/src/features/language-switcher/ui/language-switcher.tsx:
--------------------------------------------------------------------------------
1 | import { Select } from '@code-gear/web/ui'
2 | import { observer } from 'mobx-react-lite'
3 |
4 | import { LanguagesValues } from '@/shared/consts/languages'
5 | import { useGetters } from '@/shared/hooks'
6 |
7 | import { useMappedLanguages } from '../hooks'
8 |
9 | const LanguageSwitcher = observer(() => {
10 | const languages = useMappedLanguages()
11 | const getters = useGetters()
12 | const language = getters.getActiveLanguage()
13 | const activeTab = getters.getActiveTab()
14 |
15 | const handleChange = (newLanguage: LanguagesValues) => {
16 | activeTab.lang = newLanguage
17 | }
18 |
19 | return (
20 |