mirror of
https://github.com/Portabase/portabase.git
synced 2026-07-14 11:16:13 +02:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5f61c7baa6 | ||
|
|
e3c5ec9a58 | ||
|
|
6acdf73557 | ||
|
|
4405b61e03 | ||
|
|
4016191497 | ||
|
|
94b36c1622 | ||
|
|
01b7a58c75 | ||
|
|
2b6c661fea | ||
|
|
fdc613fe8e | ||
|
|
8479b6c822 | ||
|
|
21bb165103 | ||
|
|
1decd9d7a5 | ||
|
|
d0091cfed3 | ||
|
|
f85d12448c | ||
|
|
82c8ad98b4 | ||
|
|
4c70d8aac7 | ||
|
|
ba1dbcc9f3 | ||
|
|
8e4e41ca07 | ||
|
|
a8eb3f5f1a | ||
|
|
73f7ac057c | ||
|
|
d359d53fb7 | ||
|
|
ba2fc55188 | ||
|
|
a6896c9b50 | ||
|
|
8dd74f310d | ||
|
|
44ed9e9ca6 | ||
|
|
c925407f05 | ||
|
|
622fc369d0 | ||
|
|
9580ad3934 | ||
|
|
b33c0810d5 | ||
|
|
8fbe639aa1 | ||
|
|
d7e2ec3b08 | ||
|
|
fdaca0e8a7 | ||
|
|
7959f903bb | ||
|
|
59eb91f28f | ||
|
|
64724d2a92 | ||
|
|
91a6d672fa | ||
|
|
50809476fa | ||
|
|
282ffb543c | ||
|
|
68fea480ae | ||
|
|
ec64ea8229 | ||
|
|
b13433e554 | ||
|
|
d9fd382cb2 | ||
|
|
4d324d885d | ||
|
|
af1a437523 | ||
|
|
77901ae1bc | ||
|
|
1aeff542e5 | ||
|
|
b81ad079ee | ||
|
|
044edcda07 | ||
|
|
3f7eb4528e | ||
|
|
0008f70552 | ||
|
|
2695715180 | ||
|
|
b3be1a561c | ||
|
|
d297f1a27b | ||
|
|
b513509b01 | ||
|
|
25744efc66 | ||
|
|
21e37366fb | ||
|
|
3f6a47c39d | ||
|
|
4dace0a32b | ||
|
|
7b6ca12744 | ||
|
|
da1b5a969c | ||
|
|
8e5d6eec6c | ||
|
|
92f1400a35 | ||
|
|
47f1938136 | ||
|
|
f226218b3a | ||
|
|
8f7fa0dea1 | ||
|
|
292b3c805d | ||
|
|
ded26f92af | ||
|
|
8cce7bbaf4 | ||
|
|
228b8c3ec7 | ||
|
|
2e298ce757 | ||
|
|
81daa9f0b0 | ||
|
|
713c8d9177 | ||
|
|
f571162eed | ||
|
|
19d2872943 | ||
|
|
0752b8bf7f | ||
|
|
c01097196a | ||
|
|
5f1bee018d | ||
|
|
8655b81618 | ||
|
|
1702e43373 | ||
|
|
a7d411f6ff | ||
|
|
6a84da0f96 | ||
|
|
79425f4490 | ||
|
|
2fcddea0fa | ||
|
|
ac1c8552e1 | ||
|
|
6a18eefe34 | ||
|
|
a43eedaf9f | ||
|
|
77bc24990e | ||
|
|
edbc79c89e | ||
|
|
527a090f1b | ||
|
|
370b86337f | ||
|
|
1ce3acdde0 | ||
|
|
1a72be323b | ||
|
|
bf252f22f2 | ||
|
|
937d92f686 | ||
|
|
5572957731 | ||
|
|
d2db5722b7 | ||
|
|
5404185a6c | ||
|
|
800f2dfbbb | ||
|
|
ed0b5410f6 | ||
|
|
ae72e262aa | ||
|
|
c4c7050c3f | ||
|
|
81e5227270 | ||
|
|
39319d9162 | ||
|
|
12206fa856 | ||
|
|
9d8c6e26f1 | ||
|
|
eb624672e6 | ||
|
|
1b026b5f08 | ||
|
|
21b9b8b44d | ||
|
|
6ef7fcc0c2 | ||
|
|
fc4ce178cb | ||
|
|
98b72988c4 | ||
|
|
317473e528 | ||
|
|
095444610d |
@@ -72,7 +72,7 @@ If you encounter a bug or have a suggestion for improvement, follow these steps:
|
||||
|
||||
3. **Push your branch**
|
||||
```bash
|
||||
git push origin feature/<feature-name>
|
||||
git push origin feat/<feature-name>
|
||||
```
|
||||
|
||||
4. **Open a Pull Request (PR)**
|
||||
@@ -82,7 +82,7 @@ If you encounter a bug or have a suggestion for improvement, follow these steps:
|
||||
|
||||
## Code Style Guidelines
|
||||
|
||||
- Follow the [specific coding style guide] (e.g., Prettier, ESLint, PEP8).
|
||||
- Follow the [specific coding style guide] (e.g., Prettier, ESLint, PEP8,Biome).
|
||||
- Use meaningful variable names and include comments where necessary.
|
||||
- Tests before submitting your changes.
|
||||
|
||||
@@ -107,4 +107,4 @@ If you encounter a bug or have a suggestion for improvement, follow these steps:
|
||||
|
||||
Thank you for contributing! 🙌
|
||||
|
||||
---
|
||||
---
|
||||
|
||||
@@ -1,46 +0,0 @@
|
||||
name: Auto Release bot
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types: [closed]
|
||||
branches:
|
||||
- main
|
||||
|
||||
jobs:
|
||||
release:
|
||||
if: github.event.pull_request.merged == true
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
steps:
|
||||
- uses: actions/create-github-app-token@v1
|
||||
id: app-token
|
||||
with:
|
||||
app-id: ${{ vars.APP_ID }}
|
||||
private-key: ${{ secrets.APP_PRIVATE_KEY }}
|
||||
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
token: ${{ steps.app-token.outputs.token }}
|
||||
ref: ${{ github.base_ref }}
|
||||
|
||||
- uses: pnpm/action-setup@v4
|
||||
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: "lts/*"
|
||||
cache: "pnpm"
|
||||
|
||||
- run: pnpm install --frozen-lockfile
|
||||
|
||||
- run: git config --global user.name 'github-actions[bot]'
|
||||
- run: git config --global user.email 'github-actions[bot]@users.noreply.github.com'
|
||||
|
||||
- name: Run release-it
|
||||
run: |
|
||||
git pull origin main
|
||||
pnpm exec release-it --ci
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ steps.app-token.outputs.token }}
|
||||
@@ -3,6 +3,9 @@ name: Discord Notification
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
release_tag:
|
||||
required: true
|
||||
type: string
|
||||
discord_title:
|
||||
required: true
|
||||
type: string
|
||||
@@ -27,10 +30,10 @@ jobs:
|
||||
DISCORD_WEBHOOK: ${{ secrets.DISCORD_WEBHOOK }}
|
||||
GH_TOKEN: ${{ secrets.GH_TOKEN }}
|
||||
run: |
|
||||
RELEASE_INFO=$(gh release view "${{ github.ref_name }}" -R ${{ github.repository }} --json name,url,body,author)
|
||||
RELEASE_INFO=$(gh release view "${{ inputs.release_tag }}" -R ${{ github.repository }} --json name,url,body,author)
|
||||
|
||||
RELEASE_TITLE=$(echo "$RELEASE_INFO" | jq -r .name)
|
||||
if [ -z "$RELEASE_TITLE" ] || [ "$RELEASE_TITLE" = "null" ]; then RELEASE_TITLE="${{ github.ref_name }}"; fi
|
||||
if [ -z "$RELEASE_TITLE" ] || [ "$RELEASE_TITLE" = "null" ]; then RELEASE_TITLE="${{ inputs.release_tag }}"; fi
|
||||
|
||||
RELEASE_URL=$(echo "$RELEASE_INFO" | jq -r .url)
|
||||
RELEASE_BODY=$(echo "$RELEASE_INFO" | jq -r .body)
|
||||
|
||||
@@ -1,47 +0,0 @@
|
||||
name: PR Checker
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
- dev
|
||||
|
||||
jobs:
|
||||
validate-code:
|
||||
name: Code Integrity Check
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@v4
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: "lts/*"
|
||||
cache: "pnpm"
|
||||
|
||||
- name: Install dependencies
|
||||
run: pnpm install --frozen-lockfile
|
||||
|
||||
- name: Check code formatting
|
||||
run: pnpm run format:check
|
||||
continue-on-error: true
|
||||
|
||||
- name: Run Linter
|
||||
run: pnpm run lint
|
||||
continue-on-error: true
|
||||
|
||||
- name: Type Check
|
||||
run: pnpm run typecheck
|
||||
continue-on-error: true
|
||||
|
||||
- name: Run Tests
|
||||
run: pnpm run test
|
||||
continue-on-error: true
|
||||
|
||||
- name: Test Application Build
|
||||
run: pnpm run build
|
||||
+235
-17
@@ -1,31 +1,249 @@
|
||||
name: Publish Docker image for release
|
||||
#name: Publish Docker Image & Release
|
||||
#
|
||||
#on:
|
||||
# push:
|
||||
# tags:
|
||||
# - "*.*.*"
|
||||
# - "!*-*"
|
||||
#
|
||||
#permissions:
|
||||
# contents: read
|
||||
# packages: write
|
||||
#
|
||||
#jobs:
|
||||
#
|
||||
# docker_publish:
|
||||
# uses: ./.github/workflows/docker.yml
|
||||
# with:
|
||||
# add_latest: true
|
||||
# secrets:
|
||||
# DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME_2 }}
|
||||
# DOCKER_PASSWORD: ${{ secrets.DOCKER_PASSWORD_2 }}
|
||||
#
|
||||
# publish_release:
|
||||
# needs: docker_publish
|
||||
# runs-on: ubuntu-latest
|
||||
# permissions:
|
||||
# contents: write
|
||||
# steps:
|
||||
# - uses: actions/create-github-app-token@v1
|
||||
# id: app-token
|
||||
# with:
|
||||
# app-id: ${{ vars.APP_ID }}
|
||||
# private-key: ${{ secrets.APP_PRIVATE_KEY }}
|
||||
#
|
||||
# - uses: actions/checkout@v4
|
||||
# with:
|
||||
# fetch-depth: 0
|
||||
# token: ${{ steps.app-token.outputs.token }}
|
||||
# ref: main
|
||||
#
|
||||
# - uses: pnpm/action-setup@v4
|
||||
#
|
||||
# - uses: actions/setup-node@v4
|
||||
# with:
|
||||
# node-version: "lts/*"
|
||||
# cache: "pnpm"
|
||||
#
|
||||
# - run: pnpm install --frozen-lockfile
|
||||
#
|
||||
# - run: git config --global user.name 'github-actions[bot]'
|
||||
# - run: git config --global user.email 'github-actions[bot]@users.noreply.github.com'
|
||||
#
|
||||
# - name: Publish GitHub Release with release-it
|
||||
# run: |
|
||||
# pnpm exec release-it ${{ github.ref_name }} --ci --no-version --no-npm
|
||||
# env:
|
||||
# GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
#
|
||||
# discord_notification:
|
||||
# needs: docker_publish
|
||||
# uses: ./.github/workflows/discord.yml
|
||||
# with:
|
||||
# discord_title: "New Release: v${{ github.ref_name }}"
|
||||
# discord_color: 3066993
|
||||
# discord_footer: "Portabase"
|
||||
# secrets:
|
||||
# DISCORD_WEBHOOK: ${{ secrets.DISCORD_WEBHOOK }}
|
||||
# GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
#
|
||||
#
|
||||
#name: Auto Release & Publish
|
||||
#
|
||||
#on:
|
||||
# pull_request:
|
||||
# types: [ closed ]
|
||||
# branches:
|
||||
# - main
|
||||
#
|
||||
#permissions:
|
||||
# contents: write
|
||||
# packages: write
|
||||
#
|
||||
#jobs:
|
||||
# release:
|
||||
# if: github.event.pull_request.merged == true
|
||||
# runs-on: ubuntu-latest
|
||||
# outputs:
|
||||
# draft_tag: ${{ steps.release_step.outputs.draft_tag }}
|
||||
# steps:
|
||||
# - uses: actions/create-github-app-token@v1
|
||||
# id: app-token
|
||||
# with:
|
||||
# app-id: ${{ vars.APP_ID }}
|
||||
# private-key: ${{ secrets.APP_PRIVATE_KEY }}
|
||||
#
|
||||
# - uses: actions/checkout@v4
|
||||
# with:
|
||||
# fetch-depth: 0
|
||||
# token: ${{ steps.app-token.outputs.token }}
|
||||
# ref: main
|
||||
#
|
||||
# - uses: pnpm/action-setup@v4
|
||||
# - uses: actions/setup-node@v4
|
||||
# with:
|
||||
# node-version: "lts/*"
|
||||
# cache: "pnpm"
|
||||
#
|
||||
# - run: pnpm install --frozen-lockfile
|
||||
#
|
||||
# - run: |
|
||||
# git config --global user.name 'github-actions[bot]'
|
||||
# git config --global user.email 'github-actions[bot]@users.noreply.github.com'
|
||||
#
|
||||
# - name: Run release-it
|
||||
# id: release_step
|
||||
# run: |
|
||||
# git pull origin main
|
||||
# OUTPUT=$(pnpm exec release-it --ci)
|
||||
# echo "$OUTPUT"
|
||||
# # Extract the untagged draft release name
|
||||
# DRAFT_TAG=$(echo "$OUTPUT" | grep -o 'releases/tag/[^ ]*' | sed 's|releases/tag/||')
|
||||
# echo "draft_tag=$DRAFT_TAG" >> $GITHUB_OUTPUT
|
||||
# env:
|
||||
# GITHUB_TOKEN: ${{ steps.app-token.outputs.token }}
|
||||
#
|
||||
#
|
||||
#
|
||||
#
|
||||
# # - name: Build & publish Docker
|
||||
# # uses: ./.github/workflows/docker.yml
|
||||
# # with:
|
||||
# # add_latest: true
|
||||
# # secrets:
|
||||
# # DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME_2 }}
|
||||
# # DOCKER_PASSWORD: ${{ secrets.DOCKER_PASSWORD_2 }}
|
||||
#
|
||||
# - name: Publish GitHub Release
|
||||
# env:
|
||||
# GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
# run: |
|
||||
# gh release edit ${{ steps.release_step.outputs.draft_tag }} --draft=false
|
||||
#
|
||||
#
|
||||
# - name: Notify Discord
|
||||
# uses: ./.github/workflows/discord.yml
|
||||
# with:
|
||||
# discord_title: "New Release: v${{ steps.bump.outputs.version }}"
|
||||
# discord_color: 3066993
|
||||
# discord_footer: "Portabase"
|
||||
# secrets:
|
||||
# DISCORD_WEBHOOK: ${{ secrets.DISCORD_WEBHOOK }}
|
||||
# GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
|
||||
name: Auto Release & Publish
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- "*.*.*"
|
||||
- "!*-*"
|
||||
pull_request:
|
||||
types: [ closed ]
|
||||
branches:
|
||||
- main
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
contents: write
|
||||
packages: write
|
||||
|
||||
jobs:
|
||||
docker_publish:
|
||||
uses: ./.github/workflows/docker.yml
|
||||
with:
|
||||
add_latest: true
|
||||
secrets:
|
||||
DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME_2 }}
|
||||
DOCKER_PASSWORD: ${{ secrets.DOCKER_PASSWORD_2 }}
|
||||
create-release:
|
||||
if: github.event.pull_request.merged == true
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
draft_tag: ${{ steps.release_step.outputs.draft_tag }}
|
||||
steps:
|
||||
- uses: actions/create-github-app-token@v1
|
||||
id: app-token
|
||||
with:
|
||||
app-id: ${{ vars.APP_ID }}
|
||||
private-key: ${{ secrets.APP_PRIVATE_KEY }}
|
||||
|
||||
discord_notification:
|
||||
needs: docker_publish
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
token: ${{ steps.app-token.outputs.token }}
|
||||
ref: main
|
||||
|
||||
- uses: pnpm/action-setup@v4
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: "lts/*"
|
||||
cache: "pnpm"
|
||||
|
||||
- run: pnpm install --frozen-lockfile
|
||||
|
||||
- run: |
|
||||
git config --global user.name 'github-actions[bot]'
|
||||
git config --global user.email 'github-actions[bot]@users.noreply.github.com'
|
||||
|
||||
- name: Run release-it
|
||||
id: release_step
|
||||
run: |
|
||||
git pull origin main
|
||||
OUTPUT=$(pnpm exec release-it --ci)
|
||||
echo "$OUTPUT"
|
||||
DRAFT_TAG=$(echo "$OUTPUT" | grep -o 'releases/tag/[^ ]*' | sed 's|releases/tag/||')
|
||||
echo "draft_tag=$DRAFT_TAG" >> $GITHUB_OUTPUT
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ steps.app-token.outputs.token }}
|
||||
|
||||
|
||||
# publish-docker:
|
||||
# uses: ./.github/workflows/docker.yml
|
||||
# with:
|
||||
# add_latest: true
|
||||
# secrets:
|
||||
# DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME_2 }}
|
||||
# DOCKER_PASSWORD: ${{ secrets.DOCKER_PASSWORD_2 }}
|
||||
|
||||
finalize-release:
|
||||
needs: create-release
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
release_tag: ${{ steps.publish_release_step.outputs.release_tag }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Publish GitHub Release
|
||||
id: publish_release_step
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: |
|
||||
OUTPUT=$(gh release edit ${{ needs.create-release.outputs.draft_tag }} --draft=false)
|
||||
echo "$OUTPUT"
|
||||
RELEASE_TAG=$(echo "$OUTPUT" | sed -E 's|.*/releases/tag/||')
|
||||
echo "release_tag=$RELEASE_TAG" >> $GITHUB_OUTPUT
|
||||
|
||||
|
||||
notify-discord:
|
||||
needs: finalize-release
|
||||
uses: ./.github/workflows/discord.yml
|
||||
with:
|
||||
discord_title: "New Release: ${{ github.ref_name }}"
|
||||
release_tag: ${{ needs.create-release.outputs.draft_tag }}
|
||||
discord_title: "New Release"
|
||||
discord_color: 3066993
|
||||
discord_footer: "Portabase"
|
||||
secrets:
|
||||
DISCORD_WEBHOOK: ${{ secrets.DISCORD_WEBHOOK }}
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
+39
-7
@@ -1,25 +1,57 @@
|
||||
{
|
||||
"github": {
|
||||
"release": true,
|
||||
"draft": true,
|
||||
"tokenRef": "GITHUB_TOKEN",
|
||||
"update": true
|
||||
},
|
||||
"git": {
|
||||
"commit": true,
|
||||
"commitMessage": "chore: release v${version}",
|
||||
"commitMessage": "chore: release ${version}",
|
||||
"requireCleanWorkingDir": true,
|
||||
"tag": true,
|
||||
"tagName": "${version}",
|
||||
"push": true
|
||||
},
|
||||
"github": {
|
||||
"release": true,
|
||||
"tokenRef": "GITHUB_TOKEN"
|
||||
},
|
||||
"plugins": {
|
||||
"@release-it/conventional-changelog": {
|
||||
"preset": "angular"
|
||||
"preset": {
|
||||
"name": "conventionalcommits",
|
||||
"types": [
|
||||
{
|
||||
"type": "feat",
|
||||
"section": "✨ Features"
|
||||
},
|
||||
{
|
||||
"type": "fix",
|
||||
"section": "🐛 Bug Fixes"
|
||||
},
|
||||
{
|
||||
"type": "perf",
|
||||
"section": "⚡️ Performance Improvements"
|
||||
},
|
||||
{
|
||||
"type": "revert",
|
||||
"section": "⏪️ Reverts"
|
||||
},
|
||||
{
|
||||
"type": "docs",
|
||||
"section": "📝 Documentation",
|
||||
"hidden": true
|
||||
},
|
||||
{
|
||||
"type": "chore",
|
||||
"section": "🔧 Chores",
|
||||
"hidden": true
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"@release-it/bumper": {
|
||||
"out": {
|
||||
"file": "CITATION.cff",
|
||||
"path": "version",
|
||||
"type": "text/plain"
|
||||
"type": "text/yaml"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+9
-4
@@ -1,6 +1,6 @@
|
||||
cff-version: 1.2.0
|
||||
title: Portabase
|
||||
message: "If you use this software, please cite it as below."
|
||||
message: If you use this software, please cite it as below.
|
||||
type: software
|
||||
authors:
|
||||
- family-names: Gauthereau
|
||||
@@ -9,7 +9,12 @@ authors:
|
||||
given-names: Killian
|
||||
repository-code: https://github.com/Portabase/portabase
|
||||
url: https://portabase.io
|
||||
abstract: "Portabase is a free, open-source, self-hosted solution for database administration, providing backup and restore capabilities, scheduling, retention policies, notifications, and support for multiple storage backends. Its headless agent architecture enables connection to multiple database instances securely and efficiently."
|
||||
abstract: >-
|
||||
Portabase is a free, open-source, self-hosted solution for database
|
||||
administration, providing backup and restore capabilities, scheduling,
|
||||
retention policies, notifications, and support for multiple storage backends.
|
||||
Its headless agent architecture enables connection to multiple database
|
||||
instances securely and efficiently.
|
||||
keywords:
|
||||
- docker
|
||||
- kubernetes
|
||||
@@ -26,5 +31,5 @@ keywords:
|
||||
- web-ui
|
||||
- agent
|
||||
license: Apache-2.0
|
||||
version: 1.4.3
|
||||
date-released: "2026-03-02"
|
||||
version: 1.4.51
|
||||
date-released: '2026-03-02'
|
||||
|
||||
+1
-2
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "portabase",
|
||||
"version": "1.4.11",
|
||||
"version": "1.4.51",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "next dev --turbopack -p 8887",
|
||||
@@ -50,7 +50,6 @@
|
||||
"@t3-oss/env-nextjs": "^0.13.10",
|
||||
"@tanstack/react-query": "^5.90.21",
|
||||
"@tanstack/react-table": "^8.21.3",
|
||||
"@types/express": "^5.0.6",
|
||||
"@types/nodemailer": "^6.4.23",
|
||||
"@types/ws": "^8.18.1",
|
||||
"@zenstackhq/runtime": "2.14.2",
|
||||
|
||||
Generated
-67
@@ -113,9 +113,6 @@ importers:
|
||||
'@tanstack/react-table':
|
||||
specifier: ^8.21.3
|
||||
version: 8.21.3(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
|
||||
'@types/express':
|
||||
specifier: ^5.0.6
|
||||
version: 5.0.6
|
||||
'@types/nodemailer':
|
||||
specifier: ^6.4.23
|
||||
version: 6.4.23
|
||||
@@ -3143,12 +3140,6 @@ packages:
|
||||
'@tybys/wasm-util@0.10.1':
|
||||
resolution: {integrity: sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==}
|
||||
|
||||
'@types/body-parser@1.19.6':
|
||||
resolution: {integrity: sha512-HLFeCYgz89uk22N5Qg3dvGvsv46B8GLvKKo1zKG4NybA8U2DiEO3w9lqGg29t/tfLRJpJ6iQxnVw4OnB7MoM9g==}
|
||||
|
||||
'@types/connect@3.4.38':
|
||||
resolution: {integrity: sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==}
|
||||
|
||||
'@types/cors@2.8.19':
|
||||
resolution: {integrity: sha512-mFNylyeyqN93lfe/9CSxOGREz8cpzAhH+E93xJ4xWQf62V8sQ/24reV2nyzUWM6H6Xji+GGHpkbLe7pVoUEskg==}
|
||||
|
||||
@@ -3191,15 +3182,6 @@ packages:
|
||||
'@types/estree@1.0.8':
|
||||
resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==}
|
||||
|
||||
'@types/express-serve-static-core@5.1.1':
|
||||
resolution: {integrity: sha512-v4zIMr/cX7/d2BpAEX3KNKL/JrT1s43s96lLvvdTmza1oEvDudCqK9aF/djc/SWgy8Yh0h30TZx5VpzqFCxk5A==}
|
||||
|
||||
'@types/express@5.0.6':
|
||||
resolution: {integrity: sha512-sKYVuV7Sv9fbPIt/442koC7+IIwK5olP1KWeD88e/idgoJqDm3JV/YUiPwkoKK92ylff2MGxSz1CSjsXelx0YA==}
|
||||
|
||||
'@types/http-errors@2.0.5':
|
||||
resolution: {integrity: sha512-r8Tayk8HJnX0FztbZN7oVqGccWgw98T/0neJphO91KkmOzug1KkofZURD4UaD5uH8AqcFLfdPErnBod0u71/qg==}
|
||||
|
||||
'@types/json-schema@7.0.15':
|
||||
resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==}
|
||||
|
||||
@@ -3237,12 +3219,6 @@ packages:
|
||||
'@types/prismjs@1.26.6':
|
||||
resolution: {integrity: sha512-vqlvI7qlMvcCBbVe0AKAb4f97//Hy0EBTaiW8AalRnG/xAN5zOiWWyrNqNXeq8+KAuvRewjCVY1+IPxk4RdNYw==}
|
||||
|
||||
'@types/qs@6.14.0':
|
||||
resolution: {integrity: sha512-eOunJqu0K1923aExK6y8p6fsihYEn/BYuQ4g0CxAAgFc4b/ZLN4CrsRZ55srTdqoiLzU2B2evC+apEIxprEzkQ==}
|
||||
|
||||
'@types/range-parser@1.2.7':
|
||||
resolution: {integrity: sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==}
|
||||
|
||||
'@types/react-dom@19.0.4':
|
||||
resolution: {integrity: sha512-4fSQ8vWFkg+TGhePfUzVmat3eC14TXYSsiiDSLI0dVLsrm9gZFABjPy/Qu6TKgl1tq1Bu1yDsuQgY3A3DOjCcg==}
|
||||
peerDependencies:
|
||||
@@ -3259,12 +3235,6 @@ packages:
|
||||
'@types/react@19.2.14':
|
||||
resolution: {integrity: sha512-ilcTH/UniCkMdtexkoCN0bI7pMcJDvmQFPvuPvmEaYA/NSfFTAgdUSLAoVjaRJm7+6PvcM+q1zYOwS4wTYMF9w==}
|
||||
|
||||
'@types/send@1.2.1':
|
||||
resolution: {integrity: sha512-arsCikDvlU99zl1g69TcAB3mzZPpxgw0UQnaHeC1Nwb015xp8bknZv5rIfri9xTOcMuaVgvabfIRA7PSZVuZIQ==}
|
||||
|
||||
'@types/serve-static@2.2.0':
|
||||
resolution: {integrity: sha512-8mam4H1NHLtu7nmtalF7eyBH14QyOASmcxHhSfEoRyr0nP/YdoesEtU+uSRvMe96TW/HPTtkoKqQLl53N7UXMQ==}
|
||||
|
||||
'@types/webpack@5.28.5':
|
||||
resolution: {integrity: sha512-wR87cgvxj3p6D0Crt1r5avwqffqPXUkNlnQ1mjU93G7gCuFjufZR4I6j8cz5g1F1tTYpfOOFvly+cmIQwL9wvw==}
|
||||
|
||||
@@ -10490,15 +10460,6 @@ snapshots:
|
||||
tslib: 2.8.1
|
||||
optional: true
|
||||
|
||||
'@types/body-parser@1.19.6':
|
||||
dependencies:
|
||||
'@types/connect': 3.4.38
|
||||
'@types/node': 22.19.11
|
||||
|
||||
'@types/connect@3.4.38':
|
||||
dependencies:
|
||||
'@types/node': 22.19.11
|
||||
|
||||
'@types/cors@2.8.19':
|
||||
dependencies:
|
||||
'@types/node': 22.19.11
|
||||
@@ -10543,21 +10504,6 @@ snapshots:
|
||||
|
||||
'@types/estree@1.0.8': {}
|
||||
|
||||
'@types/express-serve-static-core@5.1.1':
|
||||
dependencies:
|
||||
'@types/node': 22.19.11
|
||||
'@types/qs': 6.14.0
|
||||
'@types/range-parser': 1.2.7
|
||||
'@types/send': 1.2.1
|
||||
|
||||
'@types/express@5.0.6':
|
||||
dependencies:
|
||||
'@types/body-parser': 1.19.6
|
||||
'@types/express-serve-static-core': 5.1.1
|
||||
'@types/serve-static': 2.2.0
|
||||
|
||||
'@types/http-errors@2.0.5': {}
|
||||
|
||||
'@types/json-schema@7.0.15': {}
|
||||
|
||||
'@types/json5@0.0.29': {}
|
||||
@@ -10598,10 +10544,6 @@ snapshots:
|
||||
|
||||
'@types/prismjs@1.26.6': {}
|
||||
|
||||
'@types/qs@6.14.0': {}
|
||||
|
||||
'@types/range-parser@1.2.7': {}
|
||||
|
||||
'@types/react-dom@19.0.4(@types/react@19.0.10)':
|
||||
dependencies:
|
||||
'@types/react': 19.0.10
|
||||
@@ -10618,15 +10560,6 @@ snapshots:
|
||||
dependencies:
|
||||
csstype: 3.2.3
|
||||
|
||||
'@types/send@1.2.1':
|
||||
dependencies:
|
||||
'@types/node': 22.19.11
|
||||
|
||||
'@types/serve-static@2.2.0':
|
||||
dependencies:
|
||||
'@types/http-errors': 2.0.5
|
||||
'@types/node': 22.19.11
|
||||
|
||||
'@types/webpack@5.28.5(esbuild@0.25.10)':
|
||||
dependencies:
|
||||
'@types/node': 22.19.11
|
||||
|
||||
+232
-53
@@ -1,62 +1,241 @@
|
||||
"use client"
|
||||
import {Eye} from "lucide-react";
|
||||
|
||||
import {useState} from "react";
|
||||
"use client";
|
||||
import {
|
||||
Dialog,
|
||||
DialogContent,
|
||||
DialogDescription,
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
DialogTrigger
|
||||
AlertCircle,
|
||||
Braces,
|
||||
Database,
|
||||
ExternalLink,
|
||||
Eye,
|
||||
Hash,
|
||||
Server,
|
||||
Sparkles,
|
||||
} from "lucide-react";
|
||||
import { useState } from "react";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import {
|
||||
Dialog,
|
||||
DialogContent,
|
||||
DialogDescription,
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
DialogTrigger,
|
||||
} from "@/components/ui/dialog";
|
||||
import {Button} from "@/components/ui/button";
|
||||
import {Separator} from "@/components/ui/separator";
|
||||
import {NotificationLogWithRelations} from "@/db/services/notification-log";
|
||||
import type { NotificationLogWithRelations } from "@/db/services/notification-log";
|
||||
|
||||
type NotificationLogModalProps = {
|
||||
notificationLog: NotificationLogWithRelations;
|
||||
}
|
||||
notificationLog: NotificationLogWithRelations;
|
||||
};
|
||||
|
||||
export const NotificationLogModal = ({notificationLog}: NotificationLogModalProps) => {
|
||||
const [open, setOpen] = useState(false);
|
||||
const getTroubleshootingForError = (errorMsg?: any) => {
|
||||
if (!errorMsg || String(errorMsg).toLowerCase() === "null") return null;
|
||||
|
||||
return (
|
||||
<Dialog open={open} onOpenChange={setOpen}>
|
||||
<DialogTrigger asChild>
|
||||
<Button variant="outline" onClick={() => setOpen(true)} className="relative">
|
||||
<Eye/>
|
||||
</Button>
|
||||
</DialogTrigger>
|
||||
<DialogContent>
|
||||
<DialogHeader>
|
||||
<DialogTitle>Notification details</DialogTitle>
|
||||
<DialogDescription>
|
||||
Details of the notification sent
|
||||
</DialogDescription>
|
||||
<Separator className="mt-3 mb-3"/>
|
||||
const msg = String(errorMsg).toLowerCase();
|
||||
|
||||
<div className="space-y-2 mb-4">
|
||||
<div>
|
||||
<span className="font-semibold">Title:</span>{" "}
|
||||
<span>{notificationLog.content.title}</span>
|
||||
</div>
|
||||
<div>
|
||||
<span className="font-semibold">Message:</span>{" "}
|
||||
<span>{notificationLog.content.message}</span>
|
||||
</div>
|
||||
if (msg.includes("database connection") || msg.includes("agent")) {
|
||||
return {
|
||||
title: "Agent Connection Issue",
|
||||
resolution:
|
||||
"It appears the agent cannot reach the database. Please ensure that your agent is actively running, your PostgreSQL credentials are correct, and port 5432 is open on your firewall.",
|
||||
docLink:
|
||||
"https://portabase.io/docs/agent/troubleshooting/agent-connection",
|
||||
};
|
||||
}
|
||||
|
||||
if (msg.includes("timeout")) {
|
||||
return {
|
||||
title: "Timeout",
|
||||
resolution:
|
||||
"The agent is taking too long to respond. This could be due to high server load, network issues, or a large database.",
|
||||
docLink: "https://portabase.io/docs/agent/troubleshooting/timeout",
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
title: "Unexpected Execution Error",
|
||||
resolution:
|
||||
"An unexpected error occurred during execution. Please review the raw system logs or contact support if the issue persists.",
|
||||
docLink: "https://discord.gg/Wgv7xZ8fWJ",
|
||||
};
|
||||
};
|
||||
|
||||
const getIconForKey = (key: string, value: any) => {
|
||||
const isActualError =
|
||||
key.toLowerCase().includes("error") &&
|
||||
value !== null &&
|
||||
String(value).toLowerCase() !== "null";
|
||||
|
||||
if (key.toLowerCase().includes("id"))
|
||||
return <Hash className="w-3.5 h-3.5 text-muted-foreground" />;
|
||||
if (key.toLowerCase().includes("host"))
|
||||
return <Server className="w-3.5 h-3.5 text-muted-foreground" />;
|
||||
if (isActualError)
|
||||
return <AlertCircle className="w-3.5 h-3.5 text-destructive" />;
|
||||
return <Database className="w-3.5 h-3.5 text-muted-foreground" />;
|
||||
};
|
||||
|
||||
export const NotificationLogModal = ({
|
||||
notificationLog,
|
||||
}: NotificationLogModalProps) => {
|
||||
const [open, setOpen] = useState(false);
|
||||
|
||||
// TODO : to be fixed
|
||||
// @ts-ignore
|
||||
const payloadError = notificationLog.payload?.error;
|
||||
const troubleshooting = getTroubleshootingForError(payloadError);
|
||||
|
||||
return (
|
||||
<Dialog open={open} onOpenChange={setOpen}>
|
||||
<DialogTrigger asChild>
|
||||
<Button
|
||||
variant="outline"
|
||||
onClick={() => setOpen(true)}
|
||||
className="relative"
|
||||
>
|
||||
<Eye className="w-4 h-4" />
|
||||
</Button>
|
||||
</DialogTrigger>
|
||||
<DialogContent className="sm:max-w-xl bg-background">
|
||||
<DialogHeader>
|
||||
<DialogTitle>Notification Details</DialogTitle>
|
||||
<DialogDescription>Execution logs and payload data</DialogDescription>
|
||||
</DialogHeader>
|
||||
|
||||
<div className="space-y-4 mt-2 max-h-[70vh] overflow-y-auto px-1 pb-2">
|
||||
<div className="relative border rounded-xl bg-card shadow-sm flex flex-col">
|
||||
<div className="bg-primary/5 border-b px-4 py-2.5 flex items-center gap-2 rounded-t-xl">
|
||||
<div className="p-1 bg-primary/10 rounded-md">
|
||||
<Database className="w-4 h-4 text-primary" />
|
||||
</div>
|
||||
<span className="font-semibold text-sm text-primary">
|
||||
Event Trigger
|
||||
</span>
|
||||
</div>
|
||||
<div className="p-4 flex flex-col gap-4">
|
||||
<div className="flex flex-col sm:flex-row sm:items-start justify-between gap-1 sm:gap-4">
|
||||
<span className="text-xs font-medium text-muted-foreground min-w-20 pt-0.5">
|
||||
Title
|
||||
</span>
|
||||
<span className="text-sm sm:text-right flex-1 wrap-break-words">
|
||||
{notificationLog.content.title}
|
||||
</span>
|
||||
</div>
|
||||
<div className="flex flex-col sm:flex-row sm:items-start justify-between gap-1 sm:gap-4">
|
||||
<span className="text-xs font-medium text-muted-foreground min-w-20 pt-0.5">
|
||||
Message
|
||||
</span>
|
||||
<span className="text-sm sm:text-right flex-1 wrap-break-word text-muted-foreground">
|
||||
{notificationLog.content.message}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
{notificationLog.payload && (
|
||||
<div className="absolute -bottom-1.5 left-1/2 -translate-x-1/2 w-3 h-3 bg-primary rounded-full border-2 border-background z-10" />
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className="w-px h-6 bg-border mx-auto -my-4 relative z-0" />
|
||||
|
||||
{notificationLog.payload &&
|
||||
Object.keys(notificationLog.payload).length > 0 && (
|
||||
<div className="relative border rounded-xl bg-card shadow-sm flex flex-col">
|
||||
<div className="absolute -top-1.5 left-1/2 -translate-x-1/2 w-3 h-3 bg-primary rounded-full border-2 border-background z-10" />
|
||||
|
||||
<div className="bg-primary/5 border-b px-4 py-2.5 flex items-center justify-between rounded-t-xl">
|
||||
<div className="flex items-center gap-2">
|
||||
<div className="p-1 bg-primary/10 rounded-md">
|
||||
<Braces className="w-4 h-4 text-primary" />
|
||||
</div>
|
||||
<span className="font-semibold text-sm text-primary">
|
||||
JSON Payload
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{notificationLog.payload && (
|
||||
<>
|
||||
<Separator className="mb-3" />
|
||||
<div className="text-sm font-mono bg-gray-100 dark:bg-gray-800 dark:text-gray-200 p-4 rounded-md overflow-auto">
|
||||
{JSON.stringify(notificationLog.payload, null, 2)}
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
</DialogHeader>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
)
|
||||
}
|
||||
<div className="flex flex-col">
|
||||
{Object.entries(notificationLog.payload).map(
|
||||
([key, value], index, arr) => {
|
||||
const isActualError =
|
||||
key === "error" &&
|
||||
value !== null &&
|
||||
String(value).toLowerCase() !== "null";
|
||||
|
||||
return (
|
||||
<div
|
||||
key={key}
|
||||
className={`flex flex-col sm:flex-row sm:items-center justify-between gap-2 px-4 py-3 hover:bg-muted/50 transition-colors ${
|
||||
index !== arr.length - 1
|
||||
? "border-b border-border/50"
|
||||
: ""
|
||||
}`}
|
||||
>
|
||||
<div className="flex items-center gap-2 min-w-[150px]">
|
||||
{getIconForKey(key, value)}
|
||||
<span className="text-sm font-medium">{key}</span>
|
||||
</div>
|
||||
<div className="flex-1 sm:text-right">
|
||||
{isActualError ? (
|
||||
<span className="inline-flex items-center px-2 py-1 rounded-md bg-destructive/10 text-destructive text-xs font-mono break-all">
|
||||
{String(value)}
|
||||
</span>
|
||||
) : (
|
||||
<span className="text-sm text-muted-foreground font-mono bg-muted px-2 py-1 rounded-md break-all">
|
||||
{String(value)}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
)}
|
||||
</div>
|
||||
|
||||
{troubleshooting && (
|
||||
<div className="absolute -bottom-1.5 left-1/2 -translate-x-1/2 w-3 h-3 bg-primary rounded-full border-2 border-background z-10" />
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
|
||||
{troubleshooting && (
|
||||
<>
|
||||
<div className="w-px h-6 bg-border mx-auto -my-4 relative z-0" />
|
||||
|
||||
<div className="relative border border-destructive/20 rounded-xl bg-gradient-to-b from-destructive/5 to-transparent shadow-sm flex flex-col">
|
||||
<div className="absolute -top-1.5 left-1/2 -translate-x-1/2 w-3 h-3 bg-destructive rounded-full border-2 border-background z-10" />
|
||||
|
||||
<div className="bg-destructive/10 border-b border-destructive/10 px-4 py-2.5 flex items-center justify-between rounded-t-xl">
|
||||
<div className="flex items-center gap-2">
|
||||
<div className="p-1 bg-destructive/20 rounded-md">
|
||||
<Sparkles className="w-4 h-4 text-destructive" />
|
||||
</div>
|
||||
<span className="font-semibold text-sm text-destructive">
|
||||
Suggested Resolution
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="p-4 flex flex-col gap-2">
|
||||
<h4 className="text-sm font-semibold text-foreground">
|
||||
{troubleshooting.title}
|
||||
</h4>
|
||||
<p className="text-sm text-muted-foreground leading-relaxed">
|
||||
{troubleshooting.resolution}
|
||||
</p>
|
||||
<div className="mt-2">
|
||||
<a
|
||||
href={troubleshooting.docLink}
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
className="inline-flex items-center gap-1.5 text-xs font-semibold text-destructive hover:text-destructive/80 transition-colors"
|
||||
>
|
||||
Read the documentation{" "}
|
||||
<ExternalLink className="w-3.5 h-3.5" />
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user