diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index f90b1db81cf48ab5df465acf4e715eaa5c49c14b..557a9e3168dfd2c7116064300e8aff7036dd74d6 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -3,8 +3,7 @@ stages:
- replay-and-sync
- test
- test-report-aggregate
- - deploy-mainnet
- - deploy-mirrornet
+ - deploy
- publish
- cleanup
@@ -97,12 +96,38 @@ mirrornet-haf-binaries-extraction:
- public-runner-docker
- hived-for-tests
-docker-build-auth:
- extends: .docker_build_template
+# helper job just to prepare extended version of production image additionally holding .env file specific to test environment
+.docker-build-testenv-image:
+ extends: .docker_image_builder_job_template
variables:
- TURBO_APP_SCOPE: '@hive/auth'
- TURBO_APP_PATH: '/apps/auth'
- TURBO_APP_NAME: 'auth'
+ TURBO_APP_NAME: ""
+ BASE_IMAGE_NAME: ""
+ ENV_FILE_PATHNAME: "./apps/${TURBO_APP_NAME}/.env.testing"
+ IMAGE_SUFFIX: "testenv"
+ script:
+ - |
+ echo -e "\e[0Ksection_start:$(date +%s):login[collapsed=true]\r\e[0KLogging to Docker registry..."
+ docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY
+ echo -e "\e[0Ksection_end:$(date +%s):login\r\e[0K"
+
+ export NEW_IMAGE_TAGNAME="${CI_REGISTRY_IMAGE}/${TURBO_APP_NAME}-${IMAGE_SUFFIX}:${CI_COMMIT_SHA}"
+
+ docker buildx build \
+ --push \
+ -t "${NEW_IMAGE_TAGNAME}" -f- . << EOF
+ FROM $BASE_IMAGE_NAME AS production
+ COPY "${ENV_FILE_PATHNAME}" /app/apps/.env
+ EOF
+ echo "DENSER_${TURBO_APP_NAME^^}_IMAGE_NAME=${NEW_IMAGE_TAGNAME}" > docker-build-testenv-${TURBO_APP_NAME}-image.env
+ artifacts:
+ paths:
+ - docker-build-testenv-${TURBO_APP_NAME}-image.env
+ reports:
+ dotenv: docker-build-testenv-${TURBO_APP_NAME}-image.env
+ when: always # This ensures artifacts are created even if job fails
+ tags:
+ - public-runner-docker
+ - hived-for-tests
docker-build-blog:
extends: .docker_build_template
@@ -118,6 +143,42 @@ docker-build-wallet:
TURBO_APP_PATH: '/apps/wallet'
TURBO_APP_NAME: 'wallet'
+docker-build-blog-testenv:
+ extends: .docker-build-testenv-image
+ needs:
+ - docker-build-blog
+ variables:
+ TURBO_APP_NAME: 'blog'
+ BASE_IMAGE_NAME: ${BLOG_IMAGE_NAME}
+
+docker-build-wallet-testenv:
+ extends: .docker-build-testenv-image
+ needs:
+ - docker-build-wallet
+ variables:
+ TURBO_APP_NAME: 'wallet'
+ BASE_IMAGE_NAME: ${WALLET_IMAGE_NAME}
+
+docker-build-blog-mirrornet-testenv:
+ extends: .docker-build-testenv-image
+ needs:
+ - docker-build-blog
+ variables:
+ TURBO_APP_NAME: 'blog'
+ BASE_IMAGE_NAME: ${BLOG_IMAGE_NAME}
+ ENV_FILE_PATHNAME: "./apps/${TURBO_APP_NAME}/.env.mirrornet-testing"
+ IMAGE_SUFFIX: "mirrornet-testenv"
+
+docker-build-wallet-mirrornet-testenv:
+ extends: .docker-build-testenv-image
+ needs:
+ - docker-build-wallet
+ variables:
+ TURBO_APP_NAME: 'wallet'
+ BASE_IMAGE_NAME: ${WALLET_IMAGE_NAME}
+ ENV_FILE_PATHNAME: "./apps/${TURBO_APP_NAME}/.env.mirrornet-testing"
+ IMAGE_SUFFIX: "mirrornet-testenv"
+
# Hived binary built as a part of HAF requires an additional
# library to function. This library has to be extracted from
# the image and passed to job extended_block_log_creation.
@@ -253,6 +314,7 @@ mirrornet-haf-node-replay:
FF_NETWORK_PER_BUILD: 1
REACT_APP_API_ENDPOINT: https://api.hive.blog
REACT_APP_IMAGES_ENDPOINT: https://images.hive.blog/
+ DENSER_SERVER_ENV_DUMP: true
DENSER_URL: https://caddy
parallel:
matrix:
@@ -288,16 +350,15 @@ mirrornet-based-tests:
- .node-job
needs:
- mirrornet-haf-binaries-extraction
- - docker-build-auth
- - docker-build-blog
- - docker-build-wallet
+ - docker-build-blog-mirrornet-testenv
+ - docker-build-wallet-mirrornet-testenv
- mirrornet-replay-data-copy
- block_log_processing
image: 'mcr.microsoft.com/playwright:${PLAYWRIGHT_TAG}'
allow_failure: true
services:
- !reference [.haf_api_node_test, services]
- - name: $BLOG_IMAGE_NAME
+ - name: $DENSER_BLOG_IMAGE_NAME
alias: denser-blog
variables:
HEALTHCHECK_TCP_PORT: '3000'
@@ -314,7 +375,7 @@ mirrornet-based-tests:
- --from=https://caddy-blog
- --to=denser-blog:3000
- --internal-certs
- - name: $WALLET_IMAGE_NAME
+ - name: $DENSER_WALLET_IMAGE_NAME
alias: denser-wallet
variables:
HEALTHCHECK_TCP_PORT: '4000'
@@ -331,22 +392,6 @@ mirrornet-based-tests:
- --from=https://caddy-wallet
- --to=denser-wallet:4000
- --internal-certs
- - name: $AUTH_IMAGE_NAME
- alias: denser-auth
- variables:
- HEALTHCHECK_TCP_PORT: '5000'
- PORT: '5000'
- REACT_APP_SITE_DOMAIN: 'https://caddy-auth.local'
- TURBO_APP_SCOPE: '@hive/auth'
- TURBO_APP_PATH: '/apps/auth'
- - name: caddy:${CADDY_TAG}
- alias: caddy-auth
- command:
- - caddy
- - reverse-proxy
- - --from=https://caddy-auth
- - --to=denser-auth:5000
- - --internal-certs
variables:
GIT_STRATEGY: 'clone'
CI_DEBUG_SERVICES: 'false'
@@ -372,23 +417,25 @@ mirrornet-based-tests:
- '*.log'
- 'logs/'
- '*.env'
- - 'playwright-report/'
- - 'test-results/'
- - 'junit/'
+ - './apps/blog/playwright-report/'
+ - './apps/blog/test-results/'
+ - './apps/blog/junit/'
reports:
- junit: 'junit/results.xml'
+ junit: 'apps/blog/junit/results.xml'
tags:
- data-cache-storage
e2e-tests-blog:
extends: .e2e_tests_template
needs:
- - docker-build-blog
+ - docker-build-blog-testenv
+
services:
- - name: $BLOG_IMAGE_NAME
+ - name: $DENSER_BLOG_IMAGE_NAME
alias: denser
variables:
HEALTHCHECK_TCP_PORT: '3000'
+
- name: caddy:${CADDY_TAG}
command:
- caddy
@@ -404,12 +451,14 @@ e2e-tests-blog:
e2e-tests-wallet:
extends: .e2e_tests_template
needs:
- - docker-build-wallet
+ - docker-build-wallet-testenv
+
services:
- - name: $WALLET_IMAGE_NAME
+ - name: $DENSER_WALLET_IMAGE_NAME
alias: denser
variables:
HEALTHCHECK_TCP_PORT: '4000'
+
- name: caddy:${CADDY_TAG}
command:
- caddy
@@ -492,9 +541,9 @@ publish:
tags:
- public-runner-docker
-.deploy_template_mainnet:
+.deploy_template:
extends: .job-defaults
- stage: deploy-mainnet
+ stage: deploy
before_script:
- |
echo -e "\e[0Ksection_start:$(date +%s):login[collapsed=true]\r\e[0KLogging to Docker registry..."
@@ -502,70 +551,31 @@ publish:
echo -e "\e[0Ksection_end:$(date +%s):login\r\e[0K"
script:
- |
+ # credits of solution for gitlab bug: https://gitlab.com/gitlab-org/gitlab/-/issues/294292#note_1070210709
+ export DEPLOYMENT_ENV_FILE=${!DEPLOYMENT_ENV_FILE}
+ # Make visible all vars in the bash env
+ source "${DEPLOYMENT_ENV_FILE}"
+
scripts/run_instance.sh \
--image="$IMAGE_NAME" \
- --app-scope="$TURBO_APP_SCOPE" \
- --app-path="$TURBO_APP_PATH" \
- --api-endpoint="https://api.hive.blog" \
- --chain-id="beeab0de00000000000000000000000000000000000000000000000000000000" \
- --images-endpoint="https://images.hive.blog/" \
--name="$CONTAINER_NAME" \
--port=$PORT \
+ --env-file="${DEPLOYMENT_ENV_FILE}" \
--detach
tags:
- hs-denser
-.deploy_template_mirrornet:
- extends: .deploy_template_mainnet
- stage: deploy-mirrornet
- script:
- - |
- scripts/run_instance.sh \
- --image="$IMAGE_NAME" \
- --app-scope="$TURBO_APP_SCOPE" \
- --app-path="$TURBO_APP_PATH" \
- --api-endpoint="https://api.fake.openhive.network/" \
- --chain-id="42" \
- --images-endpoint="https://images.hive.blog/" \
- --name="$CONTAINER_NAME" \
- --port=$PORT \
- --detach
-
# Main branch deployments (manual)
-main:deploy-auth-mainnet:
- extends: .deploy_template_mainnet
- needs:
- - docker-build-auth
- variables:
- CONTAINER_NAME: denser-main-auth
- PORT: 9133
- TURBO_APP_SCOPE: '@hive/auth'
- TURBO_APP_PATH: '/apps/auth'
- SITE_DOMAIN: https://auth.openhive.network
- EXPLORER_DOMAIN: https://explore.openhive.network
- IMAGE_NAME: $AUTH_IMAGE_NAME
- rules:
- - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
- when: manual
- environment:
- name: main-auth-mainnet
- url: https://auth.openhive.network
- on_stop: main:stop-auth-mainnet
-
main:deploy-blog-mainnet:
- extends: .deploy_template_mainnet
+ extends: .deploy_template
needs:
- docker-build-blog
- e2e-tests-blog
variables:
CONTAINER_NAME: denser-main-blog
PORT: 9111
- TURBO_APP_SCOPE: '@hive/blog'
- TURBO_APP_PATH: '/apps/blog'
- SITE_DOMAIN: https://blog.openhive.network
- WALLET_ENDPOINT: https://wallet.openhive.network
- EXPLORER_DOMAIN: https://explore.openhive.network
IMAGE_NAME: $BLOG_IMAGE_NAME
+ DEPLOYMENT_ENV_FILE: "MAINNET_PROD_DEPLOYMENT_ENV"
rules:
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
when: manual
@@ -575,19 +585,15 @@ main:deploy-blog-mainnet:
on_stop: main:stop-blog-mainnet
main:deploy-wallet-mainnet:
- extends: .deploy_template_mainnet
+ extends: .deploy_template
needs:
- docker-build-wallet
- e2e-tests-wallet
variables:
CONTAINER_NAME: denser-main-wallet
PORT: 9122
- TURBO_APP_SCOPE: '@hive/wallet'
- TURBO_APP_PATH: '/apps/wallet'
- SITE_DOMAIN: https://wallet.openhive.network
- BLOG_DOMAIN: https://blog.openhive.network
- EXPLORER_DOMAIN: https://explore.openhive.network
IMAGE_NAME: $WALLET_IMAGE_NAME
+ DEPLOYMENT_ENV_FILE: "MAINNET_PROD_DEPLOYMENT_ENV"
rules:
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
when: manual
@@ -596,28 +602,8 @@ main:deploy-wallet-mainnet:
url: https://wallet.openhive.network
on_stop: main:stop-wallet-mainnet
-main:deploy-auth-mirrornet:
- extends: .deploy_template_mirrornet
- needs:
- - docker-build-auth
- variables:
- CONTAINER_NAME: denser-main-auth-mirror
- PORT: 9233
- TURBO_APP_SCOPE: '@hive/auth'
- TURBO_APP_PATH: '/apps/auth'
- SITE_DOMAIN: https://auth.fake.openhive.network
- EXPLORER_DOMAIN: https://testexplorer.openhive.network
- IMAGE_NAME: $AUTH_IMAGE_NAME
- rules:
- - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
- when: manual
- environment:
- name: main-auth-mirrornet
- url: https://auth.fake.openhive.network
- on_stop: main:stop-auth-mirrornet
-
main:deploy-blog-mirrornet:
- extends: .deploy_template_mirrornet
+ extends: .deploy_template
needs:
- docker-build-blog
- e2e-tests-blog
@@ -639,7 +625,7 @@ main:deploy-blog-mirrornet:
on_stop: main:stop-blog-mirrornet
main:deploy-wallet-mirrornet:
- extends: .deploy_template_mirrornet
+ extends: .deploy_template
needs:
- docker-build-wallet
- e2e-tests-wallet
@@ -674,21 +660,6 @@ main:deploy-wallet-mirrornet:
- hs-denser
# Stop jobs for main deployments
-main:stop-auth-mainnet:
- extends: .stop_template
- needs:
- - job: main:deploy-auth-mainnet
- optional: true
- variables:
- CONTAINER_NAME: denser-main-auth
- rules:
- - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
- when: manual
- allow_failure: true
- environment:
- name: main-auth-mainnet
- action: stop
-
main:stop-blog-mainnet:
extends: .stop_template
needs:
@@ -719,21 +690,6 @@ main:stop-wallet-mainnet:
name: main-wallet-mainnet
action: stop
-main:stop-auth-mirrornet:
- extends: .stop_template
- needs:
- - job: main:deploy-auth-mirrornet
- optional: true
- variables:
- CONTAINER_NAME: denser-main-auth-mirror
- rules:
- - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
- when: manual
- allow_failure: true
- environment:
- name: main-auth-mirrornet
- action: stop
-
main:stop-blog-mirrornet:
extends: .stop_template
needs:
@@ -765,60 +721,34 @@ main:stop-wallet-mirrornet:
action: stop
# Develop branch deployments
-develop:deploy-auth-mainnet:
- extends: .deploy_template_mainnet
- needs:
- - docker-build-auth
- variables:
- CONTAINER_NAME: denser-dev-auth
- PORT: 8133
- TURBO_APP_SCOPE: '@hive/auth'
- TURBO_APP_PATH: '/apps/auth'
- SITE_DOMAIN: https://auth.dev.openhive.network
- EXPLORER_DOMAIN: https://explore.openhive.network
- IMAGE_NAME: $AUTH_IMAGE_NAME
- rules:
- - if: $CI_COMMIT_BRANCH == "develop"
- environment:
- name: develop-auth-mainnet
- url: https://auth.dev.openhive.network
- on_stop: develop:stop-auth-mainnet
develop:deploy-blog-mainnet:
- extends: .deploy_template_mainnet
+ extends: .deploy_template
needs:
- docker-build-blog
- e2e-tests-blog
variables:
CONTAINER_NAME: denser-dev-blog
PORT: 8111
- TURBO_APP_SCOPE: '@hive/blog'
- TURBO_APP_PATH: '/apps/blog'
- SITE_DOMAIN: https://blog.dev.openhive.network
- WALLET_ENDPOINT: https://wallet.dev.openhive.network
- EXPLORER_DOMAIN: https://explore.openhive.network
IMAGE_NAME: $BLOG_IMAGE_NAME
+ DEPLOYMENT_ENV_FILE: "MAINNET_DEV_DEPLOYMENT_ENV"
rules:
- - if: $CI_COMMIT_BRANCH == "develop"
+ - if: $CI_COMMIT_BRANCH == "bw_eliminate_private_secrets"
environment:
name: develop-blog-mainnet
url: https://blog.dev.openhive.network
on_stop: develop:stop-blog-mainnet
develop:deploy-wallet-mainnet:
- extends: .deploy_template_mainnet
+ extends: .deploy_template
needs:
- docker-build-wallet
- e2e-tests-wallet
variables:
CONTAINER_NAME: denser-dev-wallet
PORT: 8122
- TURBO_APP_SCOPE: '@hive/wallet'
- TURBO_APP_PATH: '/apps/wallet'
- SITE_DOMAIN: https://wallet.dev.openhive.network
- BLOG_DOMAIN: https://blog.dev.openhive.network
- EXPLORER_DOMAIN: https://explore.openhive.network
IMAGE_NAME: $WALLET_IMAGE_NAME
+ DEPLOYMENT_ENV_FILE: "MAINNET_DEV_DEPLOYMENT_ENV"
rules:
- if: $CI_COMMIT_BRANCH == "develop"
environment:
@@ -826,60 +756,33 @@ develop:deploy-wallet-mainnet:
url: https://wallet.dev.openhive.network
on_stop: develop:stop-wallet-mainnet
-develop:deploy-auth-mirrornet:
- extends: .deploy_template_mirrornet
- needs:
- - docker-build-auth
- variables:
- CONTAINER_NAME: denser-dev-auth-mirror
- PORT: 8233
- TURBO_APP_SCOPE: '@hive/auth'
- TURBO_APP_PATH: '/apps/auth'
- SITE_DOMAIN: https://auth.dev.fake.openhive.network
- EXPLORER_DOMAIN: https://testexplorer.openhive.network
- IMAGE_NAME: $AUTH_IMAGE_NAME
- rules:
- - if: $CI_COMMIT_BRANCH == "develop"
- environment:
- name: develop-auth-mirrornet
- url: https://auth.dev.fake.openhive.network
- on_stop: develop:stop-auth-mirrornet
-
develop:deploy-blog-mirrornet:
- extends: .deploy_template_mirrornet
+ extends: .deploy_template
needs:
- docker-build-blog
- e2e-tests-blog
variables:
CONTAINER_NAME: denser-dev-blog-mirror
PORT: 8211
- TURBO_APP_SCOPE: '@hive/blog'
- TURBO_APP_PATH: '/apps/blog'
- SITE_DOMAIN: https://blog.dev.fake.openhive.network
- WALLET_ENDPOINT: https://wallet.dev.fake.openhive.network
- EXPLORER_DOMAIN: https://testexplorer.openhive.network
IMAGE_NAME: $BLOG_IMAGE_NAME
+ DEPLOYMENT_ENV_FILE: "MIRRORNET_DEV_DEPLOYMENT_ENV"
rules:
- - if: $CI_COMMIT_BRANCH == "develop"
+ - if: $CI_COMMIT_BRANCH == "bw_eliminate_private_secrets"
environment:
name: develop-blog-mirrornet
url: https://blog.dev.fake.openhive.network
on_stop: develop:stop-blog-mirrornet
develop:deploy-wallet-mirrornet:
- extends: .deploy_template_mirrornet
+ extends: .deploy_template
needs:
- docker-build-wallet
- e2e-tests-wallet
variables:
CONTAINER_NAME: denser-dev-wallet-mirror
PORT: 8222
- TURBO_APP_SCOPE: '@hive/wallet'
- TURBO_APP_PATH: '/apps/wallet'
- SITE_DOMAIN: https://wallet.dev.fake.openhive.network
- BLOG_DOMAIN: https://blog.dev.fake.openhive.network
- EXPLORER_DOMAIN: https://testexplorer.openhive.network
IMAGE_NAME: $WALLET_IMAGE_NAME
+ DEPLOYMENT_ENV_FILE: "MIRRORNET_DEV_DEPLOYMENT_ENV"
rules:
- if: $CI_COMMIT_BRANCH == "develop"
environment:
@@ -888,20 +791,6 @@ develop:deploy-wallet-mirrornet:
on_stop: develop:stop-wallet-mirrornet
# Stop jobs for develop deployments
-develop:stop-auth-mainnet:
- extends: .stop_template
- needs:
- - job: develop:deploy-auth-mainnet
- optional: true
- variables:
- CONTAINER_NAME: denser-dev-auth
- rules:
- - if: $CI_COMMIT_BRANCH == "develop"
- when: manual
- allow_failure: true
- environment:
- name: develop-auth-mainnet
- action: stop
develop:stop-blog-mainnet:
extends: .stop_template
@@ -911,7 +800,7 @@ develop:stop-blog-mainnet:
variables:
CONTAINER_NAME: denser-dev-blog
rules:
- - if: $CI_COMMIT_BRANCH == "develop"
+ - if: $CI_COMMIT_BRANCH == "bw_eliminate_private_secrets"
when: manual
allow_failure: true
environment:
@@ -933,21 +822,6 @@ develop:stop-wallet-mainnet:
name: develop-wallet-mainnet
action: stop
-develop:stop-auth-mirrornet:
- extends: .stop_template
- needs:
- - job: develop:deploy-auth-mirrornet
- optional: true
- variables:
- CONTAINER_NAME: denser-dev-auth-mirror
- rules:
- - if: $CI_COMMIT_BRANCH == "develop"
- when: manual
- allow_failure: true
- environment:
- name: develop-auth-mirrornet
- action: stop
-
develop:stop-blog-mirrornet:
extends: .stop_template
needs:
diff --git a/Dockerfile b/Dockerfile
index be8a2c107f964b2129fa2543b8e9234edffe9c98..0239bdf93a57a712b0233dfcf30905f75cf8b5e5 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,102 +1,104 @@
-# syntax=docker/dockerfile:1.5
-FROM node:20.17-alpine AS base
-ENV PNPM_HOME="/pnpm"
-ENV PATH="$PNPM_HOME:$PATH"
-ENV TURBO_VERSION=2.1.1
-
-# Install and configure corepack/pnpm
-RUN apk add --no-cache libc6-compat && \
- corepack enable && \
- corepack prepare pnpm@9.6.0 --activate && \
- pnpm config set store-dir /pnpm/store
-
-FROM base AS builder
-ARG TURBO_APP_SCOPE
-RUN apk add --no-cache libc6-compat
-RUN apk update
-
-## Set working directory for an App
-WORKDIR /app
-COPY . .
-## prepare files only for docker and optimise
-RUN pnpm dlx turbo prune --scope=${TURBO_APP_SCOPE} --docker
-
-# Add lockfile and package.json's of isolated subworkspace
-# TODO: Remove python3 installation after getting rid of dhive
-FROM base AS installer
-ARG TURBO_APP_SCOPE
-RUN apk add --no-cache libc6-compat
-RUN apk update
-WORKDIR /app
-
-# First install the dependencies (as they change less often)
-COPY --from=builder /app/out/json/ .
-COPY --from=builder /app/out/pnpm-lock.yaml ./pnpm-lock.yaml
-RUN --mount=type=cache,id=pnpm,target=/pnpm/store pnpm install --frozen-lockfile
-
-# Build the project
-COPY --from=builder /app/out/full/ .
-RUN pnpm run lint
-RUN pnpm dlx turbo run build --filter=${TURBO_APP_SCOPE}
-
-FROM base AS runner
-ARG TURBO_APP_PATH
-ARG TURBO_APP_NAME
-ARG BUILD_TIME
-ARG GIT_COMMIT_SHA
-ARG GIT_CURRENT_BRANCH
-ARG GIT_LAST_LOG_MESSAGE
-ARG GIT_LAST_COMMITTER
-ARG GIT_LAST_COMMIT_DATE
-LABEL org.opencontainers.image.created="$BUILD_TIME"
-LABEL org.opencontainers.image.url="https://hive.io/"
-LABEL org.opencontainers.image.documentation="https://gitlab.syncad.com/hive/denser"
-LABEL org.opencontainers.image.source="https://gitlab.syncad.com/hive/denser"
-#LABEL org.opencontainers.image.version="${VERSION}"
-LABEL org.opencontainers.image.revision="$GIT_COMMIT_SHA"
-LABEL org.opencontainers.image.licenses="MIT"
-LABEL org.opencontainers.image.ref.name="Denser $TURBO_APP_NAME"
-LABEL org.opencontainers.image.title="Denser $TURBO_APP_NAME Image"
-LABEL org.opencontainers.image.description="Runs Denser $TURBO_APP_NAME application"
-LABEL io.hive.image.branch="$GIT_CURRENT_BRANCH"
-LABEL io.hive.image.commit.log_message="$GIT_LAST_LOG_MESSAGE"
-LABEL io.hive.image.commit.author="$GIT_LAST_COMMITTER"
-LABEL io.hive.image.commit.date="$GIT_LAST_COMMIT_DATE"
-
-WORKDIR /app
-RUN --mount=type=cache,id=pnpm,target=/pnpm/store pnpm add -g @beam-australia/react-env@3.1.1
-RUN apk add --no-cache tini
-# COPY --from=trajano/alpine-libfaketime:latest /faketime.so /lib/faketime.so
-
-# Don't run production as root
-RUN addgroup --system --gid 1001 nodejs
-RUN adduser --system --uid 1001 nextjs
-USER nextjs
-
-COPY --from=builder /app/docker/docker-entrypoint.sh .
-COPY --from=installer /app${TURBO_APP_PATH}/next.config.js .
-COPY --from=installer /app${TURBO_APP_PATH}/package.json .
-COPY --from=installer /app/node_modules ./node_modules
-COPY --from=installer /app/node_modules/@beam-australia/react-env ./node_modules/@beam-australia/react-env
-ENV PATH="/app/node_modules/.bin:$PATH"
-
-# Automatically leverage output traces to reduce image size
-# https://nextjs.org/docs/advanced-features/output-file-tracing
-COPY --from=installer --chown=nextjs:nodejs /app${TURBO_APP_PATH}/public .${TURBO_APP_PATH}/public
-COPY --from=installer --chown=nextjs:nodejs /app${TURBO_APP_PATH}/.next/standalone ./
-COPY --from=installer --chown=nextjs:nodejs /app${TURBO_APP_PATH}/.next/static .${TURBO_APP_PATH}/.next/static
-COPY --from=installer --chown=nextjs:nodejs /app${TURBO_APP_PATH}/.env* ./
-COPY --from=installer --chown=nextjs:nodejs /app${TURBO_APP_PATH}/li[b]/markdown[s]/ .${TURBO_APP_PATH}/lib/markdowns/
-
-ENV BLOG_PORT=3000
-ENV WALLET_PORT=4000
-ENV AUTH_PORT=5000
-
-# Expose ports 3000 and 4000 for the sake of GitLab CI healthcheck
-EXPOSE 3000 4000
-EXPOSE $BLOG_PORT
-EXPOSE $WALLET_PORT
-EXPOSE $AUTH_PORT
-
-ENTRYPOINT ["/sbin/tini", "--", "/app/docker-entrypoint.sh"]
-CMD node .${TURBO_APP_PATH}/server.js
\ No newline at end of file
+# syntax=docker/dockerfile:1.5
+FROM node:20.17-alpine AS base
+ENV PNPM_HOME="/pnpm"
+ENV PATH="$PNPM_HOME:$PATH"
+ENV TURBO_VERSION=2.1.1
+
+# Install and configure corepack/pnpm
+RUN apk add --no-cache libc6-compat && \
+ corepack enable && \
+ corepack prepare pnpm@10.0.0 --activate && \
+ pnpm config set store-dir /pnpm/store
+
+FROM base AS builder
+ARG TURBO_APP_SCOPE
+RUN apk add --no-cache libc6-compat
+RUN apk update
+
+## Set working directory for an App
+WORKDIR /app
+COPY . .
+## prepare files only for docker and optimise
+RUN pnpm dlx turbo prune --scope=${TURBO_APP_SCOPE} --docker
+
+# Add lockfile and package.json's of isolated subworkspace
+# TODO: Remove python3 installation after getting rid of dhive
+FROM base AS installer
+ARG TURBO_APP_SCOPE
+RUN apk add --no-cache libc6-compat
+RUN apk update
+WORKDIR /app
+
+# First install the dependencies (as they change less often)
+COPY --from=builder /app/out/json/ .
+COPY --from=builder /app/out/pnpm-lock.yaml ./pnpm-lock.yaml
+RUN --mount=type=cache,id=pnpm,target=/pnpm/store pnpm install --frozen-lockfile
+
+# Build the project
+COPY --from=builder /app/out/full/ .
+RUN pnpm run lint
+RUN pnpm dlx turbo run build --filter=${TURBO_APP_SCOPE}
+
+FROM base AS runner
+ARG TURBO_APP_PATH
+ARG TURBO_APP_NAME
+ENV TURBO_APP_PATH=${TURBO_APP_PATH}
+ENV TURBO_APP_NAME=${TURBO_APP_NAME}
+
+ARG BUILD_TIME
+ARG GIT_COMMIT_SHA
+ARG GIT_CURRENT_BRANCH
+ARG GIT_LAST_LOG_MESSAGE
+ARG GIT_LAST_COMMITTER
+ARG GIT_LAST_COMMIT_DATE
+LABEL org.opencontainers.image.created="$BUILD_TIME"
+LABEL org.opencontainers.image.url="https://hive.io/"
+LABEL org.opencontainers.image.documentation="https://gitlab.syncad.com/hive/denser"
+LABEL org.opencontainers.image.source="https://gitlab.syncad.com/hive/denser"
+#LABEL org.opencontainers.image.version="${VERSION}"
+LABEL org.opencontainers.image.revision="$GIT_COMMIT_SHA"
+LABEL org.opencontainers.image.licenses="MIT"
+LABEL org.opencontainers.image.ref.name="Denser $TURBO_APP_NAME"
+LABEL org.opencontainers.image.title="Denser $TURBO_APP_NAME Image"
+LABEL org.opencontainers.image.description="Runs Denser $TURBO_APP_NAME application"
+LABEL io.hive.image.branch="$GIT_CURRENT_BRANCH"
+LABEL io.hive.image.commit.log_message="$GIT_LAST_LOG_MESSAGE"
+LABEL io.hive.image.commit.author="$GIT_LAST_COMMITTER"
+LABEL io.hive.image.commit.date="$GIT_LAST_COMMIT_DATE"
+
+WORKDIR /app
+RUN --mount=type=cache,id=pnpm,target=/pnpm/store pnpm add -g @beam-australia/react-env@3.1.1
+RUN apk add --no-cache tini
+# COPY --from=trajano/alpine-libfaketime:latest /faketime.so /lib/faketime.so
+
+# Don't run production as root
+RUN addgroup --system --gid 1001 nodejs
+RUN adduser --system --uid 1001 nextjs
+USER nextjs
+
+COPY --from=builder /app/docker/docker-entrypoint.sh .
+COPY --from=installer /app${TURBO_APP_PATH}/next.config.js .
+COPY --from=installer /app${TURBO_APP_PATH}/package.json .
+COPY --from=installer /app/node_modules ./node_modules
+COPY --from=installer /app/node_modules/@beam-australia/react-env ./node_modules/@beam-australia/react-env
+ENV PATH="/app/node_modules/.bin:$PATH"
+
+# Automatically leverage output traces to reduce image size
+# https://nextjs.org/docs/advanced-features/output-file-tracing
+COPY --from=installer --chown=nextjs:nodejs /app${TURBO_APP_PATH}/public .${TURBO_APP_PATH}/public
+COPY --from=installer --chown=nextjs:nodejs /app${TURBO_APP_PATH}/.next/standalone ./
+COPY --from=installer --chown=nextjs:nodejs /app${TURBO_APP_PATH}/.next/static .${TURBO_APP_PATH}/.next/static
+COPY --from=installer --chown=nextjs:nodejs /app${TURBO_APP_PATH}/li[b]/markdown[s]/ .${TURBO_APP_PATH}/lib/markdowns/
+
+ENV BLOG_PORT=3000
+ENV WALLET_PORT=4000
+ENV AUTH_PORT=5000
+
+# Expose ports 3000 and 4000 for the sake of GitLab CI healthcheck
+EXPOSE 3000 4000
+EXPOSE $BLOG_PORT
+EXPOSE $WALLET_PORT
+EXPOSE $AUTH_PORT
+
+ENTRYPOINT ["/sbin/tini", "--", "/app/docker-entrypoint.sh"]
+CMD node .${TURBO_APP_PATH}/server.js
diff --git a/apps/blog/.env b/apps/blog/.env
deleted file mode 100644
index 10aa54aa98f7d2e34888ad627432815fc6a2bc17..0000000000000000000000000000000000000000
--- a/apps/blog/.env
+++ /dev/null
@@ -1,48 +0,0 @@
-#
-# Main environment file for application.
-#
-# See [README](https://gitlab.syncad.com/hive/denser#passing-environment-variables-to-application)
-#
-
-#
-# Server and browser (use prefix `REACT_APP_`).
-# Server only (use prefix `DENSER_SERVER_`).
-#
-
-REACT_APP_APP_NAME="blog"
-REACT_APP_API_ENDPOINT="https://api.hive.blog"
-REACT_APP_CHAIN_ID="beeab0de00000000000000000000000000000000000000000000000000000000"
-REACT_APP_IMAGES_ENDPOINT="https://images.hive.blog/"
-REACT_APP_LOGGING_BROWSER_ENABLED="false"
-REACT_APP_LOGGING_LOG_LEVEL="debug"
-REACT_APP_WALLET_ENDPOINT="https://wallet.openhive.network"
-REACT_APP_SITE_DOMAIN="https://blog.openhive.network"
-REACT_APP_EXPLORER_DOMAIN='https://explore.openhive.network'
-REACT_APP_AI_DOMAIN='https://api.dev.openhive.network'
-
-REACT_APP_ALLOW_NON_STRICT_LOGIN="yes"
-REACT_APP_LOGIN_AUTHENTICATE_ON_BACKEND="no"
-
-DENSER_SERVER_COOKIE_NAME_PREFIX="auth_"
-DENSER_SERVER_SECRET_COOKIE_PASSWORD="2gyZ3GDw3LHZKCMEPmPDL3sjREVRXPr1"
-
-
-#### OAUTH (OIDC) server ####
-
-DENSER_SERVER_OIDC_ENABLED="yes"
-DENSER_SERVER_OIDC_COOKIES_KEYS="secret-devel-key"
-DENSER_SERVER_OIDC_CLIENTS='[{"client_id":"foo","client_secret":"bar","token_endpoint_auth_method":"none","client_name":"Foo Application","client_uri":"https://rocket-chat.local.angala.pl","logo_uri":"https://rocket-chat.local.angala.pl/images/logo/logo.svg","policy_uri":"https://rocket-chat.local.angala.pl/privacy-policy","tos_uri":"https://rocket-chat.local.angala.pl/terms-of-service","redirect_uris":["https://oidcdebugger.com/debug"],"grant_types":["authorization_code"],"scope":"openid","urn:custom:client:allowed-cors-origins":["https://oidcdebugger.com"]},{"client_id":"openhive_chat","client_secret":"openhive_chat_secret","client_name":"OpenHive.Chat","client_uri":"https://rocket-chat.local.angala.pl","logo_uri":"https://rocket-chat.local.angala.pl/images/logo/logo.svg","policy_uri":"https://rocket-chat.local.angala.pl/privacy-policy","tos_uri":"https://rocket-chat.local.angala.pl/terms-of-service","redirect_uris":["https://rocket-chat.local.angala.pl/_oauth/denserblog"],"grant_types":["authorization_code"],"scope":"openid profile","urn:custom:client:allowed-cors-origins":["https://rocket-chat.local.angala.pl"],"urn:custom:client:allow-non-strict-login":false}]'
-DENSER_SERVER_OIDC_JWKS_KEYS='[{"p":"8rFZLdP0vHjdMuWPE0A_haq1FqcgdRVBTgVTbrx1B3z6UqRmLTt-Ok_9JaMlRdahurZ1KE_3z6aZH44MVzMmB_tpxQs6W49T8TIyxbzW4VxIB-kkTdxS7qnTUZed3DL2kx-t6kNFy1yP2DhZcHkIe7zM-R7NTGQzh1uuK7uWgjM","kty":"RSA","q":"udbJFJEbcgBwOOnekc8AjGpZ8YR1vlrcmM6AG9SucIBPRvUKyXf8khaEY8ldTBjkkHnUFsgZ6vO2PLVfciwbLoHKEAtCDpDKqi-x88sLpUyvvC9tYenhJcnR-NpuDlwKyKs0YPL0VfcWROZuBuDii8pfOaL_yTTXCE8wd1uqm2k","d":"Baiiy5MOJQ_AJ70_GBwm-_hs7s_p6R-zJNHfX0k8GARd8JnSpHaWlTGWPfYTf_bnp7OxIx-u4uNzsKavHqLf4qV59ReIDhABueyrQR0MwZlfmVCdg_xIhVDD6BeND_xwy35V9G-Bee23pUw9YYUminfxiPNbBZDcww6AQyXrotft5RXRIsNbLWfESf9tZQEl49WkuGdyVKRiT3k29nGwJxF0QKA-9r1pz5ML4x-5ynzp28nI1SidYRo26SqT9i6XPt8zMksZQMM72iyDQGRQhAy5lLGI04cU2GnehQaYeAc9X9v2tzPC7UHvfhMhH6sbBTPY6JAu6iDWKj1p0I_r0Q","e":"AQAB","use":"sig","kid":"mShU1yBPX9yrb8m96VMb-7Bhh6HtXl_SHf9ToNtcjzk","qi":"mu3j_sQaYfAB2li2zOEAp3gn1tJ1ICqaQWFSSktwsHaLGBF5_h85iPSnVieX8RSaQbJyZ7QDYAFFdsDRxK0mQIvY0ahd5X2TlY312_crXli00fRXhcEJhTz21xm0MUJ60LsAsj8WydKxil8O26oP4qIIpRrhDmPXw8qodCUMpYQ","dp":"rx4rJDdR3AE2UzhzgceVTmT8ICld8T3yDlMnfbr8kveqRKGdnLvV_EuldVgAWCFkN67aYMk7HhmvWaaM3wroQVA3ZNgSNuj4AA1ht27oelq1GwguiwQUz2O5OKG3ZaFcbJKqUmRSY0gZ_0HBv7eF2ItGN-fy6VFQITaVObc1BiM","alg":"RS256","dq":"WR8E_YT9OXW2W8TkRN6Vr8EM80MHyEsAwZM-YppjMXaHDktTafzNti1wPf6CbIz_h721FVvO-hr4STLd2_4E5w-9HGaZvix31Jfc6kJ0ikg1erTv6uXjYGDh_kqaPu6rCUL5cojw3g0Js-8h0tCkNE_PzO87ZX2epdB8OLFQJwk","n":"sC3IU2jrdhNc-T0H06Py4WceMIF8id1AJ4blBU2i_rfgf2yCpkap_dThLShurL4o777qksSICQpoW75MxzR6xelz9-lGm-sOdr6Xv9L8jVUnm9CryzHNW_nTG0wmX8W4PTA20hXhSL_bZUqh9lXeJQephMpdRPEUyU4doaYZodLR_bNfiAbPV3ySFyWTHO_p01RriSENoF0DogcovzAwczTXwSX_surffhT9lkxw4d4kW2qF3f3ZdWlEG7ZaL8U3o88FjPmff2dJOFhuudDhbeRiXkTEdNTmipiie2zIN6Zweqi31ZnbZnuEnbMPGjg3mn5NUa7cO7ts5RJzqG5H6w"}]'
-
-#### Rocket Chat Widget ####
-
-REACT_APP_OPENHIVE_CHAT_CLIENT_ID="openhive_chat"
-REACT_APP_OPENHIVE_CHAT_API_URI="https://your-chat/api/v1"
-REACT_APP_OPENHIVE_CHAT_URI="https://your-chat"
-REACT_APP_OPENHIVE_CHAT_IFRAME_INTEGRATION_ENABLE="no"
-REACT_APP_OPENHIVE_CHAT_IFRAME_VISIBLE="yes"
-REACT_APP_OPENHIVE_CHAT_ALLOW_NON_STRICT_LOGIN="no"
-DENSER_SERVER_OPENHIVE_CHAT_ADMIN_USER_ID="your-admin-user-id"
-DENSER_SERVER_OPENHIVE_CHAT_ADMIN_USER_TOKEN="your-admin-user-token"
-
-ESLINT_USE_FLAT_CONFIG=false
diff --git a/apps/blog/.env.mirrornet-testing b/apps/blog/.env.mirrornet-testing
new file mode 100644
index 0000000000000000000000000000000000000000..01ee5ca8c842adbe6ffff15736700a7e7f514208
--- /dev/null
+++ b/apps/blog/.env.mirrornet-testing
@@ -0,0 +1,27 @@
+DENSER_SERVER_ENV_DUMP=true
+REACT_APP_APP_NAME="blog"
+REACT_APP_API_ENDPOINT="https://dind/"
+REACT_APP_CHAIN_ID="44"
+REACT_APP_IMAGES_ENDPOINT="https://images.hive.blog/"
+REACT_APP_LOGGING_BROWSER_ENABLED="true"
+REACT_APP_LOGGING_LOG_LEVEL="debug"
+REACT_APP_WALLET_ENDPOINT="https://caddy-wallet"
+REACT_APP_SITE_DOMAIN="https://caddy-blog.local"
+REACT_APP_BLOG_DOMAIN="https://caddy-blog"
+REACT_APP_EXPLORER_DOMAIN='https://explore.openhive.network'
+REACT_APP_AI_DOMAIN='https://api.dev.openhive.network'
+REACT_APP_ALLOW_NON_STRICT_LOGIN="yes"
+REACT_APP_LOGIN_AUTHENTICATE_ON_BACKEND="no"
+DENSER_SERVER_COOKIE_NAME_PREFIX="auth_"
+DENSER_SERVER_SECRET_COOKIE_PASSWORD="SomeValueForTestingPurposesOnly"
+DENSER_SERVER_OIDC_ENABLED="yes"
+DENSER_SERVER_OIDC_COOKIES_KEYS="secret-devel-key"
+REACT_APP_OPENHIVE_CHAT_CLIENT_ID="openhive_chat"
+REACT_APP_OPENHIVE_CHAT_API_URI="https://your-chat/api/v1"
+REACT_APP_OPENHIVE_CHAT_URI="https://your-chat"
+REACT_APP_OPENHIVE_CHAT_IFRAME_INTEGRATION_ENABLE="no"
+REACT_APP_OPENHIVE_CHAT_IFRAME_VISIBLE="yes"
+REACT_APP_OPENHIVE_CHAT_ALLOW_NON_STRICT_LOGIN="no"
+DENSER_SERVER_OPENHIVE_CHAT_ADMIN_USER_ID="your-admin-user-id"
+DENSER_SERVER_OPENHIVE_CHAT_ADMIN_USER_TOKEN="your-admin-user-token"
+ESLINT_USE_FLAT_CONFIG=false
diff --git a/apps/blog/.env.testing b/apps/blog/.env.testing
new file mode 100644
index 0000000000000000000000000000000000000000..32097581246dea2158a4f7fb8335ce10281d166b
--- /dev/null
+++ b/apps/blog/.env.testing
@@ -0,0 +1,27 @@
+DENSER_SERVER_ENV_DUMP=true
+REACT_APP_APP_NAME="blog"
+REACT_APP_API_ENDPOINT="https://api.hive.blog"
+REACT_APP_CHAIN_ID="beeab0de00000000000000000000000000000000000000000000000000000000"
+REACT_APP_IMAGES_ENDPOINT="https://images.hive.blog/"
+REACT_APP_LOGGING_BROWSER_ENABLED="false"
+REACT_APP_LOGGING_LOG_LEVEL="debug"
+REACT_APP_WALLET_ENDPOINT="https://wallet.openhive.network"
+REACT_APP_SITE_DOMAIN="https://blog.openhive.network"
+REACT_APP_BLOG_DOMAIN="https://blog.openhive.network"
+REACT_APP_EXPLORER_DOMAIN='https://explore.openhive.network'
+REACT_APP_AI_DOMAIN='https://api.dev.openhive.network'
+REACT_APP_ALLOW_NON_STRICT_LOGIN="yes"
+REACT_APP_LOGIN_AUTHENTICATE_ON_BACKEND="no"
+DENSER_SERVER_COOKIE_NAME_PREFIX="auth_"
+DENSER_SERVER_SECRET_COOKIE_PASSWORD="SomeValueForTestingPurposesOnly"
+DENSER_SERVER_OIDC_ENABLED="yes"
+DENSER_SERVER_OIDC_COOKIES_KEYS="secret-devel-key"
+REACT_APP_OPENHIVE_CHAT_CLIENT_ID="openhive_chat"
+REACT_APP_OPENHIVE_CHAT_API_URI="https://your-chat/api/v1"
+REACT_APP_OPENHIVE_CHAT_URI="https://your-chat"
+REACT_APP_OPENHIVE_CHAT_IFRAME_INTEGRATION_ENABLE="no"
+REACT_APP_OPENHIVE_CHAT_IFRAME_VISIBLE="yes"
+REACT_APP_OPENHIVE_CHAT_ALLOW_NON_STRICT_LOGIN="no"
+DENSER_SERVER_OPENHIVE_CHAT_ADMIN_USER_ID="your-admin-user-id"
+DENSER_SERVER_OPENHIVE_CHAT_ADMIN_USER_TOKEN="your-admin-user-token"
+ESLINT_USE_FLAT_CONFIG=false
\ No newline at end of file
diff --git a/apps/blog/components/md-editor.tsx b/apps/blog/components/md-editor.tsx
index 900c26c5223d78d5ad5b4d6f8707bf8d990511ea..f776fc06761b89b5e39a1be5510ca0e9b253a36c 100644
--- a/apps/blog/components/md-editor.tsx
+++ b/apps/blog/components/md-editor.tsx
@@ -11,11 +11,12 @@ import {
useState
} from 'react';
import * as commands from '@uiw/react-md-editor/commands';
-import env from '@beam-australia/react-env';
import { useUser } from '@smart-signer/lib/auth/use-user';
import { Signer } from '@smart-signer/lib/signer/signer';
import { ICommand, TextAreaTextApi } from '@uiw/react-md-editor';
import { getLogger } from '@ui/lib/logging';
+import { configuredImagesEndpoint } from '@hive/ui/config/public-vars';
+
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@ui/components/tooltip';
import { useTranslation } from 'next-i18next';
import imageUserBlocklist from '@ui/config/lists/image-user-blocklist';
@@ -69,7 +70,7 @@ const uploadImg = async (file: File, username: string, signer: Signer): Promise<
const imageOwner = signer.authorityUsername || signer.username;
- const postUrl = `${env('IMAGES_ENDPOINT')}${imageOwner}/${sig}`;
+ const postUrl = `${configuredImagesEndpoint}${imageOwner}/${sig}`;
const response = await fetch(postUrl, { method: 'POST', body: formData });
const resJSON = await response.json();
diff --git a/apps/blog/components/notification-list-item.tsx b/apps/blog/components/notification-list-item.tsx
index b28d4ef8056cfe74134f9e308e0117a1b0bc78ca..180da045f896472186ccfeebd603072e049079e2 100644
--- a/apps/blog/components/notification-list-item.tsx
+++ b/apps/blog/components/notification-list-item.tsx
@@ -7,8 +7,10 @@ import { useTranslation } from 'next-i18next';
import { useSiteParams } from '@ui/components/hooks/use-site-params';
import { useUser } from '@smart-signer/lib/auth/use-user';
import { getLogger } from '@ui/lib/logging';
+import { configuredImagesEndpoint } from '@hive/ui/config/public-vars';
+
import { Avatar, AvatarFallback, AvatarImage } from '@ui/components';
-import env from '@beam-australia/react-env';
+
import Image from 'next/image';
import TimeAgo from '@hive/ui/components/time-ago';
@@ -40,7 +42,7 @@ const NotificationListItem = ({ date, msg, score, type, url, lastRead }: IAccoun
default:
icon = ;
}
- const imageHosterUrl = env('IMAGES_ENDPOINT');
+ const imageHosterUrl = configuredImagesEndpoint;
const participants = mentions
? mentions.map((m: string) => (
diff --git a/apps/blog/components/site-header.tsx b/apps/blog/components/site-header.tsx
index 78cebdb76e0d70a915d896ae7c539d6fb29a5325..8685c168bc94fc098ed78466cc5e71797952ac96 100644
--- a/apps/blog/components/site-header.tsx
+++ b/apps/blog/components/site-header.tsx
@@ -4,6 +4,7 @@ import Sidebar from './sidebar';
import { MainNav } from './main-nav';
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@ui/components/tooltip';
import { siteConfig } from '@ui/config/site';
+import { configuredImagesEndpoint } from '@hive/ui/config/public-vars';
import Link from 'next/link';
import React, { useState, FC, useEffect } from 'react';
import clsx from 'clsx';
@@ -19,7 +20,7 @@ import LangToggle from './lang-toggle';
import { PieChart, Pie } from 'recharts';
import useManabars from './hooks/useManabars';
import { hoursAndMinutes } from '../lib/utils';
-import env from '@beam-australia/react-env';
+
import { getAccount } from '@transaction/lib/hive';
import TooltipContainer from '@ui/components/tooltip-container';
import { ModeSwitchInput } from '@ui/components/mode-switch-input';
@@ -232,7 +233,7 @@ const SiteHeader: FC = () => {
className="h-full w-full object-cover"
src={
profile?.profile?.profile_image ||
- `${env('IMAGES_ENDPOINT')}/u/${user.username}/avatar`
+ `${configuredImagesEndpoint}/u/${user.username}/avatar`
}
alt="Profile picture"
/>
diff --git a/apps/blog/instrumentation.ts b/apps/blog/instrumentation.ts
new file mode 100644
index 0000000000000000000000000000000000000000..018446c9bc218fc248164c2fe790bdf7bb655abb
--- /dev/null
+++ b/apps/blog/instrumentation.ts
@@ -0,0 +1,5 @@
+import {commonRegister} from '@hive/ui/lib/common-instrumentation';
+
+export async function register(): Promise {
+ await commonRegister('blog');
+}
diff --git a/apps/blog/lib/proxify-images.ts b/apps/blog/lib/proxify-images.ts
index 8d59a43cc2250154bf294314d148caab1db51d92..5cf1f95f75217930d9757b081909e1bb747f8b33 100644
--- a/apps/blog/lib/proxify-images.ts
+++ b/apps/blog/lib/proxify-images.ts
@@ -1,9 +1,10 @@
import querystring from 'querystring';
import multihash from 'multihashes';
-import env from '@beam-australia/react-env';
+
+import { configuredImagesEndpoint } from '@hive/ui/config/public-vars';
// Change this when we have images.hive.blog working
-let proxyBase = `${env('IMAGES_ENDPOINT')}`;
+let proxyBase = `${configuredImagesEndpoint}`;
export function setProxyBase(p: string): void {
proxyBase = p;
diff --git a/apps/blog/lib/renderer.ts b/apps/blog/lib/renderer.ts
index 1554fbcfe3068de053147fda9dbd677c48d488eb..265c57cb723bcd5936bf757e8ef41d973d840fa9 100644
--- a/apps/blog/lib/renderer.ts
+++ b/apps/blog/lib/renderer.ts
@@ -1,11 +1,13 @@
import { DefaultRenderer, InstagramPlugin, TablePlugin, TwitterPlugin } from '@hive/renderer';
import { getDoubleSize, proxifyImageUrl } from '@ui/lib/old-profixy';
-import env from '@beam-australia/react-env';
+
import imageUserBlocklist from '@hive/ui/config/lists/image-user-blocklist';
import { isUrlWhitelisted } from '@hive/ui/config/lists/phishing';
+import { configuredSiteDomain, configuredImagesEndpoint } from '@hive/ui/config/public-vars';
+
const renderDefaultOptions = {
- baseUrl: `${env('SITE_DOMAIN')}/`,
+ baseUrl: `${configuredSiteDomain}/`,
breaks: true,
skipSanitization: false,
allowInsecureScriptTags: false,
@@ -22,14 +24,14 @@ const renderDefaultOptions = {
usertagUrlFn: (account: string) => '/@' + account,
hashtagUrlFn: (hashtag: string) => '/trending/' + hashtag,
isLinkSafeFn: (url: string) =>
- !!url.match(`^(/(?!/)|${env('IMAGES_ENDPOINT')})`) ||
- !!url.match(`^(/(?!/)|${env('SITE_DOMAIN')})`) ||
+ !!url.match(`^(/(?!/)|${configuredImagesEndpoint})`) ||
+ !!url.match(`^(/(?!/)|${configuredSiteDomain})`) ||
!!url.match(`^(/(?!/)|#)`) ||
isUrlWhitelisted(url),
addExternalCssClassToMatchingLinksFn: (url: string) =>
- !url.match(`^(/(?!/)|${env('IMAGES_ENDPOINT')})`) &&
- !url.match(`^(/(?!/)|${env('SITE_DOMAIN')})`) &&
+ !url.match(`^(/(?!/)|${configuredImagesEndpoint})`) &&
+ !url.match(`^(/(?!/)|${configuredSiteDomain})`) &&
!url.match(`^(/(?!/)|#)`) &&
!isUrlWhitelisted(url)
};
diff --git a/apps/blog/middleware.ts b/apps/blog/middleware.ts
index fe7381e346d38e4a5f6ac55f5313826ed220f5d1..bb1866f9afd6d59ac82ff6a5d02444cb7881aed9 100644
--- a/apps/blog/middleware.ts
+++ b/apps/blog/middleware.ts
@@ -1,119 +1,14 @@
-import { NextResponse } from 'next/server';
-import type { NextRequest } from 'next/server';
-import { setLoginChallengeCookies } from '@smart-signer/lib/middleware-challenge-cookies';
-import { createWaxFoundation } from '@hiveio/wax';
+import {commonMiddleware} from '@hive/ui/lib/common-middleware';
+import { type NextRequest, NextResponse } from 'next/server';
-export const config = {
- runtime: 'nodejs'
-};
-
-// Initialize WAX lazily only when needed
-let waxInstance: any = null;
-const getWax = async () => {
- if (!waxInstance) {
- try {
- waxInstance = await createWaxFoundation();
- } catch (error) {
- console.error('Failed to initialize WAX:', error);
- return null;
- }
- }
- return waxInstance;
-};
-
-const parseAuthCookie = async (cookie: string) => {
- if (!cookie) return null;
-
- const wax = await getWax();
- if (!wax) return null;
-
- try {
- const binary = Buffer.from(cookie, 'base64').toString('utf-8');
- return wax.convertTransactionFromBinaryForm(binary);
- } catch (error) {
- console.error('Failed to parse auth cookie:', error);
- return null;
- }
-};
-
-export async function middleware(request: NextRequest) {
+export async function middleware(request: NextRequest): Promise {
const { pathname } = request.nextUrl;
- // Early return for static files and API routes
- if (
- pathname.startsWith('/_next') ||
- pathname.startsWith('/api') ||
- pathname.startsWith('/static') ||
- pathname.includes('favicon.ico')
- ) {
- return NextResponse.next();
- }
+ const result = await commonMiddleware(request);
- // Handle root redirect
- if (pathname === '/') {
+ /// In blog, let's redirect root path to /trending
+ if (pathname === '/')
return NextResponse.redirect(new URL('/trending', request.url));
- }
-
- const res = NextResponse.next();
- // Handle auth cookie parsing
- try {
- const authCookie = request.cookies.get('data')?.value;
- if (authCookie) {
- const tx = await parseAuthCookie(authCookie);
- console.log('tx:', tx);
- }
- } catch (error) {
- console.error('Auth cookie parsing error:', error);
- }
-
- // Handle @username/permlink redirects
- const tempArr = pathname.split('/');
- if (tempArr.length === 3 && tempArr[1].startsWith('@')) {
- const author = tempArr[1].slice(1);
- const permlink = tempArr[2];
-
- try {
- const resp = await fetch('https://api.hive.blog', {
- method: 'POST',
- body: JSON.stringify({
- jsonrpc: '2.0',
- method: 'bridge.get_post',
- params: { author, permlink, observer: '' },
- id: 1
- })
- });
-
- const entry = await resp.json();
- if (entry?.result?.community) {
- const newUrl = new URL(`/${entry.result.community}/@${entry.result.author}/${entry.result.permlink}`, request.url);
- // Check if we're not already at the target URL to prevent loops
- if (newUrl.pathname !== pathname) {
- return NextResponse.redirect(newUrl);
- }
- }
- } catch (error) {
- console.error('Failed to fetch post:', error);
- }
- }
-
- // Set login challenge cookies for non-excluded paths
- if (pathname.match('/((?!api|_next/static|_next/image|favicon.ico).*)')) {
- setLoginChallengeCookies(request, res);
- }
-
- return res;
+ return result;
}
-
-// export const config = {
-// matcher: [
-// /*
-// * Match all paths except for:
-// * 1. /api routes
-// * 2. /_next (Next.js internals)
-// * 3. /_static (inside /public)
-// * 4. all root files inside /public (e.g. /favicon.ico)
-// */
-// '/((?!api/|_next/|_static/|_vercel|[\\w-]+.\\w+).*)'
-// ]
-// };
diff --git a/apps/blog/next.config.js b/apps/blog/next.config.js
index 563fdb2dbf0ea5952727bd5217d0a9cec7eabedf..19528014b80b74f4f9f88437ae7719175e783fa3 100644
--- a/apps/blog/next.config.js
+++ b/apps/blog/next.config.js
@@ -13,7 +13,8 @@ const nextConfig = {
output: 'standalone',
swcMinify: false,
experimental: {
- outputFileTracingRoot: path.join(__dirname, '../..')
+ outputFileTracingRoot: path.join(__dirname, '../..'),
+ instrumentationHook: true
},
/// According to notes: https://nextjs.org/docs/app/guides/progressive-web-apps#8-securing-your-application
async headers() {
diff --git a/apps/blog/pages/[param]/settings.tsx b/apps/blog/pages/[param]/settings.tsx
index 1a1342334b8110b4bc1538228fc3351cf7784f73..df8309bd876564af0bf8ea6f470ab7d581b80aed 100644
--- a/apps/blog/pages/[param]/settings.tsx
+++ b/apps/blog/pages/[param]/settings.tsx
@@ -18,6 +18,7 @@ import { GetServerSideProps } from 'next';
import { useParams } from 'next/navigation';
import { useUser } from '@smart-signer/lib/auth/use-user';
import { cn } from '@ui/lib/utils';
+import { configuredImagesEndpoint } from '@hive/ui/config/public-vars';
import { hiveChainService } from '@transaction/lib/hive-chain-service';
import { useFollowListQuery } from '@/blog/components/hooks/use-follow-list';
import { hbauthService } from '@smart-signer/lib/hbauth-service';
@@ -26,7 +27,7 @@ import { useQuery } from '@tanstack/react-query';
import { useTranslation } from 'next-i18next';
import { TFunction } from 'i18next';
import { MutableRefObject, useEffect, useRef, useState } from 'react';
-import env from '@beam-australia/react-env';
+
import { Signer } from '@smart-signer/lib/signer/signer';
import { getLogger } from '@ui/lib/logging';
import { toast } from '@ui/components/hooks/use-toast';
@@ -117,7 +118,7 @@ const uploadImg = async (file: File, username: string, signer: Signer): Promise<
password: ''
});
- const postUrl = `${env('IMAGES_ENDPOINT')}${username}/${sig}`;
+ const postUrl = `${configuredImagesEndpoint}${username}/${sig}`;
const response = await fetch(postUrl, { method: 'POST', body: formData });
const resJSON = await response.json();
diff --git a/apps/wallet/.env b/apps/wallet/.env
deleted file mode 100644
index 0983653278b20c3a91f12b73b1dc2c600509e729..0000000000000000000000000000000000000000
--- a/apps/wallet/.env
+++ /dev/null
@@ -1,28 +0,0 @@
-#
-# Main environment file for application.
-#
-# See [README](https://gitlab.syncad.com/hive/denser#passing-environment-variables-to-application)
-#
-
-#
-# Server and browser (use prefix `REACT_APP_`).
-#
-
-REACT_APP_APP_NAME="wallet"
-REACT_APP_API_ENDPOINT="https://api.hive.blog"
-REACT_APP_CHAIN_ID="beeab0de00000000000000000000000000000000000000000000000000000000"
-REACT_APP_IMAGES_ENDPOINT="https://images.hive.blog/"
-REACT_APP_SITE_DOMAIN="https://wallet.openhive.network"
-REACT_APP_BLOG_DOMAIN="https://blog.openhive.network"
-REACT_APP_EXPLORER_DOMAIN='https://explore.openhive.network'
-REACT_APP_LOGGING_BROWSER_ENABLED="false"
-REACT_APP_LOGGING_LOG_LEVEL="info"
-
-#
-# Server only (use prefix `DENSER_SERVER_`).
-#
-
-# DENSER_SERVER_HIDDEN_SECRET=hidden_secret
-DENSER_SERVER_SECRET_COOKIE_PASSWORD="2gyZ3GDw3LHZKCMEPmPDL3sjREVRXPr3"
-
-ESLINT_USE_FLAT_CONFIG=false
\ No newline at end of file
diff --git a/apps/wallet/.env.mirrornet-testing b/apps/wallet/.env.mirrornet-testing
new file mode 100644
index 0000000000000000000000000000000000000000..13d921887dffca3736a87f6b6a36ad55c0207a78
--- /dev/null
+++ b/apps/wallet/.env.mirrornet-testing
@@ -0,0 +1,27 @@
+DENSER_SERVER_ENV_DUMP=true
+REACT_APP_APP_NAME="wallet"
+REACT_APP_API_ENDPOINT="https://dind/"
+REACT_APP_CHAIN_ID="44"
+REACT_APP_IMAGES_ENDPOINT="https://images.hive.blog/"
+REACT_APP_LOGGING_BROWSER_ENABLED="true"
+REACT_APP_LOGGING_LOG_LEVEL="debug"
+REACT_APP_WALLET_ENDPOINT="https://caddy-wallet"
+REACT_APP_SITE_DOMAIN="https://caddy-wallet.local"
+REACT_APP_BLOG_DOMAIN="https://caddy-blog"
+REACT_APP_EXPLORER_DOMAIN='https://explore.openhive.network'
+REACT_APP_AI_DOMAIN='https://api.dev.openhive.network'
+REACT_APP_ALLOW_NON_STRICT_LOGIN="yes"
+REACT_APP_LOGIN_AUTHENTICATE_ON_BACKEND="no"
+DENSER_SERVER_COOKIE_NAME_PREFIX="auth_"
+DENSER_SERVER_SECRET_COOKIE_PASSWORD="SomeValueForTestingPurposesOnly"
+DENSER_SERVER_OIDC_ENABLED="yes"
+DENSER_SERVER_OIDC_COOKIES_KEYS="secret-devel-key"
+REACT_APP_OPENHIVE_CHAT_CLIENT_ID="openhive_chat"
+REACT_APP_OPENHIVE_CHAT_API_URI="https://your-chat/api/v1"
+REACT_APP_OPENHIVE_CHAT_URI="https://your-chat"
+REACT_APP_OPENHIVE_CHAT_IFRAME_INTEGRATION_ENABLE="no"
+REACT_APP_OPENHIVE_CHAT_IFRAME_VISIBLE="yes"
+REACT_APP_OPENHIVE_CHAT_ALLOW_NON_STRICT_LOGIN="no"
+DENSER_SERVER_OPENHIVE_CHAT_ADMIN_USER_ID="your-admin-user-id"
+DENSER_SERVER_OPENHIVE_CHAT_ADMIN_USER_TOKEN="your-admin-user-token"
+ESLINT_USE_FLAT_CONFIG=false
diff --git a/apps/wallet/.env.testing b/apps/wallet/.env.testing
new file mode 100644
index 0000000000000000000000000000000000000000..a528937f6510d215be10d54ed8e87f3ece2af726
--- /dev/null
+++ b/apps/wallet/.env.testing
@@ -0,0 +1,26 @@
+DENSER_SERVER_ENV_DUMP=true
+REACT_APP_APP_NAME="wallet"
+REACT_APP_API_ENDPOINT="https://api.hive.blog"
+REACT_APP_CHAIN_ID="beeab0de00000000000000000000000000000000000000000000000000000000"
+REACT_APP_IMAGES_ENDPOINT="https://images.hive.blog/"
+REACT_APP_LOGGING_BROWSER_ENABLED="false"
+REACT_APP_LOGGING_LOG_LEVEL="debug"
+REACT_APP_SITE_DOMAIN="https://wallet.openhive.network"
+REACT_APP_BLOG_DOMAIN="https://blog.openhive.network"
+REACT_APP_EXPLORER_DOMAIN='https://explore.openhive.network'
+REACT_APP_AI_DOMAIN='https://api.dev.openhive.network'
+REACT_APP_ALLOW_NON_STRICT_LOGIN="yes"
+REACT_APP_LOGIN_AUTHENTICATE_ON_BACKEND="no"
+DENSER_SERVER_COOKIE_NAME_PREFIX="auth_"
+DENSER_SERVER_SECRET_COOKIE_PASSWORD="SomeValueForTestingPurposesOnly"
+DENSER_SERVER_OIDC_ENABLED="yes"
+DENSER_SERVER_OIDC_COOKIES_KEYS="secret-devel-key"
+REACT_APP_OPENHIVE_CHAT_CLIENT_ID="openhive_chat"
+REACT_APP_OPENHIVE_CHAT_API_URI="https://your-chat/api/v1"
+REACT_APP_OPENHIVE_CHAT_URI="https://your-chat"
+REACT_APP_OPENHIVE_CHAT_IFRAME_INTEGRATION_ENABLE="no"
+REACT_APP_OPENHIVE_CHAT_IFRAME_VISIBLE="yes"
+REACT_APP_OPENHIVE_CHAT_ALLOW_NON_STRICT_LOGIN="no"
+DENSER_SERVER_OPENHIVE_CHAT_ADMIN_USER_ID="your-admin-user-id"
+DENSER_SERVER_OPENHIVE_CHAT_ADMIN_USER_TOKEN="your-admin-user-token"
+ESLINT_USE_FLAT_CONFIG=false
diff --git a/apps/wallet/instrumentation.ts b/apps/wallet/instrumentation.ts
new file mode 100644
index 0000000000000000000000000000000000000000..3b2cbf0aed6145d69c844fa75f66592500f6fd08
--- /dev/null
+++ b/apps/wallet/instrumentation.ts
@@ -0,0 +1,5 @@
+import {commonRegister} from '@hive/ui/lib/common-instrumentation';
+
+export async function register(): Promise {
+ await commonRegister('wallet');
+}
diff --git a/apps/wallet/lib/utils.ts b/apps/wallet/lib/utils.ts
index 30f36b7df769669166b37072163ec79e911eb66b..bdbb2eb29c2fc07821d22dd52ebe754c813b7511 100644
--- a/apps/wallet/lib/utils.ts
+++ b/apps/wallet/lib/utils.ts
@@ -5,6 +5,7 @@ import { TransferFilters } from '@/wallet/components/transfers-history-filter';
import { useUpdateAuthorityOperationMutation } from '../components/hooks/use-update-authority-mutation';
import { SavingsWithdrawals, IFollow, IDynamicGlobalProperties } from '@transaction/lib/extended-hive.chain';
import { numberWithCommas } from '@ui/lib/utils';
+import { configuredBlogDomain } from '@ui/config/public-vars';
import Big from 'big.js';
import { HIVE_NAI_STRING, VESTS_PRECISION } from '@transaction/lib/utils';
@@ -123,7 +124,7 @@ export const getAmountFromWithdrawal = (withdrawal: SavingsWithdrawals['withdraw
// The default is the blog domain
export const getExternalLink = (path: string, baseUrl?: string) => {
if (!baseUrl) {
- const envBlogUrl = (window as any).__ENV?.REACT_APP_BLOG_DOMAIN;
+ const envBlogUrl = configuredBlogDomain;
if (!envBlogUrl) {
throw new Error('No default blog domain found');
diff --git a/apps/wallet/middleware.ts b/apps/wallet/middleware.ts
index a4ee84d3a65cbce9ccca690a5e87bfa7b4c33184..f450545593acd9787157c2617f93ac65a731fb3a 100644
--- a/apps/wallet/middleware.ts
+++ b/apps/wallet/middleware.ts
@@ -1,60 +1,6 @@
-import { NextResponse } from 'next/server';
-import type { NextRequest } from 'next/server';
-import { setLoginChallengeCookies } from '@smart-signer/lib/middleware-challenge-cookies';
+import {commonMiddleware} from '@hive/ui/lib/common-middleware';
+import type { NextRequest, NextResponse } from 'next/server';
-export async function middleware(request: NextRequest) {
-
- const { pathname } = request.nextUrl;
- const res = NextResponse.next();
-
- const tempArr = pathname.split('/');
- let entry: any = null;
- if (tempArr.length === 3 && tempArr[1].startsWith('@')) {
- let author = tempArr[1].slice(1);
- let permlink = tempArr[2];
- try {
- const resp = await fetch('https://api.hive.blog', {
- method: 'POST',
- body: JSON.stringify({
- jsonrpc: '2.0',
- method: 'bridge.get_post',
- params: { author: author, permlink: permlink, observer: '' },
- id: 1
- })
- });
- entry = await resp.json();
- return NextResponse.redirect(
- new URL(`/${entry.result.community}/@${entry.result.author}/${entry.result.permlink}`, request.url)
- );
- } catch (e: any) {
- console.log(e.message);
- }
- }
-
- /*
- Set cookies with loginChallenge value set to random string (UID).
- * Match all request paths except for the ones starting with:
- * - api (API routes)
- * - _next/static (static files)
- * - _next/image (image optimization files)
- * - favicon.ico (favicon file)
- */
- if (pathname.match('/((?!api|_next/static|_next/image|favicon.ico).*)')) {
- setLoginChallengeCookies(request, res);
- }
-
- return res;
+export async function middleware(request: NextRequest): Promise {
+ return await commonMiddleware(request);
}
-
-// export const config = {
-// matcher: [
-// /*
-// * Match all paths except for:
-// * 1. /api routes
-// * 2. /_next (Next.js internals)
-// * 3. /_static (inside /public)
-// * 4. all root files inside /public (e.g. /favicon.ico)
-// */
-// '/((?!api/|_next/|_static/|_vercel|[\\w-]+.\\w+).*)'
-// ]
-// };
diff --git a/docker/docker-entrypoint.sh b/docker/docker-entrypoint.sh
index 8944e81c8420e1a3250c4faa1f1b64af0623bebf..60d634b2562685bf02e4c06805b840da1f425756 100755
--- a/docker/docker-entrypoint.sh
+++ b/docker/docker-entrypoint.sh
@@ -2,6 +2,9 @@
set -e
+# point default .env file
+ln -sf "${APP_ENV_FILE_PATH:-"/app/apps/.env"}" /app${TURBO_APP_PATH}/.env
+
echo "Setting environment..."
DIR=$(pwd)
cd ".${TURBO_APP_PATH}"
diff --git a/packages/ui/config/public-vars.ts b/packages/ui/config/public-vars.ts
new file mode 100644
index 0000000000000000000000000000000000000000..7a721963f9f4c629d4b08f831ec4c2e8a59c2c9b
--- /dev/null
+++ b/packages/ui/config/public-vars.ts
@@ -0,0 +1,8 @@
+import env from '@beam-australia/react-env';
+
+/// Contains list of public variables which can have safely set defaults and allow application build without explicit env. definition
+
+export const configuredSiteDomain = env('SITE_DOMAIN') ?? 'https://hive.blog/';
+export const configuredImagesEndpoint = env('IMAGES_ENDPOINT') ?? 'https://images.hive.blog/';
+export const configuredApiEndpoint = env('API_ENDPOINT') ?? 'https://api.hive.blog/';
+export const configuredBlogDomain = env('BLOG_DOMAIN') ?? 'https://hive.blog/';
\ No newline at end of file
diff --git a/packages/ui/config/site.ts b/packages/ui/config/site.ts
index bac304fe19d92592a29629bf6db1da2b5bc7deb4..358f2345ac6b251bc8dd002011f75146025c03b0 100644
--- a/packages/ui/config/site.ts
+++ b/packages/ui/config/site.ts
@@ -1,5 +1,7 @@
import env from '@beam-australia/react-env';
+import { configuredApiEndpoint, configuredSiteDomain } from '@hive/ui/config/public-vars';
+
const SERVER_VAR_PREFIX = 'DENSER_SERVER_';
const MAINNET_CHAIN_ID = 'beeab0de00000000000000000000000000000000000000000000000000000000';
@@ -16,8 +18,8 @@ const chainEnv: Record = {
const chainId = env('CHAIN_ID') ? env('CHAIN_ID') : MAINNET_CHAIN_ID;
export const siteConfig = {
name: 'Hive Blog',
- url: env('SITE_DOMAIN') || 'https://hive.blog',
- endpoint: `${env('API_ENDPOINT') ? env('API_ENDPOINT') : 'https://api.hive.blog'}`,
+ url: configuredSiteDomain,
+ endpoint: configuredApiEndpoint,
chainId,
chainEnv: chainEnv[chainId] || chainEnv['testnet'],
ogImage: '',
diff --git a/packages/ui/lib/common-instrumentation.ts b/packages/ui/lib/common-instrumentation.ts
new file mode 100644
index 0000000000000000000000000000000000000000..7b4c0dcdafff0ba22a134deeb87e52f1d670f273
--- /dev/null
+++ b/packages/ui/lib/common-instrumentation.ts
@@ -0,0 +1,34 @@
+const dumpStartupEnvironment = () => {
+ const executionEnv = process.env.NODE_ENV ?? 'test';
+ const isProduction = executionEnv === 'production';
+ const doDump = (process.env.DENSER_SERVER_ENV_DUMP ?? 'false') === 'true' ;
+
+ if (isProduction && doDump === false) {
+ console.log('Missing DENSER_SERVER_ENV_DUMP variable or set to false, skipping environment dump in production mode.');
+ return;
+ }
+
+ console.log('Attempting to dump Denser specific environment variables (you can skip it by unsetting DENSER_SERVER_ENV_DUMP variable or set it to false');
+
+ const vars = Object.keys(process.env);
+ const filteredVars = vars.filter((key) => {
+ return key.startsWith('DENSER_') || key.startsWith('HIVE_') || key.startsWith('NEXT_PUBLIC_') || key.startsWith('REACT_APP_');
+ });
+
+ const env = filteredVars.sort().forEach((key) => {
+ const value = process.env[key];
+ if (value) {
+ console.log(`${key}: ${value}`);
+ } else {
+ console.log(`Variable ${key} is !!!`);
+ }
+ });
+
+ console.log('Denser startup environment variables dump finsihed');
+};
+
+export async function commonRegister(appName: string): Promise {
+ console.log(`Starting up the '${appName}' application server...`);
+ dumpStartupEnvironment();
+}
+
diff --git a/packages/ui/lib/common-middleware.ts b/packages/ui/lib/common-middleware.ts
new file mode 100644
index 0000000000000000000000000000000000000000..3681e7f903ae6150a1cbc45c2e04915c06910fd9
--- /dev/null
+++ b/packages/ui/lib/common-middleware.ts
@@ -0,0 +1,61 @@
+import { NextResponse } from 'next/server';
+import type { NextRequest } from 'next/server';
+import { setLoginChallengeCookies } from '@smart-signer/lib/middleware-challenge-cookies';
+import { configuredApiEndpoint } from '@hive/ui/config/public-vars';
+
+export async function commonMiddleware(request: NextRequest) {
+
+ const { pathname } = request.nextUrl;
+ const res = NextResponse.next();
+
+ const tempArr = pathname.split('/');
+ let entry: any = null;
+ if (tempArr.length === 3 && tempArr[1].startsWith('@')) {
+ let author = tempArr[1].slice(1);
+ let permlink = tempArr[2];
+ try {
+ const resp = await fetch(configuredApiEndpoint, {
+ method: 'POST',
+ body: JSON.stringify({
+ jsonrpc: '2.0',
+ method: 'bridge.get_post',
+ params: { author: author, permlink: permlink, observer: '' },
+ id: 1
+ })
+ });
+ entry = await resp.json();
+ return NextResponse.redirect(
+ new URL(`/${entry.result.community}/@${entry.result.author}/${entry.result.permlink}`, request.url)
+ );
+ } catch (e: any) {
+ console.log(e.message);
+ }
+ }
+
+ /*
+ Set cookies with loginChallenge value set to random string (UID).
+ * Match all request paths except for the ones starting with:
+ * - api (API routes)
+ * - _next/static (static files)
+ * - _next/image (image optimization files)
+ * - favicon.ico (favicon file)
+ */
+ if (pathname.match('/((?!api|_next/static|_next/image|favicon.ico).*)')) {
+ setLoginChallengeCookies(request, res);
+ }
+
+ return res;
+}
+
+// export const config = {
+// matcher: [
+// /*
+// * Match all paths except for:
+// * 1. /api routes
+// * 2. /_next (Next.js internals)
+// * 3. /_static (inside /public)
+// * 4. all root files inside /public (e.g. /favicon.ico)
+// */
+// '/((?!api/|_next/|_static/|_vercel|[\\w-]+.\\w+).*)'
+// ]
+// };
diff --git a/packages/ui/lib/old-profixy.ts b/packages/ui/lib/old-profixy.ts
index 5001cff36d204a90e8dce4121ebfbddea47ee254..ce52289dcaf0df60a2cc1629837463bfeb862a32 100644
--- a/packages/ui/lib/old-profixy.ts
+++ b/packages/ui/lib/old-profixy.ts
@@ -1,4 +1,4 @@
-import env from '@beam-australia/react-env';
+import { configuredImagesEndpoint } from '@hive/ui/config/public-vars';
/**
* this regular expression should capture all possible proxy domains
@@ -15,7 +15,7 @@ const NATURAL_SIZE = '0x0/';
const CAPPED_SIZE = '768x0/';
const DOUBLE_CAPPED_SIZE = '1536x0/';
-export const imageProxy = () => `${env('IMAGES_ENDPOINT')}`;
+export const imageProxy = () => `${configuredImagesEndpoint}`;
export const defaultSrcSet = (url: string) => {
return `${url} 1x, ${url.replace(CAPPED_SIZE, DOUBLE_CAPPED_SIZE)} 2x`;
};
@@ -46,7 +46,7 @@ export const proxifyImageUrl = (url: string, dimensions: string | boolean) => {
const lastProxy = proxyList[proxyList.length - 1];
respUrl = url.substring(url.lastIndexOf(lastProxy) + lastProxy.length);
}
- if (dimensions && `${env('IMAGES_ENDPOINT')}`) {
+ if (dimensions && `${configuredImagesEndpoint}`) {
let dims = dimensions + '/';
if (typeof dimensions !== 'string') {
// @ts-ignore
@@ -60,7 +60,7 @@ export const proxifyImageUrl = (url: string, dimensions: string | boolean) => {
}
if ((NATURAL_SIZE !== dims && CAPPED_SIZE !== dims) || !rProxyDomain.test(respUrl)) {
- return `${env('IMAGES_ENDPOINT')}` + dims + respUrl;
+ return `${configuredImagesEndpoint}` + dims + respUrl;
}
}
return respUrl;
diff --git a/scripts/run_instance.sh b/scripts/run_instance.sh
index 78d0714835fe4ce4fbbdefee3f9ab2e677957528..5fa25bc7d30c7e7448c22288f40c83cd30f76634 100755
--- a/scripts/run_instance.sh
+++ b/scripts/run_instance.sh
@@ -9,90 +9,27 @@ Usage: $0 [OPTION[=VALUE]]...
Run a Denser Docker instance
OPTIONS:
--image=IMAGE Docker image to run (default: 'registry.gitlab.syncad.com/hive/denser:latest')
- --api-endpoint=URL API endpoint to be used by the new instance (default: 'https://api.hive.blog')
- --wallet-endpoint=WALLET_ENDPOINT Wallet endpoint to be used by the new instance (default: 'https://wallet.hive.blog')
- --site-domain=SITE_DOMAIN Site domain to be used by the new instance (default: 'https://blog.hive.blog')
- --blog-domain=BLOG_DOMAIN Blog domain to be used by the new instance (default: 'https://blog.hive.blog')
- --explorer-domain=EXPLORER_DOMAIN Explorer domain to be used by the new instance (default: 'https://explore.hive.blog')
- --ai-domain=AI_DOMAIN AI domain to be used by the new instance (default: 'https://api.dev.openhive.network')
- --openhive-chat-uri=OPENHIVE_CHAT_URI Chat URI to be used by the new instance (default: 'http://openhive.chat')
- --chain-id=CHAIN_ID Chain ID to be used by the new instance (default: 'beeab0de00000000000000000000000000000000000000000000000000000000')
- --images-endpoint=URL IMAGES endpoint to be used by the new instance (default: 'https://images.hive.blog/')
- --app-scope=SCOPE App scope (eg. '@hive/auth')
- --app-path=PATH App path (eg. '/apps/auth)
--port=PORT Port to be exposed (default: 3000)
--name=NAME Container name to be used (default: denser)
+ --env-file=deployment.env Obligatory path to a file containing environment variables to override i.e. deployment secrets
--detach Run in detached mode
--help|-h|-? Display this help screen and exit
EOF
}
IMAGE_NAME=${IMAGE_NAME:-"registry.gitlab.syncad.com/hive/denser:latest"}
-API_ENDPOINT=${API_ENDPOINT:-"https://api.hive.blog"}
-WALLET_ENDPOINT=${WALLET_ENDPOINT:-"https://wallet.hive.blog"}
-SITE_DOMAIN=${SITE_DOMAIN:-"https://blog.hive.blog"}
-BLOG_DOMAIN=${BLOG_DOMAIN:-"https://blog.hive.blog"}
-EXPLORER_DOMAIN=${EXPLORER_DOMAIN:-"https://explore.openhive.network"}
-AI_DOMAIN=${AI_DOMAIN:-"https://api.dev.openhive.network"}
-OPENHIVE_CHAT_URI=${OPENHIVE_CHAT_URI:-"http://openhive.chat"}
-CHAIN_ID=${CHAIN_ID:-"beeab0de00000000000000000000000000000000000000000000000000000000"}
-IMAGES_ENDPOINT=${IMAGES_ENDPOINT:="https://images.hive.blog/"}
-TURBO_APP_SCOPE=${TURBO_APP_SCOPE:-}
-TURBO_APP_PATH=${TURBO_APP_PATH:-}
PORT=${PORT:-"3000"}
CONTAINER_NAME=${CONTAINER_NAME:-"denser"}
DETACH=${DETACH:-false}
+CUSTOM_ENV_FILE=''
+
while [ $# -gt 0 ]; do
case "$1" in
--image=*)
arg="${1#*=}"
IMAGE_NAME="$arg"
;;
- --api-endpoint=*)
- arg="${1#*=}"
- API_ENDPOINT="$arg"
- ;;
- --wallet-endpoint=*)
- arg="${1#*=}"
- WALLET_ENDPOINT="$arg"
- ;;
- --site-domain=*)
- arg="${1#*=}"
- SITE_DOMAIN="$arg"
- ;;
- --blog-domain=*)
- arg="${1#*=}"
- BLOG_DOMAIN="$arg"
- ;;
- --openhive-chat-uri=*)
- arg="${1#*=}"
- OPENHIVE_CHAT_URI="$arg"
- ;;
- --explorer-domain=*)
- arg="${1#*=}"
- EXPLORER_DOMAIN="$arg"
- ;;
- --ai-domain=*)
- arg="${1#*=}"
- AI_DOMAIN="$arg"
- ;;
- --chain-id=*)
- arg="${1#*=}"
- CHAIN_ID="$arg"
- ;;
- --images-endpoint=*)
- arg="${1#*=}"
- IMAGES_ENDPOINT="$arg"
- ;;
- --app-scope=*)
- arg="${1#*=}"
- TURBO_APP_SCOPE="$arg"
- ;;
- --app-path=*)
- arg="${1#*=}"
- TURBO_APP_PATH="$arg"
- ;;
--port=*)
arg="${1#*=}"
PORT="$arg"
@@ -103,7 +40,16 @@ while [ $# -gt 0 ]; do
;;
--detach)
DETACH=true
- ;;
+ ;;
+ --env-file=*)
+ arg="${1#*=}"
+ if [ -f "${arg}" ]; then
+ CUSTOM_ENV_FILE="${arg}"
+ else
+ echo "ERROR: File '${arg}' not found"
+ exit 2
+ fi
+ ;;
--help|-?)
print_help
exit 0
@@ -120,26 +66,24 @@ done
(docker ps -q --filter "name=$CONTAINER_NAME" | grep -q . && docker stop "$CONTAINER_NAME") || true
+docker container rm --force "$CONTAINER_NAME" || true
+
RUN_OPTIONS=(
"--rm"
"--publish" "$PORT:$PORT"
"--env" "PORT=$PORT"
- "--env" "REACT_APP_API_ENDPOINT=$API_ENDPOINT"
- "--env" "REACT_APP_BLOG_DOMAIN=$BLOG_DOMAIN"
- "--env" "REACT_APP_IMAGES_ENDPOINT=$IMAGES_ENDPOINT"
- "--env" "REACT_APP_WALLET_ENDPOINT=$WALLET_ENDPOINT"
- "--env" "REACT_APP_EXPLORER_DOMAIN=$EXPLORER_DOMAIN"
- "--env" "REACT_APP_AI_DOMAIN=$AI_DOMAIN"
- "--env" "REACT_APP_OPENHIVE_CHAT_URI=$OPENHIVE_CHAT_URI"
- "--env" "REACT_APP_SITE_DOMAIN=$SITE_DOMAIN"
- "--env" "REACT_APP_CHAIN_ID=$CHAIN_ID"
- "--env" "TURBO_APP_SCOPE=$TURBO_APP_SCOPE"
- "--env" "TURBO_APP_PATH=$TURBO_APP_PATH"
"--name" "$CONTAINER_NAME"
)
+if [ -n "${CUSTOM_ENV_FILE}" ]; then
+ RUN_OPTIONS+=("-v" "${CUSTOM_ENV_FILE}:/app/apps/.env")
+else
+ echo "ERROR: Env file must be specified at command line using option: --env-file"
+ exit 2
+fi
+
if [[ "$DETACH" == "true" ]]; then
RUN_OPTIONS+=("--detach")
fi
-docker run "${RUN_OPTIONS[@]}" "$IMAGE_NAME"
\ No newline at end of file
+docker run "${RUN_OPTIONS[@]}" "$IMAGE_NAME"