mirror of
https://github.com/okxlin/appstore.git
synced 2026-09-23 00:00:59 +00:00
feat(app): add nxv
This commit is contained in:
@@ -0,0 +1,3 @@
|
||||
PANEL_APP_PORT_HTTP=8080
|
||||
APP_DATA_DIR=./data
|
||||
CONTAINER_NAME=1Panel-localnxv
|
||||
@@ -0,0 +1,35 @@
|
||||
additionalProperties:
|
||||
formFields:
|
||||
- default: 8080
|
||||
edit: true
|
||||
envKey: PANEL_APP_PORT_HTTP
|
||||
labelEn: HTTP Port
|
||||
labelZh: HTTP 端口
|
||||
label:
|
||||
en: HTTP Port
|
||||
zh: HTTP 端口
|
||||
zh-Hant: HTTP 連接埠
|
||||
ja: HTTP ポート
|
||||
ko: HTTP 포트
|
||||
ru: Порт HTTP
|
||||
ms: Port HTTP
|
||||
pt-br: Porta HTTP
|
||||
required: true
|
||||
rule: paramPort
|
||||
type: number
|
||||
- default: ./data
|
||||
edit: true
|
||||
envKey: APP_DATA_DIR
|
||||
labelEn: Data Directory
|
||||
labelZh: 数据目录
|
||||
label:
|
||||
en: Data Directory
|
||||
zh: 数据目录
|
||||
zh-Hant: 資料目錄
|
||||
ja: データディレクトリ
|
||||
ko: 데이터 디렉터리
|
||||
ru: Каталог данных
|
||||
ms: Direktori data
|
||||
pt-br: Diretorio de dados
|
||||
required: true
|
||||
type: text
|
||||
@@ -0,0 +1,36 @@
|
||||
services:
|
||||
nxv:
|
||||
image: "ghcr.io/utensils/nxv:0.7.0@sha256:5c39000455d3bb91f91f311b98df42127fbf926381eaa67abdb4c2d234b0d799"
|
||||
container_name: ${CONTAINER_NAME}
|
||||
command:
|
||||
- --db-path
|
||||
- /data/index.db
|
||||
- serve
|
||||
- --host
|
||||
- 0.0.0.0
|
||||
- --port
|
||||
- "8080"
|
||||
ports:
|
||||
- "${PANEL_APP_PORT_HTTP}:8080"
|
||||
volumes:
|
||||
- "${APP_DATA_DIR}:/data"
|
||||
restart: unless-stopped
|
||||
healthcheck:
|
||||
test:
|
||||
- CMD
|
||||
- nxv
|
||||
- --db-path
|
||||
- /data/index.db
|
||||
- stats
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
start_period: 10s
|
||||
labels:
|
||||
createdBy: "Apps"
|
||||
networks:
|
||||
- 1panel-network
|
||||
|
||||
networks:
|
||||
1panel-network:
|
||||
external: true
|
||||
Executable
+72
@@ -0,0 +1,72 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd -P)"
|
||||
ENV_FILE="${ENV_FILE:-${ROOT_DIR}/.env}"
|
||||
IMAGE="ghcr.io/utensils/nxv:0.7.0@sha256:5c39000455d3bb91f91f311b98df42127fbf926381eaa67abdb4c2d234b0d799"
|
||||
|
||||
fail() {
|
||||
printf '%s\n' "$1" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
strip_matching_quotes() {
|
||||
local value="$1"
|
||||
|
||||
if [[ ${#value} -ge 2 ]]; then
|
||||
if [[ "${value:0:1}" == '"' && "${value: -1}" == '"' ]]; then
|
||||
value="${value:1:${#value}-2}"
|
||||
elif [[ "${value:0:1}" == "'" && "${value: -1}" == "'" ]]; then
|
||||
value="${value:1:${#value}-2}"
|
||||
fi
|
||||
fi
|
||||
printf '%s\n' "$value"
|
||||
}
|
||||
|
||||
read_env_value() {
|
||||
local value=""
|
||||
|
||||
if [[ -f "$ENV_FILE" ]]; then
|
||||
value="$(grep -E '^APP_DATA_DIR=' "$ENV_FILE" | tail -n 1 | cut -d '=' -f 2- || true)"
|
||||
fi
|
||||
value="${value%$'\r'}"
|
||||
strip_matching_quotes "$value"
|
||||
}
|
||||
|
||||
if [[ ${APP_DATA_DIR+x} ]]; then
|
||||
DATA_DIR_RAW="$APP_DATA_DIR"
|
||||
else
|
||||
DATA_DIR_RAW="$(read_env_value)"
|
||||
fi
|
||||
DATA_DIR_RAW="$(strip_matching_quotes "${DATA_DIR_RAW:-./data}")"
|
||||
|
||||
[[ -n "$DATA_DIR_RAW" ]] || fail "APP_DATA_DIR must not be empty"
|
||||
case "$DATA_DIR_RAW" in
|
||||
*$'\n'* | *$'\r'* | *:*) fail "APP_DATA_DIR contains unsupported characters" ;;
|
||||
esac
|
||||
|
||||
if [[ "$DATA_DIR_RAW" = /* ]]; then
|
||||
[[ ! -L "$DATA_DIR_RAW" ]] || fail "APP_DATA_DIR must not be a symbolic link"
|
||||
DATA_DIR_ABS="$(realpath -m -- "$DATA_DIR_RAW")"
|
||||
[[ "$DATA_DIR_ABS" != "/" ]] || fail "APP_DATA_DIR must not be the filesystem root"
|
||||
else
|
||||
DATA_DIR_PATH="${ROOT_DIR}/${DATA_DIR_RAW#./}"
|
||||
[[ ! -L "$DATA_DIR_PATH" ]] || fail "APP_DATA_DIR must not be a symbolic link"
|
||||
ROOT_DIR_ABS="$(realpath -m -- "$ROOT_DIR")"
|
||||
DATA_DIR_ABS="$(realpath -m -- "$DATA_DIR_PATH")"
|
||||
case "$DATA_DIR_ABS" in
|
||||
"${ROOT_DIR_ABS}"/*) ;;
|
||||
*) fail "Relative APP_DATA_DIR must remain inside the app version directory" ;;
|
||||
esac
|
||||
fi
|
||||
|
||||
if [[ -e "$DATA_DIR_ABS" && ! -d "$DATA_DIR_ABS" ]]; then
|
||||
fail "APP_DATA_DIR must be a directory"
|
||||
fi
|
||||
install -d -m 0750 -- "$DATA_DIR_ABS"
|
||||
|
||||
docker run --rm --volume "${DATA_DIR_ABS}:/data" "$IMAGE" \
|
||||
--db-path /data/index.db sync
|
||||
|
||||
[[ -s "$DATA_DIR_ABS/index.db" ]] || fail "nxv sync did not create index.db"
|
||||
[[ -s "$DATA_DIR_ABS/index.bloom" ]] || fail "nxv sync did not create index.bloom"
|
||||
Executable
+5
@@ -0,0 +1,5 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
# The package index is intentionally retained for recovery or reinstallation.
|
||||
exit 0
|
||||
Executable
+5
@@ -0,0 +1,5 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd -P)"
|
||||
exec "$SCRIPT_DIR/init.sh"
|
||||
@@ -0,0 +1,32 @@
|
||||
# nxv
|
||||
|
||||
## 产品介绍
|
||||
|
||||
nxv 是 Nix 软件包历史版本索引服务。它下载并验证上游预构建索引,在浏览器界面和 HTTP API 中快速查询软件包版本、出现时间及对应的 nixpkgs 提交。
|
||||
|
||||
## 主要功能
|
||||
|
||||
- 按软件包名、版本和描述检索 nixpkgs 历史
|
||||
- 查看软件包版本时间线和对应提交
|
||||
- 提供 Web 界面、OpenAPI 文档和 HTTP API
|
||||
- 使用 SQLite 与 Bloom Filter 提供本地快速查询
|
||||
|
||||
## 访问说明
|
||||
|
||||
- 首次安装需要下载并验证约 220 MB 的压缩索引,完成前主服务不会启动;实际磁盘占用会高于下载大小。
|
||||
- 索引保存在数据目录中,重启不会重复下载完整索引;重新安装前请按需要备份或清理该目录。
|
||||
- nxv 本身不提供用户认证。不要直接暴露到不受信任的公网,建议通过 1Panel 网站反向代理配置访问控制。
|
||||
- 固定版本用于可复现部署,`latest` 会跟随上游镜像更新。
|
||||
|
||||
## Introduction
|
||||
|
||||
nxv indexes historical nixpkgs releases and exposes fast package-version search through a web interface and HTTP API. The first installation downloads and verifies an index of about 220 MB before the server starts. Keep the data directory persistent to avoid unnecessary downloads.
|
||||
|
||||
## Features
|
||||
|
||||
- Searches package names, versions, and descriptions across nixpkgs history
|
||||
- Shows version timelines and the corresponding nixpkgs commits
|
||||
- Provides a web interface, OpenAPI documentation, and an HTTP API
|
||||
- Uses a local SQLite index and Bloom filter for fast queries
|
||||
|
||||
nxv does not provide built-in authentication. Restrict public access with 1Panel reverse-proxy authentication or another trusted access-control layer.
|
||||
@@ -0,0 +1,30 @@
|
||||
name: nxv
|
||||
tags:
|
||||
- 实用工具
|
||||
title: 快速检索 Nix 软件包历史版本的索引服务
|
||||
description: 快速检索 Nix 软件包历史版本的索引服务
|
||||
additionalProperties:
|
||||
key: nxv
|
||||
name: nxv
|
||||
tags:
|
||||
- Tool
|
||||
shortDescZh: 快速检索 Nix 软件包历史版本的索引服务
|
||||
shortDescEn: Index service for quickly searching historical Nix package versions
|
||||
description:
|
||||
en: Index service for quickly searching historical Nix package versions
|
||||
zh: 快速检索 Nix 软件包历史版本的索引服务
|
||||
zh-Hant: 快速搜尋 Nix 軟體套件歷史版本的索引服務
|
||||
ja: Nix パッケージの過去のバージョンを素早く検索するインデックスサービス
|
||||
ko: Nix 패키지의 이전 버전을 빠르게 검색하는 인덱스 서비스
|
||||
ru: Сервис индекса для быстрого поиска исторических версий пакетов Nix
|
||||
ms: Perkhidmatan indeks untuk mencari versi sejarah pakej Nix dengan pantas
|
||||
pt-br: Servico de indice para pesquisar rapidamente versoes historicas de pacotes Nix
|
||||
type: tool
|
||||
crossVersionUpdate: true
|
||||
limit: 0
|
||||
recommend: 0
|
||||
website: https://utensils.io/nxv/
|
||||
github: https://github.com/utensils/nxv
|
||||
document: https://utensils.io/nxv/
|
||||
architectures:
|
||||
- amd64
|
||||
@@ -0,0 +1,3 @@
|
||||
PANEL_APP_PORT_HTTP=8080
|
||||
APP_DATA_DIR=./data
|
||||
CONTAINER_NAME=1Panel-localnxv
|
||||
@@ -0,0 +1,35 @@
|
||||
additionalProperties:
|
||||
formFields:
|
||||
- default: 8080
|
||||
edit: true
|
||||
envKey: PANEL_APP_PORT_HTTP
|
||||
labelEn: HTTP Port
|
||||
labelZh: HTTP 端口
|
||||
label:
|
||||
en: HTTP Port
|
||||
zh: HTTP 端口
|
||||
zh-Hant: HTTP 連接埠
|
||||
ja: HTTP ポート
|
||||
ko: HTTP 포트
|
||||
ru: Порт HTTP
|
||||
ms: Port HTTP
|
||||
pt-br: Porta HTTP
|
||||
required: true
|
||||
rule: paramPort
|
||||
type: number
|
||||
- default: ./data
|
||||
edit: true
|
||||
envKey: APP_DATA_DIR
|
||||
labelEn: Data Directory
|
||||
labelZh: 数据目录
|
||||
label:
|
||||
en: Data Directory
|
||||
zh: 数据目录
|
||||
zh-Hant: 資料目錄
|
||||
ja: データディレクトリ
|
||||
ko: 데이터 디렉터리
|
||||
ru: Каталог данных
|
||||
ms: Direktori data
|
||||
pt-br: Diretorio de dados
|
||||
required: true
|
||||
type: text
|
||||
@@ -0,0 +1,36 @@
|
||||
services:
|
||||
nxv:
|
||||
image: "ghcr.io/utensils/nxv:latest"
|
||||
container_name: ${CONTAINER_NAME}
|
||||
command:
|
||||
- --db-path
|
||||
- /data/index.db
|
||||
- serve
|
||||
- --host
|
||||
- 0.0.0.0
|
||||
- --port
|
||||
- "8080"
|
||||
ports:
|
||||
- "${PANEL_APP_PORT_HTTP}:8080"
|
||||
volumes:
|
||||
- "${APP_DATA_DIR}:/data"
|
||||
restart: unless-stopped
|
||||
healthcheck:
|
||||
test:
|
||||
- CMD
|
||||
- nxv
|
||||
- --db-path
|
||||
- /data/index.db
|
||||
- stats
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
start_period: 10s
|
||||
labels:
|
||||
createdBy: "Apps"
|
||||
networks:
|
||||
- 1panel-network
|
||||
|
||||
networks:
|
||||
1panel-network:
|
||||
external: true
|
||||
Executable
+72
@@ -0,0 +1,72 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd -P)"
|
||||
ENV_FILE="${ENV_FILE:-${ROOT_DIR}/.env}"
|
||||
IMAGE="ghcr.io/utensils/nxv:latest"
|
||||
|
||||
fail() {
|
||||
printf '%s\n' "$1" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
strip_matching_quotes() {
|
||||
local value="$1"
|
||||
|
||||
if [[ ${#value} -ge 2 ]]; then
|
||||
if [[ "${value:0:1}" == '"' && "${value: -1}" == '"' ]]; then
|
||||
value="${value:1:${#value}-2}"
|
||||
elif [[ "${value:0:1}" == "'" && "${value: -1}" == "'" ]]; then
|
||||
value="${value:1:${#value}-2}"
|
||||
fi
|
||||
fi
|
||||
printf '%s\n' "$value"
|
||||
}
|
||||
|
||||
read_env_value() {
|
||||
local value=""
|
||||
|
||||
if [[ -f "$ENV_FILE" ]]; then
|
||||
value="$(grep -E '^APP_DATA_DIR=' "$ENV_FILE" | tail -n 1 | cut -d '=' -f 2- || true)"
|
||||
fi
|
||||
value="${value%$'\r'}"
|
||||
strip_matching_quotes "$value"
|
||||
}
|
||||
|
||||
if [[ ${APP_DATA_DIR+x} ]]; then
|
||||
DATA_DIR_RAW="$APP_DATA_DIR"
|
||||
else
|
||||
DATA_DIR_RAW="$(read_env_value)"
|
||||
fi
|
||||
DATA_DIR_RAW="$(strip_matching_quotes "${DATA_DIR_RAW:-./data}")"
|
||||
|
||||
[[ -n "$DATA_DIR_RAW" ]] || fail "APP_DATA_DIR must not be empty"
|
||||
case "$DATA_DIR_RAW" in
|
||||
*$'\n'* | *$'\r'* | *:*) fail "APP_DATA_DIR contains unsupported characters" ;;
|
||||
esac
|
||||
|
||||
if [[ "$DATA_DIR_RAW" = /* ]]; then
|
||||
[[ ! -L "$DATA_DIR_RAW" ]] || fail "APP_DATA_DIR must not be a symbolic link"
|
||||
DATA_DIR_ABS="$(realpath -m -- "$DATA_DIR_RAW")"
|
||||
[[ "$DATA_DIR_ABS" != "/" ]] || fail "APP_DATA_DIR must not be the filesystem root"
|
||||
else
|
||||
DATA_DIR_PATH="${ROOT_DIR}/${DATA_DIR_RAW#./}"
|
||||
[[ ! -L "$DATA_DIR_PATH" ]] || fail "APP_DATA_DIR must not be a symbolic link"
|
||||
ROOT_DIR_ABS="$(realpath -m -- "$ROOT_DIR")"
|
||||
DATA_DIR_ABS="$(realpath -m -- "$DATA_DIR_PATH")"
|
||||
case "$DATA_DIR_ABS" in
|
||||
"${ROOT_DIR_ABS}"/*) ;;
|
||||
*) fail "Relative APP_DATA_DIR must remain inside the app version directory" ;;
|
||||
esac
|
||||
fi
|
||||
|
||||
if [[ -e "$DATA_DIR_ABS" && ! -d "$DATA_DIR_ABS" ]]; then
|
||||
fail "APP_DATA_DIR must be a directory"
|
||||
fi
|
||||
install -d -m 0750 -- "$DATA_DIR_ABS"
|
||||
|
||||
docker run --rm --volume "${DATA_DIR_ABS}:/data" "$IMAGE" \
|
||||
--db-path /data/index.db sync
|
||||
|
||||
[[ -s "$DATA_DIR_ABS/index.db" ]] || fail "nxv sync did not create index.db"
|
||||
[[ -s "$DATA_DIR_ABS/index.bloom" ]] || fail "nxv sync did not create index.bloom"
|
||||
Executable
+5
@@ -0,0 +1,5 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
# The package index is intentionally retained for recovery or reinstallation.
|
||||
exit 0
|
||||
Executable
+5
@@ -0,0 +1,5 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd -P)"
|
||||
exec "$SCRIPT_DIR/init.sh"
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 570 B |
Reference in New Issue
Block a user