chore: merge hoppscotch/main into hoppscotch/next

This commit is contained in:
Andrew Bastin
2024-08-23 15:05:01 +05:30
31 changed files with 819 additions and 701 deletions

View File

@@ -1,3 +1,8 @@
{
admin off
persist_config off
}
:3000 { :3000 {
try_files {path} / try_files {path} /
root * /site/selfhost-web root * /site/selfhost-web

View File

@@ -1,3 +1,8 @@
{
admin off
persist_config off
}
:3000 { :3000 {
respond 404 respond 404
} }

View File

@@ -1,3 +1,8 @@
{
admin off
persist_config off
}
:80 :3170 { :80 :3170 {
reverse_proxy localhost:8080 reverse_proxy localhost:8080
} }

View File

@@ -1,6 +1,6 @@
{ {
"name": "hoppscotch-backend", "name": "hoppscotch-backend",
"version": "2024.7.1", "version": "2024.7.2",
"description": "", "description": "",
"author": "", "author": "",
"private": true, "private": true,

File diff suppressed because it is too large Load Diff

View File

@@ -1,7 +1,7 @@
{ {
"name": "@hoppscotch/common", "name": "@hoppscotch/common",
"private": true, "private": true,
"version": "2024.7.1", "version": "2024.7.2",
"scripts": { "scripts": {
"dev": "pnpm exec npm-run-all -p -l dev:*", "dev": "pnpm exec npm-run-all -p -l dev:*",
"test": "vitest --run", "test": "vitest --run",

View File

@@ -1,26 +1,33 @@
<template> <template>
<div <div
class="flex flex-col py-2 px-4 w-72 relative border border-[#BCB78B] bg-[#FEFFD2] rounded-md text-[#7E7103]" class="flex flex-col p-[1px] w-72 relative border border-dividerDark bg-dividerLight rounded-md text-secondary border-animation overflow-hidden"
:class="{
'before:top-1/2 before:left-1/2 before:-translate-x-1/2 before:-translate-y-1/2 before:aspect-square before:w-full before:absolute before:rounded-md': true,
}"
> >
<button <div
class="absolute top-2 right-2 hover:text-black" class="overflow-hidden relative flex flex-1 bg-dividerLight px-4 py-2 rounded-md"
@click="$emit('close-toast')"
> >
<IconLucideX />
</button>
<div class="flex flex-col space-y-3">
<p class="leading-5 font-semibold">
{{ t("app.updated_text", { version: version }) }}
</p>
<button <button
class="flex items-center space-x-1 hover:underline" class="absolute top-2 right-2 hover:text-secondaryLight"
@click="openWhatsNew" @click="$emit('close-toast')"
> >
<span> <IconLucideX />
{{ t("app.see_whats_new") }}
</span>
<IconLucideArrowUpRight />
</button> </button>
<div class="flex flex-col space-y-3">
<p class="leading-5 font-semibold">
{{ t("app.updated_text", { version: version }) }}
</p>
<button
class="flex items-center space-x-1 hover:underline"
@click="openWhatsNew"
>
<span>
{{ t("app.see_whats_new") }}
</span>
<IconLucideArrowUpRight />
</button>
</div>
</div> </div>
</div> </div>
</template> </template>
@@ -44,3 +51,41 @@ const openWhatsNew = () => {
if (props.notesUrl) platform.io.openExternalLink(props.notesUrl) if (props.notesUrl) platform.io.openExternalLink(props.notesUrl)
} }
</script> </script>
<style>
/* Transition Classes */
.list-enter-active {
transition: all 1s ease;
}
.list-leave-active {
transition: all 0.4s ease;
}
.list-enter-from,
.list-leave-to {
opacity: 0;
transform: translateY(-30px);
}
.list-leave-active {
position: absolute;
}
/* Conic gradient */
.border-animation::before {
background: conic-gradient(
transparent 270deg,
var(--accent-dark-color),
transparent
);
animation: rotate 4s linear infinite;
}
@keyframes rotate {
from {
transform: translate(-50%, -50%) scale(1.4) rotate(0turn);
}
to {
transform: translate(-50%, -50%) scale(1.4) rotate(1turn);
}
}
</style>

View File

@@ -139,16 +139,27 @@ const workspace = workspaceService.currentWorkspace
// Switch to my environments if workspace is personal and to team environments if workspace is team // Switch to my environments if workspace is personal and to team environments if workspace is team
// also resets selected environment if workspace is personal and the previous selected environment was a team environment // also resets selected environment if workspace is personal and the previous selected environment was a team environment
watch(workspace, (newWorkspace) => { watch(workspace, (newWorkspace) => {
if (newWorkspace.type === "personal") { const { type: newWorkspaceType } = newWorkspace
if (newWorkspaceType === "personal") {
switchToMyEnvironments() switchToMyEnvironments()
if (selectedEnvironmentIndex.value.type !== "MY_ENV") { } else {
setSelectedEnvironmentIndex({
type: "NO_ENV_SELECTED",
})
}
} else if (newWorkspace.type === "team") {
updateSelectedTeam(newWorkspace) updateSelectedTeam(newWorkspace)
} }
const newTeamID =
newWorkspaceType === "team" ? newWorkspace.teamID : undefined
// Set active environment to the `No environment` state
// if navigating away from a team workspace
if (
selectedEnvironmentIndex.value.type === "TEAM_ENV" &&
selectedEnvironmentIndex.value.teamID !== newTeamID
) {
setSelectedEnvironmentIndex({
type: "NO_ENV_SELECTED",
})
}
}) })
watch( watch(

View File

@@ -143,7 +143,7 @@ watch(rawParamsBody, (newVal) => {
// propagate the edits from codemirror back to the body // propagate the edits from codemirror back to the body
watch(codemirrorValue, (updatedValue) => { watch(codemirrorValue, (updatedValue) => {
if (updatedValue && updatedValue !== rawParamsBody.value) { if (updatedValue !== undefined && updatedValue !== rawParamsBody.value) {
rawParamsBody.value = updatedValue rawParamsBody.value = updatedValue
} }
}) })

View File

@@ -70,9 +70,11 @@
:title="`${t( :title="`${t(
'action.send' 'action.send'
)} <kbd>${getSpecialKey()}</kbd><kbd>↩</kbd>`" )} <kbd>${getSpecialKey()}</kbd><kbd>↩</kbd>`"
:label="`${!loading ? t('action.send') : t('action.cancel')}`" :label="`${
!isTabResponseLoading ? t('action.send') : t('action.cancel')
}`"
class="min-w-[5rem] flex-1 rounded-r-none" class="min-w-[5rem] flex-1 rounded-r-none"
@click="!loading ? newSendRequest() : cancelRequest()" @click="!isTabResponseLoading ? newSendRequest() : cancelRequest()"
/> />
<span class="flex"> <span class="flex">
<tippy <tippy
@@ -238,7 +240,7 @@ import { useReadonlyStream, useStreamSubscriber } from "@composables/stream"
import { useToast } from "@composables/toast" import { useToast } from "@composables/toast"
import { useVModel } from "@vueuse/core" import { useVModel } from "@vueuse/core"
import * as E from "fp-ts/Either" import * as E from "fp-ts/Either"
import { Ref, computed, ref, onUnmounted } from "vue" import { computed, ref, onUnmounted } from "vue"
import { defineActionHandler, invokeAction } from "~/helpers/actions" import { defineActionHandler, invokeAction } from "~/helpers/actions"
import { runMutation } from "~/helpers/backend/GQLClient" import { runMutation } from "~/helpers/backend/GQLClient"
import { UpdateRequestDocument } from "~/helpers/backend/graphql" import { UpdateRequestDocument } from "~/helpers/backend/graphql"
@@ -302,6 +304,10 @@ const curlText = ref("")
const loading = ref(false) const loading = ref(false)
const isTabResponseLoading = computed(
() => tab.value.document.response?.type === "loading"
)
const showCurlImportModal = ref(false) const showCurlImportModal = ref(false)
const showCodegenModal = ref(false) const showCodegenModal = ref(false)
const showSaveRequestModal = ref(false) const showSaveRequestModal = ref(false)
@@ -318,8 +324,6 @@ const saveRequestAction = ref<any | null>(null)
const history = useReadonlyStream<RESTHistoryEntry[]>(restHistory$, []) const history = useReadonlyStream<RESTHistoryEntry[]>(restHistory$, [])
const requestCancelFunc: Ref<(() => void) | null> = ref(null)
const userHistories = computed(() => { const userHistories = computed(() => {
return history.value.map((history) => history.request.endpoint).slice(0, 10) return history.value.map((history) => history.request.endpoint).slice(0, 10)
}) })
@@ -351,7 +355,8 @@ const newSendRequest = async () => {
const [cancel, streamPromise] = runRESTRequest$(tab) const [cancel, streamPromise] = runRESTRequest$(tab)
const streamResult = await streamPromise const streamResult = await streamPromise
requestCancelFunc.value = cancel tab.value.document.cancelFunction = cancel
if (E.isRight(streamResult)) { if (E.isRight(streamResult)) {
subscribeToStream( subscribeToStream(
streamResult.right, streamResult.right,
@@ -441,7 +446,7 @@ onUnmounted(() => {
const cancelRequest = () => { const cancelRequest = () => {
loading.value = false loading.value = false
requestCancelFunc.value?.() tab.value.document.cancelFunction?.()
updateRESTResponse(null) updateRESTResponse(null)
} }

View File

@@ -16,6 +16,7 @@
v-if="properties?.includes('bodyParams') ?? true" v-if="properties?.includes('bodyParams') ?? true"
:id="'bodyParams'" :id="'bodyParams'"
:label="`${t('tab.body')}`" :label="`${t('tab.body')}`"
:indicator="isBodyFilled"
> >
<HttpBody <HttpBody
v-model:headers="request.headers" v-model:headers="request.headers"
@@ -154,6 +155,10 @@ const newActiveRequestVariablesCount = computed(() => {
return count ? count : null return count ? count : null
}) })
const isBodyFilled = computed(() => {
return Boolean(request.value.body.body && request.value.body.body.length > 0)
})
defineActionHandler("request.open-tab", ({ tab }) => { defineActionHandler("request.open-tab", ({ tab }) => {
selectedOptionTab.value = tab as RESTOptionTabs selectedOptionTab.value = tab as RESTOptionTabs
}) })

View File

@@ -43,6 +43,10 @@ export function useWhatsNewDialog() {
version: hoppscotchCommonPkgVersion, version: hoppscotchCommonPkgVersion,
}, },
position: "bottom-left", position: "bottom-left",
style: {
bottom: "15px",
left: "30px",
},
duration: Infinity, duration: Infinity,
}) })
} }

View File

@@ -87,4 +87,9 @@ export type HoppRESTDocument = {
* (if any) * (if any)
*/ */
inheritedProperties?: HoppInheritedProperty inheritedProperties?: HoppInheritedProperty
/**
* The function responsible for cancelling the tab request call
*/
cancelFunction?: () => void
} }

View File

@@ -539,6 +539,7 @@ export const REST_TAB_STATE_SCHEMA = z
responseTabPreference: z.optional(z.string()), responseTabPreference: z.optional(z.string()),
optionTabPreference: z.optional(z.enum(validRestOperations)), optionTabPreference: z.optional(z.enum(validRestOperations)),
inheritedProperties: z.optional(HoppInheritedPropertySchema), inheritedProperties: z.optional(HoppInheritedPropertySchema),
cancelFunction: z.optional(z.function()),
}) })
.strict(), .strict(),
}) })

View File

@@ -1,6 +1,5 @@
import { Service } from "dioc" import { Service } from "dioc"
import { reactive } from "vue" import { reactive, computed } from "vue"
import { computed } from "vue"
/** /**
* Defines a secret environment variable. * Defines a secret environment variable.

View File

@@ -1,7 +1,7 @@
{ {
"name": "@hoppscotch/selfhost-desktop", "name": "@hoppscotch/selfhost-desktop",
"private": true, "private": true,
"version": "2024.7.1", "version": "2024.7.2",
"type": "module", "type": "module",
"scripts": { "scripts": {
"dev:vite": "vite", "dev:vite": "vite",

View File

@@ -1296,7 +1296,7 @@ dependencies = [
[[package]] [[package]]
name = "hoppscotch-desktop" name = "hoppscotch-desktop"
version = "24.7.1" version = "24.7.2"
dependencies = [ dependencies = [
"cocoa 0.25.0", "cocoa 0.25.0",
"dashmap", "dashmap",

View File

@@ -1,6 +1,6 @@
[package] [package]
name = "hoppscotch-desktop" name = "hoppscotch-desktop"
version = "24.7.1" version = "24.7.2"
description = "A Tauri App" description = "A Tauri App"
authors = ["you"] authors = ["you"]
license = "" license = ""

View File

@@ -8,7 +8,7 @@
}, },
"package": { "package": {
"productName": "Hoppscotch", "productName": "Hoppscotch",
"version": "24.7.1" "version": "24.7.2"
}, },
"tauri": { "tauri": {
"allowlist": { "allowlist": {

View File

@@ -80,7 +80,7 @@ export const getSyncInitFunction = <T extends DispatchingStore<any, any>>(
) )
} }
stopSubscriptions = startSubscriptions() stopSubscriptions = startSubscriptions?.()
} }
function stopListeningToSubscriptions() { function stopListeningToSubscriptions() {
@@ -90,7 +90,7 @@ export const getSyncInitFunction = <T extends DispatchingStore<any, any>>(
) )
} }
stopSubscriptions() stopSubscriptions?.()
} }
return { return {

View File

@@ -9,9 +9,18 @@ import { updateUserSettings } from "./settings.api"
export const settingsSyncDefinition: StoreSyncDefinitionOf< export const settingsSyncDefinition: StoreSyncDefinitionOf<
typeof settingsStore typeof settingsStore
> = { > = {
toggleSetting() {
updateUserSettings(JSON.stringify(settingsStore.value))
},
toggleNestedSetting() {
updateUserSettings(JSON.stringify(settingsStore.value))
},
applySetting() { applySetting() {
updateUserSettings(JSON.stringify(settingsStore.value)) updateUserSettings(JSON.stringify(settingsStore.value))
}, },
applyNestedSetting() {
updateUserSettings(JSON.stringify(settingsStore.value))
},
} }
export const settingsSyncer = getSyncInitFunction( export const settingsSyncer = getSyncInitFunction(

View File

@@ -1,3 +1,8 @@
{
admin off
persist_config off
}
:8080 { :8080 {
try_files {path} / try_files {path} /
root * /site root * /site

View File

@@ -1,7 +1,7 @@
{ {
"name": "@hoppscotch/selfhost-web", "name": "@hoppscotch/selfhost-web",
"private": true, "private": true,
"version": "2024.7.1", "version": "2024.7.2",
"type": "module", "type": "module",
"scripts": { "scripts": {
"dev:vite": "vite", "dev:vite": "vite",

View File

@@ -1,3 +1,8 @@
{
admin off
persist_config off
}
:80 :3000 { :80 :3000 {
try_files {path} / try_files {path} /
root * /site/selfhost-web root * /site/selfhost-web

View File

@@ -80,7 +80,7 @@ export const getSyncInitFunction = <T extends DispatchingStore<any, any>>(
) )
} }
stopSubscriptions = startSubscriptions() stopSubscriptions = startSubscriptions?.()
} }
function stopListeningToSubscriptions() { function stopListeningToSubscriptions() {
@@ -90,7 +90,7 @@ export const getSyncInitFunction = <T extends DispatchingStore<any, any>>(
) )
} }
stopSubscriptions() stopSubscriptions?.()
} }
return { return {

View File

@@ -9,9 +9,18 @@ import { updateUserSettings } from "./settings.api"
export const settingsSyncDefinition: StoreSyncDefinitionOf< export const settingsSyncDefinition: StoreSyncDefinitionOf<
typeof settingsStore typeof settingsStore
> = { > = {
toggleSetting() {
updateUserSettings(JSON.stringify(settingsStore.value))
},
toggleNestedSetting() {
updateUserSettings(JSON.stringify(settingsStore.value))
},
applySetting() { applySetting() {
updateUserSettings(JSON.stringify(settingsStore.value)) updateUserSettings(JSON.stringify(settingsStore.value))
}, },
applyNestedSetting() {
updateUserSettings(JSON.stringify(settingsStore.value))
},
} }
export const settingsSyncer = getSyncInitFunction( export const settingsSyncer = getSyncInitFunction(

View File

@@ -1,3 +1,8 @@
{
admin off
persist_config off
}
:8080 { :8080 {
try_files {path} / try_files {path} /
root * /site root * /site

View File

@@ -1,7 +1,7 @@
{ {
"name": "hoppscotch-sh-admin", "name": "hoppscotch-sh-admin",
"private": true, "private": true,
"version": "2024.7.1", "version": "2024.7.2",
"type": "module", "type": "module",
"scripts": { "scripts": {
"dev": "pnpm exec npm-run-all -p -l dev:*", "dev": "pnpm exec npm-run-all -p -l dev:*",

View File

@@ -1,3 +1,8 @@
{
admin off
persist_config off
}
:80 :3100 { :80 :3100 {
try_files {path} / try_files {path} /
root * /site/sh-admin-multiport-setup root * /site/sh-admin-multiport-setup

View File

@@ -1,3 +1,8 @@
{
admin off
persist_config off
}
:80 :3100 { :80 :3100 {
handle_path /admin* { handle_path /admin* {
root * /site/sh-admin-subpath-access root * /site/sh-admin-subpath-access

View File

@@ -27,11 +27,9 @@ FROM node:20-alpine3.19 AS backend
RUN apk add caddy RUN apk add caddy
RUN npm install -g pnpm RUN npm install -g pnpm
RUN addgroup -S hoppgroup && adduser -S hoppuser -G hoppgroup
COPY --from=base_builder /usr/src/app/packages/hoppscotch-backend/backend.Caddyfile /etc/caddy/backend.Caddyfile COPY --from=base_builder /usr/src/app/packages/hoppscotch-backend/backend.Caddyfile /etc/caddy/backend.Caddyfile
COPY --from=backend_builder --chown=hoppuser:hoppgroup --chmod=755 /dist/backend /dist/backend COPY --from=backend_builder /dist/backend /dist/backend
COPY --from=base_builder --chown=hoppuser:hoppgroup --chmod=755 /usr/src/app/packages/hoppscotch-backend/prod_run.mjs /dist/backend COPY --from=base_builder /usr/src/app/packages/hoppscotch-backend/prod_run.mjs /dist/backend
# Remove the env file to avoid backend copying it in and using it # Remove the env file to avoid backend copying it in and using it
ENV PRODUCTION="true" ENV PRODUCTION="true"
@@ -39,8 +37,6 @@ ENV PORT=8080
ENV APP_PORT=${PORT} ENV APP_PORT=${PORT}
ENV DB_URL=${DATABASE_URL} ENV DB_URL=${DATABASE_URL}
USER hoppuser
WORKDIR /dist/backend WORKDIR /dist/backend
CMD ["node", "prod_run.mjs"] CMD ["node", "prod_run.mjs"]
@@ -52,18 +48,14 @@ WORKDIR /usr/src/app/packages/hoppscotch-selfhost-web
RUN pnpm run generate RUN pnpm run generate
FROM caddy:2-alpine AS app FROM caddy:2-alpine AS app
RUN addgroup -S hoppgroup && adduser -S hoppuser -G hoppgroup COPY --from=fe_builder /usr/src/app/packages/hoppscotch-selfhost-web/prod_run.mjs /site/prod_run.mjs
COPY --from=fe_builder /usr/src/app/packages/hoppscotch-selfhost-web/selfhost-web.Caddyfile /etc/caddy/selfhost-web.Caddyfile
COPY --from=fe_builder --chown=hoppuser:hoppgroup --chmod=755 /usr/src/app/packages/hoppscotch-selfhost-web/prod_run.mjs /site/prod_run.mjs COPY --from=fe_builder /usr/src/app/packages/hoppscotch-selfhost-web/dist/ /site/selfhost-web
COPY --from=fe_builder --chown=hoppuser:hoppgroup --chmod=755 /usr/src/app/packages/hoppscotch-selfhost-web/selfhost-web.Caddyfile /etc/caddy/selfhost-web.Caddyfile
COPY --from=fe_builder --chown=hoppuser:hoppgroup --chmod=755 /usr/src/app/packages/hoppscotch-selfhost-web/dist/ /site/selfhost-web
RUN apk add nodejs npm RUN apk add nodejs npm
RUN npm install -g @import-meta-env/cli RUN npm install -g @import-meta-env/cli
USER hoppuser
EXPOSE 80 EXPOSE 80
EXPOSE 3000 EXPOSE 3000
@@ -78,20 +70,17 @@ RUN pnpm run build --outDir dist-multiport-setup
RUN pnpm run build --outDir dist-subpath-access --base /admin/ RUN pnpm run build --outDir dist-subpath-access --base /admin/
FROM caddy:2-alpine AS sh_admin FROM caddy:2-alpine AS sh_admin
RUN addgroup -S hoppgroup && adduser -S hoppuser -G hoppgroup
COPY --from=sh_admin_builder --chown=hoppuser:hoppgroup --chmod=755 /usr/src/app/packages/hoppscotch-sh-admin/prod_run.mjs /site/prod_run.mjs COPY --from=sh_admin_builder /usr/src/app/packages/hoppscotch-sh-admin/prod_run.mjs /site/prod_run.mjs
COPY --from=sh_admin_builder --chown=hoppuser:hoppgroup --chmod=755 /usr/src/app/packages/hoppscotch-sh-admin/sh-admin-multiport-setup.Caddyfile /etc/caddy/sh-admin-multiport-setup.Caddyfile COPY --from=sh_admin_builder /usr/src/app/packages/hoppscotch-sh-admin/sh-admin-multiport-setup.Caddyfile /etc/caddy/sh-admin-multiport-setup.Caddyfile
COPY --from=sh_admin_builder --chown=hoppuser:hoppgroup --chmod=755 /usr/src/app/packages/hoppscotch-sh-admin/sh-admin-subpath-access.Caddyfile /etc/caddy/sh-admin-subpath-access.Caddyfile COPY --from=sh_admin_builder /usr/src/app/packages/hoppscotch-sh-admin/sh-admin-subpath-access.Caddyfile /etc/caddy/sh-admin-subpath-access.Caddyfile
COPY --from=sh_admin_builder --chown=hoppuser:hoppgroup --chmod=755 /usr/src/app/packages/hoppscotch-sh-admin/dist-multiport-setup /site/sh-admin-multiport-setup COPY --from=sh_admin_builder /usr/src/app/packages/hoppscotch-sh-admin/dist-multiport-setup /site/sh-admin-multiport-setup
COPY --from=sh_admin_builder --chown=hoppuser:hoppgroup --chmod=755 /usr/src/app/packages/hoppscotch-sh-admin/dist-subpath-access /site/sh-admin-subpath-access COPY --from=sh_admin_builder /usr/src/app/packages/hoppscotch-sh-admin/dist-subpath-access /site/sh-admin-subpath-access
RUN apk add nodejs npm RUN apk add nodejs npm
RUN npm install -g @import-meta-env/cli RUN npm install -g @import-meta-env/cli
USER hoppuser
EXPOSE 80 EXPOSE 80
EXPOSE 3100 EXPOSE 3100
@@ -113,26 +102,22 @@ RUN apk add tini curl
RUN npm install -g pnpm RUN npm install -g pnpm
RUN addgroup -S hoppgroup && adduser -S hoppuser -G hoppgroup
# Copy necessary files # Copy necessary files
# Backend files # Backend files
COPY --from=base_builder --chown=hoppuser:hoppgroup --chmod=755 /usr/src/app/packages/hoppscotch-backend/backend.Caddyfile /etc/caddy/backend.Caddyfile COPY --from=base_builder /usr/src/app/packages/hoppscotch-backend/backend.Caddyfile /etc/caddy/backend.Caddyfile
COPY --from=backend_builder --chown=hoppuser:hoppgroup --chmod=755 /dist/backend /dist/backend COPY --from=backend_builder /dist/backend /dist/backend
COPY --from=base_builder --chown=hoppuser:hoppgroup --chmod=755 /usr/src/app/packages/hoppscotch-backend/prod_run.mjs /dist/backend COPY --from=base_builder /usr/src/app/packages/hoppscotch-backend/prod_run.mjs /dist/backend
# FE Files # FE Files
COPY --from=base_builder --chown=hoppuser:hoppgroup --chmod=755 /usr/src/app/aio_run.mjs /usr/src/app/aio_run.mjs COPY --from=base_builder /usr/src/app/aio_run.mjs /usr/src/app/aio_run.mjs
COPY --from=fe_builder --chown=hoppuser:hoppgroup --chmod=755 /usr/src/app/packages/hoppscotch-selfhost-web/dist /site/selfhost-web COPY --from=fe_builder /usr/src/app/packages/hoppscotch-selfhost-web/dist /site/selfhost-web
COPY --from=sh_admin_builder --chown=hoppuser:hoppgroup --chmod=755 /usr/src/app/packages/hoppscotch-sh-admin/dist-multiport-setup /site/sh-admin-multiport-setup COPY --from=sh_admin_builder /usr/src/app/packages/hoppscotch-sh-admin/dist-multiport-setup /site/sh-admin-multiport-setup
COPY --from=sh_admin_builder --chown=hoppuser:hoppgroup --chmod=755 /usr/src/app/packages/hoppscotch-sh-admin/dist-subpath-access /site/sh-admin-subpath-access COPY --from=sh_admin_builder /usr/src/app/packages/hoppscotch-sh-admin/dist-subpath-access /site/sh-admin-subpath-access
COPY aio-multiport-setup.Caddyfile /etc/caddy/aio-multiport-setup.Caddyfile COPY aio-multiport-setup.Caddyfile /etc/caddy/aio-multiport-setup.Caddyfile
COPY aio-subpath-access.Caddyfile /etc/caddy/aio-subpath-access.Caddyfile COPY aio-subpath-access.Caddyfile /etc/caddy/aio-subpath-access.Caddyfile
RUN npm install -g @import-meta-env/cli RUN npm install -g @import-meta-env/cli
USER hoppuser
ENTRYPOINT [ "tini", "--" ] ENTRYPOINT [ "tini", "--" ]
COPY --chmod=755 healthcheck.sh . COPY --chmod=755 healthcheck.sh .
HEALTHCHECK --interval=2s CMD /bin/sh ./healthcheck.sh HEALTHCHECK --interval=2s CMD /bin/sh ./healthcheck.sh