Compare commits
11 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 2e7a52ed15 | |||
| 221b3533e5 | |||
| 578dccd0cf | |||
| 0ecad475ef | |||
| d5789b79a6 | |||
| 45ce90f3cc | |||
| 3a817625c5 | |||
| d5abea48b3 | |||
| 1da69ac272 | |||
| bd2092a3ea | |||
| afb6fb8ac7 |
@@ -7,10 +7,10 @@ jobs:
|
|||||||
lint:
|
lint:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v6
|
- uses: https://git.keligrubb.com/actions/checkout@v6
|
||||||
|
|
||||||
- name: Setup Node.js
|
- name: Setup Node.js
|
||||||
uses: actions/setup-node@v6
|
uses: https://git.keligrubb.com/actions/setup-node@v6
|
||||||
with:
|
with:
|
||||||
node-version: "24"
|
node-version: "24"
|
||||||
cache: "npm"
|
cache: "npm"
|
||||||
@@ -24,10 +24,10 @@ jobs:
|
|||||||
test:
|
test:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v6
|
- uses: https://git.keligrubb.com/actions/checkout@v6
|
||||||
|
|
||||||
- name: Setup Node.js
|
- name: Setup Node.js
|
||||||
uses: actions/setup-node@v6
|
uses: https://git.keligrubb.com/actions/setup-node@v6
|
||||||
with:
|
with:
|
||||||
node-version: "24"
|
node-version: "24"
|
||||||
cache: "npm"
|
cache: "npm"
|
||||||
@@ -43,10 +43,10 @@ jobs:
|
|||||||
container:
|
container:
|
||||||
image: mcr.microsoft.com/playwright:v1.58.2-noble
|
image: mcr.microsoft.com/playwright:v1.58.2-noble
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v6
|
- uses: https://git.keligrubb.com/actions/checkout@v6
|
||||||
|
|
||||||
- name: Setup Node.js
|
- name: Setup Node.js
|
||||||
uses: actions/setup-node@v6
|
uses: https://git.keligrubb.com/actions/setup-node@v6
|
||||||
with:
|
with:
|
||||||
node-version: "24"
|
node-version: "24"
|
||||||
cache: "npm"
|
cache: "npm"
|
||||||
@@ -65,7 +65,7 @@ jobs:
|
|||||||
docker-build:
|
docker-build:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v6
|
- uses: https://git.keligrubb.com/actions/checkout@v6
|
||||||
|
|
||||||
- name: Set Docker image tag
|
- name: Set Docker image tag
|
||||||
id: image
|
id: image
|
||||||
@@ -75,10 +75,10 @@ jobs:
|
|||||||
echo "tag=${REGISTRY}/${{ github.repository }}:latest" >> $GITHUB_OUTPUT
|
echo "tag=${REGISTRY}/${{ github.repository }}:latest" >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
- name: Set up Docker Buildx
|
- name: Set up Docker Buildx
|
||||||
uses: docker/setup-buildx-action@v3
|
uses: https://git.keligrubb.com/actions/docker-setup-buildx-action@v4
|
||||||
|
|
||||||
- name: Build (dry run)
|
- name: Build (dry run)
|
||||||
uses: docker/build-push-action@v6
|
uses: https://git.keligrubb.com/actions/docker-build-push-action@v7
|
||||||
with:
|
with:
|
||||||
context: .
|
context: .
|
||||||
push: false
|
push: false
|
||||||
|
|||||||
+14
-10
@@ -8,7 +8,7 @@ jobs:
|
|||||||
release-docker-helm:
|
release-docker-helm:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v6
|
- uses: https://git.keligrubb.com/actions/checkout@v6
|
||||||
with:
|
with:
|
||||||
token: ${{ secrets.KESTRELOS_REPO_TOKEN }}
|
token: ${{ secrets.KESTRELOS_REPO_TOKEN }}
|
||||||
|
|
||||||
@@ -24,15 +24,17 @@ jobs:
|
|||||||
./scripts/release.sh
|
./scripts/release.sh
|
||||||
|
|
||||||
- name: Log in to container registry
|
- name: Log in to container registry
|
||||||
run: |
|
uses: https://git.keligrubb.com/actions/docker-login-action@v4
|
||||||
REGISTRY="${GITHUB_SERVER_URL#https://}"
|
with:
|
||||||
echo "${{ secrets.GITEA_REGISTRY_TOKEN }}" | docker login "$REGISTRY" -u "${{ github.actor }}" --password-stdin
|
registry: git.keligrubb.com
|
||||||
|
username: ${{ github.actor }}
|
||||||
|
password: ${{ secrets.KESTRELOS_REPO_TOKEN }}
|
||||||
|
|
||||||
- name: Set up Docker Buildx
|
- name: Set up Docker Buildx
|
||||||
uses: docker/setup-buildx-action@v3
|
uses: https://git.keligrubb.com/actions/docker-setup-buildx-action@v4
|
||||||
|
|
||||||
- name: Build Docker image
|
- name: Build Docker image
|
||||||
uses: docker/build-push-action@v6
|
uses: https://git.keligrubb.com/actions/docker-build-push-action@v7
|
||||||
with:
|
with:
|
||||||
context: .
|
context: .
|
||||||
load: true
|
load: true
|
||||||
@@ -40,20 +42,22 @@ jobs:
|
|||||||
|
|
||||||
- name: Push Docker image (all tags from .tags)
|
- name: Push Docker image (all tags from .tags)
|
||||||
run: |
|
run: |
|
||||||
REGISTRY="${GITHUB_SERVER_URL#https://}"
|
REGISTRY="git.keligrubb.com"
|
||||||
IMAGE="$REGISTRY/${{ github.repository }}"
|
IMAGE="$REGISTRY/${{ github.repository }}"
|
||||||
while read -r tag; do
|
while read -r tag; do
|
||||||
docker tag kestrelos:built "$IMAGE:$tag"
|
docker tag kestrelos:built "$IMAGE:$tag"
|
||||||
docker push "$IMAGE:$tag"
|
docker push "$IMAGE:$tag"
|
||||||
done < .tags
|
done < .tags
|
||||||
|
|
||||||
|
- name: Set up Helm
|
||||||
|
uses: https://git.keligrubb.com/actions/setup-helm@v5
|
||||||
|
|
||||||
- name: Package and push Helm chart
|
- name: Package and push Helm chart
|
||||||
env:
|
env:
|
||||||
GITEA_REGISTRY_TOKEN: ${{ secrets.GITEA_REGISTRY_TOKEN }}
|
GITEA_REPO_TOKEN: ${{ secrets.KESTRELOS_REPO_TOKEN }}
|
||||||
run: |
|
run: |
|
||||||
curl -sSfL https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash
|
|
||||||
helm package helm/kestrelos
|
helm package helm/kestrelos
|
||||||
for f in kestrelos-*.tgz; do
|
for f in kestrelos-*.tgz; do
|
||||||
curl -sf -u "${{ github.actor }}:$GITEA_REGISTRY_TOKEN" -X POST --upload-file "$f" \
|
curl -sf -u "${{ github.actor }}:$GITEA_REPO_TOKEN" -X POST --upload-file "$f" \
|
||||||
"${{ github.server_url }}/api/packages/${{ github.actor }}/helm/api/charts"
|
"${{ github.server_url }}/api/packages/${{ github.actor }}/helm/api/charts"
|
||||||
done
|
done
|
||||||
|
|||||||
@@ -1,3 +1,23 @@
|
|||||||
|
## [1.0.9] - 2026-03-24
|
||||||
|
### Changed
|
||||||
|
- update https://git.keligrubb.com/actions/setup-helm action to v5 (#23)
|
||||||
|
|
||||||
|
## [1.0.8] - 2026-03-12
|
||||||
|
### Changed
|
||||||
|
- fix release file (#22)
|
||||||
|
|
||||||
|
## [1.0.7] - 2026-03-06
|
||||||
|
### Changed
|
||||||
|
- chore(deps): update docker/build-push-action action to v7 (#19)
|
||||||
|
|
||||||
|
## [1.0.6] - 2026-03-05
|
||||||
|
### Changed
|
||||||
|
- fix docker login during push stage (#18)
|
||||||
|
|
||||||
|
## [1.0.5] - 2026-03-05
|
||||||
|
### Changed
|
||||||
|
- fix deploy pipeline stages for token registry uploads (#17)
|
||||||
|
|
||||||
## [1.0.4] - 2026-03-04
|
## [1.0.4] - 2026-03-04
|
||||||
### Changed
|
### Changed
|
||||||
- fix deploy pipeline (#15)
|
- fix deploy pipeline (#15)
|
||||||
|
|||||||
@@ -2,5 +2,5 @@ apiVersion: v2
|
|||||||
name: kestrelos
|
name: kestrelos
|
||||||
description: KestrelOS TOC for OSINT feeds - map, camera feeds, offline tiles
|
description: KestrelOS TOC for OSINT feeds - map, camera feeds, offline tiles
|
||||||
type: application
|
type: application
|
||||||
version: 1.0.4
|
version: 1.0.9
|
||||||
appVersion: "1.0.4"
|
appVersion: "1.0.9"
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ replicaCount: 1
|
|||||||
|
|
||||||
image:
|
image:
|
||||||
repository: git.keligrubb.com/keligrubb/kestrelos
|
repository: git.keligrubb.com/keligrubb/kestrelos
|
||||||
tag: 1.0.4
|
tag: 1.0.9
|
||||||
pullPolicy: IfNotPresent
|
pullPolicy: IfNotPresent
|
||||||
|
|
||||||
service:
|
service:
|
||||||
|
|||||||
Generated
+2570
-3820
File diff suppressed because it is too large
Load Diff
+1
-2
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "kestrelos",
|
"name": "kestrelos",
|
||||||
"version": "1.0.4",
|
"version": "1.0.9",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
@@ -31,7 +31,6 @@
|
|||||||
"nuxt": "^4.0.0",
|
"nuxt": "^4.0.0",
|
||||||
"openid-client": "^6.8.2",
|
"openid-client": "^6.8.2",
|
||||||
"qrcode": "^1.5.4",
|
"qrcode": "^1.5.4",
|
||||||
"sqlite3": "^5.1.7",
|
|
||||||
"vue": "^3.4.0",
|
"vue": "^3.4.0",
|
||||||
"vue-router": "^5.0.0",
|
"vue-router": "^5.0.0",
|
||||||
"ws": "^8.18.0"
|
"ws": "^8.18.0"
|
||||||
|
|||||||
+33
-7
@@ -3,8 +3,21 @@ set -e
|
|||||||
|
|
||||||
# version
|
# version
|
||||||
msg="${CI_COMMIT_MESSAGE:-}"
|
msg="${CI_COMMIT_MESSAGE:-}"
|
||||||
|
# optional PR body (written by workflow from Gitea API when this commit is a merged PR)
|
||||||
|
if [ -f .ci_pr_body ]; then
|
||||||
|
CI_PR_DESCRIPTION=$(cat .ci_pr_body); rm -f .ci_pr_body
|
||||||
|
else
|
||||||
|
CI_PR_DESCRIPTION=""
|
||||||
|
fi
|
||||||
|
export CI_PR_DESCRIPTION
|
||||||
bump=patch
|
bump=patch
|
||||||
echo "$msg" | grep -qi minor: && bump=minor
|
# Conventional commits: chore/fix => patch, feat => minor
|
||||||
|
echo "$msg" | grep -Eqi '(^|[[:space:]])(fix|chore)(\([^)]*\))?:' && bump=patch
|
||||||
|
echo "$msg" | grep -Eqi '(^|[[:space:]])feat(\([^)]*\))?:' && bump=minor
|
||||||
|
# Conventional commits breaking change: type!:
|
||||||
|
echo "$msg" | grep -Eqi '(^|[[:space:]])[a-zA-Z]+(\([^)]*\))?!:' && bump=major
|
||||||
|
# Explicit bump prefixes still supported (but never downgrade a major bump)
|
||||||
|
echo "$msg" | grep -qi minor: && [ "$bump" != "major" ] && bump=minor
|
||||||
echo "$msg" | grep -qi major: && bump=major
|
echo "$msg" | grep -qi major: && bump=major
|
||||||
cur=$(awk '/"version"/ { match($0, /[0-9]+\.[0-9]+\.[0-9]+/); print substr($0, RSTART, RLENGTH); exit }' package.json)
|
cur=$(awk '/"version"/ { match($0, /[0-9]+\.[0-9]+\.[0-9]+/); print substr($0, RSTART, RLENGTH); exit }' package.json)
|
||||||
major=$(echo "$cur" | cut -d. -f1); minor=$(echo "$cur" | cut -d. -f2); patch=$(echo "$cur" | cut -d. -f3)
|
major=$(echo "$cur" | cut -d. -f1); minor=$(echo "$cur" | cut -d. -f2); patch=$(echo "$cur" | cut -d. -f3)
|
||||||
@@ -12,9 +25,21 @@ case "$bump" in major) major=$((major+1)); minor=0; patch=0 ;; minor) minor=$((m
|
|||||||
newVersion="$major.$minor.$patch"
|
newVersion="$major.$minor.$patch"
|
||||||
[ -z "$cur" ] && { echo "error: could not read version from package.json"; exit 1; }
|
[ -z "$cur" ] && { echo "error: could not read version from package.json"; exit 1; }
|
||||||
|
|
||||||
# changelog entry (strip prefix from first line)
|
# changelog entry (strip explicit bump prefixes & any conventional-commit type(scope):); optional PR description enriches it
|
||||||
changelogEntry=$(echo "$msg" | head -1 | awk '{sub(/^[mM]ajor:[ \t]*/,""); sub(/^[mM]inor:[ \t]*/,""); sub(/^[pP]atch:[ \t]*/,""); print}')
|
changelogEntry=$(
|
||||||
|
echo "$msg" \
|
||||||
|
| head -1 \
|
||||||
|
| sed -E 's/^[[:space:]]*[mM]ajor:[[:space:]]*//; s/^[[:space:]]*[mM]inor:[[:space:]]*//; s/^[[:space:]]*[pP]atch:[[:space:]]*//' \
|
||||||
|
| sed -E 's/^[[:space:]]*[a-zA-Z]+(\([^)]*\))?:[[:space:]]*//'
|
||||||
|
)
|
||||||
[ -z "$changelogEntry" ] && changelogEntry="Release v$newVersion"
|
[ -z "$changelogEntry" ] && changelogEntry="Release v$newVersion"
|
||||||
|
if [ -n "$CI_PR_DESCRIPTION" ]; then
|
||||||
|
changelogFull="- $changelogEntry
|
||||||
|
|
||||||
|
$CI_PR_DESCRIPTION"
|
||||||
|
else
|
||||||
|
changelogFull="- $changelogEntry"
|
||||||
|
fi
|
||||||
|
|
||||||
# bump files
|
# bump files
|
||||||
awk -v v="$newVersion" '/"version"/ { sub(/[0-9]+\.[0-9]+\.[0-9]+/, v) } { print }' package.json > package.json.tmp && mv package.json.tmp package.json
|
awk -v v="$newVersion" '/"version"/ { sub(/[0-9]+\.[0-9]+\.[0-9]+/, v) } { print }' package.json > package.json.tmp && mv package.json.tmp package.json
|
||||||
@@ -24,10 +49,11 @@ awk -v v="$newVersion" '/^ tag:/ { $0 = " tag: " v }; { print }' helm/kestrelo
|
|||||||
# changelog
|
# changelog
|
||||||
new="## [$newVersion] - $(date +%Y-%m-%d)
|
new="## [$newVersion] - $(date +%Y-%m-%d)
|
||||||
### Changed
|
### Changed
|
||||||
- $changelogEntry
|
$changelogFull
|
||||||
|
|
||||||
"
|
"
|
||||||
{ [ ! -f CHANGELOG.md ] && printf '# Changelog\n\n'; printf '%s' "$new"; [ -f CHANGELOG.md ] && cat CHANGELOG.md; } > CHANGELOG.md.tmp && mv CHANGELOG.md.tmp CHANGELOG.md
|
# Create CHANGELOG.md if missing (first release); otherwise prepend new entry to existing content.
|
||||||
|
{ [ ! -f CHANGELOG.md ] && printf '# Changelog\n\n'; printf '%s' "$new"; [ -f CHANGELOG.md ] && cat CHANGELOG.md || true; } > CHANGELOG.md.tmp && mv CHANGELOG.md.tmp CHANGELOG.md
|
||||||
|
|
||||||
# git
|
# git
|
||||||
git config user.email "ci@kestrelos" && git config user.name "CI"
|
git config user.email "ci@kestrelos" && git config user.name "CI"
|
||||||
@@ -35,7 +61,7 @@ git add package.json helm/kestrelos/Chart.yaml helm/kestrelos/values.yaml CHANGE
|
|||||||
git commit -m "release v$newVersion [skip ci]"
|
git commit -m "release v$newVersion [skip ci]"
|
||||||
url="https://${CI_REPO_OWNER}:${GITEA_REPO_TOKEN}@${CI_FORGE_URL#https://}/${CI_REPO_OWNER}/${CI_REPO_NAME}.git"
|
url="https://${CI_REPO_OWNER}:${GITEA_REPO_TOKEN}@${CI_FORGE_URL#https://}/${CI_REPO_OWNER}/${CI_REPO_NAME}.git"
|
||||||
git tag "v$newVersion"
|
git tag "v$newVersion"
|
||||||
# artifact for kaniko (tag list)
|
# artifact for docker (tag list)
|
||||||
printf '%s\n%s\n' "$newVersion" "latest" > .tags
|
printf '%s\n%s\n' "$newVersion" "latest" > .tags
|
||||||
retry() { n=0; while ! "$@"; do n=$((n+1)); [ $n -ge 3 ] && return 1; sleep 2; done; }
|
retry() { n=0; while ! "$@"; do n=$((n+1)); [ $n -ge 3 ] && return 1; sleep 2; done; }
|
||||||
retry git push "$url" HEAD:main "v$newVersion"
|
retry git push "$url" HEAD:main "v$newVersion"
|
||||||
@@ -43,7 +69,7 @@ retry git push "$url" HEAD:main "v$newVersion"
|
|||||||
# gitea release
|
# gitea release
|
||||||
body="## Changelog
|
body="## Changelog
|
||||||
### Changed
|
### Changed
|
||||||
- $changelogEntry
|
$changelogFull
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
- [Docker image](${CI_FORGE_URL}/${CI_REPO_OWNER}/-/packages/container/${CI_REPO_NAME})
|
- [Docker image](${CI_FORGE_URL}/${CI_REPO_OWNER}/-/packages/container/${CI_REPO_NAME})
|
||||||
|
|||||||
+86
-24
@@ -1,14 +1,12 @@
|
|||||||
import { join, dirname } from 'node:path'
|
import { join, dirname } from 'node:path'
|
||||||
import { mkdirSync, existsSync } from 'node:fs'
|
import { mkdirSync, existsSync } from 'node:fs'
|
||||||
|
import { randomBytes, randomUUID } from 'node:crypto'
|
||||||
import { createRequire } from 'node:module'
|
import { createRequire } from 'node:module'
|
||||||
import { promisify } from 'node:util'
|
|
||||||
import { randomBytes } from 'node:crypto'
|
|
||||||
import { hashPassword } from './password.js'
|
import { hashPassword } from './password.js'
|
||||||
import { registerCleanup } from './shutdown.js'
|
import { registerCleanup } from './shutdown.js'
|
||||||
|
|
||||||
// Resolve from project root so bundled server (e.g. .output) finds node_modules/sqlite3
|
|
||||||
const requireFromRoot = createRequire(join(process.cwd(), 'package.json'))
|
const requireFromRoot = createRequire(join(process.cwd(), 'package.json'))
|
||||||
const sqlite3 = requireFromRoot('sqlite3')
|
const { DatabaseSync } = requireFromRoot('node:sqlite')
|
||||||
|
|
||||||
const SCHEMA_VERSION = 4
|
const SCHEMA_VERSION = 4
|
||||||
const DB_BUSY_TIMEOUT_MS = 5000
|
const DB_BUSY_TIMEOUT_MS = 5000
|
||||||
@@ -144,7 +142,6 @@ const initDb = async (db, run, all, get) => {
|
|||||||
catch {
|
catch {
|
||||||
// WAL not supported (e.g., network filesystem)
|
// WAL not supported (e.g., network filesystem)
|
||||||
}
|
}
|
||||||
db.configure('busyTimeout', DB_BUSY_TIMEOUT_MS)
|
|
||||||
|
|
||||||
await run(SCHEMA.schema_version)
|
await run(SCHEMA.schema_version)
|
||||||
await run(SCHEMA.users)
|
await run(SCHEMA.users)
|
||||||
@@ -168,7 +165,7 @@ const initDb = async (db, run, all, get) => {
|
|||||||
|
|
||||||
await run(
|
await run(
|
||||||
'INSERT INTO users (id, identifier, password_hash, role, created_at, auth_provider, oidc_issuer, oidc_sub) VALUES (?, ?, ?, ?, ?, ?, ?, ?)',
|
'INSERT INTO users (id, identifier, password_hash, role, created_at, auth_provider, oidc_issuer, oidc_sub) VALUES (?, ?, ?, ?, ?, ?, ?, ?)',
|
||||||
[crypto.randomUUID(), identifier, hashPassword(plainPassword), 'admin', new Date().toISOString(), 'local', null, null],
|
[randomUUID(), identifier, hashPassword(plainPassword), 'admin', new Date().toISOString(), 'local', null, null],
|
||||||
)
|
)
|
||||||
|
|
||||||
if (!email || !password) {
|
if (!email || !password) {
|
||||||
@@ -181,37 +178,104 @@ const initDb = async (db, run, all, get) => {
|
|||||||
export async function getDb() {
|
export async function getDb() {
|
||||||
if (dbInstance) return dbInstance
|
if (dbInstance) return dbInstance
|
||||||
|
|
||||||
const db = new sqlite3.Database(getDbPath(), (err) => {
|
const sqliteDb = (() => {
|
||||||
if (err) {
|
try {
|
||||||
|
return new DatabaseSync(getDbPath(), { timeout: DB_BUSY_TIMEOUT_MS })
|
||||||
|
}
|
||||||
|
catch (err) {
|
||||||
console.error('[db] Failed to open database:', err.message)
|
console.error('[db] Failed to open database:', err.message)
|
||||||
throw err
|
throw err
|
||||||
}
|
}
|
||||||
})
|
})()
|
||||||
|
|
||||||
const run = promisify(db.run.bind(db))
|
const run = (sql, params = []) =>
|
||||||
const all = promisify(db.all.bind(db))
|
new Promise((resolve, reject) => {
|
||||||
const get = promisify(db.get.bind(db))
|
const stmt = sqliteDb.prepare(sql)
|
||||||
|
try {
|
||||||
|
stmt.run(...params)
|
||||||
|
resolve()
|
||||||
|
}
|
||||||
|
catch (error) {
|
||||||
|
reject(error)
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
try {
|
||||||
|
stmt.finalize()
|
||||||
|
}
|
||||||
|
catch {
|
||||||
|
// ignore finalize errors
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const all = (sql, params = []) =>
|
||||||
|
new Promise((resolve, reject) => {
|
||||||
|
const stmt = sqliteDb.prepare(sql)
|
||||||
|
try {
|
||||||
|
const rows = stmt.all(...params)
|
||||||
|
resolve(rows)
|
||||||
|
}
|
||||||
|
catch (error) {
|
||||||
|
reject(error)
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
try {
|
||||||
|
stmt.finalize()
|
||||||
|
}
|
||||||
|
catch {
|
||||||
|
// ignore finalize errors
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const get = (sql, params = []) =>
|
||||||
|
new Promise((resolve, reject) => {
|
||||||
|
const stmt = sqliteDb.prepare(sql)
|
||||||
|
try {
|
||||||
|
const row = stmt.get(...params)
|
||||||
|
resolve(row)
|
||||||
|
}
|
||||||
|
catch (error) {
|
||||||
|
reject(error)
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
try {
|
||||||
|
stmt.finalize()
|
||||||
|
}
|
||||||
|
catch {
|
||||||
|
// ignore finalize errors
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const wrappedDb = {
|
||||||
|
close(callback) {
|
||||||
|
try {
|
||||||
|
sqliteDb.close()
|
||||||
|
if (typeof callback === 'function') callback(null)
|
||||||
|
}
|
||||||
|
catch (error) {
|
||||||
|
if (typeof callback === 'function') callback(error)
|
||||||
|
else throw error
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await initDb(db, run, all, get)
|
await initDb(wrappedDb, run, all, get)
|
||||||
}
|
}
|
||||||
catch (error) {
|
catch (error) {
|
||||||
db.close()
|
wrappedDb.close()
|
||||||
console.error('[db] Database initialization failed:', error.message)
|
console.error('[db] Database initialization failed:', error.message)
|
||||||
throw error
|
throw error
|
||||||
}
|
}
|
||||||
|
|
||||||
dbInstance = { db, run, all, get }
|
dbInstance = { db: wrappedDb, run, all, get }
|
||||||
|
|
||||||
registerCleanup(async () => {
|
registerCleanup(async () => {
|
||||||
if (dbInstance) {
|
if (dbInstance) {
|
||||||
try {
|
try {
|
||||||
await new Promise((resolve, reject) => {
|
dbInstance.db.close()
|
||||||
dbInstance.db.close((err) => {
|
|
||||||
if (err) reject(err)
|
|
||||||
else resolve()
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
catch (error) {
|
catch (error) {
|
||||||
console.error('[db] Error closing database during shutdown:', error?.message)
|
console.error('[db] Error closing database during shutdown:', error?.message)
|
||||||
@@ -290,9 +354,7 @@ export async function withTransaction(db, callback) {
|
|||||||
export function closeDb() {
|
export function closeDb() {
|
||||||
if (!dbInstance) return
|
if (!dbInstance) return
|
||||||
try {
|
try {
|
||||||
dbInstance.db.close((err) => {
|
dbInstance.db.close()
|
||||||
if (err) console.error('[db] Error closing database:', err.message)
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
catch (error) {
|
catch (error) {
|
||||||
console.error('[db] Error closing database:', error.message)
|
console.error('[db] Error closing database:', error.message)
|
||||||
|
|||||||
Reference in New Issue
Block a user