Compare commits
78 Commits
fix/graphq
...
reference/
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6086ebd824 | ||
|
|
dd83f8ef24 | ||
|
|
682200ce68 | ||
|
|
18910e429c | ||
|
|
924d6a87d0 | ||
|
|
fc15a5a1e4 | ||
|
|
477811c414 | ||
|
|
631a16feb0 | ||
|
|
d0f4080771 | ||
|
|
0da75cb23d | ||
|
|
abba09ea80 | ||
|
|
fb5967294b | ||
|
|
21d8b8fb2e | ||
|
|
7ce85fee81 | ||
|
|
10615ca1a1 | ||
|
|
dd5c876e32 | ||
|
|
c2002f0f27 | ||
|
|
9cfba797f6 | ||
|
|
d1e6ffda49 | ||
|
|
4f71b163ea | ||
|
|
775bf9a9c3 | ||
|
|
33ecea5d75 | ||
|
|
551dfd1e20 | ||
|
|
8663934075 | ||
|
|
a73d64ddc1 | ||
|
|
99f119d262 | ||
|
|
6a8a687616 | ||
|
|
6a33083790 | ||
|
|
5c7c355d95 | ||
|
|
328fb1176d | ||
|
|
fdf0c95f9a | ||
|
|
9e90e703f7 | ||
|
|
0a241663ac | ||
|
|
d58fc42190 | ||
|
|
7a9bcd0a5c | ||
|
|
e3482f66cc | ||
|
|
186803a465 | ||
|
|
bdfdb44743 | ||
|
|
4f8b346024 | ||
|
|
ec1104396e | ||
|
|
630ab1f4f4 | ||
|
|
cabc775f58 | ||
|
|
f515ac4f52 | ||
|
|
11b8bb4571 | ||
|
|
7bf66d8339 | ||
|
|
8d81ff3dc2 | ||
|
|
5538b9a5b9 | ||
|
|
7077fe4621 | ||
|
|
42144b724b | ||
|
|
14183d8b91 | ||
|
|
f8e1d78824 | ||
|
|
1e8805ab4f | ||
|
|
a294a2804b | ||
|
|
8507278c40 | ||
|
|
d22bae2c60 | ||
|
|
2fefa55dce | ||
|
|
e0787d7fca | ||
|
|
c9c5df36ab | ||
|
|
5768274ef1 | ||
|
|
493594b5d7 | ||
|
|
56c96f952d | ||
|
|
2c06a66c0a | ||
|
|
1a26a0e986 | ||
|
|
9f1ee724b4 | ||
|
|
d28679de15 | ||
|
|
c8f62c4f04 | ||
|
|
8aa066e2ab | ||
|
|
a38e6cd427 | ||
|
|
c3ba45f875 | ||
|
|
9061511609 | ||
|
|
443e095775 | ||
|
|
09e6fb246a | ||
|
|
5413bc584a | ||
|
|
7006fa57e2 | ||
|
|
1a629a1219 | ||
|
|
9b60dc5f2d | ||
|
|
21021a3cd9 | ||
|
|
fd5db6c8c9 |
@@ -1,9 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "Hoppscotch",
|
|
||||||
"image": "mcr.microsoft.com/devcontainers/typescript-node:18",
|
|
||||||
"forwardPorts": [3000],
|
|
||||||
"features": {
|
|
||||||
"ghcr.io/NicoVIII/devcontainer-features/pnpm:1": {}
|
|
||||||
},
|
|
||||||
"postCreateCommand": "cp .env.example .env && pnpm i"
|
|
||||||
}
|
|
||||||
106
.dockerignore
@@ -1,2 +1,104 @@
|
|||||||
node_modules
|
Dockerfile
|
||||||
**/*/node_modules
|
.vscode
|
||||||
|
.github
|
||||||
|
|
||||||
|
# Created by .ignore support plugin (hsz.mobi)
|
||||||
|
|
||||||
|
# Firebase
|
||||||
|
.firebase
|
||||||
|
|
||||||
|
### Node template
|
||||||
|
# Logs
|
||||||
|
logs
|
||||||
|
*.log
|
||||||
|
npm-debug.log*
|
||||||
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
||||||
|
|
||||||
|
# Runtime data
|
||||||
|
pids
|
||||||
|
*.pid
|
||||||
|
*.seed
|
||||||
|
*.pid.lock
|
||||||
|
|
||||||
|
# Directory for instrumented libs generated by jscoverage/JSCover
|
||||||
|
lib-cov
|
||||||
|
|
||||||
|
# Coverage directory used by tools like istanbul
|
||||||
|
coverage
|
||||||
|
|
||||||
|
# nyc test coverage
|
||||||
|
.nyc_output
|
||||||
|
|
||||||
|
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
|
||||||
|
.grunt
|
||||||
|
|
||||||
|
# Bower dependency directory (https://bower.io/)
|
||||||
|
bower_components
|
||||||
|
|
||||||
|
# node-waf configuration
|
||||||
|
.lock-wscript
|
||||||
|
|
||||||
|
# Compiled binary addons (https://nodejs.org/api/addons.html)
|
||||||
|
build/Release
|
||||||
|
|
||||||
|
# Dependency directories
|
||||||
|
node_modules/
|
||||||
|
jspm_packages/
|
||||||
|
|
||||||
|
# TypeScript v1 declaration files
|
||||||
|
typings/
|
||||||
|
|
||||||
|
# Optional npm cache directory
|
||||||
|
.npm
|
||||||
|
|
||||||
|
# Optional eslint cache
|
||||||
|
.eslintcache
|
||||||
|
|
||||||
|
# Optional REPL history
|
||||||
|
.node_repl_history
|
||||||
|
|
||||||
|
# Output of 'npm pack'
|
||||||
|
*.tgz
|
||||||
|
|
||||||
|
# Yarn Integrity file
|
||||||
|
.yarn-integrity
|
||||||
|
|
||||||
|
# dotenv environment variables file
|
||||||
|
.env
|
||||||
|
|
||||||
|
# parcel-bundler cache (https://parceljs.org/)
|
||||||
|
.cache
|
||||||
|
|
||||||
|
# next.js build output
|
||||||
|
.next
|
||||||
|
|
||||||
|
# nuxt.js build output
|
||||||
|
.nuxt
|
||||||
|
|
||||||
|
# Nuxt generate
|
||||||
|
dist
|
||||||
|
|
||||||
|
# vuepress build output
|
||||||
|
.vuepress/dist
|
||||||
|
|
||||||
|
# Serverless directories
|
||||||
|
.serverless
|
||||||
|
|
||||||
|
# IDE / Editor
|
||||||
|
.idea
|
||||||
|
|
||||||
|
# Service worker
|
||||||
|
sw.*
|
||||||
|
|
||||||
|
# Mac OSX
|
||||||
|
.DS_Store
|
||||||
|
|
||||||
|
# Vim swap files
|
||||||
|
*.swp
|
||||||
|
|
||||||
|
# Build data
|
||||||
|
.hoppscotch
|
||||||
|
|
||||||
|
# File explorer
|
||||||
|
.directory
|
||||||
|
|||||||
61
.env.example
@@ -1,61 +0,0 @@
|
|||||||
#-----------------------Backend Config------------------------------#
|
|
||||||
# Prisma Config
|
|
||||||
DATABASE_URL=postgresql://postgres:testpass@hoppscotch-db:5432/hoppscotch
|
|
||||||
|
|
||||||
# Auth Tokens Config
|
|
||||||
JWT_SECRET="secret1233"
|
|
||||||
TOKEN_SALT_COMPLEXITY=10
|
|
||||||
MAGIC_LINK_TOKEN_VALIDITY= 3
|
|
||||||
REFRESH_TOKEN_VALIDITY="604800000" # Default validity is 7 days (604800000 ms) in ms
|
|
||||||
ACCESS_TOKEN_VALIDITY="86400000" # Default validity is 1 day (86400000 ms) in ms
|
|
||||||
SESSION_SECRET='add some secret here'
|
|
||||||
|
|
||||||
# Hoppscotch App Domain Config
|
|
||||||
REDIRECT_URL="http://localhost:3000"
|
|
||||||
WHITELISTED_ORIGINS = "http://localhost:3170,http://localhost:3000,http://localhost:3100"
|
|
||||||
VITE_ALLOWED_AUTH_PROVIDERS = GOOGLE,GITHUB,MICROSOFT,EMAIL
|
|
||||||
|
|
||||||
# Google Auth Config
|
|
||||||
GOOGLE_CLIENT_ID="************************************************"
|
|
||||||
GOOGLE_CLIENT_SECRET="************************************************"
|
|
||||||
GOOGLE_CALLBACK_URL="http://localhost:3170/v1/auth/google/callback"
|
|
||||||
GOOGLE_SCOPE="email,profile"
|
|
||||||
|
|
||||||
# Github Auth Config
|
|
||||||
GITHUB_CLIENT_ID="************************************************"
|
|
||||||
GITHUB_CLIENT_SECRET="************************************************"
|
|
||||||
GITHUB_CALLBACK_URL="http://localhost:3170/v1/auth/github/callback"
|
|
||||||
GITHUB_SCOPE="user:email"
|
|
||||||
|
|
||||||
# Microsoft Auth Config
|
|
||||||
MICROSOFT_CLIENT_ID="************************************************"
|
|
||||||
MICROSOFT_CLIENT_SECRET="************************************************"
|
|
||||||
MICROSOFT_CALLBACK_URL="http://localhost:3170/v1/auth/microsoft/callback"
|
|
||||||
MICROSOFT_SCOPE="user.read"
|
|
||||||
MICROSOFT_TENANT="common"
|
|
||||||
|
|
||||||
# Mailer config
|
|
||||||
MAILER_SMTP_URL="smtps://user@domain.com:pass@smtp.domain.com"
|
|
||||||
MAILER_ADDRESS_FROM='"From Name Here" <from@example.com>'
|
|
||||||
|
|
||||||
# Rate Limit Config
|
|
||||||
RATE_LIMIT_TTL=60 # In seconds
|
|
||||||
RATE_LIMIT_MAX=100 # Max requests per IP
|
|
||||||
|
|
||||||
|
|
||||||
#-----------------------Frontend Config------------------------------#
|
|
||||||
|
|
||||||
|
|
||||||
# Base URLs
|
|
||||||
VITE_BASE_URL=http://localhost:3000
|
|
||||||
VITE_SHORTCODE_BASE_URL=http://localhost:3000
|
|
||||||
VITE_ADMIN_URL=http://localhost:3100
|
|
||||||
|
|
||||||
# Backend URLs
|
|
||||||
VITE_BACKEND_GQL_URL=http://localhost:3170/graphql
|
|
||||||
VITE_BACKEND_WS_URL=ws://localhost:3170/graphql
|
|
||||||
VITE_BACKEND_API_URL=http://localhost:3170/v1
|
|
||||||
|
|
||||||
# Terms Of Service And Privacy Policy Links (Optional)
|
|
||||||
VITE_APP_TOS_LINK=https://docs.hoppscotch.io/support/terms
|
|
||||||
VITE_APP_PRIVACY_POLICY_LINK=https://docs.hoppscotch.io/support/privacy
|
|
||||||
2
.github/dependabot.yml
vendored
@@ -5,6 +5,6 @@ updates:
|
|||||||
schedule:
|
schedule:
|
||||||
interval: weekly
|
interval: weekly
|
||||||
time: '00:00'
|
time: '00:00'
|
||||||
open-pull-requests-limit: 0
|
open-pull-requests-limit: 10
|
||||||
reviewers:
|
reviewers:
|
||||||
- liyasthomas
|
- liyasthomas
|
||||||
|
|||||||
2
.github/pull_request_template.md
vendored
@@ -23,4 +23,4 @@ Closes # <!-- Issue # here -->
|
|||||||
- [ ] All the tests have passed
|
- [ ] All the tests have passed
|
||||||
|
|
||||||
### Additional Information
|
### Additional Information
|
||||||
<!-- Any additional information like breaking changes, dependencies added, screenshots, comparisons between new and old behaviour, etc. -->
|
<!-- Any additional information like breaking changes, dependencies added, screenshots, comparisons between new and old behavior, etc. -->
|
||||||
|
|||||||
93
.github/workflows/codeql-analysis.yml
vendored
@@ -1,63 +1,72 @@
|
|||||||
name: "CodeQL analysis"
|
# For most projects, this workflow file will not need changing; you simply need
|
||||||
|
# to commit it to your repository.
|
||||||
|
#
|
||||||
|
# You may wish to alter this file to override the set of languages analyzed,
|
||||||
|
# or to provide custom queries or build logic.
|
||||||
|
#
|
||||||
|
# ******** NOTE ********
|
||||||
|
# We have attempted to detect the languages in your repository. Please check
|
||||||
|
# the `language` matrix defined below to confirm you have the correct set of
|
||||||
|
# supported CodeQL languages.
|
||||||
|
#
|
||||||
|
name: "CodeQL"
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches: [main]
|
branches: [ main ]
|
||||||
pull_request:
|
pull_request:
|
||||||
branches: [main]
|
# The branches below must be a subset of the branches above
|
||||||
|
branches: [ main ]
|
||||||
schedule:
|
schedule:
|
||||||
# ┌───────────── minute (0 - 59)
|
- cron: '39 7 * * 2'
|
||||||
# │ ┌───────────── hour (0 - 23)
|
|
||||||
# │ │ ┌───────────── day of the month (1 - 31)
|
|
||||||
# │ │ │ ┌───────────── month (1 - 12 or JAN-DEC)
|
|
||||||
# │ │ │ │ ┌───────────── day of the week (0 - 6 or SUN-SAT)
|
|
||||||
# │ │ │ │ │
|
|
||||||
# │ │ │ │ │
|
|
||||||
# │ │ │ │ │
|
|
||||||
# * * * * *
|
|
||||||
- cron: '30 1 * * 0'
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
analyze:
|
analyze:
|
||||||
name: Analyze
|
name: Analyze
|
||||||
# CodeQL runs on ubuntu-latest, windows-latest, and macos-latest
|
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
permissions:
|
permissions:
|
||||||
# required for all workflows
|
|
||||||
security-events: write
|
|
||||||
|
|
||||||
# only required for workflows in private repositories
|
|
||||||
actions: read
|
actions: read
|
||||||
contents: read
|
contents: read
|
||||||
|
security-events: write
|
||||||
|
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
language: [ 'javascript' ]
|
||||||
|
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
|
||||||
|
# Learn more about CodeQL language support at https://git.io/codeql-language-support
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout repository
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v2
|
||||||
|
|
||||||
# Initializes the CodeQL tools for scanning.
|
# Initializes the CodeQL tools for scanning.
|
||||||
- name: Initialize CodeQL
|
- name: Initialize CodeQL
|
||||||
uses: github/codeql-action/init@v2
|
uses: github/codeql-action/init@v1
|
||||||
with:
|
with:
|
||||||
# Run extended queries including queries using machine learning
|
# Run extended queries including queries using machine learning
|
||||||
queries: security-extended
|
queries: security-extended
|
||||||
languages: ${{ matrix.language }}
|
languages: ${{ matrix.language }}
|
||||||
|
# If you wish to specify custom queries, you can do so here or in a config file.
|
||||||
|
# By default, queries listed here will override any specified in a config file.
|
||||||
|
# Prefix the list here with "+" to use these queries and those in the config file.
|
||||||
|
# queries: ./path/to/local/query, your-org/your-repo/queries@main
|
||||||
|
|
||||||
# Autobuild attempts to build any compiled languages (C/C++, C#, Go, or Java).
|
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
|
||||||
# If this step fails, then you should remove it and run the build manually (see below).
|
# If this step fails, then you should remove it and run the build manually (see below)
|
||||||
- name: Autobuild
|
- name: Autobuild
|
||||||
uses: github/codeql-action/autobuild@v2
|
uses: github/codeql-action/autobuild@v1
|
||||||
|
|
||||||
# ℹ️ Command-line programs to run using the OS shell.
|
# ℹ️ Command-line programs to run using the OS shell.
|
||||||
# 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
|
# 📚 https://git.io/JvXDl
|
||||||
|
|
||||||
# ✏️ If the Autobuild fails above, remove it and uncomment the following
|
# ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
|
||||||
# three lines and modify them (or add more) to build your code if your
|
# and modify them (or add more) to build your code if your project
|
||||||
# project uses a compiled language
|
# uses a compiled language
|
||||||
|
|
||||||
#- run: |
|
#- run: |
|
||||||
# make bootstrap
|
# make bootstrap
|
||||||
# make release
|
# make release
|
||||||
|
|
||||||
- name: Perform CodeQL Analysis
|
- name: Perform CodeQL Analysis
|
||||||
uses: github/codeql-action/analyze@v2
|
uses: github/codeql-action/analyze@v1
|
||||||
|
|||||||
34
.github/workflows/deploy-netlify.yml
vendored
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
name: Deploy to Netlify
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [main]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
name: Push build files to Netlify
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout Repository
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
|
||||||
|
- name: Setup and run pnpm install
|
||||||
|
uses: pnpm/action-setup@v2.2.2
|
||||||
|
with:
|
||||||
|
version: 7
|
||||||
|
run_install: true
|
||||||
|
|
||||||
|
- name: Setup Environment
|
||||||
|
run: mv packages/hoppscotch-app/.env.example packages/hoppscotch-app/.env
|
||||||
|
|
||||||
|
- name: Build Site
|
||||||
|
run: pnpm run generate
|
||||||
|
|
||||||
|
# Deploy the production site with netlify-cli
|
||||||
|
- name: Deploy to Netlify (production)
|
||||||
|
uses: netlify/actions/cli@master
|
||||||
|
env:
|
||||||
|
NETLIFY_SITE_ID: ${{ secrets.NETLIFY_PRODUCTION_SITE_ID }}
|
||||||
|
NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }}
|
||||||
|
with:
|
||||||
|
args: deploy --dir=packages/hoppscotch-app/dist --prod
|
||||||
18
.github/workflows/deploy-prod.yml
vendored
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
name: Deploy to Live Channel
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
deploy_live_website:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- uses: FirebaseExtended/action-hosting-deploy@v0
|
||||||
|
with:
|
||||||
|
repoToken: '${{ secrets.GITHUB_TOKEN }}'
|
||||||
|
firebaseServiceAccount: '${{ secrets.FIREBASE_SERVICE_ACCOUNT_POSTWOMAN_API }}'
|
||||||
|
channelId: live
|
||||||
|
projectId: postwoman-api
|
||||||
45
.github/workflows/deploy-staging-netlify.yml
vendored
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
name: Deploy to Staging Netlify
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
# TODO: Migrate to staging branch only
|
||||||
|
branches: [main]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
name: Push build files to Netlify
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout Repository
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
|
||||||
|
- name: Setup and run pnpm install
|
||||||
|
uses: pnpm/action-setup@v2.2.2
|
||||||
|
with:
|
||||||
|
version: 7
|
||||||
|
run_install: true
|
||||||
|
|
||||||
|
- name: Build Site
|
||||||
|
env:
|
||||||
|
GA_ID: ${{ secrets.STAGING_GA_ID }}
|
||||||
|
GTM_ID: ${{ secrets.STAGING_GTM_ID }}
|
||||||
|
API_KEY: ${{ secrets.STAGING_FB_API_KEY }}
|
||||||
|
AUTH_DOMAIN: ${{ secrets.STAGING_FB_AUTH_DOMAIN }}
|
||||||
|
DATABASE_URL: ${{ secrets.STAGING_FB_DATABASE_URL }}
|
||||||
|
PROJECT_ID: ${{ secrets.STAGING_FB_PROJECT_ID }}
|
||||||
|
STORAGE_BUCKET: ${{ secrets.STAGING_FB_STORAGE_BUCKET }}
|
||||||
|
MESSAGING_SENDER_ID: ${{ secrets.STAGING_FB_MESSAGING_SENDER_ID }}
|
||||||
|
APP_ID: ${{ secrets.STAGING_FB_APP_ID }}
|
||||||
|
BASE_URL: ${{ secrets.STAGING_BASE_URL }}
|
||||||
|
BACKEND_GQL_URL: ${{ secrets.STAGING_BACKEND_GQL_URL }}
|
||||||
|
BACKEND_WS_URL: ${{ secrets.STAGING_BACKEND_WS_URL }}
|
||||||
|
run: pnpm run generate
|
||||||
|
|
||||||
|
# Deploy the staging site with netlify-cli
|
||||||
|
- name: Deploy to Netlify (staging)
|
||||||
|
uses: netlify/actions/cli@master
|
||||||
|
env:
|
||||||
|
NETLIFY_SITE_ID: ${{ secrets.NETLIFY_STAGING_SITE_ID }}
|
||||||
|
NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }}
|
||||||
|
with:
|
||||||
|
args: deploy --dir=packages/hoppscotch-app/dist --prod
|
||||||
39
.github/workflows/publish-docker.yml
vendored
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
name: Publish Docker image
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [main]
|
||||||
|
release:
|
||||||
|
types: [published]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
push_to_registry:
|
||||||
|
name: Push Docker image to Docker Hub
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Check out the repo
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
|
||||||
|
- name: Log in to Docker Hub
|
||||||
|
uses: docker/login-action@f054a8b539a109f9f41c372932f1ae047eff08c9
|
||||||
|
with:
|
||||||
|
username: ${{ secrets.DOCKER_USERNAME }}
|
||||||
|
password: ${{ secrets.DOCKER_PASSWORD }}
|
||||||
|
|
||||||
|
- name: Extract metadata (tags, labels) for Docker
|
||||||
|
id: meta
|
||||||
|
uses: docker/metadata-action@98669ae865ea3cffbcbaa878cf57c20bbf1c6c38
|
||||||
|
with:
|
||||||
|
images: hoppscotch/hoppscotch
|
||||||
|
flavor: |
|
||||||
|
latest=true
|
||||||
|
prefix=
|
||||||
|
suffix=
|
||||||
|
|
||||||
|
- name: Build and push Docker image
|
||||||
|
uses: docker/build-push-action@ad44023a93711e3deb337508980b4b5e9bcdc5dc
|
||||||
|
with:
|
||||||
|
context: .
|
||||||
|
push: true
|
||||||
|
tags: ${{ steps.meta.outputs.tags }}
|
||||||
|
labels: ${{ steps.meta.outputs.labels }}
|
||||||
84
.github/workflows/release-push-docker.yml
vendored
@@ -1,84 +0,0 @@
|
|||||||
name: "Push containers to Docker Hub on release"
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
tags:
|
|
||||||
- '*.*.*'
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
build:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
uses: actions/checkout@v3
|
|
||||||
|
|
||||||
- name: Setup environment
|
|
||||||
run: cp .env.example .env
|
|
||||||
|
|
||||||
- name: Setup QEMU
|
|
||||||
uses: docker/setup-qemu-action@v3
|
|
||||||
|
|
||||||
- name: Setup Docker Buildx
|
|
||||||
uses: docker/setup-buildx-action@v3
|
|
||||||
|
|
||||||
- name: Log in to Docker Hub
|
|
||||||
uses: docker/login-action@v2
|
|
||||||
with:
|
|
||||||
username: ${{ secrets.DOCKER_USERNAME }}
|
|
||||||
password: ${{ secrets.DOCKER_PASSWORD }}
|
|
||||||
|
|
||||||
- name: Build and push the backend container
|
|
||||||
uses: docker/build-push-action@v4
|
|
||||||
with:
|
|
||||||
context: .
|
|
||||||
file: ./prod.Dockerfile
|
|
||||||
target: backend
|
|
||||||
push: true
|
|
||||||
platforms: |
|
|
||||||
linux/amd64
|
|
||||||
linux/arm64
|
|
||||||
tags: |
|
|
||||||
${{ secrets.DOCKER_ORG_NAME }}/${{ secrets.DOCKER_BACKEND_CONTAINER_NAME }}:latest
|
|
||||||
${{ secrets.DOCKER_ORG_NAME }}/${{ secrets.DOCKER_BACKEND_CONTAINER_NAME }}:${{ github.ref_name }}
|
|
||||||
|
|
||||||
- name: Build and push the frontend container
|
|
||||||
uses: docker/build-push-action@v4
|
|
||||||
with:
|
|
||||||
context: .
|
|
||||||
file: ./prod.Dockerfile
|
|
||||||
target: app
|
|
||||||
push: true
|
|
||||||
platforms: |
|
|
||||||
linux/amd64
|
|
||||||
linux/arm64
|
|
||||||
tags: |
|
|
||||||
${{ secrets.DOCKER_ORG_NAME }}/${{ secrets.DOCKER_FRONTEND_CONTAINER_NAME }}:latest
|
|
||||||
${{ secrets.DOCKER_ORG_NAME }}/${{ secrets.DOCKER_FRONTEND_CONTAINER_NAME }}:${{ github.ref_name }}
|
|
||||||
|
|
||||||
- name: Build and push the admin dashboard container
|
|
||||||
uses: docker/build-push-action@v4
|
|
||||||
with:
|
|
||||||
context: .
|
|
||||||
file: ./prod.Dockerfile
|
|
||||||
target: sh_admin
|
|
||||||
push: true
|
|
||||||
platforms: |
|
|
||||||
linux/amd64
|
|
||||||
linux/arm64
|
|
||||||
tags: |
|
|
||||||
${{ secrets.DOCKER_ORG_NAME }}/${{ secrets.DOCKER_SH_ADMIN_CONTAINER_NAME }}:latest
|
|
||||||
${{ secrets.DOCKER_ORG_NAME }}/${{ secrets.DOCKER_SH_ADMIN_CONTAINER_NAME }}:${{ github.ref_name }}
|
|
||||||
|
|
||||||
- name: Build and push the AIO container
|
|
||||||
uses: docker/build-push-action@v4
|
|
||||||
with:
|
|
||||||
context: .
|
|
||||||
file: ./prod.Dockerfile
|
|
||||||
target: aio
|
|
||||||
push: true
|
|
||||||
platforms: |
|
|
||||||
linux/amd64
|
|
||||||
linux/arm64
|
|
||||||
tags: |
|
|
||||||
${{ secrets.DOCKER_ORG_NAME }}/${{ secrets.DOCKER_AIO_CONTAINER_NAME }}:latest
|
|
||||||
${{ secrets.DOCKER_ORG_NAME }}/${{ secrets.DOCKER_AIO_CONTAINER_NAME }}:${{ github.ref_name }}
|
|
||||||
29
.github/workflows/tests.yml
vendored
@@ -2,13 +2,12 @@ name: Node.js CI
|
|||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches: [main, staging, "release/**"]
|
branches: [main]
|
||||||
pull_request:
|
pull_request:
|
||||||
branches: [main, staging, "release/**"]
|
branches: [main]
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
test:
|
build:
|
||||||
name: Test
|
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
strategy:
|
strategy:
|
||||||
@@ -16,23 +15,17 @@ jobs:
|
|||||||
node-version: ["lts/*"]
|
node-version: ["lts/*"]
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- uses: actions/checkout@v2
|
||||||
uses: actions/checkout@v3
|
- uses: actions/setup-node@v2
|
||||||
|
- name: Setup and run pnpm install
|
||||||
- name: Setup environment
|
uses: pnpm/action-setup@v2.2.2
|
||||||
run: mv .env.example .env
|
|
||||||
|
|
||||||
- name: Setup pnpm
|
|
||||||
uses: pnpm/action-setup@v2.2.4
|
|
||||||
with:
|
with:
|
||||||
version: 8
|
version: 7
|
||||||
run_install: true
|
run_install: true
|
||||||
|
- name: Use Node.js ${{ matrix.node-version }}
|
||||||
- name: Setup node
|
uses: actions/setup-node@v2
|
||||||
uses: actions/setup-node@v3
|
|
||||||
with:
|
with:
|
||||||
node-version: ${{ matrix.node }}
|
node-version: ${{ matrix.node-version }}
|
||||||
cache: pnpm
|
cache: pnpm
|
||||||
|
|
||||||
- name: Run tests
|
- name: Run tests
|
||||||
run: pnpm test
|
run: pnpm test
|
||||||
|
|||||||
42
.github/workflows/ui.yml
vendored
@@ -1,42 +0,0 @@
|
|||||||
name: Deploy to Netlify (ui)
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches: [main]
|
|
||||||
# run this workflow only if an update is made to the ui package
|
|
||||||
paths:
|
|
||||||
- "packages/hoppscotch-ui/**"
|
|
||||||
workflow_dispatch:
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
deploy:
|
|
||||||
name: Deploy
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
uses: actions/checkout@v3
|
|
||||||
|
|
||||||
- name: Setup environment
|
|
||||||
run: mv .env.example .env
|
|
||||||
|
|
||||||
- name: Setup pnpm
|
|
||||||
uses: pnpm/action-setup@v2.2.4
|
|
||||||
with:
|
|
||||||
version: 8
|
|
||||||
run_install: true
|
|
||||||
|
|
||||||
- name: Setup node
|
|
||||||
uses: actions/setup-node@v3
|
|
||||||
with:
|
|
||||||
node-version: ${{ matrix.node }}
|
|
||||||
cache: pnpm
|
|
||||||
|
|
||||||
- name: Build site
|
|
||||||
run: pnpm run generate-ui
|
|
||||||
|
|
||||||
# Deploy the ui site with netlify-cli
|
|
||||||
- name: Deploy to Netlify (ui)
|
|
||||||
run: npx netlify-cli@15.11.0 deploy --dir=packages/hoppscotch-ui/.histoire/dist --prod
|
|
||||||
env:
|
|
||||||
NETLIFY_SITE_ID: ${{ secrets.NETLIFY_UI_SITE_ID }}
|
|
||||||
NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }}
|
|
||||||
86
.gitignore
vendored
@@ -1,18 +1,15 @@
|
|||||||
|
# Created by .ignore support plugin (hsz.mobi)
|
||||||
|
|
||||||
# Firebase
|
# Firebase
|
||||||
.firebase
|
.firebase
|
||||||
|
|
||||||
### Node ###
|
### Node template
|
||||||
# Logs
|
# Logs
|
||||||
logs
|
logs
|
||||||
*.log
|
*.log
|
||||||
npm-debug.log*
|
npm-debug.log*
|
||||||
yarn-debug.log*
|
yarn-debug.log*
|
||||||
yarn-error.log*
|
yarn-error.log*
|
||||||
lerna-debug.log*
|
|
||||||
.pnpm-debug.log*
|
|
||||||
|
|
||||||
# Diagnostic reports (https://nodejs.org/api/report.html)
|
|
||||||
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
|
|
||||||
|
|
||||||
# Runtime data
|
# Runtime data
|
||||||
pids
|
pids
|
||||||
@@ -25,7 +22,6 @@ lib-cov
|
|||||||
|
|
||||||
# Coverage directory used by tools like istanbul
|
# Coverage directory used by tools like istanbul
|
||||||
coverage
|
coverage
|
||||||
*.lcov
|
|
||||||
|
|
||||||
# nyc test coverage
|
# nyc test coverage
|
||||||
.nyc_output
|
.nyc_output
|
||||||
@@ -49,27 +45,12 @@ jspm_packages/
|
|||||||
# TypeScript v1 declaration files
|
# TypeScript v1 declaration files
|
||||||
typings/
|
typings/
|
||||||
|
|
||||||
# Snowpack dependency directory (https://snowpack.dev/)
|
|
||||||
web_modules/
|
|
||||||
|
|
||||||
# TypeScript cache
|
|
||||||
*.tsbuildinfo
|
|
||||||
|
|
||||||
# Optional npm cache directory
|
# Optional npm cache directory
|
||||||
.npm
|
.npm
|
||||||
|
|
||||||
# Optional eslint cache
|
# Optional eslint cache
|
||||||
.eslintcache
|
.eslintcache
|
||||||
|
|
||||||
# Optional stylelint cache
|
|
||||||
.stylelintcache
|
|
||||||
|
|
||||||
# Microbundle cache
|
|
||||||
.rpt2_cache/
|
|
||||||
.rts2_cache_cjs/
|
|
||||||
.rts2_cache_es/
|
|
||||||
.rts2_cache_umd/
|
|
||||||
|
|
||||||
# Optional REPL history
|
# Optional REPL history
|
||||||
.node_repl_history
|
.node_repl_history
|
||||||
|
|
||||||
@@ -79,68 +60,26 @@ web_modules/
|
|||||||
# Yarn Integrity file
|
# Yarn Integrity file
|
||||||
.yarn-integrity
|
.yarn-integrity
|
||||||
|
|
||||||
# dotenv environment variable files
|
# dotenv environment variables file
|
||||||
.env
|
.env
|
||||||
.env.development.local
|
|
||||||
.env.test.local
|
|
||||||
.env.production.local
|
|
||||||
.env.local
|
|
||||||
|
|
||||||
# parcel-bundler cache (https://parceljs.org/)
|
# parcel-bundler cache (https://parceljs.org/)
|
||||||
.cache
|
.cache
|
||||||
.parcel-cache
|
|
||||||
|
|
||||||
# Next.js build output
|
# next.js build output
|
||||||
.next
|
.next
|
||||||
out
|
|
||||||
|
|
||||||
# Nuxt.js build / generate output
|
# nuxt.js build output
|
||||||
.nuxt
|
.nuxt
|
||||||
dist
|
|
||||||
|
|
||||||
# Gatsby files
|
# Nuxt generate
|
||||||
.cache/
|
dist
|
||||||
# Comment in the public line in if your project uses Gatsby and not Next.js
|
|
||||||
# https://nextjs.org/blog/next-9-1#public-directory-support
|
|
||||||
# public
|
|
||||||
|
|
||||||
# vuepress build output
|
# vuepress build output
|
||||||
.vuepress/dist
|
.vuepress/dist
|
||||||
|
|
||||||
# vuepress v2.x temp and cache directory
|
|
||||||
.temp
|
|
||||||
|
|
||||||
# Docusaurus cache and generated files
|
|
||||||
.docusaurus
|
|
||||||
|
|
||||||
# Serverless directories
|
# Serverless directories
|
||||||
.serverless/
|
.serverless
|
||||||
|
|
||||||
# FuseBox cache
|
|
||||||
.fusebox/
|
|
||||||
|
|
||||||
# DynamoDB Local files
|
|
||||||
.dynamodb/
|
|
||||||
|
|
||||||
# TernJS port file
|
|
||||||
.tern-port
|
|
||||||
|
|
||||||
# Stores VSCode versions used for testing VSCode extensions
|
|
||||||
.vscode-test
|
|
||||||
|
|
||||||
# yarn v2
|
|
||||||
.yarn/cache
|
|
||||||
.yarn/unplugged
|
|
||||||
.yarn/build-state.yml
|
|
||||||
.yarn/install-state.gz
|
|
||||||
.pnp.*
|
|
||||||
|
|
||||||
### Node Patch ###
|
|
||||||
# Serverless Webpack directories
|
|
||||||
.webpack/
|
|
||||||
|
|
||||||
# SvelteKit build / generate output
|
|
||||||
.svelte-kit
|
|
||||||
|
|
||||||
# IDE / Editor
|
# IDE / Editor
|
||||||
.idea
|
.idea
|
||||||
@@ -169,8 +108,5 @@ tests/*/videos
|
|||||||
# Local Netlify folder
|
# Local Netlify folder
|
||||||
.netlify
|
.netlify
|
||||||
|
|
||||||
# PNPM
|
# Andrew's crazy Volar shim generator
|
||||||
.pnpm-store
|
shims-volar.d.ts
|
||||||
|
|
||||||
# GQL SDL generated for the frontends
|
|
||||||
gql-gen/
|
|
||||||
@@ -1,8 +1,3 @@
|
|||||||
module.exports = {
|
module.exports = {
|
||||||
semi: false,
|
semi: false
|
||||||
trailingComma: "es5",
|
|
||||||
singleQuote: false,
|
|
||||||
printWidth: 80,
|
|
||||||
useTabs: false,
|
|
||||||
tabWidth: 2
|
|
||||||
}
|
}
|
||||||
|
|||||||
14
.vscode/extensions.json
vendored
@@ -1,14 +0,0 @@
|
|||||||
{
|
|
||||||
"recommendations": [
|
|
||||||
"antfu.iconify",
|
|
||||||
"vue.volar",
|
|
||||||
"esbenp.prettier-vscode",
|
|
||||||
"dbaeumer.vscode-eslint",
|
|
||||||
"editorconfig.editorconfig",
|
|
||||||
"csstools.postcss",
|
|
||||||
"folke.vscode-monorepo-workspace"
|
|
||||||
],
|
|
||||||
"unwantedRecommendations": [
|
|
||||||
"octref.vetur"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
30
CODEOWNERS
@@ -1,30 +0,0 @@
|
|||||||
# CODEOWNERS is prioritized from bottom to top
|
|
||||||
|
|
||||||
# If none of the below matched
|
|
||||||
* @AndrewBastin @liyasthomas
|
|
||||||
|
|
||||||
# Packages
|
|
||||||
/packages/codemirror-lang-graphql/ @AndrewBastin
|
|
||||||
/packages/hoppscotch-cli/ @AndrewBastin
|
|
||||||
/packages/hoppscotch-common/ @amk-dev @AndrewBastin
|
|
||||||
/packages/hoppscotch-data/ @AndrewBastin
|
|
||||||
/packages/hoppscotch-js-sandbox/ @AndrewBastin
|
|
||||||
/packages/hoppscotch-ui/ @anwarulislam
|
|
||||||
/packages/hoppscotch-web/ @amk-dev
|
|
||||||
/packages/hoppscotch-selfhost-web/ @amk-dev
|
|
||||||
/packages/hoppscotch-sh-admin/ @JoelJacobStephen
|
|
||||||
/packages/hoppscotch-backend/ @ankitsridhar16 @balub
|
|
||||||
|
|
||||||
# Sections within Hoppscotch Common
|
|
||||||
/packages/hoppscotch-common/src/components @anwarulislam
|
|
||||||
/packages/hoppscotch-common/src/components/collections @nivedin @amk-dev
|
|
||||||
/packages/hoppscotch-common/src/components/environments @nivedin @amk-dev
|
|
||||||
/packages/hoppscotch-common/src/composables @amk-dev
|
|
||||||
/packages/hoppscotch-common/src/modules @AndrewBastin @amk-dev
|
|
||||||
/packages/hoppscotch-common/src/pages @AndrewBastin @amk-dev
|
|
||||||
/packages/hoppscotch-common/src/newstore @AndrewBastin @amk-dev
|
|
||||||
|
|
||||||
README.md @liyasthomas
|
|
||||||
|
|
||||||
# The lockfile has no owner
|
|
||||||
pnpm-lock.yaml
|
|
||||||
@@ -6,8 +6,8 @@ We as members, contributors, and leaders pledge to make participation in our
|
|||||||
community a harassment-free experience for everyone, regardless of age, body
|
community a harassment-free experience for everyone, regardless of age, body
|
||||||
size, visible or invisible disability, ethnicity, sex characteristics, gender
|
size, visible or invisible disability, ethnicity, sex characteristics, gender
|
||||||
identity and expression, level of experience, education, socio-economic status,
|
identity and expression, level of experience, education, socio-economic status,
|
||||||
nationality, personal appearance, race, caste, color, religion, or sexual
|
nationality, personal appearance, race, religion, or sexual identity
|
||||||
identity and orientation.
|
and orientation.
|
||||||
|
|
||||||
We pledge to act and interact in ways that contribute to an open, welcoming,
|
We pledge to act and interact in ways that contribute to an open, welcoming,
|
||||||
diverse, inclusive, and healthy community.
|
diverse, inclusive, and healthy community.
|
||||||
@@ -22,17 +22,17 @@ community include:
|
|||||||
* Giving and gracefully accepting constructive feedback
|
* Giving and gracefully accepting constructive feedback
|
||||||
* Accepting responsibility and apologizing to those affected by our mistakes,
|
* Accepting responsibility and apologizing to those affected by our mistakes,
|
||||||
and learning from the experience
|
and learning from the experience
|
||||||
* Focusing on what is best not just for us as individuals, but for the overall
|
* Focusing on what is best not just for us as individuals, but for the
|
||||||
community
|
overall community
|
||||||
|
|
||||||
Examples of unacceptable behavior include:
|
Examples of unacceptable behavior include:
|
||||||
|
|
||||||
* The use of sexualized language or imagery, and sexual attention or advances of
|
* The use of sexualized language or imagery, and sexual attention or
|
||||||
any kind
|
advances of any kind
|
||||||
* Trolling, insulting or derogatory comments, and personal or political attacks
|
* Trolling, insulting or derogatory comments, and personal or political attacks
|
||||||
* Public or private harassment
|
* Public or private harassment
|
||||||
* Publishing others' private information, such as a physical or email address,
|
* Publishing others' private information, such as a physical or email
|
||||||
without their explicit permission
|
address, without their explicit permission
|
||||||
* Other conduct which could reasonably be considered inappropriate in a
|
* Other conduct which could reasonably be considered inappropriate in a
|
||||||
professional setting
|
professional setting
|
||||||
|
|
||||||
@@ -82,15 +82,15 @@ behavior was inappropriate. A public apology may be requested.
|
|||||||
|
|
||||||
### 2. Warning
|
### 2. Warning
|
||||||
|
|
||||||
**Community Impact**: A violation through a single incident or series of
|
**Community Impact**: A violation through a single incident or series
|
||||||
actions.
|
of actions.
|
||||||
|
|
||||||
**Consequence**: A warning with consequences for continued behavior. No
|
**Consequence**: A warning with consequences for continued behavior. No
|
||||||
interaction with the people involved, including unsolicited interaction with
|
interaction with the people involved, including unsolicited interaction with
|
||||||
those enforcing the Code of Conduct, for a specified period of time. This
|
those enforcing the Code of Conduct, for a specified period of time. This
|
||||||
includes avoiding interactions in community spaces as well as external channels
|
includes avoiding interactions in community spaces as well as external channels
|
||||||
like social media. Violating these terms may lead to a temporary or permanent
|
like social media. Violating these terms may lead to a temporary or
|
||||||
ban.
|
permanent ban.
|
||||||
|
|
||||||
### 3. Temporary Ban
|
### 3. Temporary Ban
|
||||||
|
|
||||||
@@ -106,27 +106,23 @@ Violating these terms may lead to a permanent ban.
|
|||||||
### 4. Permanent Ban
|
### 4. Permanent Ban
|
||||||
|
|
||||||
**Community Impact**: Demonstrating a pattern of violation of community
|
**Community Impact**: Demonstrating a pattern of violation of community
|
||||||
standards, including sustained inappropriate behavior, harassment of an
|
standards, including sustained inappropriate behavior, harassment of an
|
||||||
individual, or aggression toward or disparagement of classes of individuals.
|
individual, or aggression toward or disparagement of classes of individuals.
|
||||||
|
|
||||||
**Consequence**: A permanent ban from any sort of public interaction within the
|
**Consequence**: A permanent ban from any sort of public interaction within
|
||||||
community.
|
the community.
|
||||||
|
|
||||||
## Attribution
|
## Attribution
|
||||||
|
|
||||||
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
|
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
|
||||||
version 2.1, available at
|
version 2.0, available at
|
||||||
[https://www.contributor-covenant.org/version/2/1/code_of_conduct.html][v2.1].
|
https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.
|
||||||
|
|
||||||
Community Impact Guidelines were inspired by
|
Community Impact Guidelines were inspired by [Mozilla's code of conduct
|
||||||
[Mozilla's code of conduct enforcement ladder][Mozilla CoC].
|
enforcement ladder](https://github.com/mozilla/diversity).
|
||||||
|
|
||||||
For answers to common questions about this code of conduct, see the FAQ at
|
|
||||||
[https://www.contributor-covenant.org/faq][FAQ]. Translations are available at
|
|
||||||
[https://www.contributor-covenant.org/translations][translations].
|
|
||||||
|
|
||||||
[homepage]: https://www.contributor-covenant.org
|
[homepage]: https://www.contributor-covenant.org
|
||||||
[v2.1]: https://www.contributor-covenant.org/version/2/1/code_of_conduct.html
|
|
||||||
[Mozilla CoC]: https://github.com/mozilla/diversity
|
For answers to common questions about this code of conduct, see the FAQ at
|
||||||
[FAQ]: https://www.contributor-covenant.org/faq
|
https://www.contributor-covenant.org/faq. Translations are available at
|
||||||
[translations]: https://www.contributor-covenant.org/translations
|
https://www.contributor-covenant.org/translations.
|
||||||
|
|||||||
29
Dockerfile
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
FROM node:lts-alpine
|
||||||
|
|
||||||
|
LABEL maintainer="Hoppscotch (support@hoppscotch.io)"
|
||||||
|
|
||||||
|
# Add git as the prebuild target requires it to parse version information
|
||||||
|
RUN apk add --no-cache --virtual .gyp \
|
||||||
|
python3 \
|
||||||
|
make \
|
||||||
|
g++
|
||||||
|
|
||||||
|
# Create app directory
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
ADD . /app/
|
||||||
|
|
||||||
|
COPY . .
|
||||||
|
|
||||||
|
RUN npm install -g pnpm
|
||||||
|
|
||||||
|
RUN pnpm i --unsafe-perm=true
|
||||||
|
|
||||||
|
ENV HOST 0.0.0.0
|
||||||
|
EXPOSE 3000
|
||||||
|
|
||||||
|
RUN mv packages/hoppscotch-app/.env.example packages/hoppscotch-app/.env
|
||||||
|
|
||||||
|
RUN pnpm run generate
|
||||||
|
|
||||||
|
CMD ["pnpm", "run", "start"]
|
||||||
228
README.md
@@ -2,18 +2,23 @@
|
|||||||
<a href="https://hoppscotch.io">
|
<a href="https://hoppscotch.io">
|
||||||
<img
|
<img
|
||||||
src="https://avatars.githubusercontent.com/u/56705483"
|
src="https://avatars.githubusercontent.com/u/56705483"
|
||||||
alt="Hoppscotch"
|
alt="Hoppscotch Logo"
|
||||||
height="64"
|
height="64"
|
||||||
/>
|
/>
|
||||||
</a>
|
</a>
|
||||||
<h3>
|
<br />
|
||||||
|
<p>
|
||||||
|
<h3>
|
||||||
|
<b>
|
||||||
|
Hoppscotch
|
||||||
|
</b>
|
||||||
|
</h3>
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
<b>
|
<b>
|
||||||
Hoppscotch
|
Open source API development ecosystem
|
||||||
</b>
|
</b>
|
||||||
</h3>
|
</p>
|
||||||
<b>
|
|
||||||
Open Source API Development Ecosystem
|
|
||||||
</b>
|
|
||||||
<p>
|
<p>
|
||||||
|
|
||||||
[](CODE_OF_CONDUCT.md) [](https://hoppscotch.io) [](https://github.com/hoppscotch/hoppscotch/actions) [](https://twitter.com/share?text=%F0%9F%91%BD%20Hoppscotch%20%E2%80%A2%20Open%20source%20API%20development%20ecosystem%20-%20Helps%20you%20create%20requests%20faster,%20saving%20precious%20time%20on%20development.&url=https://hoppscotch.io&hashtags=hoppscotch&via=hoppscotch_io)
|
[](CODE_OF_CONDUCT.md) [](https://hoppscotch.io) [](https://github.com/hoppscotch/hoppscotch/actions) [](https://twitter.com/share?text=%F0%9F%91%BD%20Hoppscotch%20%E2%80%A2%20Open%20source%20API%20development%20ecosystem%20-%20Helps%20you%20create%20requests%20faster,%20saving%20precious%20time%20on%20development.&url=https://hoppscotch.io&hashtags=hoppscotch&via=hoppscotch_io)
|
||||||
@@ -29,18 +34,23 @@
|
|||||||
</p>
|
</p>
|
||||||
<br />
|
<br />
|
||||||
<p>
|
<p>
|
||||||
<a href="https://hoppscotch.io">
|
<a href="https://hoppscotch.io/#gh-light-mode-only" target="_blank">
|
||||||
<picture>
|
<img
|
||||||
<source media="(prefers-color-scheme: dark)" srcset="./packages/hoppscotch-common/public/images/banner-dark.png">
|
src="./packages/hoppscotch-app/static/images/banner-light.png"
|
||||||
<source media="(prefers-color-scheme: light)" srcset="./packages/hoppscotch-common/public/images/banner-light.png">
|
alt="Hoppscotch"
|
||||||
<img alt="Hoppscotch" src="./packages/hoppscotch-common/public/images/banner-dark.png">
|
width="100%"
|
||||||
</picture>
|
/>
|
||||||
|
</a>
|
||||||
|
<a href="https://hoppscotch.io/#gh-dark-mode-only" target="_blank">
|
||||||
|
<img
|
||||||
|
src="./packages/hoppscotch-app/static/images/banner-dark.png"
|
||||||
|
alt="Hoppscotch"
|
||||||
|
width="100%"
|
||||||
|
/>
|
||||||
</a>
|
</a>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
_We highly recommend you take a look at the [**Hoppscotch Documentation**](https://docs.hoppscotch.io) to learn more about the app._
|
|
||||||
|
|
||||||
#### **Support**
|
#### **Support**
|
||||||
|
|
||||||
[](https://hoppscotch.io/discord) [](https://hoppscotch.io/telegram) [](https://github.com/hoppscotch/hoppscotch/discussions)
|
[](https://hoppscotch.io/discord) [](https://hoppscotch.io/telegram) [](https://github.com/hoppscotch/hoppscotch/discussions)
|
||||||
@@ -49,9 +59,9 @@ _We highly recommend you take a look at the [**Hoppscotch Documentation**](https
|
|||||||
|
|
||||||
❤️ **Lightweight:** Crafted with minimalistic UI design.
|
❤️ **Lightweight:** Crafted with minimalistic UI design.
|
||||||
|
|
||||||
⚡️ **Fast:** Send requests and get responses in real time.
|
⚡️ **Fast:** Send requests and get/copy responses in real-time.
|
||||||
|
|
||||||
🗄️ **HTTP Methods:** Request methods define the type of action you are requesting to be performed.
|
**HTTP Methods**
|
||||||
|
|
||||||
- `GET` - Requests retrieve resource information
|
- `GET` - Requests retrieve resource information
|
||||||
- `POST` - The server creates a new entry in a database
|
- `POST` - The server creates a new entry in a database
|
||||||
@@ -64,15 +74,17 @@ _We highly recommend you take a look at the [**Hoppscotch Documentation**](https
|
|||||||
- `TRACE` - Performs a message loop-back test along the path to the target resource
|
- `TRACE` - Performs a message loop-back test along the path to the target resource
|
||||||
- `<custom>` - Some APIs use custom request methods such as `LIST`. Type in your custom methods.
|
- `<custom>` - Some APIs use custom request methods such as `LIST`. Type in your custom methods.
|
||||||
|
|
||||||
🌈 **Theming:** Customizable combinations for background, foreground, and accent colors — [customize now](https://hoppscotch.io/settings).
|
🌈 **Make it yours:** Customizable combinations for background, foreground, and accent colors — [customize now](https://hoppscotch.io/settings).
|
||||||
|
|
||||||
- Choose a theme: System preference, Light, Dark, and Black
|
**Theming**
|
||||||
- Choose accent colors: Green, Teal, Blue, Indigo, Purple, Yellow, Orange, Red, and Pink
|
|
||||||
|
- Choose a theme: System (default), Light, Dark, and Black
|
||||||
|
- Choose accent color: Green (default), Teal, Blue, Indigo, Purple, Yellow, Orange, Red, and Pink
|
||||||
- Distraction-free Zen mode
|
- Distraction-free Zen mode
|
||||||
|
|
||||||
_Customized themes are synced with your cloud/local session._
|
_Customized themes are synced with cloud / local session_
|
||||||
|
|
||||||
🔥 **PWA:** Install as a [Progressive Web App](https://web.dev/progressive-web-apps) on your device.
|
🔥 **PWA:** Install as a [PWA](https://web.dev/what-are-pwas/) on your device.
|
||||||
|
|
||||||
- Instant loading with Service Workers
|
- Instant loading with Service Workers
|
||||||
- Offline support
|
- Offline support
|
||||||
@@ -95,7 +107,7 @@ _Customized themes are synced with your cloud/local session._
|
|||||||
|
|
||||||
📡 **Server-Sent Events:** Receive a stream of updates from a server over an HTTP connection without resorting to polling.
|
📡 **Server-Sent Events:** Receive a stream of updates from a server over an HTTP connection without resorting to polling.
|
||||||
|
|
||||||
🌩 **Socket.IO:** Send and Receive data with the SocketIO server.
|
🌩 **Socket.IO:** Send and Receive data with SocketIO server.
|
||||||
|
|
||||||
🦟 **MQTT:** Subscribe and Publish to topics of an MQTT Broker.
|
🦟 **MQTT:** Subscribe and Publish to topics of an MQTT Broker.
|
||||||
|
|
||||||
@@ -115,7 +127,7 @@ _Customized themes are synced with your cloud/local session._
|
|||||||
- OAuth 2.0
|
- OAuth 2.0
|
||||||
- OIDC Access Token/PKCE
|
- OIDC Access Token/PKCE
|
||||||
|
|
||||||
📢 **Headers:** Describes the format the body of your request is being sent in.
|
📢 **Headers:** Describes the format the body of your request is being sent as.
|
||||||
|
|
||||||
📫 **Parameters:** Use request parameters to set varying parts in simulated requests.
|
📫 **Parameters:** Use request parameters to set varying parts in simulated requests.
|
||||||
|
|
||||||
@@ -125,14 +137,14 @@ _Customized themes are synced with your cloud/local session._
|
|||||||
- FormData, JSON, and many more
|
- FormData, JSON, and many more
|
||||||
- Toggle between key-value and RAW input parameter list
|
- Toggle between key-value and RAW input parameter list
|
||||||
|
|
||||||
📮 **Response:** Contains the status line, headers, and the message/response body.
|
👋 **Response:** Contains the status line, headers, and the message/response body.
|
||||||
|
|
||||||
- Copy the response to the clipboard
|
- Copy response to clipboard
|
||||||
- Download the response as a file
|
- Download response as a file
|
||||||
- View response headers
|
- View response headers
|
||||||
- View raw and preview HTML, image, JSON, and XML responses
|
- View raw and preview of HTML, image, JSON, XML responses
|
||||||
|
|
||||||
⏰ **History:** Request entries are synced with your cloud/local session storage.
|
⏰ **History:** Request entries are synced with cloud / local session storage to restore with a single click.
|
||||||
|
|
||||||
📁 **Collections:** Keep your API requests organized with collections and folders. Reuse them with a single click.
|
📁 **Collections:** Keep your API requests organized with collections and folders. Reuse them with a single click.
|
||||||
|
|
||||||
@@ -140,32 +152,7 @@ _Customized themes are synced with your cloud/local session._
|
|||||||
- Nested folders
|
- Nested folders
|
||||||
- Export and import as a file or GitHub gist
|
- Export and import as a file or GitHub gist
|
||||||
|
|
||||||
_Collections are synced with your cloud/local session storage._
|
_Collections are synced with cloud / local session storage_
|
||||||
|
|
||||||
📜 **Pre-Request Scripts:** Snippets of code associated with a request that is executed before the request is sent.
|
|
||||||
|
|
||||||
- Set environment variables
|
|
||||||
- Include timestamp in the request headers
|
|
||||||
- Send a random alphanumeric string in the URL parameters
|
|
||||||
- Any JavaScript functions
|
|
||||||
|
|
||||||
👨👩👧👦 **Teams:** Helps you collaborate across your teams to design, develop, and test APIs faster.
|
|
||||||
|
|
||||||
- Create unlimited teams
|
|
||||||
- Create unlimited shared collections
|
|
||||||
- Create unlimited team members
|
|
||||||
- Role-based access control
|
|
||||||
- Cloud sync
|
|
||||||
- Multiple devices
|
|
||||||
|
|
||||||
👥 **Workspaces:** Organize your personal and team collections environments into workspaces. Easily switch between workspaces to manage multiple projects.
|
|
||||||
|
|
||||||
- Create unlimited workspaces
|
|
||||||
- Switch between personal and team workspaces
|
|
||||||
|
|
||||||
⌨️ **Keyboard Shortcuts:** Optimized for efficiency.
|
|
||||||
|
|
||||||
> **[Read our documentation on Keyboard Shortcuts](https://docs.hoppscotch.io/documentation/features/shortcuts)**
|
|
||||||
|
|
||||||
🌐 **Proxy:** Enable Proxy Mode from Settings to access blocked APIs.
|
🌐 **Proxy:** Enable Proxy Mode from Settings to access blocked APIs.
|
||||||
|
|
||||||
@@ -174,31 +161,60 @@ _Collections are synced with your cloud/local session storage._
|
|||||||
- Access APIs served in non-HTTPS (`http://`) endpoints
|
- Access APIs served in non-HTTPS (`http://`) endpoints
|
||||||
- Use your Proxy URL
|
- Use your Proxy URL
|
||||||
|
|
||||||
_Official proxy server is hosted by Hoppscotch - **[GitHub](https://github.com/hoppscotch/proxyscotch)** - **[Privacy Policy](https://docs.hoppscotch.io/support/privacy)**._
|
_Official proxy server is hosted by Hoppscotch - **[GitHub](https://github.com/hoppscotch/proxyscotch)** - **[Privacy Policy](https://docs.hoppscotch.io/privacy)**_
|
||||||
|
|
||||||
|
📜 **Pre-Request Scripts β:** Snippets of code associated with a request that is executed before the request is sent.
|
||||||
|
|
||||||
|
- Set environment variables
|
||||||
|
- Include timestamp in the request headers
|
||||||
|
- Send a random alphanumeric string in the URL parameters
|
||||||
|
- Any JavaScript functions
|
||||||
|
|
||||||
|
📄 **API Documentation:** Create and share dynamic API documentation easily, quickly.
|
||||||
|
|
||||||
|
1. Add your requests to Collections and Folders
|
||||||
|
2. Export Collections and easily share your APIs with the rest of your team
|
||||||
|
3. Import Collections and Generate Documentation on-the-go
|
||||||
|
|
||||||
|
⌨️ **Keyboard Shortcuts:** Optimized for efficiency.
|
||||||
|
|
||||||
|
> **[Read our documentation on Keyboard Shortcuts](https://docs.hoppscotch.io/features/shortcuts)**
|
||||||
|
|
||||||
🌎 **i18n:** Experience the app in your language.
|
🌎 **i18n:** Experience the app in your language.
|
||||||
|
|
||||||
Help us to translate Hoppscotch. Please read [`TRANSLATIONS`](TRANSLATIONS.md) for details on our [`CODE OF CONDUCT`](CODE_OF_CONDUCT.md) and the process for submitting pull requests to us.
|
Help us to translate Hoppscotch. Please read [`TRANSLATIONS`](TRANSLATIONS.md) for details on our [`CODE OF CONDUCT`](CODE_OF_CONDUCT.md), and the process for submitting pull requests to us.
|
||||||
|
|
||||||
☁️ **Auth + Sync:** Sign in and sync your data in real-time across all your devices.
|
📦 **Add-ons:** Official add-ons for hoppscotch.
|
||||||
|
|
||||||
**Sign in with:**
|
- **[Proxy](https://github.com/hoppscotch/proxyscotch)** - A simple proxy server created for Hoppscotch
|
||||||
|
- **[CLI β](https://github.com/hoppscotch/hopp-cli)** - A CLI solution for Hoppscotch
|
||||||
|
- **[Browser Extensions](https://github.com/hoppscotch/hoppscotch-extension)** - Browser extensions that simplifies access to Hoppscotch
|
||||||
|
|
||||||
|
[ **Firefox**](https://addons.mozilla.org/en-US/firefox/addon/hoppscotch) | [ **Chrome**](https://chrome.google.com/webstore/detail/hoppscotch-extension-for-c/amknoiejhlmhancpahfcfcfhllgkpbld)
|
||||||
|
|
||||||
|
> **Extensions fixes `CORS` issues.**
|
||||||
|
|
||||||
|
- **[Hopp-Doc-Gen](https://github.com/hoppscotch/hopp-doc-gen)** - An API doc generator CLI for Hoppscotch
|
||||||
|
|
||||||
|
_Add-ons are developed and maintained under **[Hoppscotch Organization](https://github.com/hoppscotch)**._
|
||||||
|
|
||||||
|
☁️ **Auth + Sync:** Sign in and sync your data in real-time.
|
||||||
|
|
||||||
|
**Sign in with**
|
||||||
|
|
||||||
- GitHub
|
- GitHub
|
||||||
- Google
|
- Google
|
||||||
- Microsoft
|
- Microsoft
|
||||||
- Email
|
- Email
|
||||||
- SSO (Single Sign-On)[^EE]
|
|
||||||
|
|
||||||
**🔄 Synchronize your data:** Handoff to continue tasks on your other devices.
|
**Synchronize your data**
|
||||||
|
|
||||||
- Workspaces
|
|
||||||
- History
|
- History
|
||||||
- Collections
|
- Collections
|
||||||
- Environments
|
- Environments
|
||||||
- Settings
|
- Settings
|
||||||
|
|
||||||
✅ **Post-Request Tests:** Write tests associated with a request that is executed after the request's response.
|
✅ **Post-Request Tests β:** Write tests associated with a request that is executed after the request's response.
|
||||||
|
|
||||||
- Check the status code as an integer
|
- Check the status code as an integer
|
||||||
- Filter response headers
|
- Filter response headers
|
||||||
@@ -206,7 +222,7 @@ Help us to translate Hoppscotch. Please read [`TRANSLATIONS`](TRANSLATIONS.md) f
|
|||||||
- Set environment variables
|
- Set environment variables
|
||||||
- Write JavaScript code
|
- Write JavaScript code
|
||||||
|
|
||||||
🌱 **Environments:** Environment variables allow you to store and reuse values in your requests and scripts.
|
🌱 **Environments** : Environment variables allow you to store and reuse values in your requests and scripts.
|
||||||
|
|
||||||
- Unlimited environments and variables
|
- Unlimited environments and variables
|
||||||
- Initialize through the pre-request script
|
- Initialize through the pre-request script
|
||||||
@@ -225,31 +241,22 @@ Help us to translate Hoppscotch. Please read [`TRANSLATIONS`](TRANSLATIONS.md) f
|
|||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
|
👨👩👧👦 **Teams β:** Helps you collaborate across your team to design, develop, and test APIs faster.
|
||||||
|
|
||||||
|
- Unlimited teams
|
||||||
|
- Unlimited shared collections
|
||||||
|
- Unlimited team members
|
||||||
|
- Role-based access control
|
||||||
|
- Cloud sync
|
||||||
|
- Multiple devices
|
||||||
|
|
||||||
🚚 **Bulk Edit:** Edit key-value pairs in bulk.
|
🚚 **Bulk Edit:** Edit key-value pairs in bulk.
|
||||||
|
|
||||||
- Entries are separated by newline
|
- Entries are separated by newline
|
||||||
- Keys and values are separated by `:`
|
- Keys and values are separated by `:`
|
||||||
- Prepend `#` to any row you want to add but keep disabled
|
- Prepend `#` to any row you want to add but keep disabled
|
||||||
|
|
||||||
🎛️ **Admin dashboard:** Manage your team and invite members.
|
**For more features, please read our [documentation](https://docs.hoppscotch.io).**
|
||||||
|
|
||||||
- Insights
|
|
||||||
- Manage users
|
|
||||||
- Manage teams
|
|
||||||
|
|
||||||
📦 **Add-ons:** Official add-ons for hoppscotch.
|
|
||||||
|
|
||||||
- **[Hoppscotch CLI](https://github.com/hoppscotch/hopp-cli)** - Command-line interface for Hoppscotch.
|
|
||||||
- **[Proxy](https://github.com/hoppscotch/proxyscotch)** - A simple proxy server created for Hoppscotch.
|
|
||||||
- **[Browser Extensions](https://github.com/hoppscotch/hoppscotch-extension)** - Browser extensions that enhance your Hoppscotch experience.
|
|
||||||
|
|
||||||
[ **Firefox**](https://addons.mozilla.org/en-US/firefox/addon/hoppscotch) | [ **Chrome**](https://chrome.google.com/webstore/detail/hoppscotch-extension-for-c/amknoiejhlmhancpahfcfcfhllgkpbld)
|
|
||||||
|
|
||||||
> **Extensions fix `CORS` issues.**
|
|
||||||
|
|
||||||
_Add-ons are developed and maintained under **[Hoppscotch Organization](https://github.com/hoppscotch)**._
|
|
||||||
|
|
||||||
**For a complete list of features, please read our [documentation](https://docs.hoppscotch.io).**
|
|
||||||
|
|
||||||
## **Demo**
|
## **Demo**
|
||||||
|
|
||||||
@@ -261,9 +268,56 @@ _Add-ons are developed and maintained under **[Hoppscotch Organization](https://
|
|||||||
2. Click "Send" to simulate the request
|
2. Click "Send" to simulate the request
|
||||||
3. View the response
|
3. View the response
|
||||||
|
|
||||||
|
## **Built with**
|
||||||
|
|
||||||
|
- [HTML](https://developer.mozilla.org/en-US/docs/Web/HTML)
|
||||||
|
- [CSS](https://developer.mozilla.org/en-US/docs/Web/CSS), [SCSS](https://sass-lang.com), [Windi CSS](https://windicss.org)
|
||||||
|
- [JavaScript](https://developer.mozilla.org/en-US/docs/Web/JavaScript)
|
||||||
|
- [TypeScript](https://www.typescriptlang.org)
|
||||||
|
- [Vue](https://vuejs.org)
|
||||||
|
- [Nuxt](https://nuxtjs.org)
|
||||||
|
|
||||||
## **Developing**
|
## **Developing**
|
||||||
|
|
||||||
Follow our [self-hosting documentation](https://docs.hoppscotch.io/documentation/self-host/getting-started) to get started with the development environment.
|
0. Update [`.env.example`](https://github.com/hoppscotch/hoppscotch/blob/main/packages/hoppscotch-app/.env.example) file found in `packages/hoppscotch-app` with your own keys and rename it to `.env`.
|
||||||
|
|
||||||
|
_Sample keys only work with the [production build](https://hoppscotch.io)._
|
||||||
|
|
||||||
|
### Browser-based development environment
|
||||||
|
|
||||||
|
- [GitHub codespace](https://docs.github.com/en/codespaces/developing-in-codespaces/creating-a-codespace)
|
||||||
|
- [Gitpod](https://gitpod.io/#https://github.com/hoppscotch/hoppscotch)
|
||||||
|
|
||||||
|
### Local development environment
|
||||||
|
|
||||||
|
1. [Clone this repo](https://help.github.com/en/articles/cloning-a-repository) with git.
|
||||||
|
2. Install pnpm using npm by running `npm install -g pnpm`.
|
||||||
|
3. Install dependencies by running `pnpm install` within the directory that you cloned (probably `hoppscotch`).
|
||||||
|
4. Start the development server with `pnpm run dev`.
|
||||||
|
5. Open the development site by going to [`http://localhost:3000`](http://localhost:3000) in your browser.
|
||||||
|
|
||||||
|
### Docker compose
|
||||||
|
|
||||||
|
1. [Clone this repo](https://help.github.com/en/articles/cloning-a-repository) with git.
|
||||||
|
2. Run `docker-compose up` within the directory that you cloned (probably `hoppscotch`).
|
||||||
|
3. Open the development site by going to [`http://localhost:3000`](http://localhost:3000) in your browser.
|
||||||
|
|
||||||
|
## **Docker**
|
||||||
|
|
||||||
|
**Official container** [](https://hub.docker.com/r/hoppscotch/hoppscotch)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker run --rm --name hoppscotch -p 3000:3000 hoppscotch/hoppscotch:latest
|
||||||
|
```
|
||||||
|
|
||||||
|
## **Releasing**
|
||||||
|
|
||||||
|
1. [Clone this repo](https://help.github.com/en/articles/cloning-a-repository) with git.
|
||||||
|
2. Install pnpm using npm by running `npm install -g pnpm`.
|
||||||
|
3. Install dependencies by running `pnpm install` within the directory that you cloned (probably `hoppscotch`).
|
||||||
|
4. Update [`.env.example`](https://github.com/hoppscotch/hoppscotch/blob/main/packages/hoppscotch-app/.env.example) file found in `packages/hoppscotch-app` with your own keys and rename it to `.env`.
|
||||||
|
5. Build the release files with `pnpm run generate`.
|
||||||
|
6. Find the built project in `packages/hoppscotch-app/dist`. Host these files on any [static hosting servers](https://www.pluralsight.com/blog/software-development/where-to-host-your-jamstack-site).
|
||||||
|
|
||||||
## **Contributing**
|
## **Contributing**
|
||||||
|
|
||||||
@@ -281,7 +335,7 @@ See the [`CHANGELOG`](CHANGELOG.md) file for details.
|
|||||||
|
|
||||||
## **Authors**
|
## **Authors**
|
||||||
|
|
||||||
This project owes its existence to the collective efforts of all those who contribute — [contribute now](CONTRIBUTING.md).
|
This project exists thanks to all the people who contribute — [contribute](CONTRIBUTING.md).
|
||||||
|
|
||||||
<div align="center">
|
<div align="center">
|
||||||
<a href="https://github.com/hoppscotch/hoppscotch/graphs/contributors">
|
<a href="https://github.com/hoppscotch/hoppscotch/graphs/contributors">
|
||||||
@@ -293,6 +347,4 @@ This project owes its existence to the collective efforts of all those who contr
|
|||||||
|
|
||||||
## **License**
|
## **License**
|
||||||
|
|
||||||
This project is licensed under the [MIT License](https://opensource.org/licenses/MIT) — see the [`LICENSE`](LICENSE) file for details.
|
This project is licensed under the [MIT License](https://opensource.org/licenses/MIT) - see the [`LICENSE`](LICENSE) file for details.
|
||||||
|
|
||||||
[^EE]: Enterprise edition feature. [Learn more](https://docs.hoppscotch.io/documentation/self-host/getting-started).
|
|
||||||
|
|||||||
@@ -2,9 +2,8 @@
|
|||||||
|
|
||||||
This document outlines security procedures and general policies for the Hoppscotch project.
|
This document outlines security procedures and general policies for the Hoppscotch project.
|
||||||
|
|
||||||
- [Security Policy](#security-policy)
|
1. [Reporting a security vulnerability](#reporting-a-security-vulnerability)
|
||||||
- [Reporting a security vulnerability](#reporting-a-security-vulnerability)
|
3. [Incident response process](#incident-response-process)
|
||||||
- [Incident response process](#incident-response-process)
|
|
||||||
|
|
||||||
## Reporting a security vulnerability
|
## Reporting a security vulnerability
|
||||||
|
|
||||||
|
|||||||
@@ -9,24 +9,26 @@ Before you start working on a new language, please look through the [open pull r
|
|||||||
if there is no existing translation, you can create a new one by following these steps:
|
if there is no existing translation, you can create a new one by following these steps:
|
||||||
|
|
||||||
1. **[Fork the repository](https://github.com/hoppscotch/hoppscotch/fork).**
|
1. **[Fork the repository](https://github.com/hoppscotch/hoppscotch/fork).**
|
||||||
2. **Checkout the `main` branch for latest translations.**
|
2. **Checkout the `i18n` branch for latest translations.**
|
||||||
3. **Create a new branch for your translation with base branch `main`.**
|
3. **Create a new branch for your translation with base branch `i18n`.**
|
||||||
4. **Create target language file in the [`/packages/hoppscotch-common/locales`](https://github.com/hoppscotch/hoppscotch/tree/main/packages/hoppscotch-common/locales) directory.**
|
4. **Create target language file in the [`locales`](https://github.com/hoppscotch/hoppscotch/tree/main/packages/hoppscotch-app/locales) directory.**
|
||||||
5. **Copy the contents of the source file [`/packages/hoppscotch-common/locales/en.json`](https://github.com/hoppscotch/hoppscotch/blob/main/packages/hoppscotch-common/locales/en.json) to the target language file.**
|
5. **Copy the contents of the source file [`locales/en.json`](https://github.com/hoppscotch/hoppscotch/blob/main/packages/hoppscotch-app/locales/en.json) to the target language file.**
|
||||||
6. **Translate the strings in the target language file.**
|
6. **Translate the strings in the target language file.**
|
||||||
7. **Add your language entry to [`/packages/hoppscotch-common/languages.json`](https://github.com/hoppscotch/hoppscotch/blob/main/packages/hoppscotch-common/languages.json).**
|
7. **Add your language entry to [`languages.json`](https://github.com/hoppscotch/hoppscotch/blob/main/packages/hoppscotch-app/languages.json).**
|
||||||
8. **Save and commit changes.**
|
8. **Save & commit changes.**
|
||||||
9. **Send a pull request.**
|
9. **Send a pull request.**
|
||||||
|
|
||||||
_You may send a pull request before all steps above are complete: e.g., you may want to ask for help with translations, or getting tests to pass. However, your pull request will not be merged until all steps above are complete._
|
_You may send a pull request before all steps above are complete: e.g., you may want to ask for help with translations, or getting tests to pass. However, your pull request will not be merged until all steps above are complete._
|
||||||
|
|
||||||
|
`i18n` branch will be merged into `main` branch once every week.
|
||||||
|
|
||||||
Completing an initial translation of the whole site is a fairly large task. One way to break that task up is to work with other translators through pull requests on your fork. You can also [add collaborators to your fork](https://help.github.com/en/github/setting-up-and-managing-your-github-user-account/inviting-collaborators-to-a-personal-repository) if you'd like to invite other translators to commit directly to your fork and share responsibility for merging pull requests.
|
Completing an initial translation of the whole site is a fairly large task. One way to break that task up is to work with other translators through pull requests on your fork. You can also [add collaborators to your fork](https://help.github.com/en/github/setting-up-and-managing-your-github-user-account/inviting-collaborators-to-a-personal-repository) if you'd like to invite other translators to commit directly to your fork and share responsibility for merging pull requests.
|
||||||
|
|
||||||
## Updating a translation
|
## Updating a translation
|
||||||
|
|
||||||
### Corrections
|
### Corrections
|
||||||
|
|
||||||
If you notice spelling or grammar errors, typos, or opportunities for better phrasing, open a pull request with your suggested fix. If you see a problem that you aren't sure of or don't have time to fix, [open an issue](https://github.com/hoppscotch/hoppscotch/issues/new/choose).
|
If you notice spelling or grammar errors, typos, or opportunities for better phrasing, open a pull request with your suggested fix. If you see a problem that you aren't sure of or don't have time to fix, open an issue.
|
||||||
|
|
||||||
### Broken links
|
### Broken links
|
||||||
|
|
||||||
|
|||||||
@@ -1,11 +0,0 @@
|
|||||||
:3000 {
|
|
||||||
try_files {path} /
|
|
||||||
root * /site/selfhost-web
|
|
||||||
file_server
|
|
||||||
}
|
|
||||||
|
|
||||||
:3100 {
|
|
||||||
try_files {path} /
|
|
||||||
root * /site/sh-admin
|
|
||||||
file_server
|
|
||||||
}
|
|
||||||
72
aio_run.mjs
@@ -1,72 +0,0 @@
|
|||||||
#!/usr/local/bin/node
|
|
||||||
// @ts-check
|
|
||||||
|
|
||||||
import { execSync, spawn } from "child_process"
|
|
||||||
import fs from "fs"
|
|
||||||
import process from "process"
|
|
||||||
|
|
||||||
function runChildProcessWithPrefix(command, args, prefix) {
|
|
||||||
const childProcess = spawn(command, args);
|
|
||||||
|
|
||||||
childProcess.stdout.on('data', (data) => {
|
|
||||||
const output = data.toString().trim().split('\n');
|
|
||||||
output.forEach((line) => {
|
|
||||||
console.log(`${prefix} | ${line}`);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
childProcess.stderr.on('data', (data) => {
|
|
||||||
const error = data.toString().trim().split('\n');
|
|
||||||
error.forEach((line) => {
|
|
||||||
console.error(`${prefix} | ${line}`);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
childProcess.on('close', (code) => {
|
|
||||||
console.log(`${prefix} Child process exited with code ${code}`);
|
|
||||||
});
|
|
||||||
|
|
||||||
childProcess.on('error', (stuff) => {
|
|
||||||
console.log("error")
|
|
||||||
console.log(stuff)
|
|
||||||
})
|
|
||||||
|
|
||||||
return childProcess
|
|
||||||
}
|
|
||||||
|
|
||||||
const envFileContent = Object.entries(process.env)
|
|
||||||
.filter(([env]) => env.startsWith("VITE_"))
|
|
||||||
.map(([env, val]) => `${env}=${
|
|
||||||
(val.startsWith("\"") && val.endsWith("\""))
|
|
||||||
? val
|
|
||||||
: `"${val}"`
|
|
||||||
}`)
|
|
||||||
.join("\n")
|
|
||||||
|
|
||||||
fs.writeFileSync("build.env", envFileContent)
|
|
||||||
|
|
||||||
execSync(`npx import-meta-env -x build.env -e build.env -p "/site/**/*"`)
|
|
||||||
|
|
||||||
fs.rmSync("build.env")
|
|
||||||
|
|
||||||
const caddyProcess = runChildProcessWithPrefix("caddy", ["run", "--config", "/etc/caddy/Caddyfile", "--adapter", "caddyfile"], "App/Admin Dashboard Caddy")
|
|
||||||
const backendProcess = runChildProcessWithPrefix("pnpm", ["run", "start:prod"], "Backend Server")
|
|
||||||
|
|
||||||
caddyProcess.on("exit", (code) => {
|
|
||||||
console.log(`Exiting process because Caddy Server exited with code ${code}`)
|
|
||||||
process.exit(code)
|
|
||||||
})
|
|
||||||
|
|
||||||
backendProcess.on("exit", (code) => {
|
|
||||||
console.log(`Exiting process because Backend Server exited with code ${code}`)
|
|
||||||
process.exit(code)
|
|
||||||
})
|
|
||||||
|
|
||||||
process.on('SIGINT', () => {
|
|
||||||
console.log("SIGINT received, exiting...")
|
|
||||||
|
|
||||||
caddyProcess.kill("SIGINT")
|
|
||||||
backendProcess.kill("SIGINT")
|
|
||||||
|
|
||||||
process.exit(0)
|
|
||||||
})
|
|
||||||
@@ -1,150 +1,23 @@
|
|||||||
# To make it easier to self-host, we have a preset docker compose config that also
|
|
||||||
# has a container with a Postgres instance running.
|
|
||||||
# You can tweak around this file to match your instances
|
|
||||||
version: "3.7"
|
version: "3.7"
|
||||||
|
|
||||||
services:
|
services:
|
||||||
# This service runs the backend app in the port 3170
|
web:
|
||||||
hoppscotch-backend:
|
|
||||||
container_name: hoppscotch-backend
|
|
||||||
build:
|
build:
|
||||||
dockerfile: prod.Dockerfile
|
|
||||||
context: .
|
context: .
|
||||||
target: backend
|
|
||||||
env_file:
|
|
||||||
- ./.env
|
|
||||||
restart: always
|
|
||||||
environment:
|
|
||||||
# Edit the below line to match your PostgresDB URL if you have an outside DB (make sure to update the .env file as well)
|
|
||||||
- DATABASE_URL=postgresql://postgres:testpass@hoppscotch-db:5432/hoppscotch?connect_timeout=300
|
|
||||||
- PORT=3170
|
|
||||||
volumes:
|
volumes:
|
||||||
# Uncomment the line below when modifying code. Only applicable when using the "dev" target.
|
- "./.hoppscotch:/app/.hoppscotch"
|
||||||
# - ./packages/hoppscotch-backend/:/usr/src/app
|
- "./assets:/app/assets"
|
||||||
- /usr/src/app/node_modules/
|
- "./directives:/app/directives"
|
||||||
depends_on:
|
- "./layouts:/app/layouts"
|
||||||
hoppscotch-db:
|
- "./middleware:/app/middleware"
|
||||||
condition: service_healthy
|
- "./pages:/app/pages"
|
||||||
ports:
|
- "./plugins:/app/plugins"
|
||||||
- "3170:3170"
|
- "./static:/app/static"
|
||||||
|
- "./store:/app/store"
|
||||||
# The main hoppscotch app. This will be hosted at port 3000
|
- "./components:/app/components"
|
||||||
# NOTE: To do TLS or play around with how the app is hosted, you can look into the Caddyfile for
|
- "./helpers:/app/helpers"
|
||||||
# the SH admin dashboard server at packages/hoppscotch-selfhost-web/Caddyfile
|
|
||||||
hoppscotch-app:
|
|
||||||
container_name: hoppscotch-app
|
|
||||||
build:
|
|
||||||
dockerfile: prod.Dockerfile
|
|
||||||
context: .
|
|
||||||
target: app
|
|
||||||
env_file:
|
|
||||||
- ./.env
|
|
||||||
depends_on:
|
|
||||||
- hoppscotch-backend
|
|
||||||
ports:
|
|
||||||
- "3000:8080"
|
|
||||||
|
|
||||||
# The Self Host dashboard for managing the app. This will be hosted at port 3100
|
|
||||||
# NOTE: To do TLS or play around with how the app is hosted, you can look into the Caddyfile for
|
|
||||||
# the SH admin dashboard server at packages/hoppscotch-sh-admin/Caddyfile
|
|
||||||
hoppscotch-sh-admin:
|
|
||||||
container_name: hoppscotch-sh-admin
|
|
||||||
build:
|
|
||||||
dockerfile: prod.Dockerfile
|
|
||||||
context: .
|
|
||||||
target: sh_admin
|
|
||||||
env_file:
|
|
||||||
- ./.env
|
|
||||||
depends_on:
|
|
||||||
- hoppscotch-backend
|
|
||||||
ports:
|
|
||||||
- "3100:8080"
|
|
||||||
|
|
||||||
# The service that spins up all 3 services at once in one container
|
|
||||||
hoppscotch-aio:
|
|
||||||
container_name: hoppscotch-aio
|
|
||||||
build:
|
|
||||||
dockerfile: prod.Dockerfile
|
|
||||||
context: .
|
|
||||||
target: aio
|
|
||||||
env_file:
|
|
||||||
- ./.env
|
|
||||||
depends_on:
|
|
||||||
hoppscotch-db:
|
|
||||||
condition: service_healthy
|
|
||||||
ports:
|
ports:
|
||||||
- "3000:3000"
|
- "3000:3000"
|
||||||
- "3100:3100"
|
|
||||||
- "3170:3170"
|
|
||||||
|
|
||||||
# The preset DB service, you can delete/comment the below lines if
|
|
||||||
# you are using an external postgres instance
|
|
||||||
# This will be exposed at port 5432
|
|
||||||
hoppscotch-db:
|
|
||||||
image: postgres:15
|
|
||||||
ports:
|
|
||||||
- "5432:5432"
|
|
||||||
user: postgres
|
|
||||||
environment:
|
environment:
|
||||||
# The default user defined by the docker image
|
HOST: 0.0.0.0
|
||||||
POSTGRES_USER: postgres
|
command: "npm run dev"
|
||||||
# NOTE: Please UPDATE THIS PASSWORD!
|
|
||||||
POSTGRES_PASSWORD: testpass
|
|
||||||
POSTGRES_DB: hoppscotch
|
|
||||||
healthcheck:
|
|
||||||
test:
|
|
||||||
[
|
|
||||||
"CMD-SHELL",
|
|
||||||
"sh -c 'pg_isready -U $${POSTGRES_USER} -d $${POSTGRES_DB}'"
|
|
||||||
]
|
|
||||||
interval: 5s
|
|
||||||
timeout: 5s
|
|
||||||
retries: 10
|
|
||||||
|
|
||||||
# All the services listed below are deprececated
|
|
||||||
hoppscotch-old-backend:
|
|
||||||
container_name: hoppscotch-old-backend
|
|
||||||
build:
|
|
||||||
dockerfile: packages/hoppscotch-backend/Dockerfile
|
|
||||||
context: .
|
|
||||||
target: prod
|
|
||||||
env_file:
|
|
||||||
- ./.env
|
|
||||||
restart: always
|
|
||||||
environment:
|
|
||||||
# Edit the below line to match your PostgresDB URL if you have an outside DB (make sure to update the .env file as well)
|
|
||||||
- DATABASE_URL=postgresql://postgres:testpass@hoppscotch-db:5432/hoppscotch?connect_timeout=300
|
|
||||||
- PORT=3000
|
|
||||||
volumes:
|
|
||||||
# Uncomment the line below when modifying code. Only applicable when using the "dev" target.
|
|
||||||
# - ./packages/hoppscotch-backend/:/usr/src/app
|
|
||||||
- /usr/src/app/node_modules/
|
|
||||||
depends_on:
|
|
||||||
hoppscotch-db:
|
|
||||||
condition: service_healthy
|
|
||||||
ports:
|
|
||||||
- "3170:3000"
|
|
||||||
|
|
||||||
hoppscotch-old-app:
|
|
||||||
container_name: hoppscotch-old-app
|
|
||||||
build:
|
|
||||||
dockerfile: packages/hoppscotch-selfhost-web/Dockerfile
|
|
||||||
context: .
|
|
||||||
env_file:
|
|
||||||
- ./.env
|
|
||||||
depends_on:
|
|
||||||
- hoppscotch-old-backend
|
|
||||||
ports:
|
|
||||||
- "3000:8080"
|
|
||||||
|
|
||||||
hoppscotch-old-sh-admin:
|
|
||||||
container_name: hoppscotch-old-sh-admin
|
|
||||||
build:
|
|
||||||
dockerfile: packages/hoppscotch-sh-admin/Dockerfile
|
|
||||||
context: .
|
|
||||||
env_file:
|
|
||||||
- ./.env
|
|
||||||
depends_on:
|
|
||||||
- hoppscotch-old-backend
|
|
||||||
ports:
|
|
||||||
- "3100:8080"
|
|
||||||
|
|||||||
@@ -5,9 +5,9 @@
|
|||||||
},
|
},
|
||||||
"hosting": {
|
"hosting": {
|
||||||
"predeploy": [
|
"predeploy": [
|
||||||
"mv .env.example .env && npm install -g pnpm && pnpm i && pnpm run generate"
|
"cd packages/hoppscotch-app && mv .env.example .env && cd ../.. && npm install -g pnpm && pnpm i && pnpm run generate"
|
||||||
],
|
],
|
||||||
"public": "packages/hoppscotch-web/dist",
|
"public": "packages/hoppscotch-app/dist",
|
||||||
"ignore": ["firebase.json", "**/.*", "**/node_modules/**"],
|
"ignore": ["firebase.json", "**/.*", "**/node_modules/**"],
|
||||||
"rewrites": [
|
"rewrites": [
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,14 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
curlCheck() {
|
|
||||||
if ! curl -s --head "$1" | head -n 1 | grep -q "HTTP/1.[01] [23].."; then
|
|
||||||
echo "URL request failed!"
|
|
||||||
exit 1
|
|
||||||
else
|
|
||||||
echo "URL request succeeded!"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
curlCheck "http://localhost:3000"
|
|
||||||
curlCheck "http://localhost:3100"
|
|
||||||
curlCheck "http://localhost:3170/ping"
|
|
||||||
19
netlify.toml
@@ -4,13 +4,13 @@
|
|||||||
|
|
||||||
[build]
|
[build]
|
||||||
base = "/"
|
base = "/"
|
||||||
publish = "packages/hoppscotch-web/dist"
|
publish = "packages/hoppscotch-app/dist"
|
||||||
command = "npx pnpm i --store=node_modules/.pnpm-store && npx pnpm run generate"
|
command = "npx pnpm i --store=node_modules/.pnpm-store && npx pnpm run generate"
|
||||||
|
|
||||||
[[headers]]
|
[[headers]]
|
||||||
for = "/*"
|
for = "/*"
|
||||||
[headers.values]
|
[headers.values]
|
||||||
X-Frame-Options = "SAMEORIGIN"
|
X-Frame-Options = "DENY"
|
||||||
X-XSS-Protection = "1; mode=block"
|
X-XSS-Protection = "1; mode=block"
|
||||||
|
|
||||||
[[redirects]]
|
[[redirects]]
|
||||||
@@ -60,18 +60,3 @@
|
|||||||
to = "https://company.hoppscotch.io/announcements"
|
to = "https://company.hoppscotch.io/announcements"
|
||||||
status = 301
|
status = 301
|
||||||
force = true
|
force = true
|
||||||
|
|
||||||
[[redirects]]
|
|
||||||
from = "/robots.txt"
|
|
||||||
to = "/robots.txt"
|
|
||||||
status = 200
|
|
||||||
|
|
||||||
[[redirects]]
|
|
||||||
from = "/sitemap.xml"
|
|
||||||
to = "/sitemap.xml"
|
|
||||||
status = 200
|
|
||||||
|
|
||||||
[[redirects]]
|
|
||||||
from = "/*"
|
|
||||||
to = "/index.html"
|
|
||||||
status = 200
|
|
||||||
|
|||||||
27
package.json
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "hoppscotch-app",
|
"name": "hoppscotch-app",
|
||||||
"version": "3.0.1",
|
"version": "2.2.1",
|
||||||
"description": "Open source API development ecosystem",
|
"description": "Open source API development ecosystem",
|
||||||
"author": "Hoppscotch (support@hoppscotch.io)",
|
"author": "Hoppscotch (support@hoppscotch.io)",
|
||||||
"private": true,
|
"private": true,
|
||||||
@@ -9,35 +9,24 @@
|
|||||||
"preinstall": "npx only-allow pnpm",
|
"preinstall": "npx only-allow pnpm",
|
||||||
"prepare": "husky install",
|
"prepare": "husky install",
|
||||||
"dev": "pnpm -r do-dev",
|
"dev": "pnpm -r do-dev",
|
||||||
"gen-gql": "cross-env GQL_SCHEMA_EMIT_LOCATION='../../../gql-gen/backend-schema.gql' pnpm -r generate-gql-sdl",
|
|
||||||
"generate": "pnpm -r do-build-prod",
|
"generate": "pnpm -r do-build-prod",
|
||||||
"start": "http-server packages/hoppscotch-selfhost-web/dist -p 3000",
|
"start": "pnpm -r do-prod-start",
|
||||||
"lint": "pnpm -r do-lint",
|
"lint": "pnpm -r do-lint",
|
||||||
"typecheck": "pnpm -r do-typecheck",
|
"typecheck": "pnpm -r do-typecheck",
|
||||||
"lintfix": "pnpm -r do-lintfix",
|
"lintfix": "pnpm -r do-lintfix",
|
||||||
"pre-commit": "pnpm -r do-lint && pnpm -r do-typecheck",
|
"pre-commit": "pnpm -r do-lint && pnpm -r do-typecheck",
|
||||||
"test": "pnpm -r do-test",
|
"test": "pnpm -r do-test"
|
||||||
"generate-ui": "pnpm -r do-build-ui"
|
|
||||||
},
|
},
|
||||||
"workspaces": [
|
"workspaces": [
|
||||||
"./packages/*"
|
"./packages/*"
|
||||||
],
|
],
|
||||||
|
"dependencies": {
|
||||||
|
"husky": "^7.0.4",
|
||||||
|
"lint-staged": "^12.3.8"
|
||||||
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@commitlint/cli": "^16.2.3",
|
"@commitlint/cli": "^16.2.3",
|
||||||
"@commitlint/config-conventional": "^16.2.1",
|
"@commitlint/config-conventional": "^16.2.1",
|
||||||
"@types/node": "17.0.27",
|
"@types/node": "^17.0.24"
|
||||||
"cross-env": "^7.0.3",
|
|
||||||
"http-server": "^14.1.1",
|
|
||||||
"husky": "^7.0.4",
|
|
||||||
"lint-staged": "12.4.0"
|
|
||||||
},
|
|
||||||
"pnpm": {
|
|
||||||
"packageExtensions": {
|
|
||||||
"httpsnippet@^3.0.1": {
|
|
||||||
"peerDependencies": {
|
|
||||||
"ajv": "6.12.3"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,16 +17,16 @@
|
|||||||
"types": "dist/index.d.ts",
|
"types": "dist/index.d.ts",
|
||||||
"sideEffects": false,
|
"sideEffects": false,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@codemirror/language": "^6.9.1",
|
"@codemirror/highlight": "^0.19.8",
|
||||||
"@lezer/highlight": "^1.1.6",
|
"@codemirror/language": "^0.19.10",
|
||||||
"@lezer/lr": "^1.3.13"
|
"@lezer/lr": "^0.15.8"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@lezer/generator": "^1.5.1",
|
"@lezer/generator": "^0.15.4",
|
||||||
"mocha": "^9.2.2",
|
"mocha": "^9.2.2",
|
||||||
"rollup": "^3.29.3",
|
"rollup": "^2.70.2",
|
||||||
"rollup-plugin-dts": "^6.0.2",
|
"rollup-plugin-dts": "^4.2.1",
|
||||||
"rollup-plugin-ts": "^3.4.5",
|
"rollup-plugin-ts": "^2.0.7",
|
||||||
"typescript": "^5.2.2"
|
"typescript": "^4.6.3"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import {
|
|||||||
foldInside,
|
foldInside,
|
||||||
delimitedIndent,
|
delimitedIndent,
|
||||||
} from "@codemirror/language"
|
} from "@codemirror/language"
|
||||||
import { styleTags, tags as t } from "@lezer/highlight"
|
import { styleTags, tags as t } from "@codemirror/highlight"
|
||||||
|
|
||||||
export const GQLLanguage = LRLanguage.define({
|
export const GQLLanguage = LRLanguage.define({
|
||||||
parser: parser.configure({
|
parser: parser.configure({
|
||||||
|
|||||||
24
packages/dioc/.gitignore
vendored
@@ -1,24 +0,0 @@
|
|||||||
# Logs
|
|
||||||
logs
|
|
||||||
*.log
|
|
||||||
npm-debug.log*
|
|
||||||
yarn-debug.log*
|
|
||||||
yarn-error.log*
|
|
||||||
pnpm-debug.log*
|
|
||||||
lerna-debug.log*
|
|
||||||
|
|
||||||
node_modules
|
|
||||||
dist
|
|
||||||
dist-ssr
|
|
||||||
*.local
|
|
||||||
|
|
||||||
# Editor directories and files
|
|
||||||
.vscode/*
|
|
||||||
!.vscode/extensions.json
|
|
||||||
.idea
|
|
||||||
.DS_Store
|
|
||||||
*.suo
|
|
||||||
*.ntvs*
|
|
||||||
*.njsproj
|
|
||||||
*.sln
|
|
||||||
*.sw?
|
|
||||||
@@ -1,141 +0,0 @@
|
|||||||
# dioc
|
|
||||||
|
|
||||||
A small and lightweight dependency injection / inversion of control system.
|
|
||||||
|
|
||||||
### About
|
|
||||||
|
|
||||||
`dioc` is a really simple **DI/IOC** system where you write services (which are singletons per container) that can depend on each other and emit events that can be listened upon.
|
|
||||||
|
|
||||||
### Demo
|
|
||||||
|
|
||||||
```ts
|
|
||||||
import { Service, Container } from "dioc"
|
|
||||||
|
|
||||||
// Here is a simple service, which you can define by extending the Service class
|
|
||||||
// and providing an ID static field (of type string)
|
|
||||||
export class PersistenceService extends Service {
|
|
||||||
// This should be unique for each container
|
|
||||||
public static ID = "PERSISTENCE_SERVICE"
|
|
||||||
|
|
||||||
public read(key: string): string | undefined {
|
|
||||||
// ...
|
|
||||||
}
|
|
||||||
|
|
||||||
public write(key: string, value: string) {
|
|
||||||
// ...
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
type TodoServiceEvent =
|
|
||||||
| { type: "TODO_CREATED"; index: number }
|
|
||||||
| { type: "TODO_DELETED"; index: number }
|
|
||||||
|
|
||||||
// Services have a built in event system
|
|
||||||
// Define the generic argument to say what are the possible emitted values
|
|
||||||
export class TodoService extends Service<TodoServiceEvent> {
|
|
||||||
public static ID = "TODO_SERVICE"
|
|
||||||
|
|
||||||
// Inject persistence service into this service
|
|
||||||
private readonly persistence = this.bind(PersistenceService)
|
|
||||||
|
|
||||||
public todos = []
|
|
||||||
|
|
||||||
// Service constructors cannot have arguments
|
|
||||||
constructor() {
|
|
||||||
super()
|
|
||||||
|
|
||||||
this.todos = JSON.parse(this.persistence.read("todos") ?? "[]")
|
|
||||||
}
|
|
||||||
|
|
||||||
public addTodo(text: string) {
|
|
||||||
// ...
|
|
||||||
|
|
||||||
// You can access services via the bound fields
|
|
||||||
this.persistence.write("todos", JSON.stringify(this.todos))
|
|
||||||
|
|
||||||
// This is how you emit an event
|
|
||||||
this.emit({
|
|
||||||
type: "TODO_CREATED",
|
|
||||||
index,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
public removeTodo(index: number) {
|
|
||||||
// ...
|
|
||||||
|
|
||||||
this.emit({
|
|
||||||
type: "TODO_DELETED",
|
|
||||||
index,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Services need a container to run in
|
|
||||||
const container = new Container()
|
|
||||||
|
|
||||||
// You can initialize and get services using Container#bind
|
|
||||||
// It will automatically initialize the service (and its dependencies)
|
|
||||||
const todoService = container.bind(TodoService) // Returns an instance of TodoService
|
|
||||||
```
|
|
||||||
|
|
||||||
### Demo (Unit Test)
|
|
||||||
|
|
||||||
`dioc/testing` contains `TestContainer` which lets you bind mocked services to the container.
|
|
||||||
|
|
||||||
```ts
|
|
||||||
import { TestContainer } from "dioc/testing"
|
|
||||||
import { TodoService, PersistenceService } from "./demo.ts" // The above demo code snippet
|
|
||||||
import { describe, it, expect, vi } from "vitest"
|
|
||||||
|
|
||||||
describe("TodoService", () => {
|
|
||||||
it("addTodo writes to persistence", () => {
|
|
||||||
const container = new TestContainer()
|
|
||||||
|
|
||||||
const writeFn = vi.fn()
|
|
||||||
|
|
||||||
// The first parameter is the service to mock and the second parameter
|
|
||||||
// is the mocked service fields and functions
|
|
||||||
container.bindMock(PersistenceService, {
|
|
||||||
read: () => undefined, // Not really important for this test
|
|
||||||
write: writeFn,
|
|
||||||
})
|
|
||||||
|
|
||||||
// the peristence service bind in TodoService will now use the
|
|
||||||
// above defined mocked implementation
|
|
||||||
const todoService = container.bind(TodoService)
|
|
||||||
|
|
||||||
todoService.addTodo("sup")
|
|
||||||
|
|
||||||
expect(writeFn).toHaveBeenCalledOnce()
|
|
||||||
expect(writeFn).toHaveBeenCalledWith("todos", JSON.stringify(["sup"]))
|
|
||||||
})
|
|
||||||
})
|
|
||||||
```
|
|
||||||
|
|
||||||
### Demo (Vue)
|
|
||||||
|
|
||||||
`dioc/vue` contains a Vue Plugin and a `useService` composable that allows Vue components to use the defined services.
|
|
||||||
|
|
||||||
In the app entry point:
|
|
||||||
|
|
||||||
```ts
|
|
||||||
import { createApp } from "vue"
|
|
||||||
import { diocPlugin } from "dioc/vue"
|
|
||||||
|
|
||||||
const app = createApp()
|
|
||||||
|
|
||||||
app.use(diocPlugin, {
|
|
||||||
container: new Container(), // You can pass in the container you want to provide to the components here
|
|
||||||
})
|
|
||||||
```
|
|
||||||
|
|
||||||
In your Vue components:
|
|
||||||
|
|
||||||
```vue
|
|
||||||
<script setup>
|
|
||||||
import { TodoService } from "./demo.ts" // The above demo
|
|
||||||
import { useService } from "dioc/vue"
|
|
||||||
|
|
||||||
const todoService = useService(TodoService) // Returns an instance of the TodoService class
|
|
||||||
</script>
|
|
||||||
```
|
|
||||||
2
packages/dioc/index.d.ts
vendored
@@ -1,2 +0,0 @@
|
|||||||
export { default } from "./dist/main.d.ts"
|
|
||||||
export * from "./dist/main.d.ts"
|
|
||||||
@@ -1,147 +0,0 @@
|
|||||||
import { Service } from "./service"
|
|
||||||
import { Observable, Subject } from 'rxjs'
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Stores the current container instance in the current operating context.
|
|
||||||
*
|
|
||||||
* NOTE: This should not be used outside of dioc library code
|
|
||||||
*/
|
|
||||||
export let currentContainer: Container | null = null
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The events emitted by the container
|
|
||||||
*
|
|
||||||
* `SERVICE_BIND` - emitted when a service is bound to the container directly or as a dependency to another service
|
|
||||||
* `SERVICE_INIT` - emitted when a service is initialized
|
|
||||||
*/
|
|
||||||
export type ContainerEvent =
|
|
||||||
| {
|
|
||||||
type: 'SERVICE_BIND';
|
|
||||||
|
|
||||||
/** The Service ID of the service being bounded (the dependency) */
|
|
||||||
boundeeID: string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The Service ID of the bounder that is binding the boundee (the dependent)
|
|
||||||
*
|
|
||||||
* NOTE: This will be undefined if the service is bound directly to the container
|
|
||||||
*/
|
|
||||||
bounderID: string | undefined
|
|
||||||
}
|
|
||||||
| {
|
|
||||||
type: 'SERVICE_INIT';
|
|
||||||
|
|
||||||
/** The Service ID of the service being initialized */
|
|
||||||
serviceID: string
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The dependency injection container, allows for services to be initialized and maintains the dependency trees.
|
|
||||||
*/
|
|
||||||
export class Container {
|
|
||||||
/** Used during the `bind` operation to detect circular dependencies */
|
|
||||||
private bindStack: string[] = []
|
|
||||||
|
|
||||||
/** The map of bound services to their IDs */
|
|
||||||
protected boundMap = new Map<string, Service<unknown>>()
|
|
||||||
|
|
||||||
/** The RxJS observable representing the event stream */
|
|
||||||
protected event$ = new Subject<ContainerEvent>()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns whether a container has the given service bound
|
|
||||||
* @param service The service to check for
|
|
||||||
*/
|
|
||||||
public hasBound<
|
|
||||||
T extends typeof Service<any> & { ID: string }
|
|
||||||
>(service: T): boolean {
|
|
||||||
return this.boundMap.has(service.ID)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the service bound to the container with the given ID or if not found, undefined.
|
|
||||||
*
|
|
||||||
* NOTE: This is an advanced method and should not be used as much as possible.
|
|
||||||
*
|
|
||||||
* @param serviceID The ID of the service to get
|
|
||||||
*/
|
|
||||||
public getBoundServiceWithID(serviceID: string): Service<unknown> | undefined {
|
|
||||||
return this.boundMap.get(serviceID)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Binds a service to the container. This is equivalent to marking a service as a dependency.
|
|
||||||
* @param service The class reference of a service to bind
|
|
||||||
* @param bounder The class reference of the service that is binding the service (if bound directly to the container, this should be undefined)
|
|
||||||
*/
|
|
||||||
public bind<T extends typeof Service<any> & { ID: string }>(
|
|
||||||
service: T,
|
|
||||||
bounder: ((typeof Service<T>) & { ID: string }) | undefined = undefined
|
|
||||||
): InstanceType<T> {
|
|
||||||
// We need to store the current container in a variable so that we can restore it after the bind operation
|
|
||||||
const oldCurrentContainer = currentContainer;
|
|
||||||
currentContainer = this;
|
|
||||||
|
|
||||||
// If the service is already bound, return the existing instance
|
|
||||||
if (this.hasBound(service)) {
|
|
||||||
this.event$.next({
|
|
||||||
type: 'SERVICE_BIND',
|
|
||||||
boundeeID: service.ID,
|
|
||||||
bounderID: bounder?.ID // Return the bounder ID if it is defined, else assume its the container
|
|
||||||
})
|
|
||||||
|
|
||||||
return this.boundMap.get(service.ID) as InstanceType<T> // Casted as InstanceType<T> because service IDs and types are expected to match
|
|
||||||
}
|
|
||||||
|
|
||||||
// Detect circular dependency and throw error
|
|
||||||
if (this.bindStack.findIndex((serviceID) => serviceID === service.ID) !== -1) {
|
|
||||||
const circularServices = `${this.bindStack.join(' -> ')} -> ${service.ID}`
|
|
||||||
|
|
||||||
throw new Error(`Circular dependency detected.\nChain: ${circularServices}`)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Push the service ID onto the bind stack to detect circular dependencies
|
|
||||||
this.bindStack.push(service.ID)
|
|
||||||
|
|
||||||
// Initialize the service and emit events
|
|
||||||
|
|
||||||
// NOTE: We need to cast the service to any as TypeScript thinks that the service is abstract
|
|
||||||
const instance: Service<any> = new (service as any)()
|
|
||||||
|
|
||||||
this.boundMap.set(service.ID, instance)
|
|
||||||
|
|
||||||
this.bindStack.pop()
|
|
||||||
|
|
||||||
this.event$.next({
|
|
||||||
type: 'SERVICE_INIT',
|
|
||||||
serviceID: service.ID,
|
|
||||||
})
|
|
||||||
|
|
||||||
this.event$.next({
|
|
||||||
type: 'SERVICE_BIND',
|
|
||||||
boundeeID: service.ID,
|
|
||||||
bounderID: bounder?.ID
|
|
||||||
})
|
|
||||||
|
|
||||||
|
|
||||||
// Restore the current container
|
|
||||||
currentContainer = oldCurrentContainer;
|
|
||||||
|
|
||||||
// We expect the return type to match the service definition
|
|
||||||
return instance as InstanceType<T>
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns an iterator of the currently bound service IDs and their instances
|
|
||||||
*/
|
|
||||||
public getBoundServices(): IterableIterator<[string, Service<any>]> {
|
|
||||||
return this.boundMap.entries()
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the public container event stream
|
|
||||||
*/
|
|
||||||
public getEventStream(): Observable<ContainerEvent> {
|
|
||||||
return this.event$.asObservable()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
export * from "./container"
|
|
||||||
export * from "./service"
|
|
||||||
@@ -1,65 +0,0 @@
|
|||||||
import { Observable, Subject } from 'rxjs'
|
|
||||||
import { Container, currentContainer } from './container'
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A Dioc service that can bound to a container and can bind dependency services.
|
|
||||||
*
|
|
||||||
* NOTE: Services cannot have a constructor that takes arguments.
|
|
||||||
*
|
|
||||||
* @template EventDef The type of events that can be emitted by the service. These will be accessible by event streams
|
|
||||||
*/
|
|
||||||
export abstract class Service<EventDef = {}> {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The internal event stream of the service
|
|
||||||
*/
|
|
||||||
private event$ = new Subject<EventDef>()
|
|
||||||
|
|
||||||
/** The container the service is bound to */
|
|
||||||
#container: Container
|
|
||||||
|
|
||||||
constructor() {
|
|
||||||
if (!currentContainer) {
|
|
||||||
throw new Error(
|
|
||||||
`Tried to initialize service with no container (ID: ${ (this.constructor as any).ID })`
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
this.#container = currentContainer
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Binds a dependency service into this service.
|
|
||||||
* @param service The class reference of the service to bind
|
|
||||||
*/
|
|
||||||
protected bind<T extends typeof Service<any> & { ID: string }>(service: T): InstanceType<T> {
|
|
||||||
if (!currentContainer) {
|
|
||||||
throw new Error('No currentContainer defined.')
|
|
||||||
}
|
|
||||||
|
|
||||||
return currentContainer.bind(service, this.constructor as typeof Service<any> & { ID: string })
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the container the service is bound to
|
|
||||||
*/
|
|
||||||
protected getContainer(): Container {
|
|
||||||
return this.#container
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Emits an event on the service's event stream
|
|
||||||
* @param event The event to emit
|
|
||||||
*/
|
|
||||||
protected emit(event: EventDef) {
|
|
||||||
this.event$.next(event)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the event stream of the service
|
|
||||||
*/
|
|
||||||
public getEventStream(): Observable<EventDef> {
|
|
||||||
|
|
||||||
return this.event$.asObservable()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
import { Container, Service } from "./main";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A container that can be used for writing tests, contains additional methods
|
|
||||||
* for binding suitable for writing tests. (see `bindMock`).
|
|
||||||
*/
|
|
||||||
export class TestContainer extends Container {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Binds a mock service to the container.
|
|
||||||
*
|
|
||||||
* @param service
|
|
||||||
* @param mock
|
|
||||||
*/
|
|
||||||
public bindMock<
|
|
||||||
T extends typeof Service<any> & { ID: string },
|
|
||||||
U extends Partial<InstanceType<T>>
|
|
||||||
>(service: T, mock: U): U {
|
|
||||||
if (this.boundMap.has(service.ID)) {
|
|
||||||
throw new Error(`Service '${service.ID}' already bound to container. Did you already call bindMock on this ?`)
|
|
||||||
}
|
|
||||||
|
|
||||||
this.boundMap.set(service.ID, mock as any)
|
|
||||||
|
|
||||||
this.event$.next({
|
|
||||||
type: "SERVICE_BIND",
|
|
||||||
boundeeID: service.ID,
|
|
||||||
bounderID: undefined,
|
|
||||||
})
|
|
||||||
|
|
||||||
return mock
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,34 +0,0 @@
|
|||||||
import { Plugin, inject } from "vue"
|
|
||||||
import { Container } from "./container"
|
|
||||||
import { Service } from "./service"
|
|
||||||
|
|
||||||
const VUE_CONTAINER_KEY = Symbol()
|
|
||||||
|
|
||||||
// TODO: Some Vue version issue with plugin generics is breaking type checking
|
|
||||||
/**
|
|
||||||
* The Vue Dioc Plugin, this allows the composables to work and access the container
|
|
||||||
*
|
|
||||||
* NOTE: Make sure you add `vue` as dependency to be able to use this plugin (duh)
|
|
||||||
*/
|
|
||||||
export const diocPlugin: Plugin = {
|
|
||||||
install(app, { container }) {
|
|
||||||
app.provide(VUE_CONTAINER_KEY, container)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A composable that binds a service to a Vue Component
|
|
||||||
*
|
|
||||||
* @param service The class reference of the service to bind
|
|
||||||
*/
|
|
||||||
export function useService<
|
|
||||||
T extends typeof Service<any> & { ID: string }
|
|
||||||
>(service: T): InstanceType<T> {
|
|
||||||
const container = inject(VUE_CONTAINER_KEY) as Container | undefined | null
|
|
||||||
|
|
||||||
if (!container) {
|
|
||||||
throw new Error("Container not found, did you forget to install the dioc plugin?")
|
|
||||||
}
|
|
||||||
|
|
||||||
return container.bind(service)
|
|
||||||
}
|
|
||||||
@@ -1,54 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "dioc",
|
|
||||||
"private": true,
|
|
||||||
"version": "0.1.0",
|
|
||||||
"type": "module",
|
|
||||||
"files": [
|
|
||||||
"dist",
|
|
||||||
"index.d.ts"
|
|
||||||
],
|
|
||||||
"main": "./dist/counter.umd.cjs",
|
|
||||||
"module": "./dist/counter.js",
|
|
||||||
"types": "./index.d.ts",
|
|
||||||
"exports": {
|
|
||||||
".": {
|
|
||||||
"types": "./dist/main.d.ts",
|
|
||||||
"require": "./dist/index.cjs",
|
|
||||||
"import": "./dist/index.js"
|
|
||||||
},
|
|
||||||
"./vue": {
|
|
||||||
"types": "./dist/vue.d.ts",
|
|
||||||
"require": "./dist/vue.cjs",
|
|
||||||
"import": "./dist/vue.js"
|
|
||||||
},
|
|
||||||
"./testing": {
|
|
||||||
"types": "./dist/testing.d.ts",
|
|
||||||
"require": "./dist/testing.cjs",
|
|
||||||
"import": "./dist/testing.js"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"scripts": {
|
|
||||||
"dev": "vite",
|
|
||||||
"build": "vite build && tsc --emitDeclarationOnly",
|
|
||||||
"prepare": "pnpm run build",
|
|
||||||
"test": "vitest run",
|
|
||||||
"do-test": "pnpm run test",
|
|
||||||
"test:watch": "vitest"
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
|
||||||
"typescript": "^4.9.4",
|
|
||||||
"vite": "^4.0.4",
|
|
||||||
"vitest": "^0.29.3"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"rxjs": "^7.8.1"
|
|
||||||
},
|
|
||||||
"peerDependencies": {
|
|
||||||
"vue": "^3.2.25"
|
|
||||||
},
|
|
||||||
"peerDependenciesMeta": {
|
|
||||||
"vue": {
|
|
||||||
"optional": true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,262 +0,0 @@
|
|||||||
import { it, expect, describe, vi } from "vitest"
|
|
||||||
import { Service } from "../lib/service"
|
|
||||||
import { Container, currentContainer, ContainerEvent } from "../lib/container"
|
|
||||||
|
|
||||||
class TestServiceA extends Service {
|
|
||||||
public static ID = "TestServiceA"
|
|
||||||
}
|
|
||||||
|
|
||||||
class TestServiceB extends Service {
|
|
||||||
public static ID = "TestServiceB"
|
|
||||||
|
|
||||||
// Marked public to allow for testing
|
|
||||||
public readonly serviceA = this.bind(TestServiceA)
|
|
||||||
}
|
|
||||||
|
|
||||||
describe("Container", () => {
|
|
||||||
describe("getBoundServiceWithID", () => {
|
|
||||||
it("returns the service instance if it is bound to the container", () => {
|
|
||||||
const container = new Container()
|
|
||||||
|
|
||||||
const service = container.bind(TestServiceA)
|
|
||||||
|
|
||||||
expect(container.getBoundServiceWithID(TestServiceA.ID)).toBe(service)
|
|
||||||
})
|
|
||||||
|
|
||||||
it("returns undefined if the service is not bound to the container", () => {
|
|
||||||
const container = new Container()
|
|
||||||
|
|
||||||
expect(container.getBoundServiceWithID(TestServiceA.ID)).toBeUndefined()
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
describe("bind", () => {
|
|
||||||
it("correctly binds the service to it", () => {
|
|
||||||
const container = new Container()
|
|
||||||
|
|
||||||
const service = container.bind(TestServiceA)
|
|
||||||
|
|
||||||
// @ts-expect-error getContainer is defined as a protected property, but we are leveraging it here to check
|
|
||||||
expect(service.getContainer()).toBe(container)
|
|
||||||
})
|
|
||||||
|
|
||||||
it("after bind, the current container is set back to its previous value", () => {
|
|
||||||
const originalValue = currentContainer
|
|
||||||
|
|
||||||
const container = new Container()
|
|
||||||
container.bind(TestServiceA)
|
|
||||||
|
|
||||||
expect(currentContainer).toBe(originalValue)
|
|
||||||
})
|
|
||||||
|
|
||||||
it("dependent services are registered in the same container", () => {
|
|
||||||
const container = new Container()
|
|
||||||
|
|
||||||
const serviceB = container.bind(TestServiceB)
|
|
||||||
|
|
||||||
// @ts-expect-error getContainer is defined as a protected property, but we are leveraging it here to check
|
|
||||||
expect(serviceB.serviceA.getContainer()).toBe(container)
|
|
||||||
})
|
|
||||||
|
|
||||||
it("binding an already initialized service returns the initialized instance (services are singletons)", () => {
|
|
||||||
const container = new Container()
|
|
||||||
|
|
||||||
const serviceA = container.bind(TestServiceA)
|
|
||||||
const serviceA2 = container.bind(TestServiceA)
|
|
||||||
|
|
||||||
expect(serviceA).toBe(serviceA2)
|
|
||||||
})
|
|
||||||
|
|
||||||
it("binding a service which is a dependency of another service returns the same instance created from the dependency resolution (services are singletons)", () => {
|
|
||||||
const container = new Container()
|
|
||||||
|
|
||||||
const serviceB = container.bind(TestServiceB)
|
|
||||||
const serviceA = container.bind(TestServiceA)
|
|
||||||
|
|
||||||
expect(serviceB.serviceA).toBe(serviceA)
|
|
||||||
})
|
|
||||||
|
|
||||||
it("binding an initialized service as a dependency returns the same instance", () => {
|
|
||||||
const container = new Container()
|
|
||||||
|
|
||||||
const serviceA = container.bind(TestServiceA)
|
|
||||||
const serviceB = container.bind(TestServiceB)
|
|
||||||
|
|
||||||
expect(serviceB.serviceA).toBe(serviceA)
|
|
||||||
})
|
|
||||||
|
|
||||||
it("container emits an init event when an uninitialized service is initialized via bind and event only called once", () => {
|
|
||||||
const container = new Container()
|
|
||||||
|
|
||||||
const serviceFunc = vi.fn<
|
|
||||||
[ContainerEvent & { type: "SERVICE_INIT" }],
|
|
||||||
void
|
|
||||||
>()
|
|
||||||
|
|
||||||
container.getEventStream().subscribe((ev) => {
|
|
||||||
if (ev.type === "SERVICE_INIT") {
|
|
||||||
serviceFunc(ev)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
const instance = container.bind(TestServiceA)
|
|
||||||
|
|
||||||
expect(serviceFunc).toHaveBeenCalledOnce()
|
|
||||||
expect(serviceFunc).toHaveBeenCalledWith(<ContainerEvent>{
|
|
||||||
type: "SERVICE_INIT",
|
|
||||||
serviceID: TestServiceA.ID,
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
it("the bind event emitted has an undefined bounderID when the service is bound directly to the container", () => {
|
|
||||||
const container = new Container()
|
|
||||||
|
|
||||||
const serviceFunc = vi.fn<
|
|
||||||
[ContainerEvent & { type: "SERVICE_BIND" }],
|
|
||||||
void
|
|
||||||
>()
|
|
||||||
|
|
||||||
container.getEventStream().subscribe((ev) => {
|
|
||||||
if (ev.type === "SERVICE_BIND") {
|
|
||||||
serviceFunc(ev)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
container.bind(TestServiceA)
|
|
||||||
|
|
||||||
expect(serviceFunc).toHaveBeenCalledOnce()
|
|
||||||
expect(serviceFunc).toHaveBeenCalledWith(<ContainerEvent>{
|
|
||||||
type: "SERVICE_BIND",
|
|
||||||
boundeeID: TestServiceA.ID,
|
|
||||||
bounderID: undefined,
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
it("the bind event emitted has the correct bounderID when the service is bound to another service", () => {
|
|
||||||
const container = new Container()
|
|
||||||
|
|
||||||
const serviceFunc = vi.fn<
|
|
||||||
[ContainerEvent & { type: "SERVICE_BIND" }],
|
|
||||||
void
|
|
||||||
>()
|
|
||||||
|
|
||||||
container.getEventStream().subscribe((ev) => {
|
|
||||||
// We only care about the bind event of TestServiceA
|
|
||||||
if (ev.type === "SERVICE_BIND" && ev.boundeeID === TestServiceA.ID) {
|
|
||||||
serviceFunc(ev)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
container.bind(TestServiceB)
|
|
||||||
|
|
||||||
expect(serviceFunc).toHaveBeenCalledOnce()
|
|
||||||
expect(serviceFunc).toHaveBeenCalledWith(<ContainerEvent>{
|
|
||||||
type: "SERVICE_BIND",
|
|
||||||
boundeeID: TestServiceA.ID,
|
|
||||||
bounderID: TestServiceB.ID,
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
describe("hasBound", () => {
|
|
||||||
it("returns true if the given service is bound to the container", () => {
|
|
||||||
const container = new Container()
|
|
||||||
|
|
||||||
container.bind(TestServiceA)
|
|
||||||
|
|
||||||
expect(container.hasBound(TestServiceA)).toEqual(true)
|
|
||||||
})
|
|
||||||
|
|
||||||
it("returns false if the given service is not bound to the container", () => {
|
|
||||||
const container = new Container()
|
|
||||||
|
|
||||||
expect(container.hasBound(TestServiceA)).toEqual(false)
|
|
||||||
})
|
|
||||||
|
|
||||||
it("returns true when the service is bound because it is a dependency of another service", () => {
|
|
||||||
const container = new Container()
|
|
||||||
|
|
||||||
container.bind(TestServiceB)
|
|
||||||
|
|
||||||
expect(container.hasBound(TestServiceA)).toEqual(true)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
describe("getEventStream", () => {
|
|
||||||
it("returns an observable which emits events correctly when services are initialized", () => {
|
|
||||||
const container = new Container()
|
|
||||||
|
|
||||||
const serviceFunc = vi.fn<
|
|
||||||
[ContainerEvent & { type: "SERVICE_INIT" }],
|
|
||||||
void
|
|
||||||
>()
|
|
||||||
|
|
||||||
container.getEventStream().subscribe((ev) => {
|
|
||||||
if (ev.type === "SERVICE_INIT") {
|
|
||||||
serviceFunc(ev)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
container.bind(TestServiceB)
|
|
||||||
|
|
||||||
expect(serviceFunc).toHaveBeenCalledTimes(2)
|
|
||||||
expect(serviceFunc).toHaveBeenNthCalledWith(1, <ContainerEvent>{
|
|
||||||
type: "SERVICE_INIT",
|
|
||||||
serviceID: TestServiceA.ID,
|
|
||||||
})
|
|
||||||
expect(serviceFunc).toHaveBeenNthCalledWith(2, <ContainerEvent>{
|
|
||||||
type: "SERVICE_INIT",
|
|
||||||
serviceID: TestServiceB.ID,
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
it("returns an observable which emits events correctly when services are bound", () => {
|
|
||||||
const container = new Container()
|
|
||||||
|
|
||||||
const serviceFunc = vi.fn<
|
|
||||||
[ContainerEvent & { type: "SERVICE_BIND" }],
|
|
||||||
void
|
|
||||||
>()
|
|
||||||
|
|
||||||
container.getEventStream().subscribe((ev) => {
|
|
||||||
if (ev.type === "SERVICE_BIND") {
|
|
||||||
serviceFunc(ev)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
container.bind(TestServiceB)
|
|
||||||
|
|
||||||
expect(serviceFunc).toHaveBeenCalledTimes(2)
|
|
||||||
expect(serviceFunc).toHaveBeenNthCalledWith(1, <ContainerEvent>{
|
|
||||||
type: "SERVICE_BIND",
|
|
||||||
boundeeID: TestServiceA.ID,
|
|
||||||
bounderID: TestServiceB.ID,
|
|
||||||
})
|
|
||||||
expect(serviceFunc).toHaveBeenNthCalledWith(2, <ContainerEvent>{
|
|
||||||
type: "SERVICE_BIND",
|
|
||||||
boundeeID: TestServiceB.ID,
|
|
||||||
bounderID: undefined,
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
describe("getBoundServices", () => {
|
|
||||||
it("returns an iterator over all services bound to the container in the format [service id, service instance]", () => {
|
|
||||||
const container = new Container()
|
|
||||||
|
|
||||||
const instanceB = container.bind(TestServiceB)
|
|
||||||
const instanceA = instanceB.serviceA
|
|
||||||
|
|
||||||
expect(Array.from(container.getBoundServices())).toEqual([
|
|
||||||
[TestServiceA.ID, instanceA],
|
|
||||||
[TestServiceB.ID, instanceB],
|
|
||||||
])
|
|
||||||
})
|
|
||||||
|
|
||||||
it("returns an empty iterator if no services are bound", () => {
|
|
||||||
const container = new Container()
|
|
||||||
|
|
||||||
expect(Array.from(container.getBoundServices())).toEqual([])
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
@@ -1,66 +0,0 @@
|
|||||||
import { describe, expect, it, vi } from "vitest"
|
|
||||||
import { Service, Container } from "../lib/main"
|
|
||||||
|
|
||||||
class TestServiceA extends Service {
|
|
||||||
public static ID = "TestServiceA"
|
|
||||||
}
|
|
||||||
|
|
||||||
class TestServiceB extends Service<"test"> {
|
|
||||||
public static ID = "TestServiceB"
|
|
||||||
|
|
||||||
// Marked public to allow for testing
|
|
||||||
public readonly serviceA = this.bind(TestServiceA)
|
|
||||||
|
|
||||||
public emitTestEvent() {
|
|
||||||
this.emit("test")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
describe("Service", () => {
|
|
||||||
describe("constructor", () => {
|
|
||||||
it("throws an error if the service is initialized without a container", () => {
|
|
||||||
expect(() => new TestServiceA()).toThrowError(
|
|
||||||
"Tried to initialize service with no container (ID: TestServiceA)"
|
|
||||||
)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
describe("bind", () => {
|
|
||||||
it("correctly binds the dependency service using the container", () => {
|
|
||||||
const container = new Container()
|
|
||||||
|
|
||||||
const serviceA = container.bind(TestServiceA)
|
|
||||||
|
|
||||||
const serviceB = container.bind(TestServiceB)
|
|
||||||
expect(serviceB.serviceA).toBe(serviceA)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
describe("getContainer", () => {
|
|
||||||
it("returns the container the service is bound to", () => {
|
|
||||||
const container = new Container()
|
|
||||||
|
|
||||||
const serviceA = container.bind(TestServiceA)
|
|
||||||
|
|
||||||
// @ts-expect-error getContainer is a protected member, we are just using it to help with testing
|
|
||||||
expect(serviceA.getContainer()).toBe(container)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
describe("getEventStream", () => {
|
|
||||||
it("returns the valid event stream of the service", () => {
|
|
||||||
const container = new Container()
|
|
||||||
|
|
||||||
const serviceB = container.bind(TestServiceB)
|
|
||||||
|
|
||||||
const serviceFunc = vi.fn()
|
|
||||||
|
|
||||||
serviceB.getEventStream().subscribe(serviceFunc)
|
|
||||||
|
|
||||||
serviceB.emitTestEvent()
|
|
||||||
|
|
||||||
expect(serviceFunc).toHaveBeenCalledOnce()
|
|
||||||
expect(serviceFunc).toHaveBeenCalledWith("test")
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
@@ -1,92 +0,0 @@
|
|||||||
import { describe, expect, it, vi } from "vitest"
|
|
||||||
import { TestContainer } from "../lib/testing"
|
|
||||||
import { Service } from "../lib/service"
|
|
||||||
import { ContainerEvent } from "../lib/container"
|
|
||||||
|
|
||||||
class TestServiceA extends Service {
|
|
||||||
public static ID = "TestServiceA"
|
|
||||||
|
|
||||||
public test() {
|
|
||||||
return "real"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class TestServiceB extends Service {
|
|
||||||
public static ID = "TestServiceB"
|
|
||||||
|
|
||||||
// declared public to help with testing
|
|
||||||
public readonly serviceA = this.bind(TestServiceA)
|
|
||||||
|
|
||||||
public test() {
|
|
||||||
return this.serviceA.test()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
describe("TestContainer", () => {
|
|
||||||
describe("bindMock", () => {
|
|
||||||
it("returns the fake service defined", () => {
|
|
||||||
const container = new TestContainer()
|
|
||||||
|
|
||||||
const fakeService = {
|
|
||||||
test: () => "fake",
|
|
||||||
}
|
|
||||||
|
|
||||||
const result = container.bindMock(TestServiceA, fakeService)
|
|
||||||
|
|
||||||
expect(result).toBe(fakeService)
|
|
||||||
})
|
|
||||||
|
|
||||||
it("new services bound to the container get the mock service", () => {
|
|
||||||
const container = new TestContainer()
|
|
||||||
|
|
||||||
const fakeServiceA = {
|
|
||||||
test: () => "fake",
|
|
||||||
}
|
|
||||||
|
|
||||||
container.bindMock(TestServiceA, fakeServiceA)
|
|
||||||
|
|
||||||
const serviceB = container.bind(TestServiceB)
|
|
||||||
|
|
||||||
expect(serviceB.serviceA).toBe(fakeServiceA)
|
|
||||||
})
|
|
||||||
|
|
||||||
it("container emits SERVICE_BIND event", () => {
|
|
||||||
const container = new TestContainer()
|
|
||||||
|
|
||||||
const fakeServiceA = {
|
|
||||||
test: () => "fake",
|
|
||||||
}
|
|
||||||
|
|
||||||
const serviceFunc = vi.fn<[ContainerEvent, void]>()
|
|
||||||
|
|
||||||
container.getEventStream().subscribe((ev) => {
|
|
||||||
serviceFunc(ev)
|
|
||||||
})
|
|
||||||
|
|
||||||
container.bindMock(TestServiceA, fakeServiceA)
|
|
||||||
|
|
||||||
expect(serviceFunc).toHaveBeenCalledOnce()
|
|
||||||
expect(serviceFunc).toHaveBeenCalledWith(<ContainerEvent>{
|
|
||||||
type: "SERVICE_BIND",
|
|
||||||
boundeeID: TestServiceA.ID,
|
|
||||||
bounderID: undefined,
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
it("throws if service already bound", () => {
|
|
||||||
const container = new TestContainer()
|
|
||||||
|
|
||||||
const fakeServiceA = {
|
|
||||||
test: () => "fake",
|
|
||||||
}
|
|
||||||
|
|
||||||
container.bindMock(TestServiceA, fakeServiceA)
|
|
||||||
|
|
||||||
expect(() => {
|
|
||||||
container.bindMock(TestServiceA, fakeServiceA)
|
|
||||||
}).toThrowError(
|
|
||||||
"Service 'TestServiceA' already bound to container. Did you already call bindMock on this ?"
|
|
||||||
)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
2
packages/dioc/testing.d.ts
vendored
@@ -1,2 +0,0 @@
|
|||||||
export { default } from "./dist/testing.d.ts"
|
|
||||||
export * from "./dist/testing.d.ts"
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
{
|
|
||||||
"compilerOptions": {
|
|
||||||
"target": "ESNext",
|
|
||||||
"useDefineForClassFields": true,
|
|
||||||
"module": "ESNext",
|
|
||||||
"lib": ["ESNext", "DOM"],
|
|
||||||
"moduleResolution": "Node",
|
|
||||||
"strict": true,
|
|
||||||
"declaration": true,
|
|
||||||
"sourceMap": true,
|
|
||||||
"outDir": "dist",
|
|
||||||
"resolveJsonModule": true,
|
|
||||||
"isolatedModules": true,
|
|
||||||
"esModuleInterop": true,
|
|
||||||
"noUnusedLocals": true,
|
|
||||||
"noUnusedParameters": true,
|
|
||||||
"noImplicitReturns": true,
|
|
||||||
"skipLibCheck": true
|
|
||||||
},
|
|
||||||
"include": ["lib"]
|
|
||||||
}
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
import { defineConfig } from 'vite'
|
|
||||||
|
|
||||||
export default defineConfig({
|
|
||||||
build: {
|
|
||||||
lib: {
|
|
||||||
entry: {
|
|
||||||
index: './lib/main.ts',
|
|
||||||
vue: './lib/vue.ts',
|
|
||||||
testing: './lib/testing.ts',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
rollupOptions: {
|
|
||||||
external: ['vue'],
|
|
||||||
}
|
|
||||||
},
|
|
||||||
})
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
import { defineConfig } from "vitest/config"
|
|
||||||
|
|
||||||
export default defineConfig({
|
|
||||||
test: {
|
|
||||||
|
|
||||||
}
|
|
||||||
})
|
|
||||||
2
packages/dioc/vue.d.ts
vendored
@@ -1,2 +0,0 @@
|
|||||||
export { default } from "./dist/vue.d.ts"
|
|
||||||
export * from "./dist/vue.d.ts"
|
|
||||||
22
packages/hoppscotch-app/.env.example
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
# Google Analytics ID
|
||||||
|
GA_ID=UA-61422507-4
|
||||||
|
|
||||||
|
# Google Tag Manager ID
|
||||||
|
GTM_ID=GTM-NMKVBMV
|
||||||
|
|
||||||
|
# Firebase config
|
||||||
|
API_KEY=AIzaSyCMsFreESs58-hRxTtiqQrIcimh4i1wbsM
|
||||||
|
AUTH_DOMAIN=postwoman-api.firebaseapp.com
|
||||||
|
DATABASE_URL=https://postwoman-api.firebaseio.com
|
||||||
|
PROJECT_ID=postwoman-api
|
||||||
|
STORAGE_BUCKET=postwoman-api.appspot.com
|
||||||
|
MESSAGING_SENDER_ID=421993993223
|
||||||
|
APP_ID=1:421993993223:web:ec0baa8ee8c02ffa1fc6a2
|
||||||
|
MEASUREMENT_ID=G-BBJ3R80PJT
|
||||||
|
|
||||||
|
# Base URL
|
||||||
|
BASE_URL=https://hoppscotch.io
|
||||||
|
|
||||||
|
# Backend URLs
|
||||||
|
BACKEND_GQL_URL=https://api.hoppscotch.io/graphql
|
||||||
|
BACKEND_WS_URL=wss://api.hoppscotch.io/graphql
|
||||||
@@ -1,6 +1,3 @@
|
|||||||
/* eslint-env node */
|
|
||||||
require("@rushstack/eslint-patch/modern-module-resolution")
|
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
root: true,
|
root: true,
|
||||||
env: {
|
env: {
|
||||||
@@ -13,33 +10,25 @@ module.exports = {
|
|||||||
requireConfigFile: false,
|
requireConfigFile: false,
|
||||||
},
|
},
|
||||||
extends: [
|
extends: [
|
||||||
"@vue/typescript/recommended",
|
"@nuxtjs",
|
||||||
"plugin:vue/vue3-recommended",
|
"@nuxtjs/eslint-config-typescript",
|
||||||
|
"prettier/prettier",
|
||||||
|
"eslint:recommended",
|
||||||
|
"plugin:vue/recommended",
|
||||||
"plugin:prettier/recommended",
|
"plugin:prettier/recommended",
|
||||||
|
"plugin:nuxt/recommended",
|
||||||
],
|
],
|
||||||
ignorePatterns: [
|
ignorePatterns: ["helpers/backend/graphql.ts"],
|
||||||
"static/**/*",
|
plugins: ["vue", "nuxt", "prettier"],
|
||||||
"./helpers/backend/graphql.ts",
|
|
||||||
"**/*.d.ts",
|
|
||||||
"types/**/*",
|
|
||||||
],
|
|
||||||
plugins: ["vue", "prettier"],
|
|
||||||
// add your custom rules here
|
// add your custom rules here
|
||||||
rules: {
|
rules: {
|
||||||
semi: [2, "never"],
|
semi: [2, "never"],
|
||||||
"import/named": "off", // because, named import issue with typescript see: https://github.com/typescript-eslint/typescript-eslint/issues/154
|
"import/named": "off", // because, named import issue with typescript see: https://github.com/typescript-eslint/typescript-eslint/issues/154
|
||||||
"no-console": "off",
|
"no-console": process.env.NODE_ENV === "production" ? "error" : "off",
|
||||||
"no-debugger": process.env.HOPP_LINT_FOR_PROD === "true" ? "error" : "warn",
|
"no-debugger": process.env.NODE_ENV === "production" ? "error" : "off",
|
||||||
"prettier/prettier":
|
|
||||||
process.env.HOPP_LINT_FOR_PROD === "true" ? "error" : "warn",
|
|
||||||
"vue/multi-word-component-names": "off",
|
"vue/multi-word-component-names": "off",
|
||||||
"vue/no-side-effects-in-computed-properties": "off",
|
|
||||||
"import/no-named-as-default": "off",
|
"import/no-named-as-default": "off",
|
||||||
"import/no-named-as-default-member": "off",
|
"import/no-named-as-default-member": "off",
|
||||||
"@typescript-eslint/no-unused-vars":
|
|
||||||
process.env.HOPP_LINT_FOR_PROD === "true" ? "error" : "warn",
|
|
||||||
"@typescript-eslint/no-non-null-assertion": "off",
|
|
||||||
"@typescript-eslint/no-explicit-any": "off",
|
|
||||||
"import/default": "off",
|
"import/default": "off",
|
||||||
"no-undef": "off",
|
"no-undef": "off",
|
||||||
// localStorage block
|
// localStorage block
|
||||||
@@ -61,4 +50,7 @@ module.exports = {
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
globals: {
|
||||||
|
$nuxt: true,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
118
packages/hoppscotch-app/.gitignore
vendored
Normal file
@@ -0,0 +1,118 @@
|
|||||||
|
# Created by .ignore support plugin (hsz.mobi)
|
||||||
|
|
||||||
|
# Firebase
|
||||||
|
.firebase
|
||||||
|
|
||||||
|
### Node template
|
||||||
|
# Logs
|
||||||
|
logs
|
||||||
|
*.log
|
||||||
|
npm-debug.log*
|
||||||
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
||||||
|
|
||||||
|
# Runtime data
|
||||||
|
pids
|
||||||
|
*.pid
|
||||||
|
*.seed
|
||||||
|
*.pid.lock
|
||||||
|
|
||||||
|
# Directory for instrumented libs generated by jscoverage/JSCover
|
||||||
|
lib-cov
|
||||||
|
|
||||||
|
# Coverage directory used by tools like istanbul
|
||||||
|
coverage
|
||||||
|
|
||||||
|
# nyc test coverage
|
||||||
|
.nyc_output
|
||||||
|
|
||||||
|
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
|
||||||
|
.grunt
|
||||||
|
|
||||||
|
# Bower dependency directory (https://bower.io/)
|
||||||
|
bower_components
|
||||||
|
|
||||||
|
# node-waf configuration
|
||||||
|
.lock-wscript
|
||||||
|
|
||||||
|
# Compiled binary addons (https://nodejs.org/api/addons.html)
|
||||||
|
build/Release
|
||||||
|
|
||||||
|
# Dependency directories
|
||||||
|
node_modules/
|
||||||
|
jspm_packages/
|
||||||
|
|
||||||
|
# TypeScript v1 declaration files
|
||||||
|
typings/
|
||||||
|
|
||||||
|
# Optional npm cache directory
|
||||||
|
.npm
|
||||||
|
|
||||||
|
# Optional eslint cache
|
||||||
|
.eslintcache
|
||||||
|
|
||||||
|
# Optional REPL history
|
||||||
|
.node_repl_history
|
||||||
|
|
||||||
|
# Output of 'npm pack'
|
||||||
|
*.tgz
|
||||||
|
|
||||||
|
# Yarn Integrity file
|
||||||
|
.yarn-integrity
|
||||||
|
|
||||||
|
# dotenv environment variables file
|
||||||
|
.env
|
||||||
|
|
||||||
|
# parcel-bundler cache (https://parceljs.org/)
|
||||||
|
.cache
|
||||||
|
|
||||||
|
# next.js build output
|
||||||
|
.next
|
||||||
|
|
||||||
|
# nuxt.js build output
|
||||||
|
.nuxt
|
||||||
|
|
||||||
|
# Nuxt generate
|
||||||
|
dist
|
||||||
|
|
||||||
|
# vuepress build output
|
||||||
|
.vuepress/dist
|
||||||
|
|
||||||
|
# Serverless directories
|
||||||
|
.serverless
|
||||||
|
|
||||||
|
# IDE / Editor
|
||||||
|
.idea
|
||||||
|
|
||||||
|
# Service worker
|
||||||
|
sw.*
|
||||||
|
|
||||||
|
# Mac OSX
|
||||||
|
.DS_Store
|
||||||
|
|
||||||
|
# Vim swap files
|
||||||
|
*.swp
|
||||||
|
|
||||||
|
# Build data
|
||||||
|
.hoppscotch
|
||||||
|
|
||||||
|
# File explorer
|
||||||
|
.directory
|
||||||
|
|
||||||
|
# Tests screenshots
|
||||||
|
tests/*/screenshots
|
||||||
|
|
||||||
|
# Tests videos
|
||||||
|
tests/*/videos
|
||||||
|
|
||||||
|
# Local Netlify folder
|
||||||
|
.netlify
|
||||||
|
|
||||||
|
# Andrew's crazy Volar shim generator
|
||||||
|
shims-volar.d.ts
|
||||||
|
|
||||||
|
# Hoppscotch Backend Schema Introspection JSON
|
||||||
|
helpers/backend/backend-schema.json
|
||||||
|
|
||||||
|
# GraphQL Type Generation
|
||||||
|
helpers/backend/graphql.ts
|
||||||
33
packages/hoppscotch-app/.stylelintrc.js
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
module.exports = {
|
||||||
|
ignoreFiles: ["/**/*.vue"],
|
||||||
|
customSyntax: "postcss-html",
|
||||||
|
extends: [
|
||||||
|
"stylelint-config-standard",
|
||||||
|
"stylelint-config-prettier",
|
||||||
|
"stylelint-config-standard-scss",
|
||||||
|
"stylelint-config-recommended-vue",
|
||||||
|
],
|
||||||
|
defaultSeverity: "warning",
|
||||||
|
// add your custom config here
|
||||||
|
// https://stylelint.io/user-guide/configuration
|
||||||
|
rules: {
|
||||||
|
"at-rule-no-unknown": [
|
||||||
|
true,
|
||||||
|
{
|
||||||
|
ignoreAtRules: [
|
||||||
|
"extends",
|
||||||
|
"apply",
|
||||||
|
"variants",
|
||||||
|
"responsive",
|
||||||
|
"screen",
|
||||||
|
"mixin",
|
||||||
|
"include",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"declaration-block-trailing-semicolon": null,
|
||||||
|
"no-descending-specificity": null,
|
||||||
|
"selector-class-pattern": null,
|
||||||
|
"selector-id-pattern": null,
|
||||||
|
},
|
||||||
|
}
|
||||||
5
packages/hoppscotch-app/assets/README.md
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
# ASSETS
|
||||||
|
|
||||||
|
This directory contains your un-compiled assets such as LESS, SASS, or JavaScript.
|
||||||
|
|
||||||
|
More information about the usage of this directory in [the documentation](https://nuxtjs.org/guide/assets#webpacked).
|
||||||
13
packages/hoppscotch-app/assets/icons/activity.svg
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="24"
|
||||||
|
height="24"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
fill="none"
|
||||||
|
stroke="currentColor"
|
||||||
|
stroke-width="2"
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
>
|
||||||
|
<polyline points="22 12 18 12 15 21 9 3 6 12 2 12" />
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 264 B |
13
packages/hoppscotch-app/assets/icons/archive.svg
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="24"
|
||||||
|
height="24"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
fill="none"
|
||||||
|
stroke="currentColor"
|
||||||
|
stroke-width="2"
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
>
|
||||||
|
<path d="M20 9v9a2 2 0 01-2 2H6a2 2 0 01-2-2V9m16-5H4a2 2 0 00-2 2v1a2 2 0 002 2h16a2 2 0 002-2V6a2 2 0 00-2-2zm-10 9h4" />
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 334 B |
4
packages/hoppscotch-app/assets/icons/arrow-down-left.svg
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||||
|
<line x1="17" y1="7" x2="7" y2="17"></line>
|
||||||
|
<polyline points="17 17 7 17 7 7"></polyline>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 283 B |
4
packages/hoppscotch-app/assets/icons/arrow-down.svg
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||||
|
<line x1="12" y1="5" x2="12" y2="19"></line>
|
||||||
|
<polyline points="19 12 12 19 5 12"></polyline>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 285 B |
14
packages/hoppscotch-app/assets/icons/arrow-left.svg
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="24"
|
||||||
|
height="24"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
fill="none"
|
||||||
|
stroke="currentColor"
|
||||||
|
stroke-width="2"
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
>
|
||||||
|
<line x1="19" y1="12" x2="5" y2="12" />
|
||||||
|
<polyline points="12 19 5 12 12 5" />
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 290 B |
14
packages/hoppscotch-app/assets/icons/arrow-right.svg
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="24"
|
||||||
|
height="24"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
fill="none"
|
||||||
|
stroke="currentColor"
|
||||||
|
stroke-width="2"
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
>
|
||||||
|
<line x1="5" y1="12" x2="19" y2="12" />
|
||||||
|
<polyline points="12 5 19 12 12 19" />
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 291 B |
4
packages/hoppscotch-app/assets/icons/arrow-up-right.svg
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||||
|
<line x1="7" y1="17" x2="17" y2="7"></line>
|
||||||
|
<polyline points="7 7 17 7 17 17"></polyline>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 283 B |
4
packages/hoppscotch-app/assets/icons/arrow-up.svg
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||||
|
<line x1="12" y1="19" x2="12" y2="5"></line>
|
||||||
|
<polyline points="5 12 12 5 19 12"></polyline>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 284 B |
|
Before Width: | Height: | Size: 383 B After Width: | Height: | Size: 383 B |
|
Before Width: | Height: | Size: 571 B After Width: | Height: | Size: 571 B |
|
Before Width: | Height: | Size: 555 B After Width: | Height: | Size: 555 B |
|
Before Width: | Height: | Size: 378 B After Width: | Height: | Size: 378 B |
14
packages/hoppscotch-app/assets/icons/book-open.svg
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="24"
|
||||||
|
height="24"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
fill="none"
|
||||||
|
stroke="currentColor"
|
||||||
|
stroke-width="2"
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
>
|
||||||
|
<path d="M2 3h6a4 4 0 014 4v14a3 3 0 00-3-3H2z" />
|
||||||
|
<path d="M22 3h-6a4 4 0 00-4 4v14a3 3 0 013-3h7z" />
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 316 B |
14
packages/hoppscotch-app/assets/icons/book.svg
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="24"
|
||||||
|
height="24"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
fill="none"
|
||||||
|
stroke="currentColor"
|
||||||
|
stroke-width="2"
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
>
|
||||||
|
<path d="M4 19.5A2.5 2.5 0 016.5 17H20" />
|
||||||
|
<path d="M6.5 2H20v20H6.5A2.5 2.5 0 014 19.5v-15A2.5 2.5 0 016.5 2z" />
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 327 B |
15
packages/hoppscotch-app/assets/icons/box.svg
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="24"
|
||||||
|
height="24"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
fill="none"
|
||||||
|
stroke="currentColor"
|
||||||
|
stroke-width="2"
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
>
|
||||||
|
<path d="M21 16V8a2 2 0 00-1-1.73l-7-4a2 2 0 00-2 0l-7 4A2 2 0 003 8v8a2 2 0 001 1.73l7 4a2 2 0 002 0l7-4A2 2 0 0021 16z" />
|
||||||
|
<polyline points="3.27 6.96 12 12.01 20.73 6.96" />
|
||||||
|
<line x1="12" y1="22.08" x2="12" y2="12" />
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 435 B |
|
Before Width: | Height: | Size: 3.4 KiB After Width: | Height: | Size: 3.4 KiB |
|
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 1.9 KiB |
|
Before Width: | Height: | Size: 311 B After Width: | Height: | Size: 311 B |
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
|
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 1.6 KiB |
|
Before Width: | Height: | Size: 2.7 KiB After Width: | Height: | Size: 2.7 KiB |
|
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 1.6 KiB |
14
packages/hoppscotch-app/assets/icons/check-circle.svg
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="24"
|
||||||
|
height="24"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
fill="none"
|
||||||
|
stroke="currentColor"
|
||||||
|
stroke-width="2"
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
>
|
||||||
|
<path d="M22 11.08V12a10 10 0 11-5.93-9.14" />
|
||||||
|
<polyline points="22 4 12 14.01 9 11.01" />
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 303 B |
13
packages/hoppscotch-app/assets/icons/check.svg
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="24"
|
||||||
|
height="24"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
fill="none"
|
||||||
|
stroke="currentColor"
|
||||||
|
stroke-width="2"
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
>
|
||||||
|
<polyline points="20 6 9 17 4 12" />
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 247 B |
13
packages/hoppscotch-app/assets/icons/chevron-down.svg
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="24"
|
||||||
|
height="24"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
fill="none"
|
||||||
|
stroke="currentColor"
|
||||||
|
stroke-width="2"
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
>
|
||||||
|
<polyline points="6 9 12 15 18 9" />
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 247 B |
13
packages/hoppscotch-app/assets/icons/chevron-right.svg
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="24"
|
||||||
|
height="24"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
fill="none"
|
||||||
|
stroke="currentColor"
|
||||||
|
stroke-width="2"
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
>
|
||||||
|
<polyline points="9 18 15 12 9 6" />
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 247 B |
4
packages/hoppscotch-app/assets/icons/chevrons-down.svg
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||||
|
<polyline points="7 13 12 18 17 13"></polyline>
|
||||||
|
<polyline points="7 6 12 11 17 6"></polyline>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 286 B |
4
packages/hoppscotch-app/assets/icons/chevrons-up.svg
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||||
|
<polyline points="17 11 12 6 7 11"></polyline>
|
||||||
|
<polyline points="17 18 12 13 7 18"></polyline>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 287 B |
13
packages/hoppscotch-app/assets/icons/circle.svg
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="24"
|
||||||
|
height="24"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
fill="none"
|
||||||
|
stroke="currentColor"
|
||||||
|
stroke-width="2"
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
>
|
||||||
|
<circle cx="12" cy="12" r="10" />
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 244 B |
14
packages/hoppscotch-app/assets/icons/clipboard.svg
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="24"
|
||||||
|
height="24"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
fill="none"
|
||||||
|
stroke="currentColor"
|
||||||
|
stroke-width="2"
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
>
|
||||||
|
<path d="M16 4h2a2 2 0 012 2v14a2 2 0 01-2 2H6a2 2 0 01-2-2V6a2 2 0 012-2h2" />
|
||||||
|
<rect x="8" y="2" width="8" height="4" rx="1" ry="1" />
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 348 B |
14
packages/hoppscotch-app/assets/icons/clock.svg
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="24"
|
||||||
|
height="24"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
fill="none"
|
||||||
|
stroke="currentColor"
|
||||||
|
stroke-width="2"
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
>
|
||||||
|
<circle cx="12" cy="12" r="10" />
|
||||||
|
<polyline points="12 6 12 12 16 14" />
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 285 B |
13
packages/hoppscotch-app/assets/icons/cloud.svg
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="24"
|
||||||
|
height="24"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
fill="none"
|
||||||
|
stroke="currentColor"
|
||||||
|
stroke-width="2"
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
>
|
||||||
|
<path d="M17.5 19a4.5 4.5 0 100-9h-1.8A7 7 0 109 19h8.5z" />
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 271 B |
15
packages/hoppscotch-app/assets/icons/code-2.svg
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="24"
|
||||||
|
height="24"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
fill="none"
|
||||||
|
stroke="currentColor"
|
||||||
|
stroke-width="2"
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
>
|
||||||
|
<path d="M18 16l4-4-4-4" />
|
||||||
|
<path d="M6 8l-4 4 4 4" />
|
||||||
|
<path d="M14.5 4l-5 16" />
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 296 B |
14
packages/hoppscotch-app/assets/icons/columns.svg
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="24"
|
||||||
|
height="24"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
fill="none"
|
||||||
|
stroke="currentColor"
|
||||||
|
stroke-width="2"
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
>
|
||||||
|
<rect x="3" y="3" width="18" height="18" rx="2" ry="2" />
|
||||||
|
<line x1="12" y1="3" x2="12" y2="21" />
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 310 B |
14
packages/hoppscotch-app/assets/icons/copy.svg
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="24"
|
||||||
|
height="24"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
fill="none"
|
||||||
|
stroke="currentColor"
|
||||||
|
stroke-width="2"
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
>
|
||||||
|
<rect x="9" y="9" width="13" height="13" rx="2" ry="2" />
|
||||||
|
<path d="M5 15H4a2 2 0 01-2-2V4a2 2 0 012-2h9a2 2 0 012 2v1" />
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 334 B |
15
packages/hoppscotch-app/assets/icons/download.svg
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="24"
|
||||||
|
height="24"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
fill="none"
|
||||||
|
stroke="currentColor"
|
||||||
|
stroke-width="2"
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
>
|
||||||
|
<path d="M21 15v4a2 2 0 01-2 2H5a2 2 0 01-2-2v-4" />
|
||||||
|
<polyline points="7 10 12 15 17 10" />
|
||||||
|
<line x1="12" y1="15" x2="12" y2="3" />
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 346 B |
14
packages/hoppscotch-app/assets/icons/edit.svg
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="24"
|
||||||
|
height="24"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
fill="none"
|
||||||
|
stroke="currentColor"
|
||||||
|
stroke-width="2"
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
>
|
||||||
|
<path d="M11 4H4a2 2 0 00-2 2v14a2 2 0 002 2h14a2 2 0 002-2v-7" />
|
||||||
|
<path d="M18.5 2.5a2.121 2.121 0 013 3L12 15l-4 1 1-4 9.5-9.5z" />
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 346 B |
15
packages/hoppscotch-app/assets/icons/external-link.svg
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="24"
|
||||||
|
height="24"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
fill="none"
|
||||||
|
stroke="currentColor"
|
||||||
|
stroke-width="2"
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
>
|
||||||
|
<path d="M18 13v6a2 2 0 01-2 2H5a2 2 0 01-2-2V8a2 2 0 012-2h6" />
|
||||||
|
<polyline points="15 3 21 3 21 9" />
|
||||||
|
<line x1="10" y1="14" x2="21" y2="3" />
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 357 B |
14
packages/hoppscotch-app/assets/icons/eye-off.svg
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="24"
|
||||||
|
height="24"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
fill="none"
|
||||||
|
stroke="currentColor"
|
||||||
|
stroke-width="2"
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
>
|
||||||
|
<path d="M17.94 17.94A10.07 10.07 0 0112 20c-7 0-11-8-11-8a18.45 18.45 0 015.06-5.94M9.9 4.24A9.12 9.12 0 0112 4c7 0 11 8 11 8a18.5 18.5 0 01-2.16 3.19m-6.72-1.07a3 3 0 11-4.24-4.24" />
|
||||||
|
<line x1="1" y1="1" x2="23" y2="23" />
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 437 B |
14
packages/hoppscotch-app/assets/icons/eye.svg
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="24"
|
||||||
|
height="24"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
fill="none"
|
||||||
|
stroke="currentColor"
|
||||||
|
stroke-width="2"
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
>
|
||||||
|
<path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z" />
|
||||||
|
<circle cx="12" cy="12" r="3" />
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 303 B |
16
packages/hoppscotch-app/assets/icons/file-code.svg
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="24"
|
||||||
|
height="24"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
fill="none"
|
||||||
|
stroke="currentColor"
|
||||||
|
stroke-width="2"
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
>
|
||||||
|
<path d="M4 22h14a2 2 0 002-2V7.5L14.5 2H6a2 2 0 00-2 2v4" />
|
||||||
|
<path d="M14 2v6h6" />
|
||||||
|
<path d="M9 18l3-3-3-3" />
|
||||||
|
<path d="M5 12l-3 3 3 3" />
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 356 B |
16
packages/hoppscotch-app/assets/icons/file-plus.svg
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="24"
|
||||||
|
height="24"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
fill="none"
|
||||||
|
stroke="currentColor"
|
||||||
|
stroke-width="2"
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
>
|
||||||
|
<path d="M14.5 2H6a2 2 0 00-2 2v16a2 2 0 002 2h12a2 2 0 002-2V7.5L14.5 2z" />
|
||||||
|
<polyline points="14 2 14 8 20 8" />
|
||||||
|
<line x1="12" y1="18" x2="12" y2="12" />
|
||||||
|
<line x1="9" y1="15" x2="15" y2="15" />
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 412 B |
14
packages/hoppscotch-app/assets/icons/file.svg
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="24"
|
||||||
|
height="24"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
fill="none"
|
||||||
|
stroke="currentColor"
|
||||||
|
stroke-width="2"
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
>
|
||||||
|
<path d="M14.5 2H6a2 2 0 00-2 2v16a2 2 0 002 2h12a2 2 0 002-2V7.5L14.5 2z" />
|
||||||
|
<polyline points="14 2 14 8 20 8" />
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 327 B |
13
packages/hoppscotch-app/assets/icons/filter.svg
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="24"
|
||||||
|
height="24"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
fill="none"
|
||||||
|
stroke="currentColor"
|
||||||
|
stroke-width="2"
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
>
|
||||||
|
<polygon points="22 3 2 3 10 12.46 10 19 14 21 14 12.46 22 3"></polygon>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 283 B |
13
packages/hoppscotch-app/assets/icons/folder-open.svg
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="24"
|
||||||
|
height="24"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
fill="none"
|
||||||
|
stroke="currentColor"
|
||||||
|
stroke-width="2"
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
>
|
||||||
|
<path d="M6 17l2-5h14l-3 8a2 2 0 01-2 1H4a2 2 0 01-2-2V5a2 2 0 012-2h5l2 3h7a2 2 0 012 2v4" />
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 305 B |
15
packages/hoppscotch-app/assets/icons/folder-plus.svg
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="24"
|
||||||
|
height="24"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
fill="none"
|
||||||
|
stroke="currentColor"
|
||||||
|
stroke-width="2"
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
>
|
||||||
|
<path d="M22 19a2 2 0 01-2 2H4a2 2 0 01-2-2V5a2 2 0 012-2h5l2 3h9a2 2 0 012 2z" />
|
||||||
|
<line x1="12" y1="11" x2="12" y2="17" />
|
||||||
|
<line x1="9" y1="14" x2="15" y2="14" />
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 378 B |