mirror of
https://github.com/unraid/api.git
synced 2026-01-02 14:40:01 -06:00
Compare commits
146 Commits
release-pl
...
v4.6.2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
79397eecff | ||
|
|
99d8b31fa8 | ||
|
|
d0827df60e | ||
|
|
9568aabd17 | ||
|
|
5a61aec841 | ||
|
|
ed67af9568 | ||
|
|
5ba3fa67a2 | ||
|
|
1f10b63c8b | ||
|
|
df168224ea | ||
|
|
3911be38bc | ||
|
|
15153855f7 | ||
|
|
65b7747c0e | ||
|
|
5c1b4352cf | ||
|
|
9004313ff8 | ||
|
|
7a421ce4ec | ||
|
|
3c6683c814 | ||
|
|
6bed63805f | ||
|
|
f7f40d7906 | ||
|
|
e2d00dc346 | ||
|
|
48c6ad7afa | ||
|
|
12eddf894e | ||
|
|
61fe6966ca | ||
|
|
b4c8efa483 | ||
|
|
dc9d5ad661 | ||
|
|
4964cf557b | ||
|
|
e54f189630 | ||
|
|
9f7218da79 | ||
|
|
d5a3d0dfac | ||
|
|
2266139742 | ||
|
|
7fb78494cb | ||
|
|
2f09445f2e | ||
|
|
fa6a5c56b6 | ||
|
|
234017a828 | ||
|
|
0210b9e62e | ||
|
|
4b2763c7f9 | ||
|
|
ed44796d5d | ||
|
|
d23a89f0b3 | ||
|
|
d0d2ff65ed | ||
|
|
9f492bf217 | ||
|
|
c4b4d26af0 | ||
|
|
0bcfb47bbc | ||
|
|
b0099421f3 | ||
|
|
49f636541b | ||
|
|
419c794e03 | ||
|
|
bbb02e991c | ||
|
|
8f78b3f1ca | ||
|
|
a1d02b486a | ||
|
|
cc85fba207 | ||
|
|
5958d33fce | ||
|
|
3a20930ead | ||
|
|
bf81a63f8e | ||
|
|
7e6be67f61 | ||
|
|
6a92f61f1a | ||
|
|
9cad1a9454 | ||
|
|
2c01ba9610 | ||
|
|
9ce10a72b2 | ||
|
|
f3e6a0011e | ||
|
|
cb2020dee6 | ||
|
|
db189abec4 | ||
|
|
d8afc8f4c9 | ||
|
|
3bfcc8e8c0 | ||
|
|
1892e23c22 | ||
|
|
03ece335b8 | ||
|
|
7bc9949110 | ||
|
|
ad3906e682 | ||
|
|
a356bf03fb | ||
|
|
57a6c49f8a | ||
|
|
9e54237670 | ||
|
|
f56d6ce5a2 | ||
|
|
590ab7327f | ||
|
|
9d63e56374 | ||
|
|
afa6087e95 | ||
|
|
c9789ac1f2 | ||
|
|
14ff3398ba | ||
|
|
6c042cbe01 | ||
|
|
3380929c04 | ||
|
|
bd69b3383f | ||
|
|
a0021bf682 | ||
|
|
b5f3a37863 | ||
|
|
7aa55883e2 | ||
|
|
8cd7376db0 | ||
|
|
a4f69dc539 | ||
|
|
dd9983c8b7 | ||
|
|
12e16a6404 | ||
|
|
9285eb745e | ||
|
|
4969b19a5b | ||
|
|
3f590c56e3 | ||
|
|
acbf46df3f | ||
|
|
ce61fee41c | ||
|
|
1b0fbaf81a | ||
|
|
0f550f9d94 | ||
|
|
3ea3953f4c | ||
|
|
c8d20eb01c | ||
|
|
d467f13a5d | ||
|
|
f1838bf69a | ||
|
|
dbcedad039 | ||
|
|
c20c7750a4 | ||
|
|
a09bc85edd | ||
|
|
f2d7abedf4 | ||
|
|
74408c73bb | ||
|
|
d63e54bdbc | ||
|
|
270072266a | ||
|
|
bce06cd76c | ||
|
|
4641894240 | ||
|
|
ff8eba3df5 | ||
|
|
2cc8c9f675 | ||
|
|
bde37d6751 | ||
|
|
7044713508 | ||
|
|
a2ba518bae | ||
|
|
a9469127cc | ||
|
|
85c8ef53ad | ||
|
|
ae47866724 | ||
|
|
d59ca415af | ||
|
|
90e4913ef7 | ||
|
|
b4aafbbe48 | ||
|
|
d890fae296 | ||
|
|
9a9ef54d2d | ||
|
|
baa8eb7375 | ||
|
|
982b22b1b4 | ||
|
|
d53577cd65 | ||
|
|
3bcf7f5c29 | ||
|
|
41252392d3 | ||
|
|
f6e4ba47d4 | ||
|
|
89620e9189 | ||
|
|
a0306269c6 | ||
|
|
e11d5e976d | ||
|
|
365dcae04b | ||
|
|
a9d5ca8899 | ||
|
|
b24a575cbb | ||
|
|
b49159022d | ||
|
|
c0ad2e138c | ||
|
|
d413be8dcb | ||
|
|
653b6df4d9 | ||
|
|
5483e9fee9 | ||
|
|
7957c2a681 | ||
|
|
d47bc0277d | ||
|
|
950bee951e | ||
|
|
46a05eb76d | ||
|
|
08423b8dae | ||
|
|
364eb62726 | ||
|
|
1718af1bb6 | ||
|
|
a50a2d9aeb | ||
|
|
248d211050 | ||
|
|
6adb4484c3 | ||
|
|
dc2e02de86 | ||
|
|
f9f47cbab3 |
21
.github/CODEOWNERS
vendored
21
.github/CODEOWNERS
vendored
@@ -1 +1,20 @@
|
||||
@elibosley @pujitm @mdatelle @zackspear
|
||||
# Default owners for everything in the repo
|
||||
* @elibosley @pujitm @mdatelle @zackspear
|
||||
|
||||
# API specific files
|
||||
/api/ @elibosley @pujitm @mdatelle
|
||||
|
||||
# Web frontend files
|
||||
/web/ @elibosley @mdatelle @zackspear
|
||||
|
||||
# Plugin related files
|
||||
/plugin/ @elibosley
|
||||
|
||||
# Unraid UI specific files
|
||||
/unraid-ui/ @mdatelle @zackspear @pujitm
|
||||
|
||||
# GitHub workflows and configuration
|
||||
/.github/ @elibosley
|
||||
|
||||
# Documentation
|
||||
*.md @elibosley @pujitm @mdatelle @zackspear
|
||||
2
.github/ISSUE_TEMPLATE/work_intent.md
vendored
2
.github/ISSUE_TEMPLATE/work_intent.md
vendored
@@ -3,7 +3,7 @@ name: Work Intent
|
||||
about: Request approval for planned development work (must be approved before starting)
|
||||
title: 'Work Intent: '
|
||||
labels: work-intent, unapproved
|
||||
assignees: ''
|
||||
assignees: 'elibosley'
|
||||
---
|
||||
|
||||
<!--
|
||||
|
||||
281
.github/workflows/main.yml
vendored
281
.github/workflows/main.yml
vendored
@@ -12,19 +12,25 @@ concurrency:
|
||||
|
||||
jobs:
|
||||
release-please:
|
||||
name: Release Please
|
||||
# Only run release-please on pushes to main
|
||||
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: write
|
||||
pull-requests: write
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
|
||||
|
||||
- id: release
|
||||
uses: googleapis/release-please-action@v4
|
||||
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
|
||||
outputs:
|
||||
releases_created: ${{ steps.release.outputs.releases_created }}
|
||||
tag_name: ${{ steps.release.outputs.tag_name }}
|
||||
releases_created: ${{ steps.release.outputs.releases_created || 'false' }}
|
||||
tag_name: ${{ steps.release.outputs.tag_name || '' }}
|
||||
test-api:
|
||||
name: Test API
|
||||
defaults:
|
||||
run:
|
||||
working-directory: api
|
||||
@@ -73,7 +79,7 @@ jobs:
|
||||
run: pnpm run coverage
|
||||
|
||||
build-api:
|
||||
name: Build and Test API
|
||||
name: Build API
|
||||
runs-on: ubuntu-latest
|
||||
defaults:
|
||||
run:
|
||||
@@ -122,7 +128,6 @@ jobs:
|
||||
|
||||
- name: Type Check
|
||||
run: pnpm run type-check
|
||||
continue-on-error: true
|
||||
|
||||
- name: Build
|
||||
run: pnpm run build
|
||||
@@ -137,13 +142,21 @@ jobs:
|
||||
export API_VERSION
|
||||
|
||||
- name: Build
|
||||
run: pnpm run build-and-pack
|
||||
run: |
|
||||
pnpm run build:release
|
||||
|
||||
tar -czf deploy/unraid-api.tgz -C deploy/pack/ .
|
||||
|
||||
- name: Upload tgz to Github artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: unraid-api
|
||||
path: ${{ github.workspace }}/api/deploy/release/*.tgz
|
||||
path: ${{ github.workspace }}/api/deploy/unraid-api.tgz
|
||||
- name: Upload PNPM Store to Github artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: packed-pnpm-store
|
||||
path: ${{ github.workspace }}/api/deploy/packed-pnpm-store.txz
|
||||
|
||||
build-unraid-ui-webcomponents:
|
||||
name: Build Unraid UI Library (Webcomponent Version)
|
||||
@@ -197,13 +210,11 @@ jobs:
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: unraid-wc-ui
|
||||
path: unraid-ui/dist/
|
||||
path: unraid-ui/dist-wc/
|
||||
|
||||
build-web:
|
||||
# needs: [build-unraid-ui]
|
||||
name: Build Web App
|
||||
environment:
|
||||
name: production
|
||||
defaults:
|
||||
run:
|
||||
working-directory: web
|
||||
@@ -215,10 +226,10 @@ jobs:
|
||||
- name: Create env file
|
||||
run: |
|
||||
touch .env
|
||||
echo VITE_ACCOUNT=${{ vars.VITE_ACCOUNT }} >> .env
|
||||
echo VITE_CONNECT=${{ vars.VITE_CONNECT }} >> .env
|
||||
echo VITE_UNRAID_NET=${{ vars.VITE_UNRAID_NET }} >> .env
|
||||
echo VITE_CALLBACK_KEY=${{ vars.VITE_CALLBACK_KEY }} >> .env
|
||||
echo VITE_ACCOUNT=${{ secrets.VITE_ACCOUNT }} >> .env
|
||||
echo VITE_CONNECT=${{ secrets.VITE_CONNECT }} >> .env
|
||||
echo VITE_UNRAID_NET=${{ secrets.VITE_UNRAID_NET }} >> .env
|
||||
echo VITE_CALLBACK_KEY=${{ secrets.VITE_CALLBACK_KEY }} >> .env
|
||||
cat .env
|
||||
|
||||
- name: Install Node
|
||||
@@ -254,10 +265,13 @@ jobs:
|
||||
run: |
|
||||
cd ${{ github.workspace }}/unraid-ui
|
||||
pnpm run build
|
||||
|
||||
- name: Lint files
|
||||
continue-on-error: true
|
||||
run: pnpm run lint
|
||||
|
||||
- name: Type Check
|
||||
run: pnpm run type-check
|
||||
|
||||
- name: Test
|
||||
run: pnpm run test:ci
|
||||
|
||||
@@ -271,16 +285,20 @@ jobs:
|
||||
path: web/.nuxt/nuxt-custom-elements/dist/unraid-components
|
||||
|
||||
build-plugin:
|
||||
needs: [build-api, build-web, build-unraid-ui-webcomponents]
|
||||
outputs:
|
||||
tag: ${{ steps.build-plugin.outputs.tag }}
|
||||
name: Build and Deploy Plugin
|
||||
needs:
|
||||
- release-please
|
||||
- build-api
|
||||
- build-web
|
||||
- build-unraid-ui-webcomponents
|
||||
- test-api
|
||||
defaults:
|
||||
run:
|
||||
working-directory: plugin
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Set Timezone
|
||||
uses: szenius/set-timezone@v1.2
|
||||
uses: szenius/set-timezone@v2.0
|
||||
with:
|
||||
timezoneLinux: "America/Los_Angeles"
|
||||
- name: Checkout repo
|
||||
@@ -296,7 +314,6 @@ jobs:
|
||||
- uses: pnpm/action-setup@v4
|
||||
name: Install pnpm
|
||||
with:
|
||||
|
||||
run_install: false
|
||||
|
||||
- name: Get pnpm store directory
|
||||
@@ -304,6 +321,15 @@ jobs:
|
||||
shell: bash
|
||||
run: |
|
||||
echo "STORE_PATH=$(pnpm store path)" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Get API Version
|
||||
id: vars
|
||||
run: |
|
||||
GIT_SHA=$(git rev-parse --short HEAD)
|
||||
IS_TAGGED=$(git describe --tags --abbrev=0 --exact-match || echo '')
|
||||
PACKAGE_LOCK_VERSION=$(jq -r '.version' package.json)
|
||||
API_VERSION=$([[ -n "$IS_TAGGED" ]] && echo "$PACKAGE_LOCK_VERSION" || echo "${PACKAGE_LOCK_VERSION}+${GIT_SHA}")
|
||||
echo "API_VERSION=${API_VERSION}" >> $GITHUB_OUTPUT
|
||||
|
||||
- uses: actions/cache@v4
|
||||
name: Setup pnpm cache
|
||||
@@ -318,73 +344,118 @@ jobs:
|
||||
cd ${{ github.workspace }}
|
||||
pnpm install --frozen-lockfile --filter @unraid/connect-plugin
|
||||
|
||||
- name: Download Unraid UI Components
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: unraid-wc-ui
|
||||
path: ${{ github.workspace }}/plugin/source/dynamix.unraid.net/usr/local/emhttp/plugins/dynamix.my.servers/unraid-components/uui
|
||||
merge-multiple: true
|
||||
- name: Download Unraid Web Components
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
pattern: unraid-wc-*
|
||||
path: ./plugin/source/dynamix.unraid.net/usr/local/emhttp/plugins/dynamix.my.servers/unraid-components
|
||||
pattern: unraid-wc-rich
|
||||
path: ${{ github.workspace }}/plugin/source/dynamix.unraid.net/usr/local/emhttp/plugins/dynamix.my.servers/unraid-components/nuxt
|
||||
merge-multiple: true
|
||||
- name: Download Unraid API
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: unraid-api
|
||||
path: /tmp/unraid-api/
|
||||
- name: Extract Unraid API and Build Plugin
|
||||
id: build-plugin
|
||||
run: |
|
||||
tar -xzf /tmp/unraid-api/unraid-api.tgz -C ${{ github.workspace }}/plugin/source/dynamix.unraid.net/usr/local/unraid-api
|
||||
cd ${{ github.workspace }}/plugin
|
||||
|
||||
if [ -n "${{ github.event.pull_request.number }}" ]; then
|
||||
export TAG=PR${{ github.event.pull_request.number }}
|
||||
# Put tag into github env
|
||||
echo "TAG=${TAG}" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
|
||||
pnpm run build
|
||||
- name: Upload binary txz and plg to Github artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: connect-files
|
||||
path: |
|
||||
plugin/deploy/release/plugins/
|
||||
plugin/deploy/release/archive/*.txz
|
||||
retention-days: 5
|
||||
if-no-files-found: error
|
||||
|
||||
release-pull-request:
|
||||
if: |
|
||||
github.event_name == 'pull_request'
|
||||
runs-on: ubuntu-latest
|
||||
needs: [test-api, build-plugin]
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Make PR Release Folder
|
||||
run: mkdir pr-release/
|
||||
|
||||
- name: Download plugin binary tgz
|
||||
path: ${{ github.workspace }}/plugin/api/
|
||||
- name: Download PNPM Store
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: connect-files
|
||||
|
||||
- name: Copy other release files to pr-release
|
||||
name: packed-pnpm-store
|
||||
path: ${{ github.workspace }}/plugin/
|
||||
- name: Extract Unraid API
|
||||
run: |
|
||||
cp archive/*.txz pr-release/
|
||||
cp plugins/pr/dynamix.unraid.net.plg pr-release/dynamix.unraid.net.plg
|
||||
mkdir -p ${{ github.workspace }}/plugin/source/dynamix.unraid.net/usr/local/unraid-api
|
||||
tar -xzf ${{ github.workspace }}/plugin/api/unraid-api.tgz -C ${{ github.workspace }}/plugin/source/dynamix.unraid.net/usr/local/unraid-api
|
||||
- name: Build Plugin and TXZ Based on Event and Tag
|
||||
id: build-plugin
|
||||
run: |
|
||||
cd ${{ github.workspace }}/plugin
|
||||
ls -al
|
||||
pnpm run build:txz
|
||||
|
||||
if [ -n "${{ github.event.pull_request.number }}" ]; then
|
||||
TAG="PR${{ github.event.pull_request.number }}"
|
||||
BUCKET_PATH="unraid-api/tag/${TAG}"
|
||||
else
|
||||
TAG=""
|
||||
BUCKET_PATH="unraid-api"
|
||||
fi
|
||||
|
||||
# On release, build both prod and preview plugins
|
||||
if [ "${{ needs.release-please.outputs.releases_created }}" == 'true' ]; then
|
||||
BASE_URL="https://stable.dl.unraid.net/unraid-api"
|
||||
pnpm run build:plugin --tag="${TAG}" --base-url="${BASE_URL}"
|
||||
mv ${{ github.workspace }}/plugin/deploy ${{ github.workspace }}/plugin/deploy-prod
|
||||
pnpm run build:txz
|
||||
fi
|
||||
|
||||
BASE_URL="https://preview.dl.unraid.net/unraid-api"
|
||||
echo "BUCKET_PATH=${BUCKET_PATH}" >> $GITHUB_OUTPUT
|
||||
echo "TAG=${TAG}" >> $GITHUB_OUTPUT
|
||||
pnpm run build:plugin --tag="${TAG}" --base-url="${BASE_URL}"
|
||||
- name: Ensure Plugin Files Exist
|
||||
run: |
|
||||
ls -al ./deploy
|
||||
if [ ! -f ./deploy/*.plg ]; then
|
||||
echo "Error: .plg file not found in plugin/deploy/"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ ! -f ./deploy/*.txz ]; then
|
||||
echo "Error: .txz file not found in plugin/deploy/"
|
||||
exit 1
|
||||
fi
|
||||
- name: Ensure Production Plugin Files Exist
|
||||
if: needs.release-please.outputs.releases_created == 'true'
|
||||
run: |
|
||||
ls -al ./deploy-prod
|
||||
if [ ! -f ./deploy-prod/*.plg ]; then
|
||||
echo "Error: .plg file not found in plugin/deploy-prod/"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ ! -f ./deploy-prod/*.txz ]; then
|
||||
echo "Error: .txz file not found in plugin/deploy-prod/"
|
||||
exit 1
|
||||
fi
|
||||
- name: Upload to GHA
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: unraid-plugin
|
||||
path: plugin/deploy/
|
||||
- name: Upload to Cloudflare
|
||||
uses: jakejarvis/s3-sync-action@v0.5.1
|
||||
if: github.event_name == 'pull_request' || startsWith(github.ref, 'refs/heads/main')
|
||||
env:
|
||||
AWS_S3_ENDPOINT: ${{ secrets.CF_ENDPOINT }}
|
||||
AWS_S3_BUCKET: ${{ secrets.CF_BUCKET_PREVIEW }}
|
||||
AWS_ACCESS_KEY_ID: ${{ secrets.CF_ACCESS_KEY_ID }}
|
||||
AWS_SECRET_ACCESS_KEY: ${{ secrets.CF_SECRET_ACCESS_KEY }}
|
||||
AWS_REGION: "auto"
|
||||
SOURCE_DIR: pr-release
|
||||
DEST_DIR: unraid-api/tag/${{ needs.build-plugin.outputs.tag }}
|
||||
AWS_DEFAULT_REGION: auto
|
||||
run: |
|
||||
# Sync the deploy directory to the Cloudflare bucket with explicit content encoding and public-read ACL
|
||||
aws s3 sync deploy/ s3://${{ secrets.CF_BUCKET_PREVIEW }}/${{ steps.build-plugin.outputs.BUCKET_PATH }} \
|
||||
--endpoint-url ${{ secrets.CF_ENDPOINT }} \
|
||||
--checksum-algorithm CRC32 \
|
||||
--no-guess-mime-type \
|
||||
--content-encoding none \
|
||||
--acl public-read
|
||||
|
||||
- name: Upload Release Assets
|
||||
if: needs.release-please.outputs.releases_created == 'true'
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: |
|
||||
release_name=$(gh release list --repo ${{ github.repository }} --json name,isDraft --jq '.[] | select(.isDraft == true) | .name' | head -n 1)
|
||||
# For each file in release directory
|
||||
for file in deploy-prod/*; do
|
||||
echo "Uploading $file to release..."
|
||||
gh release upload "${release_name}" "$file" --clobber
|
||||
done
|
||||
|
||||
- name: Comment URL
|
||||
if: github.event_name == 'pull_request'
|
||||
uses: thollander/actions-comment-pull-request@v3
|
||||
with:
|
||||
comment-tag: prlink
|
||||
@@ -393,73 +464,5 @@ jobs:
|
||||
This plugin has been deployed to Cloudflare R2 and is available for testing.
|
||||
Download it at this URL:
|
||||
```
|
||||
https://preview.dl.unraid.net/unraid-api/tag/${{ needs.build-plugin.outputs.tag }}/dynamix.unraid.net.plg
|
||||
https://preview.dl.unraid.net/unraid-api/tag/${{ steps.build-plugin.outputs.tag }}/dynamix.unraid.net.plg
|
||||
```
|
||||
|
||||
release-staging:
|
||||
environment:
|
||||
name: staging
|
||||
# Only release if this is a push to the main branch
|
||||
if: startsWith(github.ref, 'refs/heads/main')
|
||||
runs-on: ubuntu-latest
|
||||
needs: [test-api, build-plugin]
|
||||
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Make Staging Release Folder
|
||||
run: mkdir staging-release/
|
||||
|
||||
- name: Download plugin binary tgz
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: connect-files
|
||||
|
||||
- name: Copy Files for Staging Release
|
||||
run: |
|
||||
cp archive/*.txz staging-release/
|
||||
cp plugins/staging/dynamix.unraid.net.plg staging-release/dynamix.unraid.net.plg
|
||||
ls -al staging-release
|
||||
|
||||
- name: Upload Staging Plugin to Cloudflare Bucket
|
||||
uses: jakejarvis/s3-sync-action@v0.5.1
|
||||
env:
|
||||
AWS_S3_ENDPOINT: ${{ secrets.CF_ENDPOINT }}
|
||||
AWS_S3_BUCKET: ${{ secrets.CF_BUCKET_PREVIEW }}
|
||||
AWS_ACCESS_KEY_ID: ${{ secrets.CF_ACCESS_KEY_ID }}
|
||||
AWS_SECRET_ACCESS_KEY: ${{ secrets.CF_SECRET_ACCESS_KEY }}
|
||||
AWS_REGION: "auto"
|
||||
SOURCE_DIR: staging-release
|
||||
DEST_DIR: unraid-api
|
||||
|
||||
create-draft-release:
|
||||
# Only run if release-please created a release
|
||||
if: needs.release-please.outputs.releases_created == 'true'
|
||||
runs-on: ubuntu-latest
|
||||
needs: [release-please, test-api, build-plugin]
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Download plugin binary tgz
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: connect-files
|
||||
|
||||
- name: Move Files to Release Folder
|
||||
run: |
|
||||
mkdir -p release/
|
||||
mv plugins/production/dynamix.unraid.net.plg release/
|
||||
mv archive/*.txz release/
|
||||
|
||||
- name: Upload Release Assets
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: |
|
||||
release_name=$(gh release list --repo ${{ github.repository }} --json name,isDraft --jq '.[] | select(.isDraft == true) | .name' | head -n 1)
|
||||
# For each file in release directory
|
||||
for file in release/*; do
|
||||
echo "Uploading $file to release..."
|
||||
gh release upload "${release_name}" "$file" --clobber
|
||||
done
|
||||
|
||||
@@ -13,7 +13,7 @@ jobs:
|
||||
contents: read
|
||||
steps:
|
||||
- name: Set Timezone
|
||||
uses: szenius/set-timezone@v1.2
|
||||
uses: szenius/set-timezone@v2.0
|
||||
with:
|
||||
timezoneLinux: "America/Los_Angeles"
|
||||
- name: Checkout repo
|
||||
|
||||
115
.github/workflows/release-production.yml
vendored
115
.github/workflows/release-production.yml
vendored
@@ -3,6 +3,12 @@ name: Publish Release to Digital Ocean
|
||||
on:
|
||||
release:
|
||||
types: [published]
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
version:
|
||||
description: 'Tag to update'
|
||||
required: true
|
||||
|
||||
|
||||
jobs:
|
||||
publish-to-digital-ocean:
|
||||
@@ -16,7 +22,7 @@ jobs:
|
||||
regex: true
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
target: "./"
|
||||
version: "latest"
|
||||
version: ${{ inputs.version && format('tags/{0}', inputs.version) || 'latest' }}
|
||||
|
||||
- uses: cardinalby/git-get-release-action@v1
|
||||
id: release-info
|
||||
@@ -25,32 +31,91 @@ jobs:
|
||||
with:
|
||||
latest: true
|
||||
prerelease: false
|
||||
- name: Get Release Changelog
|
||||
run: |
|
||||
notes=$(cat << EOF
|
||||
${{ steps.release-info.outputs.body }}
|
||||
EOF
|
||||
)
|
||||
escapedNotes=$(sed -e 's/[&\\/]/\\&/g; s/$/\\/' -e '$s/\\$//' <<<"$notes")
|
||||
sed -i -z -E "s/<CHANGES>(.*)<\/CHANGES>/<CHANGES>\n${escapedNotes}\n<\/CHANGES>/g" "dynamix.unraid.net.plg"
|
||||
|
||||
- name: Upload All Release Files to DO Spaces
|
||||
uses: BetaHuhn/do-spaces-action@v2
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
access_key: ${{ secrets.DO_ACCESS_KEY }}
|
||||
secret_key: ${{ secrets.DO_SECRET_KEY }}
|
||||
space_name: ${{ secrets.DO_SPACE_NAME }}
|
||||
space_region: ${{ secrets.DO_SPACE_REGION }}
|
||||
source: "."
|
||||
out_dir: unraid-api
|
||||
node-version: '22.x'
|
||||
- run: npm install html-escaper@2 xml2js
|
||||
- name: Update Plugin Changelog
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const fs = require('fs');
|
||||
const { escape } = require('html-escaper');
|
||||
const releaseNotes = escape(`${{ steps.release-info.outputs.body }}`);
|
||||
|
||||
if (!releaseNotes) {
|
||||
console.error('No release notes found');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
- name: Upload Staging Plugin to Cloudflare Bucket
|
||||
uses: jakejarvis/s3-sync-action@v0.5.1
|
||||
// Read the plugin file
|
||||
const pluginPath = 'dynamix.unraid.net.plg';
|
||||
|
||||
if (!fs.existsSync(pluginPath)) {
|
||||
console.error('Plugin file not found:', pluginPath);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
let pluginContent = fs.readFileSync(pluginPath, 'utf8');
|
||||
|
||||
// Replace the changelog section using CDATA
|
||||
pluginContent = pluginContent.replace(
|
||||
/<CHANGES>[\s\S]*?<\/CHANGES>/,
|
||||
`<CHANGES>\n${releaseNotes}\n</CHANGES>`
|
||||
);
|
||||
|
||||
// Validate the plugin file is valid XML
|
||||
const xml2js = require('xml2js');
|
||||
const parser = new xml2js.Parser({
|
||||
explicitCharkey: true,
|
||||
trim: true,
|
||||
explicitRoot: true,
|
||||
explicitArray: false,
|
||||
attrkey: 'ATTR',
|
||||
charkey: 'TEXT',
|
||||
xmlnskey: 'XMLNS',
|
||||
normalizeTags: false,
|
||||
normalize: false,
|
||||
strict: false // Try with less strict parsing
|
||||
});
|
||||
parser.parseStringPromise(pluginContent).then((result) => {
|
||||
if (!result) {
|
||||
console.error('Plugin file is not valid XML');
|
||||
process.exit(1);
|
||||
}
|
||||
console.log('Plugin file is valid XML');
|
||||
|
||||
// Write back to file
|
||||
fs.writeFileSync(pluginPath, pluginContent);
|
||||
}).catch((err) => {
|
||||
console.error('Plugin file is not valid XML', err);
|
||||
process.exit(1);
|
||||
});
|
||||
|
||||
- name: Upload Release Files to DO Spaces
|
||||
env:
|
||||
AWS_ACCESS_KEY_ID: ${{ secrets.DO_ACCESS_KEY }}
|
||||
AWS_SECRET_ACCESS_KEY: ${{ secrets.DO_SECRET_KEY }}
|
||||
AWS_DEFAULT_REGION: ${{ secrets.DO_SPACE_REGION }}
|
||||
AWS_ENDPOINT_URL: https://${{ secrets.DO_SPACE_REGION }}.digitaloceanspaces.com
|
||||
run: |
|
||||
# Upload files with explicit content encoding and public-read ACL
|
||||
aws s3 sync . s3://${{ secrets.DO_SPACE_NAME }}/unraid-api \
|
||||
--checksum-algorithm CRC32 \
|
||||
--no-guess-mime-type \
|
||||
--content-encoding none \
|
||||
--acl public-read
|
||||
|
||||
- name: Upload Release Files to Cloudflare Bucket
|
||||
env:
|
||||
AWS_S3_ENDPOINT: ${{ secrets.CF_ENDPOINT }}
|
||||
AWS_S3_BUCKET: ${{ secrets.CF_BUCKET }}
|
||||
AWS_ACCESS_KEY_ID: ${{ secrets.CF_ACCESS_KEY_ID }}
|
||||
AWS_SECRET_ACCESS_KEY: ${{ secrets.CF_SECRET_ACCESS_KEY }}
|
||||
AWS_REGION: 'auto'
|
||||
SOURCE_DIR: "."
|
||||
DEST_DIR: unraid-api
|
||||
AWS_DEFAULT_REGION: auto
|
||||
AWS_ENDPOINT_URL: ${{ secrets.CF_ENDPOINT }}
|
||||
run: |
|
||||
# Upload files with explicit content encoding and public-read ACL
|
||||
aws s3 sync . s3://${{ secrets.CF_BUCKET }}/unraid-api \
|
||||
--checksum-algorithm CRC32 \
|
||||
--no-guess-mime-type \
|
||||
--content-encoding none \
|
||||
--acl public-read
|
||||
|
||||
2
.github/workflows/test-libvirt.yml
vendored
2
.github/workflows/test-libvirt.yml
vendored
@@ -28,7 +28,7 @@ jobs:
|
||||
|
||||
- uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: "3.10"
|
||||
python-version: "3.13"
|
||||
|
||||
- name: Cache APT Packages
|
||||
uses: awalsh128/cache-apt-pkgs-action@v1.4.3
|
||||
|
||||
13
.gitignore
vendored
13
.gitignore
vendored
@@ -88,10 +88,21 @@ deploy/*
|
||||
.nitro
|
||||
.cache
|
||||
.output
|
||||
.env*
|
||||
!.env.example
|
||||
|
||||
fb_keepalive
|
||||
|
||||
# pnpm store
|
||||
.pnpm-store
|
||||
|
||||
# Nix
|
||||
result
|
||||
result-*
|
||||
.direnv/
|
||||
.envrc
|
||||
|
||||
# Webgui sync script helpers
|
||||
web/scripts/.sync-webgui-repo-*
|
||||
|
||||
# Activation code data
|
||||
plugin/source/dynamix.unraid.net/usr/local/emhttp/plugins/dynamix.my.servers/data/activation-data.php
|
||||
@@ -1 +1 @@
|
||||
{"api":"4.1.2","web":"4.1.2","unraid-ui":"4.1.2","plugin":"4.1.2"}
|
||||
{".":"4.6.2"}
|
||||
|
||||
@@ -7,6 +7,17 @@ Thank you for your interest in contributing to Unraid Connect! We want to make c
|
||||
- Submitting a fix
|
||||
- Proposing new features
|
||||
|
||||
## TypeScript Import Extensions in the API Directory
|
||||
|
||||
When working with the API directory, you'll notice that TypeScript files are imported with `.js` extensions (e.g., `import { something } from './file.js'`) even though the actual files have `.ts` extensions. This is because:
|
||||
|
||||
1. We use ECMAScript modules (ESM) in our TypeScript configuration
|
||||
2. When TypeScript compiles `.ts` files to `.js`, the import paths in the compiled code need to reference `.js` files
|
||||
3. TypeScript doesn't automatically change the extensions in import statements during compilation
|
||||
4. Using `.js` extensions in imports ensures that both TypeScript during development and Node.js in production can resolve the modules correctly
|
||||
|
||||
This approach follows the [official TypeScript ESM recommendation](https://www.typescriptlang.org/docs/handbook/esm-node.html) and ensures compatibility across development and production environments.
|
||||
|
||||
## Development Process
|
||||
|
||||
We use GitHub to host code, to track issues and feature requests, as well as accept pull requests.
|
||||
@@ -47,6 +58,14 @@ We use GitHub to host code, to track issues and feature requests, as well as acc
|
||||
|
||||
**Note:** Direct pushes to the main branch are not allowed. All changes must go through the PR process.
|
||||
|
||||
## Developer Documentation
|
||||
|
||||
For detailed information about development workflows, repository organization, and other technical details, please refer to our developer documentation:
|
||||
|
||||
- [Development Guide](api/docs/developer/development.md) - Setup, building, and debugging instructions
|
||||
- [Development Workflows](api/docs/developer/workflows.md) - Detailed workflows for local development, building, and deployment
|
||||
- [Repository Organization](api/docs/developer/repo-organization.md) - High-level architecture and project structure
|
||||
|
||||
## Bug Reports and Feature Requests
|
||||
|
||||
We use GitHub issues to track bugs and feature requests:
|
||||
|
||||
352
LICENSE.txt
Normal file
352
LICENSE.txt
Normal file
@@ -0,0 +1,352 @@
|
||||
Project License Notice
|
||||
----------------------
|
||||
|
||||
This project is licensed under the terms of the GNU General Public License version 2,
|
||||
**or (at your option) any later version** published by the Free Software Foundation.
|
||||
|
||||
The full text of the GNU GPL v2.0 is provided below for reference.
|
||||
|
||||
----------------------
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
|
||||
<https://fsf.org/>
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
License is intended to guarantee your freedom to share and change free
|
||||
software--to make sure the software is free for all its users. This
|
||||
General Public License applies to most of the Free Software
|
||||
Foundation's software and to any other program whose authors commit to
|
||||
using it. (Some other Free Software Foundation software is covered by
|
||||
the GNU Lesser General Public License instead.) You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
this service if you wish), that you receive source code or can get it
|
||||
if you want it, that you can change the software or use pieces of it
|
||||
in new free programs; and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
anyone to deny you these rights or to ask you to surrender the rights.
|
||||
These restrictions translate to certain responsibilities for you if you
|
||||
distribute copies of the software, or if you modify it.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must give the recipients all the rights that
|
||||
you have. You must make sure that they, too, receive or can get the
|
||||
source code. And you must show them these terms so they know their
|
||||
rights.
|
||||
|
||||
We protect your rights with two steps: (1) copyright the software, and
|
||||
(2) offer you this license which gives you legal permission to copy,
|
||||
distribute and/or modify the software.
|
||||
|
||||
Also, for each author's protection and ours, we want to make certain
|
||||
that everyone understands that there is no warranty for this free
|
||||
software. If the software is modified by someone else and passed on, we
|
||||
want its recipients to know that what they have is not the original, so
|
||||
that any problems introduced by others will not reflect on the original
|
||||
authors' reputations.
|
||||
|
||||
Finally, any free program is threatened constantly by software
|
||||
patents. We wish to avoid the danger that redistributors of a free
|
||||
program will individually obtain patent licenses, in effect making the
|
||||
program proprietary. To prevent this, we have made it clear that any
|
||||
patent must be licensed for everyone's free use or not licensed at all.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License applies to any program or other work which contains
|
||||
a notice placed by the copyright holder saying it may be distributed
|
||||
under the terms of this General Public License. The "Program", below,
|
||||
refers to any such program or work, and a "work based on the Program"
|
||||
means either the Program or any derivative work under copyright law:
|
||||
that is to say, a work containing the Program or a portion of it,
|
||||
either verbatim or with modifications and/or translated into another
|
||||
language. (Hereinafter, translation is included without limitation in
|
||||
the term "modification".) Each licensee is addressed as "you".
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running the Program is not restricted, and the output from the Program
|
||||
is covered only if its contents constitute a work based on the
|
||||
Program (independent of having been made by running the Program).
|
||||
Whether that is true depends on what the Program does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Program's
|
||||
source code as you receive it, in any medium, provided that you
|
||||
conspicuously and appropriately publish on each copy an appropriate
|
||||
copyright notice and disclaimer of warranty; keep intact all the
|
||||
notices that refer to this License and to the absence of any warranty;
|
||||
and give any other recipients of the Program a copy of this License
|
||||
along with the Program.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy, and
|
||||
you may at your option offer warranty protection in exchange for a fee.
|
||||
|
||||
2. You may modify your copy or copies of the Program or any portion
|
||||
of it, thus forming a work based on the Program, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) You must cause the modified files to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
b) You must cause any work that you distribute or publish, that in
|
||||
whole or in part contains or is derived from the Program or any
|
||||
part thereof, to be licensed as a whole at no charge to all third
|
||||
parties under the terms of this License.
|
||||
|
||||
c) If the modified program normally reads commands interactively
|
||||
when run, you must cause it, when started running for such
|
||||
interactive use in the most ordinary way, to print or display an
|
||||
announcement including an appropriate copyright notice and a
|
||||
notice that there is no warranty (or else, saying that you provide
|
||||
a warranty) and that users may redistribute the program under
|
||||
these conditions, and telling the user how to view a copy of this
|
||||
License. (Exception: if the Program itself is interactive but
|
||||
does not normally print such an announcement, your work based on
|
||||
the Program is not required to print an announcement.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Program,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Program, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Program.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Program
|
||||
with the Program (or with a work based on the Program) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may copy and distribute the Program (or a work based on it,
|
||||
under Section 2) in object code or executable form under the terms of
|
||||
Sections 1 and 2 above provided that you also do one of the following:
|
||||
|
||||
a) Accompany it with the complete corresponding machine-readable
|
||||
source code, which must be distributed under the terms of Sections
|
||||
1 and 2 above on a medium customarily used for software interchange; or,
|
||||
|
||||
b) Accompany it with a written offer, valid for at least three
|
||||
years, to give any third party, for a charge no more than your
|
||||
cost of physically performing source distribution, a complete
|
||||
machine-readable copy of the corresponding source code, to be
|
||||
distributed under the terms of Sections 1 and 2 above on a medium
|
||||
customarily used for software interchange; or,
|
||||
|
||||
c) Accompany it with the information you received as to the offer
|
||||
to distribute corresponding source code. (This alternative is
|
||||
allowed only for noncommercial distribution and only if you
|
||||
received the program in object code or executable form with such
|
||||
an offer, in accord with Subsection b above.)
|
||||
|
||||
The source code for a work means the preferred form of the work for
|
||||
making modifications to it. For an executable work, complete source
|
||||
code means all the source code for all modules it contains, plus any
|
||||
associated interface definition files, plus the scripts used to
|
||||
control compilation and installation of the executable. However, as a
|
||||
special exception, the source code distributed need not include
|
||||
anything that is normally distributed (in either source or binary
|
||||
form) with the major components (compiler, kernel, and so on) of the
|
||||
operating system on which the executable runs, unless that component
|
||||
itself accompanies the executable.
|
||||
|
||||
If distribution of executable or object code is made by offering
|
||||
access to copy from a designated place, then offering equivalent
|
||||
access to copy the source code from the same place counts as
|
||||
distribution of the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
4. You may not copy, modify, sublicense, or distribute the Program
|
||||
except as expressly provided under this License. Any attempt
|
||||
otherwise to copy, modify, sublicense or distribute the Program is
|
||||
void, and will automatically terminate your rights under this License.
|
||||
However, parties who have received copies, or rights, from you under
|
||||
this License will not have their licenses terminated so long as such
|
||||
parties remain in full compliance.
|
||||
|
||||
5. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Program or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Program (or any work based on the
|
||||
Program), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Program or works based on it.
|
||||
|
||||
6. Each time you redistribute the Program (or any work based on the
|
||||
Program), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute or modify the Program subject to
|
||||
these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties to
|
||||
this License.
|
||||
|
||||
7. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Program at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Program by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Program.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under
|
||||
any particular circumstance, the balance of the section is intended to
|
||||
apply and the section as a whole is intended to apply in other
|
||||
circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system, which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
8. If the distribution and/or use of the Program is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Program under this License
|
||||
may add an explicit geographical distribution limitation excluding
|
||||
those countries, so that distribution is permitted only in or among
|
||||
countries not thus excluded. In such case, this License incorporates
|
||||
the limitation as if written in the body of this License.
|
||||
|
||||
9. The Free Software Foundation may publish revised and/or new versions
|
||||
of the General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Program
|
||||
specifies a version number of this License which applies to it and "any
|
||||
later version", you have the option of following the terms and conditions
|
||||
either of that version or of any later version published by the Free
|
||||
Software Foundation. If the Program does not specify a version number of
|
||||
this License, you may choose any version ever published by the Free Software
|
||||
Foundation.
|
||||
|
||||
10. If you wish to incorporate parts of the Program into other free
|
||||
programs whose distribution conditions are different, write to the author
|
||||
to ask for permission. For software which is copyrighted by the Free
|
||||
Software Foundation, write to the Free Software Foundation; we sometimes
|
||||
make exceptions for this. Our decision will be guided by the two goals
|
||||
of preserving the free status of all derivatives of our free software and
|
||||
of promoting the sharing and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
||||
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
||||
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
||||
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
||||
REPAIR OR CORRECTION.
|
||||
|
||||
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
||||
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
||||
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
||||
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
convey the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
Unraid API - Core API functionality for Unraid systems
|
||||
Copyright (C) 2024 Lime Technology, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
For questions about licensing or to report issues:
|
||||
- Website: https://unraid.net
|
||||
- Email: support@unraid.net
|
||||
|
||||
If the program is interactive, make it output a short notice like this
|
||||
when it starts in an interactive mode:
|
||||
|
||||
Gnomovision version 69, Copyright (C) year name of author
|
||||
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, the commands you use may
|
||||
be called something other than `show w' and `show c'; they could even be
|
||||
mouse-clicks or menu items--whatever suits your program.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the program, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
||||
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
||||
|
||||
<signature of Moe Ghoul>, 1 April 1989
|
||||
Moe Ghoul, President of Vice
|
||||
|
||||
This General Public License does not permit incorporating your program into
|
||||
proprietary programs. If your program is a subroutine library, you may
|
||||
consider it more useful to permit linking proprietary applications with the
|
||||
library. If this is what you want to do, use the GNU Lesser General
|
||||
Public License instead of this License.
|
||||
4
api/.env.production
Normal file
4
api/.env.production
Normal file
@@ -0,0 +1,4 @@
|
||||
ENVIRONMENT="production"
|
||||
NODE_ENV="production"
|
||||
PORT="/var/run/unraid-api.sock"
|
||||
MOTHERSHIP_GRAPHQL_LINK="https://mothership.unraid.net/ws"
|
||||
4
api/.env.staging
Normal file
4
api/.env.staging
Normal file
@@ -0,0 +1,4 @@
|
||||
ENVIRONMENT="staging"
|
||||
NODE_ENV="production"
|
||||
PORT="/var/run/unraid-api.sock"
|
||||
MOTHERSHIP_GRAPHQL_LINK="https://staging.mothership.unraid.net/ws"
|
||||
@@ -1,4 +1,5 @@
|
||||
import eslint from '@eslint/js';
|
||||
import importPlugin from 'eslint-plugin-import';
|
||||
import noRelativeImportPaths from 'eslint-plugin-no-relative-import-paths';
|
||||
import prettier from 'eslint-plugin-prettier';
|
||||
import tseslint from 'typescript-eslint';
|
||||
@@ -7,6 +8,7 @@ export default tseslint.config(eslint.configs.recommended, ...tseslint.configs.r
|
||||
plugins: {
|
||||
'no-relative-import-paths': noRelativeImportPaths,
|
||||
prettier: prettier,
|
||||
import: importPlugin,
|
||||
},
|
||||
rules: {
|
||||
'@typescript-eslint/no-redundant-type-constituents': 'off',
|
||||
@@ -22,7 +24,6 @@ export default tseslint.config(eslint.configs.recommended, ...tseslint.configs.r
|
||||
'@typescript-eslint/no-unused-vars': 'off',
|
||||
'@typescript-eslint/no-unused-expressions': 'off',
|
||||
'import/no-unresolved': 'off',
|
||||
'import/extensions': 'off',
|
||||
'import/no-absolute-path': 'off',
|
||||
'import/prefer-default-export': 'off',
|
||||
'no-relative-import-paths/no-relative-import-paths': [
|
||||
@@ -30,6 +31,27 @@ export default tseslint.config(eslint.configs.recommended, ...tseslint.configs.r
|
||||
{ allowSameFolder: false, rootDir: 'src', prefix: '@app' },
|
||||
],
|
||||
'prettier/prettier': 'error',
|
||||
'import/extensions': [
|
||||
'error',
|
||||
'ignorePackages',
|
||||
{
|
||||
js: 'always',
|
||||
ts: 'always',
|
||||
},
|
||||
],
|
||||
'no-restricted-globals': [
|
||||
'error',
|
||||
{
|
||||
name: '__dirname',
|
||||
message: 'Use import.meta.url instead of __dirname in ESM',
|
||||
},
|
||||
{
|
||||
name: '__filename',
|
||||
message: 'Use import.meta.url instead of __filename in ESM',
|
||||
},
|
||||
],
|
||||
'eol-last': ['error', 'always'],
|
||||
},
|
||||
|
||||
ignores: ['src/graphql/generated/client/**/*'],
|
||||
});
|
||||
|
||||
5
api/.gqlconfig
Normal file
5
api/.gqlconfig
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
schema: {
|
||||
files: 'src/graphql/schema/types/**/*.graphql'
|
||||
}
|
||||
}
|
||||
11
api/.vscode/extensions.json
vendored
Normal file
11
api/.vscode/extensions.json
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"recommendations": [
|
||||
"mikestead.dotenv",
|
||||
"eamodio.gitlens",
|
||||
"dbaeumer.vscode-eslint",
|
||||
"antfu.goto-alias",
|
||||
"bierner.markdown-mermaid",
|
||||
"github.vscode-pull-request-github",
|
||||
"bierner.markdown-preview-github-styles"
|
||||
]
|
||||
}
|
||||
621
api/CHANGELOG.md
621
api/CHANGELOG.md
@@ -1,247 +1,400 @@
|
||||
# Changelog
|
||||
|
||||
## [4.1.2](https://github.com/unraid/api/compare/v4.1.2...v4.1.2) (2025-02-21)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* add api key creation logic ([81382bc](https://github.com/unraid/api/commit/81382bcf1d26364ad9c5445530f648209101cf91))
|
||||
* add category.json ([c9e87e2](https://github.com/unraid/api/commit/c9e87e2e5b47a8801b7865ed586c803d0b470915))
|
||||
* add command to package.json scripts ([0dfb07f](https://github.com/unraid/api/commit/0dfb07f9eb519e60441f4123423f65acfdffca3b))
|
||||
* add csrf support to api & web components ([#999](https://github.com/unraid/api/issues/999)) ([19241ed](https://github.com/unraid/api/commit/19241ed55f5112f878b9890d8695badf7eb1c3eb))
|
||||
* add description flag, remove console log, and update readme ([c416c30](https://github.com/unraid/api/commit/c416c30951de4ed6b8d7a8c014403772db1c2015))
|
||||
* add developer docs ([#1128](https://github.com/unraid/api/issues/1128)) ([bb2e340](https://github.com/unraid/api/commit/bb2e340b68268d5121db650b27e8b2580c7966bb))
|
||||
* add line about recommendation for sso command ([44727a8](https://github.com/unraid/api/commit/44727a8d1a7c16c566678da43119b17a6303e375))
|
||||
* add log rotation ([f5c7ad9](https://github.com/unraid/api/commit/f5c7ad9221f80e4630e69f78d57f08f4c7252719))
|
||||
* add logging around fixture downloads ([a1ce27b](https://github.com/unraid/api/commit/a1ce27b17c970657f52635600f0d13116523f928))
|
||||
* add logrotate cron again ([4f85f66](https://github.com/unraid/api/commit/4f85f6687f920dae50277e726e2db2c3d946e867))
|
||||
* add patch for auth-request.php ([ec6ec56](https://github.com/unraid/api/commit/ec6ec562f43aac9947de2e9c269181303f42b2db))
|
||||
* add user with cli ([37458cd](https://github.com/unraid/api/commit/37458cd7408a1ad8aedca66a55ff13ac19ee30db))
|
||||
* address log level feedback ([49774aa](https://github.com/unraid/api/commit/49774aae459797f04ef2866ca064050aa476ae91))
|
||||
* allow csrf passing through querystring ([dba38c0](https://github.com/unraid/api/commit/dba38c0d149a77e4104c718c53d426330a17f2fa))
|
||||
* allow deletion and creation of files with patches ([32c9524](https://github.com/unraid/api/commit/32c952402c25e8340b1c628b4d0fdc4816b28ade))
|
||||
* always ensureDirectory for keys exists ([c6e9f80](https://github.com/unraid/api/commit/c6e9f804c58e44b46bce9f0da2260888544354cd))
|
||||
* **api:** graphql sandbox on unraid servers ([#1047](https://github.com/unraid/api/issues/1047)) ([ec504f3](https://github.com/unraid/api/commit/ec504f39297c92b64d9d3cc2f8f482cc1f3a2e44))
|
||||
* **api:** omit tz from sys time date format by default ([b2acde3](https://github.com/unraid/api/commit/b2acde3351d7afe18a2902e90b672537aadabffd))
|
||||
* **api:** rm 2fa & t2fa from myservers config type ([#996](https://github.com/unraid/api/issues/996)) ([89e791a](https://github.com/unraid/api/commit/89e791ad2e6f0395bee05e3f8bdcb2c8d72305dd))
|
||||
* async disk mapping ([bbb27e6](https://github.com/unraid/api/commit/bbb27e686897e4f9a0c926553d75aa046d7a8323))
|
||||
* async hypervisor and FIXED vm listing ([e79f4dd](https://github.com/unraid/api/commit/e79f4ddbc7061c249efb8214a311bb629628f669))
|
||||
* auto-docusaurus-prs ([#1127](https://github.com/unraid/api/issues/1127)) ([1147e76](https://github.com/unraid/api/commit/1147e762ae2fed6dea198fa38d6bcc514a1e66fb))
|
||||
* begin building plugin with node instead of bash ([#1120](https://github.com/unraid/api/issues/1120)) ([253b65a](https://github.com/unraid/api/commit/253b65a85ab9c5f53d53ef265b41aa132678f278))
|
||||
* better patch application ([a3e7daa](https://github.com/unraid/api/commit/a3e7daa6a6565ac81004ffd13da35d8b95b429cf))
|
||||
* better pm2 calls, log lines ([338ce30](https://github.com/unraid/api/commit/338ce3061310dfc42ad5f65edacbe5272de4afc7))
|
||||
* cleanup config entries ([943e73f](https://github.com/unraid/api/commit/943e73fa696b6ecec3227be914ab4962c4fee79d))
|
||||
* cleanup disclaimer and command to add users ([6be3af8](https://github.com/unraid/api/commit/6be3af8d7569d9c413dd9349df52e3fa4cb4f631))
|
||||
* cli Commands ([f8e5367](https://github.com/unraid/api/commit/f8e5367f3eb47daa5bcbd7711ae5835369502a1d))
|
||||
* CLI options for adding and deleting users ([16bf6d4](https://github.com/unraid/api/commit/16bf6d4c27ae8fa8d6d05ec4b28ce49a12673278))
|
||||
* coderabbit suggestion ([11ac36c](https://github.com/unraid/api/commit/11ac36c3616a90853d91467526fd39ecba17db88))
|
||||
* configure PM2 on startup ([2b908f1](https://github.com/unraid/api/commit/2b908f100b9eefaccf2264d5ff9945667568acf0))
|
||||
* convert to pnpm monorepo ([#1137](https://github.com/unraid/api/issues/1137)) ([8d89f8b](https://github.com/unraid/api/commit/8d89f8b20d6f3983d4e85b33827a857aa862db37))
|
||||
* create key cli command logic and add to index command list ([9b2a62d](https://github.com/unraid/api/commit/9b2a62d642b0942e3787e4ddd582a66e40321ab2))
|
||||
* csv validation ([84aae15](https://github.com/unraid/api/commit/84aae15a73014592c226fa3701e34e57c7b60b46))
|
||||
* default value for option ([6513fc4](https://github.com/unraid/api/commit/6513fc49de61c836e1aabf32a874d7da7da18adb))
|
||||
* disable casbin logging ([2518e7c](https://github.com/unraid/api/commit/2518e7c506f0d3aa9f44031d61dce95d9db0a4cf))
|
||||
* docstrings ([b836ba7](https://github.com/unraid/api/commit/b836ba72516c554ee8973d69aaaa4ed35b465fa7))
|
||||
* dont pass entire server state for privacy ([54e3f17](https://github.com/unraid/api/commit/54e3f17bd9e541f50970c696bbe8b602ec38a748))
|
||||
* download fixtures from the web ([1258c2b](https://github.com/unraid/api/commit/1258c2bc1813f0fa3cd52b4932302ad12b4edd01))
|
||||
* enable sandbox in dev mode ([4536d70](https://github.com/unraid/api/commit/4536d7092d77c68f5a996fd63bf74ce6e64f5efe))
|
||||
* enable sandbox with developer command ([c354d48](https://github.com/unraid/api/commit/c354d482283295547afeb99c5e110b0181197c44))
|
||||
* enable token sign in with comma separated subs in myservers.config ([ebed5bd](https://github.com/unraid/api/commit/ebed5bddea1445d9aaaee60d54758dc74b77271e))
|
||||
* exit cli after running command ([04bf528](https://github.com/unraid/api/commit/04bf528616fcbdf916916734a12d5fd32db9a06d))
|
||||
* extensive file checking ([ab881c8](https://github.com/unraid/api/commit/ab881c8aed8dd4aa9fd71c32b50d3514d1496fa5))
|
||||
* fallback to local ([a2579c2](https://github.com/unraid/api/commit/a2579c2a7f80f54b4cc61533aec9ecc41a7e7f54))
|
||||
* faster failure logic ([b439434](https://github.com/unraid/api/commit/b439434f1574e174fcf23f3a5f5b8df8e092eb1e))
|
||||
* fix docusaurus build + update snapshot ([23b27bd](https://github.com/unraid/api/commit/23b27bd63ea99f4137538eab40501daa67d7e3f5))
|
||||
* force linting on build ([43e6639](https://github.com/unraid/api/commit/43e663998a55e83c142067cb64ae7a331395fe68))
|
||||
* generate key one time ([afe53c3](https://github.com/unraid/api/commit/afe53c30ea9987e6d8728faa2cb7291f8a126ecb))
|
||||
* glob for files ([3fe281f](https://github.com/unraid/api/commit/3fe281f1ae28e3cbc089b5244a6ae2863b20adcb))
|
||||
* hypervisor async imports ([32686ca](https://github.com/unraid/api/commit/32686ca4f0c25c43c6a9f7162bb8179b39e58f7e))
|
||||
* ignore generated code ([68265a2](https://github.com/unraid/api/commit/68265a26efa588b60001310b9a11b398f04ae88f))
|
||||
* improve packing ([9ef02d5](https://github.com/unraid/api/commit/9ef02d53666b70d41fdd186364808deac715e1ff))
|
||||
* initial patcher implementation using the diff tool ([c87acbb](https://github.com/unraid/api/commit/c87acbb146c2e4e30997c964cd8be325dee68cea))
|
||||
* initial setup of permissions on keys ([#1068](https://github.com/unraid/api/issues/1068)) ([cf0fa85](https://github.com/unraid/api/commit/cf0fa850954ea2f018e338a132149f872b966df4))
|
||||
* initial version of modification service ([b80469d](https://github.com/unraid/api/commit/b80469d38e519a7ba0e6eae636cda2a821e2d465))
|
||||
* inject after form ([a4b276f](https://github.com/unraid/api/commit/a4b276f7874580bbf9827025730777715c9983da))
|
||||
* kill timeout extended ([22d4026](https://github.com/unraid/api/commit/22d40264a02672a818053b5280d63a03ff7336b9))
|
||||
* log size and only tar files ([731f2f8](https://github.com/unraid/api/commit/731f2f8e77a77b544a7f526c78aabfacca71eee4))
|
||||
* logrotate test ([4504c39](https://github.com/unraid/api/commit/4504c39a2bbcf51385578b69a9fdc7b81a950e98))
|
||||
* manually install libvirt in build process to ensure it is included in the final build ([e695481](https://github.com/unraid/api/commit/e695481363f0d5d7add9d0e0d50d1e113b3024f6))
|
||||
* more pm2 fixes ([8257bdf](https://github.com/unraid/api/commit/8257bdff3624211ee645349abdec303bf271538e))
|
||||
* move fixtures into __test__ folder ([22a901d](https://github.com/unraid/api/commit/22a901de9b0c274d3f75ed4b4618cd6cd90324ba))
|
||||
* myservers_fb keepalive location ([e07e7f3](https://github.com/unraid/api/commit/e07e7f335c8ea4a73966ada90c26b7c82dbb025e))
|
||||
* only write config when a specific config update action occurs ([ec29778](https://github.com/unraid/api/commit/ec29778e37a50f43eb164991bcf2a6ff9c266033))
|
||||
* properly read log level from environment ([b5151e9](https://github.com/unraid/api/commit/b5151e9ba76a6814e24e8da34e8a3c1bf1cc2144))
|
||||
* public index ([f0641ea](https://github.com/unraid/api/commit/f0641ea7ca0919884dc3b8642c2e6694398e3246))
|
||||
* remove sso if disabled on Unraid-API start ([3bc407c](https://github.com/unraid/api/commit/3bc407c54e8e7aeadebd9ac223d71f21ef97fca1))
|
||||
* remove sso user command ([bbd809b](https://github.com/unraid/api/commit/bbd809b83826e81eef38a06e66f3393e4f83e81e))
|
||||
* remove sso user options ([e34041f](https://github.com/unraid/api/commit/e34041f86ef7ab6cf5e2fdf7efb86458d190edc1))
|
||||
* remove unused config sections ([f0b9c4f](https://github.com/unraid/api/commit/f0b9c4f44ab0ee8f75bf96fde2413988ef4f6a8c))
|
||||
* remove unused fields ([d2d0f7c](https://github.com/unraid/api/commit/d2d0f7cd9acb53ea2372245d7ef669c7ca24ee8a))
|
||||
* remove unused vars ([0507713](https://github.com/unraid/api/commit/0507713972e344ad47bd077554d5888269669e9c))
|
||||
* rename api key resource back to api_key ([ee9666b](https://github.com/unraid/api/commit/ee9666b317d7feb5c15d53e2a6b902c7771c8c7a))
|
||||
* rename modification file ([70a93f2](https://github.com/unraid/api/commit/70a93f2cc63e0e62242be6fe1a717515a6fbec85))
|
||||
* reorder index ([858553f](https://github.com/unraid/api/commit/858553f0debb6424ae0614640b82a050c33f175a))
|
||||
* restart the API when an SSO user is added ([a6b0c90](https://github.com/unraid/api/commit/a6b0c906a423df048401750943f02dfdc9bc2619))
|
||||
* restoring sso error ([234bf7d](https://github.com/unraid/api/commit/234bf7dfa4b0be88b6cc13996d8f29ec819da26e))
|
||||
* revert local api key value ([ff40e7a](https://github.com/unraid/api/commit/ff40e7ae392052d3d9e1b084c5f4851e8ebd529e))
|
||||
* rollback if patch exists before applying ([c2f4e8d](https://github.com/unraid/api/commit/c2f4e8d4e5c758601bd20ba491fd077b434ba45e))
|
||||
* secondary changes ([d75331a](https://github.com/unraid/api/commit/d75331a67e3566875ce8642fce80195e79932a4c))
|
||||
* service tests for modifier service ([08c1502](https://github.com/unraid/api/commit/08c150259f2b4630d973803f4edff69c8bf0ec3a))
|
||||
* session issues ([5981693](https://github.com/unraid/api/commit/5981693abd605337f9174ba4c85fd1bfc243edeb))
|
||||
* shared call to createPatch ([eb3e263](https://github.com/unraid/api/commit/eb3e263fb32a748bfa06ec6d119ee51d242707cf))
|
||||
* simplify docs ([d428030](https://github.com/unraid/api/commit/d428030b806f55b62421559d434fc723786b03ad))
|
||||
* style improvements ([b0f395e](https://github.com/unraid/api/commit/b0f395ef76f11047eaa13091df277df0459e9d8f))
|
||||
* swap to async exit hook ([4302f31](https://github.com/unraid/api/commit/4302f316820a109c76408092994727b2dc030a15))
|
||||
* switch to nest-commander ([1ab2ab5](https://github.com/unraid/api/commit/1ab2ab5b58a1f49cd6b05aaa84bfeced49d68e8e))
|
||||
* try catch restart ([89abee6](https://github.com/unraid/api/commit/89abee680bdbdaa9946ddb991f0e6b5ada9ccdf7))
|
||||
* **ui:** webgui-compatible web component library ([#1075](https://github.com/unraid/api/issues/1075)) ([1c7b2e0](https://github.com/unraid/api/commit/1c7b2e091b0975438860a8e1fc3db5fd8d3fcf93))
|
||||
* unnecessary comment ([0c52256](https://github.com/unraid/api/commit/0c5225612875b96319b28ef447db69ecab15cfda))
|
||||
* unraid single sign on with account app ([5183104](https://github.com/unraid/api/commit/5183104b322a328eea3e4b2f6d86fd9d4b1c76e3))
|
||||
* update packageManager field for pnpm ([8d5db7a](https://github.com/unraid/api/commit/8d5db7a9bfdf528e2d58b20cc62434ea5929d24f))
|
||||
* upgrade dependencies ([0a0cac3](https://github.com/unraid/api/commit/0a0cac3da74c2fe20f7100a9ad5d1caafa74b157))
|
||||
* use execa for start and stop ([46ab014](https://github.com/unraid/api/commit/46ab0144d41b425015487c251c1884744223ba29))
|
||||
* use zod to parse config ([19cf1be](https://github.com/unraid/api/commit/19cf1be079f2ccb9e0cfa10f2fb97a18f15c5729))
|
||||
* validate token format in both PHP and CLI ([6ef05a3](https://github.com/unraid/api/commit/6ef05a3d7770f799e7d587c2cef8d29f6058bee1))
|
||||
* **web:** add delete all notifications button to archive view in notifications sidebar ([3bda9d6](https://github.com/unraid/api/commit/3bda9d6a4ca01cc5580012b0133e72929d6dab40))
|
||||
* **web:** enhance notifications indicator in UPC ([#950](https://github.com/unraid/api/issues/950)) ([6376848](https://github.com/unraid/api/commit/63768486e4ec64ab32666a26adf96f4db4a53e81))
|
||||
* **web:** pull date format from display/date and time settings ([b058067](https://github.com/unraid/api/commit/b058067b628ca7866a9ba0a6c4c5e4d5505d98cb))
|
||||
* **web:** rm api-key validation from connect sign in ([#986](https://github.com/unraid/api/issues/986)) ([7b105d1](https://github.com/unraid/api/commit/7b105d18678e88a064f0643d6e857704789e0ee8))
|
||||
* zod config no longer any ([c32c5f5](https://github.com/unraid/api/commit/c32c5f57127b9469bde8806d78dc364562e73d9f))
|
||||
## [4.6.2](https://github.com/unraid/api/compare/v4.6.1...v4.6.2) (2025-04-03)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* allow concurrent testing with a shared patcher instance ([623846e](https://github.com/unraid/api/commit/623846ef46eb24a32c62516de58e8bc5d0219833))
|
||||
* **api:** append time to formatted date when a custom date format is selected ([0ac8ed9](https://github.com/unraid/api/commit/0ac8ed9d9e7e239e471eedf466832aed0270d123))
|
||||
* **api:** change log output location for diagnostic compatibility ([#1130](https://github.com/unraid/api/issues/1130)) ([cba1551](https://github.com/unraid/api/commit/cba155138379d47bc3151c7c27d745ba6a345d83))
|
||||
* **api:** delay pm2 start until server has booted ([bd3188e](https://github.com/unraid/api/commit/bd3188efea4d3656994ffae32bd53f821c96358d))
|
||||
* **api:** exclude duplicates from legacy script in archive retrieval ([8644e13](https://github.com/unraid/api/commit/8644e130979ed8740c5a8da0b3984266e2b3684c))
|
||||
* **api:** improve defaults in PM2 service ([#1116](https://github.com/unraid/api/issues/1116)) ([57526de](https://github.com/unraid/api/commit/57526dede69e3a6547d05183e43c5b36dd1cae89))
|
||||
* **api:** logrotate modification & permissions ([#1145](https://github.com/unraid/api/issues/1145)) ([5209df2](https://github.com/unraid/api/commit/5209df2776e1a985e82bedc655fe28acf1fd0bde))
|
||||
* **api:** make cookie recognition during websocket connection more ([353e012](https://github.com/unraid/api/commit/353e012db8ab5280863f32392c520b4a330c13cc))
|
||||
* **api:** pm2 start script & limit auto restarts ([#1040](https://github.com/unraid/api/issues/1040)) ([ebcd347](https://github.com/unraid/api/commit/ebcd3479e735724626ffc6907c338d5080898bee))
|
||||
* **api:** retry mothership connection up to 3x before logout ([#1069](https://github.com/unraid/api/issues/1069)) ([c27bb1b](https://github.com/unraid/api/commit/c27bb1be4c7a9ab201585586f3bc5e4afa1c7791))
|
||||
* **api:** sanitize incoming user session id's ([f5e3424](https://github.com/unraid/api/commit/f5e3424b79702e8f959b5519e83370a9e1d2033b))
|
||||
* **api:** slow init of unraid-api cli ([#1022](https://github.com/unraid/api/issues/1022)) ([5dbbae7](https://github.com/unraid/api/commit/5dbbae796792a62234497d056eac019aa084b21c))
|
||||
* **api:** update deploy-dev script to dist instead of src ([55cce09](https://github.com/unraid/api/commit/55cce09e65521762a6fe388d5b9b88ace1337c26))
|
||||
* **api:** validate cookie session data ([491f680](https://github.com/unraid/api/commit/491f680607ce7244d9e47a457e44cde711fbe00c))
|
||||
* apply and rollback error handling ([e22191b](https://github.com/unraid/api/commit/e22191bc77bc09f5c6c4ad57e5073829cf966ba4))
|
||||
* authorization type error ([#987](https://github.com/unraid/api/issues/987)) ([7a4799e](https://github.com/unraid/api/commit/7a4799e9cd4caef6acfc3661d205a377fcf499ab))
|
||||
* back to default configs ([b5711c9](https://github.com/unraid/api/commit/b5711c91284072991bcf409ac6126cd4b46afc7c))
|
||||
* backup restore formatting ([15210f6](https://github.com/unraid/api/commit/15210f64b0938ec884a3ef4379d245c661eab9a3))
|
||||
* basic test fixed ([2f38035](https://github.com/unraid/api/commit/2f38035520ca0fe796c981d08b9136d89ffc5888))
|
||||
* better js file handling ([ddf160e](https://github.com/unraid/api/commit/ddf160e878a352842e813154b607945ccc7b4081))
|
||||
* better loader functionality and error handling ([8a57d2d](https://github.com/unraid/api/commit/8a57d2dccbcb9c2effc5df5d8c69ad02713de24a))
|
||||
* cleaner logs for starting API ([79f26ef](https://github.com/unraid/api/commit/79f26ef251cb42e7f2106d00c6c05e2bf17b8227))
|
||||
* clearer error messaging ([e373849](https://github.com/unraid/api/commit/e37384966c5b9079bb507052dcaba56232c1c42a))
|
||||
* code review feedback ([c66079e](https://github.com/unraid/api/commit/c66079e9a8e0ef47e5054118d0581bec708ac604))
|
||||
* completion script registration ([05c8c9b](https://github.com/unraid/api/commit/05c8c9bf078ece2061ad8ae32497f52b8c9b94dc))
|
||||
* connect key role ([2dcfc1c](https://github.com/unraid/api/commit/2dcfc1c19a1d085df84f0b1b50c096e3220205dd))
|
||||
* create api key for connect on startup ([58329bc](https://github.com/unraid/api/commit/58329bc29521ebc26b27ee20013ac3926c5088c2))
|
||||
* create api key permissions ([cefb644](https://github.com/unraid/api/commit/cefb644bd7fa513f553ca0ca4c49f0fb42a74112))
|
||||
* create connect key ([6b1ab7b](https://github.com/unraid/api/commit/6b1ab7b74ae1d2938fa9105180a5f66e9604fd41))
|
||||
* cwd on ecosystem.config.json ([dfd0da4](https://github.com/unraid/api/commit/dfd0da4ca23078f6de2e54d5e5bd6cba06334abc))
|
||||
* default overwrite false test ([cf59107](https://github.com/unraid/api/commit/cf59107e568d91be684176335db5300bee9be865))
|
||||
* delete .original files ([a9eb21a](https://github.com/unraid/api/commit/a9eb21aac0f373990aaa3f7a99731612540533cf))
|
||||
* deprecated version warning ([89d0bd2](https://github.com/unraid/api/commit/89d0bd2e6da35fb1e8d95627d38edb54f82e0c6b))
|
||||
* **deps:** update all non-major dependencies ([#1158](https://github.com/unraid/api/issues/1158)) ([45ebc8b](https://github.com/unraid/api/commit/45ebc8b6e07c53ad3eee28d5cf8ac9cd0d827754))
|
||||
* **deps:** update apollo graphql packages ([7b1ee99](https://github.com/unraid/api/commit/7b1ee9940cca46e563bb79c7056996315f9decc5))
|
||||
* **deps:** update dependency @apollo/client to v3.12.6 ([bb7800a](https://github.com/unraid/api/commit/bb7800a8c088705fd8310671a9896cbe9b0184e5))
|
||||
* **deps:** update dependency @apollo/client to v3.12.9 ([6607cf2](https://github.com/unraid/api/commit/6607cf20c10a091d466c6a8031eebc17feb3e3fc))
|
||||
* **deps:** update dependency @graphql-tools/load-files to v7.0.1 ([4e5c724](https://github.com/unraid/api/commit/4e5c7242e43cc356f1c69adcfcd25b57896af476))
|
||||
* **deps:** update dependency @nestjs/schedule to v4.1.2 ([faf0de5](https://github.com/unraid/api/commit/faf0de5a19256efb83dc45a484e3cba65596ccd7))
|
||||
* **deps:** update dependency chokidar to v4.0.3 ([d63a93c](https://github.com/unraid/api/commit/d63a93c55004d17b6d17634c55ffbc5670ebbec7))
|
||||
* **deps:** update dependency dockerode to v4 ([#830](https://github.com/unraid/api/issues/830)) ([c331ecd](https://github.com/unraid/api/commit/c331ecd50c4910fd6c35e5ad92b3f676d552febc))
|
||||
* **deps:** update dependency dotenv to v16.4.7 ([c66a650](https://github.com/unraid/api/commit/c66a6502b027853046d126a14ddee870ffabd10c))
|
||||
* **deps:** update dependency execa to v9.5.2 ([d487c90](https://github.com/unraid/api/commit/d487c90ccc20162c76f0cdf49a736c1fee4271bd))
|
||||
* **deps:** update dependency express to v4.21.2 ([a070306](https://github.com/unraid/api/commit/a07030684c8777e47eb4a51be0ea680b7f217e74))
|
||||
* **deps:** update dependency got to v14.4.5 ([975a47c](https://github.com/unraid/api/commit/975a47c7d47841c49443f46264feb54abf53698c))
|
||||
* **deps:** update dependency graphql-ws to v5.16.2 ([25d8f08](https://github.com/unraid/api/commit/25d8f085b67c2e53876d837c739214dc874116b8))
|
||||
* **deps:** update dependency ini to v4.1.3 ([4c88cbe](https://github.com/unraid/api/commit/4c88cbee4b2d5f6717241dadac23bfe90ce15193))
|
||||
* **deps:** update dependency node-window-polyfill to v1.0.4 ([8bfa88f](https://github.com/unraid/api/commit/8bfa88f4bc932eb82dd9b33a494811ea15764758))
|
||||
* **deps:** update dependency openid-client to v6.1.7 ([0f50517](https://github.com/unraid/api/commit/0f50517a8544e1eb9b08ad1b3f05f798491b7f23))
|
||||
* **deps:** update dependency p-retry to v6.2.1 ([c6f3241](https://github.com/unraid/api/commit/c6f324155019e066701723a57b642c6e3ba8332d))
|
||||
* **deps:** update dependency pm2 to v5.4.3 ([a754090](https://github.com/unraid/api/commit/a75409026dd4e3d9ed120802012b67b179327448))
|
||||
* **deps:** update dependency uuid to v11.0.5 ([7e3398b](https://github.com/unraid/api/commit/7e3398b2efabf1a5407d6e20c165eb4923b3bab2))
|
||||
* **deps:** update graphql-tools monorepo ([cd7e2fe](https://github.com/unraid/api/commit/cd7e2feea199276a1d431cf355e54e12e5960d9a))
|
||||
* **deps:** update graphqlcodegenerator monorepo ([0446c59](https://github.com/unraid/api/commit/0446c5924a6a9dd15b875628ca0f1197cfe521c4))
|
||||
* **deps:** update graphqlcodegenerator monorepo ([15c789d](https://github.com/unraid/api/commit/15c789dbb34b85bed55c2731fb8ae8260f5f311f))
|
||||
* **deps:** update nest monorepo to v10.4.15 ([07b1ea9](https://github.com/unraid/api/commit/07b1ea9a10634a597909ae1d237cc3b1e7f959b7))
|
||||
* **deps:** update nest-graphql monorepo to v12.2.2 ([91aabd9](https://github.com/unraid/api/commit/91aabd9ffbfb8c2ceb4110217dfc05de8859077d))
|
||||
* do not process.exit on restart or stop command ([933575f](https://github.com/unraid/api/commit/933575fc2badbb09b3a9d3c66724e37a9ee246f2))
|
||||
* don't check code for execa ([508a5eb](https://github.com/unraid/api/commit/508a5eb49d9514dca9953317d9fa93314fe63e4c))
|
||||
* dont remove login file without a backup presetn ([0370e4f](https://github.com/unraid/api/commit/0370e4f7ea3e3df0d2264264324d8e53ffc0c086))
|
||||
* ensure directory exists before making connect key ([9e27ec9](https://github.com/unraid/api/commit/9e27ec98b68a49bdd6dc4b03de8c0cc3a1470a5e))
|
||||
* excess spacing in api-key.service ([1deb002](https://github.com/unraid/api/commit/1deb0023287a39d40e52e89c515a28e62352f62c))
|
||||
* extra log line ([1183063](https://github.com/unraid/api/commit/1183063aa7063afd8222def18f5e1fd6077e8c88))
|
||||
* extra spacing in config.ts ([f3ee7be](https://github.com/unraid/api/commit/f3ee7be80f2c60266fbb13597a70f0a389fb577f))
|
||||
* file modification service fixes ([aa5b3f4](https://github.com/unraid/api/commit/aa5b3f4e47ed88df23af00dfcccb7b64786b6231))
|
||||
* find by key, not ID ([3c3fa1e](https://github.com/unraid/api/commit/3c3fa1e27cfabbe6926c3da8870751397eed1def))
|
||||
* fix libvirt bindings ([#1167](https://github.com/unraid/api/issues/1167)) ([5817e5d](https://github.com/unraid/api/commit/5817e5d4b1697bbdfaa1984ccd650a232233cc15))
|
||||
* forced restarting on commands ([925866d](https://github.com/unraid/api/commit/925866d389e337fcb8c249ead929e1f65854465b))
|
||||
* format authrequest mod as other files ([180a81d](https://github.com/unraid/api/commit/180a81dbae8e749eae237fc8cee2950c790eedf0))
|
||||
* formatting issue ([42ca969](https://github.com/unraid/api/commit/42ca9691f7547a4340501863c1882efc0aee4c60))
|
||||
* initial feedback about report addressed ([5dee09c](https://github.com/unraid/api/commit/5dee09c77ad375de2eca59f650e5fea2070087b5))
|
||||
* install as-integrations/fastify ([ff4546d](https://github.com/unraid/api/commit/ff4546d6692d2a4799f2dbeef0d5e5c6bac62561))
|
||||
* length ([83579f1](https://github.com/unraid/api/commit/83579f1fbd03ffe929d009c20d214b4de62835c6))
|
||||
* lint ([0f218b8](https://github.com/unraid/api/commit/0f218b8b72e397734823efab8f2141973a3a80ce))
|
||||
* lint ([82bca54](https://github.com/unraid/api/commit/82bca54c594265ddf23a298691bd7ef6d4b47f32))
|
||||
* lint ([ceb443d](https://github.com/unraid/api/commit/ceb443da15d177a950c36af61b93a7126cf4ca85))
|
||||
* lint ([da04e7c](https://github.com/unraid/api/commit/da04e7ce0873d7802a936952d91e9867f0868a6e))
|
||||
* lint ([7d87f0e](https://github.com/unraid/api/commit/7d87f0eee23dfa0f391fd342d38ed9084f18d8d4))
|
||||
* logrotate error ([8c64dd2](https://github.com/unraid/api/commit/8c64dd2f2c65aa83ce0e2d501357ee595c976e56))
|
||||
* mock ensureDirSync ([7e012e6](https://github.com/unraid/api/commit/7e012e6a2eb96ccddf5a1f69d7580b4bdfe7a0a9))
|
||||
* more generic test ([0f651db](https://github.com/unraid/api/commit/0f651dbf61a1822b492aa80030f0bc231bc6f606))
|
||||
* only instantiate service one time ([933dc81](https://github.com/unraid/api/commit/933dc81b6c50db5a33f586f7094e1ea524b9a9fa))
|
||||
* only toast unread notifications, not archived ones ([cc59be6](https://github.com/unraid/api/commit/cc59be6cb3efc71226ee50f9f04e37a2e4b50de6))
|
||||
* padding and glob function issues ([1d3f2eb](https://github.com/unraid/api/commit/1d3f2eb8213115c3385ac2d29ee8f53560347ba8))
|
||||
* patch-utils unused ([047808d](https://github.com/unraid/api/commit/047808dce0cd9e9b4b273a9124dbd45ca9446208))
|
||||
* paths now correct, better download logic ([16db2d9](https://github.com/unraid/api/commit/16db2d908dcb2c65508b367712c51bf9872a95e5))
|
||||
* properly log error with template string ([3781f1f](https://github.com/unraid/api/commit/3781f1f41c7f0eef604daee0402ed9a2bb27cd46))
|
||||
* pull token from query not params ([2e827e7](https://github.com/unraid/api/commit/2e827e7cabe4a6a069d4e8779015e5896d8a1d1d))
|
||||
* remove devDependencies from output package json ([294869b](https://github.com/unraid/api/commit/294869bbea7f8a1863f8aafae6b074330e057679))
|
||||
* remove isNaN in favor of number.isNaN ([03e3a46](https://github.com/unraid/api/commit/03e3a46092db613281176b88cae284f6448027c6))
|
||||
* remove memory key generation ([b84db13](https://github.com/unraid/api/commit/b84db1322104c7f26f7b6378f25a2757b3010c6d))
|
||||
* remove unused constructor ([e0e2a7b](https://github.com/unraid/api/commit/e0e2a7b41c5e599ed4cf3bf49c7faea3b71f0b70))
|
||||
* remove usage of Role.UPC ([d1e2f6e](https://github.com/unraid/api/commit/d1e2f6e0b391cb4eca75a0997b41cb99a9953d42))
|
||||
* report issues + pm2 issues ([28c383e](https://github.com/unraid/api/commit/28c383e1d111d4ac4226d7d966533ba80ca5d9a1))
|
||||
* reset config to be closer to default ([b7fbb0b](https://github.com/unraid/api/commit/b7fbb0b6af0453f5f6a17087bb7e68c393b9fe3f))
|
||||
* resource busy when removing all subdirectories ([29936c9](https://github.com/unraid/api/commit/29936c90938fb83bc2f154315ca63a9d7cc98552))
|
||||
* restart command elegant ([296117b](https://github.com/unraid/api/commit/296117b51aac8a4c15366f2271af858868b6e071))
|
||||
* revert changelog ([e9d47ca](https://github.com/unraid/api/commit/e9d47caf181148317e5ba8f0d11a433b09add0e3))
|
||||
* revert dockerode upgrade ([#1140](https://github.com/unraid/api/issues/1140)) ([a74a379](https://github.com/unraid/api/commit/a74a379a93fd15a315e31191de1bf69c5879f8a6))
|
||||
* revert myservers.cfg ([d0896f3](https://github.com/unraid/api/commit/d0896f3ef8aebdd9c76d805ed6a35b4a5d5a1b08))
|
||||
* sandbox defaults in dev mode wrong ([2a24919](https://github.com/unraid/api/commit/2a2491936cf85013be836450ab7ed0cc11207e11))
|
||||
* sequential test execution for generic-modification ([79ee1f7](https://github.com/unraid/api/commit/79ee1f7552cee47c6f5a8eb5942468292212e2f2))
|
||||
* shell path to unraid-api ([15d11e4](https://github.com/unraid/api/commit/15d11e477bb2a08d785a7b22bd51900279a55508))
|
||||
* simplify api setup index ([701b1fb](https://github.com/unraid/api/commit/701b1fbd9096c9675475062eaf32a2cbfb0567b9))
|
||||
* simplify upcoming features ([8af79b2](https://github.com/unraid/api/commit/8af79b27501b42e1c1f7697756a56a9001000d8f))
|
||||
* staging build issues ([e6bcb8d](https://github.com/unraid/api/commit/e6bcb8de7daee463f7ac0dbf977e085e108302ba))
|
||||
* start command simplification ([e1faf3a](https://github.com/unraid/api/commit/e1faf3aa8db5973eb1bb0ea7a4844f820504618d))
|
||||
* stop command exits ([2dbfdb6](https://github.com/unraid/api/commit/2dbfdb670a773114c0fdc68c7cf9d29fa4e28a9b))
|
||||
* swap to placeholder key ([d1864d0](https://github.com/unraid/api/commit/d1864d0020ed56ab2368d23b48604b55cff21ae4))
|
||||
* test issues ([e4b55b1](https://github.com/unraid/api/commit/e4b55b133bb2dc4bf2ccfd6fd2fc244daadbea53))
|
||||
* test simplification to ensure no redownloads ([e07dad3](https://github.com/unraid/api/commit/e07dad3a6947aa186c4ac03032b5b3813cd046b6))
|
||||
* tests ([25c1c1a](https://github.com/unraid/api/commit/25c1c1a55a3fb32b76bf5cb7257a4ba44f717a89))
|
||||
* tests and validate token clears screen ([7f48ddd](https://github.com/unraid/api/commit/7f48dddcd2e2ea1ae3a55ecc54d5ac274535b714))
|
||||
* type for generic test ([e856535](https://github.com/unraid/api/commit/e85653592a9d6eadcd0be89bf90a96c5d313fda3))
|
||||
* unit test issues ([c58f7a7](https://github.com/unraid/api/commit/c58f7a7f246902c7d354eb51d1c87c8ea3b636a3))
|
||||
* unit tests updated ([9548505](https://github.com/unraid/api/commit/954850535bec6b09aaf66b01d3ee749c8a22de5d))
|
||||
* unneeded await on api-key service ([0325be7](https://github.com/unraid/api/commit/0325be757ee4c04b5c23365ff592f521a492595b))
|
||||
* unused imports ([a5447aa](https://github.com/unraid/api/commit/a5447aa2f4c99968651fa3750d6bf0e8d68678de))
|
||||
* update tests ([d0696a9](https://github.com/unraid/api/commit/d0696a93810893ccd6c676df1c639ca279992428))
|
||||
* use an enum and defaults for sandbox value ([eb56483](https://github.com/unraid/api/commit/eb56483ba2693944d39f4409c91b75ee82a7d30b))
|
||||
* use batchProcess ([ffbb9d7](https://github.com/unraid/api/commit/ffbb9d7750568bfa849d21e051503d1fcca5355f))
|
||||
* use cwd when running application ([e016652](https://github.com/unraid/api/commit/e01665264b6f45366cdacf60c0f3553adfbd85d3))
|
||||
* use placeholder in test API key ([c6b7755](https://github.com/unraid/api/commit/c6b7755214de8bedd5c0f2735473c2a559b1e26f))
|
||||
* watch all events to load keys ([59ca177](https://github.com/unraid/api/commit/59ca17787e4d36113b0a8c5ef2117acfc491c49c))
|
||||
* **web:** name of toaster component ([e093242](https://github.com/unraid/api/commit/e093242d20ddd72567396f4a53238250f2199a64))
|
||||
* build issue ([99d8b31](https://github.com/unraid/api/commit/99d8b31fa8bef13ae6c7dcf74593bc2999a676ed))
|
||||
|
||||
## [4.6.1](https://github.com/unraid/api/compare/v4.6.0...v4.6.1) (2025-04-03)
|
||||
|
||||
|
||||
### Miscellaneous Chores
|
||||
### Bug Fixes
|
||||
|
||||
* release 4.1.2 ([dbab290](https://github.com/unraid/api/commit/dbab290b429f9eff8fa903d193de2bd02bb392bd))
|
||||
* don't mv deploy on prod release ([9568aab](https://github.com/unraid/api/commit/9568aabd17fbab9e7e2f06f723ee57dc2026583c))
|
||||
|
||||
## [4.6.0](https://github.com/unraid/api/compare/v4.5.0...v4.6.0) (2025-04-03)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* add gui settings field for sso users ([#1310](https://github.com/unraid/api/issues/1310)) ([5ba3fa6](https://github.com/unraid/api/commit/5ba3fa67a26828f29e1e234c6838e7beaa3fdff3))
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* build ([ed67af9](https://github.com/unraid/api/commit/ed67af956802eec95845519997bc15b32c84c6ee))
|
||||
* **plugin:** flaky masking of benign warning during pnpm install ([#1313](https://github.com/unraid/api/issues/1313)) ([1f10b63](https://github.com/unraid/api/commit/1f10b63c8b015e9a2527f79e15a7042feb2d2aca))
|
||||
|
||||
## [4.5.0](https://github.com/unraid/api/compare/v4.4.1...v4.5.0) (2025-04-02)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* add webgui theme switcher component ([#1304](https://github.com/unraid/api/issues/1304)) ([e2d00dc](https://github.com/unraid/api/commit/e2d00dc3464f9663062ac759a8aad85e61804b91))
|
||||
* api plugin system & offline versioned dependency vendoring ([#1252](https://github.com/unraid/api/issues/1252)) ([9f492bf](https://github.com/unraid/api/commit/9f492bf2175b1b909d3bec079ce901ba34765eb7))
|
||||
* **api:** add `unraid-api --delete` command ([#1289](https://github.com/unraid/api/issues/1289)) ([2f09445](https://github.com/unraid/api/commit/2f09445f2ed6b23cd851ca64ac5b84cfde3cbd50))
|
||||
* basic array controls ([#1291](https://github.com/unraid/api/issues/1291)) ([61fe696](https://github.com/unraid/api/commit/61fe6966caf973eec3d74c67741302dd4b507134))
|
||||
* basic docker controls ([#1292](https://github.com/unraid/api/issues/1292)) ([12eddf8](https://github.com/unraid/api/commit/12eddf894e1808b61f5d4e007f3a7a39a3f2e4d6))
|
||||
* copy to webgui repo script docs + wc build options ([#1285](https://github.com/unraid/api/issues/1285)) ([e54f189](https://github.com/unraid/api/commit/e54f189630f70aeff5af6bdef4271f0a01fedb74))
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* additional url fixes ([4b2763c](https://github.com/unraid/api/commit/4b2763c7f9d8b85d5b0ce066dfc9a9a80a115658))
|
||||
* **api:** redirect benign pnpm postinstall warning to log file ([#1290](https://github.com/unraid/api/issues/1290)) ([7fb7849](https://github.com/unraid/api/commit/7fb78494cb23630f60a889e6252fc06754e14ef9))
|
||||
* **deps:** update dependency chalk to v5 ([#1296](https://github.com/unraid/api/issues/1296)) ([6bed638](https://github.com/unraid/api/commit/6bed63805ff026be98a8e20c4d8a37cd47048357))
|
||||
* **deps:** update dependency diff to v7 ([#1297](https://github.com/unraid/api/issues/1297)) ([3c6683c](https://github.com/unraid/api/commit/3c6683c81422a088c13e9545aaecececd78b8628))
|
||||
* disable all config watchers ([#1306](https://github.com/unraid/api/issues/1306)) ([5c1b435](https://github.com/unraid/api/commit/5c1b4352cf71d8525f667822f8ca202e2934f463))
|
||||
* extract callbacks to library ([#1280](https://github.com/unraid/api/issues/1280)) ([2266139](https://github.com/unraid/api/commit/226613974258f15d39932de94316a54aec2e29d2))
|
||||
* OEM plugin issues ([#1288](https://github.com/unraid/api/issues/1288)) ([d5a3d0d](https://github.com/unraid/api/commit/d5a3d0dfac214fc433c2c0aec578de564a990dd4))
|
||||
* replace files lost during pruning ([d0d2ff6](https://github.com/unraid/api/commit/d0d2ff65ed2d51223414e50bb1c2ecf82e32a071))
|
||||
|
||||
## [4.4.1](https://github.com/unraid/api/compare/v4.4.0...v4.4.1) (2025-03-26)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* .env.production from allowing console logs on build ([#1273](https://github.com/unraid/api/issues/1273)) ([32acc2d](https://github.com/unraid/api/commit/32acc2d27c8bb565b38a66d8233030de3711ea12))
|
||||
* patch version override logic incorrect ([#1275](https://github.com/unraid/api/issues/1275)) ([6a59756](https://github.com/unraid/api/commit/6a597561a3e21c27fff8d4530cf59cf382eaa015))
|
||||
|
||||
## [4.4.0](https://github.com/unraid/api/compare/v4.3.1...v4.4.0) (2025-03-25)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* add ReplaceKey functionality to plugin ([#1264](https://github.com/unraid/api/issues/1264)) ([4aadcef](https://github.com/unraid/api/commit/4aadcef1ca6b45b44885f2d2a986874e86945d4f))
|
||||
* downgrade page replace key check ([#1263](https://github.com/unraid/api/issues/1263)) ([8d56d12](https://github.com/unraid/api/commit/8d56d12f67d86d7015a358727bcb303eb511ac42))
|
||||
* make log viewer component dynamic ([#1242](https://github.com/unraid/api/issues/1242)) ([e6ec110](https://github.com/unraid/api/commit/e6ec110fbf81b329b72ef350643bf3c76734290a))
|
||||
* ReplaceKey functionality in Registration and Update pages ([#1246](https://github.com/unraid/api/issues/1246)) ([04307c9](https://github.com/unraid/api/commit/04307c977cfd4916753140e5a20811c561d2dfb2))
|
||||
* UnraidCheckExec for Check OS Updates via UPC dropdown ([#1265](https://github.com/unraid/api/issues/1265)) ([5935a3b](https://github.com/unraid/api/commit/5935a3b3c2f69ee683146c3fcc798d72996633f8))
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **deps:** update all non-major dependencies ([#1236](https://github.com/unraid/api/issues/1236)) ([7194f85](https://github.com/unraid/api/commit/7194f859ce0178116621b4bdf28db553b037940d))
|
||||
* **deps:** update all non-major dependencies ([#1247](https://github.com/unraid/api/issues/1247)) ([20b0aeb](https://github.com/unraid/api/commit/20b0aeb9d7e621ec917c928135b2c867e07ce7a4))
|
||||
* **deps:** update all non-major dependencies ([#1251](https://github.com/unraid/api/issues/1251)) ([33a1a1d](https://github.com/unraid/api/commit/33a1a1ddd2f228cf001bb492f9c76bb5bc6dc8a0))
|
||||
* **deps:** update all non-major dependencies ([#1253](https://github.com/unraid/api/issues/1253)) ([53fec0e](https://github.com/unraid/api/commit/53fec0efaba8f3e2dcf5f2899e3099e0e12f5162))
|
||||
* **deps:** update dependency @nestjs/passport to v11 ([#1244](https://github.com/unraid/api/issues/1244)) ([edc93a9](https://github.com/unraid/api/commit/edc93a921ea93d98b7c2de9a7fed2fed650365e8))
|
||||
* **deps:** update dependency graphql-subscriptions to v3 ([#1209](https://github.com/unraid/api/issues/1209)) ([c14c85f](https://github.com/unraid/api/commit/c14c85fcf7ce920edd75d15fa9b3d556f452bb88))
|
||||
* **deps:** update dependency ini to v5 ([#1217](https://github.com/unraid/api/issues/1217)) ([f27660f](https://github.com/unraid/api/commit/f27660f140acb647cab1dce162af0d49d5655fb6))
|
||||
* **deps:** update dependency jose to v6 ([#1248](https://github.com/unraid/api/issues/1248)) ([42e3d59](https://github.com/unraid/api/commit/42e3d59107dd800351ee1f7d175c550465ebddb4))
|
||||
* **deps:** update dependency marked to v15 ([#1249](https://github.com/unraid/api/issues/1249)) ([2b6693f](https://github.com/unraid/api/commit/2b6693f404a9a3405300637d2c55bd5b65c61f0b))
|
||||
* **deps:** update dependency pino-pretty to v13 ([#1250](https://github.com/unraid/api/issues/1250)) ([85fb910](https://github.com/unraid/api/commit/85fb91059a0ad7728d766cd3b429857b3fd4bd08))
|
||||
* **deps:** update dependency pm2 to v6 ([#1258](https://github.com/unraid/api/issues/1258)) ([04ad2bc](https://github.com/unraid/api/commit/04ad2bc9c8c1e5fd9622655ce9881bde17388246))
|
||||
* **deps:** update dependency shadcn-vue to v1 ([#1259](https://github.com/unraid/api/issues/1259)) ([1a4fe8f](https://github.com/unraid/api/commit/1a4fe8f85f50cf34df6af2c0bf55efc305fa9fff))
|
||||
* **deps:** update dependency vue-i18n to v11 ([#1261](https://github.com/unraid/api/issues/1261)) ([0063286](https://github.com/unraid/api/commit/0063286e29b9a7439e6acc64973a3152370c75c3))
|
||||
* **deps:** update vueuse monorepo to v13 (major) ([#1262](https://github.com/unraid/api/issues/1262)) ([94caae3](https://github.com/unraid/api/commit/94caae3d87fbfb04dfe5633030e24acddbcc0f6b))
|
||||
* make scripts executable when building the plugin ([#1255](https://github.com/unraid/api/issues/1255)) ([e237f38](https://github.com/unraid/api/commit/e237f38bc4646f13461938c03d566fef781ad406))
|
||||
* node installation not persisting across reboots ([#1256](https://github.com/unraid/api/issues/1256)) ([0415cf1](https://github.com/unraid/api/commit/0415cf1252ed8c7fba32a65c031dc0d21e0f5a81))
|
||||
* update configValid state to ineligible in var.ini and adjust rel… ([#1268](https://github.com/unraid/api/issues/1268)) ([ef8c954](https://github.com/unraid/api/commit/ef8c9548baef99010e2f26288af33a90167e5177))
|
||||
|
||||
## [4.3.1](https://github.com/unraid/api/compare/v4.3.0...v4.3.1) (2025-03-18)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* stepper fixes ([#1240](https://github.com/unraid/api/issues/1240)) ([e7f6f5e](https://github.com/unraid/api/commit/e7f6f5e8315c50fd37193f7d7de2af3d370c18ea))
|
||||
|
||||
## [4.3.0](https://github.com/unraid/api/compare/v4.2.1...v4.3.0) (2025-03-18)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* update production release flow to validate less strictly ([#1238](https://github.com/unraid/api/issues/1238)) ([3afb203](https://github.com/unraid/api/commit/3afb203b856655e4ce7c9d709e30d3f2ebd64784))
|
||||
|
||||
## [4.2.1](https://github.com/unraid/api/compare/v4.2.0...v4.2.1) (2025-03-18)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **deps:** update all non-major dependencies ([#1192](https://github.com/unraid/api/issues/1192)) ([65b8db2](https://github.com/unraid/api/commit/65b8db2845a5f4234527a70b0625b1a88df5b2fe))
|
||||
|
||||
## [4.2.0](https://github.com/unraid/api/compare/v4.1.3...v4.2.0) (2025-03-18)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* add resolver for logging ([#1222](https://github.com/unraid/api/issues/1222)) ([2d90408](https://github.com/unraid/api/commit/2d9040801f044dc7a974e9737acdffbbdcae5e37))
|
||||
* connect settings web component ([#1211](https://github.com/unraid/api/issues/1211)) ([653de00](https://github.com/unraid/api/commit/653de00d3761826c8f0a969be3cfb9253f2d3e43))
|
||||
* improve local dev with install path ([#1221](https://github.com/unraid/api/issues/1221)) ([32c5b0a](https://github.com/unraid/api/commit/32c5b0a879e59a823d5dc7bf4b4b4e9d07d2f010))
|
||||
* split plugin builds ([4d10966](https://github.com/unraid/api/commit/4d109669dba614328db068697d97d3ad424a6237))
|
||||
* swap to absolute paths for css ([#1224](https://github.com/unraid/api/issues/1224)) ([6f9fa10](https://github.com/unraid/api/commit/6f9fa10c0909874a5964818f24ed28b79463aed2))
|
||||
* update theme application logic and color picker ([#1181](https://github.com/unraid/api/issues/1181)) ([c352f49](https://github.com/unraid/api/commit/c352f4961885e16260d95b0c8be938009bcfc5e4))
|
||||
* use patch version if needed on update check ([#1227](https://github.com/unraid/api/issues/1227)) ([6ed46b3](https://github.com/unraid/api/commit/6ed46b3b61432c51a58c741ead014c856671d839))
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* add INELIGIBLE state to ConfigErrorState enum ([#1220](https://github.com/unraid/api/issues/1220)) ([1f00212](https://github.com/unraid/api/commit/1f00212a7e663f29cbdeabf5663c9f398799b761))
|
||||
* **api:** dynamix notifications dir during development ([#1216](https://github.com/unraid/api/issues/1216)) ([0a382ca](https://github.com/unraid/api/commit/0a382ca5b77ad6e7d5e5c6f35b11ac2dd2479d30))
|
||||
* **api:** type imports from generated graphql types ([#1215](https://github.com/unraid/api/issues/1215)) ([fd02297](https://github.com/unraid/api/commit/fd02297971d88ac420887969313fbca570ffdc6d))
|
||||
* **deps:** update dependency @nestjs/schedule to v5 ([#1197](https://github.com/unraid/api/issues/1197)) ([b1ff6e5](https://github.com/unraid/api/commit/b1ff6e553ed1391e8f450446088502fd6b9782c0))
|
||||
* **deps:** update dependency @vueuse/core to v12 ([#1199](https://github.com/unraid/api/issues/1199)) ([d8b8339](https://github.com/unraid/api/commit/d8b8339d6c8cdebd468160fb17c4056ad5dffd4c))
|
||||
* fix changelog thing again ([2426345](https://github.com/unraid/api/commit/24263459fc35d61065712d315a03fd425d98d328))
|
||||
* fix invalid path to node with sh execution ([#1213](https://github.com/unraid/api/issues/1213)) ([d12448d](https://github.com/unraid/api/commit/d12448d75a6637fe1608e3e3807ecfd2a20f55c9))
|
||||
* load tag correctly ([acd692b](https://github.com/unraid/api/commit/acd692b717b91d708fa93a2941ac4ee9ad544ac4))
|
||||
* log errors ([629feda](https://github.com/unraid/api/commit/629feda5b8befd1677d38999a08c667717491442))
|
||||
* one-command dev & web env files ([#1214](https://github.com/unraid/api/issues/1214)) ([8218fab](https://github.com/unraid/api/commit/8218fab98b53394171a4cc207432de01e95250ae))
|
||||
* re-release fixed ([bb526b5](https://github.com/unraid/api/commit/bb526b5444ac6aaa832adee723513b98df4de423))
|
||||
* recreate watcher on path change ([#1203](https://github.com/unraid/api/issues/1203)) ([5a9154e](https://github.com/unraid/api/commit/5a9154ebeadfbc6439e7aac6cf9fd2464acff6d0))
|
||||
* update brand loading variants for consistent sizing ([#1223](https://github.com/unraid/api/issues/1223)) ([d7a4b98](https://github.com/unraid/api/commit/d7a4b9855f182588fded088bf9c5610b2f9967b7))
|
||||
|
||||
## [4.1.3](https://github.com/unraid/api/compare/v4.1.2...v4.1.3) (2025-02-21)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* chown correctly ([#1185](https://github.com/unraid/api/issues/1185)) ([11b0441](https://github.com/unraid/api/commit/11b04417371ba77eddc12699db8575988d6deafc))
|
||||
* create releases as drafts ([0adba3a](https://github.com/unraid/api/commit/0adba3ae3566ad84626a9ab1cf7d38edb24de69f))
|
||||
* **deps:** update all non-major dependencies ([#1168](https://github.com/unraid/api/issues/1168)) ([443b608](https://github.com/unraid/api/commit/443b608163cdb64775d6758b8207cbe745f892f4))
|
||||
* revert config ([c17db6d](https://github.com/unraid/api/commit/c17db6d7648c15f71cd2195530cd0c2d051db3f6))
|
||||
* small modal window ([#1183](https://github.com/unraid/api/issues/1183)) ([2183965](https://github.com/unraid/api/commit/2183965757ded27a5a01a6e27c4b783c9434af2e))
|
||||
|
||||
## [4.1.2](https://github.com/unraid/api/compare/v4.1.2...v4.1.2) (2025-02-21)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* add api key creation logic ([81382bc](https://github.com/unraid/api/commit/81382bcf1d26364ad9c5445530f648209101cf91))
|
||||
* add category.json ([c9e87e2](https://github.com/unraid/api/commit/c9e87e2e5b47a8801b7865ed586c803d0b470915))
|
||||
* add command to package.json scripts ([0dfb07f](https://github.com/unraid/api/commit/0dfb07f9eb519e60441f4123423f65acfdffca3b))
|
||||
* add csrf support to api & web components ([#999](https://github.com/unraid/api/issues/999)) ([19241ed](https://github.com/unraid/api/commit/19241ed55f5112f878b9890d8695badf7eb1c3eb))
|
||||
* add description flag, remove console log, and update readme ([c416c30](https://github.com/unraid/api/commit/c416c30951de4ed6b8d7a8c014403772db1c2015))
|
||||
* add developer docs ([#1128](https://github.com/unraid/api/issues/1128)) ([bb2e340](https://github.com/unraid/api/commit/bb2e340b68268d5121db650b27e8b2580c7966bb))
|
||||
* add line about recommendation for sso command ([44727a8](https://github.com/unraid/api/commit/44727a8d1a7c16c566678da43119b17a6303e375))
|
||||
* add log rotation ([f5c7ad9](https://github.com/unraid/api/commit/f5c7ad9221f80e4630e69f78d57f08f4c7252719))
|
||||
* add logging around fixture downloads ([a1ce27b](https://github.com/unraid/api/commit/a1ce27b17c970657f52635600f0d13116523f928))
|
||||
* add logrotate cron again ([4f85f66](https://github.com/unraid/api/commit/4f85f6687f920dae50277e726e2db2c3d946e867))
|
||||
* add patch for auth-request.php ([ec6ec56](https://github.com/unraid/api/commit/ec6ec562f43aac9947de2e9c269181303f42b2db))
|
||||
* add user with cli ([37458cd](https://github.com/unraid/api/commit/37458cd7408a1ad8aedca66a55ff13ac19ee30db))
|
||||
* address log level feedback ([49774aa](https://github.com/unraid/api/commit/49774aae459797f04ef2866ca064050aa476ae91))
|
||||
* allow csrf passing through querystring ([dba38c0](https://github.com/unraid/api/commit/dba38c0d149a77e4104c718c53d426330a17f2fa))
|
||||
* allow deletion and creation of files with patches ([32c9524](https://github.com/unraid/api/commit/32c952402c25e8340b1c628b4d0fdc4816b28ade))
|
||||
* always ensureDirectory for keys exists ([c6e9f80](https://github.com/unraid/api/commit/c6e9f804c58e44b46bce9f0da2260888544354cd))
|
||||
* **api:** graphql sandbox on unraid servers ([#1047](https://github.com/unraid/api/issues/1047)) ([ec504f3](https://github.com/unraid/api/commit/ec504f39297c92b64d9d3cc2f8f482cc1f3a2e44))
|
||||
* **api:** omit tz from sys time date format by default ([b2acde3](https://github.com/unraid/api/commit/b2acde3351d7afe18a2902e90b672537aadabffd))
|
||||
* **api:** rm 2fa & t2fa from myservers config type ([#996](https://github.com/unraid/api/issues/996)) ([89e791a](https://github.com/unraid/api/commit/89e791ad2e6f0395bee05e3f8bdcb2c8d72305dd))
|
||||
* async disk mapping ([bbb27e6](https://github.com/unraid/api/commit/bbb27e686897e4f9a0c926553d75aa046d7a8323))
|
||||
* async hypervisor and FIXED vm listing ([e79f4dd](https://github.com/unraid/api/commit/e79f4ddbc7061c249efb8214a311bb629628f669))
|
||||
* auto-docusaurus-prs ([#1127](https://github.com/unraid/api/issues/1127)) ([1147e76](https://github.com/unraid/api/commit/1147e762ae2fed6dea198fa38d6bcc514a1e66fb))
|
||||
* begin building plugin with node instead of bash ([#1120](https://github.com/unraid/api/issues/1120)) ([253b65a](https://github.com/unraid/api/commit/253b65a85ab9c5f53d53ef265b41aa132678f278))
|
||||
* better patch application ([a3e7daa](https://github.com/unraid/api/commit/a3e7daa6a6565ac81004ffd13da35d8b95b429cf))
|
||||
* better pm2 calls, log lines ([338ce30](https://github.com/unraid/api/commit/338ce3061310dfc42ad5f65edacbe5272de4afc7))
|
||||
* cleanup config entries ([943e73f](https://github.com/unraid/api/commit/943e73fa696b6ecec3227be914ab4962c4fee79d))
|
||||
* cleanup disclaimer and command to add users ([6be3af8](https://github.com/unraid/api/commit/6be3af8d7569d9c413dd9349df52e3fa4cb4f631))
|
||||
* cli Commands ([f8e5367](https://github.com/unraid/api/commit/f8e5367f3eb47daa5bcbd7711ae5835369502a1d))
|
||||
* CLI options for adding and deleting users ([16bf6d4](https://github.com/unraid/api/commit/16bf6d4c27ae8fa8d6d05ec4b28ce49a12673278))
|
||||
* coderabbit suggestion ([11ac36c](https://github.com/unraid/api/commit/11ac36c3616a90853d91467526fd39ecba17db88))
|
||||
* configure PM2 on startup ([2b908f1](https://github.com/unraid/api/commit/2b908f100b9eefaccf2264d5ff9945667568acf0))
|
||||
* convert to pnpm monorepo ([#1137](https://github.com/unraid/api/issues/1137)) ([8d89f8b](https://github.com/unraid/api/commit/8d89f8b20d6f3983d4e85b33827a857aa862db37))
|
||||
* create key cli command logic and add to index command list ([9b2a62d](https://github.com/unraid/api/commit/9b2a62d642b0942e3787e4ddd582a66e40321ab2))
|
||||
* csv validation ([84aae15](https://github.com/unraid/api/commit/84aae15a73014592c226fa3701e34e57c7b60b46))
|
||||
* default value for option ([6513fc4](https://github.com/unraid/api/commit/6513fc49de61c836e1aabf32a874d7da7da18adb))
|
||||
* disable casbin logging ([2518e7c](https://github.com/unraid/api/commit/2518e7c506f0d3aa9f44031d61dce95d9db0a4cf))
|
||||
* docstrings ([b836ba7](https://github.com/unraid/api/commit/b836ba72516c554ee8973d69aaaa4ed35b465fa7))
|
||||
* dont pass entire server state for privacy ([54e3f17](https://github.com/unraid/api/commit/54e3f17bd9e541f50970c696bbe8b602ec38a748))
|
||||
* download fixtures from the web ([1258c2b](https://github.com/unraid/api/commit/1258c2bc1813f0fa3cd52b4932302ad12b4edd01))
|
||||
* enable sandbox in dev mode ([4536d70](https://github.com/unraid/api/commit/4536d7092d77c68f5a996fd63bf74ce6e64f5efe))
|
||||
* enable sandbox with developer command ([c354d48](https://github.com/unraid/api/commit/c354d482283295547afeb99c5e110b0181197c44))
|
||||
* enable token sign in with comma separated subs in myservers.config ([ebed5bd](https://github.com/unraid/api/commit/ebed5bddea1445d9aaaee60d54758dc74b77271e))
|
||||
* exit cli after running command ([04bf528](https://github.com/unraid/api/commit/04bf528616fcbdf916916734a12d5fd32db9a06d))
|
||||
* extensive file checking ([ab881c8](https://github.com/unraid/api/commit/ab881c8aed8dd4aa9fd71c32b50d3514d1496fa5))
|
||||
* fallback to local ([a2579c2](https://github.com/unraid/api/commit/a2579c2a7f80f54b4cc61533aec9ecc41a7e7f54))
|
||||
* faster failure logic ([b439434](https://github.com/unraid/api/commit/b439434f1574e174fcf23f3a5f5b8df8e092eb1e))
|
||||
* fix docusaurus build + update snapshot ([23b27bd](https://github.com/unraid/api/commit/23b27bd63ea99f4137538eab40501daa67d7e3f5))
|
||||
* force linting on build ([43e6639](https://github.com/unraid/api/commit/43e663998a55e83c142067cb64ae7a331395fe68))
|
||||
* generate key one time ([afe53c3](https://github.com/unraid/api/commit/afe53c30ea9987e6d8728faa2cb7291f8a126ecb))
|
||||
* glob for files ([3fe281f](https://github.com/unraid/api/commit/3fe281f1ae28e3cbc089b5244a6ae2863b20adcb))
|
||||
* hypervisor async imports ([32686ca](https://github.com/unraid/api/commit/32686ca4f0c25c43c6a9f7162bb8179b39e58f7e))
|
||||
* ignore generated code ([68265a2](https://github.com/unraid/api/commit/68265a26efa588b60001310b9a11b398f04ae88f))
|
||||
* improve packing ([9ef02d5](https://github.com/unraid/api/commit/9ef02d53666b70d41fdd186364808deac715e1ff))
|
||||
* initial patcher implementation using the diff tool ([c87acbb](https://github.com/unraid/api/commit/c87acbb146c2e4e30997c964cd8be325dee68cea))
|
||||
* initial setup of permissions on keys ([#1068](https://github.com/unraid/api/issues/1068)) ([cf0fa85](https://github.com/unraid/api/commit/cf0fa850954ea2f018e338a132149f872b966df4))
|
||||
* initial version of modification service ([b80469d](https://github.com/unraid/api/commit/b80469d38e519a7ba0e6eae636cda2a821e2d465))
|
||||
* inject after form ([a4b276f](https://github.com/unraid/api/commit/a4b276f7874580bbf9827025730777715c9983da))
|
||||
* kill timeout extended ([22d4026](https://github.com/unraid/api/commit/22d40264a02672a818053b5280d63a03ff7336b9))
|
||||
* log size and only tar files ([731f2f8](https://github.com/unraid/api/commit/731f2f8e77a77b544a7f526c78aabfacca71eee4))
|
||||
* logrotate test ([4504c39](https://github.com/unraid/api/commit/4504c39a2bbcf51385578b69a9fdc7b81a950e98))
|
||||
* manually install libvirt in build process to ensure it is included in the final build ([e695481](https://github.com/unraid/api/commit/e695481363f0d5d7add9d0e0d50d1e113b3024f6))
|
||||
* more pm2 fixes ([8257bdf](https://github.com/unraid/api/commit/8257bdff3624211ee645349abdec303bf271538e))
|
||||
* move fixtures into __test__ folder ([22a901d](https://github.com/unraid/api/commit/22a901de9b0c274d3f75ed4b4618cd6cd90324ba))
|
||||
* myservers_fb keepalive location ([e07e7f3](https://github.com/unraid/api/commit/e07e7f335c8ea4a73966ada90c26b7c82dbb025e))
|
||||
* only write config when a specific config update action occurs ([ec29778](https://github.com/unraid/api/commit/ec29778e37a50f43eb164991bcf2a6ff9c266033))
|
||||
* properly read log level from environment ([b5151e9](https://github.com/unraid/api/commit/b5151e9ba76a6814e24e8da34e8a3c1bf1cc2144))
|
||||
* public index ([f0641ea](https://github.com/unraid/api/commit/f0641ea7ca0919884dc3b8642c2e6694398e3246))
|
||||
* remove sso if disabled on Unraid-API start ([3bc407c](https://github.com/unraid/api/commit/3bc407c54e8e7aeadebd9ac223d71f21ef97fca1))
|
||||
* remove sso user command ([bbd809b](https://github.com/unraid/api/commit/bbd809b83826e81eef38a06e66f3393e4f83e81e))
|
||||
* remove sso user options ([e34041f](https://github.com/unraid/api/commit/e34041f86ef7ab6cf5e2fdf7efb86458d190edc1))
|
||||
* remove unused config sections ([f0b9c4f](https://github.com/unraid/api/commit/f0b9c4f44ab0ee8f75bf96fde2413988ef4f6a8c))
|
||||
* remove unused fields ([d2d0f7c](https://github.com/unraid/api/commit/d2d0f7cd9acb53ea2372245d7ef669c7ca24ee8a))
|
||||
* remove unused vars ([0507713](https://github.com/unraid/api/commit/0507713972e344ad47bd077554d5888269669e9c))
|
||||
* rename api key resource back to api_key ([ee9666b](https://github.com/unraid/api/commit/ee9666b317d7feb5c15d53e2a6b902c7771c8c7a))
|
||||
* rename modification file ([70a93f2](https://github.com/unraid/api/commit/70a93f2cc63e0e62242be6fe1a717515a6fbec85))
|
||||
* reorder index ([858553f](https://github.com/unraid/api/commit/858553f0debb6424ae0614640b82a050c33f175a))
|
||||
* restart the API when an SSO user is added ([a6b0c90](https://github.com/unraid/api/commit/a6b0c906a423df048401750943f02dfdc9bc2619))
|
||||
* restoring sso error ([234bf7d](https://github.com/unraid/api/commit/234bf7dfa4b0be88b6cc13996d8f29ec819da26e))
|
||||
* revert local api key value ([ff40e7a](https://github.com/unraid/api/commit/ff40e7ae392052d3d9e1b084c5f4851e8ebd529e))
|
||||
* rollback if patch exists before applying ([c2f4e8d](https://github.com/unraid/api/commit/c2f4e8d4e5c758601bd20ba491fd077b434ba45e))
|
||||
* secondary changes ([d75331a](https://github.com/unraid/api/commit/d75331a67e3566875ce8642fce80195e79932a4c))
|
||||
* service tests for modifier service ([08c1502](https://github.com/unraid/api/commit/08c150259f2b4630d973803f4edff69c8bf0ec3a))
|
||||
* session issues ([5981693](https://github.com/unraid/api/commit/5981693abd605337f9174ba4c85fd1bfc243edeb))
|
||||
* shared call to createPatch ([eb3e263](https://github.com/unraid/api/commit/eb3e263fb32a748bfa06ec6d119ee51d242707cf))
|
||||
* simplify docs ([d428030](https://github.com/unraid/api/commit/d428030b806f55b62421559d434fc723786b03ad))
|
||||
* style improvements ([b0f395e](https://github.com/unraid/api/commit/b0f395ef76f11047eaa13091df277df0459e9d8f))
|
||||
* swap to async exit hook ([4302f31](https://github.com/unraid/api/commit/4302f316820a109c76408092994727b2dc030a15))
|
||||
* switch to nest-commander ([1ab2ab5](https://github.com/unraid/api/commit/1ab2ab5b58a1f49cd6b05aaa84bfeced49d68e8e))
|
||||
* try catch restart ([89abee6](https://github.com/unraid/api/commit/89abee680bdbdaa9946ddb991f0e6b5ada9ccdf7))
|
||||
* **ui:** webgui-compatible web component library ([#1075](https://github.com/unraid/api/issues/1075)) ([1c7b2e0](https://github.com/unraid/api/commit/1c7b2e091b0975438860a8e1fc3db5fd8d3fcf93))
|
||||
* unnecessary comment ([0c52256](https://github.com/unraid/api/commit/0c5225612875b96319b28ef447db69ecab15cfda))
|
||||
* unraid single sign on with account app ([5183104](https://github.com/unraid/api/commit/5183104b322a328eea3e4b2f6d86fd9d4b1c76e3))
|
||||
* update packageManager field for pnpm ([8d5db7a](https://github.com/unraid/api/commit/8d5db7a9bfdf528e2d58b20cc62434ea5929d24f))
|
||||
* upgrade dependencies ([0a0cac3](https://github.com/unraid/api/commit/0a0cac3da74c2fe20f7100a9ad5d1caafa74b157))
|
||||
* use execa for start and stop ([46ab014](https://github.com/unraid/api/commit/46ab0144d41b425015487c251c1884744223ba29))
|
||||
* use zod to parse config ([19cf1be](https://github.com/unraid/api/commit/19cf1be079f2ccb9e0cfa10f2fb97a18f15c5729))
|
||||
* validate token format in both PHP and CLI ([6ef05a3](https://github.com/unraid/api/commit/6ef05a3d7770f799e7d587c2cef8d29f6058bee1))
|
||||
* **web:** add delete all notifications button to archive view in notifications sidebar ([3bda9d6](https://github.com/unraid/api/commit/3bda9d6a4ca01cc5580012b0133e72929d6dab40))
|
||||
* **web:** enhance notifications indicator in UPC ([#950](https://github.com/unraid/api/issues/950)) ([6376848](https://github.com/unraid/api/commit/63768486e4ec64ab32666a26adf96f4db4a53e81))
|
||||
* **web:** pull date format from display/date and time settings ([b058067](https://github.com/unraid/api/commit/b058067b628ca7866a9ba0a6c4c5e4d5505d98cb))
|
||||
* **web:** rm api-key validation from connect sign in ([#986](https://github.com/unraid/api/issues/986)) ([7b105d1](https://github.com/unraid/api/commit/7b105d18678e88a064f0643d6e857704789e0ee8))
|
||||
* zod config no longer any ([c32c5f5](https://github.com/unraid/api/commit/c32c5f57127b9469bde8806d78dc364562e73d9f))
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* allow concurrent testing with a shared patcher instance ([623846e](https://github.com/unraid/api/commit/623846ef46eb24a32c62516de58e8bc5d0219833))
|
||||
* **api:** append time to formatted date when a custom date format is selected ([0ac8ed9](https://github.com/unraid/api/commit/0ac8ed9d9e7e239e471eedf466832aed0270d123))
|
||||
* **api:** change log output location for diagnostic compatibility ([#1130](https://github.com/unraid/api/issues/1130)) ([cba1551](https://github.com/unraid/api/commit/cba155138379d47bc3151c7c27d745ba6a345d83))
|
||||
* **api:** delay pm2 start until server has booted ([bd3188e](https://github.com/unraid/api/commit/bd3188efea4d3656994ffae32bd53f821c96358d))
|
||||
* **api:** exclude duplicates from legacy script in archive retrieval ([8644e13](https://github.com/unraid/api/commit/8644e130979ed8740c5a8da0b3984266e2b3684c))
|
||||
* **api:** improve defaults in PM2 service ([#1116](https://github.com/unraid/api/issues/1116)) ([57526de](https://github.com/unraid/api/commit/57526dede69e3a6547d05183e43c5b36dd1cae89))
|
||||
* **api:** logrotate modification & permissions ([#1145](https://github.com/unraid/api/issues/1145)) ([5209df2](https://github.com/unraid/api/commit/5209df2776e1a985e82bedc655fe28acf1fd0bde))
|
||||
* **api:** make cookie recognition during websocket connection more ([353e012](https://github.com/unraid/api/commit/353e012db8ab5280863f32392c520b4a330c13cc))
|
||||
* **api:** pm2 start script & limit auto restarts ([#1040](https://github.com/unraid/api/issues/1040)) ([ebcd347](https://github.com/unraid/api/commit/ebcd3479e735724626ffc6907c338d5080898bee))
|
||||
* **api:** retry mothership connection up to 3x before logout ([#1069](https://github.com/unraid/api/issues/1069)) ([c27bb1b](https://github.com/unraid/api/commit/c27bb1be4c7a9ab201585586f3bc5e4afa1c7791))
|
||||
* **api:** sanitize incoming user session id's ([f5e3424](https://github.com/unraid/api/commit/f5e3424b79702e8f959b5519e83370a9e1d2033b))
|
||||
* **api:** slow init of unraid-api cli ([#1022](https://github.com/unraid/api/issues/1022)) ([5dbbae7](https://github.com/unraid/api/commit/5dbbae796792a62234497d056eac019aa084b21c))
|
||||
* **api:** update deploy-dev script to dist instead of src ([55cce09](https://github.com/unraid/api/commit/55cce09e65521762a6fe388d5b9b88ace1337c26))
|
||||
* **api:** validate cookie session data ([491f680](https://github.com/unraid/api/commit/491f680607ce7244d9e47a457e44cde711fbe00c))
|
||||
* apply and rollback error handling ([e22191b](https://github.com/unraid/api/commit/e22191bc77bc09f5c6c4ad57e5073829cf966ba4))
|
||||
* authorization type error ([#987](https://github.com/unraid/api/issues/987)) ([7a4799e](https://github.com/unraid/api/commit/7a4799e9cd4caef6acfc3661d205a377fcf499ab))
|
||||
* back to default configs ([b5711c9](https://github.com/unraid/api/commit/b5711c91284072991bcf409ac6126cd4b46afc7c))
|
||||
* backup restore formatting ([15210f6](https://github.com/unraid/api/commit/15210f64b0938ec884a3ef4379d245c661eab9a3))
|
||||
* basic test fixed ([2f38035](https://github.com/unraid/api/commit/2f38035520ca0fe796c981d08b9136d89ffc5888))
|
||||
* better js file handling ([ddf160e](https://github.com/unraid/api/commit/ddf160e878a352842e813154b607945ccc7b4081))
|
||||
* better loader functionality and error handling ([8a57d2d](https://github.com/unraid/api/commit/8a57d2dccbcb9c2effc5df5d8c69ad02713de24a))
|
||||
* cleaner logs for starting API ([79f26ef](https://github.com/unraid/api/commit/79f26ef251cb42e7f2106d00c6c05e2bf17b8227))
|
||||
* clearer error messaging ([e373849](https://github.com/unraid/api/commit/e37384966c5b9079bb507052dcaba56232c1c42a))
|
||||
* code review feedback ([c66079e](https://github.com/unraid/api/commit/c66079e9a8e0ef47e5054118d0581bec708ac604))
|
||||
* completion script registration ([05c8c9b](https://github.com/unraid/api/commit/05c8c9bf078ece2061ad8ae32497f52b8c9b94dc))
|
||||
* connect key role ([2dcfc1c](https://github.com/unraid/api/commit/2dcfc1c19a1d085df84f0b1b50c096e3220205dd))
|
||||
* create api key for connect on startup ([58329bc](https://github.com/unraid/api/commit/58329bc29521ebc26b27ee20013ac3926c5088c2))
|
||||
* create api key permissions ([cefb644](https://github.com/unraid/api/commit/cefb644bd7fa513f553ca0ca4c49f0fb42a74112))
|
||||
* create connect key ([6b1ab7b](https://github.com/unraid/api/commit/6b1ab7b74ae1d2938fa9105180a5f66e9604fd41))
|
||||
* cwd on ecosystem.config.json ([dfd0da4](https://github.com/unraid/api/commit/dfd0da4ca23078f6de2e54d5e5bd6cba06334abc))
|
||||
* default overwrite false test ([cf59107](https://github.com/unraid/api/commit/cf59107e568d91be684176335db5300bee9be865))
|
||||
* delete .original files ([a9eb21a](https://github.com/unraid/api/commit/a9eb21aac0f373990aaa3f7a99731612540533cf))
|
||||
* deprecated version warning ([89d0bd2](https://github.com/unraid/api/commit/89d0bd2e6da35fb1e8d95627d38edb54f82e0c6b))
|
||||
* **deps:** update all non-major dependencies ([#1158](https://github.com/unraid/api/issues/1158)) ([45ebc8b](https://github.com/unraid/api/commit/45ebc8b6e07c53ad3eee28d5cf8ac9cd0d827754))
|
||||
* **deps:** update apollo graphql packages ([7b1ee99](https://github.com/unraid/api/commit/7b1ee9940cca46e563bb79c7056996315f9decc5))
|
||||
* **deps:** update dependency @apollo/client to v3.12.6 ([bb7800a](https://github.com/unraid/api/commit/bb7800a8c088705fd8310671a9896cbe9b0184e5))
|
||||
* **deps:** update dependency @apollo/client to v3.12.9 ([6607cf2](https://github.com/unraid/api/commit/6607cf20c10a091d466c6a8031eebc17feb3e3fc))
|
||||
* **deps:** update dependency @graphql-tools/load-files to v7.0.1 ([4e5c724](https://github.com/unraid/api/commit/4e5c7242e43cc356f1c69adcfcd25b57896af476))
|
||||
* **deps:** update dependency @nestjs/schedule to v4.1.2 ([faf0de5](https://github.com/unraid/api/commit/faf0de5a19256efb83dc45a484e3cba65596ccd7))
|
||||
* **deps:** update dependency chokidar to v4.0.3 ([d63a93c](https://github.com/unraid/api/commit/d63a93c55004d17b6d17634c55ffbc5670ebbec7))
|
||||
* **deps:** update dependency dockerode to v4 ([#830](https://github.com/unraid/api/issues/830)) ([c331ecd](https://github.com/unraid/api/commit/c331ecd50c4910fd6c35e5ad92b3f676d552febc))
|
||||
* **deps:** update dependency dotenv to v16.4.7 ([c66a650](https://github.com/unraid/api/commit/c66a6502b027853046d126a14ddee870ffabd10c))
|
||||
* **deps:** update dependency execa to v9.5.2 ([d487c90](https://github.com/unraid/api/commit/d487c90ccc20162c76f0cdf49a736c1fee4271bd))
|
||||
* **deps:** update dependency express to v4.21.2 ([a070306](https://github.com/unraid/api/commit/a07030684c8777e47eb4a51be0ea680b7f217e74))
|
||||
* **deps:** update dependency got to v14.4.5 ([975a47c](https://github.com/unraid/api/commit/975a47c7d47841c49443f46264feb54abf53698c))
|
||||
* **deps:** update dependency graphql-ws to v5.16.2 ([25d8f08](https://github.com/unraid/api/commit/25d8f085b67c2e53876d837c739214dc874116b8))
|
||||
* **deps:** update dependency ini to v4.1.3 ([4c88cbe](https://github.com/unraid/api/commit/4c88cbee4b2d5f6717241dadac23bfe90ce15193))
|
||||
* **deps:** update dependency node-window-polyfill to v1.0.4 ([8bfa88f](https://github.com/unraid/api/commit/8bfa88f4bc932eb82dd9b33a494811ea15764758))
|
||||
* **deps:** update dependency openid-client to v6.1.7 ([0f50517](https://github.com/unraid/api/commit/0f50517a8544e1eb9b08ad1b3f05f798491b7f23))
|
||||
* **deps:** update dependency p-retry to v6.2.1 ([c6f3241](https://github.com/unraid/api/commit/c6f324155019e066701723a57b642c6e3ba8332d))
|
||||
* **deps:** update dependency pm2 to v5.4.3 ([a754090](https://github.com/unraid/api/commit/a75409026dd4e3d9ed120802012b67b179327448))
|
||||
* **deps:** update dependency uuid to v11.0.5 ([7e3398b](https://github.com/unraid/api/commit/7e3398b2efabf1a5407d6e20c165eb4923b3bab2))
|
||||
* **deps:** update graphql-tools monorepo ([cd7e2fe](https://github.com/unraid/api/commit/cd7e2feea199276a1d431cf355e54e12e5960d9a))
|
||||
* **deps:** update graphqlcodegenerator monorepo ([0446c59](https://github.com/unraid/api/commit/0446c5924a6a9dd15b875628ca0f1197cfe521c4))
|
||||
* **deps:** update graphqlcodegenerator monorepo ([15c789d](https://github.com/unraid/api/commit/15c789dbb34b85bed55c2731fb8ae8260f5f311f))
|
||||
* **deps:** update nest monorepo to v10.4.15 ([07b1ea9](https://github.com/unraid/api/commit/07b1ea9a10634a597909ae1d237cc3b1e7f959b7))
|
||||
* **deps:** update nest-graphql monorepo to v12.2.2 ([91aabd9](https://github.com/unraid/api/commit/91aabd9ffbfb8c2ceb4110217dfc05de8859077d))
|
||||
* do not process.exit on restart or stop command ([933575f](https://github.com/unraid/api/commit/933575fc2badbb09b3a9d3c66724e37a9ee246f2))
|
||||
* don't check code for execa ([508a5eb](https://github.com/unraid/api/commit/508a5eb49d9514dca9953317d9fa93314fe63e4c))
|
||||
* dont remove login file without a backup presetn ([0370e4f](https://github.com/unraid/api/commit/0370e4f7ea3e3df0d2264264324d8e53ffc0c086))
|
||||
* ensure directory exists before making connect key ([9e27ec9](https://github.com/unraid/api/commit/9e27ec98b68a49bdd6dc4b03de8c0cc3a1470a5e))
|
||||
* excess spacing in api-key.service ([1deb002](https://github.com/unraid/api/commit/1deb0023287a39d40e52e89c515a28e62352f62c))
|
||||
* extra log line ([1183063](https://github.com/unraid/api/commit/1183063aa7063afd8222def18f5e1fd6077e8c88))
|
||||
* extra spacing in config.ts ([f3ee7be](https://github.com/unraid/api/commit/f3ee7be80f2c60266fbb13597a70f0a389fb577f))
|
||||
* file modification service fixes ([aa5b3f4](https://github.com/unraid/api/commit/aa5b3f4e47ed88df23af00dfcccb7b64786b6231))
|
||||
* find by key, not ID ([3c3fa1e](https://github.com/unraid/api/commit/3c3fa1e27cfabbe6926c3da8870751397eed1def))
|
||||
* fix libvirt bindings ([#1167](https://github.com/unraid/api/issues/1167)) ([5817e5d](https://github.com/unraid/api/commit/5817e5d4b1697bbdfaa1984ccd650a232233cc15))
|
||||
* forced restarting on commands ([925866d](https://github.com/unraid/api/commit/925866d389e337fcb8c249ead929e1f65854465b))
|
||||
* format authrequest mod as other files ([180a81d](https://github.com/unraid/api/commit/180a81dbae8e749eae237fc8cee2950c790eedf0))
|
||||
* formatting issue ([42ca969](https://github.com/unraid/api/commit/42ca9691f7547a4340501863c1882efc0aee4c60))
|
||||
* initial feedback about report addressed ([5dee09c](https://github.com/unraid/api/commit/5dee09c77ad375de2eca59f650e5fea2070087b5))
|
||||
* install as-integrations/fastify ([ff4546d](https://github.com/unraid/api/commit/ff4546d6692d2a4799f2dbeef0d5e5c6bac62561))
|
||||
* length ([83579f1](https://github.com/unraid/api/commit/83579f1fbd03ffe929d009c20d214b4de62835c6))
|
||||
* lint ([0f218b8](https://github.com/unraid/api/commit/0f218b8b72e397734823efab8f2141973a3a80ce))
|
||||
* lint ([82bca54](https://github.com/unraid/api/commit/82bca54c594265ddf23a298691bd7ef6d4b47f32))
|
||||
* lint ([ceb443d](https://github.com/unraid/api/commit/ceb443da15d177a950c36af61b93a7126cf4ca85))
|
||||
* lint ([da04e7c](https://github.com/unraid/api/commit/da04e7ce0873d7802a936952d91e9867f0868a6e))
|
||||
* lint ([7d87f0e](https://github.com/unraid/api/commit/7d87f0eee23dfa0f391fd342d38ed9084f18d8d4))
|
||||
* logrotate error ([8c64dd2](https://github.com/unraid/api/commit/8c64dd2f2c65aa83ce0e2d501357ee595c976e56))
|
||||
* mock ensureDirSync ([7e012e6](https://github.com/unraid/api/commit/7e012e6a2eb96ccddf5a1f69d7580b4bdfe7a0a9))
|
||||
* more generic test ([0f651db](https://github.com/unraid/api/commit/0f651dbf61a1822b492aa80030f0bc231bc6f606))
|
||||
* only instantiate service one time ([933dc81](https://github.com/unraid/api/commit/933dc81b6c50db5a33f586f7094e1ea524b9a9fa))
|
||||
* only toast unread notifications, not archived ones ([cc59be6](https://github.com/unraid/api/commit/cc59be6cb3efc71226ee50f9f04e37a2e4b50de6))
|
||||
* padding and glob function issues ([1d3f2eb](https://github.com/unraid/api/commit/1d3f2eb8213115c3385ac2d29ee8f53560347ba8))
|
||||
* patch-utils unused ([047808d](https://github.com/unraid/api/commit/047808dce0cd9e9b4b273a9124dbd45ca9446208))
|
||||
* paths now correct, better download logic ([16db2d9](https://github.com/unraid/api/commit/16db2d908dcb2c65508b367712c51bf9872a95e5))
|
||||
* properly log error with template string ([3781f1f](https://github.com/unraid/api/commit/3781f1f41c7f0eef604daee0402ed9a2bb27cd46))
|
||||
* pull token from query not params ([2e827e7](https://github.com/unraid/api/commit/2e827e7cabe4a6a069d4e8779015e5896d8a1d1d))
|
||||
* remove devDependencies from output package json ([294869b](https://github.com/unraid/api/commit/294869bbea7f8a1863f8aafae6b074330e057679))
|
||||
* remove isNaN in favor of number.isNaN ([03e3a46](https://github.com/unraid/api/commit/03e3a46092db613281176b88cae284f6448027c6))
|
||||
* remove memory key generation ([b84db13](https://github.com/unraid/api/commit/b84db1322104c7f26f7b6378f25a2757b3010c6d))
|
||||
* remove unused constructor ([e0e2a7b](https://github.com/unraid/api/commit/e0e2a7b41c5e599ed4cf3bf49c7faea3b71f0b70))
|
||||
* remove usage of Role.UPC ([d1e2f6e](https://github.com/unraid/api/commit/d1e2f6e0b391cb4eca75a0997b41cb99a9953d42))
|
||||
* report issues + pm2 issues ([28c383e](https://github.com/unraid/api/commit/28c383e1d111d4ac4226d7d966533ba80ca5d9a1))
|
||||
* reset config to be closer to default ([b7fbb0b](https://github.com/unraid/api/commit/b7fbb0b6af0453f5f6a17087bb7e68c393b9fe3f))
|
||||
* resource busy when removing all subdirectories ([29936c9](https://github.com/unraid/api/commit/29936c90938fb83bc2f154315ca63a9d7cc98552))
|
||||
* restart command elegant ([296117b](https://github.com/unraid/api/commit/296117b51aac8a4c15366f2271af858868b6e071))
|
||||
* revert changelog ([e9d47ca](https://github.com/unraid/api/commit/e9d47caf181148317e5ba8f0d11a433b09add0e3))
|
||||
* revert dockerode upgrade ([#1140](https://github.com/unraid/api/issues/1140)) ([a74a379](https://github.com/unraid/api/commit/a74a379a93fd15a315e31191de1bf69c5879f8a6))
|
||||
* revert myservers.cfg ([d0896f3](https://github.com/unraid/api/commit/d0896f3ef8aebdd9c76d805ed6a35b4a5d5a1b08))
|
||||
* sandbox defaults in dev mode wrong ([2a24919](https://github.com/unraid/api/commit/2a2491936cf85013be836450ab7ed0cc11207e11))
|
||||
* sequential test execution for generic-modification ([79ee1f7](https://github.com/unraid/api/commit/79ee1f7552cee47c6f5a8eb5942468292212e2f2))
|
||||
* shell path to unraid-api ([15d11e4](https://github.com/unraid/api/commit/15d11e477bb2a08d785a7b22bd51900279a55508))
|
||||
* simplify api setup index ([701b1fb](https://github.com/unraid/api/commit/701b1fbd9096c9675475062eaf32a2cbfb0567b9))
|
||||
* simplify upcoming features ([8af79b2](https://github.com/unraid/api/commit/8af79b27501b42e1c1f7697756a56a9001000d8f))
|
||||
* staging build issues ([e6bcb8d](https://github.com/unraid/api/commit/e6bcb8de7daee463f7ac0dbf977e085e108302ba))
|
||||
* start command simplification ([e1faf3a](https://github.com/unraid/api/commit/e1faf3aa8db5973eb1bb0ea7a4844f820504618d))
|
||||
* stop command exits ([2dbfdb6](https://github.com/unraid/api/commit/2dbfdb670a773114c0fdc68c7cf9d29fa4e28a9b))
|
||||
* swap to placeholder key ([d1864d0](https://github.com/unraid/api/commit/d1864d0020ed56ab2368d23b48604b55cff21ae4))
|
||||
* test issues ([e4b55b1](https://github.com/unraid/api/commit/e4b55b133bb2dc4bf2ccfd6fd2fc244daadbea53))
|
||||
* test simplification to ensure no redownloads ([e07dad3](https://github.com/unraid/api/commit/e07dad3a6947aa186c4ac03032b5b3813cd046b6))
|
||||
* tests ([25c1c1a](https://github.com/unraid/api/commit/25c1c1a55a3fb32b76bf5cb7257a4ba44f717a89))
|
||||
* tests and validate token clears screen ([7f48ddd](https://github.com/unraid/api/commit/7f48dddcd2e2ea1ae3a55ecc54d5ac274535b714))
|
||||
* type for generic test ([e856535](https://github.com/unraid/api/commit/e85653592a9d6eadcd0be89bf90a96c5d313fda3))
|
||||
* unit test issues ([c58f7a7](https://github.com/unraid/api/commit/c58f7a7f246902c7d354eb51d1c87c8ea3b636a3))
|
||||
* unit tests updated ([9548505](https://github.com/unraid/api/commit/954850535bec6b09aaf66b01d3ee749c8a22de5d))
|
||||
* unneeded await on api-key service ([0325be7](https://github.com/unraid/api/commit/0325be757ee4c04b5c23365ff592f521a492595b))
|
||||
* unused imports ([a5447aa](https://github.com/unraid/api/commit/a5447aa2f4c99968651fa3750d6bf0e8d68678de))
|
||||
* update tests ([d0696a9](https://github.com/unraid/api/commit/d0696a93810893ccd6c676df1c639ca279992428))
|
||||
* use an enum and defaults for sandbox value ([eb56483](https://github.com/unraid/api/commit/eb56483ba2693944d39f4409c91b75ee82a7d30b))
|
||||
* use batchProcess ([ffbb9d7](https://github.com/unraid/api/commit/ffbb9d7750568bfa849d21e051503d1fcca5355f))
|
||||
* use cwd when running application ([e016652](https://github.com/unraid/api/commit/e01665264b6f45366cdacf60c0f3553adfbd85d3))
|
||||
* use placeholder in test API key ([c6b7755](https://github.com/unraid/api/commit/c6b7755214de8bedd5c0f2735473c2a559b1e26f))
|
||||
* watch all events to load keys ([59ca177](https://github.com/unraid/api/commit/59ca17787e4d36113b0a8c5ef2117acfc491c49c))
|
||||
* **web:** name of toaster component ([e093242](https://github.com/unraid/api/commit/e093242d20ddd72567396f4a53238250f2199a64))
|
||||
|
||||
|
||||
### Miscellaneous Chores
|
||||
|
||||
* release 4.1.2 ([dbab290](https://github.com/unraid/api/commit/dbab290b429f9eff8fa903d193de2bd02bb392bd))
|
||||
|
||||
### [4.1.1](https://github.com/unraid/api/compare/v4.1.0...v4.1.1) (2025-02-20)
|
||||
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
###########################################################
|
||||
# Development/Build Image
|
||||
###########################################################
|
||||
FROM node:20-bookworm-slim AS development
|
||||
FROM node:22-bookworm-slim AS development
|
||||
|
||||
# Install build tools and dependencies
|
||||
RUN apt-get update -y && apt-get install -y \
|
||||
@@ -42,4 +42,4 @@ ENV NODE_ENV=production
|
||||
|
||||
COPY . .
|
||||
|
||||
CMD ["pnpm", "run", "build-and-pack"]
|
||||
CMD ["pnpm", "run", "build:release"]
|
||||
192
api/codegen.ts
192
api/codegen.ts
@@ -1,105 +1,105 @@
|
||||
import type { CodegenConfig } from '@graphql-codegen/cli';
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
const config: CodegenConfig = {
|
||||
overwrite: true,
|
||||
emitLegacyCommonJSImports: false,
|
||||
verbose: true,
|
||||
config: {
|
||||
namingConvention: {
|
||||
typeNames: './fix-array-type.cjs',
|
||||
enumValues: 'change-case#upperCase',
|
||||
useTypeImports: true,
|
||||
},
|
||||
scalars: {
|
||||
DateTime: 'string',
|
||||
Long: 'number',
|
||||
JSON: '{ [key: string]: any }',
|
||||
URL: 'URL',
|
||||
Port: 'number',
|
||||
UUID: 'string',
|
||||
},
|
||||
},
|
||||
generates: {
|
||||
'src/graphql/generated/client/': {
|
||||
documents: './src/graphql/mothership/*.ts',
|
||||
schema: {
|
||||
[process.env.MOTHERSHIP_GRAPHQL_LINK as string]: {
|
||||
headers: {
|
||||
origin: 'https://forums.unraid.net',
|
||||
},
|
||||
overwrite: true,
|
||||
emitLegacyCommonJSImports: false,
|
||||
verbose: true,
|
||||
config: {
|
||||
namingConvention: {
|
||||
typeNames: './fix-array-type.cjs',
|
||||
enumValues: 'change-case#upperCase',
|
||||
useTypeImports: true,
|
||||
},
|
||||
},
|
||||
preset: 'client',
|
||||
presetConfig: {
|
||||
gqlTagName: 'graphql',
|
||||
},
|
||||
config: {
|
||||
useTypeImports: true,
|
||||
withObjectType: true,
|
||||
},
|
||||
plugins: [
|
||||
{ add: { content: '/* eslint-disable */' } },
|
||||
],
|
||||
},
|
||||
// Generate Types for the API Server
|
||||
'src/graphql/generated/api/types.ts': {
|
||||
schema: [
|
||||
'./src/graphql/types.ts',
|
||||
'./src/graphql/schema/types/**/*.graphql',
|
||||
],
|
||||
plugins: [
|
||||
'typescript',
|
||||
'typescript-resolvers',
|
||||
{ add: { content: '/* eslint-disable */' } },
|
||||
],
|
||||
config: {
|
||||
contextType: '@app/graphql/schema/utils#Context',
|
||||
useIndexSignature: true,
|
||||
},
|
||||
},
|
||||
// Generate Operations for any built-in API Server Operations (e.g., report.ts)
|
||||
'src/graphql/generated/api/operations.ts': {
|
||||
documents: './src/graphql/client/api/*.ts',
|
||||
schema: [
|
||||
'./src/graphql/types.ts',
|
||||
'./src/graphql/schema/types/**/*.graphql',
|
||||
],
|
||||
preset: 'import-types',
|
||||
presetConfig: {
|
||||
typesPath: '@app/graphql/generated/api/types',
|
||||
},
|
||||
plugins: [
|
||||
'typescript-validation-schema',
|
||||
'typescript-operations',
|
||||
'typed-document-node',
|
||||
{ add: { content: '/* eslint-disable */' } },
|
||||
],
|
||||
config: {
|
||||
importFrom: '@app/graphql/generated/api/types',
|
||||
strictScalars: false,
|
||||
schema: 'zod',
|
||||
withObjectType: true,
|
||||
},
|
||||
},
|
||||
'src/graphql/generated/client/validators.ts': {
|
||||
schema: {
|
||||
[process.env.MOTHERSHIP_GRAPHQL_LINK as string]: {
|
||||
headers: {
|
||||
origin: 'https://forums.unraid.net',
|
||||
},
|
||||
scalars: {
|
||||
DateTime: 'string',
|
||||
Long: 'number',
|
||||
JSON: 'Record<string, any>',
|
||||
URL: 'URL',
|
||||
Port: 'number',
|
||||
UUID: 'string',
|
||||
},
|
||||
scalarSchemas: {
|
||||
URL: 'z.instanceof(URL)',
|
||||
Long: 'z.number()',
|
||||
JSON: 'z.record(z.string(), z.any())',
|
||||
Port: 'z.number()',
|
||||
UUID: 'z.string()',
|
||||
},
|
||||
},
|
||||
generates: {
|
||||
'src/graphql/generated/client/': {
|
||||
documents: './src/graphql/mothership/*.ts',
|
||||
schema: {
|
||||
[process.env.MOTHERSHIP_GRAPHQL_LINK as string]: {
|
||||
headers: {
|
||||
origin: 'https://forums.unraid.net',
|
||||
},
|
||||
},
|
||||
},
|
||||
preset: 'client',
|
||||
presetConfig: {
|
||||
gqlTagName: 'graphql',
|
||||
},
|
||||
config: {
|
||||
useTypeImports: true,
|
||||
withObjectType: true,
|
||||
},
|
||||
plugins: [{ add: { content: '/* eslint-disable */' } }],
|
||||
},
|
||||
// Generate Types for the API Server
|
||||
'src/graphql/generated/api/types.ts': {
|
||||
schema: ['./src/graphql/types.ts', './src/graphql/schema/types/**/*.graphql'],
|
||||
plugins: [
|
||||
'typescript',
|
||||
'typescript-resolvers',
|
||||
{ add: { content: '/* eslint-disable */\n/* @ts-nocheck */' } },
|
||||
],
|
||||
config: {
|
||||
contextType: '@app/graphql/schema/utils.js#Context',
|
||||
useIndexSignature: true,
|
||||
},
|
||||
},
|
||||
// Generate Operations for any built-in API Server Operations (e.g., report.ts)
|
||||
'src/graphql/generated/api/operations.ts': {
|
||||
documents: './src/graphql/client/api/*.ts',
|
||||
schema: ['./src/graphql/types.ts', './src/graphql/schema/types/**/*.graphql'],
|
||||
preset: 'import-types',
|
||||
presetConfig: {
|
||||
typesPath: '@app/graphql/generated/api/types.js',
|
||||
},
|
||||
plugins: [
|
||||
'typescript-validation-schema',
|
||||
'typescript-operations',
|
||||
'typed-document-node',
|
||||
{ add: { content: '/* eslint-disable */' } },
|
||||
],
|
||||
config: {
|
||||
importFrom: '@app/graphql/generated/api/types.js',
|
||||
strictScalars: true,
|
||||
schema: 'zod',
|
||||
withObjectType: true,
|
||||
},
|
||||
},
|
||||
'src/graphql/generated/client/validators.ts': {
|
||||
schema: {
|
||||
[process.env.MOTHERSHIP_GRAPHQL_LINK as string]: {
|
||||
headers: {
|
||||
origin: 'https://forums.unraid.net',
|
||||
},
|
||||
},
|
||||
},
|
||||
plugins: ['typescript-validation-schema', { add: { content: '/* eslint-disable */' } }],
|
||||
config: {
|
||||
importFrom: '@app/graphql/generated/client/graphql.js',
|
||||
strictScalars: false,
|
||||
schema: 'zod',
|
||||
},
|
||||
},
|
||||
},
|
||||
plugins: [
|
||||
'typescript-validation-schema',
|
||||
{ add: { content: '/* eslint-disable */' } },
|
||||
],
|
||||
config: {
|
||||
importFrom: '@app/graphql/generated/client/graphql',
|
||||
strictScalars: false,
|
||||
schema: 'zod',
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export default config;
|
||||
1
api/commitlint.config.js
Normal file
1
api/commitlint.config.js
Normal file
@@ -0,0 +1 @@
|
||||
module.exports = { extends: ['@commitlint/config-conventional'] };
|
||||
1
api/dev/Unraid.net/Pro.key
Normal file
1
api/dev/Unraid.net/Pro.key
Normal file
@@ -0,0 +1 @@
|
||||
┘[5╢╦Ояb┴ю└;R╛леЩ²ДА├y÷шd│яя╛Еlя▓ё"Hи╜ь;QДs≈@Вы▄╠╩1·Qy╓к|й╔+╨фM)X9jя▄тГО⌠1а2WHщ'│.ЕJё-╨MPгS╜╧:Ю▓]o9^ЮО0┴$"░ l^`╪>3к:╦я ЯО┤q~ёш≈└с ш5ёЗ=р╟─]╗IWf╥и ⌡?:У2ВоE5[р╨Ш(÷╤Е}з+о│ШIмAч²%╞╓дq:ё╤эb╣┼
|
||||
@@ -1,5 +1,5 @@
|
||||
[api]
|
||||
version="4.0.1"
|
||||
version="4.1.3"
|
||||
extraOrigins="https://google.com,https://test.com"
|
||||
[local]
|
||||
sandbox="yes"
|
||||
|
||||
1
api/dev/data/machine-id
Normal file
1
api/dev/data/machine-id
Normal file
@@ -0,0 +1 @@
|
||||
d0b5433294c110f1eed72bdb63910a9a
|
||||
1
api/dev/data/unraid-version
Normal file
1
api/dev/data/unraid-version
Normal file
@@ -0,0 +1 @@
|
||||
version="6.12.0-beta5"
|
||||
BIN
api/dev/dynamix/banner.png
Normal file
BIN
api/dev/dynamix/banner.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 61 KiB |
1
api/dev/dynamix/case-model.cfg
Normal file
1
api/dev/dynamix/case-model.cfg
Normal file
@@ -0,0 +1 @@
|
||||
case-model.png
|
||||
BIN
api/dev/dynamix/case-model.png
Normal file
BIN
api/dev/dynamix/case-model.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 4.5 KiB |
@@ -32,5 +32,5 @@ display="0"
|
||||
date="d-m-Y"
|
||||
time="H:i"
|
||||
position="top-right"
|
||||
path="/app/dev/notifications"
|
||||
path="./dev/notifications"
|
||||
system="*/1 * * * *"
|
||||
0
api/dev/states/devs.ini
Normal file
0
api/dev/states/devs.ini
Normal file
@@ -1,5 +1,5 @@
|
||||
[api]
|
||||
version="4.0.1"
|
||||
version="4.4.1"
|
||||
extraOrigins="https://google.com,https://test.com"
|
||||
[local]
|
||||
sandbox="yes"
|
||||
@@ -20,5 +20,5 @@ dynamicRemoteAccessType="DISABLED"
|
||||
ssoSubIds=""
|
||||
allowedOrigins="/var/run/unraid-notifications.sock, /var/run/unraid-php.sock, /var/run/unraid-cli.sock, http://localhost:8080, https://localhost:4443, https://tower.local:4443, https://192.168.1.150:4443, https://tower:4443, https://192-168-1-150.thisisfourtyrandomcharacters012345678900.myunraid.net:4443, https://85-121-123-122.thisisfourtyrandomcharacters012345678900.myunraid.net:8443, https://10-252-0-1.hash.myunraid.net:4443, https://10-252-1-1.hash.myunraid.net:4443, https://10-253-3-1.hash.myunraid.net:4443, https://10-253-4-1.hash.myunraid.net:4443, https://10-253-5-1.hash.myunraid.net:4443, https://10-100-0-1.hash.myunraid.net:4443, https://10-100-0-2.hash.myunraid.net:4443, https://10-123-1-2.hash.myunraid.net:4443, https://221-123-121-112.hash.myunraid.net:4443, https://google.com, https://test.com, https://connect.myunraid.net, https://connect-staging.myunraid.net, https://dev-my.myunraid.net:4000, https://studio.apollographql.com"
|
||||
[connectionStatus]
|
||||
minigraph="PRE_INIT"
|
||||
minigraph="ERROR_RETRYING"
|
||||
upnpStatus=""
|
||||
|
||||
30
api/dev/states/network.ini
Normal file
30
api/dev/states/network.ini
Normal file
@@ -0,0 +1,30 @@
|
||||
[eth0]
|
||||
DHCP_KEEPRESOLV="no"
|
||||
DNS_SERVER1="1.1.1.1"
|
||||
DNS_SERVER2="8.8.8.8"
|
||||
DHCP6_KEEPRESOLV="no"
|
||||
BONDING="yes"
|
||||
BONDNAME=""
|
||||
BONDNICS="eth0,eth1,eth2,eth3"
|
||||
BONDING_MODE="1"
|
||||
BONDING_MIIMON="100"
|
||||
BRIDGING="yes"
|
||||
BRNAME=""
|
||||
BRNICS="bond0"
|
||||
BRSTP="0"
|
||||
BRFD="0"
|
||||
DESCRIPTION:0=""
|
||||
PROTOCOL:0=""
|
||||
USE_DHCP:0="yes"
|
||||
IPADDR:0="192.168.1.150"
|
||||
NETMASK:0="255.255.255.0"
|
||||
GATEWAY:0="192.168.1.1"
|
||||
METRIC:0=""
|
||||
USE_DHCP6:0=""
|
||||
IPADDR6:0=""
|
||||
NETMASK6:0=""
|
||||
GATEWAY6:0=""
|
||||
METRIC6:0=""
|
||||
PRIVACY6:0=""
|
||||
MTU=""
|
||||
TYPE="access"
|
||||
190
api/dev/states/sec.ini
Normal file
190
api/dev/states/sec.ini
Normal file
@@ -0,0 +1,190 @@
|
||||
["disk1"]
|
||||
export="e"
|
||||
fruit="no"
|
||||
caseSensitive="auto"
|
||||
security="public"
|
||||
readList=""
|
||||
writeList=""
|
||||
volsizelimit=""
|
||||
["disk2"]
|
||||
export="e"
|
||||
fruit="no"
|
||||
caseSensitive="auto"
|
||||
security="public"
|
||||
readList=""
|
||||
writeList=""
|
||||
volsizelimit=""
|
||||
["disk3"]
|
||||
export="e"
|
||||
fruit="no"
|
||||
caseSensitive="auto"
|
||||
security="public"
|
||||
readList=""
|
||||
writeList=""
|
||||
volsizelimit=""
|
||||
["disk4"]
|
||||
export="e"
|
||||
fruit="no"
|
||||
caseSensitive="auto"
|
||||
security="public"
|
||||
readList=""
|
||||
writeList=""
|
||||
volsizelimit=""
|
||||
["disk5"]
|
||||
export="e"
|
||||
fruit="no"
|
||||
caseSensitive="auto"
|
||||
security="public"
|
||||
readList=""
|
||||
writeList=""
|
||||
volsizelimit=""
|
||||
["disk6"]
|
||||
export="e"
|
||||
fruit="no"
|
||||
caseSensitive="auto"
|
||||
security="public"
|
||||
readList=""
|
||||
writeList=""
|
||||
volsizelimit=""
|
||||
["disk7"]
|
||||
export="e"
|
||||
fruit="no"
|
||||
caseSensitive="auto"
|
||||
security="public"
|
||||
readList=""
|
||||
writeList=""
|
||||
volsizelimit=""
|
||||
["disk8"]
|
||||
export="e"
|
||||
fruit="no"
|
||||
caseSensitive="auto"
|
||||
security="public"
|
||||
readList=""
|
||||
writeList=""
|
||||
volsizelimit=""
|
||||
["disk9"]
|
||||
export="e"
|
||||
fruit="no"
|
||||
caseSensitive="auto"
|
||||
security="public"
|
||||
readList=""
|
||||
writeList=""
|
||||
volsizelimit=""
|
||||
["disk10"]
|
||||
export="e"
|
||||
fruit="no"
|
||||
caseSensitive="auto"
|
||||
security="public"
|
||||
readList=""
|
||||
writeList=""
|
||||
volsizelimit=""
|
||||
["disk11"]
|
||||
export="e"
|
||||
fruit="no"
|
||||
caseSensitive="auto"
|
||||
security="public"
|
||||
readList=""
|
||||
writeList=""
|
||||
volsizelimit=""
|
||||
["disk12"]
|
||||
export="e"
|
||||
fruit="no"
|
||||
caseSensitive="auto"
|
||||
security="public"
|
||||
readList=""
|
||||
writeList=""
|
||||
volsizelimit=""
|
||||
["disk13"]
|
||||
export="e"
|
||||
fruit="no"
|
||||
caseSensitive="auto"
|
||||
security="public"
|
||||
readList=""
|
||||
writeList=""
|
||||
volsizelimit=""
|
||||
["disk14"]
|
||||
export="e"
|
||||
fruit="no"
|
||||
caseSensitive="auto"
|
||||
security="public"
|
||||
readList=""
|
||||
writeList=""
|
||||
volsizelimit=""
|
||||
["disk15"]
|
||||
export="e"
|
||||
fruit="no"
|
||||
caseSensitive="auto"
|
||||
security="public"
|
||||
readList=""
|
||||
writeList=""
|
||||
volsizelimit=""
|
||||
["disk16"]
|
||||
export="e"
|
||||
fruit="no"
|
||||
caseSensitive="auto"
|
||||
security="public"
|
||||
readList=""
|
||||
writeList=""
|
||||
volsizelimit=""
|
||||
["disk17"]
|
||||
export="e"
|
||||
fruit="no"
|
||||
caseSensitive="auto"
|
||||
security="public"
|
||||
readList=""
|
||||
writeList=""
|
||||
volsizelimit=""
|
||||
["disk18"]
|
||||
export="e"
|
||||
fruit="no"
|
||||
caseSensitive="auto"
|
||||
security="public"
|
||||
readList=""
|
||||
writeList=""
|
||||
volsizelimit=""
|
||||
["disk19"]
|
||||
export="e"
|
||||
fruit="no"
|
||||
caseSensitive="auto"
|
||||
security="public"
|
||||
readList=""
|
||||
writeList=""
|
||||
volsizelimit=""
|
||||
["disk20"]
|
||||
export="e"
|
||||
fruit="no"
|
||||
caseSensitive="auto"
|
||||
security="public"
|
||||
readList=""
|
||||
writeList=""
|
||||
volsizelimit=""
|
||||
["disk21"]
|
||||
export="e"
|
||||
fruit="no"
|
||||
caseSensitive="auto"
|
||||
security="public"
|
||||
readList=""
|
||||
writeList=""
|
||||
volsizelimit=""
|
||||
["disk22"]
|
||||
export="e"
|
||||
fruit="no"
|
||||
caseSensitive="auto"
|
||||
security="public"
|
||||
readList=""
|
||||
writeList=""
|
||||
volsizelimit=""
|
||||
["abc"]
|
||||
export="e"
|
||||
fruit="no"
|
||||
caseSensitive="auto"
|
||||
security="public"
|
||||
readList=""
|
||||
writeList=""
|
||||
volsizelimit=""
|
||||
["flash"]
|
||||
export="e"
|
||||
fruit="no"
|
||||
security="public"
|
||||
readList=""
|
||||
writeList=""
|
||||
92
api/dev/states/sec_nfs.ini
Normal file
92
api/dev/states/sec_nfs.ini
Normal file
@@ -0,0 +1,92 @@
|
||||
["disk1"]
|
||||
export="-"
|
||||
security="public"
|
||||
hostList=""
|
||||
["disk2"]
|
||||
export="-"
|
||||
security="public"
|
||||
hostList=""
|
||||
["disk3"]
|
||||
export="-"
|
||||
security="public"
|
||||
hostList=""
|
||||
["disk4"]
|
||||
export="-"
|
||||
security="public"
|
||||
hostList=""
|
||||
["disk5"]
|
||||
export="-"
|
||||
security="public"
|
||||
hostList=""
|
||||
["disk6"]
|
||||
export="-"
|
||||
security="public"
|
||||
hostList=""
|
||||
["disk7"]
|
||||
export="-"
|
||||
security="public"
|
||||
hostList=""
|
||||
["disk8"]
|
||||
export="-"
|
||||
security="public"
|
||||
hostList=""
|
||||
["disk9"]
|
||||
export="-"
|
||||
security="public"
|
||||
hostList=""
|
||||
["disk10"]
|
||||
export="-"
|
||||
security="public"
|
||||
hostList=""
|
||||
["disk11"]
|
||||
export="-"
|
||||
security="public"
|
||||
hostList=""
|
||||
["disk12"]
|
||||
export="-"
|
||||
security="public"
|
||||
hostList=""
|
||||
["disk13"]
|
||||
export="-"
|
||||
security="public"
|
||||
hostList=""
|
||||
["disk14"]
|
||||
export="-"
|
||||
security="public"
|
||||
hostList=""
|
||||
["disk15"]
|
||||
export="-"
|
||||
security="public"
|
||||
hostList=""
|
||||
["disk16"]
|
||||
export="-"
|
||||
security="public"
|
||||
hostList=""
|
||||
["disk17"]
|
||||
export="-"
|
||||
security="public"
|
||||
hostList=""
|
||||
["disk18"]
|
||||
export="-"
|
||||
security="public"
|
||||
hostList=""
|
||||
["disk19"]
|
||||
export="-"
|
||||
security="public"
|
||||
hostList=""
|
||||
["disk20"]
|
||||
export="-"
|
||||
security="public"
|
||||
hostList=""
|
||||
["disk21"]
|
||||
export="-"
|
||||
security="public"
|
||||
hostList=""
|
||||
["disk22"]
|
||||
export="-"
|
||||
security="public"
|
||||
hostList=""
|
||||
["abc"]
|
||||
export="-"
|
||||
security="public"
|
||||
hostList=""
|
||||
68
api/dev/states/shares.ini
Normal file
68
api/dev/states/shares.ini
Normal file
@@ -0,0 +1,68 @@
|
||||
["appdata"]
|
||||
name="appdata"
|
||||
nameOrig="appdata"
|
||||
comment=""
|
||||
allocator="highwater"
|
||||
splitLevel=""
|
||||
floor="0"
|
||||
include=""
|
||||
exclude=""
|
||||
useCache="no"
|
||||
cachePool="cache"
|
||||
cow="auto"
|
||||
color="yellow-on"
|
||||
size="0"
|
||||
free="9091184"
|
||||
used="32831348"
|
||||
luksStatus="0"
|
||||
["domains"]
|
||||
name="domains"
|
||||
nameOrig="domains"
|
||||
comment="saved VM instances"
|
||||
allocator="highwater"
|
||||
splitLevel="1"
|
||||
floor="0"
|
||||
include=""
|
||||
exclude=""
|
||||
useCache="prefer"
|
||||
cachePool="cache"
|
||||
cow="auto"
|
||||
color="yellow-on"
|
||||
size="0"
|
||||
free="9091184"
|
||||
used="32831348"
|
||||
luksStatus="0"
|
||||
["isos"]
|
||||
name="isos"
|
||||
nameOrig="isos"
|
||||
comment="ISO images"
|
||||
allocator="highwater"
|
||||
splitLevel=""
|
||||
floor="0"
|
||||
include=""
|
||||
exclude=""
|
||||
useCache="yes"
|
||||
cachePool="cache"
|
||||
cow="auto"
|
||||
color="yellow-on"
|
||||
size="0"
|
||||
free="9091184"
|
||||
used="32831348"
|
||||
luksStatus="0"
|
||||
["system"]
|
||||
name="system"
|
||||
nameOrig="system"
|
||||
comment="system data"
|
||||
allocator="highwater"
|
||||
splitLevel="1"
|
||||
floor="0"
|
||||
include=""
|
||||
exclude=""
|
||||
useCache="prefer"
|
||||
cachePool="cache"
|
||||
cow="auto"
|
||||
color="yellow-on"
|
||||
size="0"
|
||||
free="9091184"
|
||||
used="32831348"
|
||||
luksStatus="0"
|
||||
15
api/dev/states/users.ini
Normal file
15
api/dev/states/users.ini
Normal file
@@ -0,0 +1,15 @@
|
||||
["root"]
|
||||
idx="0"
|
||||
name="root"
|
||||
desc="Console and webGui login account"
|
||||
passwd="yes"
|
||||
["xo"]
|
||||
idx="1"
|
||||
name="xo"
|
||||
desc=""
|
||||
passwd="yes"
|
||||
["test_user"]
|
||||
idx="2"
|
||||
name="test_user"
|
||||
desc=""
|
||||
passwd="no"
|
||||
@@ -87,7 +87,7 @@ shareAvahiSMBModel="Xserve"
|
||||
shfs_logging="1"
|
||||
safeMode="no"
|
||||
startMode="Normal"
|
||||
configValid="yes"
|
||||
configValid="ineligible"
|
||||
joinStatus="Not joined"
|
||||
deviceCount="4"
|
||||
flashGUID="0000-0000-0000-000000000000"
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
## Installation
|
||||
|
||||
Manual install can be done with the following routes:
|
||||
Manual install of the staging and production plugins can be done with the following routes:
|
||||
[production](https://stable.dl.unraid.net/unraid-api/dynamix.unraid.net.plg)
|
||||
[staging](https://preview.dl.unraid.net/unraid-api/dynamix.unraid.net.staging.plg)
|
||||
|
||||
|
||||
@@ -11,11 +11,11 @@ The repository consists of:
|
||||
- Core Modules
|
||||
- Tests
|
||||
|
||||
## API Server Architecture
|
||||
## API Server Architecture
|
||||
|
||||
The API server is built with NestJS and provides the core functionality for interacting with Unraid systems.
|
||||
|
||||
### Key Components:
|
||||
### Key Components
|
||||
|
||||
- `src/unraid-api/` - Core NestJS implementation
|
||||
- `src/core/` - Legacy business logic and utilities
|
||||
@@ -61,7 +61,7 @@ The store syncs data in two ways:
|
||||
The repository is organized into several packages:
|
||||
|
||||
- `api/` - NestJS API server
|
||||
- `plugin/` - Unraid plugin package
|
||||
- `plugin/` - Unraid plugin package
|
||||
- `web/` - Frontend application
|
||||
- `unraid-ui/` - Shared UI components
|
||||
|
||||
|
||||
219
api/docs/developer/workflows.md
Normal file
219
api/docs/developer/workflows.md
Normal file
@@ -0,0 +1,219 @@
|
||||
# Unraid API Development Workflows
|
||||
|
||||
This document outlines the various workflow styles available for developing, building, and deploying the Unraid API monorepo.
|
||||
|
||||
## Repository Structure
|
||||
|
||||
The Unraid API monorepo consists of several packages:
|
||||
|
||||
- `api`: The Unraid API backend
|
||||
- `web`: The web frontend components
|
||||
- `plugin`: The Unraid plugin
|
||||
- `unraid-ui`: UI components library
|
||||
|
||||
## Development Workflows
|
||||
|
||||
### Local Development
|
||||
|
||||
To start all development servers in the monorepo:
|
||||
|
||||
```bash
|
||||
pnpm dev
|
||||
```
|
||||
|
||||
This command runs all development servers concurrently:
|
||||
|
||||
- API server: <http://localhost:3001>
|
||||
- Web components: <http://localhost:4321>
|
||||
- UI components: <http://localhost:5173>
|
||||
|
||||
### Package-Specific Development
|
||||
|
||||
If you want to work on a specific package, you can run its development server individually:
|
||||
|
||||
#### API Development
|
||||
|
||||
```bash
|
||||
cd api
|
||||
pnpm dev
|
||||
```
|
||||
|
||||
#### Web Development
|
||||
|
||||
```bash
|
||||
cd web
|
||||
pnpm dev
|
||||
```
|
||||
|
||||
#### UI Component Development
|
||||
|
||||
```bash
|
||||
cd unraid-ui
|
||||
pnpm dev
|
||||
```
|
||||
|
||||
## Building Workflows
|
||||
|
||||
### Building All Packages
|
||||
|
||||
To build all packages in the monorepo:
|
||||
|
||||
```bash
|
||||
pnpm build
|
||||
```
|
||||
|
||||
### Watch Mode Building
|
||||
|
||||
For continuous building during development:
|
||||
|
||||
```bash
|
||||
pnpm build:watch
|
||||
```
|
||||
|
||||
This is useful when you want to see your changes reflected without manually rebuilding. This will also allow you to install a local plugin to test your changes.
|
||||
|
||||
### Package-Specific Building
|
||||
|
||||
#### API Building
|
||||
|
||||
```bash
|
||||
cd api
|
||||
pnpm build
|
||||
```
|
||||
|
||||
#### Web Building
|
||||
|
||||
```bash
|
||||
cd web
|
||||
pnpm build
|
||||
```
|
||||
|
||||
#### Development Build for Web
|
||||
|
||||
```bash
|
||||
cd web
|
||||
pnpm build:dev
|
||||
```
|
||||
|
||||
## Deployment Workflows
|
||||
|
||||
### Deploying to Development Unraid Server
|
||||
|
||||
To deploy to a development Unraid server:
|
||||
|
||||
```bash
|
||||
pnpm unraid:deploy <SERVER_IP>
|
||||
```
|
||||
|
||||
This command builds and deploys all components to the specified Unraid server.
|
||||
|
||||
### Package-Specific Deployment
|
||||
|
||||
#### API Deployment
|
||||
|
||||
```bash
|
||||
cd api
|
||||
pnpm unraid:deploy <SERVER_IP>
|
||||
```
|
||||
|
||||
#### Web Deployment
|
||||
|
||||
```bash
|
||||
cd web
|
||||
pnpm unraid:deploy <SERVER_IP>
|
||||
```
|
||||
|
||||
#### Plugin Deployment
|
||||
|
||||
```bash
|
||||
cd plugin
|
||||
pnpm unraid:deploy <SERVER_IP>
|
||||
```
|
||||
|
||||
## Testing
|
||||
|
||||
To run tests across all packages:
|
||||
|
||||
```bash
|
||||
pnpm test
|
||||
```
|
||||
|
||||
### Package-Specific Testing
|
||||
|
||||
```bash
|
||||
cd <package-directory>
|
||||
pnpm test
|
||||
```
|
||||
|
||||
## Code Quality Workflows
|
||||
|
||||
### Linting
|
||||
|
||||
To lint all packages:
|
||||
|
||||
```bash
|
||||
pnpm lint
|
||||
```
|
||||
|
||||
To automatically fix linting issues:
|
||||
|
||||
```bash
|
||||
pnpm lint:fix
|
||||
```
|
||||
|
||||
### Type Checking
|
||||
|
||||
To run type checking across all packages:
|
||||
|
||||
```bash
|
||||
pnpm type-check
|
||||
```
|
||||
|
||||
## GraphQL Codegen Workflows
|
||||
|
||||
For packages that use GraphQL, you can generate types from your schema:
|
||||
|
||||
```bash
|
||||
cd <package-directory>
|
||||
pnpm codegen
|
||||
```
|
||||
|
||||
To watch for changes and regenerate types:
|
||||
|
||||
```bash
|
||||
cd <package-directory>
|
||||
pnpm codegen:watch
|
||||
```
|
||||
|
||||
## Docker Workflows
|
||||
|
||||
The API package supports Docker-based development:
|
||||
|
||||
```bash
|
||||
cd api
|
||||
pnpm container:build # Build the Docker container
|
||||
pnpm container:start # Start the container
|
||||
pnpm container:stop # Stop the container
|
||||
pnpm container:enter # Enter the container shell
|
||||
pnpm container:test # Run tests in the container
|
||||
```
|
||||
|
||||
## CLI Commands
|
||||
|
||||
When working with a deployed Unraid API, you can use the CLI:
|
||||
|
||||
```bash
|
||||
unraid-api --help
|
||||
```
|
||||
|
||||
## Recommended Workflow for New Developers
|
||||
|
||||
1. Clone the repository: `git clone git@github.com:unraid/api.git`
|
||||
2. Set up the monorepo: `just setup` or `pnpm install`
|
||||
3. Start development servers: `pnpm dev`
|
||||
4. Make your changes
|
||||
5. Test your changes: `pnpm test`
|
||||
6. Deploy to a development server: `pnpm unraid:deploy <SERVER_IP>`
|
||||
7. Verify your changes on the Unraid server
|
||||
|
||||
If using nix, run `nix develop` from the root of the repo before Step 2.
|
||||
@@ -11,6 +11,7 @@
|
||||
"max_restarts": 10,
|
||||
"min_uptime": 10000,
|
||||
"watch": false,
|
||||
"interpreter": "/usr/local/node/bin/node",
|
||||
"ignore_watch": ["node_modules", "src", ".env.*", "myservers.cfg"],
|
||||
"log_file": "/var/log/graphql-api.log",
|
||||
"kill_timeout": 10000
|
||||
|
||||
18
api/fix-array-type.cjs
Normal file
18
api/fix-array-type.cjs
Normal file
@@ -0,0 +1,18 @@
|
||||
/**
|
||||
* This function wraps constant case, that turns any string into CONSTANT_CASE
|
||||
* However, this function has a bug that, if you pass _ to it it will return an empty
|
||||
* string. This small module fixes that
|
||||
*
|
||||
* @param {string*} str
|
||||
* @return {string}
|
||||
*/
|
||||
function FixArrayType(str) {
|
||||
if (str === 'Array') {
|
||||
return 'ArrayType';
|
||||
}
|
||||
|
||||
// If result is an empty string, just return the original string
|
||||
return str;
|
||||
}
|
||||
|
||||
module.exports = FixArrayType;
|
||||
12
api/justfile
12
api/justfile
@@ -4,17 +4,13 @@ default:
|
||||
@just --list --justfile {{justfile()}} --list-heading $'\nAPI project recipes:\n'
|
||||
@just list-commands
|
||||
|
||||
setup:
|
||||
pnpm install
|
||||
pnpm run container:build
|
||||
|
||||
# builds js files that can run on an unraid server
|
||||
@build:
|
||||
pnpm run build
|
||||
|
||||
# deploys to an unraid server
|
||||
@deploy:
|
||||
./scripts/deploy-dev.sh
|
||||
@deploy remote:
|
||||
./scripts/deploy-dev.sh {{remote}}
|
||||
|
||||
# build & deploy
|
||||
bd: build deploy
|
||||
alias b := build
|
||||
alias d := deploy
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@unraid/api",
|
||||
"version": "4.1.2",
|
||||
"version": "4.6.2",
|
||||
"main": "src/cli/index.ts",
|
||||
"type": "module",
|
||||
"corepack": {
|
||||
@@ -8,34 +8,37 @@
|
||||
},
|
||||
"repository": "git@github.com:unraid/api.git",
|
||||
"author": "Lime Technology, Inc. <unraid.net>",
|
||||
"license": "UNLICENSED",
|
||||
"license": "GPL-2.0-or-later",
|
||||
"engines": {
|
||||
"pnpm": ">=8.0.0"
|
||||
},
|
||||
"scripts": {
|
||||
"// Main application commands": "",
|
||||
"// Development": "",
|
||||
"start": "node dist/main.js",
|
||||
"dev": "vite",
|
||||
"command": "pnpm run build && clear && ./dist/cli.js",
|
||||
"// Build commands": "",
|
||||
"command:raw": "./dist/cli.js",
|
||||
"// Build and Deploy": "",
|
||||
"build": "vite build --mode=production",
|
||||
"postbuild": "chmod +x dist/main.js && chmod +x dist/cli.js",
|
||||
"build:watch": "nodemon --watch src --ext ts,js,json --exec 'tsx ./scripts/build.ts'",
|
||||
"build:docker": "./scripts/dc.sh run --rm builder",
|
||||
"build-and-pack": "tsx ./scripts/build.ts",
|
||||
"// Code generation commands": "",
|
||||
"build:release": "tsx ./scripts/build.ts",
|
||||
"preunraid:deploy": "pnpm build",
|
||||
"unraid:deploy": "./scripts/deploy-dev.sh",
|
||||
"// GraphQL Codegen": "",
|
||||
"codegen": "MOTHERSHIP_GRAPHQL_LINK='https://staging.mothership.unraid.net/ws' graphql-codegen --config codegen.ts -r dotenv/config './.env.staging'",
|
||||
"codegen:watch": "DOTENV_CONFIG_PATH='./.env.staging' graphql-codegen --config codegen.ts --watch -r dotenv/config",
|
||||
"codegen:local": "NODE_TLS_REJECT_UNAUTHORIZED=0 MOTHERSHIP_GRAPHQL_LINK='https://mothership.localhost/ws' graphql-codegen --config codegen.ts --watch",
|
||||
"// Development and quality tools": "",
|
||||
"tsc": "tsc --noEmit",
|
||||
"// Code Quality": "",
|
||||
"lint": "eslint --config .eslintrc.ts src/",
|
||||
"lint:fix": "eslint --fix --config .eslintrc.ts src/",
|
||||
"release": "standard-version",
|
||||
"// Testing commands": "",
|
||||
"type-check": "tsc --noEmit",
|
||||
"// Testing": "",
|
||||
"test": "NODE_ENV=test vitest run",
|
||||
"test:watch": "NODE_ENV=test vitest --ui",
|
||||
"coverage": "NODE_ENV=test vitest run --coverage",
|
||||
"// Container management commands": "",
|
||||
"// Docker": "",
|
||||
"container:build": "./scripts/dc.sh build dev",
|
||||
"container:start": "pnpm run container:stop && ./scripts/dc.sh run --rm --service-ports dev",
|
||||
"container:stop": "./scripts/dc.sh stop dev",
|
||||
@@ -49,19 +52,21 @@
|
||||
"@apollo/client": "^3.11.8",
|
||||
"@apollo/server": "^4.11.2",
|
||||
"@as-integrations/fastify": "^2.1.1",
|
||||
"@fastify/cookie": "^9.4.0",
|
||||
"@fastify/cookie": "^11.0.2",
|
||||
"@fastify/helmet": "^13.0.1",
|
||||
"@graphql-codegen/client-preset": "^4.5.0",
|
||||
"@graphql-tools/load-files": "^7.0.0",
|
||||
"@graphql-tools/merge": "^9.0.8",
|
||||
"@graphql-tools/schema": "^10.0.7",
|
||||
"@graphql-tools/utils": "^10.5.5",
|
||||
"@nestjs/apollo": "^12.2.1",
|
||||
"@nestjs/common": "^10.4.7",
|
||||
"@nestjs/core": "^10.4.7",
|
||||
"@nestjs/graphql": "^12.2.1",
|
||||
"@nestjs/passport": "^10.0.3",
|
||||
"@nestjs/platform-fastify": "^10.4.7",
|
||||
"@nestjs/schedule": "^4.1.1",
|
||||
"@jsonforms/core": "^3.5.1",
|
||||
"@nestjs/apollo": "^13.0.3",
|
||||
"@nestjs/common": "^11.0.11",
|
||||
"@nestjs/core": "^11.0.11",
|
||||
"@nestjs/graphql": "^13.0.3",
|
||||
"@nestjs/passport": "^11.0.0",
|
||||
"@nestjs/platform-fastify": "^11.0.11",
|
||||
"@nestjs/schedule": "^5.0.0",
|
||||
"@nestjs/throttler": "^6.2.1",
|
||||
"@reduxjs/toolkit": "^2.3.0",
|
||||
"@runonflux/nat-upnp": "^1.0.2",
|
||||
@@ -73,11 +78,11 @@
|
||||
"cacheable-lookup": "^7.0.0",
|
||||
"camelcase-keys": "^9.1.3",
|
||||
"casbin": "^5.32.0",
|
||||
"catch-exit": "^1.2.2",
|
||||
"change-case": "^5.4.4",
|
||||
"chokidar": "^4.0.1",
|
||||
"cli-table": "^0.3.11",
|
||||
"command-exists": "^1.2.9",
|
||||
"convert": "^5.5.1",
|
||||
"convert": "^5.8.0",
|
||||
"cookie": "^1.0.2",
|
||||
"cron": "3.5.0",
|
||||
"cross-fetch": "^4.0.0",
|
||||
@@ -87,26 +92,27 @@
|
||||
"dotenv": "^16.4.5",
|
||||
"execa": "^9.5.1",
|
||||
"exit-hook": "^4.0.0",
|
||||
"fastify": "^5.2.1",
|
||||
"filenamify": "^6.0.0",
|
||||
"fs-extra": "^11.2.0",
|
||||
"glob": "^11.0.1",
|
||||
"global-agent": "^3.0.0",
|
||||
"got": "^14.4.4",
|
||||
"got": "^14.4.6",
|
||||
"graphql": "^16.9.0",
|
||||
"graphql-fields": "^2.0.3",
|
||||
"graphql-scalars": "^1.23.0",
|
||||
"graphql-subscriptions": "^2.0.0",
|
||||
"graphql-subscriptions": "^3.0.0",
|
||||
"graphql-tag": "^2.12.6",
|
||||
"graphql-type-json": "^0.3.2",
|
||||
"graphql-type-uuid": "^0.2.0",
|
||||
"graphql-ws": "^5.16.0",
|
||||
"ini": "^4.1.2",
|
||||
"graphql-ws": "^6.0.0",
|
||||
"ini": "^5.0.0",
|
||||
"ip": "^2.0.1",
|
||||
"jose": "^5.9.6",
|
||||
"jose": "^6.0.0",
|
||||
"lodash-es": "^4.17.21",
|
||||
"multi-ini": "^2.3.2",
|
||||
"mustache": "^4.2.0",
|
||||
"nest-authz": "^2.11.0",
|
||||
"nest-authz": "^2.14.0",
|
||||
"nest-commander": "^3.15.0",
|
||||
"nestjs-pino": "^4.1.0",
|
||||
"node-cache": "^5.1.2",
|
||||
@@ -117,18 +123,21 @@
|
||||
"path-type": "^6.0.0",
|
||||
"pino": "^9.5.0",
|
||||
"pino-http": "^10.3.0",
|
||||
"pino-pretty": "^11.3.0",
|
||||
"pm2": "^5.4.2",
|
||||
"pino-pretty": "^13.0.0",
|
||||
"pm2": "^6.0.0",
|
||||
"reflect-metadata": "^0.1.14",
|
||||
"request": "^2.88.2",
|
||||
"rxjs": "^7.8.2",
|
||||
"semver": "^7.6.3",
|
||||
"strftime": "^0.10.3",
|
||||
"systeminformation": "^5.25.11",
|
||||
"uuid": "^11.0.2",
|
||||
"ws": "^8.18.0",
|
||||
"zen-observable-ts": "^1.1.0",
|
||||
"zod": "^3.23.8"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@eslint/js": "^9.21.0",
|
||||
"@graphql-codegen/add": "^5.0.3",
|
||||
"@graphql-codegen/cli": "^5.0.3",
|
||||
"@graphql-codegen/fragment-matcher": "^5.0.2",
|
||||
@@ -136,12 +145,12 @@
|
||||
"@graphql-codegen/typed-document-node": "^5.0.11",
|
||||
"@graphql-codegen/typescript": "^4.1.1",
|
||||
"@graphql-codegen/typescript-operations": "^4.3.1",
|
||||
"@graphql-codegen/typescript-resolvers": "4.4.3",
|
||||
"@graphql-codegen/typescript-resolvers": "4.5.0",
|
||||
"@graphql-typed-document-node/core": "^3.2.0",
|
||||
"@ianvs/prettier-plugin-sort-imports": "^4.4.0",
|
||||
"@nestjs/testing": "^10.4.7",
|
||||
"@nestjs/testing": "^11.0.11",
|
||||
"@originjs/vite-plugin-commonjs": "^1.0.3",
|
||||
"@rollup/plugin-node-resolve": "^15.3.0",
|
||||
"@rollup/plugin-node-resolve": "^16.0.0",
|
||||
"@swc/core": "^1.10.1",
|
||||
"@types/async-exit-hook": "^2.0.2",
|
||||
"@types/bytes": "^3.1.4",
|
||||
@@ -155,8 +164,8 @@
|
||||
"@types/ip": "^1.1.3",
|
||||
"@types/lodash": "^4.17.13",
|
||||
"@types/mustache": "^4.2.5",
|
||||
"@types/node": "^22.9.0",
|
||||
"@types/pify": "^5.0.4",
|
||||
"@types/node": "^22.13.4",
|
||||
"@types/pify": "^6.0.0",
|
||||
"@types/semver": "^7.5.8",
|
||||
"@types/sendmail": "^1.4.7",
|
||||
"@types/stoppable": "^1.1.3",
|
||||
@@ -167,19 +176,23 @@
|
||||
"@vitest/coverage-v8": "^3.0.5",
|
||||
"@vitest/ui": "^3.0.5",
|
||||
"cz-conventional-changelog": "3.3.0",
|
||||
"eslint": "^9.14.0",
|
||||
"eslint": "^9.20.1",
|
||||
"eslint-plugin-import": "^2.31.0",
|
||||
"eslint-plugin-n": "^17.0.0",
|
||||
"eslint-plugin-no-relative-import-paths": "^1.6.1",
|
||||
"eslint-plugin-prettier": "^5.2.3",
|
||||
"graphql-codegen-typescript-validation-schema": "^0.17.0",
|
||||
"jiti": "^2.4.0",
|
||||
"nodemon": "^3.1.7",
|
||||
"rollup-plugin-node-externals": "^7.1.3",
|
||||
"prettier": "^3.5.2",
|
||||
"rollup-plugin-node-externals": "^8.0.0",
|
||||
"standard-version": "^9.5.0",
|
||||
"tsx": "^4.19.2",
|
||||
"type-fest": "^4.37.0",
|
||||
"typescript": "^5.6.3",
|
||||
"typescript-eslint": "^8.13.0",
|
||||
"unplugin-swc": "^1.5.1",
|
||||
"vite": "^5.4.14",
|
||||
"vite": "^6.0.0",
|
||||
"vite-plugin-node": "^4.0.0",
|
||||
"vite-tsconfig-paths": "^5.1.0",
|
||||
"vitest": "^3.0.5",
|
||||
@@ -191,5 +204,5 @@
|
||||
}
|
||||
},
|
||||
"private": true,
|
||||
"packageManager": "pnpm@10.4.1"
|
||||
"packageManager": "pnpm@10.7.1"
|
||||
}
|
||||
|
||||
@@ -8,8 +8,6 @@ import { getDeploymentVersion } from './get-deployment-version.js';
|
||||
|
||||
try {
|
||||
// Create release and pack directories
|
||||
// Clean existing deploy folder
|
||||
await rm('./deploy', { recursive: true }).catch(() => {});
|
||||
await mkdir('./deploy/release', { recursive: true });
|
||||
await mkdir('./deploy/pack', { recursive: true });
|
||||
|
||||
@@ -27,31 +25,35 @@ try {
|
||||
|
||||
// Update the package.json version to the deployment version
|
||||
parsedPackageJson.version = deploymentVersion;
|
||||
// omit dev dependencies from release build
|
||||
parsedPackageJson.devDependencies = {};
|
||||
|
||||
// Create a temporary directory for packaging
|
||||
await mkdir('./deploy/pack/', { recursive: true });
|
||||
|
||||
|
||||
await writeFile('./deploy/pack/package.json', JSON.stringify(parsedPackageJson, null, 4));
|
||||
// Copy necessary files to the pack directory
|
||||
await $`cp -r dist README.md .env.* ecosystem.config.json ./deploy/pack/`;
|
||||
|
||||
|
||||
// Change to the pack directory and install dependencies
|
||||
cd('./deploy/pack');
|
||||
|
||||
console.log('Installing production dependencies...');
|
||||
|
||||
console.log('Building production pnpm store...');
|
||||
$.verbose = true;
|
||||
await $`pnpm install --prod --ignore-workspace --node-linker hoisted`;
|
||||
await $`pnpm install --prod --ignore-workspace --store-dir=../.pnpm-store`;
|
||||
|
||||
await $`rm -rf node_modules`; // Don't include node_modules in final package
|
||||
|
||||
const sudoCheck = await $`command -v sudo`.nothrow();
|
||||
const SUDO = sudoCheck.exitCode === 0 ? 'sudo' : '';
|
||||
await $`${SUDO} chown -R 0:0 ../.pnpm-store`;
|
||||
|
||||
await $`XZ_OPT=-5 tar -cJf ../packed-pnpm-store.txz ../.pnpm-store`;
|
||||
await $`${SUDO} rm -rf ../.pnpm-store`;
|
||||
|
||||
// chmod the cli
|
||||
await $`chmod +x ./dist/cli.js`;
|
||||
await $`chmod +x ./dist/main.js`;
|
||||
|
||||
// Create the tarball
|
||||
await $`tar -czf ../release/unraid-api.tgz ./`;
|
||||
|
||||
// Clean up
|
||||
cd('..');
|
||||
|
||||
} catch (error) {
|
||||
// Error with a command
|
||||
if (Object.keys(error).includes('stderr')) {
|
||||
|
||||
@@ -1,26 +1,17 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Path to store the last used server name
|
||||
state_file="$HOME/.deploy_state"
|
||||
|
||||
# Read the last used server name from the state file
|
||||
if [[ -f "$state_file" ]]; then
|
||||
last_server_name=$(cat "$state_file")
|
||||
else
|
||||
last_server_name=""
|
||||
fi
|
||||
|
||||
# Read the server name from the command-line argument or use the last used server name as the default
|
||||
server_name="${1:-$last_server_name}"
|
||||
# Arguments
|
||||
# $1: SSH server name (required)
|
||||
|
||||
# Check if the server name is provided
|
||||
if [[ -z "$server_name" ]]; then
|
||||
echo "Please provide the SSH server name."
|
||||
if [[ -z "$1" ]]; then
|
||||
echo "Error: SSH server name is required."
|
||||
echo "Usage: $0 <server_name>"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Save the current server name to the state file
|
||||
echo "$server_name" > "$state_file"
|
||||
# Set server name from command-line argument
|
||||
server_name="$1"
|
||||
|
||||
# Source directory path
|
||||
source_directory="./dist"
|
||||
@@ -34,9 +25,11 @@ if [ ! -d "$source_directory" ]; then
|
||||
fi
|
||||
fi
|
||||
|
||||
# Change ownership on copy
|
||||
# Destination directory path
|
||||
destination_directory="/usr/local/unraid-api"
|
||||
|
||||
# Replace the value inside the rsync command with the user's input
|
||||
rsync_command="rsync -avz -e ssh $source_directory root@${server_name}:/usr/local/unraid-api"
|
||||
rsync_command="rsync -avz --progress --stats -e ssh \"$source_directory\" \"root@${server_name}:$destination_directory\""
|
||||
|
||||
echo "Executing the following command:"
|
||||
echo "$rsync_command"
|
||||
@@ -46,10 +39,10 @@ eval "$rsync_command"
|
||||
exit_code=$?
|
||||
|
||||
# Chown the directory
|
||||
ssh root@"${server_name}" "chown -R root:root /usr/local/unraid-api"
|
||||
ssh root@"${server_name}" 'chown -R root:root /usr/local/unraid-api'
|
||||
|
||||
# Run unraid-api restart on remote host
|
||||
ssh root@"${server_name}" "INTROSPECTION=true LOG_LEVEL=trace unraid-api restart"
|
||||
ssh root@"${server_name}" 'INTROSPECTION=true LOG_LEVEL=trace unraid-api restart'
|
||||
|
||||
# Play built-in sound based on the operating system
|
||||
if [[ "$OSTYPE" == "darwin"* ]]; then
|
||||
|
||||
@@ -19,10 +19,12 @@ export const getDeploymentVersion = async (env = process.env, packageVersion: st
|
||||
return env.IS_TAGGED ? packageVersion : `${packageVersion}+${env.GIT_SHA}`;
|
||||
} else {
|
||||
const gitShortSHA = await runCommand('git', ['rev-parse', '--short', 'HEAD']);
|
||||
const isCommitTagged = await runCommand('git', ['describe', '--tags', '--abbrev=0', '--exact-match']) !== undefined;
|
||||
|
||||
const isCommitTagged =
|
||||
(await runCommand('git', ['describe', '--tags', '--abbrev=0', '--exact-match'])) !==
|
||||
undefined;
|
||||
|
||||
console.log('gitShortSHA', gitShortSHA, 'isCommitTagged', isCommitTagged);
|
||||
|
||||
|
||||
if (!gitShortSHA) {
|
||||
console.error('Failed to get git short SHA');
|
||||
process.exit(1);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { getAllowedOrigins } from '@app/common/allowed-origins';
|
||||
import { store } from '@app/store/index';
|
||||
import { loadConfigFile } from '@app/store/modules/config';
|
||||
import { loadStateFiles } from '@app/store/modules/emhttp';
|
||||
import { getAllowedOrigins } from '@app/common/allowed-origins.js';
|
||||
import { store } from '@app/store/index.js';
|
||||
import { loadConfigFile } from '@app/store/modules/config.js';
|
||||
import { loadStateFiles } from '@app/store/modules/emhttp.js';
|
||||
|
||||
import 'reflect-metadata';
|
||||
|
||||
|
||||
3
api/src/__test__/common/nginx/nginx-state.test.ts
Normal file
3
api/src/__test__/common/nginx/nginx-state.test.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
import { test } from 'vitest';
|
||||
|
||||
test.todo('Returns generated data');
|
||||
@@ -0,0 +1,5 @@
|
||||
import { test } from 'vitest';
|
||||
|
||||
test.todo('Adds a disk to the array');
|
||||
|
||||
test.todo('Fails to add the disk if the array is started');
|
||||
@@ -1,11 +1,11 @@
|
||||
import { expect, test, vi } from 'vitest';
|
||||
|
||||
import { getArrayData } from '@app/core/modules/array/get-array-data';
|
||||
import { store } from '@app/store';
|
||||
import { loadConfigFile } from '@app/store/modules/config';
|
||||
import { loadStateFiles } from '@app/store/modules/emhttp';
|
||||
import { getArrayData } from '@app/core/modules/array/get-array-data.js';
|
||||
import { store } from '@app/store/index.js';
|
||||
import { loadConfigFile } from '@app/store/modules/config.js';
|
||||
import { loadStateFiles } from '@app/store/modules/emhttp.js';
|
||||
|
||||
vi.mock('@app/core/pubsub', () => ({
|
||||
vi.mock('@app/core/pubsub.js', () => ({
|
||||
pubsub: { publish: vi.fn() },
|
||||
}));
|
||||
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
import { test } from 'vitest';
|
||||
|
||||
test.todo('Removes a disk from the array');
|
||||
|
||||
test.todo('Fails to remove the disk if the array is started');
|
||||
5
api/src/__test__/core/modules/array/update-array.test.ts
Normal file
5
api/src/__test__/core/modules/array/update-array.test.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
import { test } from 'vitest';
|
||||
|
||||
test.todo('Starts the array');
|
||||
|
||||
test.todo('Stops the array');
|
||||
@@ -0,0 +1,7 @@
|
||||
import { test } from 'vitest';
|
||||
|
||||
test.todo('Can start a parity check');
|
||||
|
||||
test.todo('Can pause a parity check');
|
||||
|
||||
test.todo('Can start a parity check');
|
||||
3
api/src/__test__/core/modules/debug/get-context.test.ts
Normal file
3
api/src/__test__/core/modules/debug/get-context.test.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
import { test } from 'vitest';
|
||||
|
||||
test.todo('Returns the current content');
|
||||
5
api/src/__test__/core/modules/disks/id/get-disk.test.ts
Normal file
5
api/src/__test__/core/modules/disks/id/get-disk.test.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
import { test } from 'vitest';
|
||||
|
||||
test.todo('Returns a single disk by ID');
|
||||
|
||||
test.todo('Returns nothing if no disk matches the ID');
|
||||
@@ -0,0 +1,5 @@
|
||||
import { test } from 'vitest';
|
||||
|
||||
test.todo('Returns all the Docker containers');
|
||||
|
||||
test.todo('Returns running Docker containers');
|
||||
@@ -0,0 +1,7 @@
|
||||
import { test } from 'vitest';
|
||||
|
||||
test.todo('Returns all USB devices');
|
||||
|
||||
test.todo('Returns all PCI-e devices');
|
||||
|
||||
test.todo('Returns all audio devices');
|
||||
3
api/src/__test__/core/modules/info/get-app-count.test.ts
Normal file
3
api/src/__test__/core/modules/info/get-app-count.test.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
import { test } from 'vitest';
|
||||
|
||||
test.todo('Gets total count of Docker containers installed/running');
|
||||
3
api/src/__test__/core/modules/info/get-baseboard.test.ts
Normal file
3
api/src/__test__/core/modules/info/get-baseboard.test.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
import { test } from 'vitest';
|
||||
|
||||
test.todo('Returns baseboard info');
|
||||
3
api/src/__test__/core/modules/info/get-cpu.test.ts
Normal file
3
api/src/__test__/core/modules/info/get-cpu.test.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
import { test } from 'vitest';
|
||||
|
||||
test.todo('Gets CPU info');
|
||||
@@ -1,8 +1,8 @@
|
||||
import { expect, test, vi } from 'vitest';
|
||||
|
||||
import { ConsoleNotifier } from '@app/core/notifiers/console';
|
||||
import { ConsoleNotifier } from '@app/core/notifiers/console.js';
|
||||
|
||||
vi.mock('@app/core/log', () => ({
|
||||
vi.mock('@app/core/log.js', () => ({
|
||||
logger: {
|
||||
info: vi.fn(),
|
||||
error: vi.fn(),
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { expect, test, vi } from 'vitest';
|
||||
|
||||
import { UnraidLocalNotifier } from '@app/core/notifiers/unraid-local';
|
||||
import { UnraidLocalNotifier } from '@app/core/notifiers/unraid-local.js';
|
||||
|
||||
vi.mock('@app/core/log', () => ({
|
||||
vi.mock('@app/core/log.js', () => ({
|
||||
logger: {
|
||||
info: vi.fn(),
|
||||
error: vi.fn(),
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
import { expect, test, vi } from 'vitest';
|
||||
|
||||
import type { SliceState } from '@app/store/modules/emhttp';
|
||||
import { getters } from '@app/store';
|
||||
|
||||
test('Returns true if the array is started', async () => {
|
||||
vi.spyOn(getters, 'emhttp').mockImplementation(
|
||||
() => ({ var: { mdState: 'STARTED' } }) as unknown as SliceState
|
||||
);
|
||||
|
||||
const { arrayIsRunning } = await import('@app/core/utils/array/array-is-running');
|
||||
expect(arrayIsRunning()).toBe(true);
|
||||
vi.spyOn(getters, 'emhttp').mockReset();
|
||||
});
|
||||
|
||||
test('Returns false if the array is stopped', async () => {
|
||||
vi.spyOn(getters, 'emhttp').mockImplementation(
|
||||
() => ({ var: { mdState: 'Stopped' } }) as unknown as SliceState
|
||||
);
|
||||
const { arrayIsRunning } = await import('@app/core/utils/array/array-is-running');
|
||||
expect(arrayIsRunning()).toBe(false);
|
||||
vi.spyOn(getters, 'emhttp').mockReset();
|
||||
});
|
||||
@@ -3,8 +3,8 @@ import 'reflect-metadata';
|
||||
import { cloneDeep } from 'lodash-es';
|
||||
import { expect, test } from 'vitest';
|
||||
|
||||
import { getWriteableConfig } from '@app/core/utils/files/config-file-normalizer';
|
||||
import { initialState } from '@app/store/modules/config';
|
||||
import { getWriteableConfig } from '@app/core/utils/files/config-file-normalizer.js';
|
||||
import { initialState } from '@app/store/modules/config.js';
|
||||
|
||||
test('it creates a FLASH config with NO OPTIONAL values', () => {
|
||||
const basicConfig = initialState;
|
||||
|
||||
@@ -2,7 +2,7 @@ import { parse } from 'ini';
|
||||
import { Serializer } from 'multi-ini';
|
||||
import { expect, test } from 'vitest';
|
||||
|
||||
import { safelySerializeObjectToIni } from '@app/core/utils/files/safe-ini-serializer';
|
||||
import { safelySerializeObjectToIni } from '@app/core/utils/files/safe-ini-serializer.js';
|
||||
|
||||
test('MultiIni breaks when serializing an object with a boolean inside', async () => {
|
||||
const objectToSerialize = {
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
import { expect, test } from 'vitest';
|
||||
|
||||
import { getBannerPathIfPresent, getCasePathIfPresent } from '@app/core/utils/images/image-file-helpers';
|
||||
import { loadDynamixConfigFile } from '@app/store/actions/load-dynamix-config-file';
|
||||
import { store } from '@app/store/index';
|
||||
import {
|
||||
getBannerPathIfPresent,
|
||||
getCasePathIfPresent,
|
||||
} from '@app/core/utils/images/image-file-helpers.js';
|
||||
import { loadDynamixConfigFile } from '@app/store/actions/load-dynamix-config-file.js';
|
||||
import { store } from '@app/store/index.js';
|
||||
|
||||
test('get case path returns expected result', async () => {
|
||||
await expect(getCasePathIfPresent()).resolves.toContain('/dev/dynamix/case-model.png');
|
||||
|
||||
3
api/src/__test__/core/utils/misc/atomic-sleep.test.ts
Normal file
3
api/src/__test__/core/utils/misc/atomic-sleep.test.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
import { test } from 'vitest';
|
||||
|
||||
test.todo('Sleeps atomically for n milliseconds');
|
||||
@@ -1,6 +1,6 @@
|
||||
import { expect, test } from 'vitest';
|
||||
|
||||
import { cleanStdout } from '@app/core/utils/misc/clean-stdout';
|
||||
import { cleanStdout } from '@app/core/utils/misc/clean-stdout.js';
|
||||
|
||||
test('Returns trimmed stdout from execa command', () => {
|
||||
expect(cleanStdout({ stdout: 'test' })).toBe('test');
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
import { expect, test } from 'vitest';
|
||||
|
||||
import { store } from '@app/store';
|
||||
import { FileLoadStatus, StateFileKey } from '@app/store/types';
|
||||
import { store } from '@app/store/index.js';
|
||||
import { FileLoadStatus, StateFileKey } from '@app/store/types.js';
|
||||
|
||||
import '@app/core/utils/misc/get-key-file';
|
||||
import '@app/store/modules/emhttp';
|
||||
import '@app/core/utils/misc/get-key-file.js';
|
||||
import '@app/store/modules/emhttp.js';
|
||||
|
||||
test('Before loading key returns null', async () => {
|
||||
const { getKeyFile } = await import('@app/core/utils/misc/get-key-file');
|
||||
const { getKeyFile } = await import('@app/core/utils/misc/get-key-file.js');
|
||||
const { status } = store.getState().registration;
|
||||
|
||||
expect(status).toBe(FileLoadStatus.UNLOADED);
|
||||
@@ -15,8 +15,8 @@ test('Before loading key returns null', async () => {
|
||||
});
|
||||
|
||||
test('Requires emhttp to be loaded to find key file', async () => {
|
||||
const { getKeyFile } = await import('@app/core/utils/misc/get-key-file');
|
||||
const { loadRegistrationKey } = await import('@app/store/modules/registration');
|
||||
const { getKeyFile } = await import('@app/core/utils/misc/get-key-file.js');
|
||||
const { loadRegistrationKey } = await import('@app/store/modules/registration.js');
|
||||
|
||||
// Load registration key into store
|
||||
await store.dispatch(loadRegistrationKey());
|
||||
@@ -28,8 +28,8 @@ test('Requires emhttp to be loaded to find key file', async () => {
|
||||
});
|
||||
|
||||
test('Returns empty key if key location is empty', async () => {
|
||||
const { getKeyFile } = await import('@app/core/utils/misc/get-key-file');
|
||||
const { updateEmhttpState } = await import('@app/store/modules/emhttp');
|
||||
const { getKeyFile } = await import('@app/core/utils/misc/get-key-file.js');
|
||||
const { updateEmhttpState } = await import('@app/store/modules/emhttp.js');
|
||||
|
||||
// Set key file location as empty
|
||||
// This should only happen if the user doesn't have a key file
|
||||
@@ -48,17 +48,21 @@ test('Returns empty key if key location is empty', async () => {
|
||||
await expect(getKeyFile()).resolves.toBe('');
|
||||
});
|
||||
|
||||
test('Returns decoded key file if key location exists', async () => {
|
||||
const { getKeyFile } = await import('@app/core/utils/misc/get-key-file');
|
||||
const { loadStateFiles } = await import('@app/store/modules/emhttp');
|
||||
test(
|
||||
'Returns decoded key file if key location exists',
|
||||
async () => {
|
||||
const { getKeyFile } = await import('@app/core/utils/misc/get-key-file.js');
|
||||
const { loadStateFiles } = await import('@app/store/modules/emhttp.js');
|
||||
|
||||
// Load state files into store
|
||||
await store.dispatch(loadStateFiles());
|
||||
// Load state files into store
|
||||
await store.dispatch(loadStateFiles());
|
||||
|
||||
// Check if store has state files loaded
|
||||
const { status } = store.getState().registration;
|
||||
expect(status).toBe(FileLoadStatus.LOADED);
|
||||
await expect(getKeyFile()).resolves.toMatchInlineSnapshot(
|
||||
'"hVs1tLjvC9FiiQsIwIQ7G1KszAcexf0IneThhnmf22SB0dGs5WzRkqMiSMmt2DtR5HOXFUD32YyxuzGeUXmky3zKpSu6xhZNKVg5atGM1OfvkzHBMldI3SeBLuUFSgejLbpNUMdTrbk64JJdbzle4O8wiQgkIpAMIGxeYLwLBD4zHBcfyzq40QnxG--HcX6j25eE0xqa2zWj-j0b0rCAXahJV2a3ySCbPzr1MvfPRTVb0rr7KJ-25R592hYrz4H7Sc1B3p0lr6QUxHE6o7bcYrWKDRtIVoZ8SMPpd1_0gzYIcl5GsDFzFumTXUh8NEnl0Q8hwW1YE-tRc6Y_rrvd7w"'
|
||||
);
|
||||
});
|
||||
// Check if store has state files loaded
|
||||
const { status } = store.getState().registration;
|
||||
expect(status).toBe(FileLoadStatus.LOADED);
|
||||
await expect(getKeyFile()).resolves.toMatchInlineSnapshot(
|
||||
'"hVs1tLjvC9FiiQsIwIQ7G1KszAcexf0IneThhnmf22SB0dGs5WzRkqMiSMmt2DtR5HOXFUD32YyxuzGeUXmky3zKpSu6xhZNKVg5atGM1OfvkzHBMldI3SeBLuUFSgejLbpNUMdTrbk64JJdbzle4O8wiQgkIpAMIGxeYLwLBD4zHBcfyzq40QnxG--HcX6j25eE0xqa2zWj-j0b0rCAXahJV2a3ySCbPzr1MvfPRTVb0rr7KJ-25R592hYrz4H7Sc1B3p0lr6QUxHE6o7bcYrWKDRtIVoZ8SMPpd1_0gzYIcl5GsDFzFumTXUh8NEnl0Q8hwW1YE-tRc6Y_rrvd7w"'
|
||||
);
|
||||
},
|
||||
{ timeout: 10000 }
|
||||
);
|
||||
|
||||
3
api/src/__test__/core/utils/misc/get-machine-id.test.ts
Normal file
3
api/src/__test__/core/utils/misc/get-machine-id.test.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
import { test } from 'vitest';
|
||||
|
||||
test.todo('Returns machine-id');
|
||||
@@ -4,8 +4,8 @@ import { parse } from 'ini';
|
||||
import { Parser as MultiIniParser } from 'multi-ini';
|
||||
import { expect, test } from 'vitest';
|
||||
|
||||
import { safelySerializeObjectToIni } from '@app/core/utils/files/safe-ini-serializer';
|
||||
import { parseConfig } from '@app/core/utils/misc/parse-config';
|
||||
import { safelySerializeObjectToIni } from '@app/core/utils/files/safe-ini-serializer.js';
|
||||
import { parseConfig } from '@app/core/utils/misc/parse-config.js';
|
||||
|
||||
const iniTestData = `["root"]
|
||||
idx="0"
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { expect, test } from 'vitest';
|
||||
|
||||
import { getShares } from '@app/core/utils/shares/get-shares';
|
||||
import { store } from '@app/store';
|
||||
import { loadStateFiles } from '@app/store/modules/emhttp';
|
||||
import { getShares } from '@app/core/utils/shares/get-shares.js';
|
||||
import { store } from '@app/store/index.js';
|
||||
import { loadStateFiles } from '@app/store/modules/emhttp.js';
|
||||
|
||||
test('Returns both disk and user shares', async () => {
|
||||
await store.dispatch(loadStateFiles());
|
||||
|
||||
@@ -1,34 +0,0 @@
|
||||
import { afterEach, expect, test, vi } from 'vitest';
|
||||
|
||||
import { checkDNS } from '@app/graphql/resolvers/query/cloud/check-dns';
|
||||
import { store } from '@app/store';
|
||||
import { clearKey } from '@app/store/modules/cache';
|
||||
import { CacheKeys } from '@app/store/types';
|
||||
|
||||
afterEach(() => {
|
||||
store.dispatch(clearKey(CacheKeys.checkDns));
|
||||
});
|
||||
|
||||
test('it resolves dns successfully', async () => {
|
||||
// @TODO
|
||||
const dns = await checkDNS('example.com');
|
||||
expect(dns.cloudIp).not.toBeNull();
|
||||
}, 25_000);
|
||||
|
||||
test('testing twice results in a cache hit', async () => {
|
||||
// Hit mothership
|
||||
const getters = await import('@app/store/getters');
|
||||
const dnsSpy = vi.spyOn(getters, 'getDnsCache');
|
||||
const dns = await checkDNS();
|
||||
expect(dns.cloudIp).toBeTypeOf('string');
|
||||
expect(dnsSpy.mock.results[0]).toMatchInlineSnapshot(`
|
||||
{
|
||||
"type": "return",
|
||||
"value": undefined,
|
||||
}
|
||||
`);
|
||||
const dnslookup2 = await checkDNS();
|
||||
expect(dnslookup2.cloudIp).toEqual(dns.cloudIp);
|
||||
expect(dnsSpy.mock.results[1].value.cloudIp).toEqual(dns.cloudIp);
|
||||
expect(store.getState().cache.nodeCache.getTtl(CacheKeys.checkDns)).toBeGreaterThan(500);
|
||||
});
|
||||
@@ -1,12 +1,15 @@
|
||||
import 'reflect-metadata';
|
||||
|
||||
import { readFileSync } from 'fs';
|
||||
import { join } from 'path';
|
||||
|
||||
import { expect, test } from 'vitest';
|
||||
|
||||
import packageJson from '@app/../package.json';
|
||||
import { checkMothershipAuthentication } from '@app/graphql/resolvers/query/cloud/check-mothership-authentication';
|
||||
import { checkMothershipAuthentication } from '@app/graphql/resolvers/query/cloud/check-mothership-authentication.js';
|
||||
|
||||
test('It fails to authenticate with mothership with no credentials', async () => {
|
||||
try {
|
||||
const packageJson = JSON.parse(readFileSync(join(process.cwd(), 'package.json'), 'utf-8'));
|
||||
await expect(
|
||||
checkMothershipAuthentication('BAD', 'BAD')
|
||||
).rejects.toThrowErrorMatchingInlineSnapshot(
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
import { expect, test } from 'vitest';
|
||||
|
||||
import type { NginxUrlFields } from '@app/graphql/resolvers/subscription/network';
|
||||
import { type Nginx } from '@app/core/types/states/nginx';
|
||||
import type { NginxUrlFields } from '@app/graphql/resolvers/subscription/network.js';
|
||||
import { type Nginx } from '@app/core/types/states/nginx.js';
|
||||
import {
|
||||
getServerIps,
|
||||
getUrlForField,
|
||||
getUrlForServer,
|
||||
} from '@app/graphql/resolvers/subscription/network';
|
||||
import { store } from '@app/store';
|
||||
import { loadConfigFile } from '@app/store/modules/config';
|
||||
import { loadStateFiles } from '@app/store/modules/emhttp';
|
||||
} from '@app/graphql/resolvers/subscription/network.js';
|
||||
import { store } from '@app/store/index.js';
|
||||
import { loadConfigFile } from '@app/store/modules/config.js';
|
||||
import { loadStateFiles } from '@app/store/modules/emhttp.js';
|
||||
|
||||
test.each([
|
||||
[{ httpPort: 80, httpsPort: 443, url: 'my-default-url.com' }],
|
||||
@@ -117,16 +117,16 @@ test('getUrlForServer - field does not exist, ssl disabled', async () => {
|
||||
|
||||
test('getUrlForServer - FQDN - field exists, port non-empty', () => {
|
||||
const result = getUrlForServer({
|
||||
nginx: { lanFqdn: 'my-fqdn.unraid.net', httpsPort: 445 } as const as Nginx,
|
||||
field: 'lanFqdn',
|
||||
nginx: { lanFqdn: 'my-fqdn.unraid.net', httpsPort: 445 } as unknown as Nginx,
|
||||
field: 'lanFqdn' as NginxUrlFields,
|
||||
});
|
||||
expect(result).toMatchInlineSnapshot('"https://my-fqdn.unraid.net:445/"');
|
||||
});
|
||||
|
||||
test('getUrlForServer - FQDN - field exists, port empty', () => {
|
||||
const result = getUrlForServer({
|
||||
nginx: { lanFqdn: 'my-fqdn.unraid.net', httpPort: 80, httpsPort: 443 } as const as Nginx,
|
||||
field: 'lanFqdn',
|
||||
nginx: { lanFqdn: 'my-fqdn.unraid.net', httpPort: 80, httpsPort: 443 } as unknown as Nginx,
|
||||
field: 'lanFqdn' as NginxUrlFields,
|
||||
});
|
||||
expect(result).toMatchInlineSnapshot('"https://my-fqdn.unraid.net/"');
|
||||
});
|
||||
@@ -140,7 +140,7 @@ test.each([
|
||||
sslMode: 'no',
|
||||
httpPort: 80,
|
||||
httpsPort: 443,
|
||||
} as const as Nginx,
|
||||
} as unknown as Nginx,
|
||||
field: 'lanFqdn' as NginxUrlFields,
|
||||
},
|
||||
],
|
||||
@@ -152,7 +152,7 @@ test.each([
|
||||
sslMode: 'yes',
|
||||
httpPort: 80,
|
||||
httpsPort: 443,
|
||||
} as const as Nginx,
|
||||
} as unknown as Nginx,
|
||||
field: 'wanFqdn' as NginxUrlFields,
|
||||
},
|
||||
],
|
||||
@@ -164,7 +164,7 @@ test.each([
|
||||
sslMode: 'auto',
|
||||
httpPort: 80,
|
||||
httpsPort: 443,
|
||||
} as const as Nginx,
|
||||
} as unknown as Nginx,
|
||||
field: 'wanFqdn6' as NginxUrlFields,
|
||||
},
|
||||
],
|
||||
@@ -176,7 +176,7 @@ test.each([
|
||||
test('getUrlForServer - field does not exist, ssl disabled', async () => {
|
||||
const getResult = async () =>
|
||||
getUrlForServer({
|
||||
nginx: { lanFqdn: 'my-fqdn.unraid.net' } as const as Nginx,
|
||||
nginx: { lanFqdn: 'my-fqdn.unraid.net' } as unknown as Nginx,
|
||||
ports: { portSsl: '', port: '', defaultUrl: new URL('https://my-default-url.unraid.net') },
|
||||
// @ts-expect-error Field doesn't exist
|
||||
field: 'idontexist',
|
||||
|
||||
180
api/src/__test__/json-forms.test.ts
Normal file
180
api/src/__test__/json-forms.test.ts
Normal file
@@ -0,0 +1,180 @@
|
||||
import type { ControlElement } from '@jsonforms/core';
|
||||
import { describe, expect, it } from 'vitest';
|
||||
|
||||
import type { SettingSlice } from '@app/unraid-api/types/json-forms.js';
|
||||
import { createEmptySettingSlice, mergeSettingSlices } from '@app/unraid-api/types/json-forms.js';
|
||||
|
||||
describe('mergeSettingSlices', () => {
|
||||
it('returns an empty slice when given an empty array', () => {
|
||||
const result = mergeSettingSlices([]);
|
||||
expect(result).toEqual(createEmptySettingSlice());
|
||||
});
|
||||
|
||||
it('returns the same slice when given a single slice', () => {
|
||||
const slice: SettingSlice = {
|
||||
properties: {
|
||||
test: { type: 'string' },
|
||||
},
|
||||
elements: [{ type: 'Control', scope: '#/properties/test' }],
|
||||
};
|
||||
|
||||
const result = mergeSettingSlices([slice]);
|
||||
expect(result).toEqual(slice);
|
||||
});
|
||||
|
||||
it('merges properties and concatenates elements from multiple slices', () => {
|
||||
const slice1: SettingSlice = {
|
||||
properties: {
|
||||
prop1: { type: 'string' },
|
||||
},
|
||||
elements: [{ type: 'Control', scope: '#/properties/prop1' }],
|
||||
};
|
||||
|
||||
const slice2: SettingSlice = {
|
||||
properties: {
|
||||
prop2: { type: 'number' },
|
||||
},
|
||||
elements: [{ type: 'Control', scope: '#/properties/prop2' }],
|
||||
};
|
||||
|
||||
const expected: SettingSlice = {
|
||||
properties: {
|
||||
prop1: { type: 'string' },
|
||||
prop2: { type: 'number' },
|
||||
},
|
||||
elements: [
|
||||
{ type: 'Control', scope: '#/properties/prop1' },
|
||||
{ type: 'Control', scope: '#/properties/prop2' },
|
||||
],
|
||||
};
|
||||
|
||||
const result = mergeSettingSlices([slice1, slice2]);
|
||||
expect(result).toEqual(expected);
|
||||
});
|
||||
|
||||
it('handles more complex schema properties and UI elements', () => {
|
||||
const slice1: SettingSlice = {
|
||||
properties: {
|
||||
name: {
|
||||
type: 'string',
|
||||
title: 'Name',
|
||||
minLength: 3,
|
||||
},
|
||||
},
|
||||
elements: [
|
||||
{
|
||||
type: 'Control',
|
||||
scope: '#/properties/name',
|
||||
label: 'Full Name',
|
||||
} as ControlElement,
|
||||
],
|
||||
};
|
||||
|
||||
const slice2: SettingSlice = {
|
||||
properties: {
|
||||
age: {
|
||||
type: 'number',
|
||||
title: 'Age',
|
||||
minimum: 0,
|
||||
maximum: 120,
|
||||
},
|
||||
},
|
||||
elements: [
|
||||
{
|
||||
type: 'Control',
|
||||
scope: '#/properties/age',
|
||||
label: 'Your Age',
|
||||
} as ControlElement,
|
||||
],
|
||||
};
|
||||
|
||||
const slice3: SettingSlice = {
|
||||
properties: {
|
||||
active: {
|
||||
type: 'boolean',
|
||||
title: 'Active Status',
|
||||
default: true,
|
||||
},
|
||||
},
|
||||
elements: [
|
||||
{
|
||||
type: 'Control',
|
||||
scope: '#/properties/active',
|
||||
label: 'Is Active',
|
||||
options: {
|
||||
toggle: true,
|
||||
},
|
||||
} as ControlElement,
|
||||
],
|
||||
};
|
||||
|
||||
const result = mergeSettingSlices([slice1, slice2, slice3]);
|
||||
|
||||
// Check properties were merged correctly
|
||||
expect(result.properties).toHaveProperty('name');
|
||||
expect(result.properties).toHaveProperty('age');
|
||||
expect(result.properties).toHaveProperty('active');
|
||||
expect(result.properties.name.type).toBe('string');
|
||||
expect(result.properties.age.type).toBe('number');
|
||||
expect(result.properties.active.type).toBe('boolean');
|
||||
|
||||
// Check elements were concatenated in order
|
||||
expect(result.elements).toHaveLength(3);
|
||||
expect(result.elements[0]).toEqual(slice1.elements[0]);
|
||||
expect(result.elements[1]).toEqual(slice2.elements[0]);
|
||||
expect(result.elements[2]).toEqual(slice3.elements[0]);
|
||||
});
|
||||
|
||||
it('later properties override earlier ones with the same key', () => {
|
||||
const slice1: SettingSlice = {
|
||||
properties: {
|
||||
prop: { type: 'string', title: 'Original' },
|
||||
},
|
||||
elements: [
|
||||
{ type: 'Control', scope: '#/properties/prop', label: 'First' } as ControlElement,
|
||||
],
|
||||
};
|
||||
|
||||
const slice2: SettingSlice = {
|
||||
properties: {
|
||||
prop: { type: 'number', title: 'Override' },
|
||||
},
|
||||
elements: [
|
||||
{ type: 'Control', scope: '#/properties/prop', label: 'Second' } as ControlElement,
|
||||
],
|
||||
};
|
||||
|
||||
const result = mergeSettingSlices([slice1, slice2]);
|
||||
|
||||
// The property from slice2 should override the one from slice1
|
||||
expect(result.properties.prop.type).toBe('number');
|
||||
expect(result.properties.prop.title).toBe('Override');
|
||||
|
||||
// Both elements should be present
|
||||
expect(result.elements).toHaveLength(2);
|
||||
expect((result.elements[0] as ControlElement).label).toBe('First');
|
||||
expect((result.elements[1] as ControlElement).label).toBe('Second');
|
||||
});
|
||||
|
||||
it('preserves empty properties and elements', () => {
|
||||
const slice1: SettingSlice = {
|
||||
properties: {},
|
||||
elements: [],
|
||||
};
|
||||
|
||||
const slice2: SettingSlice = {
|
||||
properties: {
|
||||
prop: { type: 'string' },
|
||||
},
|
||||
elements: [{ type: 'Control', scope: '#/properties/prop' }],
|
||||
};
|
||||
|
||||
const result = mergeSettingSlices([slice1, slice2]);
|
||||
expect(result.properties).toHaveProperty('prop');
|
||||
expect(result.elements).toHaveLength(1);
|
||||
|
||||
const result2 = mergeSettingSlices([slice2, slice1]);
|
||||
expect(result2.properties).toHaveProperty('prop');
|
||||
expect(result2.elements).toHaveLength(1);
|
||||
});
|
||||
});
|
||||
@@ -1,7 +1,7 @@
|
||||
import { beforeEach, expect, test, vi } from 'vitest';
|
||||
|
||||
// Preloading imports for faster tests
|
||||
import '@app/mothership/utils/convert-to-fuzzy-time';
|
||||
import '@app/mothership/utils/convert-to-fuzzy-time.js';
|
||||
|
||||
vi.mock('fs', () => ({
|
||||
default: {
|
||||
@@ -17,7 +17,7 @@ vi.mock('@graphql-tools/schema', () => ({
|
||||
makeExecutableSchema: vi.fn(),
|
||||
}));
|
||||
|
||||
vi.mock('@app/core/log', () => ({
|
||||
vi.mock('@app/core/log.js', () => ({
|
||||
default: { relayLogger: { trace: vi.fn() } },
|
||||
relayLogger: { trace: vi.fn() },
|
||||
logger: { trace: vi.fn() },
|
||||
@@ -40,7 +40,7 @@ const generateTestCases = () => {
|
||||
};
|
||||
|
||||
test.each(generateTestCases())('Successfully converts to fuzzy time %o', async ({ min, max }) => {
|
||||
const { convertToFuzzyTime } = await import('@app/mothership/utils/convert-to-fuzzy-time');
|
||||
const { convertToFuzzyTime } = await import('@app/mothership/utils/convert-to-fuzzy-time.js');
|
||||
|
||||
const res = convertToFuzzyTime(min, max);
|
||||
expect(res).toBeGreaterThanOrEqual(min);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { vi } from 'vitest';
|
||||
|
||||
vi.mock('@app/core/utils/misc/send-form-to-keyserver', () => {
|
||||
vi.mock('@app/core/utils/misc/send-form-to-keyserver.js', () => {
|
||||
const sendFormToKeyServer = vi.fn().mockResolvedValue({ body: JSON.stringify({ valid: true }) });
|
||||
return { sendFormToKeyServer };
|
||||
});
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { expect, test } from 'vitest';
|
||||
|
||||
import { store } from '@app/store';
|
||||
import { MyServersConfigMemory } from '@app/types/my-servers-config';
|
||||
import { store } from '@app/store/index.js';
|
||||
import { MyServersConfigMemory } from '@app/types/my-servers-config.js';
|
||||
|
||||
test('Before init returns default values for all fields', async () => {
|
||||
const state = store.getState().config;
|
||||
@@ -9,7 +9,7 @@ test('Before init returns default values for all fields', async () => {
|
||||
}, 10_000);
|
||||
|
||||
test('After init returns values from cfg file for all fields', async () => {
|
||||
const { loadConfigFile } = await import('@app/store/modules/config');
|
||||
const { loadConfigFile } = await import('@app/store/modules/config.js');
|
||||
|
||||
// Load cfg into store
|
||||
await store.dispatch(loadConfigFile());
|
||||
@@ -53,7 +53,7 @@ test('After init returns values from cfg file for all fields', async () => {
|
||||
});
|
||||
|
||||
test('updateUserConfig merges in changes to current state', async () => {
|
||||
const { loadConfigFile, updateUserConfig } = await import('@app/store/modules/config');
|
||||
const { loadConfigFile, updateUserConfig } = await import('@app/store/modules/config.js');
|
||||
|
||||
// Load cfg into store
|
||||
await store.dispatch(loadConfigFile());
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import { expect, test } from 'vitest';
|
||||
|
||||
import { store } from '@app/store';
|
||||
import { FileLoadStatus } from '@app/store/types';
|
||||
import { store } from '@app/store/index.js';
|
||||
import { FileLoadStatus } from '@app/store/types.js';
|
||||
|
||||
// Preloading imports for faster tests
|
||||
import '@app/store/modules/emhttp';
|
||||
import '@app/store/modules/emhttp.js';
|
||||
|
||||
test('Before init returns default values for all fields', async () => {
|
||||
const { status, ...state } = store.getState().emhttp;
|
||||
@@ -25,7 +25,7 @@ test('Before init returns default values for all fields', async () => {
|
||||
});
|
||||
|
||||
test('After init returns values from cfg file for all fields', async () => {
|
||||
const { loadStateFiles } = await import('@app/store/modules/emhttp');
|
||||
const { loadStateFiles } = await import('@app/store/modules/emhttp.js');
|
||||
|
||||
// Load state files into store
|
||||
await store.dispatch(loadStateFiles());
|
||||
@@ -949,160 +949,160 @@ test('After init returns values from cfg file for all fields', async () => {
|
||||
]
|
||||
`);
|
||||
expect(varState).toMatchInlineSnapshot(`
|
||||
{
|
||||
"bindMgt": false,
|
||||
"cacheNumDevices": NaN,
|
||||
"cacheSbNumDisks": NaN,
|
||||
"comment": "Dev Server",
|
||||
"configState": "yes",
|
||||
"configValid": true,
|
||||
"csrfToken": "0000000000000000",
|
||||
"defaultFsType": "xfs",
|
||||
"deviceCount": 4,
|
||||
"domain": "",
|
||||
"domainLogin": "Administrator",
|
||||
"domainShort": "",
|
||||
"enableFruit": "no",
|
||||
"flashGuid": "0000-0000-0000-000000000000",
|
||||
"flashProduct": "DataTraveler_3.0",
|
||||
"flashVendor": "KINGSTON",
|
||||
"fsCopyPrcnt": 0,
|
||||
"fsNumMounted": 0,
|
||||
"fsNumUnmountable": 0,
|
||||
"fsProgress": "Autostart disabled",
|
||||
"fsState": "Stopped",
|
||||
"fsUnmountableMask": "",
|
||||
"fuseDirectio": "auto",
|
||||
"fuseDirectioDefault": "auto",
|
||||
"fuseDirectioStatus": "default",
|
||||
"fuseRemember": "330",
|
||||
"fuseRememberDefault": "330",
|
||||
"fuseRememberStatus": "default",
|
||||
"fuseUseino": "yes",
|
||||
"hideDotFiles": false,
|
||||
"joinStatus": "Not joined",
|
||||
"localMaster": true,
|
||||
"localTld": "local",
|
||||
"luksKeyfile": "/tmp/unraid/keyfile",
|
||||
"maxArraysz": 30,
|
||||
"maxCachesz": 30,
|
||||
"mdColor": "green-blink",
|
||||
"mdNumDisabled": 1,
|
||||
"mdNumDisks": 4,
|
||||
"mdNumErased": 0,
|
||||
"mdNumInvalid": 1,
|
||||
"mdNumMissing": 0,
|
||||
"mdNumNew": 0,
|
||||
"mdNumStripes": 1280,
|
||||
"mdNumStripesDefault": 1280,
|
||||
"mdNumStripesStatus": "default",
|
||||
"mdQueueLimit": "80",
|
||||
"mdQueueLimitDefault": "80",
|
||||
"mdQueueLimitStatus": "default",
|
||||
"mdResync": 0,
|
||||
"mdResyncAction": "check P",
|
||||
"mdResyncCorr": "0",
|
||||
"mdResyncDb": "0",
|
||||
"mdResyncDt": "0",
|
||||
"mdResyncPos": 0,
|
||||
"mdResyncSize": 438960096,
|
||||
"mdScheduler": "auto",
|
||||
"mdSchedulerDefault": "auto",
|
||||
"mdSchedulerStatus": "default",
|
||||
"mdState": "STOPPED",
|
||||
"mdSyncLimit": "5",
|
||||
"mdSyncLimitDefault": "5",
|
||||
"mdSyncLimitStatus": "default",
|
||||
"mdSyncThresh": NaN,
|
||||
"mdSyncThreshDefault": NaN,
|
||||
"mdSyncWindow": NaN,
|
||||
"mdSyncWindowDefault": NaN,
|
||||
"mdVersion": "2.9.14",
|
||||
"mdWriteMethod": NaN,
|
||||
"mdWriteMethodDefault": "auto",
|
||||
"mdWriteMethodStatus": "default",
|
||||
"name": "Tower",
|
||||
"nrRequests": NaN,
|
||||
"nrRequestsDefault": NaN,
|
||||
"nrRequestsStatus": "default",
|
||||
"ntpServer1": "time1.google.com",
|
||||
"ntpServer2": "time2.google.com",
|
||||
"ntpServer3": "time3.google.com",
|
||||
"ntpServer4": "time4.google.com",
|
||||
"pollAttributes": "1800",
|
||||
"pollAttributesDefault": "1800",
|
||||
"pollAttributesStatus": "default",
|
||||
"port": 80,
|
||||
"portssh": 22,
|
||||
"portssl": 443,
|
||||
"porttelnet": 23,
|
||||
"queueDepth": "auto",
|
||||
"regCheck": "Valid",
|
||||
"regExp": "",
|
||||
"regFile": "/app/dev/Unraid.net/Pro.key",
|
||||
"regGen": "0",
|
||||
"regGuid": "13FE-4200-C300-58C372A52B19",
|
||||
"regState": "PRO",
|
||||
"regTm": "1833409182",
|
||||
"regTm2": "0",
|
||||
"regTo": "Eli Bosley",
|
||||
"regTy": "PRO",
|
||||
"reservedNames": "parity,parity2,parity3,diskP,diskQ,diskR,disk,disks,flash,boot,user,user0,disk0,disk1,disk2,disk3,disk4,disk5,disk6,disk7,disk8,disk9,disk10,disk11,disk12,disk13,disk14,disk15,disk16,disk17,disk18,disk19,disk20,disk21,disk22,disk23,disk24,disk25,disk26,disk27,disk28,disk29,disk30,disk31",
|
||||
"safeMode": false,
|
||||
"sbClean": true,
|
||||
"sbEvents": 173,
|
||||
"sbName": "/boot/config/super.dat",
|
||||
"sbNumDisks": 5,
|
||||
"sbState": "1",
|
||||
"sbSyncErrs": 0,
|
||||
"sbSyncExit": "0",
|
||||
"sbSynced": 1586819259,
|
||||
"sbSynced2": 1586822456,
|
||||
"sbUpdated": "1596079143",
|
||||
"sbVersion": "2.9.13",
|
||||
"security": "user",
|
||||
"shareAvahiEnabled": true,
|
||||
"shareAvahiSmbModel": "Xserve",
|
||||
"shareAvahiSmbName": "%h",
|
||||
"shareCacheEnabled": true,
|
||||
"shareCacheFloor": "2000000",
|
||||
"shareCount": 0,
|
||||
"shareDisk": "yes",
|
||||
"shareInitialGroup": "Domain Users",
|
||||
"shareInitialOwner": "Administrator",
|
||||
"shareMoverActive": false,
|
||||
"shareMoverLogging": false,
|
||||
"shareMoverSchedule": "40 3 * * *",
|
||||
"shareNfsCount": 0,
|
||||
"shareNfsEnabled": false,
|
||||
"shareSmbCount": 1,
|
||||
"shareSmbEnabled": true,
|
||||
"shareSmbMode": "workgroup",
|
||||
"shareUser": "e",
|
||||
"shareUserExclude": "",
|
||||
"shareUserInclude": "",
|
||||
"shfsLogging": "1",
|
||||
"shutdownTimeout": 90,
|
||||
"spindownDelay": 0,
|
||||
"spinupGroups": false,
|
||||
"startArray": false,
|
||||
"startMode": "Normal",
|
||||
"startPage": "Main",
|
||||
"sysArraySlots": 24,
|
||||
"sysCacheSlots": NaN,
|
||||
"sysFlashSlots": 1,
|
||||
"sysModel": "Dell R710",
|
||||
"timeZone": "Australia/Adelaide",
|
||||
"useNetbios": "yes",
|
||||
"useNtp": true,
|
||||
"useSsh": true,
|
||||
"useSsl": null,
|
||||
"useTelnet": true,
|
||||
"useUpnp": true,
|
||||
"useWsd": "no",
|
||||
"version": "6.11.2",
|
||||
"workgroup": "WORKGROUP",
|
||||
"wsdOpt": "",
|
||||
}
|
||||
`);
|
||||
{
|
||||
"bindMgt": false,
|
||||
"cacheNumDevices": NaN,
|
||||
"cacheSbNumDisks": NaN,
|
||||
"comment": "Dev Server",
|
||||
"configErrorState": "INELIGIBLE",
|
||||
"configValid": false,
|
||||
"csrfToken": "0000000000000000",
|
||||
"defaultFsType": "xfs",
|
||||
"deviceCount": 4,
|
||||
"domain": "",
|
||||
"domainLogin": "Administrator",
|
||||
"domainShort": "",
|
||||
"enableFruit": "no",
|
||||
"flashGuid": "0000-0000-0000-000000000000",
|
||||
"flashProduct": "DataTraveler_3.0",
|
||||
"flashVendor": "KINGSTON",
|
||||
"fsCopyPrcnt": 0,
|
||||
"fsNumMounted": 0,
|
||||
"fsNumUnmountable": 0,
|
||||
"fsProgress": "Autostart disabled",
|
||||
"fsState": "Stopped",
|
||||
"fsUnmountableMask": "",
|
||||
"fuseDirectio": "auto",
|
||||
"fuseDirectioDefault": "auto",
|
||||
"fuseDirectioStatus": "default",
|
||||
"fuseRemember": "330",
|
||||
"fuseRememberDefault": "330",
|
||||
"fuseRememberStatus": "default",
|
||||
"fuseUseino": "yes",
|
||||
"hideDotFiles": false,
|
||||
"joinStatus": "Not joined",
|
||||
"localMaster": true,
|
||||
"localTld": "local",
|
||||
"luksKeyfile": "/tmp/unraid/keyfile",
|
||||
"maxArraysz": 30,
|
||||
"maxCachesz": 30,
|
||||
"mdColor": "green-blink",
|
||||
"mdNumDisabled": 1,
|
||||
"mdNumDisks": 4,
|
||||
"mdNumErased": 0,
|
||||
"mdNumInvalid": 1,
|
||||
"mdNumMissing": 0,
|
||||
"mdNumNew": 0,
|
||||
"mdNumStripes": 1280,
|
||||
"mdNumStripesDefault": 1280,
|
||||
"mdNumStripesStatus": "default",
|
||||
"mdQueueLimit": "80",
|
||||
"mdQueueLimitDefault": "80",
|
||||
"mdQueueLimitStatus": "default",
|
||||
"mdResync": 0,
|
||||
"mdResyncAction": "check P",
|
||||
"mdResyncCorr": "0",
|
||||
"mdResyncDb": "0",
|
||||
"mdResyncDt": "0",
|
||||
"mdResyncPos": 0,
|
||||
"mdResyncSize": 438960096,
|
||||
"mdScheduler": "auto",
|
||||
"mdSchedulerDefault": "auto",
|
||||
"mdSchedulerStatus": "default",
|
||||
"mdState": "STOPPED",
|
||||
"mdSyncLimit": "5",
|
||||
"mdSyncLimitDefault": "5",
|
||||
"mdSyncLimitStatus": "default",
|
||||
"mdSyncThresh": NaN,
|
||||
"mdSyncThreshDefault": NaN,
|
||||
"mdSyncWindow": NaN,
|
||||
"mdSyncWindowDefault": NaN,
|
||||
"mdVersion": "2.9.14",
|
||||
"mdWriteMethod": NaN,
|
||||
"mdWriteMethodDefault": "auto",
|
||||
"mdWriteMethodStatus": "default",
|
||||
"name": "Tower",
|
||||
"nrRequests": NaN,
|
||||
"nrRequestsDefault": NaN,
|
||||
"nrRequestsStatus": "default",
|
||||
"ntpServer1": "time1.google.com",
|
||||
"ntpServer2": "time2.google.com",
|
||||
"ntpServer3": "time3.google.com",
|
||||
"ntpServer4": "time4.google.com",
|
||||
"pollAttributes": "1800",
|
||||
"pollAttributesDefault": "1800",
|
||||
"pollAttributesStatus": "default",
|
||||
"port": 80,
|
||||
"portssh": 22,
|
||||
"portssl": 443,
|
||||
"porttelnet": 23,
|
||||
"queueDepth": "auto",
|
||||
"regCheck": "Valid",
|
||||
"regExp": "",
|
||||
"regFile": "/app/dev/Unraid.net/Pro.key",
|
||||
"regGen": "0",
|
||||
"regGuid": "13FE-4200-C300-58C372A52B19",
|
||||
"regState": "PRO",
|
||||
"regTm": "1833409182",
|
||||
"regTm2": "0",
|
||||
"regTo": "Eli Bosley",
|
||||
"regTy": "PRO",
|
||||
"reservedNames": "parity,parity2,parity3,diskP,diskQ,diskR,disk,disks,flash,boot,user,user0,disk0,disk1,disk2,disk3,disk4,disk5,disk6,disk7,disk8,disk9,disk10,disk11,disk12,disk13,disk14,disk15,disk16,disk17,disk18,disk19,disk20,disk21,disk22,disk23,disk24,disk25,disk26,disk27,disk28,disk29,disk30,disk31",
|
||||
"safeMode": false,
|
||||
"sbClean": true,
|
||||
"sbEvents": 173,
|
||||
"sbName": "/boot/config/super.dat",
|
||||
"sbNumDisks": 5,
|
||||
"sbState": "1",
|
||||
"sbSyncErrs": 0,
|
||||
"sbSyncExit": "0",
|
||||
"sbSynced": 1586819259,
|
||||
"sbSynced2": 1586822456,
|
||||
"sbUpdated": "1596079143",
|
||||
"sbVersion": "2.9.13",
|
||||
"security": "user",
|
||||
"shareAvahiEnabled": true,
|
||||
"shareAvahiSmbModel": "Xserve",
|
||||
"shareAvahiSmbName": "%h",
|
||||
"shareCacheEnabled": true,
|
||||
"shareCacheFloor": "2000000",
|
||||
"shareCount": 0,
|
||||
"shareDisk": "yes",
|
||||
"shareInitialGroup": "Domain Users",
|
||||
"shareInitialOwner": "Administrator",
|
||||
"shareMoverActive": false,
|
||||
"shareMoverLogging": false,
|
||||
"shareMoverSchedule": "40 3 * * *",
|
||||
"shareNfsCount": 0,
|
||||
"shareNfsEnabled": false,
|
||||
"shareSmbCount": 1,
|
||||
"shareSmbEnabled": true,
|
||||
"shareSmbMode": "workgroup",
|
||||
"shareUser": "e",
|
||||
"shareUserExclude": "",
|
||||
"shareUserInclude": "",
|
||||
"shfsLogging": "1",
|
||||
"shutdownTimeout": 90,
|
||||
"spindownDelay": 0,
|
||||
"spinupGroups": false,
|
||||
"startArray": false,
|
||||
"startMode": "Normal",
|
||||
"startPage": "Main",
|
||||
"sysArraySlots": 24,
|
||||
"sysCacheSlots": NaN,
|
||||
"sysFlashSlots": 1,
|
||||
"sysModel": "Dell R710",
|
||||
"timeZone": "Australia/Adelaide",
|
||||
"useNetbios": "yes",
|
||||
"useNtp": true,
|
||||
"useSsh": true,
|
||||
"useSsl": null,
|
||||
"useTelnet": true,
|
||||
"useUpnp": true,
|
||||
"useWsd": "no",
|
||||
"version": "6.11.2",
|
||||
"workgroup": "WORKGROUP",
|
||||
"wsdOpt": "",
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { expect, test } from 'vitest';
|
||||
|
||||
import { store } from '@app/store';
|
||||
import { store } from '@app/store/index.js';
|
||||
|
||||
test('Returns paths', async () => {
|
||||
const { paths } = store.getState();
|
||||
@@ -25,6 +25,7 @@ test('Returns paths', async () => {
|
||||
"keyfile-base",
|
||||
"machine-id",
|
||||
"log-base",
|
||||
"unraid-log-base",
|
||||
"var-run",
|
||||
"auth-sessions",
|
||||
"auth-keys",
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { expect, test } from 'vitest';
|
||||
|
||||
import { store } from '@app/store';
|
||||
import { loadRegistrationKey } from '@app/store/modules/registration';
|
||||
import { FileLoadStatus, StateFileKey } from '@app/store/types';
|
||||
import { store } from '@app/store/index.js';
|
||||
import { loadRegistrationKey } from '@app/store/modules/registration.js';
|
||||
import { FileLoadStatus, StateFileKey } from '@app/store/types.js';
|
||||
|
||||
// Preloading imports for faster tests
|
||||
|
||||
@@ -24,8 +24,8 @@ test('Requires emhttp to be loaded to find key file', async () => {
|
||||
});
|
||||
|
||||
test('Returns empty key if key location is empty', async () => {
|
||||
const { updateEmhttpState } = await import('@app/store/modules/emhttp');
|
||||
const { loadRegistrationKey } = await import('@app/store/modules/registration');
|
||||
const { updateEmhttpState } = await import('@app/store/modules/emhttp.js');
|
||||
const { loadRegistrationKey } = await import('@app/store/modules/registration.js');
|
||||
|
||||
// Set key file location as empty
|
||||
// This should only happen if the user doesn't have a key file
|
||||
@@ -46,21 +46,3 @@ test('Returns empty key if key location is empty', async () => {
|
||||
expect(status).toBe(FileLoadStatus.LOADED);
|
||||
expect(keyFile).toBe('');
|
||||
});
|
||||
|
||||
test('Returns decoded key file if key location exists', async () => {
|
||||
const { loadRegistrationKey } = await import('@app/store/modules/registration');
|
||||
const { loadStateFiles } = await import('@app/store/modules/emhttp');
|
||||
|
||||
// Load state files into store
|
||||
await store.dispatch(loadStateFiles());
|
||||
|
||||
// Load registration key into store
|
||||
await store.dispatch(loadRegistrationKey());
|
||||
|
||||
// Check if store has state files loaded
|
||||
const { status, keyFile } = store.getState().registration;
|
||||
expect(status).toBe(FileLoadStatus.LOADED);
|
||||
expect(keyFile).toMatchInlineSnapshot(
|
||||
'"hVs1tLjvC9FiiQsIwIQ7G1KszAcexf0IneThhnmf22SB0dGs5WzRkqMiSMmt2DtR5HOXFUD32YyxuzGeUXmky3zKpSu6xhZNKVg5atGM1OfvkzHBMldI3SeBLuUFSgejLbpNUMdTrbk64JJdbzle4O8wiQgkIpAMIGxeYLwLBD4zHBcfyzq40QnxG--HcX6j25eE0xqa2zWj-j0b0rCAXahJV2a3ySCbPzr1MvfPRTVb0rr7KJ-25R592hYrz4H7Sc1B3p0lr6QUxHE6o7bcYrWKDRtIVoZ8SMPpd1_0gzYIcl5GsDFzFumTXUh8NEnl0Q8hwW1YE-tRc6Y_rrvd7w"'
|
||||
);
|
||||
});
|
||||
|
||||
@@ -2,12 +2,12 @@ import { join } from 'path';
|
||||
|
||||
import { expect, test } from 'vitest';
|
||||
|
||||
import type { DevicesIni } from '@app/store/state-parsers/devices';
|
||||
import { store } from '@app/store';
|
||||
import type { DevicesIni } from '@app/store/state-parsers/devices.js';
|
||||
import { store } from '@app/store/index.js';
|
||||
|
||||
test('Returns parsed state file', async () => {
|
||||
const { parse } = await import('@app/store/state-parsers/devices');
|
||||
const { parseConfig } = await import('@app/core/utils/misc/parse-config');
|
||||
const { parse } = await import('@app/store/state-parsers/devices.js');
|
||||
const { parseConfig } = await import('@app/core/utils/misc/parse-config.js');
|
||||
const { paths } = store.getState();
|
||||
const filePath = join(paths.states, 'devs.ini');
|
||||
const stateFile = parseConfig<DevicesIni>({
|
||||
|
||||
@@ -2,12 +2,12 @@ import { join } from 'path';
|
||||
|
||||
import { expect, test } from 'vitest';
|
||||
|
||||
import type { NetworkIni } from '@app/store/state-parsers/network';
|
||||
import { store } from '@app/store';
|
||||
import type { NetworkIni } from '@app/store/state-parsers/network.js';
|
||||
import { store } from '@app/store/index.js';
|
||||
|
||||
test('Returns parsed state file', async () => {
|
||||
const { parse } = await import('@app/store/state-parsers/network');
|
||||
const { parseConfig } = await import('@app/core/utils/misc/parse-config');
|
||||
const { parse } = await import('@app/store/state-parsers/network.js');
|
||||
const { parseConfig } = await import('@app/core/utils/misc/parse-config.js');
|
||||
const { paths } = store.getState();
|
||||
const filePath = join(paths.states, 'network.ini');
|
||||
const stateFile = parseConfig<NetworkIni>({
|
||||
|
||||
@@ -2,12 +2,12 @@ import { join } from 'path';
|
||||
|
||||
import { expect, test } from 'vitest';
|
||||
|
||||
import type { NfsSharesIni } from '@app/store/state-parsers/nfs';
|
||||
import { store } from '@app/store';
|
||||
import type { NfsSharesIni } from '@app/store/state-parsers/nfs.js';
|
||||
import { store } from '@app/store/index.js';
|
||||
|
||||
test('Returns parsed state file', async () => {
|
||||
const { parse } = await import('@app/store/state-parsers/nfs');
|
||||
const { parseConfig } = await import('@app/core/utils/misc/parse-config');
|
||||
const { parse } = await import('@app/store/state-parsers/nfs.js');
|
||||
const { parseConfig } = await import('@app/core/utils/misc/parse-config.js');
|
||||
const { paths } = store.getState();
|
||||
const filePath = join(paths.states, 'sec_nfs.ini');
|
||||
const stateFile = parseConfig<NfsSharesIni>({
|
||||
|
||||
@@ -2,12 +2,12 @@ import { join } from 'path';
|
||||
|
||||
import { expect, test } from 'vitest';
|
||||
|
||||
import type { NginxIni } from '@app/store/state-parsers/nginx';
|
||||
import { store } from '@app/store';
|
||||
import type { NginxIni } from '@app/store/state-parsers/nginx.js';
|
||||
import { store } from '@app/store/index.js';
|
||||
|
||||
test('Returns parsed state file', async () => {
|
||||
const { parse } = await import('@app/store/state-parsers/nginx');
|
||||
const { parseConfig } = await import('@app/core/utils/misc/parse-config');
|
||||
const { parse } = await import('@app/store/state-parsers/nginx.js');
|
||||
const { parseConfig } = await import('@app/core/utils/misc/parse-config.js');
|
||||
const { paths } = store.getState();
|
||||
const filePath = join(paths.states, 'nginx.ini');
|
||||
const stateFile = parseConfig<NginxIni>({
|
||||
|
||||
@@ -2,12 +2,12 @@ import { join } from 'path';
|
||||
|
||||
import { expect, test } from 'vitest';
|
||||
|
||||
import type { SharesIni } from '@app/store/state-parsers/shares';
|
||||
import { store } from '@app/store';
|
||||
import type { SharesIni } from '@app/store/state-parsers/shares.js';
|
||||
import { store } from '@app/store/index.js';
|
||||
|
||||
test('Returns parsed state file', async () => {
|
||||
const { parse } = await import('@app/store/state-parsers/shares');
|
||||
const { parseConfig } = await import('@app/core/utils/misc/parse-config');
|
||||
const { parse } = await import('@app/store/state-parsers/shares.js');
|
||||
const { parseConfig } = await import('@app/core/utils/misc/parse-config.js');
|
||||
const { paths } = store.getState();
|
||||
const filePath = join(paths.states, 'shares.ini');
|
||||
const stateFile = parseConfig<SharesIni>({
|
||||
|
||||
@@ -2,12 +2,12 @@ import { join } from 'path';
|
||||
|
||||
import { expect, test } from 'vitest';
|
||||
|
||||
import type { SlotsIni } from '@app/store/state-parsers/slots';
|
||||
import { store } from '@app/store';
|
||||
import type { SlotsIni } from '@app/store/state-parsers/slots.js';
|
||||
import { store } from '@app/store/index.js';
|
||||
|
||||
test('Returns parsed state file', async () => {
|
||||
const { parse } = await import('@app/store/state-parsers/slots');
|
||||
const { parseConfig } = await import('@app/core/utils/misc/parse-config');
|
||||
const { parse } = await import('@app/store/state-parsers/slots.js');
|
||||
const { parseConfig } = await import('@app/core/utils/misc/parse-config.js');
|
||||
const { paths } = store.getState();
|
||||
const filePath = join(paths.states, 'disks.ini');
|
||||
const stateFile = parseConfig<SlotsIni>({
|
||||
|
||||
@@ -2,12 +2,12 @@ import { join } from 'path';
|
||||
|
||||
import { expect, test } from 'vitest';
|
||||
|
||||
import type { SmbIni } from '@app/store/state-parsers/smb';
|
||||
import { store } from '@app/store';
|
||||
import type { SmbIni } from '@app/store/state-parsers/smb.js';
|
||||
import { store } from '@app/store/index.js';
|
||||
|
||||
test('Returns parsed state file', async () => {
|
||||
const { parse } = await import('@app/store/state-parsers/smb');
|
||||
const { parseConfig } = await import('@app/core/utils/misc/parse-config');
|
||||
const { parse } = await import('@app/store/state-parsers/smb.js');
|
||||
const { parseConfig } = await import('@app/core/utils/misc/parse-config.js');
|
||||
const { paths } = store.getState();
|
||||
const filePath = join(paths.states, 'sec.ini');
|
||||
const stateFile = parseConfig<SmbIni>({
|
||||
|
||||
@@ -2,12 +2,12 @@ import { join } from 'path';
|
||||
|
||||
import { expect, test } from 'vitest';
|
||||
|
||||
import type { UsersIni } from '@app/store/state-parsers/users';
|
||||
import { store } from '@app/store';
|
||||
import type { UsersIni } from '@app/store/state-parsers/users.js';
|
||||
import { store } from '@app/store/index.js';
|
||||
|
||||
test('Returns parsed state file', async () => {
|
||||
const { parse } = await import('@app/store/state-parsers/users');
|
||||
const { parseConfig } = await import('@app/core/utils/misc/parse-config');
|
||||
const { parse } = await import('@app/store/state-parsers/users.js');
|
||||
const { parseConfig } = await import('@app/core/utils/misc/parse-config.js');
|
||||
const { paths } = store.getState();
|
||||
const filePath = join(paths.states, 'users.ini');
|
||||
const stateFile = parseConfig<UsersIni>({
|
||||
|
||||
@@ -2,12 +2,12 @@ import { join } from 'path';
|
||||
|
||||
import { expect, test } from 'vitest';
|
||||
|
||||
import type { VarIni } from '@app/store/state-parsers/var';
|
||||
import { store } from '@app/store';
|
||||
import type { VarIni } from '@app/store/state-parsers/var.js';
|
||||
import { store } from '@app/store/index.js';
|
||||
|
||||
test('Returns parsed state file', async () => {
|
||||
const { parse } = await import('@app/store/state-parsers/var');
|
||||
const { parseConfig } = await import('@app/core/utils/misc/parse-config');
|
||||
const { parse } = await import('@app/store/state-parsers/var.js');
|
||||
const { parseConfig } = await import('@app/core/utils/misc/parse-config.js');
|
||||
const { paths } = store.getState();
|
||||
const filePath = join(paths.states, 'var.ini');
|
||||
const stateFile = parseConfig<VarIni>({
|
||||
@@ -16,160 +16,160 @@ test('Returns parsed state file', async () => {
|
||||
});
|
||||
|
||||
expect(parse(stateFile)).toMatchInlineSnapshot(`
|
||||
{
|
||||
"bindMgt": false,
|
||||
"cacheNumDevices": NaN,
|
||||
"cacheSbNumDisks": NaN,
|
||||
"comment": "Dev Server",
|
||||
"configState": "yes",
|
||||
"configValid": true,
|
||||
"csrfToken": "0000000000000000",
|
||||
"defaultFsType": "xfs",
|
||||
"deviceCount": 4,
|
||||
"domain": "",
|
||||
"domainLogin": "Administrator",
|
||||
"domainShort": "",
|
||||
"enableFruit": "no",
|
||||
"flashGuid": "0000-0000-0000-000000000000",
|
||||
"flashProduct": "DataTraveler_3.0",
|
||||
"flashVendor": "KINGSTON",
|
||||
"fsCopyPrcnt": 0,
|
||||
"fsNumMounted": 0,
|
||||
"fsNumUnmountable": 0,
|
||||
"fsProgress": "Autostart disabled",
|
||||
"fsState": "Stopped",
|
||||
"fsUnmountableMask": "",
|
||||
"fuseDirectio": "auto",
|
||||
"fuseDirectioDefault": "auto",
|
||||
"fuseDirectioStatus": "default",
|
||||
"fuseRemember": "330",
|
||||
"fuseRememberDefault": "330",
|
||||
"fuseRememberStatus": "default",
|
||||
"fuseUseino": "yes",
|
||||
"hideDotFiles": false,
|
||||
"joinStatus": "Not joined",
|
||||
"localMaster": true,
|
||||
"localTld": "local",
|
||||
"luksKeyfile": "/tmp/unraid/keyfile",
|
||||
"maxArraysz": 30,
|
||||
"maxCachesz": 30,
|
||||
"mdColor": "green-blink",
|
||||
"mdNumDisabled": 1,
|
||||
"mdNumDisks": 4,
|
||||
"mdNumErased": 0,
|
||||
"mdNumInvalid": 1,
|
||||
"mdNumMissing": 0,
|
||||
"mdNumNew": 0,
|
||||
"mdNumStripes": 1280,
|
||||
"mdNumStripesDefault": 1280,
|
||||
"mdNumStripesStatus": "default",
|
||||
"mdQueueLimit": "80",
|
||||
"mdQueueLimitDefault": "80",
|
||||
"mdQueueLimitStatus": "default",
|
||||
"mdResync": 0,
|
||||
"mdResyncAction": "check P",
|
||||
"mdResyncCorr": "0",
|
||||
"mdResyncDb": "0",
|
||||
"mdResyncDt": "0",
|
||||
"mdResyncPos": 0,
|
||||
"mdResyncSize": 438960096,
|
||||
"mdScheduler": "auto",
|
||||
"mdSchedulerDefault": "auto",
|
||||
"mdSchedulerStatus": "default",
|
||||
"mdState": "STOPPED",
|
||||
"mdSyncLimit": "5",
|
||||
"mdSyncLimitDefault": "5",
|
||||
"mdSyncLimitStatus": "default",
|
||||
"mdSyncThresh": NaN,
|
||||
"mdSyncThreshDefault": NaN,
|
||||
"mdSyncWindow": NaN,
|
||||
"mdSyncWindowDefault": NaN,
|
||||
"mdVersion": "2.9.14",
|
||||
"mdWriteMethod": NaN,
|
||||
"mdWriteMethodDefault": "auto",
|
||||
"mdWriteMethodStatus": "default",
|
||||
"name": "Tower",
|
||||
"nrRequests": NaN,
|
||||
"nrRequestsDefault": NaN,
|
||||
"nrRequestsStatus": "default",
|
||||
"ntpServer1": "time1.google.com",
|
||||
"ntpServer2": "time2.google.com",
|
||||
"ntpServer3": "time3.google.com",
|
||||
"ntpServer4": "time4.google.com",
|
||||
"pollAttributes": "1800",
|
||||
"pollAttributesDefault": "1800",
|
||||
"pollAttributesStatus": "default",
|
||||
"port": 80,
|
||||
"portssh": 22,
|
||||
"portssl": 443,
|
||||
"porttelnet": 23,
|
||||
"queueDepth": "auto",
|
||||
"regCheck": "Valid",
|
||||
"regExp": "",
|
||||
"regFile": "/app/dev/Unraid.net/Pro.key",
|
||||
"regGen": "0",
|
||||
"regGuid": "13FE-4200-C300-58C372A52B19",
|
||||
"regState": "PRO",
|
||||
"regTm": "1833409182",
|
||||
"regTm2": "0",
|
||||
"regTo": "Eli Bosley",
|
||||
"regTy": "PRO",
|
||||
"reservedNames": "parity,parity2,parity3,diskP,diskQ,diskR,disk,disks,flash,boot,user,user0,disk0,disk1,disk2,disk3,disk4,disk5,disk6,disk7,disk8,disk9,disk10,disk11,disk12,disk13,disk14,disk15,disk16,disk17,disk18,disk19,disk20,disk21,disk22,disk23,disk24,disk25,disk26,disk27,disk28,disk29,disk30,disk31",
|
||||
"safeMode": false,
|
||||
"sbClean": true,
|
||||
"sbEvents": 173,
|
||||
"sbName": "/boot/config/super.dat",
|
||||
"sbNumDisks": 5,
|
||||
"sbState": "1",
|
||||
"sbSyncErrs": 0,
|
||||
"sbSyncExit": "0",
|
||||
"sbSynced": 1586819259,
|
||||
"sbSynced2": 1586822456,
|
||||
"sbUpdated": "1596079143",
|
||||
"sbVersion": "2.9.13",
|
||||
"security": "user",
|
||||
"shareAvahiEnabled": true,
|
||||
"shareAvahiSmbModel": "Xserve",
|
||||
"shareAvahiSmbName": "%h",
|
||||
"shareCacheEnabled": true,
|
||||
"shareCacheFloor": "2000000",
|
||||
"shareCount": 0,
|
||||
"shareDisk": "yes",
|
||||
"shareInitialGroup": "Domain Users",
|
||||
"shareInitialOwner": "Administrator",
|
||||
"shareMoverActive": false,
|
||||
"shareMoverLogging": false,
|
||||
"shareMoverSchedule": "40 3 * * *",
|
||||
"shareNfsCount": 0,
|
||||
"shareNfsEnabled": false,
|
||||
"shareSmbCount": 1,
|
||||
"shareSmbEnabled": true,
|
||||
"shareSmbMode": "workgroup",
|
||||
"shareUser": "e",
|
||||
"shareUserExclude": "",
|
||||
"shareUserInclude": "",
|
||||
"shfsLogging": "1",
|
||||
"shutdownTimeout": 90,
|
||||
"spindownDelay": 0,
|
||||
"spinupGroups": false,
|
||||
"startArray": false,
|
||||
"startMode": "Normal",
|
||||
"startPage": "Main",
|
||||
"sysArraySlots": 24,
|
||||
"sysCacheSlots": NaN,
|
||||
"sysFlashSlots": 1,
|
||||
"sysModel": "Dell R710",
|
||||
"timeZone": "Australia/Adelaide",
|
||||
"useNetbios": "yes",
|
||||
"useNtp": true,
|
||||
"useSsh": true,
|
||||
"useSsl": null,
|
||||
"useTelnet": true,
|
||||
"useUpnp": true,
|
||||
"useWsd": "no",
|
||||
"version": "6.11.2",
|
||||
"workgroup": "WORKGROUP",
|
||||
"wsdOpt": "",
|
||||
}
|
||||
`);
|
||||
{
|
||||
"bindMgt": false,
|
||||
"cacheNumDevices": NaN,
|
||||
"cacheSbNumDisks": NaN,
|
||||
"comment": "Dev Server",
|
||||
"configErrorState": "INELIGIBLE",
|
||||
"configValid": false,
|
||||
"csrfToken": "0000000000000000",
|
||||
"defaultFsType": "xfs",
|
||||
"deviceCount": 4,
|
||||
"domain": "",
|
||||
"domainLogin": "Administrator",
|
||||
"domainShort": "",
|
||||
"enableFruit": "no",
|
||||
"flashGuid": "0000-0000-0000-000000000000",
|
||||
"flashProduct": "DataTraveler_3.0",
|
||||
"flashVendor": "KINGSTON",
|
||||
"fsCopyPrcnt": 0,
|
||||
"fsNumMounted": 0,
|
||||
"fsNumUnmountable": 0,
|
||||
"fsProgress": "Autostart disabled",
|
||||
"fsState": "Stopped",
|
||||
"fsUnmountableMask": "",
|
||||
"fuseDirectio": "auto",
|
||||
"fuseDirectioDefault": "auto",
|
||||
"fuseDirectioStatus": "default",
|
||||
"fuseRemember": "330",
|
||||
"fuseRememberDefault": "330",
|
||||
"fuseRememberStatus": "default",
|
||||
"fuseUseino": "yes",
|
||||
"hideDotFiles": false,
|
||||
"joinStatus": "Not joined",
|
||||
"localMaster": true,
|
||||
"localTld": "local",
|
||||
"luksKeyfile": "/tmp/unraid/keyfile",
|
||||
"maxArraysz": 30,
|
||||
"maxCachesz": 30,
|
||||
"mdColor": "green-blink",
|
||||
"mdNumDisabled": 1,
|
||||
"mdNumDisks": 4,
|
||||
"mdNumErased": 0,
|
||||
"mdNumInvalid": 1,
|
||||
"mdNumMissing": 0,
|
||||
"mdNumNew": 0,
|
||||
"mdNumStripes": 1280,
|
||||
"mdNumStripesDefault": 1280,
|
||||
"mdNumStripesStatus": "default",
|
||||
"mdQueueLimit": "80",
|
||||
"mdQueueLimitDefault": "80",
|
||||
"mdQueueLimitStatus": "default",
|
||||
"mdResync": 0,
|
||||
"mdResyncAction": "check P",
|
||||
"mdResyncCorr": "0",
|
||||
"mdResyncDb": "0",
|
||||
"mdResyncDt": "0",
|
||||
"mdResyncPos": 0,
|
||||
"mdResyncSize": 438960096,
|
||||
"mdScheduler": "auto",
|
||||
"mdSchedulerDefault": "auto",
|
||||
"mdSchedulerStatus": "default",
|
||||
"mdState": "STOPPED",
|
||||
"mdSyncLimit": "5",
|
||||
"mdSyncLimitDefault": "5",
|
||||
"mdSyncLimitStatus": "default",
|
||||
"mdSyncThresh": NaN,
|
||||
"mdSyncThreshDefault": NaN,
|
||||
"mdSyncWindow": NaN,
|
||||
"mdSyncWindowDefault": NaN,
|
||||
"mdVersion": "2.9.14",
|
||||
"mdWriteMethod": NaN,
|
||||
"mdWriteMethodDefault": "auto",
|
||||
"mdWriteMethodStatus": "default",
|
||||
"name": "Tower",
|
||||
"nrRequests": NaN,
|
||||
"nrRequestsDefault": NaN,
|
||||
"nrRequestsStatus": "default",
|
||||
"ntpServer1": "time1.google.com",
|
||||
"ntpServer2": "time2.google.com",
|
||||
"ntpServer3": "time3.google.com",
|
||||
"ntpServer4": "time4.google.com",
|
||||
"pollAttributes": "1800",
|
||||
"pollAttributesDefault": "1800",
|
||||
"pollAttributesStatus": "default",
|
||||
"port": 80,
|
||||
"portssh": 22,
|
||||
"portssl": 443,
|
||||
"porttelnet": 23,
|
||||
"queueDepth": "auto",
|
||||
"regCheck": "Valid",
|
||||
"regExp": "",
|
||||
"regFile": "/app/dev/Unraid.net/Pro.key",
|
||||
"regGen": "0",
|
||||
"regGuid": "13FE-4200-C300-58C372A52B19",
|
||||
"regState": "PRO",
|
||||
"regTm": "1833409182",
|
||||
"regTm2": "0",
|
||||
"regTo": "Eli Bosley",
|
||||
"regTy": "PRO",
|
||||
"reservedNames": "parity,parity2,parity3,diskP,diskQ,diskR,disk,disks,flash,boot,user,user0,disk0,disk1,disk2,disk3,disk4,disk5,disk6,disk7,disk8,disk9,disk10,disk11,disk12,disk13,disk14,disk15,disk16,disk17,disk18,disk19,disk20,disk21,disk22,disk23,disk24,disk25,disk26,disk27,disk28,disk29,disk30,disk31",
|
||||
"safeMode": false,
|
||||
"sbClean": true,
|
||||
"sbEvents": 173,
|
||||
"sbName": "/boot/config/super.dat",
|
||||
"sbNumDisks": 5,
|
||||
"sbState": "1",
|
||||
"sbSyncErrs": 0,
|
||||
"sbSyncExit": "0",
|
||||
"sbSynced": 1586819259,
|
||||
"sbSynced2": 1586822456,
|
||||
"sbUpdated": "1596079143",
|
||||
"sbVersion": "2.9.13",
|
||||
"security": "user",
|
||||
"shareAvahiEnabled": true,
|
||||
"shareAvahiSmbModel": "Xserve",
|
||||
"shareAvahiSmbName": "%h",
|
||||
"shareCacheEnabled": true,
|
||||
"shareCacheFloor": "2000000",
|
||||
"shareCount": 0,
|
||||
"shareDisk": "yes",
|
||||
"shareInitialGroup": "Domain Users",
|
||||
"shareInitialOwner": "Administrator",
|
||||
"shareMoverActive": false,
|
||||
"shareMoverLogging": false,
|
||||
"shareMoverSchedule": "40 3 * * *",
|
||||
"shareNfsCount": 0,
|
||||
"shareNfsEnabled": false,
|
||||
"shareSmbCount": 1,
|
||||
"shareSmbEnabled": true,
|
||||
"shareSmbMode": "workgroup",
|
||||
"shareUser": "e",
|
||||
"shareUserExclude": "",
|
||||
"shareUserInclude": "",
|
||||
"shfsLogging": "1",
|
||||
"shutdownTimeout": 90,
|
||||
"spindownDelay": 0,
|
||||
"spinupGroups": false,
|
||||
"startArray": false,
|
||||
"startMode": "Normal",
|
||||
"startPage": "Main",
|
||||
"sysArraySlots": 24,
|
||||
"sysCacheSlots": NaN,
|
||||
"sysFlashSlots": 1,
|
||||
"sysModel": "Dell R710",
|
||||
"timeZone": "Australia/Adelaide",
|
||||
"useNetbios": "yes",
|
||||
"useNtp": true,
|
||||
"useSsh": true,
|
||||
"useSsl": null,
|
||||
"useTelnet": true,
|
||||
"useUpnp": true,
|
||||
"useWsd": "no",
|
||||
"version": "6.11.2",
|
||||
"workgroup": "WORKGROUP",
|
||||
"wsdOpt": "",
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
@@ -1,16 +1,20 @@
|
||||
import { expect, test, vi } from 'vitest';
|
||||
|
||||
import { store } from '@app/store/index.js';
|
||||
import { loadStateFiles } from '@app/store/modules/emhttp.js';
|
||||
import { loadRegistrationKey } from '@app/store/modules/registration.js';
|
||||
import { createRegistrationEvent } from '@app/store/sync/registration-sync.js';
|
||||
|
||||
vi.mock('@app/core/pubsub', () => ({
|
||||
pubsub: { publish: vi.fn() },
|
||||
}));
|
||||
|
||||
test('Creates a registration event', async () => {
|
||||
const { createRegistrationEvent } = await import('@app/store/sync/registration-sync');
|
||||
const { store } = await import('@app/store');
|
||||
const { loadStateFiles } = await import('@app/store/modules/emhttp');
|
||||
|
||||
// Load state files into store
|
||||
await store.dispatch(loadStateFiles());
|
||||
|
||||
const config = await store.dispatch(loadStateFiles()).unwrap();
|
||||
await store.dispatch(loadRegistrationKey());
|
||||
expect(config.var.regFile).toBe('/app/dev/Unraid.net/Pro.key');
|
||||
|
||||
const state = store.getState();
|
||||
const registrationEvent = createRegistrationEvent(state);
|
||||
@@ -19,7 +23,7 @@ test('Creates a registration event', async () => {
|
||||
"registration": {
|
||||
"guid": "13FE-4200-C300-58C372A52B19",
|
||||
"keyFile": {
|
||||
"contents": null,
|
||||
"contents": "hVs1tLjvC9FiiQsIwIQ7G1KszAcexf0IneThhnmf22SB0dGs5WzRkqMiSMmt2DtR5HOXFUD32YyxuzGeUXmky3zKpSu6xhZNKVg5atGM1OfvkzHBMldI3SeBLuUFSgejLbpNUMdTrbk64JJdbzle4O8wiQgkIpAMIGxeYLwLBD4zHBcfyzq40QnxG--HcX6j25eE0xqa2zWj-j0b0rCAXahJV2a3ySCbPzr1MvfPRTVb0rr7KJ-25R592hYrz4H7Sc1B3p0lr6QUxHE6o7bcYrWKDRtIVoZ8SMPpd1_0gzYIcl5GsDFzFumTXUh8NEnl0Q8hwW1YE-tRc6Y_rrvd7w",
|
||||
"location": "/app/dev/Unraid.net/Pro.key",
|
||||
},
|
||||
"state": "PRO",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { type Mapping } from '@runonflux/nat-upnp';
|
||||
import { expect, test, vi } from 'vitest';
|
||||
|
||||
import { getWanPortForUpnp } from '@app/upnp/helpers';
|
||||
import { getWanPortForUpnp } from '@app/upnp/helpers.js';
|
||||
|
||||
test('it successfully gets a wan port given no exclusions', () => {
|
||||
const port = getWanPortForUpnp(null, 36_000, 38_000);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { describe, expect, it } from 'vitest';
|
||||
|
||||
import { formatDatetime } from '@app/utils';
|
||||
import { csvStringToArray, formatDatetime } from '@app/utils.js';
|
||||
|
||||
describe('formatDatetime', () => {
|
||||
const testDate = new Date('2024-02-14T12:34:56');
|
||||
@@ -69,3 +69,37 @@ describe('formatDatetime', () => {
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('csvStringToArray', () => {
|
||||
it('returns an empty array for null, undefined, or empty strings', () => {
|
||||
expect(csvStringToArray(null)).toEqual([]);
|
||||
expect(csvStringToArray(undefined)).toEqual([]);
|
||||
expect(csvStringToArray('')).toEqual([]);
|
||||
});
|
||||
|
||||
it('returns an array of strings for a CSV string', () => {
|
||||
expect(csvStringToArray('one,two,three')).toEqual(['one', 'two', 'three']);
|
||||
});
|
||||
|
||||
it('returns an array of strings for a CSV string with spaces', () => {
|
||||
expect(csvStringToArray('one, two, three')).toEqual(['one', 'two', 'three']);
|
||||
});
|
||||
|
||||
it('handles single element edge cases', () => {
|
||||
expect(csvStringToArray('one', { noEmpty: false })).toEqual(['one']);
|
||||
expect(csvStringToArray('one,', { noEmpty: false })).toEqual(['one', '']);
|
||||
expect(csvStringToArray(',one', { noEmpty: false })).toEqual(['', 'one']);
|
||||
expect(csvStringToArray(',one,', { noEmpty: false })).toEqual(['', 'one', '']);
|
||||
});
|
||||
|
||||
it('handles non-empty option', () => {
|
||||
expect(csvStringToArray('one', { noEmpty: true })).toEqual(['one']);
|
||||
expect(csvStringToArray('one,', { noEmpty: true })).toEqual(['one']);
|
||||
expect(csvStringToArray(',one', { noEmpty: true })).toEqual(['one']);
|
||||
expect(csvStringToArray(',one,', { noEmpty: true })).toEqual(['one']);
|
||||
});
|
||||
|
||||
it('defaults to noEmpty', () => {
|
||||
expect(csvStringToArray(',one,')).toEqual(['one']);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,14 +1,12 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
import '@app/dotenv';
|
||||
import '@app/dotenv.js';
|
||||
|
||||
import { execa } from 'execa';
|
||||
import { CommandFactory } from 'nest-commander';
|
||||
|
||||
import { internalLogger, logger } from '@app/core/log';
|
||||
import { LOG_LEVEL } from '@app/environment';
|
||||
import { CliModule } from '@app/unraid-api/cli/cli.module';
|
||||
import { LogService } from '@app/unraid-api/cli/log.service';
|
||||
import { internalLogger, logger } from '@app/core/log.js';
|
||||
import { LOG_LEVEL } from '@app/environment.js';
|
||||
import { CliModule } from '@app/unraid-api/cli/cli.module.js';
|
||||
import { LogService } from '@app/unraid-api/cli/log.service.js';
|
||||
|
||||
const getUnraidApiLocation = async () => {
|
||||
try {
|
||||
@@ -22,7 +20,16 @@ const getUnraidApiLocation = async () => {
|
||||
};
|
||||
|
||||
try {
|
||||
await CommandFactory.run(CliModule, {
|
||||
// Register plugins and create a dynamic module configuration
|
||||
const dynamicModule = await CliModule.registerWithPlugins();
|
||||
|
||||
// Create a new class that extends CliModule with the dynamic configuration
|
||||
const DynamicCliModule = class extends CliModule {
|
||||
static module = dynamicModule.module;
|
||||
static imports = dynamicModule.imports;
|
||||
static providers = dynamicModule.providers;
|
||||
};
|
||||
await CommandFactory.run(DynamicCliModule, {
|
||||
cliName: 'unraid-api',
|
||||
logger: LOG_LEVEL === 'TRACE' ? new LogService() : false, // - enable this to see nest initialization issues
|
||||
completion: {
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import { uniq } from 'lodash-es';
|
||||
|
||||
import type { RootState } from '@app/store';
|
||||
import { logger } from '@app/core';
|
||||
import { GRAPHQL_INTROSPECTION } from '@app/environment';
|
||||
import { getServerIps, getUrlForField } from '@app/graphql/resolvers/subscription/network';
|
||||
import { getters, store } from '@app/store';
|
||||
import { FileLoadStatus } from '@app/store/types';
|
||||
import type { RootState } from '@app/store/index.js';
|
||||
import { logger } from '@app/core/log.js';
|
||||
import { GRAPHQL_INTROSPECTION } from '@app/environment.js';
|
||||
import { getServerIps, getUrlForField } from '@app/graphql/resolvers/subscription/network.js';
|
||||
import { getters, store } from '@app/store/index.js';
|
||||
import { FileLoadStatus } from '@app/store/types.js';
|
||||
|
||||
const getAllowedSocks = (): string[] => [
|
||||
// Notifier bridge
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { getters } from '@app/store';
|
||||
import { FileLoadStatus } from '@app/store/types';
|
||||
import { getters } from '@app/store/index.js';
|
||||
import { FileLoadStatus } from '@app/store/types.js';
|
||||
|
||||
/**
|
||||
* Unraid version string.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { satisfies } from 'semver';
|
||||
|
||||
import { getters } from '@app/store';
|
||||
import { getters } from '@app/store/index.js';
|
||||
|
||||
/**
|
||||
* Compare version against the current unraid version.
|
||||
|
||||
@@ -2,7 +2,7 @@ import { join } from 'path';
|
||||
|
||||
import type { JSONWebKeySet } from 'jose';
|
||||
|
||||
import { PORT } from '@app/environment';
|
||||
import { PORT } from '@app/environment.js';
|
||||
|
||||
export const getInternalApiAddress = (isHttp = true, nginxPort = 80) => {
|
||||
const envPort = PORT;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user